Exemplo n.º 1
0
static void
pdf_write_ch_widget_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf,
	fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res)
{
	int ff = pdf_field_flags(ctx, annot->obj);
	if (ff & PDF_CH_FIELD_IS_COMBO)
	{
		/* TODO: Pop-down arrow */
		pdf_write_tx_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res,
			pdf_field_value(ctx, annot->obj), 0);
	}
	else
	{
		fz_buffer *text = fz_new_buffer(ctx, 1024);
		fz_try(ctx)
		{
			pdf_obj *opt = pdf_dict_get(ctx, annot->obj, PDF_NAME(Opt));
			int i = pdf_dict_get_int(ctx, annot->obj, PDF_NAME(TI));
			int n = pdf_array_len(ctx, opt);
			/* TODO: Scrollbar */
			/* TODO: Highlight selected items */
			if (i < 0)
				i = 0;
			for (; i < n; ++i)
			{
				pdf_obj *val = pdf_array_get(ctx, opt, i);
				if (pdf_is_array(ctx, val))
					fz_append_string(ctx, text, pdf_array_get_text_string(ctx, val, 1));
				else
					fz_append_string(ctx, text, pdf_to_text_string(ctx, val));
				fz_append_byte(ctx, text, '\n');
			}
			pdf_write_tx_widget_appearance(ctx, annot, buf, rect, bbox, matrix, res,
				fz_string_from_buffer(ctx, text), PDF_TX_FIELD_IS_MULTILINE);
		}
		fz_always(ctx)
			fz_drop_buffer(ctx, text);
		fz_catch(ctx)
			fz_rethrow(ctx);
	}
}
Exemplo n.º 2
0
void
pdf_set_text_annot_position(fz_context *ctx, pdf_annot *annot, fz_point pt)
{
	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_rect(ctx, annot->obj, PDF_NAME(Rect), &rect);

	flags = pdf_dict_get_int(ctx, annot->obj, PDF_NAME(F));
	flags |= (PDF_ANNOT_IS_NO_ZOOM|PDF_ANNOT_IS_NO_ROTATE);
	pdf_dict_put_int(ctx, annot->obj, PDF_NAME(F), flags);
}
Exemplo n.º 3
0
static void
pdf_write_free_text_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf,
	fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res)
{
	const char *font;
	float size, color[3];
	const char *text;
	float w, h, t, b;
	int q, r;

	/* /Rotate is an undocumented annotation property supported by Adobe */
	text = pdf_annot_contents(ctx, annot);
	r = pdf_dict_get_int(ctx, annot->obj, PDF_NAME(Rotate));
	q = pdf_annot_quadding(ctx, annot);
	pdf_annot_default_appearance(ctx, annot, &font, &size, color);

	w = rect->x1 - rect->x0;
	h = rect->y1 - rect->y0;
	if (r == 90 || r == 270)
		t = h, h = w, w = t;

	*matrix = fz_rotate(r);
	*bbox = fz_make_rect(0, 0, w, h);

	if (pdf_write_fill_color_appearance(ctx, annot, buf))
		fz_append_printf(ctx, buf, "0 0 %g %g re\nf\n", w, h);

	b = pdf_write_border_appearance(ctx, annot, buf);
	if (b > 0)
	{
		fz_append_printf(ctx, buf, "%g %g %g RG\n", color[0], color[1], color[2]);
		fz_append_printf(ctx, buf, "%g %g %g %g re\nS\n", b/2, b/2, w-b, h-b);
	}

	fz_append_printf(ctx, buf, "%g %g %g %g re\nW\nn\n", b, b, w-b*2, h-b*2);

	write_variable_text(ctx, annot, buf, res, text, font, size, color, q, w, h, b*2,
		0.8f, 1.2f, 1, 0, 0);
}
Exemplo n.º 4
0
/*
	Performs the same task as
	pdf_clean_page_contents, but with an optional text filter
	function.

	text_filter: Function to assess whether a given character
	should be kept (return 0) or removed (return 1).

	after_text: Function called after each text object is closed
	to allow other output to be sent.

	arg: Opaque value to be passed to callback functions.
*/
void pdf_filter_page_contents(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_cookie *cookie,
		pdf_page_contents_process_fn *proc_fn, pdf_text_filter_fn *text_filter, pdf_after_text_object_fn *after_text, void *proc_arg,
		int sanitize, int ascii)
{
	pdf_processor *proc_buffer = NULL;
	pdf_processor *proc_filter = NULL;
	pdf_obj *new_obj = NULL;
	pdf_obj *new_ref = NULL;
	pdf_obj *res = NULL;
	pdf_obj *obj;
	pdf_obj *contents;
	pdf_obj *resources;
	fz_buffer *buffer;

	fz_var(new_obj);
	fz_var(new_ref);
	fz_var(res);
	fz_var(proc_buffer);
	fz_var(proc_filter);

	buffer = fz_new_buffer(ctx, 1024);

	fz_try(ctx)
	{
		contents = pdf_page_contents(ctx, page);
		resources = pdf_page_resources(ctx, page);

		proc_buffer = pdf_new_buffer_processor(ctx, buffer, ascii);
		if (sanitize)
		{
			res = pdf_new_dict(ctx, doc, 1);
			proc_filter = pdf_new_filter_processor_with_text_filter(ctx, doc, proc_buffer, resources, res, text_filter, after_text, proc_arg);
			pdf_process_contents(ctx, proc_filter, doc, resources, contents, cookie);
			pdf_close_processor(ctx, proc_filter);
		}
		else
		{
			res = pdf_keep_obj(ctx, resources);
			pdf_process_contents(ctx, proc_buffer, doc, resources, contents, cookie);
		}
		pdf_close_processor(ctx, proc_buffer);

		/* Deal with page content stream. */

		if (pdf_is_array(ctx, contents))
		{
			/* create a new object to replace the array */
			new_obj = pdf_new_dict(ctx, doc, 1);
			new_ref = pdf_add_object(ctx, doc, new_obj);
			contents = new_ref;
			pdf_dict_put(ctx, page->obj, PDF_NAME(Contents), contents);
		}
		else
		{
			pdf_dict_del(ctx, contents, PDF_NAME(Filter));
			pdf_dict_del(ctx, contents, PDF_NAME(DecodeParms));
		}

		pdf_update_stream(ctx, doc, contents, buffer, 0);

		/* Now deal with resources. The spec allows for Type3 fonts and form
		 * XObjects to omit a resource dictionary and look in the parent.
		 * Avoid that by flattening here as part of the cleaning. This could
		 * conceivably cause changes in rendering, but we don't care. */

		/* ExtGState */
		obj = pdf_dict_get(ctx, res, PDF_NAME(ExtGState));
		if (obj)
		{
			int i, l;

			l = pdf_dict_len(ctx, obj);
			for (i = 0; i < l; i++)
			{
				pdf_obj *o = pdf_dict_get(ctx, pdf_dict_get_val(ctx, obj, i), PDF_NAME(SMask));
				if (!o)
					continue;
				o = pdf_dict_get(ctx, o, PDF_NAME(G));
				if (!o)
					continue;
				/* Transparency group XObject */
				pdf_clean_stream_object(ctx, doc, o, resources, cookie, 1, text_filter, after_text, proc_arg, sanitize, ascii);
			}
		}

		/* Pattern */
		obj = pdf_dict_get(ctx, res, PDF_NAME(Pattern));
		if (obj)
		{
			int i, l;
			l = pdf_dict_len(ctx, obj);
			for (i = 0; i < l; i++)
			{
				pdf_obj *pat_res;
				pdf_obj *pat = pdf_dict_get_val(ctx, obj, i);
				if (!pat)
					continue;
				pat_res = pdf_dict_get(ctx, pat, PDF_NAME(Resources));
				if (pat_res == NULL)
					pat_res = resources;
				if (pdf_dict_get_int(ctx, pat, PDF_NAME(PatternType)) == 1)
					pdf_clean_stream_object(ctx, doc, pat, pat_res, cookie, 0, text_filter, after_text, proc_arg, sanitize, ascii);
			}
		}

		/* XObject */
		obj = pdf_dict_get(ctx, res, PDF_NAME(XObject));
		if (obj)
		{
			int i, l;
			l = pdf_dict_len(ctx, obj);
			for (i = 0; i < l; i++)
			{
				pdf_obj *xobj_res;
				pdf_obj *xobj = pdf_dict_get_val(ctx, obj, i);
				if (!xobj)
					continue;
				xobj_res = pdf_dict_get(ctx, xobj, PDF_NAME(Resources));
				if (xobj_res == NULL)
					xobj_res = resources;
				if (pdf_name_eq(ctx, PDF_NAME(Form), pdf_dict_get(ctx, xobj, PDF_NAME(Subtype))))
					pdf_clean_stream_object(ctx, doc, xobj, xobj_res, cookie, 1, text_filter, after_text, proc_arg, sanitize, ascii);
			}
		}

		/* Font */
		obj = pdf_dict_get(ctx, res, PDF_NAME(Font));
		if (obj)
		{
			int i, l;
			l = pdf_dict_len(ctx, obj);
			for (i = 0; i < l; i++)
			{
				pdf_obj *o = pdf_dict_get_val(ctx, obj, i);
				if (!o)
					continue;
				if (pdf_name_eq(ctx, PDF_NAME(Type3), pdf_dict_get(ctx, o, PDF_NAME(Subtype))))
					pdf_clean_type3(ctx, doc, o, resources, cookie, sanitize, ascii);
			}
		}

		/* ProcSet - no cleaning possible. Inherit this from the old dict. */
		obj = pdf_dict_get(ctx, resources, PDF_NAME(ProcSet));
		if (obj)
			pdf_dict_put(ctx, res, PDF_NAME(ProcSet), obj);

		/* ColorSpace - no cleaning possible. */
		/* Properties - no cleaning possible. */

		if (proc_fn)
			(*proc_fn)(ctx, buffer, res, proc_arg);

		/* Update resource dictionary */
		if (sanitize)
		{
			pdf_dict_put(ctx, page->obj, PDF_NAME(Resources), res);
		}
	}
	fz_always(ctx)
	{
		pdf_drop_processor(ctx, proc_filter);
		pdf_drop_processor(ctx, proc_buffer);
		fz_drop_buffer(ctx, buffer);
		pdf_drop_obj(ctx, new_obj);
		pdf_drop_obj(ctx, new_ref);
		pdf_drop_obj(ctx, res);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
Exemplo n.º 5
0
int
pdf_annot_quadding(fz_context *ctx, pdf_annot *annot)
{
	int q = pdf_dict_get_int(ctx, annot->obj, PDF_NAME(Q));
	return (q < 0 || q > 2) ? 0 : q;
}
Exemplo n.º 6
0
int
pdf_annot_flags(fz_context *ctx, pdf_annot *annot)
{
	return pdf_dict_get_int(ctx, annot->obj, PDF_NAME(F));
}
Exemplo n.º 7
0
static void pdf_update_button_appearance(fz_context *ctx, pdf_annot *annot)
{
	int ff = pdf_field_flags(ctx, annot->obj);
	fz_rect rect = pdf_dict_get_rect(ctx, annot->obj, PDF_NAME(Rect));
	fz_matrix matrix;
	fz_rect bbox;
	float w, h, t;
	int r;

	r = pdf_dict_get_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME(MK)), PDF_NAME(R));
	w = rect.x1 - rect.x0;
	h = rect.y1 - rect.y0;
	if (r == 90 || r == 270)
		t = h, h = w, w = t;
	matrix = fz_rotate(r);
	bbox = fz_make_rect(0, 0, w, h);


	if (ff & PDF_BTN_FIELD_IS_PUSHBUTTON)
	{
		pdf_obj *ap_n = NULL;
		pdf_obj *ap_d = NULL;
		fz_var(ap_n);
		fz_var(ap_d);
		fz_try(ctx)
		{
			pdf_obj *ap, *MK, *CA, *AC;
			const char *font;
			const char *label;
			float size, color[3];

			pdf_annot_default_appearance(ctx, annot, &font, &size, color);

			MK = pdf_dict_get(ctx, annot->obj, PDF_NAME(MK));
			CA = pdf_dict_get(ctx, MK, PDF_NAME(CA));
			AC = pdf_dict_get(ctx, MK, PDF_NAME(AC));

			label = pdf_to_text_string(ctx, CA);
			ap_n = draw_push_button(ctx, annot, bbox, matrix, w, h, label, font, size, color, 0);

			label = pdf_to_text_string(ctx, AC ? AC : CA);
			ap_d = draw_push_button(ctx, annot, bbox, matrix, w, h, label, font, size, color, 1);

			ap = pdf_dict_put_dict(ctx, annot->obj, PDF_NAME(AP), 2);
			pdf_dict_put(ctx, ap, PDF_NAME(N), ap_n);
			pdf_dict_put(ctx, ap, PDF_NAME(D), ap_d);

			pdf_drop_obj(ctx, annot->ap);
			if (annot->is_hot && annot->is_active)
				annot->ap = pdf_keep_obj(ctx, ap_d);
			else
				annot->ap = pdf_keep_obj(ctx, ap_n);
			annot->has_new_ap = 1;
		}
		fz_always(ctx)
		{
			pdf_drop_obj(ctx, ap_n);
			pdf_drop_obj(ctx, ap_d);
		}
		fz_catch(ctx)
			fz_rethrow(ctx);
	}
Exemplo n.º 8
0
static void
pdf_write_tx_widget_appearance(fz_context *ctx, pdf_annot *annot, fz_buffer *buf,
	fz_rect *rect, fz_rect *bbox, fz_matrix *matrix, pdf_obj **res,
	const char *text, int ff)
{
	const char *font;
	float size, color[3];
	float w, h, t, b;
	int has_bc = 0;
	int q, r;

	r = pdf_dict_get_int(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME(MK)), PDF_NAME(R));
	q = pdf_annot_quadding(ctx, annot);
	pdf_annot_default_appearance(ctx, annot, &font, &size, color);

	w = rect->x1 - rect->x0;
	h = rect->y1 - rect->y0;
	if (r == 90 || r == 270)
		t = h, h = w, w = t;
	*matrix = fz_rotate(r);
	*bbox = fz_make_rect(0, 0, w, h);

	fz_append_string(ctx, buf, "/Tx BMC\nq\n");

	if (pdf_write_MK_BG_appearance(ctx, annot, buf))
		fz_append_printf(ctx, buf, "0 0 %g %g re\nf\n", w, h);

	b = pdf_write_border_appearance(ctx, annot, buf);
	if (b > 0 && pdf_write_MK_BC_appearance(ctx, annot, buf))
	{
		fz_append_printf(ctx, buf, "%g %g %g %g re\ns\n", b/2, b/2, w-b, h-b);
		has_bc = 1;
	}

	fz_append_printf(ctx, buf, "%g %g %g %g re\nW\nn\n", b, b, w-b*2, h-b*2);

	if (ff & PDF_TX_FIELD_IS_MULTILINE)
	{
		write_variable_text(ctx, annot, buf, res, text, font, size, color, q, w, h, b*2,
			1.116f, 1.116f, 1, 0, 1);
	}
	else if (ff & PDF_TX_FIELD_IS_COMB)
	{
		int maxlen = pdf_to_int(ctx, pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(MaxLen)));
		if (has_bc && maxlen > 1)
		{
			float cell_w = (w - 2 * b) / maxlen;
			int i;
			for (i = 1; i < maxlen; ++i)
			{
				float x = b + cell_w * i;
				fz_append_printf(ctx, buf, "%g %g m %g %g l s\n", x, b, x, h-b);
			}
		}
		write_variable_text(ctx, annot, buf, res, text, font, size, color, q, w, h, 0,
			0.8f, 1.2f, 0, maxlen, 0);
	}
	else
	{
		write_variable_text(ctx, annot, buf, res, text, font, size, color, q, w, h, b*2,
			0.8f, 1.2f, 0, 0, 0);
	}

	fz_append_string(ctx, buf, "Q\nEMC\n");
}
Exemplo n.º 9
0
static void
pdf_load_mesh_params(fz_context *ctx, pdf_document *doc, fz_shade *shade, pdf_obj *dict)
{
	pdf_obj *obj;
	int i, n;

	shade->u.m.x0 = shade->u.m.y0 = 0;
	shade->u.m.x1 = shade->u.m.y1 = 1;
	for (i = 0; i < FZ_MAX_COLORS; i++)
	{
		shade->u.m.c0[i] = 0;
		shade->u.m.c1[i] = 1;
	}

	shade->u.m.vprow = pdf_dict_get_int(ctx, dict, PDF_NAME(VerticesPerRow));
	shade->u.m.bpflag = pdf_dict_get_int(ctx, dict, PDF_NAME(BitsPerFlag));
	shade->u.m.bpcoord = pdf_dict_get_int(ctx, dict, PDF_NAME(BitsPerCoordinate));
	shade->u.m.bpcomp = pdf_dict_get_int(ctx, dict, PDF_NAME(BitsPerComponent));

	obj = pdf_dict_get(ctx, dict, PDF_NAME(Decode));
	if (pdf_array_len(ctx, obj) >= 6)
	{
		n = fz_mini(FZ_MAX_COLORS, (pdf_array_len(ctx, obj) - 4) / 2);
		shade->u.m.x0 = pdf_array_get_real(ctx, obj, 0);
		shade->u.m.x1 = pdf_array_get_real(ctx, obj, 1);
		shade->u.m.y0 = pdf_array_get_real(ctx, obj, 2);
		shade->u.m.y1 = pdf_array_get_real(ctx, obj, 3);
		for (i = 0; i < n; i++)
		{
			shade->u.m.c0[i] = pdf_array_get_real(ctx, obj, 4 + i * 2);
			shade->u.m.c1[i] = pdf_array_get_real(ctx, obj, 5 + i * 2);
		}
	}

	if (shade->u.m.vprow < 2 && shade->type == 5)
	{
		fz_warn(ctx, "Too few vertices per row (%d)", shade->u.m.vprow);
		shade->u.m.vprow = 2;
	}

	if (shade->u.m.bpflag != 2 && shade->u.m.bpflag != 4 && shade->u.m.bpflag != 8 &&
		shade->type != 5)
	{
		fz_warn(ctx, "Invalid number of bits per flag (%d)", shade->u.m.bpflag);
		shade->u.m.bpflag = 8;
	}

	if (shade->u.m.bpcoord != 1 && shade->u.m.bpcoord != 2 && shade->u.m.bpcoord != 4 &&
		shade->u.m.bpcoord != 8 && shade->u.m.bpcoord != 12 && shade->u.m.bpcoord != 16 &&
		shade->u.m.bpcoord != 24 && shade->u.m.bpcoord != 32)
	{
		fz_warn(ctx, "Invalid number of bits per coordinate (%d)", shade->u.m.bpcoord);
		shade->u.m.bpcoord = 8;
	}

	if (shade->u.m.bpcomp != 1 && shade->u.m.bpcomp != 2 && shade->u.m.bpcomp != 4 &&
		shade->u.m.bpcomp != 8 && shade->u.m.bpcomp != 12 && shade->u.m.bpcomp != 16)
	{
		fz_warn(ctx, "Invalid number of bits per component (%d)", shade->u.m.bpcomp);
		shade->u.m.bpcomp = 8;
	}
}