diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-03-14 19:11:02 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-03-14 21:16:27 +0000 |
commit | 77eed8154c782a4d3b0e38a49986c18c240ab2f2 (patch) | |
tree | 4349aa1ce473250ba9186ed11498af96aeb4d40e /pdf | |
parent | ebd905bf410d0093bf68ff1af2621fc4303ed2bd (diff) | |
download | mupdf-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 'pdf')
-rw-r--r-- | pdf/pdf_interpret.c | 91 |
1 files changed, 50 insertions, 41 deletions
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c index 3888b35f..5b2f75a1 100644 --- a/pdf/pdf_interpret.c +++ b/pdf/pdf_interpret.c @@ -37,7 +37,7 @@ struct pdf_gstate_s int clip_depth; /* path stroking */ - fz_stroke_state stroke_state; + fz_stroke_state *stroke_state; /* materials */ pdf_material stroke; @@ -442,9 +442,9 @@ pdf_show_path(pdf_csi *csi, int doclose, int dofill, int dostroke, int even_odd) if (dostroke) { if (csi->dev->flags & (FZ_DEVFLAG_STROKECOLOR_UNDEFINED | FZ_DEVFLAG_LINEJOIN_UNDEFINED | FZ_DEVFLAG_LINEWIDTH_UNDEFINED)) csi->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; - else if (gstate->stroke_state.dash_len != 0 && csi->dev->flags & (FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED)) + else if (gstate->stroke_state->dash_len != 0 && csi->dev->flags & (FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED)) csi->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; - else if (gstate->stroke_state.linejoin == FZ_LINEJOIN_MITER && (csi->dev->flags & FZ_DEVFLAG_MITERLIMIT_UNDEFINED)) + else if (gstate->stroke_state->linejoin == FZ_LINEJOIN_MITER && (csi->dev->flags & FZ_DEVFLAG_MITERLIMIT_UNDEFINED)) csi->dev->flags |= FZ_DEVFLAG_UNCACHEABLE; } if (dofill) { @@ -461,7 +461,7 @@ pdf_show_path(pdf_csi *csi, int doclose, int dofill, int dostroke, int even_odd) fz_closepath(ctx, path); if (dostroke) - bbox = fz_bound_path(ctx, path, &gstate->stroke_state, gstate->ctm); + bbox = fz_bound_path(ctx, path, gstate->stroke_state, gstate->ctm); else bbox = fz_bound_path(ctx, path, NULL, gstate->ctm); @@ -514,13 +514,13 @@ pdf_show_path(pdf_csi *csi, int doclose, int dofill, int dostroke, int even_odd) case PDF_MAT_NONE: break; case PDF_MAT_COLOR: - fz_stroke_path(csi->dev, path, &gstate->stroke_state, gstate->ctm, + fz_stroke_path(csi->dev, path, gstate->stroke_state, gstate->ctm, gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MAT_PATTERN: if (gstate->stroke.pattern) { - fz_clip_stroke_path(csi->dev, path, &bbox, &gstate->stroke_state, gstate->ctm); + fz_clip_stroke_path(csi->dev, path, &bbox, gstate->stroke_state, gstate->ctm); pdf_show_pattern(csi, gstate->stroke.pattern, bbox, PDF_STROKE); fz_pop_clip(csi->dev); } @@ -528,7 +528,7 @@ pdf_show_path(pdf_csi *csi, int doclose, int dofill, int dostroke, int even_odd) case PDF_MAT_SHADE: if (gstate->stroke.shade) { - fz_clip_stroke_path(csi->dev, path, &bbox, &gstate->stroke_state, gstate->ctm); + fz_clip_stroke_path(csi->dev, path, &bbox, gstate->stroke_state, gstate->ctm); fz_fill_shade(csi->dev, gstate->stroke.shade, csi->top_ctm, gstate->stroke.alpha); fz_pop_clip(csi->dev); } @@ -634,13 +634,13 @@ pdf_flush_text(pdf_csi *csi) case PDF_MAT_NONE: break; case PDF_MAT_COLOR: - fz_stroke_text(csi->dev, text, &gstate->stroke_state, gstate->ctm, + fz_stroke_text(csi->dev, text, gstate->stroke_state, gstate->ctm, gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MAT_PATTERN: if (gstate->stroke.pattern) { - fz_clip_stroke_text(csi->dev, text, &gstate->stroke_state, gstate->ctm); + fz_clip_stroke_text(csi->dev, text, gstate->stroke_state, gstate->ctm); pdf_show_pattern(csi, gstate->stroke.pattern, csi->text_bbox, PDF_STROKE); fz_pop_clip(csi->dev); } @@ -648,7 +648,7 @@ pdf_flush_text(pdf_csi *csi) case PDF_MAT_SHADE: if (gstate->stroke.shade) { - fz_clip_stroke_text(csi->dev, text, &gstate->stroke_state, gstate->ctm); + fz_clip_stroke_text(csi->dev, text, gstate->stroke_state, gstate->ctm); fz_fill_shade(csi->dev, gstate->stroke.shade, csi->top_ctm, gstate->stroke.alpha); fz_pop_clip(csi->dev); } @@ -859,20 +859,12 @@ pdf_show_text(pdf_csi *csi, pdf_obj *text) */ static void -pdf_init_gstate(pdf_gstate *gs, fz_matrix ctm) +pdf_init_gstate(fz_context *ctx, pdf_gstate *gs, fz_matrix ctm) { gs->ctm = ctm; gs->clip_depth = 0; - gs->stroke_state.start_cap = FZ_LINECAP_BUTT; - gs->stroke_state.dash_cap = FZ_LINECAP_BUTT; - gs->stroke_state.end_cap = FZ_LINECAP_BUTT; - gs->stroke_state.linejoin = FZ_LINEJOIN_MITER; - gs->stroke_state.linewidth = 1; - gs->stroke_state.miterlimit = 10; - gs->stroke_state.dash_phase = 0; - gs->stroke_state.dash_len = 0; - memset(gs->stroke_state.dash_list, 0, sizeof(gs->stroke_state.dash_list)); + gs->stroke_state = fz_new_stroke_state(ctx); gs->stroke.kind = PDF_MAT_COLOR; gs->stroke.colorspace = fz_device_gray; /* No fz_keep_colorspace as static */ @@ -934,6 +926,7 @@ copy_state(fz_context *ctx, pdf_gstate *gs, pdf_gstate *old) gs->fill = old->fill; gs->font = old->font; gs->softmask = old->softmask; + gs->stroke_state = fz_keep_stroke_state(ctx, old->stroke_state); pdf_keep_material(ctx, &gs->stroke); pdf_keep_material(ctx, &gs->fill); @@ -981,7 +974,7 @@ pdf_new_csi(pdf_document *xref, fz_device *dev, fz_matrix ctm, char *event, fz_c csi->gstate = fz_malloc_array(ctx, csi->gcap, sizeof(pdf_gstate)); csi->top_ctm = ctm; - pdf_init_gstate(&csi->gstate[0], ctm); + pdf_init_gstate(ctx, &csi->gstate[0], ctm); if (gstate) copy_state(ctx, &csi->gstate[0], gstate); csi->gtop = 0; @@ -1037,6 +1030,7 @@ pdf_gsave(pdf_csi *csi) pdf_keep_font(ctx, gs->font); if (gs->softmask) pdf_keep_xobject(ctx, gs->softmask); + fz_keep_stroke_state(ctx, gs->stroke_state); } static void @@ -1058,6 +1052,7 @@ pdf_grestore(pdf_csi *csi) pdf_drop_font(ctx, gs->font); if (gs->softmask) pdf_drop_xobject(ctx, gs->softmask); + fz_drop_stroke_state(ctx, gs->stroke_state); csi->gtop --; @@ -1090,6 +1085,7 @@ pdf_free_csi(pdf_csi *csi) pdf_drop_font(ctx, csi->gstate[0].font); if (csi->gstate[0].softmask) pdf_drop_xobject(ctx, csi->gstate[0].softmask); + fz_drop_stroke_state(ctx, csi->gstate[0].stroke_state); while (csi->gstate[0].clip_depth--) fz_pop_clip(csi->dev); @@ -1483,24 +1479,28 @@ pdf_run_extgstate(pdf_csi *csi, pdf_obj *rdb, pdf_obj *extgstate) else if (!strcmp(s, "LC")) { csi->dev->flags &= ~(FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED); - gstate->stroke_state.start_cap = pdf_to_int(val); - gstate->stroke_state.dash_cap = pdf_to_int(val); - gstate->stroke_state.end_cap = pdf_to_int(val); + gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); + gstate->stroke_state->start_cap = pdf_to_int(val); + gstate->stroke_state->dash_cap = pdf_to_int(val); + gstate->stroke_state->end_cap = pdf_to_int(val); } else if (!strcmp(s, "LW")) { csi->dev->flags &= ~FZ_DEVFLAG_LINEWIDTH_UNDEFINED; - gstate->stroke_state.linewidth = pdf_to_real(val); + gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); + gstate->stroke_state->linewidth = pdf_to_real(val); } else if (!strcmp(s, "LJ")) { csi->dev->flags &= ~FZ_DEVFLAG_LINEJOIN_UNDEFINED; - gstate->stroke_state.linejoin = pdf_to_int(val); + gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); + gstate->stroke_state->linejoin = pdf_to_int(val); } else if (!strcmp(s, "ML")) { csi->dev->flags &= ~FZ_DEVFLAG_MITERLIMIT_UNDEFINED; - gstate->stroke_state.miterlimit = pdf_to_real(val); + gstate->stroke_state = fz_unshare_stroke_state(ctx, gstate->stroke_state); + gstate->stroke_state->miterlimit = pdf_to_real(val); } else if (!strcmp(s, "D")) @@ -1508,10 +1508,12 @@ pdf_run_extgstate(pdf_csi *csi, pdf_obj *rdb, pdf_obj *extgstate) if (pdf_is_array(val) && pdf_array_len(val) == 2) { pdf_obj *dashes = pdf_array_get(val, 0); - gstate->stroke_state.dash_len = MAX(pdf_array_len(dashes), 32); - for (k = 0; k < gstate->stroke_state.dash_len; k++) - gstate->stroke_state.dash_list[k] = pdf_to_real(pdf_array_get(dashes, k)); - gstate->stroke_state.dash_phase = pdf_to_real(pdf_array_get(val, 1)); + int len = pdf_array_len(dashes); + gstate->stroke_state = fz_unshare_stroke_state_with_len(ctx, gstate->stroke_state, len); + gstate->stroke_state->dash_len = len; + for (k = 0; k < len; k++) + gstate->stroke_state->dash_list[k] = pdf_to_real(pdf_array_get(dashes, k)); + gstate->stroke_state->dash_phase = pdf_to_real(pdf_array_get(val, 1)); } else fz_throw(ctx, "malformed /D"); @@ -1859,9 +1861,10 @@ static void pdf_run_J(pdf_csi *csi) { pdf_gstate *gstate = csi->gstate + csi->gtop; csi->dev->flags &= ~(FZ_DEVFLAG_STARTCAP_UNDEFINED | FZ_DEVFLAG_DASHCAP_UNDEFINED | FZ_DEVFLAG_ENDCAP_UNDEFINED); - gstate->stroke_state.start_cap = csi->stack[0]; - gstate->stroke_state.dash_cap = csi->stack[0]; - gstate->stroke_state.end_cap = csi->stack[0]; + gstate->stroke_state = fz_unshare_stroke_state(csi->dev->ctx, gstate->stroke_state); + gstate->stroke_state->start_cap = csi->stack[0]; + gstate->stroke_state->dash_cap = csi->stack[0]; + gstate->stroke_state->end_cap = csi->stack[0]; } static void pdf_run_K(pdf_csi *csi) @@ -1875,7 +1878,8 @@ static void pdf_run_M(pdf_csi *csi) { pdf_gstate *gstate = csi->gstate + csi->gtop; csi->dev->flags &= ~FZ_DEVFLAG_MITERLIMIT_UNDEFINED; - gstate->stroke_state.miterlimit = csi->stack[0]; + gstate->stroke_state = fz_unshare_stroke_state(csi->dev->ctx, gstate->stroke_state); + gstate->stroke_state->miterlimit = csi->stack[0]; } static void pdf_run_MP(pdf_csi *csi) @@ -2143,12 +2147,15 @@ static void pdf_run_d(pdf_csi *csi) pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_obj *array; int i; + int len; array = csi->obj; - gstate->stroke_state.dash_len = MIN(pdf_array_len(array), nelem(gstate->stroke_state.dash_list)); - for (i = 0; i < gstate->stroke_state.dash_len; i++) - gstate->stroke_state.dash_list[i] = pdf_to_real(pdf_array_get(array, i)); - gstate->stroke_state.dash_phase = csi->stack[0]; + len = pdf_array_len(array); + gstate->stroke_state = fz_unshare_stroke_state_with_len(csi->dev->ctx, gstate->stroke_state, len); + gstate->stroke_state->dash_len = len; + for (i = 0; i < len; i++) + gstate->stroke_state->dash_list[i] = pdf_to_real(pdf_array_get(array, i)); + gstate->stroke_state->dash_phase = csi->stack[0]; } static void pdf_run_d0(pdf_csi *csi) @@ -2217,7 +2224,8 @@ static void pdf_run_j(pdf_csi *csi) { pdf_gstate *gstate = csi->gstate + csi->gtop; csi->dev->flags &= ~FZ_DEVFLAG_LINEJOIN_UNDEFINED; - gstate->stroke_state.linejoin = csi->stack[0]; + gstate->stroke_state = fz_unshare_stroke_state(csi->dev->ctx, gstate->stroke_state); + gstate->stroke_state->linejoin = csi->stack[0]; } static void pdf_run_k(pdf_csi *csi) @@ -2333,7 +2341,8 @@ static void pdf_run_w(pdf_csi *csi) pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_flush_text(csi); /* linewidth affects stroked text rendering mode */ csi->dev->flags &= ~FZ_DEVFLAG_LINEWIDTH_UNDEFINED; - gstate->stroke_state.linewidth = csi->stack[0]; + gstate->stroke_state = fz_unshare_stroke_state(csi->dev->ctx, gstate->stroke_state); + gstate->stroke_state->linewidth = csi->stack[0]; } static void pdf_run_y(pdf_csi *csi) |