rev |
line source |
slaxemulator@13173
|
1 From f228769dfe5a8b5d73c49a41e95e31ed73a77fb3 Mon Sep 17 00:00:00 2001
|
slaxemulator@13173
|
2 From: Chris Wilson <chris@chris-wilson.co.uk>
|
slaxemulator@13173
|
3 Date: Fri, 08 Jun 2012 16:22:41 +0000
|
slaxemulator@13173
|
4 Subject: polygon-reduce: Reduce broken stopped-edge continuation
|
slaxemulator@13173
|
5
|
slaxemulator@13173
|
6 This is hopefully a lesser used path and the attempted optimisation to
|
slaxemulator@13173
|
7 continue a stopped edge with a colinear stopped edge highly unlikely and
|
slaxemulator@13173
|
8 lost in the noise of the general inefficiency of the routine. As it was
|
slaxemulator@13173
|
9 broken, rather than attempt to rectify the "optimisation" remove it.
|
slaxemulator@13173
|
10
|
slaxemulator@13173
|
11 Reported-by: Evangelos Foutras <evangelos@foutrelis.com>
|
slaxemulator@13173
|
12 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50852
|
slaxemulator@13173
|
13 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
slaxemulator@13173
|
14 ---
|
slaxemulator@13173
|
15 diff --git a/src/cairo-polygon-reduce.c b/src/cairo-polygon-reduce.c
|
slaxemulator@13173
|
16 index 8758070..ea457fe 100644
|
slaxemulator@13173
|
17 --- a/src/cairo-polygon-reduce.c
|
slaxemulator@13173
|
18 +++ b/src/cairo-polygon-reduce.c
|
slaxemulator@13173
|
19 @@ -42,6 +42,8 @@
|
slaxemulator@13173
|
20 #include "cairo-freelist-private.h"
|
slaxemulator@13173
|
21 #include "cairo-combsort-inline.h"
|
slaxemulator@13173
|
22
|
slaxemulator@13173
|
23 +#define DEBUG_POLYGON 0
|
slaxemulator@13173
|
24 +
|
slaxemulator@13173
|
25 typedef cairo_point_t cairo_bo_point32_t;
|
slaxemulator@13173
|
26
|
slaxemulator@13173
|
27 typedef struct _cairo_bo_intersect_ordinate {
|
slaxemulator@13173
|
28 @@ -114,7 +116,6 @@ typedef struct _cairo_bo_event_queue {
|
slaxemulator@13173
|
29
|
slaxemulator@13173
|
30 typedef struct _cairo_bo_sweep_line {
|
slaxemulator@13173
|
31 cairo_bo_edge_t *head;
|
slaxemulator@13173
|
32 - cairo_bo_edge_t *stopped;
|
slaxemulator@13173
|
33 int32_t current_y;
|
slaxemulator@13173
|
34 cairo_bo_edge_t *current_edge;
|
slaxemulator@13173
|
35 } cairo_bo_sweep_line_t;
|
slaxemulator@13173
|
36 @@ -476,8 +477,8 @@ edges_compare_x_for_y (const cairo_bo_edge_t *a,
|
slaxemulator@13173
|
37 static inline int
|
slaxemulator@13173
|
38 _line_equal (const cairo_line_t *a, const cairo_line_t *b)
|
slaxemulator@13173
|
39 {
|
slaxemulator@13173
|
40 - return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
|
slaxemulator@13173
|
41 - a->p2.x == b->p2.x && a->p2.y == b->p2.y;
|
slaxemulator@13173
|
42 + return (a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
|
slaxemulator@13173
|
43 + a->p2.x == b->p2.x && a->p2.y == b->p2.y);
|
slaxemulator@13173
|
44 }
|
slaxemulator@13173
|
45
|
slaxemulator@13173
|
46 static int
|
slaxemulator@13173
|
47 @@ -1024,7 +1025,6 @@ static void
|
slaxemulator@13173
|
48 _cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
|
slaxemulator@13173
|
49 {
|
slaxemulator@13173
|
50 sweep_line->head = NULL;
|
slaxemulator@13173
|
51 - sweep_line->stopped = NULL;
|
slaxemulator@13173
|
52 sweep_line->current_y = INT32_MIN;
|
slaxemulator@13173
|
53 sweep_line->current_edge = NULL;
|
slaxemulator@13173
|
54 }
|
slaxemulator@13173
|
55 @@ -1139,6 +1139,8 @@ edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
|
slaxemulator@13173
|
56 */
|
slaxemulator@13173
|
57 if (a->edge.line.p1.y == b->edge.line.p1.y) {
|
slaxemulator@13173
|
58 return a->edge.line.p1.x == b->edge.line.p1.x;
|
slaxemulator@13173
|
59 + } else if (a->edge.line.p2.y == b->edge.line.p2.y) {
|
slaxemulator@13173
|
60 + return a->edge.line.p2.x == b->edge.line.p2.x;
|
slaxemulator@13173
|
61 } else if (a->edge.line.p1.y < b->edge.line.p1.y) {
|
slaxemulator@13173
|
62 return edge_compare_for_y_against_x (b,
|
slaxemulator@13173
|
63 a->edge.line.p1.y,
|
slaxemulator@13173
|
64 @@ -1205,82 +1207,48 @@ _active_edges_to_polygon (cairo_bo_edge_t *left,
|
slaxemulator@13173
|
65 cairo_polygon_t *polygon)
|
slaxemulator@13173
|
66 {
|
slaxemulator@13173
|
67 cairo_bo_edge_t *right;
|
slaxemulator@13173
|
68 + unsigned int mask;
|
slaxemulator@13173
|
69
|
slaxemulator@13173
|
70 - if (fill_rule == CAIRO_FILL_RULE_WINDING) {
|
slaxemulator@13173
|
71 - while (left != NULL) {
|
slaxemulator@13173
|
72 - int in_out = left->edge.dir;
|
slaxemulator@13173
|
73 -
|
slaxemulator@13173
|
74 - right = left->next;
|
slaxemulator@13173
|
75 - if (left->deferred.right == NULL) {
|
slaxemulator@13173
|
76 - while (right != NULL && right->deferred.right == NULL)
|
slaxemulator@13173
|
77 - right = right->next;
|
slaxemulator@13173
|
78 -
|
slaxemulator@13173
|
79 - if (right != NULL && edges_colinear (left, right)) {
|
slaxemulator@13173
|
80 - /* continuation on left */
|
slaxemulator@13173
|
81 - left->deferred = right->deferred;
|
slaxemulator@13173
|
82 - right->deferred.right = NULL;
|
slaxemulator@13173
|
83 - }
|
slaxemulator@13173
|
84 - }
|
slaxemulator@13173
|
85 -
|
slaxemulator@13173
|
86 - right = left->next;
|
slaxemulator@13173
|
87 - while (right != NULL) {
|
slaxemulator@13173
|
88 - if (right->deferred.right != NULL)
|
slaxemulator@13173
|
89 - _cairo_bo_edge_end (right, top, polygon);
|
slaxemulator@13173
|
90 -
|
slaxemulator@13173
|
91 - in_out += right->edge.dir;
|
slaxemulator@13173
|
92 - if (in_out == 0) {
|
slaxemulator@13173
|
93 - cairo_bo_edge_t *next;
|
slaxemulator@13173
|
94 - cairo_bool_t skip = FALSE;
|
slaxemulator@13173
|
95 -
|
slaxemulator@13173
|
96 - /* skip co-linear edges */
|
slaxemulator@13173
|
97 - next = right->next;
|
slaxemulator@13173
|
98 - if (next != NULL)
|
slaxemulator@13173
|
99 - skip = edges_colinear (right, next);
|
slaxemulator@13173
|
100 + if (fill_rule == CAIRO_FILL_RULE_WINDING)
|
slaxemulator@13173
|
101 + mask = ~0;
|
slaxemulator@13173
|
102 + else
|
slaxemulator@13173
|
103 + mask = 1;
|
slaxemulator@13173
|
104
|
slaxemulator@13173
|
105 - if (! skip)
|
slaxemulator@13173
|
106 - break;
|
slaxemulator@13173
|
107 - }
|
slaxemulator@13173
|
108 + while (left != NULL) {
|
slaxemulator@13173
|
109 + int in_out = left->edge.dir;
|
slaxemulator@13173
|
110
|
slaxemulator@13173
|
111 + right = left->next;
|
slaxemulator@13173
|
112 + if (left->deferred.right == NULL) {
|
slaxemulator@13173
|
113 + while (right != NULL && right->deferred.right == NULL)
|
slaxemulator@13173
|
114 right = right->next;
|
slaxemulator@13173
|
115 - }
|
slaxemulator@13173
|
116 -
|
slaxemulator@13173
|
117 - _cairo_bo_edge_start_or_continue (left, right, top, polygon);
|
slaxemulator@13173
|
118
|
slaxemulator@13173
|
119 - left = right;
|
slaxemulator@13173
|
120 - if (left != NULL)
|
slaxemulator@13173
|
121 - left = left->next;
|
slaxemulator@13173
|
122 + if (right != NULL && edges_colinear (left, right)) {
|
slaxemulator@13173
|
123 + /* continuation on left */
|
slaxemulator@13173
|
124 + left->deferred = right->deferred;
|
slaxemulator@13173
|
125 + right->deferred.right = NULL;
|
slaxemulator@13173
|
126 + }
|
slaxemulator@13173
|
127 }
|
slaxemulator@13173
|
128 - } else {
|
slaxemulator@13173
|
129 - while (left != NULL) {
|
slaxemulator@13173
|
130 - int in_out = 0;
|
slaxemulator@13173
|
131
|
slaxemulator@13173
|
132 - right = left->next;
|
slaxemulator@13173
|
133 - while (right != NULL) {
|
slaxemulator@13173
|
134 - if (right->deferred.right != NULL)
|
slaxemulator@13173
|
135 - _cairo_bo_edge_end (right, top, polygon);
|
slaxemulator@13173
|
136 + right = left->next;
|
slaxemulator@13173
|
137 + while (right != NULL) {
|
slaxemulator@13173
|
138 + if (right->deferred.right != NULL)
|
slaxemulator@13173
|
139 + _cairo_bo_edge_end (right, top, polygon);
|
slaxemulator@13173
|
140
|
slaxemulator@13173
|
141 - if ((in_out++ & 1) == 0) {
|
slaxemulator@13173
|
142 - cairo_bo_edge_t *next;
|
slaxemulator@13173
|
143 - cairo_bool_t skip = FALSE;
|
slaxemulator@13173
|
144 -
|
slaxemulator@13173
|
145 - /* skip co-linear edges */
|
slaxemulator@13173
|
146 - next = right->next;
|
slaxemulator@13173
|
147 - if (next != NULL)
|
slaxemulator@13173
|
148 - skip = edges_colinear (right, next);
|
slaxemulator@13173
|
149 -
|
slaxemulator@13173
|
150 - if (! skip)
|
slaxemulator@13173
|
151 - break;
|
slaxemulator@13173
|
152 - }
|
slaxemulator@13173
|
153 -
|
slaxemulator@13173
|
154 - right = right->next;
|
slaxemulator@13173
|
155 + in_out += right->edge.dir;
|
slaxemulator@13173
|
156 + if ((in_out & mask) == 0) {
|
slaxemulator@13173
|
157 + /* skip co-linear edges */
|
slaxemulator@13173
|
158 + if (right->next == NULL || !edges_colinear (right, right->next))
|
slaxemulator@13173
|
159 + break;
|
slaxemulator@13173
|
160 }
|
slaxemulator@13173
|
161
|
slaxemulator@13173
|
162 - _cairo_bo_edge_start_or_continue (left, right, top, polygon);
|
slaxemulator@13173
|
163 -
|
slaxemulator@13173
|
164 - left = right;
|
slaxemulator@13173
|
165 - if (left != NULL)
|
slaxemulator@13173
|
166 - left = left->next;
|
slaxemulator@13173
|
167 + right = right->next;
|
slaxemulator@13173
|
168 }
|
slaxemulator@13173
|
169 +
|
slaxemulator@13173
|
170 + _cairo_bo_edge_start_or_continue (left, right, top, polygon);
|
slaxemulator@13173
|
171 +
|
slaxemulator@13173
|
172 + left = right;
|
slaxemulator@13173
|
173 + if (left != NULL)
|
slaxemulator@13173
|
174 + left = left->next;
|
slaxemulator@13173
|
175 }
|
slaxemulator@13173
|
176 }
|
slaxemulator@13173
|
177
|
slaxemulator@13173
|
178 @@ -1303,12 +1271,6 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
|
slaxemulator@13173
|
179
|
slaxemulator@13173
|
180 while ((event = _cairo_bo_event_dequeue (&event_queue))) {
|
slaxemulator@13173
|
181 if (event->point.y != sweep_line.current_y) {
|
slaxemulator@13173
|
182 - for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
|
slaxemulator@13173
|
183 - if (e1->deferred.right != NULL)
|
slaxemulator@13173
|
184 - _cairo_bo_edge_end (e1, e1->edge.bottom, polygon);
|
slaxemulator@13173
|
185 - }
|
slaxemulator@13173
|
186 - sweep_line.stopped = NULL;
|
slaxemulator@13173
|
187 -
|
slaxemulator@13173
|
188 _active_edges_to_polygon (sweep_line.head,
|
slaxemulator@13173
|
189 sweep_line.current_y,
|
slaxemulator@13173
|
190 fill_rule, polygon);
|
slaxemulator@13173
|
191 @@ -1328,23 +1290,6 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
|
slaxemulator@13173
|
192 if (unlikely (status))
|
slaxemulator@13173
|
193 goto unwind;
|
slaxemulator@13173
|
194
|
slaxemulator@13173
|
195 - /* check to see if this is a continuation of a stopped edge */
|
slaxemulator@13173
|
196 - /* XXX change to an infinitesimal lengthening rule */
|
slaxemulator@13173
|
197 - for (left = sweep_line.stopped; left; left = left->next) {
|
slaxemulator@13173
|
198 - if (e1->edge.top <= left->edge.bottom &&
|
slaxemulator@13173
|
199 - edges_colinear (e1, left))
|
slaxemulator@13173
|
200 - {
|
slaxemulator@13173
|
201 - e1->deferred = left->deferred;
|
slaxemulator@13173
|
202 - if (left->prev != NULL)
|
slaxemulator@13173
|
203 - left->prev = left->next;
|
slaxemulator@13173
|
204 - else
|
slaxemulator@13173
|
205 - sweep_line.stopped = left->next;
|
slaxemulator@13173
|
206 - if (left->next != NULL)
|
slaxemulator@13173
|
207 - left->next->prev = left->prev;
|
slaxemulator@13173
|
208 - break;
|
slaxemulator@13173
|
209 - }
|
slaxemulator@13173
|
210 - }
|
slaxemulator@13173
|
211 -
|
slaxemulator@13173
|
212 left = e1->prev;
|
slaxemulator@13173
|
213 right = e1->next;
|
slaxemulator@13173
|
214
|
slaxemulator@13173
|
215 @@ -1371,14 +1316,8 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
|
slaxemulator@13173
|
216
|
slaxemulator@13173
|
217 _cairo_bo_sweep_line_delete (&sweep_line, e1);
|
slaxemulator@13173
|
218
|
slaxemulator@13173
|
219 - /* first, check to see if we have a continuation via a fresh edge */
|
slaxemulator@13173
|
220 - if (e1->deferred.right != NULL) {
|
slaxemulator@13173
|
221 - e1->next = sweep_line.stopped;
|
slaxemulator@13173
|
222 - if (sweep_line.stopped != NULL)
|
slaxemulator@13173
|
223 - sweep_line.stopped->prev = e1;
|
slaxemulator@13173
|
224 - sweep_line.stopped = e1;
|
slaxemulator@13173
|
225 - e1->prev = NULL;
|
slaxemulator@13173
|
226 - }
|
slaxemulator@13173
|
227 + if (e1->deferred.right != NULL)
|
slaxemulator@13173
|
228 + _cairo_bo_edge_end (e1, e1->edge.bottom, polygon);
|
slaxemulator@13173
|
229
|
slaxemulator@13173
|
230 if (left != NULL && right != NULL) {
|
slaxemulator@13173
|
231 status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
|
slaxemulator@13173
|
232 @@ -1420,10 +1359,6 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
|
slaxemulator@13173
|
233 }
|
slaxemulator@13173
|
234 }
|
slaxemulator@13173
|
235
|
slaxemulator@13173
|
236 - for (e1 = sweep_line.stopped; e1; e1 = e1->next) {
|
slaxemulator@13173
|
237 - if (e1->deferred.right != NULL)
|
slaxemulator@13173
|
238 - _cairo_bo_edge_end (e1, e1->edge.bottom, polygon);
|
slaxemulator@13173
|
239 - }
|
slaxemulator@13173
|
240 unwind:
|
slaxemulator@13173
|
241 _cairo_bo_event_queue_fini (&event_queue);
|
slaxemulator@13173
|
242
|
slaxemulator@13173
|
243 @@ -1447,6 +1382,12 @@ _cairo_polygon_reduce (cairo_polygon_t *polygon,
|
slaxemulator@13173
|
244 if (unlikely (0 == num_events))
|
slaxemulator@13173
|
245 return CAIRO_STATUS_SUCCESS;
|
slaxemulator@13173
|
246
|
slaxemulator@13173
|
247 + if (DEBUG_POLYGON) {
|
slaxemulator@13173
|
248 + FILE *file = fopen ("reduce_in.txt", "w");
|
slaxemulator@13173
|
249 + _cairo_debug_print_polygon (file, polygon);
|
slaxemulator@13173
|
250 + fclose (file);
|
slaxemulator@13173
|
251 + }
|
slaxemulator@13173
|
252 +
|
slaxemulator@13173
|
253 events = stack_events;
|
slaxemulator@13173
|
254 event_ptrs = stack_event_ptrs;
|
slaxemulator@13173
|
255 if (num_events > ARRAY_LENGTH (stack_events)) {
|
slaxemulator@13173
|
256 @@ -1482,10 +1423,16 @@ _cairo_polygon_reduce (cairo_polygon_t *polygon,
|
slaxemulator@13173
|
257 num_events,
|
slaxemulator@13173
|
258 fill_rule,
|
slaxemulator@13173
|
259 polygon);
|
slaxemulator@13173
|
260 - polygon->num_limits = num_limits;
|
slaxemulator@13173
|
261 + polygon->num_limits = num_limits;
|
slaxemulator@13173
|
262
|
slaxemulator@13173
|
263 if (events != stack_events)
|
slaxemulator@13173
|
264 free (events);
|
slaxemulator@13173
|
265
|
slaxemulator@13173
|
266 + if (DEBUG_POLYGON) {
|
slaxemulator@13173
|
267 + FILE *file = fopen ("reduce_out.txt", "w");
|
slaxemulator@13173
|
268 + _cairo_debug_print_polygon (file, polygon);
|
slaxemulator@13173
|
269 + fclose (file);
|
slaxemulator@13173
|
270 + }
|
slaxemulator@13173
|
271 +
|
slaxemulator@13173
|
272 return status;
|
slaxemulator@13173
|
273 }
|
slaxemulator@13173
|
274 --
|
slaxemulator@13173
|
275 cgit v0.9.0.2-2-gbebe
|