Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: src/gpu/GrTessellatingPathRenderer.cpp

Issue 855513004: Tessellating GPU path renderer. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fixes for fuzzer Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrTessellatingPathRenderer.h ('k') | tests/ConcavePathTests.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrTessellatingPathRenderer.h"
9
10 #include "GrDefaultGeoProcFactory.h"
11 #include "GrPathUtils.h"
12 #include "SkChunkAlloc.h"
13 #include "SkGeometry.h"
14
15 #include <stdio.h>
16
17 /*
18 * This path renderer tessellates the path into triangles, uploads the triangles to a
19 * vertex buffer, and renders them with a single draw call. It does not currentl y do
20 * antialiasing, so it must be used in conjunction with multisampling.
21 *
22 * There are six stages to the algorithm:
23 *
24 * 1) Linearize the path contours into piecewise linear segments (path_to_contou rs()).
25 * 2) Sort the vertices in Y (and secondarily in X) (merge_sort()).
egdaniel 2015/01/29 19:31:19 step 2 and 3 here are actually reversed in the cod
Stephen White 2015/01/29 19:38:29 Good catch; will fix.
26 * 3) Build a mesh of edges connecting the vertices (build_edges()).
27 * 4) Simplify the mesh by inserting new vertices at intersecting edges (simplif y()).
28 * 5) Tessellate the simplified mesh into monotone polygons (tessellate()).
29 * 6) Triangulate the monotone polygons directly into a vertex buffer (polys_to_ triangles()).
30 *
31 * The vertex sorting in step (2) is a merge sort, since it plays well with the linked list
32 * of vertices (and the necessity of inserting new vertices on intersection).
33 *
34 * Stages (4) and (5) use an active edge list, which a list of all edges for whi ch the
35 * sweep line has crossed the top vertex, but not the bottom vertex. It's sorte d
36 * left-to-right based on the point where both edges are active (when both top v ertices
37 * have been seen, so the "lower" top vertex of the two). If the top vertices ar e equal
38 * (shared), it's sorted based on the last point where both edges are active, so the
39 * "upper" bottom vertex.
40 *
41 * The most complex step is the simplification (4). It's based on the Bentley-Ot tman
42 * line-sweep algorithm, but due to floating point inaccuracy, the intersection points are
43 * not exact and may violate the mesh topology or active edge list ordering. We
44 * accommodate this by adjusting the topology of the mesh and AEL to match the i ntersection
45 * points. This occurs in three ways:
46 *
47 * A) Intersections may cause a shortened edge to no longer be ordered with resp ect to its
48 * neighbouring edges at the top or bottom vertex. This is handled by merging the
49 * edges (merge_collinear_edges()).
50 * B) Intersections may cause an edge to violate the left-to-right ordering of t he
51 * active edge list. This is handled by splitting the neighbour edge on the
52 * intersected vertex (cleanup_active_edges()).
53 * C) Shortening an edge may cause an active edge to become inactive or an inact ive edge
54 * to become active. This is handled by removing or inserting the edge in the active
55 * edge list (fix_active_state()).
56 *
57 * The tessellation steps (5) and (6) are based on "Triangulating Simple Polygon s and
58 * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Not e that it
59 * currently uses a linked list for the active edge list, rather than a 2-3 tree as the
60 * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and remova l also
61 * become O(lg N). In all the test cases, it was found that the cost of frequent O(lg N)
62 * insertions and removals was greater than the cost of infrequent O(N) lookups with the
63 * linked list implementation. With the latter, all removals are O(1), and most insertions
64 * are O(1), since we know the adjacent edge in the active edge list based on th e topology.
65 * Only type 2 vertices (see paper) require the O(N) lookups, and these are much less
66 * frequent. There may be other data structures worth investigating, however.
67 *
68 * Note that there is a compile-time flag (SWEEP_IN_X) which changes the orienta tion of the
69 * line sweep algorithms. When SWEEP_IN_X is unset, we sort vertices based on in creasing
70 * Y coordinate, and secondarily by increasing X coordinate. When SWEEP_IN_X is set, we sort by
71 * increasing X coordinate, but secondarily by *decreasing* Y coordinate. This i s so that the
72 * "left" and "right" orientation in the code remains correct (edges to the left are increasing
73 * in Y; edges to the right are decreasing in Y). That is, the setting rotates 9 0 degrees
74 * counterclockwise, rather that transposing.
75 *
76 * The choice is arbitrary, but most test cases are wider than they are tall, so the
77 * default is to sweep in X. In the future, we may want to make this a runtime p arameter
78 * and base it on the aspect ratio of the clip bounds.
79 */
80 #define LOGGING_ENABLED 0
81 #define WIREFRAME 0
82 #define SWEEP_IN_X 1
83
84 #if LOGGING_ENABLED
85 #define LOG printf
86 #else
87 #define LOG(...)
88 #endif
89
90 #define ALLOC_NEW(Type, args, alloc) \
91 SkNEW_PLACEMENT_ARGS(alloc.allocThrow(sizeof(Type)), Type, args)
92
93 namespace {
94
95 struct Vertex;
96 struct Edge;
97 struct Poly;
98
99 template <class T, T* T::*Prev, T* T::*Next>
100 void insert(T* t, T* prev, T* next, T** head, T** tail)
101 {
102 t->*Prev = prev;
103 t->*Next = next;
104 if (prev) {
105 prev->*Next = t;
106 } else if (head) {
107 *head = t;
108 }
109 if (next) {
110 next->*Prev = t;
111 } else if (tail) {
112 *tail = t;
113 }
114 }
115
116 template <class T, T* T::*Prev, T* T::*Next>
117 void remove(T* t, T** head, T** tail)
118 {
119 if (t->*Prev) {
120 t->*Prev->*Next = t->*Next;
121 } else if (head) {
122 *head = t->*Next;
123 }
124 if (t->*Next) {
125 t->*Next->*Prev = t->*Prev;
126 } else if (tail) {
127 *tail = t->*Prev;
128 }
129 t->*Prev = t->*Next = NULL;
130 }
131
132 struct Vertex {
133 Vertex(const SkPoint& point)
134 : fPoint(point), fPrev(NULL), fNext(NULL)
135 , fFirstEdgeAbove(NULL), fLastEdgeAbove(NULL)
136 , fFirstEdgeBelow(NULL), fLastEdgeBelow(NULL)
137 , fInterior(false)
138 , fProcessed(false)
139 #if LOGGING_ENABLED
140 , fID (-1.0f)
141 #endif
142 {}
143 SkPoint fPoint;
144 Vertex* fPrev;
145 Vertex* fNext;
146 Edge* fFirstEdgeAbove;
147 Edge* fLastEdgeAbove;
148 Edge* fFirstEdgeBelow;
149 Edge* fLastEdgeBelow;
150 bool fInterior;
151 bool fProcessed;
152 #if LOGGING_ENABLED
153 float fID;
154 #endif
155 };
156
157 bool operator<(const SkPoint& a, const SkPoint& b) {
158 #if SWEEP_IN_X
159 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX;
160 #else
161 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY;
162 #endif
163 }
164
165 bool operator>(const SkPoint& a, const SkPoint& b) {
166 #if SWEEP_IN_X
167 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX;
168 #else
169 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY;
170 #endif
171 }
172
173 inline void* emit_vertex(Vertex* v, void* data) {
174 SkPoint* d = static_cast<SkPoint*>(data);
175 *d++ = v->fPoint;
176 return d;
177 }
178
179 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, void* data) {
180 #if WIREFRAME
181 data = emit_vertex(v0, data);
182 data = emit_vertex(v1, data);
183 data = emit_vertex(v1, data);
184 data = emit_vertex(v2, data);
185 data = emit_vertex(v2, data);
186 data = emit_vertex(v0, data);
187 #else
188 data = emit_vertex(v0, data);
189 data = emit_vertex(v1, data);
190 data = emit_vertex(v2, data);
191 #endif
192 return data;
193 }
194
195 struct Edge {
196 Edge(Vertex* top, Vertex* bottom, int winding)
197 : fWinding(winding)
198 , fTop(top)
199 , fBottom(bottom)
200 , fLeft(NULL)
201 , fRight(NULL)
202 , fPrevEdgeAbove(NULL)
203 , fNextEdgeAbove(NULL)
204 , fPrevEdgeBelow(NULL)
205 , fNextEdgeBelow(NULL)
206 , fLeftPoly(NULL)
207 , fRightPoly(NULL) {
208 recompute();
209 }
210 int fWinding;
211 Vertex* fTop;
212 Vertex* fBottom;
213 Edge* fLeft;
214 Edge* fRight;
215 Edge* fPrevEdgeAbove;
216 Edge* fNextEdgeAbove;
217 Edge* fPrevEdgeBelow;
218 Edge* fNextEdgeBelow;
219 Poly* fLeftPoly;
220 Poly* fRightPoly;
221 double fDX;
222 double fDY;
223 double fC;
224 double dist(const SkPoint& p) const {
225 return fDY * p.fX - fDX * p.fY + fC;
226 }
227 bool isRightOf(Vertex* v) const {
228 return dist(v->fPoint) < 0.0;
229 }
230 bool isLeftOf(Vertex* v) const {
231 return dist(v->fPoint) > 0.0;
232 }
233 void recompute() {
234 fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX;
235 fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY;
236 fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX -
237 static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY;
238 }
239 bool intersect(const Edge& other, SkPoint* p) {
240 LOG("intersecting %g -> %g with %g -> %g\n",
241 fTop->fID, fBottom->fID,
242 other.fTop->fID, other.fBottom->fID);
243 if (fTop == other.fTop || fBottom == other.fBottom) {
244 return false;
245 }
246 double denom = fDX * other.fDY - fDY * other.fDX;
247 if (denom == 0.0) {
248 return false;
249 }
250 double dx = static_cast<double>(fTop->fPoint.fX) - other.fTop->fPoint.fX ;
251 double dy = static_cast<double>(fTop->fPoint.fY) - other.fTop->fPoint.fY ;
252 double sNumer = dy * other.fDX - dx * other.fDY;
253 double tNumer = dy * fDX - dx * fDY;
254 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNu mer > denom)
255 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNu mer < denom)) {
256 return false;
257 }
258 double s = sNumer / denom;
259 p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX);
260 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY);
261 return true;
262 }
263 bool isActive(Edge** activeEdges) const {
264 return activeEdges && (fLeft || fRight || *activeEdges == this);
265 }
266 };
267
268 struct Poly {
269 Poly(int winding)
270 : fWinding(winding)
271 , fHead(NULL)
272 , fTail(NULL)
273 , fActive(NULL)
274 , fNext(NULL)
275 , fPartner(NULL)
276 , fCount(0)
277 {
278 #if LOGGING_ENABLED
279 static int gID = 0;
280 fID = gID++;
281 LOG("*** created Poly %d\n", fID);
282 #endif
283 }
284 typedef enum { kNeither_Side, kLeft_Side, kRight_Side } Side;
285 struct MonotonePoly {
286 MonotonePoly()
287 : fSide(kNeither_Side)
288 , fHead(NULL)
289 , fTail(NULL)
290 , fPrev(NULL)
291 , fNext(NULL) {}
292 Side fSide;
293 Vertex* fHead;
294 Vertex* fTail;
295 MonotonePoly* fPrev;
296 MonotonePoly* fNext;
297 bool addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
298 Vertex* newV = ALLOC_NEW(Vertex, (v->fPoint), alloc);
299 newV->fInterior = v->fInterior;
300 bool done = false;
301 if (fSide == kNeither_Side) {
302 fSide = side;
303 } else {
304 done = side != fSide;
305 }
306 if (fHead == NULL) {
307 fHead = fTail = newV;
308 } else if (fSide == kRight_Side) {
309 newV->fPrev = fTail;
310 fTail->fNext = newV;
311 fTail = newV;
312 } else {
313 newV->fNext = fHead;
314 fHead->fPrev = newV;
315 fHead = newV;
316 }
317 return done;
318 }
319
320 void* emit(void* data) {
321 Vertex* first = fHead;
322 Vertex* v = first->fNext;
323 while (v != fTail) {
324 SkASSERT(v && v->fPrev && v->fNext);
325 #ifdef SK_DEBUG
326 validate();
327 #endif
328 Vertex* prev = v->fPrev;
329 Vertex* curr = v;
330 Vertex* next = v->fNext;
331 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint. fX;
332 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint. fY;
333 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint. fX;
334 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint. fY;
335 if (ax * by - ay * bx >= 0.0) {
336 data = emit_triangle(prev, curr, next, data);
337 v->fPrev->fNext = v->fNext;
338 v->fNext->fPrev = v->fPrev;
339 if (v->fPrev == first) {
340 v = v->fNext;
341 } else {
342 v = v->fPrev;
343 }
344 } else {
345 v = v->fNext;
346 SkASSERT(v != fTail);
347 }
348 }
349 return data;
350 }
351
352 #ifdef SK_DEBUG
353 void validate() {
354 int winding = fHead->fPoint < fTail->fPoint ? 1 : -1;
355 Vertex* top = winding < 0 ? fTail : fHead;
356 Vertex* bottom = winding < 0 ? fHead : fTail;
357 Edge e(top, bottom, winding);
358 for (Vertex* v = fHead->fNext; v != fTail; v = v->fNext) {
359 if (fSide == kRight_Side) {
360 SkASSERT(!e.isRightOf(v));
361 } else if (fSide == Poly::kLeft_Side) {
362 SkASSERT(!e.isLeftOf(v));
363 }
364 }
365 }
366 #endif
367 };
368 Poly* addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
369 LOG("addVertex() to %d at %g (%g, %g), %s side\n", fID, v->fID, v->fPoin t.fX, v->fPoint.fY,
370 side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "ne ither");
371 Poly* partner = fPartner;
372 Poly* poly = this;
373 if (partner) {
374 fPartner = partner->fPartner = NULL;
375 }
376 if (!fActive) {
377 fActive = ALLOC_NEW(MonotonePoly, (), alloc);
378 }
379 if (fActive->addVertex(v, side, alloc)) {
380 #ifdef SK_DEBUG
381 fActive->validate();
382 #endif
383 if (fTail) {
384 fActive->fPrev = fTail;
385 fTail->fNext = fActive;
386 fTail = fActive;
387 } else {
388 fHead = fTail = fActive;
389 }
390 if (partner) {
391 partner->addVertex(v, side, alloc);
392 poly = partner;
393 } else {
394 Vertex* prev = fActive->fSide == Poly::kLeft_Side ?
395 fActive->fHead->fNext : fActive->fTail->fPrev;
396 fActive = ALLOC_NEW(MonotonePoly, , alloc);
397 fActive->addVertex(prev, Poly::kNeither_Side, alloc);
398 fActive->addVertex(v, side, alloc);
399 }
400 }
401 fCount++;
402 return poly;
403 }
404 void end(Vertex* v, SkChunkAlloc& alloc) {
405 LOG("end() %d at %g, %g\n", fID, v->fPoint.fX, v->fPoint.fY);
406 if (fPartner) {
407 fPartner = fPartner->fPartner = NULL;
408 }
409 addVertex(v, fActive->fSide == kLeft_Side ? kRight_Side : kLeft_Side, al loc);
410 }
411 void* emit(void *data) {
412 if (fCount < 3) {
413 return data;
414 }
415 LOG("emit() %d, size %d\n", fID, fCount);
416 for (MonotonePoly* m = fHead; m != NULL; m = m->fNext) {
417 data = m->emit(data);
418 }
419 return data;
420 }
421 int fWinding;
422 MonotonePoly* fHead;
423 MonotonePoly* fTail;
424 MonotonePoly* fActive;
425 Poly* fNext;
426 Poly* fPartner;
427 int fCount;
428 #if LOGGING_ENABLED
429 int fID;
430 #endif
431 };
432
433 bool coincident(const SkPoint& a, const SkPoint& b) {
434 return a == b;
435 }
436
437 Poly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) {
438 Poly* poly = ALLOC_NEW(Poly, (winding), alloc);
439 poly->addVertex(v, Poly::kNeither_Side, alloc);
440 poly->fNext = *head;
441 *head = poly;
442 return poly;
443 }
444
445 #ifdef SK_DEBUG
446 void validate_edges(Edge* head) {
447 for (Edge* e = head; e != NULL; e = e->fRight) {
448 SkASSERT(e->fTop != e->fBottom);
449 if (e->fLeft) {
450 SkASSERT(e->fLeft->fRight == e);
451 if (e->fTop->fPoint > e->fLeft->fTop->fPoint) {
452 SkASSERT(e->fLeft->isLeftOf(e->fTop));
453 }
454 if (e->fBottom->fPoint < e->fLeft->fBottom->fPoint) {
455 SkASSERT(e->fLeft->isLeftOf(e->fBottom));
456 }
457 } else {
458 SkASSERT(e == head);
459 }
460 if (e->fRight) {
461 SkASSERT(e->fRight->fLeft == e);
462 if (e->fTop->fPoint > e->fRight->fTop->fPoint) {
463 SkASSERT(e->fRight->isRightOf(e->fTop));
464 }
465 if (e->fBottom->fPoint < e->fRight->fBottom->fPoint) {
466 SkASSERT(e->fRight->isRightOf(e->fBottom));
467 }
468 }
469 }
470 }
471
472 void validate_connectivity(Vertex* v) {
473 for (Edge* e = v->fFirstEdgeAbove; e != NULL; e = e->fNextEdgeAbove) {
474 SkASSERT(e->fBottom == v);
475 if (e->fPrevEdgeAbove) {
476 SkASSERT(e->fPrevEdgeAbove->fNextEdgeAbove == e);
477 SkASSERT(e->fPrevEdgeAbove->isLeftOf(e->fTop));
478 } else {
479 SkASSERT(e == v->fFirstEdgeAbove);
480 }
481 if (e->fNextEdgeAbove) {
482 SkASSERT(e->fNextEdgeAbove->fPrevEdgeAbove == e);
483 SkASSERT(e->fNextEdgeAbove->isRightOf(e->fTop));
484 } else {
485 SkASSERT(e == v->fLastEdgeAbove);
486 }
487 }
488 for (Edge* e = v->fFirstEdgeBelow; e != NULL; e = e->fNextEdgeBelow) {
489 SkASSERT(e->fTop == v);
490 if (e->fPrevEdgeBelow) {
491 SkASSERT(e->fPrevEdgeBelow->fNextEdgeBelow == e);
492 SkASSERT(e->fPrevEdgeBelow->isLeftOf(e->fBottom));
493 } else {
494 SkASSERT(e == v->fFirstEdgeBelow);
495 }
496 if (e->fNextEdgeBelow) {
497 SkASSERT(e->fNextEdgeBelow->fPrevEdgeBelow == e);
498 SkASSERT(e->fNextEdgeBelow->isRightOf(e->fBottom));
499 } else {
500 SkASSERT(e == v->fLastEdgeBelow);
501 }
502 }
503 }
504 #endif
505
506 Vertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head,
507 SkChunkAlloc& alloc) {
508 Vertex* v = ALLOC_NEW(Vertex, (p), alloc);
509 #if LOGGING_ENABLED
510 static float gID = 0.0f;
511 v->fID = gID++;
512 #endif
513 if (prev) {
514 prev->fNext = v;
515 v->fPrev = prev;
516 } else {
517 *head = v;
518 }
519 return v;
520 }
521
522 Vertex* generate_quadratic_points(const SkPoint& p0,
523 const SkPoint& p1,
524 const SkPoint& p2,
525 SkScalar tolSqd,
526 Vertex* prev,
527 Vertex** head,
528 int pointsLeft,
529 SkChunkAlloc& alloc) {
530 SkScalar d = p1.distanceToLineSegmentBetweenSqd(p0, p2);
531 if (pointsLeft < 2 || d < tolSqd || !SkScalarIsFinite(d)) {
532 return append_point_to_contour(p2, prev, head, alloc);
533 }
534
535 SkPoint q[] = {
536 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
537 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
538 };
539 SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) } ;
540
541 pointsLeft >>= 1;
542 prev = generate_quadratic_points(p0, q[0], r, tolSqd, prev, head, pointsLeft , alloc);
543 prev = generate_quadratic_points(r, q[1], p2, tolSqd, prev, head, pointsLeft , alloc);
544 return prev;
545 }
546
547 Vertex* generate_cubic_points(const SkPoint& p0,
548 const SkPoint& p1,
549 const SkPoint& p2,
550 const SkPoint& p3,
551 SkScalar tolSqd,
552 Vertex* prev,
553 Vertex** head,
554 int pointsLeft,
555 SkChunkAlloc& alloc) {
556 SkScalar d1 = p1.distanceToLineSegmentBetweenSqd(p0, p3);
557 SkScalar d2 = p2.distanceToLineSegmentBetweenSqd(p0, p3);
558 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) || !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
559 return append_point_to_contour(p3, prev, head, alloc);
560 }
561 SkPoint q[] = {
562 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
563 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
564 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
565 };
566 SkPoint r[] = {
567 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
568 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
569 };
570 SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) } ;
571 pointsLeft >>= 1;
572 prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLe ft, alloc);
573 prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLe ft, alloc);
574 return prev;
575 }
576
577 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip Bounds,
578 Vertex** contours, SkChunkAlloc& alloc) {
579
580 SkScalar toleranceSqd = tolerance * tolerance;
581
582 SkPoint pts[4];
583 bool done = false;
584 SkPath::Iter iter(path, false);
585 Vertex* prev = NULL;
586 Vertex* head = NULL;
587 if (path.isInverseFillType()) {
588 SkPoint quad[4];
589 clipBounds.toQuad(quad);
590 for (int i = 3; i >= 0; i--) {
591 prev = append_point_to_contour(quad[i], prev, &head, alloc);
592 }
593 head->fPrev = prev;
594 prev->fNext = head;
595 *contours++ = head;
596 head = prev = NULL;
597 }
598 while (!done) {
599 SkPath::Verb verb = iter.next(pts);
600 switch (verb) {
601 case SkPath::kConic_Verb: {
602 SkScalar weight = iter.conicWeight();
603 SkAutoConicToQuads converter;
604 const SkPoint* quadPts = converter.computeQuads(pts, weight, tol eranceSqd);
605 for (int i = 0; i < converter.countQuads(); ++i) {
606 int pointsLeft = GrPathUtils::quadraticPointCount(quadPts, t oleranceSqd);
607 prev = generate_quadratic_points(quadPts[0], quadPts[1], qua dPts[2],
608 toleranceSqd, prev, &head, pointsLeft, alloc);
609 quadPts += 2;
610 }
611 break;
612 }
613 case SkPath::kMove_Verb:
614 if (head) {
615 head->fPrev = prev;
616 prev->fNext = head;
617 *contours++ = head;
618 }
619 head = prev = NULL;
620 prev = append_point_to_contour(pts[0], prev, &head, alloc);
621 break;
622 case SkPath::kLine_Verb: {
623 prev = append_point_to_contour(pts[1], prev, &head, alloc);
624 break;
625 }
626 case SkPath::kQuad_Verb: {
627 int pointsLeft = GrPathUtils::quadraticPointCount(pts, tolerance Sqd);
628 prev = generate_quadratic_points(pts[0], pts[1], pts[2], toleran ceSqd, prev,
629 &head, pointsLeft, alloc);
630 break;
631 }
632 case SkPath::kCubic_Verb: {
633 int pointsLeft = GrPathUtils::cubicPointCount(pts, toleranceSqd) ;
634 prev = generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
635 toleranceSqd, prev, &head, pointsLeft, alloc);
636 break;
637 }
638 case SkPath::kClose_Verb:
639 if (head) {
640 head->fPrev = prev;
641 prev->fNext = head;
642 *contours++ = head;
643 }
644 head = prev = NULL;
645 break;
646 case SkPath::kDone_Verb:
647 if (head) {
648 head->fPrev = prev;
649 prev->fNext = head;
650 *contours++ = head;
651 }
652 done = true;
653 break;
654 }
655 }
656 }
657
658 inline bool apply_fill_type(SkPath::FillType fillType, int winding) {
659 switch (fillType) {
660 case SkPath::kWinding_FillType:
661 return winding != 0;
662 case SkPath::kEvenOdd_FillType:
663 return (winding & 1) != 0;
664 case SkPath::kInverseWinding_FillType:
665 return winding == 1;
666 case SkPath::kInverseEvenOdd_FillType:
667 return (winding & 1) == 1;
668 default:
669 SkASSERT(false);
670 return false;
671 }
672 }
673
674 Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc) {
675 int winding = prev->fPoint < next->fPoint ? 1 : -1;
676 Vertex* top = winding < 0 ? next : prev;
677 Vertex* bottom = winding < 0 ? prev : next;
678 return ALLOC_NEW(Edge, (top, bottom, winding), alloc);
679 }
680
681 void remove_edge(Edge* edge, Edge** head) {
682 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
683 SkASSERT(edge->isActive(head));
684 remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, head, NULL);
685 }
686
687 void insert_edge(Edge* edge, Edge* prev, Edge** head) {
688 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
689 SkASSERT(!edge->isActive(head));
690 Edge* next = prev ? prev->fRight : *head;
691 insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, head, NULL);
692 }
693
694 void find_enclosing_edges(Vertex* v, Edge* head, Edge** left, Edge** right) {
695 if (v->fFirstEdgeAbove) {
696 *left = v->fFirstEdgeAbove->fLeft;
697 *right = v->fLastEdgeAbove->fRight;
698 return;
699 }
700 Edge* prev = NULL;
701 Edge* next;
702 for (next = head; next != NULL; next = next->fRight) {
703 if (next->isRightOf(v)) {
704 break;
705 }
706 prev = next;
707 }
708 *left = prev;
709 *right = next;
710 return;
711 }
712
713 void find_enclosing_edges(Edge* edge, Edge* head, Edge** left, Edge** right) {
714 Edge* prev = NULL;
715 Edge* next;
716 for (next = head; next != NULL; next = next->fRight) {
717 if ((edge->fTop->fPoint > next->fTop->fPoint && next->isRightOf(edge->fT op)) ||
718 (next->fTop->fPoint > edge->fTop->fPoint && edge->isLeftOf(next->fTo p)) ||
719 (edge->fBottom->fPoint < next->fBottom->fPoint && next->isRightOf(ed ge->fBottom)) ||
720 (next->fBottom->fPoint < edge->fBottom->fPoint && edge->isLeftOf(nex t->fBottom))) {
721 break;
722 }
723 prev = next;
724 }
725 *left = prev;
726 *right = next;
727 return;
728 }
729
730 void fix_active_state(Edge* edge, Edge** activeEdges) {
731 if (edge->isActive(activeEdges)) {
732 if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) {
733 remove_edge(edge, activeEdges);
734 }
735 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) {
736 Edge* left;
737 Edge* right;
738 find_enclosing_edges(edge, *activeEdges, &left, &right);
739 insert_edge(edge, left, activeEdges);
740 }
741 }
742
743 void insert_edge_above(Edge* edge, Vertex* v) {
744 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
745 edge->fTop->fPoint > edge->fBottom->fPoint) {
746 SkASSERT(false);
747 return;
748 }
749 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBott om->fID, v->fID);
750 Edge* prev = NULL;
751 Edge* next;
752 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
753 if (next->isRightOf(edge->fTop)) {
754 break;
755 }
756 prev = next;
757 }
758 insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
759 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
760 }
761
762 void insert_edge_below(Edge* edge, Vertex* v) {
763 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
764 edge->fTop->fPoint > edge->fBottom->fPoint) {
765 SkASSERT(false);
766 return;
767 }
768 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBott om->fID, v->fID);
769 Edge* prev = NULL;
770 Edge* next;
771 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
772 if (next->isRightOf(edge->fBottom)) {
773 break;
774 }
775 prev = next;
776 }
777 insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
778 edge, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
779 }
780
781 void remove_edge_above(Edge* edge) {
782 LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBo ttom->fID,
783 edge->fBottom->fID);
784 remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
785 edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
786 }
787
788 void remove_edge_below(Edge* edge) {
789 LOG("removing edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBo ttom->fID,
790 edge->fTop->fID);
791 remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
792 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
793 }
794
795 void erase_edge_if_zero_winding(Edge* edge, Edge** head) {
796 if (edge->fWinding != 0) {
797 return;
798 }
799 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
800 remove_edge_above(edge);
801 remove_edge_below(edge);
802 if (edge->isActive(head)) {
803 remove_edge(edge, head);
804 }
805 }
806
807 void merge_collinear_edges(Edge* edge, Edge** activeEdges);
808
809 void set_top(Edge* edge, Vertex* v, Edge** activeEdges) {
810 remove_edge_below(edge);
811 edge->fTop = v;
812 edge->recompute();
813 insert_edge_below(edge, v);
814 fix_active_state(edge, activeEdges);
815 merge_collinear_edges(edge, activeEdges);
816 }
817
818 void set_bottom(Edge* edge, Vertex* v, Edge** activeEdges) {
819 remove_edge_above(edge);
820 edge->fBottom = v;
821 edge->recompute();
822 insert_edge_above(edge, v);
823 fix_active_state(edge, activeEdges);
824 merge_collinear_edges(edge, activeEdges);
825 }
826
827 void merge_edges_above(Edge* edge, Edge* other, Edge** activeEdges) {
828 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
829 LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
830 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
831 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
832 other->fWinding += edge->fWinding;
833 erase_edge_if_zero_winding(other, activeEdges);
834 edge->fWinding = 0;
835 erase_edge_if_zero_winding(edge, activeEdges);
836 } else if (edge->fTop->fPoint < other->fTop->fPoint) {
837 other->fWinding += edge->fWinding;
838 erase_edge_if_zero_winding(other, activeEdges);
839 set_bottom(edge, other->fTop, activeEdges);
840 } else {
841 edge->fWinding += other->fWinding;
842 erase_edge_if_zero_winding(edge, activeEdges);
843 set_bottom(other, edge->fTop, activeEdges);
844 }
845 }
846
847 void merge_edges_below(Edge* edge, Edge* other, Edge** activeEdges) {
848 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
849 LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
850 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
851 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
852 other->fWinding += edge->fWinding;
853 erase_edge_if_zero_winding(other, activeEdges);
854 edge->fWinding = 0;
855 erase_edge_if_zero_winding(edge, activeEdges);
856 } else if (edge->fBottom->fPoint < other->fBottom->fPoint) {
857 edge->fWinding += other->fWinding;
858 erase_edge_if_zero_winding(edge, activeEdges);
859 set_top(other, edge->fBottom, activeEdges);
860 } else {
861 other->fWinding += edge->fWinding;
862 erase_edge_if_zero_winding(other, activeEdges);
863 set_top(edge, other->fBottom, activeEdges);
864 }
865 }
866
867 void merge_collinear_edges(Edge* edge, Edge** activeEdges) {
868 if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
869 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
870 merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges);
871 } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
872 !edge->isLeftOf(edge->fNextEdgeAbove->fT op))) {
873 merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges);
874 }
875 if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
876 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom)) ) {
877 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges);
878 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->f Bottom ||
879 !edge->isLeftOf(edge->fNextEdgeBelow->fB ottom))) {
880 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges);
881 }
882 }
883
884 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc);
885
886 void cleanup_active_edges(Edge* edge, Edge** activeEdges, SkChunkAlloc& alloc) {
887 Vertex* top = edge->fTop;
888 Vertex* bottom = edge->fBottom;
889 if (edge->fLeft) {
890 Vertex* leftTop = edge->fLeft->fTop;
891 Vertex* leftBottom = edge->fLeft->fBottom;
892 if (top->fPoint > leftTop->fPoint && !edge->fLeft->isLeftOf(top)) {
893 split_edge(edge->fLeft, edge->fTop, activeEdges, alloc);
894 } else if (leftTop->fPoint > top->fPoint && !edge->isRightOf(leftTop)) {
895 split_edge(edge, leftTop, activeEdges, alloc);
896 } else if (bottom->fPoint < leftBottom->fPoint && !edge->fLeft->isLeftOf (bottom)) {
897 split_edge(edge->fLeft, bottom, activeEdges, alloc);
898 } else if (leftBottom->fPoint < bottom->fPoint && !edge->isRightOf(leftB ottom)) {
899 split_edge(edge, leftBottom, activeEdges, alloc);
900 }
901 }
902 if (edge->fRight) {
903 Vertex* rightTop = edge->fRight->fTop;
904 Vertex* rightBottom = edge->fRight->fBottom;
905 if (top->fPoint > rightTop->fPoint && !edge->fRight->isRightOf(top)) {
906 split_edge(edge->fRight, top, activeEdges, alloc);
907 } else if (rightTop->fPoint > top->fPoint && !edge->isLeftOf(rightTop)) {
908 split_edge(edge, rightTop, activeEdges, alloc);
909 } else if (bottom->fPoint < rightBottom->fPoint && !edge->fRight->isRigh tOf(bottom)) {
910 split_edge(edge->fRight, bottom, activeEdges, alloc);
911 } else if (rightBottom->fPoint < bottom->fPoint && !edge->isLeftOf(right Bottom)) {
912 split_edge(edge, rightBottom, activeEdges, alloc);
913 }
914 }
915 }
916
917 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc) {
918 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
919 edge->fTop->fID, edge->fBottom->fID,
920 v->fID, v->fPoint.fX, v->fPoint.fY);
921 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc);
922 insert_edge_below(newEdge, v);
923 insert_edge_above(newEdge, edge->fBottom);
924 set_bottom(edge, v, activeEdges);
925 cleanup_active_edges(edge, activeEdges, alloc);
926 fix_active_state(newEdge, activeEdges);
927 merge_collinear_edges(newEdge, activeEdges);
928 }
929
930 void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc ) {
931 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX , src->fPoint.fY,
932 src->fID, dst->fID);
933 for (Edge* edge = src->fFirstEdgeAbove; edge;) {
934 Edge* next = edge->fNextEdgeAbove;
935 set_bottom(edge, dst, NULL);
936 edge = next;
937 }
938 for (Edge* edge = src->fFirstEdgeBelow; edge;) {
939 Edge* next = edge->fNextEdgeBelow;
940 set_top(edge, dst, NULL);
941 edge = next;
942 }
943 remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, NULL);
944 }
945
946 Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, SkCh unkAlloc& alloc) {
947 SkPoint p;
948 if (!edge || !other) {
949 return NULL;
950 }
951 if (edge->intersect(*other, &p)) {
952 Vertex* v;
953 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
954 if (p == edge->fTop->fPoint || p < edge->fTop->fPoint) {
955 split_edge(other, edge->fTop, activeEdges, alloc);
956 v = edge->fTop;
957 } else if (p == edge->fBottom->fPoint || p > edge->fBottom->fPoint) {
958 split_edge(other, edge->fBottom, activeEdges, alloc);
959 v = edge->fBottom;
960 } else if (p == other->fTop->fPoint || p < other->fTop->fPoint) {
961 split_edge(edge, other->fTop, activeEdges, alloc);
962 v = other->fTop;
963 } else if (p == other->fBottom->fPoint || p > other->fBottom->fPoint) {
964 split_edge(edge, other->fBottom, activeEdges, alloc);
965 v = other->fBottom;
966 } else {
967 Vertex* nextV = edge->fTop;
968 while (p < nextV->fPoint) {
969 nextV = nextV->fPrev;
970 }
971 while (nextV->fPoint < p) {
972 nextV = nextV->fNext;
973 }
974 Vertex* prevV = nextV->fPrev;
975 if (coincident(prevV->fPoint, p)) {
976 v = prevV;
977 } else if (coincident(nextV->fPoint, p)) {
978 v = nextV;
979 } else {
980 v = ALLOC_NEW(Vertex, (p), alloc);
981 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n",
982 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY,
983 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY);
984 #if LOGGING_ENABLED
985 v->fID = (nextV->fID + prevV->fID) * 0.5f;
986 #endif
987 v->fPrev = prevV;
988 v->fNext = nextV;
989 prevV->fNext = v;
990 nextV->fPrev = v;
991 }
992 split_edge(edge, v, activeEdges, alloc);
993 split_edge(other, v, activeEdges, alloc);
994 }
995 #ifdef SK_DEBUG
996 validate_connectivity(v);
997 #endif
998 return v;
999 }
1000 return NULL;
1001 }
1002
1003 Vertex* sorted_merge(Vertex* a, Vertex* b);
1004
1005 void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack)
1006 {
1007 Vertex* fast;
1008 Vertex* slow;
1009 if (!v || !v->fNext) {
1010 *pFront = v;
1011 *pBack = NULL;
1012 } else {
1013 slow = v;
1014 fast = v->fNext;
1015
1016 while (fast != NULL) {
1017 fast = fast->fNext;
1018 if (fast != NULL) {
1019 slow = slow->fNext;
1020 fast = fast->fNext;
1021 }
1022 }
1023
1024 *pFront = v;
1025 *pBack = slow->fNext;
1026 slow->fNext->fPrev = NULL;
1027 slow->fNext = NULL;
1028 }
1029 }
1030
1031 void merge_sort(Vertex** head)
1032 {
1033 if (!*head || !(*head)->fNext) {
1034 return;
1035 }
1036
1037 Vertex* a;
1038 Vertex* b;
1039 front_back_split(*head, &a, &b);
1040
1041 merge_sort(&a);
1042 merge_sort(&b);
1043
1044 *head = sorted_merge(a, b);
1045 }
1046
1047 Vertex* sorted_merge(Vertex* a, Vertex* b)
1048 {
1049 if (!a) {
1050 return b;
1051 } else if (!b) {
1052 return a;
1053 }
1054
1055 Vertex* result = NULL;
1056
1057 if (a->fPoint < b->fPoint) {
1058 result = a;
1059 result->fNext = sorted_merge(a->fNext, b);
1060 } else {
1061 result = b;
1062 result->fNext = sorted_merge(a, b->fNext);
1063 }
1064 result->fNext->fPrev = result;
1065 return result;
1066 }
1067
1068 void sanitize_contours(Vertex** contours, int contourCnt) {
1069 for (int i = 0; i < contourCnt; ++i) {
1070 SkASSERT(contours[i]);
1071 for (Vertex* v = contours[i];;) {
1072 if (coincident(v->fPrev->fPoint, v->fPoint)) {
1073 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoi nt.fY);
1074 if (v->fPrev == v) {
1075 contours[i] = NULL;
1076 break;
1077 }
1078 v->fPrev->fNext = v->fNext;
1079 v->fNext->fPrev = v->fPrev;
1080 if (contours[i] == v) {
1081 contours[i] = v->fNext;
1082 }
1083 v = v->fPrev;
1084 } else {
1085 v = v->fNext;
1086 if (v == contours[i]) break;
1087 }
1088 }
1089 }
1090 }
1091
1092 void merge_coincident_vertices(Vertex** vertices, SkChunkAlloc& alloc) {
1093 for (Vertex* v = (*vertices)->fNext; v != NULL; v = v->fNext) {
1094 if (v->fPoint < v->fPrev->fPoint) {
1095 v->fPoint = v->fPrev->fPoint;
1096 }
1097 if (coincident(v->fPrev->fPoint, v->fPoint)) {
1098 merge_vertices(v->fPrev, v, vertices, alloc);
1099 }
1100 }
1101 }
1102
1103 Vertex* build_edges(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) {
1104 Vertex* vertices = NULL;
1105 Vertex* prev = NULL;
1106 for (int i = 0; i < contourCnt; ++i) {
1107 for (Vertex* v = contours[i]; v != NULL;) {
1108 Vertex* vNext = v->fNext;
1109 Edge* edge = new_edge(v->fPrev, v, alloc);
1110 if (edge->fWinding > 0) {
1111 insert_edge_below(edge, v->fPrev);
1112 insert_edge_above(edge, v);
1113 } else {
1114 insert_edge_below(edge, v);
1115 insert_edge_above(edge, v->fPrev);
1116 }
1117 merge_collinear_edges(edge, NULL);
1118 if (prev) {
1119 prev->fNext = v;
1120 v->fPrev = prev;
1121 } else {
1122 vertices = v;
1123 }
1124 prev = v;
1125 v = vNext;
1126 if (v == contours[i]) break;
1127 }
1128 }
1129 if (prev) {
1130 prev->fNext = vertices->fPrev = NULL;
1131 }
1132 return vertices;
1133 }
1134
1135 void simplify(Vertex* vertices, SkChunkAlloc& alloc) {
1136 LOG("simplifying complex polygons\n");
1137 Edge* activeEdges = NULL;
1138 for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1139 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1140 continue;
1141 }
1142 #if LOGGING_ENABLED
1143 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1144 #endif
1145 #ifdef SK_DEBUG
1146 validate_connectivity(v);
1147 #endif
1148 Edge* leftEnclosingEdge = NULL;
1149 Edge* rightEnclosingEdge = NULL;
1150 bool restartChecks;
1151 do {
1152 restartChecks = false;
1153 find_enclosing_edges(v, activeEdges, &leftEnclosingEdge, &rightEnclo singEdge);
1154 if (v->fFirstEdgeBelow) {
1155 for (Edge* edge = v->fFirstEdgeBelow; edge != NULL; edge = edge- >fNextEdgeBelow) {
1156 if (check_for_intersection(edge, leftEnclosingEdge, &activeE dges, alloc)) {
1157 restartChecks = true;
1158 break;
1159 }
1160 if (check_for_intersection(edge, rightEnclosingEdge, &active Edges, alloc)) {
1161 restartChecks = true;
1162 break;
1163 }
1164 }
1165 } else {
1166 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, right EnclosingEdge,
1167 &activeEdges, alloc)) {
1168 if (pv->fPoint < v->fPoint) {
1169 v = pv;
1170 }
1171 restartChecks = true;
1172 }
1173
1174 }
1175 } while (restartChecks);
1176 SkASSERT(!leftEnclosingEdge || leftEnclosingEdge->isLeftOf(v));
1177 SkASSERT(!rightEnclosingEdge || rightEnclosingEdge->isRightOf(v));
1178 #ifdef SK_DEBUG
1179 validate_edges(activeEdges);
1180 #endif
1181 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1182 remove_edge(e, &activeEdges);
1183 }
1184 Edge* leftEdge = leftEnclosingEdge;
1185 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1186 insert_edge(e, leftEdge, &activeEdges);
1187 leftEdge = e;
1188 }
1189 v->fProcessed = true;
1190 }
1191 }
1192
1193 Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) {
1194 LOG("tessellating simple polygons\n");
1195 Edge* activeEdges = NULL;
1196 Poly* polys = NULL;
1197 for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1198 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1199 continue;
1200 }
1201 #if LOGGING_ENABLED
1202 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1203 #endif
1204 #ifdef SK_DEBUG
1205 validate_connectivity(v);
1206 #endif
1207 Edge* leftEnclosingEdge = NULL;
1208 Edge* rightEnclosingEdge = NULL;
1209 find_enclosing_edges(v, activeEdges, &leftEnclosingEdge, &rightEnclosing Edge);
1210 SkASSERT(!leftEnclosingEdge || leftEnclosingEdge->isLeftOf(v));
1211 SkASSERT(!rightEnclosingEdge || rightEnclosingEdge->isRightOf(v));
1212 #ifdef SK_DEBUG
1213 validate_edges(activeEdges);
1214 #endif
1215 Poly* leftPoly = NULL;
1216 Poly* rightPoly = NULL;
1217 if (v->fFirstEdgeAbove) {
1218 leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1219 rightPoly = v->fLastEdgeAbove->fRightPoly;
1220 } else {
1221 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : NULL;
1222 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : NUL L;
1223 }
1224 #if LOGGING_ENABLED
1225 LOG("edges above:\n");
1226 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1227 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1228 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1);
1229 }
1230 LOG("edges below:\n");
1231 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1232 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1233 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1);
1234 }
1235 #endif
1236 if (v->fFirstEdgeAbove) {
1237 if (leftPoly) {
1238 leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1239 }
1240 if (rightPoly) {
1241 rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1242 }
1243 for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fN extEdgeAbove) {
1244 Edge* leftEdge = e;
1245 Edge* rightEdge = e->fNextEdgeAbove;
1246 SkASSERT(rightEdge->isRightOf(leftEdge->fTop));
1247 remove_edge(leftEdge, &activeEdges);
1248 if (leftEdge->fRightPoly) {
1249 leftEdge->fRightPoly->end(v, alloc);
1250 }
1251 if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != leftEdge->fR ightPoly) {
1252 rightEdge->fLeftPoly->end(v, alloc);
1253 }
1254 }
1255 remove_edge(v->fLastEdgeAbove, &activeEdges);
1256 if (!v->fFirstEdgeBelow) {
1257 if (leftPoly && rightPoly && leftPoly != rightPoly) {
1258 SkASSERT(leftPoly->fPartner == NULL && rightPoly->fPartner = = NULL);
1259 rightPoly->fPartner = leftPoly;
1260 leftPoly->fPartner = rightPoly;
1261 }
1262 }
1263 }
1264 if (v->fFirstEdgeBelow) {
1265 if (!v->fFirstEdgeAbove) {
1266 if (leftPoly && leftPoly == rightPoly) {
1267 // Split the poly.
1268 if (leftPoly->fActive->fSide == Poly::kLeft_Side) {
1269 leftPoly = new_poly(&polys, leftEnclosingEdge->fTop, lef tPoly->fWinding,
1270 alloc);
1271 leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1272 rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1273 leftEnclosingEdge->fRightPoly = leftPoly;
1274 } else {
1275 rightPoly = new_poly(&polys, rightEnclosingEdge->fTop, r ightPoly->fWinding,
1276 alloc);
1277 rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1278 leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1279 rightEnclosingEdge->fLeftPoly = rightPoly;
1280 }
1281 } else {
1282 if (leftPoly) {
1283 leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, all oc);
1284 }
1285 if (rightPoly) {
1286 rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, al loc);
1287 }
1288 }
1289 }
1290 Edge* leftEdge = v->fFirstEdgeBelow;
1291 leftEdge->fLeftPoly = leftPoly;
1292 insert_edge(leftEdge, leftEnclosingEdge, &activeEdges);
1293 for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1294 rightEdge = rightEdge->fNextEdgeBelow) {
1295 insert_edge(rightEdge, leftEdge, &activeEdges);
1296 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWindin g : 0;
1297 winding += leftEdge->fWinding;
1298 if (winding != 0) {
1299 Poly* poly = new_poly(&polys, v, winding, alloc);
1300 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1301 }
1302 leftEdge = rightEdge;
1303 }
1304 v->fLastEdgeBelow->fRightPoly = rightPoly;
1305 }
1306 #ifdef SK_DEBUG
1307 validate_edges(activeEdges);
1308 #endif
1309 #if LOGGING_ENABLED
1310 LOG("\nactive edges:\n");
1311 for (Edge* e = activeEdges; e != NULL; e = e->fRight) {
1312 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1313 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1);
1314 }
1315 #endif
1316 }
1317 return polys;
1318 }
1319
1320 Poly* contours_to_polys(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) {
1321 #if LOGGING_ENABLED
1322 for (int i = 0; i < contourCnt; ++i) {
1323 Vertex* v = contours[i];
1324 SkASSERT(v);
1325 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1326 for (v = v->fNext; v != contours[i]; v = v->fNext) {
1327 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1328 }
1329 }
1330 #endif
1331 sanitize_contours(contours, contourCnt);
1332 Vertex* vertices = build_edges(contours, contourCnt, alloc);
1333 if (!vertices) {
1334 return NULL;
1335 }
1336
1337 // Sort vertices in Y (secondarily in X).
1338 merge_sort(&vertices);
1339 merge_coincident_vertices(&vertices, alloc);
1340 #if LOGGING_ENABLED
1341 for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1342 static float gID = 0.0f;
1343 v->fID = gID++;
1344 }
1345 #endif
1346 simplify(vertices, alloc);
1347 return tessellate(vertices, alloc);
1348 }
1349
1350 void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, void* data) {
1351 void* d = data;
1352 for (Poly* poly = polys; poly; poly = poly->fNext) {
1353 if (apply_fill_type(fillType, poly->fWinding)) {
1354 d = poly->emit(d);
1355 }
1356 }
1357 return d;
1358 }
1359
1360 };
1361
1362 GrTessellatingPathRenderer::GrTessellatingPathRenderer() {
1363 }
1364
1365 GrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport(
1366 const GrDrawTarget*,
1367 const GrPipelineBuil der*,
1368 const SkPath&,
1369 const SkStrokeRec&) const {
1370 return GrPathRenderer::kNoSupport_StencilSupport;
1371 }
1372
1373 bool GrTessellatingPathRenderer::canDrawPath(const GrDrawTarget* target,
1374 const GrPipelineBuilder* pipelineBu ilder,
1375 const SkMatrix& viewMatrix,
1376 const SkPath& path,
1377 const SkStrokeRec& stroke,
1378 bool antiAlias) const {
1379 return stroke.isFillStyle() && !antiAlias;
1380 }
1381
1382 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target,
1383 GrPipelineBuilder* pipelineBuilder,
1384 GrColor color,
1385 const SkMatrix& viewM,
1386 const SkPath& path,
1387 const SkStrokeRec& stroke,
1388 bool antiAlias) {
1389 SkASSERT(!antiAlias);
1390 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
1391 if (NULL == rt) {
1392 return false;
1393 }
1394 SkPath deviceSpacePath;
1395 path.transform(viewM, &deviceSpacePath);
1396 SkASSERT(target);
1397
1398 SkScalar tol = SK_Scalar1;
1399
1400 int contourCnt;
1401 int maxPts = GrPathUtils::worstCasePointCount(deviceSpacePath, &contourCnt, SK_Scalar1);
1402 if (maxPts <= 0) {
1403 return false;
1404 }
1405 if (maxPts > ((int)SK_MaxU16 + 1)) {
1406 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1407 return false;
1408 }
1409 SkPath::FillType fillType = deviceSpacePath.getFillType();
1410 if (SkPath::IsInverseFillType(fillType)) {
1411 contourCnt++;
1412 }
1413
1414 LOG("got %d pts, %d contours\n", maxPts, contourCnt);
1415
1416 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
1417
1418 // For the initial size of the chunk allocator, estimate based on the point count:
1419 // one vertex per point for the initial passes, plus two for the vertices in the
1420 // resulting Polys, since the same point may end up in two Polys. Assume mi nimal
1421 // connectivity of one Edge per Vertex (will grow for intersections).
1422 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
1423 SkIRect clipBounds;
1424 target->getClip()->getConservativeBounds(rt, &clipBounds);
1425 path_to_contours(deviceSpacePath, tol, SkRect::Make(clipBounds), contours.ge t(), alloc);
1426 Poly* polys;
1427 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1428 polys = contours_to_polys(contours.get(), contourCnt, alloc);
1429 SkAutoTUnref<const GrGeometryProcessor> gp(
1430 GrDefaultGeoProcFactory::Create(flags, color, SkMatrix::I(), SkMatrix::I ()));
1431 int count = 0;
1432 for (Poly* poly = polys; poly; poly = poly->fNext) {
1433 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1434 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
1435 }
1436 }
1437
1438 int stride = gp->getVertexStride();
1439 GrDrawTarget::AutoReleaseGeometry arg;
1440 if (!arg.set(target, count, stride, 0)) {
1441 return false;
1442 }
1443 LOG("emitting %d verts\n", count);
1444 void* end = polys_to_triangles(polys, fillType, arg.vertices());
1445 int actualCount = (static_cast<char*>(end) - static_cast<char*>(arg.vertices ())) / stride;
1446 LOG("actual count: %d\n", actualCount);
1447 SkASSERT(actualCount <= count);
1448
1449 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
1450 : kTriangles_GrPrimitiveType;
1451 target->drawNonIndexed(pipelineBuilder, gp, primitiveType, 0, actualCount);
1452
1453 return true;
1454 }
OLDNEW
« no previous file with comments | « src/gpu/GrTessellatingPathRenderer.h ('k') | tests/ConcavePathTests.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698