diff options
Diffstat (limited to 'source/pdf')
-rw-r--r-- | source/pdf/pdf-object.c | 22 | ||||
-rw-r--r-- | source/pdf/pdf-page.c | 106 |
2 files changed, 113 insertions, 15 deletions
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) { |