xref: /aosp_15_r20/external/skia/modules/sksg/include/SkSGGeometryEffect.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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