|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #ifndef SkPathEffect_DEFINED |
|
11 #define SkPathEffect_DEFINED |
|
12 |
|
13 #include "SkFlattenable.h" |
|
14 #include "SkPath.h" |
|
15 #include "SkPoint.h" |
|
16 #include "SkRect.h" |
|
17 #include "SkStrokeRec.h" |
|
18 #include "SkTDArray.h" |
|
19 |
|
20 class SkPath; |
|
21 |
|
22 /** \class SkPathEffect |
|
23 |
|
24 SkPathEffect is the base class for objects in the SkPaint that affect |
|
25 the geometry of a drawing primitive before it is transformed by the |
|
26 canvas' matrix and drawn. |
|
27 |
|
28 Dashing is implemented as a subclass of SkPathEffect. |
|
29 */ |
|
30 class SK_API SkPathEffect : public SkFlattenable { |
|
31 public: |
|
32 SK_DECLARE_INST_COUNT(SkPathEffect) |
|
33 |
|
34 /** |
|
35 * Given a src path (input) and a stroke-rec (input and output), apply |
|
36 * this effect to the src path, returning the new path in dst, and return |
|
37 * true. If this effect cannot be applied, return false and ignore dst |
|
38 * and stroke-rec. |
|
39 * |
|
40 * The stroke-rec specifies the initial request for stroking (if any). |
|
41 * The effect can treat this as input only, or it can choose to change |
|
42 * the rec as well. For example, the effect can decide to change the |
|
43 * stroke's width or join, or the effect can change the rec from stroke |
|
44 * to fill (or fill to stroke) in addition to returning a new (dst) path. |
|
45 * |
|
46 * If this method returns true, the caller will apply (as needed) the |
|
47 * resulting stroke-rec to dst and then draw. |
|
48 */ |
|
49 virtual bool filterPath(SkPath* dst, const SkPath& src, |
|
50 SkStrokeRec*, const SkRect* cullR) const = 0; |
|
51 |
|
52 /** |
|
53 * Compute a conservative bounds for its effect, given the src bounds. |
|
54 * The baseline implementation just assigns src to dst. |
|
55 */ |
|
56 virtual void computeFastBounds(SkRect* dst, const SkRect& src) const; |
|
57 |
|
58 /** \class PointData |
|
59 |
|
60 PointData aggregates all the information needed to draw the point |
|
61 primitives returned by an 'asPoints' call. |
|
62 */ |
|
63 class PointData { |
|
64 public: |
|
65 PointData() |
|
66 : fFlags(0) |
|
67 , fPoints(NULL) |
|
68 , fNumPoints(0) { |
|
69 fSize.set(SK_Scalar1, SK_Scalar1); |
|
70 // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets |
|
71 // the kUseClip flag |
|
72 }; |
|
73 ~PointData() { |
|
74 delete [] fPoints; |
|
75 } |
|
76 |
|
77 // TODO: consider using passed-in flags to limit the work asPoints does. |
|
78 // For example, a kNoPath flag could indicate don't bother generating |
|
79 // stamped solutions. |
|
80 |
|
81 // Currently none of these flags are supported. |
|
82 enum PointFlags { |
|
83 kCircles_PointFlag = 0x01, // draw points as circles (instead of rects) |
|
84 kUsePath_PointFlag = 0x02, // draw points as stamps of the returned path |
|
85 kUseClip_PointFlag = 0x04, // apply 'fClipRect' before drawing the points |
|
86 }; |
|
87 |
|
88 uint32_t fFlags; // flags that impact the drawing of the points |
|
89 SkPoint* fPoints; // the center point of each generated point |
|
90 int fNumPoints; // number of points in fPoints |
|
91 SkVector fSize; // the size to draw the points |
|
92 SkRect fClipRect; // clip required to draw the points (if kUseClip is set) |
|
93 SkPath fPath; // 'stamp' to be used at each point (if kUsePath is set) |
|
94 |
|
95 SkPath fFirst; // If not empty, contains geometry for first point |
|
96 SkPath fLast; // If not empty, contains geometry for last point |
|
97 }; |
|
98 |
|
99 /** |
|
100 * Does applying this path effect to 'src' yield a set of points? If so, |
|
101 * optionally return the points in 'results'. |
|
102 */ |
|
103 virtual bool asPoints(PointData* results, const SkPath& src, |
|
104 const SkStrokeRec&, const SkMatrix&, |
|
105 const SkRect* cullR) const; |
|
106 |
|
107 SK_DEFINE_FLATTENABLE_TYPE(SkPathEffect) |
|
108 |
|
109 protected: |
|
110 SkPathEffect() {} |
|
111 SkPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} |
|
112 |
|
113 private: |
|
114 // illegal |
|
115 SkPathEffect(const SkPathEffect&); |
|
116 SkPathEffect& operator=(const SkPathEffect&); |
|
117 |
|
118 typedef SkFlattenable INHERITED; |
|
119 }; |
|
120 |
|
121 /** \class SkPairPathEffect |
|
122 |
|
123 Common baseclass for Compose and Sum. This subclass manages two pathEffects, |
|
124 including flattening them. It does nothing in filterPath, and is only useful |
|
125 for managing the lifetimes of its two arguments. |
|
126 */ |
|
127 class SkPairPathEffect : public SkPathEffect { |
|
128 public: |
|
129 virtual ~SkPairPathEffect(); |
|
130 |
|
131 protected: |
|
132 SkPairPathEffect(SkPathEffect* pe0, SkPathEffect* pe1); |
|
133 SkPairPathEffect(SkReadBuffer&); |
|
134 virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; |
|
135 |
|
136 // these are visible to our subclasses |
|
137 SkPathEffect* fPE0, *fPE1; |
|
138 |
|
139 private: |
|
140 typedef SkPathEffect INHERITED; |
|
141 }; |
|
142 |
|
143 /** \class SkComposePathEffect |
|
144 |
|
145 This subclass of SkPathEffect composes its two arguments, to create |
|
146 a compound pathEffect. |
|
147 */ |
|
148 class SkComposePathEffect : public SkPairPathEffect { |
|
149 public: |
|
150 /** Construct a pathEffect whose effect is to apply first the inner pathEffect |
|
151 and the the outer pathEffect (e.g. outer(inner(path))) |
|
152 The reference counts for outer and inner are both incremented in the constructor, |
|
153 and decremented in the destructor. |
|
154 */ |
|
155 static SkComposePathEffect* Create(SkPathEffect* outer, SkPathEffect* inner) { |
|
156 return SkNEW_ARGS(SkComposePathEffect, (outer, inner)); |
|
157 } |
|
158 |
|
159 virtual bool filterPath(SkPath* dst, const SkPath& src, |
|
160 SkStrokeRec*, const SkRect*) const SK_OVERRIDE; |
|
161 |
|
162 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect) |
|
163 |
|
164 protected: |
|
165 SkComposePathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} |
|
166 |
|
167 #ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS |
|
168 public: |
|
169 #endif |
|
170 SkComposePathEffect(SkPathEffect* outer, SkPathEffect* inner) |
|
171 : INHERITED(outer, inner) {} |
|
172 |
|
173 private: |
|
174 // illegal |
|
175 SkComposePathEffect(const SkComposePathEffect&); |
|
176 SkComposePathEffect& operator=(const SkComposePathEffect&); |
|
177 |
|
178 typedef SkPairPathEffect INHERITED; |
|
179 }; |
|
180 |
|
181 /** \class SkSumPathEffect |
|
182 |
|
183 This subclass of SkPathEffect applies two pathEffects, one after the other. |
|
184 Its filterPath() returns true if either of the effects succeeded. |
|
185 */ |
|
186 class SkSumPathEffect : public SkPairPathEffect { |
|
187 public: |
|
188 /** Construct a pathEffect whose effect is to apply two effects, in sequence. |
|
189 (e.g. first(path) + second(path)) |
|
190 The reference counts for first and second are both incremented in the constructor, |
|
191 and decremented in the destructor. |
|
192 */ |
|
193 static SkSumPathEffect* Create(SkPathEffect* first, SkPathEffect* second) { |
|
194 return SkNEW_ARGS(SkSumPathEffect, (first, second)); |
|
195 } |
|
196 |
|
197 virtual bool filterPath(SkPath* dst, const SkPath& src, |
|
198 SkStrokeRec*, const SkRect*) const SK_OVERRIDE; |
|
199 |
|
200 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect) |
|
201 |
|
202 protected: |
|
203 SkSumPathEffect(SkReadBuffer& buffer) : INHERITED(buffer) {} |
|
204 |
|
205 #ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS |
|
206 public: |
|
207 #endif |
|
208 SkSumPathEffect(SkPathEffect* first, SkPathEffect* second) |
|
209 : INHERITED(first, second) {} |
|
210 |
|
211 private: |
|
212 // illegal |
|
213 SkSumPathEffect(const SkSumPathEffect&); |
|
214 SkSumPathEffect& operator=(const SkSumPathEffect&); |
|
215 |
|
216 typedef SkPairPathEffect INHERITED; |
|
217 }; |
|
218 |
|
219 #endif |