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