[cairo-commit] 6 commits - src/cairo-atomic.c src/cairo.c src/cairoint.h src/cairo-paginated-surface.c src/cairo-scaled-font.c src/cairo-spline.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Nov 1 15:43:53 PDT 2007


 src/cairo-atomic.c            |   24 ++---
 src/cairo-paginated-surface.c |    4 
 src/cairo-scaled-font.c       |    9 +-
 src/cairo-spline.c            |  185 ++++++++++++++++++++----------------------
 src/cairo.c                   |   10 +-
 src/cairoint.h                |   13 +-
 6 files changed, 127 insertions(+), 118 deletions(-)

New commits:
commit eb0b16837b7cbf63e4b49fb5c22cd392658033d8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Nov 1 22:11:01 2007 +0000

    [cairo-spline] Eliminate redundant _cairo_fixed_to_double().
    
    Inline and unroll PointDistanceSquaredToSegment() and eliminate the
    multiple conversions between fixed point and doubles. This simple
    transformation both shrinks the code and wins a few percent in path
    intensive benchmarks such as fuckhergently.swf

diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index 779a15e..b39257e 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -181,65 +181,62 @@ _de_casteljau (cairo_spline_knots_t *s1, cairo_spline_knots_t *s2)
     s1->d = final;
 }
 
-static double
-_PointDistanceSquaredToPoint (const cairo_point_t *a, const cairo_point_t *b)
-{
-    double dx = _cairo_fixed_to_double (b->x - a->x);
-    double dy = _cairo_fixed_to_double (b->y - a->y);
-
-    return dx*dx + dy*dy;
-}
-
-static double
-_PointDistanceSquaredToSegment (const cairo_point_t *p, const cairo_point_t *p1, const cairo_point_t *p2)
-{
-    double u;
-    double dx, dy;
-    double pdx, pdy;
-    cairo_point_t px;
-
-    /* intersection point (px):
-
-       px = p1 + u(p2 - p1)
-       (p - px) . (p2 - p1) = 0
-
-       Thus:
-
-       u = ((p - p1) . (p2 - p1)) / (||(p2 - p1)|| ^ 2);
-    */
-
-    if (p2->x == p1->x && p2->y == p1->y)
-	return _PointDistanceSquaredToPoint (p, p1);
-
-    dx = _cairo_fixed_to_double (p2->x - p1->x);
-    dy = _cairo_fixed_to_double (p2->y - p1->y);
-
-    pdx = _cairo_fixed_to_double (p->x - p1->x);
-    pdy = _cairo_fixed_to_double (p->y - p1->y);
-
-    u = (pdx * dx + pdy * dy) / (dx*dx + dy*dy);
-
-    if (u <= 0)
-	return _PointDistanceSquaredToPoint (p, p1);
-    else if (u >= 1)
-	return _PointDistanceSquaredToPoint (p, p2);
-
-    px.x = p1->x + u * (p2->x - p1->x);
-    px.y = p1->y + u * (p2->y - p1->y);
-
-    return _PointDistanceSquaredToPoint (p, &px);
-}
-
-/* Return an upper bound on the error (squared) that could result from approximating
-   a spline as a line segment connecting the two endpoints */
+/* Return an upper bound on the error (squared) that could result from
+ * approximating a spline as a line segment connecting the two endpoints. */
 static double
 _cairo_spline_error_squared (const cairo_spline_knots_t *knots)
 {
-    double berr, cerr;
-
-    berr = _PointDistanceSquaredToSegment (&knots->b, &knots->a, &knots->d);
-    cerr = _PointDistanceSquaredToSegment (&knots->c, &knots->a, &knots->d);
+    double bdx, bdy, berr;
+    double cdx, cdy, cerr;
+
+    /* Intersection point (px):
+     *	    px = p1 + u(p2 - p1)
+     *	    (p - px) ∙ (p2 - p1) = 0
+     * Thus:
+     *	    u = ((p - p1) ∙ (p2 - p1)) / ∥p2 - p1∥²;
+     */
+    bdx = _cairo_fixed_to_double (knots->b.x - knots->a.x);
+    bdy = _cairo_fixed_to_double (knots->b.y - knots->a.y);
+
+    cdx = _cairo_fixed_to_double (knots->c.x - knots->a.x);
+    cdy = _cairo_fixed_to_double (knots->c.y - knots->a.y);
+
+    if (knots->a.x != knots->d.x || knots->a.y != knots->d.y) {
+	double dx, dy, u, v;
+
+	dx = _cairo_fixed_to_double (knots->d.x - knots->a.x);
+	dy = _cairo_fixed_to_double (knots->d.y - knots->a.y);
+	 v = dx * dx + dy * dy;
+
+	u = bdx * dx + bdy * dy;
+	if (u <= 0) {
+	    /* bdx -= 0;
+	     * bdy -= 0;
+	     */
+	} else if (u >= v) {
+	    bdx -= dx;
+	    bdy -= dy;
+	} else {
+	    bdx -= u/v * dx;
+	    bdy -= u/v * dy;
+	}
+
+	u = cdx * dx + cdy * dy;
+	if (u <= 0) {
+	    /* cdx -= 0;
+	     * cdy -= 0;
+	     */
+	} else if (u >= v) {
+	    cdx -= dx;
+	    cdy -= dy;
+	} else {
+	    cdx -= u/v * dx;
+	    cdy -= u/v * dy;
+	}
+    }
 
+    berr = bdx * bdx + bdy * bdy;
+    cerr = cdx * cdx + cdy * cdy;
     if (berr > cerr)
 	return berr;
     else
commit 2a25e226588404da2970f473bdeb0d2ce106ce58
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Nov 1 19:49:19 2007 +0000

    [cairo-spline] Reduce stack requirements during recursive refinement.
    
    By splitting out the knot vectors into a smaller, separate structure, we
    can dramatically reduce the stack allocation for each level of recursion.
    Secondly we can have the storage requirements by modifying the first set
    of knots in-place, thus we need only allocate stack space for the knots
    covering the deferred half of the spline.

diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index 898ce7c..779a15e 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -40,45 +40,45 @@ static cairo_status_t
 _cairo_spline_grow (cairo_spline_t *spline);
 
 static cairo_status_t
-_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point);
+_cairo_spline_add_point (cairo_spline_t *spline, const cairo_point_t *point);
 
 static void
