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