Chromium Code Reviews| Index: src/gpu/GrTessellator.cpp |
| diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp |
| index 9ce1a739df8dff27b24d3364da825fa35928ca24..2e2c8ef18fe4ce197886e52a49858a4e6213de53 100644 |
| --- a/src/gpu/GrTessellator.cpp |
| +++ b/src/gpu/GrTessellator.cpp |
| @@ -260,6 +260,23 @@ inline void round(SkPoint* p) { |
| p->fY = SkScalarRoundToScalar(p->fY * SkFloatToScalar(4.0f)) * SkFloatToScalar(0.25f); |
| } |
| +// A line equation in implicit form. fA * x + fB * y + fC = 0, for all points (x, y) on the line. |
| +struct Line { |
| + Line(Vertex* p, Vertex* q) : Line(p->fPoint, q->fPoint) {} |
| + Line(const SkPoint& p, const SkPoint& q) |
| + : fA(static_cast<double>(q.fY) - p.fY) // a = dY |
| + , fB(static_cast<double>(p.fX) - q.fX) // b = -dX |
| + , fC(static_cast<double>(p.fY) * q.fX - // c = cross(q, p) |
| + static_cast<double>(p.fX) * q.fY) {} |
| + double dist(const SkPoint& p) const { |
| + return fA * p.fX + fB * p.fY + fC; |
| + } |
| + double magSq() const { |
| + return fA * fA + fB * fB; |
| + } |
| + double fA, fB, fC; |
| +}; |
| + |
| /** |
| * An Edge joins a top Vertex to a bottom Vertex. Edge ordering for the list of "edges above" and |
| * "edge below" a vertex as well as for the active edge list is handled by isLeftOf()/isRightOf(). |
| @@ -296,8 +313,8 @@ struct Edge { |
| , fRightPolyPrev(nullptr) |
| , fRightPolyNext(nullptr) |
| , fUsedInLeftPoly(false) |
| - , fUsedInRightPoly(false) { |
| - recompute(); |
| + , fUsedInRightPoly(false) |
| + , fLine(top, bottom) { |
| } |
| int fWinding; // 1 == edge goes downward; -1 = edge goes upward. |
| Vertex* fTop; // The top vertex in vertex-sort-order (sweep_lt). |
| @@ -316,23 +333,18 @@ struct Edge { |
| Edge* fRightPolyNext; |
| bool fUsedInLeftPoly; |
| bool fUsedInRightPoly; |
| - double fDX; // The line equation for this edge, in implicit form. |
| - double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y) on the line. |
| - double fC; |
| + Line fLine; |
| double dist(const SkPoint& p) const { |
| - return fDY * p.fX - fDX * p.fY + fC; |
| + return fLine.dist(p); |
| } |
| bool isRightOf(Vertex* v) const { |
| - return dist(v->fPoint) < 0.0; |
| + return fLine.dist(v->fPoint) < 0.0; |
| } |
| bool isLeftOf(Vertex* v) const { |
| - return dist(v->fPoint) > 0.0; |
| + return fLine.dist(v->fPoint) > 0.0; |
| } |
| void recompute() { |
| - fDX = static_cast<double>(fBottom->fPoint.fX) - fTop->fPoint.fX; |
| - fDY = static_cast<double>(fBottom->fPoint.fY) - fTop->fPoint.fY; |
| - fC = static_cast<double>(fTop->fPoint.fY) * fBottom->fPoint.fX - |
| - static_cast<double>(fTop->fPoint.fX) * fBottom->fPoint.fY; |
| + fLine = Line(fTop, fBottom); |
| } |
| bool intersect(const Edge& other, SkPoint* p) { |
| LOG("intersecting %g -> %g with %g -> %g\n", |
| @@ -341,14 +353,14 @@ struct Edge { |
| if (fTop == other.fTop || fBottom == other.fBottom) { |
| return false; |
| } |
| - double denom = fDX * other.fDY - fDY * other.fDX; |
| + double denom = fLine.fA * other.fLine.fB - fLine.fB * other.fLine.fA; |
| if (denom == 0.0) { |
| return false; |
| } |
| double dx = static_cast<double>(fTop->fPoint.fX) - other.fTop->fPoint.fX; |
| double dy = static_cast<double>(fTop->fPoint.fY) - other.fTop->fPoint.fY; |
| - double sNumer = dy * other.fDX - dx * other.fDY; |
| - double tNumer = dy * fDX - dx * fDY; |
| + double sNumer = -dy * other.fLine.fB - dx * other.fLine.fA; |
| + double tNumer = -dy * fLine.fB - dx * fLine.fA; |
| // If (sNumer / denom) or (tNumer / denom) is not in [0..1], exit early. |
| // This saves us doing the divide below unless absolutely necessary. |
| if (denom > 0.0 ? (sNumer < 0.0 || sNumer > denom || tNumer < 0.0 || tNumer > denom) |
| @@ -357,8 +369,8 @@ struct Edge { |
| } |
| double s = sNumer / denom; |
| SkASSERT(s >= 0.0 && s <= 1.0); |
| - p->fX = SkDoubleToScalar(fTop->fPoint.fX + s * fDX); |
| - p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fDY); |
| + p->fX = SkDoubleToScalar(fTop->fPoint.fX - s * fLine.fB); |
| + p->fY = SkDoubleToScalar(fTop->fPoint.fY + s * fLine.fA); |
| return true; |
| } |
| }; |
| @@ -1424,21 +1436,21 @@ Vertex* remove_non_boundary_edges(Vertex* vertices, SkPath::FillType fillType, |
| } |
| // 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.
|
| -bool intersect(const Edge& a, const Edge& b, SkPoint* point) { |
| - double denom = a.fDX * b.fDY - a.fDY * b.fDX; |
| +bool intersect(const Line& a, const Line& b, SkPoint* point) { |
| + double denom = a.fA * b.fB - a.fB * b.fA; |
| if (denom == 0.0) { |
| return false; |
| } |
| double scale = 1.0f / denom; |
| - point->fX = SkDoubleToScalar((b.fDX * a.fC - a.fDX * b.fC) * scale); |
| - point->fY = SkDoubleToScalar((b.fDY * a.fC - a.fDY * b.fC) * scale); |
| + point->fX = SkDoubleToScalar((a.fB * b.fC - b.fB * a.fC) * scale); |
| + point->fY = SkDoubleToScalar((b.fA * a.fC - a.fA * b.fC) * scale); |
| round(point); |
| return true; |
| } |
| void get_edge_normal(const Edge* e, SkVector* normal) { |
| - normal->setNormalize(SkDoubleToScalar(e->fDX) * e->fWinding, |
| - SkDoubleToScalar(e->fDY) * e->fWinding); |
| + normal->setNormalize(SkDoubleToScalar(-e->fLine.fB) * e->fWinding, |
| + SkDoubleToScalar(e->fLine.fA) * e->fWinding); |
| } |
| // Stage 5c: detect and remove "pointy" vertices whose edge normals point in opposite directions |
| @@ -1455,7 +1467,7 @@ void simplify_boundary(EdgeList* boundary, Comparator& c, SkChunkAlloc& alloc) { |
| double dist = e->dist(prev->fPoint); |
| SkVector normal; |
| get_edge_normal(e, &normal); |
| - float denom = 0.25f * static_cast<float>(e->fDX * e->fDX + e->fDY * e->fDY); |
| + float denom = 0.25f * static_cast<float>(e->fLine.magSq()); |
| if (prevNormal.dot(normal) < 0.0 && (dist * dist) <= denom) { |
| Edge* join = new_edge(prev, next, alloc, c); |
| insert_edge(join, e, boundary); |
| @@ -1485,20 +1497,19 @@ void boundary_to_aa_mesh(EdgeList* boundary, VertexList* mesh, Comparator& c, Sk |
| EdgeList outerContour; |
| Edge* prevEdge = boundary->fTail; |
| float radius = 0.5f; |
| - double offset = radius * sqrt(prevEdge->fDX * prevEdge->fDX + prevEdge->fDY * prevEdge->fDY) |
| - * prevEdge->fWinding; |
| - Edge prevInner(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding); |
| + double offset = radius * sqrt(prevEdge->fLine.magSq()) * prevEdge->fWinding; |
| + Line prevInner(prevEdge->fTop, prevEdge->fBottom); |
| prevInner.fC -= offset; |
| - Edge prevOuter(prevEdge->fTop, prevEdge->fBottom, prevEdge->fWinding); |
| + Line prevOuter(prevEdge->fTop, prevEdge->fBottom); |
| prevOuter.fC += offset; |
| VertexList innerVertices; |
| VertexList outerVertices; |
| SkScalar innerCount = SK_Scalar1, outerCount = SK_Scalar1; |
| for (Edge* e = boundary->fHead; e != nullptr; e = e->fRight) { |
| - double offset = radius * sqrt(e->fDX * e->fDX + e->fDY * e->fDY) * e->fWinding; |
| - Edge inner(e->fTop, e->fBottom, e->fWinding); |
| + double offset = radius * sqrt(e->fLine.magSq()) * e->fWinding; |
| + Line inner(e->fTop, e->fBottom); |
| inner.fC -= offset; |
| - Edge outer(e->fTop, e->fBottom, e->fWinding); |
| + Line outer(e->fTop, e->fBottom); |
| outer.fC += offset; |
| SkPoint innerPoint, outerPoint; |
| if (intersect(prevInner, inner, &innerPoint) && |