-_lerp_half (cairo_point_t *a, cairo_point_t *b, cairo_point_t *result);
+_lerp_half (const cairo_point_t *a, const cairo_point_t *b, cairo_point_t *result);
 
 static void
-_de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2);
+_de_casteljau (cairo_spline_knots_t *s1, cairo_spline_knots_t *s2);
 
 static double
-_cairo_spline_error_squared (cairo_spline_t *spline);
+_cairo_spline_error_squared (const cairo_spline_knots_t *spline);
 
 static cairo_status_t
-_cairo_spline_decompose_into (cairo_spline_t *spline, double tolerance_squared, cairo_spline_t *result);
+_cairo_spline_decompose_into (cairo_spline_knots_t *spline, double tolerance_squared, cairo_spline_t *result);
 
 cairo_int_status_t
 _cairo_spline_init (cairo_spline_t *spline,
-		    cairo_point_t *a, cairo_point_t *b,
-		    cairo_point_t *c, cairo_point_t *d)
+		    const cairo_point_t *a, const cairo_point_t *b,
+		    const cairo_point_t *c, const cairo_point_t *d)
 {
-    spline->a = *a;
-    spline->b = *b;
-    spline->c = *c;
-    spline->d = *d;
+    spline->knots.a = *a;
+    spline->knots.b = *b;
+    spline->knots.c = *c;
+    spline->knots.d = *d;
 
     if (a->x != b->x || a->y != b->y)
-	_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->b);
+	_cairo_slope_init (&spline->initial_slope, &spline->knots.a, &spline->knots.b);
     else if (a->x != c->x || a->y != c->y)
-	_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->c);
+	_cairo_slope_init (&spline->initial_slope, &spline->knots.a, &spline->knots.c);
     else if (a->x != d->x || a->y != d->y)
-	_cairo_slope_init (&spline->initial_slope, &spline->a, &spline->d);
+	_cairo_slope_init (&spline->initial_slope, &spline->knots.a, &spline->knots.d);
     else
 	return CAIRO_INT_STATUS_DEGENERATE;
 
     if (c->x != d->x || c->y != d->y)
