static void gathershadings(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict) { int i, n; n = pdf_dict_len(dict); for (i = 0; i < n; i++) { pdf_obj *shade; pdf_obj *type; int k; shade = pdf_dict_get_val(dict, i); if (!pdf_is_dict(shade)) { fz_warn(ctx, "not a shading dict (%d %d R)", pdf_to_num(shade), pdf_to_gen(shade)); continue; } type = pdf_dict_gets(shade, "ShadingType"); if (!pdf_is_int(type) || pdf_to_int(type) < 1 || pdf_to_int(type) > 7) { fz_warn(ctx, "not a shading type (%d %d R)", pdf_to_num(shade), pdf_to_gen(shade)); type = NULL; } for (k = 0; k < shadings; k++) if (!pdf_objcmp(shading[k].u.shading.obj, shade)) break; if (k < shadings) continue; shadings++; shading = fz_resize_array(ctx, shading, shadings, sizeof(struct info)); shading[shadings - 1].page = page; shading[shadings - 1].pageref = pageref; shading[shadings - 1].pageobj = pageobj; shading[shadings - 1].u.shading.obj = shade; shading[shadings - 1].u.shading.type = type; } }
decode_params * pdf_decode_params_load(pdf_obj *obj) { decode_params *dp = pdf_malloc(sizeof(decode_params)); if (!obj) return 0; if (!dp) return 0; memset(dp, 0, sizeof(decode_params)); dp->predictor = pdf_to_int(pdf_dict_get(obj, "Predictor")); dp->colors = pdf_to_int(pdf_dict_get(obj, "Colors")); dp->bitspercomponent = pdf_to_int(pdf_dict_get(obj, "BitsPerComponent")); dp->columns = pdf_to_int(pdf_dict_get(obj, "Columns")); dp->earlychange = pdf_to_int(pdf_dict_get(obj, "EarlyChange")); return dp; }
int pdf_count_pages(pdf_document *doc) { if (doc->page_count == 0) { pdf_obj *count = pdf_dict_getp(pdf_trailer(doc), "Root/Pages/Count"); doc->page_count = pdf_to_int(count); } return doc->page_count; }
static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *doc, pdf_obj *dict, char *collection, char *basefont, int iscidfont, int has_encoding) { pdf_obj *obj1, *obj2, *obj3, *obj; char *fontname, *origname; FT_Face face; fz_context *ctx = doc->ctx; /* Prefer BaseFont; don't bother with FontName */ origname = basefont; /* SumatraPDF: handle /BaseFont /Arial,Bold+000041 /FontName /Arial,Bold */ if (strchr(basefont, '+') && pdf_is_name(pdf_dict_gets(dict, "FontName"))) origname = pdf_to_name(pdf_dict_gets(dict, "FontName")); /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1616 */ if (strlen(origname) > 7 && origname[6] == '+') origname += 7; /* Look through list of alternate names for built in fonts */ fontname = clean_font_name(origname); fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags")); fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle")); fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent")); fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent")); fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight")); fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight")); fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth")); obj1 = pdf_dict_gets(dict, "FontFile"); obj2 = pdf_dict_gets(dict, "FontFile2"); obj3 = pdf_dict_gets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (pdf_is_indirect(obj)) { fz_try(ctx) { pdf_load_embedded_font(doc, fontdesc, fontname, obj); } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font"); if (origname != fontname && !iscidfont) pdf_load_builtin_font(ctx, fontdesc, fontname); else pdf_load_system_font(ctx, fontdesc, fontname, collection, has_encoding); } } else { if (origname != fontname && !iscidfont)
ErrorCode juggler_add_pages_from_file(juggler_t *dest, juggler_t *src, int dest_index) { pdf_obj *dest_pages = pdf_dict_getp(dest->ctx, pdf_trailer(dest->ctx, dest->pdf), "Root/Pages"); int dest_pages_index = pdf_array_len(dest->ctx, pdf_dict_gets(dest->ctx, dest_pages, "Kids")); /* be aware that this function does not change the two variables if the page index is greater than the number of pages */ find_destination_pages(dest->ctx, dest_pages, dest_index, &dest_pages, &dest_pages_index); pdf_obj *dest_kids = pdf_dict_gets(dest->ctx, dest_pages, "Kids"); if(!pdf_is_indirect(dest->ctx, dest_pages) || !pdf_is_dict(dest->ctx, dest_pages) || !pdf_is_array(dest->ctx, dest_kids)) { return(ERROR_INVALID_RANGE); } pdf_obj *pages_root = pdf_dict_getp(src->ctx, pdf_trailer(src->ctx, src->pdf), "Root/Pages"); if(!pdf_is_indirect(src->ctx, pages_root) || !pdf_is_dict(src->ctx, pages_root)) return(ERROR_NO_PAGES); /* if we copy the root pages-node and it's referenced objects, we will copy all pages and all objects those pages need */ pdf_obj *new_pages_ref = copy_object_single(dest->ctx, dest->pdf, src->ctx, src->pdf, pages_root); /* insert new pages-node */ pdf_array_insert_drop(dest->ctx, dest_kids, new_pages_ref, dest_pages_index); /* update the parent */ pdf_obj *new_pages_parent = pdf_new_indirect(dest->ctx, dest->pdf, pdf_to_num(dest->ctx, dest_pages), pdf_to_gen(dest->ctx, dest_pages)); pdf_dict_puts_drop(dest->ctx, new_pages_ref, "Parent", new_pages_parent); /* TODO: If dest_pages contains anything inheritable but not the new node we need to insert empty items to prevent this inerhitance */ /* update count */ int new_count = pdf_to_int(dest->ctx, pdf_dict_gets(dest->ctx, dest_pages, "Count")) + src->pagecount; pdf_dict_puts_drop(dest->ctx, dest_pages, "Count", pdf_new_int(dest->ctx, dest->pdf, new_count)); /* let MuPDF rebuild the page tree */ pdf_finish_edit(dest->ctx, dest->pdf); dest->pdf->page_count = new_count; /* update juggler's state */ juggler_page_tree_changed_due_to_insert(dest, dest_index, src->pagecount); return(NoError); }
static fz_buffer * pdf_load_image_stream(fz_context *ctx, pdf_document *doc, int num, int gen, int orig_num, int orig_gen, fz_compression_params *params, int *truncated) { fz_stream *stm = NULL; pdf_obj *dict, *obj; int i, len, n; fz_buffer *buf; fz_var(buf); if (num > 0 && num < pdf_xref_len(ctx, doc)) { pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, num); /* Return ref to existing buffer, but only if uncompressed, * or shortstoppable */ if (can_reuse_buffer(ctx, entry, params)) return fz_keep_buffer(ctx, entry->stm_buf); } dict = pdf_load_object(ctx, doc, num, gen); len = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Length)); obj = pdf_dict_get(ctx, dict, PDF_NAME_Filter); len = pdf_guess_filter_length(len, pdf_to_name(ctx, obj)); n = pdf_array_len(ctx, obj); for (i = 0; i < n; i++) len = pdf_guess_filter_length(len, pdf_to_name(ctx, pdf_array_get(ctx, obj, i))); pdf_drop_obj(ctx, dict); stm = pdf_open_image_stream(ctx, doc, num, gen, orig_num, orig_gen, params); fz_try(ctx) { if (truncated) buf = fz_read_best(ctx, stm, len, truncated); else buf = fz_read_all(ctx, stm, len); } fz_always(ctx) { fz_drop_stream(ctx, stm); } fz_catch(ctx) { fz_rethrow_message(ctx, "cannot read raw stream (%d %d R)", num, gen); } return buf; }
pdf_pattern * pdf_load_pattern(fz_context *ctx, pdf_document *doc, pdf_obj *dict) { pdf_pattern *pat; pdf_obj *obj; if ((pat = pdf_find_item(ctx, pdf_drop_pattern_imp, dict)) != NULL) { return pat; } pat = fz_malloc_struct(ctx, pdf_pattern); FZ_INIT_STORABLE(pat, 1, pdf_drop_pattern_imp); pat->document = doc; pat->resources = NULL; pat->contents = NULL; fz_try(ctx) { /* Store pattern now, to avoid possible recursion if objects refer back to this one */ pdf_store_item(ctx, dict, pat, pdf_pattern_size(pat)); pat->ismask = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_PaintType)) == 2; pat->xstep = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_XStep)); pat->ystep = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_YStep)); obj = pdf_dict_gets(ctx, dict, "BBox"); pdf_to_rect(ctx, obj, &pat->bbox); obj = pdf_dict_gets(ctx, dict, "Matrix"); if (obj) pdf_to_matrix(ctx, obj, &pat->matrix); else pat->matrix = fz_identity; pat->resources = pdf_dict_get(ctx, dict, PDF_NAME_Resources); if (pat->resources) pdf_keep_obj(ctx, pat->resources); pat->contents = pdf_keep_obj(ctx, dict); } fz_catch(ctx) { pdf_remove_item(ctx, pdf_drop_pattern_imp, dict); pdf_drop_pattern(ctx, pat); fz_rethrow_message(ctx, "cannot load pattern (%d %d R)", pdf_to_num(ctx, dict), pdf_to_gen(ctx, dict)); } return pat; }
pdf_pattern * pdf_load_pattern(pdf_document *xref, pdf_obj *dict) { pdf_pattern *pat; pdf_obj *obj; fz_context *ctx = xref->ctx; if ((pat = pdf_find_item(ctx, pdf_free_pattern_imp, dict))) { return pat; } pat = fz_malloc_struct(ctx, pdf_pattern); FZ_INIT_STORABLE(pat, 1, pdf_free_pattern_imp); pat->resources = NULL; pat->contents = NULL; /* Store pattern now, to avoid possible recursion if objects refer back to this one */ pdf_store_item(ctx, dict, pat, pdf_pattern_size(pat)); pat->ismask = pdf_to_int(pdf_dict_gets(dict, "PaintType")) == 2; pat->xstep = pdf_to_real(pdf_dict_gets(dict, "XStep")); pat->ystep = pdf_to_real(pdf_dict_gets(dict, "YStep")); obj = pdf_dict_gets(dict, "BBox"); pdf_to_rect(ctx, obj, &pat->bbox); obj = pdf_dict_gets(dict, "Matrix"); if (obj) pdf_to_matrix(ctx, obj, &pat->matrix); else pat->matrix = fz_identity; pat->resources = pdf_dict_gets(dict, "Resources"); if (pat->resources) pdf_keep_obj(pat->resources); fz_try(ctx) { pat->contents = pdf_keep_obj(dict); } fz_catch(ctx) { pdf_remove_item(ctx, pdf_free_pattern_imp, dict); pdf_drop_pattern(ctx, pat); fz_throw(ctx, "cannot load pattern stream (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict)); } return pat; }
static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *xref, pdf_obj *dict, char *collection, char *basefont) { pdf_obj *obj1, *obj2, *obj3, *obj; char *fontname; char *origname; FT_Face face; fz_context *ctx = xref->ctx; if (!strchr(basefont, ',') || strchr(basefont, '+')) origname = pdf_to_name(pdf_dict_gets(dict, "FontName")); else origname = basefont; fontname = clean_font_name(origname); fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags")); fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle")); fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent")); fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent")); fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight")); fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight")); fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth")); obj1 = pdf_dict_gets(dict, "FontFile"); obj2 = pdf_dict_gets(dict, "FontFile2"); obj3 = pdf_dict_gets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (pdf_is_indirect(obj)) { fz_try(ctx) { pdf_load_embedded_font(fontdesc, xref, obj); } fz_catch(ctx) { fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font"); if (origname != fontname) pdf_load_builtin_font(ctx, fontdesc, fontname); else pdf_load_system_font(ctx, fontdesc, fontname, collection); /* RJW: "cannot load font descriptor (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict) */ } } else { if (origname != fontname)
static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *doc, pdf_obj *dict, char *collection, char *basefont, int iscidfont) { pdf_obj *obj1, *obj2, *obj3, *obj; char *fontname, *origname; FT_Face face; fz_context *ctx = doc->ctx; /* Prefer BaseFont; don't bother with FontName */ origname = basefont; /* Look through list of alternate names for built in fonts */ fontname = clean_font_name(origname); fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags")); fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle")); fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent")); fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent")); fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight")); fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight")); fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth")); obj1 = pdf_dict_gets(dict, "FontFile"); obj2 = pdf_dict_gets(dict, "FontFile2"); obj3 = pdf_dict_gets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (pdf_is_indirect(obj)) { fz_try(ctx) { pdf_load_embedded_font(doc, fontdesc, fontname, obj); } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font"); if (origname != fontname && !iscidfont) pdf_load_builtin_font(ctx, fontdesc, fontname); else pdf_load_system_font(ctx, fontdesc, fontname, collection); } } else { if (origname != fontname && !iscidfont)
static fz_colorspace * load_icc_based(pdf_document *xref, pdf_obj *dict) { int n; n = pdf_to_int(pdf_dict_gets(dict, "N")); switch (n) { case 1: return fz_device_gray; case 3: return fz_device_rgb; case 4: return fz_device_cmyk; } fz_throw(xref->ctx, "syntaxerror: ICCBased must have 1, 3 or 4 components"); return NULL; /* Stupid MSVC */ }
void pdf_delete_page(pdf_document *doc, int at) { pdf_obj *parent, *kids; int i; pdf_lookup_page_loc(doc, at, &parent, &i); kids = pdf_dict_gets(parent, "Kids"); pdf_array_delete(kids, i); while (parent) { int count = pdf_to_int(pdf_dict_gets(parent, "Count")); pdf_dict_puts_drop(parent, "Count", pdf_new_int(doc, count - 1)); parent = pdf_dict_gets(parent, "Parent"); } }
static void pdf_load_transition(pdf_document *doc, pdf_page *page, pdf_obj *transdict) { char *name; pdf_obj *obj; int type; obj = pdf_dict_gets(transdict, "D"); page->transition.duration = (obj ? pdf_to_real(obj) : 1); page->transition.vertical = (pdf_to_name(pdf_dict_gets(transdict, "Dm"))[0] != 'H'); page->transition.outwards = (pdf_to_name(pdf_dict_gets(transdict, "M"))[0] != 'I'); /* FIXME: If 'Di' is None, it should be handled differently, but * this only affects Fly, and we don't implement that currently. */ page->transition.direction = (pdf_to_int(pdf_dict_gets(transdict, "Di"))); /* FIXME: Read SS for Fly when we implement it */ /* FIXME: Read B for Fly when we implement it */ name = pdf_to_name(pdf_dict_gets(transdict, "S")); if (!strcmp(name, "Split")) type = FZ_TRANSITION_SPLIT; else if (!strcmp(name, "Blinds")) type = FZ_TRANSITION_BLINDS; else if (!strcmp(name, "Box")) type = FZ_TRANSITION_BOX; else if (!strcmp(name, "Wipe")) type = FZ_TRANSITION_WIPE; else if (!strcmp(name, "Dissolve")) type = FZ_TRANSITION_DISSOLVE; else if (!strcmp(name, "Glitter")) type = FZ_TRANSITION_GLITTER; else if (!strcmp(name, "Fly")) type = FZ_TRANSITION_FLY; else if (!strcmp(name, "Push")) type = FZ_TRANSITION_PUSH; else if (!strcmp(name, "Cover")) type = FZ_TRANSITION_COVER; else if (!strcmp(name, "Uncover")) type = FZ_TRANSITION_UNCOVER; else if (!strcmp(name, "Fade")) type = FZ_TRANSITION_FADE; else type = FZ_TRANSITION_NONE; page->transition.type = type; }
pdfout_data * pdfout_data_scalar_from_pdf (fz_context *ctx, pdf_obj *obj) { const char *s; if (pdf_is_null (ctx, obj)) return pdfout_data_scalar_new (ctx, "null", strlen ("null")); else if (pdf_is_bool (ctx, obj)) { if (pdf_to_bool (ctx, obj)) s = "true"; else s = "false"; return pdfout_data_scalar_new (ctx, s, strlen (s)); } else if (pdf_is_name (ctx, obj)) { s = pdf_to_name (ctx, obj); return pdfout_data_scalar_new (ctx, s, strlen (s)); } else if (pdf_is_string (ctx, obj)) { int len; char *str = pdfout_str_obj_to_utf8 (ctx, obj, &len); pdfout_data *result = pdfout_data_scalar_new (ctx, str, len); free (str); return result; } else if (pdf_is_int (ctx, obj)) { int n = pdf_to_int (ctx, obj); char buf[200]; int len = pdfout_snprintf (ctx, buf, "%d", n); return pdfout_data_scalar_new (ctx, buf, len); } else if (pdf_is_real (ctx, obj)) { float f = pdf_to_real (ctx, obj); char buf[200]; int len = pdfout_snprintf (ctx, buf, "%g", f); return pdfout_data_scalar_new (ctx, buf, len); } else abort(); }
fz_buffer * pdf_load_image_stream(pdf_document *xref, int num, int gen, int orig_num, int orig_gen, pdf_image_params *params) { fz_context *ctx = xref->ctx; fz_stream *stm = NULL; pdf_obj *dict, *obj; int i, len, n; fz_buffer *buf; fz_var(buf); if (num > 0 && num < xref->len && xref->table[num].stm_buf) return fz_keep_buffer(xref->ctx, xref->table[num].stm_buf); dict = pdf_load_object(xref, num, gen); /* RJW: "cannot load stream dictionary (%d %d R)", num, gen */ len = pdf_to_int(pdf_dict_gets(dict, "Length")); obj = pdf_dict_gets(dict, "Filter"); len = pdf_guess_filter_length(len, pdf_to_name(obj)); n = pdf_array_len(obj); for (i = 0; i < n; i++) len = pdf_guess_filter_length(len, pdf_to_name(pdf_array_get(obj, i))); pdf_drop_obj(dict); stm = pdf_open_image_stream(xref, num, gen, orig_num, orig_gen, params); /* RJW: "cannot open stream (%d %d R)", num, gen */ fz_try(ctx) { buf = fz_read_all(stm, len); } fz_always(ctx) { fz_close(stm); } fz_catch(ctx) { fz_throw(ctx, "cannot read raw stream (%d %d R)", num, gen); } return buf; }
static fz_colorspace * load_icc_based(pdf_document *doc, pdf_obj *dict) { int n; pdf_obj *obj; fz_context *ctx = doc->ctx; n = pdf_to_int(pdf_dict_gets(dict, "N")); obj = pdf_dict_gets(dict, "Alternate"); if (obj) { fz_colorspace *cs_alt = NULL; fz_try(ctx) { cs_alt = pdf_load_colorspace(doc, obj); if (cs_alt->n != n) { fz_drop_colorspace(ctx, cs_alt); fz_throw(ctx, FZ_ERROR_GENERIC, "ICCBased /Alternate colorspace must have %d components", n); } } fz_catch(ctx) { cs_alt = NULL; } if (cs_alt) return cs_alt; } switch (n) { case 1: return fz_device_gray(ctx); case 3: return fz_device_rgb(ctx); case 4: return fz_device_cmyk(ctx); } fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: ICCBased must have 1, 3 or 4 components"); }
void pdf_set_text_annot_position(fz_context *ctx, pdf_document *doc, pdf_annot *annot, fz_point pt) { fz_matrix ctm; fz_rect rect; int flags; fz_invert_matrix(&ctm, &annot->page->ctm); rect.x0 = pt.x; rect.x1 = pt.x + TEXT_ANNOT_SIZE; rect.y0 = pt.y; rect.y1 = pt.y + TEXT_ANNOT_SIZE; fz_transform_rect(&rect, &ctm); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); flags = pdf_to_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_F)); flags |= (F_NoZoom|F_NoRotate); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_F, pdf_new_int(ctx, doc, flags)); update_rect(ctx, annot); }
pdfout_data * pdfout_page_labels_get (fz_context *ctx, pdf_document *doc) { pdf_obj *trailer = pdf_trailer (ctx, doc); pdf_obj *labels_obj = pdf_dict_getp (ctx, trailer, "Root/PageLabels"); pdf_obj *array = pdf_dict_gets (ctx, labels_obj, "Nums"); if (array && pdf_is_array (ctx, array) == false) pdfout_throw (ctx, "Nums is not an array"); int length = pdf_array_len (ctx, array); pdfout_data *labels = pdfout_data_array_new (ctx); for (int i = 0; i < length / 2; ++i) { pdf_obj *object = pdf_array_get (ctx, array, 2 * i); if (pdf_is_int (ctx, object) == false) pdfout_throw (ctx, "key in number tree not an int"); pdfout_data *hash = pdfout_data_hash_new (ctx); int page = pdf_to_int (ctx, object); if (page < 0) pdfout_throw (ctx, "key in number tree is < 0"); push_int_key (ctx, hash, "page", page); pdf_obj *dict = pdf_array_get (ctx, array, 2 * i + 1); if (pdf_is_dict (ctx, dict) == false) pdfout_throw (ctx, "value in number tree not a dict"); parse_dict (ctx, dict, hash); pdfout_data_array_push (ctx, labels, hash); } return labels; }
void pdf_set_text_annot_position(fz_context *ctx, pdf_annot *annot, fz_point pt) { pdf_document *doc = annot->page->doc; fz_matrix page_ctm, inv_page_ctm; fz_rect rect; int flags; pdf_page_transform(ctx, annot->page, NULL, &page_ctm); fz_invert_matrix(&inv_page_ctm, &page_ctm); rect.x0 = pt.x; rect.x1 = pt.x + TEXT_ANNOT_SIZE; rect.y0 = pt.y; rect.y1 = pt.y + TEXT_ANNOT_SIZE; fz_transform_rect(&rect, &inv_page_ctm); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_Rect, pdf_new_rect(ctx, doc, &rect)); flags = pdf_to_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME_F)); flags |= (PDF_ANNOT_IS_NO_ZOOM|PDF_ANNOT_IS_NO_ROTATE); pdf_dict_put_drop(ctx, annot->obj, PDF_NAME_F, pdf_new_int(ctx, doc, flags)); }
static void execute_action(fz_context *ctx, pdf_document *doc, pdf_obj *obj, pdf_obj *a) { if (a) { pdf_obj *type = pdf_dict_get(ctx, a, PDF_NAME_S); if (pdf_name_eq(ctx, type, PDF_NAME_JavaScript)) { pdf_obj *js = pdf_dict_get(ctx, a, PDF_NAME_JS); if (js) { char *code = pdf_to_utf8(ctx, doc, js); fz_try(ctx) { pdf_js_execute(doc->js, code); } fz_always(ctx) { fz_free(ctx, code); } fz_catch(ctx) { fz_rethrow(ctx); } } } else if (pdf_name_eq(ctx, type, PDF_NAME_ResetForm)) { reset_form(ctx, doc, pdf_dict_get(ctx, a, PDF_NAME_Fields), pdf_to_int(ctx, pdf_dict_get(ctx, a, PDF_NAME_Flags)) & 1); } else if (pdf_name_eq(ctx, type, PDF_NAME_Named)) { pdf_obj *name = pdf_dict_get(ctx, a, PDF_NAME_N); if (pdf_name_eq(ctx, name, PDF_NAME_Print)) pdf_event_issue_print(ctx, doc); } }
void pdf_insert_page(pdf_document *doc, pdf_page *page, int at) { int count = pdf_count_pages(doc); pdf_obj *parent, *kids; int i; if (count == 0) { /* TODO: create new page tree? */ fz_throw(doc->ctx, FZ_ERROR_GENERIC, "empty page tree, cannot insert page"); } else if (at >= count) { if (at > count) fz_throw(doc->ctx, FZ_ERROR_GENERIC, "cannot insert page beyond end of page tree"); /* append after last page */ pdf_lookup_page_loc(doc, count - 1, &parent, &i); kids = pdf_dict_gets(parent, "Kids"); pdf_array_insert_drop(kids, pdf_new_ref(doc, page->me), i + 1); } else { /* insert before found page */ pdf_lookup_page_loc(doc, at, &parent, &i); kids = pdf_dict_gets(parent, "Kids"); pdf_array_insert_drop(kids, pdf_new_ref(doc, page->me), i); } /* Adjust page counts */ while (parent) { int count = pdf_to_int(pdf_dict_gets(parent, "Count")); pdf_dict_puts_drop(parent, "Count", pdf_new_int(doc, count + 1)); parent = pdf_dict_gets(parent, "Parent"); } }
static int pdf_count_pages_before_kid(pdf_document *doc, pdf_obj *parent, int kid_num) { pdf_obj *kids = pdf_dict_gets(parent, "Kids"); int i, total = 0, len = pdf_array_len(kids); for (i = 0; i < len; i++) { pdf_obj *kid = pdf_array_get(kids, i); if (pdf_to_num(kid) == kid_num) return total; if (!strcmp(pdf_to_name(pdf_dict_gets(kid, "Type")), "Pages")) { pdf_obj *count = pdf_dict_gets(kid, "Count"); int n = pdf_to_int(count); if (count == NULL || n <= 0) fz_throw(doc->ctx, FZ_ERROR_GENERIC, "illegal or missing count in pages tree"); total += n; } else total++; } fz_throw(doc->ctx, FZ_ERROR_GENERIC, "kid not found in parent's kids array"); }
/* * Load raw (compressed but decrypted) contents of a stream into buf. */ fz_buffer * pdf_load_raw_stream(pdf_document *xref, int num, int gen) { fz_stream *stm; pdf_obj *dict; int len; fz_buffer *buf; dict = pdf_load_object(xref, num, gen); /* RJW: "cannot load stream dictionary (%d %d R)", num, gen */ len = pdf_to_int(pdf_dict_gets(dict, "Length")); pdf_drop_obj(dict); stm = pdf_open_raw_stream(xref, num, gen); /* RJW: "cannot open raw stream (%d %d R)", num, gen */ buf = fz_read_all(stm, len); /* RJW: "cannot read raw stream (%d %d R)", num, gen */ fz_close(stm); return buf; }
static pdf_font_desc * load_cid_font(pdf_document *xref, pdf_obj *dict, pdf_obj *encoding, pdf_obj *to_unicode) { pdf_obj *widths; pdf_obj *descriptor; pdf_font_desc *fontdesc = NULL; FT_Face face; int kind; char collection[256]; char *basefont; int i, k, fterr; pdf_obj *obj; int dw; fz_context *ctx = xref->ctx; fz_var(fontdesc); fz_try(ctx) { /* Get font name and CID collection */ basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont")); { pdf_obj *cidinfo; char tmpstr[64]; int tmplen; cidinfo = pdf_dict_gets(dict, "CIDSystemInfo"); if (!cidinfo) fz_throw(ctx, "cid font is missing info"); obj = pdf_dict_gets(cidinfo, "Registry"); tmplen = fz_mini(sizeof tmpstr - 1, pdf_to_str_len(obj)); memcpy(tmpstr, pdf_to_str_buf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcpy(collection, tmpstr, sizeof collection); fz_strlcat(collection, "-", sizeof collection); obj = pdf_dict_gets(cidinfo, "Ordering"); tmplen = fz_mini(sizeof tmpstr - 1, pdf_to_str_len(obj)); memcpy(tmpstr, pdf_to_str_buf(obj), tmplen); tmpstr[tmplen] = '\0'; fz_strlcat(collection, tmpstr, sizeof collection); } /* Load font file */ fontdesc = pdf_new_font_desc(ctx); descriptor = pdf_dict_gets(dict, "FontDescriptor"); if (!descriptor) fz_throw(ctx, "syntaxerror: missing font descriptor"); pdf_load_font_descriptor(fontdesc, xref, descriptor, collection, basefont); face = fontdesc->font->ft_face; kind = ft_kind(face); /* Encoding */ if (pdf_is_name(encoding)) { if (!strcmp(pdf_to_name(encoding), "Identity-H")) fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 2); else if (!strcmp(pdf_to_name(encoding), "Identity-V")) fontdesc->encoding = pdf_new_identity_cmap(ctx, 1, 2); else fontdesc->encoding = pdf_load_system_cmap(ctx, pdf_to_name(encoding)); } else if (pdf_is_indirect(encoding)) { fontdesc->encoding = pdf_load_embedded_cmap(xref, encoding); } else { fz_throw(ctx, "syntaxerror: font missing encoding"); } fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding); pdf_set_font_wmode(ctx, fontdesc, pdf_cmap_wmode(ctx, fontdesc->encoding)); if (kind == TRUETYPE) { pdf_obj *cidtogidmap; cidtogidmap = pdf_dict_gets(dict, "CIDToGIDMap"); if (pdf_is_indirect(cidtogidmap)) { fz_buffer *buf; buf = pdf_load_stream(xref, pdf_to_num(cidtogidmap), pdf_to_gen(cidtogidmap)); fontdesc->cid_to_gid_len = (buf->len) / 2; fontdesc->cid_to_gid = fz_malloc_array(ctx, fontdesc->cid_to_gid_len, sizeof(unsigned short)); fontdesc->size += fontdesc->cid_to_gid_len * sizeof(unsigned short); for (i = 0; i < fontdesc->cid_to_gid_len; i++) fontdesc->cid_to_gid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; fz_drop_buffer(ctx, buf); } /* if truetype font is external, cidtogidmap should not be identity */ /* so we map from cid to unicode and then map that through the (3 1) */ /* unicode cmap to get a glyph id */ else if (fontdesc->font->ft_substitute) { fterr = FT_Select_Charmap(face, ft_encoding_unicode); if (fterr) { fz_throw(ctx, "fonterror: no unicode cmap when emulating CID font: %s", ft_error_string(fterr)); } if (!strcmp(collection, "Adobe-CNS1")) fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan2-UCS2"); else if (!strcmp(collection, "Adobe-Korea1")) fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Korea1-UCS2"); } } pdf_load_to_unicode(xref, fontdesc, NULL, collection, to_unicode); /* Horizontal */ dw = 1000; obj = pdf_dict_gets(dict, "DW"); if (obj) dw = pdf_to_int(obj); pdf_set_default_hmtx(ctx, fontdesc, dw); widths = pdf_dict_gets(dict, "W"); if (widths) { int c0, c1, w, n, m; n = pdf_array_len(widths); for (i = 0; i < n; ) { c0 = pdf_to_int(pdf_array_get(widths, i)); obj = pdf_array_get(widths, i + 1); if (pdf_is_array(obj)) { m = pdf_array_len(obj); for (k = 0; k < m; k++) { w = pdf_to_int(pdf_array_get(obj, k)); pdf_add_hmtx(ctx, fontdesc, c0 + k, c0 + k, w); } i += 2; } else { c1 = pdf_to_int(obj); w = pdf_to_int(pdf_array_get(widths, i + 2)); pdf_add_hmtx(ctx, fontdesc, c0, c1, w); i += 3; } } } pdf_end_hmtx(ctx, fontdesc); /* Vertical */ if (pdf_cmap_wmode(ctx, fontdesc->encoding) == 1) { int dw2y = 880; int dw2w = -1000; obj = pdf_dict_gets(dict, "DW2"); if (obj) { dw2y = pdf_to_int(pdf_array_get(obj, 0)); dw2w = pdf_to_int(pdf_array_get(obj, 1)); } pdf_set_default_vmtx(ctx, fontdesc, dw2y, dw2w); widths = pdf_dict_gets(dict, "W2"); if (widths) { int c0, c1, w, x, y, n; n = pdf_array_len(widths); for (i = 0; i < n; ) { c0 = pdf_to_int(pdf_array_get(widths, i)); obj = pdf_array_get(widths, i + 1); if (pdf_is_array(obj)) { int m = pdf_array_len(obj); for (k = 0; k * 3 < m; k ++) { w = pdf_to_int(pdf_array_get(obj, k * 3 + 0)); x = pdf_to_int(pdf_array_get(obj, k * 3 + 1)); y = pdf_to_int(pdf_array_get(obj, k * 3 + 2)); pdf_add_vmtx(ctx, fontdesc, c0 + k, c0 + k, x, y, w); } i += 2; } else { c1 = pdf_to_int(obj); w = pdf_to_int(pdf_array_get(widths, i + 2)); x = pdf_to_int(pdf_array_get(widths, i + 3)); y = pdf_to_int(pdf_array_get(widths, i + 4)); pdf_add_vmtx(ctx, fontdesc, c0, c1, x, y, w); i += 5; } } } pdf_end_vmtx(ctx, fontdesc); } } fz_catch(ctx) { pdf_drop_font(ctx, fontdesc); fz_throw(ctx, "cannot load cid font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict)); } return fontdesc; }
static pdf_font_desc * pdf_load_simple_font(pdf_document *xref, pdf_obj *dict) { pdf_obj *descriptor; pdf_obj *encoding; pdf_obj *widths; unsigned short *etable = NULL; pdf_font_desc *fontdesc = NULL; char *subtype; FT_Face face; FT_CharMap cmap; int symbolic; int kind; char *basefont; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; fz_context *ctx = xref->ctx; fz_var(fontdesc); fz_var(etable); basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont")); /* Load font file */ fz_try(ctx) { fontdesc = pdf_new_font_desc(ctx); descriptor = pdf_dict_gets(dict, "FontDescriptor"); if (descriptor) pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont); else pdf_load_builtin_font(ctx, fontdesc, basefont); /* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */ if (descriptor && pdf_is_string(pdf_dict_gets(descriptor, "FontName")) && !pdf_dict_gets(dict, "ToUnicode") && !strcmp(pdf_to_name(pdf_dict_gets(dict, "Encoding")), "WinAnsiEncoding") && pdf_to_int(pdf_dict_gets(descriptor, "Flags")) == 4) { char *cp936fonts[] = { "\xCB\xCE\xCC\xE5", "SimSun,Regular", "\xBA\xDA\xCC\xE5", "SimHei,Regular", "\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular", "\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular", "\xC1\xA5\xCA\xE9", "SimLi,Regular", NULL }; for (i = 0; cp936fonts[i]; i += 2) if (!strcmp(basefont, cp936fonts[i])) break; if (cp936fonts[i]) { fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings"); pdf_drop_font(ctx, fontdesc); fontdesc = pdf_new_font_desc(ctx); pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]); fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H"); fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); face = fontdesc->font->ft_face; kind = ft_kind(face); goto skip_encoding; } } face = fontdesc->font->ft_face; kind = ft_kind(face); /* Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = NULL; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; if (symbolic && test->platform_id == 3 && test->encoding_id == 0) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr)); } else fz_warn(ctx, "freetype could not find any cmaps"); etable = fz_malloc_array(ctx, 256, sizeof(unsigned short)); fontdesc->size += 256 * sizeof(unsigned short); for (i = 0; i < 256; i++) { estrings[i] = NULL; etable[i] = 0; } encoding = pdf_dict_gets(dict, "Encoding"); if (encoding) { if (pdf_is_name(encoding)) pdf_load_encoding(estrings, pdf_to_name(encoding)); if (pdf_is_dict(encoding)) { pdf_obj *base, *diff, *item; base = pdf_dict_gets(encoding, "BaseEncoding"); if (pdf_is_name(base)) pdf_load_encoding(estrings, pdf_to_name(base)); else if (!fontdesc->is_embedded && !symbolic) pdf_load_encoding(estrings, "StandardEncoding"); diff = pdf_dict_gets(encoding, "Differences"); if (pdf_is_array(diff)) { n = pdf_array_len(diff); k = 0; for (i = 0; i < n; i++) { item = pdf_array_get(diff, i); if (pdf_is_int(item)) k = pdf_to_int(item); if (pdf_is_name(item) && k >= 0 && k < nelem(estrings)) estrings[k++] = pdf_to_name(item); } } } } /* start with the builtin encoding */ for (i = 0; i < 256; i++) etable[i] = ft_char_index(face, i); fz_lock(ctx, FZ_LOCK_FREETYPE); /* built-in and substitute fonts may be a different type than what the document expects */ subtype = pdf_to_name(pdf_dict_gets(dict, "Subtype")); if (!strcmp(subtype, "Type1")) kind = TYPE1; else if (!strcmp(subtype, "MMType1")) kind = TYPE1; else if (!strcmp(subtype, "TrueType")) kind = TRUETYPE; else if (!strcmp(subtype, "CIDFontType0")) kind = TYPE1; else if (!strcmp(subtype, "CIDFontType2")) kind = TRUETYPE; /* encode by glyph name where we can */ if (kind == TYPE1) { for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) { int aglcode = pdf_lookup_agl(estrings[i]); const char **dupnames = pdf_lookup_agl_duplicates(aglcode); while (*dupnames) { etable[i] = FT_Get_Name_Index(face, (char*)*dupnames); if (etable[i]) break; dupnames++; } } } } } /* encode by glyph name where we can */ if (kind == TRUETYPE) { /* Unicode cmap */ if (!symbolic && face->charmap && face->charmap->platform_id == 3) { for (i = 0; i < 256; i++) { if (estrings[i]) { int aglcode = pdf_lookup_agl(estrings[i]); if (!aglcode) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ft_char_index(face, aglcode); } } } /* MacRoman cmap */ else if (!symbolic && face->charmap && face->charmap->platform_id == 1) { for (i = 0; i < 256; i++) { if (estrings[i]) { k = lookup_mre_code(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ft_char_index(face, k); } } } /* Symbolic cmap */ else if (!face->charmap || face->charmap->encoding != FT_ENCODING_MS_SYMBOL) { for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) etable[i] = ft_char_index(face, i); } } } } /* try to reverse the glyph names from the builtin encoding */ for (i = 0; i < 256; i++) { if (etable[i] && !estrings[i]) { if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr)); if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } else { estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */ } } } /* symbolic Type 1 fonts with an implicit encoding and non-standard glyph names */ if (kind == TYPE1 && symbolic) { for (i = 0; i < 256; i++) if (etable[i] && estrings[i] && !pdf_lookup_agl(estrings[i])) estrings[i] = (char*) pdf_standard[i]; } fz_unlock(ctx, FZ_LOCK_FREETYPE); fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1); fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding); fontdesc->cid_to_gid_len = 256; fontdesc->cid_to_gid = etable; fz_try(ctx) { pdf_load_to_unicode(xref, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode")); } fz_catch(ctx) { fz_warn(ctx, "cannot load ToUnicode CMap"); } skip_encoding: /* Widths */ pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width); widths = pdf_dict_gets(dict, "Widths"); if (widths) { int first, last; first = pdf_to_int(pdf_dict_gets(dict, "FirstChar")); last = pdf_to_int(pdf_dict_gets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = pdf_to_int(pdf_array_get(widths, i)); pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid); } } else { fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr)); for (i = 0; i < 256; i++) { pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i)); } fz_unlock(ctx, FZ_LOCK_FREETYPE); } pdf_end_hmtx(ctx, fontdesc); } fz_catch(ctx) { if (fontdesc && etable != fontdesc->cid_to_gid) fz_free(ctx, etable); pdf_drop_font(ctx, fontdesc); fz_throw(ctx, "cannot load simple font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict)); } return fontdesc; }
static pdf_image * pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask) { fz_stream *stm = NULL; pdf_image *image = NULL; pdf_obj *obj, *res; int w, h, bpc, n; int imagemask; int interpolate; int indexed; fz_image *mask = NULL; /* explicit mask/soft mask image */ int usecolorkey; int i; fz_context *ctx = xref->ctx; fz_var(stm); fz_var(mask); image = fz_malloc_struct(ctx, pdf_image); fz_try(ctx) { /* special case for JPEG2000 images */ if (pdf_is_jpx_image(ctx, dict)) { pdf_load_jpx(xref, dict, image, forcemask); if (forcemask) { fz_pixmap *mask_pixmap; if (image->n != 2) fz_throw(ctx, "soft mask must be grayscale"); mask_pixmap = fz_alpha_from_gray(ctx, image->tile, 1); fz_drop_pixmap(ctx, image->tile); image->tile = mask_pixmap; } break; /* Out of fz_try */ } w = pdf_to_int(pdf_dict_getsa(dict, "Width", "W")); h = pdf_to_int(pdf_dict_getsa(dict, "Height", "H")); bpc = pdf_to_int(pdf_dict_getsa(dict, "BitsPerComponent", "BPC")); if (bpc == 0) bpc = 8; imagemask = pdf_to_bool(pdf_dict_getsa(dict, "ImageMask", "IM")); interpolate = pdf_to_bool(pdf_dict_getsa(dict, "Interpolate", "I")); indexed = 0; usecolorkey = 0; mask = NULL; if (imagemask) bpc = 1; if (w <= 0) fz_throw(ctx, "image width is zero (or less)"); if (h <= 0) fz_throw(ctx, "image height is zero (or less)"); if (bpc <= 0) fz_throw(ctx, "image depth is zero (or less)"); if (bpc > 16) fz_throw(ctx, "image depth is too large: %d", bpc); if (w > (1 << 16)) fz_throw(ctx, "image is too wide"); if (h > (1 << 16)) fz_throw(ctx, "image is too high"); obj = pdf_dict_getsa(dict, "ColorSpace", "CS"); if (obj && !imagemask && !forcemask) { /* colorspace resource lookup is only done for inline images */ if (pdf_is_name(obj)) { res = pdf_dict_get(pdf_dict_gets(rdb, "ColorSpace"), obj); if (res) obj = res; } image->base.colorspace = pdf_load_colorspace(xref, obj); if (!strcmp(image->base.colorspace->name, "Indexed")) indexed = 1; n = image->base.colorspace->n; } else { n = 1; } obj = pdf_dict_getsa(dict, "Decode", "D"); if (obj) { for (i = 0; i < n * 2; i++) image->decode[i] = pdf_to_real(pdf_array_get(obj, i)); } else { float maxval = indexed ? (1 << bpc) - 1 : 1; for (i = 0; i < n * 2; i++) image->decode[i] = i & 1 ? maxval : 0; } obj = pdf_dict_getsa(dict, "SMask", "Mask"); if (pdf_is_dict(obj)) { /* Not allowed for inline images or soft masks */ if (cstm) fz_warn(ctx, "Ignoring invalid inline image soft mask"); else if (forcemask) fz_warn(ctx, "Ignoring recursive image soft mask"); else mask = (fz_image *)pdf_load_image_imp(xref, rdb, obj, NULL, 1); } else if (pdf_is_array(obj)) { usecolorkey = 1; for (i = 0; i < n * 2; i++) { if (!pdf_is_int(pdf_array_get(obj, i))) { fz_warn(ctx, "invalid value in color key mask"); usecolorkey = 0; } image->colorkey[i] = pdf_to_int(pdf_array_get(obj, i)); } } /* Now, do we load a ref, or do we load the actual thing? */ FZ_INIT_STORABLE(&image->base, 1, pdf_free_image); image->base.get_pixmap = pdf_image_get_pixmap; image->base.w = w; image->base.h = h; image->base.bpc = bpc; image->n = n; image->interpolate = interpolate; image->imagemask = imagemask; image->usecolorkey = usecolorkey; image->base.mask = mask; if (!cstm) { /* Just load the compressed image data now and we can * decode it on demand. */ int num = pdf_to_num(dict); int gen = pdf_to_gen(dict); image->buffer = pdf_load_compressed_stream(xref, num, gen); break; /* Out of fz_try */ } /* We need to decompress the image now */ if (cstm) { int stride = (w * image->n * image->base.bpc + 7) / 8; stm = pdf_open_inline_stream(xref, dict, stride * h, cstm, NULL); } else { stm = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict)); } image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 0, 0, 0); } fz_catch(ctx) { pdf_free_image(ctx, (fz_storable *) image); fz_rethrow(ctx); } return image; }
static fz_colorspace * load_indexed(pdf_document *xref, pdf_obj *array) { struct indexed *idx = NULL; fz_context *ctx = xref->ctx; pdf_obj *baseobj = pdf_array_get(array, 1); pdf_obj *highobj = pdf_array_get(array, 2); pdf_obj *lookup = pdf_array_get(array, 3); fz_colorspace *base = NULL; fz_colorspace *cs = NULL; int i, n; fz_var(idx); fz_var(base); fz_var(cs); fz_try(ctx) { base = pdf_load_colorspace(xref, baseobj); /* "cannot load base colorspace (%d %d R)", pdf_to_num(baseobj), pdf_to_gen(baseobj) */ idx = fz_malloc_struct(ctx, struct indexed); idx->lookup = NULL; idx->base = base; idx->high = pdf_to_int(highobj); idx->high = CLAMP(idx->high, 0, 255); n = base->n * (idx->high + 1); idx->lookup = fz_malloc_array(ctx, 1, n); cs = fz_new_colorspace(ctx, "Indexed", 1); cs->to_rgb = indexed_to_rgb; cs->free_data = free_indexed; cs->data = idx; cs->size += sizeof(*idx) + n + (base ? base->size : 0); if (pdf_is_string(lookup) && pdf_to_str_len(lookup) == n) { unsigned char *buf = (unsigned char *) pdf_to_str_buf(lookup); for (i = 0; i < n; i++) idx->lookup[i] = buf[i]; } else if (pdf_is_indirect(lookup)) { fz_stream *file = NULL; fz_try(ctx) { file = pdf_open_stream(xref, pdf_to_num(lookup), pdf_to_gen(lookup)); } fz_catch(ctx) { fz_throw(ctx, "cannot open colorspace lookup table (%d 0 R)", pdf_to_num(lookup)); } i = fz_read(file, idx->lookup, n); if (i < 0) { fz_close(file); fz_throw(ctx, "cannot read colorspace lookup table (%d 0 R)", pdf_to_num(lookup)); } fz_close(file); } else { fz_throw(ctx, "cannot parse colorspace lookup table"); } }
{ pdf_js_execute(doc->js, code); } fz_always(ctx) { fz_free(ctx, code); } fz_catch(ctx) { fz_rethrow(ctx); } } } else if (!strcmp(type, "ResetForm")) { reset_form(doc, pdf_dict_gets(a, "Fields"), pdf_to_int(pdf_dict_gets(a, "Flags")) & 1); } else if (!strcmp(type, "Named")) { char *name = pdf_to_name(pdf_dict_gets(a, "N")); if (!strcmp(name, "Print")) pdf_event_issue_print(doc); } } } void pdf_update_appearance(pdf_document *doc, pdf_annot *annot) { pdf_obj *obj = annot->obj; if (!pdf_dict_gets(obj, "AP") || pdf_obj_is_dirty(obj))
pdf_err pdf_encrypt_load(pdf_obj *o, pdf_encrypt **encrypt) { pdf_obj *a; pdf_encrypt *e; if (!o) return pdf_ok; pdf_obj_resolve(o); if (!o) return pdf_ok; *encrypt = pdf_malloc(sizeof(pdf_encrypt)); if (!*encrypt) return pdf_mem_err; memset(*encrypt, 0, sizeof(pdf_encrypt)); e = *encrypt; e->v = 0; a = pdf_dict_get(o, "Filter"); if (a) { pdf_obj_resolve(a); (*encrypt)->filter = pdf_malloc(strlen(a->value.k)+1); memcpy((*encrypt)->filter, a->value.k, strlen(a->value.k)); (*encrypt)->filter[strlen(a->value.k)] = 0; } a = pdf_dict_get(o, "SubFilter"); if (a) { pdf_obj_resolve(a); (*encrypt)->subfilter = pdf_malloc(strlen(a->value.k)+1); memcpy((*encrypt)->subfilter, a->value.k, strlen(a->value.k)); (*encrypt)->subfilter[strlen(a->value.k)] = 0; } a = pdf_dict_get(o, "V"); if (a) { (*encrypt)->v = pdf_to_int(a); } e->length = 40; a = pdf_dict_get(o, "Length"); if (a) { (*encrypt)->length = pdf_to_int(a); } if (e->v == 4) { pdf_obj *cf = pdf_dict_get(o, "CF"); if (cf) { a = pdf_dict_get(o, "StmF"); if (a) { pdf_obj_resolve(a); pdf_cf_load(e, cf, a->value.k, &e->stmf); } a = pdf_dict_get(o, "StrF"); if (a) { pdf_obj_resolve(a); pdf_cf_load(e, cf, a->value.k, &e->strf); } a = pdf_dict_get(o, "EFF"); if (a) { pdf_obj_resolve(a); pdf_cf_load(e, cf, a->value.k, &e->eff); } } } // standard encryption dictionary (items) a = pdf_dict_get(o, "R"); if (a) { (*encrypt)->r = pdf_to_int(a); } a = pdf_dict_get(o, "O"); // owner password if (a) { // should verify length to 32 bytes pdf_obj_resolve(a); memcpy((*encrypt)->o, a->value.s.buf, a->value.s.len); } a = pdf_dict_get(o, "U"); // user password if (a) { // should verify length to 32 bytes pdf_obj_resolve(a); memcpy((*encrypt)->u, a->value.s.buf, a->value.s.len); } a = pdf_dict_get(o, "P"); // permission flags if (a) { (*encrypt)->p = pdf_to_int(a); } a = pdf_dict_get(o, "EncryptMetadata"); if (a) { pdf_obj_resolve(a); (*encrypt)->encrypt_metadata = a->value.b; } return pdf_ok; }
pdf_err pdf_page_load(pdf_doc *doc, pdf_obj *o, pdf_page **page) { pdf_page *p; pdf_obj *mediabox; pdf_obj *v; if (o->t != eRef) return pdf_syntax_err; *page = pdf_malloc(sizeof(pdf_page)); p = *page; memset(p, 0, sizeof(pdf_page)); p->ref = *o; // parse tree dict p->parent = pdf_dict_get(o, "Parent"); mediabox = pdf_dict_get(o, "MediaBox"); if (mediabox) p->mediabox = pdf_rect_get(mediabox); else { gs_rect *r = doc->get_mediabox(doc); if (r) p->mediabox = *r; } p->resources = pdf_resources_load(pdf_dict_get(o, "Resources")); // optionals p->contents = pdf_dict_get(o, "Contents"); v = (pdf_obj*)pdf_dict_get(o, "Rotate"); if (v) { p->rotate = v->value.i; if (p->rotate < 0) p->rotate = 360 - ((-p->rotate) % 360); if (p->rotate >= 360) p->rotate = p->rotate % 360; p->rotate = 90*((p->rotate + 45)/90); if (p->rotate > 360) p->rotate = 0; if (p->rotate == 90 || p->rotate == 270) { float x = p->mediabox.y1; p->mediabox.y1 = p->mediabox.x1; p->mediabox.x1 = x; } } p->group = pdf_group_load(pdf_dict_get(o, "Group")); p->cropbox = pdf_dict_get(o, "CropBox"); p->bleedbox = pdf_dict_get(o, "BleedBox"); p->trimbox = pdf_dict_get(o, "TrimBox"); p->artbox = pdf_dict_get(o, "ArtBox"); p->boxcolorinfo = pdf_dict_get(o, "BoxColorInfo"); p->thumb = pdf_dict_get(o, "Thumb"); p->b = pdf_dict_get(o, "b"); p->dur = pdf_to_float(pdf_dict_get(o, "Dur")); p->trans = pdf_dict_get(o, "Trans"); p->annots = pdf_annots_load(pdf_dict_get(o, "Annots")); p->aa = pdf_dict_get(o, "AA"); p->metadata = pdf_dict_get(o, "Metadata"); p->pieceinfo = pdf_dict_get(o, "PieceInfo"); p->structparents = pdf_to_int(pdf_dict_get(o, "StructParents")); p->id = pdf_to_int(pdf_dict_get(o, "ID")); p->pz = pdf_to_float(pdf_dict_get(o, "PZ")); p->separationinfo = pdf_dict_get(o, "SeparationInfo"); p->tabs = pdf_dict_get(o, "Tabs"); p->templateinstantiated = pdf_dict_get(o, "TemplateInstantiated"); p->pressteps = pdf_dict_get(o, "PresSteps"); p->userunit = pdf_to_float(pdf_dict_get(o, "UserUnit")); p->vp = pdf_dict_get(o, "VP"); // required depends p->lastmodified = pdf_dict_get(o, "LastModified"); return pdf_ok; }