• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 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 "SkCanvasPriv.h"
9 #include "SkDebugCanvas.h"
10 #include "SkDrawCommand.h"
11 #include "SkJSONWriter.h"
12 #include "SkPaintFilterCanvas.h"
13 #include "SkPicture.h"
14 #include "SkRectPriv.h"
15 #include "SkTextBlob.h"
16 #include "SkClipOpPriv.h"
17 
18 #include "GrAuditTrail.h"
19 #include "GrContext.h"
20 #include "GrRenderTargetContext.h"
21 
22 #define SKDEBUGCANVAS_VERSION                     1
23 #define SKDEBUGCANVAS_ATTRIBUTE_VERSION           "version"
24 #define SKDEBUGCANVAS_ATTRIBUTE_COMMANDS          "commands"
25 #define SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL        "auditTrail"
26 
27 class DebugPaintFilterCanvas : public SkPaintFilterCanvas {
28 public:
DebugPaintFilterCanvas(SkCanvas * canvas,bool overdrawViz)29     DebugPaintFilterCanvas(SkCanvas* canvas,
30                            bool overdrawViz)
31         : INHERITED(canvas)
32         , fOverdrawViz(overdrawViz) {}
33 
34 protected:
onFilter(SkTCopyOnFirstWrite<SkPaint> * paint,Type) const35     bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
36         if (*paint) {
37             if (fOverdrawViz) {
38                 paint->writable()->setColor(SK_ColorRED);
39                 paint->writable()->setAlpha(0x08);
40                 paint->writable()->setBlendMode(SkBlendMode::kSrcOver);
41             }
42         }
43         return true;
44     }
45 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)46     void onDrawPicture(const SkPicture* picture,
47                        const SkMatrix* matrix,
48                        const SkPaint* paint) override {
49         // We need to replay the picture onto this canvas in order to filter its internal paints.
50         this->SkCanvas::onDrawPicture(picture, matrix, paint);
51     }
52 
53 private:
54     bool fOverdrawViz;
55 
56     typedef SkPaintFilterCanvas INHERITED;
57 };
58 
SkDebugCanvas(int width,int height)59 SkDebugCanvas::SkDebugCanvas(int width, int height)
60         : INHERITED(width, height)
61         , fOverdrawViz(false)
62         , fClipVizColor(SK_ColorTRANSPARENT)
63         , fDrawGpuOpBounds(false) {
64     // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
65     // operations. This can lead to problems in the debugger which expects all
66     // the operations in the captured skp to appear in the debug canvas. To
67     // circumvent this we create a wide open clip here (an empty clip rect
68     // is not sufficient).
69     // Internally, the SkRect passed to clipRect is converted to an SkIRect and
70     // rounded out. The following code creates a nearly maximal rect that will
71     // not get collapsed by the coming conversions (Due to precision loss the
72     // inset has to be surprisingly large).
73     SkIRect largeIRect = SkRectPriv::MakeILarge();
74     largeIRect.inset(1024, 1024);
75     SkRect large = SkRect::Make(largeIRect);
76 #ifdef SK_DEBUG
77     SkASSERT(!large.roundOut().isEmpty());
78 #endif
79     // call the base class' version to avoid adding a draw command
80     this->INHERITED::onClipRect(large, kReplace_SkClipOp, kHard_ClipEdgeStyle);
81 }
82 
~SkDebugCanvas()83 SkDebugCanvas::~SkDebugCanvas() {
84     fCommandVector.deleteAll();
85 }
86 
addDrawCommand(SkDrawCommand * command)87 void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
88     fCommandVector.push_back(command);
89 }
90 
draw(SkCanvas * canvas)91 void SkDebugCanvas::draw(SkCanvas* canvas) {
92     if (!fCommandVector.isEmpty()) {
93         this->drawTo(canvas, fCommandVector.count() - 1);
94     }
95 }
96 
drawTo(SkCanvas * originalCanvas,int index,int m)97 void SkDebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
98     SkASSERT(!fCommandVector.isEmpty());
99     SkASSERT(index < fCommandVector.count());
100 
101     int saveCount = originalCanvas->save();
102 
103     SkRect windowRect = SkRect::MakeWH(SkIntToScalar(originalCanvas->getBaseLayerSize().width()),
104                                        SkIntToScalar(originalCanvas->getBaseLayerSize().height()));
105 
106     originalCanvas->clear(SK_ColorWHITE);
107     originalCanvas->resetMatrix();
108     if (!windowRect.isEmpty()) {
109         originalCanvas->clipRect(windowRect, kReplace_SkClipOp);
110     }
111 
112     DebugPaintFilterCanvas filterCanvas(originalCanvas, fOverdrawViz);
113 
114     // If we have a GPU backend we can also visualize the op information
115     GrAuditTrail* at = nullptr;
116     if (fDrawGpuOpBounds || m != -1) {
117         // The audit trail must be obtained from the original canvas.
118         at = this->getAuditTrail(originalCanvas);
119     }
120 
121     for (int i = 0; i <= index; i++) {
122         // We need to flush any pending operations, or they might combine with commands below.
123         // Previous operations were not registered with the audit trail when they were
124         // created, so if we allow them to combine, the audit trail will fail to find them.
125         filterCanvas.flush();
126 
127         GrAuditTrail::AutoCollectOps* acb = nullptr;
128         if (at) {
129             acb = new GrAuditTrail::AutoCollectOps(at, i);
130         }
131 
132         if (fCommandVector[i]->isVisible()) {
133             fCommandVector[i]->execute(&filterCanvas);
134         }
135         if (at && acb) {
136             delete acb;
137         }
138     }
139 
140     if (SkColorGetA(fClipVizColor) != 0) {
141         filterCanvas.save();
142         #define LARGE_COORD 1000000000
143         filterCanvas.clipRect(
144                 SkRect::MakeLTRB(-LARGE_COORD, -LARGE_COORD, LARGE_COORD, LARGE_COORD),
145                 kReverseDifference_SkClipOp);
146         SkPaint clipPaint;
147         clipPaint.setColor(fClipVizColor);
148         filterCanvas.drawPaint(clipPaint);
149         filterCanvas.restore();
150     }
151 
152     fMatrix = filterCanvas.getTotalMatrix();
153     fClip = filterCanvas.getDeviceClipBounds();
154     filterCanvas.restoreToCount(saveCount);
155 
156     // draw any ops if required and issue a full reset onto GrAuditTrail
157     if (at) {
158         // just in case there is global reordering, we flush the canvas before querying
159         // GrAuditTrail
160         GrAuditTrail::AutoEnable ae(at);
161         filterCanvas.flush();
162 
163         // we pick three colorblind-safe colors, 75% alpha
164         static const SkColor kTotalBounds = SkColorSetARGB(0xC0, 0x6A, 0x3D, 0x9A);
165         static const SkColor kCommandOpBounds = SkColorSetARGB(0xC0, 0xE3, 0x1A, 0x1C);
166         static const SkColor kOtherOpBounds = SkColorSetARGB(0xC0, 0xFF, 0x7F, 0x00);
167 
168         // get the render target of the top device (from the original canvas) so we can ignore ops
169         // drawn offscreen
170         GrRenderTargetContext* rtc =
171                 originalCanvas->internal_private_accessTopLayerRenderTargetContext();
172         GrSurfaceProxy::UniqueID proxyID = rtc->asSurfaceProxy()->uniqueID();
173 
174         // get the bounding boxes to draw
175         SkTArray<GrAuditTrail::OpInfo> childrenBounds;
176         if (m == -1) {
177             at->getBoundsByClientID(&childrenBounds, index);
178         } else {
179             // the client wants us to draw the mth op
180             at->getBoundsByOpListID(&childrenBounds.push_back(), m);
181         }
182         SkPaint paint;
183         paint.setStyle(SkPaint::kStroke_Style);
184         paint.setStrokeWidth(1);
185         for (int i = 0; i < childrenBounds.count(); i++) {
186             if (childrenBounds[i].fProxyUniqueID != proxyID) {
187                 // offscreen draw, ignore for now
188                 continue;
189             }
190             paint.setColor(kTotalBounds);
191             filterCanvas.drawRect(childrenBounds[i].fBounds, paint);
192             for (int j = 0; j < childrenBounds[i].fOps.count(); j++) {
193                 const GrAuditTrail::OpInfo::Op& op = childrenBounds[i].fOps[j];
194                 if (op.fClientID != index) {
195                     paint.setColor(kOtherOpBounds);
196                 } else {
197                     paint.setColor(kCommandOpBounds);
198                 }
199                 filterCanvas.drawRect(op.fBounds, paint);
200             }
201         }
202     }
203     this->cleanupAuditTrail(originalCanvas);
204 }
205 
deleteDrawCommandAt(int index)206 void SkDebugCanvas::deleteDrawCommandAt(int index) {
207     SkASSERT(index < fCommandVector.count());
208     delete fCommandVector[index];
209     fCommandVector.remove(index);
210 }
211 
getDrawCommandAt(int index)212 SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
213     SkASSERT(index < fCommandVector.count());
214     return fCommandVector[index];
215 }
216 
getAuditTrail(SkCanvas * canvas)217 GrAuditTrail* SkDebugCanvas::getAuditTrail(SkCanvas* canvas) {
218     GrAuditTrail* at = nullptr;
219     GrContext* ctx = canvas->getGrContext();
220     if (ctx) {
221         at = ctx->contextPriv().getAuditTrail();
222     }
223     return at;
224 }
225 
drawAndCollectOps(int n,SkCanvas * canvas)226 void SkDebugCanvas::drawAndCollectOps(int n, SkCanvas* canvas) {
227     GrAuditTrail* at = this->getAuditTrail(canvas);
228     if (at) {
229         // loop over all of the commands and draw them, this is to collect reordering
230         // information
231         for (int i = 0; i < this->getSize() && i <= n; i++) {
232             GrAuditTrail::AutoCollectOps enable(at, i);
233             fCommandVector[i]->execute(canvas);
234         }
235 
236         // in case there is some kind of global reordering
237         {
238             GrAuditTrail::AutoEnable ae(at);
239             canvas->flush();
240         }
241     }
242 }
243 
cleanupAuditTrail(SkCanvas * canvas)244 void SkDebugCanvas::cleanupAuditTrail(SkCanvas* canvas) {
245     GrAuditTrail* at = this->getAuditTrail(canvas);
246     if (at) {
247         GrAuditTrail::AutoEnable ae(at);
248         at->fullReset();
249     }
250 }
251 
toJSON(SkJSONWriter & writer,UrlDataManager & urlDataManager,int n,SkCanvas * canvas)252 void SkDebugCanvas::toJSON(SkJSONWriter& writer, UrlDataManager& urlDataManager, int n,
253                            SkCanvas* canvas) {
254     this->drawAndCollectOps(n, canvas);
255 
256     // now collect json
257     GrAuditTrail* at = this->getAuditTrail(canvas);
258     writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_VERSION, SKDEBUGCANVAS_VERSION);
259     writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_COMMANDS);
260 
261     for (int i = 0; i < this->getSize() && i <= n; i++) {
262         writer.beginObject(); // command
263         this->getDrawCommandAt(i)->toJSON(writer, urlDataManager);
264 
265         if (at) {
266             writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL);
267             at->toJson(writer, i);
268         }
269         writer.endObject(); // command
270     }
271 
272     writer.endArray(); // commands
273     this->cleanupAuditTrail(canvas);
274 }
275 
toJSONOpList(SkJSONWriter & writer,int n,SkCanvas * canvas)276 void SkDebugCanvas::toJSONOpList(SkJSONWriter& writer, int n, SkCanvas* canvas) {
277     this->drawAndCollectOps(n, canvas);
278 
279     GrAuditTrail* at = this->getAuditTrail(canvas);
280     if (at) {
281         GrAuditTrail::AutoManageOpList enable(at);
282         at->toJson(writer);
283     } else {
284         writer.beginObject();
285         writer.endObject();
286     }
287     this->cleanupAuditTrail(canvas);
288 }
289 
setOverdrawViz(bool overdrawViz)290 void SkDebugCanvas::setOverdrawViz(bool overdrawViz) {
291     fOverdrawViz = overdrawViz;
292 }
293 
onClipPath(const SkPath & path,SkClipOp op,ClipEdgeStyle edgeStyle)294 void SkDebugCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
295     this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
296 }
297 
onClipRect(const SkRect & rect,SkClipOp op,ClipEdgeStyle edgeStyle)298 void SkDebugCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
299     this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
300 }
301 
onClipRRect(const SkRRect & rrect,SkClipOp op,ClipEdgeStyle edgeStyle)302 void SkDebugCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
303     this->addDrawCommand(new SkClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
304 }
305 
onClipRegion(const SkRegion & region,SkClipOp op)306 void SkDebugCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
307     this->addDrawCommand(new SkClipRegionCommand(region, op));
308 }
309 
didConcat(const SkMatrix & matrix)310 void SkDebugCanvas::didConcat(const SkMatrix& matrix) {
311     this->addDrawCommand(new SkConcatCommand(matrix));
312     this->INHERITED::didConcat(matrix);
313 }
314 
onDrawAnnotation(const SkRect & rect,const char key[],SkData * value)315 void SkDebugCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
316     this->addDrawCommand(new SkDrawAnnotationCommand(rect, key, sk_ref_sp(value)));
317 }
318 
onDrawBitmap(const SkBitmap & bitmap,SkScalar left,SkScalar top,const SkPaint * paint)319 void SkDebugCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar left,
320                                  SkScalar top, const SkPaint* paint) {
321     this->addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
322 }
323 
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)324 void SkDebugCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
325                                         const SkRect& dst, const SkPaint* paint) {
326     this->addDrawCommand(new SkDrawBitmapLatticeCommand(bitmap, lattice, dst, paint));
327 }
328 
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)329 void SkDebugCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
330                                      const SkPaint* paint, SrcRectConstraint constraint) {
331     this->addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint,
332                                                      (SrcRectConstraint)constraint));
333 }
334 
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)335 void SkDebugCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
336                                      const SkRect& dst, const SkPaint* paint) {
337     this->addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
338 }
339 
onDrawImage(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)340 void SkDebugCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
341                                 const SkPaint* paint) {
342     this->addDrawCommand(new SkDrawImageCommand(image, left, top, paint));
343 }
344 
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)345 void SkDebugCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
346                                        const SkRect& dst, const SkPaint* paint) {
347     this->addDrawCommand(new SkDrawImageLatticeCommand(image, lattice, dst, paint));
348 }
349 
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)350 void SkDebugCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
351                                     const SkPaint* paint, SrcRectConstraint constraint) {
352     this->addDrawCommand(new SkDrawImageRectCommand(image, src, dst, paint, constraint));
353 }
354 
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)355 void SkDebugCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center,
356                                     const SkRect& dst, const SkPaint* paint) {
357     this->addDrawCommand(new SkDrawImageNineCommand(image, center, dst, paint));
358 }
359 
onDrawImageSet(const SkCanvas::ImageSetEntry set[],int count,SkFilterQuality filterQuality,SkBlendMode mode)360 void SkDebugCanvas::onDrawImageSet(const SkCanvas::ImageSetEntry set[], int count,
361                                    SkFilterQuality filterQuality, SkBlendMode mode) {
362     this->addDrawCommand(new SkDrawImageSetCommand(set, count, filterQuality, mode));
363 }
364 
onDrawOval(const SkRect & oval,const SkPaint & paint)365 void SkDebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
366     this->addDrawCommand(new SkDrawOvalCommand(oval, paint));
367 }
368 
onDrawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)369 void SkDebugCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
370                                bool useCenter, const SkPaint& paint) {
371     this->addDrawCommand(new SkDrawArcCommand(oval, startAngle, sweepAngle, useCenter, paint));
372 }
373 
onDrawPaint(const SkPaint & paint)374 void SkDebugCanvas::onDrawPaint(const SkPaint& paint) {
375     this->addDrawCommand(new SkDrawPaintCommand(paint));
376 }
377 
onDrawPath(const SkPath & path,const SkPaint & paint)378 void SkDebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
379     this->addDrawCommand(new SkDrawPathCommand(path, paint));
380 }
381 
onDrawRegion(const SkRegion & region,const SkPaint & paint)382 void SkDebugCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
383     this->addDrawCommand(new SkDrawRegionCommand(region, paint));
384 }
385 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)386 void SkDebugCanvas::onDrawPicture(const SkPicture* picture,
387                                   const SkMatrix* matrix,
388                                   const SkPaint* paint) {
389     this->addDrawCommand(new SkBeginDrawPictureCommand(picture, matrix, paint));
390     SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
391     picture->playback(this);
392     this->addDrawCommand(new SkEndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint)));
393 }
394 
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)395 void SkDebugCanvas::onDrawPoints(PointMode mode, size_t count,
396                                  const SkPoint pts[], const SkPaint& paint) {
397     this->addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
398 }
399 
onDrawRect(const SkRect & rect,const SkPaint & paint)400 void SkDebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
401     // NOTE(chudy): Messing up when renamed to DrawRect... Why?
402     addDrawCommand(new SkDrawRectCommand(rect, paint));
403 }
404 
onDrawEdgeAARect(const SkRect & rect,SkCanvas::QuadAAFlags aa,SkColor color,SkBlendMode mode)405 void SkDebugCanvas::onDrawEdgeAARect(const SkRect& rect, SkCanvas::QuadAAFlags aa, SkColor color,
406                                      SkBlendMode mode) {
407     this->addDrawCommand(new SkDrawEdgeAARectCommand(rect, aa, color, mode));
408 }
409 
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)410 void SkDebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
411     this->addDrawCommand(new SkDrawRRectCommand(rrect, paint));
412 }
413 
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)414 void SkDebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
415                                  const SkPaint& paint) {
416     this->addDrawCommand(new SkDrawDRRectCommand(outer, inner, paint));
417 }
418 
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)419 void SkDebugCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
420                                    const SkPaint& paint) {
421     this->addDrawCommand(new SkDrawTextBlobCommand(sk_ref_sp(const_cast<SkTextBlob*>(blob)),
422                                                    x, y, paint));
423 }
424 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)425 void SkDebugCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
426                                 const SkPoint texCoords[4], SkBlendMode bmode,
427                                 const SkPaint& paint) {
428     this->addDrawCommand(new SkDrawPatchCommand(cubics, colors, texCoords, bmode, paint));
429 }
430 
onDrawVerticesObject(const SkVertices * vertices,const SkVertices::Bone bones[],int boneCount,SkBlendMode bmode,const SkPaint & paint)431 void SkDebugCanvas::onDrawVerticesObject(const SkVertices* vertices, const SkVertices::Bone bones[],
432                                          int boneCount, SkBlendMode bmode, const SkPaint& paint) {
433     // TODO: ANIMATION NOT LOGGED
434     this->addDrawCommand(new SkDrawVerticesCommand(sk_ref_sp(const_cast<SkVertices*>(vertices)),
435                                                    bmode, paint));
436 }
437 
onDrawAtlas(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)438 void SkDebugCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[], const SkRect tex[],
439                                 const SkColor colors[], int count, SkBlendMode bmode,
440                                 const SkRect* cull, const SkPaint* paint) {
441     this->addDrawCommand(new SkDrawAtlasCommand(image, xform, tex, colors, count, bmode, cull,
442                                                 paint));
443 }
444 
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)445 void SkDebugCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
446     this->addDrawCommand(new SkDrawShadowCommand(path, rec));
447 }
448 
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)449 void SkDebugCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
450     this->addDrawCommand(new SkDrawDrawableCommand(drawable, matrix));
451 }
452 
willRestore()453 void SkDebugCanvas::willRestore() {
454     this->addDrawCommand(new SkRestoreCommand());
455     this->INHERITED::willRestore();
456 }
457 
willSave()458 void SkDebugCanvas::willSave() {
459     this->addDrawCommand(new SkSaveCommand());
460     this->INHERITED::willSave();
461 }
462 
getSaveLayerStrategy(const SaveLayerRec & rec)463 SkCanvas::SaveLayerStrategy SkDebugCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
464     this->addDrawCommand(new SkSaveLayerCommand(rec));
465     (void)this->INHERITED::getSaveLayerStrategy(rec);
466     // No need for a full layer.
467     return kNoLayer_SaveLayerStrategy;
468 }
469 
onDoSaveBehind(const SkRect * subset)470 bool SkDebugCanvas::onDoSaveBehind(const SkRect* subset) {
471     // TODO
472     return false;
473 }
474 
didSetMatrix(const SkMatrix & matrix)475 void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
476     this->addDrawCommand(new SkSetMatrixCommand(matrix));
477     this->INHERITED::didSetMatrix(matrix);
478 }
479 
toggleCommand(int index,bool toggle)480 void SkDebugCanvas::toggleCommand(int index, bool toggle) {
481     SkASSERT(index < fCommandVector.count());
482     fCommandVector[index]->setVisible(toggle);
483 }
484