• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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