示例#1
0
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
}
示例#2
0
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");
			}
		}
	}
}
示例#3
0
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);
}
示例#4
0
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);
		}
	}
示例#5
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;
		}
	}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
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;
}