void pdf_update_annot(pdf_document *doc, pdf_annot *annot) { /* SumatraPDF: prevent regressions */ #if 0 pdf_obj *obj, *ap, *as, *n; fz_context *ctx = doc->ctx; if (doc->update_appearance) doc->update_appearance(doc, annot); obj = annot->obj; ap = pdf_dict_gets(obj, "AP"); as = pdf_dict_gets(obj, "AS"); if (pdf_is_dict(ap)) { pdf_hotspot *hp = &doc->hotspot; n = NULL; if (hp->num == pdf_to_num(obj) && hp->gen == pdf_to_gen(obj) && (hp->state & HOTSPOT_POINTER_DOWN)) { n = pdf_dict_gets(ap, "D"); /* down state */ } if (n == NULL) n = pdf_dict_gets(ap, "N"); /* normal state */ /* lookup current state in sub-dictionary */ if (!pdf_is_stream(doc, pdf_to_num(n), pdf_to_gen(n))) n = pdf_dict_get(n, as); pdf_drop_xobject(ctx, annot->ap); annot->ap = NULL; if (pdf_is_stream(doc, pdf_to_num(n), pdf_to_gen(n))) { fz_try(ctx) { annot->ap = pdf_load_xobject(doc, n); pdf_transform_annot(annot); annot->ap_iteration = annot->ap->iteration; } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "ignoring broken annotation"); } } } #endif }
void pdf_free_annot(fz_context *ctx, pdf_annot *annot) { if (annot->next) pdf_free_annot(ctx, annot->next); if (annot->ap) pdf_drop_xobject(ctx, annot->ap); if (annot->obj) fz_drop_obj(ctx, annot->obj); fz_free(ctx, annot); }
void pdf_update_annot(fz_context *ctx, pdf_document *doc, pdf_annot *annot) { pdf_obj *obj, *ap, *as, *n; if (doc->update_appearance) doc->update_appearance(ctx, doc, annot); obj = annot->obj; ap = pdf_dict_get(ctx, obj, PDF_NAME_AP); as = pdf_dict_get(ctx, obj, PDF_NAME_AS); if (pdf_is_dict(ctx, ap)) { pdf_hotspot *hp = &doc->hotspot; n = NULL; if (hp->num == pdf_to_num(ctx, obj) && hp->gen == pdf_to_gen(ctx, obj) && (hp->state & HOTSPOT_POINTER_DOWN)) { n = pdf_dict_get(ctx, ap, PDF_NAME_D); /* down state */ } if (n == NULL) n = pdf_dict_get(ctx, ap, PDF_NAME_N); /* normal state */ /* lookup current state in sub-dictionary */ if (!pdf_is_stream(ctx, doc, pdf_to_num(ctx, n), pdf_to_gen(ctx, n))) n = pdf_dict_get(ctx, n, as); pdf_drop_xobject(ctx, annot->ap); annot->ap = NULL; if (pdf_is_stream(ctx, doc, pdf_to_num(ctx, n), pdf_to_gen(ctx, n))) { fz_try(ctx) { annot->ap = pdf_load_xobject(ctx, doc, n); pdf_transform_annot(ctx, annot); annot->ap_iteration = annot->ap->iteration; } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "ignoring broken annotation"); } } } }
void pdf_free_annot(fz_context *ctx, pdf_annot *annot) { pdf_annot *next; do { next = annot->next; if (annot->ap) pdf_drop_xobject(ctx, annot->ap); pdf_drop_obj(annot->obj); fz_free(ctx, annot); annot = next; } while (annot); }
static void pdf_prepend_ap_background(fz_buffer *content, pdf_xref *xref, fz_obj *obj) { fz_context *ctx = xref->ctx; pdf_xobject *form; int i; fz_obj *ap = pdf_get_ap_stream(xref, obj); if (!ap) return; if (pdf_load_xobject(&form, xref, ap) != fz_okay) return; for (i = 0; i < form->contents->len - 3 && memcmp(form->contents->data + i, "/Tx", 3) != 0; i++); if (i == form->contents->len - 3) i = form->contents->len; if (content->cap < content->len + i) fz_resize_buffer(ctx, content, content->len + i); memcpy(content->data + content->len, form->contents->data, i); content->len += i; pdf_drop_xobject(ctx, form); }
static void pdf_process_extgstate(fz_context *ctx, pdf_processor *proc, pdf_csi *csi, pdf_obj *dict) { pdf_obj *obj; obj = pdf_dict_get(ctx, dict, PDF_NAME_LW); if (pdf_is_number(ctx, obj) && proc->op_w) proc->op_w(ctx, proc, pdf_to_real(ctx, obj)); obj = pdf_dict_get(ctx, dict, PDF_NAME_LC); if (pdf_is_int(ctx, obj) && proc->op_J) proc->op_J(ctx, proc, fz_clampi(pdf_to_int(ctx, obj), 0, 2)); obj = pdf_dict_get(ctx, dict, PDF_NAME_LJ); if (pdf_is_int(ctx, obj) && proc->op_j) proc->op_j(ctx, proc, fz_clampi(pdf_to_int(ctx, obj), 0, 2)); obj = pdf_dict_get(ctx, dict, PDF_NAME_ML); if (pdf_is_number(ctx, obj) && proc->op_M) proc->op_M(ctx, proc, pdf_to_real(ctx, obj)); obj = pdf_dict_get(ctx, dict, PDF_NAME_D); if (pdf_is_array(ctx, obj) && proc->op_d) { pdf_obj *dash_array = pdf_array_get(ctx, obj, 0); pdf_obj *dash_phase = pdf_array_get(ctx, obj, 1); proc->op_d(ctx, proc, dash_array, pdf_to_real(ctx, dash_phase)); } obj = pdf_dict_get(ctx, dict, PDF_NAME_RI); if (pdf_is_name(ctx, obj) && proc->op_ri) proc->op_ri(ctx, proc, pdf_to_name(ctx, obj)); obj = pdf_dict_get(ctx, dict, PDF_NAME_FL); if (pdf_is_number(ctx, obj) && proc->op_i) proc->op_i(ctx, proc, pdf_to_real(ctx, obj)); obj = pdf_dict_get(ctx, dict, PDF_NAME_Font); if (pdf_is_array(ctx, obj) && proc->op_Tf) { pdf_obj *font_ref = pdf_array_get(ctx, obj, 0); pdf_obj *font_size = pdf_array_get(ctx, obj, 1); pdf_font_desc *font = load_font_or_hail_mary(ctx, csi->doc, csi->rdb, font_ref, 0, csi->cookie); fz_try(ctx) proc->op_Tf(ctx, proc, "ExtGState", font, pdf_to_real(ctx, font_size)); fz_always(ctx) pdf_drop_font(ctx, font); fz_catch(ctx) fz_rethrow(ctx); } /* transfer functions */ obj = pdf_dict_get(ctx, dict, PDF_NAME_TR2); if (pdf_is_name(ctx, obj)) if (!pdf_name_eq(ctx, obj, PDF_NAME_Identity) && !pdf_name_eq(ctx, obj, PDF_NAME_Default)) fz_warn(ctx, "ignoring transfer function"); if (!obj) /* TR is ignored in the presence of TR2 */ { pdf_obj *tr = pdf_dict_get(ctx, dict, PDF_NAME_TR); if (pdf_is_name(ctx, tr)) if (!pdf_name_eq(ctx, tr, PDF_NAME_Identity)) fz_warn(ctx, "ignoring transfer function"); } /* transparency state */ obj = pdf_dict_get(ctx, dict, PDF_NAME_CA); if (pdf_is_number(ctx, obj) && proc->op_gs_CA) proc->op_gs_CA(ctx, proc, pdf_to_real(ctx, obj)); obj = pdf_dict_get(ctx, dict, PDF_NAME_ca); if (pdf_is_number(ctx, obj) && proc->op_gs_ca) proc->op_gs_ca(ctx, proc, pdf_to_real(ctx, obj)); obj = pdf_dict_get(ctx, dict, PDF_NAME_BM); if (pdf_is_array(ctx, obj)) obj = pdf_array_get(ctx, obj, 0); if (pdf_is_name(ctx, obj) && proc->op_gs_BM) proc->op_gs_BM(ctx, proc, pdf_to_name(ctx, obj)); obj = pdf_dict_get(ctx, dict, PDF_NAME_SMask); if (proc->op_gs_SMask) { if (pdf_is_dict(ctx, obj)) { pdf_xobject *xobj; pdf_obj *group, *s, *bc, *tr; float softmask_bc[FZ_MAX_COLORS]; fz_colorspace *colorspace; int colorspace_n = 1; int k, luminosity; fz_var(xobj); group = pdf_dict_get(ctx, obj, PDF_NAME_G); if (!group) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot load softmask xobject (%d 0 R)", pdf_to_num(ctx, obj)); xobj = pdf_load_xobject(ctx, csi->doc, group); fz_try(ctx) { colorspace = pdf_xobject_colorspace(ctx, xobj); if (colorspace) { colorspace_n = fz_colorspace_n(ctx, colorspace); fz_drop_colorspace(ctx, colorspace); } /* Default background color is black. */ for (k = 0; k < colorspace_n; k++) softmask_bc[k] = 0; /* Which in CMYK means not all zeros! This should really be * a test for subtractive color spaces, but this will have * to do for now. */ if (colorspace == fz_device_cmyk(ctx)) softmask_bc[3] = 1.0; bc = pdf_dict_get(ctx, obj, PDF_NAME_BC); if (pdf_is_array(ctx, bc)) { for (k = 0; k < colorspace_n; k++) softmask_bc[k] = pdf_to_real(ctx, pdf_array_get(ctx, bc, k)); } s = pdf_dict_get(ctx, obj, PDF_NAME_S); if (pdf_name_eq(ctx, s, PDF_NAME_Luminosity)) luminosity = 1; else luminosity = 0; tr = pdf_dict_get(ctx, obj, PDF_NAME_TR); if (tr && !pdf_name_eq(ctx, tr, PDF_NAME_Identity)) fz_warn(ctx, "ignoring transfer function"); proc->op_gs_SMask(ctx, proc, xobj, csi->rdb, softmask_bc, luminosity); } fz_always(ctx) { pdf_drop_xobject(ctx, xobj); } fz_catch(ctx) { fz_rethrow(ctx); } } else if (pdf_is_name(ctx, obj) && pdf_name_eq(ctx, obj, PDF_NAME_None)) { proc->op_gs_SMask(ctx, proc, NULL, NULL, NULL, 0); } }
void pdf_update_annot(pdf_document *xref, pdf_annot *annot) { pdf_obj *obj, *ap, *as, *n, *d, *c; fz_context *ctx = xref->ctx; int suitable; int mouse_states; pdf_hotspot *hp = &xref->hotspot; obj = annot->obj; if (hp->num == pdf_to_num(obj) && hp->gen == pdf_to_gen(obj) && (hp->state & HOTSPOT_POINTER_DOWN)) { mouse_states = MOUSE_DOWN_APPEARANCE; } else { mouse_states = MOUSE_UP_APPEARANCE; } suitable = (annot->mouse_states & mouse_states); if (pdf_update_appearance(xref, obj) || !suitable || annot->has_states) { ap = pdf_dict_gets(obj, "AP"); as = pdf_dict_gets(obj, "AS"); if (pdf_is_dict(ap)) { pdf_hotspot *hp = &xref->hotspot; n = pdf_dict_gets(ap, "N"); /* normal state */ d = pdf_dict_gets(ap, "D"); /* down state */ if (mouse_states == MOUSE_DOWN_APPEARANCE) c = d?d:n; else c = n?n:d; annot->has_states = 0; /* lookup current state in sub-dictionary */ if (!pdf_is_stream(xref, pdf_to_num(c), pdf_to_gen(c))) { annot->has_states = 1; c = pdf_dict_get(c, as); } /* This test is important to avoid losing the knowledge * that an appearance stream is for both mouse states */ if (!suitable) annot->mouse_states = mouse_states; pdf_drop_xobject(ctx, annot->ap); annot->ap = NULL; if (pdf_is_stream(xref, pdf_to_num(c), pdf_to_gen(c))) { fz_try(ctx) { annot->ap = pdf_load_xobject(xref, c); pdf_transform_annot(annot); } fz_catch(ctx) { fz_warn(ctx, "ignoring broken annotation"); } } if (obj == xref->focus_obj) xref->focus = annot; } }
void pdf_delete_annot(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_annot *annot) { pdf_annot **annotptr; pdf_obj *old_annot_arr; pdf_obj *annot_arr; if (annot == NULL) return; /* Remove annot from page's list */ for (annotptr = &page->annots; *annotptr; annotptr = &(*annotptr)->next) { if (*annotptr == annot) break; } /* Check the passed annotation was of this page */ if (*annotptr == NULL) return; *annotptr = annot->next; /* If the removed annotation was the last in the list adjust the end pointer */ if (*annotptr == NULL) page->annot_tailp = annotptr; /* Stick it in the deleted list */ annot->next = page->deleted_annots; page->deleted_annots = annot; pdf_drop_xobject(ctx, annot->ap); annot->ap = NULL; /* Recreate the "Annots" array with this annot removed */ old_annot_arr = pdf_dict_get(ctx, page->me, PDF_NAME_Annots); if (old_annot_arr) { int i, n = pdf_array_len(ctx, old_annot_arr); annot_arr = pdf_new_array(ctx, doc, n?(n-1):0); fz_try(ctx) { for (i = 0; i < n; i++) { pdf_obj *obj = pdf_array_get(ctx, old_annot_arr, i); if (obj != annot->obj) pdf_array_push(ctx, annot_arr, obj); } if (pdf_is_indirect(ctx, old_annot_arr)) pdf_update_object(ctx, doc, pdf_to_num(ctx, old_annot_arr), annot_arr); else pdf_dict_put(ctx, page->me, PDF_NAME_Annots, annot_arr); if (pdf_is_indirect(ctx, annot->obj)) pdf_delete_object(ctx, doc, pdf_to_num(ctx, annot->obj)); } fz_always(ctx) { pdf_drop_obj(ctx, annot_arr); } fz_catch(ctx) { fz_rethrow(ctx); } } pdf_drop_obj(ctx, annot->obj); annot->obj = NULL; doc->dirty = 1; }
pdf_xobject * pdf_load_xobject(pdf_document *xref, pdf_obj *dict) { pdf_xobject *form; pdf_obj *obj; fz_context *ctx = xref->ctx; if ((form = pdf_find_item(ctx, pdf_free_xobject_imp, dict))) { return form; } form = fz_malloc_struct(ctx, pdf_xobject); FZ_INIT_STORABLE(form, 1, pdf_free_xobject_imp); form->resources = NULL; form->contents = NULL; form->colorspace = NULL; form->me = NULL; /* Store item immediately, to avoid possible recursion if objects refer back to this one */ pdf_store_item(ctx, dict, form, pdf_xobject_size(form)); obj = pdf_dict_gets(dict, "BBox"); form->bbox = pdf_to_rect(ctx, obj); obj = pdf_dict_gets(dict, "Matrix"); if (obj) form->matrix = pdf_to_matrix(ctx, obj); else form->matrix = fz_identity; form->isolated = 0; form->knockout = 0; form->transparency = 0; obj = pdf_dict_gets(dict, "Group"); if (obj) { pdf_obj *attrs = obj; form->isolated = pdf_to_bool(pdf_dict_gets(attrs, "I")); form->knockout = pdf_to_bool(pdf_dict_gets(attrs, "K")); obj = pdf_dict_gets(attrs, "S"); if (pdf_is_name(obj) && !strcmp(pdf_to_name(obj), "Transparency")) form->transparency = 1; obj = pdf_dict_gets(attrs, "CS"); if (obj) { form->colorspace = pdf_load_colorspace(xref, obj); if (!form->colorspace) fz_throw(ctx, "cannot load xobject colorspace"); } } form->resources = pdf_dict_gets(dict, "Resources"); if (form->resources) pdf_keep_obj(form->resources); fz_try(ctx) { form->contents = pdf_load_stream(xref, pdf_to_num(dict), pdf_to_gen(dict)); } fz_catch(ctx) { pdf_remove_item(ctx, pdf_free_xobject_imp, dict); pdf_drop_xobject(ctx, form); fz_throw(ctx, "cannot load xobject content stream (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict)); } form->me = pdf_keep_obj(dict); return form; }
static void pdf_drop_annot_imp(fz_context *ctx, pdf_annot *annot) { pdf_drop_xobject(ctx, annot->ap); pdf_drop_obj(ctx, annot->obj); }
pdf_obj * pdf_new_xobject(pdf_document *doc, const fz_rect *bbox, const fz_matrix *mat) { int idict_num; pdf_obj *idict = NULL; pdf_obj *dict = NULL; pdf_xobject *form = NULL; pdf_obj *obj = NULL; pdf_obj *res = NULL; pdf_obj *procset = NULL; fz_context *ctx = doc->ctx; fz_var(idict); fz_var(dict); fz_var(form); fz_var(obj); fz_var(res); fz_var(procset); fz_try(ctx) { dict = pdf_new_dict(doc, 0); obj = pdf_new_rect(doc, bbox); pdf_print_obj(obj); pdf_dict_puts(dict, "BBox", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_int(doc, 1); pdf_dict_puts(dict, "FormType", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_int(doc, 0); pdf_dict_puts(dict, "Length", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_matrix(doc, mat); pdf_dict_puts(dict, "Matrix", obj); pdf_drop_obj(obj); obj = NULL; res = pdf_new_dict(doc, 0); procset = pdf_new_array(doc, 2); obj = pdf_new_name(doc, "PDF"); pdf_array_push(procset, obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_name(doc, "Text"); pdf_array_push(procset, obj); pdf_drop_obj(obj); obj = NULL; pdf_dict_puts(res, "ProcSet", procset); pdf_drop_obj(procset); procset = NULL; pdf_dict_puts(dict, "Resources", res); obj = pdf_new_name(doc, "Form"); pdf_dict_puts(dict, "Subtype", obj); pdf_drop_obj(obj); obj = NULL; obj = pdf_new_name(doc, "XObject"); pdf_dict_puts(dict, "Type", obj); pdf_drop_obj(obj); obj = NULL; form = fz_malloc_struct(ctx, pdf_xobject); FZ_INIT_STORABLE(form, 1, pdf_free_xobject_imp); form->resources = NULL; form->contents = NULL; form->colorspace = NULL; form->me = NULL; form->iteration = 0; form->bbox = *bbox; form->matrix = *mat; form->isolated = 0; form->knockout = 0; form->transparency = 0; form->resources = res; res = NULL; idict_num = pdf_create_object(doc); pdf_update_object(doc, idict_num, dict); idict = pdf_new_indirect(doc, idict_num, 0); pdf_drop_obj(dict); dict = NULL; pdf_store_item(ctx, idict, form, pdf_xobject_size(form)); form->contents = pdf_keep_obj(idict); form->me = pdf_keep_obj(idict); pdf_drop_xobject(ctx, form); form = NULL; } fz_catch(ctx) { pdf_drop_obj(procset); pdf_drop_obj(res); pdf_drop_obj(obj); pdf_drop_obj(dict); pdf_drop_obj(idict); pdf_drop_xobject(ctx, form); fz_rethrow_message(ctx, "failed to create xobject)"); } return idict; }