blob: 337c9d0d651930f15da31873293e90f451939ae0 [file] [log] [blame]
chudy@google.com902ebe52012-06-29 14:21:22 +00001
2/*
3 * Copyright 2012 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
robertphillips@google.comf4741c12013-02-06 20:13:54 +000010#include "SkColorPriv.h"
chudy@google.com902ebe52012-06-29 14:21:22 +000011#include "SkDebugCanvas.h"
12#include "SkDrawCommand.h"
robertphillips@google.comf4741c12013-02-06 20:13:54 +000013#include "SkDrawFilter.h"
robertphillips@google.com6dec8fc2012-11-21 17:11:02 +000014#include "SkDevice.h"
robertphillips@google.comf4741c12013-02-06 20:13:54 +000015#include "SkXfermode.h"
chudy@google.com902ebe52012-06-29 14:21:22 +000016
kkinnunen26e54002015-01-05 12:58:56 -080017SkDebugCanvas::SkDebugCanvas(int width, int height)
18 : INHERITED(width, height)
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +000019 , fPicture(NULL)
commit-bot@chromium.org1735d662013-12-04 13:42:46 +000020 , fFilter(false)
commit-bot@chromium.org768ac852014-03-03 16:32:17 +000021 , fMegaVizMode(false)
robertphillips@google.comf4741c12013-02-06 20:13:54 +000022 , fOverdrawViz(false)
scroggo@google.com06d6ac62013-02-08 21:16:19 +000023 , fOverdrawFilter(NULL)
robertphillips@google.com32bbcf82013-10-17 17:56:10 +000024 , fOverrideTexFiltering(false)
kkinnunen26a00de2015-01-13 23:09:19 -080025 , fTexOverrideFilter(NULL) {
bungeman@google.come8cc6e82013-01-17 16:30:56 +000026 fUserMatrix.reset();
robertphillips@google.com8b157172013-11-07 22:20:31 +000027
28 // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
29 // operations. This can lead to problems in the debugger which expects all
30 // the operations in the captured skp to appear in the debug canvas. To
31 // circumvent this we create a wide open clip here (an empty clip rect
32 // is not sufficient).
33 // Internally, the SkRect passed to clipRect is converted to an SkIRect and
34 // rounded out. The following code creates a nearly maximal rect that will
35 // not get collapsed by the coming conversions (Due to precision loss the
36 // inset has to be surprisingly large).
37 SkIRect largeIRect = SkIRect::MakeLargest();
38 largeIRect.inset(1024, 1024);
robertphillips@google.com6c1e49a2013-11-10 15:08:45 +000039 SkRect large = SkRect::Make(largeIRect);
robertphillips@google.com8b157172013-11-07 22:20:31 +000040#ifdef SK_DEBUG
reedb07a94f2014-11-19 05:03:18 -080041 SkASSERT(!large.roundOut().isEmpty());
robertphillips@google.com8b157172013-11-07 22:20:31 +000042#endif
robertphillips@google.com8f90a892014-02-28 18:19:39 +000043 // call the base class' version to avoid adding a draw command
44 this->INHERITED::onClipRect(large, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
chudy@google.com902ebe52012-06-29 14:21:22 +000045}
46
chudy@google.com9cda6f72012-08-07 15:08:33 +000047SkDebugCanvas::~SkDebugCanvas() {
robertphillips@google.com67baba42013-01-02 20:20:31 +000048 fCommandVector.deleteAll();
robertphillips@google.comf4741c12013-02-06 20:13:54 +000049 SkSafeUnref(fOverdrawFilter);
commit-bot@chromium.org1735d662013-12-04 13:42:46 +000050 SkSafeUnref(fTexOverrideFilter);
chudy@google.com9cda6f72012-08-07 15:08:33 +000051}
chudy@google.com902ebe52012-06-29 14:21:22 +000052
53void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +000054 command->setOffset(this->getOpID());
robertphillips@google.com67baba42013-01-02 20:20:31 +000055 fCommandVector.push(command);
chudy@google.com902ebe52012-06-29 14:21:22 +000056}
57
58void SkDebugCanvas::draw(SkCanvas* canvas) {
commit-bot@chromium.org1735d662013-12-04 13:42:46 +000059 if (!fCommandVector.isEmpty()) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +000060 this->drawTo(canvas, fCommandVector.count() - 1);
chudy@google.com902ebe52012-06-29 14:21:22 +000061 }
62}
63
chudy@google.com830b8792012-08-01 15:57:52 +000064void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
bungeman@google.come8cc6e82013-01-17 16:30:56 +000065 canvas->concat(fUserMatrix);
chudy@google.com830b8792012-08-01 15:57:52 +000066}
67
68int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +000069 SkBitmap bitmap;
reed@google.com9ebcac52014-01-24 18:53:42 +000070 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
chudy@google.com902ebe52012-06-29 14:21:22 +000071
chudy@google.com0b5bbb02012-07-31 19:55:32 +000072 SkCanvas canvas(bitmap);
robertphillips@google.com94acc702012-09-06 18:43:21 +000073 canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
robertphillipsa8d7f0b2014-08-29 08:03:56 -070074 this->applyUserTransform(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +000075
76 int layer = 0;
chudy@google.com751961d2012-07-31 20:07:42 +000077 SkColor prev = bitmap.getColor(0,0);
chudy@google.com0b5bbb02012-07-31 19:55:32 +000078 for (int i = 0; i < index; i++) {
robertphillips@google.com67baba42013-01-02 20:20:31 +000079 if (fCommandVector[i]->isVisible()) {
robertphillips70171682014-10-16 14:28:28 -070080 fCommandVector[i]->setUserMatrix(fUserMatrix);
robertphillips@google.com67baba42013-01-02 20:20:31 +000081 fCommandVector[i]->execute(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +000082 }
83 if (prev != bitmap.getColor(0,0)) {
84 layer = i;
85 }
86 prev = bitmap.getColor(0,0);
87 }
88 return layer;
89}
90
commit-bot@chromium.orgcc277b72014-04-17 15:19:32 +000091class OverdrawXfermode : public SkXfermode {
92public:
mtklein72c9faa2015-01-09 10:06:39 -080093 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const SK_OVERRIDE {
commit-bot@chromium.orgcc277b72014-04-17 15:19:32 +000094 // This table encodes the color progression of the overdraw visualization
95 static const SkPMColor gTable[] = {
96 SkPackARGB32(0x00, 0x00, 0x00, 0x00),
97 SkPackARGB32(0xFF, 128, 158, 255),
98 SkPackARGB32(0xFF, 170, 185, 212),
99 SkPackARGB32(0xFF, 213, 195, 170),
100 SkPackARGB32(0xFF, 255, 192, 127),
101 SkPackARGB32(0xFF, 255, 185, 85),
102 SkPackARGB32(0xFF, 255, 165, 42),
103 SkPackARGB32(0xFF, 255, 135, 0),
104 SkPackARGB32(0xFF, 255, 95, 0),
105 SkPackARGB32(0xFF, 255, 50, 0),
106 SkPackARGB32(0xFF, 255, 0, 0)
107 };
skia.committer@gmail.com60bd7512014-04-18 03:03:54 +0000108
commit-bot@chromium.orgcc277b72014-04-17 15:19:32 +0000109 for (size_t i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) {
110 if (gTable[i] == dst) {
111 return gTable[i+1];
112 }
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000113 }
skia.committer@gmail.com60bd7512014-04-18 03:03:54 +0000114
commit-bot@chromium.orgcc277b72014-04-17 15:19:32 +0000115 return gTable[SK_ARRAY_COUNT(gTable)-1];
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000116 }
117
mtklein72c9faa2015-01-09 10:06:39 -0800118 Factory getFactory() const SK_OVERRIDE { return NULL; }
commit-bot@chromium.orgcc277b72014-04-17 15:19:32 +0000119#ifndef SK_IGNORE_TO_STRING
rmistry465206a2015-02-02 12:08:18 -0800120 virtual void toString(SkString* str) const SK_OVERRIDE { str->set("OverdrawXfermode"); }
commit-bot@chromium.orgcc277b72014-04-17 15:19:32 +0000121#endif
122};
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000123
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000124class SkOverdrawFilter : public SkDrawFilter {
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000125public:
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000126 SkOverdrawFilter() {
commit-bot@chromium.orgcc277b72014-04-17 15:19:32 +0000127 fXferMode = SkNEW(OverdrawXfermode);
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000128 }
129
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000130 virtual ~SkOverdrawFilter() {
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000131 delete fXferMode;
132 }
133
mtklein72c9faa2015-01-09 10:06:39 -0800134 bool filter(SkPaint* p, Type) SK_OVERRIDE {
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000135 p->setXfermode(fXferMode);
136 return true;
137 }
138
139protected:
140 SkXfermode* fXferMode;
141
142private:
143 typedef SkDrawFilter INHERITED;
144};
145
skia.committer@gmail.comf84ad8f2013-10-18 07:01:59 +0000146// SkTexOverrideFilter modifies every paint to use the specified
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000147// texture filtering mode
148class SkTexOverrideFilter : public SkDrawFilter {
149public:
150 SkTexOverrideFilter() : fFilterLevel(SkPaint::kNone_FilterLevel) {
151 }
152
153 void setFilterLevel(SkPaint::FilterLevel filterLevel) {
154 fFilterLevel = filterLevel;
155 }
156
mtklein72c9faa2015-01-09 10:06:39 -0800157 bool filter(SkPaint* p, Type) SK_OVERRIDE {
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000158 p->setFilterLevel(fFilterLevel);
159 return true;
160 }
161
162protected:
163 SkPaint::FilterLevel fFilterLevel;
164
165private:
166 typedef SkDrawFilter INHERITED;
167};
168
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000169class SkDebugClipVisitor : public SkCanvas::ClipVisitor {
170public:
171 SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
172
mtklein72c9faa2015-01-09 10:06:39 -0800173 void clipRect(const SkRect& r, SkRegion::Op, bool doAA) SK_OVERRIDE {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000174 SkPaint p;
175 p.setColor(SK_ColorRED);
176 p.setStyle(SkPaint::kStroke_Style);
177 p.setAntiAlias(doAA);
178 fCanvas->drawRect(r, p);
179 }
mtklein72c9faa2015-01-09 10:06:39 -0800180 void clipRRect(const SkRRect& rr, SkRegion::Op, bool doAA) SK_OVERRIDE {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000181 SkPaint p;
182 p.setColor(SK_ColorGREEN);
183 p.setStyle(SkPaint::kStroke_Style);
184 p.setAntiAlias(doAA);
185 fCanvas->drawRRect(rr, p);
186 }
mtklein72c9faa2015-01-09 10:06:39 -0800187 void clipPath(const SkPath& path, SkRegion::Op, bool doAA) SK_OVERRIDE {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000188 SkPaint p;
189 p.setColor(SK_ColorBLUE);
190 p.setStyle(SkPaint::kStroke_Style);
191 p.setAntiAlias(doAA);
192 fCanvas->drawPath(path, p);
193 }
194
195protected:
196 SkCanvas* fCanvas;
197
198private:
199 typedef SkCanvas::ClipVisitor INHERITED;
200};
201
202// set up the saveLayer commands so that the active ones
203// return true in their 'active' method
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000204void SkDebugCanvas::markActiveCommands(int index) {
205 fActiveLayers.rewind();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000206
207 for (int i = 0; i < fCommandVector.count(); ++i) {
208 fCommandVector[i]->setActive(false);
209 }
210
211 for (int i = 0; i < index; ++i) {
212 SkDrawCommand::Action result = fCommandVector[i]->action();
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000213 if (SkDrawCommand::kPushLayer_Action == result) {
214 fActiveLayers.push(fCommandVector[i]);
215 } else if (SkDrawCommand::kPopLayer_Action == result) {
216 fActiveLayers.pop();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000217 }
218 }
219
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000220 for (int i = 0; i < fActiveLayers.count(); ++i) {
221 fActiveLayers[i]->setActive(true);
222 }
223
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000224}
225
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000226void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000227 SkASSERT(!fCommandVector.isEmpty());
228 SkASSERT(index < fCommandVector.count());
kkinnunen26a00de2015-01-13 23:09:19 -0800229
230 int saveCount = canvas->save();
231
kkinnunen26e54002015-01-05 12:58:56 -0800232 SkRect windowRect = SkRect::MakeWH(SkIntToScalar(canvas->getBaseLayerSize().width()),
233 SkIntToScalar(canvas->getBaseLayerSize().height()));
chudy@google.com830b8792012-08-01 15:57:52 +0000234
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000235 bool pathOpsMode = getAllowSimplifyClip();
236 canvas->setAllowSimplifyClip(pathOpsMode);
kkinnunen26a00de2015-01-13 23:09:19 -0800237 canvas->clear(SK_ColorTRANSPARENT);
238 canvas->resetMatrix();
239 if (!windowRect.isEmpty()) {
240 canvas->clipRect(windowRect, SkRegion::kReplace_Op);
commit-bot@chromium.orga27622c2013-08-05 16:31:27 +0000241 }
kkinnunen26a00de2015-01-13 23:09:19 -0800242 this->applyUserTransform(canvas);
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000243
commit-bot@chromium.orga27622c2013-08-05 16:31:27 +0000244 // The setting of the draw filter has to go here (rather than in
245 // SkRasterWidget) due to the canvas restores this class performs.
246 // Since the draw filter is stored in the layer stack if we
247 // call setDrawFilter on anything but the root layer odd things happen.
248 if (fOverdrawViz) {
249 if (NULL == fOverdrawFilter) {
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000250 fOverdrawFilter = new SkOverdrawFilter;
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000251 }
commit-bot@chromium.orga27622c2013-08-05 16:31:27 +0000252
253 if (fOverdrawFilter != canvas->getDrawFilter()) {
254 canvas->setDrawFilter(fOverdrawFilter);
255 }
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000256 } else if (fOverrideTexFiltering) {
257 if (NULL == fTexOverrideFilter) {
258 fTexOverrideFilter = new SkTexOverrideFilter;
259 }
260
261 if (fTexOverrideFilter != canvas->getDrawFilter()) {
262 canvas->setDrawFilter(fTexOverrideFilter);
263 }
commit-bot@chromium.orga27622c2013-08-05 16:31:27 +0000264 } else {
265 canvas->setDrawFilter(NULL);
chudy@google.com830b8792012-08-01 15:57:52 +0000266 }
267
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000268 if (fMegaVizMode) {
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000269 this->markActiveCommands(index);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000270 }
271
kkinnunen26a00de2015-01-13 23:09:19 -0800272 for (int i = 0; i <= index; i++) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000273 if (i == index && fFilter) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700274 canvas->clear(0xAAFFFFFF);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000275 }
276
robertphillips@google.com67baba42013-01-02 20:20:31 +0000277 if (fCommandVector[i]->isVisible()) {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000278 if (fMegaVizMode && fCommandVector[i]->active()) {
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000279 // "active" commands execute their visualization behaviors:
280 // All active saveLayers get replaced with saves so all draws go to the
281 // visible canvas.
282 // All active culls draw their cull box
283 fCommandVector[i]->vizExecute(canvas);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000284 } else {
robertphillips70171682014-10-16 14:28:28 -0700285 fCommandVector[i]->setUserMatrix(fUserMatrix);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000286 fCommandVector[i]->execute(canvas);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000287 }
chudy@google.com902ebe52012-06-29 14:21:22 +0000288 }
289 }
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000290
291 if (fMegaVizMode) {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000292 canvas->save();
293 // nuke the CTM
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700294 canvas->resetMatrix();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000295 // turn off clipping
kkinnunen26e54002015-01-05 12:58:56 -0800296 if (!windowRect.isEmpty()) {
297 SkRect r = windowRect;
298 r.outset(SK_Scalar1, SK_Scalar1);
299 canvas->clipRect(r, SkRegion::kReplace_Op);
300 }
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000301 // visualize existing clips
302 SkDebugClipVisitor visitor(canvas);
303
304 canvas->replayClips(&visitor);
305
306 canvas->restore();
307 }
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000308 if (pathOpsMode) {
309 this->resetClipStackData();
310 const SkClipStack* clipStack = canvas->getClipStack();
311 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
312 const SkClipStack::Element* element;
313 SkPath devPath;
314 while ((element = iter.next())) {
315 SkClipStack::Element::Type type = element->getType();
316 SkPath operand;
317 if (type != SkClipStack::Element::kEmpty_Type) {
318 element->asPath(&operand);
319 }
320 SkRegion::Op elementOp = element->getOp();
321 this->addClipStackData(devPath, operand, elementOp);
322 if (elementOp == SkRegion::kReplace_Op) {
323 devPath = operand;
324 } else {
325 Op(devPath, operand, (SkPathOp) elementOp, &devPath);
326 }
327 }
328 this->lastClipStackData(devPath);
329 }
chudy@google.coma9e937c2012-08-03 17:32:05 +0000330 fMatrix = canvas->getTotalMatrix();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +0000331 if (!canvas->getClipDeviceBounds(&fClip)) {
332 fClip.setEmpty();
333 }
kkinnunen26a00de2015-01-13 23:09:19 -0800334
335 canvas->restoreToCount(saveCount);
chudy@google.com902ebe52012-06-29 14:21:22 +0000336}
337
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000338void SkDebugCanvas::deleteDrawCommandAt(int index) {
339 SkASSERT(index < fCommandVector.count());
340 delete fCommandVector[index];
341 fCommandVector.remove(index);
342}
343
chudy@google.com902ebe52012-06-29 14:21:22 +0000344SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000345 SkASSERT(index < fCommandVector.count());
346 return fCommandVector[index];
chudy@google.com902ebe52012-06-29 14:21:22 +0000347}
348
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000349void SkDebugCanvas::setDrawCommandAt(int index, SkDrawCommand* command) {
350 SkASSERT(index < fCommandVector.count());
351 delete fCommandVector[index];
352 fCommandVector[index] = command;
353}
354
fmalita8c89c522014-11-08 16:18:56 -0800355const SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) const {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000356 SkASSERT(index < fCommandVector.count());
357 return fCommandVector[index]->Info();
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000358}
chudy@google.com902ebe52012-06-29 14:21:22 +0000359
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000360bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000361 SkASSERT(index < fCommandVector.count());
362 return fCommandVector[index]->isVisible();
chudy@google.com902ebe52012-06-29 14:21:22 +0000363}
364
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000365const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000366 return fCommandVector;
chudy@google.com902ebe52012-06-29 14:21:22 +0000367}
368
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000369SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() {
370 return fCommandVector;
371}
372
skia.committer@gmail.comf84ad8f2013-10-18 07:01:59 +0000373void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkPaint::FilterLevel level) {
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000374 if (NULL == fTexOverrideFilter) {
375 fTexOverrideFilter = new SkTexOverrideFilter;
376 }
377
skia.committer@gmail.comf84ad8f2013-10-18 07:01:59 +0000378 fOverrideTexFiltering = overrideTexFiltering;
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000379 fTexOverrideFilter->setFilterLevel(level);
380}
381
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000382void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
383 this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
chudy@google.com902ebe52012-06-29 14:21:22 +0000384}
385
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000386void SkDebugCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
387 this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
chudy@google.com902ebe52012-06-29 14:21:22 +0000388}
389
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000390void SkDebugCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
391 this->addDrawCommand(new SkClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000392}
393
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000394void SkDebugCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
395 this->addDrawCommand(new SkClipRegionCommand(region, op));
chudy@google.com902ebe52012-06-29 14:21:22 +0000396}
397
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000398void SkDebugCanvas::didConcat(const SkMatrix& matrix) {
robertphillips2e602422015-02-11 13:07:12 -0800399 switch (matrix.getType()) {
400 case SkMatrix::kTranslate_Mask:
401 this->addDrawCommand(new SkTranslateCommand(matrix.getTranslateX(),
402 matrix.getTranslateY()));
403 break;
404 case SkMatrix::kScale_Mask:
405 this->addDrawCommand(new SkScaleCommand(matrix.getScaleX(),
406 matrix.getScaleY()));
407 break;
408 default:
409 this->addDrawCommand(new SkConcatCommand(matrix));
410 break;
411 }
412
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000413 this->INHERITED::didConcat(matrix);
chudy@google.com902ebe52012-06-29 14:21:22 +0000414}
415
reed41af9662015-01-05 07:49:08 -0800416void SkDebugCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar left,
417 SkScalar top, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000418 this->addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000419}
420
reed41af9662015-01-05 07:49:08 -0800421void SkDebugCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
422 const SkPaint* paint, DrawBitmapRectFlags flags) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000423 this->addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint, flags));
chudy@google.com902ebe52012-06-29 14:21:22 +0000424}
425
reed41af9662015-01-05 07:49:08 -0800426void SkDebugCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
427 const SkRect& dst, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000428 this->addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000429}
430
reed41af9662015-01-05 07:49:08 -0800431void SkDebugCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
432 const SkPaint* paint) {
433 SkDebugf("SkDebugCanvas::onDrawImage unimplemented\n");
434}
435
436void SkDebugCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
437 const SkPaint* paint) {
438 SkDebugf("SkDebugCanvas::onDrawImageRect unimplemented\n");
439}
440
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000441void SkDebugCanvas::beginCommentGroup(const char* description) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000442 this->addDrawCommand(new SkBeginCommentGroupCommand(description));
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000443}
444
445void SkDebugCanvas::addComment(const char* kywd, const char* value) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000446 this->addDrawCommand(new SkCommentCommand(kywd, value));
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000447}
448
449void SkDebugCanvas::endCommentGroup() {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000450 this->addDrawCommand(new SkEndCommentGroupCommand());
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000451}
452
reed41af9662015-01-05 07:49:08 -0800453void SkDebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000454 this->addDrawCommand(new SkDrawOvalCommand(oval, paint));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000455}
456
reed41af9662015-01-05 07:49:08 -0800457void SkDebugCanvas::onDrawPaint(const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000458 this->addDrawCommand(new SkDrawPaintCommand(paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000459}
460
reed41af9662015-01-05 07:49:08 -0800461void SkDebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000462 this->addDrawCommand(new SkDrawPathCommand(path, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000463}
464
mtkleinf0f14112014-12-12 08:46:25 -0800465void SkDebugCanvas::onDrawPicture(const SkPicture* picture,
466 const SkMatrix* matrix,
robertphillipsb3f319f2014-08-13 10:46:23 -0700467 const SkPaint* paint) {
468 this->addDrawCommand(new SkDrawPictureCommand(picture, matrix, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000469}
470
reed41af9662015-01-05 07:49:08 -0800471void SkDebugCanvas::onDrawPoints(PointMode mode, size_t count,
472 const SkPoint pts[], const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000473 this->addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000474}
475
reed@google.come0d9ce82014-04-23 04:00:17 +0000476void SkDebugCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
477 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000478 this->addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000479}
480
reed@google.come0d9ce82014-04-23 04:00:17 +0000481void SkDebugCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
482 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000483 this->addDrawCommand(
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000484 new SkDrawPosTextHCommand(text, byteLength, xpos, constY, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000485}
486
reed41af9662015-01-05 07:49:08 -0800487void SkDebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
chudy@google.com902ebe52012-06-29 14:21:22 +0000488 // NOTE(chudy): Messing up when renamed to DrawRect... Why?
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000489 addDrawCommand(new SkDrawRectCommand(rect, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000490}
491
reed41af9662015-01-05 07:49:08 -0800492void SkDebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000493 this->addDrawCommand(new SkDrawRRectCommand(rrect, paint));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000494}
495
commit-bot@chromium.orgab582732014-02-21 12:20:45 +0000496void SkDebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
497 const SkPaint& paint) {
commit-bot@chromium.org3d305202014-02-24 17:28:55 +0000498 this->addDrawCommand(new SkDrawDRRectCommand(outer, inner, paint));
commit-bot@chromium.orgab582732014-02-21 12:20:45 +0000499}
500
reed41af9662015-01-05 07:49:08 -0800501void SkDebugCanvas::onDrawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000502 this->addDrawCommand(new SkDrawSpriteCommand(bitmap, left, top, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000503}
504
reed@google.come0d9ce82014-04-23 04:00:17 +0000505void SkDebugCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
506 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000507 this->addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000508}
509
reed@google.come0d9ce82014-04-23 04:00:17 +0000510void SkDebugCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
511 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000512 this->addDrawCommand(
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000513 new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000514}
515
fmalitab7425172014-08-26 07:56:44 -0700516void SkDebugCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
517 const SkPaint& paint) {
518 this->addDrawCommand(new SkDrawTextBlobCommand(blob, x, y, paint));
519}
520
reed41af9662015-01-05 07:49:08 -0800521void SkDebugCanvas::onDrawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
522 const SkPoint texs[], const SkColor colors[],
523 SkXfermode*, const uint16_t indices[], int indexCount,
524 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000525 this->addDrawCommand(new SkDrawVerticesCommand(vmode, vertexCount, vertices,
526 texs, colors, NULL, indices, indexCount, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000527}
528
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000529void SkDebugCanvas::willRestore() {
530 this->addDrawCommand(new SkRestoreCommand());
531 this->INHERITED::willRestore();
chudy@google.com902ebe52012-06-29 14:21:22 +0000532}
533
Florin Malita5f6102d2014-06-30 10:13:28 -0400534void SkDebugCanvas::willSave() {
535 this->addDrawCommand(new SkSaveCommand());
536 this->INHERITED::willSave();
chudy@google.com902ebe52012-06-29 14:21:22 +0000537}
538
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000539SkCanvas::SaveLayerStrategy SkDebugCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
540 SaveFlags flags) {
541 this->addDrawCommand(new SkSaveLayerCommand(bounds, paint, flags));
542 this->INHERITED::willSaveLayer(bounds, paint, flags);
543 // No need for a full layer.
544 return kNoLayer_SaveLayerStrategy;
chudy@google.com902ebe52012-06-29 14:21:22 +0000545}
546
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000547void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000548 this->addDrawCommand(new SkSetMatrixCommand(matrix));
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000549 this->INHERITED::didSetMatrix(matrix);
chudy@google.com902ebe52012-06-29 14:21:22 +0000550}
551
chudy@google.com902ebe52012-06-29 14:21:22 +0000552void SkDebugCanvas::toggleCommand(int index, bool toggle) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000553 SkASSERT(index < fCommandVector.count());
554 fCommandVector[index]->setVisible(toggle);
chudy@google.com902ebe52012-06-29 14:21:22 +0000555}
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000556
557static const char* gFillTypeStrs[] = {
558 "kWinding_FillType",
559 "kEvenOdd_FillType",
560 "kInverseWinding_FillType",
561 "kInverseEvenOdd_FillType"
562};
563
564static const char* gOpStrs[] = {
565 "kDifference_PathOp",
566 "kIntersect_PathOp",
567 "kUnion_PathOp",
568 "kXor_PathOp",
569 "kReverseDifference_PathOp",
570};
571
572static const char kHTML4SpaceIndent[] = "&nbsp;&nbsp;&nbsp;&nbsp;";
573
574void SkDebugCanvas::outputScalar(SkScalar num) {
575 if (num == (int) num) {
576 fClipStackData.appendf("%d", (int) num);
577 } else {
578 SkString str;
579 str.printf("%1.9g", num);
580 int width = (int) str.size();
581 const char* cStr = str.c_str();
582 while (cStr[width - 1] == '0') {
583 --width;
584 }
585 str.resize(width);
586 fClipStackData.appendf("%sf", str.c_str());
587 }
588}
589
590void SkDebugCanvas::outputPointsCommon(const SkPoint* pts, int count) {
591 for (int index = 0; index < count; ++index) {
592 this->outputScalar(pts[index].fX);
593 fClipStackData.appendf(", ");
594 this->outputScalar(pts[index].fY);
595 if (index + 1 < count) {
596 fClipStackData.appendf(", ");
597 }
598 }
599}
600
601void SkDebugCanvas::outputPoints(const SkPoint* pts, int count) {
602 this->outputPointsCommon(pts, count);
603 fClipStackData.appendf(");<br>");
604}
605
606void SkDebugCanvas::outputConicPoints(const SkPoint* pts, SkScalar weight) {
607 this->outputPointsCommon(pts, 2);
608 fClipStackData.appendf(", ");
609 this->outputScalar(weight);
610 fClipStackData.appendf(");<br>");
611}
612
613void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) {
614 SkPath::RawIter iter(path);
615 SkPath::FillType fillType = path.getFillType();
616 fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName);
617 fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceIndent, pathName,
618 gFillTypeStrs[fillType]);
619 iter.setPath(path);
620 uint8_t verb;
621 SkPoint pts[4];
622 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
623 switch (verb) {
624 case SkPath::kMove_Verb:
625 fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathName);
626 this->outputPoints(&pts[0], 1);
627 continue;
628 case SkPath::kLine_Verb:
629 fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathName);
630 this->outputPoints(&pts[1], 1);
631 break;
632 case SkPath::kQuad_Verb:
633 fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathName);
634 this->outputPoints(&pts[1], 2);
635 break;
636 case SkPath::kConic_Verb:
637 fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathName);
638 this->outputConicPoints(&pts[1], iter.conicWeight());
639 break;
640 case SkPath::kCubic_Verb:
641 fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathName);
642 this->outputPoints(&pts[1], 3);
643 break;
644 case SkPath::kClose_Verb:
645 fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, pathName);
646 break;
647 default:
648 SkDEBUGFAIL("bad verb");
649 return;
650 }
651 }
652}
653
654void SkDebugCanvas::addClipStackData(const SkPath& devPath, const SkPath& operand,
655 SkRegion::Op elementOp) {
656 if (elementOp == SkRegion::kReplace_Op) {
657 if (!lastClipStackData(devPath)) {
658 fSaveDevPath = operand;
659 }
660 fCalledAddStackData = false;
661 } else {
662 fClipStackData.appendf("<br>static void test(skiatest::Reporter* reporter,"
663 " const char* filename) {<br>");
664 addPathData(fCalledAddStackData ? devPath : fSaveDevPath, "path");
665 addPathData(operand, "pathB");
666 fClipStackData.appendf("%stestPathOp(reporter, path, pathB, %s, filename);<br>",
667 kHTML4SpaceIndent, gOpStrs[elementOp]);
668 fClipStackData.appendf("}<br>");
669 fCalledAddStackData = true;
670 }
671}
672
673bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) {
674 if (fCalledAddStackData) {
675 fClipStackData.appendf("<br>");
676 addPathData(devPath, "pathOut");
677 return true;
678 }
679 return false;
680}