[cairo-commit] 21 commits - boilerplate/cairo-boilerplate.c boilerplate/Makefile.am src/cairo-bentley-ottmann.c src/cairo.c src/cairo-clip.c src/cairo-directfb.h src/cairo-gstate.c src/cairoint.h src/cairo-os2.h src/cairo-path-fill.c src/cairo-path-fixed.c src/cairo-path-fixed-private.h src/cairo-private.h src/cairo-quartz-surface.c src/cairo-skiplist.c src/cairo-skiplist-private.h src/cairo-slope.c src/cairo-spline.c src/cairo-traps.c src/test-fallback-surface.c src/test-fallback-surface.h src/test-meta-surface.c src/test-meta-surface.h src/test-paginated-surface.c src/test-paginated-surface.h test/Makefile.am

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Mar 13 02:14:46 PDT 2007


 boilerplate/Makefile.am         |    2 
 boilerplate/cairo-boilerplate.c |    6 
 src/cairo-bentley-ottmann.c     |   24 +--
 src/cairo-clip.c                |    5 
 src/cairo-directfb.h            |    3 
 src/cairo-gstate.c              |   44 -----
 src/cairo-os2.h                 |    2 
 src/cairo-path-fill.c           |   51 +++---
 src/cairo-path-fixed-private.h  |   28 +--
 src/cairo-path-fixed.c          |  303 ++++++++++++++--------------------------
 src/cairo-private.h             |    5 
 src/cairo-quartz-surface.c      |    1 
 src/cairo-skiplist-private.h    |   22 +-
 src/cairo-skiplist.c            |   35 ++--
 src/cairo-slope.c               |    8 -
 src/cairo-spline.c              |   39 +++--
 src/cairo-traps.c               |   49 ++++--
 src/cairo.c                     |   89 +++++------
 src/cairoint.h                  |   17 +-
 src/test-fallback-surface.c     |    8 -
 src/test-fallback-surface.h     |    2 
 src/test-meta-surface.c         |    2 
 src/test-meta-surface.h         |    2 
 src/test-paginated-surface.c    |    2 
 src/test-paginated-surface.h    |    2 
 test/Makefile.am                |    3 
 26 files changed, 334 insertions(+), 420 deletions(-)

New commits:
diff-tree 6976ab1392e0fd07a081e6d6056510070e1d6df9 (from 9eee167210b6cc562014652572872cf0a7ccb00e)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Mar 9 16:23:35 2007 -0500

    [cairo-slope] Make comparison stable if both vectors are zero

