[cairo-commit] 7 commits - src/cairo-bentley-ottmann.c src/cairo-default-context.c src/cairo-script-surface.c src/cairo-tor-scan-converter.c src/cairo-xlib-surface.c util/show-polygon.c util/show-traps.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Aug 12 13:37:37 PDT 2011


 src/cairo-bentley-ottmann.c    |   47 ++-
 src/cairo-default-context.c    |   15 -
 src/cairo-script-surface.c     |    1 
 src/cairo-tor-scan-converter.c |  583 +++++++++++++++--------------------------
 src/cairo-xlib-surface.c       |   35 --
 util/show-polygon.c            |   23 +
 util/show-traps.c              |  100 ++++++-
 7 files changed, 373 insertions(+), 431 deletions(-)

New commits:
commit be1ff2f45fdbc69537e513834fcffa0435e63073
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Aug 12 20:36:13 2011 +0100

    xlib: Set the clip_region for glyphs
    
    Broken (never set!) since the clipping overhaul. We could emulate the
    xcb code to avoid setting it unnecessarily...
    
    Fixes partial-clip-test.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 57b2604..dc3aac8 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -4767,7 +4767,6 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
     composite_operation_t operation;
     cairo_surface_attributes_t attributes;
     cairo_xlib_surface_t *src = NULL;
-    cairo_region_t *clip_region = NULL;
     cairo_xlib_display_t *display;
 
     if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst))
@@ -4807,30 +4806,8 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 
     X_DEBUG ((display->display, "show_glyphs (dst=%x)", (unsigned int) dst->drawable));
 
-    if (clip_region != NULL &&
-	cairo_region_num_rectangles (clip_region) == 1)
-    {
-	cairo_rectangle_int_t glyph_extents;
-	const cairo_rectangle_int_t *clip_extents;
-
-	/* Can we do without the clip?
-	 * Around 50% of the time the clip is redundant (firefox).
-	 */
-	_cairo_scaled_font_glyph_approximate_extents (scaled_font,
-						      glyphs, num_glyphs,
-						      &glyph_extents);
-
-	clip_extents = &clip->path->extents;
-	if (clip_extents->x <= glyph_extents.x &&
-	    clip_extents->y <= glyph_extents.y &&
-	    clip_extents->x + clip_extents->width  >= glyph_extents.x + glyph_extents.width &&
-	    clip_extents->y + clip_extents->height >= glyph_extents.y + glyph_extents.height)
-	{
-	    clip_region = NULL;
-	}
-    }
-
-    status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
+    status = _cairo_xlib_surface_set_clip_region (dst,
+						  _cairo_clip_get_region (clip));
     if (unlikely (status))
         goto BAIL0;
 
@@ -4869,14 +4846,6 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
         if (unlikely (status))
 	    goto BAIL0;
 
-	if (clip != NULL) {
-	    if (! _cairo_rectangle_intersect (&glyph_extents,
-					      _cairo_clip_get_extents (clip)))
-	    {
-		goto BAIL0;
-	    }
-	}
-
         status = _cairo_xlib_surface_acquire_pattern_surface (display,
                                                               dst, src_pattern,
 							      glyph_extents.x,
commit e7fcbed63ac19d894cb94fd0a7589f4580a072f1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 11 18:43:56 2011 +0100

    bo: Perform an initial bucket sort on the start events
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index d7b017a..70d4482 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -1040,9 +1040,6 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t	 *event_queue,
 			    cairo_bo_event_t		**start_events,
 			    int				  num_events)
 {
-    _cairo_bo_event_queue_sort (start_events, num_events);
-    start_events[num_events] = NULL;
-
     event_queue->start_events = start_events;
 
     _cairo_freepool_init (&event_queue->pool,
@@ -1162,6 +1159,7 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t	*sweep_line,
 	}
     } else {
 	sweep_line->head = edge;
+	edge->next = NULL;
     }
 
     sweep_line->current_edge = edge;
@@ -1727,13 +1725,25 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
     cairo_bo_start_event_t *events;
     cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
     cairo_bo_event_t **event_ptrs;
-    int num_events;
-    int i;
+    cairo_bo_start_event_t *stack_event_y[64];
+    cairo_bo_start_event_t **event_y = NULL;
+    int i, num_events, y, ymin, ymax;
 
     num_events = polygon->num_edges;
     if (unlikely (0 == num_events))
 	return CAIRO_STATUS_SUCCESS;
 
+    if (polygon->num_limits) {
+	ymin = _cairo_fixed_integer_floor (polygon->limit.p1.y);
+	ymax = _cairo_fixed_integer_ceil (polygon->limit.p2.y) - ymin;
+
+	if (ymax > 64)
+	    event_y = _cairo_malloc_ab(sizeof (cairo_bo_event_t*), ymax);
+	else
+	    event_y = stack_event_y;
+	memset (event_y, 0, ymax * sizeof(cairo_bo_event_t *));
+    }
+
     events = stack_events;
     event_ptrs = stack_event_ptrs;
     if (num_events > ARRAY_LENGTH (stack_events)) {
@@ -1748,8 +1758,6 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
     }
 
     for (i = 0; i < num_events; i++) {
-	event_ptrs[i] = (cairo_bo_event_t *) &events[i];
-
 	events[i].type = CAIRO_BO_EVENT_TYPE_START;
 	events[i].point.y = polygon->edges[i].top;
 	events[i].point.x =
@@ -1760,8 +1768,30 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
 	events[i].edge.deferred_trap.right = NULL;
 	events[i].edge.prev = NULL;
 	events[i].edge.next = NULL;
+
+	if (event_y) {
+	    y = _cairo_fixed_integer_floor (events[i].point.y) - ymin;
+	    events[i].edge.next = (cairo_bo_edge_t *) event_y[y];
+	    event_y[y] = (cairo_bo_start_event_t *) &events[i];
+	} else
+	    event_ptrs[i] = (cairo_bo_event_t *) &events[i];
     }
 
