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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 private: | 90 private: |
91 Cache* fCache; | 91 Cache* fCache; |
92 Encoder* fEncoder; | 92 Encoder* fEncoder; |
93 SkSTArray<4, ID> fToUndefine; | 93 SkSTArray<4, ID> fToUndefine; |
94 }; | 94 }; |
95 | 95 |
96 | 96 |
97 Cache* Cache::CreateNeverCache() { | 97 Cache* Cache::CreateNeverCache() { |
98 struct NeverCache final : public Cache { | 98 struct NeverCache final : public Cache { |
99 NeverCache() | 99 NeverCache() |
100 : fNextMatrix(Type::kMatrix) | 100 : fNextMatrix (Type::kMatrix) |
101 , fNextMisc (Type::kMisc) | 101 , fNextMisc (Type::kMisc) |
102 , fNextPath (Type::kPath) | 102 , fNextPath (Type::kPath) |
103 , fNextStroke(Type::kStroke) | 103 , fNextStroke (Type::kStroke) |
| 104 , fNextXfermode(Type::kXfermode) |
104 {} | 105 {} |
105 void cleanup(Encoder*) override {} | 106 void cleanup(Encoder*) override {} |
106 | 107 |
107 static bool Helper(ID* next, ID* id, LookupScope* ls) { | 108 static bool Helper(ID* next, ID* id, LookupScope* ls) { |
108 *id = (*next)++; | 109 *id = ++(*next); |
109 ls->undefineWhenDone(*id); | 110 ls->undefineWhenDone(*id); |
110 return false; | 111 return false; |
111 } | 112 } |
112 | 113 |
113 bool lookup(const SkMatrix&, ID* id, LookupScope* ls) override { | 114 bool lookup(const SkMatrix&, ID* id, LookupScope* ls) override { |
114 return Helper(&fNextMatrix, id, ls); | 115 return Helper(&fNextMatrix, id, ls); |
115 } | 116 } |
116 bool lookup(const Misc&, ID* id, LookupScope* ls) override { | 117 bool lookup(const Misc&, ID* id, LookupScope* ls) override { |
117 return Helper(&fNextMisc, id, ls); | 118 return Helper(&fNextMisc, id, ls); |
118 } | 119 } |
119 bool lookup(const SkPath&, ID* id, LookupScope* ls) override { | 120 bool lookup(const SkPath&, ID* id, LookupScope* ls) override { |
120 return Helper(&fNextPath, id, ls); | 121 return Helper(&fNextPath, id, ls); |
121 } | 122 } |
122 bool lookup(const Stroke&, ID* id, LookupScope* ls) override { | 123 bool lookup(const Stroke&, ID* id, LookupScope* ls) override { |
123 return Helper(&fNextStroke, id, ls); | 124 return Helper(&fNextStroke, id, ls); |
124 } | 125 } |
| 126 bool lookup(const SkXfermode* xfermode, ID* id, LookupScope* ls) ove
rride { |
| 127 if (!xfermode) { |
| 128 *id = ID(Type::kXfermode); |
| 129 return true; // Null IDs are always defined. |
| 130 } |
| 131 return Helper(&fNextXfermode, id, ls); |
| 132 } |
125 | 133 |
126 ID fNextMatrix, | 134 ID fNextMatrix, |
127 fNextMisc, | 135 fNextMisc, |
128 fNextPath, | 136 fNextPath, |
129 fNextStroke; | 137 fNextStroke, |
| 138 fNextXfermode; |
130 }; | 139 }; |
131 return new NeverCache; | 140 return new NeverCache; |
132 } | 141 } |
133 | 142 |
134 // Can't be declared locally inside AlwaysCache because of the templating.
:( | 143 // These can't be declared locally inside AlwaysCache because of the templat
ing. :( |
135 template <typename T, typename Map> | 144 namespace { |
136 static bool always_cache_helper(const T& val, Map* map, ID* next, ID* id) { | 145 template <typename T, typename Map> |
137 if (ID* found = map->find(val)) { | 146 static bool always_cache_lookup(const T& val, Map* map, ID* next, ID* id
) { |
138 *id = *found; | 147 if (const ID* found = map->find(val)) { |
139 return true; | 148 *id = *found; |
| 149 return true; |
| 150 } |
| 151 *id = ++(*next); |
| 152 map->set(val, *id); |
| 153 return false; |
140 } | 154 } |
141 *id = (*next)++; | 155 |
142 map->set(val, *id); | 156 struct Undefiner { |
143 return false; | 157 Encoder* fEncoder; |
144 } | 158 |
| 159 template <typename T> |
| 160 void operator()(const T&, ID* id) const { fEncoder->undefine(*id); } |
| 161 }; |
| 162 |
| 163 // Maps const T* -> ID, and refs the key. nullptr always maps to ID(kTy
pe). |
| 164 template <typename T, Type kType> |
| 165 class RefKeyMap { |
| 166 public: |
| 167 RefKeyMap() {} |
| 168 ~RefKeyMap() { fMap.foreach([](const T* key, ID*) { key->unref(); })
; } |
| 169 |
| 170 void set(const T* key, const ID& id) { |
| 171 SkASSERT(key && id.type() == kType); |
| 172 fMap.set(SkRef(key), id); |
| 173 } |
| 174 |
| 175 void remove(const T* key) { |
| 176 SkASSERT(key); |
| 177 fMap.remove(key); |
| 178 key->unref(); |
| 179 } |
| 180 |
| 181 const ID* find(const T* key) const { |
| 182 static const ID nullID(kType); |
| 183 return key ? fMap.find(key) : &nullID; |
| 184 } |
| 185 |
| 186 template <typename Fn> |
| 187 void foreach(const Fn& fn) { fMap.foreach(fn); } |
| 188 private: |
| 189 SkTHashMap<const T*, ID> fMap; |
| 190 }; |
| 191 } // namespace |
145 | 192 |
146 Cache* Cache::CreateAlwaysCache() { | 193 Cache* Cache::CreateAlwaysCache() { |
147 struct AlwaysCache final : public Cache { | 194 struct AlwaysCache final : public Cache { |
148 AlwaysCache() | 195 AlwaysCache() |
149 : fNextMatrix(Type::kMatrix) | 196 : fNextMatrix (Type::kMatrix) |
150 , fNextMisc (Type::kMisc) | 197 , fNextMisc (Type::kMisc) |
151 , fNextPath (Type::kPath) | 198 , fNextPath (Type::kPath) |
152 , fNextStroke(Type::kStroke) | 199 , fNextStroke (Type::kStroke) |
| 200 , fNextXfermode(Type::kXfermode) |
153 {} | 201 {} |
154 | 202 |
155 void cleanup(Encoder* encoder) override { | 203 void cleanup(Encoder* encoder) override { |
156 fMatrix.foreach([=](const SkMatrix&, ID* id) { encoder->undefine
(*id); }); | 204 Undefiner undef{encoder}; |
157 fMisc .foreach([=](const Misc&, ID* id) { encoder->undefine
(*id); }); | 205 fMatrix .foreach(undef); |
158 fPath .foreach([=](const SkPath&, ID* id) { encoder->undefine
(*id); }); | 206 fMisc .foreach(undef); |
159 fStroke.foreach([=](const Stroke&, ID* id) { encoder->undefine
(*id); }); | 207 fPath .foreach(undef); |
| 208 fStroke .foreach(undef); |
| 209 fXfermode.foreach(undef); |
160 } | 210 } |
161 | 211 |
162 | 212 |
163 bool lookup(const SkMatrix& matrix, ID* id, LookupScope*) override { | 213 bool lookup(const SkMatrix& matrix, ID* id, LookupScope*) override { |
164 return always_cache_helper(matrix, &fMatrix, &fNextMatrix, id); | 214 return always_cache_lookup(matrix, &fMatrix, &fNextMatrix, id); |
165 } | 215 } |
166 bool lookup(const Misc& misc, ID* id, LookupScope*) override { | 216 bool lookup(const Misc& misc, ID* id, LookupScope*) override { |
167 return always_cache_helper(misc, &fMisc, &fNextMisc, id); | 217 return always_cache_lookup(misc, &fMisc, &fNextMisc, id); |
168 } | 218 } |
169 bool lookup(const SkPath& path, ID* id, LookupScope*) override { | 219 bool lookup(const SkPath& path, ID* id, LookupScope*) override { |
170 return always_cache_helper(path, &fPath, &fNextPath, id); | 220 return always_cache_lookup(path, &fPath, &fNextPath, id); |
171 } | 221 } |
172 bool lookup(const Stroke& stroke, ID* id, LookupScope*) override { | 222 bool lookup(const Stroke& stroke, ID* id, LookupScope*) override { |
173 return always_cache_helper(stroke, &fStroke, &fNextStroke, id); | 223 return always_cache_lookup(stroke, &fStroke, &fNextStroke, id); |
| 224 } |
| 225 bool lookup(const SkXfermode* xfermode, ID* id, LookupScope*) overri
de { |
| 226 return always_cache_lookup(xfermode, &fXfermode, &fNextXfermode,
id); |
174 } | 227 } |
175 | 228 |
176 SkTHashMap<SkMatrix, ID> fMatrix; | 229 SkTHashMap<SkMatrix, ID> fMatrix; |
177 SkTHashMap<Misc, ID, MiscHash> fMisc; | 230 SkTHashMap<Misc, ID, MiscHash> fMisc; |
178 SkTHashMap<SkPath, ID> fPath; | 231 SkTHashMap<SkPath, ID> fPath; |
179 SkTHashMap<Stroke, ID> fStroke; | 232 SkTHashMap<Stroke, ID> fStroke; |
| 233 RefKeyMap<SkXfermode, Type::kXfermode> fXfermode; |
| 234 |
180 ID fNextMatrix, | 235 ID fNextMatrix, |
181 fNextMisc, | 236 fNextMisc, |
182 fNextPath, | 237 fNextPath, |
183 fNextStroke; | 238 fNextStroke, |
| 239 fNextXfermode; |
184 }; | 240 }; |
185 return new AlwaysCache; | 241 return new AlwaysCache; |
186 } | 242 } |
187 | 243 |
188 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | 244 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
189 | 245 |
190 Client::Client(Cache* cache, Encoder* encoder) | 246 Client::Client(Cache* cache, Encoder* encoder) |
191 : SkCanvas(1,1) | 247 : SkCanvas(1,1) |
192 , fCache(cache) | 248 , fCache(cache) |
193 , fEncoder(encoder) | 249 , fEncoder(encoder) |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 const SkPaint& paint) { | 285 const SkPaint& paint) { |
230 SkPath path; | 286 SkPath path; |
231 path.addRRect(outside); | 287 path.addRRect(outside); |
232 path.addRRect(inside, SkPath::kCCW_Direction); | 288 path.addRRect(inside, SkPath::kCCW_Direction); |
233 this->onDrawPath(path, paint); | 289 this->onDrawPath(path, paint); |
234 } | 290 } |
235 | 291 |
236 void Client::onDrawPath(const SkPath& path, const SkPaint& paint) { | 292 void Client::onDrawPath(const SkPath& path, const SkPaint& paint) { |
237 LookupScope ls(fCache, fEncoder); | 293 LookupScope ls(fCache, fEncoder); |
238 ID p = ls.lookup(path), | 294 ID p = ls.lookup(path), |
239 m = ls.lookup(Misc::CreateFrom(paint)); | 295 m = ls.lookup(Misc::CreateFrom(paint)), |
| 296 x = ls.lookup(paint.getXfermode()); |
240 | 297 |
241 if (paint.getStyle() == SkPaint::kFill_Style) { | 298 if (paint.getStyle() == SkPaint::kFill_Style) { |
242 fEncoder->fillPath(p, m); | 299 fEncoder->fillPath(p, m, x); |
243 } else { | 300 } else { |
244 // TODO: handle kStrokeAndFill_Style | 301 // TODO: handle kStrokeAndFill_Style |
245 fEncoder->strokePath(p, m, ls.lookup(Stroke::CreateFrom(paint))); | 302 fEncoder->strokePath(p, m, x, ls.lookup(Stroke::CreateFrom(paint))); |
246 } | 303 } |
247 } | 304 } |
248 | 305 |
249 void Client::onDrawPaint(const SkPaint& paint) { | 306 void Client::onDrawPaint(const SkPaint& paint) { |
250 SkPath path; | 307 SkPath path; |
251 path.setFillType(SkPath::kInverseWinding_FillType); // Either inverse F
illType works fine. | 308 path.setFillType(SkPath::kInverseWinding_FillType); // Either inverse F
illType works fine. |
252 this->onDrawPath(path, paint); | 309 this->onDrawPath(path, paint); |
253 } | 310 } |
254 | 311 |
255 void Client::onDrawText(const void* text, size_t byteLength, SkScalar x, | 312 void Client::onDrawText(const void* text, size_t byteLength, SkScalar x, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 | 352 |
296 void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle e
dgeStyle) { | 353 void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle e
dgeStyle) { |
297 LookupScope ls(fCache, fEncoder); | 354 LookupScope ls(fCache, fEncoder); |
298 fEncoder->clipPath(ls.lookup(path), op, edgeStyle == kSoft_ClipEdgeStyle
); | 355 fEncoder->clipPath(ls.lookup(path), op, edgeStyle == kSoft_ClipEdgeStyle
); |
299 } | 356 } |
300 | 357 |
301 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | 358 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
302 | 359 |
303 Server::Server(SkCanvas* canvas) : fCanvas(canvas) {} | 360 Server::Server(SkCanvas* canvas) : fCanvas(canvas) {} |
304 | 361 |
305 void Server::define(ID id, const SkMatrix& v) { fMatrix.set(id, v); } | 362 void Server::define(ID id, const SkMatrix& v) { fMatrix .set(id, v); } |
306 void Server::define(ID id, const Misc& v) { fMisc .set(id, v); } | 363 void Server::define(ID id, const Misc& v) { fMisc .set(id, v); } |
307 void Server::define(ID id, const SkPath& v) { fPath .set(id, v); } | 364 void Server::define(ID id, const SkPath& v) { fPath .set(id, v); } |
308 void Server::define(ID id, const Stroke& v) { fStroke.set(id, v); } | 365 void Server::define(ID id, const Stroke& v) { fStroke .set(id, v); } |
| 366 void Server::define(ID id, SkXfermode* v) { fXfermode.set(id, v); } |
309 | 367 |
310 void Server::undefine(ID id) { | 368 void Server::undefine(ID id) { |
311 switch(id.type()) { | 369 switch(id.type()) { |
312 case Type::kMatrix: return fMatrix.remove(id); | 370 case Type::kMatrix: return fMatrix .remove(id); |
313 case Type::kMisc: return fMisc .remove(id); | 371 case Type::kMisc: return fMisc .remove(id); |
314 case Type::kPath: return fPath .remove(id); | 372 case Type::kPath: return fPath .remove(id); |
315 case Type::kStroke: return fStroke.remove(id); | 373 case Type::kStroke: return fStroke .remove(id); |
| 374 case Type::kXfermode: return fXfermode.remove(id); |
316 | 375 |
317 case Type::kNone: SkASSERT(false); | 376 case Type::kNone: SkASSERT(false); |
318 }; | 377 }; |
319 } | 378 } |
320 | 379 |
321 void Server:: save() { fCanvas->save(); } | 380 void Server:: save() { fCanvas->save(); } |
322 void Server::restore() { fCanvas->restore(); } | 381 void Server::restore() { fCanvas->restore(); } |
323 | 382 |
324 void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix))
; } | 383 void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix))
; } |
325 | 384 |
326 void Server::clipPath(ID path, SkRegion::Op op, bool aa) { | 385 void Server::clipPath(ID path, SkRegion::Op op, bool aa) { |
327 fCanvas->clipPath(fPath.find(path), op, aa); | 386 fCanvas->clipPath(fPath.find(path), op, aa); |
328 } | 387 } |
329 void Server::fillPath(ID path, ID misc) { | 388 void Server::fillPath(ID path, ID misc, ID xfermode) { |
330 SkPaint paint; | 389 SkPaint paint; |
331 paint.setStyle(SkPaint::kFill_Style); | 390 paint.setStyle(SkPaint::kFill_Style); |
332 fMisc.find(misc).applyTo(&paint); | 391 fMisc.find(misc).applyTo(&paint); |
| 392 paint.setXfermode(fXfermode.find(xfermode)); |
333 fCanvas->drawPath(fPath.find(path), paint); | 393 fCanvas->drawPath(fPath.find(path), paint); |
334 } | 394 } |
335 void Server::strokePath(ID path, ID misc, ID stroke) { | 395 void Server::strokePath(ID path, ID misc, ID xfermode, ID stroke) { |
336 SkPaint paint; | 396 SkPaint paint; |
337 paint.setStyle(SkPaint::kStroke_Style); | 397 paint.setStyle(SkPaint::kStroke_Style); |
338 fMisc .find(misc ).applyTo(&paint); | 398 fMisc .find(misc ).applyTo(&paint); |
339 fStroke.find(stroke).applyTo(&paint); | 399 fStroke.find(stroke).applyTo(&paint); |
| 400 paint.setXfermode(fXfermode.find(xfermode)); |
340 fCanvas->drawPath(fPath.find(path), paint); | 401 fCanvas->drawPath(fPath.find(path), paint); |
341 } | 402 } |
342 | 403 |
343 } // namespace SkRemote | 404 } // namespace SkRemote |
OLD | NEW |