1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/clip-invariant.patch Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1255 @@ 1.4 +diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c 1.5 +index 2acc8b5..019249e 100644 1.6 +--- a/src/cairo-gl-surface.c 1.7 ++++ b/src/cairo-gl-surface.c 1.8 +@@ -2012,13 +2012,14 @@ typedef struct _cairo_gl_surface_span_renderer { 1.9 + 1.10 + cairo_gl_composite_setup_t setup; 1.11 + 1.12 ++ int xmin, xmax; 1.13 ++ 1.14 + cairo_operator_t op; 1.15 + cairo_antialias_t antialias; 1.16 + 1.17 + cairo_gl_surface_t *dst; 1.18 + cairo_region_t *clip; 1.19 + 1.20 +- cairo_composite_rectangles_t composite_rectangles; 1.21 + GLuint vbo; 1.22 + void *vbo_base; 1.23 + unsigned int vbo_size; 1.24 +@@ -2049,11 +2050,11 @@ _cairo_gl_span_renderer_flush (cairo_gl_surface_span_renderer_t *renderer) 1.25 + cairo_region_get_rectangle (renderer->clip, i, &rect); 1.26 + 1.27 + glScissor (rect.x, rect.y, rect.width, rect.height); 1.28 +- glDrawArrays (GL_LINES, 0, count); 1.29 ++ glDrawArrays (GL_QUADS, 0, count); 1.30 + } 1.31 + glDisable (GL_SCISSOR_TEST); 1.32 + } else { 1.33 +- glDrawArrays (GL_LINES, 0, count); 1.34 ++ glDrawArrays (GL_QUADS, 0, count); 1.35 + } 1.36 + } 1.37 + 1.38 +@@ -2134,72 +2135,87 @@ _cairo_gl_emit_span_vertex (cairo_gl_surface_span_renderer_t *renderer, 1.39 + 1.40 + static void 1.41 + _cairo_gl_emit_span (cairo_gl_surface_span_renderer_t *renderer, 1.42 +- int x1, int x2, int y, uint8_t alpha) 1.43 ++ int x, int y1, int y2, 1.44 ++ uint8_t alpha) 1.45 + { 1.46 + float *vertices = _cairo_gl_span_renderer_get_vbo (renderer, 2); 1.47 + 1.48 +- _cairo_gl_emit_span_vertex (renderer, x1, y, alpha, vertices); 1.49 +- _cairo_gl_emit_span_vertex (renderer, x2, y, alpha, 1.50 ++ _cairo_gl_emit_span_vertex (renderer, x, y1, alpha, vertices); 1.51 ++ _cairo_gl_emit_span_vertex (renderer, x, y2, alpha, 1.52 + vertices + renderer->vertex_size / 4); 1.53 + } 1.54 + 1.55 +-/* Emits the contents of the span renderer rows as GL_LINES with the span's 1.56 +- * alpha. 1.57 +- * 1.58 +- * Unlike the image surface, which is compositing into a temporary, we emit 1.59 +- * coverage even for alpha == 0, in case we're using an unbounded operator. 1.60 +- * But it means we avoid having to do the fixup. 1.61 +- */ 1.62 ++static void 1.63 ++_cairo_gl_emit_rectangle (cairo_gl_surface_span_renderer_t *renderer, 1.64 ++ int x1, int y1, 1.65 ++ int x2, int y2, 1.66 ++ int coverage) 1.67 ++{ 1.68 ++ _cairo_gl_emit_span (renderer, x1, y1, y2, coverage); 1.69 ++ _cairo_gl_emit_span (renderer, x2, y2, y1, coverage); 1.70 ++} 1.71 ++ 1.72 + static cairo_status_t 1.73 +-_cairo_gl_surface_span_renderer_render_row ( 1.74 +- void *abstract_renderer, 1.75 +- int y, 1.76 +- const cairo_half_open_span_t *spans, 1.77 +- unsigned num_spans) 1.78 ++_cairo_gl_render_bounded_spans (void *abstract_renderer, 1.79 ++ int y, int height, 1.80 ++ const cairo_half_open_span_t *spans, 1.81 ++ unsigned num_spans) 1.82 + { 1.83 + cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; 1.84 +- int xmin = renderer->composite_rectangles.mask.x; 1.85 +- int xmax = xmin + renderer->composite_rectangles.width; 1.86 +- int prev_x = xmin; 1.87 +- int prev_alpha = 0; 1.88 +- unsigned i; 1.89 +- int x_translate; 1.90 +- 1.91 +- /* Make sure we're within y-range. */ 1.92 +- if (y < renderer->composite_rectangles.mask.y || 1.93 +- y >= renderer->composite_rectangles.mask.y + 1.94 +- renderer->composite_rectangles.height) 1.95 ++ 1.96 ++ if (num_spans == 0) 1.97 + return CAIRO_STATUS_SUCCESS; 1.98 + 1.99 +- x_translate = renderer->composite_rectangles.dst.x - 1.100 +- renderer->composite_rectangles.mask.x; 1.101 +- y += renderer->composite_rectangles.dst.y - 1.102 +- renderer->composite_rectangles.mask.y; 1.103 ++ do { 1.104 ++ if (spans[0].coverage) { 1.105 ++ _cairo_gl_emit_rectangle (renderer, 1.106 ++ spans[0].x, y, 1.107 ++ spans[1].x, y + height, 1.108 ++ spans[0].coverage); 1.109 ++ } 1.110 + 1.111 +- /* Find the first span within x-range. */ 1.112 +- for (i=0; i < num_spans && spans[i].x < xmin; i++) {} 1.113 +- if (i>0) 1.114 +- prev_alpha = spans[i-1].coverage; 1.115 ++ spans++; 1.116 ++ } while (--num_spans > 1); 1.117 + 1.118 +- /* Set the intermediate spans. */ 1.119 +- for (; i < num_spans; i++) { 1.120 +- int x = spans[i].x; 1.121 ++ return CAIRO_STATUS_SUCCESS; 1.122 ++} 1.123 + 1.124 +- if (x >= xmax) 1.125 +- break; 1.126 ++static cairo_status_t 1.127 ++_cairo_gl_render_unbounded_spans (void *abstract_renderer, 1.128 ++ int y, int height, 1.129 ++ const cairo_half_open_span_t *spans, 1.130 ++ unsigned num_spans) 1.131 ++{ 1.132 ++ cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; 1.133 + 1.134 +- _cairo_gl_emit_span (renderer, 1.135 +- prev_x + x_translate, x + x_translate, y, 1.136 +- prev_alpha); 1.137 ++ if (num_spans == 0) { 1.138 ++ _cairo_gl_emit_rectangle (renderer, 1.139 ++ renderer->xmin, y, 1.140 ++ renderer->xmax, y + height, 1.141 ++ 0); 1.142 ++ return CAIRO_STATUS_SUCCESS; 1.143 ++ } 1.144 + 1.145 +- prev_x = x; 1.146 +- prev_alpha = spans[i].coverage; 1.147 ++ if (spans[0].x != renderer->xmin) { 1.148 ++ _cairo_gl_emit_rectangle (renderer, 1.149 ++ renderer->xmin, y, 1.150 ++ spans[0].x, y + height, 1.151 ++ 0); 1.152 + } 1.153 + 1.154 +- if (prev_x < xmax) { 1.155 +- _cairo_gl_emit_span (renderer, 1.156 +- prev_x + x_translate, xmax + x_translate, y, 1.157 +- prev_alpha); 1.158 ++ do { 1.159 ++ _cairo_gl_emit_rectangle (renderer, 1.160 ++ spans[0].x, y, 1.161 ++ spans[1].x, y + height, 1.162 ++ spans[0].coverage); 1.163 ++ spans++; 1.164 ++ } while (--num_spans > 1); 1.165 ++ 1.166 ++ if (spans[0].x != renderer->xmax) { 1.167 ++ _cairo_gl_emit_rectangle (renderer, 1.168 ++ spans[0].x, y, 1.169 ++ renderer->xmax, y + height, 1.170 ++ 0); 1.171 + } 1.172 + 1.173 + return CAIRO_STATUS_SUCCESS; 1.174 +@@ -2274,8 +2290,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op, 1.175 + cairo_gl_surface_t *dst = abstract_dst; 1.176 + cairo_gl_surface_span_renderer_t *renderer; 1.177 + cairo_status_t status; 1.178 +- int width = rects->width; 1.179 +- int height = rects->height; 1.180 + cairo_surface_attributes_t *src_attributes; 1.181 + GLenum err; 1.182 + 1.183 +diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c 1.184 +index 48d8013..d52979d 100644 1.185 +--- a/src/cairo-image-surface.c 1.186 ++++ b/src/cairo-image-surface.c 1.187 +@@ -1390,11 +1390,13 @@ typedef struct _cairo_image_surface_span_renderer { 1.188 + const cairo_pattern_t *pattern; 1.189 + cairo_antialias_t antialias; 1.190 + 1.191 ++ uint8_t *mask_data; 1.192 ++ uint32_t mask_stride; 1.193 ++ 1.194 + cairo_image_surface_t *src; 1.195 + cairo_surface_attributes_t src_attributes; 1.196 + cairo_image_surface_t *mask; 1.197 + cairo_image_surface_t *dst; 1.198 +- 1.199 + cairo_composite_rectangles_t composite_rectangles; 1.200 + } cairo_image_surface_span_renderer_t; 1.201 + 1.202 +@@ -1403,66 +1405,46 @@ _cairo_image_surface_span_render_row ( 1.203 + int y, 1.204 + const cairo_half_open_span_t *spans, 1.205 + unsigned num_spans, 1.206 +- cairo_image_surface_t *mask, 1.207 +- const cairo_composite_rectangles_t *rects) 1.208 ++ uint8_t *data, 1.209 ++ uint32_t stride) 1.210 + { 1.211 +- int xmin = rects->mask.x; 1.212 +- int xmax = xmin + rects->width; 1.213 + uint8_t *row; 1.214 +- int prev_x = xmin; 1.215 +- int prev_alpha = 0; 1.216 + unsigned i; 1.217 + 1.218 +- /* Make sure we're within y-range. */ 1.219 +- y -= rects->mask.y; 1.220 +- if (y < 0 || y >= rects->height) 1.221 ++ if (num_spans == 0) 1.222 + return; 1.223 + 1.224 +- row = (uint8_t*)(mask->data) + y*(size_t)mask->stride - xmin; 1.225 +- 1.226 +- /* Find the first span within x-range. */ 1.227 +- for (i=0; i < num_spans && spans[i].x < xmin; i++) {} 1.228 +- if (i>0) 1.229 +- prev_alpha = spans[i-1].coverage; 1.230 +- 1.231 +- /* Set the intermediate spans. */ 1.232 +- for (; i < num_spans; i++) { 1.233 +- int x = spans[i].x; 1.234 +- 1.235 +- if (x >= xmax) 1.236 +- break; 1.237 +- 1.238 +- if (prev_alpha != 0) { 1.239 +- /* We implement setting rendering the most common single 1.240 +- * pixel wide span case to avoid the overhead of a memset 1.241 +- * call. Open coding setting longer spans didn't show a 1.242 +- * noticeable improvement over memset. */ 1.243 +- if (x == prev_x + 1) { 1.244 +- row[prev_x] = prev_alpha; 1.245 +- } 1.246 +- else { 1.247 +- memset(row + prev_x, prev_alpha, x - prev_x); 1.248 +- } 1.249 ++ row = data + y * stride; 1.250 ++ for (i = 0; i < num_spans - 1; i++) { 1.251 ++ if (! spans[i].coverage) 1.252 ++ continue; 1.253 ++ 1.254 ++ /* We implement setting the most common single pixel wide 1.255 ++ * span case to avoid the overhead of a memset call. 1.256 ++ * Open coding setting longer spans didn't show a 1.257 ++ * noticeable improvement over memset. 1.258 ++ */ 1.259 ++ if (spans[i+1].x == spans[i].x + 1) { 1.260 ++ row[spans[i].x] = spans[i].coverage; 1.261 ++ } else { 1.262 ++ memset (row + spans[i].x, 1.263 ++ spans[i].coverage, 1.264 ++ spans[i+1].x - spans[i].x); 1.265 + } 1.266 +- 1.267 +- prev_x = x; 1.268 +- prev_alpha = spans[i].coverage; 1.269 +- } 1.270 +- 1.271 +- if (prev_alpha != 0 && prev_x < xmax) { 1.272 +- memset(row + prev_x, prev_alpha, xmax - prev_x); 1.273 + } 1.274 + } 1.275 + 1.276 + static cairo_status_t 1.277 +-_cairo_image_surface_span_renderer_render_row ( 1.278 ++_cairo_image_surface_span_renderer_render_rows ( 1.279 + void *abstract_renderer, 1.280 + int y, 1.281 ++ int height, 1.282 + const cairo_half_open_span_t *spans, 1.283 + unsigned num_spans) 1.284 + { 1.285 + cairo_image_surface_span_renderer_t *renderer = abstract_renderer; 1.286 +- _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles); 1.287 ++ while (height--) 1.288 ++ _cairo_image_surface_span_render_row (y++, spans, num_spans, renderer->mask_data, renderer->mask_stride); 1.289 + return CAIRO_STATUS_SUCCESS; 1.290 + } 1.291 + 1.292 +@@ -1517,11 +1499,11 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer) 1.293 + &dst->base, 1.294 + src_attributes, 1.295 + src->width, src->height, 1.296 +- rects->width, rects->height, 1.297 ++ width, height, 1.298 + rects->src.x, rects->src.y, 1.299 + 0, 0, /* mask.x, mask.y */ 1.300 + rects->dst.x, rects->dst.y, 1.301 +- rects->width, rects->height, 1.302 ++ width, height, 1.303 + dst->clip_region); 1.304 + } 1.305 + } 1.306 +@@ -1567,7 +1549,7 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op, 1.307 + 1.308 + renderer->base.destroy = _cairo_image_surface_span_renderer_destroy; 1.309 + renderer->base.finish = _cairo_image_surface_span_renderer_finish; 1.310 +- renderer->base.render_row = _cairo_image_surface_span_renderer_render_row; 1.311 ++ renderer->base.render_rows = _cairo_image_surface_span_renderer_render_rows; 1.312 + renderer->op = op; 1.313 + renderer->pattern = pattern; 1.314 + renderer->antialias = antialias; 1.315 +@@ -1604,6 +1586,9 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op, 1.316 + _cairo_image_surface_span_renderer_destroy (renderer); 1.317 + return _cairo_span_renderer_create_in_error (status); 1.318 + } 1.319 ++ 1.320 ++ renderer->mask_data = renderer->mask->data - rects->mask.x - rects->mask.y * renderer->mask->stride; 1.321 ++ renderer->mask_stride = renderer->mask->stride; 1.322 + return &renderer->base; 1.323 + } 1.324 + 1.325 +diff --git a/src/cairo-spans-private.h b/src/cairo-spans-private.h 1.326 +index e29a567..af3b38c 100644 1.327 +--- a/src/cairo-spans-private.h 1.328 ++++ b/src/cairo-spans-private.h 1.329 +@@ -47,26 +47,24 @@ typedef struct _cairo_half_open_span { 1.330 + * surfaces if they want to composite spans instead of trapezoids. */ 1.331 + typedef struct _cairo_span_renderer cairo_span_renderer_t; 1.332 + struct _cairo_span_renderer { 1.333 ++ /* Private status variable. */ 1.334 ++ cairo_status_t status; 1.335 ++ 1.336 + /* Called to destroy the renderer. */ 1.337 + cairo_destroy_func_t destroy; 1.338 + 1.339 +- /* Render the spans on row y of the source by whatever compositing 1.340 +- * method is required. The function should ignore spans outside 1.341 +- * the bounding box set by the init() function. */ 1.342 +- cairo_status_t (*render_row)( 1.343 +- void *abstract_renderer, 1.344 +- int y, 1.345 +- const cairo_half_open_span_t *coverages, 1.346 +- unsigned num_coverages); 1.347 ++ /* Render the spans on row y of the destination by whatever compositing 1.348 ++ * method is required. */ 1.349 ++ cairo_warn cairo_status_t 1.350 ++ (*render_rows) (void *abstract_renderer, 1.351 ++ int y, int height, 1.352 ++ const cairo_half_open_span_t *coverages, 1.353 ++ unsigned num_coverages); 1.354 + 1.355 + /* Called after all rows have been rendered to perform whatever 1.356 + * final rendering step is required. This function is called just 1.357 + * once before the renderer is destroyed. */ 1.358 +- cairo_status_t (*finish)( 1.359 +- void *abstract_renderer); 1.360 +- 1.361 +- /* Private status variable. */ 1.362 +- cairo_status_t status; 1.363 ++ cairo_status_t (*finish) (void *abstract_renderer); 1.364 + }; 1.365 + 1.366 + /* Scan converter interface. */ 1.367 +diff --git a/src/cairo-spans.c b/src/cairo-spans.c 1.368 +index af3b85f..69894c1 100644 1.369 +--- a/src/cairo-spans.c 1.370 ++++ b/src/cairo-spans.c 1.371 +@@ -275,13 +275,15 @@ _cairo_scan_converter_create_in_error (cairo_status_t status) 1.372 + } 1.373 + 1.374 + static cairo_status_t 1.375 +-_cairo_nil_span_renderer_render_row ( 1.376 ++_cairo_nil_span_renderer_render_rows ( 1.377 + void *abstract_renderer, 1.378 + int y, 1.379 ++ int height, 1.380 + const cairo_half_open_span_t *coverages, 1.381 + unsigned num_coverages) 1.382 + { 1.383 + (void) y; 1.384 ++ (void) height; 1.385 + (void) coverages; 1.386 + (void) num_coverages; 1.387 + return _cairo_span_renderer_status (abstract_renderer); 1.388 +@@ -310,7 +312,7 @@ _cairo_span_renderer_set_error ( 1.389 + ASSERT_NOT_REACHED; 1.390 + } 1.391 + if (renderer->status == CAIRO_STATUS_SUCCESS) { 1.392 +- renderer->render_row = _cairo_nil_span_renderer_render_row; 1.393 ++ renderer->render_rows = _cairo_nil_span_renderer_render_rows; 1.394 + renderer->finish = _cairo_nil_span_renderer_finish; 1.395 + renderer->status = error; 1.396 + } 1.397 +diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c 1.398 +index 29262c2..2b9fb1b 100644 1.399 +--- a/src/cairo-tor-scan-converter.c 1.400 ++++ b/src/cairo-tor-scan-converter.c 1.401 +@@ -128,27 +128,29 @@ blit_with_span_renderer( 1.402 + cairo_span_renderer_t *span_renderer, 1.403 + struct pool *span_pool, 1.404 + int y, 1.405 ++ int height, 1.406 + int xmin, 1.407 + int xmax); 1.408 + 1.409 + static glitter_status_t 1.410 +-blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y); 1.411 ++blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height); 1.412 + 1.413 + #define GLITTER_BLIT_COVERAGES_ARGS \ 1.414 + cairo_span_renderer_t *span_renderer, \ 1.415 + struct pool *span_pool 1.416 + 1.417 +-#define GLITTER_BLIT_COVERAGES(cells, y, xmin, xmax) do { \ 1.418 ++#define GLITTER_BLIT_COVERAGES(cells, y, height,xmin, xmax) do { \ 1.419 + cairo_status_t status = blit_with_span_renderer (cells, \ 1.420 + span_renderer, \ 1.421 + span_pool, \ 1.422 +- y, xmin, xmax); \ 1.423 ++ y, height, \ 1.424 ++ xmin, xmax); \ 1.425 + if (unlikely (status)) \ 1.426 + return status; \ 1.427 + } while (0) 1.428 + 1.429 +-#define GLITTER_BLIT_COVERAGES_EMPTY(y, xmin, xmax) do { \ 1.430 +- cairo_status_t status = blit_empty_with_span_renderer (span_renderer, y); \ 1.431 ++#define GLITTER_BLIT_COVERAGES_EMPTY(y, height, xmin, xmax) do { \ 1.432 ++ cairo_status_t status = blit_empty_with_span_renderer (span_renderer, y, height); \ 1.433 + if (unlikely (status)) \ 1.434 + return status; \ 1.435 + } while (0) 1.436 +@@ -309,8 +311,8 @@ typedef int grid_area_t; 1.437 + #define UNROLL3(x) x x x 1.438 + 1.439 + struct quorem { 1.440 +- int quo; 1.441 +- int rem; 1.442 ++ int32_t quo; 1.443 ++ int32_t rem; 1.444 + }; 1.445 + 1.446 + /* Header for a chunk of memory in a memory pool. */ 1.447 +@@ -382,6 +384,7 @@ struct edge { 1.448 + /* Original sign of the edge: +1 for downwards, -1 for upwards 1.449 + * edges. */ 1.450 + int dir; 1.451 ++ int vertical; 1.452 + }; 1.453 + 1.454 + /* Number of subsample rows per y-bucket. Must be GRID_Y. */ 1.455 +@@ -389,18 +392,28 @@ struct edge { 1.456 + 1.457 + #define EDGE_Y_BUCKET_INDEX(y, ymin) (((y) - (ymin))/EDGE_Y_BUCKET_HEIGHT) 1.458 + 1.459 ++struct bucket { 1.460 ++ /* Unsorted list of edges starting within this bucket. */ 1.461 ++ struct edge *edges; 1.462 ++ 1.463 ++ /* Set to non-zero if there are edges starting strictly within the 1.464 ++ * bucket. */ 1.465 ++ unsigned have_inside_edges; 1.466 ++}; 1.467 ++ 1.468 + /* A collection of sorted and vertically clipped edges of the polygon. 1.469 + * Edges are moved from the polygon to an active list while scan 1.470 + * converting. */ 1.471 + struct polygon { 1.472 +- /* The vertical clip extents. */ 1.473 ++ /* The clip extents. */ 1.474 ++ grid_scaled_x_t xmin, xmax; 1.475 + grid_scaled_y_t ymin, ymax; 1.476 + 1.477 + /* Array of edges all starting in the same bucket. An edge is put 1.478 + * into bucket EDGE_BUCKET_INDEX(edge->ytop, polygon->ymin) when 1.479 + * it is added to the polygon. */ 1.480 +- struct edge **y_buckets; 1.481 +- struct edge *y_buckets_embedded[64]; 1.482 ++ struct bucket *y_buckets; 1.483 ++ struct bucket y_buckets_embedded[64]; 1.484 + 1.485 + struct { 1.486 + struct pool base[1]; 1.487 +@@ -702,7 +715,6 @@ static void 1.488 + cell_list_fini(struct cell_list *cells) 1.489 + { 1.490 + pool_fini (cells->cell_pool.base); 1.491 +- cell_list_init (cells); 1.492 + } 1.493 + 1.494 + /* Empty the cell list. This is called at the start of every pixel 1.495 +@@ -715,6 +727,26 @@ cell_list_reset (struct cell_list *cells) 1.496 + pool_reset (cells->cell_pool.base); 1.497 + } 1.498 + 1.499 ++static struct cell * 1.500 ++cell_list_alloc (struct cell_list *cells, 1.501 ++ struct cell **cursor, 1.502 ++ struct cell *tail, 1.503 ++ int x) 1.504 ++{ 1.505 ++ struct cell *cell; 1.506 ++ 1.507 ++ cell = pool_alloc (cells->cell_pool.base, sizeof (struct cell)); 1.508 ++ if (unlikely (NULL == cell)) 1.509 ++ return NULL; 1.510 ++ 1.511 ++ *cursor = cell; 1.512 ++ cell->next = tail; 1.513 ++ cell->x = x; 1.514 ++ cell->uncovered_area = 0; 1.515 ++ cell->covered_height = 0; 1.516 ++ return cell; 1.517 ++} 1.518 ++ 1.519 + /* Find a cell at the given x-coordinate. Returns %NULL if a new cell 1.520 + * needed to be allocated but couldn't be. Cells must be found with 1.521 + * non-decreasing x-coordinate until the cell list is rewound using 1.522 +@@ -737,22 +769,10 @@ cell_list_find (struct cell_list *cells, int x) 1.523 + } 1.524 + cells->cursor = cursor; 1.525 + 1.526 +- if (tail->x == x) { 1.527 ++ if (tail->x == x) 1.528 + return tail; 1.529 +- } else { 1.530 +- struct cell *cell; 1.531 +- 1.532 +- cell = pool_alloc (cells->cell_pool.base, sizeof (struct cell)); 1.533 +- if (unlikely (NULL == cell)) 1.534 +- return NULL; 1.535 + 1.536 +- *cursor = cell; 1.537 +- cell->next = tail; 1.538 +- cell->x = x; 1.539 +- cell->uncovered_area = 0; 1.540 +- cell->covered_height = 0; 1.541 +- return cell; 1.542 +- } 1.543 ++ return cell_list_alloc (cells, cursor, tail, x); 1.544 + } 1.545 + 1.546 + /* Find two cells at x1 and x2. This is exactly equivalent 1.547 +@@ -832,9 +852,8 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2) 1.548 + /* Add an unbounded subpixel span covering subpixels >= x to the 1.549 + * coverage cells. */ 1.550 + static glitter_status_t 1.551 +-cell_list_add_unbounded_subspan( 1.552 +- struct cell_list *cells, 1.553 +- grid_scaled_x_t x) 1.554 ++cell_list_add_unbounded_subspan (struct cell_list *cells, 1.555 ++ grid_scaled_x_t x) 1.556 + { 1.557 + struct cell *cell; 1.558 + int ix, fx; 1.559 +@@ -907,20 +926,24 @@ cell_list_render_edge( 1.560 + struct edge *edge, 1.561 + int sign) 1.562 + { 1.563 +- struct quorem x1 = edge->x; 1.564 +- struct quorem x2 = x1; 1.565 + grid_scaled_y_t y1, y2, dy; 1.566 + grid_scaled_x_t dx; 1.567 + int ix1, ix2; 1.568 + grid_scaled_x_t fx1, fx2; 1.569 + 1.570 +- x2.quo += edge->dxdy_full.quo; 1.571 +- x2.rem += edge->dxdy_full.rem; 1.572 +- if (x2.rem >= 0) { 1.573 +- ++x2.quo; 1.574 +- x2.rem -= edge->dy; 1.575 ++ struct quorem x1 = edge->x; 1.576 ++ struct quorem x2 = x1; 1.577 ++ 1.578 ++ if (! edge->vertical) { 1.579 ++ x2.quo += edge->dxdy_full.quo; 1.580 ++ x2.rem += edge->dxdy_full.rem; 1.581 ++ if (x2.rem >= 0) { 1.582 ++ ++x2.quo; 1.583 ++ x2.rem -= edge->dy; 1.584 ++ } 1.585 ++ 1.586 ++ edge->x = x2; 1.587 + } 1.588 +- edge->x = x2; 1.589 + 1.590 + GRID_X_TO_INT_FRAC(x1.quo, ix1, fx1); 1.591 + GRID_X_TO_INT_FRAC(x2.quo, ix2, fx2); 1.592 +@@ -1026,6 +1049,7 @@ static void 1.593 + polygon_init (struct polygon *polygon) 1.594 + { 1.595 + polygon->ymin = polygon->ymax = 0; 1.596 ++ polygon->xmin = polygon->xmax = 0; 1.597 + polygon->y_buckets = polygon->y_buckets_embedded; 1.598 + pool_init (polygon->edge_pool.base, 1.599 + 8192 - sizeof (struct _pool_chunk), 1.600 +@@ -1045,10 +1069,11 @@ polygon_fini (struct polygon *polygon) 1.601 + * receive new edges and clip them to the vertical range 1.602 + * [ymin,ymax). */ 1.603 + static glitter_status_t 1.604 +-polygon_reset( 1.605 +- struct polygon *polygon, 1.606 +- grid_scaled_y_t ymin, 1.607 +- grid_scaled_y_t ymax) 1.608 ++polygon_reset (struct polygon *polygon, 1.609 ++ grid_scaled_x_t xmin, 1.610 ++ grid_scaled_x_t xmax, 1.611 ++ grid_scaled_y_t ymin, 1.612 ++ grid_scaled_y_t ymax) 1.613 + { 1.614 + unsigned h = ymax - ymin; 1.615 + unsigned num_buckets = EDGE_Y_BUCKET_INDEX(ymax + EDGE_Y_BUCKET_HEIGHT-1, 1.616 +@@ -1065,14 +1090,16 @@ polygon_reset( 1.617 + polygon->y_buckets = polygon->y_buckets_embedded; 1.618 + if (num_buckets > ARRAY_LENGTH (polygon->y_buckets_embedded)) { 1.619 + polygon->y_buckets = _cairo_malloc_ab (num_buckets, 1.620 +- sizeof (struct edge *)); 1.621 ++ sizeof (struct bucket)); 1.622 + if (unlikely (NULL == polygon->y_buckets)) 1.623 + goto bail_no_mem; 1.624 + } 1.625 +- memset (polygon->y_buckets, 0, num_buckets * sizeof (struct edge *)); 1.626 ++ memset (polygon->y_buckets, 0, num_buckets * sizeof (struct bucket)); 1.627 + 1.628 + polygon->ymin = ymin; 1.629 + polygon->ymax = ymax; 1.630 ++ polygon->xmin = xmin; 1.631 ++ polygon->xmax = xmax; 1.632 + return GLITTER_STATUS_SUCCESS; 1.633 + 1.634 + bail_no_mem: 1.635 +@@ -1086,10 +1113,13 @@ _polygon_insert_edge_into_its_y_bucket( 1.636 + struct polygon *polygon, 1.637 + struct edge *e) 1.638 + { 1.639 +- unsigned ix = EDGE_Y_BUCKET_INDEX(e->ytop, polygon->ymin); 1.640 +- struct edge **ptail = &polygon->y_buckets[ix]; 1.641 ++ unsigned j = e->ytop - polygon->ymin; 1.642 ++ unsigned ix = j / EDGE_Y_BUCKET_HEIGHT; 1.643 ++ unsigned offset = j % EDGE_Y_BUCKET_HEIGHT; 1.644 ++ struct edge **ptail = &polygon->y_buckets[ix].edges; 1.645 + e->next = *ptail; 1.646 + *ptail = e; 1.647 ++ polygon->y_buckets[ix].have_inside_edges |= offset; 1.648 + } 1.649 + 1.650 + inline static glitter_status_t 1.651 +@@ -1115,30 +1145,53 @@ polygon_add_edge (struct polygon *polygon, 1.652 + dx = edge->line.p2.x - edge->line.p1.x; 1.653 + dy = edge->line.p2.y - edge->line.p1.y; 1.654 + e->dy = dy; 1.655 +- e->dxdy = floored_divrem (dx, dy); 1.656 +- 1.657 +- if (ymin <= edge->top) 1.658 +- ytop = edge->top; 1.659 +- else 1.660 +- ytop = ymin; 1.661 +- if (ytop == edge->line.p1.y) { 1.662 +- e->x.quo = edge->line.p1.x; 1.663 +- e->x.rem = 0; 1.664 +- } else { 1.665 +- e->x = floored_muldivrem (ytop - edge->line.p1.y, dx, dy); 1.666 +- e->x.quo += edge->line.p1.x; 1.667 +- } 1.668 +- 1.669 + e->dir = edge->dir; 1.670 ++ 1.671 ++ ytop = edge->top >= ymin ? edge->top : ymin; 1.672 ++ ybot = edge->bottom <= ymax ? edge->bottom : ymax; 1.673 + e->ytop = ytop; 1.674 +- ybot = edge->bottom < ymax ? edge->bottom : ymax; 1.675 + e->height_left = ybot - ytop; 1.676 + 1.677 +- if (e->height_left >= GRID_Y) { 1.678 +- e->dxdy_full = floored_muldivrem (GRID_Y, dx, dy); 1.679 +- } else { 1.680 ++ if (dx == 0) { 1.681 ++ e->vertical = TRUE; 1.682 ++ e->x.quo = edge->line.p1.x; 1.683 ++ e->x.rem = 0; 1.684 ++ e->dxdy.quo = 0; 1.685 ++ e->dxdy.rem = 0; 1.686 + e->dxdy_full.quo = 0; 1.687 + e->dxdy_full.rem = 0; 1.688 ++ 1.689 ++ /* Drop edges to the right of the clip extents. */ 1.690 ++ if (e->x.quo >= polygon->xmax) 1.691 ++ return GLITTER_STATUS_SUCCESS; 1.692 ++ 1.693 ++ /* Offset vertical edges at the left side of the clip extents 1.694 ++ * to just shy of the left side. We depend on this when 1.695 ++ * checking for possible intersections within the clip 1.696 ++ * rectangle. */ 1.697 ++ if (e->x.quo <= polygon->xmin) { 1.698 ++ e->x.quo = polygon->xmin - 1; 1.699 ++ } 1.700 ++ } else { 1.701 ++ e->vertical = FALSE; 1.702 ++ e->dxdy = floored_divrem (dx, dy); 1.703 ++ if (ytop == edge->line.p1.y) { 1.704 ++ e->x.quo = edge->line.p1.x; 1.705 ++ e->x.rem = 0; 1.706 ++ } else { 1.707 ++ e->x = floored_muldivrem (ytop - edge->line.p1.y, dx, dy); 1.708 ++ e->x.quo += edge->line.p1.x; 1.709 ++ } 1.710 ++ 1.711 ++ if (e->x.quo >= polygon->xmax && e->dxdy.quo >= 0) 1.712 ++ return GLITTER_STATUS_SUCCESS; 1.713 ++ 1.714 ++ if (e->height_left >= GRID_Y) { 1.715 ++ e->dxdy_full = floored_muldivrem (GRID_Y, dx, dy); 1.716 ++ } else { 1.717 ++ e->dxdy_full.quo = 0; 1.718 ++ e->dxdy_full.rem = 0; 1.719 ++ } 1.720 + } 1.721 + 1.722 + _polygon_insert_edge_into_its_y_bucket (polygon, e); 1.723 +@@ -1161,31 +1214,30 @@ active_list_init(struct active_list *active) 1.724 + active_list_reset(active); 1.725 + } 1.726 + 1.727 +-static void 1.728 +-active_list_fini( 1.729 +- struct active_list *active) 1.730 +-{ 1.731 +- active_list_reset(active); 1.732 +-} 1.733 +- 1.734 + /* Merge the edges in an unsorted list of edges into a sorted 1.735 + * list. The sort order is edges ascending by edge->x.quo. Returns 1.736 + * the new head of the sorted list. */ 1.737 + static struct edge * 1.738 + merge_unsorted_edges(struct edge *sorted_head, struct edge *unsorted_head) 1.739 + { 1.740 +- struct edge *head = unsorted_head; 1.741 + struct edge **cursor = &sorted_head; 1.742 + int x; 1.743 + 1.744 +- while (NULL != head) { 1.745 ++ if (sorted_head == NULL) { 1.746 ++ sorted_head = unsorted_head; 1.747 ++ unsorted_head = unsorted_head->next; 1.748 ++ sorted_head->next = NULL; 1.749 ++ if (unsorted_head == NULL) 1.750 ++ return sorted_head; 1.751 ++ } 1.752 ++ 1.753 ++ do { 1.754 ++ struct edge *next = unsorted_head->next; 1.755 + struct edge *prev = *cursor; 1.756 +- struct edge *next = head->next; 1.757 +- x = head->x.quo; 1.758 + 1.759 +- if (NULL == prev || x < prev->x.quo) { 1.760 ++ x = unsorted_head->x.quo; 1.761 ++ if (x < prev->x.quo) 1.762 + cursor = &sorted_head; 1.763 +- } 1.764 + 1.765 + while (1) { 1.766 + UNROLL3({ 1.767 +@@ -1196,26 +1248,29 @@ merge_unsorted_edges(struct edge *sorted_head, struct edge *unsorted_head) 1.768 + }); 1.769 + } 1.770 + 1.771 +- head->next = *cursor; 1.772 +- *cursor = head; 1.773 ++ unsorted_head->next = *cursor; 1.774 ++ *cursor = unsorted_head; 1.775 ++ unsorted_head = next; 1.776 ++ } while (unsorted_head != NULL); 1.777 + 1.778 +- head = next; 1.779 +- } 1.780 + return sorted_head; 1.781 + } 1.782 + 1.783 + /* Test if the edges on the active list can be safely advanced by a 1.784 + * full row without intersections or any edges ending. */ 1.785 + inline static int 1.786 +-active_list_can_step_full_row( 1.787 +- struct active_list *active) 1.788 ++active_list_can_step_full_row (struct active_list *active, 1.789 ++ grid_scaled_x_t xmin) 1.790 + { 1.791 ++ const struct edge *e; 1.792 ++ grid_scaled_x_t prev_x = INT_MIN; 1.793 ++ 1.794 + /* Recomputes the minimum height of all edges on the active 1.795 + * list if we have been dropping edges. */ 1.796 + if (active->min_height <= 0) { 1.797 +- struct edge *e = active->head; 1.798 + int min_height = INT_MAX; 1.799 + 1.800 ++ e = active->head; 1.801 + while (NULL != e) { 1.802 + if (e->height_left < min_height) 1.803 + min_height = e->height_left; 1.804 +@@ -1225,27 +1280,38 @@ active_list_can_step_full_row( 1.805 + active->min_height = min_height; 1.806 + } 1.807 + 1.808 +- /* Check for intersections only if no edges end during the next 1.809 +- * row. */ 1.810 +- if (active->min_height >= GRID_Y) { 1.811 +- grid_scaled_x_t prev_x = INT_MIN; 1.812 +- struct edge *e = active->head; 1.813 +- while (NULL != e) { 1.814 +- struct quorem x = e->x; 1.815 ++ if (active->min_height < GRID_Y) 1.816 ++ return 0; 1.817 + 1.818 ++ /* Check for intersections as no edges end during the next row. */ 1.819 ++ e = active->head; 1.820 ++ while (NULL != e) { 1.821 ++ struct quorem x = e->x; 1.822 ++ 1.823 ++ if (! e->vertical) { 1.824 + x.quo += e->dxdy_full.quo; 1.825 + x.rem += e->dxdy_full.rem; 1.826 + if (x.rem >= 0) 1.827 + ++x.quo; 1.828 ++ } 1.829 + 1.830 +- if (x.quo <= prev_x) 1.831 ++ /* There's may be an intersection if the edge sort order might 1.832 ++ * change. */ 1.833 ++ if (x.quo <= prev_x) { 1.834 ++ /* Ignore intersections to the left of the clip extents. 1.835 ++ * This assumes that all vertical edges on or at the left 1.836 ++ * side of the clip rectangle have been shifted slightly 1.837 ++ * to the left in polygon_add_edge(). */ 1.838 ++ if (prev_x >= xmin || x.quo >= xmin || e->x.quo >= xmin) 1.839 + return 0; 1.840 ++ } 1.841 ++ else { 1.842 + prev_x = x.quo; 1.843 +- e = e->next; 1.844 + } 1.845 +- return 1; 1.846 ++ e = e->next; 1.847 + } 1.848 +- return 0; 1.849 ++ 1.850 ++ return 1; 1.851 + } 1.852 + 1.853 + /* Merges edges on the given subpixel row from the polygon to the 1.854 +@@ -1261,7 +1327,7 @@ active_list_merge_edges_from_polygon( 1.855 + unsigned ix = EDGE_Y_BUCKET_INDEX(y, polygon->ymin); 1.856 + int min_height = active->min_height; 1.857 + struct edge *subrow_edges = NULL; 1.858 +- struct edge **ptail = &polygon->y_buckets[ix]; 1.859 ++ struct edge **ptail = &polygon->y_buckets[ix].edges; 1.860 + 1.861 + while (1) { 1.862 + struct edge *tail = *ptail; 1.863 +@@ -1277,8 +1343,10 @@ active_list_merge_edges_from_polygon( 1.864 + ptail = &tail->next; 1.865 + } 1.866 + } 1.867 +- active->head = merge_unsorted_edges(active->head, subrow_edges); 1.868 +- active->min_height = min_height; 1.869 ++ if (subrow_edges) { 1.870 ++ active->head = merge_unsorted_edges(active->head, subrow_edges); 1.871 ++ active->min_height = min_height; 1.872 ++ } 1.873 + } 1.874 + 1.875 + /* Advance the edges on the active list by one subsample row by 1.876 +@@ -1439,11 +1507,13 @@ apply_nonzero_fill_rule_and_step_edges (struct active_list *active, 1.877 + } 1.878 + } 1.879 + 1.880 +- right_edge->x.quo += right_edge->dxdy_full.quo; 1.881 +- right_edge->x.rem += right_edge->dxdy_full.rem; 1.882 +- if (right_edge->x.rem >= 0) { 1.883 +- ++right_edge->x.quo; 1.884 +- right_edge->x.rem -= right_edge->dy; 1.885 ++ if (! right_edge->vertical) { 1.886 ++ right_edge->x.quo += right_edge->dxdy_full.quo; 1.887 ++ right_edge->x.rem += right_edge->dxdy_full.rem; 1.888 ++ if (right_edge->x.rem >= 0) { 1.889 ++ ++right_edge->x.quo; 1.890 ++ right_edge->x.rem -= right_edge->dy; 1.891 ++ } 1.892 + } 1.893 + } 1.894 + 1.895 +@@ -1472,6 +1542,7 @@ apply_evenodd_fill_rule_and_step_edges (struct active_list *active, 1.896 + left_edge = *cursor; 1.897 + while (NULL != left_edge) { 1.898 + struct edge *right_edge; 1.899 ++ int winding = left_edge->dir; 1.900 + 1.901 + left_edge->height_left -= GRID_Y; 1.902 + if (left_edge->height_left) 1.903 +@@ -1490,17 +1561,22 @@ apply_evenodd_fill_rule_and_step_edges (struct active_list *active, 1.904 + else 1.905 + *cursor = right_edge->next; 1.906 + 1.907 ++ winding += right_edge->dir; 1.908 ++ if ((winding & 1) == 0) { 1.909 + if (right_edge->next == NULL || 1.910 + right_edge->next->x.quo != right_edge->x.quo) 1.911 + { 1.912 + break; 1.913 + } 1.914 ++ } 1.915 + 1.916 +- right_edge->x.quo += right_edge->dxdy_full.quo; 1.917 +- right_edge->x.rem += right_edge->dxdy_full.rem; 1.918 +- if (right_edge->x.rem >= 0) { 1.919 +- ++right_edge->x.quo; 1.920 +- right_edge->x.rem -= right_edge->dy; 1.921 ++ if (! right_edge->vertical) { 1.922 ++ right_edge->x.quo += right_edge->dxdy_full.quo; 1.923 ++ right_edge->x.rem += right_edge->dxdy_full.rem; 1.924 ++ if (right_edge->x.rem >= 0) { 1.925 ++ ++right_edge->x.quo; 1.926 ++ right_edge->x.rem -= right_edge->dy; 1.927 ++ } 1.928 + } 1.929 + } 1.930 + 1.931 +@@ -1537,8 +1613,14 @@ blit_span( 1.932 + } 1.933 + } 1.934 + 1.935 +-#define GLITTER_BLIT_COVERAGES(coverages, y, xmin, xmax) \ 1.936 +- blit_cells(coverages, raster_pixels + (y)*raster_stride, xmin, xmax) 1.937 ++#define GLITTER_BLIT_COVERAGES(coverages, y, height, xmin, xmax) \ 1.938 ++ do { \ 1.939 ++ int __y = y; \ 1.940 ++ int __h = height; \ 1.941 ++ do { \ 1.942 ++ blit_cells(coverages, raster_pixels + (__y)*raster_stride, xmin, xmax); \ 1.943 ++ } while (--__h); \ 1.944 ++ } while (0) 1.945 + 1.946 + static void 1.947 + blit_cells( 1.948 +@@ -1597,7 +1679,6 @@ static void 1.949 + _glitter_scan_converter_fini(glitter_scan_converter_t *converter) 1.950 + { 1.951 + polygon_fini(converter->polygon); 1.952 +- active_list_fini(converter->active); 1.953 + cell_list_fini(converter->coverages); 1.954 + converter->xmin=0; 1.955 + converter->ymin=0; 1.956 +@@ -1641,7 +1722,7 @@ glitter_scan_converter_reset( 1.957 + 1.958 + active_list_reset(converter->active); 1.959 + cell_list_reset(converter->coverages); 1.960 +- status = polygon_reset(converter->polygon, ymin, ymax); 1.961 ++ status = polygon_reset(converter->polygon, xmin, xmax, ymin, ymax); 1.962 + if (status) 1.963 + return status; 1.964 + 1.965 +@@ -1711,19 +1792,48 @@ glitter_scan_converter_add_edge (glitter_scan_converter_t *converter, 1.966 + #endif 1.967 + 1.968 + #ifndef GLITTER_BLIT_COVERAGES_EMPTY 1.969 +-# define GLITTER_BLIT_COVERAGES_EMPTY(y, xmin, xmax) 1.970 ++# define GLITTER_BLIT_COVERAGES_EMPTY(y0, y1, xmin, xmax) 1.971 + #endif 1.972 + 1.973 ++static cairo_bool_t 1.974 ++active_list_is_vertical (struct active_list *active) 1.975 ++{ 1.976 ++ struct edge *e; 1.977 ++ 1.978 ++ for (e = active->head; e != NULL; e = e->next) { 1.979 ++ if (! e->vertical) 1.980 ++ return FALSE; 1.981 ++ } 1.982 ++ 1.983 ++ return TRUE; 1.984 ++} 1.985 ++ 1.986 ++static void 1.987 ++step_edges (struct active_list *active, int count) 1.988 ++{ 1.989 ++ struct edge **cursor = &active->head; 1.990 ++ struct edge *edge; 1.991 ++ 1.992 ++ for (edge = *cursor; edge != NULL; edge = *cursor) { 1.993 ++ edge->height_left -= GRID_Y * count; 1.994 ++ if (edge->height_left) 1.995 ++ cursor = &edge->next; 1.996 ++ else 1.997 ++ *cursor = edge->next; 1.998 ++ } 1.999 ++} 1.1000 ++ 1.1001 + I glitter_status_t 1.1002 + glitter_scan_converter_render( 1.1003 + glitter_scan_converter_t *converter, 1.1004 + int nonzero_fill, 1.1005 + GLITTER_BLIT_COVERAGES_ARGS) 1.1006 + { 1.1007 +- int i; 1.1008 ++ int i, j; 1.1009 + int ymax_i = converter->ymax / GRID_Y; 1.1010 + int ymin_i = converter->ymin / GRID_Y; 1.1011 + int xmin_i, xmax_i; 1.1012 ++ grid_scaled_x_t xmin = converter->xmin; 1.1013 + int h = ymax_i - ymin_i; 1.1014 + struct polygon *polygon = converter->polygon; 1.1015 + struct cell_list *coverages = converter->coverages; 1.1016 +@@ -1738,22 +1848,28 @@ glitter_scan_converter_render( 1.1017 + GLITTER_BLIT_COVERAGES_BEGIN; 1.1018 + 1.1019 + /* Render each pixel row. */ 1.1020 +- for (i=0; i<h; i++) { 1.1021 ++ for (i = 0; i < h; i = j) { 1.1022 + int do_full_step = 0; 1.1023 + glitter_status_t status = 0; 1.1024 + 1.1025 ++ j = i + 1; 1.1026 ++ 1.1027 + /* Determine if we can ignore this row or use the full pixel 1.1028 + * stepper. */ 1.1029 +- if (GRID_Y == EDGE_Y_BUCKET_HEIGHT && ! polygon->y_buckets[i]) { 1.1030 ++ if (polygon->y_buckets[i].edges == NULL) { 1.1031 + if (! active->head) { 1.1032 +- GLITTER_BLIT_COVERAGES_EMPTY (i+ymin_i, xmin_i, xmax_i); 1.1033 ++ for (; j < h && ! polygon->y_buckets[j].edges; j++) 1.1034 ++ ; 1.1035 ++ GLITTER_BLIT_COVERAGES_EMPTY (i+ymin_i, j-i, xmin_i, xmax_i); 1.1036 + continue; 1.1037 + } 1.1038 +- 1.1039 +- do_full_step = active_list_can_step_full_row (active); 1.1040 ++ do_full_step = active_list_can_step_full_row (active, xmin); 1.1041 ++ } 1.1042 ++ else if (! polygon->y_buckets[i].have_inside_edges) { 1.1043 ++ grid_scaled_y_t y = (i+ymin_i)*GRID_Y; 1.1044 ++ active_list_merge_edges_from_polygon (active, y, polygon); 1.1045 ++ do_full_step = active_list_can_step_full_row (active, xmin); 1.1046 + } 1.1047 +- 1.1048 +- cell_list_reset (coverages); 1.1049 + 1.1050 + if (do_full_step) { 1.1051 + /* Step by a full pixel row's worth. */ 1.1052 +@@ -1764,8 +1880,20 @@ glitter_scan_converter_render( 1.1053 + status = apply_evenodd_fill_rule_and_step_edges (active, 1.1054 + coverages); 1.1055 + } 1.1056 ++ 1.1057 ++ if (active_list_is_vertical (active)) { 1.1058 ++ while (j < h && 1.1059 ++ polygon->y_buckets[j].edges == NULL && 1.1060 ++ active->min_height >= 2*GRID_Y) 1.1061 ++ { 1.1062 ++ active->min_height -= GRID_Y; 1.1063 ++ j++; 1.1064 ++ } 1.1065 ++ if (j != i + 1) 1.1066 ++ step_edges (active, j - (i + 1)); 1.1067 ++ } 1.1068 + } else { 1.1069 +- /* Subsample this row. */ 1.1070 ++ /* Supersample this row. */ 1.1071 + grid_scaled_y_t suby; 1.1072 + for (suby = 0; suby < GRID_Y; suby++) { 1.1073 + grid_scaled_y_t y = (i+ymin_i)*GRID_Y + suby; 1.1074 +@@ -1787,13 +1915,13 @@ glitter_scan_converter_render( 1.1075 + if (unlikely (status)) 1.1076 + return status; 1.1077 + 1.1078 +- GLITTER_BLIT_COVERAGES(coverages, i+ymin_i, xmin_i, xmax_i); 1.1079 ++ GLITTER_BLIT_COVERAGES(coverages, i+ymin_i, j-i, xmin_i, xmax_i); 1.1080 ++ cell_list_reset (coverages); 1.1081 + 1.1082 +- if (! active->head) { 1.1083 ++ if (! active->head) 1.1084 + active->min_height = INT_MAX; 1.1085 +- } else { 1.1086 ++ else 1.1087 + active->min_height -= GRID_Y; 1.1088 +- } 1.1089 + } 1.1090 + 1.1091 + /* Clean up the coverage blitter. */ 1.1092 +@@ -1807,21 +1935,20 @@ glitter_scan_converter_render( 1.1093 + * scan converter subclass. */ 1.1094 + 1.1095 + static glitter_status_t 1.1096 +-blit_with_span_renderer( 1.1097 +- struct cell_list *cells, 1.1098 +- cairo_span_renderer_t *renderer, 1.1099 +- struct pool *span_pool, 1.1100 +- int y, 1.1101 +- int xmin, 1.1102 +- int xmax) 1.1103 ++blit_with_span_renderer (struct cell_list *cells, 1.1104 ++ cairo_span_renderer_t *renderer, 1.1105 ++ struct pool *span_pool, 1.1106 ++ int y, int height, 1.1107 ++ int xmin, int xmax) 1.1108 + { 1.1109 + struct cell *cell = cells->head; 1.1110 + int prev_x = xmin; 1.1111 + int cover = 0; 1.1112 + cairo_half_open_span_t *spans; 1.1113 + unsigned num_spans; 1.1114 ++ 1.1115 + if (cell == NULL) 1.1116 +- return CAIRO_STATUS_SUCCESS; 1.1117 ++ return blit_empty_with_span_renderer (renderer, y, height); 1.1118 + 1.1119 + /* Skip cells to the left of the clip region. */ 1.1120 + while (cell != NULL && cell->x < xmin) { 1.1121 +@@ -1833,12 +1960,12 @@ blit_with_span_renderer( 1.1122 + /* Count number of cells remaining. */ 1.1123 + { 1.1124 + struct cell *next = cell; 1.1125 +- num_spans = 0; 1.1126 +- while (next) { 1.1127 ++ num_spans = 1; 1.1128 ++ while (next != NULL) { 1.1129 + next = next->next; 1.1130 + ++num_spans; 1.1131 + } 1.1132 +- num_spans = 2*num_spans + 1; 1.1133 ++ num_spans = 2*num_spans; 1.1134 + } 1.1135 + 1.1136 + /* Allocate enough spans for the row. */ 1.1137 +@@ -1853,6 +1980,7 @@ blit_with_span_renderer( 1.1138 + for (; cell != NULL; cell = cell->next) { 1.1139 + int x = cell->x; 1.1140 + int area; 1.1141 ++ 1.1142 + if (x >= xmax) 1.1143 + break; 1.1144 + 1.1145 +@@ -1872,20 +2000,26 @@ blit_with_span_renderer( 1.1146 + prev_x = x+1; 1.1147 + } 1.1148 + 1.1149 +- if (prev_x < xmax) { 1.1150 ++ if (prev_x <= xmax) { 1.1151 + spans[num_spans].x = prev_x; 1.1152 + spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover); 1.1153 + ++num_spans; 1.1154 + } 1.1155 + 1.1156 ++ if (prev_x < xmax && cover) { 1.1157 ++ spans[num_spans].x = xmax; 1.1158 ++ spans[num_spans].coverage = 0; 1.1159 ++ ++num_spans; 1.1160 ++ } 1.1161 ++ 1.1162 + /* Dump them into the renderer. */ 1.1163 +- return renderer->render_row (renderer, y, spans, num_spans); 1.1164 ++ return renderer->render_rows (renderer, y, height, spans, num_spans); 1.1165 + } 1.1166 + 1.1167 + static glitter_status_t 1.1168 +-blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y) 1.1169 ++blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height) 1.1170 + { 1.1171 +- return renderer->render_row (renderer, y, NULL, 0); 1.1172 ++ return renderer->render_rows (renderer, y, height, NULL, 0); 1.1173 + } 1.1174 + 1.1175 + struct _cairo_tor_scan_converter { 1.1176 +diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c 1.1177 +index 82d1cf5..d4575a3 100644 1.1178 +--- a/src/cairo-win32-surface.c 1.1179 ++++ b/src/cairo-win32-surface.c 1.1180 +@@ -1954,6 +1954,9 @@ typedef struct _cairo_win32_surface_span_renderer { 1.1181 + const cairo_pattern_t *pattern; 1.1182 + cairo_antialias_t antialias; 1.1183 + 1.1184 ++ uint8_t *mask_data; 1.1185 ++ uint32_t mask_stride; 1.1186 ++ 1.1187 + cairo_image_surface_t *mask; 1.1188 + cairo_win32_surface_t *dst; 1.1189 + cairo_region_t *clip_region; 1.1190 +@@ -1962,14 +1965,16 @@ typedef struct _cairo_win32_surface_span_renderer { 1.1191 + } cairo_win32_surface_span_renderer_t; 1.1192 + 1.1193 + static cairo_status_t 1.1194 +-_cairo_win32_surface_span_renderer_render_row ( 1.1195 ++_cairo_win32_surface_span_renderer_render_rows ( 1.1196 + void *abstract_renderer, 1.1197 + int y, 1.1198 ++ int height, 1.1199 + const cairo_half_open_span_t *spans, 1.1200 + unsigned num_spans) 1.1201 + { 1.1202 + cairo_win32_surface_span_renderer_t *renderer = abstract_renderer; 1.1203 +- _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles); 1.1204 ++ while (height--) 1.1205 ++ _cairo_image_surface_span_render_row (y++, spans, num_spans, renderer->mask_data, renderer->mask_stride); 1.1206 + return CAIRO_STATUS_SUCCESS; 1.1207 + } 1.1208 + 1.1209 +@@ -2066,8 +2071,7 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op, 1.1210 + 1.1211 + renderer->base.destroy = _cairo_win32_surface_span_renderer_destroy; 1.1212 + renderer->base.finish = _cairo_win32_surface_span_renderer_finish; 1.1213 +- renderer->base.render_row = 1.1214 +- _cairo_win32_surface_span_renderer_render_row; 1.1215 ++ renderer->base.render_rows = _cairo_win32_surface_span_renderer_render_rows; 1.1216 + renderer->op = op; 1.1217 + renderer->pattern = pattern; 1.1218 + renderer->antialias = antialias; 1.1219 +@@ -2088,6 +2092,9 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op, 1.1220 + _cairo_win32_surface_span_renderer_destroy (renderer); 1.1221 + return _cairo_span_renderer_create_in_error (status); 1.1222 + } 1.1223 ++ 1.1224 ++ renderer->mask_data = renderer->mask->data - rects->mask.x - rects->mask.y * renderer->mask->stride; 1.1225 ++ renderer->mask_stride = renderer->mask->stride; 1.1226 + return &renderer->base; 1.1227 + } 1.1228 + 1.1229 +diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c 1.1230 +index a7a40b8..566d9fb 100644 1.1231 +--- a/src/cairo-xlib-display.c 1.1232 ++++ b/src/cairo-xlib-display.c 1.1233 +@@ -407,6 +407,10 @@ _cairo_xlib_display_get (Display *dpy, 1.1234 + display->buggy_pad_reflect = TRUE; 1.1235 + } 1.1236 + 1.1237 ++ /* gradients don't seem to work */ 1.1238 ++ display->buggy_gradients = TRUE; 1.1239 ++ 1.1240 ++ 1.1241 + /* XXX workaround; see https://bugzilla.mozilla.org/show_bug.cgi?id=413583 */ 1.1242 + /* If buggy_repeat_force == -1, then initialize. 1.1243 + * - set to -2, meaning "nothing was specified", and we trust the above detection. 1.1244 +diff --git a/src/cairoint.h b/src/cairoint.h 1.1245 +index 58850ab..1cdf6ff 100644 1.1246 +--- a/src/cairoint.h 1.1247 ++++ b/src/cairoint.h 1.1248 +@@ -2257,8 +2257,8 @@ cairo_private void 1.1249 + _cairo_image_surface_span_render_row (int y, 1.1250 + const cairo_half_open_span_t *spans, 1.1251 + unsigned num_spans, 1.1252 +- cairo_image_surface_t *mask, 1.1253 +- const cairo_composite_rectangles_t *rects); 1.1254 ++ uint8_t *data, 1.1255 ++ uint32_t stride); 1.1256 + 1.1257 + cairo_private cairo_image_transparency_t 1.1258 + _cairo_image_analyze_transparency (cairo_image_surface_t *image);