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 "SkCanvas.h" |
8 #include "SkPath.h" | 9 #include "SkPath.h" |
9 #include "SkRect.h" | 10 #include "SkRect.h" |
10 #include "SkRemote.h" | 11 #include "SkRemote.h" |
| 12 #include "SkShader.h" |
| 13 #include "SkTHash.h" |
11 | 14 |
12 namespace SkRemote { | 15 namespace SkRemote { |
13 | 16 |
14 Misc Misc::CreateFrom(const SkPaint& paint) { | 17 Misc Misc::CreateFrom(const SkPaint& paint) { |
15 Misc misc = { | 18 Misc misc = { |
16 paint.getColor(), | 19 paint.getColor(), |
17 paint.getFilterQuality(), | 20 paint.getFilterQuality(), |
18 paint.isAntiAlias(), | 21 paint.isAntiAlias(), |
19 paint.isDither(), | 22 paint.isDither(), |
20 }; | 23 }; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 && a.fMiter == b.fMiter | 68 && a.fMiter == b.fMiter |
66 && a.fCap == b.fCap | 69 && a.fCap == b.fCap |
67 && a.fJoin == b.fJoin; | 70 && a.fJoin == b.fJoin; |
68 } | 71 } |
69 | 72 |
70 // The default SkGoodHash works fine for Stroke, as it's dense. | 73 // The default SkGoodHash works fine for Stroke, as it's dense. |
71 static_assert(sizeof(Stroke) == offsetof(Stroke, fJoin) + sizeof(Stroke().fJ
oin), ""); | 74 static_assert(sizeof(Stroke) == offsetof(Stroke, fJoin) + sizeof(Stroke().fJ
oin), ""); |
72 | 75 |
73 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | 76 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
74 | 77 |
| 78 class Canvas final : public SkCanvas { |
| 79 public: |
| 80 explicit Canvas(Encoder* encoder) |
| 81 : SkCanvas(1,1) |
| 82 , fEncoder(encoder) {} |
| 83 |
| 84 private: |
| 85 // Calls Encoder::define() when created, Encoder::undefine() when destro
yed. |
| 86 class AutoID : ::SkNoncopyable { |
| 87 public: |
| 88 template <typename T> |
| 89 explicit AutoID(Encoder* encoder, const T& val) |
| 90 : fEncoder(encoder) |
| 91 , fID(encoder->define(val)) {} |
| 92 ~AutoID() { if (fEncoder) fEncoder->undefine(fID); } |
| 93 |
| 94 AutoID(AutoID&& o) : fEncoder(o.fEncoder), fID(o.fID) { |
| 95 o.fEncoder = nullptr; |
| 96 } |
| 97 AutoID& operator=(AutoID&&) = delete; |
| 98 |
| 99 operator ID () const { return fID; } |
| 100 |
| 101 private: |
| 102 Encoder* fEncoder; |
| 103 const ID fID; |
| 104 }; |
| 105 |
| 106 template <typename T> |
| 107 AutoID id(const T& val) { return AutoID(fEncoder, val); } |
| 108 |
| 109 void willSave() override { fEncoder-> save(); } |
| 110 void didRestore() override { fEncoder->restore(); } |
| 111 |
| 112 void didConcat(const SkMatrix&) override { this->didSetMatrix(this->g
etTotalMatrix()); } |
| 113 void didSetMatrix(const SkMatrix& matrix) override { |
| 114 fEncoder->setMatrix(this->id(matrix)); |
| 115 } |
| 116 |
| 117 void onDrawOval(const SkRect& oval, const SkPaint& paint) override { |
| 118 SkPath path; |
| 119 path.addOval(oval); |
| 120 this->onDrawPath(path, paint); |
| 121 } |
| 122 |
| 123 void onDrawRect(const SkRect& rect, const SkPaint& paint) override { |
| 124 SkPath path; |
| 125 path.addRect(rect); |
| 126 this->onDrawPath(path, paint); |
| 127 } |
| 128 |
| 129 void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override { |
| 130 SkPath path; |
| 131 path.addRRect(rrect); |
| 132 this->onDrawPath(path, paint); |
| 133 } |
| 134 |
| 135 void onDrawDRRect(const SkRRect& outside, const SkRRect& inside, |
| 136 const SkPaint& paint) override { |
| 137 SkPath path; |
| 138 path.addRRect(outside); |
| 139 path.addRRect(inside, SkPath::kCCW_Direction); |
| 140 this->onDrawPath(path, paint); |
| 141 } |
| 142 |
| 143 void onDrawPath(const SkPath& path, const SkPaint& paint) override { |
| 144 auto p = this->id(path), |
| 145 m = this->id(Misc::CreateFrom(paint)), |
| 146 s = this->id(paint.getShader()), |
| 147 x = this->id(paint.getXfermode()); |
| 148 |
| 149 if (paint.getStyle() == SkPaint::kFill_Style) { |
| 150 fEncoder->fillPath(p, m, s, x); |
| 151 } else { |
| 152 // TODO: handle kStrokeAndFill_Style |
| 153 fEncoder->strokePath(p, m, s, x, this->id(Stroke::CreateFrom(pai
nt))); |
| 154 } |
| 155 } |
| 156 |
| 157 void onDrawPaint(const SkPaint& paint) override { |
| 158 SkPath path; |
| 159 path.setFillType(SkPath::kInverseWinding_FillType); // Either inver
se FillType is fine. |
| 160 this->onDrawPath(path, paint); |
| 161 } |
| 162 |
| 163 void onDrawText(const void* text, size_t byteLength, |
| 164 SkScalar x, SkScalar y, const SkPaint& paint) override { |
| 165 // Text-as-paths is a temporary hack. |
| 166 // TODO: send SkTextBlobs and SkTypefaces |
| 167 SkPath path; |
| 168 paint.getTextPath(text, byteLength, x, y, &path); |
| 169 this->onDrawPath(path, paint); |
| 170 } |
| 171 |
| 172 void onDrawPosText(const void* text, size_t byteLength, |
| 173 const SkPoint pos[], const SkPaint& paint) override { |
| 174 // Text-as-paths is a temporary hack. |
| 175 // TODO: send SkTextBlobs and SkTypefaces |
| 176 SkPath path; |
| 177 paint.getPosTextPath(text, byteLength, pos, &path); |
| 178 this->onDrawPath(path, paint); |
| 179 } |
| 180 |
| 181 void onDrawPosTextH(const void* text, size_t byteLength, |
| 182 const SkScalar xpos[], SkScalar constY, const SkPain
t& paint) override { |
| 183 size_t length = paint.countText(text, byteLength); |
| 184 SkAutoTArray<SkPoint> pos(length); |
| 185 for(size_t i = 0; i < length; ++i) { |
| 186 pos[i].set(xpos[i], constY); |
| 187 } |
| 188 this->onDrawPosText(text, byteLength, &pos[0], paint); |
| 189 } |
| 190 |
| 191 void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeS
tyle) override { |
| 192 SkPath path; |
| 193 path.addRect(rect); |
| 194 this->onClipPath(path, op, edgeStyle); |
| 195 } |
| 196 |
| 197 void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle ed
geStyle) override { |
| 198 SkPath path; |
| 199 path.addRRect(rrect); |
| 200 this->onClipPath(path, op, edgeStyle); |
| 201 } |
| 202 |
| 203 void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeS
tyle) override { |
| 204 fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeSt
yle); |
| 205 } |
| 206 |
| 207 Encoder* fEncoder; |
| 208 }; |
| 209 |
| 210 SkCanvas* NewCanvas(Encoder* encoder) { return new Canvas(encoder); } |
| 211 |
| 212 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
| 213 |
| 214 class Decoder final : public Encoder { |
| 215 public: |
| 216 explicit Decoder(SkCanvas* canvas) : fCanvas(canvas) {} |
| 217 |
| 218 private: |
| 219 template <typename Map, typename T> |
| 220 ID define(Type type, Map* map, const T& val) { |
| 221 ID id(type, fNextID++); |
| 222 map->set(id, val); |
| 223 return id; |
| 224 } |
| 225 |
| 226 ID define(const SkMatrix& v) override {return this->define(Type::kMatrix
, &fMatrix, v);} |
| 227 ID define(const Misc& v) override {return this->define(Type::kMisc,
&fMisc, v);} |
| 228 ID define(const SkPath& v) override {return this->define(Type::kPath,
&fPath, v);} |
| 229 ID define(const Stroke& v) override {return this->define(Type::kStroke
, &fStroke, v);} |
| 230 ID define(SkShader* v) override {return this->define(Type::kShader
, &fShader, v);} |
| 231 ID define(SkXfermode* v) override {return this->define(Type::kXfermo
de, &fXfermode, v);} |
| 232 |
| 233 void undefine(ID id) override { |
| 234 switch(id.type()) { |
| 235 case Type::kMatrix: return fMatrix .remove(id); |
| 236 case Type::kMisc: return fMisc .remove(id); |
| 237 case Type::kPath: return fPath .remove(id); |
| 238 case Type::kStroke: return fStroke .remove(id); |
| 239 case Type::kShader: return fShader .remove(id); |
| 240 case Type::kXfermode: return fXfermode.remove(id); |
| 241 }; |
| 242 } |
| 243 |
| 244 void save() override { fCanvas->save(); } |
| 245 void restore() override { fCanvas->restore(); } |
| 246 |
| 247 void setMatrix(ID matrix) override { fCanvas->setMatrix(fMatrix.find(mat
rix)); } |
| 248 |
| 249 void clipPath(ID path, SkRegion::Op op, bool aa) override { |
| 250 fCanvas->clipPath(fPath.find(path), op, aa); |
| 251 } |
| 252 void fillPath(ID path, ID misc, ID shader, ID xfermode) override { |
| 253 SkPaint paint; |
| 254 paint.setStyle(SkPaint::kFill_Style); |
| 255 fMisc.find(misc).applyTo(&paint); |
| 256 paint.setShader (fShader .find(shader)); |
| 257 paint.setXfermode(fXfermode.find(xfermode)); |
| 258 fCanvas->drawPath(fPath.find(path), paint); |
| 259 } |
| 260 void strokePath(ID path, ID misc, ID shader, ID xfermode, ID stroke) ove
rride { |
| 261 SkPaint paint; |
| 262 paint.setStyle(SkPaint::kStroke_Style); |
| 263 fMisc .find(misc ).applyTo(&paint); |
| 264 fStroke.find(stroke).applyTo(&paint); |
| 265 paint.setShader (fShader .find(shader)); |
| 266 paint.setXfermode(fXfermode.find(xfermode)); |
| 267 fCanvas->drawPath(fPath.find(path), paint); |
| 268 } |
| 269 |
| 270 // Maps ID -> T. |
| 271 template <typename T, Type kType> |
| 272 class IDMap { |
| 273 public: |
| 274 ~IDMap() { |
| 275 // A well-behaved client always cleans up its definitions. |
| 276 SkASSERT(fMap.count() == 0); |
| 277 } |
| 278 |
| 279 void set(const ID& id, const T& val) { |
| 280 SkASSERT(id.type() == kType); |
| 281 fMap.set(id, val); |
| 282 } |
| 283 |
| 284 void remove(const ID& id) { |
| 285 SkASSERT(id.type() == kType); |
| 286 fMap.remove(id); |
| 287 } |
| 288 |
| 289 const T& find(const ID& id) const { |
| 290 SkASSERT(id.type() == kType); |
| 291 T* val = fMap.find(id); |
| 292 SkASSERT(val != nullptr); |
| 293 return *val; |
| 294 } |
| 295 |
| 296 private: |
| 297 SkTHashMap<ID, T> fMap; |
| 298 }; |
| 299 |
| 300 // Maps ID -> T*, and keeps the T alive by reffing it. |
| 301 template <typename T, Type kType> |
| 302 class ReffedIDMap { |
| 303 public: |
| 304 ReffedIDMap() {} |
| 305 ~ReffedIDMap() { |
| 306 // A well-behaved client always cleans up its definitions. |
| 307 SkASSERT(fMap.count() == 0); |
| 308 } |
| 309 |
| 310 void set(const ID& id, T* val) { |
| 311 SkASSERT(id.type() == kType); |
| 312 fMap.set(id, SkSafeRef(val)); |
| 313 } |
| 314 |
| 315 void remove(const ID& id) { |
| 316 SkASSERT(id.type() == kType); |
| 317 T** val = fMap.find(id); |
| 318 SkASSERT(val); |
| 319 SkSafeUnref(*val); |
| 320 fMap.remove(id); |
| 321 } |
| 322 |
| 323 T* find(const ID& id) const { |
| 324 SkASSERT(id.type() == kType); |
| 325 T** val = fMap.find(id); |
| 326 SkASSERT(val); |
| 327 return *val; |
| 328 } |
| 329 |
| 330 private: |
| 331 SkTHashMap<ID, T*> fMap; |
| 332 }; |
| 333 |
| 334 |
| 335 IDMap<SkMatrix , Type::kMatrix> fMatrix; |
| 336 IDMap<Misc , Type::kMisc > fMisc; |
| 337 IDMap<SkPath , Type::kPath > fPath; |
| 338 IDMap<Stroke , Type::kStroke> fStroke; |
| 339 ReffedIDMap<SkShader , Type::kShader> fShader; |
| 340 ReffedIDMap<SkXfermode, Type::kXfermode> fXfermode; |
| 341 |
| 342 SkCanvas* fCanvas; |
| 343 uint64_t fNextID = 0; |
| 344 }; |
| 345 |
| 346 Encoder* NewDecoder(SkCanvas* canvas) { return new Decoder(canvas); } |
| 347 |
| 348 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // |
| 349 |
75 class CachingEncoder final : public Encoder { | 350 class CachingEncoder final : public Encoder { |
76 public: | 351 public: |
77 explicit CachingEncoder(Encoder* wrapped) : fWrapped(wrapped) {} | 352 explicit CachingEncoder(Encoder* wrapped) : fWrapped(wrapped) {} |
78 | 353 |
79 private: | 354 private: |
80 struct Undef { | 355 struct Undef { |
81 Encoder* fEncoder; | 356 Encoder* fEncoder; |
82 template <typename T> | 357 template <typename T> |
83 void operator()(const T&, ID* id) const { fEncoder->undefine(*id); } | 358 void operator()(const T&, ID* id) const { fEncoder->undefine(*id); } |
84 }; | 359 }; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 SkTHashMap<SkMatrix, ID> fMatrix; | 434 SkTHashMap<SkMatrix, ID> fMatrix; |
160 SkTHashMap<Misc, ID, MiscHash> fMisc; | 435 SkTHashMap<Misc, ID, MiscHash> fMisc; |
161 SkTHashMap<SkPath, ID> fPath; | 436 SkTHashMap<SkPath, ID> fPath; |
162 SkTHashMap<Stroke, ID> fStroke; | 437 SkTHashMap<Stroke, ID> fStroke; |
163 RefKeyMap<SkShader, Type::kShader> fShader; | 438 RefKeyMap<SkShader, Type::kShader> fShader; |
164 RefKeyMap<SkXfermode, Type::kXfermode> fXfermode; | 439 RefKeyMap<SkXfermode, Type::kXfermode> fXfermode; |
165 | 440 |
166 Encoder* fWrapped; | 441 Encoder* fWrapped; |
167 }; | 442 }; |
168 | 443 |
169 Encoder* Encoder::CreateCachingEncoder(Encoder* wrapped) { return new Cachin
gEncoder(wrapped); } | 444 Encoder* NewCachingEncoder(Encoder* wrapped) { return new CachingEncoder(wra
pped); } |
170 | |
171 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | |
172 | |
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) | |
200 : SkCanvas(1,1) | |
201 , fEncoder(encoder) | |
202 {} | |
203 | |
204 void Client::willSave() { fEncoder->save(); } | |
205 void Client::didRestore() { fEncoder->restore(); } | |
206 | |
207 void Client::didConcat (const SkMatrix&) { this->didSetMatrix(this->getTot
alMatrix()); } | |
208 void Client::didSetMatrix(const SkMatrix& matrix) { | |
209 fEncoder->setMatrix(this->id(matrix)); | |
210 } | |
211 | |
212 void Client::onDrawOval(const SkRect& oval, const SkPaint& paint) { | |
213 SkPath path; | |
214 path.addOval(oval); | |
215 this->onDrawPath(path, paint); | |
216 } | |
217 | |
218 void Client::onDrawRect(const SkRect& rect, const SkPaint& paint) { | |
219 SkPath path; | |
220 path.addRect(rect); | |
221 this->onDrawPath(path, paint); | |
222 } | |
223 | |
224 void Client::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { | |
225 SkPath path; | |
226 path.addRRect(rrect); | |
227 this->onDrawPath(path, paint); | |
228 } | |
229 | |
230 void Client::onDrawDRRect(const SkRRect& outside, | |
231 const SkRRect& inside, | |
232 const SkPaint& paint) { | |
233 SkPath path; | |
234 path.addRRect(outside); | |
235 path.addRRect(inside, SkPath::kCCW_Direction); | |
236 this->onDrawPath(path, paint); | |
237 } | |
238 | |
239 void Client::onDrawPath(const SkPath& path, const SkPaint& paint) { | |
240 auto p = this->id(path), | |
241 m = this->id(Misc::CreateFrom(paint)), | |
242 s = this->id(paint.getShader()), | |
243 x = this->id(paint.getXfermode()); | |
244 | |
245 if (paint.getStyle() == SkPaint::kFill_Style) { | |
246 fEncoder->fillPath(p, m, s, x); | |
247 } else { | |
248 // TODO: handle kStrokeAndFill_Style | |
249 fEncoder->strokePath(p, m, s, x, this->id(Stroke::CreateFrom(paint))
); | |
250 } | |
251 } | |
252 | |
253 void Client::onDrawPaint(const SkPaint& paint) { | |
254 SkPath path; | |
255 path.setFillType(SkPath::kInverseWinding_FillType); // Either inverse F
illType works fine. | |
256 this->onDrawPath(path, paint); | |
257 } | |
258 | |
259 void Client::onDrawText(const void* text, size_t byteLength, SkScalar x, | |
260 SkScalar y, const SkPaint& paint) { | |
261 // Text-as-paths is a temporary hack. | |
262 // TODO: send SkTextBlobs and SkTypefaces | |
263 SkPath path; | |
264 paint.getTextPath(text, byteLength, x, y, &path); | |
265 this->onDrawPath(path, paint); | |
266 } | |
267 | |
268 void Client::onDrawPosText(const void* text, size_t byteLength, | |
269 const SkPoint pos[], const SkPaint& paint) { | |
270 // Text-as-paths is a temporary hack. | |
271 // TODO: send SkTextBlobs and SkTypefaces | |
272 SkPath path; | |
273 paint.getPosTextPath(text, byteLength, pos, &path); | |
274 this->onDrawPath(path, paint); | |
275 } | |
276 | |
277 void Client::onDrawPosTextH(const void* text, size_t byteLength, | |
278 const SkScalar xpos[], SkScalar constY, | |
279 const SkPaint& paint) { | |
280 size_t length = paint.countText(text, byteLength); | |
281 SkAutoTArray<SkPoint> pos(length); | |
282 for(size_t i = 0; i < length; ++i) { | |
283 pos[i].set(xpos[i], constY); | |
284 } | |
285 this->onDrawPosText(text, byteLength, &pos[0], paint); | |
286 } | |
287 | |
288 void Client::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle e
dgeStyle) { | |
289 SkPath path; | |
290 path.addRect(rect); | |
291 this->onClipPath(path, op, edgeStyle); | |
292 } | |
293 | |
294 void Client::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyl
e edgeStyle) { | |
295 SkPath path; | |
296 path.addRRect(rrect); | |
297 this->onClipPath(path, op, edgeStyle); | |
298 } | |
299 | |
300 void Client::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle e
dgeStyle) { | |
301 fEncoder->clipPath(this->id(path), op, edgeStyle == kSoft_ClipEdgeStyle)
; | |
302 } | |
303 | |
304 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | |
305 | |
306 Server::Server(SkCanvas* canvas) : fCanvas(canvas) {} | |
307 | |
308 template <typename Map, typename T> | |
309 ID Server::define(Type type, Map* map, const T& val) { | |
310 ID id(type, fNextID++); | |
311 map->set(id, val); | |
312 return id; | |
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); } | |
321 | |
322 void Server::undefine(ID id) { | |
323 switch(id.type()) { | |
324 case Type::kMatrix: return fMatrix .remove(id); | |
325 case Type::kMisc: return fMisc .remove(id); | |
326 case Type::kPath: return fPath .remove(id); | |
327 case Type::kStroke: return fStroke .remove(id); | |
328 case Type::kShader: return fShader .remove(id); | |
329 case Type::kXfermode: return fXfermode.remove(id); | |
330 }; | |
331 } | |
332 | |
333 void Server:: save() { fCanvas->save(); } | |
334 void Server::restore() { fCanvas->restore(); } | |
335 | |
336 void Server::setMatrix(ID matrix) { fCanvas->setMatrix(fMatrix.find(matrix))
; } | |
337 | |
338 void Server::clipPath(ID path, SkRegion::Op op, bool aa) { | |
339 fCanvas->clipPath(fPath.find(path), op, aa); | |
340 } | |
341 void Server::fillPath(ID path, ID misc, ID shader, ID xfermode) { | |
342 SkPaint paint; | |
343 paint.setStyle(SkPaint::kFill_Style); | |
344 fMisc.find(misc).applyTo(&paint); | |
345 paint.setShader (fShader .find(shader)); | |
346 paint.setXfermode(fXfermode.find(xfermode)); | |
347 fCanvas->drawPath(fPath.find(path), paint); | |
348 } | |
349 void Server::strokePath(ID path, ID misc, ID shader, ID xfermode, ID stroke)
{ | |
350 SkPaint paint; | |
351 paint.setStyle(SkPaint::kStroke_Style); | |
352 fMisc .find(misc ).applyTo(&paint); | |
353 fStroke.find(stroke).applyTo(&paint); | |
354 paint.setShader (fShader .find(shader)); | |
355 paint.setXfermode(fXfermode.find(xfermode)); | |
356 fCanvas->drawPath(fPath.find(path), paint); | |
357 } | |
358 | 445 |
359 } // namespace SkRemote | 446 } // namespace SkRemote |
OLD | NEW |