Rip out variable offsetting
Bug: skia:
Change-Id: I0ca1f3b60d05ce02d1e53bb8b989c9dc1babddd1
Reviewed-on: https://skia-review.googlesource.com/150915
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/utils/SkPolyUtils.cpp b/src/utils/SkPolyUtils.cpp
index 8d378f5..06e8546 100644
--- a/src/utils/SkPolyUtils.cpp
+++ b/src/utils/SkPolyUtils.cpp
@@ -58,65 +58,14 @@
return (quadArea > 0) ? 1 : -1;
}
-// Helper function to compute the individual vector for non-equal offsets
-inline void compute_offset(SkScalar d, const SkPoint& polyPoint, int side,
- const SkPoint& outerTangentIntersect, SkVector* v) {
- SkScalar dsq = d * d;
- SkVector dP = outerTangentIntersect - polyPoint;
- SkScalar dPlenSq = SkPointPriv::LengthSqd(dP);
- if (SkScalarNearlyZero(dPlenSq, SK_ScalarNearlyZero*SK_ScalarNearlyZero)) {
- v->set(0, 0);
- } else {
- SkScalar discrim = SkScalarSqrt(dPlenSq - dsq);
- v->fX = (dsq*dP.fX - side * d*dP.fY*discrim) / dPlenSq;
- v->fY = (dsq*dP.fY + side * d*dP.fX*discrim) / dPlenSq;
- }
-}
-
-// Compute difference vector to offset p0-p1 'd0' and 'd1' units in direction specified by 'side'
-bool compute_offset_vectors(const SkPoint& p0, const SkPoint& p1, SkScalar d0, SkScalar d1,
- int side, SkPoint* vector0, SkPoint* vector1) {
+// Compute difference vector to offset p0-p1 'offset' units in direction specified by 'side'
+void compute_offset_vector(const SkPoint& p0, const SkPoint& p1, SkScalar offset, int side,
+ SkPoint* vector) {
SkASSERT(side == -1 || side == 1);
- if (SkScalarNearlyEqual(d0, d1)) {
- // if distances are equal, can just outset by the perpendicular
- SkVector perp = SkVector::Make(p0.fY - p1.fY, p1.fX - p0.fX);
- perp.setLength(d0*side);
- *vector0 = perp;
- *vector1 = perp;
- } else {
- SkScalar d0abs = SkTAbs(d0);
- SkScalar d1abs = SkTAbs(d1);
- // Otherwise we need to compute the outer tangent.
- // See: http://www.ambrsoft.com/TrigoCalc/Circles2/Circles2Tangent_.htm
- if (d0abs < d1abs) {
- side = -side;
- }
- SkScalar dD = d0abs - d1abs;
- // if one circle is inside another, we can't compute an offset
- if (dD*dD >= SkPointPriv::DistanceToSqd(p0, p1)) {
- return false;
- }
- SkPoint outerTangentIntersect = SkPoint::Make((p1.fX*d0abs - p0.fX*d1abs) / dD,
- (p1.fY*d0abs - p0.fY*d1abs) / dD);
-
- compute_offset(d0, p0, side, outerTangentIntersect, vector0);
- compute_offset(d1, p1, side, outerTangentIntersect, vector1);
- }
-
- return true;
-}
-
-// Offset line segment p0-p1 'd0' and 'd1' units in the direction specified by 'side'
-bool SkOffsetSegment(const SkPoint& p0, const SkPoint& p1, SkScalar d0, SkScalar d1,
- int side, SkPoint* offset0, SkPoint* offset1) {
- SkVector v0, v1;
- if (!compute_offset_vectors(p0, p1, d0, d1, side, &v0, &v1)) {
- return false;
- }
- *offset0 = p0 + v0;
- *offset1 = p1 + v1;
-
- return true;
+ // if distances are equal, can just outset by the perpendicular
+ SkVector perp = SkVector::Make(p0.fY - p1.fY, p1.fX - p0.fX);
+ perp.setLength(offset*side);
+ *vector = perp;
}
// check interval to see if intersection is in segment
@@ -269,14 +218,14 @@
struct OffsetEdge {
OffsetEdge* fPrev;
OffsetEdge* fNext;
- OffsetSegment fInset;
+ OffsetSegment fOffset;
SkPoint fIntersection;
SkScalar fTValue;
uint16_t fIndex;
uint16_t fEnd;
void init(uint16_t start = 0, uint16_t end = 0) {
- fIntersection = fInset.fP0;
+ fIntersection = fOffset.fP0;
fTValue = SK_ScalarMin;
fIndex = start;
fEnd = end;
@@ -286,8 +235,8 @@
bool checkIntersection(const OffsetEdge* that,
SkPoint* p, SkScalar* s, SkScalar* t) {
if (this->fEnd == that->fIndex) {
- SkPoint p1 = this->fInset.fP0 + this->fInset.fV;
- if (SkPointPriv::EqualsWithinTolerance(p1, that->fInset.fP0)) {
+ SkPoint p1 = this->fOffset.fP0 + this->fOffset.fV;
+ if (SkPointPriv::EqualsWithinTolerance(p1, that->fOffset.fP0)) {
*p = p1;
*s = SK_Scalar1;
*t = 0;
@@ -295,15 +244,15 @@
}
}
- return compute_intersection(this->fInset, that->fInset, p, s, t);
+ return compute_intersection(this->fOffset, that->fOffset, p, s, t);
}
// computes the line intersection and then the "distance" from that to this
// this is really a signed squared distance, where negative means that
- // the intersection lies inside this->fInset
+ // the intersection lies inside this->fOffset
SkScalar computeCrossingDistance(const OffsetEdge* that) {
- const OffsetSegment& s0 = this->fInset;
- const OffsetSegment& s1 = that->fInset;
+ const OffsetSegment& s0 = this->fOffset;
+ const OffsetSegment& s1 = that->fOffset;
const SkVector& v0 = s0.fV;
const SkVector& v1 = s1.fV;
@@ -353,8 +302,7 @@
// Note: the assumption is that inputPolygon is convex and has no coincident points.
//
bool SkInsetConvexPolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize,
- std::function<SkScalar(const SkPoint&)> insetDistanceFunc,
- SkTDArray<SkPoint>* insetPolygon) {
+ SkScalar inset, SkTDArray<SkPoint>* insetPolygon) {
if (inputPolygonSize < 3) {
return false;
}
@@ -384,18 +332,13 @@
inputPolygonVerts[next])*winding < 0) {
return false;
}
- SkPoint p0, p1;
- if (!SkOffsetSegment(inputPolygonVerts[curr], inputPolygonVerts[next],
- insetDistanceFunc(inputPolygonVerts[curr]),
- insetDistanceFunc(inputPolygonVerts[next]),
- winding,
- &p0, &p1)) {
- return false;
- }
+ SkVector v = inputPolygonVerts[next] - inputPolygonVerts[curr];
+ SkVector perp = SkVector::Make(-v.fY, v.fX);
+ perp.setLength(inset*winding);
edgeData[curr].fPrev = &edgeData[prev];
edgeData[curr].fNext = &edgeData[next];
- edgeData[curr].fInset.fP0 = p0;
- edgeData[curr].fInset.fV = p1 - p0;
+ edgeData[curr].fOffset.fP0 = inputPolygonVerts[curr] + perp;
+ edgeData[curr].fOffset.fV = v;
edgeData[curr].init();
}
@@ -413,7 +356,7 @@
SkScalar s, t;
SkPoint intersection;
- if (compute_intersection(prevEdge->fInset, currEdge->fInset,
+ if (compute_intersection(prevEdge->fOffset, currEdge->fOffset,
&intersection, &s, &t)) {
// if new intersection is further back on previous inset from the prior intersection
if (s < prevEdge->fTValue) {
@@ -439,13 +382,13 @@
}
} else {
// if prev to right side of curr
- int side = winding*compute_side(currEdge->fInset.fP0,
- currEdge->fInset.fV,
- prevEdge->fInset.fP0);
+ int side = winding*compute_side(currEdge->fOffset.fP0,
+ currEdge->fOffset.fV,
+ prevEdge->fOffset.fP0);
if (side < 0 &&
- side == winding*compute_side(currEdge->fInset.fP0,
- currEdge->fInset.fV,
- prevEdge->fInset.fP0 + prevEdge->fInset.fV)) {
+ side == winding*compute_side(currEdge->fOffset.fP0,
+ currEdge->fOffset.fV,
+ prevEdge->fOffset.fP0 + prevEdge->fOffset.fV)) {
// no point in considering this one again
remove_node(prevEdge, &head);
--insetVertexCount;
@@ -1165,8 +1108,8 @@
static void setup_offset_edge(OffsetEdge* currEdge,
const SkPoint& endpoint0, const SkPoint& endpoint1,
uint16_t startIndex, uint16_t endIndex) {
- currEdge->fInset.fP0 = endpoint0;
- currEdge->fInset.fV = endpoint1 - endpoint0;
+ currEdge->fOffset.fP0 = endpoint0;
+ currEdge->fOffset.fV = endpoint1 - endpoint0;
currEdge->init(startIndex, endIndex);
}
@@ -1179,8 +1122,7 @@
return (side*winding*offset < 0);
}
-bool SkOffsetSimplePolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize,
- std::function<SkScalar(const SkPoint&)> offsetDistanceFunc,
+bool SkOffsetSimplePolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize, SkScalar offset,
SkTDArray<SkPoint>* offsetPolygon, SkTDArray<int>* polygonIndices) {
if (inputPolygonSize < 3) {
return false;
@@ -1191,6 +1133,10 @@
return false;
}
+ if (!SkScalarIsFinite(offset)) {
+ return false;
+ }
+
// get winding direction
int winding = SkGetPolygonWinding(inputPolygonVerts, inputPolygonSize);
if (0 == winding) {
@@ -1198,14 +1144,7 @@
}
// build normals
- SkAutoSTMalloc<64, SkVector> normal0(inputPolygonSize);
- SkAutoSTMalloc<64, SkVector> normal1(inputPolygonSize);
- SkAutoSTMalloc<64, SkScalar> offset(inputPolygonSize);
- SkScalar currOffset = offsetDistanceFunc(inputPolygonVerts[0]);
- if (!SkScalarIsFinite(currOffset)) {
- return false;
- }
- offset[0] = currOffset;
+ SkAutoSTMalloc<64, SkVector> normals(inputPolygonSize);
int numEdges = 0;
for (int currIndex = 0, prevIndex = inputPolygonSize - 1;
currIndex < inputPolygonSize;
@@ -1214,23 +1153,15 @@
return false;
}
int nextIndex = (currIndex + 1) % inputPolygonSize;
- SkScalar nextOffset = offsetDistanceFunc(inputPolygonVerts[nextIndex]);
- if (!SkScalarIsFinite(nextOffset)) {
- return false;
- }
- offset[nextIndex] = nextOffset;
- if (!compute_offset_vectors(inputPolygonVerts[currIndex], inputPolygonVerts[nextIndex],
- currOffset, nextOffset, winding,
- &normal0[currIndex], &normal1[nextIndex])) {
- return false;
- }
+ compute_offset_vector(inputPolygonVerts[currIndex], inputPolygonVerts[nextIndex],
+ offset, winding, &normals[currIndex]);
if (currIndex > 0) {
// if reflex point, we need to add extra edges
- if (is_reflex_vertex(inputPolygonVerts, winding, currOffset,
+ if (is_reflex_vertex(inputPolygonVerts, winding, offset,
prevIndex, currIndex, nextIndex)) {
SkScalar rotSin, rotCos;
int numSteps;
- if (!SkComputeRadialSteps(normal1[currIndex], normal0[currIndex], currOffset,
+ if (!SkComputeRadialSteps(normals[prevIndex], normals[currIndex], offset,
&rotSin, &rotCos, &numSteps)) {
return false;
}
@@ -1238,13 +1169,12 @@
}
}
numEdges++;
- currOffset = nextOffset;
}
// finish up the edge counting
- if (is_reflex_vertex(inputPolygonVerts, winding, currOffset, inputPolygonSize-1, 0, 1)) {
+ if (is_reflex_vertex(inputPolygonVerts, winding, offset, inputPolygonSize-1, 0, 1)) {
SkScalar rotSin, rotCos;
int numSteps;
- if (!SkComputeRadialSteps(normal1[0], normal0[0], currOffset,
+ if (!SkComputeRadialSteps(normals[inputPolygonSize-1], normals[0], offset,
&rotSin, &rotCos, &numSteps)) {
return false;
}
@@ -1259,12 +1189,12 @@
prevIndex = currIndex, ++currIndex) {
int nextIndex = (currIndex + 1) % inputPolygonSize;
// if reflex point, fill in curve
- if (is_reflex_vertex(inputPolygonVerts, winding, offset[currIndex],
+ if (is_reflex_vertex(inputPolygonVerts, winding, offset,
prevIndex, currIndex, nextIndex)) {
SkScalar rotSin, rotCos;
int numSteps;
- SkVector prevNormal = normal1[currIndex];
- if (!SkComputeRadialSteps(prevNormal, normal0[currIndex], offset[currIndex],
+ SkVector prevNormal = normals[prevIndex];
+ if (!SkComputeRadialSteps(prevNormal, normals[currIndex], offset,
&rotSin, &rotCos, &numSteps)) {
return false;
}
@@ -1286,7 +1216,7 @@
}
setup_offset_edge(currEdge,
inputPolygonVerts[currIndex] + prevNormal,
- inputPolygonVerts[currIndex] + normal0[currIndex],
+ inputPolygonVerts[currIndex] + normals[currIndex],
currIndex, currIndex);
currEdge->fPrev = prevEdge;
if (prevEdge) {
@@ -1298,8 +1228,8 @@
// Add the edge
auto currEdge = edgeData.push_back_n(1);
setup_offset_edge(currEdge,
- inputPolygonVerts[currIndex] + normal0[currIndex],
- inputPolygonVerts[nextIndex] + normal1[nextIndex],
+ inputPolygonVerts[currIndex] + normals[currIndex],
+ inputPolygonVerts[nextIndex] + normals[currIndex],
currIndex, nextIndex);
currEdge->fPrev = prevEdge;
if (prevEdge) {
@@ -1361,12 +1291,12 @@
// if both lead to direct collision
if (dist0 < 0 && dist1 < 0) {
// check first to see if either represent parts of one contour
- SkPoint p1 = prevPrevEdge->fInset.fP0 + prevPrevEdge->fInset.fV;
+ SkPoint p1 = prevPrevEdge->fOffset.fP0 + prevPrevEdge->fOffset.fV;
bool prevSameContour = SkPointPriv::EqualsWithinTolerance(p1,
- prevEdge->fInset.fP0);
- p1 = currEdge->fInset.fP0 + currEdge->fInset.fV;
+ prevEdge->fOffset.fP0);
+ p1 = currEdge->fOffset.fP0 + currEdge->fOffset.fV;
bool currSameContour = SkPointPriv::EqualsWithinTolerance(p1,
- currNextEdge->fInset.fP0);
+ currNextEdge->fOffset.fP0);
// want to step along contour to find intersections rather than jump to new one
if (currSameContour && !prevSameContour) {