+    if (event_y) {
+	for (y = i = 0; y < ymax && i < num_events; y++) {
+	    cairo_bo_start_event_t *e;
+	    int j = i;
+	    for (e = event_y[y]; e; e = (cairo_bo_start_event_t *)e->edge.next) 
+		event_ptrs[i++] = (cairo_bo_event_t *) e;
+	    if (i > j + 1)
+		_cairo_bo_event_queue_sort (event_ptrs+j, i-j);
+	}
+	if (event_y != stack_event_y)
+	    free (event_y);
+    } else
+	_cairo_bo_event_queue_sort (event_ptrs, i);
+    event_ptrs[i] = NULL;
+
 #if DEBUG_TRAPS
     dump_edges (events, num_events, "bo-polygon-edges.txt");
 #endif
@@ -1770,8 +1800,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t	 *traps,
      * passes of the Bentley-Ottmann algorithm. It would merely
      * require storing the results of each pass into a temporary
      * cairo_traps_t. */
-    status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs,
-							 num_events,
+    status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs, num_events,
 							 fill_rule, traps,
 							 &intersections);
 #if DEBUG_TRAPS
commit 64bcabfe4bcc5d95ee47e0bc7eed5b4544640279
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 11 23:12:44 2011 +0100

    tor: Micro-optimise
    
    Inline sub-step edges and combine non-zero/even-odd paths by using a
    winding_mask.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c
index c35ec0f..d571f6e 100644
--- a/src/cairo-tor-scan-converter.c
+++ b/src/cairo-tor-scan-converter.c
@@ -97,7 +97,6 @@
 #include "cairo-spans-private.h"
 #include "cairo-error-private.h"
 
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
@@ -124,35 +123,6 @@ typedef cairo_status_t glitter_status_t;
 struct pool;
 struct cell_list;
 
-static glitter_status_t
-blit_with_span_renderer(
-    struct cell_list		*coverages,
-    cairo_span_renderer_t	*span_renderer,
-    struct pool			*span_pool,
-    int				 y,
-    int				 height,
-    int				 xmin,
-    int				 xmax);
-
-static glitter_status_t
-blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height);
-
-#define GLITTER_BLIT_COVERAGES_ARGS \
-	cairo_span_renderer_t *span_renderer, \
-	struct pool *span_pool
-
-#define GLITTER_BLIT_COVERAGES(cells, y, height,xmin, xmax) do {	\
-    blit_with_span_renderer (cells,		\
-			     span_renderer,	\
-			     span_pool,		\
-			     y, height,		\
-			     xmin, xmax);	\
-} while (0)
-
-#define GLITTER_BLIT_COVERAGES_EMPTY(y, height, xmin, xmax) do {		\
-    blit_empty_with_span_renderer (span_renderer, y, height); \
-} while (0)
-
 /*-------------------------------------------------------------------------
  * glitter-paths.h
  */
@@ -212,14 +182,6 @@ glitter_scan_converter_add_edge (glitter_scan_converter_t *converter,
  * rule is used.
  *
  * The scan converter must be reset or destroyed after this call. */
-#ifndef GLITTER_BLIT_COVERAGES_ARGS
-# define GLITTER_BLIT_COVERAGES_ARGS unsigned char *raster_pixels, long raster_stride
-#endif
-I void
-glitter_scan_converter_render(
-    glitter_scan_converter_t *converter,
-    int nonzero_fill,
-    GLITTER_BLIT_COVERAGES_ARGS);
 
 /*-------------------------------------------------------------------------
  * glitter-paths.c: Implementation internal types
@@ -284,7 +246,6 @@ typedef int grid_scaled_y_t;
  * vertices are given in grid scaled coordinates.  The scale factor
  * comes from needing to accurately represent the area 0.5*dx*dy of a
  * triangle with base dx and height dy in grid scaled numbers. */
-typedef int grid_area_t;
 #define GRID_XY (2*GRID_X*GRID_Y) /* Unit area on the grid. */
 
 /* GRID_AREA_TO_ALPHA(area): map [0,GRID_XY] to [0,255]. */
@@ -455,8 +416,8 @@ struct polygon {
 struct cell {
     struct cell		*next;
     int			 x;
-    grid_area_t		 uncovered_area;
-    grid_scaled_y_t	 covered_height;
+    int16_t		 uncovered_area;
+    int16_t		 covered_height;
 };
 
 /* A cell list represents the scan line sparsely as cells ordered by
@@ -467,7 +428,7 @@ struct cell_list {
     struct cell head, tail;
 
     /* Cursor state for iterating through the cell list. */
-    struct cell *cursor;
+    struct cell *cursor, *rewind;
 
     /* Cells in the cell list are owned by the cell list and are
      * allocated from this pool.  */
@@ -501,6 +462,9 @@ struct glitter_scan_converter {
     struct active_list	active[1];
     struct cell_list	coverages[1];
 
+    cairo_half_open_span_t *spans;
+    cairo_half_open_span_t spans_embedded[64];
+
     /* Clip box. */
     grid_scaled_x_t xmin, xmax;
     grid_scaled_y_t ymin, ymax;
@@ -672,13 +636,20 @@ cell_list_rewind (struct cell_list *cells)
     cells->cursor = &cells->head;
 }
 
-/* Rewind the cell list if its cursor has been advanced past x. */
 inline static void
 cell_list_maybe_rewind (struct cell_list *cells, int x)
 {
-    struct cell *tail = cells->cursor;
-    if (tail->x > x)
-	cell_list_rewind (cells);
+    if (x < cells->cursor->x) {
+	cells->cursor = cells->rewind;
+	if (x < cells->cursor->x)
+	    cells->cursor = &cells->head;
+    }
+}
+
+inline static void
+cell_list_set_rewind (struct cell_list *cells)
+{
+    cells->rewind = cells->cursor;
 }
 
 static void
@@ -710,7 +681,7 @@ cell_list_reset (struct cell_list *cells)
     pool_reset (cells->cell_pool.base);
 }
 
-static struct cell *
+inline static struct cell *
 cell_list_alloc (struct cell_list *cells,
 		 struct cell *tail,
 		 int x)
@@ -721,8 +692,8 @@ cell_list_alloc (struct cell_list *cells,
     cell->next = tail->next;
     tail->next = cell;
     cell->x = x;
-    cell->uncovered_area = 0;
-    cell->covered_height = 0;
+    *(uint32_t *)&cell->uncovered_area = 0;
+
     return cell;
 }
 
@@ -736,6 +707,11 @@ cell_list_find (struct cell_list *cells, int x)
 {
     struct cell *tail = cells->cursor;
 
+    assert (x >= tail->x);
+
+    if (tail->x == x)
+	return tail;
+
     while (1) {
 	UNROLL3({
 	    if (tail->next->x > x)
@@ -762,6 +738,9 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2)
 {
     struct cell_pair pair;
 
+    assert (x2 > x1);
+    assert (x1 >= cells->cursor->x);
+
     pair.cell1 = cells->cursor;
     while (1) {
 	UNROLL3({
@@ -770,16 +749,8 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2)
 	    pair.cell1 = pair.cell1->next;
 	});
     }
-    if (pair.cell1->x != x1) {
-	struct cell *cell = pool_alloc (cells->cell_pool.base,
-					sizeof (struct cell));
-	cell->x = x1;
-	cell->uncovered_area = 0;
-	cell->covered_height = 0;
-	cell->next = pair.cell1->next;
-	pair.cell1->next = cell;
-	pair.cell1 = cell;
-    }
+    if (pair.cell1->x != x1)
+	pair.cell1 = cell_list_alloc (cells, pair.cell1, x1);
 
     pair.cell2 = pair.cell1;
     while (1) {
@@ -789,47 +760,25 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2)
 	    pair.cell2 = pair.cell2->next;
 	});
     }
-    if (pair.cell2->x != x2) {
-	struct cell *cell = pool_alloc (cells->cell_pool.base,
-					sizeof (struct cell));
-	cell->uncovered_area = 0;
-	cell->covered_height = 0;
-	cell->x = x2;
-	cell->next = pair.cell2->next;
-	pair.cell2->next = cell;
-	pair.cell2 = cell;
-    }
+    if (pair.cell2->x != x2)
+	pair.cell2 = cell_list_alloc (cells, pair.cell2, x2);
 
     cells->cursor = pair.cell2;
     return pair;
 }
 
