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 "include/core/SkPath.h" |
9 | #include "include/core/SkPathEffect.h" |
10 | #include "src/core/SkReadBuffer.h" |
11 | #include "src/core/SkWriteBuffer.h" |
12 | |
13 | /////////////////////////////////////////////////////////////////////////////// |
14 | |
15 | bool SkPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, |
16 | const SkRect* bounds) const { |
17 | SkPath tmp, *tmpDst = dst; |
18 | if (dst == &src) { |
19 | tmpDst = &tmp; |
20 | } |
21 | if (this->onFilterPath(tmpDst, src, rec, bounds)) { |
22 | if (dst == &src) { |
23 | *dst = tmp; |
24 | } |
25 | return true; |
26 | } |
27 | return false; |
28 | } |
29 | |
30 | void SkPathEffect::computeFastBounds(SkRect* dst, const SkRect& src) const { |
31 | *dst = this->onComputeFastBounds(src); |
32 | } |
33 | |
34 | bool SkPathEffect::asPoints(PointData* results, const SkPath& src, |
35 | const SkStrokeRec& rec, const SkMatrix& mx, const SkRect* rect) const { |
36 | return this->onAsPoints(results, src, rec, mx, rect); |
37 | } |
38 | |
39 | SkPathEffect::DashType SkPathEffect::asADash(DashInfo* info) const { |
40 | return this->onAsADash(info); |
41 | } |
42 | |
43 | /////////////////////////////////////////////////////////////////////////////// |
44 | |
45 | /** \class SkPairPathEffect |
46 | |
47 | Common baseclass for Compose and Sum. This subclass manages two pathEffects, |
48 | including flattening them. It does nothing in filterPath, and is only useful |
49 | for managing the lifetimes of its two arguments. |
50 | */ |
51 | class SkPairPathEffect : public SkPathEffect { |
52 | protected: |
53 | SkPairPathEffect(sk_sp<SkPathEffect> pe0, sk_sp<SkPathEffect> pe1) |
54 | : fPE0(std::move(pe0)), fPE1(std::move(pe1)) |
55 | { |
56 | SkASSERT(fPE0.get()); |
57 | SkASSERT(fPE1.get()); |
58 | } |
59 | |
60 | void flatten(SkWriteBuffer& buffer) const override { |
61 | buffer.writeFlattenable(fPE0.get()); |
62 | buffer.writeFlattenable(fPE1.get()); |
63 | } |
64 | |
65 | // these are visible to our subclasses |
66 | sk_sp<SkPathEffect> fPE0; |
67 | sk_sp<SkPathEffect> fPE1; |
68 | |
69 | private: |
70 | typedef SkPathEffect INHERITED; |
71 | }; |
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 | */ |
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 | |
97 | protected: |
98 | SkComposePathEffect(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner) |
99 | : INHERITED(outer, inner) {} |
100 | |
101 | bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, |
102 | const SkRect* cullRect) const override { |
103 | SkPath tmp; |
104 | const SkPath* ptr = &src; |
105 | |
106 | if (fPE1->filterPath(&tmp, src, rec, cullRect)) { |
107 | ptr = &tmp; |
108 | } |
109 | return fPE0->filterPath(dst, *ptr, rec, cullRect); |
110 | } |
111 | |
112 | private: |
113 | SK_FLATTENABLE_HOOKS(SkComposePathEffect) |
114 | |
115 | // illegal |
116 | SkComposePathEffect(const SkComposePathEffect&); |
117 | SkComposePathEffect& operator=(const SkComposePathEffect&); |
118 | friend class SkPathEffect; |
119 | |
120 | typedef SkPairPathEffect INHERITED; |
121 | }; |
122 | |
123 | sk_sp<SkFlattenable> SkComposePathEffect::CreateProc(SkReadBuffer& buffer) { |
124 | sk_sp<SkPathEffect> pe0(buffer.readPathEffect()); |
125 | sk_sp<SkPathEffect> pe1(buffer.readPathEffect()); |
126 | return SkComposePathEffect::Make(std::move(pe0), std::move(pe1)); |
127 | } |
128 | |
129 | /////////////////////////////////////////////////////////////////////////////// |
130 | |
131 | /** \class SkSumPathEffect |
132 | |
133 | This subclass of SkPathEffect applies two pathEffects, one after the other. |
134 | Its filterPath() returns true if either of the effects succeeded. |
135 | */ |
136 | class SkSumPathEffect : public SkPairPathEffect { |
137 | public: |
138 | /** Construct a pathEffect whose effect is to apply two effects, in sequence. |
139 | (e.g. first(path) + second(path)) |
140 | The reference counts for first and second are both incremented in the constructor, |
141 | and decremented in the destructor. |
142 | */ |
143 | static sk_sp<SkPathEffect> Make(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) { |
144 | if (!first) { |
145 | return second; |
146 | } |
147 | if (!second) { |
148 | return first; |
149 | } |
150 | return sk_sp<SkPathEffect>(new SkSumPathEffect(first, second)); |
151 | } |
152 | |
153 | SK_FLATTENABLE_HOOKS(SkSumPathEffect) |
154 | |
155 | protected: |
156 | SkSumPathEffect(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) |
157 | : INHERITED(first, second) {} |
158 | |
159 | bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, |
160 | const SkRect* cullRect) const override { |
161 | // use bit-or so that we always call both, even if the first one succeeds |
162 | return fPE0->filterPath(dst, src, rec, cullRect) | |
163 | fPE1->filterPath(dst, src, rec, cullRect); |
164 | } |
165 | |
166 | private: |
167 | // illegal |
168 | SkSumPathEffect(const SkSumPathEffect&); |
169 | SkSumPathEffect& operator=(const SkSumPathEffect&); |
170 | friend class SkPathEffect; |
171 | |
172 | typedef SkPairPathEffect INHERITED; |
173 | }; |
174 | |
175 | sk_sp<SkFlattenable> SkSumPathEffect::CreateProc(SkReadBuffer& buffer) { |
176 | sk_sp<SkPathEffect> pe0(buffer.readPathEffect()); |
177 | sk_sp<SkPathEffect> pe1(buffer.readPathEffect()); |
178 | return SkSumPathEffect::Make(pe0, pe1); |
179 | } |
180 | |
181 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
182 | |
183 | sk_sp<SkPathEffect> SkPathEffect::MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second) { |
184 | return SkSumPathEffect::Make(std::move(first), std::move(second)); |
185 | } |
186 | |
187 | sk_sp<SkPathEffect> SkPathEffect::MakeCompose(sk_sp<SkPathEffect> outer, |
188 | sk_sp<SkPathEffect> inner) { |
189 | return SkComposePathEffect::Make(std::move(outer), std::move(inner)); |
190 | } |
191 | |
192 | void SkPathEffect::RegisterFlattenables() { |
193 | SK_REGISTER_FLATTENABLE(SkComposePathEffect); |
194 | SK_REGISTER_FLATTENABLE(SkSumPathEffect); |
195 | } |
196 | |