summaryrefslogtreecommitdiff
path: root/source/fitz/path.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2015-12-09 17:52:15 +0000
committerRobin Watts <robin.watts@artifex.com>2015-12-14 16:22:35 +0000
commit88a1d527a50e3cc48606ce097a335669ae84a716 (patch)
tree1a40eb7f797768bdae975c0c5e3c371567cc9e2d /source/fitz/path.c
parent3b183d95c919bf56a5ffcecf9717aa5b73db0db6 (diff)
downloadmupdf-88a1d527a50e3cc48606ce097a335669ae84a716.tar.xz
Add fz_clone_path
Will be required for JNI bindings.
Diffstat (limited to 'source/fitz/path.c')
-rw-r--r--source/fitz/path.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/source/fitz/path.c b/source/fitz/path.c
index 5481a90d..fbc5ef47 100644
--- a/source/fitz/path.c
+++ b/source/fitz/path.c
@@ -1520,3 +1520,127 @@ fz_unshare_stroke_state(fz_context *ctx, fz_stroke_state *shared)
{
return fz_unshare_stroke_state_with_dash_len(ctx, shared, shared->dash_len);
}
+
+static void *
+clone_block(fz_context *ctx, void *block, size_t len)
+{
+ void *target;
+
+ if (len == 0 || block == NULL)
+ return NULL;
+
+ target = fz_malloc(ctx, len);
+ memcpy(target, block, len);
+ return target;
+}
+
+fz_path *
+fz_clone_path(fz_context *ctx, fz_path *path)
+{
+ fz_path *new_path;
+
+ assert(ctx != NULL);
+
+ if (ctx == NULL || path == NULL)
+ return NULL;
+
+ new_path = fz_malloc_struct(ctx, fz_path);
+ new_path->refs = 1;
+ new_path->packed = FZ_PATH_UNPACKED;
+ fz_try(ctx)
+ {
+ switch(path->packed)
+ {
+ case FZ_PATH_UNPACKED:
+ case FZ_PATH_PACKED_OPEN:
+ new_path->cmd_len = path->cmd_len;
+ new_path->cmd_cap = path->cmd_cap;
+ new_path->cmds = clone_block(ctx, path->cmds, path->cmd_cap);
+ new_path->coord_len = path->coord_len;
+ new_path->coord_cap = path->coord_cap;
+ new_path->coords = clone_block(ctx, path->coords, sizeof(float)*path->coord_cap);
+ new_path->current = path->current;
+ new_path->begin = path->begin;
+ break;
+ case FZ_PATH_PACKED_FLAT:
+ {
+ uint8_t *data;
+ float *xy;
+ int i;
+ fz_packed_path *ppath = (fz_packed_path *)path;
+
+ new_path->cmd_len = ppath->cmd_len;
+ new_path->cmd_cap = ppath->cmd_len;
+ new_path->coord_len = ppath->coord_len;
+ new_path->coord_cap = ppath->coord_len;
+ data = (uint8_t *)&ppath[1];
+ new_path->coords = clone_block(ctx, data, sizeof(float)*path->coord_cap);
+ data += sizeof(float) * path->coord_cap;
+ new_path->cmds = clone_block(ctx, data, path->cmd_cap);
+ xy = new_path->coords;
+ for (i = 0; i < new_path->cmd_len; i++)
+ {
+ switch (new_path->cmds[i])
+ {
+ case FZ_MOVETOCLOSE:
+ case FZ_MOVETO:
+ new_path->current.x = *xy++;
+ new_path->current.y = *xy++;
+ new_path->begin.x = new_path->current.x;
+ new_path->begin.y = new_path->current.y;
+ break;
+ case FZ_CURVETO:
+ xy += 2;
+ /* fallthrough */
+ case FZ_CURVETOV:
+ case FZ_CURVETOY:
+ case FZ_QUADTO:
+ /* fallthrough */
+ xy += 2;
+ case FZ_LINETO:
+ new_path->current.x = *xy++;
+ new_path->current.y = *xy++;
+ break;
+ case FZ_DEGENLINETO:
+ break;
+ case FZ_HORIZTO:
+ new_path->current.x = *xy++;
+ break;
+ case FZ_VERTTO:
+ new_path->current.y = *xy++;
+ break;
+ case FZ_RECTTO:
+ xy += 2;
+ break;
+ case FZ_CURVETOCLOSE:
+ xy += 2;
+ /* fallthrough */
+ case FZ_CURVETOVCLOSE:
+ case FZ_CURVETOYCLOSE:
+ case FZ_QUADTOCLOSE:
+ case FZ_LINETOCLOSE:
+ xy++;
+ /* fallthrough */
+ case FZ_HORIZTOCLOSE:
+ case FZ_VERTTOCLOSE:
+ xy++;
+ /* fallthrough */
+ case FZ_DEGENLINETOCLOSE:
+ new_path->current.x = new_path->begin.x;
+ new_path->current.y = new_path->begin.y;
+ break;
+ }
+ }
+ }
+ default:
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Unknown packing method found in path");
+ }
+ }
+ fz_catch(ctx)
+ {
+ fz_free(ctx, new_path->cmds);
+ fz_free(ctx, new_path);
+ fz_rethrow(ctx);
+ }
+ return new_path;
+}