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 "GrTessellator.h" | 8 #include "GrTessellator.h" |
9 | 9 |
10 #include "GrDefaultGeoProcFactory.h" | 10 #include "GrDefaultGeoProcFactory.h" |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
253 } | 253 } |
254 }; | 254 }; |
255 | 255 |
256 // Round to nearest quarter-pixel. This is used for screenspace tessellation. | 256 // Round to nearest quarter-pixel. This is used for screenspace tessellation. |
257 | 257 |
258 inline void round(SkPoint* p) { | 258 inline void round(SkPoint* p) { |
259 p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScal ar(0.25f); | 259 p->fX = SkScalarRoundToScalar(p->fX * SkFloatToScalar(4.0f)) * SkFloatToScal ar(0.25f); |
260 p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScal ar(0.25f); | 260 p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScal ar(0.25f); |
261 } | 261 } |
262 | 262 |
263 // A line equation in implicit form. fA * x + fB * y + fC = 0, for all points (x , y) on the line. | |
264 struct Line { | |
265 Line(Vertex* p, Vertex* q) : Line(p->fPoint, q->fPoint) {} | |
266 Line(const SkPoint& p, const SkPoint& q) | |
267 : fA(static_cast<double>(q.fY) - p.fY) // a = dY | |
268 , fB(static_cast<double>(p.fX) - q.fX) // b = -dX | |
269 , fC(static_cast<double>(p.fY) * q.fX - // c = cross(q, p) | |
270 static_cast<double>(p.fX) * q.fY) {} | |
271 double dist(const SkPoint& p) const { | |
272 return fA * p.fX + fB * p.fY + fC; | |
273 } | |
274 double magSq() const { | |
275 return fA * fA + fB * fB; | |
276 } | |
277 double fA, fB, fC; | |
278 }; | |
279 | |
263 /** | 280 /** |
264 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and | 281 * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and |
265 * "edge below" a vertex as well as for the active edge list is handled by isLef tOf()/isRightOf(). | 282 * "edge below" a vertex as well as for the active edge list is handled by isLef tOf()/isRightOf(). |
266 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (b ecause floating | 283 * Note that an Edge will give occasionally dist() != 0 for its own endpoints (b ecause floating |
267 * point). For speed, that case is only tested by the callers which require it ( e.g., | 284 * point). For speed, that case is only tested by the callers which require it ( e.g., |
268 * cleanup_active_edges()). Edges also handle checking for intersection with oth er edges. | 285 * cleanup_active_edges()). Edges also handle checking for intersection with oth er edges. |
269 * Currently, this converts the edges to the parametric form, in order to avoid doing a division | 286 * Currently, this converts the edges to the parametric form, in order to avoid doing a division |
270 * until an intersection has been confirmed. This is slightly slower in the "fou nd" case, but | 287 * until an intersection has been confirmed. This is slightly slower in the "fou nd" case, but |
271 * a lot faster in the "not found" case. | 288 * a lot faster in the "not found" case. |
272 * | 289 * |
(...skipping 16 matching lines...) Expand all Loading... | |
289 , fNextEdgeAbove(nullptr) | 306 , fNextEdgeAbove(nullptr) |
290 , fPrevEdgeBelow(nullptr) | 307 , fPrevEdgeBelow(nullptr) |
291 , fNextEdgeBelow(nullptr) | 308 , fNextEdgeBelow(nullptr) |
292 , fLeftPoly(nullptr) | 309 , fLeftPoly(nullptr) |
293 , fRightPoly(nullptr) | 310 , fRightPoly(nullptr) |
294 , fLeftPolyPrev(nullptr) | 311 , fLeftPolyPrev(nullptr) |
295 , fLeftPolyNext(nullptr) | 312 , fLeftPolyNext(nullptr) |
296 , fRightPolyPrev(nullptr) | 313 , fRightPolyPrev(nullptr) |
297 , fRightPolyNext(nullptr) | 314 , fRightPolyNext(nullptr) |
298 , fUsedInLeftPoly(false) | 315 , fUsedInLeftPoly(false) |
299 , fUsedInRightPoly(false) { | 316 , fUsedInRightPoly(false) |
300 recompute(); | 317 , fLine(top, bottom) { |
301 } | 318 } |
302 int fWinding; // 1 == edge goes downward; -1 = edge goes upwar d. | 319 int fWinding; // 1 == edge goes downward; -1 = edge goes upwar d. |
303 Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt ). | 320 Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt ). |
304 Vertex* fBottom; // The bottom vertex in vertex-sort-order. | 321 Vertex* fBottom; // The bottom vertex in vertex-sort-order. |
305 Edge* fLeft; // The linked list of edges in the active edge l ist. | 322 Edge* fLeft; // The linked list of edges in the active edge l ist. |
306 Edge* fRight; // " | 323 Edge* fRight; // " |
307 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex 's "edges above". | 324 Edge* fPrevEdgeAbove; // The linked list of edges in the bottom Vertex 's "edges above". |
308 Edge* fNextEdgeAbove; // " | 325 Edge* fNextEdgeAbove; // " |
309 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex's "edges below". | 326 Edge* fPrevEdgeBelow; // The linked list of edges in the top Vertex's "edges below". |
310 Edge* fNextEdgeBelow; // " | 327 Edge* fNextEdgeBelow; // " |
311 Poly* fLeftPoly; // The Poly to the left of this edge, if any. | 328 Poly* fLeftPoly; // The Poly to the left of this edge, if any. |
312 Poly* fRightPoly; // The Poly to the right of this edge, if any. | 329 Poly* fRightPoly; // The Poly to the right of this edge, if any. |
313 Edge* fLeftPolyPrev; | 330 Edge* fLeftPolyPrev; |
314 Edge* fLeftPolyNext; | 331 Edge* fLeftPolyNext; |
315 Edge* fRightPolyPrev; | 332 Edge* fRightPolyPrev; |
316 Edge* fRightPolyNext; | 333 Edge* fRightPolyNext; |
317 bool fUsedInLeftPoly; | 334 bool fUsedInLeftPoly; |
318 bool fUsedInRightPoly; | 335 bool fUsedInRightPoly; |
319 double fDX; // The line equation for this edge, in implicit form. | 336 Line fLine; |
320 double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y) on the line. | |
321 double fC; | |
322 double dist(const SkPoint& p) const { | 337 double dist(const SkPoint& p) const { |
323 return fDY * p.fX - fDX * p.fY + fC; | 338 return fLine.dist(p); |
324 } | 339 } |
325 bool isRightOf(Vertex* v) const { | 340 bool isRightOf(Vertex* v) const { |
326 return dist(v->fPoint) < 0.0; | 341 return fLine.dist(v->fPoint) < 0.0; |
327 } | 342 } |
328 bool isLeftOf(Vertex* v) const { | 343 bool isLeftOf(Vertex* v) const { |
329 return dist(v->fPoint) > 0.0; | 344 return fLine.dist(v->fPoint) > 0.0; |
330 } | 345 } |
331 void recompute() { | 346 void recompute() { |
332 fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX; | 347 fLine = Line(fTop, fBottom); |
333 fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY; | |
334 fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX - | |
335 static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY; | |
336 } | 348 } |
337 bool intersect(const Edge& other, SkPoint* p) { | 349 bool intersect(const Edge& other, SkPoint* p) { |
338 LOG("intersecting %g -> %g with %g -> %g\n", | 350 LOG("intersecting %g -> %g with %g -> %g\n", |
339 fTop->fID, fBottom->fID, | 351 fTop->fID, fBottom->fID, |
340 other.fTop->fID, other.fBottom->fID); | 352 other.fTop->fID, other.fBottom->fID); |
341 if (fTop == other.fTop || fBottom == other.fBottom) { | 353 if (fTop == other.fTop || fBottom == other.fBottom) { |
342 return false; | 354 return false; |
343 } | 355 } |
344 double denom = fDX * other.fDY - fDY * other.fDX; | 356 double denom = fLine.fA * other.fLine.fB - fLine.fB * other.fLine.fA; |
345 if (denom == 0.0) { | 357 if (denom == 0.0) { |
346 return false; | 358 return false; |
347 } | 359 } |
348 double dx = static_cast<double>(fTop->fPoint.fX) - other.fTop->fPoint.fX ; | 360 double dx = static_cast<double>(fTop->fPoint.fX) - other.fTop->fPoint.fX ; |
349 double dy = static_cast<double>(fTop->fPoint.fY) - other.fTop->fPoint.fY ; | 361 double dy = static_cast<double>(fTop->fPoint.fY) - other.fTop->fPoint.fY ; |
350 double sNumer = dy * other.fDX - dx * other.fDY; | 362 double sNumer = -dy * other.fLine.fB - dx * other.fLine.fA; |
351 double tNumer = dy * fDX - dx * fDY; | 363 double tNumer = -dy * fLine.fB - dx * fLine.fA; |
352 // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early. | 364 // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early. |
353 // This saves us doing the divide below unless absolutely necessary. | 365 // This saves us doing the divide below unless absolutely necessary. |
354 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNu mer > denom) | 366 if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNu mer > denom) |
355 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNu mer < denom)) { | 367 : (sNumer > 0.0 || sNumer < denom || tNumer > 0.0 || tNu mer < denom)) { |
356 return false; | 368 return false; |
357 } | 369 } |
358 double s = sNumer / denom; | 370 double s = sNumer / denom; |
359 SkASSERT(s >= 0.0 && s <= 1.0); | 371 SkASSERT(s >= 0.0 && s <= 1.0); |
360 p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX); | 372 p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB); |
361 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY); | 373 p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA); |
362 return true; | 374 return true; |
363 } | 375 } |
364 }; | 376 }; |
365 | 377 |
366 struct EdgeList { | 378 struct EdgeList { |
367 EdgeList() : fHead(nullptr), fTail(nullptr), fNext(nullptr), fCount(0) {} | 379 EdgeList() : fHead(nullptr), fTail(nullptr), fNext(nullptr), fCount(0) {} |
368 Edge* fHead; | 380 Edge* fHead; |
369 Edge* fTail; | 381 Edge* fTail; |
370 EdgeList* fNext; | 382 EdgeList* fNext; |
371 int fCount; | 383 int fCount; |
(...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1416 if (!is_boundary_edge(e, fillType)) { | 1428 if (!is_boundary_edge(e, fillType)) { |
1417 remove_edge_above(e); | 1429 remove_edge_above(e); |
1418 remove_edge_below(e); | 1430 remove_edge_below(e); |
1419 } | 1431 } |
1420 e = next; | 1432 e = next; |
1421 } | 1433 } |
1422 } | 1434 } |
1423 return vertices; | 1435 return vertices; |
1424 } | 1436 } |
1425 | 1437 |
1426 // This is different from Edge::intersect, in that it intersects lines, not line segments. | 1438 // This is different from Edge::intersect, in that it intersects lines, not line segments. |
robertphillips
2016/10/07 13:30:58
Should this somehow be associated more explicitly
Stephen White
2016/10/07 15:03:20
Done.
| |
1427 bool intersect(const Edge& a, const Edge& b, SkPoint* point) { | 1439 bool intersect(const Line& a, const Line& b, SkPoint* point) { |
1428 double denom = a.fDX * b.fDY - a.fDY * b.fDX; | 1440 double denom = a.fA * b.fB - a.fB * b.fA; |
1429 if (denom == 0.0) { | 1441 if (denom == 0.0) { |
1430 return false; | 1442 return false; |
1431 } | 1443 } |
1432 double scale = 1.0f / denom; | 1444 double scale = 1.0f / denom; |
1433 point->fX = SkDoubleToScalar((b.fDX * a.fC - a.fDX * b.fC) * scale); | 1445 point->fX = SkDoubleToScalar((a.fB * b.fC - b.fB * a.fC) * scale); |
1434 point->fY = SkDoubleToScalar((b.fDY * a.fC - a.fDY * b.fC) * scale); | 1446 point->fY = SkDoubleToScalar((b.fA * a.fC - a.fA * b.fC) * scale); |
1435 round(point); | 1447 round(point); |
1436 return true; | 1448 return true; |
1437 } | 1449 } |
1438 | 1450 |
1439 void get_edge_normal(const Edge* e, SkVector* normal) { | 1451 void get_edge_normal(const Edge* e, SkVector* normal) { |
1440 normal->setNormalize(SkDoubleToScalar(e->fDX) * e->fWinding, | 1452 normal->setNormalize(SkDoubleToScalar(-e->fLine.fB) * e->fWinding, |
1441 SkDoubleToScalar(e->fDY) * e->fWinding); | 1453 SkDoubleToScalar(e->fLine.fA) * e->fWinding); |
1442 } | 1454 } |
1443 | 1455 |
1444 // Stage 5c: detect and remove "pointy" vertices whose edge normals point in opp osite directions | 1456 // Stage 5c: detect and remove "pointy" vertices whose edge normals point in opp osite directions |
1445 // and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to | 1457 // and whose adjacent vertices are less than a quarter pixel from an edge. These are guaranteed to |
1446 // invert on stroking. | 1458 // invert on stroking. |
1447 | 1459 |
1448 void simplify_boundary(EdgeList* boundary, Comparator& c, SkChunkAlloc& alloc) { | 1460 void simplify_boundary(EdgeList* boundary, Comparator& c, SkChunkAlloc& alloc) { |
1449 Edge* prevEdge = boundary->fTail; | 1461 Edge* prevEdge = boundary->fTail; |
1450 SkVector prevNormal; | 1462 SkVector prevNormal; |
1451 get_edge_normal(prevEdge, &prevNormal); | 1463 get_edge_normal(prevEdge, &prevNormal); |
1452 for (Edge* e = boundary->fHead; e != nullptr;) { | 1464 for (Edge* e = boundary->fHead; e != nullptr;) { |
1453 Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBot tom; | 1465 Vertex* prev = prevEdge->fWinding == 1 ? prevEdge->fTop : prevEdge->fBot tom; |
1454 Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop; | 1466 Vertex* next = e->fWinding == 1 ? e->fBottom : e->fTop; |
1455 double dist = e->dist(prev->fPoint); | 1467 double dist = e->dist(prev->fPoint); |
1456 SkVector normal; | 1468 SkVector normal; |
1457 get_edge_normal(e, &normal); | 1469 get_edge_normal(e, &normal); |
1458 float denom = 0.25f * static_cast<float>(e->fDX * e->fDX + e->fDY * e->f DY); | 1470 float denom = 0.25f * static_cast<float>(e->fLine.magSq()); |
1459 if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) { | 1471 if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) { |
1460 Edge* join = new_edge(prev, next, alloc, c); | 1472 Edge* join = new_edge(prev, next, alloc, c); |
1461 insert_edge(join, e, boundary); | 1473 insert_edge(join, e, boundary); |
1462 remove_edge(prevEdge, boundary); | 1474 remove_edge(prevEdge, boundary); |
1463 remove_edge(e, boundary); | 1475 remove_edge(e, boundary); |
1464 if (join->fLeft && join->fRight) { | 1476 if (join->fLeft && join->fRight) { |
1465 prevEdge = join->fLeft; | 1477 prevEdge = join->fLeft; |
1466 e = join; | 1478 e = join; |
1467 } else { | 1479 } else { |
1468 prevEdge = boundary->fTail; | 1480 prevEdge = boundary->fTail; |
1469 e = boundary->fHead; // join->fLeft ? join->fLeft : join; | 1481 e = boundary->fHead; // join->fLeft ? join->fLeft : join; |
1470 } | 1482 } |
1471 get_edge_normal(prevEdge, &prevNormal); | 1483 get_edge_normal(prevEdge, &prevNormal); |
1472 } else { | 1484 } else { |
1473 prevEdge = e; | 1485 prevEdge = e; |
1474 prevNormal = normal; | 1486 prevNormal = normal; |
1475 e = e->fRight; | 1487 e = e->fRight; |
1476 } | 1488 } |
1477 } | 1489 } |
1478 } | 1490 } |
1479 | 1491 |
1480 // Stage 5d: Displace edges by half a pixel inward and outward along their norma ls. Intersect to | 1492 // Stage 5d: Displace edges by half a pixel inward and outward along their norma ls. Intersect to |
1481 // find new vertices, and set zero alpha on the exterior and one alpha on the in terior. Build a | 1493 // find new vertices, and set zero alpha on the exterior and one alpha on the in terior. Build a |
1482 // new antialiased mesh from those vertices. | 1494 // new antialiased mesh from those vertices. |
1483 | 1495 |
1484 void boundary_to_aa_mesh(EdgeList* boundary, VertexList* mesh, Comparator& c, Sk ChunkAlloc& alloc) { | 1496 void boundary_to_aa_mesh(EdgeList* boundary, VertexList* mesh, Comparator& c, Sk ChunkAlloc& alloc) { |
1485 EdgeList outerContour; | 1497 EdgeList outerContour; |
1486 Edge* prevEdge = boundary->fTail; | 1498 Edge* prevEdge = boundary->fTail; |
1487 float radius = 0.5f; | 1499 float radius = 0.5f; |
1488 double offset = radius * sqrt(prevEdge->fDX * prevEdge->fDX + prevEdge->fDY * prevEdge->fDY) | 1500 double offset = radius * sqrt(prevEdge->fLine.magSq()) * prevEdge->fWinding; |
1489 * prevEdge->fWinding; | 1501 Line prevInner(prevEdge->fTop, prevEdge->fBottom); |
1490 Edge prevInner(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding); | |
1491 prevInner.fC -= offset; | 1502 prevInner.fC -= offset; |
1492 Edge prevOuter(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding); | 1503 Line prevOuter(prevEdge->fTop, prevEdge->fBottom); |
1493 prevOuter.fC += offset; | 1504 prevOuter.fC += offset; |
1494 VertexList innerVertices; | 1505 VertexList innerVertices; |
1495 VertexList outerVertices; | 1506 VertexList outerVertices; |
1496 SkScalar innerCount = SK_Scalar1, outerCount = SK_Scalar1; | 1507 SkScalar innerCount = SK_Scalar1, outerCount = SK_Scalar1; |
1497 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) { | 1508 for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) { |
1498 double offset = radius * sqrt(e->fDX * e->fDX + e->fDY * e->fDY) * e->fW inding; | 1509 double offset = radius * sqrt(e->fLine.magSq()) * e->fWinding; |
1499 Edge inner(e->fTop, e->fBottom, e->fWinding); | 1510 Line inner(e->fTop, e->fBottom); |
1500 inner.fC -= offset; | 1511 inner.fC -= offset; |
1501 Edge outer(e->fTop, e->fBottom, e->fWinding); | 1512 Line outer(e->fTop, e->fBottom); |
1502 outer.fC += offset; | 1513 outer.fC += offset; |
1503 SkPoint innerPoint, outerPoint; | 1514 SkPoint innerPoint, outerPoint; |
1504 if (intersect(prevInner, inner, &innerPoint) && | 1515 if (intersect(prevInner, inner, &innerPoint) && |
1505 intersect(prevOuter, outer, &outerPoint)) { | 1516 intersect(prevOuter, outer, &outerPoint)) { |
1506 Vertex* innerVertex = ALLOC_NEW(Vertex, (innerPoint, 255), alloc); | 1517 Vertex* innerVertex = ALLOC_NEW(Vertex, (innerPoint, 255), alloc); |
1507 Vertex* outerVertex = ALLOC_NEW(Vertex, (outerPoint, 0), alloc); | 1518 Vertex* outerVertex = ALLOC_NEW(Vertex, (outerPoint, 0), alloc); |
1508 if (innerVertices.fTail && outerVertices.fTail) { | 1519 if (innerVertices.fTail && outerVertices.fTail) { |
1509 Edge innerEdge(innerVertices.fTail, innerVertex, 1); | 1520 Edge innerEdge(innerVertices.fTail, innerVertex, 1); |
1510 Edge outerEdge(outerVertices.fTail, outerVertex, 1); | 1521 Edge outerEdge(outerVertices.fTail, outerVertex, 1); |
1511 SkVector innerNormal; | 1522 SkVector innerNormal; |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1804 } | 1815 } |
1805 } | 1816 } |
1806 int actualCount = static_cast<int>(vertsEnd - *verts); | 1817 int actualCount = static_cast<int>(vertsEnd - *verts); |
1807 SkASSERT(actualCount <= count); | 1818 SkASSERT(actualCount <= count); |
1808 SkASSERT(pointsEnd - points == actualCount); | 1819 SkASSERT(pointsEnd - points == actualCount); |
1809 delete[] points; | 1820 delete[] points; |
1810 return actualCount; | 1821 return actualCount; |
1811 } | 1822 } |
1812 | 1823 |
1813 } // namespace | 1824 } // namespace |
OLD | NEW |