summaryrefslogtreecommitdiff
path: root/fitz/res_path.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-03-14 19:11:02 +0000
committerRobin Watts <robin.watts@artifex.com>2012-03-14 21:16:27 +0000
commit77eed8154c782a4d3b0e38a49986c18c240ab2f2 (patch)
tree4349aa1ce473250ba9186ed11498af96aeb4d40e /fitz/res_path.c
parentebd905bf410d0093bf68ff1af2621fc4303ed2bd (diff)
downloadmupdf-77eed8154c782a4d3b0e38a49986c18c240ab2f2.tar.xz
Bug 692917: Move to dynamic stroke_states.
Move fz_stroke_state from being a simple structure whose contents are copied repeatedly to being a dynamically allocated reference counted object so we can cope with large numbers of entries in the dash array.
Diffstat (limited to 'fitz/res_path.c')
-rw-r--r--fitz/res_path.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/fitz/res_path.c b/fitz/res_path.c
index fed1504a..13705969 100644
--- a/fitz/res_path.c
+++ b/fitz/res_path.c
@@ -365,3 +365,100 @@ fz_print_path(fz_context *ctx, FILE *out, fz_path *path, int indent)
}
}
}
+
+fz_stroke_state *
+fz_keep_stroke_state(fz_context *ctx, fz_stroke_state *stroke)
+{
+ fz_lock(ctx, FZ_LOCK_ALLOC);
+
+ if (!stroke)
+ return NULL;
+
+ if (stroke->refs > 0)
+ stroke->refs++;
+ fz_unlock(ctx, FZ_LOCK_ALLOC);
+ return stroke;
+}
+
+void
+fz_drop_stroke_state(fz_context *ctx, fz_stroke_state *stroke)
+{
+ int drop;
+
+ if (!stroke)
+ return;
+
+ fz_lock(ctx, FZ_LOCK_ALLOC);
+ drop = (stroke->refs > 0 ? --stroke->refs == 0 : 0);
+ fz_unlock(ctx, FZ_LOCK_ALLOC);
+ if (drop)
+ fz_free(ctx, stroke);
+}
+
+fz_stroke_state *
+fz_new_stroke_state_with_len(fz_context *ctx, int len)
+{
+ fz_stroke_state *state;
+
+ len -= nelem(state->dash_list);
+ if (len < 0)
+ len = 0;
+
+ state = Memento_label(fz_malloc(ctx, sizeof(*state) + sizeof(state->dash_list[0]) * len), "fz_stroke_state");
+ state->refs = 1;
+ state->start_cap = FZ_LINECAP_BUTT;
+ state->dash_cap = FZ_LINECAP_BUTT;
+ state->end_cap = FZ_LINECAP_BUTT;
+ state->linejoin = FZ_LINEJOIN_MITER;
+ state->linewidth = 1;
+ state->miterlimit = 10;
+ state->dash_phase = 0;
+ state->dash_len = 0;
+ memset(state->dash_list, 0, sizeof(state->dash_list[0]) * (len + nelem(state->dash_list)));
+
+ return state;
+}
+
+fz_stroke_state *
+fz_new_stroke_state(fz_context *ctx)
+{
+ return fz_new_stroke_state_with_len(ctx, 0);
+}
+
+
+fz_stroke_state *
+fz_unshare_stroke_state_with_len(fz_context *ctx, fz_stroke_state *shared, int len)
+{
+ int single, unsize, shsize, shlen, drop;
+ fz_stroke_state *unshared;
+
+ fz_lock(ctx, FZ_LOCK_ALLOC);
+ single = (shared->refs == 1);
+ fz_unlock(ctx, FZ_LOCK_ALLOC);
+
+ shlen = shared->dash_len - nelem(shared->dash_list);
+ if (shlen < 0)
+ shlen = 0;
+ shsize = sizeof(*shared) + sizeof(shared->dash_list[0]) * shlen;
+ len -= nelem(shared->dash_list);
+ if (len < 0)
+ len = 0;
+ if (single && shlen >= len)
+ return shared;
+ unsize = sizeof(*unshared) + sizeof(unshared->dash_list[0]) * len;
+ unshared = Memento_label(fz_malloc(ctx, unsize), "fz_stroke_state");
+ memcpy(unshared, shared, (shsize > unsize ? unsize : shsize));
+ unshared->refs = 1;
+ fz_lock(ctx, FZ_LOCK_ALLOC);
+ drop = (shared->refs > 0 ? --shared->refs == 0 : 0);
+ fz_unlock(ctx, FZ_LOCK_ALLOC);
+ if (drop)
+ fz_free(ctx, shared);
+ return unshared;
+}
+
+fz_stroke_state *
+fz_unshare_stroke_state(fz_context *ctx, fz_stroke_state *shared)
+{
+ return fz_unshare_stroke_state_with_len(ctx, shared, shared->dash_len);
+}