From 8f4e924181f4898bf7e4268bddd5ce85e3418121 Mon Sep 17 00:00:00 2001 From: Mike Reed Date: Fri, 21 May 2021 11:00:36 -0400 Subject: [PATCH] Move class into impl I think this finishes all public subclasses, so we can proceed next with moving the virtuals themselves to a private subclass. Change-Id: I490f3cf6497a6bdcafc1ce756cfdeb32eab18585 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/411239 Reviewed-by: Tyler Denniston Commit-Queue: Mike Reed --- include/effects/SkCornerPathEffect.h | 27 +- include/effects/SkDiscretePathEffect.h | 20 +- src/effects/SkCornerPathEffect.cpp | 247 ++++++++++--------- src/effects/SkDiscretePathEffect.cpp | 190 +++++++------- src/ports/SkGlobalInitialization_default.cpp | 4 +- 5 files changed, 245 insertions(+), 243 deletions(-) diff --git a/include/effects/SkCornerPathEffect.h b/include/effects/SkCornerPathEffect.h index dbd59a36db..6017df46ac 100644 --- a/include/effects/SkCornerPathEffect.h +++ b/include/effects/SkCornerPathEffect.h @@ -8,7 +8,6 @@ #ifndef SkCornerPathEffect_DEFINED #define SkCornerPathEffect_DEFINED -#include "include/core/SkFlattenable.h" #include "include/core/SkPathEffect.h" /** \class SkCornerPathEffect @@ -16,34 +15,14 @@ SkCornerPathEffect is a subclass of SkPathEffect that can turn sharp corners into various treatments (e.g. rounded corners) */ -class SK_API SkCornerPathEffect : public SkPathEffect { +class SK_API SkCornerPathEffect { public: /** radius must be > 0 to have an effect. It specifies the distance from each corner that should be "rounded". */ - static sk_sp Make(SkScalar radius) { - return radius > 0 ? sk_sp(new SkCornerPathEffect(radius)) : nullptr; - } + static sk_sp Make(SkScalar radius); -protected: - ~SkCornerPathEffect() override; - - explicit SkCornerPathEffect(SkScalar radius); - void flatten(SkWriteBuffer&) const override; - bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override; - -private: - SK_FLATTENABLE_HOOKS(SkCornerPathEffect) - - bool computeFastBounds(SkRect*) const override { - // Rounding sharp corners within a path produces a new path that is still contained within - // the original's bounds, so leave 'bounds' unmodified. - return true; - } - - SkScalar fRadius; - - using INHERITED = SkPathEffect; + static void RegisterFlattenables(); }; #endif diff --git a/include/effects/SkDiscretePathEffect.h b/include/effects/SkDiscretePathEffect.h index 7f607689cf..542536fb05 100644 --- a/include/effects/SkDiscretePathEffect.h +++ b/include/effects/SkDiscretePathEffect.h @@ -8,7 +8,6 @@ #ifndef SkDiscretePathEffect_DEFINED #define SkDiscretePathEffect_DEFINED -#include "include/core/SkFlattenable.h" #include "include/core/SkPathEffect.h" /** \class SkDiscretePathEffect @@ -32,24 +31,7 @@ public: */ static sk_sp Make(SkScalar segLength, SkScalar dev, uint32_t seedAssist = 0); -protected: - SkDiscretePathEffect(SkScalar segLength, - SkScalar deviation, - uint32_t seedAssist); - void flatten(SkWriteBuffer&) const override; - bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override; - -private: - SK_FLATTENABLE_HOOKS(SkDiscretePathEffect) - - bool computeFastBounds(SkRect* bounds) const override; - - SkScalar fSegLength, fPerterb; - - /* Caller-supplied 32 bit seed assist */ - uint32_t fSeedAssist; - - using INHERITED = SkPathEffect; + static void RegisterFlattenables(); }; #endif diff --git a/src/effects/SkCornerPathEffect.cpp b/src/effects/SkCornerPathEffect.cpp index 16670e55e9..678853743c 100644 --- a/src/effects/SkCornerPathEffect.cpp +++ b/src/effects/SkCornerPathEffect.cpp @@ -12,15 +12,6 @@ #include "src/core/SkReadBuffer.h" #include "src/core/SkWriteBuffer.h" -SkCornerPathEffect::SkCornerPathEffect(SkScalar radius) { - // check with ! to catch NaNs - if (!(radius > 0)) { - radius = 0; - } - fRadius = radius; -} -SkCornerPathEffect::~SkCornerPathEffect() {} - static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, SkPoint* step) { SkScalar dist = SkPoint::Distance(a, b); @@ -35,122 +26,152 @@ static bool ComputeStep(const SkPoint& a, const SkPoint& b, SkScalar radius, } } -bool SkCornerPathEffect::onFilterPath(SkPath* dst, const SkPath& src, - SkStrokeRec*, const SkRect*) const { - if (fRadius <= 0) { - return false; +class SkCornerPathEffectImpl : public SkPathEffect { +public: + explicit SkCornerPathEffectImpl(SkScalar radius) : fRadius(radius) { + SkASSERT(radius > 0); } - SkPath::Iter iter(src, false); - SkPath::Verb verb, prevVerb = SkPath::kDone_Verb; - SkPoint pts[4]; + bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const override { + if (fRadius <= 0) { + return false; + } - bool closed; - SkPoint moveTo, lastCorner; - SkVector firstStep, step; - bool prevIsValid = true; + SkPath::Iter iter(src, false); + SkPath::Verb verb, prevVerb = SkPath::kDone_Verb; + SkPoint pts[4]; - // to avoid warnings - step.set(0, 0); - moveTo.set(0, 0); - firstStep.set(0, 0); - lastCorner.set(0, 0); + bool closed; + SkPoint moveTo, lastCorner; + SkVector firstStep, step; + bool prevIsValid = true; - for (;;) { - switch (verb = iter.next(pts)) { - case SkPath::kMove_Verb: - // close out the previous (open) contour - if (SkPath::kLine_Verb == prevVerb) { - dst->lineTo(lastCorner); + // to avoid warnings + step.set(0, 0); + moveTo.set(0, 0); + firstStep.set(0, 0); + lastCorner.set(0, 0); + + for (;;) { + switch (verb = iter.next(pts)) { + case SkPath::kMove_Verb: + // close out the previous (open) contour + if (SkPath::kLine_Verb == prevVerb) { + dst->lineTo(lastCorner); + } + closed = iter.isClosedContour(); + if (closed) { + moveTo = pts[0]; + prevIsValid = false; + } else { + dst->moveTo(pts[0]); + prevIsValid = true; + } + break; + case SkPath::kLine_Verb: { + bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); + // prev corner + if (!prevIsValid) { + dst->moveTo(moveTo + step); + prevIsValid = true; + } else { + dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, + pts[0].fY + step.fY); + } + if (drawSegment) { + dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); + } + lastCorner = pts[1]; + prevIsValid = true; + break; } - closed = iter.isClosedContour(); - if (closed) { - moveTo = pts[0]; + case SkPath::kQuad_Verb: + // TBD - just replicate the curve for now + if (!prevIsValid) { + dst->moveTo(pts[0]); + prevIsValid = true; + } + dst->quadTo(pts[1], pts[2]); + lastCorner = pts[2]; + firstStep.set(0, 0); + break; + case SkPath::kConic_Verb: + // TBD - just replicate the curve for now + if (!prevIsValid) { + dst->moveTo(pts[0]); + prevIsValid = true; + } + dst->conicTo(pts[1], pts[2], iter.conicWeight()); + lastCorner = pts[2]; + firstStep.set(0, 0); + break; + case SkPath::kCubic_Verb: + if (!prevIsValid) { + dst->moveTo(pts[0]); + prevIsValid = true; + } + // TBD - just replicate the curve for now + dst->cubicTo(pts[1], pts[2], pts[3]); + lastCorner = pts[3]; + firstStep.set(0, 0); + break; + case SkPath::kClose_Verb: + if (firstStep.fX || firstStep.fY) { + dst->quadTo(lastCorner.fX, lastCorner.fY, + lastCorner.fX + firstStep.fX, + lastCorner.fY + firstStep.fY); + } + dst->close(); prevIsValid = false; - } else { - dst->moveTo(pts[0]); - prevIsValid = true; - } - break; - case SkPath::kLine_Verb: { - bool drawSegment = ComputeStep(pts[0], pts[1], fRadius, &step); - // prev corner - if (!prevIsValid) { - dst->moveTo(moveTo + step); - prevIsValid = true; - } else { - dst->quadTo(pts[0].fX, pts[0].fY, pts[0].fX + step.fX, - pts[0].fY + step.fY); - } - if (drawSegment) { - dst->lineTo(pts[1].fX - step.fX, pts[1].fY - step.fY); - } - lastCorner = pts[1]; - prevIsValid = true; - break; + break; + case SkPath::kDone_Verb: + if (prevIsValid) { + dst->lineTo(lastCorner); + } + return true; + default: + SkDEBUGFAIL("default should not be reached"); + return false; } - case SkPath::kQuad_Verb: - // TBD - just replicate the curve for now - if (!prevIsValid) { - dst->moveTo(pts[0]); - prevIsValid = true; - } - dst->quadTo(pts[1], pts[2]); - lastCorner = pts[2]; - firstStep.set(0, 0); - break; - case SkPath::kConic_Verb: - // TBD - just replicate the curve for now - if (!prevIsValid) { - dst->moveTo(pts[0]); - prevIsValid = true; - } - dst->conicTo(pts[1], pts[2], iter.conicWeight()); - lastCorner = pts[2]; - firstStep.set(0, 0); - break; - case SkPath::kCubic_Verb: - if (!prevIsValid) { - dst->moveTo(pts[0]); - prevIsValid = true; - } - // TBD - just replicate the curve for now - dst->cubicTo(pts[1], pts[2], pts[3]); - lastCorner = pts[3]; - firstStep.set(0, 0); - break; - case SkPath::kClose_Verb: - if (firstStep.fX || firstStep.fY) { - dst->quadTo(lastCorner.fX, lastCorner.fY, - lastCorner.fX + firstStep.fX, - lastCorner.fY + firstStep.fY); - } - dst->close(); - prevIsValid = false; - break; - case SkPath::kDone_Verb: - if (prevIsValid) { - dst->lineTo(lastCorner); - } - return true; - default: - SkDEBUGFAIL("default should not be reached"); - return false; - } - if (SkPath::kMove_Verb == prevVerb) { - firstStep = step; + if (SkPath::kMove_Verb == prevVerb) { + firstStep = step; + } + prevVerb = verb; } - prevVerb = verb; + return true; } - return true; + bool computeFastBounds(SkRect*) const override { + // Rounding sharp corners within a path produces a new path that is still contained within + // the original's bounds, so leave 'bounds' unmodified. + return true; + } + + static sk_sp CreateProc(SkReadBuffer& buffer) { + return SkCornerPathEffect::Make(buffer.readScalar()); + } + + void flatten(SkWriteBuffer& buffer) const override { + buffer.writeScalar(fRadius); + } + + Factory getFactory() const override { return CreateProc; } + const char* getTypeName() const override { return "SkCornerPathEffect"; } + +private: + const SkScalar fRadius; + + using INHERITED = SkPathEffect; +}; + +////////////////////////////////////////////////////////////////////////////////////////////////// + +sk_sp SkCornerPathEffect::Make(SkScalar radius) { + return SkScalarIsFinite(radius) && (radius > 0) ? + sk_sp(new SkCornerPathEffectImpl(radius)) : nullptr; } -sk_sp SkCornerPathEffect::CreateProc(SkReadBuffer& buffer) { - return SkCornerPathEffect::Make(buffer.readScalar()); -} - -void SkCornerPathEffect::flatten(SkWriteBuffer& buffer) const { - buffer.writeScalar(fRadius); +void SkCornerPathEffect::RegisterFlattenables() { + SkFlattenable::Register("SkCornerPathEffect", SkCornerPathEffectImpl::CreateProc); } diff --git a/src/effects/SkDiscretePathEffect.cpp b/src/effects/SkDiscretePathEffect.cpp index 342fe2e846..e6dabcf893 100644 --- a/src/effects/SkDiscretePathEffect.cpp +++ b/src/effects/SkDiscretePathEffect.cpp @@ -14,31 +14,6 @@ #include "src/core/SkReadBuffer.h" #include "src/core/SkWriteBuffer.h" -sk_sp SkDiscretePathEffect::Make(SkScalar segLength, SkScalar deviation, - uint32_t seedAssist) { - if (!SkScalarIsFinite(segLength) || !SkScalarIsFinite(deviation)) { - return nullptr; - } - if (segLength <= SK_ScalarNearlyZero) { - return nullptr; - } - return sk_sp(new SkDiscretePathEffect(segLength, deviation, seedAssist)); -} - -static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) { - SkVector normal = tangent; - SkPointPriv::RotateCCW(&normal); - normal.setLength(scale); - *p += normal; -} - -SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, - SkScalar deviation, - uint32_t seedAssist) - : fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist) -{ -} - /** \class LCGRandom Utility class that implements pseudo random 32bit numbers using a fast @@ -49,7 +24,6 @@ SkDiscretePathEffect::SkDiscretePathEffect(SkScalar segLength, methods used by SkDiscretePathEffect::filterPath, with methods that were not called directly moved to private. */ - class LCGRandom { public: LCGRandom(uint32_t seed) : fSeed(seed) {} @@ -81,78 +55,124 @@ private: uint32_t fSeed; }; -bool SkDiscretePathEffect::onFilterPath(SkPath* dst, const SkPath& src, - SkStrokeRec* rec, const SkRect*) const { - bool doFill = rec->isFillStyle(); +static void Perterb(SkPoint* p, const SkVector& tangent, SkScalar scale) { + SkVector normal = tangent; + SkPointPriv::RotateCCW(&normal); + normal.setLength(scale); + *p += normal; +} - SkPathMeasure meas(src, doFill); +class SK_API SkDiscretePathEffectImpl : public SkPathEffect { +public: + SkDiscretePathEffectImpl(SkScalar segLength, SkScalar deviation, uint32_t seedAssist) + : fSegLength(segLength), fPerterb(deviation), fSeedAssist(seedAssist) + { + SkASSERT(SkScalarIsFinite(segLength)); + SkASSERT(SkScalarIsFinite(deviation)); + SkASSERT(segLength > SK_ScalarNearlyZero); + } - /* Caller may supply their own seed assist, which by default is 0 */ - uint32_t seed = fSeedAssist ^ SkScalarRoundToInt(meas.getLength()); + bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, + const SkRect*) const override { + bool doFill = rec->isFillStyle(); - LCGRandom rand(seed ^ ((seed << 16) | (seed >> 16))); - SkScalar scale = fPerterb; - SkPoint p; - SkVector v; + SkPathMeasure meas(src, doFill); - do { - SkScalar length = meas.getLength(); -#if defined(SK_BUILD_FOR_FUZZER) - if (length > 1000) { - return false; - } -#endif + /* Caller may supply their own seed assist, which by default is 0 */ + uint32_t seed = fSeedAssist ^ SkScalarRoundToInt(meas.getLength()); - if (fSegLength * (2 + doFill) > length) { - meas.getSegment(0, length, dst, true); // to short for us to mangle - } else { - int n = SkScalarRoundToInt(length / fSegLength); - constexpr int kMaxReasonableIterations = 100000; - n = std::min(n, kMaxReasonableIterations); - SkScalar delta = length / n; - SkScalar distance = 0; + LCGRandom rand(seed ^ ((seed << 16) | (seed >> 16))); + SkScalar scale = fPerterb; + SkPoint p; + SkVector v; - if (meas.isClosed()) { - n -= 1; - distance += delta/2; + do { + SkScalar length = meas.getLength(); + #if defined(SK_BUILD_FOR_FUZZER) + if (length > 1000) { + return false; } + #endif + + if (fSegLength * (2 + doFill) > length) { + meas.getSegment(0, length, dst, true); // to short for us to mangle + } else { + int n = SkScalarRoundToInt(length / fSegLength); + constexpr int kMaxReasonableIterations = 100000; + n = std::min(n, kMaxReasonableIterations); + SkScalar delta = length / n; + SkScalar distance = 0; + + if (meas.isClosed()) { + n -= 1; + distance += delta/2; + } - if (meas.getPosTan(distance, &p, &v)) { - Perterb(&p, v, rand.nextSScalar1() * scale); - dst->moveTo(p); - } - while (--n >= 0) { - distance += delta; if (meas.getPosTan(distance, &p, &v)) { Perterb(&p, v, rand.nextSScalar1() * scale); - dst->lineTo(p); + dst->moveTo(p); + } + while (--n >= 0) { + distance += delta; + if (meas.getPosTan(distance, &p, &v)) { + Perterb(&p, v, rand.nextSScalar1() * scale); + dst->lineTo(p); + } + } + if (meas.isClosed()) { + dst->close(); } } - if (meas.isClosed()) { - dst->close(); - } - } - } while (meas.nextContour()); - return true; -} - -bool SkDiscretePathEffect::computeFastBounds(SkRect* bounds) const { - if (bounds) { - SkScalar maxOutset = SkScalarAbs(fPerterb); - bounds->outset(maxOutset, maxOutset); + } while (meas.nextContour()); + return true; } - return true; + + bool computeFastBounds(SkRect* bounds) const override { + if (bounds) { + SkScalar maxOutset = SkScalarAbs(fPerterb); + bounds->outset(maxOutset, maxOutset); + } + return true; + } + + static sk_sp CreateProc(SkReadBuffer& buffer) { + SkScalar segLength = buffer.readScalar(); + SkScalar perterb = buffer.readScalar(); + uint32_t seed = buffer.readUInt(); + return SkDiscretePathEffect::Make(segLength, perterb, seed); + } + + void flatten(SkWriteBuffer& buffer) const override { + buffer.writeScalar(fSegLength); + buffer.writeScalar(fPerterb); + buffer.writeUInt(fSeedAssist); + } + + Factory getFactory() const override { return CreateProc; } + const char* getTypeName() const override { return "SkDiscretePathEffect"; } + +private: + const SkScalar fSegLength, + fPerterb; + /* Caller-supplied 32 bit seed assist */ + const uint32_t fSeedAssist; + + using INHERITED = SkPathEffect; +}; + +////////////////////////////////////////////////////////////////////////////////////////////////// + +sk_sp SkDiscretePathEffect::Make(SkScalar segLength, SkScalar deviation, + uint32_t seedAssist) { + if (!SkScalarIsFinite(segLength) || !SkScalarIsFinite(deviation)) { + return nullptr; + } + if (segLength <= SK_ScalarNearlyZero) { + return nullptr; + } + return sk_sp(new SkDiscretePathEffectImpl(segLength, deviation, seedAssist)); } -sk_sp SkDiscretePathEffect::CreateProc(SkReadBuffer& buffer) { - SkScalar segLength = buffer.readScalar(); - SkScalar perterb = buffer.readScalar(); - uint32_t seed = buffer.readUInt(); - return Make(segLength, perterb, seed); -} - -void SkDiscretePathEffect::flatten(SkWriteBuffer& buffer) const { - buffer.writeScalar(fSegLength); - buffer.writeScalar(fPerterb); - buffer.writeUInt(fSeedAssist); +void SkDiscretePathEffect::RegisterFlattenables() { + SkFlattenable::Register("SkDiscretePathEffect", SkDiscretePathEffectImpl::CreateProc); } diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index 97f4bfba3f..29fe799bd9 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -86,9 +86,9 @@ SkShaderMaskFilter::RegisterFlattenables(); // Path effects. - SK_REGISTER_FLATTENABLE(SkCornerPathEffect); + SkCornerPathEffect::RegisterFlattenables(); SK_REGISTER_FLATTENABLE(SkDashImpl); - SK_REGISTER_FLATTENABLE(SkDiscretePathEffect); + SkDiscretePathEffect::RegisterFlattenables(); SkLine2DPathEffect::RegisterFlattenables(); SkPath2DPathEffect::RegisterFlattenables(); SK_REGISTER_FLATTENABLE(SkMatrixPE);