Beispiel #1
0
static void
fz_dash_bezier(struct sctx *s,
	float xa, float ya,
	float xb, float yb,
	float xc, float yc,
	float xd, float yd, int depth,
	int dash_cap)
{
	float dmax;
	float xab, yab;
	float xbc, ybc;
	float xcd, ycd;
	float xabc, yabc;
	float xbcd, ybcd;
	float xabcd, yabcd;

	/* termination check */
	dmax = fz_abs(xa - xb);
	dmax = fz_max(dmax, fz_abs(ya - yb));
	dmax = fz_max(dmax, fz_abs(xd - xc));
	dmax = fz_max(dmax, fz_abs(yd - yc));
	if (dmax < s->flatness || depth >= MAX_DEPTH)
	{
		fz_point p;
		p.x = xd;
		p.y = yd;
		fz_dash_lineto(s, p, dash_cap, 1);
		return;
	}

	xab = xa + xb;
	yab = ya + yb;
	xbc = xb + xc;
	ybc = yb + yc;
	xcd = xc + xd;
	ycd = yc + yd;

	xabc = xab + xbc;
	yabc = yab + ybc;
	xbcd = xbc + xcd;
	ybcd = ybc + ycd;

	xabcd = xabc + xbcd;
	yabcd = yabc + ybcd;

	xab *= 0.5f; yab *= 0.5f;
	xbc *= 0.5f; ybc *= 0.5f;
	xcd *= 0.5f; ycd *= 0.5f;

	xabc *= 0.25f; yabc *= 0.25f;
	xbcd *= 0.25f; ybcd *= 0.25f;

	xabcd *= 0.125f; yabcd *= 0.125f;

	fz_dash_bezier(s, xa, ya, xab, yab, xabc, yabc, xabcd, yabcd, depth + 1, dash_cap);
	fz_dash_bezier(s, xabcd, yabcd, xbcd, ybcd, xcd, ycd, xd, yd, depth + 1, dash_cap);
}
Beispiel #2
0
void
fz_flatten_dash_path(fz_gel *gel, fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, float flatness, float linewidth)
{
	struct sctx s;
	fz_point p0, p1, p2, p3, beg;
	float phase_len, max_expand;
	int i;

	s.gel = gel;
	s.ctm = ctm;
	s.flatness = flatness;

	s.linejoin = stroke->linejoin;
	s.linewidth = linewidth * 0.5f;
	s.miterlimit = stroke->miterlimit;
	s.sn = 0;
	s.bn = 0;
	s.dot = 0;

	s.dash_list = stroke->dash_list;
	s.dash_phase = stroke->dash_phase;
	s.dash_len = stroke->dash_len;
	s.toggle = 0;
	s.offset = 0;
	s.phase = 0;

	s.cap = stroke->start_cap;

	if (path->len > 0 && path->items[0].k != FZ_MOVETO)
		return;

	phase_len = 0;
	for (i = 0; i < stroke->dash_len; i++)
		phase_len += stroke->dash_list[i];
	max_expand = fz_matrix_max_expansion(ctm);
	if (phase_len < 1.0f && phase_len * max_expand < 0.5f)
	{
		fz_flatten_stroke_path(gel, path, stroke, ctm, flatness, linewidth);
		return;
	}

	p0.x = p0.y = 0;
	i = 0;

	while (i < path->len)
	{
		switch (path->items[i++].k)
		{
		case FZ_MOVETO:
			p1.x = path->items[i++].v;
			p1.y = path->items[i++].v;
			fz_dash_moveto(&s, p1, stroke->start_cap, stroke->end_cap);
			beg = p0 = p1;
			break;

		case FZ_LINETO:
			p1.x = path->items[i++].v;
			p1.y = path->items[i++].v;
			fz_dash_lineto(&s, p1, stroke->dash_cap, 0);
			p0 = p1;
			break;

		case FZ_CURVETO:
			p1.x = path->items[i++].v;
			p1.y = path->items[i++].v;
			p2.x = path->items[i++].v;
			p2.y = path->items[i++].v;
			p3.x = path->items[i++].v;
			p3.y = path->items[i++].v;
			fz_dash_bezier(&s, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, 0, stroke->dash_cap);
			p0 = p3;
			break;

		case FZ_CLOSE_PATH:
			fz_dash_lineto(&s, beg, stroke->dash_cap, 0);
			p0 = p1 = beg;
			break;
		}
	}

	fz_stroke_flush(&s, s.cap, stroke->end_cap);
}
Beispiel #3
0
void
fz_flatten_dash_path(fz_gel *gel, fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, float flatness, float linewidth)
{
	struct sctx s;
	fz_point p0, p1, p2, p3, beg;
	float phase_len, max_expand;
	int i, k;
	fz_matrix inv;

	s.gel = gel;
	s.ctm = ctm;
	s.flatness = flatness;

	s.linejoin = stroke->linejoin;
	s.linewidth = linewidth * 0.5f;
	s.miterlimit = stroke->miterlimit;
	s.sn = 0;
	s.dot = 0;

	s.dash_list = stroke->dash_list;
	s.dash_phase = stroke->dash_phase;
	s.dash_len = stroke->dash_len;
	s.toggle = 0;
	s.offset = 0;
	s.phase = 0;

	s.cap = stroke->start_cap;

	if (path->cmd_len > 0 && path->cmds[0] != FZ_MOVETO)
		return;

	phase_len = 0;
	for (i = 0; i < stroke->dash_len; i++)
		phase_len += stroke->dash_list[i];
	if (stroke->dash_len > 0 && phase_len == 0)
		return;
	fz_gel_scissor(gel, &s.rect);
	if (fz_try_invert_matrix(&inv, ctm))
		return;
	fz_transform_rect(&s.rect, &inv);
	s.rect.x0 -= linewidth;
	s.rect.x1 += linewidth;
	s.rect.y0 -= linewidth;
	s.rect.y1 += linewidth;

	max_expand = fz_matrix_max_expansion(ctm);
	if (phase_len < 1.0f && phase_len * max_expand < 0.5f)
	{
		fz_flatten_stroke_path(gel, path, stroke, ctm, flatness, linewidth);
		return;
	}
	s.dash_total = phase_len;

	/* cf. http://git.ghostscript.com/?p=mupdf.git;a=commitdiff;h=fd54bf89f2adfd5545202a6df87076fb7269f62c */
	s.dash_phase = fmodf(s.dash_phase, s.dash_total);

	p0.x = p0.y = 0;
	i = k = 0;

	while (i < path->cmd_len)
	{
		switch (path->cmds[i++])
		{
		case FZ_MOVETO:
			p1.x = path->coords[k++];
			p1.y = path->coords[k++];
			fz_dash_moveto(&s, p1, stroke->start_cap, stroke->end_cap);
			beg = p0 = p1;
			break;

		case FZ_LINETO:
			p1.x = path->coords[k++];
			p1.y = path->coords[k++];
			fz_dash_lineto(&s, p1, stroke->dash_cap, 0);
			p0 = p1;
			break;

		case FZ_CURVETO:
			p1.x = path->coords[k++];
			p1.y = path->coords[k++];
			p2.x = path->coords[k++];
			p2.y = path->coords[k++];
			p3.x = path->coords[k++];
			p3.y = path->coords[k++];
			fz_dash_bezier(&s, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, 0, stroke->dash_cap);
			p0 = p3;
			break;

		case FZ_CLOSE_PATH:
			fz_dash_lineto(&s, beg, stroke->dash_cap, 0);
			p0 = p1 = beg;
			break;
		}
	}

	fz_stroke_flush(&s, s.cap, stroke->end_cap);
}