1 /*
2 * Copyright 2006 The Android Open Source Project
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 #include "SkPathEffect.h"
9 #include "SkPath.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12
13 ///////////////////////////////////////////////////////////////////////////////
14
computeFastBounds(SkRect * dst,const SkRect & src) const15 void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) const {
16 *dst = src;
17 }
18
asPoints(PointData * results,const SkPath & src,const SkStrokeRec &,const SkMatrix &,const SkRect *) const19 bool SkPathEffect::asPoints(PointData* results, const SkPath& src,
20 const SkStrokeRec&, const SkMatrix&, const SkRect*) const {
21 return false;
22 }
23
asADash(DashInfo * info) const24 SkPathEffect::DashType SkPathEffect::asADash(DashInfo* info) const {
25 return kNone_DashType;
26 }
27
28 ///////////////////////////////////////////////////////////////////////////////
29
30 /** \class SkPairPathEffect
31
32 Common baseclass for Compose and Sum. This subclass manages two pathEffects,
33 including flattening them. It does nothing in filterPath, and is only useful
34 for managing the lifetimes of its two arguments.
35 */
36 class SkPairPathEffect : public SkPathEffect {
37 protected:
SkPairPathEffect(sk_sp<SkPathEffect> pe0,sk_sp<SkPathEffect> pe1)38 SkPairPathEffect(sk_sp<SkPathEffect> pe0, sk_sp<SkPathEffect> pe1)
39 : fPE0(std::move(pe0)), fPE1(std::move(pe1))
40 {
41 SkASSERT(fPE0.get());
42 SkASSERT(fPE1.get());
43 }
44
flatten(SkWriteBuffer & buffer) const45 void flatten(SkWriteBuffer& buffer) const override {
46 buffer.writeFlattenable(fPE0.get());
47 buffer.writeFlattenable(fPE1.get());
48 }
49
50 // these are visible to our subclasses
51 sk_sp<SkPathEffect> fPE0;
52 sk_sp<SkPathEffect> fPE1;
53
54 SK_TO_STRING_OVERRIDE()
55
56 private:
57 typedef SkPathEffect INHERITED;
58 };
59
60 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const61 void SkPairPathEffect::toString(SkString* str) const {
62 str->appendf("first: ");
63 if (fPE0) {
64 fPE0->toString(str);
65 }
66 str->appendf(" second: ");
67 if (fPE1) {
68 fPE1->toString(str);
69 }
70 }
71 #endif
72
73 ///////////////////////////////////////////////////////////////////////////////////////////////////
74
75 /** \class SkComposePathEffect
76
77 This subclass of SkPathEffect composes its two arguments, to create
78 a compound pathEffect.
79 */
80 class SkComposePathEffect : public SkPairPathEffect {
81 public:
82 /** Construct a pathEffect whose effect is to apply first the inner pathEffect
83 and the the outer pathEffect (e.g. outer(inner(path)))
84 The reference counts for outer and inner are both incremented in the constructor,
85 and decremented in the destructor.
86 */
Make(sk_sp<SkPathEffect> outer,sk_sp<SkPathEffect> inner)87 static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner) {
88 if (!outer) {
89 return inner;
90 }
91 if (!inner) {
92 return outer;
93 }
94 return sk_sp<SkPathEffect>(new SkComposePathEffect(outer, inner));
95 }
96
filterPath(SkPath * dst,const SkPath & src,SkStrokeRec * rec,const SkRect * cullRect) const97 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
98 const SkRect* cullRect) const override {
99 SkPath tmp;
100 const SkPath* ptr = &src;
101
102 if (fPE1->filterPath(&tmp, src, rec, cullRect)) {
103 ptr = &tmp;
104 }
105 return fPE0->filterPath(dst, *ptr, rec, cullRect);
106 }
107
108
109 SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)110 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposePathEffect)
111
112 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
113 bool exposedInAndroidJavaAPI() const override { return true; }
114 #endif
115
116 protected:
SkComposePathEffect(sk_sp<SkPathEffect> outer,sk_sp<SkPathEffect> inner)117 SkComposePathEffect(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner)
118 : INHERITED(outer, inner) {}
119
120 private:
121 // illegal
122 SkComposePathEffect(const SkComposePathEffect&);
123 SkComposePathEffect& operator=(const SkComposePathEffect&);
124 friend class SkPathEffect;
125
126 typedef SkPairPathEffect INHERITED;
127 };
128
CreateProc(SkReadBuffer & buffer)129 sk_sp<SkFlattenable> SkComposePathEffect::CreateProc(SkReadBuffer& buffer) {
130 sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
131 sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
132 return SkComposePathEffect::Make(std::move(pe0), std::move(pe1));
133 }
134
135 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const136 void SkComposePathEffect::toString(SkString* str) const {
137 str->appendf("SkComposePathEffect: (");
138 this->INHERITED::toString(str);
139 str->appendf(")");
140 }
141 #endif
142
143 ///////////////////////////////////////////////////////////////////////////////
144
145 /** \class SkSumPathEffect
146
147 This subclass of SkPathEffect applies two pathEffects, one after the other.
148 Its filterPath() returns true if either of the effects succeeded.
149 */
150 class SkSumPathEffect : public SkPairPathEffect {
151 public:
152 /** Construct a pathEffect whose effect is to apply two effects, in sequence.
153 (e.g. first(path) + second(path))
154 The reference counts for first and second are both incremented in the constructor,
155 and decremented in the destructor.
156 */
Make(sk_sp<SkPathEffect> first,sk_sp<SkPathEffect> second)157 static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
158 if (!first) {
159 return second;
160 }
161 if (!second) {
162 return first;
163 }
164 return sk_sp<SkPathEffect>(new SkSumPathEffect(first, second));
165 }
166
filterPath(SkPath * dst,const SkPath & src,SkStrokeRec * rec,const SkRect * cullRect) const167 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
168 const SkRect* cullRect) const override {
169 // use bit-or so that we always call both, even if the first one succeeds
170 return fPE0->filterPath(dst, src, rec, cullRect) |
171 fPE1->filterPath(dst, src, rec, cullRect);
172 }
173
174
175 SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)176 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSumPathEffect)
177
178 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
179 bool exposedInAndroidJavaAPI() const override { return true; }
180 #endif
181
182 protected:
SkSumPathEffect(sk_sp<SkPathEffect> first,sk_sp<SkPathEffect> second)183 SkSumPathEffect(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second)
184 : INHERITED(first, second) {}
185
186 private:
187 // illegal
188 SkSumPathEffect(const SkSumPathEffect&);
189 SkSumPathEffect& operator=(const SkSumPathEffect&);
190 friend class SkPathEffect;
191
192 typedef SkPairPathEffect INHERITED;
193 };
194
CreateProc(SkReadBuffer & buffer)195 sk_sp<SkFlattenable> SkSumPathEffect::CreateProc(SkReadBuffer& buffer) {
196 sk_sp<SkPathEffect> pe0(buffer.readPathEffect());
197 sk_sp<SkPathEffect> pe1(buffer.readPathEffect());
198 return SkSumPathEffect::Make(pe0, pe1);
199 }
200
201 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const202 void SkSumPathEffect::toString(SkString* str) const {
203 str->appendf("SkSumPathEffect: (");
204 this->INHERITED::toString(str);
205 str->appendf(")");
206 }
207 #endif
208
209 ///////////////////////////////////////////////////////////////////////////////////////////////////
210
MakeSum(sk_sp<SkPathEffect> first,sk_sp<SkPathEffect> second)211 sk_sp<SkPathEffect> SkPathEffect::MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) {
212 return SkSumPathEffect::Make(std::move(first), std::move(second));
213 }
214
MakeCompose(sk_sp<SkPathEffect> outer,sk_sp<SkPathEffect> inner)215 sk_sp<SkPathEffect> SkPathEffect::MakeCompose(sk_sp<SkPathEffect> outer,
216 sk_sp<SkPathEffect> inner) {
217 return SkComposePathEffect::Make(std::move(outer), std::move(inner));
218 }
219
220 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkPathEffect)
221 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposePathEffect)
222 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
223 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
224