#include "pdf-interpret-imp.h" #define TILE /* * Emit graphics calls to device. */ typedef struct pdf_material_s pdf_material; 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; }; typedef struct pdf_run_state_s { fz_context *ctx; fz_device *dev; pdf_csi *csi; int nested_depth; int in_hidden_ocg; /* path object state */ fz_path *path; int clip; int clip_even_odd; const char *event; /* 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; } pdf_run_state; typedef struct softmask_save_s softmask_save; struct softmask_save_s { pdf_xobject *softmask; fz_matrix ctm; }; static void run_xobject(pdf_csi *csi, void *state, pdf_obj *resources, pdf_xobject *xobj, const fz_matrix *transform); 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; } int pdf_is_hidden_ocg(pdf_obj *ocg, pdf_csi *csi, pdf_run_state *pr, pdf_obj *rdb) { char event_state[16]; pdf_obj *obj, *obj2; char *type; pdf_ocg_descriptor *desc = csi->doc->ocg; fz_context *ctx = csi->doc->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, pr->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