コード例 #1
0
ファイル: pdf_annot.c プロジェクト: DeepGopani/mupdf
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);
}
コード例 #2
0
ファイル: dev_bbox.c プロジェクト: AvinashKiran/mupdf
static void
fz_bbox_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
{
	fz_rect *result = dev->user;
	fz_rect r;
	fz_union_rect(result, fz_bound_shade(dev->ctx, shade, ctm, &r));
}
コード例 #3
0
ファイル: dev_bbox.c プロジェクト: AvinashKiran/mupdf
static void
fz_bbox_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
{
	fz_rect *result = dev->user;
	fz_rect r = fz_unit_rect;
	fz_union_rect(result, fz_transform_rect(&r, ctm));
}
コード例 #4
0
ファイル: device.c プロジェクト: lintmars/sumatrapdf
static void
push_clip_stack_accumulate(fz_device *dev, const fz_rect *rect, int accumulate)
{
	if (accumulate <= 1)
	{
		dev->scissor_accumulator = *rect;
		if (dev->container_len == dev->container_cap)
		{
			int newmax = dev->container_cap * 2;
			if (newmax == 0)
				newmax = 4;
			dev->container = fz_resize_array(dev->ctx, dev->container, newmax, sizeof(*dev->container));
			dev->container_cap = newmax;
		}
		if (dev->container_len > 0)
			dev->container[dev->container_len].scissor = dev->container[dev->container_len-1].scissor;
		else
			dev->container[dev->container_len].scissor = fz_infinite_rect;
		fz_intersect_rect(&dev->container[dev->container_len].scissor, rect);
		dev->container[dev->container_len].flags = fz_device_container_stack_is_clip_text;
		dev->container[dev->container_len].user = 0;
		dev->container_len++;
	}
	else
	{
		if (dev->container_len <= 0)
			return;
		fz_union_rect(&dev->scissor_accumulator, rect);
		fz_intersect_rect(&dev->container[dev->container_len-1].scissor, &dev->scissor_accumulator);
	}
}
コード例 #5
0
ファイル: dev_bbox.c プロジェクト: AvinashKiran/mupdf
static void
fz_bbox_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke,
	const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha)
{
	fz_rect *result = dev->user;
	fz_rect r;
	fz_union_rect(result, fz_bound_text(dev->ctx, text, ctm, &r));
}
コード例 #6
0
ファイル: dev_bbox.c プロジェクト: AvinashKiran/mupdf
static void
fz_bbox_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm,
	fz_colorspace *colorspace, float *color, float alpha)
{
	fz_rect *result = dev->user;
	fz_rect r;
	fz_union_rect(result, fz_bound_path(dev->ctx, path, NULL, ctm, &r));
}
コード例 #7
0
ファイル: pdf-appearance.c プロジェクト: TamirEvan/mupdf
static void
union_quad(fz_rect *rect, const fz_point quad[4], float lw)
{
	fz_rect qbox;
	qbox.x0 = fz_min(fz_min(quad[0].x, quad[1].x), fz_min(quad[2].x, quad[3].x));
	qbox.y0 = fz_min(fz_min(quad[0].y, quad[1].y), fz_min(quad[2].y, quad[3].y));
	qbox.x1 = fz_max(fz_max(quad[0].x, quad[1].x), fz_max(quad[2].x, quad[3].x));
	qbox.y1 = fz_max(fz_max(quad[0].y, quad[1].y), fz_max(quad[2].y, quad[3].y));
	*rect = fz_union_rect(*rect, fz_expand_rect(qbox, lw));
}
コード例 #8
0
ファイル: dev_text.c プロジェクト: aarjones55/sumatrapdf
static void
append_line(fz_context *ctx, fz_text_block *block, fz_text_line *line)
{
	if (block->len == block->cap)
	{
		int new_cap = fz_maxi(16, block->cap * 2);
		block->lines = fz_resize_array(ctx, block->lines, new_cap, sizeof *block->lines);
		block->cap = new_cap;
	}
	fz_union_rect(&block->bbox, &line->bbox);
	block->lines[block->len++] = *line;
}
コード例 #9
0
ファイル: dev_bbox.c プロジェクト: DavidWiberg/sumatrapdf
static void
fz_bbox_add_rect(fz_device *dev, const fz_rect *rect, int clip)
{
	fz_bbox_data *data = dev->user;
	fz_rect r = *rect;

	if (0 < data->top && data->top <= STACK_SIZE)
		fz_intersect_rect(&r, &data->stack[data->top-1]);
	if (!clip && data->top <= STACK_SIZE && !data->ignore)
		fz_union_rect(data->result, &r);
	if (clip && ++data->top <= STACK_SIZE)
		data->stack[data->top-1] = r;
}
コード例 #10
0
ファイル: stext-search.c プロジェクト: ArtifexSoftware/mupdf
int
fz_highlight_selection(fz_context *ctx, fz_stext_page *page, fz_rect rect, fz_rect *hit_bbox, int hit_max)
{
	fz_rect linebox, charbox;
	fz_stext_block *block;
	fz_stext_line *line;
	fz_stext_span *span;
	int i, block_num, hit_count;

	float x0 = rect.x0;
	float x1 = rect.x1;
	float y0 = rect.y0;
	float y1 = rect.y1;

	hit_count = 0;

	for (block_num = 0; block_num < page->len; block_num++)
	{
		if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
			continue;
		block = page->blocks[block_num].u.text;
		for (line = block->lines; line < block->lines + block->len; line++)
		{
			linebox = fz_empty_rect;
			for (span = line->first_span; span; span = span->next)
			{
				for (i = 0; i < span->len; i++)
				{
					fz_stext_char_bbox(ctx, &charbox, span, i);
					if (charbox.x1 >= x0 && charbox.x0 <= x1 && charbox.y1 >= y0 && charbox.y0 <= y1)
					{
						if (charbox.y0 != linebox.y0 || fz_abs(charbox.x0 - linebox.x1) > 5)
						{
							if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
								hit_bbox[hit_count++] = linebox;
							linebox = charbox;
						}
						else
						{
							fz_union_rect(&linebox, &charbox);
						}
					}
				}
			}
			if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
				hit_bbox[hit_count++] = linebox;
		}
	}

	return hit_count;
}
コード例 #11
0
ファイル: dev_text.c プロジェクト: aarjones55/sumatrapdf
static void
append_span(fz_context *ctx, fz_text_line *line, fz_text_span *span)
{
	if (span->len == 0)
		return;
	if (line->len == line->cap)
	{
		int new_cap = fz_maxi(8, line->cap * 2);
		line->spans = fz_resize_array(ctx, line->spans, new_cap, sizeof(*line->spans));
		line->cap = new_cap;
	}
	fz_union_rect(&line->bbox, &span->bbox);
	line->spans[line->len++] = *span;
}
コード例 #12
0
ファイル: dev_text.c プロジェクト: aarjones55/sumatrapdf
static void
append_char(fz_context *ctx, fz_text_span *span, int c, fz_rect bbox)
{
	if (span->len == span->cap)
	{
		int new_cap = fz_maxi(64, span->cap * 2);
		span->text = fz_resize_array(ctx, span->text, new_cap, sizeof(*span->text));
		span->cap = new_cap;
	}
	fz_union_rect(&span->bbox, &bbox);
	span->text[span->len].c = c;
	span->text[span->len].bbox = bbox;
	span->len++;
}
コード例 #13
0
ファイル: doc_search.c プロジェクト: Jshauk/sumatrapdf
int
fz_highlight_selection(fz_context *ctx, fz_text_page *page, fz_rect rect, fz_rect *hit_bbox, int hit_max)
{
	fz_rect linebox, charbox;
	fz_text_block *block;
	fz_text_line *line;
	int i, hit_count;

	float x0 = rect.x0;
	float x1 = rect.x1;
	float y0 = rect.y0;
	float y1 = rect.y1;

	hit_count = 0;

	for (block = page->blocks; block < page->blocks + page->len; block++)
	{
		for (line = block->lines; line < block->lines + block->len; line++)
		{
			int span_num;
			linebox = fz_empty_rect;
			for (span_num = 0; span_num < line->len; span_num++)
			{
				fz_text_span *span = line->spans[span_num];
				for (i = 0; i < span->len; i++)
				{
					fz_text_char_bbox(&charbox, span, i);
					if (charbox.x1 >= x0 && charbox.x0 <= x1 && charbox.y1 >= y0 && charbox.y0 <= y1)
					{
						if (charbox.y0 != linebox.y0 || fz_abs(charbox.x0 - linebox.x1) > 5)
						{
							if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
								hit_bbox[hit_count++] = linebox;
							linebox = charbox;
						}
						else
						{
							fz_union_rect(&linebox, &charbox);
						}
					}
				}
			}
			if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
				hit_bbox[hit_count++] = linebox;
		}
	}

	return hit_count;
}
コード例 #14
0
ファイル: pdf_annot.c プロジェクト: DeepGopani/mupdf
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);
}
コード例 #15
0
ファイル: stext-search.c プロジェクト: ccxvii/mupdf
int
fz_highlight_selection(fz_context *ctx, fz_stext_page *page, fz_rect rect, fz_rect *hit_bbox, int hit_max)
{
	fz_rect linebox, charbox;
	fz_stext_block *block;
	fz_stext_line *line;
	fz_stext_char *ch;
	int hit_count;

	float x0 = rect.x0;
	float x1 = rect.x1;
	float y0 = rect.y0;
	float y1 = rect.y1;

	hit_count = 0;

	for (block = page->first_block; block; block = block->next)
	{
		if (block->type != FZ_STEXT_BLOCK_TEXT)
			continue;
		for (line = block->u.t.first_line; line; line = line->next)
		{
			linebox = fz_empty_rect;
			for (ch = line->first_char; ch; ch = ch->next)
			{
				fz_stext_char_bbox(ctx, &charbox, line, ch);
				if (charbox.x1 >= x0 && charbox.x0 <= x1 && charbox.y1 >= y0 && charbox.y0 <= y1)
				{
					if (charbox.y0 != linebox.y0 || fz_abs(charbox.x0 - linebox.x1) > 5)
					{
						if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
							hit_bbox[hit_count++] = linebox;
						linebox = charbox;
					}
					else
					{
						fz_union_rect(&linebox, &charbox);
					}
				}
			}
			if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
				hit_bbox[hit_count++] = linebox;
		}
	}

	return hit_count;
}
コード例 #16
0
ファイル: stext-search.c プロジェクト: ccxvii/mupdf
int
fz_search_stext_page(fz_context *ctx, fz_stext_page *text, const char *needle, fz_rect *hit_bbox, int hit_max)
{
	int pos, len, i, n, hit_count;

	if (strlen(needle) == 0)
		return 0;

	hit_count = 0;
	len = textlen_stext(ctx, text);
	pos = 0;
	while (pos < len)
	{
		n = match_stext(ctx, text, needle, pos);
		if (n)
		{
			fz_rect linebox = fz_empty_rect;
			for (i = 0; i < n; i++)
			{
				fz_rect charbox;
				bboxat(ctx, text, pos + i, &charbox);
				if (!fz_is_empty_rect(&charbox))
				{
					if (charbox.y0 != linebox.y0 || fz_abs(charbox.x0 - linebox.x1) > 5)
					{
						if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
							hit_bbox[hit_count++] = linebox;
						linebox = charbox;
					}
					else
					{
						fz_union_rect(&linebox, &charbox);
					}
				}
			}
			if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
				hit_bbox[hit_count++] = linebox;
			pos += n;
		}
		else
		{
			pos += 1;
		}
	}

	return hit_count;
}
コード例 #17
0
ファイル: text.c プロジェクト: mandeep57/mupdf
fz_rect *
fz_bound_text(fz_context *ctx, const fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_rect *bbox)
{
	fz_text_span *span;
	fz_matrix tm, trm;
	fz_rect gbox;
	int i;

	*bbox = fz_empty_rect;

	for (span = text->head; span; span = span->next)
	{
		if (span->len > 0)
		{
			tm = span->trm;
			for (i = 0; i < span->len; i++)
			{
				if (span->items[i].gid >= 0)
				{
					tm.e = span->items[i].x;
					tm.f = span->items[i].y;
					fz_concat(&trm, &tm, ctm);
					fz_bound_glyph(ctx, span->font, span->items[i].gid, &trm, &gbox);
					fz_union_rect(bbox, &gbox);
				}
			}

		}
	}

	if (!fz_is_empty_rect(bbox))
	{
		if (stroke)
			fz_adjust_rect_for_stroke(ctx, bbox, stroke, ctm);

		/* Compensate for the glyph cache limited positioning precision */
		bbox->x0 -= 1;
		bbox->y0 -= 1;
		bbox->x1 += 1;
		bbox->y1 += 1;
	}

	return bbox;
}
コード例 #18
0
static void
fz_bbox_add_rect(fz_context *ctx, fz_device *dev, const fz_rect *rect, int clip)
{
	fz_bbox_device *bdev = (fz_bbox_device*)dev;
	fz_rect r = *rect;

	if (0 < bdev->top && bdev->top <= STACK_SIZE)
	{
		fz_intersect_rect(&r, &bdev->stack[bdev->top-1]);
	}
	if (!clip && bdev->top <= STACK_SIZE && !bdev->ignore)
	{
		fz_union_rect(bdev->result, &r);
	}
	if (clip && ++bdev->top <= STACK_SIZE)
	{
		bdev->stack[bdev->top-1] = r;
	}
}
コード例 #19
0
void
xps_parse_path(xps_document *doc, const fz_matrix *ctm, char *base_uri, xps_resource *dict, fz_xml *root)
{
	fz_xml *node;

	char *fill_uri;
	char *stroke_uri;
	char *opacity_mask_uri;

	char *transform_att;
	char *clip_att;
	char *data_att;
	char *fill_att;
	char *stroke_att;
	char *opacity_att;
	char *opacity_mask_att;

	fz_xml *transform_tag = NULL;
	fz_xml *clip_tag = NULL;
	fz_xml *data_tag = NULL;
	fz_xml *fill_tag = NULL;
	fz_xml *stroke_tag = NULL;
	fz_xml *opacity_mask_tag = NULL;

	char *fill_opacity_att = NULL;
	char *stroke_opacity_att = NULL;

	char *stroke_dash_array_att;
	char *stroke_dash_cap_att;
	char *stroke_dash_offset_att;
	char *stroke_end_line_cap_att;
	char *stroke_start_line_cap_att;
	char *stroke_line_join_att;
	char *stroke_miter_limit_att;
	char *stroke_thickness_att;
	char *navigate_uri_att;

	fz_stroke_state *stroke = NULL;
	fz_matrix transform;
	float samples[32];
	fz_colorspace *colorspace;
	fz_path *path = NULL;
	fz_path *stroke_path = NULL;
	fz_rect area;
	int fill_rule;
	int dash_len = 0;
	fz_matrix local_ctm;

	/*
	 * Extract attributes and extended attributes.
	 */

	transform_att = fz_xml_att(root, "RenderTransform");
	clip_att = fz_xml_att(root, "Clip");
	data_att = fz_xml_att(root, "Data");
	fill_att = fz_xml_att(root, "Fill");
	stroke_att = fz_xml_att(root, "Stroke");
	opacity_att = fz_xml_att(root, "Opacity");
	opacity_mask_att = fz_xml_att(root, "OpacityMask");

	stroke_dash_array_att = fz_xml_att(root, "StrokeDashArray");
	stroke_dash_cap_att = fz_xml_att(root, "StrokeDashCap");
	stroke_dash_offset_att = fz_xml_att(root, "StrokeDashOffset");
	stroke_end_line_cap_att = fz_xml_att(root, "StrokeEndLineCap");
	stroke_start_line_cap_att = fz_xml_att(root, "StrokeStartLineCap");
	stroke_line_join_att = fz_xml_att(root, "StrokeLineJoin");
	stroke_miter_limit_att = fz_xml_att(root, "StrokeMiterLimit");
	stroke_thickness_att = fz_xml_att(root, "StrokeThickness");
	navigate_uri_att = fz_xml_att(root, "FixedPage.NavigateUri");

	for (node = fz_xml_down(root); node; node = fz_xml_next(node))
	{
		if (!strcmp(fz_xml_tag(node), "Path.RenderTransform"))
			transform_tag = fz_xml_down(node);
		if (!strcmp(fz_xml_tag(node), "Path.OpacityMask"))
			opacity_mask_tag = fz_xml_down(node);
		if (!strcmp(fz_xml_tag(node), "Path.Clip"))
			clip_tag = fz_xml_down(node);
		if (!strcmp(fz_xml_tag(node), "Path.Fill"))
			fill_tag = fz_xml_down(node);
		if (!strcmp(fz_xml_tag(node), "Path.Stroke"))
			stroke_tag = fz_xml_down(node);
		if (!strcmp(fz_xml_tag(node), "Path.Data"))
			data_tag = fz_xml_down(node);
	}

	fill_uri = base_uri;
	stroke_uri = base_uri;
	opacity_mask_uri = base_uri;

	xps_resolve_resource_reference(doc, dict, &data_att, &data_tag, NULL);
	xps_resolve_resource_reference(doc, dict, &clip_att, &clip_tag, NULL);
	xps_resolve_resource_reference(doc, dict, &transform_att, &transform_tag, NULL);
	xps_resolve_resource_reference(doc, dict, &fill_att, &fill_tag, &fill_uri);
	xps_resolve_resource_reference(doc, dict, &stroke_att, &stroke_tag, &stroke_uri);
	xps_resolve_resource_reference(doc, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri);

	/*
	 * Act on the information we have gathered:
	 */

	if (!data_att && !data_tag)
		return;

	if (fill_tag && !strcmp(fz_xml_tag(fill_tag), "SolidColorBrush"))
	{
		fill_opacity_att = fz_xml_att(fill_tag, "Opacity");
		fill_att = fz_xml_att(fill_tag, "Color");
		fill_tag = NULL;
	}

	if (stroke_tag && !strcmp(fz_xml_tag(stroke_tag), "SolidColorBrush"))
	{
		stroke_opacity_att = fz_xml_att(stroke_tag, "Opacity");
		stroke_att = fz_xml_att(stroke_tag, "Color");
		stroke_tag = NULL;
	}

	if (stroke_att || stroke_tag)
	{
		if (stroke_dash_array_att)
		{
			char *s = stroke_dash_array_att;

			while (*s)
			{
				while (*s == ' ')
					s++;
				if (*s) /* needed in case of a space before the last quote */
					dash_len++;

				while (*s && *s != ' ')
					s++;
			}
		}
		stroke = fz_new_stroke_state_with_len(doc->ctx, dash_len);
		stroke->start_cap = xps_parse_line_cap(stroke_start_line_cap_att);
		stroke->dash_cap = xps_parse_line_cap(stroke_dash_cap_att);
		stroke->end_cap = xps_parse_line_cap(stroke_end_line_cap_att);

		stroke->linejoin = FZ_LINEJOIN_MITER_XPS;
		if (stroke_line_join_att)
		{
			if (!strcmp(stroke_line_join_att, "Miter")) stroke->linejoin = FZ_LINEJOIN_MITER_XPS;
			if (!strcmp(stroke_line_join_att, "Round")) stroke->linejoin = FZ_LINEJOIN_ROUND;
			if (!strcmp(stroke_line_join_att, "Bevel")) stroke->linejoin = FZ_LINEJOIN_BEVEL;
		}

		stroke->miterlimit = 10;
		if (stroke_miter_limit_att)
			stroke->miterlimit = fz_atof(stroke_miter_limit_att);

		stroke->linewidth = 1;
		if (stroke_thickness_att)
			stroke->linewidth = fz_atof(stroke_thickness_att);

		stroke->dash_phase = 0;
		stroke->dash_len = 0;
		if (stroke_dash_array_att)
		{
			char *s = stroke_dash_array_att;

			if (stroke_dash_offset_att)
				stroke->dash_phase = fz_atof(stroke_dash_offset_att) * stroke->linewidth;

			while (*s)
			{
				while (*s == ' ')
					s++;
				if (*s) /* needed in case of a space before the last quote */
					stroke->dash_list[stroke->dash_len++] = fz_atof(s) * stroke->linewidth;
				while (*s && *s != ' ')
					s++;
			}
			/* cf. https://code.google.com/p/sumatrapdf/issues/detail?id=2339 */
			if (dash_len > 0)
			{
				float phase_len = 0.0f;
				int i;
				for (i = 0; i < dash_len; i++)
					phase_len += stroke->dash_list[i];
				if (phase_len == 0.0f)
					dash_len = 0;
			}
			stroke->dash_len = dash_len;
		}
	}

	transform = fz_identity;
	if (transform_att)
		xps_parse_render_transform(doc, transform_att, &transform);
	if (transform_tag)
		xps_parse_matrix_transform(doc, transform_tag, &transform);
	fz_concat(&local_ctm, &transform, ctm);

	if (clip_att || clip_tag)
		xps_clip(doc, &local_ctm, dict, clip_att, clip_tag);

	fill_rule = 0;
	if (data_att)
		path = xps_parse_abbreviated_geometry(doc, data_att, &fill_rule);
	else if (data_tag)
	{
		path = xps_parse_path_geometry(doc, dict, data_tag, 0, &fill_rule);
		if (stroke_att || stroke_tag)
			stroke_path = xps_parse_path_geometry(doc, dict, data_tag, 1, &fill_rule);
	}
	if (!stroke_path)
		stroke_path = path;

	if (stroke_att || stroke_tag)
	{
		fz_bound_path(doc->ctx, stroke_path, stroke, &local_ctm, &area);
		if (stroke_path != path && (fill_att || fill_tag)) {
			fz_rect bounds;
			fz_bound_path(doc->ctx, path, NULL, &local_ctm, &bounds);
			fz_union_rect(&area, &bounds);
		}
	}
	else
		fz_bound_path(doc->ctx, path, NULL, &local_ctm, &area);

	/* SumatraPDF: extended link support */
	xps_extract_anchor_info(doc, &area, navigate_uri_att, fz_xml_att(root, "Name"), 0);
	navigate_uri_att = NULL;

	if (navigate_uri_att)
		xps_add_link(doc, &area, base_uri, navigate_uri_att);

	xps_begin_opacity(doc, &local_ctm, &area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);

	if (fill_att)
	{
		xps_parse_color(doc, base_uri, fill_att, &colorspace, samples);
		if (fill_opacity_att)
			samples[0] *= fz_atof(fill_opacity_att);
		xps_set_color(doc, colorspace, samples);

		fz_fill_path(doc->dev, path, fill_rule == 0, &local_ctm,
			doc->colorspace, doc->color, doc->alpha);
	}

	if (fill_tag)
	{
		fz_clip_path(doc->dev, path, NULL, fill_rule == 0, &local_ctm);
		xps_parse_brush(doc, &local_ctm, &area, fill_uri, dict, fill_tag);
		fz_pop_clip(doc->dev);
	}

	if (stroke_att)
	{
		xps_parse_color(doc, base_uri, stroke_att, &colorspace, samples);
		if (stroke_opacity_att)
			samples[0] *= fz_atof(stroke_opacity_att);
		xps_set_color(doc, colorspace, samples);

		fz_stroke_path(doc->dev, stroke_path, stroke, &local_ctm,
			doc->colorspace, doc->color, doc->alpha);
	}

	if (stroke_tag)
	{
		fz_clip_stroke_path(doc->dev, stroke_path, NULL, stroke, &local_ctm);
		xps_parse_brush(doc, &local_ctm, &area, stroke_uri, dict, stroke_tag);
		fz_pop_clip(doc->dev);
	}

	xps_end_opacity(doc, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);

	if (stroke_path != path)
		fz_free_path(doc->ctx, stroke_path);
	fz_free_path(doc->ctx, path);
	path = NULL;
	fz_drop_stroke_state(doc->ctx, stroke);

	if (clip_att || clip_tag)
		fz_pop_clip(doc->dev);
}
コード例 #20
0
ファイル: xps-path.c プロジェクト: TamirEvan/mupdf
void
xps_parse_path(fz_context *ctx, xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *dict, fz_xml *root)
{
	fz_device *dev = doc->dev;

	fz_xml *node;

	char *fill_uri;
	char *stroke_uri;
	char *opacity_mask_uri;

	char *transform_att;
	char *clip_att;
	char *data_att;
	char *fill_att;
	char *stroke_att;
	char *opacity_att;
	char *opacity_mask_att;

	fz_xml *transform_tag = NULL;
	fz_xml *clip_tag = NULL;
	fz_xml *data_tag = NULL;
	fz_xml *fill_tag = NULL;
	fz_xml *stroke_tag = NULL;
	fz_xml *opacity_mask_tag = NULL;

	char *fill_opacity_att = NULL;
	char *stroke_opacity_att = NULL;

	char *stroke_dash_array_att;
	char *stroke_dash_cap_att;
	char *stroke_dash_offset_att;
	char *stroke_end_line_cap_att;
	char *stroke_start_line_cap_att;
	char *stroke_line_join_att;
	char *stroke_miter_limit_att;
	char *stroke_thickness_att;

	fz_stroke_state *stroke = NULL;
	float samples[FZ_MAX_COLORS];
	fz_colorspace *colorspace;
	fz_path *path = NULL;
	fz_path *stroke_path = NULL;
	fz_rect area;
	int fill_rule;
	int dash_len = 0;

	/*
	 * Extract attributes and extended attributes.
	 */

	transform_att = fz_xml_att(root, "RenderTransform");
	clip_att = fz_xml_att(root, "Clip");
	data_att = fz_xml_att(root, "Data");
	fill_att = fz_xml_att(root, "Fill");
	stroke_att = fz_xml_att(root, "Stroke");
	opacity_att = fz_xml_att(root, "Opacity");
	opacity_mask_att = fz_xml_att(root, "OpacityMask");

	stroke_dash_array_att = fz_xml_att(root, "StrokeDashArray");
	stroke_dash_cap_att = fz_xml_att(root, "StrokeDashCap");
	stroke_dash_offset_att = fz_xml_att(root, "StrokeDashOffset");
	stroke_end_line_cap_att = fz_xml_att(root, "StrokeEndLineCap");
	stroke_start_line_cap_att = fz_xml_att(root, "StrokeStartLineCap");
	stroke_line_join_att = fz_xml_att(root, "StrokeLineJoin");
	stroke_miter_limit_att = fz_xml_att(root, "StrokeMiterLimit");
	stroke_thickness_att = fz_xml_att(root, "StrokeThickness");

	for (node = fz_xml_down(root); node; node = fz_xml_next(node))
	{
		if (fz_xml_is_tag(node, "Path.RenderTransform"))
			transform_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Path.OpacityMask"))
			opacity_mask_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Path.Clip"))
			clip_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Path.Fill"))
			fill_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Path.Stroke"))
			stroke_tag = fz_xml_down(node);
		if (fz_xml_is_tag(node, "Path.Data"))
			data_tag = fz_xml_down(node);
	}

	fill_uri = base_uri;
	stroke_uri = base_uri;
	opacity_mask_uri = base_uri;

	xps_resolve_resource_reference(ctx, doc, dict, &data_att, &data_tag, NULL);
	xps_resolve_resource_reference(ctx, doc, dict, &clip_att, &clip_tag, NULL);
	xps_resolve_resource_reference(ctx, doc, dict, &transform_att, &transform_tag, NULL);
	xps_resolve_resource_reference(ctx, doc, dict, &fill_att, &fill_tag, &fill_uri);
	xps_resolve_resource_reference(ctx, doc, dict, &stroke_att, &stroke_tag, &stroke_uri);
	xps_resolve_resource_reference(ctx, doc, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri);

	/*
	 * Act on the information we have gathered:
	 */

	if (!data_att && !data_tag)
		return;

	if (fz_xml_is_tag(fill_tag, "SolidColorBrush"))
	{
		fill_opacity_att = fz_xml_att(fill_tag, "Opacity");
		fill_att = fz_xml_att(fill_tag, "Color");
		fill_tag = NULL;
	}

	if (fz_xml_is_tag(stroke_tag, "SolidColorBrush"))
	{
		stroke_opacity_att = fz_xml_att(stroke_tag, "Opacity");
		stroke_att = fz_xml_att(stroke_tag, "Color");
		stroke_tag = NULL;
	}

	if (stroke_att || stroke_tag)
	{
		if (stroke_dash_array_att)
		{
			char *s = stroke_dash_array_att;

			while (*s)
			{
				while (*s == ' ')
					s++;
				if (*s) /* needed in case of a space before the last quote */
					dash_len++;

				while (*s && *s != ' ')
					s++;
			}
		}
		stroke = fz_new_stroke_state_with_dash_len(ctx, dash_len);
		stroke->start_cap = xps_parse_line_cap(stroke_start_line_cap_att);
		stroke->dash_cap = xps_parse_line_cap(stroke_dash_cap_att);
		stroke->end_cap = xps_parse_line_cap(stroke_end_line_cap_att);

		stroke->linejoin = FZ_LINEJOIN_MITER_XPS;
		if (stroke_line_join_att)
		{
			if (!strcmp(stroke_line_join_att, "Miter")) stroke->linejoin = FZ_LINEJOIN_MITER_XPS;
			if (!strcmp(stroke_line_join_att, "Round")) stroke->linejoin = FZ_LINEJOIN_ROUND;
			if (!strcmp(stroke_line_join_att, "Bevel")) stroke->linejoin = FZ_LINEJOIN_BEVEL;
		}

		stroke->miterlimit = 10;
		if (stroke_miter_limit_att)
			stroke->miterlimit = fz_atof(stroke_miter_limit_att);

		stroke->linewidth = 1;
		if (stroke_thickness_att)
			stroke->linewidth = fz_atof(stroke_thickness_att);

		stroke->dash_phase = 0;
		stroke->dash_len = 0;
		if (stroke_dash_array_att)
		{
			char *s = stroke_dash_array_att;

			if (stroke_dash_offset_att)
				stroke->dash_phase = fz_atof(stroke_dash_offset_att) * stroke->linewidth;

			while (*s)
			{
				while (*s == ' ')
					s++;
				if (*s) /* needed in case of a space before the last quote */
					stroke->dash_list[stroke->dash_len++] = fz_atof(s) * stroke->linewidth;
				while (*s && *s != ' ')
					s++;
			}
			if (dash_len > 0)
			{
				/* fz_stroke_path doesn't draw non-empty paths with phase length zero */
				float phase_len = 0;
				int i;
				for (i = 0; i < dash_len; i++)
					phase_len += stroke->dash_list[i];
				if (phase_len == 0)
					dash_len = 0;
			}
			stroke->dash_len = dash_len;
		}
	}

	ctm = xps_parse_transform(ctx, doc, transform_att, transform_tag, ctm);

	if (clip_att || clip_tag)
		xps_clip(ctx, doc, ctm, dict, clip_att, clip_tag);

	fz_try(ctx)
	{
		fill_rule = 0;
		if (data_att)
			path = xps_parse_abbreviated_geometry(ctx, doc, data_att, &fill_rule);
		else if (data_tag)
		{
			path = xps_parse_path_geometry(ctx, doc, dict, data_tag, 0, &fill_rule);
			// /home/sebras/src/jxr/fts_06xx.xps
			if (stroke_att || stroke_tag)
				stroke_path = xps_parse_path_geometry(ctx, doc, dict, data_tag, 1, &fill_rule);
		}
		if (!stroke_path)
			stroke_path = path;

		if (stroke_att || stroke_tag)
		{
			area = fz_bound_path(ctx, stroke_path, stroke, ctm);
			if (stroke_path != path && (fill_att || fill_tag)) {
				fz_rect bounds = fz_bound_path(ctx, path, NULL, ctm);
				area = fz_union_rect(area, bounds);
			}
		}
		else
			area = fz_bound_path(ctx, path, NULL, ctm);

		xps_begin_opacity(ctx, doc, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);

		if (fill_att)
		{
			xps_parse_color(ctx, doc, base_uri, fill_att, &colorspace, samples);
			if (fill_opacity_att)
				samples[0] *= fz_atof(fill_opacity_att);
			xps_set_color(ctx, doc, colorspace, samples);
			fz_fill_path(ctx, dev, path, fill_rule == 0, ctm,
				doc->colorspace, doc->color, doc->alpha, NULL);
		}

		if (fill_tag)
		{
			fz_clip_path(ctx, dev, path, fill_rule == 0, ctm, area);
			xps_parse_brush(ctx, doc, ctm, area, fill_uri, dict, fill_tag);
			fz_pop_clip(ctx, dev);
		}

		if (stroke_att)
		{
			xps_parse_color(ctx, doc, base_uri, stroke_att, &colorspace, samples);
			if (stroke_opacity_att)
				samples[0] *= fz_atof(stroke_opacity_att);
			xps_set_color(ctx, doc, colorspace, samples);
			fz_stroke_path(ctx, dev, stroke_path, stroke, ctm,
				doc->colorspace, doc->color, doc->alpha, NULL);
		}

		if (stroke_tag)
		{
			fz_clip_stroke_path(ctx, dev, stroke_path, stroke, ctm, area);
			xps_parse_brush(ctx, doc, ctm, area, stroke_uri, dict, stroke_tag);
			fz_pop_clip(ctx, dev);
		}

		xps_end_opacity(ctx, doc, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);
	}
	fz_always(ctx)
	{
		if (stroke_path != path)
			fz_drop_path(ctx, stroke_path);
		fz_drop_path(ctx, path);
		fz_drop_stroke_state(ctx, stroke);
	}
	fz_catch(ctx)
		fz_rethrow(ctx);

	if (clip_att || clip_tag)
		fz_pop_clip(ctx, dev);
}
コード例 #21
0
ファイル: dev_list.c プロジェクト: scroco/mupdf
static void
fz_append_display_node(fz_display_list *list, fz_display_node *node)
{
	switch (node->cmd) {
	case FZ_CMD_CLIP_PATH:
	case FZ_CMD_CLIP_STROKE_PATH:
	case FZ_CMD_CLIP_IMAGE_MASK:
		list->stack[list->top].update = &node->rect;
		list->stack[list->top].rect = fz_empty_rect;
		list->top++;
		break;
	case FZ_CMD_CLIP_TEXT:
	case FZ_CMD_CLIP_STROKE_TEXT:
		list->stack[list->top].update = NULL;
		list->stack[list->top].rect = fz_empty_rect;
		list->top++;
		break;
	case FZ_CMD_BEGIN_TILE:
		list->tiled++;
		if (list->top > 0) {
			list->stack[list->top-1].rect = fz_infinite_rect;
		}
		break;
	case FZ_CMD_END_TILE:
		list->tiled--;
		break;
	case FZ_CMD_END_GROUP:
		break;
	case FZ_CMD_POP_CLIP:
		if (list->top > 0) {
			fz_rect *update;
			list->top--;
			update = list->stack[list->top].update;
			if (list->tiled == 0) {
				if (update != NULL) {
					*update = fz_intersect_rect(*update, list->stack[list->top].rect);
					node->rect = *update;
				} else {
					node->rect = list->stack[list->top].rect;
				}
			} else {
				node->rect = fz_infinite_rect;
			}
		}
		/*@fallthrough@*/
	default:
		if ((list->top > 0) && (list->tiled == 0)) {
			list->stack[list->top-1].rect = fz_union_rect(list->stack[list->top-1].rect, node->rect);
		}
		break;
	}
	if (!list->first)
	{
		list->first = node;
		list->last = node;
	}
	else
	{
		list->last->next = node;
		list->last = node;
	}
}
コード例 #22
0
ファイル: stext-device.c プロジェクト: ziel/mupdf
static fz_text_line *
push_span(fz_context *ctx, fz_text_device *tdev, fz_text_span *span, int new_line, float distance)
{
	fz_text_line *line;
	fz_text_block *block;
	fz_text_page *page = tdev->page;
	int prev_not_text = 0;

	if (page->len == 0 || page->blocks[page->len-1].type != FZ_PAGE_BLOCK_TEXT)
		prev_not_text = 1;

	if (new_line || prev_not_text)
	{
		float size = fz_matrix_expansion(&span->transform);
		/* So, a new line. Part of the same block or not? */
		if (distance == 0 || distance > size * 1.5 || distance < -size * PARAGRAPH_DIST || page->len == 0 || prev_not_text)
		{
			/* New block */
			if (page->len == page->cap)
			{
				int newcap = (page->cap ? page->cap*2 : 4);
				page->blocks = fz_resize_array(ctx, page->blocks, newcap, sizeof(*page->blocks));
				page->cap = newcap;
			}
			block = fz_malloc_struct(ctx, fz_text_block);
			page->blocks[page->len].type = FZ_PAGE_BLOCK_TEXT;
			page->blocks[page->len].u.text = block;
			block->cap = 0;
			block->len = 0;
			block->lines = 0;
			block->bbox = fz_empty_rect;
			page->len++;
			distance = 0;
		}

		/* New line */
		block = page->blocks[page->len-1].u.text;
		if (block->len == block->cap)
		{
			int newcap = (block->cap ? block->cap*2 : 4);
			block->lines = fz_resize_array(ctx, block->lines, newcap, sizeof(*block->lines));
			block->cap = newcap;
		}
		block->lines[block->len].first_span = NULL;
		block->lines[block->len].last_span = NULL;
		block->lines[block->len].distance = distance;
		block->lines[block->len].bbox = fz_empty_rect;
		block->len++;
	}

	/* Find last line and append to it */
	block = page->blocks[page->len-1].u.text;
	line = &block->lines[block->len-1];

	fz_union_rect(&block->lines[block->len-1].bbox, &span->bbox);
	fz_union_rect(&block->bbox, &span->bbox);
	span->base_offset = (new_line ? 0 : distance);

	if (!line->first_span)
	{
		line->first_span = line->last_span = span;
		span->next = NULL;
	}
	else
	{
		line->last_span->next = span;
		line->last_span = span;
	}

	return line;
}
コード例 #23
0
ファイル: list-device.c プロジェクト: RazvanB/sumatrapdf
static void
fz_append_display_node(fz_display_list *list, fz_display_node *node)
{
	switch (node->cmd)
	{
	case FZ_CMD_CLIP_PATH:
	case FZ_CMD_CLIP_STROKE_PATH:
	case FZ_CMD_CLIP_IMAGE_MASK:
		if (list->top < STACK_SIZE)
		{
			list->stack[list->top].update = &node->rect;
			list->stack[list->top].rect = fz_empty_rect;
		}
		list->top++;
		break;
	case FZ_CMD_CLIP_TEXT:
		/* don't reset the clip rect for accumulated text */
		if (node->flag == 2)
			break;
		/* fallthrough */
	case FZ_CMD_END_MASK:
	case FZ_CMD_CLIP_STROKE_TEXT:
		if (list->top < STACK_SIZE)
		{
			list->stack[list->top].update = NULL;
			list->stack[list->top].rect = fz_empty_rect;
		}
		list->top++;
		break;
	case FZ_CMD_BEGIN_TILE:
		list->tiled++;
		if (list->top > 0 && list->top <= STACK_SIZE)
		{
			list->stack[list->top-1].rect = fz_infinite_rect;
		}
		break;
	case FZ_CMD_END_TILE:
		list->tiled--;
		break;
	case FZ_CMD_END_GROUP:
		break;
	case FZ_CMD_POP_CLIP:
		if (list->top > STACK_SIZE)
		{
			list->top--;
			node->rect = fz_infinite_rect;
		}
		else if (list->top > 0)
		{
			fz_rect *update;
			list->top--;
			update = list->stack[list->top].update;
			if (list->tiled == 0)
			{
				if (update)
				{
					fz_intersect_rect(update, &list->stack[list->top].rect);
					node->rect = *update;
				}
				else
					node->rect = list->stack[list->top].rect;
			}
			else
				node->rect = fz_infinite_rect;
		}
		/* fallthrough */
	default:
		if (list->top > 0 && list->tiled == 0 && list->top <= STACK_SIZE)
			fz_union_rect(&list->stack[list->top-1].rect, &node->rect);
		break;
	}
	if (!list->first)
	{
		list->first = node;
		list->last = node;
	}
	else
	{
		list->last->next = node;
		list->last = node;
	}
	list->len++;
}