-/* Add an unbounded subpixel span covering subpixels >= x to the
- * coverage cells. */
-static void
-cell_list_add_unbounded_subspan (struct cell_list *cells,
-				 grid_scaled_x_t x)
-{
-    struct cell *cell;
-    int ix, fx;
-
-    GRID_X_TO_INT_FRAC(x, ix, fx);
-
-    cell = cell_list_find (cells, ix);
-    cell->uncovered_area += 2*fx;
-    cell->covered_height++;
-}
-
 /* Add a subpixel span covering [x1, x2) to the coverage cells. */
 inline static void
-cell_list_add_subspan(
-    struct cell_list *cells,
-    grid_scaled_x_t x1,
-    grid_scaled_x_t x2)
+cell_list_add_subspan(struct cell_list *cells,
+		      grid_scaled_x_t x1,
+		      grid_scaled_x_t x2)
 {
     int ix1, fx1;
     int ix2, fx2;
 
+    if (x1 == x2)
+	return;
+
     GRID_X_TO_INT_FRAC(x1, ix1, fx1);
     GRID_X_TO_INT_FRAC(x2, ix2, fx2);
 
@@ -864,10 +813,9 @@ cell_list_add_subspan(
  * active list in the order they appear on the list (i.e. with
  * non-decreasing x-coordinate.)  */
 static void
-cell_list_render_edge(
-    struct cell_list *cells,
-    struct edge *edge,
-    int sign)
+cell_list_render_edge(struct cell_list *cells,
+		      struct edge *edge,
+		      int sign)
 {
     grid_scaled_y_t y1, y2, dy;
     grid_scaled_x_t dx;
@@ -1058,8 +1006,6 @@ polygon_add_edge (struct polygon *polygon,
     grid_scaled_y_t ymin = polygon->ymin;
     grid_scaled_y_t ymax = polygon->ymax;
 
-    assert (edge->bottom > edge->top);
-
     if (unlikely (edge->top >= ymax || edge->bottom <= ymin))
 	return;
 
@@ -1255,7 +1201,7 @@ merge_unsorted_edges (struct edge *head, struct edge *unsorted)
 /* Test if the edges on the active list can be safely advanced by a
  * full row without intersections or any edges ending. */
 inline static int
-active_list_can_step_full_row (struct active_list *active)
+can_do_full_row (struct active_list *active)
 {
     const struct edge *e;
     int prev_x = INT_MIN;
@@ -1292,7 +1238,7 @@ active_list_can_step_full_row (struct active_list *active)
 		++x.quo;
 	}
 
-	if (x.quo <= prev_x)
+	if (x.quo < prev_x)
 	    return 0;
 
 	prev_x = x.quo;
@@ -1345,13 +1291,9 @@ active_list_substep_edges(struct active_list *active)
     grid_scaled_x_t prev_x = INT_MIN;
     struct edge *edge = active->head.next;
 
-    do {
-	struct edge *next;
-
-	if (&active->tail == edge)
-	    break;
+    while (edge != &active->tail) {
+	struct edge *next = edge->next;
 
-	next = edge->next;
 	if (--edge->height_left) {
 	    edge->x.quo += edge->dxdy.quo;
 	    edge->x.rem += edge->dxdy.rem;
@@ -1377,167 +1319,118 @@ active_list_substep_edges(struct active_list *active)
 	    edge->prev->next = next;
 	    next->prev = edge->prev;
 	}
-	edge = next;
-    } while (1);
-}
-
-inline static void
-apply_nonzero_fill_rule_for_subrow (struct active_list *active,
-				    struct cell_list *coverages)
-{
-    struct edge *edge = active->head.next;
-
-    cell_list_rewind (coverages);
-
-    while (&active->tail != edge) {
-	int xstart = edge->x.quo;
-	int winding = edge->dir;
-	while (1) {
-	    edge = edge->next;
-	    if (&active->tail == edge)
-		return cell_list_add_unbounded_subspan (coverages, xstart);
-
-	    winding += edge->dir;
-	    if (0 == winding && edge->next->x.quo != edge->x.quo)
-		break;
-	}
 
-	cell_list_add_subspan (coverages, xstart, edge->x.quo);
-	edge = edge->next;
+	edge = next;
     }
 }
 
-static void
-apply_evenodd_fill_rule_for_subrow (struct active_list *active,
-				    struct cell_list *coverages)
+inline static void
+sub_row (struct active_list *active,
+	 struct cell_list *coverages,
+	 unsigned int mask)
 {
     struct edge *edge = active->head.next;
+    int xstart = INT_MIN, prev_x = INT_MIN;
+    int winding = 0;
 
     cell_list_rewind (coverages);
 
     while (&active->tail != edge) {
-	int xstart = edge->x.quo;
+	struct edge *next = edge->next;
+	int xend = edge->x.quo;
 
-	while (1) {
-	    edge = edge->next;
-	    if (&active->tail == edge) {
-		cell_list_add_unbounded_subspan (coverages, xstart);
-		return;
+	if (--edge->height_left) {
+	    edge->x.quo += edge->dxdy.quo;
+	    edge->x.rem += edge->dxdy.rem;
+	    if (edge->x.rem >= 0) {
+		++edge->x.quo;
+		edge->x.rem -= edge->dy;
 	    }
 
-	    if (edge->next->x.quo != edge->x.quo)
-		break;
-
-	    edge = edge->next;
+	    if (edge->x.quo < prev_x) {
+		struct edge *pos = edge->prev;
+		pos->next = next;
+		next->prev = pos;
+		do {
+		    pos = pos->prev;
+		} while (edge->x.quo < pos->x.quo);
+		pos->next->prev = edge;
+		edge->next = pos->next;
+		edge->prev = pos;
+		pos->next = edge;
+	    } else
+		prev_x = edge->x.quo;
+	} else {
+	    edge->prev->next = next;
+	    next->prev = edge->prev;
 	}
 
-	cell_list_add_subspan (coverages, xstart,  edge->x.quo);
-	edge = edge->next;
+	winding += edge->dir;
+	if ((winding & mask) == 0) {
+	    if (next->x.quo != xend) {
+		cell_list_add_subspan (coverages, xstart, xend);
+		xstart = INT_MIN;
+	    }
+	} else if (xstart == INT_MIN)
+	    xstart = xend;
+
+	edge = next;
     }
 }
 
-static void
-apply_nonzero_fill_rule_and_step_edges (struct active_list *active,
-					struct cell_list *coverages)
+inline static void dec (struct edge *e, int h)
 {
-    struct edge *pos = active->head.next;
-
-    while (&active->tail != pos) {
-	struct edge *left_edge = pos;
-	struct edge *right_edge;
-	int winding;
-
-	left_edge->height_left -= GRID_Y;
-	if (! left_edge->height_left) {
-	    left_edge->prev->next = left_edge->next;
-	    left_edge->next->prev = left_edge->prev;
-	}
-
-	winding = left_edge->dir;
-	right_edge = left_edge->next;
-	while (1) {
-	    if (&active->tail == right_edge) {
-		cell_list_render_edge (coverages, left_edge, +1);
-		return;
-	    }
-
-	    right_edge->height_left -= GRID_Y;
-	    if (! right_edge->height_left) {
-		right_edge->prev->next = right_edge->next;
-		right_edge->next->prev = right_edge->prev;
-	    }
-
-	    winding += right_edge->dir;
-	    if (0 == winding && right_edge->next->x.quo != right_edge->x.quo)
-		break;
-
-	    if (! right_edge->vertical) {
-		right_edge->x.quo += right_edge->dxdy_full.quo;
-		right_edge->x.rem += right_edge->dxdy_full.rem;
-		if (right_edge->x.rem >= 0) {
-		    ++right_edge->x.quo;
-		    right_edge->x.rem -= right_edge->dy;
-		}
-	    }
+    e->height_left -= h;
+    if (e->height_left == 0) {
+	e->prev->next = e->next;
+	e->next->prev = e->prev;
+    }
+}
 
-	    right_edge = right_edge->next;
+inline static void full_step (struct edge *e)
+{
+    if (! e->vertical) {
+	e->x.quo += e->dxdy_full.quo;
+	e->x.rem += e->dxdy_full.rem;
+	if (e->x.rem >= 0) {
+	    ++e->x.quo;
+	    e->x.rem -= e->dy;
 	}
-
-	cell_list_render_edge (coverages, left_edge, +1);
-	cell_list_render_edge (coverages, right_edge, -1);
-
-	pos = right_edge->next;
     }
 }
 
 static void
-apply_evenodd_fill_rule_and_step_edges (struct active_list *active,
-					struct cell_list *coverages)
+full_row (struct active_list *active,
+	  struct cell_list *coverages,
+	  unsigned int mask)
 {
-    struct edge *pos = active->head.next;
-
-    while (&active->tail != pos) {
-	struct edge *left_edge = pos;
-	struct edge *right_edge;
+    struct edge *left = active->head.next;
 
-	left_edge->height_left -= GRID_Y;
-	if (! left_edge->height_left) {
-	    left_edge->prev->next = left_edge->next;
-	    left_edge->next->prev = left_edge->prev;
-	}
+    while (&active->tail != left) {
+	struct edge *right;
+	int winding;
 
-	right_edge = left_edge->next;
-	while (1) {
-	    if (&active->tail == right_edge) {
-		cell_list_render_edge (coverages, left_edge, +1);
-		return;
-	    }
+	dec (left, GRID_Y);
 
-	    right_edge->height_left -= GRID_Y;
-	    if (! right_edge->height_left) {
-		right_edge->prev->next = right_edge->next;
-		right_edge->next->prev = right_edge->prev;
-	    }
+	winding = left->dir;
+	right = left->next;
+	do {
+	    dec (right, GRID_Y);
 
-	    if (right_edge->next->x.quo != right_edge->x.quo)
+	    winding += right->dir;
+	    if ((winding & mask) == 0 && right->next->x.quo != right->x.quo)
 		break;
 
-	    if (! right_edge->vertical) {
-		right_edge->x.quo += right_edge->dxdy_full.quo;
-		right_edge->x.rem += right_edge->dxdy_full.rem;
-		if (right_edge->x.rem >= 0) {
-		    ++right_edge->x.quo;
-		    right_edge->x.rem -= right_edge->dy;
-		}
-	    }
+	    full_step (right);
 
-	    right_edge = right_edge->next;
-	}
+	    right = right->next;
+	} while (1);
 
-	cell_list_render_edge (coverages, left_edge, +1);
-	cell_list_render_edge (coverages, right_edge, -1);
+	cell_list_set_rewind (coverages);
+	cell_list_render_edge (coverages, left, +1);
+	cell_list_render_edge (coverages, right, -1);
 
-	pos = right_edge->next;
+	left = right->next;
     }
 }
 
@@ -1554,14 +1447,18 @@ _glitter_scan_converter_init(glitter_scan_converter_t *converter, jmp_buf *jmp)
 }
 
 static void
-_glitter_scan_converter_fini(glitter_scan_converter_t *converter)
+_glitter_scan_converter_fini(glitter_scan_converter_t *self)
 {
-    polygon_fini(converter->polygon);
-    cell_list_fini(converter->coverages);
-    converter->xmin=0;
-    converter->ymin=0;
-    converter->xmax=0;
-    converter->ymax=0;
+    if (self->spans != self->spans_embedded)
+	free (self->spans);
+
+    polygon_fini(self->polygon);
+    cell_list_fini(self->coverages);
+
+    self->xmin=0;
+    self->ymin=0;
+    self->xmax=0;
+    self->ymax=0;
 }
 
 static grid_scaled_t
@@ -1593,6 +1490,14 @@ glitter_scan_converter_reset(
     converter->xmin = 0; converter->xmax = 0;
     converter->ymin = 0; converter->ymax = 0;
 
+    if (xmax - xmin > ARRAY_LENGTH(converter->spans_embedded)) {
+	converter->spans = _cairo_malloc_ab (xmax - xmin,
+					     sizeof (cairo_half_open_span_t));
+	if (unlikely (converter->spans == NULL))
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    } else
+	converter->spans = converter->spans_embedded;
+
     xmin = int_to_grid_scaled_x(xmin);
     ymin = int_to_grid_scaled_y(ymin);
     xmax = int_to_grid_scaled_x(xmax);
@@ -1688,11 +1593,79 @@ step_edges (struct active_list *active, int count)
     }
 }
 
+static glitter_status_t
+blit (struct cell_list *cells,
+      cairo_span_renderer_t *renderer,
+      cairo_half_open_span_t *spans,
+      int y, int height,
+      int xmin, int xmax)
+{
+    struct cell *cell = cells->head.next;
+    int prev_x = xmin, last_x = -1;
+    int16_t cover = 0, last_cover = 0;
+    unsigned num_spans;
+
+    if (cell == &cells->tail)
+	return CAIRO_STATUS_SUCCESS;
+
+    /* Skip cells to the left of the clip region. */
+    while (cell->x < xmin) {
+	cover += cell->covered_height;
+	cell = cell->next;
+    }
+    cover *= GRID_X*2;
+
+    /* Form the spans from the coverages and areas. */
+    num_spans = 0;
+    for (; cell->x < xmax; cell = cell->next) {
+	int x = cell->x;
+	int16_t area;
+
+	if (x > prev_x && cover != last_cover) {
+	    spans[num_spans].x = prev_x;
+	    spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
+	    last_cover = cover;
+	    last_x = prev_x;
+	    ++num_spans;
+	}
+
+	cover += cell->covered_height*GRID_X*2;
+	area = cover - cell->uncovered_area;
+
+	if (area != last_cover) {
+	    spans[num_spans].x = x;
+	    spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
+	    last_cover = area;
+	    last_x = x;
+	    ++num_spans;
+	}
+
+	prev_x = x+1;
+    }
+
+    if (prev_x <= xmax && cover != last_cover) {
+	spans[num_spans].x = prev_x;
+	spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
+	last_cover = cover;
+	last_x = prev_x;
+	++num_spans;
+    }
+
+    if (last_x < xmax && last_cover) {
+	spans[num_spans].x = xmax;
+	spans[num_spans].coverage = 0;
+	++num_spans;
+    }
+
+    /* Dump them into the renderer. */
+    return renderer->render_rows (renderer, y, height, spans, num_spans);
+}
+
+
 I void
-glitter_scan_converter_render(
-    glitter_scan_converter_t *converter,
-    int nonzero_fill,
-    GLITTER_BLIT_COVERAGES_ARGS)
+glitter_scan_converter_render(glitter_scan_converter_t *converter,
+			      unsigned int winding_mask,
+			      cairo_span_renderer_t *renderer)
 {
     int i, j;
     int ymax_i = converter->ymax / GRID_Y;
@@ -1714,7 +1687,7 @@ glitter_scan_converter_render(
 
     /* Render each pixel row. */
     for (i = 0; i < h; i = j) {
-	int do_full_step = 0;
+	int do_full_row = 0;
 
 	j = i + 1;
 
@@ -1730,15 +1703,12 @@ glitter_scan_converter_render(
 		continue;
 	    }
 
-	    do_full_step = active_list_can_step_full_row (active);
+	    do_full_row = can_do_full_row (active);
 	}
 
-	if (do_full_step) {
+	if (do_full_row) {
 	    /* Step by a full pixel row's worth. */
-	    if (nonzero_fill)
-		apply_nonzero_fill_rule_and_step_edges (active, coverages);
-	    else
-		apply_evenodd_fill_rule_and_step_edges (active, coverages);
+	    full_row (active, coverages, winding_mask);
 
 	    if (active->is_vertical) {
 		while (j < h &&
@@ -1766,16 +1736,12 @@ glitter_scan_converter_render(
 		    buckets[sub] = NULL;
 		}
 
-		if (nonzero_fill)
-		    apply_nonzero_fill_rule_for_subrow (active, coverages);
-		else
-		    apply_evenodd_fill_rule_for_subrow (active, coverages);
-
-		active_list_substep_edges(active);
+		sub_row (active, coverages, winding_mask);
 	    }
 	}
 
-	GLITTER_BLIT_COVERAGES(coverages, i+ymin_i, j-i, xmin_i, xmax_i);
+	blit (coverages, renderer, converter->spans,
+	      i+ymin_i, j-i, xmin_i, xmax_i);
 	cell_list_reset (coverages);
 
 	active->min_height -= GRID_Y;
@@ -1785,100 +1751,6 @@ glitter_scan_converter_render(
     GLITTER_BLIT_COVERAGES_END;
 }
 
-/*-------------------------------------------------------------------------
- * cairo specific implementation: the coverage blitter and
- * scan converter subclass. */
-
-static glitter_status_t
-blit_with_span_renderer (struct cell_list *cells,
-			 cairo_span_renderer_t *renderer,
-			 struct pool *span_pool,
-			 int y, int height,
-			 int xmin, int xmax)
-{
-    struct cell *cell = cells->head.next;
-    int prev_x = xmin, last_x = -1;
-    int cover = 0, last_cover = 0;
-    cairo_half_open_span_t *spans;
-    unsigned num_spans;
-
-    if (cell == &cells->tail)
-	return blit_empty_with_span_renderer (renderer, y, height);
-
-    /* Skip cells to the left of the clip region. */
-    while (cell->x < xmin) {
-	cover += cell->covered_height;
-	cell = cell->next;
-    }
-    cover *= GRID_X*2;
-
-    /* Count number of cells remaining. */
-    {
-	struct cell *next = cell;
-	num_spans = 2;
-	while (next->x < xmax) {
-	    next = next->next;
-	    ++num_spans;
-	}
-	num_spans = 2*num_spans;
-    }
-
-    /* Allocate enough spans for the row. */
-    pool_reset (span_pool);
-    spans = pool_alloc (span_pool, sizeof(spans[0])*num_spans);
-    num_spans = 0;
-
-    /* Form the spans from the coverages and areas. */
-    for (; cell->x < xmax; cell = cell->next) {
-	int x = cell->x;
-	int area;
-
-	if (x > prev_x && cover != last_cover) {
-	    spans[num_spans].x = prev_x;
-	    spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
-	    last_cover = cover;
-	    last_x = prev_x;
-	    ++num_spans;
-	}
-
-	cover += cell->covered_height*GRID_X*2;
-	area = cover - cell->uncovered_area;
-
-	if (area != last_cover) {
-	    spans[num_spans].x = x;
-	    spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
-	    last_cover = area;
-	    last_x = x;
-	    ++num_spans;
-	}
-
-	prev_x = x+1;
-    }
-
-    if (prev_x <= xmax && cover != last_cover) {
-	spans[num_spans].x = prev_x;
-	spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
-	last_cover = cover;
-	last_x = prev_x;
-	++num_spans;
-    }
-
-    if (last_x < xmax && last_cover) {
-	spans[num_spans].x = xmax;
-	spans[num_spans].coverage = 0;
-	++num_spans;
-    }
-
-    /* Dump them into the renderer. */
-    return renderer->render_rows (renderer, y, height, spans, num_spans);
-}
-
-static glitter_status_t
-blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height)
-{
-    return renderer->render_rows (renderer, y, height, NULL, 0);
-}
-
 struct _cairo_tor_scan_converter {
     cairo_scan_converter_t base;
 
@@ -1886,11 +1758,6 @@ struct _cairo_tor_scan_converter {
     cairo_fill_rule_t fill_rule;
 
     jmp_buf jmp;
-
-    struct {
-	struct pool base[1];
-	cairo_half_open_span_t embedded[32];
-    } span_pool;
 };
 
 typedef struct _cairo_tor_scan_converter cairo_tor_scan_converter_t;
@@ -1903,7 +1770,6 @@ _cairo_tor_scan_converter_destroy (void *converter)
 	return;
     }
     _glitter_scan_converter_fini (self->converter);
-    pool_fini (self->span_pool.base);
     free(self);
 }
 
@@ -1952,9 +1818,8 @@ _cairo_tor_scan_converter_generate (void			*converter,
 	return _cairo_scan_converter_set_error (self, _cairo_error (status));
 
     glitter_scan_converter_render (self->converter,
-				   self->fill_rule == CAIRO_FILL_RULE_WINDING,
-				   renderer,
-				   self->span_pool.base);
+				   self->fill_rule == CAIRO_FILL_RULE_WINDING ? ~0 : 1,
+				   renderer);
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -1979,10 +1844,6 @@ _cairo_tor_scan_converter_create (int			xmin,
     self->base.add_polygon = _cairo_tor_scan_converter_add_polygon;
     self->base.generate = _cairo_tor_scan_converter_generate;
 
-    pool_init (self->span_pool.base, &self->jmp,
-	       250 * sizeof(self->span_pool.embedded[0]),
-	       sizeof(self->span_pool.embedded));
-
     _glitter_scan_converter_init (self->converter, &self->jmp);
     status = glitter_scan_converter_reset (self->converter,
 					   xmin, ymin, xmax, ymax);
commit 02da8c7efb007d046f95456734968d7e9335a7af
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 11 13:46:16 2011 +0100

    default-context: Tidy push-group
    
    Fix a couple of instances of the older style clipping code.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-default-context.c b/src/cairo-default-context.c
index 4124632..017eb7b 100644
--- a/src/cairo-default-context.c
+++ b/src/cairo-default-context.c
@@ -141,18 +141,18 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
 	    goto bail;
     } else {
 	cairo_surface_t *parent_surface;
-	const cairo_rectangle_int_t *clip_extents;
 	cairo_rectangle_int_t extents;
-        cairo_matrix_t matrix;
 	cairo_bool_t is_empty;
 
 	parent_surface = _cairo_gstate_get_target (cr->gstate);
 
 	/* Get the extents that we'll use in creating our new group surface */
 	is_empty = _cairo_surface_get_extents (parent_surface, &extents);
-	clip_extents = _cairo_clip_get_extents (_cairo_gstate_get_clip (cr->gstate));
-	if (clip_extents != NULL)
-	    is_empty = _cairo_rectangle_intersect (&extents, clip_extents);
+	if (clip)
+	    is_empty = _cairo_rectangle_intersect (&extents,
+						   _cairo_clip_get_extents (clip));
+
+	/* XXX unbounded surface creation */
 
 	group_surface = _cairo_surface_create_similar_solid (parent_surface,
 							     content,
@@ -175,8 +175,9 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
 
 	/* If we have a current path, we need to adjust it to compensate for
 	 * the device offset just applied. */
-        cairo_matrix_init_translate (&matrix, -extents.x, -extents.y);
-	_cairo_path_fixed_transform (cr->path, &matrix);
+	_cairo_path_fixed_translate (cr->path,
+				     _cairo_fixed_from_int (-extents.x),
+				     _cairo_fixed_from_int (-extents.y));
     }
 
     /* create a new gstate for the redirect */
commit a3d2d5b42b769241e888a34c3edd015619560431
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Aug 12 19:02:35 2011 +0100

    script: Remove reference to image-surface-private
    
    That header doesn't exist yet.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 0f7252a..b6e0098 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -50,7 +50,6 @@
 #include "cairo-default-context-private.h"
 #include "cairo-device-private.h"
 #include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
 #include "cairo-list-private.h"
 #include "cairo-recording-surface-private.h"
 #include "cairo-output-stream-private.h"
commit e7bd4c93e320325b09e6a2cc8c3d9547c7b0d1f2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Aug 12 20:15:19 2011 +0100

    util/show-traps: Cache the rendering of the traps+edges
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/util/show-traps.c b/util/show-traps.c
index 9a99aba..f46c8b0 100644
--- a/util/show-traps.c
+++ b/util/show-traps.c
@@ -47,6 +47,9 @@ typedef struct _TrapView {
     struct _TrapView *group_next;
     struct _TrapView *group_prev;
 
+    cairo_surface_t *pixmap;
+    int pixmap_width, pixmap_height;
+
     traps_t *traps_list;
     traps_t *current_traps;
 
@@ -95,30 +98,27 @@ _compute_intersection_point (const line_t *line,
     p->x = _compute_intersection_x_for_y (line, p->y = y);
 }
 
-static void
-trap_view_draw (TrapView *self, cairo_t *cr)
+static cairo_surface_t *
+pixmap_create (TrapView *self, cairo_surface_t *target)
 {
+    cairo_surface_t *surface = cairo_surface_create_similar (target, CAIRO_CONTENT_COLOR,
+							     self->widget.allocation.width,
+							     self->widget.allocation.height);
+    cairo_t *cr;
     traps_t *traps;
     edges_t *edges;
     gdouble sf_x, sf_y, sf;
     gdouble mid, dim;
-    gdouble x0, x1,  y0, y1;
+    gdouble x0,  y0;
     double dash[2] = {8, 8};
     double dots[2] = {0., 1.};
     int n;
     box_t extents;
     point_t p;
 
-    cairo_save (cr);
-    cairo_save (cr);
-    cairo_set_source_rgb (cr, 1, 1, 1);
-    cairo_paint (cr);
-    cairo_restore (cr);
-
     traps = self->current_traps;
     if (traps == NULL)
-	return;
-
+	return surface;
     edges = self->current_edges;
 
     extents = traps->extents;
@@ -146,11 +146,13 @@ trap_view_draw (TrapView *self, cairo_t *cr)
     mid = (extents.p2.x + extents.p1.x) / 2.;
     dim = sf_x / sf * (extents.p2.x - extents.p1.x) / 2. * 1.25;
     x0 = mid - dim;
-    x1 = mid + dim;
     mid = (extents.p2.y + extents.p1.y) / 2.;
     dim = sf_y / sf * (extents.p2.y - extents.p1.y) / 2. * 1.25;
     y0 = mid - dim;
-    y1 = mid + dim;
+
+    cr = cairo_create (surface);
+    cairo_set_source_rgb (cr, 1, 1, 1);
+    cairo_paint (cr);
 
     cairo_save (cr);
     cairo_scale (cr, sf, sf);
@@ -353,12 +355,80 @@ trap_view_draw (TrapView *self, cairo_t *cr)
 	cairo_restore (cr);
     }
 
+    cairo_destroy (cr);
+    return surface;
+}
+
+static void
+trap_view_draw (TrapView *self, cairo_t *cr)
+{
+    traps_t *traps;
+    edges_t *edges;
+    gdouble sf_x, sf_y, sf;
+    gdouble mid, dim;
+    gdouble x0, y0;
+    double dash[2] = {8, 8};
+    int n;
+    box_t extents;
+    point_t p;
+
+    if (self->pixmap_width != self->widget.allocation.width ||
+	self->pixmap_height != self->widget.allocation.height)
+    {
+	cairo_surface_destroy (self->pixmap);
+	self->pixmap = pixmap_create (self, cairo_get_target (cr));
+	self->pixmap_width = self->widget.allocation.width;
+	self->pixmap_height = self->widget.allocation.height;
+    }
+
+    cairo_save (cr);
+    cairo_set_source_surface (cr, self->pixmap, 0, 0);
+    cairo_paint (cr);
+    cairo_restore (cr);
+
+    traps = self->current_traps;
+    if (traps == NULL)
+	return;
+
+    extents = traps->extents;
+    edges = self->current_edges;
+    if (edges != NULL) {
+	if (edges->extents.p1.x < extents.p1.x)
+	    extents.p1.x = edges->extents.p1.x;
+	if (edges->extents.p1.y < extents.p1.y)
+	    extents.p1.y = edges->extents.p1.y;
+	if (edges->extents.p2.x > extents.p2.x)
+	    extents.p2.x = edges->extents.p2.x;
+	if (edges->extents.p2.y > extents.p2.y)
+	    extents.p2.y = edges->extents.p2.y;
+    }
+
+    mid = (extents.p2.x + extents.p1.x) / 2.;
+    dim = (extents.p2.x - extents.p1.x) / 2. * 1.25;
+    sf_x = self->widget.allocation.width / dim / 2;
+
+    mid = (extents.p2.y + extents.p1.y) / 2.;
+    dim = (extents.p2.y - extents.p1.y) / 2. * 1.25;
+    sf_y = self->widget.allocation.height / dim / 2;
+
+    sf = MIN (sf_x, sf_y);
+
+    mid = (extents.p2.x + extents.p1.x) / 2.;
+    dim = sf_x / sf * (extents.p2.x - extents.p1.x) / 2. * 1.25;
+    x0 = mid - dim;
+    mid = (extents.p2.y + extents.p1.y) / 2.;
+    dim = sf_y / sf * (extents.p2.y - extents.p1.y) / 2. * 1.25;
+    y0 = mid - dim;
+
+    cairo_save (cr);
+
     /* draw a zoom view of the area around the mouse */
     {
-	cairo_save (cr);
 	double zoom = self->mag_zoom;
 	int size = self->mag_size;
 
+	cairo_save (cr);
+
 	/* bottom right */
 	cairo_rectangle (cr, self->mag_x, self->mag_y, size, size);
 	cairo_stroke_preserve (cr);
@@ -645,6 +715,7 @@ trap_view_advance (TrapView *self)
 	self->current_traps = self->current_traps->prev;
     if (self->current_edges && self->current_edges->prev)
 	self->current_edges = self->current_edges->prev;
+    self->pixmap_width = self->pixmap_height = 0;
     gtk_widget_queue_draw (&self->widget);
 }
 
@@ -655,6 +726,7 @@ trap_view_back (TrapView *self)
 	self->current_traps = self->current_traps->next;
     if (self->current_edges && self->current_edges->next)
 	self->current_edges = self->current_edges->next;
+    self->pixmap_width = self->pixmap_height = 0;
     gtk_widget_queue_draw (&self->widget);
 }
 
commit b8e8c4cf9a10834923d7185d379d6457687912a1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 11 23:12:32 2011 +0100

    util/show-polygon: Show end-points
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/util/show-polygon.c b/util/show-polygon.c
index 7c9031c..5549cf2 100644
--- a/util/show-polygon.c
+++ b/util/show-polygon.c
@@ -49,7 +49,7 @@ typedef struct _PolygonViewClass {
 
 G_DEFINE_TYPE (PolygonView, polygon_view, GTK_TYPE_WIDGET)
 
-static void draw_edges (cairo_t *cr, polygon_t *p, int dir)
+static void draw_edges (cairo_t *cr, polygon_t *p, gdouble sf, int dir)
 {
     int n;
 
@@ -59,6 +59,17 @@ static void draw_edges (cairo_t *cr, polygon_t *p, int dir)
 	if (e->dir != dir)
 	    continue;
 
+	cairo_arc (cr, e->p1.x, e->p1.y, 3/sf, 0, 2*M_PI);
+	cairo_arc (cr, e->p2.x, e->p2.y, 3/sf, 0, 2*M_PI);
+	cairo_fill (cr);
+    }
+
+    for (n = 0; n < p->num_edges; n++) {
+	const edge_t *e = &p->edges[n];
+
+	if (e->dir != dir)
+	    continue;
+
 	cairo_move_to (cr, e->p1.x, e->p1.y);
 	cairo_line_to (cr, e->p2.x, e->p2.y);
     }
@@ -69,13 +80,13 @@ static void draw_edges (cairo_t *cr, polygon_t *p, int dir)
     } cairo_restore (cr);
 }
 
-static void draw_polygon (cairo_t *cr, polygon_t *p)
+static void draw_polygon (cairo_t *cr, polygon_t *p, gdouble sf)
 {
     cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
-    draw_edges (cr, p, -1);
+    draw_edges (cr, p, sf, -1);
 
     cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
-    draw_edges (cr, p, +1);
+    draw_edges (cr, p, sf, +1);
 }
 
 static cairo_surface_t *
@@ -127,7 +138,7 @@ pixmap_create (PolygonView *self, cairo_surface_t *target)
 	    if (polygon->num_edges == 0)
 		continue;
 
-	    draw_polygon (cr, polygon);
+	    draw_polygon (cr, polygon, sf);
 	}
     } cairo_restore (cr);
 
@@ -211,7 +222,7 @@ polygon_view_draw (PolygonView *self, cairo_t *cr)
 		    if (polygon->num_edges == 0)
 			continue;
 
-		    draw_polygon (cr, polygon);
+		    draw_polygon (cr, polygon, zoom);
 		}
 	    } cairo_restore (cr);
 


More information about the cairo-commit mailing list