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

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

Powered by Google App Engine
This is Rietveld 408576698