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_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"); } } } }
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; } }
pdf_annot * pdf_load_annots(pdf_document *xref, pdf_obj *annots, fz_matrix page_ctm) { pdf_annot *annot, *head, *tail; pdf_obj *obj, *ap, *as, *n, *d, *c, *rect; int i, len; int mouse_states; int has_states = 0; fz_context *ctx = xref->ctx; head = tail = NULL; annot = NULL; len = pdf_array_len(annots); for (i = 0; i < len; i++) { obj = pdf_array_get(annots, i); pdf_update_appearance(xref, obj); rect = pdf_dict_gets(obj, "Rect"); 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 (n && d) { if (hp->num == pdf_to_num(obj) && hp->gen == pdf_to_gen(obj) && (hp->state & HOTSPOT_POINTER_DOWN)) { /* Use the down appearance, but as we also have * a normal appearance, it is suitable only for mouse * down */ c = d; mouse_states = MOUSE_DOWN_APPEARANCE; } else { /* Use the normal appearance, but as we also have * a down appearance, it is suitable only for mouse * up */ c = n; mouse_states = MOUSE_UP_APPEARANCE; } } else { /* Use whichever appearance we have for both states */ c = n?n:d; mouse_states = MOUSE_UP_APPEARANCE|MOUSE_DOWN_APPEARANCE; } /* lookup current state in sub-dictionary */ if (!pdf_is_stream(xref, pdf_to_num(c), pdf_to_gen(c))) { has_states = 1; c = pdf_dict_get(c, as); } annot = fz_malloc_struct(ctx, pdf_annot); annot->obj = pdf_keep_obj(obj); annot->rect = pdf_to_rect(ctx, rect); annot->pagerect = fz_transform_rect(page_ctm, annot->rect); annot->ap = NULL; annot->type = pdf_field_type(xref, obj); annot->mouse_states = mouse_states; annot->has_states = has_states; 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"); } } annot->next = NULL; if (obj == xref->focus_obj) xref->focus = annot; if (!head) head = tail = annot; else { tail->next = annot; tail = annot; } } } return head; }
void pdf_load_annots(fz_context *ctx, pdf_page *page, pdf_obj *annots) { pdf_document *doc = page->doc; pdf_annot *annot, **itr; pdf_obj *obj, *ap, *as, *n; int i, len, keep_annot; fz_var(annot); fz_var(itr); fz_var(keep_annot); itr = &page->annots; len = pdf_array_len(ctx, annots); /* Create an initial linked list of pdf_annot structures with only the obj field filled in. We do this because update_appearance has the potential to change the annot array, so we don't want to be iterating through the array while that happens. */ fz_try(ctx) { for (i = 0; i < len; i++) { obj = pdf_array_get(ctx, annots, i); annot = pdf_new_annot(ctx, page); *itr = annot; annot->obj = pdf_keep_obj(ctx, obj); itr = &annot->next; } } fz_catch(ctx) { pdf_drop_annots(ctx, page->annots); page->annots = NULL; fz_rethrow(ctx); } /* Iterate through the newly created annot linked list, using a double pointer to facilitate deleting broken annotations. */ itr = &page->annots; while (*itr) { annot = *itr; fz_try(ctx) { pdf_hotspot *hp = &doc->hotspot; n = NULL; 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); /* We only collect annotations with an appearance * stream into this list, so remove any that don't * (such as links) and continue. */ keep_annot = pdf_is_dict(ctx, ap); if (!keep_annot) break; if (hp->num == pdf_to_num(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, n)) n = pdf_dict_get(ctx, n, as); annot->ap = NULL; if (pdf_is_stream(ctx, n)) { annot->ap = pdf_load_xobject(ctx, doc, n); annot->ap_iteration = annot->ap->iteration; } else fz_warn(ctx, "no appearance stream for annotation %d 0 R", pdf_to_num(ctx, annot->obj)); if (obj == doc->focus_obj) doc->focus = annot; /* Move to next item in the linked list */ itr = &annot->next; } fz_catch(ctx) { if (fz_caught(ctx) == FZ_ERROR_TRYLATER) { pdf_drop_annots(ctx, page->annots); page->annots = NULL; fz_rethrow(ctx); } keep_annot = 0; fz_warn(ctx, "ignoring broken annotation"); } if (!keep_annot) { /* Move to next item in the linked list, dropping this one */ *itr = annot->next; annot->next = NULL; /* Required because pdf_drop_annots follows the "next" chain */ pdf_drop_annots(ctx, annot); } } page->annot_tailp = itr; }
void pdf_load_annots(pdf_annot **annotp, pdf_xref *xref, fz_obj *annots) { pdf_annot *annot, *head, *tail; fz_obj *obj, *ap, *as, *n, *rect; pdf_xobject *form; fz_error error; int i; fz_context *ctx = xref->ctx; head = tail = NULL; annot = NULL; for (i = 0; i < fz_array_len(ctx, annots); i++) { obj = fz_array_get(ctx, annots, i); /* cf. http://bugs.ghostscript.com/show_bug.cgi?id=692078 */ if ((annot = pdf_update_tx_widget_annot(xref, obj))) { if (!head) head = tail = annot; else { tail->next = annot; tail = annot; } continue; } rect = fz_dict_gets(ctx, obj, "Rect"); ap = fz_dict_gets(ctx, obj, "AP"); as = fz_dict_gets(ctx, obj, "AS"); if (fz_is_dict(ctx, ap)) { n = fz_dict_gets(ctx, ap, "N"); /* normal state */ /* lookup current state in sub-dictionary */ if (!pdf_is_stream(xref, fz_to_num(n), fz_to_gen(n))) n = fz_dict_get(ctx, n, as); if (pdf_is_stream(xref, fz_to_num(n), fz_to_gen(n))) { error = pdf_load_xobject(&form, xref, n); if (error) { fz_error_handle(ctx, error, "ignoring broken annotation"); continue; } annot = fz_malloc(ctx, sizeof(pdf_annot)); annot->obj = fz_keep_obj(obj); annot->rect = pdf_to_rect(ctx, rect); annot->ap = form; annot->next = NULL; pdf_transform_annot(annot); if (annot) { if (!head) head = tail = annot; else { tail->next = annot; tail = annot; } } } } /* SumatraPDF: synthesize appearance streams for a few more annotations */ else if ((annot = pdf_create_annot_with_appearance(xref, obj))) { if (!head) head = tail = annot; else { tail->next = annot; tail = annot; } } } *annotp = head; }