-	_cairo_slope_init (&spline->final_slope, &spline->c, &spline->d);
+	_cairo_slope_init (&spline->final_slope, &spline->knots.c, &spline->knots.d);
     else if (b->x != d->x || b->y != d->y)
-	_cairo_slope_init (&spline->final_slope, &spline->b, &spline->d);
+	_cairo_slope_init (&spline->final_slope, &spline->knots.b, &spline->knots.d);
     else
-	_cairo_slope_init (&spline->final_slope, &spline->a, &spline->d);
+	_cairo_slope_init (&spline->final_slope, &spline->knots.a, &spline->knots.d);
 
     spline->points = spline->points_embedded;
     spline->points_size = ARRAY_LENGTH (spline->points_embedded);
@@ -114,7 +114,7 @@ _cairo_spline_grow (cairo_spline_t *spline)
 	    memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t));
     } else {
 	new_points = _cairo_realloc_ab (spline->points,
-	       	                        new_size, sizeof (cairo_point_t));
+		                        new_size, sizeof (cairo_point_t));
     }
 
     if (new_points == NULL)
@@ -127,7 +127,7 @@ _cairo_spline_grow (cairo_spline_t *spline)
 }
 
 static cairo_status_t
-_cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point)
+_cairo_spline_add_point (cairo_spline_t *spline, const cairo_point_t *point)
 {
     cairo_status_t status;
     cairo_point_t *prev;
@@ -151,39 +151,38 @@ _cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point)
 }
 
 static void
-_lerp_half (cairo_point_t *a, cairo_point_t *b, cairo_point_t *result)
+_lerp_half (const cairo_point_t *a, const cairo_point_t *b, cairo_point_t *result)
 {
     result->x = a->x + ((b->x - a->x) >> 1);
     result->y = a->y + ((b->y - a->y) >> 1);
 }
 
 static void
-_de_casteljau (cairo_spline_t *spline, cairo_spline_t *s1, cairo_spline_t *s2)
+_de_casteljau (cairo_spline_knots_t *s1, cairo_spline_knots_t *s2)
 {
     cairo_point_t ab, bc, cd;
     cairo_point_t abbc, bccd;
     cairo_point_t final;
 
-    _lerp_half (&spline->a, &spline->b, &ab);
-    _lerp_half (&spline->b, &spline->c, &bc);
-    _lerp_half (&spline->c, &spline->d, &cd);
+    _lerp_half (&s1->a, &s1->b, &ab);
+    _lerp_half (&s1->b, &s1->c, &bc);
+    _lerp_half (&s1->c, &s1->d, &cd);
     _lerp_half (&ab, &bc, &abbc);
     _lerp_half (&bc, &cd, &bccd);
     _lerp_half (&abbc, &bccd, &final);
 
-    s1->a = spline->a;
-    s1->b = ab;
-    s1->c = abbc;
-    s1->d = final;
-
     s2->a = final;
     s2->b = bccd;
     s2->c = cd;
-    s2->d = spline->d;
+    s2->d = s1->d;
+
+    s1->b = ab;
+    s1->c = abbc;
+    s1->d = final;
 }
 
 static double
-_PointDistanceSquaredToPoint (cairo_point_t *a, cairo_point_t *b)
+_PointDistanceSquaredToPoint (const cairo_point_t *a, const cairo_point_t *b)
 {
     double dx = _cairo_fixed_to_double (b->x - a->x);
     double dy = _cairo_fixed_to_double (b->y - a->y);
@@ -192,7 +191,7 @@ _PointDistanceSquaredToPoint (cairo_point_t *a, cairo_point_t *b)
 }
 
 static double
