diff options
-rw-r--r-- | include/mupdf/fitz/document.h | 13 | ||||
-rw-r--r-- | include/mupdf/pdf/object.h | 11 | ||||
-rw-r--r-- | include/mupdf/pdf/page.h | 1 | ||||
-rw-r--r-- | source/fitz/document.c | 7 | ||||
-rw-r--r-- | source/pdf/pdf-object.c | 22 | ||||
-rw-r--r-- | source/pdf/pdf-page.c | 106 | ||||
-rw-r--r-- | source/tools/mudraw.c | 29 |
7 files changed, 164 insertions, 25 deletions
diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h index d3b9abd5..95e59632 100644 --- a/include/mupdf/fitz/document.h +++ b/include/mupdf/fitz/document.h @@ -178,6 +178,12 @@ typedef int (fz_page_separation_disabled_fn)(fz_context *ctx, fz_page *page, int */ typedef fz_separations *(fz_page_separations_fn)(fz_context *ctx, fz_page *page); +/* + fz_page_uses_overprint_fn: Type for a function to retrieve + whether or not a given page uses overprint. +*/ +typedef int (fz_page_uses_overprint_fn)(fz_context *ctx, fz_page *page); + typedef void (fz_annot_drop_fn)(fz_context *ctx, fz_annot *annot); typedef fz_annot *(fz_annot_next_fn)(fz_context *ctx, fz_annot *annot); typedef fz_rect *(fz_annot_bound_fn)(fz_context *ctx, fz_annot *annot, fz_rect *rect); @@ -212,6 +218,7 @@ struct fz_page_s fz_page_control_separation_fn *control_separation; fz_page_separation_disabled_fn *separation_disabled; fz_page_separations_fn *separations; + fz_page_uses_overprint_fn *overprint; }; /* @@ -610,6 +617,12 @@ fz_colorspace *fz_document_output_intent(fz_context *ctx, fz_document *doc); fz_separations *fz_page_separations(fz_context *ctx, fz_page *page); /* + fz_page_uses_overprint: Find out whether a given page requests + overprint. +*/ +int fz_page_uses_overprint(fz_context *ctx, fz_page *page); + +/* fz_save_gproof: Given a currently open document, create a gproof skeleton file from that document. diff --git a/include/mupdf/pdf/object.h b/include/mupdf/pdf/object.h index 5ceab1f0..285acf4d 100644 --- a/include/mupdf/pdf/object.h +++ b/include/mupdf/pdf/object.h @@ -66,8 +66,15 @@ void pdf_unmark_obj(fz_context *ctx, pdf_obj *obj); /* obj memo functions - allows us to secretly remember "a memo" (a bool) in * an object, and to read back whether there was a memo, and if so, what it * was. */ -void pdf_set_obj_memo(fz_context *ctx, pdf_obj *obj, int memo); -int pdf_obj_memo(fz_context *ctx, pdf_obj *obj, int *memo); + +enum +{ + PDF_FLAGS_MEMO_BM = 0, + PDF_FLAGS_MEMO_OP = 1 +}; + +void pdf_set_obj_memo(fz_context *ctx, pdf_obj *obj, int bit, int memo); +int pdf_obj_memo(fz_context *ctx, pdf_obj *obj, int bit, int *memo); /* obj dirty bit support. */ int pdf_obj_is_dirty(fz_context *ctx, pdf_obj *obj); diff --git a/include/mupdf/pdf/page.h b/include/mupdf/pdf/page.h index 13f61bfa..969aedf0 100644 --- a/include/mupdf/pdf/page.h +++ b/include/mupdf/pdf/page.h @@ -194,6 +194,7 @@ struct pdf_page_s pdf_obj *obj; int transparency; + int overprint; int incomplete; fz_link *links; diff --git a/source/fitz/document.c b/source/fitz/document.c index 0e511c05..6f9d1316 100644 --- a/source/fitz/document.c +++ b/source/fitz/document.c @@ -490,3 +490,10 @@ fz_page_separations(fz_context *ctx, fz_page *page) return page->separations(ctx, page); return NULL; } + +int fz_page_uses_overprint(fz_context *ctx, fz_page *page) +{ + if (page && page->overprint) + return page->overprint(ctx, page); + return 0; +} diff --git a/source/pdf/pdf-object.c b/source/pdf/pdf-object.c index 2d60edf1..def683d0 100644 --- a/source/pdf/pdf-object.c +++ b/source/pdf/pdf-object.c @@ -28,9 +28,9 @@ enum { PDF_FLAGS_MARKED = 1, PDF_FLAGS_SORTED = 2, - PDF_FLAGS_MEMO = 4, - PDF_FLAGS_MEMO_BOOL = 8, - PDF_FLAGS_DIRTY = 16 + PDF_FLAGS_DIRTY = 4, + PDF_FLAGS_MEMO_BASE = 8, + PDF_FLAGS_MEMO_BASE_BOOL = 16 }; struct pdf_obj_s @@ -1643,26 +1643,28 @@ pdf_unmark_obj(fz_context *ctx, pdf_obj *obj) } void -pdf_set_obj_memo(fz_context *ctx, pdf_obj *obj, int memo) +pdf_set_obj_memo(fz_context *ctx, pdf_obj *obj, int bit, int memo) { if (obj < PDF_OBJ__LIMIT) return; - obj->flags |= PDF_FLAGS_MEMO; + bit <<= 1; + obj->flags |= PDF_FLAGS_MEMO_BASE << bit; if (memo) - obj->flags |= PDF_FLAGS_MEMO_BOOL; + obj->flags |= PDF_FLAGS_MEMO_BASE_BOOL << bit; else - obj->flags &= ~PDF_FLAGS_MEMO_BOOL; + obj->flags &= ~(PDF_FLAGS_MEMO_BASE_BOOL << bit); } int -pdf_obj_memo(fz_context *ctx, pdf_obj *obj, int *memo) +pdf_obj_memo(fz_context *ctx, pdf_obj *obj, int bit, int *memo) { if (obj < PDF_OBJ__LIMIT) return 0; - if (!(obj->flags & PDF_FLAGS_MEMO)) + bit <<= 1; + if (!(obj->flags & (PDF_FLAGS_MEMO_BASE<<bit))) return 0; - *memo = !!(obj->flags & PDF_FLAGS_MEMO_BOOL); + *memo = !!(obj->flags & (PDF_FLAGS_MEMO_BASE_BOOL<<bit)); return 1; } 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) { diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c index d3cef7a2..f7b87626 100644 --- a/source/tools/mudraw.c +++ b/source/tools/mudraw.c @@ -256,7 +256,12 @@ static int lowmemory = 0; static int errored = 0; static fz_colorspace *colorspace; +static fz_colorspace *oi = NULL; +#ifdef FZ_ENABLE_SPOT_RENDERING +static int spots = SPOTS_OVERPRINT_SIM; +#else static int spots = SPOTS_NONE; +#endif static int alpha; static char *filename; static int files = 0; @@ -352,12 +357,14 @@ static void usage(void) "\t-P\tparallel interpretation/rendering (disabled in this non-threading build)\n" #endif "\t-N\tdisable ICC workflow (\"N\"o color management)\n" - "\t-O -\tControl spot rendering\n" + "\t-O -\tControl spot/overprint rendering\n" "\t\t 0 = No spot rendering\n" #ifdef FZ_ENABLE_SPOT_RENDERING - "\t\t 1 = Overprint simulation\n" + "\t\t 0 = No spot rendering\n" + "\t\t 1 = Overprint simulation (default)\n" "\t\t 2 = Full spot rendering\n" #else + "\t\t 0 = No spot rendering (default)\n" "\t\t 1 = Overprint simulation (Disabled in this build)\n" "\t\t 2 = Full spot rendering (Disabled in this build)\n" #endif @@ -1027,7 +1034,7 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) page = fz_load_page(ctx, doc, pagenum - 1); - if (spots) + if (spots != SPOTS_NONE) { fz_try(ctx) { @@ -1042,11 +1049,18 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) for (i = 0; i < n; i++) fz_set_separation_behavior(ctx, seps, i, FZ_SEPARATION_COMPOSITE); } - else + else if (fz_page_uses_overprint(ctx, page)) + { + /* This page uses overprint, so we need an empty + * sep object to force the overprint simulation on. */ + seps = fz_new_separations(ctx, 0); + } + else if (oi && fz_colorspace_n(ctx, oi) != fz_colorspace_n(ctx, colorspace)) { - /* If we are doing spot rendering (or overprint simulation) - * then we need (at least) an empty sep object to force the - * overprint simulation in the draw device. */ + /* We have an output intent, and it's incompatible + * with the colorspace our device needs. Force the + * overprint simulation on, because this ensures that + * we 'simulate' the output intent too. */ seps = fz_new_separations(ctx, 0); } } @@ -1446,7 +1460,6 @@ int mudraw_main(int argc, char **argv) trace_info info = { 0, 0, 0 }; fz_alloc_context alloc_ctx = { &info, trace_malloc, trace_realloc, trace_free }; fz_locks_context *locks = NULL; - fz_colorspace *oi = NULL; fz_var(doc); |