Index: src/gpu/GrTessellator.cpp |
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp |
index 9ce1a739df8dff27b24d3364da825fa35928ca24..4024ad0c16d2138b0d4b1476d411d135fec0b206 100644 |
--- a/src/gpu/GrTessellator.cpp |
+++ b/src/gpu/GrTessellator.cpp |
@@ -260,6 +260,36 @@ 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; |
+ } |
+ |
+ // Compute the intersection of two (infinite) Lines. |
+ bool intersect(const Line& other, SkPoint* point) { |
+ double denom = fA * other.fB - fB * other.fA; |
+ if (denom == 0.0) { |
+ return false; |
+ } |
+ double scale = 1.0f / denom; |
+ point->fX = SkDoubleToScalar((fB * other.fC - other.fB * fC) * scale); |
+ point->fY = SkDoubleToScalar((other.fA * fC - fA * other.fC) * scale); |
+ round(point); |
+ return true; |
+ } |
+ 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 +326,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 +346,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 +366,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 +382,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; |
} |
}; |
@@ -1423,22 +1448,9 @@ Vertex* remove_non_boundary_edges(Vertex* vertices, SkPath::FillType fillType, |
return vertices; |
} |
-// This is different from Edge::intersect, in that it intersects lines, not line segments. |
-bool intersect(const Edge& a, const Edge& b, SkPoint* point) { |
- double denom = a.fDX * b.fDY - a.fDY * b.fDX; |
- 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); |
- 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,24 +1497,23 @@ 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) && |
- intersect(prevOuter, outer, &outerPoint)) { |
+ if (prevInner.intersect(inner, &innerPoint) && |
+ prevOuter.intersect(outer, &outerPoint)) { |
Vertex* innerVertex = ALLOC_NEW(Vertex, (innerPoint, 255), alloc); |
Vertex* outerVertex = ALLOC_NEW(Vertex, (outerPoint, 0), alloc); |
if (innerVertices.fTail && outerVertices.fTail) { |