OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPath.h" | 8 #include "SkPath.h" |
9 #include "SkRect.h" | 9 #include "SkRect.h" |
10 #include "SkRemote.h" | 10 #include "SkRemote.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 && a.fMiter == b.fMiter | 65 && a.fMiter == b.fMiter |
66 && a.fCap == b.fCap | 66 && a.fCap == b.fCap |
67 && a.fJoin == b.fJoin; | 67 && a.fJoin == b.fJoin; |
68 } | 68 } |
69 | 69 |
70 // The default SkGoodHash works fine for Stroke, as it's dense. | 70 // The default SkGoodHash works fine for Stroke, as it's dense. |
71 static_assert(sizeof(Stroke) == offsetof(Stroke, fJoin) + sizeof(Stroke().fJ
oin), ""); | 71 static_assert(sizeof(Stroke) == offsetof(Stroke, fJoin) + sizeof(Stroke().fJ
oin), ""); |
72 | 72 |
73 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | 73 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
74 | 74 |
75 class LookupScope { | 75 class CachingEncoder final : public Encoder { |
76 public: | 76 public: |
77 LookupScope(Cache* cache, Encoder* encoder) : fCache(cache), fEncoder(en
coder) {} | 77 explicit CachingEncoder(Encoder* wrapped) : fWrapped(wrapped) {} |
78 ~LookupScope() { for (ID id : fToUndefine) { fEncoder->undefine(id); } } | |
79 void undefineWhenDone(ID id) { fToUndefine.push_back(id); } | |
80 | |
81 template <typename T> | |
82 ID lookup(const T& val) { | |
83 ID id; | |
84 if (!fCache->lookup(val, &id, this)) { | |
85 fEncoder->define(id, val); | |
86 } | |
87 return id; | |
88 } | |
89 | 78 |
90 private: | 79 private: |
91 Cache* fCache; | 80 struct Undef { |
92 Encoder* fEncoder; | |
93 SkSTArray<4, ID> fToUndefine; | |
94 }; | |
95 | |
96 | |
97 Cache* Cache::CreateNeverCache() { | |
98 struct NeverCache final : public Cache { | |
99 NeverCache() | |
100 : fNextMatrix (Type::kMatrix) | |
101 , fNextMisc (Type::kMisc) | |
102 , fNextPath (Type::kPath) | |
103 , fNextStroke (Type::kStroke) | |
104 , fNextShader (Type::kShader) | |
105 , fNextXfermode(Type::kXfermode) | |
106 {} | |
107 void cleanup(Encoder*) override {} | |
108 | |
109 static bool Helper(ID* next, ID* id, LookupScope* ls) { | |
110 *id = ++(*next); | |
111 ls->undefineWhenDone(*id); | |
112 return false; | |
113 } | |
114 | |
115 bool lookup(const SkMatrix&, ID* id, LookupScope* ls) override { | |
116 return Helper(&fNextMatrix, id, ls); | |
117 } | |
118 bool lookup(const Misc&, ID* id, LookupScope* ls) override { | |
119 return Helper(&fNextMisc, id, ls); | |
120 } | |
121 bool lookup(const SkPath&, ID* id, LookupScope* ls) override { | |
122 return Helper(&fNextPath, id, ls); | |
123 } | |
124 bool lookup(const Stroke&, ID* id, LookupScope* ls) override { | |
125 return Helper(&fNextStroke, id, ls); | |
126 } | |
127 bool lookup(const SkShader* shader, ID* id, LookupScope* ls) overrid
e { | |
128 if (!shader) { | |
129 *id = ID(Type::kShader); | |
130 return true; // Null IDs are always defined. | |
131 } | |
132 return Helper(&fNextShader, id, ls); | |
133 } | |
134 bool lookup(const SkXfermode* xfermode, ID* id, LookupScope* ls) ove
rride { | |
135 if (!xfermode) { | |
136 *id = ID(Type::kXfermode); | |
137 return true; // Null IDs are always defined. | |
138 } | |
139 return Helper(&fNextXfermode, id, ls); | |
140 } | |
141 | |
142 ID fNextMatrix, | |
143 fNextMisc, | |
144 fNextPath, | |
145 fNextStroke, | |
146 fNextShader, | |
147 fNextXfermode; | |
148 }; | |
149 return new NeverCache; | |
150 } | |
151 | |
152 // These can't be declared locally inside AlwaysCache because of the templat
ing. :( | |
153 namespace { | |
154 template <typename T, typename Map> | |
155 static bool always_cache_lookup(const T& val, Map* map, ID* next, ID* id
) { | |
156 if (const ID* found = map->find(val)) { | |
157 *id = *found; | |
158 return true; | |
159 } | |
160 *id = ++(*next); | |
161 map->set(val, *id); | |
162 return false; | |
163 } | |
164 | |
165 struct Undefiner { | |
166 Encoder* fEncoder; | 81 Encoder* fEncoder; |
167 | |
168 template <typename T> | 82 template <typename T> |
169 void operator()(const T&, ID* id) const { fEncoder->undefine(*id); } | 83 void operator()(const T&, ID* id) const { fEncoder->undefine(*id); } |
170 }; | 84 }; |
171 | 85 |
172 // Maps const T* -> ID, and refs the key. nullptr always maps to ID(kTy
pe). | 86 ~CachingEncoder() override { |
| 87 Undef undef{fWrapped}; |
| 88 fMatrix .foreach(undef); |
| 89 fMisc .foreach(undef); |
| 90 fPath .foreach(undef); |
| 91 fStroke .foreach(undef); |
| 92 fShader .foreach(undef); |
| 93 fXfermode.foreach(undef); |
| 94 } |
| 95 |
| 96 template <typename Map, typename T> |
| 97 ID define(Map* map, const T& v) { |
| 98 if (const ID* id = map->find(v)) { |
| 99 return *id; |
| 100 } |
| 101 ID id = fWrapped->define(v); |
| 102 map->set(v, id); |
| 103 return id; |
| 104 } |
| 105 |
| 106 ID define(const SkMatrix& v) override { return this->define(&fMatrix,
v); } |
| 107 ID define(const Misc& v) override { return this->define(&fMisc,
v); } |
| 108 ID define(const SkPath& v) override { return this->define(&fPath,
v); } |
| 109 ID define(const Stroke& v) override { return this->define(&fStroke,
v); } |
| 110 ID define(SkShader* v) override { return this->define(&fShader,
v); } |
| 111 ID define(SkXfermode* v) override { return this->define(&fXfermode,
v); } |
| 112 |
| 113 void undefine(ID) override {} |
| 114 |
| 115 void save() override { fWrapped-> save(); } |
| 116 void restore() override { fWrapped->restore(); } |
| 117 |
| 118 void setMatrix(ID matrix) override { fWrapped->setMatrix(matrix); } |
| 119 |
| 120 void clipPath(ID path, SkRegion::Op op, bool aa) override { |
| 121 fWrapped->clipPath(path, op, aa); |
| 122 } |
| 123 void fillPath(ID path, ID misc, ID shader, ID xfermode) override { |
| 124 fWrapped->fillPath(path, misc, shader, xfermode); |
| 125 } |
| 126 void strokePath(ID path, ID misc, ID shader, ID xfermode, ID stroke) ove
rride { |
| 127 fWrapped->strokePath(path, misc, shader, xfermode, stroke); |
| 128 } |
| 129 |
| 130 // Maps const T* -> ID, and refs the key. |
173 template <typename T, Type kType> | 131 template <typename T, Type kType> |
174 class RefKeyMap { | 132 class RefKeyMap { |
175 public: | 133 public: |
176 RefKeyMap() {} | 134 RefKeyMap() {} |
177 ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { key->unref(); })
; } | 135 ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { SkSafeUnref(key)
; }); } |
178 | 136 |
179 void set(const T* key, const ID& id) { | 137 void set(const T* key, ID id) { |
180 SkASSERT(key && id.type() == kType); | 138 SkASSERT(id.type() == kType); |
181 fMap.set(SkRef(key), id); | 139 fMap.set(SkSafeRef(key), id); |
182 } | 140 } |
183 | 141 |
184 void remove(const T* key) { | 142 void remove(const T* key) { |
185 SkASSERT(key); | |
186 fMap.remove(key); | 143 fMap.remove(key); |
187 key->unref(); | 144 SkSafeUnref(key); |
188 } | 145 } |
189 | 146 |
190 const ID* find(const T* key) const { | 147 const ID* find(const T* key) const { |
191 static const ID nullID(kType); | 148 return fMap.find(key); |
192 return key ? fMap.find(key) : &nullID; | |
193 } | 149 } |
194 | 150 |
195 template <typename Fn> | 151 template <typename Fn> |
196 void foreach(const Fn& fn) { fMap.foreach(fn); } | 152 void foreach(const Fn& fn) { |
| 153 fMap.foreach(fn); |
| 154 } |
197 private: | 155 private: |
198 SkTHashMap<const T*, ID> fMap; | 156 SkTHashMap<const T*, ID> fMap; |
199 }; | 157 }; |
200 } // namespace | |
201 | 158 |
202 Cache* Cache::CreateAlwaysCache() { | 159 SkTHashMap<SkMatrix, ID> fMatrix; |
203 struct AlwaysCache final : public Cache { | 160 SkTHashMap<Misc, ID, MiscHash> fMisc; |
204 AlwaysCache() | 161 SkTHashMap<SkPath, ID> fPath; |
205 : fNextMatrix (Type::kMatrix) | 162 SkTHashMap<Stroke, ID> fStroke; |
206 , fNextMisc (Type::kMisc) | 163 RefKeyMap<SkShader, Type::kShader> fShader; |
207 , fNextPath (Type::kPath) | 164 RefKeyMap<SkXfermode, Type::kXfermode> fXfermode; |
208 , fNextStroke (Type::kStroke) | |
209 , fNextShader (Type::kShader) | |
210 , fNextXfermode(Type::kXfermode) | |
211 {} | |
212 | 165 |
213 void cleanup(Encoder* encoder) override { | 166 Encoder* fWrapped; |
214 Undefiner undef{encoder}; | 167 }; |
215 fMatrix .foreach(undef); | |
216 fMisc .foreach(undef); | |
217 fPath .foreach(undef); | |
218 fStroke .foreach(undef); | |
219 fShader .foreach(undef); | |
220 fXfermode.foreach(undef); | |
221 } | |
222 | 168 |
223 | 169 Encoder* Encoder::CreateCachingEncoder(Encoder* wrapped) { return new Cachin
gEncoder(wrapped); } |
224 bool lookup(const SkMatrix& matrix, ID* id, LookupScope*) override { | |
225 return always_cache_lookup(matrix, &fMatrix, &fNextMatrix, id); | |
226 } | |
227 bool lookup(const Misc& misc, ID* id, LookupScope*) override { | |
228 return always_cache_lookup(misc, &fMisc, &fNextMisc, id); | |
229 } | |
230 bool lookup(const SkPath& path, ID* id, LookupScope*) override { | |
231 return always_cache_lookup(path, &fPath, &fNextPath, id); | |
232 } | |
233 bool lookup(const Stroke& stroke, ID* id, LookupScope*) override { | |
234 return always_cache_lookup(stroke, &fStroke, &fNextStroke, id); | |
235 } | |
236 bool lookup(const SkShader* shader, ID* id, LookupScope*) override { | |
237 return always_cache_lookup(shader, &fShader, &fNextShader, id); | |
238 } | |
239 bool lookup(const SkXfermode* xfermode, ID* id, LookupScope*) overri
de { | |
240 return always_cache_lookup(xfermode, &fXfermode, &fNextXfermode,
id); | |
241 } | |
242 | |
243 SkTHashMap<SkMatrix, ID> fMatrix; | |
244 SkTHashMap<Misc, ID, MiscHash> fMisc; | |
245 SkTHashMap<SkPath, ID> fPath; | |
246 SkTHashMap<Stroke, ID> fStroke; | |
247 RefKeyMap<SkShader, Type::kShader> fShader; | |
248 RefKeyMap<SkXfermode, Type::kXfermode> fXfermode; | |
249 | |
250 ID fNextMatrix, | |
251 fNextMisc, | |
252 fNextPath, | |
253 fNextStroke, | |
254 fNextShader, | |
255 fNextXfermode; | |
256 }; | |
257 return new AlwaysCache; | |
258 } | |
259 | 170 |
260 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | 171 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
261 | 172 |
262 Client::Client(Cache* cache, Encoder* encoder) | 173 // Calls Encoder::define() when created, Encoder::undefine() when destroyed. |
| 174 class Client::AutoID : ::SkNoncopyable { |
| 175 public: |
| 176 template <typename T> |
| 177 explicit AutoID(Encoder* encoder, const T& val) |
| 178 : fEncoder(encoder) |
| 179 , fID(encoder->define(val)) {} |
| 180 ~AutoID() { if (fEncoder) fEncoder->undefine(fID); } |
| 181 |
| 182 AutoID(AutoID&& o) : fEncoder(o.fEncoder), fID(o.fID) { |
| 183 o.fEncoder = nullptr; |
| 184 } |
| 185 AutoID& operator=(AutoID&&) = delete; |
| 186 |
| 187 operator ID () const { return fID; } |
| 188 |
| 189 private: |
| 190 Encoder* fEncoder; |
| 191 const ID fID; |
| 192 }; |
| 193 |
| 194 template <typename T> |
| 195 Client::AutoID Client::id(const T& val) { return AutoID(fEncoder, val); } |
| 196 |
| 197 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
| 198 |
| 199 Client::Client(Encoder* encoder) |
263 : SkCanvas(1,1) | 200 : SkCanvas(1,1) |
264 , fCache(cache) | |
265 , fEncoder(encoder) | 201 , fEncoder(encoder) |
266 {} | 202 {} |
267 | 203 |
268 Client::~Client() { | |
269 fCache->cleanup(fEncoder); | |
270 } | |
271 | |
272 void Client::willSave() { fEncoder->save(); } | 204 void Client::willSave() { fEncoder->save(); } |
273 void Client::didRestore() { fEncoder->restore(); } | 205 void Client::didRestore() { fEncoder->restore(); } |
274 | 206 |
275 void Client::didConcat (const SkMatrix&) { this->didSetMatrix(this->getTot
alMatrix()); } | 207 void Client::didConcat (const SkMatrix&) { this->didSetMatrix(this->getTot
alMatrix()); } |
276 void Client::didSetMatrix(const SkMatrix& matrix) { | 208 void Client::didSetMatrix(const SkMatrix& matrix) { |
277 LookupScope ls(fCache, fEncoder); | 209 fEncoder->setMatrix(this->id(matrix)); |
278 fEncoder->setMatrix(ls.lookup(matrix)); | |
279 } | 210 } |
280 | 211 |
281 void Client::onDrawOval(const SkRect& oval, const SkPaint& paint) { | 212 void Client::onDrawOval(const SkRect& oval, const SkPaint& paint) { |
282 SkPath path; | 213 SkPath path; |
283 path.addOval(oval); | 214 path.addOval(oval); |
284 this->onDrawPath(path, paint); | 215 this->onDrawPath(path, paint); |
285 } | 216 } |
286 | 217 |
287 void Client::onDrawRect(const SkRect& rect, const SkPaint& paint) { | 218 void Client::onDrawRect(const SkRect& rect, const SkPaint& paint) { |
288 SkPath path; | 219 SkPath path; |
(...skipping 10 matching lines...) Expand all Loading... |
299 void Client::onDrawDRRect(const SkRRect& outside, | 230 void Client::onDrawDRRect(const SkRRect& outside, |
300 const SkRRect& inside, | 231 const SkRRect& inside, |
301 const SkPaint& paint) { | 232 const SkPaint& paint) { |
302 SkPath path; | 233 SkPath path; |
303 path.addRRect(outside); | 234 path.addRRect(outside); |
304 path.addRRect(inside, SkPath::kCCW_Direction); | 235 path.addRRect(inside, SkPath::kCCW_Direction); |
305 this->onDrawPath(path, paint); | 236 this->onDrawPath(path, paint); |
306 } | 237 } |
307 | 238 |
308 void Client::onDrawPath(const SkPath& path, const SkPaint& paint) { | 239 void Client::onDrawPath(const SkPath& path, const SkPaint& paint) { |
309 LookupScope ls(fCache, fEncoder); | 240 auto p = this->id(path), |
310 ID p = ls.lookup(path), | 241 m = this->id(Misc::CreateFrom(paint)), |
311 m = ls.lookup(Misc::CreateFrom(paint)), | 242 s = this->id(paint.getShader()), |
312 s = ls.lookup(paint.getShader()), | 243 x = this->id(paint.getXfermode()); |
313 x = ls.lookup(paint.getXfermode()); | |
314 | 244 |
315 if (paint.getStyle() == SkPaint::kFill_Style) { | 245 if (paint.getStyle() == SkPaint::kFill_Style) { |
316 fEncoder->fillPath(p, m, s, x); | 246 fEncoder->fillPath(p, m, s, x); |
317 } else { | 247 } else { |
318 // TODO: handle kStrokeAndFill_Style | 248 // TODO: handle kStrokeAndFill_Style |
319 fEncoder->strokePath(p, m, s, x, ls.lookup(Stroke::CreateFrom(paint)
)); | 249 fEncoder->strokePath(p, m, s, x, this->id(Stroke::CreateFrom(paint))
); |
320 } | 250 } |
321 } | 251 } |
322 | 252 |
323 void Client::onDrawPaint(const SkPaint& paint) { | 253 void Client::onDrawPaint(const SkPaint& paint) { |
324 SkPath path; | 254 SkPath path; |
325 path.setFillType(SkPath::kInverseWinding_FillType); // Either inverse F
illType works fine. | 255 path.setFillType(SkPath::kInverseWinding_FillType); // Either inverse F
illType works fine. |
326 this->onDrawPath(path, paint); | 256 this->onDrawPath(path, paint); |
327 } | 257 } |
328 | 258 |
329 void Client::onDrawText(const void* text, size_t byteLength, SkScalar x, | 259 void Client::onDrawText(const void* text, size_t byteLength, SkScalar x, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 this->onClipPath(path, op, edgeStyle); | 291 this->onClipPath(path, op, edgeStyle); |
362 } | 292 } |
363 | 293 |
364 void Client::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyl
e edgeStyle) { | 294 void Client::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyl
e edgeStyle) { |
365 SkPath path; | 295 SkPath path; |
366 path.addRRect(rrect); | 296 path.addRRect(rrect); |
367 this->onClipPath(path, op, edgeStyle); | 297 this->onClipPath(path, op, edgeStyle); |
368 } | 298 } |
369 | 299 |
370 void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle e
dgeStyle) { | 300 void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle e
dgeStyle) { |
371 LookupScope ls(fCache, fEncoder); | 301 fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeStyle)
; |
372 fEncoder->clipPath(ls.lookup(path), op, edgeStyle == kSoft_ClipEdgeStyle
); | |
373 } | 302 } |
374 | 303 |
375 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | 304 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
376 | 305 |
377 Server::Server(SkCanvas* canvas) : fCanvas(canvas) {} | 306 Server::Server(SkCanvas* canvas) : fCanvas(canvas) {} |
378 | 307 |
379 void Server::define(ID id, const SkMatrix& v) { fMatrix .set(id, v); } | 308 template <typename Map, typename T> |
380 void Server::define(ID id, const Misc& v) { fMisc .set(id, v); } | 309 ID Server::define(Type type, Map* map, const T& val) { |
381 void Server::define(ID id, const SkPath& v) { fPath .set(id, v); } | 310 ID id(type, fNextID++); |
382 void Server::define(ID id, const Stroke& v) { fStroke .set(id, v); } | 311 map->set(id, val); |
383 void Server::define(ID id, SkShader* v) { fShader .set(id, v); } | 312 return id; |
384 void Server::define(ID id, SkXfermode* v) { fXfermode.set(id, v); } | 313 } |
| 314 |
| 315 ID Server::define(const SkMatrix& v) { return this->define(Type::kMatrix,
&fMatrix, v); } |
| 316 ID Server::define(const Misc& v) { return this->define(Type::kMisc,
&fMisc, v); } |
| 317 ID Server::define(const SkPath& v) { return this->define(Type::kPath,
&fPath, v); } |
| 318 ID Server::define(const Stroke& v) { return this->define(Type::kStroke,
&fStroke, v); } |
| 319 ID Server::define(SkShader* v) { return this->define(Type::kShader,
&fShader, v); } |
| 320 ID Server::define(SkXfermode* v) { return this->define(Type::kXfermode,
&fXfermode, v); } |
385 | 321 |
386 void Server::undefine(ID id) { | 322 void Server::undefine(ID id) { |
387 switch(id.type()) { | 323 switch(id.type()) { |
388 case Type::kMatrix: return fMatrix .remove(id); | 324 case Type::kMatrix: return fMatrix .remove(id); |
389 case Type::kMisc: return fMisc .remove(id); | 325 case Type::kMisc: return fMisc .remove(id); |
390 case Type::kPath: return fPath .remove(id); | 326 case Type::kPath: return fPath .remove(id); |
391 case Type::kStroke: return fStroke .remove(id); | 327 case Type::kStroke: return fStroke .remove(id); |
392 case Type::kShader: return fShader .remove(id); | 328 case Type::kShader: return fShader .remove(id); |
393 case Type::kXfermode: return fXfermode.remove(id); | 329 case Type::kXfermode: return fXfermode.remove(id); |
394 | |
395 case Type::kNone: SkASSERT(false); | |
396 }; | 330 }; |
397 } | 331 } |
398 | 332 |
399 void Server:: save() { fCanvas->save(); } | 333 void Server:: save() { fCanvas->save(); } |
400 void Server::restore() { fCanvas->restore(); } | 334 void Server::restore() { fCanvas->restore(); } |
401 | 335 |
402 void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix))
; } | 336 void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix))
; } |
403 | 337 |
404 void Server::clipPath(ID path, SkRegion::Op op, bool aa) { | 338 void Server::clipPath(ID path, SkRegion::Op op, bool aa) { |
405 fCanvas->clipPath(fPath.find(path), op, aa); | 339 fCanvas->clipPath(fPath.find(path), op, aa); |
(...skipping 10 matching lines...) Expand all Loading... |
416 SkPaint paint; | 350 SkPaint paint; |
417 paint.setStyle(SkPaint::kStroke_Style); | 351 paint.setStyle(SkPaint::kStroke_Style); |
418 fMisc .find(misc ).applyTo(&paint); | 352 fMisc .find(misc ).applyTo(&paint); |
419 fStroke.find(stroke).applyTo(&paint); | 353 fStroke.find(stroke).applyTo(&paint); |
420 paint.setShader (fShader .find(shader)); | 354 paint.setShader (fShader .find(shader)); |
421 paint.setXfermode(fXfermode.find(xfermode)); | 355 paint.setXfermode(fXfermode.find(xfermode)); |
422 fCanvas->drawPath(fPath.find(path), paint); | 356 fCanvas->drawPath(fPath.find(path), paint); |
423 } | 357 } |
424 | 358 |
425 } // namespace SkRemote | 359 } // namespace SkRemote |
OLD | NEW |