OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrTessellatingPathRenderer.h" | 8 #include "GrTessellatingPathRenderer.h" |
9 | 9 |
10 #include "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
11 #include "GrBatchTest.h" | 11 #include "GrBatchTest.h" |
12 #include "GrDefaultGeoProcFactory.h" | 12 #include "GrDefaultGeoProcFactory.h" |
13 #include "GrPathUtils.h" | 13 #include "GrPathUtils.h" |
14 #include "GrVertices.h" | 14 #include "GrVertices.h" |
15 #include "GrResourceCache.h" | 15 #include "GrResourceCache.h" |
16 #include "GrResourceProvider.h" | 16 #include "GrResourceProvider.h" |
17 #include "SkChunkAlloc.h" | |
18 #include "SkGeometry.h" | 17 #include "SkGeometry.h" |
19 | 18 |
20 #include "batches/GrVertexBatch.h" | 19 #include "batches/GrVertexBatch.h" |
21 | 20 |
22 #include <stdio.h> | 21 #include <stdio.h> |
23 | 22 |
24 /* | 23 /* |
25 * This path renderer tessellates the path into triangles, uploads the triangles
to a | 24 * This path renderer tessellates the path into triangles, uploads the triangles
to a |
26 * vertex buffer, and renders them with a single draw call. It does not currentl
y do | 25 * vertex buffer, and renders them with a single draw call. It does not currentl
y do |
27 * antialiasing, so it must be used in conjunction with multisampling. | 26 * antialiasing, so it must be used in conjunction with multisampling. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 * frequent. There may be other data structures worth investigating, however. | 72 * frequent. There may be other data structures worth investigating, however. |
74 * | 73 * |
75 * Note that the orientation of the line sweep algorithms is determined by the a
spect ratio of the | 74 * Note that the orientation of the line sweep algorithms is determined by the a
spect ratio of the |
76 * path bounds. When the path is taller than it is wide, we sort vertices based
on increasing Y | 75 * path bounds. When the path is taller than it is wide, we sort vertices based
on increasing Y |
77 * coordinate, and secondarily by increasing X coordinate. When the path is wide
r than it is tall, | 76 * coordinate, and secondarily by increasing X coordinate. When the path is wide
r than it is tall, |
78 * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordin
ate. This is so | 77 * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordin
ate. This is so |
79 * that the "left" and "right" orientation in the code remains correct (edges to
the left are | 78 * that the "left" and "right" orientation in the code remains correct (edges to
the left are |
80 * increasing in Y; edges to the right are decreasing in Y). That is, the settin
g rotates 90 | 79 * increasing in Y; edges to the right are decreasing in Y). That is, the settin
g rotates 90 |
81 * degrees counterclockwise, rather that transposing. | 80 * degrees counterclockwise, rather that transposing. |
82 */ | 81 */ |
83 #define LOGGING_ENABLED 0 | |
84 #define WIREFRAME 0 | 82 #define WIREFRAME 0 |
85 | 83 |
86 #if LOGGING_ENABLED | 84 #if TESSELLATION_LOGGING_ENABLED |
87 #define LOG printf | 85 #define LOG printf |
88 #else | 86 #else |
89 #define LOG(...) | 87 #define LOG(...) |
90 #endif | 88 #endif |
91 | 89 |
92 #define ALLOC_NEW(Type, args, alloc) new (alloc.allocThrow(sizeof(Type))) Type a
rgs | 90 #define ALLOC_NEW(Type, args, alloc) new (alloc.allocThrow(sizeof(Type))) Type a
rgs |
93 | 91 |
94 namespace { | |
95 | |
96 struct Vertex; | |
97 struct Edge; | 92 struct Edge; |
98 struct Poly; | 93 struct Poly; |
99 | 94 |
100 template <class T, T* T::*Prev, T* T::*Next> | 95 template <class T, T* T::*Prev, T* T::*Next> |
101 void insert(T* t, T* prev, T* next, T** head, T** tail) { | 96 void insert(T* t, T* prev, T* next, T** head, T** tail) { |
102 t->*Prev = prev; | 97 t->*Prev = prev; |
103 t->*Next = next; | 98 t->*Next = next; |
104 if (prev) { | 99 if (prev) { |
105 prev->*Next = t; | 100 prev->*Next = t; |
106 } else if (head) { | 101 } else if (head) { |
(...skipping 14 matching lines...) Expand all Loading... |
121 *head = t->*Next; | 116 *head = t->*Next; |
122 } | 117 } |
123 if (t->*Next) { | 118 if (t->*Next) { |
124 t->*Next->*Prev = t->*Prev; | 119 t->*Next->*Prev = t->*Prev; |
125 } else if (tail) { | 120 } else if (tail) { |
126 *tail = t->*Prev; | 121 *tail = t->*Prev; |
127 } | 122 } |
128 t->*Prev = t->*Next = nullptr; | 123 t->*Prev = t->*Next = nullptr; |
129 } | 124 } |
130 | 125 |
131 /** | |
132 * Vertices are used in three ways: first, the path contours are converted into
a | |
133 * circularly-linked list of Vertices for each contour. After edge construction,
the same Vertices | |
134 * are re-ordered by the merge sort according to the sweep_lt comparator (usuall
y, increasing | |
135 * in Y) using the same fPrev/fNext pointers that were used for the contours, to
avoid | |
136 * reallocation. Finally, MonotonePolys are built containing a circularly-linked
list of | |
137 * Vertices. (Currently, those Vertices are newly-allocated for the MonotonePoly
s, since | |
138 * an individual Vertex from the path mesh may belong to multiple | |
139 * MonotonePolys, so the original Vertices cannot be re-used. | |
140 */ | |
141 | |
142 struct Vertex { | |
143 Vertex(const SkPoint& point) | |
144 : fPoint(point), fPrev(nullptr), fNext(nullptr) | |
145 , fFirstEdgeAbove(nullptr), fLastEdgeAbove(nullptr) | |
146 , fFirstEdgeBelow(nullptr), fLastEdgeBelow(nullptr) | |
147 , fProcessed(false) | |
148 #if LOGGING_ENABLED | |
149 , fID (-1.0f) | |
150 #endif | |
151 {} | |
152 SkPoint fPoint; // Vertex position | |
153 Vertex* fPrev; // Linked list of contours, then Y-sorted vertices
. | |
154 Vertex* fNext; // " | |
155 Edge* fFirstEdgeAbove; // Linked list of edges above this vertex. | |
156 Edge* fLastEdgeAbove; // " | |
157 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex. | |
158 Edge* fLastEdgeBelow; // " | |
159 bool fProcessed; // Has this vertex been seen in simplify()? | |
160 #if LOGGING_ENABLED | |
161 float fID; // Identifier used for logging. | |
162 #endif | |
163 }; | |
164 | |
165 /*******************************************************************************
********/ | 126 /*******************************************************************************
********/ |
166 | 127 |
167 typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b); | 128 typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b); |
168 | 129 |
169 struct Comparator { | 130 struct Comparator { |
170 CompareFunc sweep_lt; | 131 CompareFunc sweep_lt; |
171 CompareFunc sweep_gt; | 132 CompareFunc sweep_gt; |
172 }; | 133 }; |
173 | 134 |
174 bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) { | 135 bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) { |
175 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX; | 136 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX; |
176 } | 137 } |
177 | 138 |
178 bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) { | 139 bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) { |
179 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY; | 140 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY; |
180 } | 141 } |
181 | 142 |
182 bool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) { | 143 bool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) { |
183 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX; | 144 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX; |
184 } | 145 } |
185 | 146 |
186 bool sweep_gt_vert(const SkPoint& a, const SkPoint& b) { | 147 bool sweep_gt_vert(const SkPoint& a, const SkPoint& b) { |
187 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY; | 148 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY; |
188 } | 149 } |
189 | 150 |
190 inline SkPoint* emit_vertex(Vertex* v, SkPoint* data) { | 151 inline SkPoint* emit_vertex(TessellatingVertex* v, SkPoint* data) { |
191 *data++ = v->fPoint; | 152 *data++ = v->fPoint; |
192 return data; | 153 return data; |
193 } | 154 } |
194 | 155 |
195 SkPoint* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, SkPoint* data) { | 156 SkPoint* emit_triangle(TessellatingVertex* v0, TessellatingVertex* v1, Tessellat
ingVertex* v2, |
| 157 SkPoint* data) { |
196 #if WIREFRAME | 158 #if WIREFRAME |
197 data = emit_vertex(v0, data); | 159 data = emit_vertex(v0, data); |
198 data = emit_vertex(v1, data); | 160 data = emit_vertex(v1, data); |
199 data = emit_vertex(v1, data); | 161 data = emit_vertex(v1, data); |
200 data = emit_vertex(v2, data); | 162 data = emit_vertex(v2, data); |
201 data = emit_vertex(v2, data); | 163 data = emit_vertex(v2, data); |
202 data = emit_vertex(v0, data); | 164 data = emit_vertex(v0, data); |
203 #else | 165 #else |
204 data = emit_vertex(v0, data); | 166 data = emit_vertex(v0, data); |
205 data = emit_vertex(v1, data); | 167 data = emit_vertex(v1, data); |
(...skipping 20 matching lines...) Expand all Loading... |
226 * | 188 * |
227 * The coefficients of the line equation stored in double precision to avoid cat
astrphic | 189 * The coefficients of the line equation stored in double precision to avoid cat
astrphic |
228 * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures
that the result is | 190 * cancellation in the isLeftOf() and isRightOf() checks. Using doubles ensures
that the result is |
229 * correct in float, since it's a polynomial of degree 2. The intersect() functi
on, being | 191 * correct in float, since it's a polynomial of degree 2. The intersect() functi
on, being |
230 * degree 5, is still subject to catastrophic cancellation. We deal with that by
assuming its | 192 * degree 5, is still subject to catastrophic cancellation. We deal with that by
assuming its |
231 * output may be incorrect, and adjusting the mesh topology to match (see commen
t at the top of | 193 * output may be incorrect, and adjusting the mesh topology to match (see commen
t at the top of |
232 * this file). | 194 * this file). |
233 */ | 195 */ |
234 | 196 |
235 struct Edge { | 197 struct Edge { |
236 Edge(Vertex* top, Vertex* bottom, int winding) | 198 Edge(TessellatingVertex* top, TessellatingVertex* bottom, int winding) |
237 : fWinding(winding) | 199 : fWinding(winding) |
238 , fTop(top) | 200 , fTop(top) |
239 , fBottom(bottom) | 201 , fBottom(bottom) |
240 , fLeft(nullptr) | 202 , fLeft(nullptr) |
241 , fRight(nullptr) | 203 , fRight(nullptr) |
242 , fPrevEdgeAbove(nullptr) | 204 , fPrevEdgeAbove(nullptr) |
243 , fNextEdgeAbove(nullptr) | 205 , fNextEdgeAbove(nullptr) |
244 , fPrevEdgeBelow(nullptr) | 206 , fPrevEdgeBelow(nullptr) |
245 , fNextEdgeBelow(nullptr) | 207 , fNextEdgeBelow(nullptr) |
246 , fLeftPoly(nullptr) | 208 , fLeftPoly(nullptr) |
247 , fRightPoly(nullptr) { | 209 , fRightPoly(nullptr) { |
248 recompute(); | 210 recompute(); |
249 } | 211 } |
250 int fWinding; // 1 == edge goes downward; -1 = edge goes upwar
d. | 212 int fWinding; // 1 == edge goes downward; -1 = edge goes up
ward. |
251 Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt
). | 213 TessellatingVertex* fTop; // The top vertex in vertex-sort-order (sweep_
lt). |
252 Vertex* fBottom; // The bottom vertex in vertex-sort-order. | 214 TessellatingVertex* fBottom; // The bottom vertex in vertex-sort-order. |
253 Edge* fLeft; // The linked list of edges in the active edge l
ist. | 215 Edge* fLeft; // The linked list of edges in the active edge
list. |
254 Edge* fRight; // " | 216 Edge* fRight; // " |
255 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex
's "edges above". | 217 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vert
ex's "edges above". |
256 Edge* fNextEdgeAbove; // " | 218 Edge* fNextEdgeAbove; // " |
257 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex's
"edges below". | 219 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex'
s "edges below". |
258 Edge* fNextEdgeBelow; // " | 220 Edge* fNextEdgeBelow; // " |
259 Poly* fLeftPoly; // The Poly to the left of this edge, if any. | 221 Poly* fLeftPoly; // The Poly to the left of this edge, if any. |
260 Poly* fRightPoly; // The Poly to the right of this edge, if any. | 222 Poly* fRightPoly; // The Poly to the right of this edge, if any. |
261 double fDX; // The line equation for this edge, in implicit
form. | 223 double fDX; // The line equation for this edge, in implici
t form. |
262 double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y)
on the line. | 224 double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y
) on the line. |
263 double fC; | 225 double fC; |
264 double dist(const SkPoint& p) const { | 226 double dist(const SkPoint& p) const { |
265 return fDY * p.fX - fDX * p.fY + fC; | 227 return fDY * p.fX - fDX * p.fY + fC; |
266 } | 228 } |
267 bool isRightOf(Vertex* v) const { | 229 bool isRightOf(TessellatingVertex* v) const { |
268 return dist(v->fPoint) < 0.0; | 230 return dist(v->fPoint) < 0.0; |
269 } | 231 } |
270 bool isLeftOf(Vertex* v) const { | 232 bool isLeftOf(TessellatingVertex* v) const { |
271 return dist(v->fPoint) > 0.0; | 233 return dist(v->fPoint) > 0.0; |
272 } | 234 } |
273 void recompute() { | 235 void recompute() { |
274 fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX; | 236 fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX; |
275 fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY; | 237 fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY; |
276 fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX - | 238 fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX - |
277 static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY; | 239 static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY; |
278 } | 240 } |
279 bool intersect(const Edge& other, SkPoint* p) { | 241 bool intersect(const Edge& other, SkPoint* p) { |
280 LOG("intersecting %g -> %g with %g -> %g\n", | 242 LOG("intersecting %g -> %g with %g -> %g\n", |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 struct Poly { | 275 struct Poly { |
314 Poly(int winding) | 276 Poly(int winding) |
315 : fWinding(winding) | 277 : fWinding(winding) |
316 , fHead(nullptr) | 278 , fHead(nullptr) |
317 , fTail(nullptr) | 279 , fTail(nullptr) |
318 , fActive(nullptr) | 280 , fActive(nullptr) |
319 , fNext(nullptr) | 281 , fNext(nullptr) |
320 , fPartner(nullptr) | 282 , fPartner(nullptr) |
321 , fCount(0) | 283 , fCount(0) |
322 { | 284 { |
323 #if LOGGING_ENABLED | 285 #if TESSELLATION_LOGGING_ENABLED |
324 static int gID = 0; | 286 static int gID = 0; |
325 fID = gID++; | 287 fID = gID++; |
326 LOG("*** created Poly %d\n", fID); | 288 LOG("*** created Poly %d\n", fID); |
327 #endif | 289 #endif |
328 } | 290 } |
329 typedef enum { kNeither_Side, kLeft_Side, kRight_Side } Side; | 291 typedef enum { kNeither_Side, kLeft_Side, kRight_Side } Side; |
330 struct MonotonePoly { | 292 struct MonotonePoly { |
331 MonotonePoly() | 293 MonotonePoly() |
332 : fSide(kNeither_Side) | 294 : fSide(kNeither_Side) |
333 , fHead(nullptr) | 295 , fHead(nullptr) |
334 , fTail(nullptr) | 296 , fTail(nullptr) |
335 , fPrev(nullptr) | 297 , fPrev(nullptr) |
336 , fNext(nullptr) {} | 298 , fNext(nullptr) {} |
337 Side fSide; | 299 Side fSide; |
338 Vertex* fHead; | 300 TessellatingVertex* fHead; |
339 Vertex* fTail; | 301 TessellatingVertex* fTail; |
340 MonotonePoly* fPrev; | 302 MonotonePoly* fPrev; |
341 MonotonePoly* fNext; | 303 MonotonePoly* fNext; |
342 bool addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) { | 304 bool addVertex(TessellatingVertex* v, Side side, SkChunkAlloc& alloc) { |
343 Vertex* newV = ALLOC_NEW(Vertex, (v->fPoint), alloc); | 305 TessellatingVertex* newV = ALLOC_NEW(TessellatingVertex, (v->fPoint)
, alloc); |
344 bool done = false; | 306 bool done = false; |
345 if (fSide == kNeither_Side) { | 307 if (fSide == kNeither_Side) { |
346 fSide = side; | 308 fSide = side; |
347 } else { | 309 } else { |
348 done = side != fSide; | 310 done = side != fSide; |
349 } | 311 } |
350 if (fHead == nullptr) { | 312 if (fHead == nullptr) { |
351 fHead = fTail = newV; | 313 fHead = fTail = newV; |
352 } else if (fSide == kRight_Side) { | 314 } else if (fSide == kRight_Side) { |
353 newV->fPrev = fTail; | 315 newV->fPrev = fTail; |
354 fTail->fNext = newV; | 316 fTail->fNext = newV; |
355 fTail = newV; | 317 fTail = newV; |
356 } else { | 318 } else { |
357 newV->fNext = fHead; | 319 newV->fNext = fHead; |
358 fHead->fPrev = newV; | 320 fHead->fPrev = newV; |
359 fHead = newV; | 321 fHead = newV; |
360 } | 322 } |
361 return done; | 323 return done; |
362 } | 324 } |
363 | 325 |
364 SkPoint* emit(SkPoint* data) { | 326 SkPoint* emit(int winding, SkPoint* data) { |
365 Vertex* first = fHead; | 327 TessellatingVertex* first = fHead; |
366 Vertex* v = first->fNext; | 328 TessellatingVertex* v = first->fNext; |
367 while (v != fTail) { | 329 while (v != fTail) { |
368 SkASSERT(v && v->fPrev && v->fNext); | 330 SkASSERT(v && v->fPrev && v->fNext); |
369 Vertex* prev = v->fPrev; | 331 TessellatingVertex* prev = v->fPrev; |
370 Vertex* curr = v; | 332 TessellatingVertex* curr = v; |
371 Vertex* next = v->fNext; | 333 TessellatingVertex* next = v->fNext; |
372 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.
fX; | 334 double ax = static_cast<double>(curr->fPoint.fX) - prev->fPoint.
fX; |
373 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.
fY; | 335 double ay = static_cast<double>(curr->fPoint.fY) - prev->fPoint.
fY; |
374 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.
fX; | 336 double bx = static_cast<double>(next->fPoint.fX) - curr->fPoint.
fX; |
375 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.
fY; | 337 double by = static_cast<double>(next->fPoint.fY) - curr->fPoint.
fY; |
376 if (ax * by - ay * bx >= 0.0) { | 338 if (ax * by - ay * bx >= 0.0) { |
377 data = emit_triangle(prev, curr, next, data); | 339 data = emit_triangle(prev, curr, next, data); |
378 v->fPrev->fNext = v->fNext; | 340 v->fPrev->fNext = v->fNext; |
379 v->fNext->fPrev = v->fPrev; | 341 v->fNext->fPrev = v->fPrev; |
380 if (v->fPrev == first) { | 342 if (v->fPrev == first) { |
381 v = v->fNext; | 343 v = v->fNext; |
382 } else { | 344 } else { |
383 v = v->fPrev; | 345 v = v->fPrev; |
384 } | 346 } |
385 } else { | 347 } else { |
386 v = v->fNext; | 348 v = v->fNext; |
387 } | 349 } |
388 } | 350 } |
389 return data; | 351 return data; |
390 } | 352 } |
391 }; | 353 }; |
392 Poly* addVertex(Vertex* v, Side side, SkChunkAlloc& alloc) { | 354 Poly* addVertex(TessellatingVertex* v, Side side, SkChunkAlloc& alloc) { |
393 LOG("addVertex() to %d at %g (%g, %g), %s side\n", fID, v->fID, v->fPoin
t.fX, v->fPoint.fY, | 355 LOG("addVertex() to %d at %g (%g, %g), %s side\n", fID, v->fID, v->fPoin
t.fX, v->fPoint.fY, |
394 side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "ne
ither"); | 356 side == kLeft_Side ? "left" : side == kRight_Side ? "right" : "ne
ither"); |
395 Poly* partner = fPartner; | 357 Poly* partner = fPartner; |
396 Poly* poly = this; | 358 Poly* poly = this; |
397 if (partner) { | 359 if (partner) { |
398 fPartner = partner->fPartner = nullptr; | 360 fPartner = partner->fPartner = nullptr; |
399 } | 361 } |
400 if (!fActive) { | 362 if (!fActive) { |
401 fActive = ALLOC_NEW(MonotonePoly, (), alloc); | 363 fActive = ALLOC_NEW(MonotonePoly, (), alloc); |
402 } | 364 } |
403 if (fActive->addVertex(v, side, alloc)) { | 365 if (fActive->addVertex(v, side, alloc)) { |
404 if (fTail) { | 366 if (fTail) { |
405 fActive->fPrev = fTail; | 367 fActive->fPrev = fTail; |
406 fTail->fNext = fActive; | 368 fTail->fNext = fActive; |
407 fTail = fActive; | 369 fTail = fActive; |
408 } else { | 370 } else { |
409 fHead = fTail = fActive; | 371 fHead = fTail = fActive; |
410 } | 372 } |
411 if (partner) { | 373 if (partner) { |
412 partner->addVertex(v, side, alloc); | 374 partner->addVertex(v, side, alloc); |
413 poly = partner; | 375 poly = partner; |
414 } else { | 376 } else { |
415 Vertex* prev = fActive->fSide == Poly::kLeft_Side ? | 377 TessellatingVertex* prev = fActive->fSide == Poly::kLeft_Side ? |
416 fActive->fHead->fNext : fActive->fTail->fPrev; | 378 fActive->fHead->fNext : fActive->fTail->fPrev; |
417 fActive = ALLOC_NEW(MonotonePoly, , alloc); | 379 fActive = ALLOC_NEW(MonotonePoly, , alloc); |
418 fActive->addVertex(prev, Poly::kNeither_Side, alloc); | 380 fActive->addVertex(prev, Poly::kNeither_Side, alloc); |
419 fActive->addVertex(v, side, alloc); | 381 fActive->addVertex(v, side, alloc); |
420 } | 382 } |
421 } | 383 } |
422 fCount++; | 384 fCount++; |
423 return poly; | 385 return poly; |
424 } | 386 } |
425 void end(Vertex* v, SkChunkAlloc& alloc) { | 387 void end(TessellatingVertex* v, SkChunkAlloc& alloc) { |
426 LOG("end() %d at %g, %g\n", fID, v->fPoint.fX, v->fPoint.fY); | 388 LOG("end() %d at %g, %g\n", fID, v->fPoint.fX, v->fPoint.fY); |
427 if (fPartner) { | 389 if (fPartner) { |
428 fPartner = fPartner->fPartner = nullptr; | 390 fPartner = fPartner->fPartner = nullptr; |
429 } | 391 } |
430 addVertex(v, fActive->fSide == kLeft_Side ? kRight_Side : kLeft_Side, al
loc); | 392 addVertex(v, fActive->fSide == kLeft_Side ? kRight_Side : kLeft_Side, al
loc); |
431 } | 393 } |
432 SkPoint* emit(SkPoint *data) { | 394 SkPoint* emit(SkPoint *data) { |
433 if (fCount < 3) { | 395 if (fCount < 3) { |
434 return data; | 396 return data; |
435 } | 397 } |
436 LOG("emit() %d, size %d\n", fID, fCount); | 398 LOG("emit() %d, size %d\n", fID, fCount); |
437 for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) { | 399 for (MonotonePoly* m = fHead; m != nullptr; m = m->fNext) { |
438 data = m->emit(data); | 400 data = m->emit(fWinding, data); |
439 } | 401 } |
440 return data; | 402 return data; |
441 } | 403 } |
442 int fWinding; | 404 int fWinding; |
443 MonotonePoly* fHead; | 405 MonotonePoly* fHead; |
444 MonotonePoly* fTail; | 406 MonotonePoly* fTail; |
445 MonotonePoly* fActive; | 407 MonotonePoly* fActive; |
446 Poly* fNext; | 408 Poly* fNext; |
447 Poly* fPartner; | 409 Poly* fPartner; |
448 int fCount; | 410 int fCount; |
449 #if LOGGING_ENABLED | 411 #if TESSELLATION_LOGGING_ENABLED |
450 int fID; | 412 int fID; |
451 #endif | 413 #endif |
452 }; | 414 }; |
453 | 415 |
454 /*******************************************************************************
********/ | 416 /*******************************************************************************
********/ |
455 | 417 |
456 bool coincident(const SkPoint& a, const SkPoint& b) { | 418 bool coincident(const SkPoint& a, const SkPoint& b) { |
457 return a == b; | 419 return a == b; |
458 } | 420 } |
459 | 421 |
460 Poly* new_poly(Poly** head, Vertex* v, int winding, SkChunkAlloc& alloc) { | 422 Poly* new_poly(Poly** head, TessellatingVertex* v, int winding, SkChunkAlloc& al
loc) { |
461 Poly* poly = ALLOC_NEW(Poly, (winding), alloc); | 423 Poly* poly = ALLOC_NEW(Poly, (winding), alloc); |
462 poly->addVertex(v, Poly::kNeither_Side, alloc); | 424 poly->addVertex(v, Poly::kNeither_Side, alloc); |
463 poly->fNext = *head; | 425 poly->fNext = *head; |
464 *head = poly; | 426 *head = poly; |
465 return poly; | 427 return poly; |
466 } | 428 } |
467 | 429 |
468 Vertex* append_point_to_contour(const SkPoint& p, Vertex* prev, Vertex** head, | 430 TessellatingVertex* append_point_to_contour(const SkPoint& p, TessellatingVertex
* prev, |
469 SkChunkAlloc& alloc) { | 431 TessellatingVertex** head, SkChunkAl
loc& alloc) { |
470 Vertex* v = ALLOC_NEW(Vertex, (p), alloc); | 432 TessellatingVertex* v = ALLOC_NEW(TessellatingVertex, (p), alloc); |
471 #if LOGGING_ENABLED | 433 #if TESSELLATION_LOGGING_ENABLED |
472 static float gID = 0.0f; | 434 static float gID = 0.0f; |
473 v->fID = gID++; | 435 v->fID = gID++; |
474 #endif | 436 #endif |
475 if (prev) { | 437 if (prev) { |
476 prev->fNext = v; | 438 prev->fNext = v; |
477 v->fPrev = prev; | 439 v->fPrev = prev; |
478 } else { | 440 } else { |
479 *head = v; | 441 *head = v; |
480 } | 442 } |
481 return v; | 443 return v; |
482 } | 444 } |
483 | 445 |
484 Vertex* generate_quadratic_points(const SkPoint& p0, | 446 TessellatingVertex* generate_quadratic_points(const SkPoint& p0, |
485 const SkPoint& p1, | 447 const SkPoint& p1, |
486 const SkPoint& p2, | 448 const SkPoint& p2, |
487 SkScalar tolSqd, | 449 SkScalar tolSqd, |
488 Vertex* prev, | 450 TessellatingVertex* prev, |
489 Vertex** head, | 451 TessellatingVertex** head, |
490 int pointsLeft, | 452 int pointsLeft, |
491 SkChunkAlloc& alloc) { | 453 SkChunkAlloc& alloc) { |
492 SkScalar d = p1.distanceToLineSegmentBetweenSqd(p0, p2); | 454 SkScalar d = p1.distanceToLineSegmentBetweenSqd(p0, p2); |
493 if (pointsLeft < 2 || d < tolSqd || !SkScalarIsFinite(d)) { | 455 if (pointsLeft < 2 || d < tolSqd || !SkScalarIsFinite(d)) { |
494 return append_point_to_contour(p2, prev, head, alloc); | 456 return append_point_to_contour(p2, prev, head, alloc); |
495 } | 457 } |
496 | 458 |
497 const SkPoint q[] = { | 459 const SkPoint q[] = { |
498 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) }, | 460 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) }, |
499 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) }, | 461 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) }, |
500 }; | 462 }; |
501 const SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1]
.fY) }; | 463 const SkPoint r = { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1]
.fY) }; |
502 | 464 |
503 pointsLeft >>= 1; | 465 pointsLeft >>= 1; |
504 prev = generate_quadratic_points(p0, q[0], r, tolSqd, prev, head, pointsLeft
, alloc); | 466 prev = generate_quadratic_points(p0, q[0], r, tolSqd, prev, head, pointsLeft
, alloc); |
505 prev = generate_quadratic_points(r, q[1], p2, tolSqd, prev, head, pointsLeft
, alloc); | 467 prev = generate_quadratic_points(r, q[1], p2, tolSqd, prev, head, pointsLeft
, alloc); |
506 return prev; | 468 return prev; |
507 } | 469 } |
508 | 470 |
509 Vertex* generate_cubic_points(const SkPoint& p0, | 471 TessellatingVertex* generate_cubic_points(const SkPoint& p0, |
510 const SkPoint& p1, | 472 const SkPoint& p1, |
511 const SkPoint& p2, | 473 const SkPoint& p2, |
512 const SkPoint& p3, | 474 const SkPoint& p3, |
513 SkScalar tolSqd, | 475 SkScalar tolSqd, |
514 Vertex* prev, | 476 TessellatingVertex* prev, |
515 Vertex** head, | 477 TessellatingVertex** head, |
516 int pointsLeft, | 478 int pointsLeft, |
517 SkChunkAlloc& alloc) { | 479 SkChunkAlloc& alloc) { |
518 SkScalar d1 = p1.distanceToLineSegmentBetweenSqd(p0, p3); | 480 SkScalar d1 = p1.distanceToLineSegmentBetweenSqd(p0, p3); |
519 SkScalar d2 = p2.distanceToLineSegmentBetweenSqd(p0, p3); | 481 SkScalar d2 = p2.distanceToLineSegmentBetweenSqd(p0, p3); |
520 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) || | 482 if (pointsLeft < 2 || (d1 < tolSqd && d2 < tolSqd) || |
521 !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) { | 483 !SkScalarIsFinite(d1) || !SkScalarIsFinite(d2)) { |
522 return append_point_to_contour(p3, prev, head, alloc); | 484 return append_point_to_contour(p3, prev, head, alloc); |
523 } | 485 } |
524 const SkPoint q[] = { | 486 const SkPoint q[] = { |
525 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) }, | 487 { SkScalarAve(p0.fX, p1.fX), SkScalarAve(p0.fY, p1.fY) }, |
526 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) }, | 488 { SkScalarAve(p1.fX, p2.fX), SkScalarAve(p1.fY, p2.fY) }, |
527 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) } | 489 { SkScalarAve(p2.fX, p3.fX), SkScalarAve(p2.fY, p3.fY) } |
528 }; | 490 }; |
529 const SkPoint r[] = { | 491 const SkPoint r[] = { |
530 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) }, | 492 { SkScalarAve(q[0].fX, q[1].fX), SkScalarAve(q[0].fY, q[1].fY) }, |
531 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) } | 493 { SkScalarAve(q[1].fX, q[2].fX), SkScalarAve(q[1].fY, q[2].fY) } |
532 }; | 494 }; |
533 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1]
.fY) }; | 495 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1]
.fY) }; |
534 pointsLeft >>= 1; | 496 pointsLeft >>= 1; |
535 prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLe
ft, alloc); | 497 prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLe
ft, alloc); |
536 prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLe
ft, alloc); | 498 prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLe
ft, alloc); |
537 return prev; | 499 return prev; |
538 } | 500 } |
539 | 501 |
540 // Stage 1: convert the input path to a set of linear contours (linked list of V
ertices). | 502 // Stage 1: convert the input path to a set of linear contours (linked list of V
ertices). |
541 | 503 |
542 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
Bounds, | 504 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
Bounds, |
543 Vertex** contours, SkChunkAlloc& alloc, bool *isLinear) { | 505 TessellatingVertex** contours, SkChunkAlloc& alloc, bool *
isLinear) { |
544 | 506 |
545 SkScalar toleranceSqd = tolerance * tolerance; | 507 SkScalar toleranceSqd = tolerance * tolerance; |
546 | 508 |
547 SkPoint pts[4]; | 509 SkPoint pts[4]; |
548 bool done = false; | 510 bool done = false; |
549 *isLinear = true; | 511 *isLinear = true; |
550 SkPath::Iter iter(path, false); | 512 SkPath::Iter iter(path, false); |
551 Vertex* prev = nullptr; | 513 TessellatingVertex* prev = nullptr; |
552 Vertex* head = nullptr; | 514 TessellatingVertex* head = nullptr; |
553 if (path.isInverseFillType()) { | 515 if (path.isInverseFillType()) { |
554 SkPoint quad[4]; | 516 SkPoint quad[4]; |
555 clipBounds.toQuad(quad); | 517 clipBounds.toQuad(quad); |
556 for (int i = 3; i >= 0; i--) { | 518 for (int i = 3; i >= 0; i--) { |
557 prev = append_point_to_contour(quad[i], prev, &head, alloc); | 519 prev = append_point_to_contour(quad[i], prev, &head, alloc); |
558 } | 520 } |
559 head->fPrev = prev; | 521 head->fPrev = prev; |
560 prev->fNext = head; | 522 prev->fNext = head; |
561 *contours++ = head; | 523 *contours++ = head; |
562 head = prev = nullptr; | 524 head = prev = nullptr; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 case SkPath::kInverseWinding_FillType: | 595 case SkPath::kInverseWinding_FillType: |
634 return winding == 1; | 596 return winding == 1; |
635 case SkPath::kInverseEvenOdd_FillType: | 597 case SkPath::kInverseEvenOdd_FillType: |
636 return (winding & 1) == 1; | 598 return (winding & 1) == 1; |
637 default: | 599 default: |
638 SkASSERT(false); | 600 SkASSERT(false); |
639 return false; | 601 return false; |
640 } | 602 } |
641 } | 603 } |
642 | 604 |
643 Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c) { | 605 Edge* new_edge(TessellatingVertex* prev, TessellatingVertex* next, SkChunkAlloc&
alloc, |
| 606 Comparator& c) { |
644 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1; | 607 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1; |
645 Vertex* top = winding < 0 ? next : prev; | 608 TessellatingVertex* top = winding < 0 ? next : prev; |
646 Vertex* bottom = winding < 0 ? prev : next; | 609 TessellatingVertex* bottom = winding < 0 ? prev : next; |
647 return ALLOC_NEW(Edge, (top, bottom, winding), alloc); | 610 return ALLOC_NEW(Edge, (top, bottom, winding), alloc); |
648 } | 611 } |
649 | 612 |
650 void remove_edge(Edge* edge, EdgeList* edges) { | 613 void remove_edge(Edge* edge, EdgeList* edges) { |
651 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); | 614 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); |
652 SkASSERT(edge->isActive(edges)); | 615 SkASSERT(edge->isActive(edges)); |
653 remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &edges->fHead, &edges->fTail
); | 616 remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, &edges->fHead, &edges->fTail
); |
654 } | 617 } |
655 | 618 |
656 void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) { | 619 void insert_edge(Edge* edge, Edge* prev, EdgeList* edges) { |
657 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); | 620 LOG("inserting edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); |
658 SkASSERT(!edge->isActive(edges)); | 621 SkASSERT(!edge->isActive(edges)); |
659 Edge* next = prev ? prev->fRight : edges->fHead; | 622 Edge* next = prev ? prev->fRight : edges->fHead; |
660 insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &edges->fHead, &
edges->fTail); | 623 insert<Edge, &Edge::fLeft, &Edge::fRight>(edge, prev, next, &edges->fHead, &
edges->fTail); |
661 } | 624 } |
662 | 625 |
663 void find_enclosing_edges(Vertex* v, EdgeList* edges, Edge** left, Edge** right)
{ | 626 void find_enclosing_edges(TessellatingVertex* v, EdgeList* edges, Edge** left, E
dge** right) { |
664 if (v->fFirstEdgeAbove) { | 627 if (v->fFirstEdgeAbove) { |
665 *left = v->fFirstEdgeAbove->fLeft; | 628 *left = v->fFirstEdgeAbove->fLeft; |
666 *right = v->fLastEdgeAbove->fRight; | 629 *right = v->fLastEdgeAbove->fRight; |
667 return; | 630 return; |
668 } | 631 } |
669 Edge* next = nullptr; | 632 Edge* next = nullptr; |
670 Edge* prev; | 633 Edge* prev; |
671 for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) { | 634 for (prev = edges->fTail; prev != nullptr; prev = prev->fLeft) { |
672 if (prev->isLeftOf(v)) { | 635 if (prev->isLeftOf(v)) { |
673 break; | 636 break; |
(...skipping 30 matching lines...) Expand all Loading... |
704 remove_edge(edge, activeEdges); | 667 remove_edge(edge, activeEdges); |
705 } | 668 } |
706 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) { | 669 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) { |
707 Edge* left; | 670 Edge* left; |
708 Edge* right; | 671 Edge* right; |
709 find_enclosing_edges(edge, activeEdges, c, &left, &right); | 672 find_enclosing_edges(edge, activeEdges, c, &left, &right); |
710 insert_edge(edge, left, activeEdges); | 673 insert_edge(edge, left, activeEdges); |
711 } | 674 } |
712 } | 675 } |
713 | 676 |
714 void insert_edge_above(Edge* edge, Vertex* v, Comparator& c) { | 677 void insert_edge_above(Edge* edge, TessellatingVertex* v, Comparator& c) { |
715 if (edge->fTop->fPoint == edge->fBottom->fPoint || | 678 if (edge->fTop->fPoint == edge->fBottom->fPoint || |
716 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { | 679 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { |
717 return; | 680 return; |
718 } | 681 } |
719 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); | 682 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); |
720 Edge* prev = nullptr; | 683 Edge* prev = nullptr; |
721 Edge* next; | 684 Edge* next; |
722 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) { | 685 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) { |
723 if (next->isRightOf(edge->fTop)) { | 686 if (next->isRightOf(edge->fTop)) { |
724 break; | 687 break; |
725 } | 688 } |
726 prev = next; | 689 prev = next; |
727 } | 690 } |
728 insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>( | 691 insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>( |
729 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove); | 692 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove); |
730 } | 693 } |
731 | 694 |
732 void insert_edge_below(Edge* edge, Vertex* v, Comparator& c) { | 695 void insert_edge_below(Edge* edge, TessellatingVertex* v, Comparator& c) { |
733 if (edge->fTop->fPoint == edge->fBottom->fPoint || | 696 if (edge->fTop->fPoint == edge->fBottom->fPoint || |
734 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { | 697 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { |
735 return; | 698 return; |
736 } | 699 } |
737 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); | 700 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); |
738 Edge* prev = nullptr; | 701 Edge* prev = nullptr; |
739 Edge* next; | 702 Edge* next; |
740 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) { | 703 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) { |
741 if (next->isRightOf(edge->fBottom)) { | 704 if (next->isRightOf(edge->fBottom)) { |
742 break; | 705 break; |
(...skipping 25 matching lines...) Expand all Loading... |
768 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID); | 731 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID); |
769 remove_edge_above(edge); | 732 remove_edge_above(edge); |
770 remove_edge_below(edge); | 733 remove_edge_below(edge); |
771 if (edge->isActive(edges)) { | 734 if (edge->isActive(edges)) { |
772 remove_edge(edge, edges); | 735 remove_edge(edge, edges); |
773 } | 736 } |
774 } | 737 } |
775 | 738 |
776 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c); | 739 void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Comparator& c); |
777 | 740 |
778 void set_top(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) { | 741 void set_top(Edge* edge, TessellatingVertex* v, EdgeList* activeEdges, Comparato
r& c) { |
779 remove_edge_below(edge); | 742 remove_edge_below(edge); |
780 edge->fTop = v; | 743 edge->fTop = v; |
781 edge->recompute(); | 744 edge->recompute(); |
782 insert_edge_below(edge, v, c); | 745 insert_edge_below(edge, v, c); |
783 fix_active_state(edge, activeEdges, c); | 746 fix_active_state(edge, activeEdges, c); |
784 merge_collinear_edges(edge, activeEdges, c); | 747 merge_collinear_edges(edge, activeEdges, c); |
785 } | 748 } |
786 | 749 |
787 void set_bottom(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c) { | 750 void set_bottom(Edge* edge, TessellatingVertex* v, EdgeList* activeEdges, Compar
ator& c) { |
788 remove_edge_above(edge); | 751 remove_edge_above(edge); |
789 edge->fBottom = v; | 752 edge->fBottom = v; |
790 edge->recompute(); | 753 edge->recompute(); |
791 insert_edge_above(edge, v, c); | 754 insert_edge_above(edge, v, c); |
792 fix_active_state(edge, activeEdges, c); | 755 fix_active_state(edge, activeEdges, c); |
793 merge_collinear_edges(edge, activeEdges, c); | 756 merge_collinear_edges(edge, activeEdges, c); |
794 } | 757 } |
795 | 758 |
796 void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Comparato
r& c) { | 759 void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Comparato
r& c) { |
797 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) { | 760 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 } | 806 } |
844 if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom
|| | 807 if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom
|| |
845 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))
) { | 808 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))
) { |
846 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, c); | 809 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, c); |
847 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->f
Bottom || | 810 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->f
Bottom || |
848 !edge->isLeftOf(edge->fNextEdgeBelow->fB
ottom))) { | 811 !edge->isLeftOf(edge->fNextEdgeBelow->fB
ottom))) { |
849 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, c); | 812 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, c); |
850 } | 813 } |
851 } | 814 } |
852 | 815 |
853 void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkC
hunkAlloc& alloc); | 816 void split_edge(Edge* edge, TessellatingVertex* v, EdgeList* activeEdges, Compar
ator& c, |
| 817 SkChunkAlloc& alloc); |
854 | 818 |
855 void cleanup_active_edges(Edge* edge, EdgeList* activeEdges, Comparator& c, SkCh
unkAlloc& alloc) { | 819 void cleanup_active_edges(Edge* edge, EdgeList* activeEdges, Comparator& c, SkCh
unkAlloc& alloc) { |
856 Vertex* top = edge->fTop; | 820 TessellatingVertex* top = edge->fTop; |
857 Vertex* bottom = edge->fBottom; | 821 TessellatingVertex* bottom = edge->fBottom; |
858 if (edge->fLeft) { | 822 if (edge->fLeft) { |
859 Vertex* leftTop = edge->fLeft->fTop; | 823 TessellatingVertex* leftTop = edge->fLeft->fTop; |
860 Vertex* leftBottom = edge->fLeft->fBottom; | 824 TessellatingVertex* leftBottom = edge->fLeft->fBottom; |
861 if (c.sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(t
op)) { | 825 if (c.sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(t
op)) { |
862 split_edge(edge->fLeft, edge->fTop, activeEdges, c, alloc); | 826 split_edge(edge->fLeft, edge->fTop, activeEdges, c, alloc); |
863 } else if (c.sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(
leftTop)) { | 827 } else if (c.sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(
leftTop)) { |
864 split_edge(edge, leftTop, activeEdges, c, alloc); | 828 split_edge(edge, leftTop, activeEdges, c, alloc); |
865 } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) && | 829 } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) && |
866 !edge->fLeft->isLeftOf(bottom)) { | 830 !edge->fLeft->isLeftOf(bottom)) { |
867 split_edge(edge->fLeft, bottom, activeEdges, c, alloc); | 831 split_edge(edge->fLeft, bottom, activeEdges, c, alloc); |
868 } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRi
ghtOf(leftBottom)) { | 832 } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRi
ghtOf(leftBottom)) { |
869 split_edge(edge, leftBottom, activeEdges, c, alloc); | 833 split_edge(edge, leftBottom, activeEdges, c, alloc); |
870 } | 834 } |
871 } | 835 } |
872 if (edge->fRight) { | 836 if (edge->fRight) { |
873 Vertex* rightTop = edge->fRight->fTop; | 837 TessellatingVertex* rightTop = edge->fRight->fTop; |
874 Vertex* rightBottom = edge->fRight->fBottom; | 838 TessellatingVertex* rightBottom = edge->fRight->fBottom; |
875 if (c.sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightO
f(top)) { | 839 if (c.sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightO
f(top)) { |
876 split_edge(edge->fRight, top, activeEdges, c, alloc); | 840 split_edge(edge->fRight, top, activeEdges, c, alloc); |
877 } else if (c.sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(
rightTop)) { | 841 } else if (c.sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(
rightTop)) { |
878 split_edge(edge, rightTop, activeEdges, c, alloc); | 842 split_edge(edge, rightTop, activeEdges, c, alloc); |
879 } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) && | 843 } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) && |
880 !edge->fRight->isRightOf(bottom)) { | 844 !edge->fRight->isRightOf(bottom)) { |
881 split_edge(edge->fRight, bottom, activeEdges, c, alloc); | 845 split_edge(edge->fRight, bottom, activeEdges, c, alloc); |
882 } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) && | 846 } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) && |
883 !edge->isLeftOf(rightBottom)) { | 847 !edge->isLeftOf(rightBottom)) { |
884 split_edge(edge, rightBottom, activeEdges, c, alloc); | 848 split_edge(edge, rightBottom, activeEdges, c, alloc); |
885 } | 849 } |
886 } | 850 } |
887 } | 851 } |
888 | 852 |
889 void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Comparator& c, SkC
hunkAlloc& alloc) { | 853 void split_edge(Edge* edge, TessellatingVertex* v, EdgeList* activeEdges, Compar
ator& c, |
| 854 SkChunkAlloc& alloc) { |
890 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n", | 855 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n", |
891 edge->fTop->fID, edge->fBottom->fID, | 856 edge->fTop->fID, edge->fBottom->fID, |
892 v->fID, v->fPoint.fX, v->fPoint.fY); | 857 v->fID, v->fPoint.fX, v->fPoint.fY); |
893 if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) { | 858 if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) { |
894 set_top(edge, v, activeEdges, c); | 859 set_top(edge, v, activeEdges, c); |
895 } else if (c.sweep_gt(v->fPoint, edge->fBottom->fPoint)) { | 860 } else if (c.sweep_gt(v->fPoint, edge->fBottom->fPoint)) { |
896 set_bottom(edge, v, activeEdges, c); | 861 set_bottom(edge, v, activeEdges, c); |
897 } else { | 862 } else { |
898 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), allo
c); | 863 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), allo
c); |
899 insert_edge_below(newEdge, v, c); | 864 insert_edge_below(newEdge, v, c); |
900 insert_edge_above(newEdge, edge->fBottom, c); | 865 insert_edge_above(newEdge, edge->fBottom, c); |
901 set_bottom(edge, v, activeEdges, c); | 866 set_bottom(edge, v, activeEdges, c); |
902 cleanup_active_edges(edge, activeEdges, c, alloc); | 867 cleanup_active_edges(edge, activeEdges, c, alloc); |
903 fix_active_state(newEdge, activeEdges, c); | 868 fix_active_state(newEdge, activeEdges, c); |
904 merge_collinear_edges(newEdge, activeEdges, c); | 869 merge_collinear_edges(newEdge, activeEdges, c); |
905 } | 870 } |
906 } | 871 } |
907 | 872 |
908 void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkCh
unkAlloc& alloc) { | 873 void merge_vertices(TessellatingVertex* src, TessellatingVertex* dst, Tessellati
ngVertex** head, |
| 874 Comparator& c, SkChunkAlloc& alloc) { |
909 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX
, src->fPoint.fY, | 875 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX
, src->fPoint.fY, |
910 src->fID, dst->fID); | 876 src->fID, dst->fID); |
911 for (Edge* edge = src->fFirstEdgeAbove; edge;) { | 877 for (Edge* edge = src->fFirstEdgeAbove; edge;) { |
912 Edge* next = edge->fNextEdgeAbove; | 878 Edge* next = edge->fNextEdgeAbove; |
913 set_bottom(edge, dst, nullptr, c); | 879 set_bottom(edge, dst, nullptr, c); |
914 edge = next; | 880 edge = next; |
915 } | 881 } |
916 for (Edge* edge = src->fFirstEdgeBelow; edge;) { | 882 for (Edge* edge = src->fFirstEdgeBelow; edge;) { |
917 Edge* next = edge->fNextEdgeBelow; | 883 Edge* next = edge->fNextEdgeBelow; |
918 set_top(edge, dst, nullptr, c); | 884 set_top(edge, dst, nullptr, c); |
919 edge = next; | 885 edge = next; |
920 } | 886 } |
921 remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, nullptr); | 887 remove<TessellatingVertex, &TessellatingVertex::fPrev, &TessellatingVertex::
fNext>(src, head, |
| 888
nullptr); |
922 } | 889 } |
923 | 890 |
924 Vertex* check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, C
omparator& c, | 891 TessellatingVertex* check_for_intersection(Edge* edge, Edge* other, EdgeList* ac
tiveEdges, |
925 SkChunkAlloc& alloc) { | 892 Comparator& c, SkChunkAlloc& alloc) { |
926 SkPoint p; | 893 SkPoint p; |
927 if (!edge || !other) { | 894 if (!edge || !other) { |
928 return nullptr; | 895 return nullptr; |
929 } | 896 } |
930 if (edge->intersect(*other, &p)) { | 897 if (edge->intersect(*other, &p)) { |
931 Vertex* v; | 898 TessellatingVertex* v; |
932 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY); | 899 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY); |
933 if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) { | 900 if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) { |
934 split_edge(other, edge->fTop, activeEdges, c, alloc); | 901 split_edge(other, edge->fTop, activeEdges, c, alloc); |
935 v = edge->fTop; | 902 v = edge->fTop; |
936 } else if (p == edge->fBottom->fPoint || c.sweep_gt(p, edge->fBottom->fP
oint)) { | 903 } else if (p == edge->fBottom->fPoint || c.sweep_gt(p, edge->fBottom->fP
oint)) { |
937 split_edge(other, edge->fBottom, activeEdges, c, alloc); | 904 split_edge(other, edge->fBottom, activeEdges, c, alloc); |
938 v = edge->fBottom; | 905 v = edge->fBottom; |
939 } else if (p == other->fTop->fPoint || c.sweep_lt(p, other->fTop->fPoint
)) { | 906 } else if (p == other->fTop->fPoint || c.sweep_lt(p, other->fTop->fPoint
)) { |
940 split_edge(edge, other->fTop, activeEdges, c, alloc); | 907 split_edge(edge, other->fTop, activeEdges, c, alloc); |
941 v = other->fTop; | 908 v = other->fTop; |
942 } else if (p == other->fBottom->fPoint || c.sweep_gt(p, other->fBottom->
fPoint)) { | 909 } else if (p == other->fBottom->fPoint || c.sweep_gt(p, other->fBottom->
fPoint)) { |
943 split_edge(edge, other->fBottom, activeEdges, c, alloc); | 910 split_edge(edge, other->fBottom, activeEdges, c, alloc); |
944 v = other->fBottom; | 911 v = other->fBottom; |
945 } else { | 912 } else { |
946 Vertex* nextV = edge->fTop; | 913 TessellatingVertex* nextV = edge->fTop; |
947 while (c.sweep_lt(p, nextV->fPoint)) { | 914 while (c.sweep_lt(p, nextV->fPoint)) { |
948 nextV = nextV->fPrev; | 915 nextV = nextV->fPrev; |
949 } | 916 } |
950 while (c.sweep_lt(nextV->fPoint, p)) { | 917 while (c.sweep_lt(nextV->fPoint, p)) { |
951 nextV = nextV->fNext; | 918 nextV = nextV->fNext; |
952 } | 919 } |
953 Vertex* prevV = nextV->fPrev; | 920 TessellatingVertex* prevV = nextV->fPrev; |
954 if (coincident(prevV->fPoint, p)) { | 921 if (coincident(prevV->fPoint, p)) { |
955 v = prevV; | 922 v = prevV; |
956 } else if (coincident(nextV->fPoint, p)) { | 923 } else if (coincident(nextV->fPoint, p)) { |
957 v = nextV; | 924 v = nextV; |
958 } else { | 925 } else { |
959 v = ALLOC_NEW(Vertex, (p), alloc); | 926 v = ALLOC_NEW(TessellatingVertex, (p), alloc); |
960 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n", | 927 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n", |
961 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY, | 928 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY, |
962 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY); | 929 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY); |
963 #if LOGGING_ENABLED | 930 #if TESSELLATION_LOGGING_ENABLED |
964 v->fID = (nextV->fID + prevV->fID) * 0.5f; | 931 v->fID = (nextV->fID + prevV->fID) * 0.5f; |
965 #endif | 932 #endif |
966 v->fPrev = prevV; | 933 v->fPrev = prevV; |
967 v->fNext = nextV; | 934 v->fNext = nextV; |
968 prevV->fNext = v; | 935 prevV->fNext = v; |
969 nextV->fPrev = v; | 936 nextV->fPrev = v; |
970 } | 937 } |
971 split_edge(edge, v, activeEdges, c, alloc); | 938 split_edge(edge, v, activeEdges, c, alloc); |
972 split_edge(other, v, activeEdges, c, alloc); | 939 split_edge(other, v, activeEdges, c, alloc); |
973 } | 940 } |
974 return v; | 941 return v; |
975 } | 942 } |
976 return nullptr; | 943 return nullptr; |
977 } | 944 } |
978 | 945 |
979 void sanitize_contours(Vertex** contours, int contourCnt) { | 946 void sanitize_contours(TessellatingVertex** contours, int contourCnt) { |
980 for (int i = 0; i < contourCnt; ++i) { | 947 for (int i = 0; i < contourCnt; ++i) { |
981 SkASSERT(contours[i]); | 948 SkASSERT(contours[i]); |
982 for (Vertex* v = contours[i];;) { | 949 for (TessellatingVertex* v = contours[i];;) { |
983 if (coincident(v->fPrev->fPoint, v->fPoint)) { | 950 if (coincident(v->fPrev->fPoint, v->fPoint)) { |
984 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoi
nt.fY); | 951 LOG("vertex %g,%g coincident; removing\n", v->fPoint.fX, v->fPoi
nt.fY); |
985 if (v->fPrev == v) { | 952 if (v->fPrev == v) { |
986 contours[i] = nullptr; | 953 contours[i] = nullptr; |
987 break; | 954 break; |
988 } | 955 } |
989 v->fPrev->fNext = v->fNext; | 956 v->fPrev->fNext = v->fNext; |
990 v->fNext->fPrev = v->fPrev; | 957 v->fNext->fPrev = v->fPrev; |
991 if (contours[i] == v) { | 958 if (contours[i] == v) { |
992 contours[i] = v->fNext; | 959 contours[i] = v->fNext; |
993 } | 960 } |
994 v = v->fPrev; | 961 v = v->fPrev; |
995 } else { | 962 } else { |
996 v = v->fNext; | 963 v = v->fNext; |
997 if (v == contours[i]) break; | 964 if (v == contours[i]) break; |
998 } | 965 } |
999 } | 966 } |
1000 } | 967 } |
1001 } | 968 } |
1002 | 969 |
1003 void merge_coincident_vertices(Vertex** vertices, Comparator& c, SkChunkAlloc& a
lloc) { | 970 void merge_coincident_vertices(TessellatingVertex** vertices, Comparator& c, SkC
hunkAlloc& alloc) { |
1004 for (Vertex* v = (*vertices)->fNext; v != nullptr; v = v->fNext) { | 971 for (TessellatingVertex* v = (*vertices)->fNext; v != nullptr; v = v->fNext)
{ |
1005 if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) { | 972 if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) { |
1006 v->fPoint = v->fPrev->fPoint; | 973 v->fPoint = v->fPrev->fPoint; |
1007 } | 974 } |
1008 if (coincident(v->fPrev->fPoint, v->fPoint)) { | 975 if (coincident(v->fPrev->fPoint, v->fPoint)) { |
1009 merge_vertices(v->fPrev, v, vertices, c, alloc); | 976 merge_vertices(v->fPrev, v, vertices, c, alloc); |
1010 } | 977 } |
1011 } | 978 } |
1012 } | 979 } |
1013 | 980 |
1014 // Stage 2: convert the contours to a mesh of edges connecting the vertices. | 981 // Stage 2: convert the contours to a mesh of edges connecting the vertices. |
1015 | 982 |
1016 Vertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAll
oc& alloc) { | 983 TessellatingVertex* build_edges(TessellatingVertex** contours, int contourCnt, C
omparator& c, |
1017 Vertex* vertices = nullptr; | 984 SkChunkAlloc& alloc) { |
1018 Vertex* prev = nullptr; | 985 TessellatingVertex* vertices = nullptr; |
| 986 TessellatingVertex* prev = nullptr; |
1019 for (int i = 0; i < contourCnt; ++i) { | 987 for (int i = 0; i < contourCnt; ++i) { |
1020 for (Vertex* v = contours[i]; v != nullptr;) { | 988 for (TessellatingVertex* v = contours[i]; v != nullptr;) { |
1021 Vertex* vNext = v->fNext; | 989 TessellatingVertex* vNext = v->fNext; |
1022 Edge* edge = new_edge(v->fPrev, v, alloc, c); | 990 Edge* edge = new_edge(v->fPrev, v, alloc, c); |
1023 if (edge->fWinding > 0) { | 991 if (edge->fWinding > 0) { |
1024 insert_edge_below(edge, v->fPrev, c); | 992 insert_edge_below(edge, v->fPrev, c); |
1025 insert_edge_above(edge, v, c); | 993 insert_edge_above(edge, v, c); |
1026 } else { | 994 } else { |
1027 insert_edge_below(edge, v, c); | 995 insert_edge_below(edge, v, c); |
1028 insert_edge_above(edge, v->fPrev, c); | 996 insert_edge_above(edge, v->fPrev, c); |
1029 } | 997 } |
1030 merge_collinear_edges(edge, nullptr, c); | 998 merge_collinear_edges(edge, nullptr, c); |
1031 if (prev) { | 999 if (prev) { |
1032 prev->fNext = v; | 1000 prev->fNext = v; |
1033 v->fPrev = prev; | 1001 v->fPrev = prev; |
1034 } else { | 1002 } else { |
1035 vertices = v; | 1003 vertices = v; |
1036 } | 1004 } |
1037 prev = v; | 1005 prev = v; |
1038 v = vNext; | 1006 v = vNext; |
1039 if (v == contours[i]) break; | 1007 if (v == contours[i]) break; |
1040 } | 1008 } |
1041 } | 1009 } |
1042 if (prev) { | 1010 if (prev) { |
1043 prev->fNext = vertices->fPrev = nullptr; | 1011 prev->fNext = vertices->fPrev = nullptr; |
1044 } | 1012 } |
1045 return vertices; | 1013 return vertices; |
1046 } | 1014 } |
1047 | 1015 |
1048 // Stage 3: sort the vertices by increasing sweep direction. | 1016 // Stage 3: sort the vertices by increasing sweep direction. |
1049 | 1017 |
1050 Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c); | 1018 TessellatingVertex* sorted_merge(TessellatingVertex* a, TessellatingVertex* b, C
omparator& c); |
1051 | 1019 |
1052 void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) { | 1020 void front_back_split(TessellatingVertex* v, TessellatingVertex** pFront, |
1053 Vertex* fast; | 1021 TessellatingVertex** pBack) { |
1054 Vertex* slow; | 1022 TessellatingVertex* fast; |
| 1023 TessellatingVertex* slow; |
1055 if (!v || !v->fNext) { | 1024 if (!v || !v->fNext) { |
1056 *pFront = v; | 1025 *pFront = v; |
1057 *pBack = nullptr; | 1026 *pBack = nullptr; |
1058 } else { | 1027 } else { |
1059 slow = v; | 1028 slow = v; |
1060 fast = v->fNext; | 1029 fast = v->fNext; |
1061 | 1030 |
1062 while (fast != nullptr) { | 1031 while (fast != nullptr) { |
1063 fast = fast->fNext; | 1032 fast = fast->fNext; |
1064 if (fast != nullptr) { | 1033 if (fast != nullptr) { |
1065 slow = slow->fNext; | 1034 slow = slow->fNext; |
1066 fast = fast->fNext; | 1035 fast = fast->fNext; |
1067 } | 1036 } |
1068 } | 1037 } |
1069 | 1038 |
1070 *pFront = v; | 1039 *pFront = v; |
1071 *pBack = slow->fNext; | 1040 *pBack = slow->fNext; |
1072 slow->fNext->fPrev = nullptr; | 1041 slow->fNext->fPrev = nullptr; |
1073 slow->fNext = nullptr; | 1042 slow->fNext = nullptr; |
1074 } | 1043 } |
1075 } | 1044 } |
1076 | 1045 |
1077 void merge_sort(Vertex** head, Comparator& c) { | 1046 void merge_sort(TessellatingVertex** head, Comparator& c) { |
1078 if (!*head || !(*head)->fNext) { | 1047 if (!*head || !(*head)->fNext) { |
1079 return; | 1048 return; |
1080 } | 1049 } |
1081 | 1050 |
1082 Vertex* a; | 1051 TessellatingVertex* a; |
1083 Vertex* b; | 1052 TessellatingVertex* b; |
1084 front_back_split(*head, &a, &b); | 1053 front_back_split(*head, &a, &b); |
1085 | 1054 |
1086 merge_sort(&a, c); | 1055 merge_sort(&a, c); |
1087 merge_sort(&b, c); | 1056 merge_sort(&b, c); |
1088 | 1057 |
1089 *head = sorted_merge(a, b, c); | 1058 *head = sorted_merge(a, b, c); |
1090 } | 1059 } |
1091 | 1060 |
1092 inline void append_vertex(Vertex* v, Vertex** head, Vertex** tail) { | 1061 inline void append_vertex(TessellatingVertex* v, TessellatingVertex** head, |
1093 insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, nullptr, head, tail
); | 1062 TessellatingVertex** tail) { |
| 1063 insert<TessellatingVertex, &TessellatingVertex::fPrev, &TessellatingVertex::
fNext>(v, *tail, |
| 1064
nullptr, |
| 1065
head, tail); |
1094 } | 1066 } |
1095 | 1067 |
1096 inline void append_vertex_list(Vertex* v, Vertex** head, Vertex** tail) { | 1068 inline void append_vertex_list(TessellatingVertex* v, TessellatingVertex** head,
|
1097 insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, v->fNext, head, tai
l); | 1069 TessellatingVertex** tail) { |
| 1070 insert<TessellatingVertex, &TessellatingVertex::fPrev, &TessellatingVertex::
fNext>(v, *tail, |
| 1071
v->fNext, |
| 1072
head, tail); |
1098 } | 1073 } |
1099 | 1074 |
1100 Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c) { | 1075 TessellatingVertex* sorted_merge(TessellatingVertex* a, TessellatingVertex* b, C
omparator& c) { |
1101 Vertex* head = nullptr; | 1076 TessellatingVertex* head = nullptr; |
1102 Vertex* tail = nullptr; | 1077 TessellatingVertex* tail = nullptr; |
1103 | 1078 |
1104 while (a && b) { | 1079 while (a && b) { |
1105 if (c.sweep_lt(a->fPoint, b->fPoint)) { | 1080 if (c.sweep_lt(a->fPoint, b->fPoint)) { |
1106 Vertex* next = a->fNext; | 1081 TessellatingVertex* next = a->fNext; |
1107 append_vertex(a, &head, &tail); | 1082 append_vertex(a, &head, &tail); |
1108 a = next; | 1083 a = next; |
1109 } else { | 1084 } else { |
1110 Vertex* next = b->fNext; | 1085 TessellatingVertex* next = b->fNext; |
1111 append_vertex(b, &head, &tail); | 1086 append_vertex(b, &head, &tail); |
1112 b = next; | 1087 b = next; |
1113 } | 1088 } |
1114 } | 1089 } |
1115 if (a) { | 1090 if (a) { |
1116 append_vertex_list(a, &head, &tail); | 1091 append_vertex_list(a, &head, &tail); |
1117 } | 1092 } |
1118 if (b) { | 1093 if (b) { |
1119 append_vertex_list(b, &head, &tail); | 1094 append_vertex_list(b, &head, &tail); |
1120 } | 1095 } |
1121 return head; | 1096 return head; |
1122 } | 1097 } |
1123 | 1098 |
1124 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges. | 1099 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges. |
1125 | 1100 |
1126 void simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) { | 1101 void simplify(TessellatingVertex* vertices, Comparator& c, SkChunkAlloc& alloc)
{ |
1127 LOG("simplifying complex polygons\n"); | 1102 LOG("simplifying complex polygons\n"); |
1128 EdgeList activeEdges; | 1103 EdgeList activeEdges; |
1129 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | 1104 for (TessellatingVertex* v = vertices; v != nullptr; v = v->fNext) { |
1130 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { | 1105 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { |
1131 continue; | 1106 continue; |
1132 } | 1107 } |
1133 #if LOGGING_ENABLED | 1108 #if TESSELLATION_LOGGING_ENABLED |
1134 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); | 1109 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); |
1135 #endif | 1110 #endif |
1136 Edge* leftEnclosingEdge = nullptr; | 1111 Edge* leftEnclosingEdge = nullptr; |
1137 Edge* rightEnclosingEdge = nullptr; | 1112 Edge* rightEnclosingEdge = nullptr; |
1138 bool restartChecks; | 1113 bool restartChecks; |
1139 do { | 1114 do { |
1140 restartChecks = false; | 1115 restartChecks = false; |
1141 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEncl
osingEdge); | 1116 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEncl
osingEdge); |
1142 if (v->fFirstEdgeBelow) { | 1117 if (v->fFirstEdgeBelow) { |
1143 for (Edge* edge = v->fFirstEdgeBelow; edge != nullptr; edge = ed
ge->fNextEdgeBelow) { | 1118 for (Edge* edge = v->fFirstEdgeBelow; edge != nullptr; edge = ed
ge->fNextEdgeBelow) { |
1144 if (check_for_intersection(edge, leftEnclosingEdge, &activeE
dges, c, alloc)) { | 1119 if (check_for_intersection(edge, leftEnclosingEdge, &activeE
dges, c, alloc)) { |
1145 restartChecks = true; | 1120 restartChecks = true; |
1146 break; | 1121 break; |
1147 } | 1122 } |
1148 if (check_for_intersection(edge, rightEnclosingEdge, &active
Edges, c, alloc)) { | 1123 if (check_for_intersection(edge, rightEnclosingEdge, &active
Edges, c, alloc)) { |
1149 restartChecks = true; | 1124 restartChecks = true; |
1150 break; | 1125 break; |
1151 } | 1126 } |
1152 } | 1127 } |
1153 } else { | 1128 } else { |
1154 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, right
EnclosingEdge, | 1129 if (TessellatingVertex* pv = check_for_intersection(leftEnclosin
gEdge, |
1155 &activeEdges, c, alloc))
{ | 1130 rightEnclosi
ngEdge, |
| 1131 &activeEdges
, c, alloc)) { |
1156 if (c.sweep_lt(pv->fPoint, v->fPoint)) { | 1132 if (c.sweep_lt(pv->fPoint, v->fPoint)) { |
1157 v = pv; | 1133 v = pv; |
1158 } | 1134 } |
1159 restartChecks = true; | 1135 restartChecks = true; |
1160 } | 1136 } |
1161 | 1137 |
1162 } | 1138 } |
1163 } while (restartChecks); | 1139 } while (restartChecks); |
1164 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { | 1140 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { |
1165 remove_edge(e, &activeEdges); | 1141 remove_edge(e, &activeEdges); |
1166 } | 1142 } |
1167 Edge* leftEdge = leftEnclosingEdge; | 1143 Edge* leftEdge = leftEnclosingEdge; |
1168 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { | 1144 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { |
1169 insert_edge(e, leftEdge, &activeEdges); | 1145 insert_edge(e, leftEdge, &activeEdges); |
1170 leftEdge = e; | 1146 leftEdge = e; |
1171 } | 1147 } |
1172 v->fProcessed = true; | 1148 v->fProcessed = true; |
1173 } | 1149 } |
1174 } | 1150 } |
1175 | 1151 |
1176 // Stage 5: Tessellate the simplified mesh into monotone polygons. | 1152 // Stage 5: Tessellate the simplified mesh into monotone polygons. |
1177 | 1153 |
1178 Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) { | 1154 Poly* tessellate(TessellatingVertex* vertices, SkChunkAlloc& alloc) { |
1179 LOG("tessellating simple polygons\n"); | 1155 LOG("tessellating simple polygons\n"); |
1180 EdgeList activeEdges; | 1156 EdgeList activeEdges; |
1181 Poly* polys = nullptr; | 1157 Poly* polys = nullptr; |
1182 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | 1158 for (TessellatingVertex* v = vertices; v != nullptr; v = v->fNext) { |
1183 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { | 1159 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { |
1184 continue; | 1160 continue; |
1185 } | 1161 } |
1186 #if LOGGING_ENABLED | 1162 #if TESSELLATION_LOGGING_ENABLED |
1187 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); | 1163 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); |
1188 #endif | 1164 #endif |
1189 Edge* leftEnclosingEdge = nullptr; | 1165 Edge* leftEnclosingEdge = nullptr; |
1190 Edge* rightEnclosingEdge = nullptr; | 1166 Edge* rightEnclosingEdge = nullptr; |
1191 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosin
gEdge); | 1167 find_enclosing_edges(v, &activeEdges, &leftEnclosingEdge, &rightEnclosin
gEdge); |
1192 Poly* leftPoly = nullptr; | 1168 Poly* leftPoly = nullptr; |
1193 Poly* rightPoly = nullptr; | 1169 Poly* rightPoly = nullptr; |
1194 if (v->fFirstEdgeAbove) { | 1170 if (v->fFirstEdgeAbove) { |
1195 leftPoly = v->fFirstEdgeAbove->fLeftPoly; | 1171 leftPoly = v->fFirstEdgeAbove->fLeftPoly; |
1196 rightPoly = v->fLastEdgeAbove->fRightPoly; | 1172 rightPoly = v->fLastEdgeAbove->fRightPoly; |
1197 } else { | 1173 } else { |
1198 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullp
tr; | 1174 leftPoly = leftEnclosingEdge ? leftEnclosingEdge->fRightPoly : nullp
tr; |
1199 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nul
lptr; | 1175 rightPoly = rightEnclosingEdge ? rightEnclosingEdge->fLeftPoly : nul
lptr; |
1200 } | 1176 } |
1201 #if LOGGING_ENABLED | 1177 #if TESSELLATION_LOGGING_ENABLED |
1202 LOG("edges above:\n"); | 1178 LOG("edges above:\n"); |
1203 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { | 1179 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { |
1204 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, | 1180 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, |
1205 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); | 1181 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); |
1206 } | 1182 } |
1207 LOG("edges below:\n"); | 1183 LOG("edges below:\n"); |
1208 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { | 1184 for (Edge* e = v->fFirstEdgeBelow; e; e = e->fNextEdgeBelow) { |
1209 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, | 1185 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, |
1210 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); | 1186 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); |
1211 } | 1187 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWindin
g : 0; | 1249 int winding = leftEdge->fLeftPoly ? leftEdge->fLeftPoly->fWindin
g : 0; |
1274 winding += leftEdge->fWinding; | 1250 winding += leftEdge->fWinding; |
1275 if (winding != 0) { | 1251 if (winding != 0) { |
1276 Poly* poly = new_poly(&polys, v, winding, alloc); | 1252 Poly* poly = new_poly(&polys, v, winding, alloc); |
1277 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly; | 1253 leftEdge->fRightPoly = rightEdge->fLeftPoly = poly; |
1278 } | 1254 } |
1279 leftEdge = rightEdge; | 1255 leftEdge = rightEdge; |
1280 } | 1256 } |
1281 v->fLastEdgeBelow->fRightPoly = rightPoly; | 1257 v->fLastEdgeBelow->fRightPoly = rightPoly; |
1282 } | 1258 } |
1283 #if LOGGING_ENABLED | 1259 #if TESSELLATION_LOGGING_ENABLED |
1284 LOG("\nactive edges:\n"); | 1260 LOG("\nactive edges:\n"); |
1285 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) { | 1261 for (Edge* e = activeEdges.fHead; e != nullptr; e = e->fRight) { |
1286 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, | 1262 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, |
1287 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); | 1263 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); |
1288 } | 1264 } |
1289 #endif | 1265 #endif |
1290 } | 1266 } |
1291 return polys; | 1267 return polys; |
1292 } | 1268 } |
1293 | 1269 |
1294 // This is a driver function which calls stages 2-5 in turn. | 1270 // This is a driver function which calls stages 2-5 in turn. |
1295 | 1271 |
1296 Poly* contours_to_polys(Vertex** contours, int contourCnt, Comparator& c, SkChun
kAlloc& alloc) { | 1272 Poly* contours_to_polys(TessellatingVertex** contours, int contourCnt, SkRect pa
thBounds, |
1297 #if LOGGING_ENABLED | 1273 SkChunkAlloc& alloc) { |
| 1274 Comparator c; |
| 1275 if (pathBounds.width() > pathBounds.height()) { |
| 1276 c.sweep_lt = sweep_lt_horiz; |
| 1277 c.sweep_gt = sweep_gt_horiz; |
| 1278 } else { |
| 1279 c.sweep_lt = sweep_lt_vert; |
| 1280 c.sweep_gt = sweep_gt_vert; |
| 1281 } |
| 1282 #if TESSELLATION_LOGGING_ENABLED |
1298 for (int i = 0; i < contourCnt; ++i) { | 1283 for (int i = 0; i < contourCnt; ++i) { |
1299 Vertex* v = contours[i]; | 1284 TessellatingVertex* v = contours[i]; |
1300 SkASSERT(v); | 1285 SkASSERT(v); |
1301 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); | 1286 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); |
1302 for (v = v->fNext; v != contours[i]; v = v->fNext) { | 1287 for (v = v->fNext; v != contours[i]; v = v->fNext) { |
1303 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); | 1288 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); |
1304 } | 1289 } |
1305 } | 1290 } |
1306 #endif | 1291 #endif |
1307 sanitize_contours(contours, contourCnt); | 1292 sanitize_contours(contours, contourCnt); |
1308 Vertex* vertices = build_edges(contours, contourCnt, c, alloc); | 1293 TessellatingVertex* vertices = build_edges(contours, contourCnt, c, alloc); |
1309 if (!vertices) { | 1294 if (!vertices) { |
1310 return nullptr; | 1295 return nullptr; |
1311 } | 1296 } |
1312 | 1297 |
1313 // Sort vertices in Y (secondarily in X). | 1298 // Sort vertices in Y (secondarily in X). |
1314 merge_sort(&vertices, c); | 1299 merge_sort(&vertices, c); |
1315 merge_coincident_vertices(&vertices, c, alloc); | 1300 merge_coincident_vertices(&vertices, c, alloc); |
1316 #if LOGGING_ENABLED | 1301 #if TESSELLATION_LOGGING_ENABLED |
1317 for (Vertex* v = vertices; v != nullptr; v = v->fNext) { | 1302 for (TessellatingVertex* v = vertices; v != nullptr; v = v->fNext) { |
1318 static float gID = 0.0f; | 1303 static float gID = 0.0f; |
1319 v->fID = gID++; | 1304 v->fID = gID++; |
1320 } | 1305 } |
1321 #endif | 1306 #endif |
1322 simplify(vertices, c, alloc); | 1307 simplify(vertices, c, alloc); |
1323 return tessellate(vertices, alloc); | 1308 return tessellate(vertices, alloc); |
1324 } | 1309 } |
1325 | 1310 |
1326 // Stage 6: Triangulate the monotone polygons into a vertex buffer. | |
1327 | |
1328 SkPoint* polys_to_triangles(Poly* polys, SkPath::FillType fillType, SkPoint* dat
a) { | |
1329 SkPoint* d = data; | |
1330 for (Poly* poly = polys; poly; poly = poly->fNext) { | |
1331 if (apply_fill_type(fillType, poly->fWinding)) { | |
1332 d = poly->emit(d); | |
1333 } | |
1334 } | |
1335 return d; | |
1336 } | |
1337 | 1311 |
1338 struct TessInfo { | 1312 struct TessInfo { |
1339 SkScalar fTolerance; | 1313 SkScalar fTolerance; |
1340 int fCount; | 1314 int fCount; |
1341 }; | 1315 }; |
1342 | 1316 |
| 1317 // Stage 6: Triangulate the monotone polygons into a vertex buffer. |
| 1318 |
| 1319 int polys_to_triangles(Poly* polys, SkPath::FillType fillType, bool isLinear, |
| 1320 GrResourceProvider* resourceProvider, SkAutoTUnref<GrVertexBuffer>& vert
exBuffer, |
| 1321 bool canMapVB) { |
| 1322 int count = 0; |
| 1323 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1324 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { |
| 1325 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |
| 1326 } |
| 1327 } |
| 1328 if (0 == count) { |
| 1329 return 0; |
| 1330 } |
| 1331 |
| 1332 size_t size = count * sizeof(SkPoint); |
| 1333 if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) { |
| 1334 vertexBuffer.reset(resourceProvider->createVertexBuffer( |
| 1335 size, GrResourceProvider::kStatic_BufferUsage, 0)); |
| 1336 } |
| 1337 if (!vertexBuffer.get()) { |
| 1338 SkDebugf("Could not allocate vertices\n"); |
| 1339 return 0; |
| 1340 } |
| 1341 SkPoint* verts; |
| 1342 if (canMapVB) { |
| 1343 verts = static_cast<SkPoint*>(vertexBuffer->map()); |
| 1344 } else { |
| 1345 verts = new SkPoint[count]; |
| 1346 } |
| 1347 SkPoint* end = verts; |
| 1348 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1349 if (apply_fill_type(fillType, poly->fWinding)) { |
| 1350 end = poly->emit(end); |
| 1351 } |
| 1352 } |
| 1353 int actualCount = static_cast<int>(end - verts); |
| 1354 LOG("actual count: %d\n", actualCount); |
| 1355 SkASSERT(actualCount <= count); |
| 1356 if (canMapVB) { |
| 1357 vertexBuffer->unmap(); |
| 1358 } else { |
| 1359 vertexBuffer->updateData(verts, actualCount * sizeof(SkPoint)); |
| 1360 delete[] verts; |
| 1361 } |
| 1362 |
| 1363 return actualCount; |
| 1364 } |
| 1365 |
| 1366 // creates an array of (point, winding) vertices and sets the 'verts' out |
| 1367 // parameter to point to it. CALLER IS RESPONSIBLE for deleting this buffer to |
| 1368 // avoid a memory leak! |
| 1369 int polys_to_vertices(Poly* polys, SkPath::FillType fillType, bool isLinear, |
| 1370 WindingVertex** verts) { |
| 1371 int count = 0; |
| 1372 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1373 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { |
| 1374 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |
| 1375 } |
| 1376 } |
| 1377 if (0 == count) { |
| 1378 *verts = nullptr; |
| 1379 return 0; |
| 1380 } |
| 1381 |
| 1382 *verts = new WindingVertex[count]; |
| 1383 WindingVertex* vertsEnd = *verts; |
| 1384 SkPoint* points = new SkPoint[count]; |
| 1385 SkPoint* pointsEnd = points; |
| 1386 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1387 if (apply_fill_type(fillType, poly->fWinding)) { |
| 1388 SkPoint* start = pointsEnd; |
| 1389 pointsEnd = poly->emit(pointsEnd); |
| 1390 while (start != pointsEnd) { |
| 1391 vertsEnd->fPos = *start; |
| 1392 vertsEnd->fWinding = poly->fWinding; |
| 1393 ++start; |
| 1394 ++vertsEnd; |
| 1395 } |
| 1396 } |
| 1397 } |
| 1398 int actualCount = static_cast<int>(vertsEnd - *verts); |
| 1399 SkASSERT(actualCount <= count); |
| 1400 SkASSERT(pointsEnd - points == actualCount); |
| 1401 delete[] points; |
| 1402 return actualCount; |
| 1403 } |
| 1404 |
1343 bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* actualCount) { | 1405 bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* actualCount) { |
1344 if (!vertexBuffer) { | 1406 if (!vertexBuffer) { |
1345 return false; | 1407 return false; |
1346 } | 1408 } |
1347 const SkData* data = vertexBuffer->getUniqueKey().getCustomData(); | 1409 const SkData* data = vertexBuffer->getUniqueKey().getCustomData(); |
1348 SkASSERT(data); | 1410 SkASSERT(data); |
1349 const TessInfo* info = static_cast<const TessInfo*>(data->data()); | 1411 const TessInfo* info = static_cast<const TessInfo*>(data->data()); |
1350 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) { | 1412 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) { |
1351 *actualCount = info->fCount; | 1413 *actualCount = info->fCount; |
1352 return true; | 1414 return true; |
1353 } | 1415 } |
1354 return false; | 1416 return false; |
1355 } | 1417 } |
1356 | 1418 |
1357 }; | |
1358 | |
1359 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { | 1419 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { |
1360 } | 1420 } |
1361 | 1421 |
1362 namespace { | 1422 namespace { |
1363 | 1423 |
1364 // When the SkPathRef genID changes, invalidate a corresponding GrResource descr
ibed by key. | 1424 // When the SkPathRef genID changes, invalidate a corresponding GrResource descr
ibed by key. |
1365 class PathInvalidator : public SkPathRef::GenIDChangeListener { | 1425 class PathInvalidator : public SkPathRef::GenIDChangeListener { |
1366 public: | 1426 public: |
1367 explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {} | 1427 explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {} |
1368 private: | 1428 private: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1428 } else { | 1488 } else { |
1429 path = fPath; | 1489 path = fPath; |
1430 } | 1490 } |
1431 if (!stroke.isFillStyle()) { | 1491 if (!stroke.isFillStyle()) { |
1432 stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale())); | 1492 stroke.setResScale(SkScalarAbs(fViewMatrix.getMaxScale())); |
1433 if (!stroke.applyToPath(&path, path)) { | 1493 if (!stroke.applyToPath(&path, path)) { |
1434 return 0; | 1494 return 0; |
1435 } | 1495 } |
1436 stroke.setFillStyle(); | 1496 stroke.setFillStyle(); |
1437 } | 1497 } |
| 1498 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; |
1438 SkRect pathBounds = path.getBounds(); | 1499 SkRect pathBounds = path.getBounds(); |
1439 Comparator c; | |
1440 if (pathBounds.width() > pathBounds.height()) { | |
1441 c.sweep_lt = sweep_lt_horiz; | |
1442 c.sweep_gt = sweep_gt_horiz; | |
1443 } else { | |
1444 c.sweep_lt = sweep_lt_vert; | |
1445 c.sweep_gt = sweep_gt_vert; | |
1446 } | |
1447 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; | |
1448 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat
rix, pathBounds); | 1500 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat
rix, pathBounds); |
1449 int contourCnt; | 1501 int contourCnt; |
1450 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol); | 1502 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol); |
1451 if (maxPts <= 0) { | 1503 if (maxPts <= 0) { |
1452 return 0; | 1504 return 0; |
1453 } | 1505 } |
1454 if (maxPts > ((int)SK_MaxU16 + 1)) { | 1506 if (maxPts > ((int)SK_MaxU16 + 1)) { |
1455 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); | 1507 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); |
1456 return 0; | 1508 return 0; |
1457 } | 1509 } |
1458 SkPath::FillType fillType = path.getFillType(); | 1510 SkPath::FillType fillType = path.getFillType(); |
1459 if (SkPath::IsInverseFillType(fillType)) { | 1511 if (SkPath::IsInverseFillType(fillType)) { |
1460 contourCnt++; | 1512 contourCnt++; |
1461 } | 1513 } |
1462 | 1514 |
1463 LOG("got %d pts, %d contours\n", maxPts, contourCnt); | 1515 SkAutoTDeleteArray<TessellatingVertex*> contours(new TessellatingVertex*
[contourCnt]); |
1464 SkAutoTDeleteArray<Vertex*> contours(new Vertex* [contourCnt]); | |
1465 | 1516 |
1466 // For the initial size of the chunk allocator, estimate based on the po
int count: | 1517 // For the initial size of the chunk allocator, estimate based on the po
int count: |
1467 // one vertex per point for the initial passes, plus two for the vertice
s in the | 1518 // one vertex per point for the initial passes, plus two for the vertice
s in the |
1468 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal | 1519 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal |
1469 // connectivity of one Edge per Vertex (will grow for intersections). | 1520 // connectivity of one Edge per TessellatingVertex (will grow for inters
ections). |
1470 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); | 1521 SkChunkAlloc alloc(maxPts * (3 * sizeof(TessellatingVertex) + sizeof(Edg
e))); |
1471 bool isLinear; | 1522 bool isLinear; |
1472 path_to_contours(path, tol, fClipBounds, contours.get(), alloc, &isLinea
r); | 1523 path_to_contours(path, tol, fClipBounds, contours.get(), alloc, &isLinea
r); |
1473 Poly* polys; | 1524 Poly* polys; |
1474 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); | 1525 polys = contours_to_polys(contours.get(), contourCnt, path.getBounds(),
alloc); |
1475 int count = 0; | 1526 int count = polys_to_triangles(polys, fillType, isLinear, resourceProvid
er, vertexBuffer, |
1476 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1527 canMapVB); |
1477 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3)
{ | |
1478 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); | |
1479 } | |
1480 } | |
1481 if (0 == count) { | |
1482 return 0; | |
1483 } | |
1484 | |
1485 size_t size = count * sizeof(SkPoint); | |
1486 if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) { | |
1487 vertexBuffer.reset(resourceProvider->createVertexBuffer( | |
1488 size, GrResourceProvider::kStatic_BufferUsage, 0)); | |
1489 } | |
1490 if (!vertexBuffer.get()) { | |
1491 SkDebugf("Could not allocate vertices\n"); | |
1492 return 0; | |
1493 } | |
1494 SkPoint* verts; | |
1495 if (canMapVB) { | |
1496 verts = static_cast<SkPoint*>(vertexBuffer->map()); | |
1497 } else { | |
1498 verts = new SkPoint[count]; | |
1499 } | |
1500 SkPoint* end = polys_to_triangles(polys, fillType, verts); | |
1501 int actualCount = static_cast<int>(end - verts); | |
1502 LOG("actual count: %d\n", actualCount); | |
1503 SkASSERT(actualCount <= count); | |
1504 if (canMapVB) { | |
1505 vertexBuffer->unmap(); | |
1506 } else { | |
1507 vertexBuffer->updateData(verts, actualCount * sizeof(SkPoint)); | |
1508 delete[] verts; | |
1509 } | |
1510 | |
1511 | |
1512 if (!fPath.isVolatile()) { | 1528 if (!fPath.isVolatile()) { |
1513 TessInfo info; | 1529 TessInfo info; |
1514 info.fTolerance = isLinear ? 0 : tol; | 1530 info.fTolerance = isLinear ? 0 : tol; |
1515 info.fCount = actualCount; | 1531 info.fCount = count; |
1516 SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); | 1532 SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); |
1517 key->setCustomData(data.get()); | 1533 key->setCustomData(data.get()); |
1518 resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get()
); | 1534 resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get()
); |
1519 SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(*key))
; | 1535 SkPathPriv::AddGenIDChangeListener(fPath, new PathInvalidator(*key))
; |
1520 } | 1536 } |
1521 return actualCount; | 1537 return count; |
1522 } | 1538 } |
1523 | 1539 |
1524 void onPrepareDraws(Target* target) const override { | 1540 void onPrepareDraws(Target* target) const override { |
1525 // construct a cache key from the path's genID and the view matrix | 1541 // construct a cache key from the path's genID and the view matrix |
1526 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; | 1542 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; |
1527 GrUniqueKey key; | 1543 GrUniqueKey key; |
1528 int clipBoundsSize32 = | 1544 int clipBoundsSize32 = |
1529 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) :
0; | 1545 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) :
0; |
1530 int strokeDataSize32 = fStroke.computeUniqueKeyFragmentData32Cnt(); | 1546 int strokeDataSize32 = fStroke.computeUniqueKeyFragmentData32Cnt(); |
1531 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + strok
eDataSize32); | 1547 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32 + strok
eDataSize32); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1662 bool result = viewMatrix.invert(&vmi); | 1678 bool result = viewMatrix.invert(&vmi); |
1663 if (!result) { | 1679 if (!result) { |
1664 SkFAIL("Cannot invert matrix\n"); | 1680 SkFAIL("Cannot invert matrix\n"); |
1665 } | 1681 } |
1666 vmi.mapRect(&clipBounds); | 1682 vmi.mapRect(&clipBounds); |
1667 GrStrokeInfo strokeInfo = GrTest::TestStrokeInfo(random); | 1683 GrStrokeInfo strokeInfo = GrTest::TestStrokeInfo(random); |
1668 return TessellatingPathBatch::Create(color, path, strokeInfo, viewMatrix, cl
ipBounds); | 1684 return TessellatingPathBatch::Create(color, path, strokeInfo, viewMatrix, cl
ipBounds); |
1669 } | 1685 } |
1670 | 1686 |
1671 #endif | 1687 #endif |
OLD | NEW |