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