[sksg] Consolidate geometry effects
Dash, trim, round, transform and upcoming offset have a lot in common.
Introduce a GeometryEffect base class to consolidate.
TBR=
Change-Id: Ib5556e6ebe416685c624d53ba8591e118aa4f0d6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/300496
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/modules/skottie/src/layers/shapelayer/FillStroke.cpp b/modules/skottie/src/layers/shapelayer/FillStroke.cpp
index a635698..1193219 100644
--- a/modules/skottie/src/layers/shapelayer/FillStroke.cpp
+++ b/modules/skottie/src/layers/shapelayer/FillStroke.cpp
@@ -10,7 +10,7 @@
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/layers/shapelayer/ShapeLayer.h"
-#include "modules/sksg/include/SkSGDashEffect.h"
+#include "modules/sksg/include/SkSGGeometryEffect.h"
#include "modules/sksg/include/SkSGPaint.h"
namespace skottie {
diff --git a/modules/skottie/src/layers/shapelayer/RoundCorners.cpp b/modules/skottie/src/layers/shapelayer/RoundCorners.cpp
index 7baa6d6..cf5f1b6 100644
--- a/modules/skottie/src/layers/shapelayer/RoundCorners.cpp
+++ b/modules/skottie/src/layers/shapelayer/RoundCorners.cpp
@@ -10,7 +10,7 @@
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/layers/shapelayer/ShapeLayer.h"
-#include "modules/sksg/include/SkSGRoundEffect.h"
+#include "modules/sksg/include/SkSGGeometryEffect.h"
namespace skottie {
namespace internal {
diff --git a/modules/skottie/src/layers/shapelayer/ShapeLayer.cpp b/modules/skottie/src/layers/shapelayer/ShapeLayer.cpp
index 3ab9394..e9993a1 100644
--- a/modules/skottie/src/layers/shapelayer/ShapeLayer.cpp
+++ b/modules/skottie/src/layers/shapelayer/ShapeLayer.cpp
@@ -12,16 +12,14 @@
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/sksg/include/SkSGDraw.h"
-#include "modules/sksg/include/SkSGGeometryTransform.h"
+#include "modules/sksg/include/SkSGGeometryEffect.h"
#include "modules/sksg/include/SkSGGroup.h"
#include "modules/sksg/include/SkSGMerge.h"
#include "modules/sksg/include/SkSGPaint.h"
#include "modules/sksg/include/SkSGPath.h"
#include "modules/sksg/include/SkSGRect.h"
#include "modules/sksg/include/SkSGRenderEffect.h"
-#include "modules/sksg/include/SkSGRoundEffect.h"
#include "modules/sksg/include/SkSGTransform.h"
-#include "modules/sksg/include/SkSGTrimEffect.h"
#include "src/utils/SkJSON.h"
#include <algorithm>
diff --git a/modules/skottie/src/layers/shapelayer/TrimPaths.cpp b/modules/skottie/src/layers/shapelayer/TrimPaths.cpp
index 7db26cc..bc2dc15 100644
--- a/modules/skottie/src/layers/shapelayer/TrimPaths.cpp
+++ b/modules/skottie/src/layers/shapelayer/TrimPaths.cpp
@@ -10,8 +10,8 @@
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/layers/shapelayer/ShapeLayer.h"
+#include "modules/sksg/include/SkSGGeometryEffect.h"
#include "modules/sksg/include/SkSGMerge.h"
-#include "modules/sksg/include/SkSGTrimEffect.h"
#include <vector>
diff --git a/modules/sksg/include/SkSGDashEffect.h b/modules/sksg/include/SkSGDashEffect.h
deleted file mode 100644
index 341e71e..0000000
--- a/modules/sksg/include/SkSGDashEffect.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2020 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkSGDashEffect_DEFINED
-#define SkSGDashEffect_DEFINED
-
-#include "include/core/SkPath.h"
-#include "modules/sksg/include/SkSGGeometryNode.h"
-
-#include <vector>
-
-namespace sksg {
-
-/**
- * Apply a dash effect to the child geometry.
- *
- * Follows the same semantics as SkDashPathEffect, with one minor tweak: when the number of
- * intervals is odd, they are repeated once more to attain an even sequence (same as SVG
- * stroke-dasharray: https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty).
- */
-class DashEffect final : public GeometryNode {
-public:
- static sk_sp<DashEffect> Make(sk_sp<GeometryNode> child) {
- return child ? sk_sp<DashEffect>(new DashEffect(std::move(child))) : nullptr;
- }
-
- ~DashEffect() override;
-
- SG_ATTRIBUTE(Intervals, std::vector<float>, fIntervals)
- SG_ATTRIBUTE(Phase, float , fPhase )
-
-protected:
- void onClip(SkCanvas*, bool antiAlias) const override;
- void onDraw(SkCanvas*, const SkPaint&) const override;
- bool onContains(const SkPoint&) const override;
-
- SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
- SkPath onAsPath() const override;
-
-private:
- explicit DashEffect(sk_sp<GeometryNode>);
-
- const sk_sp<GeometryNode> fChild;
-
- SkPath fDashedPath; // cache
-
- std::vector<float> fIntervals;
- float fPhase;
-};
-
-} // namespace sksg
-
-#endif // SkSGDashEffect_DEFINED
diff --git a/modules/sksg/include/SkSGGeometryEffect.h b/modules/sksg/include/SkSGGeometryEffect.h
new file mode 100644
index 0000000..01b501c
--- /dev/null
+++ b/modules/sksg/include/SkSGGeometryEffect.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSGGeometryEffect_DEFINED
+#define SkSGGeometryEffect_DEFINED
+
+#include "modules/sksg/include/SkSGGeometryNode.h"
+
+#include "include/core/SkPath.h"
+#include "include/effects/SkTrimPathEffect.h"
+#include "modules/sksg/include/SkSGTransform.h"
+
+namespace sksg {
+
+/**
+ * Base class for geometry effects.
+ */
+class GeometryEffect : public GeometryNode {
+protected:
+ explicit GeometryEffect(sk_sp<GeometryNode>);
+ ~GeometryEffect() override;
+
+ void onClip(SkCanvas*, bool antiAlias) const final;
+ void onDraw(SkCanvas*, const SkPaint&) const final;
+ bool onContains(const SkPoint&) const final;
+
+ SkRect onRevalidate(InvalidationController*, const SkMatrix&) final;
+ SkPath onAsPath() const final;
+
+ virtual SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) = 0;
+
+private:
+ const sk_sp<GeometryNode> fChild;
+ SkPath fPath; // transformed child cache.
+
+ using INHERITED = GeometryNode;
+};
+
+/**
+ * Apply a trim effect to the child geometry.
+ */
+class TrimEffect final : public GeometryEffect {
+public:
+ static sk_sp<TrimEffect> Make(sk_sp<GeometryNode> child) {
+ return child ? sk_sp<TrimEffect>(new TrimEffect(std::move(child))) : nullptr;
+ }
+
+ SG_ATTRIBUTE(Start , SkScalar , fStart )
+ SG_ATTRIBUTE(Stop , SkScalar , fStop )
+ SG_ATTRIBUTE(Mode , SkTrimPathEffect::Mode, fMode )
+
+private:
+ explicit TrimEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {}
+
+ SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
+
+ SkScalar fStart = 0,
+ fStop = 1;
+ SkTrimPathEffect::Mode fMode = SkTrimPathEffect::Mode::kNormal;
+
+ using INHERITED = GeometryEffect;
+};
+
+/**
+ * Apply a transform to a GeometryNode.
+ */
+class GeometryTransform final : public GeometryEffect {
+public:
+ static sk_sp<GeometryTransform> Make(sk_sp<GeometryNode> child, sk_sp<Transform> transform) {
+ return child && transform
+ ? sk_sp<GeometryTransform>(new GeometryTransform(std::move(child),
+ std::move(transform)))
+ : nullptr;
+ }
+
+ ~GeometryTransform() override;
+
+ const sk_sp<Transform>& getTransform() const { return fTransform; }
+
+private:
+ GeometryTransform(sk_sp<GeometryNode>, sk_sp<Transform>);
+
+ SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
+
+ const sk_sp<Transform> fTransform;
+
+ using INHERITED = GeometryEffect;
+};
+
+/**
+ * Apply a dash effect to the child geometry.
+ *
+ * Follows the same semantics as SkDashPathEffect, with one minor tweak: when the number of
+ * intervals is odd, they are repeated once more to attain an even sequence (same as SVG
+ * stroke-dasharray: https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty).
+ */
+class DashEffect final : public GeometryEffect {
+public:
+ static sk_sp<DashEffect> Make(sk_sp<GeometryNode> child) {
+ return child ? sk_sp<DashEffect>(new DashEffect(std::move(child))) : nullptr;
+ }
+
+ SG_ATTRIBUTE(Intervals, std::vector<float>, fIntervals)
+ SG_ATTRIBUTE(Phase, float , fPhase )
+
+private:
+ explicit DashEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {}
+
+ SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
+
+ std::vector<float> fIntervals;
+ float fPhase;
+
+ using INHERITED = GeometryEffect;
+};
+
+/**
+ * Apply a rounded-corner effect to the child geometry.
+ */
+class RoundEffect final : public GeometryEffect {
+public:
+ static sk_sp<RoundEffect> Make(sk_sp<GeometryNode> child) {
+ return child ? sk_sp<RoundEffect>(new RoundEffect(std::move(child))) : nullptr;
+ }
+
+ SG_ATTRIBUTE(Radius, SkScalar, fRadius)
+
+private:
+ explicit RoundEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {}
+
+ SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override;
+
+ SkScalar fRadius = 0;
+
+ using INHERITED = GeometryEffect;
+};
+
+} // namespace sksg
+
+#endif // SkSGGeometryEffect_DEFINED
diff --git a/modules/sksg/include/SkSGGeometryTransform.h b/modules/sksg/include/SkSGGeometryTransform.h
deleted file mode 100644
index 400ab8a..0000000
--- a/modules/sksg/include/SkSGGeometryTransform.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkSGGeometryTransform_DEFINED
-#define SkSGGeometryTransform_DEFINED
-
-#include "modules/sksg/include/SkSGGeometryNode.h"
-
-#include "include/core/SkPath.h"
-
-class SkMatrix;
-
-namespace sksg {
-
-class Transform;
-
-/**
- * Concrete Effect node, binding a Matrix to a GeometryNode.
- */
-class GeometryTransform final : public GeometryNode {
-public:
- static sk_sp<GeometryTransform> Make(sk_sp<GeometryNode> child, sk_sp<Transform> transform) {
- return child && transform
- ? sk_sp<GeometryTransform>(new GeometryTransform(std::move(child),
- std::move(transform)))
- : nullptr;
- }
-
- ~GeometryTransform() override;
-
- const sk_sp<Transform>& getTransform() const { return fTransform; }
-
-protected:
- void onClip(SkCanvas*, bool antiAlias) const override;
- void onDraw(SkCanvas*, const SkPaint&) const override;
- bool onContains(const SkPoint&) const override;
-
- SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
- SkPath onAsPath() const override;
-
-private:
- GeometryTransform(sk_sp<GeometryNode>, sk_sp<Transform>);
-
- const sk_sp<GeometryNode> fChild;
- const sk_sp<Transform> fTransform;
- SkPath fTransformedPath;
-
- using INHERITED = GeometryNode;
-};
-
-}
-
-#endif // SkSGGeometryTransform_DEFINED
diff --git a/modules/sksg/include/SkSGRoundEffect.h b/modules/sksg/include/SkSGRoundEffect.h
deleted file mode 100644
index 20a02d0..0000000
--- a/modules/sksg/include/SkSGRoundEffect.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkSGRoundEffect_DEFINED
-#define SkSGRoundEffect_DEFINED
-
-#include "modules/sksg/include/SkSGGeometryNode.h"
-
-#include "include/core/SkPath.h"
-
-namespace sksg {
-
-/**
- * Concrete Geometry node, applying a rounded-corner effect to its child.
- */
-class RoundEffect final : public GeometryNode {
-public:
- static sk_sp<RoundEffect> Make(sk_sp<GeometryNode> child) {
- return child ? sk_sp<RoundEffect>(new RoundEffect(std::move(child))) : nullptr;
- }
-
- ~RoundEffect() override;
-
- SG_ATTRIBUTE(Radius, SkScalar, fRadius)
-
-protected:
- void onClip(SkCanvas*, bool antiAlias) const override;
- void onDraw(SkCanvas*, const SkPaint&) const override;
- bool onContains(const SkPoint&) const override;
-
- SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
- SkPath onAsPath() const override;
-
-private:
- explicit RoundEffect(sk_sp<GeometryNode>);
-
- const sk_sp<GeometryNode> fChild;
-
- SkPath fRoundedPath;
- SkScalar fRadius = 0;
-
- using INHERITED = GeometryNode;
-};
-
-} // namespace sksg
-
-#endif // SkSGRoundEffect_DEFINED
diff --git a/modules/sksg/include/SkSGTrimEffect.h b/modules/sksg/include/SkSGTrimEffect.h
deleted file mode 100644
index 804f028..0000000
--- a/modules/sksg/include/SkSGTrimEffect.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkSGTrimEffect_DEFINED
-#define SkSGTrimEffect_DEFINED
-
-#include "modules/sksg/include/SkSGGeometryNode.h"
-
-#include "include/core/SkPath.h"
-#include "include/effects/SkTrimPathEffect.h"
-
-class SkCanvas;
-class SkPaint;
-
-namespace sksg {
-
-/**
- * Concrete Geometry node, applying a trim effect to its child.
- */
-class TrimEffect final : public GeometryNode {
-public:
- static sk_sp<TrimEffect> Make(sk_sp<GeometryNode> child) {
- return child ? sk_sp<TrimEffect>(new TrimEffect(std::move(child))) : nullptr;
- }
-
- ~TrimEffect() override;
-
- SG_ATTRIBUTE(Start , SkScalar , fStart )
- SG_ATTRIBUTE(Stop , SkScalar , fStop )
- SG_ATTRIBUTE(Mode , SkTrimPathEffect::Mode, fMode )
-
-protected:
- void onClip(SkCanvas*, bool antiAlias) const override;
- void onDraw(SkCanvas*, const SkPaint&) const override;
- bool onContains(const SkPoint&) const override;
-
- SkRect onRevalidate(InvalidationController*, const SkMatrix&) override;
- SkPath onAsPath() const override;
-
-private:
- explicit TrimEffect(sk_sp<GeometryNode>);
-
- const sk_sp<GeometryNode> fChild;
-
- SkPath fTrimmedPath;
- SkScalar fStart = 0,
- fStop = 1;
- SkTrimPathEffect::Mode fMode = SkTrimPathEffect::Mode::kNormal;
-
- using INHERITED = GeometryNode;
-};
-
-} // namespace sksg
-
-#endif // SkSGTrimEffect_DEFINED
diff --git a/modules/sksg/sksg.gni b/modules/sksg/sksg.gni
index 739941b1..5e55e9a 100644
--- a/modules/sksg/sksg.gni
+++ b/modules/sksg/sksg.gni
@@ -9,11 +9,10 @@
skia_sksg_sources = [
"$_src/SkSGClipEffect.cpp",
"$_src/SkSGColorFilter.cpp",
- "$_src/SkSGDashEffect.cpp",
"$_src/SkSGDraw.cpp",
"$_src/SkSGEffectNode.cpp",
+ "$_src/SkSGGeometryEffect.cpp",
"$_src/SkSGGeometryNode.cpp",
- "$_src/SkSGGeometryTransform.cpp",
"$_src/SkSGGradient.cpp",
"$_src/SkSGGroup.cpp",
"$_src/SkSGImage.cpp",
@@ -29,10 +28,8 @@
"$_src/SkSGRect.cpp",
"$_src/SkSGRenderEffect.cpp",
"$_src/SkSGRenderNode.cpp",
- "$_src/SkSGRoundEffect.cpp",
"$_src/SkSGScene.cpp",
"$_src/SkSGText.cpp",
"$_src/SkSGTransform.cpp",
"$_src/SkSGTransformPriv.h",
- "$_src/SkSGTrimEffect.cpp",
]
diff --git a/modules/sksg/src/SkSGDashEffect.cpp b/modules/sksg/src/SkSGDashEffect.cpp
deleted file mode 100644
index 2b4002c..0000000
--- a/modules/sksg/src/SkSGDashEffect.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2020 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "modules/sksg/include/SkSGDashEffect.h"
-
-#include "include/core/SkCanvas.h"
-#include "include/core/SkStrokeRec.h"
-#include "include/effects/SkDashPathEffect.h"
-
-#include <algorithm>
-
-namespace sksg {
-
-namespace {
-
-sk_sp<SkPathEffect> make_dash(const std::vector<float> intervals, float phase) {
- if (intervals.empty()) {
- return nullptr;
- }
-
- const auto* intervals_ptr = intervals.data();
- auto intervals_count = intervals.size();
-
- SkSTArray<32, float, true> storage;
- if (intervals_count & 1) {
- intervals_count *= 2;
- storage.resize(intervals_count);
- intervals_ptr = storage.data();
-
- std::copy(intervals.begin(), intervals.end(), storage.begin());
- std::copy(intervals.begin(), intervals.end(), storage.begin() + intervals.size());
- }
-
- return SkDashPathEffect::Make(intervals_ptr, SkToInt(intervals_count), phase);
-}
-
-} // namespace
-
-DashEffect::DashEffect(sk_sp<GeometryNode> child)
- : fChild(std::move(child)) {
- this->observeInval(fChild);
-}
-
-DashEffect::~DashEffect() {
- this->unobserveInval(fChild);
-}
-
-void DashEffect::onClip(SkCanvas* canvas, bool antiAlias) const {
- canvas->clipPath(fDashedPath, SkClipOp::kIntersect, antiAlias);
-}
-
-void DashEffect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
- canvas->drawPath(fDashedPath, paint);
-}
-
-bool DashEffect::onContains(const SkPoint& p) const {
- return fDashedPath.contains(p.x(), p.y());
-}
-
-SkPath DashEffect::onAsPath() const {
- return fDashedPath;
-}
-
-SkRect DashEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
- SkASSERT(this->hasInval());
-
- const auto child_bounds = fChild->revalidate(ic, ctm);
- const auto child_path = fChild->asPath();
-
- fDashedPath.reset();
-
- auto dash_patheffect = make_dash(fIntervals, fPhase);
- SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
-
- if (!dash_patheffect ||
- !dash_patheffect->filterPath(&fDashedPath, child_path, &rec, &child_bounds)) {
- fDashedPath = std::move(child_path);
- }
- fDashedPath.shrinkToFit();
-
- return fDashedPath.computeTightBounds();
-}
-
-} // namespace sksg
diff --git a/modules/sksg/src/SkSGGeometryEffect.cpp b/modules/sksg/src/SkSGGeometryEffect.cpp
new file mode 100644
index 0000000..935c917
--- /dev/null
+++ b/modules/sksg/src/SkSGGeometryEffect.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2020 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "modules/sksg/include/SkSGGeometryEffect.h"
+
+#include "include/core/SkCanvas.h"
+#include "include/core/SkStrokeRec.h"
+#include "include/effects/SkCornerPathEffect.h"
+#include "include/effects/SkDashPathEffect.h"
+#include "include/effects/SkTrimPathEffect.h"
+#include "modules/sksg/src/SkSGTransformPriv.h"
+
+namespace sksg {
+
+GeometryEffect::GeometryEffect(sk_sp<GeometryNode> child)
+ : fChild(std::move(child)) {
+ SkASSERT(fChild);
+
+ this->observeInval(fChild);
+}
+
+GeometryEffect::~GeometryEffect() {
+ this->unobserveInval(fChild);
+}
+
+void GeometryEffect::onClip(SkCanvas* canvas, bool antiAlias) const {
+ canvas->clipPath(fPath, SkClipOp::kIntersect, antiAlias);
+}
+
+void GeometryEffect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
+ canvas->drawPath(fPath, paint);
+}
+
+bool GeometryEffect::onContains(const SkPoint& p) const {
+ return fPath.contains(p.x(), p.y());
+}
+
+SkPath GeometryEffect::onAsPath() const {
+ return fPath;
+}
+
+SkRect GeometryEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
+ SkASSERT(this->hasInval());
+
+ fChild->revalidate(ic, ctm);
+
+ fPath = this->onRevalidateEffect(fChild);
+ fPath.shrinkToFit();
+
+ return fPath.computeTightBounds();
+}
+
+SkPath TrimEffect::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
+ SkPath path = child->asPath();
+
+ if (const auto trim = SkTrimPathEffect::Make(fStart, fStop, fMode)) {
+ SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
+ SkAssertResult(trim->filterPath(&path, path, &rec, nullptr));
+ }
+
+ return path;
+}
+
+GeometryTransform::GeometryTransform(sk_sp<GeometryNode> child, sk_sp<Transform> transform)
+ : INHERITED(std::move(child))
+ , fTransform(std::move(transform)) {
+ SkASSERT(fTransform);
+ this->observeInval(fTransform);
+}
+
+GeometryTransform::~GeometryTransform() {
+ this->unobserveInval(fTransform);
+}
+
+SkPath GeometryTransform::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
+ fTransform->revalidate(nullptr, SkMatrix::I());
+ const auto m = TransformPriv::As<SkMatrix>(fTransform);
+
+ SkPath path = child->asPath();
+ path.transform(m);
+
+ return path;
+}
+
+namespace {
+
+sk_sp<SkPathEffect> make_dash(const std::vector<float> intervals, float phase) {
+ if (intervals.empty()) {
+ return nullptr;
+ }
+
+ const auto* intervals_ptr = intervals.data();
+ auto intervals_count = intervals.size();
+
+ SkSTArray<32, float, true> storage;
+ if (intervals_count & 1) {
+ intervals_count *= 2;
+ storage.resize(intervals_count);
+ intervals_ptr = storage.data();
+
+ std::copy(intervals.begin(), intervals.end(), storage.begin());
+ std::copy(intervals.begin(), intervals.end(), storage.begin() + intervals.size());
+ }
+
+ return SkDashPathEffect::Make(intervals_ptr, SkToInt(intervals_count), phase);
+}
+
+} // namespace
+
+SkPath DashEffect::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
+ SkPath path = child->asPath();
+
+ if (const auto dash_patheffect = make_dash(fIntervals, fPhase)) {
+ SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
+ dash_patheffect->filterPath(&path, path, &rec, nullptr);
+ }
+
+ return path;
+}
+
+SkPath RoundEffect::onRevalidateEffect(const sk_sp<GeometryNode>& child) {
+ SkPath path = child->asPath();
+
+ if (const auto round = SkCornerPathEffect::Make(fRadius)) {
+ SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
+ SkAssertResult(round->filterPath(&path, path, &rec, nullptr));
+ }
+
+ return path;
+}
+
+} // namesapce sksg
diff --git a/modules/sksg/src/SkSGGeometryTransform.cpp b/modules/sksg/src/SkSGGeometryTransform.cpp
deleted file mode 100644
index d0ff83ea..0000000
--- a/modules/sksg/src/SkSGGeometryTransform.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "modules/sksg/include/SkSGGeometryTransform.h"
-
-#include "include/core/SkCanvas.h"
-#include "modules/sksg/include/SkSGTransform.h"
-#include "modules/sksg/src/SkSGTransformPriv.h"
-
-namespace sksg {
-
-GeometryTransform::GeometryTransform(sk_sp<GeometryNode> child, sk_sp<Transform> transform)
- : fChild(std::move(child))
- , fTransform(std::move(transform)) {
- this->observeInval(fChild);
- this->observeInval(fTransform);
-}
-
-GeometryTransform::~GeometryTransform() {
- this->unobserveInval(fChild);
- this->unobserveInval(fTransform);
-}
-
-void GeometryTransform::onClip(SkCanvas* canvas, bool antiAlias) const {
- canvas->clipPath(fTransformedPath, SkClipOp::kIntersect, antiAlias);
-}
-
-void GeometryTransform::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
- canvas->drawPath(fTransformedPath, paint);
-}
-
-bool GeometryTransform::onContains(const SkPoint& p) const {
- return fTransformedPath.contains(p.x(), p.y());
-}
-
-SkRect GeometryTransform::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
- SkASSERT(this->hasInval());
-
- // We don't care about matrix reval results.
- fTransform->revalidate(ic, ctm);
- const auto m = TransformPriv::As<SkMatrix>(fTransform);
-
- auto bounds = fChild->revalidate(ic, ctm);
- fTransformedPath = fChild->asPath();
- fTransformedPath.transform(m);
- fTransformedPath.shrinkToFit();
-
- m.mapRect(&bounds);
- return bounds;
-}
-
-SkPath GeometryTransform::onAsPath() const {
- return fTransformedPath;
-}
-
-} // namespace sksg
diff --git a/modules/sksg/src/SkSGRoundEffect.cpp b/modules/sksg/src/SkSGRoundEffect.cpp
deleted file mode 100644
index ba5db05..0000000
--- a/modules/sksg/src/SkSGRoundEffect.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "modules/sksg/include/SkSGRoundEffect.h"
-
-#include "include/core/SkCanvas.h"
-#include "include/core/SkStrokeRec.h"
-#include "include/effects/SkCornerPathEffect.h"
-
-namespace sksg {
-
-RoundEffect::RoundEffect(sk_sp<GeometryNode> child)
- : fChild(std::move(child)) {
- this->observeInval(fChild);
-}
-
-RoundEffect::~RoundEffect() {
- this->unobserveInval(fChild);
-}
-
-void RoundEffect::onClip(SkCanvas* canvas, bool antiAlias) const {
- canvas->clipPath(fRoundedPath, SkClipOp::kIntersect, antiAlias);
-}
-
-void RoundEffect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
- SkASSERT(!paint.getPathEffect());
-
- canvas->drawPath(fRoundedPath, paint);
-}
-
-bool RoundEffect::onContains(const SkPoint& p) const {
- return fRoundedPath.contains(p.x(), p.y());
-}
-
-SkPath RoundEffect::onAsPath() const {
- return fRoundedPath;
-}
-
-SkRect RoundEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
- SkASSERT(this->hasInval());
-
- const auto childbounds = fChild->revalidate(ic, ctm);
- const auto path = fChild->asPath();
-
- if (auto round = SkCornerPathEffect::Make(fRadius)) {
- fRoundedPath.reset();
- SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
- SkAssertResult(round->filterPath(&fRoundedPath, path, &rec, &childbounds));
- } else {
- fRoundedPath = path;
- }
-
- fRoundedPath.shrinkToFit();
-
- return fRoundedPath.computeTightBounds();
-}
-
-} // namespace sksg
diff --git a/modules/sksg/src/SkSGTrimEffect.cpp b/modules/sksg/src/SkSGTrimEffect.cpp
deleted file mode 100644
index 4c63b0c..0000000
--- a/modules/sksg/src/SkSGTrimEffect.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "modules/sksg/include/SkSGTrimEffect.h"
-
-#include "include/core/SkCanvas.h"
-#include "include/core/SkStrokeRec.h"
-#include "include/effects/SkTrimPathEffect.h"
-
-namespace sksg {
-
-TrimEffect::TrimEffect(sk_sp<GeometryNode> child)
- : fChild(std::move(child)) {
- this->observeInval(fChild);
-}
-
-TrimEffect::~TrimEffect() {
- this->unobserveInval(fChild);
-}
-
-void TrimEffect::onClip(SkCanvas* canvas, bool antiAlias) const {
- canvas->clipPath(fTrimmedPath, SkClipOp::kIntersect, antiAlias);
-}
-
-void TrimEffect::onDraw(SkCanvas* canvas, const SkPaint& paint) const {
- SkASSERT(!paint.getPathEffect());
-
- canvas->drawPath(fTrimmedPath, paint);
-}
-
-bool TrimEffect::onContains(const SkPoint& p) const {
- return fTrimmedPath.contains(p.x(), p.y());
-}
-
-SkPath TrimEffect::onAsPath() const {
- return fTrimmedPath;
-}
-
-SkRect TrimEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
- SkASSERT(this->hasInval());
-
- const auto childbounds = fChild->revalidate(ic, ctm);
- const auto path = fChild->asPath();
-
- if (auto trim = SkTrimPathEffect::Make(fStart, fStop, fMode)) {
- fTrimmedPath.reset();
- SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
- SkAssertResult(trim->filterPath(&fTrimmedPath, path, &rec, &childbounds));
- } else {
- fTrimmedPath = path;
- }
-
- fTrimmedPath.shrinkToFit();
-
- return fTrimmedPath.computeTightBounds();
-}
-
-} // namespace sksg