blob: 4c633ab8fcb4f23b623d439092d8987af28a7f91 [file] [log] [blame]
chudy@google.com902ebe52012-06-29 14:21:22 +00001/*
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
ethannicholas891ad662016-02-12 07:15:45 -08008#include "SkCanvasPriv.h"
bungemand3ebb482015-08-05 13:57:49 -07009#include "SkClipStack.h"
chudy@google.com902ebe52012-06-29 14:21:22 +000010#include "SkDebugCanvas.h"
11#include "SkDrawCommand.h"
robertphillipsf42fca42016-01-27 05:00:04 -080012#include "SkOverdrawMode.h"
fmalita37283c22016-09-13 10:00:23 -070013#include "SkPaintFilterCanvas.h"
14#include "SkTextBlob.h"
fmalita65cdb572015-03-26 07:24:48 -070015
joshualitt10d8fc22016-02-29 11:15:06 -080016#if SK_SUPPORT_GPU
17#include "GrAuditTrail.h"
18#include "GrContext.h"
19#include "GrRenderTarget.h"
joshualitt1d7decf2016-03-01 07:15:52 -080020#include "SkGpuDevice.h"
joshualitt10d8fc22016-02-29 11:15:06 -080021#endif
22
joshualitte43f7e62016-03-04 10:45:05 -080023#define SKDEBUGCANVAS_VERSION 1
24#define SKDEBUGCANVAS_ATTRIBUTE_VERSION "version"
25#define SKDEBUGCANVAS_ATTRIBUTE_COMMANDS "commands"
26#define SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL "auditTrail"
ethannicholas402cd912016-02-10 12:57:30 -080027
fmalita65cdb572015-03-26 07:24:48 -070028class DebugPaintFilterCanvas : public SkPaintFilterCanvas {
29public:
halcanary385fe4d2015-08-26 13:07:48 -070030 DebugPaintFilterCanvas(int width,
31 int height,
32 bool overdrawViz,
33 bool overrideFilterQuality,
fmalita65cdb572015-03-26 07:24:48 -070034 SkFilterQuality quality)
35 : INHERITED(width, height)
reedcfb6bdf2016-03-29 11:32:50 -070036 , fOverdrawXfermode(overdrawViz ? SkOverdrawMode::Make() : nullptr)
fmalita65cdb572015-03-26 07:24:48 -070037 , fOverrideFilterQuality(overrideFilterQuality)
halcanary385fe4d2015-08-26 13:07:48 -070038 , fFilterQuality(quality) {}
fmalita65cdb572015-03-26 07:24:48 -070039
40protected:
fmalita32cdc322016-01-12 07:21:11 -080041 bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type) const override {
42 if (*paint) {
fmalitabad23dc2016-01-11 13:58:29 -080043 if (nullptr != fOverdrawXfermode.get()) {
fmalita32cdc322016-01-12 07:21:11 -080044 paint->writable()->setAntiAlias(false);
reedcfb6bdf2016-03-29 11:32:50 -070045 paint->writable()->setXfermode(fOverdrawXfermode);
fmalitabad23dc2016-01-11 13:58:29 -080046 }
fmalita65cdb572015-03-26 07:24:48 -070047
fmalitabad23dc2016-01-11 13:58:29 -080048 if (fOverrideFilterQuality) {
fmalita32cdc322016-01-12 07:21:11 -080049 paint->writable()->setFilterQuality(fFilterQuality);
fmalitabad23dc2016-01-11 13:58:29 -080050 }
fmalita65cdb572015-03-26 07:24:48 -070051 }
fmalitabad23dc2016-01-11 13:58:29 -080052 return true;
fmalita65cdb572015-03-26 07:24:48 -070053 }
54
mtkleinf0599002015-07-13 06:18:39 -070055 void onDrawPicture(const SkPicture* picture,
56 const SkMatrix* matrix,
57 const SkPaint* paint) override {
fmalita65cdb572015-03-26 07:24:48 -070058 // We need to replay the picture onto this canvas in order to filter its internal paints.
59 this->SkCanvas::onDrawPicture(picture, matrix, paint);
60 }
61
vjiaoblack95302da2016-07-21 10:25:54 -070062 void onDrawShadowedPicture(const SkPicture* picture,
63 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -070064 const SkPaint* paint,
65 const SkShadowParams& params) {
vjiaoblack95302da2016-07-21 10:25:54 -070066#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke6f5d562016-08-25 06:30:23 -070067 this->SkCanvas::onDrawShadowedPicture(picture, matrix, paint, params);
vjiaoblack95302da2016-07-21 10:25:54 -070068#else
69 this->SkCanvas::onDrawPicture(picture, matrix, paint);
70#endif
71 }
72
fmalita65cdb572015-03-26 07:24:48 -070073private:
reedcfb6bdf2016-03-29 11:32:50 -070074 sk_sp<SkXfermode> fOverdrawXfermode;
fmalita65cdb572015-03-26 07:24:48 -070075
76 bool fOverrideFilterQuality;
77 SkFilterQuality fFilterQuality;
78
79 typedef SkPaintFilterCanvas INHERITED;
80};
81
kkinnunen26e54002015-01-05 12:58:56 -080082SkDebugCanvas::SkDebugCanvas(int width, int height)
83 : INHERITED(width, height)
halcanary96fcdcc2015-08-27 07:41:13 -070084 , fPicture(nullptr)
commit-bot@chromium.org1735d662013-12-04 13:42:46 +000085 , fFilter(false)
commit-bot@chromium.org768ac852014-03-03 16:32:17 +000086 , fMegaVizMode(false)
robertphillips@google.comf4741c12013-02-06 20:13:54 +000087 , fOverdrawViz(false)
fmalita65cdb572015-03-26 07:24:48 -070088 , fOverrideFilterQuality(false)
ethannicholas0a0520a2016-02-12 12:06:53 -080089 , fFilterQuality(kNone_SkFilterQuality)
joshualitt10d8fc22016-02-29 11:15:06 -080090 , fClipVizColor(SK_ColorTRANSPARENT)
joshualitt5d5207a2016-02-29 12:46:04 -080091 , fDrawGpuBatchBounds(false) {
bungeman@google.come8cc6e82013-01-17 16:30:56 +000092 fUserMatrix.reset();
robertphillips@google.com8b157172013-11-07 22:20:31 +000093
94 // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
95 // operations. This can lead to problems in the debugger which expects all
96 // the operations in the captured skp to appear in the debug canvas. To
97 // circumvent this we create a wide open clip here (an empty clip rect
98 // is not sufficient).
99 // Internally, the SkRect passed to clipRect is converted to an SkIRect and
100 // rounded out. The following code creates a nearly maximal rect that will
101 // not get collapsed by the coming conversions (Due to precision loss the
102 // inset has to be surprisingly large).
103 SkIRect largeIRect = SkIRect::MakeLargest();
104 largeIRect.inset(1024, 1024);
robertphillips@google.com6c1e49a2013-11-10 15:08:45 +0000105 SkRect large = SkRect::Make(largeIRect);
robertphillips@google.com8b157172013-11-07 22:20:31 +0000106#ifdef SK_DEBUG
reedb07a94f2014-11-19 05:03:18 -0800107 SkASSERT(!large.roundOut().isEmpty());
robertphillips@google.com8b157172013-11-07 22:20:31 +0000108#endif
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000109 // call the base class' version to avoid adding a draw command
110 this->INHERITED::onClipRect(large, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
chudy@google.com902ebe52012-06-29 14:21:22 +0000111}
112
chudy@google.com9cda6f72012-08-07 15:08:33 +0000113SkDebugCanvas::~SkDebugCanvas() {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000114 fCommandVector.deleteAll();
chudy@google.com9cda6f72012-08-07 15:08:33 +0000115}
chudy@google.com902ebe52012-06-29 14:21:22 +0000116
117void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000118 fCommandVector.push(command);
chudy@google.com902ebe52012-06-29 14:21:22 +0000119}
120
121void SkDebugCanvas::draw(SkCanvas* canvas) {
commit-bot@chromium.org1735d662013-12-04 13:42:46 +0000122 if (!fCommandVector.isEmpty()) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000123 this->drawTo(canvas, fCommandVector.count() - 1);
chudy@google.com902ebe52012-06-29 14:21:22 +0000124 }
125}
126
chudy@google.com830b8792012-08-01 15:57:52 +0000127void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
bungeman@google.come8cc6e82013-01-17 16:30:56 +0000128 canvas->concat(fUserMatrix);
chudy@google.com830b8792012-08-01 15:57:52 +0000129}
130
131int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000132 SkBitmap bitmap;
reed@google.com9ebcac52014-01-24 18:53:42 +0000133 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
chudy@google.com902ebe52012-06-29 14:21:22 +0000134
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000135 SkCanvas canvas(bitmap);
robertphillips@google.com94acc702012-09-06 18:43:21 +0000136 canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700137 this->applyUserTransform(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000138
139 int layer = 0;
chudy@google.com751961d2012-07-31 20:07:42 +0000140 SkColor prev = bitmap.getColor(0,0);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000141 for (int i = 0; i < index; i++) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000142 if (fCommandVector[i]->isVisible()) {
robertphillips70171682014-10-16 14:28:28 -0700143 fCommandVector[i]->setUserMatrix(fUserMatrix);
robertphillips@google.com67baba42013-01-02 20:20:31 +0000144 fCommandVector[i]->execute(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000145 }
146 if (prev != bitmap.getColor(0,0)) {
147 layer = i;
148 }
149 prev = bitmap.getColor(0,0);
150 }
151 return layer;
152}
153
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000154class SkDebugClipVisitor : public SkCanvas::ClipVisitor {
155public:
156 SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
157
mtklein36352bf2015-03-25 18:17:31 -0700158 void clipRect(const SkRect& r, SkRegion::Op, bool doAA) override {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000159 SkPaint p;
160 p.setColor(SK_ColorRED);
161 p.setStyle(SkPaint::kStroke_Style);
162 p.setAntiAlias(doAA);
163 fCanvas->drawRect(r, p);
164 }
mtklein36352bf2015-03-25 18:17:31 -0700165 void clipRRect(const SkRRect& rr, SkRegion::Op, bool doAA) override {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000166 SkPaint p;
167 p.setColor(SK_ColorGREEN);
168 p.setStyle(SkPaint::kStroke_Style);
169 p.setAntiAlias(doAA);
170 fCanvas->drawRRect(rr, p);
171 }
mtklein36352bf2015-03-25 18:17:31 -0700172 void clipPath(const SkPath& path, SkRegion::Op, bool doAA) override {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000173 SkPaint p;
174 p.setColor(SK_ColorBLUE);
175 p.setStyle(SkPaint::kStroke_Style);
176 p.setAntiAlias(doAA);
177 fCanvas->drawPath(path, p);
178 }
179
180protected:
181 SkCanvas* fCanvas;
182
183private:
184 typedef SkCanvas::ClipVisitor INHERITED;
185};
186
187// set up the saveLayer commands so that the active ones
188// return true in their 'active' method
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000189void SkDebugCanvas::markActiveCommands(int index) {
190 fActiveLayers.rewind();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000191
192 for (int i = 0; i < fCommandVector.count(); ++i) {
193 fCommandVector[i]->setActive(false);
194 }
195
196 for (int i = 0; i < index; ++i) {
197 SkDrawCommand::Action result = fCommandVector[i]->action();
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000198 if (SkDrawCommand::kPushLayer_Action == result) {
199 fActiveLayers.push(fCommandVector[i]);
200 } else if (SkDrawCommand::kPopLayer_Action == result) {
201 fActiveLayers.pop();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000202 }
203 }
204
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000205 for (int i = 0; i < fActiveLayers.count(); ++i) {
206 fActiveLayers[i]->setActive(true);
207 }
208
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000209}
210
joshualitt46b301d2016-03-02 08:32:37 -0800211void SkDebugCanvas::drawTo(SkCanvas* canvas, int index, int m) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000212 SkASSERT(!fCommandVector.isEmpty());
213 SkASSERT(index < fCommandVector.count());
kkinnunen26a00de2015-01-13 23:09:19 -0800214
215 int saveCount = canvas->save();
216
kkinnunen26e54002015-01-05 12:58:56 -0800217 SkRect windowRect = SkRect::MakeWH(SkIntToScalar(canvas->getBaseLayerSize().width()),
218 SkIntToScalar(canvas->getBaseLayerSize().height()));
chudy@google.com830b8792012-08-01 15:57:52 +0000219
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000220 bool pathOpsMode = getAllowSimplifyClip();
221 canvas->setAllowSimplifyClip(pathOpsMode);
ethannicholascecbbe22016-02-17 11:49:43 -0800222 canvas->clear(SK_ColorWHITE);
kkinnunen26a00de2015-01-13 23:09:19 -0800223 canvas->resetMatrix();
224 if (!windowRect.isEmpty()) {
225 canvas->clipRect(windowRect, SkRegion::kReplace_Op);
commit-bot@chromium.orga27622c2013-08-05 16:31:27 +0000226 }
kkinnunen26a00de2015-01-13 23:09:19 -0800227 this->applyUserTransform(canvas);
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000228
fmalita65cdb572015-03-26 07:24:48 -0700229 if (fPaintFilterCanvas) {
230 fPaintFilterCanvas->addCanvas(canvas);
231 canvas = fPaintFilterCanvas.get();
halcanary9d524f22016-03-29 09:03:52 -0700232
chudy@google.com830b8792012-08-01 15:57:52 +0000233 }
234
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000235 if (fMegaVizMode) {
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000236 this->markActiveCommands(index);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000237 }
halcanary9d524f22016-03-29 09:03:52 -0700238
joshualitt40836102016-03-11 11:45:53 -0800239#if SK_SUPPORT_GPU
joshualitt10d8fc22016-02-29 11:15:06 -0800240 // If we have a GPU backend we can also visualize the batching information
joshualitt10d8fc22016-02-29 11:15:06 -0800241 GrAuditTrail* at = nullptr;
joshualittae47aee2016-03-10 13:29:36 -0800242 if (fDrawGpuBatchBounds || m != -1) {
243 at = this->getAuditTrail(canvas);
joshualitt10d8fc22016-02-29 11:15:06 -0800244 }
joshualitt40836102016-03-11 11:45:53 -0800245#endif
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000246
kkinnunen26a00de2015-01-13 23:09:19 -0800247 for (int i = 0; i <= index; i++) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000248 if (i == index && fFilter) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700249 canvas->clear(0xAAFFFFFF);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000250 }
halcanary9d524f22016-03-29 09:03:52 -0700251
joshualitt10d8fc22016-02-29 11:15:06 -0800252#if SK_SUPPORT_GPU
brianosman1c9f9222016-04-15 11:00:51 -0700253 // We need to flush any pending operations, or they might batch with commands below.
254 // Previous operations were not registered with the audit trail when they were
255 // created, so if we allow them to combine, the audit trail will fail to find them.
256 canvas->flush();
257
joshualitt10d8fc22016-02-29 11:15:06 -0800258 GrAuditTrail::AutoCollectBatches* acb = nullptr;
259 if (at) {
260 acb = new GrAuditTrail::AutoCollectBatches(at, i);
261 }
262#endif
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000263
robertphillips@google.com67baba42013-01-02 20:20:31 +0000264 if (fCommandVector[i]->isVisible()) {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000265 if (fMegaVizMode && fCommandVector[i]->active()) {
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000266 // "active" commands execute their visualization behaviors:
267 // All active saveLayers get replaced with saves so all draws go to the
268 // visible canvas.
269 // All active culls draw their cull box
270 fCommandVector[i]->vizExecute(canvas);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000271 } else {
robertphillips70171682014-10-16 14:28:28 -0700272 fCommandVector[i]->setUserMatrix(fUserMatrix);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000273 fCommandVector[i]->execute(canvas);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000274 }
chudy@google.com902ebe52012-06-29 14:21:22 +0000275 }
joshualitt10d8fc22016-02-29 11:15:06 -0800276#if SK_SUPPORT_GPU
277 if (at && acb) {
278 delete acb;
279 }
280#endif
chudy@google.com902ebe52012-06-29 14:21:22 +0000281 }
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000282
ethannicholas0a0520a2016-02-12 12:06:53 -0800283 if (SkColorGetA(fClipVizColor) != 0) {
284 canvas->save();
285 #define LARGE_COORD 1000000000
286 canvas->clipRect(SkRect::MakeLTRB(-LARGE_COORD, -LARGE_COORD, LARGE_COORD, LARGE_COORD),
287 SkRegion::kReverseDifference_Op);
288 SkPaint clipPaint;
289 clipPaint.setColor(fClipVizColor);
290 canvas->drawPaint(clipPaint);
291 canvas->restore();
292 }
293
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000294 if (fMegaVizMode) {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000295 canvas->save();
296 // nuke the CTM
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700297 canvas->resetMatrix();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000298 // turn off clipping
kkinnunen26e54002015-01-05 12:58:56 -0800299 if (!windowRect.isEmpty()) {
300 SkRect r = windowRect;
301 r.outset(SK_Scalar1, SK_Scalar1);
302 canvas->clipRect(r, SkRegion::kReplace_Op);
303 }
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000304 // visualize existing clips
305 SkDebugClipVisitor visitor(canvas);
306
307 canvas->replayClips(&visitor);
308
309 canvas->restore();
310 }
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000311 if (pathOpsMode) {
312 this->resetClipStackData();
313 const SkClipStack* clipStack = canvas->getClipStack();
314 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
315 const SkClipStack::Element* element;
316 SkPath devPath;
317 while ((element = iter.next())) {
318 SkClipStack::Element::Type type = element->getType();
319 SkPath operand;
320 if (type != SkClipStack::Element::kEmpty_Type) {
321 element->asPath(&operand);
322 }
323 SkRegion::Op elementOp = element->getOp();
324 this->addClipStackData(devPath, operand, elementOp);
325 if (elementOp == SkRegion::kReplace_Op) {
326 devPath = operand;
327 } else {
328 Op(devPath, operand, (SkPathOp) elementOp, &devPath);
329 }
330 }
331 this->lastClipStackData(devPath);
332 }
chudy@google.coma9e937c2012-08-03 17:32:05 +0000333 fMatrix = canvas->getTotalMatrix();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +0000334 if (!canvas->getClipDeviceBounds(&fClip)) {
335 fClip.setEmpty();
336 }
kkinnunen26a00de2015-01-13 23:09:19 -0800337
338 canvas->restoreToCount(saveCount);
fmalita65cdb572015-03-26 07:24:48 -0700339
340 if (fPaintFilterCanvas) {
341 fPaintFilterCanvas->removeAll();
342 }
joshualitt10d8fc22016-02-29 11:15:06 -0800343
344#if SK_SUPPORT_GPU
345 // draw any batches if required and issue a full reset onto GrAuditTrail
346 if (at) {
joshualitte43f7e62016-03-04 10:45:05 -0800347 // just in case there is global reordering, we flush the canvas before querying
348 // GrAuditTrail
joshualittb0666ad2016-03-08 10:43:41 -0800349 GrAuditTrail::AutoEnable ae(at);
joshualitte43f7e62016-03-04 10:45:05 -0800350 canvas->flush();
351
joshualittbdc6b2b2016-03-01 14:22:02 -0800352 // we pick three colorblind-safe colors, 75% alpha
353 static const SkColor kTotalBounds = SkColorSetARGB(0xC0, 0x6A, 0x3D, 0x9A);
354 static const SkColor kOpBatchBounds = SkColorSetARGB(0xC0, 0xE3, 0x1A, 0x1C);
355 static const SkColor kOtherBatchBounds = SkColorSetARGB(0xC0, 0xFF, 0x7F, 0x00);
356
joshualitt1d7decf2016-03-01 07:15:52 -0800357 // get the render target of the top device so we can ignore batches drawn offscreen
358 SkBaseDevice* bd = canvas->getDevice_just_for_deprecated_compatibility_testing();
359 SkGpuDevice* gbd = reinterpret_cast<SkGpuDevice*>(bd);
robertphillips8abb3702016-08-31 14:04:06 -0700360 uint32_t rtID = gbd->accessDrawContext()->accessRenderTarget()->uniqueID();
joshualitt1d7decf2016-03-01 07:15:52 -0800361
362 // get the bounding boxes to draw
joshualitt10d8fc22016-02-29 11:15:06 -0800363 SkTArray<GrAuditTrail::BatchInfo> childrenBounds;
joshualitt46b301d2016-03-02 08:32:37 -0800364 if (m == -1) {
365 at->getBoundsByClientID(&childrenBounds, index);
366 } else {
367 // the client wants us to draw the mth batch
368 at->getBoundsByBatchListID(&childrenBounds.push_back(), m);
369 }
joshualitt10d8fc22016-02-29 11:15:06 -0800370 SkPaint paint;
371 paint.setStyle(SkPaint::kStroke_Style);
372 paint.setStrokeWidth(1);
373 for (int i = 0; i < childrenBounds.count(); i++) {
joshualitt1d7decf2016-03-01 07:15:52 -0800374 if (childrenBounds[i].fRenderTargetUniqueID != rtID) {
375 // offscreen draw, ignore for now
376 continue;
377 }
joshualittbdc6b2b2016-03-01 14:22:02 -0800378 paint.setColor(kTotalBounds);
joshualitt10d8fc22016-02-29 11:15:06 -0800379 canvas->drawRect(childrenBounds[i].fBounds, paint);
380 for (int j = 0; j < childrenBounds[i].fBatches.count(); j++) {
381 const GrAuditTrail::BatchInfo::Batch& batch = childrenBounds[i].fBatches[j];
382 if (batch.fClientID != index) {
joshualittbdc6b2b2016-03-01 14:22:02 -0800383 paint.setColor(kOtherBatchBounds);
joshualitt10d8fc22016-02-29 11:15:06 -0800384 } else {
joshualittbdc6b2b2016-03-01 14:22:02 -0800385 paint.setColor(kOpBatchBounds);
joshualitt10d8fc22016-02-29 11:15:06 -0800386 }
387 canvas->drawRect(batch.fBounds, paint);
388 }
389 }
joshualitt10d8fc22016-02-29 11:15:06 -0800390 }
joshualitt10d8fc22016-02-29 11:15:06 -0800391#endif
joshualittae47aee2016-03-10 13:29:36 -0800392 this->cleanupAuditTrail(canvas);
chudy@google.com902ebe52012-06-29 14:21:22 +0000393}
394
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000395void SkDebugCanvas::deleteDrawCommandAt(int index) {
396 SkASSERT(index < fCommandVector.count());
397 delete fCommandVector[index];
398 fCommandVector.remove(index);
399}
400
chudy@google.com902ebe52012-06-29 14:21:22 +0000401SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000402 SkASSERT(index < fCommandVector.count());
403 return fCommandVector[index];
chudy@google.com902ebe52012-06-29 14:21:22 +0000404}
405
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000406void SkDebugCanvas::setDrawCommandAt(int index, SkDrawCommand* command) {
407 SkASSERT(index < fCommandVector.count());
408 delete fCommandVector[index];
409 fCommandVector[index] = command;
410}
411
fmalita8c89c522014-11-08 16:18:56 -0800412const SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) const {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000413 SkASSERT(index < fCommandVector.count());
414 return fCommandVector[index]->Info();
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000415}
chudy@google.com902ebe52012-06-29 14:21:22 +0000416
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000417bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000418 SkASSERT(index < fCommandVector.count());
419 return fCommandVector[index]->isVisible();
chudy@google.com902ebe52012-06-29 14:21:22 +0000420}
421
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000422const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000423 return fCommandVector;
chudy@google.com902ebe52012-06-29 14:21:22 +0000424}
425
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000426SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() {
427 return fCommandVector;
428}
429
joshualittae47aee2016-03-10 13:29:36 -0800430GrAuditTrail* SkDebugCanvas::getAuditTrail(SkCanvas* canvas) {
431 GrAuditTrail* at = nullptr;
joshualitte43f7e62016-03-04 10:45:05 -0800432#if SK_SUPPORT_GPU
robertphillips175dd9b2016-04-28 14:32:04 -0700433 GrContext* ctx = canvas->getGrContext();
434 if (ctx) {
435 at = ctx->getAuditTrail();
joshualitte43f7e62016-03-04 10:45:05 -0800436 }
437#endif
joshualittae47aee2016-03-10 13:29:36 -0800438 return at;
439}
440
441void SkDebugCanvas::drawAndCollectBatches(int n, SkCanvas* canvas) {
joshualitt40836102016-03-11 11:45:53 -0800442#if SK_SUPPORT_GPU
joshualittae47aee2016-03-10 13:29:36 -0800443 GrAuditTrail* at = this->getAuditTrail(canvas);
444 if (at) {
joshualittae47aee2016-03-10 13:29:36 -0800445 // loop over all of the commands and draw them, this is to collect reordering
446 // information
447 for (int i = 0; i < this->getSize() && i <= n; i++) {
448 GrAuditTrail::AutoCollectBatches enable(at, i);
449 fCommandVector[i]->execute(canvas);
450 }
451
452 // in case there is some kind of global reordering
453 {
454 GrAuditTrail::AutoEnable ae(at);
455 canvas->flush();
456 }
joshualittae47aee2016-03-10 13:29:36 -0800457 }
joshualitt40836102016-03-11 11:45:53 -0800458#endif
joshualittae47aee2016-03-10 13:29:36 -0800459}
460
461void SkDebugCanvas::cleanupAuditTrail(SkCanvas* canvas) {
462 GrAuditTrail* at = this->getAuditTrail(canvas);
463 if (at) {
464#if SK_SUPPORT_GPU
465 GrAuditTrail::AutoEnable ae(at);
466 at->fullReset();
467#endif
468 }
469}
470
471Json::Value SkDebugCanvas::toJSON(UrlDataManager& urlDataManager, int n, SkCanvas* canvas) {
472 this->drawAndCollectBatches(n, canvas);
halcanary9d524f22016-03-29 09:03:52 -0700473
joshualitte43f7e62016-03-04 10:45:05 -0800474 // now collect json
joshualitt40836102016-03-11 11:45:53 -0800475#if SK_SUPPORT_GPU
joshualittae47aee2016-03-10 13:29:36 -0800476 GrAuditTrail* at = this->getAuditTrail(canvas);
joshualitt40836102016-03-11 11:45:53 -0800477#endif
ethannicholas402cd912016-02-10 12:57:30 -0800478 Json::Value result = Json::Value(Json::objectValue);
479 result[SKDEBUGCANVAS_ATTRIBUTE_VERSION] = Json::Value(SKDEBUGCANVAS_VERSION);
480 Json::Value commands = Json::Value(Json::arrayValue);
ethannicholas0a0520a2016-02-12 12:06:53 -0800481 for (int i = 0; i < this->getSize() && i <= n; i++) {
joshualitte43f7e62016-03-04 10:45:05 -0800482 commands[i] = this->getDrawCommandAt(i)->toJSON(urlDataManager);
483#if SK_SUPPORT_GPU
484 if (at) {
485 // TODO if this is inefficient we could add a method to GrAuditTrail which takes
486 // a Json::Value and is only compiled in this file
487 Json::Value parsedFromString;
488 Json::Reader reader;
489 SkAssertResult(reader.parse(at->toJson(i).c_str(), parsedFromString));
490
491 commands[i][SKDEBUGCANVAS_ATTRIBUTE_AUDITTRAIL] = parsedFromString;
492 }
493#endif
ethannicholas402cd912016-02-10 12:57:30 -0800494 }
joshualittae47aee2016-03-10 13:29:36 -0800495 this->cleanupAuditTrail(canvas);
ethannicholas402cd912016-02-10 12:57:30 -0800496 result[SKDEBUGCANVAS_ATTRIBUTE_COMMANDS] = commands;
497 return result;
498}
499
joshualittae47aee2016-03-10 13:29:36 -0800500Json::Value SkDebugCanvas::toJSONBatchList(int n, SkCanvas* canvas) {
501 this->drawAndCollectBatches(n, canvas);
502
503 Json::Value parsedFromString;
joshualittae47aee2016-03-10 13:29:36 -0800504#if SK_SUPPORT_GPU
joshualitt40836102016-03-11 11:45:53 -0800505 GrAuditTrail* at = this->getAuditTrail(canvas);
joshualittae47aee2016-03-10 13:29:36 -0800506 if (at) {
507 GrAuditTrail::AutoManageBatchList enable(at);
508 Json::Reader reader;
509 SkAssertResult(reader.parse(at->toJson().c_str(), parsedFromString));
510 }
511#endif
512 this->cleanupAuditTrail(canvas);
513 return parsedFromString;
514}
515
fmalita65cdb572015-03-26 07:24:48 -0700516void SkDebugCanvas::updatePaintFilterCanvas() {
517 if (!fOverdrawViz && !fOverrideFilterQuality) {
halcanary96fcdcc2015-08-27 07:41:13 -0700518 fPaintFilterCanvas.reset(nullptr);
fmalita65cdb572015-03-26 07:24:48 -0700519 return;
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000520 }
521
fmalita65cdb572015-03-26 07:24:48 -0700522 const SkImageInfo info = this->imageInfo();
halcanary385fe4d2015-08-26 13:07:48 -0700523 fPaintFilterCanvas.reset(new DebugPaintFilterCanvas(info.width(), info.height(), fOverdrawViz,
524 fOverrideFilterQuality, fFilterQuality));
fmalita65cdb572015-03-26 07:24:48 -0700525}
526
527void SkDebugCanvas::setOverdrawViz(bool overdrawViz) {
528 if (fOverdrawViz == overdrawViz) {
529 return;
530 }
531
532 fOverdrawViz = overdrawViz;
533 this->updatePaintFilterCanvas();
534}
535
536void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkFilterQuality quality) {
537 if (fOverrideFilterQuality == overrideTexFiltering && fFilterQuality == quality) {
538 return;
539 }
540
541 fOverrideFilterQuality = overrideTexFiltering;
542 fFilterQuality = quality;
543 this->updatePaintFilterCanvas();
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000544}
545
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000546void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
547 this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
chudy@google.com902ebe52012-06-29 14:21:22 +0000548}
549
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000550void SkDebugCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
551 this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
chudy@google.com902ebe52012-06-29 14:21:22 +0000552}
553
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000554void SkDebugCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
555 this->addDrawCommand(new SkClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000556}
557
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000558void SkDebugCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
559 this->addDrawCommand(new SkClipRegionCommand(region, op));
chudy@google.com902ebe52012-06-29 14:21:22 +0000560}
561
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000562void SkDebugCanvas::didConcat(const SkMatrix& matrix) {
robertphillips9bafc302015-02-13 11:13:00 -0800563 this->addDrawCommand(new SkConcatCommand(matrix));
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000564 this->INHERITED::didConcat(matrix);
chudy@google.com902ebe52012-06-29 14:21:22 +0000565}
566
reed97660cc2016-06-28 18:54:19 -0700567void SkDebugCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
568 this->addDrawCommand(new SkDrawAnnotationCommand(rect, key, sk_ref_sp(value)));
569}
570
reed41af9662015-01-05 07:49:08 -0800571void SkDebugCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar left,
572 SkScalar top, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000573 this->addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000574}
575
reed41af9662015-01-05 07:49:08 -0800576void SkDebugCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700577 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700578 this->addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint,
579 (SrcRectConstraint)constraint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000580}
581
reed41af9662015-01-05 07:49:08 -0800582void SkDebugCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
583 const SkRect& dst, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000584 this->addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000585}
586
reed41af9662015-01-05 07:49:08 -0800587void SkDebugCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
588 const SkPaint* paint) {
fmalita651c9202015-07-22 10:23:01 -0700589 this->addDrawCommand(new SkDrawImageCommand(image, left, top, paint));
reed41af9662015-01-05 07:49:08 -0800590}
591
592void SkDebugCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700593 const SkPaint* paint, SrcRectConstraint constraint) {
fmalita651c9202015-07-22 10:23:01 -0700594 this->addDrawCommand(new SkDrawImageRectCommand(image, src, dst, paint, constraint));
reed41af9662015-01-05 07:49:08 -0800595}
596
reed41af9662015-01-05 07:49:08 -0800597void SkDebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000598 this->addDrawCommand(new SkDrawOvalCommand(oval, paint));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000599}
600
bsalomonac3aa242016-08-19 11:25:19 -0700601void SkDebugCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
602 bool useCenter, const SkPaint& paint) {
603 this->addDrawCommand(new SkDrawArcCommand(oval, startAngle, sweepAngle, useCenter, paint));
604}
605
reed41af9662015-01-05 07:49:08 -0800606void SkDebugCanvas::onDrawPaint(const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000607 this->addDrawCommand(new SkDrawPaintCommand(paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000608}
609
reed41af9662015-01-05 07:49:08 -0800610void SkDebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000611 this->addDrawCommand(new SkDrawPathCommand(path, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000612}
613
mtkleinf0f14112014-12-12 08:46:25 -0800614void SkDebugCanvas::onDrawPicture(const SkPicture* picture,
615 const SkMatrix* matrix,
robertphillipsb3f319f2014-08-13 10:46:23 -0700616 const SkPaint* paint) {
fmalita160ebb22015-04-01 20:58:37 -0700617 this->addDrawCommand(new SkBeginDrawPictureCommand(picture, matrix, paint));
ethannicholas891ad662016-02-12 07:15:45 -0800618 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
619 picture->playback(this);
fmalita160ebb22015-04-01 20:58:37 -0700620 this->addDrawCommand(new SkEndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint)));
chudy@google.com902ebe52012-06-29 14:21:22 +0000621}
622
vjiaoblack95302da2016-07-21 10:25:54 -0700623void SkDebugCanvas::onDrawShadowedPicture(const SkPicture* picture,
624 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -0700625 const SkPaint* paint,
626 const SkShadowParams& params) {
627 this->addDrawCommand(new SkBeginDrawShadowedPictureCommand(picture, matrix, paint, params));
vjiaoblack95302da2016-07-21 10:25:54 -0700628 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
629 picture->playback(this);
630 this->addDrawCommand(new SkEndDrawShadowedPictureCommand(SkToBool(matrix) || SkToBool(paint)));
631}
632
reed41af9662015-01-05 07:49:08 -0800633void SkDebugCanvas::onDrawPoints(PointMode mode, size_t count,
634 const SkPoint pts[], const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000635 this->addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000636}
637
reed@google.come0d9ce82014-04-23 04:00:17 +0000638void SkDebugCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
639 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000640 this->addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000641}
642
reed@google.come0d9ce82014-04-23 04:00:17 +0000643void SkDebugCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
644 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000645 this->addDrawCommand(
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000646 new SkDrawPosTextHCommand(text, byteLength, xpos, constY, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000647}
648
reed41af9662015-01-05 07:49:08 -0800649void SkDebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
chudy@google.com902ebe52012-06-29 14:21:22 +0000650 // NOTE(chudy): Messing up when renamed to DrawRect... Why?
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000651 addDrawCommand(new SkDrawRectCommand(rect, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000652}
653
reed41af9662015-01-05 07:49:08 -0800654void SkDebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000655 this->addDrawCommand(new SkDrawRRectCommand(rrect, paint));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000656}
657
commit-bot@chromium.orgab582732014-02-21 12:20:45 +0000658void SkDebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
659 const SkPaint& paint) {
commit-bot@chromium.org3d305202014-02-24 17:28:55 +0000660 this->addDrawCommand(new SkDrawDRRectCommand(outer, inner, paint));
commit-bot@chromium.orgab582732014-02-21 12:20:45 +0000661}
662
reed@google.come0d9ce82014-04-23 04:00:17 +0000663void SkDebugCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
664 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000665 this->addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000666}
667
reed@google.come0d9ce82014-04-23 04:00:17 +0000668void SkDebugCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
669 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000670 this->addDrawCommand(
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000671 new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000672}
673
reed45561a02016-07-07 12:47:17 -0700674void SkDebugCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
675 const SkRect* cull, const SkPaint& paint) {
676 this->addDrawCommand(new SkDrawTextRSXformCommand(text, byteLength, xform, cull, paint));
677}
678
fmalitab7425172014-08-26 07:56:44 -0700679void SkDebugCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
680 const SkPaint& paint) {
fmalita37283c22016-09-13 10:00:23 -0700681 this->addDrawCommand(new SkDrawTextBlobCommand(sk_ref_sp(const_cast<SkTextBlob*>(blob)),
682 x, y, paint));
fmalitab7425172014-08-26 07:56:44 -0700683}
684
robertphillips9bafc302015-02-13 11:13:00 -0800685void SkDebugCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
686 const SkPoint texCoords[4], SkXfermode* xmode,
687 const SkPaint& paint) {
688 this->addDrawCommand(new SkDrawPatchCommand(cubics, colors, texCoords, xmode, paint));
689}
690
reed41af9662015-01-05 07:49:08 -0800691void SkDebugCanvas::onDrawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
692 const SkPoint texs[], const SkColor colors[],
693 SkXfermode*, const uint16_t indices[], int indexCount,
694 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000695 this->addDrawCommand(new SkDrawVerticesCommand(vmode, vertexCount, vertices,
halcanary96fcdcc2015-08-27 07:41:13 -0700696 texs, colors, nullptr, indices, indexCount, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000697}
698
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000699void SkDebugCanvas::willRestore() {
700 this->addDrawCommand(new SkRestoreCommand());
701 this->INHERITED::willRestore();
chudy@google.com902ebe52012-06-29 14:21:22 +0000702}
703
Florin Malita5f6102d2014-06-30 10:13:28 -0400704void SkDebugCanvas::willSave() {
705 this->addDrawCommand(new SkSaveCommand());
706 this->INHERITED::willSave();
chudy@google.com902ebe52012-06-29 14:21:22 +0000707}
708
reed4960eee2015-12-18 07:09:18 -0800709SkCanvas::SaveLayerStrategy SkDebugCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
710 this->addDrawCommand(new SkSaveLayerCommand(rec));
711 (void)this->INHERITED::getSaveLayerStrategy(rec);
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000712 // No need for a full layer.
713 return kNoLayer_SaveLayerStrategy;
chudy@google.com902ebe52012-06-29 14:21:22 +0000714}
715
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000716void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000717 this->addDrawCommand(new SkSetMatrixCommand(matrix));
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000718 this->INHERITED::didSetMatrix(matrix);
chudy@google.com902ebe52012-06-29 14:21:22 +0000719}
720
vjiaoblacke5de1302016-07-13 14:05:28 -0700721void SkDebugCanvas::didTranslateZ(SkScalar z) {
vjiaoblack95302da2016-07-21 10:25:54 -0700722#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -0700723 this->addDrawCommand(new SkTranslateZCommand(z));
724 this->INHERITED::didTranslateZ(z);
vjiaoblack95302da2016-07-21 10:25:54 -0700725#endif
vjiaoblacke5de1302016-07-13 14:05:28 -0700726}
727
chudy@google.com902ebe52012-06-29 14:21:22 +0000728void SkDebugCanvas::toggleCommand(int index, bool toggle) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000729 SkASSERT(index < fCommandVector.count());
730 fCommandVector[index]->setVisible(toggle);
chudy@google.com902ebe52012-06-29 14:21:22 +0000731}
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000732
733static const char* gFillTypeStrs[] = {
734 "kWinding_FillType",
735 "kEvenOdd_FillType",
736 "kInverseWinding_FillType",
737 "kInverseEvenOdd_FillType"
738};
739
740static const char* gOpStrs[] = {
scroggo5965b732015-04-07 06:53:21 -0700741 "kDifference_PathOp",
742 "kIntersect_PathOp",
743 "kUnion_PathOp",
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000744 "kXor_PathOp",
scroggo5965b732015-04-07 06:53:21 -0700745 "kReverseDifference_PathOp",
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000746};
747
748static const char kHTML4SpaceIndent[] = "&nbsp;&nbsp;&nbsp;&nbsp;";
749
750void SkDebugCanvas::outputScalar(SkScalar num) {
751 if (num == (int) num) {
752 fClipStackData.appendf("%d", (int) num);
753 } else {
754 SkString str;
755 str.printf("%1.9g", num);
756 int width = (int) str.size();
757 const char* cStr = str.c_str();
758 while (cStr[width - 1] == '0') {
759 --width;
760 }
761 str.resize(width);
762 fClipStackData.appendf("%sf", str.c_str());
763 }
764}
765
766void SkDebugCanvas::outputPointsCommon(const SkPoint* pts, int count) {
767 for (int index = 0; index < count; ++index) {
768 this->outputScalar(pts[index].fX);
769 fClipStackData.appendf(", ");
770 this->outputScalar(pts[index].fY);
771 if (index + 1 < count) {
772 fClipStackData.appendf(", ");
773 }
774 }
775}
776
777void SkDebugCanvas::outputPoints(const SkPoint* pts, int count) {
778 this->outputPointsCommon(pts, count);
779 fClipStackData.appendf(");<br>");
780}
781
782void SkDebugCanvas::outputConicPoints(const SkPoint* pts, SkScalar weight) {
783 this->outputPointsCommon(pts, 2);
784 fClipStackData.appendf(", ");
785 this->outputScalar(weight);
786 fClipStackData.appendf(");<br>");
787}
788
789void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) {
790 SkPath::RawIter iter(path);
791 SkPath::FillType fillType = path.getFillType();
792 fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName);
793 fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceIndent, pathName,
794 gFillTypeStrs[fillType]);
795 iter.setPath(path);
796 uint8_t verb;
797 SkPoint pts[4];
798 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
799 switch (verb) {
800 case SkPath::kMove_Verb:
801 fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathName);
802 this->outputPoints(&pts[0], 1);
803 continue;
804 case SkPath::kLine_Verb:
805 fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathName);
806 this->outputPoints(&pts[1], 1);
807 break;
808 case SkPath::kQuad_Verb:
809 fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathName);
810 this->outputPoints(&pts[1], 2);
811 break;
812 case SkPath::kConic_Verb:
813 fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathName);
814 this->outputConicPoints(&pts[1], iter.conicWeight());
815 break;
816 case SkPath::kCubic_Verb:
817 fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathName);
818 this->outputPoints(&pts[1], 3);
819 break;
820 case SkPath::kClose_Verb:
821 fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, pathName);
822 break;
823 default:
824 SkDEBUGFAIL("bad verb");
825 return;
826 }
827 }
828}
829
830void SkDebugCanvas::addClipStackData(const SkPath& devPath, const SkPath& operand,
831 SkRegion::Op elementOp) {
832 if (elementOp == SkRegion::kReplace_Op) {
833 if (!lastClipStackData(devPath)) {
834 fSaveDevPath = operand;
835 }
836 fCalledAddStackData = false;
837 } else {
838 fClipStackData.appendf("<br>static void test(skiatest::Reporter* reporter,"
839 " const char* filename) {<br>");
840 addPathData(fCalledAddStackData ? devPath : fSaveDevPath, "path");
841 addPathData(operand, "pathB");
842 fClipStackData.appendf("%stestPathOp(reporter, path, pathB, %s, filename);<br>",
843 kHTML4SpaceIndent, gOpStrs[elementOp]);
844 fClipStackData.appendf("}<br>");
845 fCalledAddStackData = true;
846 }
847}
848
849bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) {
850 if (fCalledAddStackData) {
851 fClipStackData.appendf("<br>");
852 addPathData(devPath, "pathOut");
853 return true;
854 }
855 return false;
856}