remove LEGACY_CONVEXITY code -- no more clients
Change-Id: Ifd33831b6a83a56685435ce8e4fbb218a147b34e Reviewed-on: https://skia-review.googlesource.com/c/skia/+/255981 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com>
This commit is contained in:
parent
189c98042f
commit
8ee77d8f42
@ -1959,288 +1959,6 @@ bool SkPath::isValidImpl() const {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef SK_LEGACY_PATH_CONVEXITY // for rebaselining Chrome
|
||||
|
||||
static int sign(SkScalar x) { return x < 0; }
|
||||
#define kValueNeverReturnedBySign 2
|
||||
|
||||
enum DirChange {
|
||||
kLeft_DirChange,
|
||||
kRight_DirChange,
|
||||
kStraight_DirChange,
|
||||
kBackwards_DirChange,
|
||||
|
||||
kInvalid_DirChange
|
||||
};
|
||||
|
||||
|
||||
static bool almost_equal(SkScalar compA, SkScalar compB) {
|
||||
// The error epsilon was empirically derived; worse case round rects
|
||||
// with a mid point outset by 2x float epsilon in tests had an error
|
||||
// of 12.
|
||||
const int epsilon = 16;
|
||||
if (!SkScalarIsFinite(compA) || !SkScalarIsFinite(compB)) {
|
||||
return false;
|
||||
}
|
||||
// no need to check for small numbers because SkPath::Iter has removed degenerate values
|
||||
int aBits = SkFloatAs2sCompliment(compA);
|
||||
int bBits = SkFloatAs2sCompliment(compB);
|
||||
return aBits < bBits + epsilon && bBits < aBits + epsilon;
|
||||
}
|
||||
|
||||
// only valid for a single contour
|
||||
struct Convexicator {
|
||||
Convexicator()
|
||||
: fPtCount(0)
|
||||
, fConvexity(SkPath::kConvex_Convexity)
|
||||
, fFirstDirection(SkPathPriv::kUnknown_FirstDirection)
|
||||
, fIsFinite(true)
|
||||
, fIsCurve(false)
|
||||
, fBackwards(false) {
|
||||
fExpectedDir = kInvalid_DirChange;
|
||||
// warnings
|
||||
fPriorPt.set(0,0);
|
||||
fLastPt.set(0, 0);
|
||||
fCurrPt.set(0, 0);
|
||||
fLastVec.set(0, 0);
|
||||
fFirstVec.set(0, 0);
|
||||
|
||||
fDx = fDy = 0;
|
||||
fSx = fSy = kValueNeverReturnedBySign;
|
||||
}
|
||||
|
||||
SkPath::Convexity getConvexity() const { return fConvexity; }
|
||||
|
||||
/** The direction returned is only valid if the path is determined convex */
|
||||
SkPathPriv::FirstDirection getFirstDirection() const { return fFirstDirection; }
|
||||
|
||||
void addPt(const SkPoint& pt) {
|
||||
if (SkPath::kConcave_Convexity == fConvexity || !fIsFinite) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == fPtCount) {
|
||||
fCurrPt = pt;
|
||||
++fPtCount;
|
||||
} else {
|
||||
SkVector vec = pt - fCurrPt;
|
||||
SkScalar lengthSqd = SkPointPriv::LengthSqd(vec);
|
||||
if (!SkScalarIsFinite(lengthSqd)) {
|
||||
fIsFinite = false;
|
||||
} else if (lengthSqd) {
|
||||
fPriorPt = fLastPt;
|
||||
fLastPt = fCurrPt;
|
||||
fCurrPt = pt;
|
||||
if (++fPtCount == 2) {
|
||||
fFirstVec = fLastVec = vec;
|
||||
} else {
|
||||
SkASSERT(fPtCount > 2);
|
||||
this->addVec(vec);
|
||||
}
|
||||
|
||||
int sx = sign(vec.fX);
|
||||
int sy = sign(vec.fY);
|
||||
fDx += (sx != fSx);
|
||||
fDy += (sy != fSy);
|
||||
fSx = sx;
|
||||
fSy = sy;
|
||||
|
||||
if (fDx > 3 || fDy > 3) {
|
||||
fConvexity = SkPath::kConcave_Convexity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close() {
|
||||
if (fPtCount > 2) {
|
||||
this->addVec(fFirstVec);
|
||||
}
|
||||
}
|
||||
|
||||
DirChange directionChange(const SkVector& curVec) {
|
||||
SkScalar cross = SkPoint::CrossProduct(fLastVec, curVec);
|
||||
|
||||
SkScalar smallest = SkTMin(fCurrPt.fX, SkTMin(fCurrPt.fY, SkTMin(fLastPt.fX, fLastPt.fY)));
|
||||
SkScalar largest = SkTMax(fCurrPt.fX, SkTMax(fCurrPt.fY, SkTMax(fLastPt.fX, fLastPt.fY)));
|
||||
largest = SkTMax(largest, -smallest);
|
||||
|
||||
if (!almost_equal(largest, largest + cross)) {
|
||||
int sign = SkScalarSignAsInt(cross);
|
||||
if (sign) {
|
||||
return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
|
||||
}
|
||||
}
|
||||
|
||||
if (cross) {
|
||||
double dLastVecX = SkScalarToDouble(fLastPt.fX) - SkScalarToDouble(fPriorPt.fX);
|
||||
double dLastVecY = SkScalarToDouble(fLastPt.fY) - SkScalarToDouble(fPriorPt.fY);
|
||||
double dCurrVecX = SkScalarToDouble(fCurrPt.fX) - SkScalarToDouble(fLastPt.fX);
|
||||
double dCurrVecY = SkScalarToDouble(fCurrPt.fY) - SkScalarToDouble(fLastPt.fY);
|
||||
double dCross = dLastVecX * dCurrVecY - dLastVecY * dCurrVecX;
|
||||
if (!approximately_zero_when_compared_to(dCross, SkScalarToDouble(largest))) {
|
||||
int sign = SkScalarSignAsInt(SkDoubleToScalar(dCross));
|
||||
if (sign) {
|
||||
return (1 == sign) ? kRight_DirChange : kLeft_DirChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!SkScalarNearlyZero(SkPointPriv::LengthSqd(fLastVec),
|
||||
SK_ScalarNearlyZero*SK_ScalarNearlyZero) &&
|
||||
!SkScalarNearlyZero(SkPointPriv::LengthSqd(curVec),
|
||||
SK_ScalarNearlyZero*SK_ScalarNearlyZero) &&
|
||||
fLastVec.dot(curVec) < 0.0f) {
|
||||
return kBackwards_DirChange;
|
||||
}
|
||||
|
||||
return kStraight_DirChange;
|
||||
}
|
||||
|
||||
bool hasBackwards() const {
|
||||
return fBackwards;
|
||||
}
|
||||
|
||||
bool isFinite() const {
|
||||
return fIsFinite;
|
||||
}
|
||||
|
||||
void setCurve(bool isCurve) {
|
||||
fIsCurve = isCurve;
|
||||
}
|
||||
|
||||
private:
|
||||
void addVec(const SkVector& vec) {
|
||||
SkASSERT(vec.fX || vec.fY);
|
||||
DirChange dir = this->directionChange(vec);
|
||||
switch (dir) {
|
||||
case kLeft_DirChange: // fall through
|
||||
case kRight_DirChange:
|
||||
if (kInvalid_DirChange == fExpectedDir) {
|
||||
fExpectedDir = dir;
|
||||
fFirstDirection = (kRight_DirChange == dir) ? SkPathPriv::kCW_FirstDirection
|
||||
: SkPathPriv::kCCW_FirstDirection;
|
||||
} else if (dir != fExpectedDir) {
|
||||
fConvexity = SkPath::kConcave_Convexity;
|
||||
fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
|
||||
}
|
||||
fLastVec = vec;
|
||||
break;
|
||||
case kStraight_DirChange:
|
||||
break;
|
||||
case kBackwards_DirChange:
|
||||
if (fIsCurve) {
|
||||
// If any of the subsequent dir is non-backward, it'll be concave.
|
||||
// Otherwise, it's still convex.
|
||||
fExpectedDir = dir;
|
||||
}
|
||||
fLastVec = vec;
|
||||
fBackwards = true;
|
||||
break;
|
||||
case kInvalid_DirChange:
|
||||
SK_ABORT("Use of invalid direction change flag");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SkPoint fPriorPt;
|
||||
SkPoint fLastPt;
|
||||
SkPoint fCurrPt;
|
||||
// fLastVec does not necessarily start at fLastPt. We only advance it when the cross product
|
||||
// value with the current vec is deemed to be of a significant value.
|
||||
SkVector fLastVec, fFirstVec;
|
||||
int fPtCount; // non-degenerate points
|
||||
DirChange fExpectedDir;
|
||||
SkPath::Convexity fConvexity;
|
||||
SkPathPriv::FirstDirection fFirstDirection;
|
||||
int fDx, fDy, fSx, fSy;
|
||||
bool fIsFinite;
|
||||
bool fIsCurve;
|
||||
bool fBackwards;
|
||||
};
|
||||
|
||||
SkPath::Convexity SkPath::internalGetConvexity() const {
|
||||
// Sometimes we think we need to calculate convexity but another thread already did.
|
||||
auto c = this->getConvexityOrUnknown();
|
||||
if (c != kUnknown_Convexity) {
|
||||
return c;
|
||||
}
|
||||
|
||||
SkPoint pts[4];
|
||||
SkPath::Verb verb;
|
||||
SkPath::Iter iter(*this, true);
|
||||
|
||||
int contourCount = 0;
|
||||
int count;
|
||||
Convexicator state;
|
||||
|
||||
if (!isFinite()) {
|
||||
return kUnknown_Convexity;
|
||||
}
|
||||
while ((verb = iter.next(pts, false, false)) != SkPath::kDone_Verb) {
|
||||
switch (verb) {
|
||||
case kMove_Verb:
|
||||
if (++contourCount > 1) {
|
||||
this->setConvexity(kConcave_Convexity);
|
||||
return kConcave_Convexity;
|
||||
}
|
||||
pts[1] = pts[0];
|
||||
// fall through
|
||||
case kLine_Verb:
|
||||
count = 1;
|
||||
state.setCurve(false);
|
||||
break;
|
||||
case kQuad_Verb:
|
||||
// fall through
|
||||
case kConic_Verb:
|
||||
// fall through
|
||||
case kCubic_Verb:
|
||||
count = 2 + (kCubic_Verb == verb);
|
||||
// As an additional enhancement, this could set curve true only
|
||||
// if the curve is nonlinear
|
||||
state.setCurve(true);
|
||||
break;
|
||||
case kClose_Verb:
|
||||
state.setCurve(false);
|
||||
state.close();
|
||||
count = 0;
|
||||
break;
|
||||
default:
|
||||
SkDEBUGFAIL("bad verb");
|
||||
this->setConvexity(kConcave_Convexity);
|
||||
return kConcave_Convexity;
|
||||
}
|
||||
|
||||
for (int i = 1; i <= count; i++) {
|
||||
state.addPt(pts[i]);
|
||||
}
|
||||
// early exit
|
||||
if (!state.isFinite()) {
|
||||
return kUnknown_Convexity;
|
||||
}
|
||||
if (kConcave_Convexity == state.getConvexity()) {
|
||||
this->setConvexity(kConcave_Convexity);
|
||||
return kConcave_Convexity;
|
||||
}
|
||||
}
|
||||
this->setConvexity(state.getConvexity());
|
||||
|
||||
if (this->getConvexityOrUnknown() == kConvex_Convexity &&
|
||||
this->getFirstDirection() == SkPathPriv::kUnknown_FirstDirection) {
|
||||
|
||||
if (state.getFirstDirection() == SkPathPriv::kUnknown_FirstDirection
|
||||
&& !this->getBounds().isEmpty()
|
||||
&& !state.hasBackwards()) {
|
||||
this->setConvexity(Convexity::kConcave_Convexity);
|
||||
} else {
|
||||
this->setFirstDirection(state.getFirstDirection());
|
||||
}
|
||||
}
|
||||
return this->getConvexityOrUnknown();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int sign(SkScalar x) { return x < 0; }
|
||||
#define kValueNeverReturnedBySign 2
|
||||
|
||||
@ -2522,8 +2240,6 @@ bool SkPathPriv::IsConvex(const SkPoint points[], int count) {
|
||||
|| state.reversals() < 3;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ContourIter {
|
||||
|
@ -158,7 +158,6 @@ public:
|
||||
return path.fPathRef->conicWeights();
|
||||
}
|
||||
|
||||
#ifndef SK_LEGACY_PATH_CONVEXITY
|
||||
/** Returns true if path formed by pts is convex.
|
||||
|
||||
@param pts SkPoint array of path
|
||||
@ -167,7 +166,6 @@ public:
|
||||
@return true if pts represent a convex geometry
|
||||
*/
|
||||
static bool IsConvex(const SkPoint pts[], int count);
|
||||
#endif
|
||||
|
||||
/** Returns true if the underlying SkPathRef has one single owner. */
|
||||
static bool TestingOnly_unique(const SkPath& path) {
|
||||
|
@ -1321,7 +1321,7 @@ static void check_convexity(skiatest::Reporter* reporter, const SkPath& path,
|
||||
SkPath copy(path); // we make a copy so that we don't cache the result on the passed in path.
|
||||
SkPath::Convexity c = copy.getConvexity();
|
||||
REPORTER_ASSERT(reporter, c == expected);
|
||||
#ifndef SK_LEGACY_PATH_CONVEXITY
|
||||
|
||||
// test points-by-array interface
|
||||
SkPath::Iter iter(path, true);
|
||||
int initialMoves = 0;
|
||||
@ -1337,7 +1337,6 @@ static void check_convexity(skiatest::Reporter* reporter, const SkPath& path,
|
||||
bool isConvex = SkPathPriv::IsConvex(&points.front() + skip, points.size() - skip);
|
||||
REPORTER_ASSERT(reporter, isConvex == (SkPath::kConvex_Convexity == expected));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_path_crbug389050(skiatest::Reporter* reporter) {
|
||||
|
Loading…
Reference in New Issue
Block a user