From 63713f22ae830142dfe0d3896948ec53c4705ace Mon Sep 17 00:00:00 2001 From: Michael Vrhel Date: Fri, 23 Jun 2017 12:23:36 -0700 Subject: Add colorspace handling to transparency groups Also force softmasks to be isolated groups. --- source/fitz/bbox-device.c | 2 +- source/fitz/colorspace.c | 2 +- source/fitz/device.c | 4 ++-- source/fitz/draw-device.c | 12 +++++++++++- source/fitz/list-device.c | 46 ++++++++++++++++++++++++++++++---------------- source/fitz/svg-device.c | 2 +- source/fitz/test-device.c | 4 ++-- source/fitz/trace-device.c | 2 +- source/pdf/pdf-device.c | 4 ++-- source/pdf/pdf-op-run.c | 19 ++++++++++--------- source/pdf/pdf-page.c | 6 ++++++ source/pdf/pdf-run.c | 22 +++++++++++++++++++++- source/tools/murun.c | 4 ++-- 13 files changed, 90 insertions(+), 39 deletions(-) (limited to 'source') diff --git a/source/fitz/bbox-device.c b/source/fitz/bbox-device.c index a288ec45..37778741 100644 --- a/source/fitz/bbox-device.c +++ b/source/fitz/bbox-device.c @@ -151,7 +151,7 @@ fz_bbox_end_mask(fz_context *ctx, fz_device *dev) } static void -fz_bbox_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha) +fz_bbox_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *rect, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { fz_bbox_add_rect(ctx, dev, rect, 1); } diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c index 229cd4ca..0a6d2b91 100644 --- a/source/fitz/colorspace.c +++ b/source/fitz/colorspace.c @@ -324,7 +324,7 @@ fz_new_icc_link(fz_context *ctx, fz_iccprofile *src, fz_iccprofile *prf, fz_iccp link->num_in = src->num_devcomp; link->num_out = dst->num_devcomp; - if (memcmp(src->md5, dst->md5, 16) == 0 && rend->ri == FZ_RI_RELATIVE_COLORIMETRIC && prf == NULL) + if (memcmp(src->md5, dst->md5, 16) == 0 && prf == NULL) { link->is_identity = 1; return link; diff --git a/source/fitz/device.c b/source/fitz/device.c index fcf135d0..0f658d31 100644 --- a/source/fitz/device.c +++ b/source/fitz/device.c @@ -416,7 +416,7 @@ fz_end_mask(fz_context *ctx, fz_device *dev) } void -fz_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *area, int isolated, int knockout, int blendmode, float alpha) +fz_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *area, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { if (dev->error_depth) { @@ -429,7 +429,7 @@ fz_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *area, int isolate if (dev->hints & FZ_MAINTAIN_CONTAINER_STACK) push_clip_stack(ctx, dev, area, fz_device_container_stack_is_group); if (dev->begin_group) - dev->begin_group(ctx, dev, area, isolated, knockout, blendmode, alpha); + dev->begin_group(ctx, dev, area, cs, isolated, knockout, blendmode, alpha); } fz_catch(ctx) { diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c index 54ed3f05..66b198fc 100644 --- a/source/fitz/draw-device.c +++ b/source/fitz/draw-device.c @@ -1854,7 +1854,7 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp) } static void -fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha) +fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { fz_draw_device *dev = (fz_draw_device*)devp; fz_irect bbox; @@ -1863,6 +1863,9 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int i fz_colorspace *model = state->dest->colorspace; fz_rect trect = *rect; + if (cs != NULL) + model = fz_default_colorspace(ctx, dev->default_cs, cs); + if (state->blendmode & FZ_BLEND_KNOCKOUT) fz_knockout_begin(ctx, dev); @@ -1952,6 +1955,13 @@ fz_draw_end_group(fz_context *ctx, fz_device *devp) if (state[1].blendmode & FZ_BLEND_KNOCKOUT) printf(" (knockout)"); #endif + if (state[0].dest->colorspace != state[1].dest->colorspace) + { + fz_pixmap *converted = fz_convert_pixmap(ctx, state[1].dest, state[0].dest->colorspace, NULL, dev->default_cs, fz_default_color_params(ctx), 1); + fz_drop_pixmap(ctx, state[1].dest); + state[1].dest = converted; + } + if ((blendmode == 0) && (state[0].shape == state[1].shape)) fz_paint_pixmap(state[0].dest, state[1].dest, alpha * 255); else diff --git a/source/fitz/list-device.c b/source/fitz/list-device.c index 4d2f0c00..03f163a5 100644 --- a/source/fitz/list-device.c +++ b/source/fitz/list-device.c @@ -1098,29 +1098,40 @@ fz_list_end_mask(fz_context *ctx, fz_device *dev) } static void -fz_list_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha) +fz_list_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *rect, fz_colorspace *colorspace, int isolated, int knockout, int blendmode, float alpha) { int flags; + colorspace = fz_keep_colorspace(ctx, colorspace); + flags = (blendmode<<2); if (isolated) flags |= ISOLATED; if (knockout) flags |= KNOCKOUT; - fz_append_display_node( - ctx, - dev, - FZ_CMD_BEGIN_GROUP, - flags, - rect, - NULL, /* path */ - NULL, /* color */ - NULL, /* colorspace */ - &alpha, /* alpha */ - NULL, /* ctm */ - NULL, /* stroke */ - NULL, /* private_data */ - 0); /* private_data_len */ + + fz_try(ctx) + { + fz_append_display_node( + ctx, + dev, + FZ_CMD_BEGIN_GROUP, + flags, + rect, + NULL, /* path */ + NULL, /* color */ + NULL, /* colorspace */ + &alpha, /* alpha */ + NULL, /* ctm */ + NULL, /* stroke */ + &colorspace, /* private_data */ + sizeof(colorspace)); /* private_data_len */ + } + fz_catch(ctx) + { + fz_drop_colorspace(ctx, colorspace); + fz_rethrow(ctx); + } } static void @@ -1394,6 +1405,9 @@ fz_drop_display_list_imp(fz_context *ctx, fz_storable *list_) case FZ_CMD_CLIP_IMAGE_MASK: fz_drop_image(ctx, *(fz_image **)node); break; + case FZ_CMD_BEGIN_GROUP: + fz_drop_colorspace(ctx, *(fz_colorspace **)node); + break; case FZ_CMD_DEFAULT_COLORSPACES: fz_drop_default_colorspaces(ctx, *(fz_default_colorspaces **)node); break; @@ -1732,7 +1746,7 @@ visible: fz_end_mask(ctx, dev); break; case FZ_CMD_BEGIN_GROUP: - fz_begin_group(ctx, dev, &trans_rect, (n.flags & ISOLATED) != 0, (n.flags & KNOCKOUT) != 0, (n.flags>>2), alpha); + fz_begin_group(ctx, dev, &trans_rect, *(fz_colorspace **)node, (n.flags & ISOLATED) != 0, (n.flags & KNOCKOUT) != 0, (n.flags>>2), alpha); break; case FZ_CMD_END_GROUP: fz_end_group(ctx, dev); diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c index 1bd6987f..b327824f 100644 --- a/source/fitz/svg-device.c +++ b/source/fitz/svg-device.c @@ -1094,7 +1094,7 @@ svg_dev_end_mask(fz_context *ctx, fz_device *dev) } static void -svg_dev_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int isolated, int knockout, int blendmode, float alpha) +svg_dev_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { svg_device *sdev = (svg_device*)dev; fz_output *out = sdev->out; diff --git a/source/fitz/test-device.c b/source/fitz/test-device.c index aa6631a8..94572a55 100644 --- a/source/fitz/test-device.c +++ b/source/fitz/test-device.c @@ -439,11 +439,11 @@ fz_test_end_mask(fz_context *ctx, fz_device *dev_) } static void -fz_test_begin_group(fz_context *ctx, fz_device *dev_, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha) +fz_test_begin_group(fz_context *ctx, fz_device *dev_, const fz_rect *rect, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { fz_test_device *dev = (fz_test_device*)dev_; - fz_begin_group(ctx, dev->passthrough, rect, isolated, knockout, blendmode, alpha); + fz_begin_group(ctx, dev->passthrough, rect, cs, isolated, knockout, blendmode, alpha); } static void diff --git a/source/fitz/trace-device.c b/source/fitz/trace-device.c index db08aa52..13ce7256 100644 --- a/source/fitz/trace-device.c +++ b/source/fitz/trace-device.c @@ -313,7 +313,7 @@ fz_trace_end_mask(fz_context *ctx, fz_device *dev) } static void -fz_trace_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int isolated, int knockout, int blendmode, float alpha) +fz_trace_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { fz_output *out = ((fz_trace_device*)dev)->out; fz_write_printf(ctx, out, "\n", diff --git a/source/pdf/pdf-device.c b/source/pdf/pdf-device.c index ba51265a..34aab893 100644 --- a/source/pdf/pdf-device.c +++ b/source/pdf/pdf-device.c @@ -977,7 +977,7 @@ pdf_dev_end_mask(fz_context *ctx, fz_device *dev) } static void -pdf_dev_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int isolated, int knockout, int blendmode, float alpha) +pdf_dev_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { pdf_device *pdev = (pdf_device*)dev; pdf_document *doc = pdev->doc; @@ -987,7 +987,7 @@ pdf_dev_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, int is pdf_dev_end_text(ctx, pdev); - num = pdf_dev_new_form(ctx, &form_ref, pdev, bbox, isolated, knockout, alpha, NULL); + num = pdf_dev_new_form(ctx, &form_ref, pdev, bbox, isolated, knockout, alpha, cs); /* Do we have an appropriate blending extgstate already? */ { diff --git a/source/pdf/pdf-op-run.c b/source/pdf/pdf-op-run.c index 2e6d9cac..56c84cd9 100644 --- a/source/pdf/pdf-op-run.c +++ b/source/pdf/pdf-op-run.c @@ -13,7 +13,7 @@ typedef struct pdf_material_s pdf_material; typedef struct pdf_run_processor_s pdf_run_processor; -static void pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_xobject *xobj, pdf_obj *page_resources, const fz_matrix *transform); +static void pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_xobject *xobj, pdf_obj *page_resources, const fz_matrix *transform, int is_smask); enum { @@ -150,7 +150,7 @@ begin_softmask(fz_context *ctx, pdf_run_processor *pr, softmask_save *save) fz_try(ctx) { fz_begin_mask(ctx, pr->dev, &mask_bbox, gstate->luminosity, mask_colorspace, gstate->softmask_bc, &gstate->fill.color_params); - pdf_run_xobject(ctx, pr, softmask, save->page_resources, &fz_identity); + pdf_run_xobject(ctx, pr, softmask, save->page_resources, &fz_identity, 1); } fz_always(ctx) fz_drop_colorspace(ctx, mask_colorspace); @@ -193,7 +193,7 @@ pdf_begin_group(fz_context *ctx, pdf_run_processor *pr, const fz_rect *bbox, sof pdf_gstate *gstate = begin_softmask(ctx, pr, softmask); if (gstate->blendmode) - fz_begin_group(ctx, pr->dev, bbox, 1, 0, gstate->blendmode, 1); + fz_begin_group(ctx, pr->dev, bbox, NULL, 1, 0, gstate->blendmode, 1); return pr->gstate + pr->gtop; } @@ -527,7 +527,7 @@ pdf_show_image(fz_context *ctx, pdf_run_processor *pr, fz_image *image) { /* apply blend group even though we skip the soft mask */ if (gstate->blendmode) - fz_begin_group(ctx, pr->dev, &bbox, 0, 0, gstate->blendmode, 1); + fz_begin_group(ctx, pr->dev, &bbox, NULL, 0, 0, gstate->blendmode, 1); fz_clip_image_mask(ctx, pr->dev, image->mask, &image_ctm, &bbox); } else @@ -635,7 +635,7 @@ pdf_show_path(fz_context *ctx, pdf_run_processor *pr, int doclose, int dofill, i else { knockout_group = 1; - fz_begin_group(ctx, pr->dev, &bbox, 0, 1, FZ_BLEND_NORMAL, 1); + fz_begin_group(ctx, pr->dev, &bbox, NULL, 0, 1, FZ_BLEND_NORMAL, 1); } } @@ -780,7 +780,7 @@ pdf_flush_text(fz_context *ctx, pdf_run_processor *pr) else { knockout_group = 1; - fz_begin_group(ctx, pr->dev, &tb, 0, 1, FZ_BLEND_NORMAL, 1); + fz_begin_group(ctx, pr->dev, &tb, NULL, 0, 1, FZ_BLEND_NORMAL, 1); } } @@ -1197,7 +1197,7 @@ pdf_set_pattern(fz_context *ctx, pdf_run_processor *pr, int what, pdf_pattern *p } static void -pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_xobject *xobj, pdf_obj *page_resources, const fz_matrix *transform) +pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_xobject *xobj, pdf_obj *page_resources, const fz_matrix *transform, int is_smask) { pdf_run_processor *pr = (pdf_run_processor *)proc; pdf_gstate *gstate = NULL; @@ -1262,7 +1262,8 @@ pdf_run_xobject(fz_context *ctx, pdf_run_processor *proc, pdf_xobject *xobj, pdf * if it throws an error, we must call fz_end_group. */ cleanup_state = 2; fz_begin_group(ctx, pr->dev, &bbox, - pdf_xobject_isolated(ctx, xobj), + pdf_xobject_colorspace(ctx, xobj), + (is_smask ? 1 : pdf_xobject_isolated(ctx, xobj)), pdf_xobject_knockout(ctx, xobj), gstate->blendmode, gstate->fill.alpha); @@ -1983,7 +1984,7 @@ static void pdf_run_Do_image(fz_context *ctx, pdf_processor *proc, const char *n static void pdf_run_Do_form(fz_context *ctx, pdf_processor *proc, const char *name, pdf_xobject *xobj, pdf_obj *page_resources) { - pdf_run_xobject(ctx, (pdf_run_processor*)proc, xobj, page_resources, &fz_identity); + pdf_run_xobject(ctx, (pdf_run_processor*)proc, xobj, page_resources, &fz_identity, 0); } /* marked content */ diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c index 0a7f968e..1830409a 100644 --- a/source/pdf/pdf-page.c +++ b/source/pdf/pdf-page.c @@ -562,6 +562,12 @@ pdf_page_contents(fz_context *ctx, pdf_page *page) return pdf_dict_get(ctx, page->obj, PDF_NAME_Contents); } +pdf_obj * +pdf_page_group(fz_context *ctx, pdf_page *page) +{ + return pdf_dict_get(ctx, page->obj, PDF_NAME_Group); +} + void pdf_page_obj_transform(fz_context *ctx, pdf_obj *pageobj, fz_rect *page_mediabox, fz_matrix *page_ctm) { diff --git a/source/pdf/pdf-run.c b/source/pdf/pdf-run.c index 14dc4ed0..1d823277 100644 --- a/source/pdf/pdf-run.c +++ b/source/pdf/pdf-run.c @@ -51,7 +51,27 @@ pdf_run_page_contents_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *p contents = pdf_page_contents(ctx, page); if (page->transparency) - fz_begin_group(ctx, dev, fz_transform_rect(&mediabox, &local_ctm), 1, 0, 0, 1); + { + fz_colorspace *colorspace = NULL; + pdf_obj *group = pdf_page_group(ctx, page); + + if (group) + { + pdf_obj *cs = pdf_dict_get(ctx, group, PDF_NAME_CS); + if (cs) + { + fz_try(ctx) + { + colorspace = pdf_load_colorspace(ctx, cs); + } + fz_catch(ctx) + { + colorspace = NULL; + } + } + } + fz_begin_group(ctx, dev, fz_transform_rect(&mediabox, &local_ctm), colorspace, 1, 0, 0, 1); + } proc = pdf_new_run_processor(ctx, dev, &local_ctm, usage, NULL, 0); fz_try(ctx) diff --git a/source/tools/murun.c b/source/tools/murun.c index 5e627295..ec9a93e3 100644 --- a/source/tools/murun.c +++ b/source/tools/murun.c @@ -1067,7 +1067,7 @@ js_dev_end_mask(fz_context *ctx, fz_device *dev) static void js_dev_begin_group(fz_context *ctx, fz_device *dev, const fz_rect *bbox, - int isolated, int knockout, int blendmode, float alpha) + fz_colorspace *cs, int isolated, int knockout, int blendmode, float alpha) { js_State *J = ((js_device*)dev)->J; if (js_try(J)) @@ -1404,7 +1404,7 @@ static void ffi_Device_beginGroup(js_State *J) int blendmode = fz_lookup_blendmode(js_tostring(J, 4)); float alpha = js_tonumber(J, 5); fz_try(ctx) - fz_begin_group(ctx, dev, &area, isolated, knockout, blendmode, alpha); + fz_begin_group(ctx, dev, &area, NULL, isolated, knockout, blendmode, alpha); fz_catch(ctx) rethrow(J); } -- cgit v1.2.3