diff --git a/src/cairo-slope.c b/src/cairo-slope.c
index 2c888e4..78664c5 100644
--- a/src/cairo-slope.c
+++ b/src/cairo-slope.c
@@ -51,7 +51,7 @@ _cairo_slope_init (cairo_slope_t *slope,
    difference between a and b is less than PI.
 
    <  0 => a less positive than b
-   == 0 => a equal to be
+   == 0 => a equal to b
    >  0 => a more positive than b
 */
 int
@@ -67,6 +67,12 @@ _cairo_slope_compare (cairo_slope_t *a, 
     if (diff < 0)
 	return -1;
 
+    /* special-case zero vectors.  the intended logic here is:
+     * zero vectors all compare equal, and more positive than any
+     * non-zero vector.
+     */
+    if (a->dx == 0 && a->dy == 0 && b->dx == 0 && b->dy ==0)
+	return 0;
     if (a->dx == 0 && a->dy == 0)
 	return 1;
     if (b->dx == 0 && b->dy ==0)
diff-tree 9eee167210b6cc562014652572872cf0a7ccb00e (from 1e64ecf0758a208b469ae0a87a747b3a70c70ceb)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 22:34:44 2007 -0500

    [cairo-spline] Add a cache of eight points to cairo_spline_t
    
    Most of the splines need not more than eight points.  This avoids
    calling malloc() for those cases, and eight-points take only 64 bytes.

diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index 726dc86..d8dd477 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -90,22 +90,40 @@ _cairo_spline_init (cairo_spline_t *spli
 void
 _cairo_spline_fini (cairo_spline_t *spline)
 {
-    spline->num_points = 0;
-    spline->points_size = 0;
-    free (spline->points);
+    if (spline->points != spline->points_embedded)
+	free (spline->points);
+
     spline->points = NULL;
+    spline->points_size = 0;
+    spline->num_points = 0;
 }
 
+/* make room for at least one more trap */
 static cairo_status_t
 _cairo_spline_grow (cairo_spline_t *spline)
 {
     cairo_point_t *new_points;
     int old_size = spline->points_size;
-    int new_size = old_size ? 2 * old_size : 32;
+    int embedded_size = sizeof (spline->points_embedded) / sizeof (spline->points_embedded[0]);
+    int new_size = 2 * MAX (old_size, 16);
+
+    /* we have a local buffer at spline->points_embedded.  try to fulfill the request
+     * from there. */
+    if (old_size < embedded_size) {
+	spline->points = spline->points_embedded;
+	spline->points_size = embedded_size;
+	return CAIRO_STATUS_SUCCESS;
+    }
 
     assert (spline->num_points <= spline->points_size);
 
-    new_points = realloc (spline->points, new_size * sizeof (cairo_point_t));
+    if (spline->points == spline->points_embedded) {
+	new_points = malloc (new_size * sizeof (cairo_point_t));
+	if (new_points)
+	    memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t));
+    } else {
+	new_points = realloc (spline->points, new_size * sizeof (cairo_point_t));
+    }
 
     if (new_points == NULL) {
 	return CAIRO_STATUS_NO_MEMORY;
diff --git a/src/cairoint.h b/src/cairoint.h
index 125b1fb..aee5ad9 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -441,6 +441,7 @@ typedef struct _cairo_spline {
     int num_points;
     int points_size;
     cairo_point_t *points;
+    cairo_point_t  points_embedded[8];
 } cairo_spline_t;
 
 typedef struct _cairo_pen_vertex {
diff-tree 1e64ecf0758a208b469ae0a87a747b3a70c70ceb (from cee687a33fb46b68d39bbfa64c44f0b28e10a9ee)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 22:17:30 2007 -0500

    [cairo-spline] Clean-up realloc algorithm for clarity

diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index 900d3ca..726dc86 100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -37,7 +37,7 @@
 #include "cairoint.h"
 
 static cairo_status_t
-_cairo_spline_grow_by (cairo_spline_t *spline, int additional);
+_cairo_spline_grow (cairo_spline_t *spline);
 
 static cairo_status_t
 _cairo_spline_add_point (cairo_spline_t *spline, cairo_point_t *point);
@@ -97,24 +97,22 @@ _cairo_spline_fini (cairo_spline_t *spli
 }
 
 static cairo_status_t
-_cairo_spline_grow_by (cairo_spline_t *spline, int additional)
+_cairo_spline_grow (cairo_spline_t *spline)
 {
     cairo_point_t *new_points;
     int old_size = spline->points_size;
-    int new_size = spline->num_points + additional;
+    int new_size = old_size ? 2 * old_size : 32;
 
-    if (new_size <= spline->points_size)
-	return CAIRO_STATUS_SUCCESS;
+    assert (spline->num_points <= spline->points_size);
 
-    spline->points_size = new_size;
-    new_points = realloc (spline->points, spline->points_size * sizeof (cairo_point_t));
+    new_points = realloc (spline->points, new_size * sizeof (cairo_point_t));
 
     if (new_points == NULL) {
-	spline->points_size = old_size;
 	return CAIRO_STATUS_NO_MEMORY;
     }
 
     spline->points = new_points;
+    spline->points_size = new_size;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -132,8 +130,7 @@ _cairo_spline_add_point (cairo_spline_t 
     }
 
     if (spline->num_points >= spline->points_size) {
-	int additional = spline->points_size ? spline->points_size : 32;
-	status = _cairo_spline_grow_by (spline, additional);
+	status = _cairo_spline_grow (spline);
 	if (status)
 	    return status;
     }
diff-tree cee687a33fb46b68d39bbfa64c44f0b28e10a9ee (from 24aec99ffb9abce659146ea6ecbfb92856355855)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 22:19:49 2007 -0500

    [cairo_traps_t] Reorder struct members for clarity

diff --git a/src/cairoint.h b/src/cairoint.h
index 38c5536..125b1fb 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1222,11 +1222,11 @@ typedef struct _cairo_surface_attributes
 typedef struct _cairo_traps {
     cairo_status_t status;
 
-    cairo_trapezoid_t *traps;
-    int num_traps;
-    int traps_size;
     cairo_box_t extents;
 
+    int num_traps;
+    int traps_size;
+    cairo_trapezoid_t *traps;
     cairo_trapezoid_t  traps_embedded[1];
 } cairo_traps_t;
 
diff-tree 24aec99ffb9abce659146ea6ecbfb92856355855 (from 4737416c6e7829ec21230103a1b993d2bd08cc0e)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 20:32:36 2007 -0500

    [cairo-traps] Add a cache of one trapezoid to cairo_traps_t
    
    Seems like half the time, we just need one trap.  This avoids
    calling malloc() for those cases.

diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 2415ee6..04228c1 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -77,12 +77,12 @@ _cairo_traps_init (cairo_traps_t *traps)
 void
 _cairo_traps_fini (cairo_traps_t *traps)
 {
-    if (traps->traps_size) {
+    if (traps->traps != traps->traps_embedded)
 	free (traps->traps);
-	traps->traps = NULL;
-	traps->traps_size = 0;
-	traps->num_traps = 0;
-    }
+
+    traps->traps = NULL;
+    traps->traps_size = 0;
+    traps->num_traps = 0;
 }
 
 /**
@@ -192,19 +192,35 @@ _cairo_traps_add_trap_from_points (cairo
     return _cairo_traps_add_trap (traps, top, bottom, &left, &right);
 }
 
+/* make room for at least one more trap */
 static cairo_status_t
 _cairo_traps_grow (cairo_traps_t *traps)
 {
     cairo_trapezoid_t *new_traps;
     int old_size = traps->traps_size;
-    int new_size = old_size ? 2 * old_size : 32;
+    int embedded_size = sizeof (traps->traps_embedded) / sizeof (traps->traps_embedded[0]);
+    int new_size = 2 * MAX (old_size, 16);
+
+    /* we have a local buffer at traps->traps_embedded.  try to fulfill the request
+     * from there. */
+    if (old_size < embedded_size) {
+	traps->traps = traps->traps_embedded;
+	traps->traps_size = embedded_size;
+	return traps->status;
+    }
 
     assert (traps->num_traps <= traps->traps_size);
 
     if (traps->status)
 	return traps->status;
 
-    new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
+    if (traps->traps == traps->traps_embedded) {
+	new_traps = malloc (new_size * sizeof (cairo_trapezoid_t));
+	if (new_traps)
+	    memcpy (new_traps, traps->traps, old_size * sizeof (cairo_trapezoid_t));
+    } else {
+	new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
+    }
 
     if (new_traps == NULL) {
 	traps->status = CAIRO_STATUS_NO_MEMORY;
diff --git a/src/cairoint.h b/src/cairoint.h
index c0d3a17..38c5536 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1226,6 +1226,8 @@ typedef struct _cairo_traps {
     int num_traps;
     int traps_size;
     cairo_box_t extents;
+
+    cairo_trapezoid_t  traps_embedded[1];
 } cairo_traps_t;
 
 #define CAIRO_FONT_SLANT_DEFAULT   CAIRO_FONT_SLANT_NORMAL
diff-tree 4737416c6e7829ec21230103a1b993d2bd08cc0e (from a9d8cb3e8aceb5831dfb3920df1502bf3b9450a6)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 20:05:13 2007 -0500

    [cairo-traps] Clean-up realloc algorithm for clarity

diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 01305c6..2415ee6 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -40,7 +40,7 @@
 /* private functions */
 
 static cairo_status_t
-_cairo_traps_grow_by (cairo_traps_t *traps, int additional);
+_cairo_traps_grow (cairo_traps_t *traps);
 
 static cairo_status_t
 _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
@@ -100,7 +100,7 @@ _cairo_traps_init_box (cairo_traps_t *tr
 {
   _cairo_traps_init (traps);
 
-  traps->status = _cairo_traps_grow_by (traps, 1);
+  traps->status = _cairo_traps_grow (traps);
   if (traps->status)
     return traps->status;
 
@@ -134,8 +134,7 @@ _cairo_traps_add_trap (cairo_traps_t *tr
     }
 
     if (traps->num_traps >= traps->traps_size) {
-	int inc = traps->traps_size ? traps->traps_size : 32;
-	traps->status = _cairo_traps_grow_by (traps, inc);
+	traps->status = _cairo_traps_grow (traps);
 	if (traps->status)
 	    return traps->status;
     }
@@ -194,28 +193,26 @@ _cairo_traps_add_trap_from_points (cairo
 }
 
 static cairo_status_t
-_cairo_traps_grow_by (cairo_traps_t *traps, int additional)
+_cairo_traps_grow (cairo_traps_t *traps)
 {
     cairo_trapezoid_t *new_traps;
     int old_size = traps->traps_size;
-    int new_size = traps->num_traps + additional;
+    int new_size = old_size ? 2 * old_size : 32;
+
+    assert (traps->num_traps <= traps->traps_size);
 
     if (traps->status)
 	return traps->status;
 
-    if (new_size <= traps->traps_size)
-	return traps->status;
-
-    traps->traps_size = new_size;
-    new_traps = realloc (traps->traps, traps->traps_size * sizeof (cairo_trapezoid_t));
+    new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
 
     if (new_traps == NULL) {
-	traps->traps_size = old_size;
 	traps->status = CAIRO_STATUS_NO_MEMORY;
 	return traps->status;
     }
 
     traps->traps = new_traps;
+    traps->traps_size = new_size;
 
     return traps->status;
 }
diff-tree a9d8cb3e8aceb5831dfb3920df1502bf3b9450a6 (from 5d28bf605fee84520e82818dd35cae8899ecc2ba)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 19:34:43 2007 -0500

    [cairo-traps] Use INT32_MIN/MAX instead of INT16_MIN/MAX << 16

diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 9b3931f..01305c6 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -70,8 +70,8 @@ _cairo_traps_init (cairo_traps_t *traps)
 
     traps->traps_size = 0;
     traps->traps = NULL;
-    traps->extents.p1.x = traps->extents.p1.y = INT16_MAX << 16;
-    traps->extents.p2.x = traps->extents.p2.y = INT16_MIN << 16;
+    traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
+    traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
 }
 
 void
diff-tree 5d28bf605fee84520e82818dd35cae8899ecc2ba (from e765ac745e0438296d2c852fd8231bd8f1fff034)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 19:22:57 2007 -0500

    [test] Make pdiff if necessary

diff --git a/test/Makefile.am b/test/Makefile.am
index 721f4e8..ea4787c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -463,6 +463,9 @@ $(top_builddir)/boilerplate/libcairoboil
 $(top_builddir)/src/libcairo.la:
 	cd $(top_builddir)/src && $(MAKE) $(AM_MAKEFLAGS) libcairo.la
 
+$(top_builddir)/test/pdiff/libpdiff.la:
+	cd $(top_builddir)/test/pdiff && $(MAKE) $(AM_MAKEFLAGS) libpdiff.la
+
 if HAVE_PTHREAD
 LDADD += -lpthread
 endif
diff-tree e765ac745e0438296d2c852fd8231bd8f1fff034 (from cd78da36f663b99c67d50dcd692cd7b67677c82a)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 18:13:55 2007 -0500

    [skiplist] Prefix symbols with _cairo

diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index b4f7066..928b6cd 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -121,7 +121,7 @@ typedef struct _cairo_bo_event {
 #define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
 
 typedef struct _cairo_bo_event_queue {
-    skip_list_t intersection_queue;
+    cairo_skip_list_t intersection_queue;
 
     cairo_bo_event_t *startstop_events;
     cairo_bo_event_t **sorted_startstop_event_ptrs;
@@ -129,9 +129,9 @@ typedef struct _cairo_bo_event_queue {
     unsigned num_startstop_events;
 } cairo_bo_event_queue_t;
 
-/* This structure extends skip_list_t, which must come first. */
+/* This structure extends cairo_skip_list_t, which must come first. */
 typedef struct _cairo_bo_sweep_line {
-    skip_list_t active_edges;
+    cairo_skip_list_t active_edges;
     cairo_bo_edge_t *head;
     cairo_bo_edge_t *tail;
     int32_t current_y;
@@ -697,7 +697,7 @@ _cairo_bo_event_queue_insert (cairo_bo_e
 			      cairo_bo_event_t	     *event)
 {
     /* Don't insert if there's already an equivalent intersection event in the queue. */
-    skip_list_insert (&queue->intersection_queue, event,
+    _cairo_skip_list_insert (&queue->intersection_queue, event,
 		      event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION);
 }
 
@@ -706,7 +706,7 @@ _cairo_bo_event_queue_delete (cairo_bo_e
 			      cairo_bo_event_t	     *event)
 {
     if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type)
-	skip_list_delete_given ( &queue->intersection_queue, &event->elt );
+	_cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt );
 }
 
 static cairo_bo_event_t *
@@ -740,7 +740,7 @@ _cairo_bo_event_queue_init (cairo_bo_eve
 
     memset (event_queue, 0, sizeof(*event_queue));
 
-    skip_list_init (&event_queue->intersection_queue,
+    _cairo_skip_list_init (&event_queue->intersection_queue,
 		    cairo_bo_event_compare_abstract,
 		    sizeof (cairo_bo_event_t));
     if (0 == num_edges)
@@ -789,7 +789,7 @@ _cairo_bo_event_queue_init (cairo_bo_eve
 static void
 _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
 {
-    skip_list_fini (&event_queue->intersection_queue);
+    _cairo_skip_list_fini (&event_queue->intersection_queue);
     if (event_queue->startstop_events)
 	free (event_queue->startstop_events);
     if (event_queue->sorted_startstop_event_ptrs)
@@ -834,7 +834,7 @@ _cairo_bo_event_queue_insert_if_intersec
 static void
 _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
 {
-    skip_list_init (&sweep_line->active_edges,
+    _cairo_skip_list_init (&sweep_line->active_edges,
 		    _sweep_line_elt_compare,
 		    sizeof (sweep_line_elt_t));
     sweep_line->head = NULL;
@@ -845,7 +845,7 @@ _cairo_bo_sweep_line_init (cairo_bo_swee
 static void
 _cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
 {
-    skip_list_fini (&sweep_line->active_edges);
+    _cairo_skip_list_fini (&sweep_line->active_edges);
 }
 
 static void
@@ -856,7 +856,7 @@ _cairo_bo_sweep_line_insert (cairo_bo_sw
     sweep_line_elt_t *sweep_line_elt;
     cairo_bo_edge_t **prev_of_next, **next_of_prev;
 
-    sweep_line_elt = skip_list_insert (&sweep_line->active_edges, &edge,
+    sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
 				       1 /* unique inserts*/);
 
     next_elt = sweep_line_elt->elt.next[0];
@@ -884,7 +884,7 @@ _cairo_bo_sweep_line_delete (cairo_bo_sw
 {
     cairo_bo_edge_t **left_next, **right_prev;
 
-    skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
+    _cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
 
     left_next = &sweep_line->head;
     if (edge->prev)
@@ -975,7 +975,7 @@ _cairo_bo_event_queue_print (cairo_bo_ev
 {
     skip_elt_t *elt;
     /* XXX: fixme to print the start/stop array too. */
-    skip_list_t *queue = &event_queue->intersection_queue;
+    cairo_skip_list_t *queue = &event_queue->intersection_queue;
     cairo_bo_event_t *event;
 
     printf ("Event queue:\n");
diff --git a/src/cairo-skiplist-private.h b/src/cairo-skiplist-private.h
index d776ad6..b152f4b 100644
--- a/src/cairo-skiplist-private.h
+++ b/src/cairo-skiplist-private.h
@@ -34,7 +34,7 @@
  * a skip_elt_t, (which will be allocated with variable size).
  *
  * The caller must also pass the size of the structure to
- * skip_list_init.
+ * _cairo_skip_list_init.
  */
 typedef struct _skip_elt {
     int prev_index;
@@ -45,16 +45,16 @@ typedef struct _skip_elt {
 #define SKIP_LIST_ELT_TO_DATA(type, elt) ((type *) ((char *) (elt) - (sizeof (type) - sizeof (skip_elt_t))))
 
 typedef int
-(*skip_list_compare_t) (void *list, void *a, void *b);
+(*cairo_skip_list_compare_t) (void *list, void *a, void *b);
 
 typedef struct _skip_list {
-    skip_list_compare_t compare;
+    cairo_skip_list_compare_t compare;
     size_t elt_size;
     size_t data_size;
     skip_elt_t *chains[MAX_LEVEL];
     skip_elt_t *freelists[MAX_LEVEL];
     int		max_level;
-} skip_list_t;
+} cairo_skip_list_t;
 
 /* Initialize a new skip list. The compare function accepts a pointer
  * to the list as well as pointers to two elements. The function must
@@ -65,8 +65,8 @@ typedef struct _skip_list {
  * list elements must have as its final member a skip_elt_t
  */
 cairo_private void
-skip_list_init (skip_list_t		*list,
-		skip_list_compare_t	 compare,
+_cairo_skip_list_init (cairo_skip_list_t		*list,
+		cairo_skip_list_compare_t	 compare,
 		size_t			 elt_size);
 
 
@@ -74,7 +74,7 @@ skip_list_init (skip_list_t		*list,
  * in it. (XXX: currently this simply deletes all elements.)
  */
 cairo_private void
-skip_list_fini (skip_list_t		*list);
+_cairo_skip_list_fini (cairo_skip_list_t		*list);
 
 /* Insert a new element into the list at the correct sort order as
  * determined by compare. If unique is true, then duplicate elements
@@ -82,18 +82,18 @@ skip_list_fini (skip_list_t		*list);
  * Otherwise data will be copied (elt_size bytes from <data> via
  * memcpy) and the new element is returned. */
 cairo_private void *
-skip_list_insert (skip_list_t *list, void *data, int unique);
+_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique);
 
 /* Find an element which compare considers equal to <data> */
 cairo_private void *
-skip_list_find (skip_list_t *list, void *data);
+_cairo_skip_list_find (cairo_skip_list_t *list, void *data);
 
 /* Delete an element which compare considers equal to <data> */
 cairo_private void
-skip_list_delete (skip_list_t *list, void *data);
+_cairo_skip_list_delete (cairo_skip_list_t *list, void *data);
 
 /* Delete the given element from the list. */
 cairo_private void
-skip_list_delete_given (skip_list_t *list, skip_elt_t *given);
+_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given);
 
 #endif
diff --git a/src/cairo-skiplist.c b/src/cairo-skiplist.c
index fbcab31..451ecb0 100644
--- a/src/cairo-skiplist.c
+++ b/src/cairo-skiplist.c
@@ -224,8 +224,8 @@ lfsr_random(void)
  * Initialize an empty skip list
  */
 void
-skip_list_init (skip_list_t		*list,
-		skip_list_compare_t	 compare,
+_cairo_skip_list_init (cairo_skip_list_t		*list,
+		cairo_skip_list_compare_t	 compare,
 		size_t			 elt_size)
 {
     int i;
@@ -243,13 +243,13 @@ skip_list_init (skip_list_t		*list,
 }
 
 void
-skip_list_fini (skip_list_t *list)
+_cairo_skip_list_fini (cairo_skip_list_t *list)
 {
     skip_elt_t *elt;
     int i;
 
     while ((elt = list->chains[0])) {
-	skip_list_delete_given (list, elt);
+	_cairo_skip_list_delete_given (list, elt);
     }
     for (i=0; i<MAX_LEVEL; i++) {
 	elt = list->freelists[i];
@@ -284,7 +284,7 @@ random_level (void)
 }
 
 static void *
-alloc_node_for_level (skip_list_t *list, unsigned level)
+alloc_node_for_level (cairo_skip_list_t *list, unsigned level)
 {
     if (list->freelists[level-1]) {
 	skip_elt_t *elt = list->freelists[level-1];
@@ -295,7 +295,7 @@ alloc_node_for_level (skip_list_t *list,
 }
 
 static void
-free_elt (skip_list_t *list, skip_elt_t *elt)
+free_elt (cairo_skip_list_t *list, skip_elt_t *elt)
 {
     elt->prev = list->freelists[elt->prev_index];
     list->freelists[elt->prev_index] = elt;
@@ -305,7 +305,7 @@ free_elt (skip_list_t *list, skip_elt_t 
  * Insert 'data' into the list
  */
 void *
-skip_list_insert (skip_list_t *list, void *data, int unique)
+_cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique)
 {
     skip_elt_t **update[MAX_LEVEL];
     skip_elt_t *prev[MAX_LEVEL];
@@ -370,7 +370,7 @@ skip_list_insert (skip_list_t *list, voi
 }
 
 void *
-skip_list_find (skip_list_t *list, void *data)
+_cairo_skip_list_find (cairo_skip_list_t *list, void *data)
 {
     int i;
     skip_elt_t **next = list->chains;
@@ -395,7 +395,7 @@ skip_list_find (skip_list_t *list, void 
 }
 
 void
-skip_list_delete (skip_list_t *list, void *data)
+_cairo_skip_list_delete (cairo_skip_list_t *list, void *data)
 {
     skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
     skip_elt_t *elt, **next;
@@ -431,7 +431,7 @@ skip_list_delete (skip_list_t *list, voi
 }
 
 void
-skip_list_delete_given (skip_list_t *list, skip_elt_t *given)
+_cairo_skip_list_delete_given (cairo_skip_list_t *list, skip_elt_t *given)
 {
     skip_elt_t **update[MAX_LEVEL], *prev[MAX_LEVEL];
     skip_elt_t *elt, **next;
diff-tree cd78da36f663b99c67d50dcd692cd7b67677c82a (from 8997b3a023b0edb8877675ce520fbb883d6fa188)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 18:08:37 2007 -0500

    [test-surfaces] Prefix public symbols with _cairo

diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index 561e6df..f726d42 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -134,7 +134,7 @@ create_test_fallback_surface (const char
 			      void			**closure)
 {
     *closure = NULL;
-    return _test_fallback_surface_create (content, width, height);
+    return _cairo_test_fallback_surface_create (content, width, height);
 }
 
 static cairo_surface_t *
@@ -146,7 +146,7 @@ create_test_meta_surface (const char			 
 			  void				**closure)
 {
     *closure = NULL;
-    return _test_meta_surface_create (content, width, height);
+    return _cairo_test_meta_surface_create (content, width, height);
 }
 
 static const cairo_user_data_key_t test_paginated_closure_key;
@@ -179,7 +179,7 @@ create_test_paginated_surface (const cha
 
     tpc->data = xcalloc (tpc->stride * height, 1);
 
-    surface = _test_paginated_surface_create_for_data (tpc->data,
+    surface = _cairo_test_paginated_surface_create_for_data (tpc->data,
 						       tpc->content,
 						       tpc->width,
 						       tpc->height,
diff --git a/src/test-fallback-surface.c b/src/test-fallback-surface.c
index 479c8ef..21ee190 100644
--- a/src/test-fallback-surface.c
+++ b/src/test-fallback-surface.c
@@ -64,10 +64,10 @@ typedef struct _test_fallback_surface {
 
 const cairo_private cairo_surface_backend_t test_fallback_surface_backend;
 
-slim_hidden_proto (_test_fallback_surface_create);
+slim_hidden_proto (_cairo_test_fallback_surface_create);
 
 cairo_surface_t *
-_test_fallback_surface_create (cairo_content_t	content,
+_cairo_test_fallback_surface_create (cairo_content_t	content,
 			       int		width,
 			       int		height)
 {
@@ -91,7 +91,7 @@ _test_fallback_surface_create (cairo_con
 
     return &surface->base;
 }
-slim_hidden_def (_test_fallback_surface_create);
+slim_hidden_def (_cairo_test_fallback_surface_create);
 
 static cairo_surface_t *
 _test_fallback_surface_create_similar (void		*abstract_surface,
@@ -101,7 +101,7 @@ _test_fallback_surface_create_similar (v
 {
     assert (CAIRO_CONTENT_VALID (content));
 
-    return _test_fallback_surface_create (content,
+    return _cairo_test_fallback_surface_create (content,
 					  width, height);
 }
 
diff --git a/src/test-fallback-surface.h b/src/test-fallback-surface.h
index 2560307..744b303 100644
--- a/src/test-fallback-surface.h
+++ b/src/test-fallback-surface.h
@@ -41,7 +41,7 @@
 CAIRO_BEGIN_DECLS
 
 cairo_surface_t *
-_test_fallback_surface_create (cairo_content_t	content,
+_cairo_test_fallback_surface_create (cairo_content_t	content,
 			       int		width,
 			       int		height);
 
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index 5fea766..6c58779 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -68,7 +68,7 @@ static cairo_int_status_t
 _test_meta_surface_show_page (void *abstract_surface);
 
 cairo_surface_t *
-_test_meta_surface_create (cairo_content_t	content,
+_cairo_test_meta_surface_create (cairo_content_t	content,
 			   int		 	width,
 			   int		 	height)
 {
diff --git a/src/test-meta-surface.h b/src/test-meta-surface.h
index 4022ab7..c036bb9 100644
--- a/src/test-meta-surface.h
+++ b/src/test-meta-surface.h
@@ -41,7 +41,7 @@
 CAIRO_BEGIN_DECLS
 
 cairo_surface_t *
-_test_meta_surface_create (cairo_content_t	content,
+_cairo_test_meta_surface_create (cairo_content_t	content,
 			   int			width,
 			   int			height);
 
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index 1950052..d82749f 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -61,7 +61,7 @@ static const cairo_surface_backend_t tes
 static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend;
 
 cairo_surface_t *
-_test_paginated_surface_create_for_data (unsigned char		*data,
+_cairo_test_paginated_surface_create_for_data (unsigned char		*data,
 					 cairo_content_t	 content,
 					 int		 	 width,
 					 int		 	 height,
diff --git a/src/test-paginated-surface.h b/src/test-paginated-surface.h
index df55002..4879cfc 100644
--- a/src/test-paginated-surface.h
+++ b/src/test-paginated-surface.h
@@ -41,7 +41,7 @@
 CAIRO_BEGIN_DECLS
 
 cairo_surface_t *
-_test_paginated_surface_create_for_data (unsigned char		*data,
+_cairo_test_paginated_surface_create_for_data (unsigned char		*data,
 					 cairo_content_t	 content,
 					 int			 width,
 					 int			 height,
diff-tree 8997b3a023b0edb8877675ce520fbb883d6fa188 (from d40126f5aba481e4f4d9582cb5c37478f8ef37e7)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 17:54:00 2007 -0500

    [skiplist] Move static variable out of function
    
    Part of my secrect plan to make cairo compilable with:
    
    	#define static
    
    Useful for some weird debugging purposes.

diff --git a/src/cairo-skiplist.c b/src/cairo-skiplist.c
index 6dc4e3c..fbcab31 100644
--- a/src/cairo-skiplist.c
+++ b/src/cairo-skiplist.c
@@ -34,7 +34,7 @@
 
 /* Four 256 element lookup tables back to back implementing a linear
  * feedback shift register of degree 32. */
-static unsigned const lfsr_lut[1024] = {
+static unsigned const _cairo_lfsr_random_lut[1024] = {
  0x00000000, 0x9a795537, 0xae8bff59, 0x34f2aa6e, 0xc76eab85, 0x5d17feb2,
  0x69e554dc, 0xf39c01eb, 0x14a4023d, 0x8edd570a, 0xba2ffd64, 0x2056a853,
  0xd3caa9b8, 0x49b3fc8f, 0x7d4156e1, 0xe73803d6, 0x2948047a, 0xb331514d,
@@ -207,16 +207,17 @@ static unsigned const lfsr_lut[1024] = {
  0xeaa6b0df, 0x6a98c0b4, 0x184c1316, 0x9872637d, 0x8249a6f7, 0x0277d69c,
  0xb63e2de3, 0x36005d88, 0x2c3b9802, 0xac05e869};
 
+static unsigned _cairo_lfsr_random_state = 0x12345678;
+
 static unsigned
 lfsr_random(void)
 {
-    static unsigned state = 0x12345678;
     unsigned next;
-    next  = lfsr_lut[((state>> 0) & 0xFF) + 0*256];
-    next ^= lfsr_lut[((state>> 8) & 0xFF) + 1*256];
-    next ^= lfsr_lut[((state>>16) & 0xFF) + 2*256];
-    next ^= lfsr_lut[((state>>24) & 0xFF) + 3*256];
-    return state = next;
+    next  = _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 0) & 0xFF) + 0*256];
+    next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>> 8) & 0xFF) + 1*256];
+    next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>16) & 0xFF) + 2*256];
+    next ^= _cairo_lfsr_random_lut[((_cairo_lfsr_random_state>>24) & 0xFF) + 3*256];
+    return _cairo_lfsr_random_state = next;
 }
 
 /*
diff-tree d40126f5aba481e4f4d9582cb5c37478f8ef37e7 (from 01f9ee39feb6ca48b9e07fdec62d8ab1b94ab75d)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 17:47:33 2007 -0500

    [cairo_t] Embed a gstate into cairo_t
    
    So we don't have to malloc the first gstate.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index f2d9280..6175df7 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -43,15 +43,8 @@
 #include "cairo-gstate-private.h"
 
 static cairo_status_t
-_cairo_gstate_init (cairo_gstate_t  *gstate,
-		    cairo_surface_t *target);
-
-static cairo_status_t
 _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
 
-static void
-_cairo_gstate_fini (cairo_gstate_t *gstate);
-
 static cairo_status_t
 _cairo_gstate_ensure_font_face (cairo_gstate_t *gstate);
 
@@ -67,40 +60,7 @@ _cairo_gstate_transform_glyphs_to_backen
                                            int                  num_glyphs,
                                            cairo_glyph_t       *transformed_glyphs);
 
-/**
- * _cairo_gstate_create:
- * @target: a #cairo_surface_t, not NULL
- *
- * Create a new #cairo_gstate_t to draw to target with all graphics
- * state parameters set to defaults. gstate->next will be set to NULL
- * and may be used by the caller to chain #cairo_gstate_t objects
- * together.
- *
- * Return value: a new #cairo_gstate_t or NULL if there is
- * insufficient memory.
- **/
-cairo_gstate_t *
-_cairo_gstate_create (cairo_surface_t *target)
-{
-    cairo_status_t status;
-    cairo_gstate_t *gstate;
-
-    assert (target != NULL);
-
-    gstate = malloc (sizeof (cairo_gstate_t));
-    if (gstate == NULL)
-	return NULL;
-
-    status = _cairo_gstate_init (gstate, target);
-    if (status) {
-	free (gstate);
-	return NULL;
-    }
-
-    return gstate;
-}
-
-static cairo_status_t
+cairo_status_t
 _cairo_gstate_init (cairo_gstate_t  *gstate,
 		    cairo_surface_t *target)
 {
@@ -189,7 +149,7 @@ _cairo_gstate_init_copy (cairo_gstate_t 
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+void
 _cairo_gstate_fini (cairo_gstate_t *gstate)
 {
     _cairo_stroke_style_fini (&gstate->stroke_style);
diff --git a/src/cairo-private.h b/src/cairo-private.h
index c3be6e9..14cc79a 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -47,6 +47,7 @@ struct _cairo {
     cairo_user_data_array_t user_data;
 
     cairo_gstate_t *gstate;
+    cairo_gstate_t  gstate_tail[1];
 
     cairo_path_fixed_t path[1];
 };
diff --git a/src/cairo.c b/src/cairo.c
index b9e2779..21303de 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -49,6 +49,9 @@ static const cairo_t cairo_nil = {
   CAIRO_STATUS_NO_MEMORY,	/* status */
   { 0, 0, 0, NULL },		/* user_data */
   NULL,				/* gstate */
+  {{				/* gstate_tail */
+    0
+  }},
   {{ 				/* path */
     { 0, 0 },			   /* last_move_point */
     { 0, 0 },			   /* current point */
@@ -197,18 +200,15 @@ cairo_create (cairo_surface_t *target)
 
     _cairo_user_data_array_init (&cr->user_data);
 
+    cr->gstate = cr->gstate_tail;
+    _cairo_gstate_init (cr->gstate, target);
+
     _cairo_path_fixed_init (cr->path);
 
     if (target == NULL) {
-	cr->gstate = NULL;
 	_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
-	return cr;
     }
 
-    cr->gstate = _cairo_gstate_create (target);
-    if (cr->gstate == NULL)
-	_cairo_set_error (cr, CAIRO_STATUS_NO_MEMORY);
-
     return cr;
 }
 slim_hidden_def (cairo_create);
@@ -259,13 +259,15 @@ cairo_destroy (cairo_t *cr)
     if (cr->ref_count)
 	return;
 
-    while (cr->gstate) {
+    while (cr->gstate != cr->gstate_tail) {
 	cairo_gstate_t *tmp = cr->gstate;
 	cr->gstate = tmp->next;
 
 	_cairo_gstate_destroy (tmp);
     }
 
+    _cairo_gstate_fini (cr->gstate);
+
     _cairo_path_fixed_fini (cr->path);
 
     _cairo_user_data_array_fini (&cr->user_data);
@@ -399,21 +401,15 @@ cairo_restore (cairo_t *cr)
     if (cr->status)
 	return;
 
+    if (cr->gstate == cr->gstate_tail) {
+	_cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);
+	return;
+    }
+
     top = cr->gstate;
     cr->gstate = top->next;
 
     _cairo_gstate_destroy (top);
-
-    if (cr->gstate == NULL) {
-	_cairo_set_error (cr, CAIRO_STATUS_INVALID_RESTORE);
-	/* We go ahead and create a new gstate here, just for the sake
-	 * of the various cairo_get functions that don't check
-	 * cr->status. This gstate should never be written to, (since
-	 * the cairo functions that do modify anything all check
-	 * status and immediately abort).
-	 */
-	cr->gstate = _cairo_gstate_create ((cairo_surface_t *)&_cairo_surface_nil);
-    }
 }
 slim_hidden_def(cairo_restore);
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 3e54857..c0d3a17 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1308,15 +1308,19 @@ cairo_private int
 _cairo_fixed_integer_ceil (cairo_fixed_t f);
 
 /* cairo_gstate.c */
-cairo_private cairo_gstate_t *
-_cairo_gstate_create (cairo_surface_t *target);
+cairo_private cairo_status_t
+_cairo_gstate_init (cairo_gstate_t  *gstate,
+		    cairo_surface_t *target);
 
 cairo_private void
-_cairo_gstate_destroy (cairo_gstate_t *gstate);
+_cairo_gstate_fini (cairo_gstate_t *gstate);
 
 cairo_private cairo_gstate_t *
 _cairo_gstate_clone (cairo_gstate_t *gstate);
 
+cairo_private void
+_cairo_gstate_destroy (cairo_gstate_t *gstate);
+
 cairo_private cairo_bool_t
 _cairo_gstate_is_redirected (cairo_gstate_t *gstate);
 
diff-tree 01f9ee39feb6ca48b9e07fdec62d8ab1b94ab75d (from bc8987068d1849cf7c16c38132fcc3c8d3b4e12e)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 17:42:23 2007 -0500

    [cairo-clip] Make _cairo_clip_init tolerate NULL target
    
    (needed for upcoming patches.)

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 605589b..efecd89 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -48,7 +48,10 @@ _cairo_clip_path_destroy (cairo_clip_pat
 void
 _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
 {
-    clip->mode = _cairo_surface_get_clip_mode (target);
+    if (target)
+	clip->mode = _cairo_surface_get_clip_mode (target);
+    else
+	clip->mode = CAIRO_CLIP_MODE_MASK;
 
     clip->surface = NULL;
     clip->surface_rect.x = 0;
diff-tree bc8987068d1849cf7c16c38132fcc3c8d3b4e12e (from 74e6a24e98baf70284b65d5f4ed41bdf7449d72d)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 17:15:35 2007 -0500

    [cairo_t] Make path an array of size one
    
    This is more natural since cr->path can be used as if it was a pointer.
    This means, for example, if we move on to making it a pointer, most of
    the code using it does not need any change.  So we get some level of
    encapsulation of implementation details, if you prefer the terminology :).

diff --git a/src/cairo-private.h b/src/cairo-private.h
index ccae0a4..c3be6e9 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -48,7 +48,7 @@ struct _cairo {
 
     cairo_gstate_t *gstate;
 
-    cairo_path_fixed_t path;
+    cairo_path_fixed_t path[1];
 };
 
 #endif /* CAIRO_PRIVATE_H */
diff --git a/src/cairo.c b/src/cairo.c
index 00f1cfa..b9e2779 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -49,13 +49,13 @@ static const cairo_t cairo_nil = {
   CAIRO_STATUS_NO_MEMORY,	/* status */
   { 0, 0, 0, NULL },		/* user_data */
   NULL,				/* gstate */
-  { 				/* path */
+  {{ 				/* path */
     { 0, 0 },			   /* last_move_point */
     { 0, 0 },			   /* current point */
     FALSE,			   /* has_current_point */
     FALSE,			   /* has_curve_to */
-    NULL, {0}			   /* buf_tail, buf_head */
-  }
+    NULL, {{0}}			   /* buf_tail, buf_head */
+  }}
 };
 
 #include <assert.h>
@@ -197,7 +197,7 @@ cairo_create (cairo_surface_t *target)
 
     _cairo_user_data_array_init (&cr->user_data);
 
-    _cairo_path_fixed_init (&cr->path);
+    _cairo_path_fixed_init (cr->path);
 
     if (target == NULL) {
 	cr->gstate = NULL;
@@ -266,7 +266,7 @@ cairo_destroy (cairo_t *cr)
 	_cairo_gstate_destroy (tmp);
     }
 
-    _cairo_path_fixed_fini (&cr->path);
+    _cairo_path_fixed_fini (cr->path);
 
     _cairo_user_data_array_fini (&cr->user_data);
 
@@ -1336,7 +1336,7 @@ cairo_new_path (cairo_t *cr)
     if (cr->status)
 	return;
 
-    _cairo_path_fixed_fini (&cr->path);
+    _cairo_path_fixed_fini (cr->path);
 }
 slim_hidden_def(cairo_new_path);
 
@@ -1361,7 +1361,7 @@ cairo_move_to (cairo_t *cr, double x, do
     x_fixed = _cairo_fixed_from_double (x);
     y_fixed = _cairo_fixed_from_double (y);
 
-    cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed);
+    cr->status = _cairo_path_fixed_move_to (cr->path, x_fixed, y_fixed);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -1391,7 +1391,7 @@ cairo_new_sub_path (cairo_t *cr)
     if (cr->status)
 	return;
 
-    _cairo_path_fixed_new_sub_path (&cr->path);
+    _cairo_path_fixed_new_sub_path (cr->path);
 }
 
 /**
@@ -1419,7 +1419,7 @@ cairo_line_to (cairo_t *cr, double x, do
     x_fixed = _cairo_fixed_from_double (x);
     y_fixed = _cairo_fixed_from_double (y);
 
-    cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed);
+    cr->status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -1470,7 +1470,7 @@ cairo_curve_to (cairo_t *cr,
     x3_fixed = _cairo_fixed_from_double (x3);
     y3_fixed = _cairo_fixed_from_double (y3);
 
-    cr->status = _cairo_path_fixed_curve_to (&cr->path,
+    cr->status = _cairo_path_fixed_curve_to (cr->path,
 					     x1_fixed, y1_fixed,
 					     x2_fixed, y2_fixed,
 					     x3_fixed, y3_fixed);
@@ -1636,7 +1636,7 @@ cairo_rel_move_to (cairo_t *cr, double d
     dx_fixed = _cairo_fixed_from_double (dx);
     dy_fixed = _cairo_fixed_from_double (dy);
 
-    cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed);
+    cr->status = _cairo_path_fixed_rel_move_to (cr->path, dx_fixed, dy_fixed);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -1671,7 +1671,7 @@ cairo_rel_line_to (cairo_t *cr, double d
     dx_fixed = _cairo_fixed_from_double (dx);
     dy_fixed = _cairo_fixed_from_double (dy);
 
-    cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed);
+    cr->status = _cairo_path_fixed_rel_line_to (cr->path, dx_fixed, dy_fixed);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -1729,7 +1729,7 @@ cairo_rel_curve_to (cairo_t *cr,
     dx3_fixed = _cairo_fixed_from_double (dx3);
     dy3_fixed = _cairo_fixed_from_double (dy3);
 
-    cr->status = _cairo_path_fixed_rel_curve_to (&cr->path,
+    cr->status = _cairo_path_fixed_rel_curve_to (cr->path,
 						 dx1_fixed, dy1_fixed,
 						 dx2_fixed, dy2_fixed,
 						 dx3_fixed, dy3_fixed);
@@ -1817,7 +1817,7 @@ cairo_close_path (cairo_t *cr)
     if (cr->status)
 	return;
 
-    cr->status = _cairo_path_fixed_close_path (&cr->path);
+    cr->status = _cairo_path_fixed_close_path (cr->path);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -2007,7 +2007,7 @@ cairo_stroke_preserve (cairo_t *cr)
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path);
+    cr->status = _cairo_gstate_stroke (cr->gstate, cr->path);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -2048,7 +2048,7 @@ cairo_fill_preserve (cairo_t *cr)
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_fill (cr->gstate, &cr->path);
+    cr->status = _cairo_gstate_fill (cr->gstate, cr->path);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -2118,7 +2118,7 @@ cairo_in_stroke (cairo_t *cr, double x, 
 	return 0;
 
     cr->status = _cairo_gstate_in_stroke (cr->gstate,
-					  &cr->path,
+					  cr->path,
 					  x, y, &inside);
     if (cr->status)
 	return 0;
@@ -2150,7 +2150,7 @@ cairo_in_fill (cairo_t *cr, double x, do
 	return 0;
 
     cr->status = _cairo_gstate_in_fill (cr->gstate,
-					&cr->path,
+					cr->path,
 					x, y, &inside);
     if (cr->status) {
 	_cairo_set_error (cr, cr->status);
@@ -2186,7 +2186,7 @@ cairo_stroke_extents (cairo_t *cr,
 	return;
 
     cr->status = _cairo_gstate_stroke_extents (cr->gstate,
-					       &cr->path,
+					       cr->path,
 					       x1, y1, x2, y2);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
@@ -2216,7 +2216,7 @@ cairo_fill_extents (cairo_t *cr,
 	return;
 
     cr->status = _cairo_gstate_fill_extents (cr->gstate,
-					     &cr->path,
+					     cr->path,
 					     x1, y1, x2, y2);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
@@ -2280,7 +2280,7 @@ cairo_clip_preserve (cairo_t *cr)
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_clip (cr->gstate, &cr->path);
+    cr->status = _cairo_gstate_clip (cr->gstate, cr->path);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -2911,7 +2911,7 @@ cairo_text_path  (cairo_t *cr, const cha
 
     cr->status = _cairo_gstate_glyph_path (cr->gstate,
 					   glyphs, num_glyphs,
-					   &cr->path);
+					   cr->path);
 
     if (cr->status)
 	goto BAIL;
@@ -2954,7 +2954,7 @@ cairo_glyph_path (cairo_t *cr, const cai
 
     cr->status = _cairo_gstate_glyph_path (cr->gstate,
 					   glyphs, num_glyphs,
-					   &cr->path);
+					   cr->path);
     if (cr->status)
 	_cairo_set_error (cr, cr->status);
 }
@@ -3030,7 +3030,7 @@ cairo_get_current_point (cairo_t *cr, do
     cairo_fixed_t x_fixed, y_fixed;
     double x, y;
 
-    status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed);
+    status = _cairo_path_fixed_get_current_point (cr->path, &x_fixed, &y_fixed);
     if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
 	x = 0.0;
 	y = 0.0;
@@ -3222,7 +3222,7 @@ cairo_copy_path (cairo_t *cr)
     if (cr->status)
 	return _cairo_path_create_in_error (cr->status);
 
-    return _cairo_path_create (&cr->path, cr->gstate);
+    return _cairo_path_create (cr->path, cr->gstate);
 }
 
 /**
@@ -3264,7 +3264,7 @@ cairo_copy_path_flat (cairo_t *cr)
     if (cr->status)
 	return _cairo_path_create_in_error (cr->status);
 
-    return _cairo_path_create_flat (&cr->path, cr->gstate);
+    return _cairo_path_create_flat (cr->path, cr->gstate);
 }
 
 /**
diff-tree 74e6a24e98baf70284b65d5f4ed41bdf7449d72d (from 6bc543a0ebe4076da31bad4d3ccca4d713948587)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 17:04:43 2007 -0500

    [Quartz] Don't include cairo-private.h

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index bcd688c..1ac4c7b 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -37,7 +37,6 @@
 #include <Carbon/Carbon.h>
 
 #include "cairoint.h"
-#include "cairo-private.h"
 
 #include "cairo-quartz-private.h"
 
diff-tree 6bc543a0ebe4076da31bad4d3ccca4d713948587 (from 85aff353ca38e607599282bc955e467df82fa01b)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 16:58:18 2007 -0500

    [cairo_t] Move gstate pointer before cairo_path_fixed_t for better cache behavior

diff --git a/src/cairo-private.h b/src/cairo-private.h
index 24ab3c1..ccae0a4 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -46,9 +46,9 @@ struct _cairo {
 
     cairo_user_data_array_t user_data;
 
-    cairo_path_fixed_t path;
-
     cairo_gstate_t *gstate;
+
+    cairo_path_fixed_t path;
 };
 
 #endif /* CAIRO_PRIVATE_H */
diff --git a/src/cairo.c b/src/cairo.c
index 46f2c0b..00f1cfa 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -48,14 +48,14 @@ static const cairo_t cairo_nil = {
   CAIRO_REF_COUNT_INVALID,	/* ref_count */
   CAIRO_STATUS_NO_MEMORY,	/* status */
   { 0, 0, 0, NULL },		/* user_data */
+  NULL,				/* gstate */
   { 				/* path */
     { 0, 0 },			   /* last_move_point */
     { 0, 0 },			   /* current point */
     FALSE,			   /* has_current_point */
     FALSE,			   /* has_curve_to */
     NULL, {0}			   /* buf_tail, buf_head */
-  },
-  NULL				/* gstate */
+  }
 };
 
 #include <assert.h>
diff-tree 85aff353ca38e607599282bc955e467df82fa01b (from 1bd073a1a2951bbb09fdab6637baae0172a223f0)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 16:52:09 2007 -0500

    [cairo-path-fixed] Fine-tune size of buffer
    
    such that cairo_path_fixed_t fits in 512 bytes.

diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index 1e73550..65401f3 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -44,7 +44,9 @@ typedef enum cairo_path_op {
 } __attribute__ ((packed)) cairo_path_op_t; /* Don't want 32 bits if we can avoid it. */
 /* XXX Shall we just not use char instead of hoping for __attribute__ working? */
 
-#define CAIRO_PATH_BUF_SIZE 64
+/* make cairo_path_fixed fit a 512 bytes.  about 50 items */
+#define CAIRO_PATH_BUF_SIZE ((512 - 12 * sizeof (void*)) \
+			   / (sizeof (cairo_point_t) + sizeof (cairo_path_op_t)))
 
 typedef struct _cairo_path_buf {
     struct _cairo_path_buf *next, *prev;
@@ -57,13 +59,13 @@ typedef struct _cairo_path_buf {
 } cairo_path_buf_t;
 
 struct _cairo_path_fixed {
-    cairo_path_buf_t  buf_head[1];
-    cairo_path_buf_t *buf_tail;
-
     cairo_point_t last_move_point;
     cairo_point_t current_point;
     unsigned int has_current_point	: 1;
     unsigned int has_curve_to		: 1;
+
+    cairo_path_buf_t *buf_tail;
+    cairo_path_buf_t  buf_head[1];
 };
 
 #endif /* CAIRO_PATH_FIXED_PRIVATE_H */
diff --git a/src/cairo.c b/src/cairo.c
index 4b701ce..46f2c0b 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -49,11 +49,11 @@ static const cairo_t cairo_nil = {
   CAIRO_STATUS_NO_MEMORY,	/* status */
   { 0, 0, 0, NULL },		/* user_data */
   { 				/* path */
-    {0}, NULL,			   /* buf_head, buf_tail */
     { 0, 0 },			   /* last_move_point */
     { 0, 0 },			   /* current point */
     FALSE,			   /* has_current_point */
-    FALSE			   /* has_curve_to */
+    FALSE,			   /* has_curve_to */
+    NULL, {0}			   /* buf_tail, buf_head */
   },
   NULL				/* gstate */
 };
diff-tree 1bd073a1a2951bbb09fdab6637baae0172a223f0 (from 5750d669af24fe1d2707326b9d74dfbb18adf636)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 16:23:49 2007 -0500

    [cairo-path-fixed] Merge op and arg bufs
    
    This means, we have to malloc only one buffer, not two.  Worst case
    is that one always draws curves, which fills the arg (point) buffer
    six times faster than op buffer.  But that's not a big deal since
    each op takes 1 byte, while each point takes 8 bytes.  So op space
    is cheap to spare, so to speak (about 10% memory waste at worst).

diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index 71b2637..b1b7a12 100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -228,19 +228,18 @@ static cairo_int_status_t
 _cairo_path_fixed_fill_rectangle (cairo_path_fixed_t	*path,
 				  cairo_traps_t		*traps)
 {
-    cairo_path_op_buf_t *op = path->op_buf_head;
-    cairo_path_arg_buf_t *arg = path->arg_buf_head;
+    cairo_path_buf_t *buf = path->buf_head;
     int final;
 
     /* Ensure the path has the operators we expect for a rectangular path.
      */
-    if (op == NULL || op->num_ops < 5)
+    if (buf == NULL || buf->num_ops < 5)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (op->op[0] != CAIRO_PATH_OP_MOVE_TO ||
-	op->op[1] != CAIRO_PATH_OP_LINE_TO ||
-	op->op[2] != CAIRO_PATH_OP_LINE_TO ||
-	op->op[3] != CAIRO_PATH_OP_LINE_TO)
+    if (buf->op[0] != CAIRO_PATH_OP_MOVE_TO ||
+	buf->op[1] != CAIRO_PATH_OP_LINE_TO ||
+	buf->op[2] != CAIRO_PATH_OP_LINE_TO ||
+	buf->op[3] != CAIRO_PATH_OP_LINE_TO)
     {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -248,13 +247,13 @@ _cairo_path_fixed_fill_rectangle (cairo_
     /* Now, there are choices. The rectangle might end with a LINE_TO
      * (to the original point), but this isn't required. If it
      * doesn't, then it must end with a CLOSE_PATH. */
-    if (op->op[4] == CAIRO_PATH_OP_LINE_TO) {
-	if (arg->points[4].x != arg->points[0].x ||
-	    arg->points[4].y != arg->points[0].y)
+    if (buf->op[4] == CAIRO_PATH_OP_LINE_TO) {
+	if (buf->points[4].x != buf->points[0].x ||
+	    buf->points[4].y != buf->points[0].y)
 	{
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 	}
-    } else if (op->op[4] != CAIRO_PATH_OP_CLOSE_PATH) {
+    } else if (buf->op[4] != CAIRO_PATH_OP_CLOSE_PATH) {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
 
@@ -262,38 +261,38 @@ _cairo_path_fixed_fill_rectangle (cairo_
      * is fine. But anything more than that means we must return
      * unsupported. */
     final = 5;
-    if (final < op->num_ops &&
-	op->op[final] == CAIRO_PATH_OP_CLOSE_PATH)
+    if (final < buf->num_ops &&
+	buf->op[final] == CAIRO_PATH_OP_CLOSE_PATH)
     {
 	final++;
     }
-    if (final < op->num_ops &&
-	op->op[final] == CAIRO_PATH_OP_MOVE_TO)
+    if (final < buf->num_ops &&
+	buf->op[final] == CAIRO_PATH_OP_MOVE_TO)
     {
 	final++;
     }
-    if (final < op->num_ops)
+    if (final < buf->num_ops)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     /* Now that we've verified the operators, we must ensure that the
      * path coordinates are consistent with a rectangle. There are two
      * choices here. */
-    if (arg->points[0].y == arg->points[1].y &&
-	arg->points[1].x == arg->points[2].x &&
-	arg->points[2].y == arg->points[3].y &&
-	arg->points[3].x == arg->points[0].x)
+    if (buf->points[0].y == buf->points[1].y &&
+	buf->points[1].x == buf->points[2].x &&
+	buf->points[2].y == buf->points[3].y &&
+	buf->points[3].x == buf->points[0].x)
     {
 	return _cairo_traps_tessellate_convex_quad (traps,
-						    arg->points);
+						    buf->points);
     }
 
-    if (arg->points[0].x == arg->points[1].x &&
-	arg->points[1].y == arg->points[2].y &&
-	arg->points[2].x == arg->points[3].x &&
-	arg->points[3].y == arg->points[0].y)
+    if (buf->points[0].x == buf->points[1].x &&
+	buf->points[1].y == buf->points[2].y &&
+	buf->points[2].x == buf->points[3].x &&
+	buf->points[3].y == buf->points[0].y)
     {
 	return _cairo_traps_tessellate_convex_quad (traps,
-						    arg->points);
+						    buf->points);
     }
 
     return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index 93afaf3..1e73550 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -42,29 +42,23 @@ typedef enum cairo_path_op {
     CAIRO_PATH_OP_CURVE_TO = 2,
     CAIRO_PATH_OP_CLOSE_PATH = 3
 } __attribute__ ((packed)) cairo_path_op_t; /* Don't want 32 bits if we can avoid it. */
+/* XXX Shall we just not use char instead of hoping for __attribute__ working? */
 
 #define CAIRO_PATH_BUF_SIZE 64
 
-typedef struct _cairo_path_op_buf {
+typedef struct _cairo_path_buf {
+    struct _cairo_path_buf *next, *prev;
     int num_ops;
-    cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
-
-    struct _cairo_path_op_buf *next, *prev;
-} cairo_path_op_buf_t;
-
-typedef struct _cairo_path_arg_buf {
     int num_points;
+
+    cairo_path_op_t op[CAIRO_PATH_BUF_SIZE];
     cairo_point_t points[CAIRO_PATH_BUF_SIZE];
 
-    struct _cairo_path_arg_buf *next, *prev;
-} cairo_path_arg_buf_t;
+} cairo_path_buf_t;
 
 struct _cairo_path_fixed {
-    cairo_path_op_buf_t  op_buf_head[1];
-    cairo_path_op_buf_t *op_buf_tail;
-
-    cairo_path_arg_buf_t  arg_buf_head[1];
-    cairo_path_arg_buf_t *arg_buf_tail;
+    cairo_path_buf_t  buf_head[1];
+    cairo_path_buf_t *buf_tail;
 
     cairo_point_t last_move_point;
     cairo_point_t current_point;
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index b457910..4845ada 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -48,46 +48,33 @@ _cairo_path_fixed_add (cairo_path_fixed_
 		       int		   num_points);
 
 static void
-_cairo_path_fixed_add_op_buf (cairo_path_fixed_t  *path,
-			      cairo_path_op_buf_t *op_buf);
+_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
+			   cairo_path_buf_t   *buf);
 
-static void
-_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t   *path,
-			       cairo_path_arg_buf_t *arg_buf);
-
-static cairo_path_op_buf_t *
-_cairo_path_op_buf_create (void);
-
-static void
-_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf);
+static cairo_path_buf_t *
+_cairo_path_buf_create (void);
 
 static void
-_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
-			   cairo_path_op_t      op);
-
-static cairo_path_arg_buf_t *
-_cairo_path_arg_buf_create (void);
+_cairo_path_buf_destroy (cairo_path_buf_t *buf);
 
 static void
-_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf);
+_cairo_path_buf_add_op (cairo_path_buf_t *buf,
+			cairo_path_op_t   op);
 
 static void
-_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
-				cairo_point_t	     *points,
-				int		      num_points);
+_cairo_path_buf_add_points (cairo_path_buf_t *buf,
+			    cairo_point_t    *points,
+			    int		      num_points);
 
 void
 _cairo_path_fixed_init (cairo_path_fixed_t *path)
 {
-    path->op_buf_head->num_ops = 0;
-    path->op_buf_head->next = NULL;
-    path->op_buf_head->prev = NULL;
-    path->op_buf_tail = path->op_buf_head;
-
-    path->arg_buf_head->num_points = 0;
-    path->arg_buf_head->next = NULL;
-    path->arg_buf_head->prev = NULL;
-    path->arg_buf_tail = path->arg_buf_head;
+    path->buf_head->next = NULL;
+    path->buf_head->prev = NULL;
+    path->buf_tail = path->buf_head;
+
+    path->buf_head->num_ops = 0;
+    path->buf_head->num_points = 0;
 
     path->current_point.x = 0;
     path->current_point.y = 0;
@@ -100,8 +87,7 @@ cairo_status_t
 _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
 			     cairo_path_fixed_t *other)
 {
-    cairo_path_op_buf_t *op_buf, *other_op_buf;
-    cairo_path_arg_buf_t *arg_buf, *other_arg_buf;
+    cairo_path_buf_t *buf, *other_buf;
 
     _cairo_path_fixed_init (path);
     path->current_point = other->current_point;
@@ -109,36 +95,23 @@ _cairo_path_fixed_init_copy (cairo_path_
     path->has_curve_to = other->has_curve_to;
     path->last_move_point = other->last_move_point;
 
-    path->op_buf_head->num_ops = other->op_buf_head->num_ops;
-    memcpy (path->op_buf_head->op, other->op_buf_head->op,
-	    other->op_buf_head->num_ops * sizeof (cairo_path_op_t));
-    for (other_op_buf = other->op_buf_head->next;
-	 other_op_buf;
-	 other_op_buf = other_op_buf->next)
-    {
-	op_buf = _cairo_path_op_buf_create ();
-	if (op_buf == NULL) {
-	    _cairo_path_fixed_fini (path);
-	    return CAIRO_STATUS_NO_MEMORY;
-	}
-	memcpy (op_buf, other_op_buf, sizeof (cairo_path_op_buf_t));
-	_cairo_path_fixed_add_op_buf (path, op_buf);
-    }
-
-    path->arg_buf_head->num_points = other->arg_buf_head->num_points;
-    memcpy (path->arg_buf_head->points, other->arg_buf_head->points,
-	    other->arg_buf_head->num_points * sizeof (cairo_point_t));
-    for (other_arg_buf = other->arg_buf_head->next;
-	 other_arg_buf;
-	 other_arg_buf = other_arg_buf->next)
+    path->buf_head->num_ops = other->buf_head->num_ops;
+    path->buf_head->num_points = other->buf_head->num_points;
+    memcpy (path->buf_head->op, other->buf_head->op,
+	    other->buf_head->num_ops * sizeof (other->buf_head->op[0]));
+    memcpy (path->buf_head->points, other->buf_head->points,
+	    other->buf_head->num_points * sizeof (other->buf_head->points[0]));
+    for (other_buf = other->buf_head->next;
+	 other_buf;
+	 other_buf = other_buf->next)
     {
-	arg_buf = _cairo_path_arg_buf_create ();
-	if (arg_buf == NULL) {
+	buf = _cairo_path_buf_create ();
+	if (buf == NULL) {
 	    _cairo_path_fixed_fini (path);
 	    return CAIRO_STATUS_NO_MEMORY;
 	}
-	memcpy (arg_buf, other_arg_buf, sizeof (cairo_path_arg_buf_t));
-	_cairo_path_fixed_add_arg_buf (path, arg_buf);
+	memcpy (buf, other_buf, sizeof (cairo_path_buf_t));
+	_cairo_path_fixed_add_buf (path, buf);
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -158,30 +131,19 @@ _cairo_path_fixed_create (void)
 void
 _cairo_path_fixed_fini (cairo_path_fixed_t *path)
 {
-    cairo_path_op_buf_t *op_buf;
-    cairo_path_arg_buf_t *arg_buf;
+    cairo_path_buf_t *buf;
 
-    op_buf = path->op_buf_head->next;
-    while (op_buf) {
-	cairo_path_op_buf_t *this = op_buf;
-	op_buf = op_buf->next;
-	_cairo_path_op_buf_destroy (this);
-    }
-    path->op_buf_head->num_ops = 0;
-    path->op_buf_head->next = NULL;
-    path->op_buf_head->prev = NULL;
-    path->op_buf_tail = path->op_buf_head;
-
-    arg_buf = path->arg_buf_head->next;
-    while (arg_buf) {
-	cairo_path_arg_buf_t *this = arg_buf;
-	arg_buf = arg_buf->next;
-	_cairo_path_arg_buf_destroy (this);
-    }
-    path->arg_buf_head->num_points = 0;
-    path->arg_buf_head->next = NULL;
-    path->arg_buf_head->prev = NULL;
-    path->arg_buf_tail = path->arg_buf_head;
+    buf = path->buf_head->next;
+    while (buf) {
+	cairo_path_buf_t *this = buf;
+	buf = buf->next;
+	_cairo_path_buf_destroy (this);
+    }
+    path->buf_head->next = NULL;
+    path->buf_head->prev = NULL;
+    path->buf_tail = path->buf_head;
+    path->buf_head->num_ops = 0;
+    path->buf_head->num_points = 0;
 
     path->has_current_point = FALSE;
     path->has_curve_to = FALSE;
@@ -207,11 +169,11 @@ _cairo_path_fixed_move_to (cairo_path_fi
 
     /* If the previous op was also a MOVE_TO, then just change its
      * point rather than adding a new op. */
-    if (path->op_buf_tail && path->op_buf_tail->num_ops &&
-	path->op_buf_tail->op[path->op_buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
+    if (path->buf_tail && path->buf_tail->num_ops &&
+	path->buf_tail->op[path->buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
     {
 	cairo_point_t *last_move_to_point;
-	last_move_to_point = &path->arg_buf_tail->points[path->arg_buf_tail->num_points - 1];
+	last_move_to_point = &path->buf_tail->points[path->buf_tail->num_points - 1];
 	*last_move_to_point = point;
     } else {
 	status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
@@ -394,125 +356,77 @@ _cairo_path_fixed_add (cairo_path_fixed_
 		       cairo_point_t	  *points,
 		       int		   num_points)
 {
-    if (path->op_buf_tail == NULL ||
-	path->op_buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE)
-    {
-	cairo_path_op_buf_t *op_buf;
-
-	op_buf = _cairo_path_op_buf_create ();
-	if (op_buf == NULL)
-	    return CAIRO_STATUS_NO_MEMORY;
-
-	_cairo_path_fixed_add_op_buf (path, op_buf);
-    }
-
-    _cairo_path_op_buf_add_op (path->op_buf_tail, op);
-
-    if (path->arg_buf_tail == NULL ||
-	path->arg_buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
+    if (path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
+	path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
     {
-	cairo_path_arg_buf_t *arg_buf;
+	cairo_path_buf_t *buf;
 
-	arg_buf = _cairo_path_arg_buf_create ();
-
-	if (arg_buf == NULL)
+	buf = _cairo_path_buf_create ();
+	if (buf == NULL)
 	    return CAIRO_STATUS_NO_MEMORY;
 
-	_cairo_path_fixed_add_arg_buf (path, arg_buf);
+	_cairo_path_fixed_add_buf (path, buf);
     }
 
-    _cairo_path_arg_buf_add_points (path->arg_buf_tail, points, num_points);
+    _cairo_path_buf_add_op (path->buf_tail, op);
+    _cairo_path_buf_add_points (path->buf_tail, points, num_points);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
-_cairo_path_fixed_add_op_buf (cairo_path_fixed_t  *path,
-			      cairo_path_op_buf_t *op_buf)
+_cairo_path_fixed_add_buf (cairo_path_fixed_t *path,
+			   cairo_path_buf_t   *buf)
 {
-    op_buf->next = NULL;
-    op_buf->prev = path->op_buf_tail;
+    buf->next = NULL;
+    buf->prev = path->buf_tail;
 
-    path->op_buf_tail->next = op_buf;
-    path->op_buf_tail = op_buf;
+    path->buf_tail->next = buf;
+    path->buf_tail = buf;
 }
 
-static void
-_cairo_path_fixed_add_arg_buf (cairo_path_fixed_t   *path,
-			       cairo_path_arg_buf_t *arg_buf)
+static cairo_path_buf_t *
+_cairo_path_buf_create (void)
 {
-    arg_buf->next = NULL;
-    arg_buf->prev = path->arg_buf_tail;
+    cairo_path_buf_t *buf;
 
-    path->arg_buf_tail->next = arg_buf;
-    path->arg_buf_tail = arg_buf;
-}
+    buf = malloc (sizeof (cairo_path_buf_t));
 
-static cairo_path_op_buf_t *
-_cairo_path_op_buf_create (void)
-{
-    cairo_path_op_buf_t *op_buf;
-
-    op_buf = malloc (sizeof (cairo_path_op_buf_t));
-
-    if (op_buf) {
-	op_buf->num_ops = 0;
-	op_buf->next = NULL;
-	op_buf->prev = NULL;
+    if (buf) {
+	buf->next = NULL;
+	buf->prev = NULL;
+	buf->num_ops = 0;
+	buf->num_points = 0;
     }
 
-    return op_buf;
+    return buf;
 }
 
 static void
-_cairo_path_op_buf_destroy (cairo_path_op_buf_t *op_buf)
+_cairo_path_buf_destroy (cairo_path_buf_t *buf)
 {
-    free (op_buf);
+    free (buf);
 }
 
 static void
-_cairo_path_op_buf_add_op (cairo_path_op_buf_t *op_buf,
-			   cairo_path_op_t	op)
-{
-    op_buf->op[op_buf->num_ops++] = op;
-}
-
-static cairo_path_arg_buf_t *
-_cairo_path_arg_buf_create (void)
+_cairo_path_buf_add_op (cairo_path_buf_t *buf,
+			cairo_path_op_t	  op)
 {
-    cairo_path_arg_buf_t *arg_buf;
-
-    arg_buf = malloc (sizeof (cairo_path_arg_buf_t));
-
-    if (arg_buf) {
-	arg_buf->num_points = 0;
-	arg_buf->next = NULL;
-	arg_buf->prev = NULL;
-    }
-
-    return arg_buf;
+    buf->op[buf->num_ops++] = op;
 }
 
 static void
-_cairo_path_arg_buf_destroy (cairo_path_arg_buf_t *arg_buf)
-{
-    free (arg_buf);
-}
-
-static void
-_cairo_path_arg_buf_add_points (cairo_path_arg_buf_t *arg_buf,
-				cairo_point_t	     *points,
-				int		      num_points)
+_cairo_path_buf_add_points (cairo_path_buf_t *buf,
+			    cairo_point_t    *points,
+			    int		      num_points)
 {
     int i;
 
     for (i=0; i < num_points; i++) {
-	arg_buf->points[arg_buf->num_points++] = points[i];
+	buf->points[buf->num_points++] = points[i];
     }
 }
 
-#define CAIRO_PATH_OP_MAX_ARGS 3
-
 static int const num_args[] =
 {
     1, /* cairo_path_move_to */
@@ -531,61 +445,43 @@ _cairo_path_fixed_interpret (cairo_path_
 			     void				*closure)
 {
     cairo_status_t status;
-    int i, arg;
-    cairo_path_op_buf_t *op_buf;
+    cairo_path_buf_t *buf;
     cairo_path_op_t op;
-    cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
-    int buf_i = 0;
-    cairo_point_t point[CAIRO_PATH_OP_MAX_ARGS];
     cairo_bool_t forward = (dir == CAIRO_DIRECTION_FORWARD);
     int step = forward ? 1 : -1;
 
-    for (op_buf = forward ? path->op_buf_head : path->op_buf_tail;
-	 op_buf;
-	 op_buf = forward ? op_buf->next : op_buf->prev)
+    for (buf = forward ? path->buf_head : path->buf_tail;
+	 buf;
+	 buf = forward ? buf->next : buf->prev)
     {
-	int start, stop;
+	cairo_point_t *points;
+	int start, stop, i;
 	if (forward) {
 	    start = 0;
-	    stop = op_buf->num_ops;
+	    stop = buf->num_ops;
+	    points = buf->points;
 	} else {
-	    start = op_buf->num_ops - 1;
+	    start = buf->num_ops - 1;
 	    stop = -1;
+	    points = buf->points + buf->num_points;
 	}
 
 	for (i=start; i != stop; i += step) {
-	    op = op_buf->op[i];
+	    op = buf->op[i];
 
 	    if (! forward) {
-		if (buf_i == 0) {
-		    arg_buf = arg_buf->prev;
-		    buf_i = arg_buf->num_points;
-		}
-		buf_i -= num_args[op];
-	    }
-
-	    for (arg = 0; arg < num_args[op]; arg++) {
-		point[arg] = arg_buf->points[buf_i];
-		buf_i++;
-		if (buf_i >= arg_buf->num_points) {
-		    arg_buf = arg_buf->next;
-		    buf_i = 0;
-		}
-	    }
-
-	    if (! forward) {
-		buf_i -= num_args[op];
+		points -= num_args[op];
 	    }
 
 	    switch (op) {
 	    case CAIRO_PATH_OP_MOVE_TO:
-		status = (*move_to) (closure, &point[0]);
+		status = (*move_to) (closure, &points[0]);
 		break;
 	    case CAIRO_PATH_OP_LINE_TO:
-		status = (*line_to) (closure, &point[0]);
+		status = (*line_to) (closure, &points[0]);
 		break;
 	    case CAIRO_PATH_OP_CURVE_TO:
-		status = (*curve_to) (closure, &point[0], &point[1], &point[2]);
+		status = (*curve_to) (closure, &points[0], &points[1], &points[2]);
 		break;
 	    case CAIRO_PATH_OP_CLOSE_PATH:
 	    default:
@@ -594,6 +490,11 @@ _cairo_path_fixed_interpret (cairo_path_
 	    }
 	    if (status)
 		return status;
+
+	    if (forward) {
+		points += num_args[op];
+	    }
+
 	}
     }
 
@@ -607,31 +508,31 @@ _cairo_path_fixed_offset_and_scale (cair
 				    cairo_fixed_t scalex,
 				    cairo_fixed_t scaley)
 {
-    cairo_path_arg_buf_t *arg_buf = path->arg_buf_head;
+    cairo_path_buf_t *buf = path->buf_head;
     int i;
     cairo_int64_t i64temp;
     cairo_fixed_t fixedtemp;
 
-    while (arg_buf) {
-	 for (i = 0; i < arg_buf->num_points; i++) {
+    while (buf) {
+	 for (i = 0; i < buf->num_points; i++) {
 	     if (scalex == CAIRO_FIXED_ONE) {
-		 arg_buf->points[i].x += offx;
+		 buf->points[i].x += offx;
 	     } else {
-		 fixedtemp = arg_buf->points[i].x + offx;
+		 fixedtemp = buf->points[i].x + offx;
 		 i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex);
-		 arg_buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
+		 buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
 	     }
 
 	     if (scaley == CAIRO_FIXED_ONE) {
-		 arg_buf->points[i].y += offy;
+		 buf->points[i].y += offy;
 	     } else {
-		 fixedtemp = arg_buf->points[i].y + offy;
+		 fixedtemp = buf->points[i].y + offy;
 		 i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley);
-		 arg_buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
+		 buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
 	     }
 	 }
 
-	 arg_buf = arg_buf->next;
+	 buf = buf->next;
     }
 }
 
diff --git a/src/cairo.c b/src/cairo.c
index fdfb042..4b701ce 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -49,8 +49,7 @@ static const cairo_t cairo_nil = {
   CAIRO_STATUS_NO_MEMORY,	/* status */
   { 0, 0, 0, NULL },		/* user_data */
   { 				/* path */
-    {0}, NULL,			   /* op_buf_head, op_buf_tail */
-    {0}, NULL,			   /* arg_buf_head, arg_buf_tail */
+    {0}, NULL,			   /* buf_head, buf_tail */
     { 0, 0 },			   /* last_move_point */
     { 0, 0 },			   /* current point */
     FALSE,			   /* has_current_point */
diff-tree 5750d669af24fe1d2707326b9d74dfbb18adf636 (from 994dd1a134484d7a1ee246906f21f02d916014a8)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Mar 8 14:30:10 2007 -0500

    [cairo-path-fixed] Avoid malloc for small paths
    
    We do this by including an initial op and arg buf in cairo_path_fixed_t,
    so for small paths we don't have to alloc those buffers.
    
    The way this is done is a bit unusual.  Specifically, using an array of
    length one instead of a normal member:
    
    -    cairo_path_op_buf_t *op_buf_head;
    +    cairo_path_op_buf_t  op_buf_head[1];
    
    Has the advantage that read-only use of the buffers does not need any
    change as arrays act like pointers syntactically.  All manipulation code
    however needs to be updates, which the patch supposed does.  Still, there
    seems to be bugs remaining as cairo-perf quits with a Bad X Request error
    with this patch.

diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index 12ca618..93afaf3 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -60,10 +60,10 @@ typedef struct _cairo_path_arg_buf {
 } cairo_path_arg_buf_t;
 
 struct _cairo_path_fixed {
-    cairo_path_op_buf_t *op_buf_head;
+    cairo_path_op_buf_t  op_buf_head[1];
     cairo_path_op_buf_t *op_buf_tail;
 
-    cairo_path_arg_buf_t *arg_buf_head;
+    cairo_path_arg_buf_t  arg_buf_head[1];
     cairo_path_arg_buf_t *arg_buf_tail;
 
     cairo_point_t last_move_point;
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 3505c66..b457910 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -79,11 +79,15 @@ _cairo_path_arg_buf_add_points (cairo_pa
 void
 _cairo_path_fixed_init (cairo_path_fixed_t *path)
 {
-    path->op_buf_head = NULL;
-    path->op_buf_tail = NULL;
-
-    path->arg_buf_head = NULL;
-    path->arg_buf_tail = NULL;
+    path->op_buf_head->num_ops = 0;
+    path->op_buf_head->next = NULL;
+    path->op_buf_head->prev = NULL;
+    path->op_buf_tail = path->op_buf_head;
+
+    path->arg_buf_head->num_points = 0;
+    path->arg_buf_head->next = NULL;
+    path->arg_buf_head->prev = NULL;
+    path->arg_buf_tail = path->arg_buf_head;
 
     path->current_point.x = 0;
     path->current_point.y = 0;
@@ -105,7 +109,10 @@ _cairo_path_fixed_init_copy (cairo_path_
     path->has_curve_to = other->has_curve_to;
     path->last_move_point = other->last_move_point;
 
-    for (other_op_buf = other->op_buf_head;
+    path->op_buf_head->num_ops = other->op_buf_head->num_ops;
+    memcpy (path->op_buf_head->op, other->op_buf_head->op,
+	    other->op_buf_head->num_ops * sizeof (cairo_path_op_t));
+    for (other_op_buf = other->op_buf_head->next;
 	 other_op_buf;
 	 other_op_buf = other_op_buf->next)
     {
@@ -118,7 +125,10 @@ _cairo_path_fixed_init_copy (cairo_path_
 	_cairo_path_fixed_add_op_buf (path, op_buf);
     }
 
-    for (other_arg_buf = other->arg_buf_head;
+    path->arg_buf_head->num_points = other->arg_buf_head->num_points;
+    memcpy (path->arg_buf_head->points, other->arg_buf_head->points,
+	    other->arg_buf_head->num_points * sizeof (cairo_point_t));
+    for (other_arg_buf = other->arg_buf_head->next;
 	 other_arg_buf;
 	 other_arg_buf = other_arg_buf->next)
     {
@@ -151,19 +161,27 @@ _cairo_path_fixed_fini (cairo_path_fixed
     cairo_path_op_buf_t *op_buf;
     cairo_path_arg_buf_t *arg_buf;
 
-    while (path->op_buf_head) {
-	op_buf = path->op_buf_head;
-	path->op_buf_head = op_buf->next;
-	_cairo_path_op_buf_destroy (op_buf);
-    }
-    path->op_buf_tail = NULL;
-
-    while (path->arg_buf_head) {
-	arg_buf = path->arg_buf_head;
-	path->arg_buf_head = arg_buf->next;
-	_cairo_path_arg_buf_destroy (arg_buf);
-    }
-    path->arg_buf_tail = NULL;
+    op_buf = path->op_buf_head->next;
+    while (op_buf) {
+	cairo_path_op_buf_t *this = op_buf;
+	op_buf = op_buf->next;
+	_cairo_path_op_buf_destroy (this);
+    }
+    path->op_buf_head->num_ops = 0;
+    path->op_buf_head->next = NULL;
+    path->op_buf_head->prev = NULL;
+    path->op_buf_tail = path->op_buf_head;
+
+    arg_buf = path->arg_buf_head->next;
+    while (arg_buf) {
+	cairo_path_arg_buf_t *this = arg_buf;
+	arg_buf = arg_buf->next;
+	_cairo_path_arg_buf_destroy (this);
+    }
+    path->arg_buf_head->num_points = 0;
+    path->arg_buf_head->next = NULL;
+    path->arg_buf_head->prev = NULL;
+    path->arg_buf_tail = path->arg_buf_head;
 
     path->has_current_point = FALSE;
     path->has_curve_to = FALSE;
@@ -415,12 +433,7 @@ _cairo_path_fixed_add_op_buf (cairo_path
     op_buf->next = NULL;
     op_buf->prev = path->op_buf_tail;
 
-    if (path->op_buf_tail) {
-	path->op_buf_tail->next = op_buf;
-    } else {
-	path->op_buf_head = op_buf;
-    }
-
+    path->op_buf_tail->next = op_buf;
     path->op_buf_tail = op_buf;
 }
 
@@ -431,12 +444,7 @@ _cairo_path_fixed_add_arg_buf (cairo_pat
     arg_buf->next = NULL;
     arg_buf->prev = path->arg_buf_tail;
 
-    if (path->arg_buf_tail) {
-	path->arg_buf_tail->next = arg_buf;
-    } else {
-	path->arg_buf_head = arg_buf;
-    }
-
+    path->arg_buf_tail->next = arg_buf;
     path->arg_buf_tail = arg_buf;
 }
 
@@ -450,6 +458,7 @@ _cairo_path_op_buf_create (void)
     if (op_buf) {
 	op_buf->num_ops = 0;
 	op_buf->next = NULL;
+	op_buf->prev = NULL;
     }
 
     return op_buf;
@@ -478,6 +487,7 @@ _cairo_path_arg_buf_create (void)
     if (arg_buf) {
 	arg_buf->num_points = 0;
 	arg_buf->next = NULL;
+	arg_buf->prev = NULL;
     }
 
     return arg_buf;
diff --git a/src/cairo.c b/src/cairo.c
index 355fcae..fdfb042 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -49,8 +49,8 @@ static const cairo_t cairo_nil = {
   CAIRO_STATUS_NO_MEMORY,	/* status */
   { 0, 0, 0, NULL },		/* user_data */
   { 				/* path */
-    NULL, NULL,			   /* op_buf_head, op_buf_tail */
-    NULL, NULL,			   /* arg_buf_head, arg_buf_tail */
+    {0}, NULL,			   /* op_buf_head, op_buf_tail */
+    {0}, NULL,			   /* arg_buf_head, arg_buf_tail */
     { 0, 0 },			   /* last_move_point */
     { 0, 0 },			   /* current point */
     FALSE,			   /* has_current_point */
diff-tree 994dd1a134484d7a1ee246906f21f02d916014a8 (from 2894ed19a3acd955a5d0e2f5a231a6f1eee8ac06)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Mar 13 04:56:54 2007 -0400

    [boilerplate] Prefer top_builddir to top_srcdir
    
    This may fix some build problems the Ubuntu guys are experiencing
    with out-of-tree builds.

diff --git a/boilerplate/Makefile.am b/boilerplate/Makefile.am
index 21423e0..340b53d 100644
--- a/boilerplate/Makefile.am
+++ b/boilerplate/Makefile.am
@@ -39,6 +39,6 @@ INCLUDES =					\
 	-D_GNU_SOURCE				\
 	-I$(srcdir)				\
 	-I$(top_srcdir)/pixman/src		\
-	-I$(top_srcdir)/src			\
 	-I$(top_builddir)/src			\
+	-I$(top_srcdir)/src			\
 	$(CAIRO_CFLAGS)
diff-tree 2894ed19a3acd955a5d0e2f5a231a6f1eee8ac06 (from 073d06d4661feb16b15ece5282a5134e3f05d8e7)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Mar 13 04:55:18 2007 -0400

    [directfb,os2] #error if the backend is not compiled in, like others do

diff --git a/src/cairo-directfb.h b/src/cairo-directfb.h
index 845f3de..795a0dc 100644
--- a/src/cairo-directfb.h
+++ b/src/cairo-directfb.h
@@ -48,5 +48,8 @@ cairo_directfb_surface_create (IDirectFB
 
 CAIRO_END_DECLS
 
+#else  /*CAIRO_HAS_DIRECTFB_SURFACE*/
+# error Cairo was not compiled with support for the directfb backend
 #endif /*CAIRO_HAS_DIRECTFB_SURFACE*/
+
 #endif /*CAIRO_DIRECTFB_H*/
diff --git a/src/cairo-os2.h b/src/cairo-os2.h
index 3e1b4aa..6a6c04d 100644
--- a/src/cairo-os2.h
+++ b/src/cairo-os2.h
@@ -194,6 +194,8 @@ cairo_os2_surface_set_manual_window_refr
 cairo_public cairo_bool_t
 cairo_os2_surface_get_manual_window_refresh (cairo_surface_t *surface);
 
+#else  /* CAIRO_HAS_OS2_SURFACE */
+# error Cairo was not compiled with support for the OS/2 backend
 #endif /* CAIRO_HAS_OS2_SURFACE */
 
 CAIRO_END_DECLS


More information about the cairo-commit mailing list