summaryrefslogtreecommitdiff
path: root/source/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'source/pdf')
-rw-r--r--source/pdf/pdf-object.c22
-rw-r--r--source/pdf/pdf-page.c106
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)
{