#include "mupdf/pdf.h" #define TILE typedef struct pdf_material_s pdf_material; typedef struct pdf_gstate_s pdf_gstate; typedef struct pdf_csi_s pdf_csi; enum { PDF_FILL, PDF_STROKE, }; enum { PDF_MAT_NONE, PDF_MAT_COLOR, PDF_MAT_PATTERN, PDF_MAT_SHADE, }; struct pdf_material_s { int kind; fz_colorspace *colorspace; pdf_pattern *pattern; fz_shade *shade; int gstate_num; float alpha; float v[FZ_MAX_COLORS]; }; struct pdf_gstate_s { fz_matrix ctm; int clip_depth; /* path stroking */ fz_stroke_state *stroke_state; /* materials */ pdf_material stroke; pdf_material fill; /* text state */ float char_space; float word_space; float scale; float leading; pdf_font_desc *font; float size; int render; float rise; /* transparency */ int blendmode; pdf_xobject *softmask; fz_matrix softmask_ctm; float softmask_bc[FZ_MAX_COLORS]; int luminosity; }; struct pdf_csi_s { fz_device *dev; pdf_document *doc; int nested_depth; /* usage mode for optional content groups */ char *event; /* "View", "Print", "Export" */ /* interpreter stack */ pdf_obj *obj; char name[256]; unsigned char string[256]; int string_len; float stack[32]; int top; int xbalance; int in_text; int in_hidden_ocg; /* path object state */ fz_path *path; int clip; int clip_even_odd; /* text object state */ fz_text *text; fz_rect text_bbox; fz_matrix tlm; fz_matrix tm; int text_mode; int accumulate; /* graphics state */ pdf_gstate *gstate; int gcap; int gtop; int gbot; int gparent; /* cookie support */ fz_cookie *cookie; }; static void pdf_run_contents_object(pdf_csi *csi, pdf_obj *rdb, pdf_obj *contents); static void pdf_run_xobject(pdf_csi *csi, pdf_obj *resources, pdf_xobject *xobj, const fz_matrix *transform); static void pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, pdf_gstate *pat_gstate, const fz_rect *area, int what); static int ocg_intents_include(pdf_ocg_descriptor *desc, char *name) { int i, len; if (strcmp(name, "All") == 0) return 1; /* In the absence of a specified intent, it's 'View' */ if (!desc->intent) return (strcmp(name, "View") == 0); if (pdf_is_name(desc->intent)) { char *intent = pdf_to_name(desc->intent); if (strcmp(intent, "All") == 0) return 1; return (strcmp(intent, name) == 0); } if (!pdf_is_array(desc->intent)) return 0; len = pdf_array_len(desc->intent); for (i=0; i < len; i++) { char *intent = pdf_to_name(pdf_array_get(desc->intent, i)); if (strcmp(intent, "All") == 0) return 1; if (strcmp(intent, name) == 0) return 1; } return 0; } static int pdf_is_hidden_ocg(pdf_obj *ocg, pdf_csi *csi, pdf_obj *rdb) { char event_state[16]; pdf_obj *obj, *obj2; char *type; pdf_ocg_descriptor *desc = csi->doc->ocg; fz_context *ctx = csi->dev->ctx; /* Avoid infinite recursions */ if (pdf_obj_marked(ocg)) return 0; /* If no ocg descriptor, everything is visible */ if (!desc) return 0; /* If we've been handed a name, look it up in the properties. */ if (pdf_is_name(ocg)) { ocg = pdf_dict_gets(pdf_dict_gets(rdb, "Properties"), pdf_to_name(ocg)); } /* If we haven't been given an ocg at all, then we're visible */ if (!ocg) return 0; fz_strlcpy(event_state, csi->event, sizeof event_state); fz_strlcat(event_state, "State", sizeof event_state); type = pdf_to_name(pdf_dict_gets(ocg, "Type")); if (strcmp(type, "OCG") == 0) { /* An Optional Content Group */ int default_value = 0; int num = pdf_to_num(ocg); int gen = pdf_to_gen(ocg); int len = desc->len; int i; /* by default an OCG is visible, unless it's explicitly hidden */ for (i = 0; i < len; i++) { if (desc->ocgs[i].num == num && desc->ocgs[i].gen == gen) { default_value = desc->ocgs[i].state == 0; break; } } /* Check Intents; if our intent is not part of the set given * by the current config, we should ignore it. */ obj = pdf_dict_gets(ocg, "Intent"); if (pdf_is_name(obj)) { /* If it doesn't match, it's hidden */ if (ocg_intents_include(desc, pdf_to_name(obj)) == 0) return 1; } else if (pdf_is_array(obj)) { int match = 0; len = pdf_array_len(obj); for (i=0; i