1 /* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkSGGeometryEffect_DEFINED 9 #define SkSGGeometryEffect_DEFINED 10 11 #include "modules/sksg/include/SkSGGeometryNode.h" 12 13 #include "include/core/SkPaint.h" 14 #include "include/core/SkPath.h" 15 #include "include/effects/SkTrimPathEffect.h" 16 #include "modules/sksg/include/SkSGTransform.h" 17 18 namespace sksg { 19 20 /** 21 * Base class for geometry effects. 22 */ 23 class GeometryEffect : public GeometryNode { 24 protected: 25 explicit GeometryEffect(sk_sp<GeometryNode>); 26 ~GeometryEffect() override; 27 28 void onClip(SkCanvas*, bool antiAlias) const final; 29 void onDraw(SkCanvas*, const SkPaint&) const final; 30 bool onContains(const SkPoint&) const final; 31 32 SkRect onRevalidate(InvalidationController*, const SkMatrix&) final; 33 SkPath onAsPath() const final; 34 35 virtual SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) = 0; 36 37 private: 38 const sk_sp<GeometryNode> fChild; 39 SkPath fPath; // transformed child cache. 40 41 using INHERITED = GeometryNode; 42 }; 43 44 /** 45 * Apply a trim effect to the child geometry. 46 */ 47 class TrimEffect final : public GeometryEffect { 48 public: Make(sk_sp<GeometryNode> child)49 static sk_sp<TrimEffect> Make(sk_sp<GeometryNode> child) { 50 return child ? sk_sp<TrimEffect>(new TrimEffect(std::move(child))) : nullptr; 51 } 52 SG_ATTRIBUTE(Start,SkScalar,fStart)53 SG_ATTRIBUTE(Start , SkScalar , fStart ) 54 SG_ATTRIBUTE(Stop , SkScalar , fStop ) 55 SG_ATTRIBUTE(Mode , SkTrimPathEffect::Mode, fMode ) 56 57 private: 58 explicit TrimEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {} 59 60 SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override; 61 62 SkScalar fStart = 0, 63 fStop = 1; 64 SkTrimPathEffect::Mode fMode = SkTrimPathEffect::Mode::kNormal; 65 66 using INHERITED = GeometryEffect; 67 }; 68 69 /** 70 * Apply a transform to a GeometryNode. 71 */ 72 class GeometryTransform final : public GeometryEffect { 73 public: Make(sk_sp<GeometryNode> child,sk_sp<Transform> transform)74 static sk_sp<GeometryTransform> Make(sk_sp<GeometryNode> child, sk_sp<Transform> transform) { 75 return child && transform 76 ? sk_sp<GeometryTransform>(new GeometryTransform(std::move(child), 77 std::move(transform))) 78 : nullptr; 79 } 80 81 ~GeometryTransform() override; 82 getTransform()83 const sk_sp<Transform>& getTransform() const { return fTransform; } 84 85 private: 86 GeometryTransform(sk_sp<GeometryNode>, sk_sp<Transform>); 87 88 SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override; 89 90 const sk_sp<Transform> fTransform; 91 92 using INHERITED = GeometryEffect; 93 }; 94 95 /** 96 * Apply a dash effect to the child geometry. 97 * 98 * Follows the same semantics as SkDashPathEffect, with one minor tweak: when the number of 99 * intervals is odd, they are repeated once more to attain an even sequence (same as SVG 100 * stroke-dasharray: https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty). 101 */ 102 class DashEffect final : public GeometryEffect { 103 public: Make(sk_sp<GeometryNode> child)104 static sk_sp<DashEffect> Make(sk_sp<GeometryNode> child) { 105 return child ? sk_sp<DashEffect>(new DashEffect(std::move(child))) : nullptr; 106 } 107 SG_ATTRIBUTE(Intervals,std::vector<float>,fIntervals)108 SG_ATTRIBUTE(Intervals, std::vector<float>, fIntervals) 109 SG_ATTRIBUTE(Phase, float , fPhase ) 110 111 private: 112 explicit DashEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {} 113 114 SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override; 115 116 std::vector<float> fIntervals; 117 float fPhase = 0; 118 119 using INHERITED = GeometryEffect; 120 }; 121 122 /** 123 * Apply a rounded-corner effect to the child geometry. 124 */ 125 class RoundEffect final : public GeometryEffect { 126 public: Make(sk_sp<GeometryNode> child)127 static sk_sp<RoundEffect> Make(sk_sp<GeometryNode> child) { 128 return child ? sk_sp<RoundEffect>(new RoundEffect(std::move(child))) : nullptr; 129 } 130 SG_ATTRIBUTE(Radius,SkScalar,fRadius)131 SG_ATTRIBUTE(Radius, SkScalar, fRadius) 132 133 private: 134 explicit RoundEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {} 135 136 SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override; 137 138 SkScalar fRadius = 0; 139 140 using INHERITED = GeometryEffect; 141 }; 142 143 /** 144 * Apply an offset effect to the child geometry. 145 */ 146 class OffsetEffect final : public GeometryEffect { 147 public: Make(sk_sp<GeometryNode> child)148 static sk_sp<OffsetEffect> Make(sk_sp<GeometryNode> child) { 149 return child ? sk_sp<OffsetEffect>(new OffsetEffect(std::move(child))) : nullptr; 150 } 151 SG_ATTRIBUTE(Offset,SkScalar,fOffset)152 SG_ATTRIBUTE(Offset , SkScalar , fOffset ) 153 SG_ATTRIBUTE(MiterLimit , SkScalar , fMiterLimit) 154 SG_ATTRIBUTE(Join , SkPaint::Join, fJoin ) 155 156 private: 157 explicit OffsetEffect(sk_sp<GeometryNode> child) : INHERITED(std::move(child)) {} 158 159 SkPath onRevalidateEffect(const sk_sp<GeometryNode>&) override; 160 161 SkScalar fOffset = 0, 162 fMiterLimit = 4; 163 SkPaint::Join fJoin = SkPaint::kMiter_Join; 164 165 using INHERITED = GeometryEffect; 166 }; 167 168 } // namespace sksg 169 170 #endif // SkSGGeometryEffect_DEFINED 171