| 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 |