diff options
author | Robin Watts <robin.watts@artifex.com> | 2017-09-21 14:10:33 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2017-10-24 15:16:36 +0100 |
commit | abd4c0da5d50cc5b81e430dea3eaa01502370dad (patch) | |
tree | 86df6381b21acc05eba42c2b884068ad96e45110 /source/pdf/pdf-page.c | |
parent | a1e696d27e0927855dd2e0d505afd571b0f37ed7 (diff) | |
download | mupdf-abd4c0da5d50cc5b81e430dea3eaa01502370dad.tar.xz |
Improved overprint (simulation) control.
First, we add an fz_page_overprint function to detect if a
page uses overprint. Only PDF implements this currently (other
formats all return false). PDF looks for '/OP true' in any
ExtGState entry.
We make Mutool check this. If it finds it, and spot rendering
is not completely disabled, then it ensures that the separation
object passed to the pixmap into which we draw is non NULL. This
causes the draw device to do overprint simulation.
We ensure that mutool draw defaults to having the spot rendering
mode default to simulation in builds that support it.
Finally, we ensure that if an output intent is set by the document,
and spot rendering is not completely disabled, then we ensure the
seps object is non NULL so that we render to a group in the
specified output intent, and THEN convert down to the required
colorspace for the output.
This should make us match acrobats behaviour.
Diffstat (limited to 'source/pdf/pdf-page.c')
-rw-r--r-- | source/pdf/pdf-page.c | 106 |
1 files changed, 101 insertions, 5 deletions
diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c index 12319678..da8a2394 100644 --- a/source/pdf/pdf-page.c +++ b/source/pdf/pdf-page.c @@ -436,7 +436,7 @@ pdf_resources_use_blending(fz_context *ctx, pdf_obj *rdb) return 0; /* Have we been here before and remembered an answer? */ - if (pdf_obj_memo(ctx, rdb, &useBM)) + if (pdf_obj_memo(ctx, rdb, PDF_FLAGS_MEMO_BM, &useBM)) return useBM; /* stop on cyclic resource dependencies */ @@ -477,10 +477,94 @@ found: fz_rethrow(ctx); } - pdf_set_obj_memo(ctx, rdb, useBM); + pdf_set_obj_memo(ctx, rdb, PDF_FLAGS_MEMO_BM, useBM); return useBM; } +static int pdf_resources_use_overprint(fz_context *ctx, pdf_obj *rdb); + +static int +pdf_extgstate_uses_overprint(fz_context *ctx, pdf_obj *dict) +{ + pdf_obj *obj = pdf_dict_get(ctx, dict, PDF_NAME_OP); + if (obj && pdf_to_bool(ctx, obj)) + return 1; + return 0; +} + +static int +pdf_pattern_uses_overprint(fz_context *ctx, pdf_obj *dict) +{ + pdf_obj *obj; + obj = pdf_dict_get(ctx, dict, PDF_NAME_Resources); + if (pdf_resources_use_overprint(ctx, obj)) + return 1; + obj = pdf_dict_get(ctx, dict, PDF_NAME_ExtGState); + return pdf_extgstate_uses_overprint(ctx, obj); +} + +static int +pdf_xobject_uses_overprint(fz_context *ctx, pdf_obj *dict) +{ + pdf_obj *obj = pdf_dict_get(ctx, dict, PDF_NAME_Resources); + return pdf_resources_use_overprint(ctx, obj); +} + +static int +pdf_resources_use_overprint(fz_context *ctx, pdf_obj *rdb) +{ + pdf_obj *obj; + int i, n, useOP = 0; + + if (!rdb) + return 0; + + /* Have we been here before and remembered an answer? */ + if (pdf_obj_memo(ctx, rdb, PDF_FLAGS_MEMO_OP, &useOP)) + return useOP; + + /* stop on cyclic resource dependencies */ + if (pdf_mark_obj(ctx, rdb)) + return 0; + + fz_try(ctx) + { + obj = pdf_dict_get(ctx, rdb, PDF_NAME_ExtGState); + n = pdf_dict_len(ctx, obj); + for (i = 0; i < n; i++) + if (pdf_extgstate_uses_overprint(ctx, pdf_dict_get_val(ctx, obj, i))) + goto found; + + obj = pdf_dict_get(ctx, rdb, PDF_NAME_Pattern); + n = pdf_dict_len(ctx, obj); + for (i = 0; i < n; i++) + if (pdf_pattern_uses_overprint(ctx, pdf_dict_get_val(ctx, obj, i))) + goto found; + + obj = pdf_dict_get(ctx, rdb, PDF_NAME_XObject); + n = pdf_dict_len(ctx, obj); + for (i = 0; i < n; i++) + if (pdf_xobject_uses_overprint(ctx, pdf_dict_get_val(ctx, obj, i))) + goto found; + if (0) + { +found: + useOP = 1; + } + } + fz_always(ctx) + { + pdf_unmark_obj(ctx, rdb); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + pdf_set_obj_memo(ctx, rdb, PDF_FLAGS_MEMO_OP, useOP); + return useOP; +} + fz_transition * pdf_page_presentation(fz_context *ctx, pdf_page *page, fz_transition *transition, float *duration) { @@ -823,6 +907,12 @@ pdf_page_separations(fz_context *ctx, pdf_page *page) return seps; } +int +pdf_page_uses_overprint(fz_context *ctx, pdf_page *page) +{ + return page ? page->overprint : 0; +} + static void pdf_drop_page_imp(fz_context *ctx, pdf_page *page) { @@ -856,6 +946,7 @@ pdf_new_page(fz_context *ctx, pdf_document *doc) page->super.run_page_contents = (fz_page_run_page_contents_fn*)pdf_run_page_contents; page->super.page_presentation = (fz_page_page_presentation_fn*)pdf_page_presentation; page->super.separations = (fz_page_separations_fn *)pdf_page_separations; + page->super.overprint = (fz_page_uses_overprint_fn *)pdf_page_uses_overprint; page->obj = NULL; @@ -1009,17 +1100,22 @@ pdf_load_page(fz_context *ctx, pdf_document *doc, int number) page->links = NULL; } - /* Scan for transparency */ + /* Scan for transparency and overprint */ fz_try(ctx) { pdf_obj *resources = pdf_page_resources(ctx, page); - if (pdf_resources_use_blending(ctx, resources)) + if (pdf_name_eq(ctx, pdf_dict_getp(ctx, pageobj, "Group/S"), PDF_NAME_Transparency)) page->transparency = 1; - else if (pdf_name_eq(ctx, pdf_dict_getp(ctx, pageobj, "Group/S"), PDF_NAME_Transparency)) + else if (pdf_resources_use_blending(ctx, resources)) page->transparency = 1; for (annot = page->annots; annot && !page->transparency; annot = annot->next) if (annot->ap && pdf_resources_use_blending(ctx, pdf_xobject_resources(ctx, annot->ap))) page->transparency = 1; + if (pdf_resources_use_overprint(ctx, resources)) + page->overprint = 1; + for (annot = page->annots; annot && !page->overprint; annot = annot->next) + if (annot->ap && pdf_resources_use_overprint(ctx, pdf_xobject_resources(ctx, annot->ap))) + page->overprint = 1; } fz_catch(ctx) { |