Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Unified Diff: src/gpu/GrTessellator.cpp

Issue 2397963003: GrTessellator: refactor Line out of Edge. (Closed)
Patch Set: Move intersect() into Line. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698