From 2b4a96702789a5f59fe468a7be907ccd18071cec Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Fri, 7 Sep 2018 15:48:58 +0800 Subject: Bug 699743: Pop clip upon error when flushing text. Not popping causes assert to be triggered in fz_draw_end_group(). --- source/pdf/pdf-op-run.c | 89 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/source/pdf/pdf-op-run.c b/source/pdf/pdf-op-run.c index cce39cf7..09fc4e23 100644 --- a/source/pdf/pdf-op-run.c +++ b/source/pdf/pdf-op-run.c @@ -823,6 +823,14 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) int doinvisible; softmask_save softmask = { NULL }; int knockout_group = 0; + int innerclip = 0; + fz_rect tb; + char errmess[256] = ""; + int err = FZ_ERROR_NONE; + + fz_var(innerclip); + fz_var(knockout_group); + fz_var(tb); text = pdf_tos_get_text(ctx, &pr->tos); if (!text) @@ -844,9 +852,10 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) if (pr->super.hidden) dostroke = dofill = 0; + tb = fz_transform_rect(pr->tos.text_bbox, gstate->ctm); + fz_try(ctx) { - fz_rect tb = fz_transform_rect(pr->tos.text_bbox, gstate->ctm); if (dostroke) tb = fz_adjust_rect_for_stroke(ctx, tb, gstate->stroke_state, gstate->ctm); @@ -892,17 +901,21 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) if (gstate->fill.pattern) { fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); + innerclip = 1; gstate = pdf_show_pattern(ctx, pr, gstate->fill.pattern, gstate->fill.gstate_num, tb, PDF_FILL); fz_pop_clip(ctx, pr->dev); + innerclip = 0; } break; case PDF_MAT_SHADE: if (gstate->fill.shade) { fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); + innerclip = 1; /* Page 2 of patterns.pdf shows that fz_fill_shade should NOT be called with gstate->ctm */ fz_fill_shade(ctx, pr->dev, gstate->fill.shade, pr->gstate[gstate->fill.gstate_num].ctm, gstate->fill.alpha, &gstate->fill.color_params); fz_pop_clip(ctx, pr->dev); + innerclip = 0; } break; } @@ -922,35 +935,91 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) if (gstate->stroke.pattern) { fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb); + innerclip = 1; gstate = pdf_show_pattern(ctx, pr, gstate->stroke.pattern, gstate->stroke.gstate_num, tb, PDF_STROKE); fz_pop_clip(ctx, pr->dev); + innerclip = 0; } break; case PDF_MAT_SHADE: if (gstate->stroke.shade) { fz_clip_stroke_text(ctx, pr->dev, text, gstate->stroke_state, gstate->ctm, tb); + innerclip = 1; fz_fill_shade(ctx, pr->dev, gstate->stroke.shade, pr->gstate[gstate->stroke.gstate_num].ctm, gstate->stroke.alpha, &gstate->stroke.color_params); fz_pop_clip(ctx, pr->dev); + innerclip = 0; } break; } } + } + fz_always(ctx) + { + if (innerclip) + { + fz_try(ctx) + { + fz_pop_clip(ctx, pr->dev); + } + fz_catch(ctx) + { + /* Postpone the problem */ + err = fz_caught(ctx); + strcpy(errmess, fz_caught_message(ctx)); + } + } + if (knockout_group) - fz_end_group(ctx, pr->dev); + { + fz_try(ctx) + { + fz_end_group(ctx, pr->dev); + } + fz_catch(ctx) + { + /* Postpone the problem */ + if (err) + fz_warn(ctx, "ignoring error: %s", fz_caught_message(ctx)); + err = fz_caught(ctx); + strcpy(errmess, fz_caught_message(ctx)); + } + } if (dofill || dostroke) - pdf_end_group(ctx, pr, &softmask); + { + fz_try(ctx) + { + pdf_end_group(ctx, pr, &softmask); + } + fz_catch(ctx) + { + /* Postpone the problem */ + if (err) + fz_warn(ctx, "ignoring error: %s", fz_caught_message(ctx)); + err = fz_caught(ctx); + strcpy(errmess, fz_caught_message(ctx)); + } + } if (doclip) { - gstate->clip_depth++; - fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); + fz_try(ctx) + { + gstate->clip_depth++; + fz_clip_text(ctx, pr->dev, text, gstate->ctm, tb); + } + fz_catch(ctx) + { + /* Postpone the problem */ + if (err) + fz_warn(ctx, "ignoring error: %s", fz_caught_message(ctx)); + err = fz_caught(ctx); + strcpy(errmess, fz_caught_message(ctx)); + } } - } - fz_always(ctx) - { + fz_drop_text(ctx, text); } fz_catch(ctx) @@ -958,6 +1027,10 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) fz_rethrow(ctx); } + /* Rethrow postponed errors */ + if (err) + fz_throw(ctx, err, "%s", errmess); + return pr->gstate + pr->gtop; } -- cgit v1.2.3