Beispiel #1
0
static void
fz_dash_moveto(struct sctx *s, fz_point a, fz_linecap start_cap, fz_linecap end_cap)
{
	s->toggle = 1;
	s->offset = 0;
	s->phase = s->dash_phase;

	while (s->phase >= s->dash_list[s->offset])
	{
		s->toggle = !s->toggle;
		s->phase -= s->dash_list[s->offset];
		s->offset ++;
		if (s->offset == s->dash_len)
			s->offset = 0;
	}

	s->cur = a;

	if (s->toggle)
	{
		fz_stroke_flush(s, s->cap, end_cap);
		s->cap = start_cap;
		fz_stroke_moveto(s, a);
	}
}
Beispiel #2
0
static void
fz_dash_lineto(struct sctx *s, fz_point b, int dash_cap, int from_bezier)
{
	float dx, dy;
	float total, used, ratio;
	fz_point a;
	fz_point m;

	a = s->cur;
	dx = b.x - a.x;
	dy = b.y - a.y;
	total = sqrtf(dx * dx + dy * dy);
	used = 0;

	while (total - used > s->dash_list[s->offset] - s->phase)
	{
		used += s->dash_list[s->offset] - s->phase;
		ratio = used / total;
		m.x = a.x + ratio * dx;
		m.y = a.y + ratio * dy;

		if (s->toggle)
		{
			fz_stroke_lineto(s, m, from_bezier);
		}
		else
		{
			fz_stroke_flush(s, s->cap, dash_cap);
			s->cap = dash_cap;
			fz_stroke_moveto(s, m);
		}

		s->toggle = !s->toggle;
		s->phase = 0;
		s->offset ++;
		if (s->offset == s->dash_len)
			s->offset = 0;
	}

	s->phase += total - used;

	s->cur = b;

	if (s->toggle)
	{
		fz_stroke_lineto(s, b, from_bezier);
	}
}
Beispiel #3
0
void
fz_flatten_stroke_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;
	int i;

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

	s.linejoin = stroke->linejoin;
	s.linewidth = linewidth * 0.5f; /* hairlines use a different value from the path value */
	s.miterlimit = stroke->miterlimit;
	s.sn = 0;
	s.bn = 0;
	s.dot = 0;

	s.dash_list = NULL;
	s.dash_phase = 0;
	s.dash_len = 0;
	s.toggle = 0;
	s.offset = 0;
	s.phase = 0;

	s.cap = stroke->start_cap;

	i = 0;

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

	p0.x = p0.y = 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_stroke_flush(&s, stroke->start_cap, stroke->end_cap);
			fz_stroke_moveto(&s, p1);
			p0 = p1;
			break;

		case FZ_LINETO:
			p1.x = path->items[i++].v;
			p1.y = path->items[i++].v;
			fz_stroke_lineto(&s, p1, 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_stroke_bezier(&s, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, 0);
			p0 = p3;
			break;

		case FZ_CLOSE_PATH:
			fz_stroke_closepath(&s);
			break;
		}
	}

	fz_stroke_flush(&s, stroke->start_cap, stroke->end_cap);
}
Beispiel #4
0
static void
fz_dash_lineto(struct sctx *s, fz_point b, int dash_cap, int from_bezier)
{
	float dx, dy, d;
	float total, used, ratio, tail;
	fz_point a;
	fz_point m;
	fz_point old_b;
	int n;

	a = s->cur;
	dx = b.x - a.x;
	dy = b.y - a.y;
	used = 0;
	tail = 0;
	total = sqrtf(dx * dx + dy * dy);

	/* If a is off screen, bring it onto the screen. First
	 * horizontally... */
	if ((d = s->rect.x0 - a.x) > 0)
	{
		if (b.x < s->rect.x0)
		{
			/* Entirely off screen */
			tail = total;
			old_b = b;
			goto adjust_for_tail;
		}
		a.x = s->rect.x0;	/* d > 0, dx > 0 */
		goto a_moved_horizontally;
	}
	else if (d < 0 && (d = (s->rect.x1 - a.x)) < 0)
	{
		if (b.x > s->rect.x1)
		{
			/* Entirely off screen */
			tail = total;
			old_b = b;
			goto adjust_for_tail;
		}
		a.x = s->rect.x1;	/* d < 0, dx < 0 */
a_moved_horizontally:	/* d and dx have the same sign */
		a.y += dy * d/dx;
		used = total * d/dx;
		total -= used;
		dx = b.x - a.x;
		dy = b.y - a.y;
	}
	/* Then vertically... */
	if ((d = s->rect.y0 - a.y) > 0)
	{
		if (b.y < s->rect.y0)
		{
			/* Entirely off screen */
			tail = total;
			old_b = b;
			goto adjust_for_tail;
		}
		a.y = s->rect.y0;	/* d > 0, dy > 0 */
		goto a_moved_vertically;
	}
	else if (d < 0 && (d = (s->rect.y1 - a.y)) < 0)
	{
		if (b.y > s->rect.y1)
		{
			/* Entirely off screen */
			tail = total;
			old_b = b;
			goto adjust_for_tail;
		}
		a.y = s->rect.y1;	/* d < 0, dy < 0 */
a_moved_vertically:	/* d and dy have the same sign */
		a.x += dx * d/dy;
		d = total * d/dy;
		total -= d;
		used += d;
		dx = b.x - a.x;
		dy = b.y - a.y;
	}
	if (used != 0.0f)
	{
		/* Update the position in the dash array */
		if (s->toggle)
		{
			fz_stroke_lineto(s, a, from_bezier);
		}
		else
		{
			fz_stroke_flush(s, s->cap, dash_cap);
			s->cap = dash_cap;
			fz_stroke_moveto(s, a);
		}
		used += s->phase;
		n = used/s->dash_total;
		used -= n*s->dash_total;
		if (n & s->dash_len & 1)
			s->toggle = !s->toggle;
		while (used >= s->dash_list[s->offset])
		{
			used -= s->dash_list[s->offset];
			s->offset++;
			if (s->offset == s->dash_len)
				s->offset = 0;
			s->toggle = !s->toggle;
		}
		if (s->toggle)
		{
			fz_stroke_lineto(s, a, from_bezier);
		}
		else
		{
			fz_stroke_flush(s, s->cap, dash_cap);
			s->cap = dash_cap;
			fz_stroke_moveto(s, a);
		}
		s->phase = used;
		used = 0;
	}

	/* Now if b.x is off screen, bring it back */
	if ((d = b.x - s->rect.x0) < 0)
	{
		old_b = b;
		b.x = s->rect.x0;	/* d < 0, dx < 0 */
		goto b_moved_horizontally;
	}
	else if (d > 0 && (d = (b.x - s->rect.x1)) > 0)
	{
		old_b = b;
		b.x = s->rect.x1;	/* d > 0, dx > 0 */
b_moved_horizontally:	/* d and dx have the same sign */
		b.y -= dy * d/dx;
		tail = total * d/dx;
		total -= tail;
		dx = b.x - a.x;
		dy = b.y - a.y;
	}
	/* Then vertically... */
	if ((d = b.y - s->rect.y0) < 0)
	{
		old_b = b;
		b.y = s->rect.y0;	/* d < 0, dy < 0 */
		goto b_moved_vertically;
	}
	else if (d > 0 && (d = (b.y - s->rect.y1)) > 0)
	{
		float t;
		old_b = b;
		b.y = s->rect.y1;	/* d > 0, dy > 0 */
b_moved_vertically:	/* d and dy have the same sign */
		b.x -= dx * d/dy;
		t = total * d/dy;
		tail += t;
		total -= t;
		dx = b.x - a.x;
		dy = b.y - a.y;
	}

	while (total - used > s->dash_list[s->offset] - s->phase)
	{
		used += s->dash_list[s->offset] - s->phase;
		ratio = used / total;
		m.x = a.x + ratio * dx;
		m.y = a.y + ratio * dy;

		if (s->toggle)
		{
			fz_stroke_lineto(s, m, from_bezier);
		}
		else
		{
			fz_stroke_flush(s, s->cap, dash_cap);
			s->cap = dash_cap;
			fz_stroke_moveto(s, m);
		}

		s->toggle = !s->toggle;
		s->phase = 0;
		s->offset ++;
		if (s->offset == s->dash_len)
			s->offset = 0;
	}

	s->phase += total - used;

	if (tail == 0.0f)
	{
		s->cur = b;

		if (s->toggle)
		{
			fz_stroke_lineto(s, b, from_bezier);
		}
	}
	else
	{
adjust_for_tail:
		s->cur = old_b;
		/* Update the position in the dash array */
		if (s->toggle)
		{
			fz_stroke_lineto(s, old_b, from_bezier);
		}
		else
		{
			fz_stroke_flush(s, s->cap, dash_cap);
			s->cap = dash_cap;
			fz_stroke_moveto(s, old_b);
		}
		tail += s->phase;
		n = tail/s->dash_total;
		tail -= n*s->dash_total;
		if (n & s->dash_len & 1)
			s->toggle = !s->toggle;
		while (tail > s->dash_list[s->offset])
		{
			tail -= s->dash_list[s->offset];
			s->offset++;
			if (s->offset == s->dash_len)
				s->offset = 0;
			s->toggle = !s->toggle;
		}
		if (s->toggle)
		{
			fz_stroke_lineto(s, old_b, from_bezier);
		}
		else
		{
			fz_stroke_flush(s, s->cap, dash_cap);
			s->cap = dash_cap;
			fz_stroke_moveto(s, old_b);
		}
		s->phase = tail;
	}
}