[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