/work/workdir/UnpackedTarball/cairo/src/cairo-polygon-intersect.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright © 2004 Carl Worth |
3 | | * Copyright © 2006 Red Hat, Inc. |
4 | | * Copyright © 2008 Chris Wilson |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it either under the terms of the GNU Lesser General Public |
8 | | * License version 2.1 as published by the Free Software Foundation |
9 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
10 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
11 | | * notice, a recipient may use your version of this file under either |
12 | | * the MPL or the LGPL. |
13 | | * |
14 | | * You should have received a copy of the LGPL along with this library |
15 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
16 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
17 | | * You should have received a copy of the MPL along with this library |
18 | | * in the file COPYING-MPL-1.1 |
19 | | * |
20 | | * The contents of this file are subject to the Mozilla Public License |
21 | | * Version 1.1 (the "License"); you may not use this file except in |
22 | | * compliance with the License. You may obtain a copy of the License at |
23 | | * http://www.mozilla.org/MPL/ |
24 | | * |
25 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
26 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
27 | | * the specific language governing rights and limitations. |
28 | | * |
29 | | * The Original Code is the cairo graphics library. |
30 | | * |
31 | | * The Initial Developer of the Original Code is Carl Worth |
32 | | * |
33 | | * Contributor(s): |
34 | | * Carl D. Worth <cworth@cworth.org> |
35 | | * Chris Wilson <chris@chris-wilson.co.uk> |
36 | | */ |
37 | | |
38 | | /* Provide definitions for standalone compilation */ |
39 | | #include "cairoint.h" |
40 | | |
41 | | #include "cairo-error-private.h" |
42 | | #include "cairo-freelist-private.h" |
43 | | #include "cairo-combsort-inline.h" |
44 | | |
45 | | |
46 | | typedef struct _cairo_bo_intersect_ordinate { |
47 | | int32_t ordinate; |
48 | | enum { EXCESS = -1, EXACT = 0, DEFAULT = 1 } approx; |
49 | | } cairo_bo_intersect_ordinate_t; |
50 | | |
51 | | typedef struct _cairo_bo_intersect_point { |
52 | | cairo_bo_intersect_ordinate_t x; |
53 | | cairo_bo_intersect_ordinate_t y; |
54 | | } cairo_bo_intersect_point_t; |
55 | | |
56 | | typedef struct _cairo_bo_edge cairo_bo_edge_t; |
57 | | |
58 | | typedef struct _cairo_bo_deferred { |
59 | | cairo_bo_edge_t *other; |
60 | | int32_t top; |
61 | | } cairo_bo_deferred_t; |
62 | | |
63 | | struct _cairo_bo_edge { |
64 | | int a_or_b; |
65 | | cairo_edge_t edge; |
66 | | cairo_bo_edge_t *prev; |
67 | | cairo_bo_edge_t *next; |
68 | | cairo_bo_deferred_t deferred; |
69 | | }; |
70 | | |
71 | | /* the parent is always given by index/2 */ |
72 | 0 | #define PQ_PARENT_INDEX(i) ((i) >> 1) |
73 | 0 | #define PQ_FIRST_ENTRY 1 |
74 | | |
75 | | /* left and right children are index * 2 and (index * 2) +1 respectively */ |
76 | 0 | #define PQ_LEFT_CHILD_INDEX(i) ((i) << 1) |
77 | | |
78 | | typedef enum { |
79 | | CAIRO_BO_EVENT_TYPE_STOP = -1, |
80 | | CAIRO_BO_EVENT_TYPE_INTERSECTION, |
81 | | CAIRO_BO_EVENT_TYPE_START |
82 | | } cairo_bo_event_type_t; |
83 | | |
84 | | typedef struct _cairo_bo_event { |
85 | | cairo_bo_event_type_t type; |
86 | | cairo_bo_intersect_point_t point; |
87 | | } cairo_bo_event_t; |
88 | | |
89 | | typedef struct _cairo_bo_start_event { |
90 | | cairo_bo_event_type_t type; |
91 | | cairo_bo_intersect_point_t point; |
92 | | cairo_bo_edge_t edge; |
93 | | } cairo_bo_start_event_t; |
94 | | |
95 | | typedef struct _cairo_bo_queue_event { |
96 | | cairo_bo_event_type_t type; |
97 | | cairo_bo_intersect_point_t point; |
98 | | cairo_bo_edge_t *e1; |
99 | | cairo_bo_edge_t *e2; |
100 | | } cairo_bo_queue_event_t; |
101 | | |
102 | | typedef struct _pqueue { |
103 | | int size, max_size; |
104 | | |
105 | | cairo_bo_event_t **elements; |
106 | | cairo_bo_event_t *elements_embedded[1024]; |
107 | | } pqueue_t; |
108 | | |
109 | | typedef struct _cairo_bo_event_queue { |
110 | | cairo_freepool_t pool; |
111 | | pqueue_t pqueue; |
112 | | cairo_bo_event_t **start_events; |
113 | | } cairo_bo_event_queue_t; |
114 | | |
115 | | typedef struct _cairo_bo_sweep_line { |
116 | | cairo_bo_edge_t *head; |
117 | | int32_t current_y; |
118 | | cairo_bo_edge_t *current_edge; |
119 | | } cairo_bo_sweep_line_t; |
120 | | |
121 | | static cairo_fixed_t |
122 | | _line_compute_intersection_x_for_y (const cairo_line_t *line, |
123 | | cairo_fixed_t y) |
124 | 0 | { |
125 | 0 | cairo_fixed_t x, dy; |
126 | |
|
127 | 0 | if (y == line->p1.y) |
128 | 0 | return line->p1.x; |
129 | 0 | if (y == line->p2.y) |
130 | 0 | return line->p2.x; |
131 | | |
132 | 0 | x = line->p1.x; |
133 | 0 | dy = line->p2.y - line->p1.y; |
134 | 0 | if (dy != 0) { |
135 | 0 | x += _cairo_fixed_mul_div_floor (y - line->p1.y, |
136 | 0 | line->p2.x - line->p1.x, |
137 | 0 | dy); |
138 | 0 | } |
139 | |
|
140 | 0 | return x; |
141 | 0 | } |
142 | | |
143 | | static inline int |
144 | | _cairo_bo_point32_compare (cairo_bo_intersect_point_t const *a, |
145 | | cairo_bo_intersect_point_t const *b) |
146 | 0 | { |
147 | 0 | int cmp; |
148 | |
|
149 | 0 | cmp = a->y.ordinate - b->y.ordinate; |
150 | 0 | if (cmp) |
151 | 0 | return cmp; |
152 | | |
153 | 0 | cmp = a->y.approx - b->y.approx; |
154 | 0 | if (cmp) |
155 | 0 | return cmp; |
156 | | |
157 | 0 | return a->x.ordinate - b->x.ordinate; |
158 | 0 | } |
159 | | |
160 | | /* Compare the slope of a to the slope of b, returning 1, 0, -1 if the |
161 | | * slope a is respectively greater than, equal to, or less than the |
162 | | * slope of b. |
163 | | * |
164 | | * For each edge, consider the direction vector formed from: |
165 | | * |
166 | | * top -> bottom |
167 | | * |
168 | | * which is: |
169 | | * |
170 | | * (dx, dy) = (line.p2.x - line.p1.x, line.p2.y - line.p1.y) |
171 | | * |
172 | | * We then define the slope of each edge as dx/dy, (which is the |
173 | | * inverse of the slope typically used in math instruction). We never |
174 | | * compute a slope directly as the value approaches infinity, but we |
175 | | * can derive a slope comparison without division as follows, (where |
176 | | * the ? represents our compare operator). |
177 | | * |
178 | | * 1. slope(a) ? slope(b) |
179 | | * 2. adx/ady ? bdx/bdy |
180 | | * 3. (adx * bdy) ? (bdx * ady) |
181 | | * |
182 | | * Note that from step 2 to step 3 there is no change needed in the |
183 | | * sign of the result since both ady and bdy are guaranteed to be |
184 | | * greater than or equal to 0. |
185 | | * |
186 | | * When using this slope comparison to sort edges, some care is needed |
187 | | * when interpreting the results. Since the slope compare operates on |
188 | | * distance vectors from top to bottom it gives a correct left to |
189 | | * right sort for edges that have a common top point, (such as two |
190 | | * edges with start events at the same location). On the other hand, |
191 | | * the sense of the result will be exactly reversed for two edges that |
192 | | * have a common stop point. |
193 | | */ |
194 | | static inline int |
195 | | _slope_compare (const cairo_bo_edge_t *a, |
196 | | const cairo_bo_edge_t *b) |
197 | 0 | { |
198 | | /* XXX: We're assuming here that dx and dy will still fit in 32 |
199 | | * bits. That's not true in general as there could be overflow. We |
200 | | * should prevent that before the tessellation algorithm |
201 | | * begins. |
202 | | */ |
203 | 0 | int32_t adx = a->edge.line.p2.x - a->edge.line.p1.x; |
204 | 0 | int32_t bdx = b->edge.line.p2.x - b->edge.line.p1.x; |
205 | | |
206 | | /* Since the dy's are all positive by construction we can fast |
207 | | * path several common cases. |
208 | | */ |
209 | | |
210 | | /* First check for vertical lines. */ |
211 | 0 | if (adx == 0) |
212 | 0 | return -bdx; |
213 | 0 | if (bdx == 0) |
214 | 0 | return adx; |
215 | | |
216 | | /* Then where the two edges point in different directions wrt x. */ |
217 | 0 | if ((adx ^ bdx) < 0) |
218 | 0 | return adx; |
219 | | |
220 | | /* Finally we actually need to do the general comparison. */ |
221 | 0 | { |
222 | 0 | int32_t ady = a->edge.line.p2.y - a->edge.line.p1.y; |
223 | 0 | int32_t bdy = b->edge.line.p2.y - b->edge.line.p1.y; |
224 | 0 | cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy); |
225 | 0 | cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady); |
226 | |
|
227 | 0 | return _cairo_int64_cmp (adx_bdy, bdx_ady); |
228 | 0 | } |
229 | 0 | } |
230 | | |
231 | | /* |
232 | | * We need to compare the x-coordinates of a pair of lines for a particular y, |
233 | | * without loss of precision. |
234 | | * |
235 | | * The x-coordinate along an edge for a given y is: |
236 | | * X = A_x + (Y - A_y) * A_dx / A_dy |
237 | | * |
238 | | * So the inequality we wish to test is: |
239 | | * A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy, |
240 | | * where ∘ is our inequality operator. |
241 | | * |
242 | | * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are |
243 | | * all positive, so we can rearrange it thus without causing a sign change: |
244 | | * A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy |
245 | | * - (Y - A_y) * A_dx * B_dy |
246 | | * |
247 | | * Given the assumption that all the deltas fit within 32 bits, we can compute |
248 | | * this comparison directly using 128 bit arithmetic. For certain, but common, |
249 | | * input we can reduce this down to a single 32 bit compare by inspecting the |
250 | | * deltas. |
251 | | * |
252 | | * (And put the burden of the work on developing fast 128 bit ops, which are |
253 | | * required throughout the tessellator.) |
254 | | * |
255 | | * See the similar discussion for _slope_compare(). |
256 | | */ |
257 | | static int |
258 | | edges_compare_x_for_y_general (const cairo_bo_edge_t *a, |
259 | | const cairo_bo_edge_t *b, |
260 | | int32_t y) |
261 | 0 | { |
262 | | /* XXX: We're assuming here that dx and dy will still fit in 32 |
263 | | * bits. That's not true in general as there could be overflow. We |
264 | | * should prevent that before the tessellation algorithm |
265 | | * begins. |
266 | | */ |
267 | 0 | int32_t dx; |
268 | 0 | int32_t adx, ady; |
269 | 0 | int32_t bdx, bdy; |
270 | 0 | enum { |
271 | 0 | HAVE_NONE = 0x0, |
272 | 0 | HAVE_DX = 0x1, |
273 | 0 | HAVE_ADX = 0x2, |
274 | 0 | HAVE_DX_ADX = HAVE_DX | HAVE_ADX, |
275 | 0 | HAVE_BDX = 0x4, |
276 | 0 | HAVE_DX_BDX = HAVE_DX | HAVE_BDX, |
277 | 0 | HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX, |
278 | 0 | HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX |
279 | 0 | } have_dx_adx_bdx = HAVE_ALL; |
280 | | |
281 | | /* don't bother solving for abscissa if the edges' bounding boxes |
282 | | * can be used to order them. */ |
283 | 0 | { |
284 | 0 | int32_t amin, amax; |
285 | 0 | int32_t bmin, bmax; |
286 | 0 | if (a->edge.line.p1.x < a->edge.line.p2.x) { |
287 | 0 | amin = a->edge.line.p1.x; |
288 | 0 | amax = a->edge.line.p2.x; |
289 | 0 | } else { |
290 | 0 | amin = a->edge.line.p2.x; |
291 | 0 | amax = a->edge.line.p1.x; |
292 | 0 | } |
293 | 0 | if (b->edge.line.p1.x < b->edge.line.p2.x) { |
294 | 0 | bmin = b->edge.line.p1.x; |
295 | 0 | bmax = b->edge.line.p2.x; |
296 | 0 | } else { |
297 | 0 | bmin = b->edge.line.p2.x; |
298 | 0 | bmax = b->edge.line.p1.x; |
299 | 0 | } |
300 | 0 | if (amax < bmin) return -1; |
301 | 0 | if (amin > bmax) return +1; |
302 | 0 | } |
303 | | |
304 | 0 | ady = a->edge.line.p2.y - a->edge.line.p1.y; |
305 | 0 | adx = a->edge.line.p2.x - a->edge.line.p1.x; |
306 | 0 | if (adx == 0) |
307 | 0 | have_dx_adx_bdx &= ~HAVE_ADX; |
308 | |
|
309 | 0 | bdy = b->edge.line.p2.y - b->edge.line.p1.y; |
310 | 0 | bdx = b->edge.line.p2.x - b->edge.line.p1.x; |
311 | 0 | if (bdx == 0) |
312 | 0 | have_dx_adx_bdx &= ~HAVE_BDX; |
313 | |
|
314 | 0 | dx = a->edge.line.p1.x - b->edge.line.p1.x; |
315 | 0 | if (dx == 0) |
316 | 0 | have_dx_adx_bdx &= ~HAVE_DX; |
317 | |
|
318 | 0 | #define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx) |
319 | 0 | #define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->edge.line.p1.y) |
320 | 0 | #define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->edge.line.p1.y) |
321 | 0 | switch (have_dx_adx_bdx) { |
322 | 0 | default: |
323 | 0 | case HAVE_NONE: |
324 | 0 | return 0; |
325 | 0 | case HAVE_DX: |
326 | | /* A_dy * B_dy * (A_x - B_x) ∘ 0 */ |
327 | 0 | return dx; /* ady * bdy is positive definite */ |
328 | 0 | case HAVE_ADX: |
329 | | /* 0 ∘ - (Y - A_y) * A_dx * B_dy */ |
330 | 0 | return adx; /* bdy * (y - a->top.y) is positive definite */ |
331 | 0 | case HAVE_BDX: |
332 | | /* 0 ∘ (Y - B_y) * B_dx * A_dy */ |
333 | 0 | return -bdx; /* ady * (y - b->top.y) is positive definite */ |
334 | 0 | case HAVE_ADX_BDX: |
335 | | /* 0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */ |
336 | 0 | if ((adx ^ bdx) < 0) { |
337 | 0 | return adx; |
338 | 0 | } else if (a->edge.line.p1.y == b->edge.line.p1.y) { /* common origin */ |
339 | 0 | cairo_int64_t adx_bdy, bdx_ady; |
340 | | |
341 | | /* ∴ A_dx * B_dy ∘ B_dx * A_dy */ |
342 | |
|
343 | 0 | adx_bdy = _cairo_int32x32_64_mul (adx, bdy); |
344 | 0 | bdx_ady = _cairo_int32x32_64_mul (bdx, ady); |
345 | |
|
346 | 0 | return _cairo_int64_cmp (adx_bdy, bdx_ady); |
347 | 0 | } else |
348 | 0 | return _cairo_int128_cmp (A, B); |
349 | 0 | case HAVE_DX_ADX: |
350 | | /* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */ |
351 | 0 | if ((-adx ^ dx) < 0) { |
352 | 0 | return dx; |
353 | 0 | } else { |
354 | 0 | cairo_int64_t ady_dx, dy_adx; |
355 | |
|
356 | 0 | ady_dx = _cairo_int32x32_64_mul (ady, dx); |
357 | 0 | dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx); |
358 | |
|
359 | 0 | return _cairo_int64_cmp (ady_dx, dy_adx); |
360 | 0 | } |
361 | 0 | case HAVE_DX_BDX: |
362 | | /* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */ |
363 | 0 | if ((bdx ^ dx) < 0) { |
364 | 0 | return dx; |
365 | 0 | } else { |
366 | 0 | cairo_int64_t bdy_dx, dy_bdx; |
367 | |
|
368 | 0 | bdy_dx = _cairo_int32x32_64_mul (bdy, dx); |
369 | 0 | dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.y, bdx); |
370 | |
|
371 | 0 | return _cairo_int64_cmp (bdy_dx, dy_bdx); |
372 | 0 | } |
373 | 0 | case HAVE_ALL: |
374 | | /* XXX try comparing (a->edge.line.p2.x - b->edge.line.p2.x) et al */ |
375 | 0 | return _cairo_int128_cmp (L, _cairo_int128_sub (B, A)); |
376 | 0 | } |
377 | 0 | #undef B |
378 | 0 | #undef A |
379 | 0 | #undef L |
380 | 0 | } |
381 | | |
382 | | /* |
383 | | * We need to compare the x-coordinate of a line for a particular y wrt to a |
384 | | * given x, without loss of precision. |
385 | | * |
386 | | * The x-coordinate along an edge for a given y is: |
387 | | * X = A_x + (Y - A_y) * A_dx / A_dy |
388 | | * |
389 | | * So the inequality we wish to test is: |
390 | | * A_x + (Y - A_y) * A_dx / A_dy ∘ X |
391 | | * where ∘ is our inequality operator. |
392 | | * |
393 | | * By construction, we know that A_dy (and (Y - A_y)) are |
394 | | * all positive, so we can rearrange it thus without causing a sign change: |
395 | | * (Y - A_y) * A_dx ∘ (X - A_x) * A_dy |
396 | | * |
397 | | * Given the assumption that all the deltas fit within 32 bits, we can compute |
398 | | * this comparison directly using 64 bit arithmetic. |
399 | | * |
400 | | * See the similar discussion for _slope_compare() and |
401 | | * edges_compare_x_for_y_general(). |
402 | | */ |
403 | | static int |
404 | | edge_compare_for_y_against_x (const cairo_bo_edge_t *a, |
405 | | int32_t y, |
406 | | int32_t x) |
407 | 0 | { |
408 | 0 | int32_t adx, ady; |
409 | 0 | int32_t dx, dy; |
410 | 0 | cairo_int64_t L, R; |
411 | |
|
412 | 0 | if (x < a->edge.line.p1.x && x < a->edge.line.p2.x) |
413 | 0 | return 1; |
414 | 0 | if (x > a->edge.line.p1.x && x > a->edge.line.p2.x) |
415 | 0 | return -1; |
416 | | |
417 | 0 | adx = a->edge.line.p2.x - a->edge.line.p1.x; |
418 | 0 | dx = x - a->edge.line.p1.x; |
419 | |
|
420 | 0 | if (adx == 0) |
421 | 0 | return -dx; |
422 | 0 | if (dx == 0 || (adx ^ dx) < 0) |
423 | 0 | return adx; |
424 | | |
425 | 0 | dy = y - a->edge.line.p1.y; |
426 | 0 | ady = a->edge.line.p2.y - a->edge.line.p1.y; |
427 | |
|
428 | 0 | L = _cairo_int32x32_64_mul (dy, adx); |
429 | 0 | R = _cairo_int32x32_64_mul (dx, ady); |
430 | |
|
431 | 0 | return _cairo_int64_cmp (L, R); |
432 | 0 | } |
433 | | |
434 | | static int |
435 | | edges_compare_x_for_y (const cairo_bo_edge_t *a, |
436 | | const cairo_bo_edge_t *b, |
437 | | int32_t y) |
438 | 0 | { |
439 | | /* If the sweep-line is currently on an end-point of a line, |
440 | | * then we know its precise x value (and considering that we often need to |
441 | | * compare events at end-points, this happens frequently enough to warrant |
442 | | * special casing). |
443 | | */ |
444 | 0 | enum { |
445 | 0 | HAVE_NEITHER = 0x0, |
446 | 0 | HAVE_AX = 0x1, |
447 | 0 | HAVE_BX = 0x2, |
448 | 0 | HAVE_BOTH = HAVE_AX | HAVE_BX |
449 | 0 | } have_ax_bx = HAVE_BOTH; |
450 | 0 | int32_t ax = 0, bx = 0; |
451 | |
|
452 | 0 | if (y == a->edge.line.p1.y) |
453 | 0 | ax = a->edge.line.p1.x; |
454 | 0 | else if (y == a->edge.line.p2.y) |
455 | 0 | ax = a->edge.line.p2.x; |
456 | 0 | else |
457 | 0 | have_ax_bx &= ~HAVE_AX; |
458 | |
|
459 | 0 | if (y == b->edge.line.p1.y) |
460 | 0 | bx = b->edge.line.p1.x; |
461 | 0 | else if (y == b->edge.line.p2.y) |
462 | 0 | bx = b->edge.line.p2.x; |
463 | 0 | else |
464 | 0 | have_ax_bx &= ~HAVE_BX; |
465 | |
|
466 | 0 | switch (have_ax_bx) { |
467 | 0 | default: |
468 | 0 | case HAVE_NEITHER: |
469 | 0 | return edges_compare_x_for_y_general (a, b, y); |
470 | 0 | case HAVE_AX: |
471 | 0 | return -edge_compare_for_y_against_x (b, y, ax); |
472 | 0 | case HAVE_BX: |
473 | 0 | return edge_compare_for_y_against_x (a, y, bx); |
474 | 0 | case HAVE_BOTH: |
475 | 0 | return ax - bx; |
476 | 0 | } |
477 | 0 | } |
478 | | |
479 | | static inline int |
480 | | _line_equal (const cairo_line_t *a, const cairo_line_t *b) |
481 | 0 | { |
482 | 0 | return a->p1.x == b->p1.x && a->p1.y == b->p1.y && |
483 | 0 | a->p2.x == b->p2.x && a->p2.y == b->p2.y; |
484 | 0 | } |
485 | | |
486 | | static int |
487 | | _cairo_bo_sweep_line_compare_edges (cairo_bo_sweep_line_t *sweep_line, |
488 | | const cairo_bo_edge_t *a, |
489 | | const cairo_bo_edge_t *b) |
490 | 0 | { |
491 | 0 | int cmp; |
492 | | |
493 | | /* compare the edges if not identical */ |
494 | 0 | if (! _line_equal (&a->edge.line, &b->edge.line)) { |
495 | 0 | cmp = edges_compare_x_for_y (a, b, sweep_line->current_y); |
496 | 0 | if (cmp) |
497 | 0 | return cmp; |
498 | | |
499 | | /* The two edges intersect exactly at y, so fall back on slope |
500 | | * comparison. We know that this compare_edges function will be |
501 | | * called only when starting a new edge, (not when stopping an |
502 | | * edge), so we don't have to worry about conditionally inverting |
503 | | * the sense of _slope_compare. */ |
504 | 0 | cmp = _slope_compare (a, b); |
505 | 0 | if (cmp) |
506 | 0 | return cmp; |
507 | 0 | } |
508 | | |
509 | | /* We've got two collinear edges now. */ |
510 | 0 | return b->edge.bottom - a->edge.bottom; |
511 | 0 | } |
512 | | |
513 | | static inline cairo_int64_t |
514 | | det32_64 (int32_t a, int32_t b, |
515 | | int32_t c, int32_t d) |
516 | 0 | { |
517 | | /* det = a * d - b * c */ |
518 | 0 | return _cairo_int64_sub (_cairo_int32x32_64_mul (a, d), |
519 | 0 | _cairo_int32x32_64_mul (b, c)); |
520 | 0 | } |
521 | | |
522 | | static inline cairo_int128_t |
523 | | det64x32_128 (cairo_int64_t a, int32_t b, |
524 | | cairo_int64_t c, int32_t d) |
525 | 0 | { |
526 | | /* det = a * d - b * c */ |
527 | 0 | return _cairo_int128_sub (_cairo_int64x32_128_mul (a, d), |
528 | 0 | _cairo_int64x32_128_mul (c, b)); |
529 | 0 | } |
530 | | |
531 | | static inline cairo_bo_intersect_ordinate_t |
532 | | round_to_nearest (cairo_quorem64_t d, |
533 | | cairo_int64_t den) |
534 | 0 | { |
535 | 0 | cairo_bo_intersect_ordinate_t ordinate; |
536 | 0 | int32_t quo = d.quo; |
537 | 0 | cairo_int64_t drem_2 = _cairo_int64_mul (d.rem, _cairo_int32_to_int64 (2)); |
538 | | |
539 | | /* assert (! _cairo_int64_negative (den));*/ |
540 | |
|
541 | 0 | if (_cairo_int64_lt (drem_2, _cairo_int64_negate (den))) { |
542 | 0 | quo -= 1; |
543 | 0 | drem_2 = _cairo_int64_negate (drem_2); |
544 | 0 | } else if (_cairo_int64_le (den, drem_2)) { |
545 | 0 | quo += 1; |
546 | 0 | drem_2 = _cairo_int64_negate (drem_2); |
547 | 0 | } |
548 | |
|
549 | 0 | ordinate.ordinate = quo; |
550 | 0 | ordinate.approx = _cairo_int64_is_zero (drem_2) ? EXACT : _cairo_int64_negative (drem_2) ? EXCESS : DEFAULT; |
551 | |
|
552 | 0 | return ordinate; |
553 | 0 | } |
554 | | |
555 | | /* Compute the intersection of two lines as defined by two edges. The |
556 | | * result is provided as a coordinate pair of 128-bit integers. |
557 | | * |
558 | | * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection or |
559 | | * %CAIRO_BO_STATUS_PARALLEL if the two lines are exactly parallel. |
560 | | */ |
561 | | static cairo_bool_t |
562 | | intersect_lines (cairo_bo_edge_t *a, |
563 | | cairo_bo_edge_t *b, |
564 | | cairo_bo_intersect_point_t *intersection) |
565 | 0 | { |
566 | 0 | cairo_int64_t a_det, b_det; |
567 | | |
568 | | /* XXX: We're assuming here that dx and dy will still fit in 32 |
569 | | * bits. That's not true in general as there could be overflow. We |
570 | | * should prevent that before the tessellation algorithm begins. |
571 | | * What we're doing to mitigate this is to perform clamping in |
572 | | * cairo_bo_tessellate_polygon(). |
573 | | */ |
574 | 0 | int32_t dx1 = a->edge.line.p1.x - a->edge.line.p2.x; |
575 | 0 | int32_t dy1 = a->edge.line.p1.y - a->edge.line.p2.y; |
576 | |
|
577 | 0 | int32_t dx2 = b->edge.line.p1.x - b->edge.line.p2.x; |
578 | 0 | int32_t dy2 = b->edge.line.p1.y - b->edge.line.p2.y; |
579 | |
|
580 | 0 | cairo_int64_t den_det; |
581 | 0 | cairo_int64_t R; |
582 | 0 | cairo_quorem64_t qr; |
583 | |
|
584 | 0 | den_det = det32_64 (dx1, dy1, dx2, dy2); |
585 | | |
586 | | /* Q: Can we determine that the lines do not intersect (within range) |
587 | | * much more cheaply than computing the intersection point i.e. by |
588 | | * avoiding the division? |
589 | | * |
590 | | * X = ax + t * adx = bx + s * bdx; |
591 | | * Y = ay + t * ady = by + s * bdy; |
592 | | * ∴ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx) |
593 | | * => t * L = R |
594 | | * |
595 | | * Therefore we can reject any intersection (under the criteria for |
596 | | * valid intersection events) if: |
597 | | * L^R < 0 => t < 0, or |
598 | | * L<R => t > 1 |
599 | | * |
600 | | * (where top/bottom must at least extend to the line endpoints). |
601 | | * |
602 | | * A similar substitution can be performed for s, yielding: |
603 | | * s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by) |
604 | | */ |
605 | 0 | R = det32_64 (dx2, dy2, |
606 | 0 | b->edge.line.p1.x - a->edge.line.p1.x, |
607 | 0 | b->edge.line.p1.y - a->edge.line.p1.y); |
608 | 0 | if (_cairo_int64_le (den_det, R)) |
609 | 0 | return FALSE; |
610 | | |
611 | 0 | R = det32_64 (dy1, dx1, |
612 | 0 | a->edge.line.p1.y - b->edge.line.p1.y, |
613 | 0 | a->edge.line.p1.x - b->edge.line.p1.x); |
614 | 0 | if (_cairo_int64_le (den_det, R)) |
615 | 0 | return FALSE; |
616 | | |
617 | | /* We now know that the two lines should intersect within range. */ |
618 | | |
619 | 0 | a_det = det32_64 (a->edge.line.p1.x, a->edge.line.p1.y, |
620 | 0 | a->edge.line.p2.x, a->edge.line.p2.y); |
621 | 0 | b_det = det32_64 (b->edge.line.p1.x, b->edge.line.p1.y, |
622 | 0 | b->edge.line.p2.x, b->edge.line.p2.y); |
623 | | |
624 | | /* x = det (a_det, dx1, b_det, dx2) / den_det */ |
625 | 0 | qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1, |
626 | 0 | b_det, dx2), |
627 | 0 | den_det); |
628 | 0 | if (_cairo_int64_eq (qr.rem, den_det)) |
629 | 0 | return FALSE; |
630 | | |
631 | 0 | intersection->x = round_to_nearest (qr, den_det); |
632 | | |
633 | | /* y = det (a_det, dy1, b_det, dy2) / den_det */ |
634 | 0 | qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dy1, |
635 | 0 | b_det, dy2), |
636 | 0 | den_det); |
637 | 0 | if (_cairo_int64_eq (qr.rem, den_det)) |
638 | 0 | return FALSE; |
639 | | |
640 | 0 | intersection->y = round_to_nearest (qr, den_det); |
641 | |
|
642 | 0 | return TRUE; |
643 | 0 | } |
644 | | |
645 | | static int |
646 | | _cairo_bo_intersect_ordinate_32_compare (cairo_bo_intersect_ordinate_t a, |
647 | | int32_t b) |
648 | 0 | { |
649 | | /* First compare the quotient */ |
650 | 0 | if (a.ordinate > b) |
651 | 0 | return +1; |
652 | 0 | if (a.ordinate < b) |
653 | 0 | return -1; |
654 | | |
655 | 0 | return a.approx; /* == EXCESS ? -1 : a.approx == EXACT ? 0 : 1;*/ |
656 | 0 | } |
657 | | |
658 | | /* Does the given edge contain the given point. The point must already |
659 | | * be known to be contained within the line determined by the edge, |
660 | | * (most likely the point results from an intersection of this edge |
661 | | * with another). |
662 | | * |
663 | | * If we had exact arithmetic, then this function would simply be a |
664 | | * matter of examining whether the y value of the point lies within |
665 | | * the range of y values of the edge. But since intersection points |
666 | | * are not exact due to being rounded to the nearest integer within |
667 | | * the available precision, we must also examine the x value of the |
668 | | * point. |
669 | | * |
670 | | * The definition of "contains" here is that the given intersection |
671 | | * point will be seen by the sweep line after the start event for the |
672 | | * given edge and before the stop event for the edge. See the comments |
673 | | * in the implementation for more details. |
674 | | */ |
675 | | static cairo_bool_t |
676 | | _cairo_bo_edge_contains_intersect_point (cairo_bo_edge_t *edge, |
677 | | cairo_bo_intersect_point_t *point) |
678 | 0 | { |
679 | 0 | return _cairo_bo_intersect_ordinate_32_compare (point->y, |
680 | 0 | edge->edge.bottom) < 0; |
681 | 0 | } |
682 | | |
683 | | /* Compute the intersection of two edges. The result is provided as a |
684 | | * coordinate pair of 128-bit integers. |
685 | | * |
686 | | * Returns %CAIRO_BO_STATUS_INTERSECTION if there is an intersection |
687 | | * that is within both edges, %CAIRO_BO_STATUS_NO_INTERSECTION if the |
688 | | * intersection of the lines defined by the edges occurs outside of |
689 | | * one or both edges, and %CAIRO_BO_STATUS_PARALLEL if the two edges |
690 | | * are exactly parallel. |
691 | | * |
692 | | * Note that when determining if a candidate intersection is "inside" |
693 | | * an edge, we consider both the infinitesimal shortening and the |
694 | | * infinitesimal tilt rules described by John Hobby. Specifically, if |
695 | | * the intersection is exactly the same as an edge point, it is |
696 | | * effectively outside (no intersection is returned). Also, if the |
697 | | * intersection point has the same |
698 | | */ |
699 | | static cairo_bool_t |
700 | | _cairo_bo_edge_intersect (cairo_bo_edge_t *a, |
701 | | cairo_bo_edge_t *b, |
702 | | cairo_bo_intersect_point_t *intersection) |
703 | 0 | { |
704 | 0 | if (! intersect_lines (a, b, intersection)) |
705 | 0 | return FALSE; |
706 | | |
707 | 0 | if (! _cairo_bo_edge_contains_intersect_point (a, intersection)) |
708 | 0 | return FALSE; |
709 | | |
710 | 0 | if (! _cairo_bo_edge_contains_intersect_point (b, intersection)) |
711 | 0 | return FALSE; |
712 | | |
713 | 0 | return TRUE; |
714 | 0 | } |
715 | | |
716 | | static inline int |
717 | | cairo_bo_event_compare (const cairo_bo_event_t *a, |
718 | | const cairo_bo_event_t *b) |
719 | 0 | { |
720 | 0 | int cmp; |
721 | |
|
722 | 0 | cmp = _cairo_bo_point32_compare (&a->point, &b->point); |
723 | 0 | if (cmp) |
724 | 0 | return cmp; |
725 | | |
726 | 0 | cmp = a->type - b->type; |
727 | 0 | if (cmp) |
728 | 0 | return cmp; |
729 | | |
730 | 0 | return a < b ? -1 : a == b ? 0 : 1; |
731 | 0 | } |
732 | | |
733 | | static inline void |
734 | | _pqueue_init (pqueue_t *pq) |
735 | 0 | { |
736 | 0 | pq->max_size = ARRAY_LENGTH (pq->elements_embedded); |
737 | 0 | pq->size = 0; |
738 | |
|
739 | 0 | pq->elements = pq->elements_embedded; |
740 | 0 | } |
741 | | |
742 | | static inline void |
743 | | _pqueue_fini (pqueue_t *pq) |
744 | 0 | { |
745 | 0 | if (pq->elements != pq->elements_embedded) |
746 | 0 | free (pq->elements); |
747 | 0 | } |
748 | | |
749 | | static cairo_status_t |
750 | | _pqueue_grow (pqueue_t *pq) |
751 | 0 | { |
752 | 0 | cairo_bo_event_t **new_elements; |
753 | 0 | pq->max_size *= 2; |
754 | |
|
755 | 0 | if (pq->elements == pq->elements_embedded) { |
756 | 0 | new_elements = _cairo_malloc_ab (pq->max_size, |
757 | 0 | sizeof (cairo_bo_event_t *)); |
758 | 0 | if (unlikely (new_elements == NULL)) |
759 | 0 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
760 | | |
761 | 0 | memcpy (new_elements, pq->elements_embedded, |
762 | 0 | sizeof (pq->elements_embedded)); |
763 | 0 | } else { |
764 | 0 | new_elements = _cairo_realloc_ab (pq->elements, |
765 | 0 | pq->max_size, |
766 | 0 | sizeof (cairo_bo_event_t *)); |
767 | 0 | if (unlikely (new_elements == NULL)) |
768 | 0 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
769 | 0 | } |
770 | | |
771 | 0 | pq->elements = new_elements; |
772 | 0 | return CAIRO_STATUS_SUCCESS; |
773 | 0 | } |
774 | | |
775 | | static inline cairo_status_t |
776 | | _pqueue_push (pqueue_t *pq, cairo_bo_event_t *event) |
777 | 0 | { |
778 | 0 | cairo_bo_event_t **elements; |
779 | 0 | int i, parent; |
780 | |
|
781 | 0 | if (unlikely (pq->size + 1 == pq->max_size)) { |
782 | 0 | cairo_status_t status; |
783 | |
|
784 | 0 | status = _pqueue_grow (pq); |
785 | 0 | if (unlikely (status)) |
786 | 0 | return status; |
787 | 0 | } |
788 | | |
789 | 0 | elements = pq->elements; |
790 | |
|
791 | 0 | for (i = ++pq->size; |
792 | 0 | i != PQ_FIRST_ENTRY && |
793 | 0 | cairo_bo_event_compare (event, |
794 | 0 | elements[parent = PQ_PARENT_INDEX (i)]) < 0; |
795 | 0 | i = parent) |
796 | 0 | { |
797 | 0 | elements[i] = elements[parent]; |
798 | 0 | } |
799 | |
|
800 | 0 | elements[i] = event; |
801 | |
|
802 | 0 | return CAIRO_STATUS_SUCCESS; |
803 | 0 | } |
804 | | |
805 | | static inline void |
806 | | _pqueue_pop (pqueue_t *pq) |
807 | 0 | { |
808 | 0 | cairo_bo_event_t **elements = pq->elements; |
809 | 0 | cairo_bo_event_t *tail; |
810 | 0 | int child, i; |
811 | |
|
812 | 0 | tail = elements[pq->size--]; |
813 | 0 | if (pq->size == 0) { |
814 | 0 | elements[PQ_FIRST_ENTRY] = NULL; |
815 | 0 | return; |
816 | 0 | } |
817 | | |
818 | 0 | for (i = PQ_FIRST_ENTRY; |
819 | 0 | (child = PQ_LEFT_CHILD_INDEX (i)) <= pq->size; |
820 | 0 | i = child) |
821 | 0 | { |
822 | 0 | if (child != pq->size && |
823 | 0 | cairo_bo_event_compare (elements[child+1], |
824 | 0 | elements[child]) < 0) |
825 | 0 | { |
826 | 0 | child++; |
827 | 0 | } |
828 | |
|
829 | 0 | if (cairo_bo_event_compare (elements[child], tail) >= 0) |
830 | 0 | break; |
831 | | |
832 | 0 | elements[i] = elements[child]; |
833 | 0 | } |
834 | 0 | elements[i] = tail; |
835 | 0 | } |
836 | | |
837 | | static inline cairo_status_t |
838 | | _cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue, |
839 | | cairo_bo_event_type_t type, |
840 | | cairo_bo_edge_t *e1, |
841 | | cairo_bo_edge_t *e2, |
842 | | const cairo_bo_intersect_point_t *point) |
843 | 0 | { |
844 | 0 | cairo_bo_queue_event_t *event; |
845 | |
|
846 | 0 | event = _cairo_freepool_alloc (&queue->pool); |
847 | 0 | if (unlikely (event == NULL)) |
848 | 0 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
849 | | |
850 | 0 | event->type = type; |
851 | 0 | event->e1 = e1; |
852 | 0 | event->e2 = e2; |
853 | 0 | event->point = *point; |
854 | |
|
855 | 0 | return _pqueue_push (&queue->pqueue, (cairo_bo_event_t *) event); |
856 | 0 | } |
857 | | |
858 | | static void |
859 | | _cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue, |
860 | | cairo_bo_event_t *event) |
861 | 0 | { |
862 | 0 | _cairo_freepool_free (&queue->pool, event); |
863 | 0 | } |
864 | | |
865 | | static cairo_bo_event_t * |
866 | | _cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue) |
867 | 0 | { |
868 | 0 | cairo_bo_event_t *event, *cmp; |
869 | |
|
870 | 0 | event = event_queue->pqueue.elements[PQ_FIRST_ENTRY]; |
871 | 0 | cmp = *event_queue->start_events; |
872 | 0 | if (event == NULL || |
873 | 0 | (cmp != NULL && cairo_bo_event_compare (cmp, event) < 0)) |
874 | 0 | { |
875 | 0 | event = cmp; |
876 | 0 | event_queue->start_events++; |
877 | 0 | } |
878 | 0 | else |
879 | 0 | { |
880 | 0 | _pqueue_pop (&event_queue->pqueue); |
881 | 0 | } |
882 | |
|
883 | 0 | return event; |
884 | 0 | } |
885 | | |
886 | | CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort, |
887 | | cairo_bo_event_t *, |
888 | | cairo_bo_event_compare) |
889 | | |
890 | | static void |
891 | | _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue, |
892 | | cairo_bo_event_t **start_events, |
893 | | int num_events) |
894 | 0 | { |
895 | 0 | _cairo_bo_event_queue_sort (start_events, num_events); |
896 | 0 | start_events[num_events] = NULL; |
897 | |
|
898 | 0 | event_queue->start_events = start_events; |
899 | |
|
900 | 0 | _cairo_freepool_init (&event_queue->pool, |
901 | 0 | sizeof (cairo_bo_queue_event_t)); |
902 | 0 | _pqueue_init (&event_queue->pqueue); |
903 | 0 | event_queue->pqueue.elements[PQ_FIRST_ENTRY] = NULL; |
904 | 0 | } |
905 | | |
906 | | static cairo_status_t |
907 | | event_queue_insert_stop (cairo_bo_event_queue_t *event_queue, |
908 | | cairo_bo_edge_t *edge) |
909 | 0 | { |
910 | 0 | cairo_bo_intersect_point_t point; |
911 | |
|
912 | 0 | point.y.ordinate = edge->edge.bottom; |
913 | 0 | point.y.approx = EXACT; |
914 | 0 | point.x.ordinate = _line_compute_intersection_x_for_y (&edge->edge.line, |
915 | 0 | point.y.ordinate); |
916 | 0 | point.x.approx = EXACT; |
917 | |
|
918 | 0 | return _cairo_bo_event_queue_insert (event_queue, |
919 | 0 | CAIRO_BO_EVENT_TYPE_STOP, |
920 | 0 | edge, NULL, |
921 | 0 | &point); |
922 | 0 | } |
923 | | |
924 | | static void |
925 | | _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue) |
926 | 0 | { |
927 | 0 | _pqueue_fini (&event_queue->pqueue); |
928 | 0 | _cairo_freepool_fini (&event_queue->pool); |
929 | 0 | } |
930 | | |
931 | | static inline cairo_status_t |
932 | | event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue, |
933 | | cairo_bo_edge_t *left, |
934 | | cairo_bo_edge_t *right) |
935 | 0 | { |
936 | 0 | cairo_bo_intersect_point_t intersection; |
937 | |
|
938 | 0 | if (_line_equal (&left->edge.line, &right->edge.line)) |
939 | 0 | return CAIRO_STATUS_SUCCESS; |
940 | | |
941 | | /* The names "left" and "right" here are correct descriptions of |
942 | | * the order of the two edges within the active edge list. So if a |
943 | | * slope comparison also puts left less than right, then we know |
944 | | * that the intersection of these two segments has already |
945 | | * occurred before the current sweep line position. */ |
946 | 0 | if (_slope_compare (left, right) <= 0) |
947 | 0 | return CAIRO_STATUS_SUCCESS; |
948 | | |
949 | 0 | if (! _cairo_bo_edge_intersect (left, right, &intersection)) |
950 | 0 | return CAIRO_STATUS_SUCCESS; |
951 | | |
952 | 0 | return _cairo_bo_event_queue_insert (event_queue, |
953 | 0 | CAIRO_BO_EVENT_TYPE_INTERSECTION, |
954 | 0 | left, right, |
955 | 0 | &intersection); |
956 | 0 | } |
957 | | |
958 | | static void |
959 | | _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line) |
960 | 0 | { |
961 | 0 | sweep_line->head = NULL; |
962 | 0 | sweep_line->current_y = INT32_MIN; |
963 | 0 | sweep_line->current_edge = NULL; |
964 | 0 | } |
965 | | |
966 | | static cairo_status_t |
967 | | sweep_line_insert (cairo_bo_sweep_line_t *sweep_line, |
968 | | cairo_bo_edge_t *edge) |
969 | 0 | { |
970 | 0 | if (sweep_line->current_edge != NULL) { |
971 | 0 | cairo_bo_edge_t *prev, *next; |
972 | 0 | int cmp; |
973 | |
|
974 | 0 | cmp = _cairo_bo_sweep_line_compare_edges (sweep_line, |
975 | 0 | sweep_line->current_edge, |
976 | 0 | edge); |
977 | 0 | if (cmp < 0) { |
978 | 0 | prev = sweep_line->current_edge; |
979 | 0 | next = prev->next; |
980 | 0 | while (next != NULL && |
981 | 0 | _cairo_bo_sweep_line_compare_edges (sweep_line, |
982 | 0 | next, edge) < 0) |
983 | 0 | { |
984 | 0 | prev = next, next = prev->next; |
985 | 0 | } |
986 | |
|
987 | 0 | prev->next = edge; |
988 | 0 | edge->prev = prev; |
989 | 0 | edge->next = next; |
990 | 0 | if (next != NULL) |
991 | 0 | next->prev = edge; |
992 | 0 | } else if (cmp > 0) { |
993 | 0 | next = sweep_line->current_edge; |
994 | 0 | prev = next->prev; |
995 | 0 | while (prev != NULL && |
996 | 0 | _cairo_bo_sweep_line_compare_edges (sweep_line, |
997 | 0 | prev, edge) > 0) |
998 | 0 | { |
999 | 0 | next = prev, prev = next->prev; |
1000 | 0 | } |
1001 | |
|
1002 | 0 | next->prev = edge; |
1003 | 0 | edge->next = next; |
1004 | 0 | edge->prev = prev; |
1005 | 0 | if (prev != NULL) |
1006 | 0 | prev->next = edge; |
1007 | 0 | else |
1008 | 0 | sweep_line->head = edge; |
1009 | 0 | } else { |
1010 | 0 | prev = sweep_line->current_edge; |
1011 | 0 | edge->prev = prev; |
1012 | 0 | edge->next = prev->next; |
1013 | 0 | if (prev->next != NULL) |
1014 | 0 | prev->next->prev = edge; |
1015 | 0 | prev->next = edge; |
1016 | 0 | } |
1017 | 0 | } else { |
1018 | 0 | sweep_line->head = edge; |
1019 | 0 | } |
1020 | |
|
1021 | 0 | sweep_line->current_edge = edge; |
1022 | |
|
1023 | 0 | return CAIRO_STATUS_SUCCESS; |
1024 | 0 | } |
1025 | | |
1026 | | static void |
1027 | | _cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line, |
1028 | | cairo_bo_edge_t *edge) |
1029 | 0 | { |
1030 | 0 | if (edge->prev != NULL) |
1031 | 0 | edge->prev->next = edge->next; |
1032 | 0 | else |
1033 | 0 | sweep_line->head = edge->next; |
1034 | |
|
1035 | 0 | if (edge->next != NULL) |
1036 | 0 | edge->next->prev = edge->prev; |
1037 | |
|
1038 | 0 | if (sweep_line->current_edge == edge) |
1039 | 0 | sweep_line->current_edge = edge->prev ? edge->prev : edge->next; |
1040 | 0 | } |
1041 | | |
1042 | | static void |
1043 | | _cairo_bo_sweep_line_swap (cairo_bo_sweep_line_t *sweep_line, |
1044 | | cairo_bo_edge_t *left, |
1045 | | cairo_bo_edge_t *right) |
1046 | 0 | { |
1047 | 0 | if (left->prev != NULL) |
1048 | 0 | left->prev->next = right; |
1049 | 0 | else |
1050 | 0 | sweep_line->head = right; |
1051 | |
|
1052 | 0 | if (right->next != NULL) |
1053 | 0 | right->next->prev = left; |
1054 | |
|
1055 | 0 | left->next = right->next; |
1056 | 0 | right->next = left; |
1057 | |
|
1058 | 0 | right->prev = left->prev; |
1059 | 0 | left->prev = right; |
1060 | 0 | } |
1061 | | |
1062 | | static inline cairo_bool_t |
1063 | | edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b) |
1064 | 0 | { |
1065 | 0 | if (_line_equal (&a->edge.line, &b->edge.line)) |
1066 | 0 | return TRUE; |
1067 | | |
1068 | 0 | if (_slope_compare (a, b)) |
1069 | 0 | return FALSE; |
1070 | | |
1071 | | /* The choice of y is not truly arbitrary since we must guarantee that it |
1072 | | * is greater than the start of either line. |
1073 | | */ |
1074 | 0 | if (a->edge.line.p1.y == b->edge.line.p1.y) { |
1075 | 0 | return a->edge.line.p1.x == b->edge.line.p1.x; |
1076 | 0 | } else if (a->edge.line.p1.y < b->edge.line.p1.y) { |
1077 | 0 | return edge_compare_for_y_against_x (b, |
1078 | 0 | a->edge.line.p1.y, |
1079 | 0 | a->edge.line.p1.x) == 0; |
1080 | 0 | } else { |
1081 | 0 | return edge_compare_for_y_against_x (a, |
1082 | 0 | b->edge.line.p1.y, |
1083 | 0 | b->edge.line.p1.x) == 0; |
1084 | 0 | } |
1085 | 0 | } |
1086 | | |
1087 | | static void |
1088 | | edges_end (cairo_bo_edge_t *left, |
1089 | | int32_t bot, |
1090 | | cairo_polygon_t *polygon) |
1091 | 0 | { |
1092 | 0 | cairo_bo_deferred_t *l = &left->deferred; |
1093 | 0 | cairo_bo_edge_t *right = l->other; |
1094 | |
|
1095 | 0 | assert(right->deferred.other == NULL); |
1096 | 0 | if (likely (l->top < bot)) { |
1097 | 0 | _cairo_polygon_add_line (polygon, &left->edge.line, l->top, bot, 1); |
1098 | 0 | _cairo_polygon_add_line (polygon, &right->edge.line, l->top, bot, -1); |
1099 | 0 | } |
1100 | |
|
1101 | 0 | l->other = NULL; |
1102 | 0 | } |
1103 | | |
1104 | | static inline void |
1105 | | edges_start_or_continue (cairo_bo_edge_t *left, |
1106 | | cairo_bo_edge_t *right, |
1107 | | int top, |
1108 | | cairo_polygon_t *polygon) |
1109 | 0 | { |
1110 | 0 | assert (right != NULL); |
1111 | 0 | assert (right->deferred.other == NULL); |
1112 | | |
1113 | 0 | if (left->deferred.other == right) |
1114 | 0 | return; |
1115 | | |
1116 | 0 | if (left->deferred.other != NULL) { |
1117 | 0 | if (edges_colinear (left->deferred.other, right)) { |
1118 | 0 | cairo_bo_edge_t *old = left->deferred.other; |
1119 | | |
1120 | | /* continuation on right, extend right to cover both */ |
1121 | 0 | assert (old->deferred.other == NULL); |
1122 | 0 | assert (old->edge.line.p2.y > old->edge.line.p1.y); |
1123 | | |
1124 | 0 | if (old->edge.line.p1.y < right->edge.line.p1.y) |
1125 | 0 | right->edge.line.p1 = old->edge.line.p1; |
1126 | 0 | if (old->edge.line.p2.y > right->edge.line.p2.y) |
1127 | 0 | right->edge.line.p2 = old->edge.line.p2; |
1128 | 0 | left->deferred.other = right; |
1129 | 0 | return; |
1130 | 0 | } |
1131 | | |
1132 | 0 | edges_end (left, top, polygon); |
1133 | 0 | } |
1134 | | |
1135 | 0 | if (! edges_colinear (left, right)) { |
1136 | 0 | left->deferred.top = top; |
1137 | 0 | left->deferred.other = right; |
1138 | 0 | } |
1139 | 0 | } |
1140 | | |
1141 | 0 | #define is_zero(w) ((w)[0] == 0 || (w)[1] == 0) |
1142 | | |
1143 | | static inline void |
1144 | | active_edges (cairo_bo_edge_t *left, |
1145 | | int32_t top, |
1146 | | cairo_polygon_t *polygon) |
1147 | 0 | { |
1148 | 0 | cairo_bo_edge_t *right; |
1149 | 0 | int winding[2] = {0, 0}; |
1150 | | |
1151 | | /* Yes, this is naive. Consider this a placeholder. */ |
1152 | |
|
1153 | 0 | while (left != NULL) { |
1154 | 0 | assert (is_zero (winding)); |
1155 | | |
1156 | 0 | do { |
1157 | 0 | winding[left->a_or_b] += left->edge.dir; |
1158 | 0 | if (! is_zero (winding)) |
1159 | 0 | break; |
1160 | | |
1161 | 0 | if unlikely ((left->deferred.other)) |
1162 | 0 | edges_end (left, top, polygon); |
1163 | |
|
1164 | 0 | left = left->next; |
1165 | 0 | if (! left) |
1166 | 0 | return; |
1167 | 0 | } while (1); |
1168 | | |
1169 | 0 | right = left->next; |
1170 | 0 | do { |
1171 | 0 | if unlikely ((right->deferred.other)) |
1172 | 0 | edges_end (right, top, polygon); |
1173 | |
|
1174 | 0 | winding[right->a_or_b] += right->edge.dir; |
1175 | 0 | if (is_zero (winding)) { |
1176 | 0 | if (right->next == NULL || |
1177 | 0 | ! edges_colinear (right, right->next)) |
1178 | 0 | break; |
1179 | 0 | } |
1180 | | |
1181 | 0 | right = right->next; |
1182 | 0 | } while (1); |
1183 | | |
1184 | 0 | edges_start_or_continue (left, right, top, polygon); |
1185 | |
|
1186 | 0 | left = right->next; |
1187 | 0 | } |
1188 | 0 | } |
1189 | | |
1190 | | static cairo_status_t |
1191 | | intersection_sweep (cairo_bo_event_t **start_events, |
1192 | | int num_events, |
1193 | | cairo_polygon_t *polygon) |
1194 | 0 | { |
1195 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; /* silence compiler */ |
1196 | 0 | cairo_bo_event_queue_t event_queue; |
1197 | 0 | cairo_bo_sweep_line_t sweep_line; |
1198 | 0 | cairo_bo_event_t *event; |
1199 | 0 | cairo_bo_edge_t *left, *right; |
1200 | 0 | cairo_bo_edge_t *e1, *e2; |
1201 | |
|
1202 | 0 | _cairo_bo_event_queue_init (&event_queue, start_events, num_events); |
1203 | 0 | _cairo_bo_sweep_line_init (&sweep_line); |
1204 | |
|
1205 | 0 | while ((event = _cairo_bo_event_dequeue (&event_queue))) { |
1206 | 0 | if (event->point.y.ordinate != sweep_line.current_y) { |
1207 | 0 | active_edges (sweep_line.head, |
1208 | 0 | sweep_line.current_y, |
1209 | 0 | polygon); |
1210 | 0 | sweep_line.current_y = event->point.y.ordinate; |
1211 | 0 | } |
1212 | |
|
1213 | 0 | switch (event->type) { |
1214 | 0 | case CAIRO_BO_EVENT_TYPE_START: |
1215 | 0 | e1 = &((cairo_bo_start_event_t *) event)->edge; |
1216 | |
|
1217 | 0 | status = sweep_line_insert (&sweep_line, e1); |
1218 | 0 | if (unlikely (status)) |
1219 | 0 | goto unwind; |
1220 | | |
1221 | 0 | status = event_queue_insert_stop (&event_queue, e1); |
1222 | 0 | if (unlikely (status)) |
1223 | 0 | goto unwind; |
1224 | | |
1225 | 0 | left = e1->prev; |
1226 | 0 | right = e1->next; |
1227 | |
|
1228 | 0 | if (left != NULL) { |
1229 | 0 | status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, e1); |
1230 | 0 | if (unlikely (status)) |
1231 | 0 | goto unwind; |
1232 | 0 | } |
1233 | | |
1234 | 0 | if (right != NULL) { |
1235 | 0 | status = event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right); |
1236 | 0 | if (unlikely (status)) |
1237 | 0 | goto unwind; |
1238 | 0 | } |
1239 | | |
1240 | 0 | break; |
1241 | | |
1242 | 0 | case CAIRO_BO_EVENT_TYPE_STOP: |
1243 | 0 | e1 = ((cairo_bo_queue_event_t *) event)->e1; |
1244 | 0 | _cairo_bo_event_queue_delete (&event_queue, event); |
1245 | |
|
1246 | 0 | if (e1->deferred.other) |
1247 | 0 | edges_end (e1, sweep_line.current_y, polygon); |
1248 | |
|
1249 | 0 | left = e1->prev; |
1250 | 0 | right = e1->next; |
1251 | |
|
1252 | 0 | _cairo_bo_sweep_line_delete (&sweep_line, e1); |
1253 | |
|
1254 | 0 | if (left != NULL && right != NULL) { |
1255 | 0 | status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, right); |
1256 | 0 | if (unlikely (status)) |
1257 | 0 | goto unwind; |
1258 | 0 | } |
1259 | | |
1260 | 0 | break; |
1261 | | |
1262 | 0 | case CAIRO_BO_EVENT_TYPE_INTERSECTION: |
1263 | 0 | e1 = ((cairo_bo_queue_event_t *) event)->e1; |
1264 | 0 | e2 = ((cairo_bo_queue_event_t *) event)->e2; |
1265 | 0 | _cairo_bo_event_queue_delete (&event_queue, event); |
1266 | | |
1267 | | /* skip this intersection if its edges are not adjacent */ |
1268 | 0 | if (e2 != e1->next) |
1269 | 0 | break; |
1270 | | |
1271 | 0 | if (e1->deferred.other) |
1272 | 0 | edges_end (e1, sweep_line.current_y, polygon); |
1273 | 0 | if (e2->deferred.other) |
1274 | 0 | edges_end (e2, sweep_line.current_y, polygon); |
1275 | |
|
1276 | 0 | left = e1->prev; |
1277 | 0 | right = e2->next; |
1278 | |
|
1279 | 0 | _cairo_bo_sweep_line_swap (&sweep_line, e1, e2); |
1280 | | |
1281 | | /* after the swap e2 is left of e1 */ |
1282 | |
|
1283 | 0 | if (left != NULL) { |
1284 | 0 | status = event_queue_insert_if_intersect_below_current_y (&event_queue, left, e2); |
1285 | 0 | if (unlikely (status)) |
1286 | 0 | goto unwind; |
1287 | 0 | } |
1288 | | |
1289 | 0 | if (right != NULL) { |
1290 | 0 | status = event_queue_insert_if_intersect_below_current_y (&event_queue, e1, right); |
1291 | 0 | if (unlikely (status)) |
1292 | 0 | goto unwind; |
1293 | 0 | } |
1294 | | |
1295 | 0 | break; |
1296 | 0 | } |
1297 | 0 | } |
1298 | | |
1299 | 0 | unwind: |
1300 | 0 | _cairo_bo_event_queue_fini (&event_queue); |
1301 | |
|
1302 | 0 | return status; |
1303 | 0 | } |
1304 | | |
1305 | | cairo_status_t |
1306 | | _cairo_polygon_intersect (cairo_polygon_t *a, int winding_a, |
1307 | | cairo_polygon_t *b, int winding_b) |
1308 | 0 | { |
1309 | 0 | cairo_status_t status; |
1310 | 0 | cairo_bo_start_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_start_event_t)]; |
1311 | 0 | cairo_bo_start_event_t *events; |
1312 | 0 | cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1]; |
1313 | 0 | cairo_bo_event_t **event_ptrs; |
1314 | 0 | int num_events; |
1315 | 0 | int i, j; |
1316 | | |
1317 | | /* XXX lazy */ |
1318 | 0 | if (winding_a != CAIRO_FILL_RULE_WINDING) { |
1319 | 0 | status = _cairo_polygon_reduce (a, winding_a); |
1320 | 0 | if (unlikely (status)) |
1321 | 0 | return status; |
1322 | 0 | } |
1323 | | |
1324 | 0 | if (winding_b != CAIRO_FILL_RULE_WINDING) { |
1325 | 0 | status = _cairo_polygon_reduce (b, winding_b); |
1326 | 0 | if (unlikely (status)) |
1327 | 0 | return status; |
1328 | 0 | } |
1329 | | |
1330 | 0 | if (unlikely (0 == a->num_edges)) |
1331 | 0 | return CAIRO_STATUS_SUCCESS; |
1332 | | |
1333 | 0 | if (unlikely (0 == b->num_edges)) { |
1334 | 0 | a->num_edges = 0; |
1335 | 0 | return CAIRO_STATUS_SUCCESS; |
1336 | 0 | } |
1337 | | |
1338 | 0 | events = stack_events; |
1339 | 0 | event_ptrs = stack_event_ptrs; |
1340 | 0 | num_events = a->num_edges + b->num_edges; |
1341 | 0 | if (num_events > ARRAY_LENGTH (stack_events)) { |
1342 | 0 | events = _cairo_malloc_ab_plus_c (num_events, |
1343 | 0 | sizeof (cairo_bo_start_event_t) + |
1344 | 0 | sizeof (cairo_bo_event_t *), |
1345 | 0 | sizeof (cairo_bo_event_t *)); |
1346 | 0 | if (unlikely (events == NULL)) |
1347 | 0 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1348 | | |
1349 | 0 | event_ptrs = (cairo_bo_event_t **) (events + num_events); |
1350 | 0 | } |
1351 | | |
1352 | 0 | j = 0; |
1353 | 0 | for (i = 0; i < a->num_edges; i++) { |
1354 | 0 | event_ptrs[j] = (cairo_bo_event_t *) &events[j]; |
1355 | |
|
1356 | 0 | events[j].type = CAIRO_BO_EVENT_TYPE_START; |
1357 | 0 | events[j].point.y.ordinate = a->edges[i].top; |
1358 | 0 | events[j].point.y.approx = EXACT; |
1359 | 0 | events[j].point.x.ordinate = |
1360 | 0 | _line_compute_intersection_x_for_y (&a->edges[i].line, |
1361 | 0 | events[j].point.y.ordinate); |
1362 | 0 | events[j].point.x.approx = EXACT; |
1363 | |
|
1364 | 0 | events[j].edge.a_or_b = 0; |
1365 | 0 | events[j].edge.edge = a->edges[i]; |
1366 | 0 | events[j].edge.deferred.other = NULL; |
1367 | 0 | events[j].edge.prev = NULL; |
1368 | 0 | events[j].edge.next = NULL; |
1369 | 0 | j++; |
1370 | 0 | } |
1371 | |
|
1372 | 0 | for (i = 0; i < b->num_edges; i++) { |
1373 | 0 | event_ptrs[j] = (cairo_bo_event_t *) &events[j]; |
1374 | |
|
1375 | 0 | events[j].type = CAIRO_BO_EVENT_TYPE_START; |
1376 | 0 | events[j].point.y.ordinate = b->edges[i].top; |
1377 | 0 | events[j].point.y.approx = EXACT; |
1378 | 0 | events[j].point.x.ordinate = |
1379 | 0 | _line_compute_intersection_x_for_y (&b->edges[i].line, |
1380 | 0 | events[j].point.y.ordinate); |
1381 | 0 | events[j].point.x.approx = EXACT; |
1382 | |
|
1383 | 0 | events[j].edge.a_or_b = 1; |
1384 | 0 | events[j].edge.edge = b->edges[i]; |
1385 | 0 | events[j].edge.deferred.other = NULL; |
1386 | 0 | events[j].edge.prev = NULL; |
1387 | 0 | events[j].edge.next = NULL; |
1388 | 0 | j++; |
1389 | 0 | } |
1390 | 0 | assert (j == num_events); |
1391 | | |
1392 | | #if 0 |
1393 | | { |
1394 | | FILE *file = fopen ("clip_a.txt", "w"); |
1395 | | _cairo_debug_print_polygon (file, a); |
1396 | | fclose (file); |
1397 | | } |
1398 | | { |
1399 | | FILE *file = fopen ("clip_b.txt", "w"); |
1400 | | _cairo_debug_print_polygon (file, b); |
1401 | | fclose (file); |
1402 | | } |
1403 | | #endif |
1404 | | |
1405 | 0 | a->num_edges = 0; |
1406 | 0 | status = intersection_sweep (event_ptrs, num_events, a); |
1407 | 0 | if (events != stack_events) |
1408 | 0 | free (events); |
1409 | |
|
1410 | | #if 0 |
1411 | | { |
1412 | | FILE *file = fopen ("clip_result.txt", "w"); |
1413 | | _cairo_debug_print_polygon (file, a); |
1414 | | fclose (file); |
1415 | | } |
1416 | | #endif |
1417 | |
|
1418 | 0 | return status; |
1419 | 0 | } |
1420 | | |
1421 | | cairo_status_t |
1422 | | _cairo_polygon_intersect_with_boxes (cairo_polygon_t *polygon, |
1423 | | cairo_fill_rule_t *winding, |
1424 | | cairo_box_t *boxes, |
1425 | | int num_boxes) |
1426 | 0 | { |
1427 | 0 | cairo_polygon_t b; |
1428 | 0 | cairo_status_t status; |
1429 | 0 | int n; |
1430 | |
|
1431 | 0 | if (num_boxes == 0) { |
1432 | 0 | polygon->num_edges = 0; |
1433 | 0 | return CAIRO_STATUS_SUCCESS; |
1434 | 0 | } |
1435 | | |
1436 | 0 | for (n = 0; n < num_boxes; n++) { |
1437 | 0 | if (polygon->extents.p1.x >= boxes[n].p1.x && |
1438 | 0 | polygon->extents.p2.x <= boxes[n].p2.x && |
1439 | 0 | polygon->extents.p1.y >= boxes[n].p1.y && |
1440 | 0 | polygon->extents.p2.y <= boxes[n].p2.y) |
1441 | 0 | { |
1442 | 0 | return CAIRO_STATUS_SUCCESS; |
1443 | 0 | } |
1444 | 0 | } |
1445 | | |
1446 | 0 | _cairo_polygon_init (&b, NULL, 0); |
1447 | 0 | for (n = 0; n < num_boxes; n++) { |
1448 | 0 | if (boxes[n].p2.x > polygon->extents.p1.x && |
1449 | 0 | boxes[n].p1.x < polygon->extents.p2.x && |
1450 | 0 | boxes[n].p2.y > polygon->extents.p1.y && |
1451 | 0 | boxes[n].p1.y < polygon->extents.p2.y) |
1452 | 0 | { |
1453 | 0 | cairo_point_t p1, p2; |
1454 | |
|
1455 | 0 | p1.y = boxes[n].p1.y; |
1456 | 0 | p2.y = boxes[n].p2.y; |
1457 | |
|
1458 | 0 | p2.x = p1.x = boxes[n].p1.x; |
1459 | 0 | _cairo_polygon_add_external_edge (&b, &p1, &p2); |
1460 | |
|
1461 | 0 | p2.x = p1.x = boxes[n].p2.x; |
1462 | 0 | _cairo_polygon_add_external_edge (&b, &p2, &p1); |
1463 | 0 | } |
1464 | 0 | } |
1465 | |
|
1466 | 0 | status = _cairo_polygon_intersect (polygon, *winding, |
1467 | 0 | &b, CAIRO_FILL_RULE_WINDING); |
1468 | 0 | _cairo_polygon_fini (&b); |
1469 | |
|
1470 | 0 | *winding = CAIRO_FILL_RULE_WINDING; |
1471 | 0 | return status; |
1472 | 0 | } |