[cairo-commit] src/cairoint.h src/cairo-path-stroke.c src/cairo-rectangle.c src/cairo-stroke-style.c

Vladimir Vukicevic vladimir at kemper.freedesktop.org
Wed Feb 6 13:09:26 PST 2008


 src/cairo-path-stroke.c  |   33 +++++++++++++--------------------
 src/cairo-rectangle.c    |    2 +-
 src/cairo-stroke-style.c |   17 +++++++++++++++++
 src/cairoint.h           |   11 ++++++++++-
 4 files changed, 41 insertions(+), 22 deletions(-)

New commits:
commit bf1f7f70b61b5bb657b2531dab63c541ac8fb59d
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Wed Feb 6 13:01:52 2008 -0800

    Do correct calculation of pen dimensions for stroke optimization

diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 71510b1..b82c28a 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -192,30 +192,23 @@ _cairo_stroker_init (cairo_stroker_t		*stroker,
 
     stroker->has_bounds = _cairo_traps_get_limit (traps, &stroker->bounds);
     if (stroker->has_bounds) {
-	/* Extend the bounds by the line width in each direction so that we correctly
-	 * capture segment endcaps and other similar renderings that would extend beyond
-	 * the segment itself.
+	/* Extend the bounds in each direction to account for the maximum area
+	 * we might generate trapezoids, to capture line segments that are outside
+	 * of the bounds but which might generate rendering that's within bounds.
 	 */
-	double width_x = stroker->style->line_width;
-	double width_y = stroker->style->line_width;
-
-	cairo_fixed_t fixed_x, fixed_y;
-
-	if (stroke_style->line_join == CAIRO_LINE_JOIN_MITER) {
-	    width_x *= stroker->style->miter_limit;
-	    width_y *= stroker->style->miter_limit;
-	}
+	double dx, dy;
+	cairo_fixed_t fdx, fdy;
 
-	cairo_matrix_transform_distance (stroker->ctm, &width_x, &width_y);
+	_cairo_stroke_style_max_distance_from_path (stroker->style, stroker->ctm, &dx, &dy);
 
-	fixed_x = _cairo_fixed_from_double (width_x);
-	fixed_y = _cairo_fixed_from_double (width_y);
+	fdx = _cairo_fixed_from_double (dx);
+	fdy = _cairo_fixed_from_double (dy);
 
-	stroker->bounds.p1.x -= fixed_x;
-	stroker->bounds.p2.x += fixed_x;
+	stroker->bounds.p1.x -= fdx;
+	stroker->bounds.p2.x += fdx;
 
-	stroker->bounds.p1.y -= fixed_y;
-	stroker->bounds.p2.y += fixed_y;
+	stroker->bounds.p1.y -= fdy;
+	stroker->bounds.p2.y += fdy;
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -864,7 +857,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
 	segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
 
 	if (fully_in_bounds ||
-	    _cairo_box_intersects_line (&stroker->bounds, &segment))
+	    _cairo_box_intersects_line_segment (&stroker->bounds, &segment))
 	{
 	    if (stroker->dash_on) {
 		status = _cairo_stroker_add_sub_edge (stroker, &segment.p1, &segment.p2, slope_dx, slope_dy, &sub_start, &sub_end);
diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index 7ebdfb5..d2ec52d 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -106,7 +106,7 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *
  */
 
 cairo_bool_t
-_cairo_box_intersects_line (cairo_box_t *box, cairo_line_t *line)
+_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line)
 {
     cairo_fixed_t t1, t2, t3, t4;
     cairo_int64_t t1y, t2y, t3x, t4x;
diff --git a/src/cairo-stroke-style.c b/src/cairo-stroke-style.c
index a7c17b2..3bc234e 100644
--- a/src/cairo-stroke-style.c
+++ b/src/cairo-stroke-style.c
@@ -84,3 +84,20 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style)
     }
     style->num_dashes = 0;
 }
+
+/*
+ * For a stroke in the given style, compute the maximum distance
+ * from the path that vertices could be generated.  In the case
+ * of rotation in the ctm, the distance will not be exact.
+ */
+void
+_cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style,
+                                            const cairo_matrix_t *ctm,
+                                            double *dx, double *dy)
+{
+    double style_expansion = MAX(style->line_cap == CAIRO_LINE_CAP_SQUARE ? M_SQRT1_2 : 0.5,
+                                 style->line_join == CAIRO_LINE_JOIN_MITER ? style->miter_limit : 0.5);
+
+    *dx = style->line_width * style_expansion * (fabs(ctm->xx) + fabs(ctm->xy));
+    *dy = style->line_width * style_expansion * (fabs(ctm->yy) + fabs(ctm->yx));
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index 2a1df7b..0ca08f4 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -98,6 +98,10 @@ _cairo_win32_tmpfile (void);
 #define M_SQRT2 1.41421356237309504880
 #endif
 
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 0.707106781186547524400844362104849039
+#endif
+
 #undef  ARRAY_LENGTH
 #define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
 
@@ -180,7 +184,7 @@ cairo_private void
 _cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *src);
 
 cairo_private cairo_bool_t
-_cairo_box_intersects_line (cairo_box_t *box, cairo_line_t *line);
+_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line);
 
 cairo_private cairo_bool_t
 _cairo_box_contains_point (cairo_box_t *box, cairo_point_t *point);
@@ -1482,6 +1486,11 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
 cairo_private void
 _cairo_stroke_style_fini (cairo_stroke_style_t *style);
 
+cairo_private void
+_cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style,
+                                            const cairo_matrix_t *ctm,
+                                            double *dx, double *dy);
+
 /* cairo-surface.c */
 
 cairo_private cairo_surface_t *


More information about the cairo-commit mailing list