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

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: Fix inverse fill types (inverse transform clip rect) 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
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) Build a mesh of edges connecting the vertices (build_edges()).
26 * 3) Sort the vertices in Y (and secondarily in X) (merge_sort()).
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 (3) 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 t->*Prev = prev;
102 t->*Next = next;
103 if (prev) {
104 prev->*Next = t;
105 } else if (head) {
106 *head = t;
107 }
108 if (next) {
109 next->*Prev = t;
110 } else if (tail) {
111 *tail = t;
112 }
113 }
114
115 template <class T, T* T::*Prev, T* T::*Next>
116 void remove(T* t, T** head, T** tail) {
117 if (t->*Prev) {
118 t->*Prev->*Next = t->*Next;
119 } else if (head) {
120 *head = t->*Next;
121 }
122 if (t->*Next) {
123 t->*Next->*Prev = t->*Prev;
124 } else if (tail) {
125 *tail = t->*Prev;
126 }
127 t->*Prev = t->*Next = NULL;
128 }
129
130 /**
131 * Vertices are used in three ways: first, the path contours are converted into a
132 * circularly-linked list of Vertices for each contour. After edge construction, the same Vertices
133 * are re-ordered by the merge sort according to the sweep_lt comparator (usuall y, increasing
134 * in Y) using the same fPrev/fNext pointers that were used for the contours, to avoid
135 * reallocation. Finally, MonotonePolys are built containing a circularly-linked list of
136 * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePoly s, since
137 * an individual Vertex from the path mesh may belong to multiple
138 * MonotonePolys, so the original Vertices cannot be re-used.
139 */
140
141 struct Vertex {
142 Vertex(const SkPoint& point)
143 : fPoint(point), fPrev(NULL), fNext(NULL)
144 , fFirstEdgeAbove(NULL), fLastEdgeAbove(NULL)
145 , fFirstEdgeBelow(NULL), fLastEdgeBelow(NULL)
146 , fProcessed(false)
147 #if LOGGING_ENABLED
148 , fID (-1.0f)
149 #endif
150 {}
151 SkPoint fPoint; // Vertex position
152 Vertex* fPrev; // Linked list of contours, then Y-sorted vertices .
153 Vertex* fNext; // "
154 Edge* fFirstEdgeAbove; // Linked list of edges above this vertex.
155 Edge* fLastEdgeAbove; // "
156 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex.
157 Edge* fLastEdgeBelow; // "
158 bool fProcessed; // Has this vertex been seen in simplify()?
159 #if LOGGING_ENABLED
160 float fID; // Identifier used for logging.
161 #endif
162 };
163
164 /******************************************************************************* ********/
165
166 bool sweep_lt(const SkPoint& a, const SkPoint& b) {
167 #if SWEEP_IN_X
168 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX;
169 #else
170 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY;
171 #endif
172 }
173
174 bool sweep_gt(const SkPoint& a, const SkPoint& b) {
175 #if SWEEP_IN_X
176 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX;
177 #else
178 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY;
179 #endif
180 }
181
182 inline void* emit_vertex(Vertex* v, void* data) {
183 SkPoint* d = static_cast<SkPoint*>(data);
184 *d++ = v->fPoint;
185 return d;
186 }
187
188 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, void* data) {
189 #if WIREFRAME
190 data = emit_vertex(v0, data);
191 data = emit_vertex(v1, data);
192 data = emit_vertex(v1, data);
193 data = emit_vertex(v2, data);
194 data = emit_vertex(v2, data);
195 data = emit_vertex(v0, data);
196 #else
197 data = emit_vertex(v0, data);
198 data = emit_vertex(v1, data);
199 data = emit_vertex(v2, data);
200 #endif
201 return data;
202 }
203
204 /**
205 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and
206 * "edge below" a vertex as well as for the active edge list is handled by isLef tOf()/isRightOf().
207 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (b ecause floating
208 * point). For speed, that case is only tested by the callers which require it ( e.g.,
209 * cleanup_active_edges()). Edges also handle checking for intersection with oth er edges.
210 * Currently, this converts the edges to the parametric form, in order to avoid doing a division
211 * until an intersection has been confirmed. This is slightly slower in the "fou nd" case, but
212 * a lot faster in the "not found" case.
213 */
214
215 struct Edge {
216 Edge(Vertex* top, Vertex* bottom, int winding)
217 : fWinding(winding)
218 , fTop(top)
219 , fBottom(bottom)
220 , fLeft(NULL)
221 , fRight(NULL)
222 , fPrevEdgeAbove(NULL)
223 , fNextEdgeAbove(NULL)
224 , fPrevEdgeBelow(NULL)
225 , fNextEdgeBelow(NULL)
226 , fLeftPoly(NULL)
227 , fRightPoly(NULL) {
228 recompute();
229 }
230 int fWinding; // 1 == edge goes downward; -1 = edge goes upwar d.
231 Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt ).
232 Vertex* fBottom; // The bottom vertex in vertex-sort-order.
233 Edge* fLeft; // The linked list of edges in the active edge l ist.
234 Edge* fRight; // "
235 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex 's "edges above".
236 Edge* fNextEdgeAbove; // "
237 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex's "edges below".
238 Edge* fNextEdgeBelow; // "
239 Poly* fLeftPoly; // The Poly to the left of this edge, if any.
240 Poly* fRightPoly; // The Poly to the right of this edge, if any.
241 double fDX; // The line equation for this edge, in implicit form.
reed2 2015/02/24 16:30:01 Did you try using SkScalar first, and it failed fo
Stephen White 2015/02/24 18:45:16 Added a comment.
242 double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y) on the line.
243 double fC;
244 double dist(const SkPoint& p) const {
245 return fDY * p.fX - fDX * p.fY + fC;
246 }
247 bool isRightOf(Vertex* v) const {
248 return dist(v->fPoint) < 0.0;
249 }
250 bool isLeftOf(Vertex* v) const {
251 return dist(v->fPoint) > 0.0;
252 }
253 void recompute() {
254 fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX;
255 fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY;
256 fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX -
257 static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY;
258 }
259 bool intersect(const Edge& other, SkPoint* p) {
260 LOG("intersecting %g -> %g with %g -> %g\n",
261 fTop->fID, fBottom->fID,
262 other.fTop->fID, other.fBottom->fID);
263 if (fTop == other.fTop || fBottom == other.fBottom) {
264 return false;
265 }
266 double denom = fDX * other.fDY - fDY * other.fDX;
267 if (denom == 0.0) {
268 return false;
269 }
270 double dx = static_cast<double>(fTop->fPoint.fX) - other.fTop->fPoint.fX ;
271 double dy = static_cast<double>(fTop->fPoint.fY) - other.fTop->fPoint.fY ;
272 double sNumer = dy * other.fDX - dx * other.fDY;
273 double tNumer = dy * fDX - dx * fDY;
274 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNu mer > denom)
reed2 2015/02/24 16:30:01 // We check that the result of the divide (sNumer
Stephen White 2015/02/24 18:45:16 See the comment above "struct Edge {". It would be
275 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNu mer < denom)) {
276 return false;
277 }
278 double s = sNumer / denom;
279 p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX);
280 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY);
281 return true;
282 }
283 bool isActive(Edge** activeEdges) const {
284 return activeEdges && (fLeft || fRight || *activeEdges == this);
285 }
286 };
287
288 /******************************************************************************* ********/
289
290 struct Poly {
291 Poly(int winding)
292 : fWinding(winding)
293 , fHead(NULL)
294 , fTail(NULL)
295 , fActive(NULL)
296 , fNext(NULL)
297 , fPartner(NULL)
298 , fCount(0)
299 {
300 #if LOGGING_ENABLED
301 static int gID = 0;
302 fID = gID++;
303 LOG("*** created Poly %d\n", fID);
304 #endif
305 }
306 typedef enum { kNeither_Side, kLeft_Side, kRight_Side } Side;
307 struct MonotonePoly {
308 MonotonePoly()
309 : fSide(kNeither_Side)
310 , fHead(NULL)
311 , fTail(NULL)
312 , fPrev(NULL)
313 , fNext(NULL) {}
314 Side fSide;
315 Vertex* fHead;
316 Vertex* fTail;
317 MonotonePoly* fPrev;
318 MonotonePoly* fNext;
319 bool addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
320 Vertex* newV = ALLOC_NEW(Vertex, (v->fPoint), alloc);
321 bool done = false;
322 if (fSide == kNeither_Side) {
323 fSide = side;
324 } else {
325 done = side != fSide;
326 }
327 if (fHead == NULL) {
328 fHead = fTail = newV;
329 } else if (fSide == kRight_Side) {
330 newV->fPrev = fTail;
331 fTail->fNext = newV;
332 fTail = newV;
333 } else {
334 newV->fNext = fHead;
335 fHead->fPrev = newV;
336 fHead = newV;
337 }
338 return done;
339 }
340
341 void* emit(void* data) {
342 Vertex* first = fHead;
343 Vertex* v = first->fNext;
344 while (v != fTail) {
345 SkASSERT(v && v->fPrev && v->fNext);
346 #ifdef SK_DEBUG
347 validate();
348 #endif
349 Vertex* prev = v->fPrev;
350 Vertex* curr = v;
351 Vertex* next = v->fNext;
352 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint. fX;
353 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint. fY;
354 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint. fX;
355 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint. fY;
356 if (ax * by - ay * bx >= 0.0) {
357 data = emit_triangle(prev, curr, next, data);
358 v->fPrev->fNext = v->fNext;
359 v->fNext->fPrev = v->fPrev;
360 if (v->fPrev == first) {
361 v = v->fNext;
362 } else {
363 v = v->fPrev;
364 }
365 } else {
366 v = v->fNext;
367 SkASSERT(v != fTail);
368 }
369 }
370 return data;
371 }
372
373 #ifdef SK_DEBUG
374 void validate() {
375 int winding = sweep_lt(fHead->fPoint, fTail->fPoint) ? 1 : -1;
376 Vertex* top = winding < 0 ? fTail : fHead;
377 Vertex* bottom = winding < 0 ? fHead : fTail;
378 Edge e(top, bottom, winding);
379 for (Vertex* v = fHead->fNext; v != fTail; v = v->fNext) {
380 if (fSide == kRight_Side) {
381 SkASSERT(!e.isRightOf(v));
382 } else if (fSide == Poly::kLeft_Side) {
383 SkASSERT(!e.isLeftOf(v));
384 }
385 }
386 }
387 #endif
388 };
389 Poly* addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) {
390 LOG("addVertex() to %d at %g (%g, %g), %s side\n", fID, v->fID, v->fPoin t.fX, v->fPoint.fY,
391 side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "ne ither");
392 Poly* partner = fPartner;
393 Poly* poly = this;
394 if (partner) {
395 fPartner = partner->fPartner = NULL;
396 }
397 if (!fActive) {
398 fActive = ALLOC_NEW(MonotonePoly, (), alloc);
399 }
400 if (fActive->addVertex(v, side, alloc)) {
401 #ifdef SK_DEBUG
402 fActive->validate();
403 #endif
404 if (fTail) {
405 fActive->fPrev = fTail;
406 fTail->fNext = fActive;
407 fTail = fActive;
408 } else {
409 fHead = fTail = fActive;
410 }
411 if (partner) {
412 partner->addVertex(v, side, alloc);
413 poly = partner;
414 } else {
415 Vertex* prev = fActive->fSide == Poly::kLeft_Side ?
416 fActive->fHead->fNext : fActive->fTail->fPrev;
417 fActive = ALLOC_NEW(MonotonePoly, , alloc);
418 fActive->addVertex(prev, Poly::kNeither_Side, alloc);
419 fActive->addVertex(v, side, alloc);
420 }
421 }
422 fCount++;
423 return poly;
424 }
425 void end(Vertex* v, SkChunkAlloc& alloc) {
426 LOG("end() %d at %g, %g\n", fID, v->fPoint.fX, v->fPoint.fY);
427 if (fPartner) {
428 fPartner = fPartner->fPartner = NULL;
429 }
430 addVertex(v, fActive->fSide == kLeft_Side ? kRight_Side : kLeft_Side, al loc);
431 }
432 void* emit(void *data) {
433 if (fCount < 3) {
434 return data;
435 }
436 LOG("emit() %d, size %d\n", fID, fCount);
437 for (MonotonePoly* m = fHead; m != NULL; m = m->fNext) {
438 data = m->emit(data);
439 }
440 return data;
441 }
442 int fWinding;
443 MonotonePoly* fHead;
444 MonotonePoly* fTail;
445 MonotonePoly* fActive;
446 Poly* fNext;
447 Poly* fPartner;
448 int fCount;
449 #if LOGGING_ENABLED
450 int fID;
451 #endif
452 };
453
454 /******************************************************************************* ********/
455
456 bool coincident(const SkPoint& a, const SkPoint& b) {
457 return a == b;
458 }
459
460 Poly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) {
461 Poly* poly = ALLOC_NEW(Poly, (winding), alloc);
462 poly->addVertex(v, Poly::kNeither_Side, alloc);
463 poly->fNext = *head;
464 *head = poly;
465 return poly;
466 }
467
468 #ifdef SK_DEBUG
469 void validate_edges(Edge* head) {
470 for (Edge* e = head; e != NULL; e = e->fRight) {
471 SkASSERT(e->fTop != e->fBottom);
472 if (e->fLeft) {
473 SkASSERT(e->fLeft->fRight == e);
474 if (sweep_gt(e->fTop->fPoint, e->fLeft->fTop->fPoint)) {
475 SkASSERT(e->fLeft->isLeftOf(e->fTop));
476 }
477 if (sweep_lt(e->fBottom->fPoint, e->fLeft->fBottom->fPoint)) {
478 SkASSERT(e->fLeft->isLeftOf(e->fBottom));
479 }
480 } else {
481 SkASSERT(e == head);
482 }
483 if (e->fRight) {
484 SkASSERT(e->fRight->fLeft == e);
485 if (sweep_gt(e->fTop->fPoint, e->fRight->fTop->fPoint)) {
486 SkASSERT(e->fRight->isRightOf(e->fTop));
487 }
488 if (sweep_lt(e->fBottom->fPoint, e->fRight->fBottom->fPoint)) {
489 SkASSERT(e->fRight->isRightOf(e->fBottom));
490 }
491 }
492 }
493 }
494
495 void validate_connectivity(Vertex* v) {
496 for (Edge* e = v->fFirstEdgeAbove; e != NULL; e = e->fNextEdgeAbove) {
497 SkASSERT(e->fBottom == v);
498 if (e->fPrevEdgeAbove) {
499 SkASSERT(e->fPrevEdgeAbove->fNextEdgeAbove == e);
500 SkASSERT(e->fPrevEdgeAbove->isLeftOf(e->fTop));
501 } else {
502 SkASSERT(e == v->fFirstEdgeAbove);
503 }
504 if (e->fNextEdgeAbove) {
505 SkASSERT(e->fNextEdgeAbove->fPrevEdgeAbove == e);
506 SkASSERT(e->fNextEdgeAbove->isRightOf(e->fTop));
507 } else {
508 SkASSERT(e == v->fLastEdgeAbove);
509 }
510 }
511 for (Edge* e = v->fFirstEdgeBelow; e != NULL; e = e->fNextEdgeBelow) {
512 SkASSERT(e->fTop == v);
513 if (e->fPrevEdgeBelow) {
514 SkASSERT(e->fPrevEdgeBelow->fNextEdgeBelow == e);
515 SkASSERT(e->fPrevEdgeBelow->isLeftOf(e->fBottom));
516 } else {
517 SkASSERT(e == v->fFirstEdgeBelow);
518 }
519 if (e->fNextEdgeBelow) {
520 SkASSERT(e->fNextEdgeBelow->fPrevEdgeBelow == e);
521 SkASSERT(e->fNextEdgeBelow->isRightOf(e->fBottom));
522 } else {
523 SkASSERT(e == v->fLastEdgeBelow);
524 }
525 }
526 }
527 #endif
528
529 Vertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head,
530 SkChunkAlloc& alloc) {
531 Vertex* v = ALLOC_NEW(Vertex, (p), alloc);
532 #if LOGGING_ENABLED
533 static float gID = 0.0f;
534 v->fID = gID++;
535 #endif
536 if (prev) {
537 prev->fNext = v;
538 v->fPrev = prev;
539 } else {
540 *head = v;
541 }
542 return v;
543 }
544
545 Vertex* generate_quadratic_points(const SkPoint& p0,
546 const SkPoint& p1,
547 const SkPoint& p2,
548 SkScalar tolSqd,
549 Vertex* prev,
550 Vertex** head,
551 int pointsLeft,
552 SkChunkAlloc& alloc) {
553 SkScalar d = p1.distanceToLineSegmentBetweenSqd(p0, p2);
554 if (pointsLeft < 2 || d < tolSqd || !SkScalarIsFinite(d)) {
555 return append_point_to_contour(p2, prev, head, alloc);
556 }
557
558 SkPoint q[] = {
559 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
560 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
561 };
562 SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) } ;
563
564 pointsLeft >>= 1;
565 prev = generate_quadratic_points(p0, q[0], r, tolSqd, prev, head, pointsLeft , alloc);
566 prev = generate_quadratic_points(r, q[1], p2, tolSqd, prev, head, pointsLeft , alloc);
567 return prev;
568 }
569
570 Vertex* generate_cubic_points(const SkPoint& p0,
571 const SkPoint& p1,
572 const SkPoint& p2,
573 const SkPoint& p3,
574 SkScalar tolSqd,
575 Vertex* prev,
576 Vertex** head,
577 int pointsLeft,
578 SkChunkAlloc& alloc) {
579 SkScalar d1 = p1.distanceToLineSegmentBetweenSqd(p0, p3);
580 SkScalar d2 = p2.distanceToLineSegmentBetweenSqd(p0, p3);
581 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) || !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) {
582 return append_point_to_contour(p3, prev, head, alloc);
583 }
584 SkPoint q[] = {
reed2 2015/02/24 16:30:01 nit: can q[] and r[] be const?
Stephen White 2015/02/24 18:45:16 Done.
585 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) },
586 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) },
587 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) }
588 };
589 SkPoint r[] = {
590 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) },
591 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) }
592 };
593 SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1].fY) } ;
594 pointsLeft >>= 1;
595 prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLe ft, alloc);
596 prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLe ft, alloc);
597 return prev;
598 }
599
600 // Stage 1: convert the input path to a set of linear contours (linked list of V ertices).
601
602 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip Bounds,
603 Vertex** contours, SkChunkAlloc& alloc) {
604
605 SkScalar toleranceSqd = tolerance * tolerance;
606
607 SkPoint pts[4];
608 bool done = false;
609 SkPath::Iter iter(path, false);
610 Vertex* prev = NULL;
611 Vertex* head = NULL;
612 if (path.isInverseFillType()) {
613 SkPoint quad[4];
614 clipBounds.toQuad(quad);
615 for (int i = 3; i >= 0; i--) {
616 prev = append_point_to_contour(quad[i], prev, &head, alloc);
617 }
618 head->fPrev = prev;
619 prev->fNext = head;
620 *contours++ = head;
621 head = prev = NULL;
622 }
623 SkAutoConicToQuads converter;
624 while (!done) {
625 SkPath::Verb verb = iter.next(pts);
626 switch (verb) {
627 case SkPath::kConic_Verb: {
628 SkScalar weight = iter.conicWeight();
629 const SkPoint* quadPts = converter.computeQuads(pts, weight, tol eranceSqd);
630 for (int i = 0; i < converter.countQuads(); ++i) {
631 int pointsLeft = GrPathUtils::quadraticPointCount(quadPts, t oleranceSqd);
632 prev = generate_quadratic_points(quadPts[0], quadPts[1], qua dPts[2],
633 toleranceSqd, prev, &head, pointsLeft, alloc);
634 quadPts += 2;
635 }
636 break;
637 }
638 case SkPath::kMove_Verb:
639 if (head) {
640 head->fPrev = prev;
641 prev->fNext = head;
642 *contours++ = head;
643 }
644 head = prev = NULL;
645 prev = append_point_to_contour(pts[0], prev, &head, alloc);
646 break;
647 case SkPath::kLine_Verb: {
648 prev = append_point_to_contour(pts[1], prev, &head, alloc);
649 break;
650 }
651 case SkPath::kQuad_Verb: {
652 int pointsLeft = GrPathUtils::quadraticPointCount(pts, tolerance Sqd);
653 prev = generate_quadratic_points(pts[0], pts[1], pts[2], toleran ceSqd, prev,
654 &head, pointsLeft, alloc);
655 break;
656 }
657 case SkPath::kCubic_Verb: {
658 int pointsLeft = GrPathUtils::cubicPointCount(pts, toleranceSqd) ;
659 prev = generate_cubic_points(pts[0], pts[1], pts[2], pts[3],
660 toleranceSqd, prev, &head, pointsLeft, alloc);
661 break;
662 }
663 case SkPath::kClose_Verb:
664 if (head) {
665 head->fPrev = prev;
666 prev->fNext = head;
667 *contours++ = head;
668 }
669 head = prev = NULL;
670 break;
671 case SkPath::kDone_Verb:
672 if (head) {
673 head->fPrev = prev;
674 prev->fNext = head;
675 *contours++ = head;
676 }
677 done = true;
678 break;
679 }
680 }
681 }
682
683 inline bool apply_fill_type(SkPath::FillType fillType, int winding) {
684 switch (fillType) {
685 case SkPath::kWinding_FillType:
686 return winding != 0;
687 case SkPath::kEvenOdd_FillType:
688 return (winding & 1) != 0;
689 case SkPath::kInverseWinding_FillType:
690 return winding == 1;
691 case SkPath::kInverseEvenOdd_FillType:
692 return (winding & 1) == 1;
693 default:
694 SkASSERT(false);
695 return false;
696 }
697 }
698
699 Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc) {
700 int winding = sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
701 Vertex* top = winding < 0 ? next : prev;
702 Vertex* bottom = winding < 0 ? prev : next;
703 return ALLOC_NEW(Edge, (top, bottom, winding), alloc);
704 }
705
706 void remove_edge(Edge* edge, Edge** head) {
707 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
708 SkASSERT(edge->isActive(head));
709 remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, head, NULL);
710 }
711
712 void insert_edge(Edge* edge, Edge* prev, Edge** head) {
713 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID);
714 SkASSERT(!edge->isActive(head));
715 Edge* next = prev ? prev->fRight : *head;
716 insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, head, NULL);
717 }
718
719 void find_enclosing_edges(Vertex* v, Edge* head, Edge** left, Edge** right) {
720 if (v->fFirstEdgeAbove) {
721 *left = v->fFirstEdgeAbove->fLeft;
722 *right = v->fLastEdgeAbove->fRight;
723 return;
724 }
725 Edge* prev = NULL;
726 Edge* next;
727 for (next = head; next != NULL; next = next->fRight) {
728 if (next->isRightOf(v)) {
729 break;
730 }
731 prev = next;
732 }
733 *left = prev;
734 *right = next;
735 return;
736 }
737
738 void find_enclosing_edges(Edge* edge, Edge* head, Edge** left, Edge** right) {
739 Edge* prev = NULL;
740 Edge* next;
741 for (next = head; next != NULL; next = next->fRight) {
742 if ((sweep_gt(edge->fTop->fPoint, next->fTop->fPoint) && next->isRightOf (edge->fTop)) ||
743 (sweep_gt(next->fTop->fPoint, edge->fTop->fPoint) && edge->isLeftOf( next->fTop)) ||
744 (sweep_lt(edge->fBottom->fPoint, next->fBottom->fPoint) &&
745 next->isRightOf(edge->fBottom)) ||
746 (sweep_lt(next->fBottom->fPoint, edge->fBottom->fPoint) &&
747 edge->isLeftOf(next->fBottom))) {
748 break;
749 }
750 prev = next;
751 }
752 *left = prev;
753 *right = next;
754 return;
755 }
756
757 void fix_active_state(Edge* edge, Edge** activeEdges) {
758 if (edge->isActive(activeEdges)) {
759 if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) {
760 remove_edge(edge, activeEdges);
761 }
762 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) {
763 Edge* left;
764 Edge* right;
765 find_enclosing_edges(edge, *activeEdges, &left, &right);
766 insert_edge(edge, left, activeEdges);
767 }
768 }
769
770 void insert_edge_above(Edge* edge, Vertex* v) {
771 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
772 sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
773 SkASSERT(false);
774 return;
775 }
776 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBott om->fID, v->fID);
777 Edge* prev = NULL;
778 Edge* next;
779 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) {
780 if (next->isRightOf(edge->fTop)) {
781 break;
782 }
783 prev = next;
784 }
785 insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
786 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
787 }
788
789 void insert_edge_below(Edge* edge, Vertex* v) {
790 if (edge->fTop->fPoint == edge->fBottom->fPoint ||
791 sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
792 SkASSERT(false);
793 return;
794 }
795 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBott om->fID, v->fID);
796 Edge* prev = NULL;
797 Edge* next;
798 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) {
799 if (next->isRightOf(edge->fBottom)) {
800 break;
801 }
802 prev = next;
803 }
804 insert<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
805 edge, prev, next, &v->fFirstEdgeBelow, &v->fLastEdgeBelow);
806 }
807
808 void remove_edge_above(Edge* edge) {
809 LOG("removing edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBo ttom->fID,
810 edge->fBottom->fID);
811 remove<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>(
812 edge, &edge->fBottom->fFirstEdgeAbove, &edge->fBottom->fLastEdgeAbove);
813 }
814
815 void remove_edge_below(Edge* edge) {
816 LOG("removing edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBo ttom->fID,
817 edge->fTop->fID);
818 remove<Edge, &Edge::fPrevEdgeBelow, &Edge::fNextEdgeBelow>(
819 edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
820 }
821
822 void erase_edge_if_zero_winding(Edge* edge, Edge** head) {
823 if (edge->fWinding != 0) {
824 return;
825 }
826 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
827 remove_edge_above(edge);
828 remove_edge_below(edge);
829 if (edge->isActive(head)) {
830 remove_edge(edge, head);
831 }
832 }
833
834 void merge_collinear_edges(Edge* edge, Edge** activeEdges);
835
836 void set_top(Edge* edge, Vertex* v, Edge** activeEdges) {
837 remove_edge_below(edge);
838 edge->fTop = v;
839 edge->recompute();
840 insert_edge_below(edge, v);
841 fix_active_state(edge, activeEdges);
842 merge_collinear_edges(edge, activeEdges);
843 }
844
845 void set_bottom(Edge* edge, Vertex* v, Edge** activeEdges) {
846 remove_edge_above(edge);
847 edge->fBottom = v;
848 edge->recompute();
849 insert_edge_above(edge, v);
850 fix_active_state(edge, activeEdges);
851 merge_collinear_edges(edge, activeEdges);
852 }
853
854 void merge_edges_above(Edge* edge, Edge* other, Edge** activeEdges) {
855 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
856 LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
857 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
858 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
859 other->fWinding += edge->fWinding;
860 erase_edge_if_zero_winding(other, activeEdges);
861 edge->fWinding = 0;
862 erase_edge_if_zero_winding(edge, activeEdges);
863 } else if (sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
864 other->fWinding += edge->fWinding;
865 erase_edge_if_zero_winding(other, activeEdges);
866 set_bottom(edge, other->fTop, activeEdges);
867 } else {
868 edge->fWinding += other->fWinding;
869 erase_edge_if_zero_winding(edge, activeEdges);
870 set_bottom(other, edge->fTop, activeEdges);
871 }
872 }
873
874 void merge_edges_below(Edge* edge, Edge* other, Edge** activeEdges) {
875 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
876 LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
877 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
878 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
879 other->fWinding += edge->fWinding;
880 erase_edge_if_zero_winding(other, activeEdges);
881 edge->fWinding = 0;
882 erase_edge_if_zero_winding(edge, activeEdges);
883 } else if (sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
884 edge->fWinding += other->fWinding;
885 erase_edge_if_zero_winding(edge, activeEdges);
886 set_top(other, edge->fBottom, activeEdges);
887 } else {
888 other->fWinding += edge->fWinding;
889 erase_edge_if_zero_winding(other, activeEdges);
890 set_top(edge, other->fBottom, activeEdges);
891 }
892 }
893
894 void merge_collinear_edges(Edge* edge, Edge** activeEdges) {
895 if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
896 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
897 merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges);
898 } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
899 !edge->isLeftOf(edge->fNextEdgeAbove->fT op))) {
900 merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges);
901 }
902 if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
903 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom)) ) {
904 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges);
905 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->f Bottom ||
906 !edge->isLeftOf(edge->fNextEdgeBelow->fB ottom))) {
907 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges);
908 }
909 }
910
911 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc);
912
913 void cleanup_active_edges(Edge* edge, Edge** activeEdges, SkChunkAlloc& alloc) {
914 Vertex* top = edge->fTop;
915 Vertex* bottom = edge->fBottom;
916 if (edge->fLeft) {
917 Vertex* leftTop = edge->fLeft->fTop;
918 Vertex* leftBottom = edge->fLeft->fBottom;
919 if (sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(top )) {
920 split_edge(edge->fLeft, edge->fTop, activeEdges, alloc);
921 } else if (sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(le ftTop)) {
922 split_edge(edge, leftTop, activeEdges, alloc);
923 } else if (sweep_lt(bottom->fPoint, leftBottom->fPoint) && !edge->fLeft- >isLeftOf(bottom)) {
924 split_edge(edge->fLeft, bottom, activeEdges, alloc);
925 } else if (sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRigh tOf(leftBottom)) {
926 split_edge(edge, leftBottom, activeEdges, alloc);
927 }
928 }
929 if (edge->fRight) {
930 Vertex* rightTop = edge->fRight->fTop;
931 Vertex* rightBottom = edge->fRight->fBottom;
932 if (sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightOf( top)) {
933 split_edge(edge->fRight, top, activeEdges, alloc);
934 } else if (sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(ri ghtTop)) {
935 split_edge(edge, rightTop, activeEdges, alloc);
936 } else if (sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
937 !edge->fRight->isRightOf(bottom)) {
938 split_edge(edge->fRight, bottom, activeEdges, alloc);
939 } else if (sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
940 !edge->isLeftOf(rightBottom)) {
941 split_edge(edge, rightBottom, activeEdges, alloc);
942 }
943 }
944 }
945
946 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc) {
947 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
948 edge->fTop->fID, edge->fBottom->fID,
949 v->fID, v->fPoint.fX, v->fPoint.fY);
950 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc);
951 insert_edge_below(newEdge, v);
952 insert_edge_above(newEdge, edge->fBottom);
953 set_bottom(edge, v, activeEdges);
954 cleanup_active_edges(edge, activeEdges, alloc);
955 fix_active_state(newEdge, activeEdges);
956 merge_collinear_edges(newEdge, activeEdges);
957 }
958
959 void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc ) {
960 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX , src->fPoint.fY,
961 src->fID, dst->fID);
962 for (Edge* edge = src->fFirstEdgeAbove; edge;) {
963 Edge* next = edge->fNextEdgeAbove;
964 set_bottom(edge, dst, NULL);
965 edge = next;
966 }
967 for (Edge* edge = src->fFirstEdgeBelow; edge;) {
968 Edge* next = edge->fNextEdgeBelow;
969 set_top(edge, dst, NULL);
970 edge = next;
971 }
972 remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, NULL);
973 }
974
975 Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, SkCh unkAlloc& alloc) {
976 SkPoint p;
977 if (!edge || !other) {
978 return NULL;
979 }
980 if (edge->intersect(*other, &p)) {
981 Vertex* v;
982 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
983 if (p == edge->fTop->fPoint || sweep_lt(p, edge->fTop->fPoint)) {
984 split_edge(other, edge->fTop, activeEdges, alloc);
985 v = edge->fTop;
986 } else if (p == edge->fBottom->fPoint || sweep_gt(p, edge->fBottom->fPoi nt)) {
987 split_edge(other, edge->fBottom, activeEdges, alloc);
988 v = edge->fBottom;
989 } else if (p == other->fTop->fPoint || sweep_lt(p, other->fTop->fPoint)) {
990 split_edge(edge, other->fTop, activeEdges, alloc);
991 v = other->fTop;
992 } else if (p == other->fBottom->fPoint || sweep_gt(p, other->fBottom->fP oint)) {
993 split_edge(edge, other->fBottom, activeEdges, alloc);
994 v = other->fBottom;
995 } else {
996 Vertex* nextV = edge->fTop;
997 while (sweep_lt(p, nextV->fPoint)) {
998 nextV = nextV->fPrev;
999 }
1000 while (sweep_lt(nextV->fPoint, p)) {
1001 nextV = nextV->fNext;
1002 }
1003 Vertex* prevV = nextV->fPrev;
1004 if (coincident(prevV->fPoint, p)) {
1005 v = prevV;
1006 } else if (coincident(nextV->fPoint, p)) {
1007 v = nextV;
1008 } else {
1009 v = ALLOC_NEW(Vertex, (p), alloc);
1010 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n",
1011 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY,
1012 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY);
1013 #if LOGGING_ENABLED
1014 v->fID = (nextV->fID + prevV->fID) * 0.5f;
1015 #endif
1016 v->fPrev = prevV;
1017 v->fNext = nextV;
1018 prevV->fNext = v;
1019 nextV->fPrev = v;
1020 }
1021 split_edge(edge, v, activeEdges, alloc);
1022 split_edge(other, v, activeEdges, alloc);
1023 }
1024 #ifdef SK_DEBUG
1025 validate_connectivity(v);
1026 #endif
1027 return v;
1028 }
1029 return NULL;
1030 }
1031
1032 void sanitize_contours(Vertex** contours, int contourCnt) {
1033 for (int i = 0; i < contourCnt; ++i) {
1034 SkASSERT(contours[i]);
1035 for (Vertex* v = contours[i];;) {
1036 if (coincident(v->fPrev->fPoint, v->fPoint)) {
1037 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoi nt.fY);
1038 if (v->fPrev == v) {
1039 contours[i] = NULL;
1040 break;
1041 }
1042 v->fPrev->fNext = v->fNext;
1043 v->fNext->fPrev = v->fPrev;
1044 if (contours[i] == v) {
1045 contours[i] = v->fNext;
1046 }
1047 v = v->fPrev;
1048 } else {
1049 v = v->fNext;
1050 if (v == contours[i]) break;
1051 }
1052 }
1053 }
1054 }
1055
1056 void merge_coincident_vertices(Vertex** vertices, SkChunkAlloc& alloc) {
1057 for (Vertex* v = (*vertices)->fNext; v != NULL; v = v->fNext) {
1058 if (sweep_lt(v->fPoint, v->fPrev->fPoint)) {
1059 v->fPoint = v->fPrev->fPoint;
1060 }
1061 if (coincident(v->fPrev->fPoint, v->fPoint)) {
1062 merge_vertices(v->fPrev, v, vertices, alloc);
1063 }
1064 }
1065 }
1066
1067 // Stage 2: convert the contours to a mesh of edges connecting the vertices.
1068
1069 Vertex* build_edges(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) {
1070 Vertex* vertices = NULL;
1071 Vertex* prev = NULL;
1072 for (int i = 0; i < contourCnt; ++i) {
1073 for (Vertex* v = contours[i]; v != NULL;) {
1074 Vertex* vNext = v->fNext;
1075 Edge* edge = new_edge(v->fPrev, v, alloc);
1076 if (edge->fWinding > 0) {
1077 insert_edge_below(edge, v->fPrev);
1078 insert_edge_above(edge, v);
1079 } else {
1080 insert_edge_below(edge, v);
1081 insert_edge_above(edge, v->fPrev);
1082 }
1083 merge_collinear_edges(edge, NULL);
1084 if (prev) {
1085 prev->fNext = v;
1086 v->fPrev = prev;
1087 } else {
1088 vertices = v;
1089 }
1090 prev = v;
1091 v = vNext;
1092 if (v == contours[i]) break;
1093 }
1094 }
1095 if (prev) {
1096 prev->fNext = vertices->fPrev = NULL;
1097 }
1098 return vertices;
1099 }
1100
1101 // Stage 3: sort the vertices by increasing Y (or X if SWEEP_IN_X is on).
1102
1103 Vertex* sorted_merge(Vertex* a, Vertex* b);
1104
1105 void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) {
1106 Vertex* fast;
1107 Vertex* slow;
1108 if (!v || !v->fNext) {
1109 *pFront = v;
1110 *pBack = NULL;
1111 } else {
1112 slow = v;
1113 fast = v->fNext;
1114
1115 while (fast != NULL) {
1116 fast = fast->fNext;
1117 if (fast != NULL) {
1118 slow = slow->fNext;
1119 fast = fast->fNext;
1120 }
1121 }
1122
1123 *pFront = v;
1124 *pBack = slow->fNext;
1125 slow->fNext->fPrev = NULL;
1126 slow->fNext = NULL;
1127 }
1128 }
1129
1130 void merge_sort(Vertex** head) {
1131 if (!*head || !(*head)->fNext) {
1132 return;
1133 }
1134
1135 Vertex* a;
1136 Vertex* b;
1137 front_back_split(*head, &a, &b);
1138
1139 merge_sort(&a);
1140 merge_sort(&b);
1141
1142 *head = sorted_merge(a, b);
1143 }
1144
1145 Vertex* sorted_merge(Vertex* a, Vertex* b) {
1146 if (!a) {
1147 return b;
1148 } else if (!b) {
1149 return a;
1150 }
1151
1152 Vertex* result = NULL;
1153
1154 if (sweep_lt(a->fPoint, b->fPoint)) {
1155 result = a;
1156 result->fNext = sorted_merge(a->fNext, b);
1157 } else {
1158 result = b;
1159 result->fNext = sorted_merge(a, b->fNext);
1160 }
1161 result->fNext->fPrev = result;
1162 return result;
1163 }
1164
1165 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
1166
1167 void simplify(Vertex* vertices, SkChunkAlloc& alloc) {
1168 LOG("simplifying complex polygons\n");
1169 Edge* activeEdges = NULL;
1170 for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1171 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1172 continue;
1173 }
1174 #if LOGGING_ENABLED
1175 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1176 #endif
1177 #ifdef SK_DEBUG
1178 validate_connectivity(v);
1179 #endif
1180 Edge* leftEnclosingEdge = NULL;
1181 Edge* rightEnclosingEdge = NULL;
1182 bool restartChecks;
1183 do {
1184 restartChecks = false;
1185 find_enclosing_edges(v, activeEdges, &leftEnclosingEdge, &rightEnclo singEdge);
1186 if (v->fFirstEdgeBelow) {
1187 for (Edge* edge = v->fFirstEdgeBelow; edge != NULL; edge = edge- >fNextEdgeBelow) {
1188 if (check_for_intersection(edge, leftEnclosingEdge, &activeE dges, alloc)) {
1189 restartChecks = true;
1190 break;
1191 }
1192 if (check_for_intersection(edge, rightEnclosingEdge, &active Edges, alloc)) {
1193 restartChecks = true;
1194 break;
1195 }
1196 }
1197 } else {
1198 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, right EnclosingEdge,
1199 &activeEdges, alloc)) {
1200 if (sweep_lt(pv->fPoint, v->fPoint)) {
1201 v = pv;
1202 }
1203 restartChecks = true;
1204 }
1205
1206 }
1207 } while (restartChecks);
1208 SkASSERT(!leftEnclosingEdge || leftEnclosingEdge->isLeftOf(v));
1209 SkASSERT(!rightEnclosingEdge || rightEnclosingEdge->isRightOf(v));
1210 #ifdef SK_DEBUG
1211 validate_edges(activeEdges);
1212 #endif
1213 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1214 remove_edge(e, &activeEdges);
1215 }
1216 Edge* leftEdge = leftEnclosingEdge;
1217 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1218 insert_edge(e, leftEdge, &activeEdges);
1219 leftEdge = e;
1220 }
1221 v->fProcessed = true;
1222 }
1223 }
1224
1225 // Stage 5: Tessellate the simplified mesh into monotone polygons.
1226
1227 Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) {
1228 LOG("tessellating simple polygons\n");
1229 Edge* activeEdges = NULL;
1230 Poly* polys = NULL;
1231 for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1232 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
1233 continue;
1234 }
1235 #if LOGGING_ENABLED
1236 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY);
1237 #endif
1238 #ifdef SK_DEBUG
1239 validate_connectivity(v);
1240 #endif
1241 Edge* leftEnclosingEdge = NULL;
1242 Edge* rightEnclosingEdge = NULL;
1243 find_enclosing_edges(v, activeEdges, &leftEnclosingEdge, &rightEnclosing Edge);
1244 SkASSERT(!leftEnclosingEdge || leftEnclosingEdge->isLeftOf(v));
1245 SkASSERT(!rightEnclosingEdge || rightEnclosingEdge->isRightOf(v));
1246 #ifdef SK_DEBUG
1247 validate_edges(activeEdges);
1248 #endif
1249 Poly* leftPoly = NULL;
1250 Poly* rightPoly = NULL;
1251 if (v->fFirstEdgeAbove) {
1252 leftPoly = v->fFirstEdgeAbove->fLeftPoly;
1253 rightPoly = v->fLastEdgeAbove->fRightPoly;
1254 } else {
1255 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : NULL;
1256 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : NUL L;
1257 }
1258 #if LOGGING_ENABLED
1259 LOG("edges above:\n");
1260 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) {
1261 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1262 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1);
1263 }
1264 LOG("edges below:\n");
1265 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) {
1266 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1267 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1);
1268 }
1269 #endif
1270 if (v->fFirstEdgeAbove) {
1271 if (leftPoly) {
1272 leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1273 }
1274 if (rightPoly) {
1275 rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1276 }
1277 for (Edge* e = v->fFirstEdgeAbove; e != v->fLastEdgeAbove; e = e->fN extEdgeAbove) {
1278 Edge* leftEdge = e;
1279 Edge* rightEdge = e->fNextEdgeAbove;
1280 SkASSERT(rightEdge->isRightOf(leftEdge->fTop));
1281 remove_edge(leftEdge, &activeEdges);
1282 if (leftEdge->fRightPoly) {
1283 leftEdge->fRightPoly->end(v, alloc);
1284 }
1285 if (rightEdge->fLeftPoly && rightEdge->fLeftPoly != leftEdge->fR ightPoly) {
1286 rightEdge->fLeftPoly->end(v, alloc);
1287 }
1288 }
1289 remove_edge(v->fLastEdgeAbove, &activeEdges);
1290 if (!v->fFirstEdgeBelow) {
1291 if (leftPoly && rightPoly && leftPoly != rightPoly) {
1292 SkASSERT(leftPoly->fPartner == NULL && rightPoly->fPartner = = NULL);
1293 rightPoly->fPartner = leftPoly;
1294 leftPoly->fPartner = rightPoly;
1295 }
1296 }
1297 }
1298 if (v->fFirstEdgeBelow) {
1299 if (!v->fFirstEdgeAbove) {
1300 if (leftPoly && leftPoly == rightPoly) {
1301 // Split the poly.
1302 if (leftPoly->fActive->fSide == Poly::kLeft_Side) {
1303 leftPoly = new_poly(&polys, leftEnclosingEdge->fTop, lef tPoly->fWinding,
1304 alloc);
1305 leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1306 rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1307 leftEnclosingEdge->fRightPoly = leftPoly;
1308 } else {
1309 rightPoly = new_poly(&polys, rightEnclosingEdge->fTop, r ightPoly->fWinding,
1310 alloc);
1311 rightPoly->addVertex(v, Poly::kLeft_Side, alloc);
1312 leftPoly->addVertex(v, Poly::kRight_Side, alloc);
1313 rightEnclosingEdge->fLeftPoly = rightPoly;
1314 }
1315 } else {
1316 if (leftPoly) {
1317 leftPoly = leftPoly->addVertex(v, Poly::kRight_Side, all oc);
1318 }
1319 if (rightPoly) {
1320 rightPoly = rightPoly->addVertex(v, Poly::kLeft_Side, al loc);
1321 }
1322 }
1323 }
1324 Edge* leftEdge = v->fFirstEdgeBelow;
1325 leftEdge->fLeftPoly = leftPoly;
1326 insert_edge(leftEdge, leftEnclosingEdge, &activeEdges);
1327 for (Edge* rightEdge = leftEdge->fNextEdgeBelow; rightEdge;
1328 rightEdge = rightEdge->fNextEdgeBelow) {
1329 insert_edge(rightEdge, leftEdge, &activeEdges);
1330 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWindin g : 0;
1331 winding += leftEdge->fWinding;
1332 if (winding != 0) {
1333 Poly* poly = new_poly(&polys, v, winding, alloc);
1334 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly;
1335 }
1336 leftEdge = rightEdge;
1337 }
1338 v->fLastEdgeBelow->fRightPoly = rightPoly;
1339 }
1340 #ifdef SK_DEBUG
1341 validate_edges(activeEdges);
1342 #endif
1343 #if LOGGING_ENABLED
1344 LOG("\nactive edges:\n");
1345 for (Edge* e = activeEdges; e != NULL; e = e->fRight) {
1346 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID,
1347 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight Poly->fID : -1);
1348 }
1349 #endif
1350 }
1351 return polys;
1352 }
1353
1354 // This is a driver function which calls stages 2-5 in turn.
1355
1356 Poly* contours_to_polys(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) {
1357 #if LOGGING_ENABLED
1358 for (int i = 0; i < contourCnt; ++i) {
1359 Vertex* v = contours[i];
1360 SkASSERT(v);
1361 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1362 for (v = v->fNext; v != contours[i]; v = v->fNext) {
1363 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY);
1364 }
1365 }
1366 #endif
1367 sanitize_contours(contours, contourCnt);
1368 Vertex* vertices = build_edges(contours, contourCnt, alloc);
1369 if (!vertices) {
1370 return NULL;
1371 }
1372
1373 // Sort vertices in Y (secondarily in X).
1374 merge_sort(&vertices);
1375 merge_coincident_vertices(&vertices, alloc);
1376 #if LOGGING_ENABLED
1377 for (Vertex* v = vertices; v != NULL; v = v->fNext) {
1378 static float gID = 0.0f;
1379 v->fID = gID++;
1380 }
1381 #endif
1382 simplify(vertices, alloc);
1383 return tessellate(vertices, alloc);
1384 }
1385
1386 // Stage 6: Triangulate the monotone polygons into a vertex buffer.
1387
1388 void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, void* data) {
1389 void* d = data;
1390 for (Poly* poly = polys; poly; poly = poly->fNext) {
1391 if (apply_fill_type(fillType, poly->fWinding)) {
1392 d = poly->emit(d);
1393 }
1394 }
1395 return d;
1396 }
1397
1398 };
1399
1400 GrTessellatingPathRenderer::GrTessellatingPathRenderer() {
1401 }
1402
1403 GrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport(
1404 const GrDrawTarget*,
1405 const GrPipelineBuil der*,
1406 const SkPath&,
1407 const SkStrokeRec&) const {
1408 return GrPathRenderer::kNoSupport_StencilSupport;
1409 }
1410
1411 bool GrTessellatingPathRenderer::canDrawPath(const GrDrawTarget* target,
1412 const GrPipelineBuilder* pipelineBu ilder,
1413 const SkMatrix& viewMatrix,
1414 const SkPath& path,
1415 const SkStrokeRec& stroke,
1416 bool antiAlias) const {
1417 // This path renderer can draw all fill styles, but does not do antialiasing . It can do convex
1418 // and concave paths, but we'll leave the convex ones to simpler algorithms.
1419 return stroke.isFillStyle() && !antiAlias && !path.isConvex();
1420 }
1421
1422 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target,
1423 GrPipelineBuilder* pipelineBuilder,
1424 GrColor color,
1425 const SkMatrix& viewM,
1426 const SkPath& path,
1427 const SkStrokeRec& stroke,
1428 bool antiAlias) {
1429 SkASSERT(!antiAlias);
1430 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
1431 if (NULL == rt) {
1432 return false;
1433 }
1434
1435 SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, viewM, path.getB ounds());
1436
1437 int contourCnt;
1438 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol);
1439 if (maxPts <= 0) {
1440 return false;
1441 }
1442 if (maxPts > ((int)SK_MaxU16 + 1)) {
1443 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1444 return false;
1445 }
1446 SkPath::FillType fillType = path.getFillType();
1447 if (SkPath::IsInverseFillType(fillType)) {
1448 contourCnt++;
1449 }
1450
1451 LOG("got %d pts, %d contours\n", maxPts, contourCnt);
1452
1453 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
1454
1455 // For the initial size of the chunk allocator, estimate based on the point count:
1456 // one vertex per point for the initial passes, plus two for the vertices in the
1457 // resulting Polys, since the same point may end up in two Polys. Assume mi nimal
1458 // connectivity of one Edge per Vertex (will grow for intersections).
1459 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
1460 SkIRect clipBoundsI;
1461 target->getClip()->getConservativeBounds(rt, &clipBoundsI);
1462 SkRect clipBounds = SkRect::Make(clipBoundsI);
1463 SkMatrix vmi;
1464 if (!viewM.invert(&vmi)) {
1465 return false;
1466 }
1467 vmi.mapRect(&clipBounds);
1468 path_to_contours(path, tol, clipBounds, contours.get(), alloc);
1469 Poly* polys;
1470 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1471 polys = contours_to_polys(contours.get(), contourCnt, alloc);
1472 SkAutoTUnref<const GrGeometryProcessor> gp(
1473 GrDefaultGeoProcFactory::Create(flags, color, viewM, SkMatrix::I()));
1474 int count = 0;
1475 for (Poly* poly = polys; poly; poly = poly->fNext) {
1476 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1477 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
1478 }
1479 }
1480
1481 int stride = gp->getVertexStride();
1482 GrDrawTarget::AutoReleaseGeometry arg;
1483 if (!arg.set(target, count, stride, 0)) {
1484 return false;
1485 }
1486 LOG("emitting %d verts\n", count);
1487 void* end = polys_to_triangles(polys, fillType, arg.vertices());
1488 int actualCount = (static_cast<char*>(end) - static_cast<char*>(arg.vertices ())) / stride;
1489 LOG("actual count: %d\n", actualCount);
1490 SkASSERT(actualCount <= count);
1491
1492 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
1493 : kTriangles_GrPrimitiveType;
1494 target->drawNonIndexed(pipelineBuilder, gp, primitiveType, 0, actualCount);
1495
1496 return true;
1497 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698