1 /*
2 * Copyright 2016 Google Inc.
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 "SkDeferredCanvas.h"
9 #include "SkDrawable.h"
10 #include "SkPath.h"
11 #include "SkRSXform.h"
12 #include "SkRRect.h"
13 #include "SkSurface.h"
14 #include "SkTextBlob.h"
15 #include "SkClipOpPriv.h"
16
isConcat(SkMatrix * m) const17 bool SkDeferredCanvas::Rec::isConcat(SkMatrix* m) const {
18 switch (fType) {
19 case kTrans_Type:
20 m->setTranslate(fData.fTranslate.x(), fData.fTranslate.y());
21 return true;
22 case kScaleTrans_Type:
23 m->setScaleTranslate(fData.fScaleTrans.fScale.x(),
24 fData.fScaleTrans.fScale.y(),
25 fData.fScaleTrans.fTrans.x(),
26 fData.fScaleTrans.fTrans.y());
27 return true;
28 default:
29 break;
30 }
31 return false;
32 }
33
setConcat(const SkMatrix & m)34 void SkDeferredCanvas::Rec::setConcat(const SkMatrix& m) {
35 SkASSERT(m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask));
36
37 if (m.getType() <= SkMatrix::kTranslate_Mask) {
38 fType = kTrans_Type;
39 fData.fTranslate.set(m.getTranslateX(), m.getTranslateY());
40 } else {
41 fType = kScaleTrans_Type;
42 fData.fScaleTrans.fScale.set(m.getScaleX(), m.getScaleY());
43 fData.fScaleTrans.fTrans.set(m.getTranslateX(), m.getTranslateY());
44 }
45 }
46
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
48
SkDeferredCanvas(SkCanvas * canvas,EvalType evalType)49 SkDeferredCanvas::SkDeferredCanvas(SkCanvas* canvas, EvalType evalType)
50 : INHERITED(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().height())
51 , fCanvas(nullptr) // must be here for reset to work.
52 , fEvalType(evalType)
53 {
54 this->reset(canvas);
55 }
56
~SkDeferredCanvas()57 SkDeferredCanvas::~SkDeferredCanvas() {}
58
reset(SkCanvas * canvas)59 void SkDeferredCanvas::reset(SkCanvas* canvas) {
60 if (fCanvas) {
61 this->flush();
62 fCanvas = nullptr;
63 }
64 fRecs.reset();
65 if (canvas) {
66 this->resetForNextPicture(SkIRect::MakeSize(canvas->getBaseLayerSize()));
67 fCanvas = canvas;
68 }
69 }
70
push_save()71 void SkDeferredCanvas::push_save() {
72 Rec* r = fRecs.append();
73 r->fType = kSave_Type;
74 }
75
push_cliprect(const SkRect & bounds)76 void SkDeferredCanvas::push_cliprect(const SkRect& bounds) {
77 int index = fRecs.count() - 1;
78 if (index >= 0 && fRecs[index].fType == kClipRect_Type) {
79 if (!fRecs[index].fData.fBounds.intersect(bounds)) {
80 fRecs[index].fData.fBounds.setEmpty();
81 }
82 } else {
83 Rec* r = fRecs.append();
84 r->fType = kClipRect_Type;
85 r->fData.fBounds = bounds;
86 }
87 }
88
push_concat(const SkMatrix & mat)89 bool SkDeferredCanvas::push_concat(const SkMatrix& mat) {
90 if (mat.getType() > (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
91 return false;
92 }
93 // At the moment, we don't know which ops can scale and which can also flip, so
94 // we reject negative scales for now
95 if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
96 return false;
97 }
98
99 int index = fRecs.count() - 1;
100 SkMatrix m;
101 if (index >= 0 && fRecs[index].isConcat(&m)) {
102 m.preConcat(mat);
103 fRecs[index].setConcat(m);
104 } else {
105 fRecs.append()->setConcat(mat);
106 }
107 return true;
108 }
109
emit(const Rec & rec)110 void SkDeferredCanvas::emit(const Rec& rec) {
111 switch (rec.fType) {
112 case kSave_Type:
113 fCanvas->save();
114 this->INHERITED::willSave();
115 break;
116 case kClipRect_Type:
117 fCanvas->clipRect(rec.fData.fBounds);
118 this->INHERITED::onClipRect(rec.fData.fBounds,
119 kIntersect_SkClipOp, kHard_ClipEdgeStyle);
120 break;
121 case kTrans_Type:
122 case kScaleTrans_Type: {
123 SkMatrix mat;
124 rec.getConcat(&mat);
125 fCanvas->concat(mat);
126 this->INHERITED::didConcat(mat);
127 } break;
128 }
129 }
130
flush_le(int index)131 void SkDeferredCanvas::flush_le(int index) {
132 SkASSERT(index >= -1 && index < fRecs.count());
133
134 int count = index + 1;
135 for (int i = 0; i < count; ++i) {
136 this->emit(fRecs[i]);
137 }
138 fRecs.remove(0, count);
139 }
140
flush_all()141 void SkDeferredCanvas::flush_all() {
142 this->flush_le(fRecs.count() - 1);
143 }
144
flush_before_saves()145 void SkDeferredCanvas::flush_before_saves() {
146 int i;
147 for (i = fRecs.count() - 1; i >= 0; --i) {
148 if (kSave_Type != fRecs[i].fType) {
149 break;
150 }
151 }
152 this->flush_le(i);
153 }
154
155 enum Flags {
156 kNoTranslate_Flag = 1 << 0,
157 kNoClip_Flag = 1 << 1,
158 kNoCull_Flag = 1 << 2,
159 kNoScale_Flag = 1 << 3,
160 };
161
flush_check(SkRect * bounds,const SkPaint * paint,unsigned flags)162 void SkDeferredCanvas::flush_check(SkRect* bounds, const SkPaint* paint, unsigned flags) {
163 if (paint) {
164 if (paint->getShader() || paint->getImageFilter()) {
165 flags |= kNoTranslate_Flag | kNoScale_Flag;
166 }
167 // TODO: replace these with code to enlarge the bounds conservatively?
168 if (paint->getStyle() != SkPaint::kFill_Style || paint->getMaskFilter() ||
169 paint->getImageFilter() || paint->getPathEffect())
170 {
171 flags |= kNoCull_Flag | kNoScale_Flag | kNoClip_Flag;
172 }
173 if (paint->getLooper()) {
174 // to be conservative, we disable both, since embedded layers could have shaders
175 // or strokes etc.
176 flags |= kNoTranslate_Flag | kNoCull_Flag | kNoScale_Flag;
177 }
178 }
179 bool canClip = !(flags & kNoClip_Flag);
180 bool canTranslate = !(flags & kNoTranslate_Flag);
181 bool canCull = !(flags & kNoCull_Flag);
182 bool canScale = !(flags & kNoScale_Flag);
183
184 int i;
185 for (i = fRecs.count() - 1; i >= 0; --i) {
186 const Rec& rec = fRecs[i];
187 switch (rec.fType) {
188 case kSave_Type:
189 // continue to the next rec
190 break;
191 case kClipRect_Type:
192 if (!canCull) {
193 goto STOP;
194 }
195 if (canClip) {
196 if (!bounds->intersect(rec.fData.fBounds)) {
197 bounds->setEmpty();
198 return;
199 }
200 // continue to the next rec
201 } else {
202 if (!rec.fData.fBounds.contains(*bounds)) {
203 goto STOP;
204 }
205 // continue to the next rec
206 }
207 break;
208 case kTrans_Type:
209 if (canTranslate) {
210 bounds->offset(rec.fData.fTranslate.x(), rec.fData.fTranslate.y());
211 // continue to the next rec
212 } else {
213 goto STOP;
214 }
215 break;
216 case kScaleTrans_Type:
217 if (canScale) {
218 SkMatrix m;
219 rec.getConcat(&m);
220 m.mapRectScaleTranslate(bounds, *bounds);
221 } else {
222 goto STOP;
223 }
224 break;
225 }
226 }
227 STOP:
228 this->flush_le(i);
229 }
230
flush_translate(SkScalar * x,SkScalar * y,const SkRect & bounds,const SkPaint * paint)231 void SkDeferredCanvas::flush_translate(SkScalar* x, SkScalar* y, const SkRect& bounds,
232 const SkPaint* paint) {
233 SkRect tmp = bounds;
234 this->flush_check(&tmp, paint, kNoClip_Flag | kNoScale_Flag);
235 *x += tmp.x() - bounds.x();
236 *y += tmp.y() - bounds.y();
237 }
238
flush_translate(SkScalar * x,SkScalar * y,const SkPaint & paint)239 void SkDeferredCanvas::flush_translate(SkScalar* x, SkScalar* y, const SkPaint& paint) {
240 SkRect tmp = SkRect::MakeXYWH(*x, *y, 1, 1);
241 this->flush_check(&tmp, &paint, kNoClip_Flag | kNoCull_Flag | kNoScale_Flag);
242 *x = tmp.x();
243 *y = tmp.y();
244 }
245
246 ///////////////////////////////////////////////////////////////////////////////////////////////////
247
willSave()248 void SkDeferredCanvas::willSave() {
249 this->push_save();
250 }
251
getSaveLayerStrategy(const SaveLayerRec & rec)252 SkCanvas::SaveLayerStrategy SkDeferredCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
253 this->flush_all();
254 fCanvas->saveLayer(rec);
255 this->INHERITED::getSaveLayerStrategy(rec);
256 // No need for a layer.
257 return kNoLayer_SaveLayerStrategy;
258 }
259
willRestore()260 void SkDeferredCanvas::willRestore() {
261 for (int i = fRecs.count() - 1; i >= 0; --i) {
262 if (kSave_Type == fRecs[i].fType) {
263 fRecs.setCount(i); // pop off everything here and later
264 return;
265 }
266 }
267 for (int i = 0; i < fRecs.count(); ++i) {
268 SkASSERT(kSave_Type != fRecs[i].fType);
269 }
270 fRecs.setCount(0);
271 fCanvas->restore();
272 this->INHERITED::willRestore();
273 }
274
didConcat(const SkMatrix & matrix)275 void SkDeferredCanvas::didConcat(const SkMatrix& matrix) {
276 if (matrix.isIdentity()) {
277 return;
278 }
279 if (!this->push_concat(matrix)) {
280 this->flush_all();
281 fCanvas->concat(matrix);
282 this->INHERITED::didConcat(matrix);
283 }
284 }
285
didSetMatrix(const SkMatrix & matrix)286 void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) {
287 this->flush_all();
288 fCanvas->setMatrix(matrix);
289 this->INHERITED::didSetMatrix(matrix);
290 }
291
onClipRect(const SkRect & rect,SkClipOp op,ClipEdgeStyle edgeStyle)292 void SkDeferredCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
293 if (kIntersect_SkClipOp == op) {
294 this->push_cliprect(rect);
295 } else {
296 this->flush_all();
297 fCanvas->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
298 this->INHERITED::onClipRect(rect, op, edgeStyle);
299 }
300 }
301
onClipRRect(const SkRRect & rrect,SkClipOp op,ClipEdgeStyle edgeStyle)302 void SkDeferredCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
303 this->flush_all();
304 fCanvas->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
305 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
306 }
307
onClipPath(const SkPath & path,SkClipOp op,ClipEdgeStyle edgeStyle)308 void SkDeferredCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
309 this->flush_all();
310 fCanvas->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle);
311 this->INHERITED::onClipPath(path, op, edgeStyle);
312 }
313
onClipRegion(const SkRegion & deviceRgn,SkClipOp op)314 void SkDeferredCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
315 this->flush_all();
316 fCanvas->clipRegion(deviceRgn, op);
317 this->INHERITED::onClipRegion(deviceRgn, op);
318 }
319
onDrawPaint(const SkPaint & paint)320 void SkDeferredCanvas::onDrawPaint(const SkPaint& paint) {
321 // TODO: Can we turn this into drawRect?
322 this->flush_all();
323 fCanvas->drawPaint(paint);
324 }
325
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)326 void SkDeferredCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
327 const SkPaint& paint) {
328 this->flush_all();
329 fCanvas->drawPoints(mode, count, pts, paint);
330 }
331
onDrawRect(const SkRect & rect,const SkPaint & paint)332 void SkDeferredCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
333 SkRect modRect = rect;
334 this->flush_check(&modRect, &paint);
335 fCanvas->drawRect(modRect, paint);
336 }
337
onDrawRegion(const SkRegion & region,const SkPaint & paint)338 void SkDeferredCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
339 this->flush_all(); // can we do better?
340 fCanvas->drawRegion(region, paint);
341 }
342
onDrawOval(const SkRect & rect,const SkPaint & paint)343 void SkDeferredCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
344 SkRect modRect = rect;
345 this->flush_check(&modRect, &paint, kNoClip_Flag);
346 fCanvas->drawOval(modRect, paint);
347 }
348
onDrawArc(const SkRect & rect,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)349 void SkDeferredCanvas::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
350 bool useCenter, const SkPaint& paint) {
351 SkRect modRect = rect;
352 this->flush_check(&modRect, &paint, kNoClip_Flag);
353 fCanvas->drawArc(modRect, startAngle, sweepAngle, useCenter, paint);
354 }
355
make_offset(const SkRRect & src,SkScalar dx,SkScalar dy)356 static SkRRect make_offset(const SkRRect& src, SkScalar dx, SkScalar dy) {
357 SkRRect dst = src;
358 dst.offset(dx, dy);
359 return dst;
360 }
361
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)362 void SkDeferredCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
363 SkRect modRect = rrect.getBounds();
364 this->flush_check(&modRect, &paint, kNoClip_Flag);
365 fCanvas->drawRRect(make_offset(rrect,
366 modRect.x() - rrect.getBounds().x(),
367 modRect.y() - rrect.getBounds().y()), paint);
368 }
369
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)370 void SkDeferredCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
371 this->flush_all();
372 fCanvas->drawDRRect(outer, inner, paint);
373 }
374
onDrawPath(const SkPath & path,const SkPaint & paint)375 void SkDeferredCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
376 if (path.isInverseFillType()) {
377 this->flush_before_saves();
378 } else {
379 SkRect modRect = path.getBounds();
380 this->flush_check(&modRect, &paint, kNoClip_Flag | kNoTranslate_Flag | kNoScale_Flag);
381 }
382 fCanvas->drawPath(path, paint);
383 }
384
onDrawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)385 void SkDeferredCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
386 const SkPaint* paint) {
387 const SkScalar w = SkIntToScalar(bitmap.width());
388 const SkScalar h = SkIntToScalar(bitmap.height());
389 SkRect bounds = SkRect::MakeXYWH(x, y, w, h);
390 this->flush_check(&bounds, paint, kNoClip_Flag);
391 if (bounds.width() == w && bounds.height() == h) {
392 fCanvas->drawBitmap(bitmap, bounds.x(), bounds.y(), paint);
393 } else {
394 fCanvas->drawBitmapRect(bitmap, bounds, paint);
395 }
396 }
397
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)398 void SkDeferredCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
399 const SkPaint* paint, SrcRectConstraint constraint) {
400 SkRect modRect = dst;
401 this->flush_check(&modRect, paint, kNoClip_Flag);
402 fCanvas->legacy_drawBitmapRect(bitmap, src, modRect, paint, constraint);
403 }
404
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)405 void SkDeferredCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
406 const SkRect& dst, const SkPaint* paint) {
407 SkRect modRect = dst;
408 this->flush_check(&modRect, paint, kNoClip_Flag);
409 fCanvas->drawBitmapNine(bitmap, center, modRect, paint);
410 }
411
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)412 void SkDeferredCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
413 const SkRect& dst, const SkPaint* paint) {
414 SkRect modRect = dst;
415 this->flush_check(&modRect, paint, kNoClip_Flag);
416 fCanvas->drawBitmapLattice(bitmap, lattice, modRect, paint);
417 }
418
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)419 void SkDeferredCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center,
420 const SkRect& dst, const SkPaint* paint) {
421 SkRect modRect = dst;
422 this->flush_check(&modRect, paint, kNoClip_Flag);
423 fCanvas->drawImageNine(image, center, modRect, paint);
424 }
425
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)426 void SkDeferredCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
427 const SkPaint* paint) {
428 const SkScalar w = SkIntToScalar(image->width());
429 const SkScalar h = SkIntToScalar(image->height());
430 SkRect bounds = SkRect::MakeXYWH(x, y, w, h);
431 this->flush_check(&bounds, paint, kNoClip_Flag);
432 if (bounds.width() == w && bounds.height() == h) {
433 fCanvas->drawImage(image, bounds.x(), bounds.y(), paint);
434 } else {
435 fCanvas->drawImageRect(image, bounds, paint);
436 }
437 }
438
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)439 void SkDeferredCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
440 const SkPaint* paint, SrcRectConstraint constraint) {
441 SkRect modRect = dst;
442 this->flush_check(&modRect, paint, kNoClip_Flag);
443 fCanvas->legacy_drawImageRect(image, src, modRect, paint, constraint);
444 }
445
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)446 void SkDeferredCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
447 const SkRect& dst, const SkPaint* paint) {
448 SkRect modRect = dst;
449 this->flush_check(&modRect, paint, kNoClip_Flag);
450 fCanvas->drawImageLattice(image, lattice, modRect, paint);
451 }
452
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)453 void SkDeferredCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
454 const SkPaint& paint) {
455 this->flush_translate(&x, &y, paint);
456 fCanvas->drawText(text, byteLength, x, y, paint);
457 }
458
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)459 void SkDeferredCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
460 const SkPaint& paint) {
461 this->flush_before_saves();
462 fCanvas->drawPosText(text, byteLength, pos, paint);
463 }
464
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)465 void SkDeferredCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
466 SkScalar constY, const SkPaint& paint) {
467 this->flush_before_saves();
468 fCanvas->drawPosTextH(text, byteLength, xpos, constY, paint);
469 }
470
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)471 void SkDeferredCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
472 const SkMatrix* matrix, const SkPaint& paint) {
473 this->flush_before_saves();
474 fCanvas->drawTextOnPath(text, byteLength, path, matrix, paint);
475 }
476
onDrawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)477 void SkDeferredCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
478 const SkRSXform xform[], const SkRect* cullRect,
479 const SkPaint& paint) {
480 if (cullRect) {
481 SkRect modRect = *cullRect;
482 // only allow culling
483 this->flush_check(&modRect, &paint, kNoClip_Flag | kNoScale_Flag | kNoTranslate_Flag);
484 } else {
485 this->flush_before_saves();
486 }
487 fCanvas->drawTextRSXform(text, byteLength, xform, cullRect, paint);
488 }
489
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)490 void SkDeferredCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
491 const SkPaint &paint) {
492 this->flush_translate(&x, &y, blob->bounds(), &paint);
493 fCanvas->drawTextBlob(blob, x, y, paint);
494 }
495
496 #include "SkPicture.h"
497 #include "SkCanvasPriv.h"
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)498 void SkDeferredCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
499 const SkPaint* paint) {
500 if (kEager == fEvalType) {
501 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
502 picture->playback(this);
503 } else {
504 this->flush_before_saves();
505 fCanvas->drawPicture(picture, matrix, paint);
506 }
507 }
508
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)509 void SkDeferredCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
510 if (kEager == fEvalType) {
511 // TODO: investigate culling and applying concat to the matrix
512 drawable->draw(this, matrix);
513 } else {
514 this->flush_before_saves();
515 fCanvas->drawDrawable(drawable, matrix);
516 }
517 }
518
onDrawAtlas(const SkImage * image,const SkRSXform xform[],const SkRect rects[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)519 void SkDeferredCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[],
520 const SkRect rects[], const SkColor colors[],
521 int count, SkBlendMode bmode,
522 const SkRect* cull, const SkPaint* paint) {
523 this->flush_before_saves();
524 fCanvas->drawAtlas(image, xform, rects, colors, count, bmode, cull, paint);
525 }
526
onDrawVerticesObject(const SkVertices * vertices,SkBlendMode bmode,const SkPaint & paint)527 void SkDeferredCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
528 const SkPaint& paint) {
529 this->flush_before_saves();
530 fCanvas->drawVertices(vertices, bmode, paint);
531 }
532
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)533 void SkDeferredCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
534 const SkPoint texCoords[4], SkBlendMode bmode,
535 const SkPaint& paint) {
536 this->flush_before_saves();
537 fCanvas->drawPatch(cubics, colors, texCoords, bmode, paint);
538 }
539
onDrawAnnotation(const SkRect & rect,const char key[],SkData * data)540 void SkDeferredCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
541 SkRect modRect = rect;
542 this->flush_check(&modRect, nullptr, kNoClip_Flag);
543 fCanvas->drawAnnotation(modRect, key, data);
544 }
545
546 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
setDrawFilter(SkDrawFilter * filter)547 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
548 fCanvas->setDrawFilter(filter);
549 return this->INHERITED::setDrawFilter(filter);
550 }
551 #endif
552
553 ///////////////////////////////////////////////////////////////////////////////////////////////////
554
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)555 sk_sp<SkSurface> SkDeferredCanvas::onNewSurface(const SkImageInfo& info,
556 const SkSurfaceProps& props) {
557 return fCanvas->makeSurface(info, &props);
558 }
getBaseLayerSize() const559 SkISize SkDeferredCanvas::getBaseLayerSize() const { return fCanvas->getBaseLayerSize(); }
onGetLocalClipBounds() const560 SkRect SkDeferredCanvas::onGetLocalClipBounds() const {
561 return fCanvas->getLocalClipBounds();
562 }
onGetDeviceClipBounds() const563 SkIRect SkDeferredCanvas::onGetDeviceClipBounds() const {
564 return fCanvas->getDeviceClipBounds();
565 }
isClipEmpty() const566 bool SkDeferredCanvas::isClipEmpty() const { return fCanvas->isClipEmpty(); }
isClipRect() const567 bool SkDeferredCanvas::isClipRect() const { return fCanvas->isClipRect(); }
onPeekPixels(SkPixmap * pixmap)568 bool SkDeferredCanvas::onPeekPixels(SkPixmap* pixmap) { return fCanvas->peekPixels(pixmap); }
onAccessTopLayerPixels(SkPixmap * pixmap)569 bool SkDeferredCanvas::onAccessTopLayerPixels(SkPixmap* pixmap) {
570 SkImageInfo info;
571 size_t rowBytes;
572 SkIPoint* origin = nullptr;
573 void* addr = fCanvas->accessTopLayerPixels(&info, &rowBytes, origin);
574 if (addr) {
575 *pixmap = SkPixmap(info, addr, rowBytes);
576 return true;
577 }
578 return false;
579 }
onImageInfo() const580 SkImageInfo SkDeferredCanvas::onImageInfo() const { return fCanvas->imageInfo(); }
onGetProps(SkSurfaceProps * props) const581 bool SkDeferredCanvas::onGetProps(SkSurfaceProps* props) const { return fCanvas->getProps(props); }
onFlush()582 void SkDeferredCanvas::onFlush() {
583 this->flush_all();
584 return fCanvas->flush();
585 }
586