Line data Source code
1 : /*
2 : * Copyright © 2004 Carl Worth
3 : * Copyright © 2006 Red Hat, Inc.
4 : * Copyright © 2007 David Turner
5 : * Copyright © 2008 M Joonas Pihlaja
6 : * Copyright © 2008 Chris Wilson
7 : * Copyright © 2009 Intel Corporation
8 : *
9 : * This library is free software; you can redistribute it and/or
10 : * modify it either under the terms of the GNU Lesser General Public
11 : * License version 2.1 as published by the Free Software Foundation
12 : * (the "LGPL") or, at your option, under the terms of the Mozilla
13 : * Public License Version 1.1 (the "MPL"). If you do not alter this
14 : * notice, a recipient may use your version of this file under either
15 : * the MPL or the LGPL.
16 : *
17 : * You should have received a copy of the LGPL along with this library
18 : * in the file COPYING-LGPL-2.1; if not, write to the Free Software
19 : * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
20 : * You should have received a copy of the MPL along with this library
21 : * in the file COPYING-MPL-1.1
22 : *
23 : * The contents of this file are subject to the Mozilla Public License
24 : * Version 1.1 (the "License"); you may not use this file except in
25 : * compliance with the License. You may obtain a copy of the License at
26 : * http://www.mozilla.org/MPL/
27 : *
28 : * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
29 : * OF ANY KIND, either express or implied. See the LGPL or the MPL for
30 : * the specific language governing rights and limitations.
31 : *
32 : * The Original Code is the cairo graphics library.
33 : *
34 : * The Initial Developer of the Original Code is Carl Worth
35 : *
36 : * Contributor(s):
37 : * Carl D. Worth <cworth@cworth.org>
38 : * M Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
39 : * Chris Wilson <chris@chris-wilson.co.uk>
40 : */
41 :
42 : /* Provide definitions for standalone compilation */
43 : #include "cairoint.h"
44 :
45 : #include "cairo-error-private.h"
46 : #include "cairo-list-private.h"
47 : #include "cairo-freelist-private.h"
48 : #include "cairo-combsort-private.h"
49 :
50 : #include <setjmp.h>
51 :
52 : #define STEP_X CAIRO_FIXED_ONE
53 : #define STEP_Y CAIRO_FIXED_ONE
54 : #define UNROLL3(x) x x x
55 :
56 : #define STEP_XY (2*STEP_X*STEP_Y) /* Unit area in the step. */
57 : #define AREA_TO_ALPHA(c) (((c)*255 + STEP_XY/2) / STEP_XY)
58 :
59 : typedef struct _cairo_bo_intersect_ordinate {
60 : int32_t ordinate;
61 : enum { EXACT, INEXACT } exactness;
62 : } cairo_bo_intersect_ordinate_t;
63 :
64 : typedef struct _cairo_bo_intersect_point {
65 : cairo_bo_intersect_ordinate_t x;
66 : cairo_bo_intersect_ordinate_t y;
67 : } cairo_bo_intersect_point_t;
68 :
69 : struct quorem {
70 : cairo_fixed_t quo;
71 : cairo_fixed_t rem;
72 : };
73 :
74 : struct run {
75 : struct run *next;
76 : int sign;
77 : cairo_fixed_t y;
78 : };
79 :
80 : typedef struct edge {
81 : cairo_list_t link;
82 :
83 : cairo_edge_t edge;
84 :
85 : /* Current x coordinate and advancement.
86 : * Initialised to the x coordinate of the top of the
87 : * edge. The quotient is in cairo_fixed_t units and the
88 : * remainder is mod dy in cairo_fixed_t units.
89 : */
90 : cairo_fixed_t dy;
91 : struct quorem x;
92 : struct quorem dxdy;
93 : struct quorem dxdy_full;
94 :
95 : cairo_bool_t vertical;
96 : unsigned int flags;
97 :
98 : int current_sign;
99 : struct run *runs;
100 : } edge_t;
101 :
102 : enum {
103 : START = 0x1,
104 : STOP = 0x2,
105 : };
106 :
107 : /* the parent is always given by index/2 */
108 : #define PQ_PARENT_INDEX(i) ((i) >> 1)
109 : #define PQ_FIRST_ENTRY 1
110 :
111 : /* left and right children are index * 2 and (index * 2) +1 respectively */
112 : #define PQ_LEFT_CHILD_INDEX(i) ((i) << 1)
113 :
114 : typedef enum {
115 : EVENT_TYPE_STOP,
116 : EVENT_TYPE_INTERSECTION,
117 : EVENT_TYPE_START
118 : } event_type_t;
119 :
120 : typedef struct _event {
121 : cairo_fixed_t y;
122 : event_type_t type;
123 : } event_t;
124 :
125 : typedef struct _start_event {
126 : cairo_fixed_t y;
127 : event_type_t type;
128 : edge_t *edge;
129 : } start_event_t;
130 :
131 : typedef struct _queue_event {
132 : cairo_fixed_t y;
133 : event_type_t type;
134 : edge_t *e1;
135 : edge_t *e2;
136 : } queue_event_t;
137 :
138 : typedef struct _pqueue {
139 : int size, max_size;
140 :
141 : event_t **elements;
142 : event_t *elements_embedded[1024];
143 : } pqueue_t;
144 :
145 : struct cell {
146 : struct cell *prev;
147 : struct cell *next;
148 : int x;
149 : int uncovered_area;
150 : int covered_height;
151 : };
152 :
153 : typedef struct _sweep_line {
154 : cairo_list_t active;
155 : cairo_list_t stopped;
156 : cairo_list_t *insert_cursor;
157 : cairo_bool_t is_vertical;
158 :
159 : cairo_fixed_t current_row;
160 : cairo_fixed_t current_subrow;
161 :
162 : struct coverage {
163 : struct cell head;
164 : struct cell tail;
165 :
166 : struct cell *cursor;
167 : int count;
168 :
169 : cairo_freepool_t pool;
170 : } coverage;
171 :
172 : struct event_queue {
173 : pqueue_t pq;
174 : event_t **start_events;
175 :
176 : cairo_freepool_t pool;
177 : } queue;
178 :
179 : cairo_freepool_t runs;
180 :
181 : jmp_buf unwind;
182 : } sweep_line_t;
183 :
184 : cairo_always_inline static struct quorem
185 : floored_divrem (int a, int b)
186 : {
187 : struct quorem qr;
188 0 : qr.quo = a/b;
189 0 : qr.rem = a%b;
190 0 : if ((a^b)<0 && qr.rem) {
191 0 : qr.quo--;
192 0 : qr.rem += b;
193 : }
194 0 : return qr;
195 : }
196 :
197 : static struct quorem
198 0 : floored_muldivrem(int x, int a, int b)
199 : {
200 : struct quorem qr;
201 0 : long long xa = (long long)x*a;
202 0 : qr.quo = xa/b;
203 0 : qr.rem = xa%b;
204 0 : if ((xa>=0) != (b>=0) && qr.rem) {
205 0 : qr.quo--;
206 0 : qr.rem += b;
207 : }
208 0 : return qr;
209 : }
210 :
211 : static cairo_fixed_t
212 0 : line_compute_intersection_x_for_y (const cairo_line_t *line,
213 : cairo_fixed_t y)
214 : {
215 : cairo_fixed_t x, dy;
216 :
217 0 : if (y == line->p1.y)
218 0 : return line->p1.x;
219 0 : if (y == line->p2.y)
220 0 : return line->p2.x;
221 :
222 0 : x = line->p1.x;
223 0 : dy = line->p2.y - line->p1.y;
224 0 : if (dy != 0) {
225 0 : x += _cairo_fixed_mul_div_floor (y - line->p1.y,
226 0 : line->p2.x - line->p1.x,
227 : dy);
228 : }
229 :
230 0 : return x;
231 : }
232 :
233 : /*
234 : * We need to compare the x-coordinates of a pair of lines for a particular y,
235 : * without loss of precision.
236 : *
237 : * The x-coordinate along an edge for a given y is:
238 : * X = A_x + (Y - A_y) * A_dx / A_dy
239 : *
240 : * So the inequality we wish to test is:
241 : * A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy,
242 : * where ∘ is our inequality operator.
243 : *
244 : * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
245 : * all positive, so we can rearrange it thus without causing a sign change:
246 : * A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy
247 : * - (Y - A_y) * A_dx * B_dy
248 : *
249 : * Given the assumption that all the deltas fit within 32 bits, we can compute
250 : * this comparison directly using 128 bit arithmetic. For certain, but common,
251 : * input we can reduce this down to a single 32 bit compare by inspecting the
252 : * deltas.
253 : *
254 : * (And put the burden of the work on developing fast 128 bit ops, which are
255 : * required throughout the tessellator.)
256 : *
257 : * See the similar discussion for _slope_compare().
258 : */
259 : static int
260 0 : edges_compare_x_for_y_general (const cairo_edge_t *a,
261 : const cairo_edge_t *b,
262 : int32_t y)
263 : {
264 : /* XXX: We're assuming here that dx and dy will still fit in 32
265 : * bits. That's not true in general as there could be overflow. We
266 : * should prevent that before the tessellation algorithm
267 : * begins.
268 : */
269 : int32_t dx;
270 : int32_t adx, ady;
271 : int32_t bdx, bdy;
272 : enum {
273 : HAVE_NONE = 0x0,
274 : HAVE_DX = 0x1,
275 : HAVE_ADX = 0x2,
276 : HAVE_DX_ADX = HAVE_DX | HAVE_ADX,
277 : HAVE_BDX = 0x4,
278 : HAVE_DX_BDX = HAVE_DX | HAVE_BDX,
279 : HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
280 : HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX
281 0 : } have_dx_adx_bdx = HAVE_ALL;
282 :
283 : /* don't bother solving for abscissa if the edges' bounding boxes
284 : * can be used to order them. */
285 : {
286 : int32_t amin, amax;
287 : int32_t bmin, bmax;
288 0 : if (a->line.p1.x < a->line.p2.x) {
289 0 : amin = a->line.p1.x;
290 0 : amax = a->line.p2.x;
291 : } else {
292 0 : amin = a->line.p2.x;
293 0 : amax = a->line.p1.x;
294 : }
295 0 : if (b->line.p1.x < b->line.p2.x) {
296 0 : bmin = b->line.p1.x;
297 0 : bmax = b->line.p2.x;
298 : } else {
299 0 : bmin = b->line.p2.x;
300 0 : bmax = b->line.p1.x;
301 : }
302 0 : if (amax < bmin) return -1;
303 0 : if (amin > bmax) return +1;
304 : }
305 :
306 0 : ady = a->line.p2.y - a->line.p1.y;
307 0 : adx = a->line.p2.x - a->line.p1.x;
308 0 : if (adx == 0)
309 0 : have_dx_adx_bdx &= ~HAVE_ADX;
310 :
311 0 : bdy = b->line.p2.y - b->line.p1.y;
312 0 : bdx = b->line.p2.x - b->line.p1.x;
313 0 : if (bdx == 0)
314 0 : have_dx_adx_bdx &= ~HAVE_BDX;
315 :
316 0 : dx = a->line.p1.x - b->line.p1.x;
317 0 : if (dx == 0)
318 0 : have_dx_adx_bdx &= ~HAVE_DX;
319 :
320 : #define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
321 : #define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->line.p1.y)
322 : #define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->line.p1.y)
323 0 : switch (have_dx_adx_bdx) {
324 : default:
325 : case HAVE_NONE:
326 0 : return 0;
327 : case HAVE_DX:
328 : /* A_dy * B_dy * (A_x - B_x) ∘ 0 */
329 0 : return dx; /* ady * bdy is positive definite */
330 : case HAVE_ADX:
331 : /* 0 ∘ - (Y - A_y) * A_dx * B_dy */
332 0 : return adx; /* bdy * (y - a->top.y) is positive definite */
333 : case HAVE_BDX:
334 : /* 0 ∘ (Y - B_y) * B_dx * A_dy */
335 0 : return -bdx; /* ady * (y - b->top.y) is positive definite */
336 : case HAVE_ADX_BDX:
337 : /* 0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
338 0 : if ((adx ^ bdx) < 0) {
339 0 : return adx;
340 0 : } else if (a->line.p1.y == b->line.p1.y) { /* common origin */
341 : cairo_int64_t adx_bdy, bdx_ady;
342 :
343 : /* ∴ A_dx * B_dy ∘ B_dx * A_dy */
344 :
345 0 : adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
346 0 : bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
347 :
348 0 : return _cairo_int64_cmp (adx_bdy, bdx_ady);
349 : } else
350 0 : return _cairo_int128_cmp (A, B);
351 : case HAVE_DX_ADX:
352 : /* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
353 0 : if ((-adx ^ dx) < 0) {
354 0 : return dx;
355 : } else {
356 : cairo_int64_t ady_dx, dy_adx;
357 :
358 0 : ady_dx = _cairo_int32x32_64_mul (ady, dx);
359 0 : dy_adx = _cairo_int32x32_64_mul (a->line.p1.y - y, adx);
360 :
361 0 : return _cairo_int64_cmp (ady_dx, dy_adx);
362 : }
363 : case HAVE_DX_BDX:
364 : /* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
365 0 : if ((bdx ^ dx) < 0) {
366 0 : return dx;
367 : } else {
368 : cairo_int64_t bdy_dx, dy_bdx;
369 :
370 0 : bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
371 0 : dy_bdx = _cairo_int32x32_64_mul (y - b->line.p1.y, bdx);
372 :
373 0 : return _cairo_int64_cmp (bdy_dx, dy_bdx);
374 : }
375 : case HAVE_ALL:
376 : /* XXX try comparing (a->line.p2.x - b->line.p2.x) et al */
377 0 : return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
378 : }
379 : #undef B
380 : #undef A
381 : #undef L
382 : }
383 :
384 : /*
385 : * We need to compare the x-coordinate of a line for a particular y wrt to a
386 : * given x, without loss of precision.
387 : *
388 : * The x-coordinate along an edge for a given y is:
389 : * X = A_x + (Y - A_y) * A_dx / A_dy
390 : *
391 : * So the inequality we wish to test is:
392 : * A_x + (Y - A_y) * A_dx / A_dy ∘ X
393 : * where ∘ is our inequality operator.
394 : *
395 : * By construction, we know that A_dy (and (Y - A_y)) are
396 : * all positive, so we can rearrange it thus without causing a sign change:
397 : * (Y - A_y) * A_dx ∘ (X - A_x) * A_dy
398 : *
399 : * Given the assumption that all the deltas fit within 32 bits, we can compute
400 : * this comparison directly using 64 bit arithmetic.
401 : *
402 : * See the similar discussion for _slope_compare() and
403 : * edges_compare_x_for_y_general().
404 : */
405 : static int
406 0 : edge_compare_for_y_against_x (const cairo_edge_t *a,
407 : int32_t y,
408 : int32_t x)
409 : {
410 : int32_t adx, ady;
411 : int32_t dx, dy;
412 : cairo_int64_t L, R;
413 :
414 0 : if (a->line.p1.x <= a->line.p2.x) {
415 0 : if (x < a->line.p1.x)
416 0 : return 1;
417 0 : if (x > a->line.p2.x)
418 0 : return -1;
419 : } else {
420 0 : if (x < a->line.p2.x)
421 0 : return 1;
422 0 : if (x > a->line.p1.x)
423 0 : return -1;
424 : }
425 :
426 0 : adx = a->line.p2.x - a->line.p1.x;
427 0 : dx = x - a->line.p1.x;
428 :
429 0 : if (adx == 0)
430 0 : return -dx;
431 0 : if (dx == 0 || (adx ^ dx) < 0)
432 0 : return adx;
433 :
434 0 : dy = y - a->line.p1.y;
435 0 : ady = a->line.p2.y - a->line.p1.y;
436 :
437 0 : L = _cairo_int32x32_64_mul (dy, adx);
438 0 : R = _cairo_int32x32_64_mul (dx, ady);
439 :
440 0 : return _cairo_int64_cmp (L, R);
441 : }
442 :
443 : static int
444 0 : edges_compare_x_for_y (const cairo_edge_t *a,
445 : const cairo_edge_t *b,
446 : int32_t y)
447 : {
448 : /* If the sweep-line is currently on an end-point of a line,
449 : * then we know its precise x value (and considering that we often need to
450 : * compare events at end-points, this happens frequently enough to warrant
451 : * special casing).
452 : */
453 : enum {
454 : HAVE_NEITHER = 0x0,
455 : HAVE_AX = 0x1,
456 : HAVE_BX = 0x2,
457 : HAVE_BOTH = HAVE_AX | HAVE_BX
458 0 : } have_ax_bx = HAVE_BOTH;
459 : int32_t ax, bx;
460 :
461 : /* XXX given we have x and dx? */
462 :
463 0 : if (y == a->line.p1.y)
464 0 : ax = a->line.p1.x;
465 0 : else if (y == a->line.p2.y)
466 0 : ax = a->line.p2.x;
467 : else
468 0 : have_ax_bx &= ~HAVE_AX;
469 :
470 0 : if (y == b->line.p1.y)
471 0 : bx = b->line.p1.x;
472 0 : else if (y == b->line.p2.y)
473 0 : bx = b->line.p2.x;
474 : else
475 0 : have_ax_bx &= ~HAVE_BX;
476 :
477 0 : switch (have_ax_bx) {
478 : default:
479 : case HAVE_NEITHER:
480 0 : return edges_compare_x_for_y_general (a, b, y);
481 : case HAVE_AX:
482 0 : return -edge_compare_for_y_against_x (b, y, ax);
483 : case HAVE_BX:
484 0 : return edge_compare_for_y_against_x (a, y, bx);
485 : case HAVE_BOTH:
486 0 : return ax - bx;
487 : }
488 : }
489 :
490 : static inline int
491 0 : slope_compare (const edge_t *a,
492 : const edge_t *b)
493 : {
494 : cairo_int64_t L, R;
495 : int cmp;
496 :
497 0 : cmp = a->dxdy.quo - b->dxdy.quo;
498 0 : if (cmp)
499 0 : return cmp;
500 :
501 0 : if (a->dxdy.rem == 0)
502 0 : return -b->dxdy.rem;
503 0 : if (b->dxdy.rem == 0)
504 0 : return a->dxdy.rem;
505 :
506 0 : L = _cairo_int32x32_64_mul (b->dy, a->dxdy.rem);
507 0 : R = _cairo_int32x32_64_mul (a->dy, b->dxdy.rem);
508 0 : return _cairo_int64_cmp (L, R);
509 : }
510 :
511 : static inline int
512 0 : line_equal (const cairo_line_t *a, const cairo_line_t *b)
513 : {
514 0 : return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
515 0 : a->p2.x == b->p2.x && a->p2.y == b->p2.y;
516 : }
517 :
518 : static inline int
519 0 : sweep_line_compare_edges (const edge_t *a,
520 : const edge_t *b,
521 : cairo_fixed_t y)
522 : {
523 : int cmp;
524 :
525 0 : if (line_equal (&a->edge.line, &b->edge.line))
526 0 : return 0;
527 :
528 0 : cmp = edges_compare_x_for_y (&a->edge, &b->edge, y);
529 0 : if (cmp)
530 0 : return cmp;
531 :
532 0 : return slope_compare (a, b);
533 : }
534 :
535 : static inline cairo_int64_t
536 0 : det32_64 (int32_t a, int32_t b,
537 : int32_t c, int32_t d)
538 : {
539 : /* det = a * d - b * c */
540 0 : return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d),
541 : _cairo_int32x32_64_mul (b, c));
542 : }
543 :
544 : static inline cairo_int128_t
545 0 : det64x32_128 (cairo_int64_t a, int32_t b,
546 : cairo_int64_t c, int32_t d)
547 : {
548 : /* det = a * d - b * c */
549 0 : return _cairo_int128_sub (_cairo_int64x32_128_mul (a, d),
550 : _cairo_int64x32_128_mul (c, b));
551 : }
552 :
553 : /* Compute the intersection of two lines as defined by two edges. The
554 : * result is provided as a coordinate pair of 128-bit integers.
555 : *
556 : * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or
557 : * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel.
558 : */
559 : static cairo_bool_t
560 0 : intersect_lines (const edge_t *a, const edge_t *b,
561 : cairo_bo_intersect_point_t *intersection)
562 : {
563 : cairo_int64_t a_det, b_det;
564 :
565 : /* XXX: We're assuming here that dx and dy will still fit in 32
566 : * bits. That's not true in general as there could be overflow. We
567 : * should prevent that before the tessellation algorithm begins.
568 : * What we're doing to mitigate this is to perform clamping in
569 : * cairo_bo_tessellate_polygon().
570 : */
571 0 : int32_t dx1 = a->edge.line.p1.x - a->edge.line.p2.x;
572 0 : int32_t dy1 = a->edge.line.p1.y - a->edge.line.p2.y;
573 :
574 0 : int32_t dx2 = b->edge.line.p1.x - b->edge.line.p2.x;
575 0 : int32_t dy2 = b->edge.line.p1.y - b->edge.line.p2.y;
576 :
577 : cairo_int64_t den_det;
578 : cairo_int64_t R;
579 : cairo_quorem64_t qr;
580 :
581 0 : den_det = det32_64 (dx1, dy1, dx2, dy2);
582 :
583 : /* Q: Can we determine that the lines do not intersect (within range)
584 : * much more cheaply than computing the intersection point i.e. by
585 : * avoiding the division?
586 : *
587 : * X = ax + t * adx = bx + s * bdx;
588 : * Y = ay + t * ady = by + s * bdy;
589 : * ∴ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
590 : * => t * L = R
591 : *
592 : * Therefore we can reject any intersection (under the criteria for
593 : * valid intersection events) if:
594 : * L^R < 0 => t < 0, or
595 : * L<R => t > 1
596 : *
597 : * (where top/bottom must at least extend to the line endpoints).
598 : *
599 : * A similar substitution can be performed for s, yielding:
600 : * s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
601 : */
602 0 : R = det32_64 (dx2, dy2,
603 0 : b->edge.line.p1.x - a->edge.line.p1.x,
604 0 : b->edge.line.p1.y - a->edge.line.p1.y);
605 0 : if (_cairo_int64_negative (den_det)) {
606 0 : if (_cairo_int64_ge (den_det, R))
607 0 : return FALSE;
608 : } else {
609 0 : if (_cairo_int64_le (den_det, R))
610 0 : return FALSE;
611 : }
612 :
613 0 : R = det32_64 (dy1, dx1,
614 0 : a->edge.line.p1.y - b->edge.line.p1.y,
615 0 : a->edge.line.p1.x - b->edge.line.p1.x);
616 0 : if (_cairo_int64_negative (den_det)) {
617 0 : if (_cairo_int64_ge (den_det, R))
618 0 : return FALSE;
619 : } else {
620 0 : if (_cairo_int64_le (den_det, R))
621 0 : return FALSE;
622 : }
623 :
624 : /* We now know that the two lines should intersect within range. */
625 :
626 0 : a_det = det32_64 (a->edge.line.p1.x, a->edge.line.p1.y,
627 : a->edge.line.p2.x, a->edge.line.p2.y);
628 0 : b_det = det32_64 (b->edge.line.p1.x, b->edge.line.p1.y,
629 : b->edge.line.p2.x, b->edge.line.p2.y);
630 :
631 : /* x = det (a_det, dx1, b_det, dx2) / den_det */
632 0 : qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
633 : b_det, dx2),
634 : den_det);
635 0 : if (_cairo_int64_eq (qr.rem, den_det))
636 0 : return FALSE;
637 : #if 0
638 : intersection->x.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
639 : #else
640 0 : intersection->x.exactness = EXACT;
641 0 : if (! _cairo_int64_is_zero (qr.rem)) {
642 0 : if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (qr.rem))
643 0 : qr.rem = _cairo_int64_negate (qr.rem);
644 0 : qr.rem = _cairo_int64_mul (qr.rem, _cairo_int32_to_int64 (2));
645 0 : if (_cairo_int64_ge (qr.rem, den_det)) {
646 0 : qr.quo = _cairo_int64_add (qr.quo,
647 : _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
648 : } else
649 0 : intersection->x.exactness = INEXACT;
650 : }
651 : #endif
652 0 : intersection->x.ordinate = _cairo_int64_to_int32 (qr.quo);
653 :
654 : /* y = det (a_det, dy1, b_det, dy2) / den_det */
655 0 : qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1,
656 : b_det, dy2),
657 : den_det);
658 0 : if (_cairo_int64_eq (qr.rem, den_det))
659 0 : return FALSE;
660 : #if 0
661 : intersection->y.exactness = _cairo_int64_is_zero (qr.rem) ? EXACT : INEXACT;
662 : #else
663 0 : intersection->y.exactness = EXACT;
664 0 : if (! _cairo_int64_is_zero (qr.rem)) {
665 : /* compute ceiling away from zero */
666 0 : qr.quo = _cairo_int64_add (qr.quo,
667 : _cairo_int32_to_int64 (_cairo_int64_negative (qr.quo) ? -1 : 1));
668 0 : intersection->y.exactness = INEXACT;
669 : }
670 : #endif
671 0 : intersection->y.ordinate = _cairo_int64_to_int32 (qr.quo);
672 :
673 0 : return TRUE;
674 : }
675 :
676 : static int
677 0 : bo_intersect_ordinate_32_compare (int32_t a, int32_t b, int exactness)
678 : {
679 : int cmp;
680 :
681 : /* First compare the quotient */
682 0 : cmp = a - b;
683 0 : if (cmp)
684 0 : return cmp;
685 :
686 : /* With quotient identical, if remainder is 0 then compare equal */
687 : /* Otherwise, the non-zero remainder makes a > b */
688 0 : return -(INEXACT == exactness);
689 : }
690 :
691 : /* Does the given edge contain the given point. The point must already
692 : * be known to be contained within the line determined by the edge,
693 : * (most likely the point results from an intersection of this edge
694 : * with another).
695 : *
696 : * If we had exact arithmetic, then this function would simply be a
697 : * matter of examining whether the y value of the point lies within
698 : * the range of y values of the edge. But since intersection points
699 : * are not exact due to being rounded to the nearest integer within
700 : * the available precision, we must also examine the x value of the
701 : * point.
702 : *
703 : * The definition of "contains" here is that the given intersection
704 : * point will be seen by the sweep line after the start event for the
705 : * given edge and before the stop event for the edge. See the comments
706 : * in the implementation for more details.
707 : */
708 : static cairo_bool_t
709 0 : bo_edge_contains_intersect_point (const edge_t *edge,
710 : cairo_bo_intersect_point_t *point)
711 : {
712 : int cmp_top, cmp_bottom;
713 :
714 : /* XXX: When running the actual algorithm, we don't actually need to
715 : * compare against edge->top at all here, since any intersection above
716 : * top is eliminated early via a slope comparison. We're leaving these
717 : * here for now only for the sake of the quadratic-time intersection
718 : * finder which needs them.
719 : */
720 :
721 0 : cmp_top = bo_intersect_ordinate_32_compare (point->y.ordinate,
722 : edge->edge.top,
723 0 : point->y.exactness);
724 0 : if (cmp_top < 0)
725 0 : return FALSE;
726 :
727 0 : cmp_bottom = bo_intersect_ordinate_32_compare (point->y.ordinate,
728 : edge->edge.bottom,
729 0 : point->y.exactness);
730 0 : if (cmp_bottom > 0)
731 0 : return FALSE;
732 :
733 0 : if (cmp_top > 0 && cmp_bottom < 0)
734 0 : return TRUE;
735 :
736 : /* At this stage, the point lies on the same y value as either
737 : * edge->top or edge->bottom, so we have to examine the x value in
738 : * order to properly determine containment. */
739 :
740 : /* If the y value of the point is the same as the y value of the
741 : * top of the edge, then the x value of the point must be greater
742 : * to be considered as inside the edge. Similarly, if the y value
743 : * of the point is the same as the y value of the bottom of the
744 : * edge, then the x value of the point must be less to be
745 : * considered as inside. */
746 :
747 0 : if (cmp_top == 0) {
748 : cairo_fixed_t top_x;
749 :
750 0 : top_x = line_compute_intersection_x_for_y (&edge->edge.line,
751 : edge->edge.top);
752 0 : return bo_intersect_ordinate_32_compare (top_x, point->x.ordinate, point->x.exactness) < 0;
753 : } else { /* cmp_bottom == 0 */
754 : cairo_fixed_t bot_x;
755 :
756 0 : bot_x = line_compute_intersection_x_for_y (&edge->edge.line,
757 : edge->edge.bottom);
758 0 : return bo_intersect_ordinate_32_compare (point->x.ordinate, bot_x, point->x.exactness) < 0;
759 : }
760 : }
761 :
762 : static cairo_bool_t
763 0 : edge_intersect (const edge_t *a,
764 : const edge_t *b,
765 : cairo_point_t *intersection)
766 : {
767 : cairo_bo_intersect_point_t quorem;
768 :
769 0 : if (! intersect_lines (a, b, &quorem))
770 0 : return FALSE;
771 :
772 0 : if (a->edge.top != a->edge.line.p1.y || a->edge.bottom != a->edge.line.p2.y) {
773 0 : if (! bo_edge_contains_intersect_point (a, &quorem))
774 0 : return FALSE;
775 : }
776 :
777 0 : if (b->edge.top != b->edge.line.p1.y || b->edge.bottom != b->edge.line.p2.y) {
778 0 : if (! bo_edge_contains_intersect_point (b, &quorem))
779 0 : return FALSE;
780 : }
781 :
782 : /* Now that we've correctly compared the intersection point and
783 : * determined that it lies within the edge, then we know that we
784 : * no longer need any more bits of storage for the intersection
785 : * than we do for our edge coordinates. We also no longer need the
786 : * remainder from the division. */
787 0 : intersection->x = quorem.x.ordinate;
788 0 : intersection->y = quorem.y.ordinate;
789 :
790 0 : return TRUE;
791 : }
792 :
793 : static inline int
794 0 : event_compare (const event_t *a, const event_t *b)
795 : {
796 0 : return a->y - b->y;
797 : }
798 :
799 : static void
800 0 : pqueue_init (pqueue_t *pq)
801 : {
802 0 : pq->max_size = ARRAY_LENGTH (pq->elements_embedded);
803 0 : pq->size = 0;
804 :
805 0 : pq->elements = pq->elements_embedded;
806 0 : }
807 :
808 : static void
809 0 : pqueue_fini (pqueue_t *pq)
810 : {
811 0 : if (pq->elements != pq->elements_embedded)
812 0 : free (pq->elements);
813 0 : }
814 :
815 : static cairo_bool_t
816 0 : pqueue_grow (pqueue_t *pq)
817 : {
818 : event_t **new_elements;
819 0 : pq->max_size *= 2;
820 :
821 0 : if (pq->elements == pq->elements_embedded) {
822 0 : new_elements = _cairo_malloc_ab (pq->max_size,
823 : sizeof (event_t *));
824 0 : if (unlikely (new_elements == NULL))
825 0 : return FALSE;
826 :
827 0 : memcpy (new_elements, pq->elements_embedded,
828 : sizeof (pq->elements_embedded));
829 : } else {
830 0 : new_elements = _cairo_realloc_ab (pq->elements,
831 : pq->max_size,
832 : sizeof (event_t *));
833 0 : if (unlikely (new_elements == NULL))
834 0 : return FALSE;
835 : }
836 :
837 0 : pq->elements = new_elements;
838 0 : return TRUE;
839 : }
840 :
841 : static inline void
842 0 : pqueue_push (sweep_line_t *sweep_line, event_t *event)
843 : {
844 : event_t **elements;
845 : int i, parent;
846 :
847 0 : if (unlikely (sweep_line->queue.pq.size + 1 == sweep_line->queue.pq.max_size)) {
848 0 : if (unlikely (! pqueue_grow (&sweep_line->queue.pq))) {
849 0 : longjmp (sweep_line->unwind,
850 0 : _cairo_error (CAIRO_STATUS_NO_MEMORY));
851 : }
852 : }
853 :
854 0 : elements = sweep_line->queue.pq.elements;
855 0 : for (i = ++sweep_line->queue.pq.size;
856 0 : i != PQ_FIRST_ENTRY &&
857 0 : event_compare (event,
858 0 : elements[parent = PQ_PARENT_INDEX (i)]) < 0;
859 0 : i = parent)
860 : {
861 0 : elements[i] = elements[parent];
862 : }
863 :
864 0 : elements[i] = event;
865 0 : }
866 :
867 : static inline void
868 0 : pqueue_pop (pqueue_t *pq)
869 : {
870 0 : event_t **elements = pq->elements;
871 : event_t *tail;
872 : int child, i;
873 :
874 0 : tail = elements[pq->size--];
875 0 : if (pq->size == 0) {
876 0 : elements[PQ_FIRST_ENTRY] = NULL;
877 0 : return;
878 : }
879 :
880 0 : for (i = PQ_FIRST_ENTRY;
881 0 : (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size;
882 0 : i = child)
883 : {
884 0 : if (child != pq->size &&
885 0 : event_compare (elements[child+1],
886 0 : elements[child]) < 0)
887 : {
888 0 : child++;
889 : }
890 :
891 0 : if (event_compare (elements[child], tail) >= 0)
892 0 : break;
893 :
894 0 : elements[i] = elements[child];
895 : }
896 0 : elements[i] = tail;
897 : }
898 :
899 : static inline void
900 0 : event_insert (sweep_line_t *sweep_line,
901 : event_type_t type,
902 : edge_t *e1,
903 : edge_t *e2,
904 : cairo_fixed_t y)
905 : {
906 : queue_event_t *event;
907 :
908 0 : event = _cairo_freepool_alloc (&sweep_line->queue.pool);
909 0 : if (unlikely (event == NULL)) {
910 0 : longjmp (sweep_line->unwind,
911 0 : _cairo_error (CAIRO_STATUS_NO_MEMORY));
912 : }
913 :
914 0 : event->y = y;
915 0 : event->type = type;
916 0 : event->e1 = e1;
917 0 : event->e2 = e2;
918 :
919 0 : pqueue_push (sweep_line, (event_t *) event);
920 0 : }
921 :
922 : static void
923 0 : event_delete (sweep_line_t *sweep_line,
924 : event_t *event)
925 : {
926 0 : _cairo_freepool_free (&sweep_line->queue.pool, event);
927 0 : }
928 :
929 : static inline event_t *
930 0 : event_next (sweep_line_t *sweep_line)
931 : {
932 : event_t *event, *cmp;
933 :
934 0 : event = sweep_line->queue.pq.elements[PQ_FIRST_ENTRY];
935 0 : cmp = *sweep_line->queue.start_events;
936 0 : if (event == NULL ||
937 0 : (cmp != NULL && event_compare (cmp, event) < 0))
938 : {
939 0 : event = cmp;
940 0 : sweep_line->queue.start_events++;
941 : }
942 : else
943 : {
944 0 : pqueue_pop (&sweep_line->queue.pq);
945 : }
946 :
947 0 : return event;
948 : }
949 :
950 0 : CAIRO_COMBSORT_DECLARE (start_event_sort, event_t *, event_compare)
951 :
952 : static inline void
953 0 : event_insert_stop (sweep_line_t *sweep_line,
954 : edge_t *edge)
955 : {
956 0 : event_insert (sweep_line,
957 : EVENT_TYPE_STOP,
958 : edge, NULL,
959 : edge->edge.bottom);
960 0 : }
961 :
962 : static inline void
963 0 : event_insert_if_intersect_below_current_y (sweep_line_t *sweep_line,
964 : edge_t *left,
965 : edge_t *right)
966 : {
967 : cairo_point_t intersection;
968 :
969 : /* start points intersect */
970 0 : if (left->edge.line.p1.x == right->edge.line.p1.x &&
971 0 : left->edge.line.p1.y == right->edge.line.p1.y)
972 : {
973 0 : return;
974 : }
975 :
976 : /* end points intersect, process DELETE events first */
977 0 : if (left->edge.line.p2.x == right->edge.line.p2.x &&
978 0 : left->edge.line.p2.y == right->edge.line.p2.y)
979 : {
980 0 : return;
981 : }
982 :
983 0 : if (slope_compare (left, right) <= 0)
984 0 : return;
985 :
986 0 : if (! edge_intersect (left, right, &intersection))
987 0 : return;
988 :
989 0 : event_insert (sweep_line,
990 : EVENT_TYPE_INTERSECTION,
991 : left, right,
992 : intersection.y);
993 : }
994 :
995 : static inline edge_t *
996 0 : link_to_edge (cairo_list_t *link)
997 : {
998 0 : return (edge_t *) link;
999 : }
1000 :
1001 : static void
1002 0 : sweep_line_insert (sweep_line_t *sweep_line,
1003 : edge_t *edge)
1004 : {
1005 : cairo_list_t *pos;
1006 0 : cairo_fixed_t y = sweep_line->current_subrow;
1007 :
1008 0 : pos = sweep_line->insert_cursor;
1009 0 : if (pos == &sweep_line->active)
1010 0 : pos = sweep_line->active.next;
1011 0 : if (pos != &sweep_line->active) {
1012 : int cmp;
1013 :
1014 0 : cmp = sweep_line_compare_edges (link_to_edge (pos),
1015 : edge,
1016 : y);
1017 0 : if (cmp < 0) {
1018 0 : while (pos->next != &sweep_line->active &&
1019 0 : sweep_line_compare_edges (link_to_edge (pos->next),
1020 : edge,
1021 : y) < 0)
1022 : {
1023 0 : pos = pos->next;
1024 : }
1025 0 : } else if (cmp > 0) {
1026 : do {
1027 0 : pos = pos->prev;
1028 0 : } while (pos != &sweep_line->active &&
1029 0 : sweep_line_compare_edges (link_to_edge (pos),
1030 : edge,
1031 0 : y) > 0);
1032 : }
1033 : }
1034 0 : cairo_list_add (&edge->link, pos);
1035 0 : sweep_line->insert_cursor = &edge->link;
1036 0 : }
1037 :
1038 : inline static void
1039 0 : coverage_rewind (struct coverage *cells)
1040 : {
1041 0 : cells->cursor = &cells->head;
1042 0 : }
1043 :
1044 : static void
1045 0 : coverage_init (struct coverage *cells)
1046 : {
1047 0 : _cairo_freepool_init (&cells->pool,
1048 : sizeof (struct cell));
1049 0 : cells->head.prev = NULL;
1050 0 : cells->head.next = &cells->tail;
1051 0 : cells->head.x = INT_MIN;
1052 0 : cells->tail.prev = &cells->head;
1053 0 : cells->tail.next = NULL;
1054 0 : cells->tail.x = INT_MAX;
1055 0 : cells->count = 0;
1056 0 : coverage_rewind (cells);
1057 0 : }
1058 :
1059 : static void
1060 0 : coverage_fini (struct coverage *cells)
1061 : {
1062 0 : _cairo_freepool_fini (&cells->pool);
1063 0 : }
1064 :
1065 : inline static void
1066 0 : coverage_reset (struct coverage *cells)
1067 : {
1068 0 : cells->head.next = &cells->tail;
1069 0 : cells->tail.prev = &cells->head;
1070 0 : cells->count = 0;
1071 0 : _cairo_freepool_reset (&cells->pool);
1072 0 : coverage_rewind (cells);
1073 0 : }
1074 :
1075 : inline static struct cell *
1076 0 : coverage_alloc (sweep_line_t *sweep_line,
1077 : struct cell *tail,
1078 : int x)
1079 : {
1080 : struct cell *cell;
1081 :
1082 0 : cell = _cairo_freepool_alloc (&sweep_line->coverage.pool);
1083 0 : if (unlikely (NULL == cell)) {
1084 0 : longjmp (sweep_line->unwind,
1085 0 : _cairo_error (CAIRO_STATUS_NO_MEMORY));
1086 : }
1087 :
1088 0 : tail->prev->next = cell;
1089 0 : cell->prev = tail->prev;
1090 0 : cell->next = tail;
1091 0 : tail->prev = cell;
1092 0 : cell->x = x;
1093 0 : cell->uncovered_area = 0;
1094 0 : cell->covered_height = 0;
1095 0 : sweep_line->coverage.count++;
1096 0 : return cell;
1097 : }
1098 :
1099 : inline static struct cell *
1100 0 : coverage_find (sweep_line_t *sweep_line, int x)
1101 : {
1102 : struct cell *cell;
1103 :
1104 0 : cell = sweep_line->coverage.cursor;
1105 0 : if (unlikely (cell->x > x)) {
1106 : do {
1107 0 : if (cell->prev->x < x)
1108 0 : break;
1109 0 : cell = cell->prev;
1110 : } while (TRUE);
1111 : } else {
1112 0 : if (cell->x == x)
1113 0 : return cell;
1114 :
1115 : do {
1116 0 : UNROLL3({
1117 : cell = cell->next;
1118 : if (cell->x >= x)
1119 : break;
1120 : });
1121 : } while (TRUE);
1122 : }
1123 :
1124 0 : if (cell->x != x)
1125 0 : cell = coverage_alloc (sweep_line, cell, x);
1126 :
1127 0 : return sweep_line->coverage.cursor = cell;
1128 : }
1129 :
1130 : static void
1131 0 : coverage_render_cells (sweep_line_t *sweep_line,
1132 : cairo_fixed_t left, cairo_fixed_t right,
1133 : cairo_fixed_t y1, cairo_fixed_t y2,
1134 : int sign)
1135 : {
1136 : int fx1, fx2;
1137 : int ix1, ix2;
1138 : int dx, dy;
1139 :
1140 : /* Orient the edge left-to-right. */
1141 0 : dx = right - left;
1142 0 : if (dx >= 0) {
1143 0 : ix1 = _cairo_fixed_integer_part (left);
1144 0 : fx1 = _cairo_fixed_fractional_part (left);
1145 :
1146 0 : ix2 = _cairo_fixed_integer_part (right);
1147 0 : fx2 = _cairo_fixed_fractional_part (right);
1148 :
1149 0 : dy = y2 - y1;
1150 : } else {
1151 0 : ix1 = _cairo_fixed_integer_part (right);
1152 0 : fx1 = _cairo_fixed_fractional_part (right);
1153 :
1154 0 : ix2 = _cairo_fixed_integer_part (left);
1155 0 : fx2 = _cairo_fixed_fractional_part (left);
1156 :
1157 0 : dx = -dx;
1158 0 : sign = -sign;
1159 0 : dy = y1 - y2;
1160 0 : y1 = y2 - dy;
1161 0 : y2 = y1 + dy;
1162 : }
1163 :
1164 : /* Add coverage for all pixels [ix1,ix2] on this row crossed
1165 : * by the edge. */
1166 : {
1167 0 : struct quorem y = floored_divrem ((STEP_X - fx1)*dy, dx);
1168 : struct cell *cell;
1169 :
1170 0 : cell = sweep_line->coverage.cursor;
1171 0 : if (cell->x != ix1) {
1172 0 : if (unlikely (cell->x > ix1)) {
1173 : do {
1174 0 : if (cell->prev->x < ix1)
1175 0 : break;
1176 0 : cell = cell->prev;
1177 : } while (TRUE);
1178 : } else do {
1179 0 : UNROLL3({
1180 : if (cell->x >= ix1)
1181 : break;
1182 : cell = cell->next;
1183 : });
1184 : } while (TRUE);
1185 :
1186 0 : if (cell->x != ix1)
1187 0 : cell = coverage_alloc (sweep_line, cell, ix1);
1188 : }
1189 :
1190 0 : cell->uncovered_area += sign * y.quo * (STEP_X + fx1);
1191 0 : cell->covered_height += sign * y.quo;
1192 0 : y.quo += y1;
1193 :
1194 0 : cell = cell->next;
1195 0 : if (cell->x != ++ix1)
1196 0 : cell = coverage_alloc (sweep_line, cell, ix1);
1197 0 : if (ix1 < ix2) {
1198 0 : struct quorem dydx_full = floored_divrem (STEP_X*dy, dx);
1199 :
1200 : do {
1201 0 : cairo_fixed_t y_skip = dydx_full.quo;
1202 0 : y.rem += dydx_full.rem;
1203 0 : if (y.rem >= dx) {
1204 0 : ++y_skip;
1205 0 : y.rem -= dx;
1206 : }
1207 :
1208 0 : y.quo += y_skip;
1209 :
1210 0 : y_skip *= sign;
1211 0 : cell->covered_height += y_skip;
1212 0 : cell->uncovered_area += y_skip*STEP_X;
1213 :
1214 0 : cell = cell->next;
1215 0 : if (cell->x != ++ix1)
1216 0 : cell = coverage_alloc (sweep_line, cell, ix1);
1217 0 : } while (ix1 != ix2);
1218 : }
1219 0 : cell->uncovered_area += sign*(y2 - y.quo)*fx2;
1220 0 : cell->covered_height += sign*(y2 - y.quo);
1221 0 : sweep_line->coverage.cursor = cell;
1222 : }
1223 0 : }
1224 :
1225 : inline static void
1226 0 : full_inc_edge (edge_t *edge)
1227 : {
1228 0 : edge->x.quo += edge->dxdy_full.quo;
1229 0 : edge->x.rem += edge->dxdy_full.rem;
1230 0 : if (edge->x.rem >= 0) {
1231 0 : ++edge->x.quo;
1232 0 : edge->x.rem -= edge->dy;
1233 : }
1234 0 : }
1235 :
1236 : static void
1237 0 : full_add_edge (sweep_line_t *sweep_line, edge_t *edge, int sign)
1238 : {
1239 : struct cell *cell;
1240 : cairo_fixed_t x1, x2;
1241 : int ix1, ix2;
1242 : int frac;
1243 :
1244 0 : edge->current_sign = sign;
1245 :
1246 0 : ix1 = _cairo_fixed_integer_part (edge->x.quo);
1247 :
1248 0 : if (edge->vertical) {
1249 0 : frac = _cairo_fixed_fractional_part (edge->x.quo);
1250 0 : cell = coverage_find (sweep_line, ix1);
1251 0 : cell->covered_height += sign * STEP_Y;
1252 0 : cell->uncovered_area += sign * 2 * frac * STEP_Y;
1253 0 : return;
1254 : }
1255 :
1256 0 : x1 = edge->x.quo;
1257 0 : full_inc_edge (edge);
1258 0 : x2 = edge->x.quo;
1259 :
1260 0 : ix2 = _cairo_fixed_integer_part (edge->x.quo);
1261 :
1262 : /* Edge is entirely within a column? */
1263 0 : if (likely (ix1 == ix2)) {
1264 0 : frac = _cairo_fixed_fractional_part (x1) +
1265 0 : _cairo_fixed_fractional_part (x2);
1266 0 : cell = coverage_find (sweep_line, ix1);
1267 0 : cell->covered_height += sign * STEP_Y;
1268 0 : cell->uncovered_area += sign * frac * STEP_Y;
1269 0 : return;
1270 : }
1271 :
1272 0 : coverage_render_cells (sweep_line, x1, x2, 0, STEP_Y, sign);
1273 : }
1274 :
1275 : static void
1276 0 : full_nonzero (sweep_line_t *sweep_line)
1277 : {
1278 : cairo_list_t *pos;
1279 :
1280 0 : sweep_line->is_vertical = TRUE;
1281 0 : pos = sweep_line->active.next;
1282 : do {
1283 0 : edge_t *left = link_to_edge (pos), *right;
1284 0 : int winding = left->edge.dir;
1285 :
1286 0 : sweep_line->is_vertical &= left->vertical;
1287 :
1288 0 : pos = left->link.next;
1289 : do {
1290 0 : if (unlikely (pos == &sweep_line->active)) {
1291 0 : full_add_edge (sweep_line, left, +1);
1292 0 : return;
1293 : }
1294 :
1295 0 : right = link_to_edge (pos);
1296 0 : pos = pos->next;
1297 0 : sweep_line->is_vertical &= right->vertical;
1298 :
1299 0 : winding += right->edge.dir;
1300 0 : if (0 == winding) {
1301 0 : if (pos == &sweep_line->active ||
1302 0 : link_to_edge (pos)->x.quo != right->x.quo)
1303 : {
1304 : break;
1305 : }
1306 : }
1307 :
1308 0 : if (! right->vertical)
1309 0 : full_inc_edge (right);
1310 : } while (TRUE);
1311 :
1312 0 : full_add_edge (sweep_line, left, +1);
1313 0 : full_add_edge (sweep_line, right, -1);
1314 0 : } while (pos != &sweep_line->active);
1315 : }
1316 :
1317 : static void
1318 0 : full_evenodd (sweep_line_t *sweep_line)
1319 : {
1320 : cairo_list_t *pos;
1321 :
1322 0 : sweep_line->is_vertical = TRUE;
1323 0 : pos = sweep_line->active.next;
1324 : do {
1325 0 : edge_t *left = link_to_edge (pos), *right;
1326 0 : int winding = 0;
1327 :
1328 0 : sweep_line->is_vertical &= left->vertical;
1329 :
1330 0 : pos = left->link.next;
1331 : do {
1332 0 : if (pos == &sweep_line->active) {
1333 0 : full_add_edge (sweep_line, left, +1);
1334 0 : return;
1335 : }
1336 :
1337 0 : right = link_to_edge (pos);
1338 0 : pos = pos->next;
1339 0 : sweep_line->is_vertical &= right->vertical;
1340 :
1341 0 : if (++winding & 1) {
1342 0 : if (pos == &sweep_line->active ||
1343 0 : link_to_edge (pos)->x.quo != right->x.quo)
1344 : {
1345 : break;
1346 : }
1347 : }
1348 :
1349 0 : if (! right->vertical)
1350 0 : full_inc_edge (right);
1351 : } while (TRUE);
1352 :
1353 0 : full_add_edge (sweep_line, left, +1);
1354 0 : full_add_edge (sweep_line, right, -1);
1355 0 : } while (pos != &sweep_line->active);
1356 : }
1357 :
1358 : static void
1359 0 : render_rows (cairo_botor_scan_converter_t *self,
1360 : sweep_line_t *sweep_line,
1361 : int y, int height,
1362 : cairo_span_renderer_t *renderer)
1363 : {
1364 : cairo_half_open_span_t spans_stack[CAIRO_STACK_ARRAY_LENGTH (cairo_half_open_span_t)];
1365 0 : cairo_half_open_span_t *spans = spans_stack;
1366 : struct cell *cell;
1367 : int prev_x, cover;
1368 : int num_spans;
1369 : cairo_status_t status;
1370 :
1371 0 : if (unlikely (sweep_line->coverage.count == 0)) {
1372 0 : status = renderer->render_rows (renderer, y, height, NULL, 0);
1373 0 : if (unlikely (status))
1374 0 : longjmp (sweep_line->unwind, status);
1375 0 : return;
1376 : }
1377 :
1378 : /* Allocate enough spans for the row. */
1379 :
1380 0 : num_spans = 2*sweep_line->coverage.count+2;
1381 0 : if (unlikely (num_spans > ARRAY_LENGTH (spans_stack))) {
1382 0 : spans = _cairo_malloc_ab (num_spans, sizeof (cairo_half_open_span_t));
1383 0 : if (unlikely (spans == NULL)) {
1384 0 : longjmp (sweep_line->unwind,
1385 0 : _cairo_error (CAIRO_STATUS_NO_MEMORY));
1386 : }
1387 : }
1388 :
1389 : /* Form the spans from the coverage and areas. */
1390 0 : num_spans = 0;
1391 0 : prev_x = self->xmin;
1392 0 : cover = 0;
1393 0 : cell = sweep_line->coverage.head.next;
1394 : do {
1395 0 : int x = cell->x;
1396 : int area;
1397 :
1398 0 : if (x > prev_x) {
1399 0 : spans[num_spans].x = prev_x;
1400 0 : spans[num_spans].coverage = AREA_TO_ALPHA (cover);
1401 0 : ++num_spans;
1402 : }
1403 :
1404 0 : cover += cell->covered_height*STEP_X*2;
1405 0 : area = cover - cell->uncovered_area;
1406 :
1407 0 : spans[num_spans].x = x;
1408 0 : spans[num_spans].coverage = AREA_TO_ALPHA (area);
1409 0 : ++num_spans;
1410 :
1411 0 : prev_x = x + 1;
1412 0 : } while ((cell = cell->next) != &sweep_line->coverage.tail);
1413 :
1414 0 : if (prev_x <= self->xmax) {
1415 0 : spans[num_spans].x = prev_x;
1416 0 : spans[num_spans].coverage = AREA_TO_ALPHA (cover);
1417 0 : ++num_spans;
1418 : }
1419 :
1420 0 : if (cover && prev_x < self->xmax) {
1421 0 : spans[num_spans].x = self->xmax;
1422 0 : spans[num_spans].coverage = 0;
1423 0 : ++num_spans;
1424 : }
1425 :
1426 0 : status = renderer->render_rows (renderer, y, height, spans, num_spans);
1427 :
1428 0 : if (unlikely (spans != spans_stack))
1429 0 : free (spans);
1430 :
1431 0 : coverage_reset (&sweep_line->coverage);
1432 :
1433 0 : if (unlikely (status))
1434 0 : longjmp (sweep_line->unwind, status);
1435 : }
1436 :
1437 : static void
1438 0 : full_repeat (sweep_line_t *sweep)
1439 : {
1440 : edge_t *edge;
1441 :
1442 0 : cairo_list_foreach_entry (edge, edge_t, &sweep->active, link) {
1443 0 : if (edge->current_sign)
1444 0 : full_add_edge (sweep, edge, edge->current_sign);
1445 0 : else if (! edge->vertical)
1446 0 : full_inc_edge (edge);
1447 : }
1448 0 : }
1449 :
1450 : static void
1451 0 : full_reset (sweep_line_t *sweep)
1452 : {
1453 : edge_t *edge;
1454 :
1455 0 : cairo_list_foreach_entry (edge, edge_t, &sweep->active, link)
1456 0 : edge->current_sign = 0;
1457 0 : }
1458 :
1459 : static void
1460 0 : full_step (cairo_botor_scan_converter_t *self,
1461 : sweep_line_t *sweep_line,
1462 : cairo_fixed_t row,
1463 : cairo_span_renderer_t *renderer)
1464 : {
1465 : int top, bottom;
1466 :
1467 0 : top = _cairo_fixed_integer_part (sweep_line->current_row);
1468 0 : bottom = _cairo_fixed_integer_part (row);
1469 0 : if (cairo_list_is_empty (&sweep_line->active)) {
1470 : cairo_status_t status;
1471 :
1472 0 : status = renderer->render_rows (renderer, top, bottom - top, NULL, 0);
1473 0 : if (unlikely (status))
1474 0 : longjmp (sweep_line->unwind, status);
1475 :
1476 0 : return;
1477 : }
1478 :
1479 0 : if (self->fill_rule == CAIRO_FILL_RULE_WINDING)
1480 0 : full_nonzero (sweep_line);
1481 : else
1482 0 : full_evenodd (sweep_line);
1483 :
1484 0 : if (sweep_line->is_vertical || bottom == top + 1) {
1485 0 : render_rows (self, sweep_line, top, bottom - top, renderer);
1486 0 : full_reset (sweep_line);
1487 0 : return;
1488 : }
1489 :
1490 0 : render_rows (self, sweep_line, top++, 1, renderer);
1491 : do {
1492 0 : full_repeat (sweep_line);
1493 0 : render_rows (self, sweep_line, top, 1, renderer);
1494 0 : } while (++top != bottom);
1495 :
1496 0 : full_reset (sweep_line);
1497 : }
1498 :
1499 : cairo_always_inline static void
1500 : sub_inc_edge (edge_t *edge,
1501 : cairo_fixed_t height)
1502 : {
1503 0 : if (height == 1) {
1504 0 : edge->x.quo += edge->dxdy.quo;
1505 0 : edge->x.rem += edge->dxdy.rem;
1506 0 : if (edge->x.rem >= 0) {
1507 0 : ++edge->x.quo;
1508 0 : edge->x.rem -= edge->dy;
1509 : }
1510 : } else {
1511 0 : edge->x.quo += height * edge->dxdy.quo;
1512 0 : edge->x.rem += height * edge->dxdy.rem;
1513 0 : if (edge->x.rem >= 0) {
1514 0 : int carry = edge->x.rem / edge->dy + 1;
1515 0 : edge->x.quo += carry;
1516 0 : edge->x.rem -= carry * edge->dy;
1517 : }
1518 : }
1519 : }
1520 :
1521 : static void
1522 0 : sub_add_run (sweep_line_t *sweep_line, edge_t *edge, int y, int sign)
1523 : {
1524 : struct run *run;
1525 :
1526 0 : run = _cairo_freepool_alloc (&sweep_line->runs);
1527 0 : if (unlikely (run == NULL))
1528 0 : longjmp (sweep_line->unwind, _cairo_error (CAIRO_STATUS_NO_MEMORY));
1529 :
1530 0 : run->y = y;
1531 0 : run->sign = sign;
1532 0 : run->next = edge->runs;
1533 0 : edge->runs = run;
1534 :
1535 0 : edge->current_sign = sign;
1536 0 : }
1537 :
1538 : inline static cairo_bool_t
1539 0 : edges_coincident (edge_t *left, edge_t *right, cairo_fixed_t y)
1540 : {
1541 : /* XXX is compare_x_for_y() worth executing during sub steps? */
1542 0 : return line_equal (&left->edge.line, &right->edge.line);
1543 : //edges_compare_x_for_y (&left->edge, &right->edge, y) >= 0;
1544 : }
1545 :
1546 : static void
1547 0 : sub_nonzero (sweep_line_t *sweep_line)
1548 : {
1549 0 : cairo_fixed_t y = sweep_line->current_subrow;
1550 0 : cairo_fixed_t fy = _cairo_fixed_fractional_part (y);
1551 : cairo_list_t *pos;
1552 :
1553 0 : pos = sweep_line->active.next;
1554 : do {
1555 0 : edge_t *left = link_to_edge (pos), *right;
1556 0 : int winding = left->edge.dir;
1557 :
1558 0 : pos = left->link.next;
1559 : do {
1560 0 : if (unlikely (pos == &sweep_line->active)) {
1561 0 : if (left->current_sign != +1)
1562 0 : sub_add_run (sweep_line, left, fy, +1);
1563 0 : return;
1564 : }
1565 :
1566 0 : right = link_to_edge (pos);
1567 0 : pos = pos->next;
1568 :
1569 0 : winding += right->edge.dir;
1570 0 : if (0 == winding) {
1571 0 : if (pos == &sweep_line->active ||
1572 0 : ! edges_coincident (right, link_to_edge (pos), y))
1573 : {
1574 : break;
1575 : }
1576 : }
1577 :
1578 0 : if (right->current_sign)
1579 0 : sub_add_run (sweep_line, right, fy, 0);
1580 : } while (TRUE);
1581 :
1582 0 : if (left->current_sign != +1)
1583 0 : sub_add_run (sweep_line, left, fy, +1);
1584 0 : if (right->current_sign != -1)
1585 0 : sub_add_run (sweep_line, right, fy, -1);
1586 0 : } while (pos != &sweep_line->active);
1587 : }
1588 :
1589 : static void
1590 0 : sub_evenodd (sweep_line_t *sweep_line)
1591 : {
1592 0 : cairo_fixed_t y = sweep_line->current_subrow;
1593 0 : cairo_fixed_t fy = _cairo_fixed_fractional_part (y);
1594 : cairo_list_t *pos;
1595 :
1596 0 : pos = sweep_line->active.next;
1597 : do {
1598 0 : edge_t *left = link_to_edge (pos), *right;
1599 0 : int winding = 0;
1600 :
1601 0 : pos = left->link.next;
1602 : do {
1603 0 : if (unlikely (pos == &sweep_line->active)) {
1604 0 : if (left->current_sign != +1)
1605 0 : sub_add_run (sweep_line, left, fy, +1);
1606 0 : return;
1607 : }
1608 :
1609 0 : right = link_to_edge (pos);
1610 0 : pos = pos->next;
1611 :
1612 0 : if (++winding & 1) {
1613 0 : if (pos == &sweep_line->active ||
1614 0 : ! edges_coincident (right, link_to_edge (pos), y))
1615 : {
1616 : break;
1617 : }
1618 : }
1619 :
1620 0 : if (right->current_sign)
1621 0 : sub_add_run (sweep_line, right, fy, 0);
1622 : } while (TRUE);
1623 :
1624 0 : if (left->current_sign != +1)
1625 0 : sub_add_run (sweep_line, left, fy, +1);
1626 0 : if (right->current_sign != -1)
1627 0 : sub_add_run (sweep_line, right, fy, -1);
1628 0 : } while (pos != &sweep_line->active);
1629 : }
1630 :
1631 : cairo_always_inline static void
1632 : sub_step (cairo_botor_scan_converter_t *self,
1633 : sweep_line_t *sweep_line)
1634 : {
1635 0 : if (cairo_list_is_empty (&sweep_line->active))
1636 : return;
1637 :
1638 0 : if (self->fill_rule == CAIRO_FILL_RULE_WINDING)
1639 0 : sub_nonzero (sweep_line);
1640 : else
1641 0 : sub_evenodd (sweep_line);
1642 : }
1643 :
1644 : static void
1645 0 : coverage_render_runs (sweep_line_t *sweep, edge_t *edge,
1646 : cairo_fixed_t y1, cairo_fixed_t y2)
1647 : {
1648 : struct run tail;
1649 0 : struct run *run = &tail;
1650 :
1651 0 : tail.next = NULL;
1652 0 : tail.y = y2;
1653 :
1654 : /* Order the runs top->bottom */
1655 0 : while (edge->runs) {
1656 : struct run *r;
1657 :
1658 0 : r = edge->runs;
1659 0 : edge->runs = r->next;
1660 0 : r->next = run;
1661 0 : run = r;
1662 : }
1663 :
1664 0 : if (run->y > y1)
1665 0 : sub_inc_edge (edge, run->y - y1);
1666 :
1667 : do {
1668 : cairo_fixed_t x1, x2;
1669 :
1670 0 : y1 = run->y;
1671 0 : y2 = run->next->y;
1672 :
1673 0 : x1 = edge->x.quo;
1674 0 : if (y2 - y1 == STEP_Y)
1675 0 : full_inc_edge (edge);
1676 : else
1677 0 : sub_inc_edge (edge, y2 - y1);
1678 0 : x2 = edge->x.quo;
1679 :
1680 0 : if (run->sign) {
1681 : int ix1, ix2;
1682 :
1683 0 : ix1 = _cairo_fixed_integer_part (x1);
1684 0 : ix2 = _cairo_fixed_integer_part (x2);
1685 :
1686 : /* Edge is entirely within a column? */
1687 0 : if (likely (ix1 == ix2)) {
1688 : struct cell *cell;
1689 : int frac;
1690 :
1691 0 : frac = _cairo_fixed_fractional_part (x1) +
1692 0 : _cairo_fixed_fractional_part (x2);
1693 0 : cell = coverage_find (sweep, ix1);
1694 0 : cell->covered_height += run->sign * (y2 - y1);
1695 0 : cell->uncovered_area += run->sign * (y2 - y1) * frac;
1696 : } else {
1697 0 : coverage_render_cells (sweep, x1, x2, y1, y2, run->sign);
1698 : }
1699 : }
1700 :
1701 0 : run = run->next;
1702 0 : } while (run->next != NULL);
1703 0 : }
1704 :
1705 : static void
1706 0 : coverage_render_vertical_runs (sweep_line_t *sweep, edge_t *edge, cairo_fixed_t y2)
1707 : {
1708 : struct cell *cell;
1709 : struct run *run;
1710 0 : int height = 0;
1711 :
1712 0 : for (run = edge->runs; run != NULL; run = run->next) {
1713 0 : if (run->sign)
1714 0 : height += run->sign * (y2 - run->y);
1715 0 : y2 = run->y;
1716 : }
1717 :
1718 0 : cell = coverage_find (sweep, _cairo_fixed_integer_part (edge->x.quo));
1719 0 : cell->covered_height += height;
1720 0 : cell->uncovered_area += 2 * _cairo_fixed_fractional_part (edge->x.quo) * height;
1721 0 : }
1722 :
1723 : cairo_always_inline static void
1724 : sub_emit (cairo_botor_scan_converter_t *self,
1725 : sweep_line_t *sweep,
1726 : cairo_span_renderer_t *renderer)
1727 : {
1728 : edge_t *edge;
1729 :
1730 : sub_step (self, sweep);
1731 :
1732 : /* convert the runs into coverages */
1733 :
1734 0 : cairo_list_foreach_entry (edge, edge_t, &sweep->active, link) {
1735 0 : if (edge->runs == NULL) {
1736 0 : if (! edge->vertical) {
1737 0 : if (edge->flags & START) {
1738 0 : sub_inc_edge (edge,
1739 0 : STEP_Y - _cairo_fixed_fractional_part (edge->edge.top));
1740 0 : edge->flags &= ~START;
1741 : } else
1742 0 : full_inc_edge (edge);
1743 : }
1744 : } else {
1745 0 : if (edge->vertical) {
1746 0 : coverage_render_vertical_runs (sweep, edge, STEP_Y);
1747 : } else {
1748 0 : int y1 = 0;
1749 0 : if (edge->flags & START) {
1750 0 : y1 = _cairo_fixed_fractional_part (edge->edge.top);
1751 0 : edge->flags &= ~START;
1752 : }
1753 0 : coverage_render_runs (sweep, edge, y1, STEP_Y);
1754 : }
1755 : }
1756 0 : edge->current_sign = 0;
1757 0 : edge->runs = NULL;
1758 : }
1759 :
1760 0 : cairo_list_foreach_entry (edge, edge_t, &sweep->stopped, link) {
1761 0 : int y2 = _cairo_fixed_fractional_part (edge->edge.bottom);
1762 0 : if (edge->vertical) {
1763 0 : coverage_render_vertical_runs (sweep, edge, y2);
1764 : } else {
1765 0 : int y1 = 0;
1766 0 : if (edge->flags & START)
1767 0 : y1 = _cairo_fixed_fractional_part (edge->edge.top);
1768 0 : coverage_render_runs (sweep, edge, y1, y2);
1769 : }
1770 : }
1771 0 : cairo_list_init (&sweep->stopped);
1772 :
1773 0 : _cairo_freepool_reset (&sweep->runs);
1774 :
1775 0 : render_rows (self, sweep,
1776 : _cairo_fixed_integer_part (sweep->current_row), 1,
1777 : renderer);
1778 : }
1779 :
1780 : static void
1781 0 : sweep_line_init (sweep_line_t *sweep_line,
1782 : event_t **start_events,
1783 : int num_events)
1784 : {
1785 0 : cairo_list_init (&sweep_line->active);
1786 0 : cairo_list_init (&sweep_line->stopped);
1787 0 : sweep_line->insert_cursor = &sweep_line->active;
1788 :
1789 0 : sweep_line->current_row = INT32_MIN;
1790 0 : sweep_line->current_subrow = INT32_MIN;
1791 :
1792 0 : coverage_init (&sweep_line->coverage);
1793 0 : _cairo_freepool_init (&sweep_line->runs, sizeof (struct run));
1794 :
1795 0 : start_event_sort (start_events, num_events);
1796 0 : start_events[num_events] = NULL;
1797 :
1798 0 : sweep_line->queue.start_events = start_events;
1799 :
1800 0 : _cairo_freepool_init (&sweep_line->queue.pool,
1801 : sizeof (queue_event_t));
1802 0 : pqueue_init (&sweep_line->queue.pq);
1803 0 : sweep_line->queue.pq.elements[PQ_FIRST_ENTRY] = NULL;
1804 0 : }
1805 :
1806 : static void
1807 0 : sweep_line_delete (sweep_line_t *sweep_line,
1808 : edge_t *edge)
1809 : {
1810 0 : if (sweep_line->insert_cursor == &edge->link)
1811 0 : sweep_line->insert_cursor = edge->link.prev;
1812 :
1813 0 : cairo_list_del (&edge->link);
1814 0 : if (edge->runs)
1815 0 : cairo_list_add_tail (&edge->link, &sweep_line->stopped);
1816 0 : edge->flags |= STOP;
1817 0 : }
1818 :
1819 : static void
1820 0 : sweep_line_swap (sweep_line_t *sweep_line,
1821 : edge_t *left,
1822 : edge_t *right)
1823 : {
1824 0 : right->link.prev = left->link.prev;
1825 0 : left->link.next = right->link.next;
1826 0 : right->link.next = &left->link;
1827 0 : left->link.prev = &right->link;
1828 0 : left->link.next->prev = &left->link;
1829 0 : right->link.prev->next = &right->link;
1830 0 : }
1831 :
1832 : static void
1833 0 : sweep_line_fini (sweep_line_t *sweep_line)
1834 : {
1835 0 : pqueue_fini (&sweep_line->queue.pq);
1836 0 : _cairo_freepool_fini (&sweep_line->queue.pool);
1837 0 : coverage_fini (&sweep_line->coverage);
1838 0 : _cairo_freepool_fini (&sweep_line->runs);
1839 0 : }
1840 :
1841 : static cairo_status_t
1842 0 : botor_generate (cairo_botor_scan_converter_t *self,
1843 : event_t **start_events,
1844 : cairo_span_renderer_t *renderer)
1845 : {
1846 : cairo_status_t status;
1847 : sweep_line_t sweep_line;
1848 : cairo_fixed_t ybot;
1849 : event_t *event;
1850 : cairo_list_t *left, *right;
1851 : edge_t *e1, *e2;
1852 : int bottom;
1853 :
1854 0 : sweep_line_init (&sweep_line, start_events, self->num_edges);
1855 0 : if ((status = setjmp (sweep_line.unwind)))
1856 0 : goto unwind;
1857 :
1858 0 : ybot = self->extents.p2.y;
1859 0 : sweep_line.current_subrow = self->extents.p1.y;
1860 0 : sweep_line.current_row = _cairo_fixed_floor (self->extents.p1.y);
1861 0 : event = *sweep_line.queue.start_events++;
1862 : do {
1863 : /* Can we process a full step in one go? */
1864 0 : if (event->y >= sweep_line.current_row + STEP_Y) {
1865 0 : bottom = _cairo_fixed_floor (event->y);
1866 0 : full_step (self, &sweep_line, bottom, renderer);
1867 0 : sweep_line.current_row = bottom;
1868 0 : sweep_line.current_subrow = bottom;
1869 : }
1870 :
1871 : do {
1872 0 : if (event->y > sweep_line.current_subrow) {
1873 : sub_step (self, &sweep_line);
1874 0 : sweep_line.current_subrow = event->y;
1875 : }
1876 :
1877 : do {
1878 : /* Update the active list using Bentley-Ottmann */
1879 0 : switch (event->type) {
1880 : case EVENT_TYPE_START:
1881 0 : e1 = ((start_event_t *) event)->edge;
1882 :
1883 0 : sweep_line_insert (&sweep_line, e1);
1884 0 : event_insert_stop (&sweep_line, e1);
1885 :
1886 0 : left = e1->link.prev;
1887 0 : right = e1->link.next;
1888 :
1889 0 : if (left != &sweep_line.active) {
1890 0 : event_insert_if_intersect_below_current_y (&sweep_line,
1891 : link_to_edge (left), e1);
1892 : }
1893 :
1894 0 : if (right != &sweep_line.active) {
1895 0 : event_insert_if_intersect_below_current_y (&sweep_line,
1896 : e1, link_to_edge (right));
1897 : }
1898 :
1899 0 : break;
1900 :
1901 : case EVENT_TYPE_STOP:
1902 0 : e1 = ((queue_event_t *) event)->e1;
1903 0 : event_delete (&sweep_line, event);
1904 :
1905 0 : left = e1->link.prev;
1906 0 : right = e1->link.next;
1907 :
1908 0 : sweep_line_delete (&sweep_line, e1);
1909 :
1910 0 : if (left != &sweep_line.active &&
1911 : right != &sweep_line.active)
1912 : {
1913 0 : event_insert_if_intersect_below_current_y (&sweep_line,
1914 : link_to_edge (left),
1915 : link_to_edge (right));
1916 : }
1917 :
1918 0 : break;
1919 :
1920 : case EVENT_TYPE_INTERSECTION:
1921 0 : e1 = ((queue_event_t *) event)->e1;
1922 0 : e2 = ((queue_event_t *) event)->e2;
1923 :
1924 0 : event_delete (&sweep_line, event);
1925 0 : if (e1->flags & STOP)
1926 0 : break;
1927 0 : if (e2->flags & STOP)
1928 0 : break;
1929 :
1930 : /* skip this intersection if its edges are not adjacent */
1931 0 : if (&e2->link != e1->link.next)
1932 0 : break;
1933 :
1934 0 : left = e1->link.prev;
1935 0 : right = e2->link.next;
1936 :
1937 0 : sweep_line_swap (&sweep_line, e1, e2);
1938 :
1939 : /* after the swap e2 is left of e1 */
1940 0 : if (left != &sweep_line.active) {
1941 0 : event_insert_if_intersect_below_current_y (&sweep_line,
1942 : link_to_edge (left), e2);
1943 : }
1944 :
1945 0 : if (right != &sweep_line.active) {
1946 0 : event_insert_if_intersect_below_current_y (&sweep_line,
1947 : e1, link_to_edge (right));
1948 : }
1949 :
1950 0 : break;
1951 : }
1952 :
1953 0 : event = event_next (&sweep_line);
1954 0 : if (event == NULL)
1955 0 : goto end;
1956 0 : } while (event->y == sweep_line.current_subrow);
1957 0 : } while (event->y < sweep_line.current_row + STEP_Y);
1958 :
1959 0 : bottom = sweep_line.current_row + STEP_Y;
1960 : sub_emit (self, &sweep_line, renderer);
1961 0 : sweep_line.current_subrow = bottom;
1962 0 : sweep_line.current_row = sweep_line.current_subrow;
1963 : } while (TRUE);
1964 :
1965 : end:
1966 : /* flush any partial spans */
1967 0 : if (sweep_line.current_subrow != sweep_line.current_row) {
1968 : sub_emit (self, &sweep_line, renderer);
1969 0 : sweep_line.current_row += STEP_Y;
1970 0 : sweep_line.current_subrow = sweep_line.current_row;
1971 : }
1972 : /* clear the rest */
1973 0 : if (sweep_line.current_subrow < ybot) {
1974 0 : bottom = _cairo_fixed_integer_part (sweep_line.current_row);
1975 0 : status = renderer->render_rows (renderer,
1976 0 : bottom, _cairo_fixed_integer_ceil (ybot) - bottom,
1977 : NULL, 0);
1978 : }
1979 :
1980 : unwind:
1981 0 : sweep_line_fini (&sweep_line);
1982 :
1983 0 : return status;
1984 : }
1985 :
1986 : static cairo_status_t
1987 0 : _cairo_botor_scan_converter_generate (void *converter,
1988 : cairo_span_renderer_t *renderer)
1989 : {
1990 0 : cairo_botor_scan_converter_t *self = converter;
1991 : start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (start_event_t)];
1992 : start_event_t *events;
1993 : event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
1994 : event_t **event_ptrs;
1995 : struct _cairo_botor_scan_converter_chunk *chunk;
1996 : cairo_status_t status;
1997 : int num_events;
1998 : int i, j;
1999 :
2000 0 : num_events = self->num_edges;
2001 0 : if (unlikely (0 == num_events)) {
2002 0 : return renderer->render_rows (renderer,
2003 : _cairo_fixed_integer_floor (self->extents.p1.y),
2004 0 : _cairo_fixed_integer_ceil (self->extents.p2.y) -
2005 0 : _cairo_fixed_integer_floor (self->extents.p1.y),
2006 : NULL, 0);
2007 : }
2008 :
2009 0 : events = stack_events;
2010 0 : event_ptrs = stack_event_ptrs;
2011 0 : if (unlikely (num_events >= ARRAY_LENGTH (stack_events))) {
2012 0 : events = _cairo_malloc_ab_plus_c (num_events,
2013 : sizeof (start_event_t) + sizeof (event_t *),
2014 : sizeof (event_t *));
2015 0 : if (unlikely (events == NULL))
2016 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2017 :
2018 0 : event_ptrs = (event_t **) (events + num_events);
2019 : }
2020 :
2021 0 : j = 0;
2022 0 : for (chunk = &self->chunks; chunk != NULL; chunk = chunk->next) {
2023 : edge_t *edge;
2024 :
2025 0 : edge = chunk->base;
2026 0 : for (i = 0; i < chunk->count; i++) {
2027 0 : event_ptrs[j] = (event_t *) &events[j];
2028 :
2029 0 : events[j].y = edge->edge.top;
2030 0 : events[j].type = EVENT_TYPE_START;
2031 0 : events[j].edge = edge;
2032 :
2033 0 : edge++, j++;
2034 : }
2035 : }
2036 :
2037 0 : status = botor_generate (self, event_ptrs, renderer);
2038 :
2039 0 : if (events != stack_events)
2040 0 : free (events);
2041 :
2042 0 : return status;
2043 : }
2044 :
2045 : static edge_t *
2046 0 : botor_allocate_edge (cairo_botor_scan_converter_t *self)
2047 : {
2048 : struct _cairo_botor_scan_converter_chunk *chunk;
2049 :
2050 0 : chunk = self->tail;
2051 0 : if (chunk->count == chunk->size) {
2052 : int size;
2053 :
2054 0 : size = chunk->size * 2;
2055 0 : chunk->next = _cairo_malloc_ab_plus_c (size,
2056 : sizeof (edge_t),
2057 : sizeof (struct _cairo_botor_scan_converter_chunk));
2058 0 : if (unlikely (chunk->next == NULL))
2059 0 : return NULL;
2060 :
2061 0 : chunk = chunk->next;
2062 0 : chunk->next = NULL;
2063 0 : chunk->count = 0;
2064 0 : chunk->size = size;
2065 0 : chunk->base = chunk + 1;
2066 0 : self->tail = chunk;
2067 : }
2068 :
2069 0 : return (edge_t *) chunk->base + chunk->count++;
2070 : }
2071 :
2072 : static cairo_status_t
2073 0 : botor_add_edge (cairo_botor_scan_converter_t *self,
2074 : const cairo_edge_t *edge)
2075 : {
2076 : edge_t *e;
2077 : cairo_fixed_t dx, dy;
2078 :
2079 0 : e = botor_allocate_edge (self);
2080 0 : if (unlikely (e == NULL))
2081 0 : return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2082 :
2083 0 : cairo_list_init (&e->link);
2084 0 : e->edge = *edge;
2085 :
2086 0 : dx = edge->line.p2.x - edge->line.p1.x;
2087 0 : dy = edge->line.p2.y - edge->line.p1.y;
2088 0 : e->dy = dy;
2089 :
2090 0 : if (dx == 0) {
2091 0 : e->vertical = TRUE;
2092 0 : e->x.quo = edge->line.p1.x;
2093 0 : e->x.rem = 0;
2094 0 : e->dxdy.quo = 0;
2095 0 : e->dxdy.rem = 0;
2096 0 : e->dxdy_full.quo = 0;
2097 0 : e->dxdy_full.rem = 0;
2098 : } else {
2099 0 : e->vertical = FALSE;
2100 0 : e->dxdy = floored_divrem (dx, dy);
2101 0 : if (edge->top == edge->line.p1.y) {
2102 0 : e->x.quo = edge->line.p1.x;
2103 0 : e->x.rem = 0;
2104 : } else {
2105 0 : e->x = floored_muldivrem (edge->top - edge->line.p1.y,
2106 : dx, dy);
2107 0 : e->x.quo += edge->line.p1.x;
2108 : }
2109 :
2110 0 : if (_cairo_fixed_integer_part (edge->bottom) - _cairo_fixed_integer_part (edge->top) > 1) {
2111 0 : e->dxdy_full = floored_muldivrem (STEP_Y, dx, dy);
2112 : } else {
2113 0 : e->dxdy_full.quo = 0;
2114 0 : e->dxdy_full.rem = 0;
2115 : }
2116 : }
2117 :
2118 0 : e->x.rem = -e->dy;
2119 0 : e->current_sign = 0;
2120 0 : e->runs = NULL;
2121 0 : e->flags = START;
2122 :
2123 0 : self->num_edges++;
2124 :
2125 0 : return CAIRO_STATUS_SUCCESS;
2126 : }
2127 :
2128 : static cairo_status_t
2129 0 : _cairo_botor_scan_converter_add_edge (void *converter,
2130 : const cairo_point_t *p1,
2131 : const cairo_point_t *p2,
2132 : int top, int bottom,
2133 : int dir)
2134 : {
2135 0 : cairo_botor_scan_converter_t *self = converter;
2136 : cairo_edge_t edge;
2137 :
2138 0 : edge.line.p1 = *p1;
2139 0 : edge.line.p2 = *p2;
2140 0 : edge.top = top;
2141 0 : edge.bottom = bottom;
2142 0 : edge.dir = dir;
2143 :
2144 0 : return botor_add_edge (self, &edge);
2145 : }
2146 :
2147 : static cairo_status_t
2148 0 : _cairo_botor_scan_converter_add_polygon (void *converter,
2149 : const cairo_polygon_t *polygon)
2150 : {
2151 0 : cairo_botor_scan_converter_t *self = converter;
2152 : cairo_status_t status;
2153 : int i;
2154 :
2155 0 : for (i = 0; i < polygon->num_edges; i++) {
2156 0 : status = botor_add_edge (self, &polygon->edges[i]);
2157 0 : if (unlikely (status))
2158 0 : return status;
2159 : }
2160 :
2161 0 : return CAIRO_STATUS_SUCCESS;
2162 : }
2163 :
2164 : static void
2165 0 : _cairo_botor_scan_converter_destroy (void *converter)
2166 : {
2167 0 : cairo_botor_scan_converter_t *self = converter;
2168 : struct _cairo_botor_scan_converter_chunk *chunk, *next;
2169 :
2170 0 : for (chunk = self->chunks.next; chunk != NULL; chunk = next) {
2171 0 : next = chunk->next;
2172 0 : free (chunk);
2173 : }
2174 0 : }
2175 :
2176 : void
2177 0 : _cairo_botor_scan_converter_init (cairo_botor_scan_converter_t *self,
2178 : const cairo_box_t *extents,
2179 : cairo_fill_rule_t fill_rule)
2180 : {
2181 0 : self->base.destroy = _cairo_botor_scan_converter_destroy;
2182 0 : self->base.add_edge = _cairo_botor_scan_converter_add_edge;
2183 0 : self->base.add_polygon = _cairo_botor_scan_converter_add_polygon;
2184 0 : self->base.generate = _cairo_botor_scan_converter_generate;
2185 :
2186 0 : self->extents = *extents;
2187 0 : self->fill_rule = fill_rule;
2188 :
2189 0 : self->xmin = _cairo_fixed_integer_floor (extents->p1.x);
2190 0 : self->xmax = _cairo_fixed_integer_ceil (extents->p2.x);
2191 :
2192 0 : self->chunks.base = self->buf;
2193 0 : self->chunks.next = NULL;
2194 0 : self->chunks.count = 0;
2195 0 : self->chunks.size = sizeof (self->buf) / sizeof (edge_t);
2196 0 : self->tail = &self->chunks;
2197 :
2198 0 : self->num_edges = 0;
2199 0 : }
|