Esempio n. 1
0
static pdf_annot *
pdf_create_highlight_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_context *ctx = xref->ctx;
	fz_buffer *content = fz_new_buffer(ctx, 512);
	fz_rect rect = pdf_to_rect(ctx, fz_dict_gets(ctx, obj, "Rect"));
	fz_obj *quad_points = fz_dict_gets(ctx, obj, "QuadPoints");
	fz_obj *resources = pdf_dict_from_string(xref, ANNOT_HIGHLIGHT_AP_RESOURCES);
	fz_rect a, b;
	float rgb[3];
	float skew;
	int i;

	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		skew = 0.15 * fabs(a.y0 - b.y0);
		b.x0 -= skew; b.x1 += skew;
		rect = fz_union_rect(rect, fz_union_rect(a, b));
	}
	pdf_get_annot_color(ctx, obj, rgb);

	fz_buffer_printf(ctx, content, "q /GS gs %.4f %.4f %.4f rg 1 0 0 1 -%.4f -%.4f cm ",
		rgb[0], rgb[1], rgb[2], rect.x0, rect.y0);
	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		skew = 0.15 * fabs(a.y0 - b.y0);
		fz_buffer_printf(ctx, content, "%.4f %.4f m %.4f %.4f l %.4f %.4f l %.4f %.4f l h ",
			a.x0, a.y0, b.x1 + skew, b.y1, a.x1, a.y1, b.x0 - skew, b.y0);
	}
	fz_buffer_printf(ctx, content, "f Q");

	return pdf_create_annot(ctx, rect, fz_keep_obj(obj), content, resources, 1);
}
Esempio n. 2
0
/* SumatraPDF: partial support for file attachment icons */
static pdf_annot *
pdf_create_file_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_buffer *content = fz_new_buffer(xref->ctx, 512);
	fz_rect rect = pdf_to_rect(xref->ctx, fz_dict_gets(xref->ctx, obj, "Rect"));
	char *icon_name = fz_to_name(xref->ctx, fz_dict_gets(xref->ctx, obj, "Name"));
	char *content_ap = ANNOT_FILE_ATTACHMENT_AP_PUSHPIN;
	float rgb[3];

	pdf_get_annot_color(xref->ctx, obj, rgb);

	if (!strcmp(icon_name, "Graph"))
		content_ap = ANNOT_FILE_ATTACHMENT_AP_GRAPH;
	else if (!strcmp(icon_name, "Paperclip"))
		content_ap = ANNOT_FILE_ATTACHMENT_AP_PAPERCLIP;
	else if (!strcmp(icon_name, "Tag"))
		content_ap = ANNOT_FILE_ATTACHMENT_AP_TAG;

	fz_buffer_printf(xref->ctx, content, "q %.4f 0 0 %.4f 0 0 cm ",
		(rect.x1 - rect.x0) / 24, (rect.y1 - rect.y0) / 24);
	fz_buffer_printf(xref->ctx, content, content_ap, 0.5, 0.5, 0.5);
	fz_buffer_printf(xref->ctx, content, " 1 0 0 1 0 1 cm ");
	fz_buffer_printf(xref->ctx, content, content_ap, rgb[0], rgb[1], rgb[2]);
	fz_buffer_printf(xref->ctx, content, " Q", content_ap);

	obj = pdf_clone_for_view_only(xref, obj);
	return pdf_create_annot(xref->ctx, rect, obj, content, NULL, 0);
}
Esempio n. 3
0
/* SumatraPDF: partial support for link borders */
static pdf_annot *
pdf_create_link_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_obj *border, *dashes;
	fz_buffer *content;
	fz_rect rect;
	float rgb[3];
	int i;

	border = fz_dict_gets(xref->ctx, obj, "Border");
	if (fz_to_real(xref->ctx, fz_array_get(xref->ctx, border, 2)) <= 0)
		return NULL;

	pdf_get_annot_color(xref->ctx, obj, rgb);
	dashes = fz_array_get(xref->ctx, border, 3);
	rect = pdf_to_rect(xref->ctx, fz_dict_gets(xref->ctx, obj, "Rect"));

	obj = pdf_clone_for_view_only(xref, obj);

	// TODO: draw rounded rectangles if the first two /Border values are non-zero
	content = fz_new_buffer(xref->ctx, 128);
	fz_buffer_printf(xref->ctx, content, "q %.4f w [", fz_to_real(xref->ctx, fz_array_get(xref->ctx, border, 2)));
	for (i = 0; i < fz_array_len(xref->ctx, dashes); i++)
		fz_buffer_printf(xref->ctx, content, "%.4f ", fz_to_real(xref->ctx, fz_array_get(xref->ctx, dashes, i)));
	fz_buffer_printf(xref->ctx, content, "] 0 d %.4f %.4f %.4f RG 0 0 %.4f %.4f re S Q",
		rgb[0], rgb[1], rgb[2], rect.x1 - rect.x0, rect.y1 - rect.y0);

	return pdf_create_annot(xref->ctx, rect, obj, content, NULL, 0);
}
Esempio n. 4
0
static void
pdf_string_to_Tj(fz_context *ctx, fz_buffer *content, unsigned short *ucs2, unsigned short *end)
{
	fz_buffer_printf(ctx, content, "(");
	for (; ucs2 < end; ucs2++)
	{
		// TODO: convert to CID(?)
		if (*ucs2 < 0x20 || *ucs2 == '(' || *ucs2 == ')' || *ucs2 == '\\')
			fz_buffer_printf(ctx, content, "\\%03o", *ucs2);
		else
			fz_buffer_printf(ctx, content, "%c", *ucs2);
	}
	fz_buffer_printf(ctx, content, ") Tj ");
}
Esempio n. 5
0
void pdf_print_token(fz_context *ctx, fz_buffer *fzbuf, int tok, pdf_lexbuf *buf)
{
	switch (tok)
	{
	case PDF_TOK_NAME:
		fz_buffer_printf(ctx, fzbuf, "/%s", buf->scratch);
		break;
	case PDF_TOK_STRING:
		if (buf->len >= buf->size)
			pdf_lexbuf_grow(buf);
		buf->scratch[buf->len] = 0;
		fz_buffer_cat_pdf_string(ctx, fzbuf, buf->scratch);
		break;
	case PDF_TOK_OPEN_DICT:
		fz_buffer_printf(ctx, fzbuf, "<<");
		break;
	case PDF_TOK_CLOSE_DICT:
		fz_buffer_printf(ctx, fzbuf, ">>");
		break;
	case PDF_TOK_OPEN_ARRAY:
		fz_buffer_printf(ctx, fzbuf, "[");
		break;
	case PDF_TOK_CLOSE_ARRAY:
		fz_buffer_printf(ctx, fzbuf, "]");
		break;
	case PDF_TOK_OPEN_BRACE:
		fz_buffer_printf(ctx, fzbuf, "{");
		break;
	case PDF_TOK_CLOSE_BRACE:
		fz_buffer_printf(ctx, fzbuf, "}");
		break;
	case PDF_TOK_INT:
		fz_buffer_printf(ctx, fzbuf, "%d", buf->i);
		break;
	case PDF_TOK_REAL:
		{
			char sbuf[256];
			sprintf(sbuf, "%g", buf->f);
			if (strchr(sbuf, 'e')) /* bad news! */
				sprintf(sbuf, fabsf(buf->f) > 1 ? "%1.1f" : "%1.8f", buf->f);
			fz_buffer_printf(ctx, fzbuf, "%s", sbuf);
		}
		break;
	default:
		fz_buffer_printf(ctx, fzbuf, "%s", buf->scratch);
		break;
	}
}
Esempio n. 6
0
static void
pdf_dev_path_curveto(fz_context *ctx, void *arg, float x1, float y1, float x2, float y2, float x3, float y3)
{
	fz_buffer *buf = (fz_buffer *)arg;

	fz_buffer_printf(ctx, buf, "%f %f %f %f %f %f c\n", x1, y1, x2, y2, x3, y3);
}
Esempio n. 7
0
static void
pdf_dev_path_close(fz_context *ctx, void *arg)
{
	fz_buffer *buf = (fz_buffer *)arg;

	fz_buffer_printf(ctx, buf, "h\n");
}
Esempio n. 8
0
static void
pdf_dev_path_lineto(fz_context *ctx, void *arg, float x, float y)
{
	fz_buffer *buf = (fz_buffer *)arg;

	fz_buffer_printf(ctx, buf, "%f %f l\n", x, y);
}
Esempio n. 9
0
void pdf_print_token(fz_context *ctx, fz_buffer *fzbuf, int tok, pdf_lexbuf *buf)
{
	switch (tok)
	{
	case PDF_TOK_NAME:
		fz_buffer_printf(ctx, fzbuf, "/%s", buf->scratch);
		break;
	case PDF_TOK_STRING:
		if (buf->len >= buf->size)
			pdf_lexbuf_grow(buf);
		buf->scratch[buf->len] = 0;
		fz_buffer_cat_pdf_string(ctx, fzbuf, buf->scratch);
		break;
	case PDF_TOK_OPEN_DICT:
		fz_buffer_printf(ctx, fzbuf, "<<");
		break;
	case PDF_TOK_CLOSE_DICT:
		fz_buffer_printf(ctx, fzbuf, ">>");
		break;
	case PDF_TOK_OPEN_ARRAY:
		fz_buffer_printf(ctx, fzbuf, "[");
		break;
	case PDF_TOK_CLOSE_ARRAY:
		fz_buffer_printf(ctx, fzbuf, "]");
		break;
	case PDF_TOK_OPEN_BRACE:
		fz_buffer_printf(ctx, fzbuf, "{");
		break;
	case PDF_TOK_CLOSE_BRACE:
		fz_buffer_printf(ctx, fzbuf, "}");
		break;
	case PDF_TOK_INT:
		fz_buffer_printf(ctx, fzbuf, "%d", buf->i);
		break;
	case PDF_TOK_REAL:
		{
			fz_buffer_printf(ctx, fzbuf, "%g", buf->f);
		}
		break;
	default:
		fz_buffer_printf(ctx, fzbuf, "%s", buf->scratch);
		break;
	}
}
Esempio n. 10
0
static pdf_annot *
pdf_create_freetext_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_context *ctx = xref->ctx;
	fz_buffer *content = fz_new_buffer(ctx, 256);
	fz_buffer *base_ap = fz_new_buffer(ctx, 256);
	fz_obj *ap = fz_dict_gets(ctx, obj, "DA");
	fz_obj *value = fz_dict_gets(ctx, obj, "Contents");
	fz_rect rect = pdf_to_rect(ctx, fz_dict_gets(ctx, obj, "Rect"));
	int align = fz_to_int(ctx, fz_dict_gets(ctx, obj, "Q"));
	fz_obj *res = pdf_dict_from_string(xref, ANNOT_FREETEXT_AP_RESOURCES);
	unsigned short *ucs2, *rest;
	float x;

	char *font_name = NULL;
	float font_size = pdf_extract_font_size(xref, fz_to_str_buf(ctx, ap), &font_name);
	if (!font_size)
		font_size = 10;
	/* TODO: what resource dictionary does this font name refer to? */
	if (font_name)
	{
		fz_obj *font = fz_dict_gets(ctx, res, "Font");
		fz_dict_puts(ctx, font, font_name, fz_dict_gets(ctx, font, "Default"));
		fz_free(ctx, font_name);
	}

	fz_buffer_printf(ctx, content, "q 1 1 %.4f %.4f re W n BT %s ",
		rect.x1 - rect.x0 - 2.0f, rect.y1 - rect.y0 - 2.0f, fz_to_str_buf(ctx, ap));
	fz_buffer_printf(ctx, base_ap, "q BT %s ", fz_to_str_buf(ctx, ap));
	fz_buffer_printf(ctx, content, "/Default %.4f Tf ", font_size);
	fz_buffer_printf(ctx, base_ap, "/Default %.4f Tf ", font_size);
	fz_buffer_printf(ctx, content, "1 0 0 1 2 %.4f Tm ", rect.y1 - rect.y0 - 2);

	/* Adobe Reader seems to consider "[1 0 0] r" and "1 0 0 rg" to mean the same(?) */
	if (strchr(base_ap->data, '['))
	{
		float r, g, b;
		if (sscanf(strchr(base_ap->data, '['), "[%f %f %f] r", &r, &g, &b) == 3)
			fz_buffer_printf(ctx, content, "%.4f %.4f %.4f rg ", r, g, b);
	}

	ucs2 = pdf_to_ucs2(ctx, value);
	for (rest = ucs2; *rest; rest++)
		if (*rest > 0xFF)
			*rest = '?';

	x = 0;
	rest = ucs2;
	while (*rest)
		rest = pdf_append_line(xref, res, content, base_ap, rest, font_size, align, rect.x1 - rect.x0 - 4.0f, 1, &x);

	fz_free(ctx, ucs2);
	fz_buffer_printf(ctx, content, "ET Q");
	fz_drop_buffer(ctx, base_ap);

	return pdf_create_annot(ctx, rect, fz_keep_obj(obj), content, res, 0);
}
Esempio n. 11
0
/* SumatraPDF: partial support for text icons */
static pdf_annot *
pdf_create_text_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_context *ctx = xref->ctx;
	fz_buffer *content = fz_new_buffer(ctx, 512);
	fz_rect rect = pdf_to_rect(ctx, fz_dict_gets(ctx, obj, "Rect"));
	char *icon_name = fz_to_name(ctx, fz_dict_gets(ctx, obj, "Name"));
	char *content_ap = ANNOT_TEXT_AP_NOTE;
	float rgb[3];

	rect.x1 = rect.x0 + 24;
	rect.y0 = rect.y1 - 24;
	pdf_get_annot_color(ctx, obj, rgb);

	if (!strcmp(icon_name, "Comment"))
		content_ap = ANNOT_TEXT_AP_COMMENT;
	else if (!strcmp(icon_name, "Key"))
		content_ap = ANNOT_TEXT_AP_KEY;
	else if (!strcmp(icon_name, "Help"))
		content_ap = ANNOT_TEXT_AP_HELP;
	else if (!strcmp(icon_name, "Paragraph"))
		content_ap = ANNOT_TEXT_AP_PARAGRAPH;
	else if (!strcmp(icon_name, "NewParagraph"))
		content_ap = ANNOT_TEXT_AP_NEW_PARAGRAPH;
	else if (!strcmp(icon_name, "Insert"))
		content_ap = ANNOT_TEXT_AP_INSERT;
	else if (!strcmp(icon_name, "Cross"))
		content_ap = ANNOT_TEXT_AP_CROSS;
	else if (!strcmp(icon_name, "Circle"))
		content_ap = ANNOT_TEXT_AP_CIRCLE;

	// TODO: make icons semi-transparent (cf. pdf_create_highlight_annot)?
	fz_buffer_printf(ctx, content, "q ");
	fz_buffer_printf(ctx, content, content_ap, 0.5, 0.5, 0.5);
	fz_buffer_printf(ctx, content, " 1 0 0 1 0 1 cm ");
	fz_buffer_printf(ctx, content, content_ap, rgb[0], rgb[1], rgb[2]);
	fz_buffer_printf(ctx, content, " Q", content_ap);

	obj = pdf_clone_for_view_only(xref, obj);
	return pdf_create_annot(ctx, rect, obj, content, NULL, 0);
}
Esempio n. 12
0
static void
pdf_dev_ctm(fz_context *ctx, pdf_device *pdev, const fz_matrix *ctm)
{
	fz_matrix inverse;
	gstate *gs = CURRENT_GSTATE(pdev);

	if (memcmp(&gs->ctm, ctm, sizeof(*ctm)) == 0)
		return;
	fz_invert_matrix(&inverse, &gs->ctm);
	fz_concat(&inverse, ctm, &inverse);
	gs->ctm = *ctm;
	fz_buffer_printf(ctx, gs->buf, "%M cm\n", &inverse);
}
Esempio n. 13
0
static pdf_annot *
pdf_create_markup_annot(pdf_xref *xref, fz_obj *obj, char *type)
{
	fz_context *ctx = xref->ctx;
	fz_buffer *content = fz_new_buffer(ctx, 512);
	fz_rect rect = pdf_to_rect(ctx, fz_dict_gets(ctx, obj, "Rect"));
	fz_obj *quad_points = fz_dict_gets(ctx, obj, "QuadPoints");
	fz_rect a, b;
	float rgb[3];
	int i;

	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		b.y0 -= 0.25; a.y1 += 0.25;
		rect = fz_union_rect(rect, fz_union_rect(a, b));
	}
	pdf_get_annot_color(ctx, obj, rgb);

	fz_buffer_printf(ctx, content, "q %.4f %.4f %.4f RG 1 0 0 1 -%.4f -%.4f cm 0.5 w ",
		rgb[0], rgb[1], rgb[2], rect.x0, rect.y0);
	if (!strcmp(type, "Squiggly"))
		fz_buffer_printf(ctx, content, "[1 1] d ");
	for (i = 0; i < fz_array_len(ctx, quad_points) / 8; i++)
	{
		pdf_get_quadrilaterals(ctx, quad_points, i, &a, &b);
		if (!strcmp(type, "StrikeOut"))
			fz_buffer_printf(ctx, content, "%.4f %.4f m %.4f %.4f l ",
				(a.x0 + b.x0) / 2, (a.y0 + b.y0) / 2, (a.x1 + b.x1) / 2, (a.y1 + b.y1) / 2);
		else
			fz_buffer_printf(ctx, content, "%.4f %.4f m %.4f %.4f l ", b.x0, b.y0, a.x1, a.y1);
	}
	fz_buffer_printf(ctx, content, "S Q");

	return pdf_create_annot(ctx, rect, fz_keep_obj(obj), content, NULL, 0);
}
Esempio n. 14
0
static int
pdf_get_string_width(pdf_xref *xref, fz_obj *res, fz_buffer *base, unsigned short *string, unsigned short *end)
{
	fz_bbox bbox;
	fz_error error;
	int width, old_len = base->len;
	fz_device *dev = fz_new_bbox_device(xref->ctx, &bbox);

	pdf_string_to_Tj(xref->ctx, base, string, end);
	fz_buffer_printf(xref->ctx, base, "ET Q EMC");
	error = pdf_run_glyph(xref, res, base, dev, fz_identity);
	width = error ? -1 : bbox.x1 - bbox.x0;
	base->len = old_len;
	fz_free_device(dev);

	return width;
}
Esempio n. 15
0
static void
pdf_append_combed_line(pdf_xref *xref, fz_obj *res, fz_buffer *content, fz_buffer *base_ap,
	unsigned short *ucs2, float font_size, float width, int max_len)
{
	float comb_width = max_len > 0 ? width / max_len : 0;
	unsigned short c[2] = { 0 };
	float x = -2.0f;
	int i;

	fz_buffer_printf(xref->ctx, content, "0 %.4f Td ", -font_size);
	for (i = 0; i < max_len && ucs2[i]; i++)
	{
		*c = ucs2[i];
		pdf_append_line(xref, res, content, base_ap, c, 0, 1 /* centered */, comb_width, 0, &x);
		x -= comb_width;
	}
}
Esempio n. 16
0
/* Helper functions */
static void
pdf_dev_stroke_state(fz_context *ctx, pdf_device *pdev, const fz_stroke_state *stroke_state)
{
	gstate *gs = CURRENT_GSTATE(pdev);

	if (stroke_state == gs->stroke_state)
		return;
	if (gs->stroke_state && !memcmp(stroke_state, gs->stroke_state, sizeof(*stroke_state)))
		return;
	if (!gs->stroke_state || gs->stroke_state->linewidth != stroke_state->linewidth)
	{
		fz_buffer_printf(ctx, gs->buf, "%f w\n", stroke_state->linewidth);
	}
	if (!gs->stroke_state || gs->stroke_state->start_cap != stroke_state->start_cap)
	{
		int cap = stroke_state->start_cap;
		/* FIXME: Triangle caps aren't supported in pdf */
		if (cap == FZ_LINECAP_TRIANGLE)
			cap = FZ_LINECAP_BUTT;
		fz_buffer_printf(ctx, gs->buf, "%d J\n", cap);
	}
	if (!gs->stroke_state || gs->stroke_state->linejoin != stroke_state->linejoin)
	{
		int join = stroke_state->linejoin;
		if (join == FZ_LINEJOIN_MITER_XPS)
			join = FZ_LINEJOIN_MITER;
		fz_buffer_printf(ctx, gs->buf, "%d j\n", join);
	}
	if (!gs->stroke_state || gs->stroke_state->miterlimit != stroke_state->miterlimit)
	{
		fz_buffer_printf(ctx, gs->buf, "%f M\n", stroke_state->miterlimit);
	}
	if (gs->stroke_state == NULL && stroke_state->dash_len == 0)
	{}
	else if (!gs->stroke_state || gs->stroke_state->dash_phase != stroke_state->dash_phase || gs->stroke_state->dash_len != stroke_state->dash_len ||
		memcmp(gs->stroke_state->dash_list, stroke_state->dash_list, sizeof(float)*stroke_state->dash_len))
	{
		int i;
		if (stroke_state->dash_len == 0)
			fz_buffer_printf(ctx, gs->buf, "[");
		for (i = 0; i < stroke_state->dash_len; i++)
			fz_buffer_printf(ctx, gs->buf, "%c%f", (i == 0 ? '[' : ' '), stroke_state->dash_list[i]);
		fz_buffer_printf(ctx, gs->buf, "]%f d\n", stroke_state->dash_phase);

	}
	fz_drop_stroke_state(ctx, gs->stroke_state);
	gs->stroke_state = fz_keep_stroke_state(ctx, stroke_state);
}
Esempio n. 17
0
static unsigned short *
pdf_append_line(pdf_xref *xref, fz_obj *res, fz_buffer *content, fz_buffer *base_ap,
	unsigned short *ucs2, float font_size, int align, float width, int is_multiline, float *x)
{
	unsigned short *end, *keep;
	float x1 = 0;
	int w;

	if (is_multiline)
	{
		end = ucs2;
		do
		{
			if (*end == '\n' || *end == '\r' && *(end + 1) != '\n')
				break;

			for (keep = end + 1; *keep && !iswspace(*keep); keep++);
			w = pdf_get_string_width(xref, res, base_ap, ucs2, keep);
			if (w <= width || end == ucs2)
				end = keep;
		} while (w <= width && *end);
	}
	else
		end = ucs2 + wcslen(ucs2);

	if (align != 0)
	{
		w = pdf_get_string_width(xref, res, base_ap, ucs2, end);
		if (w < 0)
			fz_error_handle(xref->ctx, -1, "can't change the text's alignment");
		else if (align == 1 /* centered */)
			x1 = (width - w) / 2;
		else if (align == 2 /* right-aligned */)
			x1 = width - w;
		else
			fz_warn(xref->ctx, "ignoring unknown quadding value %d", align);
	}

	fz_buffer_printf(xref->ctx, content, "%.4f %.4f Td ", x1 - *x, -font_size);
	pdf_string_to_Tj(xref->ctx, content, ucs2, end);
	*x = x1;

	return end + (*end ? 1 : 0);
}
Esempio n. 18
0
static int make_fake_doc(pdfapp_t *app)
{
	fz_context *ctx = app->ctx;
	pdf_document *pdf = NULL;
	fz_buffer *contents = NULL;

	fz_try(ctx)
	{
		fz_rect mediabox = { 0, 0, app->winw, app->winh };
		pdf_obj *page_obj;
		int i;

		contents = fz_new_buffer(ctx, 100);
		pdf = pdf_create_document(ctx);

		app->doc = (fz_document*)pdf;

		fz_buffer_printf(ctx, contents, "1 0 0 rg %f w 0 0 m %f %f l 0 %f m %f 0 l\n",
			fz_min(mediabox.x1, mediabox.y1) / 4,
			mediabox.x1, mediabox.y1,
			mediabox.y1, mediabox.x1);

		/* Create enough copies of our blank(ish) page so that the
		 * page number is preserved if and when a subsequent load
		 * works. */
		page_obj = pdf_add_page(ctx, pdf, &mediabox, 0, contents, NULL);
		for (i = 0; i < app->pagecount; i++)
			pdf_insert_page(ctx, pdf, -1, page_obj);
		pdf_drop_obj(ctx, page_obj);
	}
	fz_always(ctx)
	{
		fz_drop_buffer(ctx, contents);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
	return 0;
}
Esempio n. 19
0
static void
pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, const float *color, int stroke)
{
	int diff = 0;
	int i;
	int cspace = 0;
	float rgb[FZ_MAX_COLORS];
	gstate *gs = CURRENT_GSTATE(pdev);

	if (colorspace == fz_device_gray(ctx))
		cspace = 1;
	else if (colorspace == fz_device_rgb(ctx))
		cspace = 3;
	else if (colorspace == fz_device_cmyk(ctx))
		cspace = 4;

	if (cspace == 0)
	{
		/* If it's an unknown colorspace, fallback to rgb */
		colorspace->to_rgb(ctx, colorspace, color, rgb);
		color = rgb;
		colorspace = fz_device_rgb(ctx);
	}

	if (gs->colorspace[stroke] != colorspace)
	{
		gs->colorspace[stroke] = colorspace;
		diff = 1;
	}

	for (i=0; i < colorspace->n; i++)
		if (gs->color[stroke][i] != color[i])
		{
			gs->color[stroke][i] = color[i];
			diff = 1;
		}

	if (diff == 0)
		return;

	switch (cspace + stroke*8)
	{
		case 1:
			fz_buffer_printf(ctx, gs->buf, "%f g\n", color[0]);
			break;
		case 3:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f rg\n", color[0], color[1], color[2]);
			break;
		case 4:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f %f k\n", color[0], color[1], color[2], color[3]);
			break;
		case 1+8:
			fz_buffer_printf(ctx, gs->buf, "%f G\n", color[0]);
			break;
		case 3+8:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f RG\n", color[0], color[1], color[2]);
			break;
		case 4+8:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f %f K\n", color[0], color[1], color[2], color[3]);
			break;
	}
}
Esempio n. 20
0
static pdf_annot *
pdf_update_tx_widget_annot(pdf_xref *xref, fz_obj *obj)
{
	fz_obj *ap, *res, *value;
	fz_rect rect;
	fz_buffer *content, *base_ap;
	int flags, align, rotate, is_multiline;
	float font_size, x, y;
	char *font_name;
	unsigned short *ucs2, *rest;

	fz_context *ctx = xref->ctx;

	if (strcmp(fz_to_name(ctx, fz_dict_gets(ctx, obj, "Subtype")), "Widget") != 0)
		return NULL;
	if (!fz_to_bool(ctx, pdf_dict_get_inheritable(xref, NULL, "NeedAppearances")) && pdf_get_ap_stream(xref, obj))
		return NULL;
	value = pdf_dict_get_inheritable(xref, obj, "FT");
	if (strcmp(fz_to_name(ctx, value), "Tx") != 0)
		return NULL;

	ap = pdf_dict_get_inheritable(xref, obj, "DA");
	value = pdf_dict_get_inheritable(xref, obj, "V");
	if (!ap || !value)
		return NULL;

	res = pdf_dict_get_inheritable(xref, obj, "DR");
	rect = pdf_to_rect(ctx, fz_dict_gets(ctx, obj, "Rect"));
	rotate = fz_to_int(ctx, fz_dict_gets(ctx, fz_dict_gets(ctx, obj, "MK"), "R"));
	rect = fz_transform_rect(fz_rotate(rotate), rect);

	flags = fz_to_int(ctx, fz_dict_gets(ctx, obj, "Ff"));
	is_multiline = (flags & (1 << 12)) != 0;
	if ((flags & (1 << 25) /* richtext */))
		fz_warn(ctx, "missing support for richtext fields");
	align = fz_to_int(ctx, fz_dict_gets(ctx, obj, "Q"));

	font_size = pdf_extract_font_size(xref, fz_to_str_buf(ctx, ap), &font_name);
	if (!font_size || !font_name)
		font_size = is_multiline ? 10 /* FIXME */ : floor(rect.y1 - rect.y0 - 2);

	content = fz_new_buffer(ctx, 256);
	base_ap = fz_new_buffer(ctx, 256);
	pdf_prepend_ap_background(content, xref, obj);
	fz_buffer_printf(ctx, content, "/Tx BMC q 1 1 %.4f %.4f re W n BT %s ",
		rect.x1 - rect.x0 - 2.0f, rect.y1 - rect.y0 - 2.0f, fz_to_str_buf(ctx, ap));
	fz_buffer_printf(ctx, base_ap, "/Tx BMC q BT %s ", fz_to_str_buf(ctx, ap));
	if (font_name)
	{
		fz_buffer_printf(ctx, content, "/%s %.4f Tf ", font_name, font_size);
		fz_buffer_printf(ctx, base_ap, "/%s %.4f Tf ", font_name, font_size);
		fz_free(ctx, font_name);
	}
	y = 0.5f * (rect.y1 - rect.y0) + 0.6f * font_size;
	if (is_multiline)
		y = rect.y1 - rect.y0 - 2;
	fz_buffer_printf(ctx, content, "1 0 0 1 2 %.4f Tm ", y);

	ucs2 = pdf_to_ucs2(ctx, value);
	for (rest = ucs2; *rest; rest++)
		if (*rest > 0xFF)
			*rest = '?';
	if ((flags & (1 << 13) /* password */))
		for (rest = ucs2; *rest; rest++)
			*rest = '*';

	x = 0;
	rest = ucs2;
	if ((flags & (1 << 24) /* comb */))
	{
		pdf_append_combed_line(xref, res, content, base_ap, ucs2, font_size, rect.x1 - rect.x0, fz_to_int(ctx, pdf_dict_get_inheritable(xref, obj, "MaxLen")));
		rest = L"";
	}
	while (*rest)
		rest = pdf_append_line(xref, res, content, base_ap, rest, font_size, align, rect.x1 - rect.x0 - 4.0f, is_multiline, &x);

	fz_free(ctx, ucs2);
	fz_buffer_printf(ctx, content, "ET Q EMC");
	fz_drop_buffer(ctx, base_ap);

	rect = fz_transform_rect(fz_rotate(-rotate), rect);
	return pdf_create_annot(ctx, rect, fz_keep_obj(obj), content, res ? fz_keep_obj(res) : NULL, 0);
}