1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2002 University of Southern California
5  * Copyright © 2013 Intel Corporation
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is University of Southern
33  * California.
34  *
35  * Contributor(s):
36  *	Carl D. Worth <cworth@cworth.org>
37  *	Chris Wilson <chris@chris-wilson.co.uk>
38  */
39 
40 #include "cairoint.h"
41 
42 #include "cairo-box-inline.h"
43 #include "cairo-path-fixed-private.h"
44 #include "cairo-slope-private.h"
45 #include "cairo-stroke-dash-private.h"
46 #include "cairo-traps-private.h"
47 
48 #include <float.h>
49 
50 struct stroker {
51     const cairo_stroke_style_t	*style;
52 
53     const cairo_matrix_t *ctm;
54     const cairo_matrix_t *ctm_inverse;
55     double spline_cusp_tolerance;
56     double half_line_width;
57     double tolerance;
58     double ctm_determinant;
59     cairo_bool_t ctm_det_positive;
60     cairo_line_join_t line_join;
61 
62     cairo_traps_t *traps;
63 
64     cairo_pen_t pen;
65 
66     cairo_point_t first_point;
67 
68     cairo_bool_t has_initial_sub_path;
69 
70     cairo_bool_t has_current_face;
71     cairo_stroke_face_t current_face;
72 
73     cairo_bool_t has_first_face;
74     cairo_stroke_face_t first_face;
75 
76     cairo_stroker_dash_t dash;
77 
78     cairo_bool_t has_bounds;
79     cairo_box_t tight_bounds;
80     cairo_box_t line_bounds;
81     cairo_box_t join_bounds;
82 };
83 
84 static cairo_status_t
stroker_init(struct stroker * stroker,const cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse,double tolerance,cairo_traps_t * traps)85 stroker_init (struct stroker		*stroker,
86 	      const cairo_path_fixed_t	*path,
87 	      const cairo_stroke_style_t	*style,
88 	      const cairo_matrix_t	*ctm,
89 	      const cairo_matrix_t	*ctm_inverse,
90 	      double			 tolerance,
91 	      cairo_traps_t		*traps)
92 {
93     cairo_status_t status;
94 
95     stroker->style = style;
96     stroker->ctm = ctm;
97     stroker->ctm_inverse = NULL;
98     if (! _cairo_matrix_is_identity (ctm_inverse))
99 	stroker->ctm_inverse = ctm_inverse;
100     stroker->line_join = style->line_join;
101     stroker->half_line_width = style->line_width / 2.0;
102     stroker->tolerance = tolerance;
103     stroker->traps = traps;
104 
105     /* To test whether we need to join two segments of a spline using
106      * a round-join or a bevel-join, we can inspect the angle between the
107      * two segments. If the difference between the chord distance
108      * (half-line-width times the cosine of the bisection angle) and the
109      * half-line-width itself is greater than tolerance then we need to
110      * inject a point.
111      */
112     stroker->spline_cusp_tolerance = 1 - tolerance / stroker->half_line_width;
113     stroker->spline_cusp_tolerance *= stroker->spline_cusp_tolerance;
114     stroker->spline_cusp_tolerance *= 2;
115     stroker->spline_cusp_tolerance -= 1;
116 
117     stroker->ctm_determinant = _cairo_matrix_compute_determinant (stroker->ctm);
118     stroker->ctm_det_positive = stroker->ctm_determinant >= 0.0;
119 
120     status = _cairo_pen_init (&stroker->pen,
121 		              stroker->half_line_width,
122 			      tolerance, ctm);
123     if (unlikely (status))
124 	return status;
125 
126     stroker->has_current_face = FALSE;
127     stroker->has_first_face = FALSE;
128     stroker->has_initial_sub_path = FALSE;
129 
130     _cairo_stroker_dash_init (&stroker->dash, style);
131 
132     stroker->has_bounds = traps->num_limits;
133     if (stroker->has_bounds) {
134 	/* Extend the bounds in each direction to account for the maximum area
135 	 * we might generate trapezoids, to capture line segments that are outside
136 	 * of the bounds but which might generate rendering that's within bounds.
137 	 */
138 	double dx, dy;
139 	cairo_fixed_t fdx, fdy;
140 
141 	stroker->tight_bounds = traps->bounds;
142 
143 	_cairo_stroke_style_max_distance_from_path (stroker->style, path,
144 						    stroker->ctm, &dx, &dy);
145 
146 	_cairo_stroke_style_max_line_distance_from_path (stroker->style, path,
147 							 stroker->ctm, &dx, &dy);
148 
149 	fdx = _cairo_fixed_from_double (dx);
150 	fdy = _cairo_fixed_from_double (dy);
151 
152 	stroker->line_bounds = stroker->tight_bounds;
153 	stroker->line_bounds.p1.x -= fdx;
154 	stroker->line_bounds.p2.x += fdx;
155 	stroker->line_bounds.p1.y -= fdy;
156 	stroker->line_bounds.p2.y += fdy;
157 
158 	_cairo_stroke_style_max_join_distance_from_path (stroker->style, path,
159 							 stroker->ctm, &dx, &dy);
160 
161 	fdx = _cairo_fixed_from_double (dx);
162 	fdy = _cairo_fixed_from_double (dy);
163 
164 	stroker->join_bounds = stroker->tight_bounds;
165 	stroker->join_bounds.p1.x -= fdx;
166 	stroker->join_bounds.p2.x += fdx;
167 	stroker->join_bounds.p1.y -= fdy;
168 	stroker->join_bounds.p2.y += fdy;
169     }
170 
171     return CAIRO_STATUS_SUCCESS;
172 }
173 
174 static void
stroker_fini(struct stroker * stroker)175 stroker_fini (struct stroker *stroker)
176 {
177     _cairo_pen_fini (&stroker->pen);
178 }
179 
180 static void
translate_point(cairo_point_t * point,cairo_point_t * offset)181 translate_point (cairo_point_t *point, cairo_point_t *offset)
182 {
183     point->x += offset->x;
184     point->y += offset->y;
185 }
186 
187 static int
join_is_clockwise(const cairo_stroke_face_t * in,const cairo_stroke_face_t * out)188 join_is_clockwise (const cairo_stroke_face_t *in,
189 		   const cairo_stroke_face_t *out)
190 {
191     return _cairo_slope_compare (&in->dev_vector, &out->dev_vector) < 0;
192 }
193 
194 static int
slope_compare_sgn(double dx1,double dy1,double dx2,double dy2)195 slope_compare_sgn (double dx1, double dy1, double dx2, double dy2)
196 {
197     double c = dx1 * dy2 - dx2 * dy1;
198     if (c > 0) return 1;
199     if (c < 0) return -1;
200     return 0;
201 }
202 
203 static cairo_bool_t
stroker_intersects_join(const struct stroker * stroker,const cairo_point_t * in,const cairo_point_t * out)204 stroker_intersects_join (const struct stroker *stroker,
205 			 const cairo_point_t *in,
206 			 const cairo_point_t *out)
207 {
208     cairo_line_t segment;
209 
210     if (! stroker->has_bounds)
211 	return TRUE;
212 
213     segment.p1 = *in;
214     segment.p2 = *out;
215     return _cairo_box_intersects_line_segment (&stroker->join_bounds, &segment);
216 }
217 
218 static void
join(struct stroker * stroker,cairo_stroke_face_t * in,cairo_stroke_face_t * out)219 join (struct stroker *stroker,
220       cairo_stroke_face_t *in,
221       cairo_stroke_face_t *out)
222 {
223     int clockwise = join_is_clockwise (out, in);
224     cairo_point_t *inpt, *outpt;
225 
226     if (in->cw.x == out->cw.x &&
227 	in->cw.y == out->cw.y &&
228 	in->ccw.x == out->ccw.x &&
229 	in->ccw.y == out->ccw.y)
230     {
231 	return;
232     }
233 
234     if (clockwise) {
235 	inpt = &in->ccw;
236 	outpt = &out->ccw;
237     } else {
238 	inpt = &in->cw;
239 	outpt = &out->cw;
240     }
241 
242     if (! stroker_intersects_join (stroker, inpt, outpt))
243 	    return;
244 
245     switch (stroker->line_join) {
246     case CAIRO_LINE_JOIN_ROUND:
247 	/* construct a fan around the common midpoint */
248 	if ((in->dev_slope.x * out->dev_slope.x +
249 	     in->dev_slope.y * out->dev_slope.y) < stroker->spline_cusp_tolerance)
250 	{
251 	    int start, stop;
252 	    cairo_point_t tri[3], edges[4];
253 	    cairo_pen_t *pen = &stroker->pen;
254 
255 	    edges[0] = in->cw;
256 	    edges[1] = in->ccw;
257 	    tri[0] = in->point;
258 	    tri[1] = *inpt;
259 	    if (clockwise) {
260 		_cairo_pen_find_active_ccw_vertices (pen,
261 						     &in->dev_vector, &out->dev_vector,
262 						     &start, &stop);
263 		while (start != stop) {
264 		    tri[2] = in->point;
265 		    translate_point (&tri[2], &pen->vertices[start].point);
266 		    edges[2] = in->point;
267 		    edges[3] = tri[2];
268 		    _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
269 								 tri, edges);
270 		    tri[1] = tri[2];
271 		    edges[0] = edges[2];
272 		    edges[1] = edges[3];
273 
274 		    if (start-- == 0)
275 			start += pen->num_vertices;
276 		}
277 	    } else {
278 		_cairo_pen_find_active_cw_vertices (pen,
279 						    &in->dev_vector, &out->dev_vector,
280 						    &start, &stop);
281 		while (start != stop) {
282 		    tri[2] = in->point;
283 		    translate_point (&tri[2], &pen->vertices[start].point);
284 		    edges[2] = in->point;
285 		    edges[3] = tri[2];
286 		    _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
287 								 tri, edges);
288 		    tri[1] = tri[2];
289 		    edges[0] = edges[2];
290 		    edges[1] = edges[3];
291 
292 		    if (++start == pen->num_vertices)
293 			start = 0;
294 		}
295 	    }
296 	    tri[2] = *outpt;
297 	    edges[2] = out->cw;
298 	    edges[3] = out->ccw;
299 	    _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
300 							 tri, edges);
301 	} else {
302 	    cairo_point_t t[] = { { in->point.x, in->point.y}, { inpt->x, inpt->y }, { outpt->x, outpt->y } };
303 	    cairo_point_t e[] = { { in->cw.x, in->cw.y}, { in->ccw.x, in->ccw.y },
304 				  { out->cw.x, out->cw.y}, { out->ccw.x, out->ccw.y } };
305 	    _cairo_traps_tessellate_triangle_with_edges (stroker->traps, t, e);
306 	}
307 	break;
308 
309     case CAIRO_LINE_JOIN_MITER:
310     default: {
311 	/* dot product of incoming slope vector with outgoing slope vector */
312 	double in_dot_out = (-in->usr_vector.x * out->usr_vector.x +
313 			     -in->usr_vector.y * out->usr_vector.y);
314 	double ml = stroker->style->miter_limit;
315 
316 	/* Check the miter limit -- lines meeting at an acute angle
317 	 * can generate long miters, the limit converts them to bevel
318 	 *
319 	 * Consider the miter join formed when two line segments
320 	 * meet at an angle psi:
321 	 *
322 	 *	   /.\
323 	 *	  /. .\
324 	 *	 /./ \.\
325 	 *	/./psi\.\
326 	 *
327 	 * We can zoom in on the right half of that to see:
328 	 *
329 	 *	    |\
330 	 *	    | \ psi/2
331 	 *	    |  \
332 	 *	    |   \
333 	 *	    |    \
334 	 *	    |     \
335 	 *	  miter    \
336 	 *	 length     \
337 	 *	    |        \
338 	 *	    |        .\
339 	 *	    |    .     \
340 	 *	    |.   line   \
341 	 *	     \    width  \
342 	 *	      \           \
343 	 *
344 	 *
345 	 * The right triangle in that figure, (the line-width side is
346 	 * shown faintly with three '.' characters), gives us the
347 	 * following expression relating miter length, angle and line
348 	 * width:
349 	 *
350 	 *	1 /sin (psi/2) = miter_length / line_width
351 	 *
352 	 * The right-hand side of this relationship is the same ratio
353 	 * in which the miter limit (ml) is expressed. We want to know
354 	 * when the miter length is within the miter limit. That is
355 	 * when the following condition holds:
356 	 *
357 	 *	1/sin(psi/2) <= ml
358 	 *	1 <= ml sin(psi/2)
359 	 *	1 <= ml² sin²(psi/2)
360 	 *	2 <= ml² 2 sin²(psi/2)
361 	 *				2·sin²(psi/2) = 1-cos(psi)
362 	 *	2 <= ml² (1-cos(psi))
363 	 *
364 	 *				in · out = |in| |out| cos (psi)
365 	 *
366 	 * in and out are both unit vectors, so:
367 	 *
368 	 *				in · out = cos (psi)
369 	 *
370 	 *	2 <= ml² (1 - in · out)
371 	 *
372 	 */
373 	if (2 <= ml * ml * (1 - in_dot_out)) {
374 	    double		x1, y1, x2, y2;
375 	    double		mx, my;
376 	    double		dx1, dx2, dy1, dy2;
377 	    cairo_point_t	outer;
378 	    cairo_point_t	quad[4];
379 	    double		ix, iy;
380 	    double		fdx1, fdy1, fdx2, fdy2;
381 	    double		mdx, mdy;
382 
383 	    /*
384 	     * we've got the points already transformed to device
385 	     * space, but need to do some computation with them and
386 	     * also need to transform the slope from user space to
387 	     * device space
388 	     */
389 	    /* outer point of incoming line face */
390 	    x1 = _cairo_fixed_to_double (inpt->x);
391 	    y1 = _cairo_fixed_to_double (inpt->y);
392 	    dx1 = in->usr_vector.x;
393 	    dy1 = in->usr_vector.y;
394 	    cairo_matrix_transform_distance (stroker->ctm, &dx1, &dy1);
395 
396 	    /* outer point of outgoing line face */
397 	    x2 = _cairo_fixed_to_double (outpt->x);
398 	    y2 = _cairo_fixed_to_double (outpt->y);
399 	    dx2 = out->usr_vector.x;
400 	    dy2 = out->usr_vector.y;
401 	    cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
402 
403 	    /*
404 	     * Compute the location of the outer corner of the miter.
405 	     * That's pretty easy -- just the intersection of the two
406 	     * outer edges.  We've got slopes and points on each
407 	     * of those edges.  Compute my directly, then compute
408 	     * mx by using the edge with the larger dy; that avoids
409 	     * dividing by values close to zero.
410 	     */
411 	    my = (((x2 - x1) * dy1 * dy2 - y2 * dx2 * dy1 + y1 * dx1 * dy2) /
412 		  (dx1 * dy2 - dx2 * dy1));
413 	    if (fabs (dy1) >= fabs (dy2))
414 		mx = (my - y1) * dx1 / dy1 + x1;
415 	    else
416 		mx = (my - y2) * dx2 / dy2 + x2;
417 
418 	    /*
419 	     * When the two outer edges are nearly parallel, slight
420 	     * perturbations in the position of the outer points of the lines
421 	     * caused by representing them in fixed point form can cause the
422 	     * intersection point of the miter to move a large amount. If
423 	     * that moves the miter intersection from between the two faces,
424 	     * then draw a bevel instead.
425 	     */
426 
427 	    ix = _cairo_fixed_to_double (in->point.x);
428 	    iy = _cairo_fixed_to_double (in->point.y);
429 
430 	    /* slope of one face */
431 	    fdx1 = x1 - ix; fdy1 = y1 - iy;
432 
433 	    /* slope of the other face */
434 	    fdx2 = x2 - ix; fdy2 = y2 - iy;
435 
436 	    /* slope from the intersection to the miter point */
437 	    mdx = mx - ix; mdy = my - iy;
438 
439 	    /*
440 	     * Make sure the miter point line lies between the two
441 	     * faces by comparing the slopes
442 	     */
443 	    if (slope_compare_sgn (fdx1, fdy1, mdx, mdy) !=
444 		slope_compare_sgn (fdx2, fdy2, mdx, mdy))
445 	    {
446 		/*
447 		 * Draw the quadrilateral
448 		 */
449 		outer.x = _cairo_fixed_from_double (mx);
450 		outer.y = _cairo_fixed_from_double (my);
451 
452 		quad[0] = in->point;
453 		quad[1] = *inpt;
454 		quad[2] = outer;
455 		quad[3] = *outpt;
456 
457 		_cairo_traps_tessellate_convex_quad (stroker->traps, quad);
458 		break;
459 	    }
460 	}
461     }
462     /* fall through ... */
463     case CAIRO_LINE_JOIN_BEVEL: {
464 	cairo_point_t t[] = { { in->point.x, in->point.y }, { inpt->x, inpt->y }, { outpt->x, outpt->y } };
465 	cairo_point_t e[] = { { in->cw.x, in->cw.y }, { in->ccw.x, in->ccw.y },
466 			      { out->cw.x, out->cw.y }, { out->ccw.x, out->ccw.y } };
467 	_cairo_traps_tessellate_triangle_with_edges (stroker->traps, t, e);
468 	break;
469     }
470     }
471 }
472 
473 static void
add_cap(struct stroker * stroker,cairo_stroke_face_t * f)474 add_cap (struct stroker *stroker, cairo_stroke_face_t *f)
475 {
476     switch (stroker->style->line_cap) {
477     case CAIRO_LINE_CAP_ROUND: {
478 	int start, stop;
479 	cairo_slope_t in_slope, out_slope;
480 	cairo_point_t tri[3], edges[4];
481 	cairo_pen_t *pen = &stroker->pen;
482 
483 	in_slope = f->dev_vector;
484 	out_slope.dx = -in_slope.dx;
485 	out_slope.dy = -in_slope.dy;
486 	_cairo_pen_find_active_cw_vertices (pen, &in_slope, &out_slope,
487 					    &start, &stop);
488 	edges[0] = f->cw;
489 	edges[1] = f->ccw;
490 	tri[0] = f->point;
491 	tri[1] = f->cw;
492 	while (start != stop) {
493 	    tri[2] = f->point;
494 	    translate_point (&tri[2], &pen->vertices[start].point);
495 	    edges[2] = f->point;
496 	    edges[3] = tri[2];
497 	    _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
498 							 tri, edges);
499 
500 	    tri[1] = tri[2];
501 	    edges[0] = edges[2];
502 	    edges[1] = edges[3];
503 	    if (++start == pen->num_vertices)
504 		start = 0;
505 	}
506 	tri[2] = f->ccw;
507 	edges[2] = f->cw;
508 	edges[3] = f->ccw;
509 	_cairo_traps_tessellate_triangle_with_edges (stroker->traps,
510 						     tri, edges);
511 	break;
512     }
513 
514     case CAIRO_LINE_CAP_SQUARE: {
515 	double dx, dy;
516 	cairo_slope_t fvector;
517 	cairo_point_t quad[4];
518 
519 	dx = f->usr_vector.x;
520 	dy = f->usr_vector.y;
521 	dx *= stroker->half_line_width;
522 	dy *= stroker->half_line_width;
523 	cairo_matrix_transform_distance (stroker->ctm, &dx, &dy);
524 	fvector.dx = _cairo_fixed_from_double (dx);
525 	fvector.dy = _cairo_fixed_from_double (dy);
526 
527 	quad[0] = f->cw;
528 	quad[1].x = f->cw.x + fvector.dx;
529 	quad[1].y = f->cw.y + fvector.dy;
530 	quad[2].x = f->ccw.x + fvector.dx;
531 	quad[2].y = f->ccw.y + fvector.dy;
532 	quad[3] = f->ccw;
533 
534 	_cairo_traps_tessellate_convex_quad (stroker->traps, quad);
535 	break;
536     }
537 
538     case CAIRO_LINE_CAP_BUTT:
539     default:
540 	break;
541     }
542 }
543 
544 static void
add_leading_cap(struct stroker * stroker,cairo_stroke_face_t * face)545 add_leading_cap (struct stroker     *stroker,
546 		 cairo_stroke_face_t *face)
547 {
548     cairo_stroke_face_t reversed;
549     cairo_point_t t;
550 
551     reversed = *face;
552 
553     /* The initial cap needs an outward facing vector. Reverse everything */
554     reversed.usr_vector.x = -reversed.usr_vector.x;
555     reversed.usr_vector.y = -reversed.usr_vector.y;
556     reversed.dev_vector.dx = -reversed.dev_vector.dx;
557     reversed.dev_vector.dy = -reversed.dev_vector.dy;
558     t = reversed.cw;
559     reversed.cw = reversed.ccw;
560     reversed.ccw = t;
561 
562     add_cap (stroker, &reversed);
563 }
564 
565 static void
add_trailing_cap(struct stroker * stroker,cairo_stroke_face_t * face)566 add_trailing_cap (struct stroker *stroker, cairo_stroke_face_t *face)
567 {
568     add_cap (stroker, face);
569 }
570 
571 static inline double
normalize_slope(double * dx,double * dy)572 normalize_slope (double *dx, double *dy)
573 {
574     double dx0 = *dx, dy0 = *dy;
575 
576     if (dx0 == 0.0 && dy0 == 0.0)
577 	return 0;
578 
579     if (dx0 == 0.0) {
580 	*dx = 0.0;
581 	if (dy0 > 0.0) {
582 	    *dy = 1.0;
583 	    return dy0;
584 	} else {
585 	    *dy = -1.0;
586 	    return -dy0;
587 	}
588     } else if (dy0 == 0.0) {
589 	*dy = 0.0;
590 	if (dx0 > 0.0) {
591 	    *dx = 1.0;
592 	    return dx0;
593 	} else {
594 	    *dx = -1.0;
595 	    return -dx0;
596 	}
597     } else {
598 	double mag = hypot (dx0, dy0);
599 	*dx = dx0 / mag;
600 	*dy = dy0 / mag;
601 	return mag;
602     }
603 }
604 
605 static void
compute_face(const cairo_point_t * point,const cairo_slope_t * dev_slope,struct stroker * stroker,cairo_stroke_face_t * face)606 compute_face (const cairo_point_t *point,
607 	      const cairo_slope_t *dev_slope,
608 	      struct stroker *stroker,
609 	      cairo_stroke_face_t *face)
610 {
611     double face_dx, face_dy;
612     cairo_point_t offset_ccw, offset_cw;
613     double slope_dx, slope_dy;
614 
615     slope_dx = _cairo_fixed_to_double (dev_slope->dx);
616     slope_dy = _cairo_fixed_to_double (dev_slope->dy);
617     face->length = normalize_slope (&slope_dx, &slope_dy);
618     face->dev_slope.x = slope_dx;
619     face->dev_slope.y = slope_dy;
620 
621     /*
622      * rotate to get a line_width/2 vector along the face, note that
623      * the vector must be rotated the right direction in device space,
624      * but by 90° in user space. So, the rotation depends on
625      * whether the ctm reflects or not, and that can be determined
626      * by looking at the determinant of the matrix.
627      */
628     if (stroker->ctm_inverse) {
629 	cairo_matrix_transform_distance (stroker->ctm_inverse, &slope_dx, &slope_dy);
630 	normalize_slope (&slope_dx, &slope_dy);
631 
632 	if (stroker->ctm_det_positive) {
633 	    face_dx = - slope_dy * stroker->half_line_width;
634 	    face_dy = slope_dx * stroker->half_line_width;
635 	} else {
636 	    face_dx = slope_dy * stroker->half_line_width;
637 	    face_dy = - slope_dx * stroker->half_line_width;
638 	}
639 
640 	/* back to device space */
641 	cairo_matrix_transform_distance (stroker->ctm, &face_dx, &face_dy);
642     } else {
643 	face_dx = - slope_dy * stroker->half_line_width;
644 	face_dy = slope_dx * stroker->half_line_width;
645     }
646 
647     offset_ccw.x = _cairo_fixed_from_double (face_dx);
648     offset_ccw.y = _cairo_fixed_from_double (face_dy);
649     offset_cw.x = -offset_ccw.x;
650     offset_cw.y = -offset_ccw.y;
651 
652     face->ccw = *point;
653     translate_point (&face->ccw, &offset_ccw);
654 
655     face->point = *point;
656 
657     face->cw = *point;
658     translate_point (&face->cw, &offset_cw);
659 
660     face->usr_vector.x = slope_dx;
661     face->usr_vector.y = slope_dy;
662 
663     face->dev_vector = *dev_slope;
664 }
665 
666 static void
add_caps(struct stroker * stroker)667 add_caps (struct stroker *stroker)
668 {
669     /* check for a degenerative sub_path */
670     if (stroker->has_initial_sub_path &&
671 	!stroker->has_first_face &&
672 	!stroker->has_current_face &&
673 	stroker->style->line_cap == CAIRO_LINE_CAP_ROUND)
674     {
675 	/* pick an arbitrary slope to use */
676 	cairo_slope_t slope = { CAIRO_FIXED_ONE, 0 };
677 	cairo_stroke_face_t face;
678 
679 	/* arbitrarily choose first_point
680 	 * first_point and current_point should be the same */
681 	compute_face (&stroker->first_point, &slope, stroker, &face);
682 
683 	add_leading_cap (stroker, &face);
684 	add_trailing_cap (stroker, &face);
685     }
686 
687     if (stroker->has_first_face)
688 	add_leading_cap (stroker, &stroker->first_face);
689 
690     if (stroker->has_current_face)
691 	add_trailing_cap (stroker, &stroker->current_face);
692 }
693 
694 static cairo_bool_t
stroker_intersects_edge(const struct stroker * stroker,const cairo_stroke_face_t * start,const cairo_stroke_face_t * end)695 stroker_intersects_edge (const struct stroker *stroker,
696 			 const cairo_stroke_face_t *start,
697 			 const cairo_stroke_face_t *end)
698 {
699     cairo_box_t box;
700 
701     if (! stroker->has_bounds)
702 	return TRUE;
703 
704     if (_cairo_box_contains_point (&stroker->tight_bounds, &start->cw))
705 	return TRUE;
706     box.p2 = box.p1 = start->cw;
707 
708     if (_cairo_box_contains_point (&stroker->tight_bounds, &start->ccw))
709 	return TRUE;
710     _cairo_box_add_point (&box, &start->ccw);
711 
712     if (_cairo_box_contains_point (&stroker->tight_bounds, &end->cw))
713 	return TRUE;
714     _cairo_box_add_point (&box, &end->cw);
715 
716     if (_cairo_box_contains_point (&stroker->tight_bounds, &end->ccw))
717 	return TRUE;
718     _cairo_box_add_point (&box, &end->ccw);
719 
720     return (box.p2.x > stroker->tight_bounds.p1.x &&
721 	    box.p1.x < stroker->tight_bounds.p2.x &&
722 	    box.p2.y > stroker->tight_bounds.p1.y &&
723 	    box.p1.y < stroker->tight_bounds.p2.y);
724 }
725 
726 static void
add_sub_edge(struct stroker * stroker,const cairo_point_t * p1,const cairo_point_t * p2,const cairo_slope_t * dev_slope,cairo_stroke_face_t * start,cairo_stroke_face_t * end)727 add_sub_edge (struct stroker *stroker,
728 	      const cairo_point_t *p1, const cairo_point_t *p2,
729 	      const cairo_slope_t *dev_slope,
730 	      cairo_stroke_face_t *start, cairo_stroke_face_t *end)
731 {
732     cairo_point_t rectangle[4];
733 
734     compute_face (p1, dev_slope, stroker, start);
735 
736     *end = *start;
737     end->point = *p2;
738     rectangle[0].x = p2->x - p1->x;
739     rectangle[0].y = p2->y - p1->y;
740     translate_point (&end->ccw, &rectangle[0]);
741     translate_point (&end->cw, &rectangle[0]);
742 
743     if (p1->x == p2->x && p1->y == p2->y)
744 	return;
745 
746     if (! stroker_intersects_edge (stroker, start, end))
747 	return;
748 
749     rectangle[0] = start->cw;
750     rectangle[1] = start->ccw;
751     rectangle[2] = end->ccw;
752     rectangle[3] = end->cw;
753 
754     _cairo_traps_tessellate_convex_quad (stroker->traps, rectangle);
755 }
756 
757 static cairo_status_t
move_to(void * closure,const cairo_point_t * point)758 move_to (void *closure, const cairo_point_t *point)
759 {
760     struct stroker *stroker = closure;
761 
762     /* Cap the start and end of the previous sub path as needed */
763     add_caps (stroker);
764 
765     stroker->first_point = *point;
766     stroker->current_face.point = *point;
767 
768     stroker->has_first_face = FALSE;
769     stroker->has_current_face = FALSE;
770     stroker->has_initial_sub_path = FALSE;
771 
772     return CAIRO_STATUS_SUCCESS;
773 }
774 
775 static cairo_status_t
move_to_dashed(void * closure,const cairo_point_t * point)776 move_to_dashed (void *closure, const cairo_point_t *point)
777 {
778     /* reset the dash pattern for new sub paths */
779     struct stroker *stroker = closure;
780 
781     _cairo_stroker_dash_start (&stroker->dash);
782     return move_to (closure, point);
783 }
784 
785 static cairo_status_t
line_to(void * closure,const cairo_point_t * point)786 line_to (void *closure, const cairo_point_t *point)
787 {
788     struct stroker *stroker = closure;
789     cairo_stroke_face_t start, end;
790     const cairo_point_t *p1 = &stroker->current_face.point;
791     const cairo_point_t *p2 = point;
792     cairo_slope_t dev_slope;
793 
794     stroker->has_initial_sub_path = TRUE;
795 
796     if (p1->x == p2->x && p1->y == p2->y)
797 	return CAIRO_STATUS_SUCCESS;
798 
799     _cairo_slope_init (&dev_slope, p1, p2);
800     add_sub_edge (stroker, p1, p2, &dev_slope, &start, &end);
801 
802     if (stroker->has_current_face) {
803 	/* Join with final face from previous segment */
804 	join (stroker, &stroker->current_face, &start);
805     } else if (!stroker->has_first_face) {
806 	/* Save sub path's first face in case needed for closing join */
807 	stroker->first_face = start;
808 	stroker->has_first_face = TRUE;
809     }
810     stroker->current_face = end;
811     stroker->has_current_face = TRUE;
812 
813     return CAIRO_STATUS_SUCCESS;
814 }
815 
816 /*
817  * Dashed lines.  Cap each dash end, join around turns when on
818  */
819 static cairo_status_t
line_to_dashed(void * closure,const cairo_point_t * point)820 line_to_dashed (void *closure, const cairo_point_t *point)
821 {
822     struct stroker *stroker = closure;
823     double mag, remain, step_length = 0;
824     double slope_dx, slope_dy;
825     double dx2, dy2;
826     cairo_stroke_face_t sub_start, sub_end;
827     const cairo_point_t *p1 = &stroker->current_face.point;
828     const cairo_point_t *p2 = point;
829     cairo_slope_t dev_slope;
830     cairo_line_t segment;
831     cairo_bool_t fully_in_bounds;
832 
833     stroker->has_initial_sub_path = stroker->dash.dash_starts_on;
834 
835     if (p1->x == p2->x && p1->y == p2->y)
836 	return CAIRO_STATUS_SUCCESS;
837 
838     fully_in_bounds = TRUE;
839     if (stroker->has_bounds &&
840 	(! _cairo_box_contains_point (&stroker->join_bounds, p1) ||
841 	 ! _cairo_box_contains_point (&stroker->join_bounds, p2)))
842     {
843 	fully_in_bounds = FALSE;
844     }
845 
846     _cairo_slope_init (&dev_slope, p1, p2);
847 
848     slope_dx = _cairo_fixed_to_double (p2->x - p1->x);
849     slope_dy = _cairo_fixed_to_double (p2->y - p1->y);
850 
851     if (stroker->ctm_inverse)
852 	cairo_matrix_transform_distance (stroker->ctm_inverse, &slope_dx, &slope_dy);
853     mag = normalize_slope (&slope_dx, &slope_dy);
854     if (mag <= DBL_EPSILON)
855 	return CAIRO_STATUS_SUCCESS;
856 
857     remain = mag;
858     segment.p1 = *p1;
859     while (remain) {
860 	step_length = MIN (stroker->dash.dash_remain, remain);
861 	remain -= step_length;
862 	dx2 = slope_dx * (mag - remain);
863 	dy2 = slope_dy * (mag - remain);
864 	cairo_matrix_transform_distance (stroker->ctm, &dx2, &dy2);
865 	segment.p2.x = _cairo_fixed_from_double (dx2) + p1->x;
866 	segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
867 
868 	if (stroker->dash.dash_on &&
869 	    (fully_in_bounds ||
870 	     (! stroker->has_first_face && stroker->dash.dash_starts_on) ||
871 	     _cairo_box_intersects_line_segment (&stroker->join_bounds, &segment)))
872 	{
873 	    add_sub_edge (stroker,
874 			  &segment.p1, &segment.p2,
875 			  &dev_slope,
876 			  &sub_start, &sub_end);
877 
878 	    if (stroker->has_current_face) {
879 		/* Join with final face from previous segment */
880 		join (stroker, &stroker->current_face, &sub_start);
881 
882 		stroker->has_current_face = FALSE;
883 	    } else if (! stroker->has_first_face && stroker->dash.dash_starts_on) {
884 		/* Save sub path's first face in case needed for closing join */
885 		stroker->first_face = sub_start;
886 		stroker->has_first_face = TRUE;
887 	    } else {
888 		/* Cap dash start if not connecting to a previous segment */
889 		add_leading_cap (stroker, &sub_start);
890 	    }
891 
892 	    if (remain) {
893 		/* Cap dash end if not at end of segment */
894 		add_trailing_cap (stroker, &sub_end);
895 	    } else {
896 		stroker->current_face = sub_end;
897 		stroker->has_current_face = TRUE;
898 	    }
899 	} else {
900 	    if (stroker->has_current_face) {
901 		/* Cap final face from previous segment */
902 		add_trailing_cap (stroker, &stroker->current_face);
903 
904 		stroker->has_current_face = FALSE;
905 	    }
906 	}
907 
908 	_cairo_stroker_dash_step (&stroker->dash, step_length);
909 	segment.p1 = segment.p2;
910     }
911 
912     if (stroker->dash.dash_on && ! stroker->has_current_face) {
913 	/* This segment ends on a transition to dash_on, compute a new face
914 	 * and add cap for the beginning of the next dash_on step.
915 	 *
916 	 * Note: this will create a degenerate cap if this is not the last line
917 	 * in the path. Whether this behaviour is desirable or not is debatable.
918 	 * On one side these degenerate caps can not be reproduced with regular
919 	 * path stroking.
920 	 * On the other hand, Acroread 7 also produces the degenerate caps.
921 	 */
922 	compute_face (point, &dev_slope, stroker, &stroker->current_face);
923 
924 	add_leading_cap (stroker, &stroker->current_face);
925 
926 	stroker->has_current_face = TRUE;
927     } else
928 	stroker->current_face.point = *point;
929 
930     return CAIRO_STATUS_SUCCESS;
931 }
932 
933 static cairo_status_t
spline_to(void * closure,const cairo_point_t * point,const cairo_slope_t * tangent)934 spline_to (void *closure,
935 	   const cairo_point_t *point,
936 	   const cairo_slope_t *tangent)
937 {
938     struct stroker *stroker = closure;
939     cairo_stroke_face_t face;
940 
941     if ((tangent->dx | tangent->dy) == 0) {
942 	cairo_point_t t;
943 
944 	face = stroker->current_face;
945 
946 	face.usr_vector.x = -face.usr_vector.x;
947 	face.usr_vector.y = -face.usr_vector.y;
948 	face.dev_slope.x = -face.dev_slope.x;
949 	face.dev_slope.y = -face.dev_slope.y;
950 	face.dev_vector.dx = -face.dev_vector.dx;
951 	face.dev_vector.dy = -face.dev_vector.dy;
952 
953 	t = face.cw;
954 	face.cw = face.ccw;
955 	face.ccw = t;
956 
957 	join (stroker, &stroker->current_face, &face);
958     } else {
959 	cairo_point_t rectangle[4];
960 
961 	compute_face (&stroker->current_face.point, tangent, stroker, &face);
962 	join (stroker, &stroker->current_face, &face);
963 
964 	rectangle[0] = face.cw;
965 	rectangle[1] = face.ccw;
966 
967 	rectangle[2].x = point->x - face.point.x;
968 	rectangle[2].y = point->y - face.point.y;
969 	face.point = *point;
970 	translate_point (&face.ccw, &rectangle[2]);
971 	translate_point (&face.cw, &rectangle[2]);
972 
973 	rectangle[2] = face.ccw;
974 	rectangle[3] = face.cw;
975 
976 	_cairo_traps_tessellate_convex_quad (stroker->traps, rectangle);
977     }
978 
979     stroker->current_face = face;
980 
981     return CAIRO_STATUS_SUCCESS;
982 }
983 
984 static cairo_status_t
curve_to(void * closure,const cairo_point_t * b,const cairo_point_t * c,const cairo_point_t * d)985 curve_to (void *closure,
986 	  const cairo_point_t *b,
987 	  const cairo_point_t *c,
988 	  const cairo_point_t *d)
989 {
990     struct stroker *stroker = closure;
991     cairo_line_join_t line_join_save;
992     cairo_spline_t spline;
993     cairo_stroke_face_t face;
994     cairo_status_t status;
995 
996     if (stroker->has_bounds &&
997 	! _cairo_spline_intersects (&stroker->current_face.point, b, c, d,
998 				    &stroker->line_bounds))
999 	return line_to (closure, d);
1000 
1001     if (! _cairo_spline_init (&spline, spline_to, stroker,
1002 			      &stroker->current_face.point, b, c, d))
1003 	return line_to (closure, d);
1004 
1005     compute_face (&stroker->current_face.point, &spline.initial_slope,
1006 		  stroker, &face);
1007 
1008     if (stroker->has_current_face) {
1009 	/* Join with final face from previous segment */
1010 	join (stroker, &stroker->current_face, &face);
1011     } else {
1012 	if (! stroker->has_first_face) {
1013 	    /* Save sub path's first face in case needed for closing join */
1014 	    stroker->first_face = face;
1015 	    stroker->has_first_face = TRUE;
1016 	}
1017 	stroker->has_current_face = TRUE;
1018     }
1019     stroker->current_face = face;
1020 
1021     /* Temporarily modify the stroker to use round joins to guarantee
1022      * smooth stroked curves. */
1023     line_join_save = stroker->line_join;
1024     stroker->line_join = CAIRO_LINE_JOIN_ROUND;
1025 
1026     status = _cairo_spline_decompose (&spline, stroker->tolerance);
1027 
1028     stroker->line_join = line_join_save;
1029 
1030     return status;
1031 }
1032 
1033 static cairo_status_t
curve_to_dashed(void * closure,const cairo_point_t * b,const cairo_point_t * c,const cairo_point_t * d)1034 curve_to_dashed (void *closure,
1035 		 const cairo_point_t *b,
1036 		 const cairo_point_t *c,
1037 		 const cairo_point_t *d)
1038 {
1039     struct stroker *stroker = closure;
1040     cairo_spline_t spline;
1041     cairo_line_join_t line_join_save;
1042     cairo_spline_add_point_func_t func;
1043     cairo_status_t status;
1044 
1045     func = (cairo_spline_add_point_func_t)line_to_dashed;
1046 
1047     if (stroker->has_bounds &&
1048 	! _cairo_spline_intersects (&stroker->current_face.point, b, c, d,
1049 				    &stroker->line_bounds))
1050 	return func (closure, d, NULL);
1051 
1052     if (! _cairo_spline_init (&spline, func, stroker,
1053 			      &stroker->current_face.point, b, c, d))
1054 	return func (closure, d, NULL);
1055 
1056     /* Temporarily modify the stroker to use round joins to guarantee
1057      * smooth stroked curves. */
1058     line_join_save = stroker->line_join;
1059     stroker->line_join = CAIRO_LINE_JOIN_ROUND;
1060 
1061     status = _cairo_spline_decompose (&spline, stroker->tolerance);
1062 
1063     stroker->line_join = line_join_save;
1064 
1065     return status;
1066 }
1067 
1068 static cairo_status_t
_close_path(struct stroker * stroker)1069 _close_path (struct stroker *stroker)
1070 {
1071     if (stroker->has_first_face && stroker->has_current_face) {
1072 	/* Join first and final faces of sub path */
1073 	join (stroker, &stroker->current_face, &stroker->first_face);
1074     } else {
1075 	/* Cap the start and end of the sub path as needed */
1076 	add_caps (stroker);
1077     }
1078 
1079     stroker->has_initial_sub_path = FALSE;
1080     stroker->has_first_face = FALSE;
1081     stroker->has_current_face = FALSE;
1082     return CAIRO_STATUS_SUCCESS;
1083 }
1084 
1085 static cairo_status_t
close_path(void * closure)1086 close_path (void *closure)
1087 {
1088     struct stroker *stroker = closure;
1089     cairo_status_t status;
1090 
1091     status = line_to (stroker, &stroker->first_point);
1092     if (unlikely (status))
1093 	return status;
1094 
1095     return _close_path (stroker);
1096 }
1097 
1098 static cairo_status_t
close_path_dashed(void * closure)1099 close_path_dashed (void *closure)
1100 {
1101     struct stroker *stroker = closure;
1102     cairo_status_t status;
1103 
1104     status = line_to_dashed (stroker, &stroker->first_point);
1105     if (unlikely (status))
1106 	return status;
1107 
1108     return _close_path (stroker);
1109 }
1110 
1111 cairo_int_status_t
_cairo_path_fixed_stroke_to_traps(const cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse,double tolerance,cairo_traps_t * traps)1112 _cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t	*path,
1113 				   const cairo_stroke_style_t	*style,
1114 				   const cairo_matrix_t		*ctm,
1115 				   const cairo_matrix_t		*ctm_inverse,
1116 				   double			 tolerance,
1117 				   cairo_traps_t		*traps)
1118 {
1119     struct stroker stroker;
1120     cairo_status_t status;
1121 
1122     status = stroker_init (&stroker, path, style,
1123 			   ctm, ctm_inverse, tolerance,
1124 			   traps);
1125     if (unlikely (status))
1126 	return status;
1127 
1128     if (stroker.dash.dashed)
1129 	status = _cairo_path_fixed_interpret (path,
1130 					      move_to_dashed,
1131 					      line_to_dashed,
1132 					      curve_to_dashed,
1133 					      close_path_dashed,
1134 					      &stroker);
1135     else
1136 	status = _cairo_path_fixed_interpret (path,
1137 					      move_to,
1138 					      line_to,
1139 					      curve_to,
1140 					      close_path,
1141 					      &stroker);
1142     assert(status == CAIRO_STATUS_SUCCESS);
1143     add_caps (&stroker);
1144 
1145     stroker_fini (&stroker);
1146 
1147     return traps->status;
1148 }
1149