-_PointDistanceSquaredToSegment (cairo_point_t *p, cairo_point_t *p1, cairo_point_t *p2)
+_PointDistanceSquaredToSegment (const cairo_point_t *p, const cairo_point_t *p1, const cairo_point_t *p2)
 {
     double u;
     double dx, dy;
@@ -209,12 +208,12 @@ _PointDistanceSquaredToSegment (cairo_point_t *p, cairo_point_t *p1, cairo_point
        u = ((p - p1) . (p2 - p1)) / (||(p2 - p1)|| ^ 2);
     */
 
+    if (p2->x == p1->x && p2->y == p1->y)
+	return _PointDistanceSquaredToPoint (p, p1);
+
     dx = _cairo_fixed_to_double (p2->x - p1->x);
     dy = _cairo_fixed_to_double (p2->y - p1->y);
 
-    if (dx == 0 && dy == 0)
-	return _PointDistanceSquaredToPoint (p, p1);
-
     pdx = _cairo_fixed_to_double (p->x - p1->x);
     pdy = _cairo_fixed_to_double (p->y - p1->y);
 
@@ -234,12 +233,12 @@ _PointDistanceSquaredToSegment (cairo_point_t *p, cairo_point_t *p1, cairo_point
 /* Return an upper bound on the error (squared) that could result from approximating
    a spline as a line segment connecting the two endpoints */
 static double
-_cairo_spline_error_squared (cairo_spline_t *spline)
+_cairo_spline_error_squared (const cairo_spline_knots_t *knots)
 {
     double berr, cerr;
 
-    berr = _PointDistanceSquaredToSegment (&spline->b, &spline->a, &spline->d);
-    cerr = _PointDistanceSquaredToSegment (&spline->c, &spline->a, &spline->d);
+    berr = _PointDistanceSquaredToSegment (&knots->b, &knots->a, &knots->d);
+    cerr = _PointDistanceSquaredToSegment (&knots->c, &knots->a, &knots->d);
 
     if (berr > cerr)
 	return berr;
@@ -248,18 +247,17 @@ _cairo_spline_error_squared (cairo_spline_t *spline)
 }
 
 static cairo_status_t
-_cairo_spline_decompose_into (cairo_spline_t *spline, double tolerance_squared, cairo_spline_t *result)
+_cairo_spline_decompose_into (cairo_spline_knots_t *s1, double tolerance_squared, cairo_spline_t *result)
 {
+    cairo_spline_knots_t s2;
     cairo_status_t status;
-    cairo_spline_t s1, s2;
 
-    if (_cairo_spline_error_squared (spline) < tolerance_squared) {
-	return _cairo_spline_add_point (result, &spline->a);
-    }
+    if (_cairo_spline_error_squared (s1) < tolerance_squared)
+	return _cairo_spline_add_point (result, &s1->a);
 
-    _de_casteljau (spline, &s1, &s2);
+    _de_casteljau (s1, &s2);
 
-    status = _cairo_spline_decompose_into (&s1, tolerance_squared, result);
+    status = _cairo_spline_decompose_into (s1, tolerance_squared, result);
     if (status)
 	return status;
 
@@ -274,15 +272,17 @@ cairo_status_t
 _cairo_spline_decompose (cairo_spline_t *spline, double tolerance)
 {
     cairo_status_t status;
+    cairo_spline_knots_t s1;
 
     /* reset the spline, but keep the buffer */
     spline->num_points = 0;
 
-    status = _cairo_spline_decompose_into (spline, tolerance * tolerance, spline);
+    s1 = spline->knots;
+    status = _cairo_spline_decompose_into (&s1, tolerance * tolerance, spline);
     if (status)
 	return status;
 
-    status = _cairo_spline_add_point (spline, &spline->d);
+    status = _cairo_spline_add_point (spline, &spline->knots.d);
     if (status)
 	return status;
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 225cb4b..bde8f6b 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -283,8 +283,11 @@ typedef struct _cairo_polygon {
     cairo_edge_t  edges_embedded[8];
 } cairo_polygon_t;
 
-typedef struct _cairo_spline {
+typedef struct _cairo_spline_knots {
     cairo_point_t a, b, c, d;
+} cairo_spline_knots_t;
+typedef struct _cairo_spline {
+    cairo_spline_knots_t knots;
 
     cairo_slope_t initial_slope;
     cairo_slope_t final_slope;
@@ -2086,10 +2089,10 @@ _cairo_polygon_close (cairo_polygon_t *polygon);
 /* cairo_spline.c */
 cairo_private cairo_int_status_t
 _cairo_spline_init (cairo_spline_t *spline,
-		    cairo_point_t *a,
-		    cairo_point_t *b,
-		    cairo_point_t *c,
-		    cairo_point_t *d);
+		    const cairo_point_t *a,
+		    const cairo_point_t *b,
+		    const cairo_point_t *c,
+		    const cairo_point_t *d);
 
 cairo_private cairo_status_t
 _cairo_spline_decompose (cairo_spline_t *spline, double tolerance);
commit b311c414a27b7374540671b3ef7153b30def0451
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Nov 1 19:40:25 2007 +0000

    [cairo] Use NULL instead of a bare 0.
    
    Silence a sparse warning.

diff --git a/src/cairo.c b/src/cairo.c
index f2b7917..dc01ffc 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -53,11 +53,11 @@ static const cairo_t _cairo_nil = {
     0
   }},
   {{ 				/* path */
-    { 0, 0 },			   /* last_move_point */
-    { 0, 0 },			   /* current point */
-    FALSE,			   /* has_current_point */
-    FALSE,			   /* has_curve_to */
-    NULL, {{0}}			   /* buf_tail, buf_head */
+    { 0, 0 },			/* last_move_point */
+    { 0, 0 },			/* current point */
+    FALSE,			/* has_current_point */
+    FALSE,			/* has_curve_to */
+    NULL, {{NULL}}		/* buf_tail, buf_head */
   }}
 };
 
commit fd5c5178189d2035f3e25919c7453fa4e1c5a76a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Nov 1 19:39:02 2007 +0000

    [cairo-scaled-font] Zero extents on early error.
    
    Ensure that the output extents of cairo_scaled_font_glyph_extents(),
    are zeroed if we return early due to being passed by the user a
    cairo_scaled_font_t with an error set.

diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 1ce998a..2fd1fff 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -939,8 +939,15 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t   *scaled_font,
     cairo_bool_t visible = FALSE;
     cairo_scaled_glyph_t *scaled_glyph = NULL;
 
-    if (scaled_font->status)
+    if (scaled_font->status) {
+	extents->x_bearing = 0.0;
+	extents->y_bearing = 0.0;
+	extents->width = 0.0;
+	extents->height = 0.0;
+	extents->x_advance = 0.0;
+	extents->y_advance = 0.0;
 	return;
+    }
 
     CAIRO_MUTEX_LOCK (scaled_font->mutex);
     _cairo_scaled_font_freeze_cache (scaled_font);
commit cee6aa016b9d96d3430187d44397df2b311de8bc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Nov 1 19:30:19 2007 +0000

    [cairo-paginated-surface] Mark the backend static.
    
    Only used within the file, so do not expose outside the library.

diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 0ebe2c1..e25204e 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -49,7 +49,7 @@
 #include "cairo-meta-surface-private.h"
 #include "cairo-analysis-surface-private.h"
 
-const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
+static const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
 
 static cairo_int_status_t
 _cairo_paginated_surface_show_page (void *abstract_surface);
@@ -653,7 +653,7 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
 #endif
 }
 
-const cairo_surface_backend_t cairo_paginated_surface_backend = {
+static const cairo_surface_backend_t cairo_paginated_surface_backend = {
     CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
     _cairo_paginated_surface_create_similar,
     _cairo_paginated_surface_finish,
commit 6e0151df469b67ea56c36f7b0050b5d5c959c67d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Nov 1 19:29:00 2007 +0000

    [cairo-atomic] Rearrange code under the correct ifdefs.
    
    The atomic get/set depend upon NEED_MEMORY_BARRIER which is separate
    from HAVE_ATOMIC_OPS.

diff --git a/src/cairo-atomic.c b/src/cairo-atomic.c
index f9e4de7..9e388ac 100644
--- a/src/cairo-atomic.c
+++ b/src/cairo-atomic.c
@@ -58,37 +58,39 @@ _cairo_atomic_int_dec_and_test (int *x)
 }
 
 int
-_cairo_atomic_int_get (int *x)
+_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
 {
     int ret;
 
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     ret = *x;
+    if (ret == oldv)
+	*x = newv;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 
     return ret;
 }
 
-void
-_cairo_atomic_int_set (int *x, int value)
-{
-    CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
-    *x = value;
-    CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
-}
+#endif
 
+#ifdef CAIRO_ATOMIC_OP_NEEDS_MEMORY_BARRIER
 int
-_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
+_cairo_atomic_int_get (int *x)
 {
     int ret;
 
     CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
     ret = *x;
-    if (ret == oldv)
-	*x = newv;
     CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
 
     return ret;
 }
 
+void
+_cairo_atomic_int_set (int *x, int value)
+{
+    CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
+    *x = value;
+    CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
+}
 #endif


More information about the cairo-commit mailing list