summaryrefslogtreecommitdiff
path: root/fitz
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
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')
-rw-r--r--fitz/dev_list.c18
-rw-r--r--fitz/fitz-internal.h8
-rw-r--r--fitz/res_path.c97
3 files changed, 110 insertions, 13 deletions
diff --git a/fitz/dev_list.c b/fitz/dev_list.c
index d0dfabc5..f0cfdeb5 100644
--- a/fitz/dev_list.c
+++ b/fitz/dev_list.c
@@ -96,14 +96,6 @@ fz_new_display_node(fz_context *ctx, fz_display_command cmd, fz_matrix ctm,
return node;
}
-static fz_stroke_state *
-fz_clone_stroke_state(fz_context *ctx, fz_stroke_state *stroke)
-{
- fz_stroke_state *newstroke = fz_malloc_struct(ctx, fz_stroke_state);
- *newstroke = *stroke;
- return newstroke;
-}
-
static void
fz_append_display_node(fz_display_list *list, fz_display_node *node)
{
@@ -219,7 +211,7 @@ fz_free_display_node(fz_context *ctx, fz_display_node *node)
break;
}
if (node->stroke)
- fz_free(ctx, node->stroke);
+ fz_drop_stroke_state(ctx, node->stroke);
if (node->colorspace)
fz_drop_colorspace(ctx, node->colorspace);
fz_free(ctx, node);
@@ -257,7 +249,7 @@ fz_list_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_m
{
node->rect = fz_bound_path(dev->ctx, path, stroke, ctm);
node->item.path = fz_clone_path(dev->ctx, path);
- node->stroke = fz_clone_stroke_state(dev->ctx, stroke);
+ node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
}
fz_catch(ctx)
{
@@ -301,7 +293,7 @@ fz_list_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke
if (rect)
node->rect = fz_intersect_rect(node->rect, *rect);
node->item.path = fz_clone_path(dev->ctx, path);
- node->stroke = fz_clone_stroke_state(dev->ctx, stroke);
+ node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
}
fz_catch(ctx)
{
@@ -343,7 +335,7 @@ fz_list_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_m
{
node->rect = fz_bound_text(dev->ctx, text, ctm);
node->item.text = fz_clone_text(dev->ctx, text);
- node->stroke = fz_clone_stroke_state(dev->ctx, stroke);
+ node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
}
fz_catch(ctx)
{
@@ -386,7 +378,7 @@ fz_list_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke,
{
node->rect = fz_bound_text(dev->ctx, text, ctm);
node->item.text = fz_clone_text(dev->ctx, text);
- node->stroke = fz_clone_stroke_state(dev->ctx, stroke);
+ node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
}
fz_catch(ctx)
{
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index 0a639b1c..eda9736a 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -791,6 +791,7 @@ struct fz_path_s
struct fz_stroke_state_s
{
+ int refs;
fz_linecap start_cap, dash_cap, end_cap;
fz_linejoin linejoin;
float linewidth;
@@ -816,6 +817,13 @@ fz_path *fz_clone_path(fz_context *ctx, fz_path *old);
fz_rect fz_bound_path(fz_context *ctx, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm);
void fz_print_path(fz_context *ctx, FILE *out, fz_path *, int indent);
+fz_stroke_state *fz_new_stroke_state(fz_context *ctx);
+fz_stroke_state *fz_new_stroke_state_with_len(fz_context *ctx, int len);
+fz_stroke_state *fz_keep_stroke_state(fz_context *ctx, fz_stroke_state *stroke);
+void fz_drop_stroke_state(fz_context *ctx, fz_stroke_state *stroke);
+fz_stroke_state *fz_unshare_stroke_state(fz_context *ctx, fz_stroke_state *shared);
+fz_stroke_state *fz_unshare_stroke_state_with_len(fz_context *ctx, fz_stroke_state *shared, int len);
+
/*
* Glyph cache
*/
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);
+}