blob: 5bf46621be0ac36a527d21e8f3993f01c1b039df [file] [log] [blame]
Mike Klein8f4e2242019-03-20 11:59:00 -05001/*
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 "DebugCanvas.h"
9#include "DrawCommand.h"
10#include "SkCanvasPriv.h"
11#include "SkClipOpPriv.h"
12#include "SkJSONWriter.h"
13#include "SkPaintFilterCanvas.h"
14#include "SkPicture.h"
15#include "SkRectPriv.h"
16#include "SkTextBlob.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
28class DebugPaintFilterCanvas : public SkPaintFilterCanvas {
29public:
30 DebugPaintFilterCanvas(SkCanvas* canvas, bool overdrawViz)
31 : INHERITED(canvas), fOverdrawViz(overdrawViz) {}
32
33protected:
34 bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
35 if (*paint) {
36 if (fOverdrawViz) {
37 paint->writable()->setColor(SK_ColorRED);
38 paint->writable()->setAlpha(0x08);
39 paint->writable()->setBlendMode(SkBlendMode::kSrcOver);
40 }
41 }
42 return true;
43 }
44
45 void onDrawPicture(const SkPicture* picture,
46 const SkMatrix* matrix,
47 const SkPaint* paint) override {
48 // We need to replay the picture onto this canvas in order to filter its internal paints.
49 this->SkCanvas::onDrawPicture(picture, matrix, paint);
50 }
51
52private:
53 bool fOverdrawViz;
54
55 typedef SkPaintFilterCanvas INHERITED;
56};
57
58DebugCanvas::DebugCanvas(int width, int height)
59 : INHERITED(width, height)
60 , fOverdrawViz(false)
61 , fClipVizColor(SK_ColorTRANSPARENT)
62 , fDrawGpuOpBounds(false) {
63 // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
64 // operations. This can lead to problems in the debugger which expects all
65 // the operations in the captured skp to appear in the debug canvas. To
66 // circumvent this we create a wide open clip here (an empty clip rect
67 // is not sufficient).
68 // Internally, the SkRect passed to clipRect is converted to an SkIRect and
69 // rounded out. The following code creates a nearly maximal rect that will
70 // not get collapsed by the coming conversions (Due to precision loss the
71 // inset has to be surprisingly large).
72 SkIRect largeIRect = SkRectPriv::MakeILarge();
73 largeIRect.inset(1024, 1024);
74 SkRect large = SkRect::Make(largeIRect);
75#ifdef SK_DEBUG
76 SkASSERT(!large.roundOut().isEmpty());
77#endif
78 // call the base class' version to avoid adding a draw command
79 this->INHERITED::onClipRect(large, kReplace_SkClipOp, kHard_ClipEdgeStyle);
80}
81
82DebugCanvas::DebugCanvas(SkIRect bounds) { DebugCanvas(bounds.width(), bounds.height()); }
83
84DebugCanvas::~DebugCanvas() { fCommandVector.deleteAll(); }
85
86void DebugCanvas::addDrawCommand(DrawCommand* command) { fCommandVector.push_back(command); }
87
88void DebugCanvas::draw(SkCanvas* canvas) {
89 if (!fCommandVector.isEmpty()) {
90 this->drawTo(canvas, fCommandVector.count() - 1);
91 }
92}
93
94void DebugCanvas::drawTo(SkCanvas* originalCanvas, int index, int m) {
95 SkASSERT(!fCommandVector.isEmpty());
96 SkASSERT(index < fCommandVector.count());
97
98 int saveCount = originalCanvas->save();
99
100 SkRect windowRect = SkRect::MakeWH(SkIntToScalar(originalCanvas->getBaseLayerSize().width()),
101 SkIntToScalar(originalCanvas->getBaseLayerSize().height()));
102
Nathaniel Nifongde5df652019-03-28 13:08:51 -0400103 originalCanvas->clear(SK_ColorTRANSPARENT);
Mike Klein8f4e2242019-03-20 11:59:00 -0500104 originalCanvas->resetMatrix();
105 if (!windowRect.isEmpty()) {
106 originalCanvas->clipRect(windowRect, kReplace_SkClipOp);
107 }
108
109 DebugPaintFilterCanvas filterCanvas(originalCanvas, fOverdrawViz);
110
111 // If we have a GPU backend we can also visualize the op information
112 GrAuditTrail* at = nullptr;
113 if (fDrawGpuOpBounds || m != -1) {
114 // The audit trail must be obtained from the original canvas.
115 at = this->getAuditTrail(originalCanvas);
116 }
117
118 for (int i = 0; i <= index; i++) {
119 // We need to flush any pending operations, or they might combine with commands below.
120 // Previous operations were not registered with the audit trail when they were
121 // created, so if we allow them to combine, the audit trail will fail to find them.
122 filterCanvas.flush();
123
124 GrAuditTrail::AutoCollectOps* acb = nullptr;
125 if (at) {
126 acb = new GrAuditTrail::AutoCollectOps(at, i);
127 }
128
129 if (fCommandVector[i]->isVisible()) {
130 fCommandVector[i]->execute(&filterCanvas);
131 }
132 if (at && acb) {
133 delete acb;
134 }
135 }
136
137 if (SkColorGetA(fClipVizColor) != 0) {
138 filterCanvas.save();
139#define LARGE_COORD 1000000000
140 filterCanvas.clipRect(
141 SkRect::MakeLTRB(-LARGE_COORD, -LARGE_COORD, LARGE_COORD, LARGE_COORD),
142 kReverseDifference_SkClipOp);
143 SkPaint clipPaint;
144 clipPaint.setColor(fClipVizColor);
145 filterCanvas.drawPaint(clipPaint);
146 filterCanvas.restore();
147 }
148
149 fMatrix = filterCanvas.getTotalMatrix();
150 fClip = filterCanvas.getDeviceClipBounds();
151 filterCanvas.restoreToCount(saveCount);
152
153 // draw any ops if required and issue a full reset onto GrAuditTrail
154 if (at) {
155 // just in case there is global reordering, we flush the canvas before querying
156 // GrAuditTrail
157 GrAuditTrail::AutoEnable ae(at);
158 filterCanvas.flush();
159
160 // we pick three colorblind-safe colors, 75% alpha
161 static const SkColor kTotalBounds = SkColorSetARGB(0xC0, 0x6A, 0x3D, 0x9A);
162 static const SkColor kCommandOpBounds = SkColorSetARGB(0xC0, 0xE3, 0x1A, 0x1C);
163 static const SkColor kOtherOpBounds = SkColorSetARGB(0xC0, 0xFF, 0x7F, 0x00);
164
165 // get the render target of the top device (from the original canvas) so we can ignore ops
166 // drawn offscreen
167 GrRenderTargetContext* rtc =
168 originalCanvas->internal_private_accessTopLayerRenderTargetContext();
169 GrSurfaceProxy::UniqueID proxyID = rtc->asSurfaceProxy()->uniqueID();
170
171 // get the bounding boxes to draw
172 SkTArray<GrAuditTrail::OpInfo> childrenBounds;
173 if (m == -1) {
174 at->getBoundsByClientID(&childrenBounds, index);
175 } else {
176 // the client wants us to draw the mth op
177 at->getBoundsByOpListID(&childrenBounds.push_back(), m);
178 }
179 SkPaint paint;
180 paint.setStyle(SkPaint::kStroke_Style);
181 paint.setStrokeWidth(1);
182 for (int i = 0; i < childrenBounds.count(); i++) {
183 if (childrenBounds[i].fProxyUniqueID != proxyID) {
184 // offscreen draw, ignore for now
185 continue;
186 }
187 paint.setColor(kTotalBounds);
188 filterCanvas.drawRect(childrenBounds[i].fBounds, paint);
189 for (int j = 0; j < childrenBounds[i].fOps.count(); j++) {
190 const GrAuditTrail::OpInfo::Op& op = childrenBounds[i].fOps[j];
191 if (op.fClientID != index) {
192 paint.setColor(kOtherOpBounds);
193 } else {
194 paint.setColor(kCommandOpBounds);
195 }
196 filterCanvas.drawRect(op.fBounds, paint);
197 }
198 }
199 }
200 this->cleanupAuditTrail(originalCanvas);
201}
202
203void DebugCanvas::deleteDrawCommandAt(int index) {
204 SkASSERT(index < fCommandVector.count());
205 delete fCommandVector[index];
206 fCommandVector.remove(index);
207}
208
209DrawCommand* DebugCanvas::getDrawCommandAt(int index) {
210 SkASSERT(index < fCommandVector.count());
211 return fCommandVector[index];
212}
213
214GrAuditTrail* DebugCanvas::getAuditTrail(SkCanvas* canvas) {
215 GrAuditTrail* at = nullptr;
216 GrContext* ctx = canvas->getGrContext();
217 if (ctx) {
218 at = ctx->priv().auditTrail();
219 }
220 return at;
221}
222
223void DebugCanvas::drawAndCollectOps(int n, SkCanvas* canvas) {
224 GrAuditTrail* at = this->getAuditTrail(canvas);
225 if (at) {
226 // loop over all of the commands and draw them, this is to collect reordering
227 // information
228 for (int i = 0; i < this->getSize() && i <= n; i++) {
229 GrAuditTrail::AutoCollectOps enable(at, i);
230 fCommandVector[i]->execute(canvas);
231 }
232
233 // in case there is some kind of global reordering
234 {
235 GrAuditTrail::AutoEnable ae(at);
236 canvas->flush();
237 }
238 }
239}
240
241void DebugCanvas::cleanupAuditTrail(SkCanvas* canvas) {
242 GrAuditTrail* at = this->getAuditTrail(canvas);
243 if (at) {
244 GrAuditTrail::AutoEnable ae(at);
245 at->fullReset();
246 }
247}
248
249void DebugCanvas::toJSON(SkJSONWriter& writer,
250 UrlDataManager& urlDataManager,
251 int n,
252 SkCanvas* canvas) {
253 this->drawAndCollectOps(n, canvas);
254
255 // now collect json
256 GrAuditTrail* at = this->getAuditTrail(canvas);
257 writer.appendS32(SKDEBUGCANVAS_ATTRIBUTE_VERSION, SKDEBUGCANVAS_VERSION);
258 writer.beginArray(SKDEBUGCANVAS_ATTRIBUTE_COMMANDS);
259
260 for (int i = 0; i < this->getSize() && i <= n; i++) {
261 writer.beginObject(); // command
262 this->getDrawCommandAt(i)->toJSON(writer, urlDataManager);
263
264 if (at) {
265 writer.appendName(SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL);
266 at->toJson(writer, i);
267 }
268 writer.endObject(); // command
269 }
270
271 writer.endArray(); // commands
272 this->cleanupAuditTrail(canvas);
273}
274
275void DebugCanvas::toJSONOpList(SkJSONWriter& writer, int n, SkCanvas* canvas) {
276 this->drawAndCollectOps(n, canvas);
277
278 GrAuditTrail* at = this->getAuditTrail(canvas);
279 if (at) {
280 GrAuditTrail::AutoManageOpList enable(at);
281 at->toJson(writer);
282 } else {
283 writer.beginObject();
284 writer.endObject();
285 }
286 this->cleanupAuditTrail(canvas);
287}
288
289void DebugCanvas::setOverdrawViz(bool overdrawViz) { fOverdrawViz = overdrawViz; }
290
291void DebugCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
Mike Klein17428132019-03-20 13:02:32 -0500292 this->addDrawCommand(new ClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
Mike Klein8f4e2242019-03-20 11:59:00 -0500293}
294
295void DebugCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
Mike Klein17428132019-03-20 13:02:32 -0500296 this->addDrawCommand(new ClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
Mike Klein8f4e2242019-03-20 11:59:00 -0500297}
298
299void DebugCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
Mike Klein17428132019-03-20 13:02:32 -0500300 this->addDrawCommand(new ClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
Mike Klein8f4e2242019-03-20 11:59:00 -0500301}
302
303void DebugCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
Mike Klein17428132019-03-20 13:02:32 -0500304 this->addDrawCommand(new ClipRegionCommand(region, op));
Mike Klein8f4e2242019-03-20 11:59:00 -0500305}
306
307void DebugCanvas::didConcat(const SkMatrix& matrix) {
Mike Klein17428132019-03-20 13:02:32 -0500308 this->addDrawCommand(new ConcatCommand(matrix));
Mike Klein8f4e2242019-03-20 11:59:00 -0500309 this->INHERITED::didConcat(matrix);
310}
311
312void DebugCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
Mike Klein17428132019-03-20 13:02:32 -0500313 this->addDrawCommand(new DrawAnnotationCommand(rect, key, sk_ref_sp(value)));
Mike Klein8f4e2242019-03-20 11:59:00 -0500314}
315
316void DebugCanvas::onDrawBitmap(const SkBitmap& bitmap,
317 SkScalar left,
318 SkScalar top,
319 const SkPaint* paint) {
Mike Klein17428132019-03-20 13:02:32 -0500320 this->addDrawCommand(new DrawBitmapCommand(bitmap, left, top, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500321}
322
323void DebugCanvas::onDrawBitmapLattice(const SkBitmap& bitmap,
324 const Lattice& lattice,
325 const SkRect& dst,
326 const SkPaint* paint) {
Mike Klein17428132019-03-20 13:02:32 -0500327 this->addDrawCommand(new DrawBitmapLatticeCommand(bitmap, lattice, dst, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500328}
329
330void DebugCanvas::onDrawBitmapRect(const SkBitmap& bitmap,
331 const SkRect* src,
332 const SkRect& dst,
333 const SkPaint* paint,
334 SrcRectConstraint constraint) {
335 this->addDrawCommand(
Mike Klein17428132019-03-20 13:02:32 -0500336 new DrawBitmapRectCommand(bitmap, src, dst, paint, (SrcRectConstraint)constraint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500337}
338
339void DebugCanvas::onDrawBitmapNine(const SkBitmap& bitmap,
340 const SkIRect& center,
341 const SkRect& dst,
342 const SkPaint* paint) {
Mike Klein17428132019-03-20 13:02:32 -0500343 this->addDrawCommand(new DrawBitmapNineCommand(bitmap, center, dst, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500344}
345
346void DebugCanvas::onDrawImage(const SkImage* image,
347 SkScalar left,
348 SkScalar top,
349 const SkPaint* paint) {
Mike Klein17428132019-03-20 13:02:32 -0500350 this->addDrawCommand(new DrawImageCommand(image, left, top, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500351}
352
353void DebugCanvas::onDrawImageLattice(const SkImage* image,
354 const Lattice& lattice,
355 const SkRect& dst,
356 const SkPaint* paint) {
Mike Klein17428132019-03-20 13:02:32 -0500357 this->addDrawCommand(new DrawImageLatticeCommand(image, lattice, dst, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500358}
359
360void DebugCanvas::onDrawImageRect(const SkImage* image,
361 const SkRect* src,
362 const SkRect& dst,
363 const SkPaint* paint,
364 SrcRectConstraint constraint) {
Mike Klein17428132019-03-20 13:02:32 -0500365 this->addDrawCommand(new DrawImageRectCommand(image, src, dst, paint, constraint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500366}
367
368void DebugCanvas::onDrawImageNine(const SkImage* image,
369 const SkIRect& center,
370 const SkRect& dst,
371 const SkPaint* paint) {
Mike Klein17428132019-03-20 13:02:32 -0500372 this->addDrawCommand(new DrawImageNineCommand(image, center, dst, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500373}
374
375void DebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500376 this->addDrawCommand(new DrawOvalCommand(oval, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500377}
378
379void DebugCanvas::onDrawArc(const SkRect& oval,
380 SkScalar startAngle,
381 SkScalar sweepAngle,
382 bool useCenter,
383 const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500384 this->addDrawCommand(new DrawArcCommand(oval, startAngle, sweepAngle, useCenter, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500385}
386
387void DebugCanvas::onDrawPaint(const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500388 this->addDrawCommand(new DrawPaintCommand(paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500389}
390
391void DebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500392 this->addDrawCommand(new DrawPathCommand(path, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500393}
394
395void DebugCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500396 this->addDrawCommand(new DrawRegionCommand(region, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500397}
398
399void DebugCanvas::onDrawPicture(const SkPicture* picture,
400 const SkMatrix* matrix,
401 const SkPaint* paint) {
Mike Klein17428132019-03-20 13:02:32 -0500402 this->addDrawCommand(new BeginDrawPictureCommand(picture, matrix, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500403 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
404 picture->playback(this);
Mike Klein17428132019-03-20 13:02:32 -0500405 this->addDrawCommand(new EndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint)));
Mike Klein8f4e2242019-03-20 11:59:00 -0500406}
407
408void DebugCanvas::onDrawPoints(PointMode mode,
409 size_t count,
410 const SkPoint pts[],
411 const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500412 this->addDrawCommand(new DrawPointsCommand(mode, count, pts, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500413}
414
415void DebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
416 // NOTE(chudy): Messing up when renamed to DrawRect... Why?
Mike Klein17428132019-03-20 13:02:32 -0500417 addDrawCommand(new DrawRectCommand(rect, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500418}
419
420void DebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500421 this->addDrawCommand(new DrawRRectCommand(rrect, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500422}
423
424void DebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500425 this->addDrawCommand(new DrawDRRectCommand(outer, inner, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500426}
427
428void DebugCanvas::onDrawTextBlob(const SkTextBlob* blob,
429 SkScalar x,
430 SkScalar y,
431 const SkPaint& paint) {
432 this->addDrawCommand(
Mike Klein17428132019-03-20 13:02:32 -0500433 new DrawTextBlobCommand(sk_ref_sp(const_cast<SkTextBlob*>(blob)), x, y, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500434}
435
436void DebugCanvas::onDrawPatch(const SkPoint cubics[12],
437 const SkColor colors[4],
438 const SkPoint texCoords[4],
439 SkBlendMode bmode,
440 const SkPaint& paint) {
Mike Klein17428132019-03-20 13:02:32 -0500441 this->addDrawCommand(new DrawPatchCommand(cubics, colors, texCoords, bmode, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500442}
443
444void DebugCanvas::onDrawVerticesObject(const SkVertices* vertices,
445 const SkVertices::Bone bones[],
446 int boneCount,
447 SkBlendMode bmode,
448 const SkPaint& paint) {
449 // TODO: ANIMATION NOT LOGGED
450 this->addDrawCommand(
Mike Klein17428132019-03-20 13:02:32 -0500451 new DrawVerticesCommand(sk_ref_sp(const_cast<SkVertices*>(vertices)), bmode, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500452}
453
454void DebugCanvas::onDrawAtlas(const SkImage* image,
455 const SkRSXform xform[],
456 const SkRect tex[],
457 const SkColor colors[],
458 int count,
459 SkBlendMode bmode,
460 const SkRect* cull,
461 const SkPaint* paint) {
462 this->addDrawCommand(
Mike Klein17428132019-03-20 13:02:32 -0500463 new DrawAtlasCommand(image, xform, tex, colors, count, bmode, cull, paint));
Mike Klein8f4e2242019-03-20 11:59:00 -0500464}
465
466void DebugCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
Mike Klein17428132019-03-20 13:02:32 -0500467 this->addDrawCommand(new DrawShadowCommand(path, rec));
Mike Klein8f4e2242019-03-20 11:59:00 -0500468}
469
470void DebugCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
Mike Klein17428132019-03-20 13:02:32 -0500471 this->addDrawCommand(new DrawDrawableCommand(drawable, matrix));
Mike Klein8f4e2242019-03-20 11:59:00 -0500472}
473
474void DebugCanvas::onDrawEdgeAAQuad(const SkRect& rect,
475 const SkPoint clip[4],
476 QuadAAFlags aa,
477 SkColor color,
478 SkBlendMode mode) {
Mike Klein17428132019-03-20 13:02:32 -0500479 this->addDrawCommand(new DrawEdgeAAQuadCommand(rect, clip, aa, color, mode));
Mike Klein8f4e2242019-03-20 11:59:00 -0500480}
481
482void DebugCanvas::onDrawEdgeAAImageSet(const ImageSetEntry set[],
483 int count,
484 const SkPoint dstClips[],
485 const SkMatrix preViewMatrices[],
486 const SkPaint* paint,
487 SrcRectConstraint constraint) {
Mike Klein17428132019-03-20 13:02:32 -0500488 this->addDrawCommand(new DrawEdgeAAImageSetCommand(
Mike Klein8f4e2242019-03-20 11:59:00 -0500489 set, count, dstClips, preViewMatrices, paint, constraint));
490}
491
492void DebugCanvas::willRestore() {
Mike Klein17428132019-03-20 13:02:32 -0500493 this->addDrawCommand(new RestoreCommand());
Mike Klein8f4e2242019-03-20 11:59:00 -0500494 this->INHERITED::willRestore();
495}
496
497void DebugCanvas::willSave() {
Mike Klein17428132019-03-20 13:02:32 -0500498 this->addDrawCommand(new SaveCommand());
Mike Klein8f4e2242019-03-20 11:59:00 -0500499 this->INHERITED::willSave();
500}
501
502SkCanvas::SaveLayerStrategy DebugCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
Mike Klein17428132019-03-20 13:02:32 -0500503 this->addDrawCommand(new SaveLayerCommand(rec));
Mike Klein8f4e2242019-03-20 11:59:00 -0500504 (void)this->INHERITED::getSaveLayerStrategy(rec);
505 // No need for a full layer.
506 return kNoLayer_SaveLayerStrategy;
507}
508
509bool DebugCanvas::onDoSaveBehind(const SkRect* subset) {
510 // TODO
511 return false;
512}
513
514void DebugCanvas::didSetMatrix(const SkMatrix& matrix) {
Mike Klein17428132019-03-20 13:02:32 -0500515 this->addDrawCommand(new SetMatrixCommand(matrix));
Mike Klein8f4e2242019-03-20 11:59:00 -0500516 this->INHERITED::didSetMatrix(matrix);
517}
518
519void DebugCanvas::toggleCommand(int index, bool toggle) {
520 SkASSERT(index < fCommandVector.count());
521 fCommandVector[index]->setVisible(toggle);
522}