blob: 6251c1b7a19a132432bf03059f1805b781e3272a [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
bungemand3ebb482015-08-05 13:57:49 -07008#include "SkClipStack.h"
robertphillips@google.comf4741c12013-02-06 20:13:54 +00009#include "SkColorPriv.h"
chudy@google.com902ebe52012-06-29 14:21:22 +000010#include "SkDebugCanvas.h"
11#include "SkDrawCommand.h"
robertphillips@google.com6dec8fc2012-11-21 17:11:02 +000012#include "SkDevice.h"
fmalita65cdb572015-03-26 07:24:48 -070013#include "SkPaintFilterCanvas.h"
robertphillips@google.comf4741c12013-02-06 20:13:54 +000014#include "SkXfermode.h"
chudy@google.com902ebe52012-06-29 14:21:22 +000015
fmalita65cdb572015-03-26 07:24:48 -070016namespace {
17
18class OverdrawXfermode : public SkXfermode {
19public:
20 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const override {
21 // This table encodes the color progression of the overdraw visualization
22 static const SkPMColor gTable[] = {
23 SkPackARGB32(0x00, 0x00, 0x00, 0x00),
24 SkPackARGB32(0xFF, 128, 158, 255),
25 SkPackARGB32(0xFF, 170, 185, 212),
26 SkPackARGB32(0xFF, 213, 195, 170),
27 SkPackARGB32(0xFF, 255, 192, 127),
28 SkPackARGB32(0xFF, 255, 185, 85),
29 SkPackARGB32(0xFF, 255, 165, 42),
30 SkPackARGB32(0xFF, 255, 135, 0),
31 SkPackARGB32(0xFF, 255, 95, 0),
32 SkPackARGB32(0xFF, 255, 50, 0),
33 SkPackARGB32(0xFF, 255, 0, 0)
34 };
35
36
37 int idx;
38 if (SkColorGetR(dst) < 64) { // 0
39 idx = 0;
40 } else if (SkColorGetG(dst) < 25) { // 10
41 idx = 9; // cap at 9 for upcoming increment
42 } else if ((SkColorGetB(dst)+21)/42 > 0) { // 1-6
43 idx = 7 - (SkColorGetB(dst)+21)/42;
44 } else { // 7-9
45 idx = 10 - (SkColorGetG(dst)+22)/45;
46 }
47 ++idx;
48 SkASSERT(idx < (int)SK_ARRAY_COUNT(gTable));
49
50 return gTable[idx];
51 }
52
53 Factory getFactory() const override { return NULL; }
54#ifndef SK_IGNORE_TO_STRING
tfarina283b5872015-04-25 12:59:44 -070055 void toString(SkString* str) const override { str->set("OverdrawXfermode"); }
fmalita65cdb572015-03-26 07:24:48 -070056#endif
57};
58
59class DebugPaintFilterCanvas : public SkPaintFilterCanvas {
60public:
61 DebugPaintFilterCanvas(int width, int height, bool overdrawViz, bool overrideFilterQuality,
62 SkFilterQuality quality)
63 : INHERITED(width, height)
64 , fOverdrawXfermode(overdrawViz ? SkNEW(OverdrawXfermode) : NULL)
65 , fOverrideFilterQuality(overrideFilterQuality)
66 , fFilterQuality(quality) { }
67
68protected:
69 void onFilterPaint(SkPaint* paint, Type) const override {
70 if (NULL != fOverdrawXfermode.get()) {
71 paint->setAntiAlias(false);
72 paint->setXfermode(fOverdrawXfermode.get());
73 }
74
75 if (fOverrideFilterQuality) {
76 paint->setFilterQuality(fFilterQuality);
77 }
78 }
79
mtkleinf0599002015-07-13 06:18:39 -070080 void onDrawPicture(const SkPicture* picture,
81 const SkMatrix* matrix,
82 const SkPaint* paint) override {
fmalita65cdb572015-03-26 07:24:48 -070083 // We need to replay the picture onto this canvas in order to filter its internal paints.
84 this->SkCanvas::onDrawPicture(picture, matrix, paint);
85 }
86
87private:
88 SkAutoTUnref<SkXfermode> fOverdrawXfermode;
89
90 bool fOverrideFilterQuality;
91 SkFilterQuality fFilterQuality;
92
93 typedef SkPaintFilterCanvas INHERITED;
94};
95
96}
97
kkinnunen26e54002015-01-05 12:58:56 -080098SkDebugCanvas::SkDebugCanvas(int width, int height)
99 : INHERITED(width, height)
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000100 , fPicture(NULL)
commit-bot@chromium.org1735d662013-12-04 13:42:46 +0000101 , fFilter(false)
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000102 , fMegaVizMode(false)
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000103 , fOverdrawViz(false)
fmalita65cdb572015-03-26 07:24:48 -0700104 , fOverrideFilterQuality(false)
105 , fFilterQuality(kNone_SkFilterQuality) {
bungeman@google.come8cc6e82013-01-17 16:30:56 +0000106 fUserMatrix.reset();
robertphillips@google.com8b157172013-11-07 22:20:31 +0000107
108 // SkPicturePlayback uses the base-class' quickReject calls to cull clipped
109 // operations. This can lead to problems in the debugger which expects all
110 // the operations in the captured skp to appear in the debug canvas. To
111 // circumvent this we create a wide open clip here (an empty clip rect
112 // is not sufficient).
113 // Internally, the SkRect passed to clipRect is converted to an SkIRect and
114 // rounded out. The following code creates a nearly maximal rect that will
115 // not get collapsed by the coming conversions (Due to precision loss the
116 // inset has to be surprisingly large).
117 SkIRect largeIRect = SkIRect::MakeLargest();
118 largeIRect.inset(1024, 1024);
robertphillips@google.com6c1e49a2013-11-10 15:08:45 +0000119 SkRect large = SkRect::Make(largeIRect);
robertphillips@google.com8b157172013-11-07 22:20:31 +0000120#ifdef SK_DEBUG
reedb07a94f2014-11-19 05:03:18 -0800121 SkASSERT(!large.roundOut().isEmpty());
robertphillips@google.com8b157172013-11-07 22:20:31 +0000122#endif
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000123 // call the base class' version to avoid adding a draw command
124 this->INHERITED::onClipRect(large, SkRegion::kReplace_Op, kHard_ClipEdgeStyle);
chudy@google.com902ebe52012-06-29 14:21:22 +0000125}
126
chudy@google.com9cda6f72012-08-07 15:08:33 +0000127SkDebugCanvas::~SkDebugCanvas() {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000128 fCommandVector.deleteAll();
chudy@google.com9cda6f72012-08-07 15:08:33 +0000129}
chudy@google.com902ebe52012-06-29 14:21:22 +0000130
131void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000132 fCommandVector.push(command);
chudy@google.com902ebe52012-06-29 14:21:22 +0000133}
134
135void SkDebugCanvas::draw(SkCanvas* canvas) {
commit-bot@chromium.org1735d662013-12-04 13:42:46 +0000136 if (!fCommandVector.isEmpty()) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000137 this->drawTo(canvas, fCommandVector.count() - 1);
chudy@google.com902ebe52012-06-29 14:21:22 +0000138 }
139}
140
chudy@google.com830b8792012-08-01 15:57:52 +0000141void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
bungeman@google.come8cc6e82013-01-17 16:30:56 +0000142 canvas->concat(fUserMatrix);
chudy@google.com830b8792012-08-01 15:57:52 +0000143}
144
145int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000146 SkBitmap bitmap;
reed@google.com9ebcac52014-01-24 18:53:42 +0000147 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
chudy@google.com902ebe52012-06-29 14:21:22 +0000148
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000149 SkCanvas canvas(bitmap);
robertphillips@google.com94acc702012-09-06 18:43:21 +0000150 canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700151 this->applyUserTransform(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000152
153 int layer = 0;
chudy@google.com751961d2012-07-31 20:07:42 +0000154 SkColor prev = bitmap.getColor(0,0);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000155 for (int i = 0; i < index; i++) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000156 if (fCommandVector[i]->isVisible()) {
robertphillips70171682014-10-16 14:28:28 -0700157 fCommandVector[i]->setUserMatrix(fUserMatrix);
robertphillips@google.com67baba42013-01-02 20:20:31 +0000158 fCommandVector[i]->execute(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000159 }
160 if (prev != bitmap.getColor(0,0)) {
161 layer = i;
162 }
163 prev = bitmap.getColor(0,0);
164 }
165 return layer;
166}
167
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000168class SkDebugClipVisitor : public SkCanvas::ClipVisitor {
169public:
170 SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {}
171
mtklein36352bf2015-03-25 18:17:31 -0700172 void clipRect(const SkRect& r, SkRegion::Op, bool doAA) override {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000173 SkPaint p;
174 p.setColor(SK_ColorRED);
175 p.setStyle(SkPaint::kStroke_Style);
176 p.setAntiAlias(doAA);
177 fCanvas->drawRect(r, p);
178 }
mtklein36352bf2015-03-25 18:17:31 -0700179 void clipRRect(const SkRRect& rr, SkRegion::Op, bool doAA) override {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000180 SkPaint p;
181 p.setColor(SK_ColorGREEN);
182 p.setStyle(SkPaint::kStroke_Style);
183 p.setAntiAlias(doAA);
184 fCanvas->drawRRect(rr, p);
185 }
mtklein36352bf2015-03-25 18:17:31 -0700186 void clipPath(const SkPath& path, SkRegion::Op, bool doAA) override {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000187 SkPaint p;
188 p.setColor(SK_ColorBLUE);
189 p.setStyle(SkPaint::kStroke_Style);
190 p.setAntiAlias(doAA);
191 fCanvas->drawPath(path, p);
192 }
193
194protected:
195 SkCanvas* fCanvas;
196
197private:
198 typedef SkCanvas::ClipVisitor INHERITED;
199};
200
201// set up the saveLayer commands so that the active ones
202// return true in their 'active' method
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000203void SkDebugCanvas::markActiveCommands(int index) {
204 fActiveLayers.rewind();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000205
206 for (int i = 0; i < fCommandVector.count(); ++i) {
207 fCommandVector[i]->setActive(false);
208 }
209
210 for (int i = 0; i < index; ++i) {
211 SkDrawCommand::Action result = fCommandVector[i]->action();
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000212 if (SkDrawCommand::kPushLayer_Action == result) {
213 fActiveLayers.push(fCommandVector[i]);
214 } else if (SkDrawCommand::kPopLayer_Action == result) {
215 fActiveLayers.pop();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000216 }
217 }
218
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000219 for (int i = 0; i < fActiveLayers.count(); ++i) {
220 fActiveLayers[i]->setActive(true);
221 }
222
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000223}
224
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000225void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000226 SkASSERT(!fCommandVector.isEmpty());
227 SkASSERT(index < fCommandVector.count());
kkinnunen26a00de2015-01-13 23:09:19 -0800228
229 int saveCount = canvas->save();
230
kkinnunen26e54002015-01-05 12:58:56 -0800231 SkRect windowRect = SkRect::MakeWH(SkIntToScalar(canvas->getBaseLayerSize().width()),
232 SkIntToScalar(canvas->getBaseLayerSize().height()));
chudy@google.com830b8792012-08-01 15:57:52 +0000233
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000234 bool pathOpsMode = getAllowSimplifyClip();
235 canvas->setAllowSimplifyClip(pathOpsMode);
kkinnunen26a00de2015-01-13 23:09:19 -0800236 canvas->clear(SK_ColorTRANSPARENT);
237 canvas->resetMatrix();
238 if (!windowRect.isEmpty()) {
239 canvas->clipRect(windowRect, SkRegion::kReplace_Op);
commit-bot@chromium.orga27622c2013-08-05 16:31:27 +0000240 }
kkinnunen26a00de2015-01-13 23:09:19 -0800241 this->applyUserTransform(canvas);
robertphillips@google.comf4741c12013-02-06 20:13:54 +0000242
fmalita65cdb572015-03-26 07:24:48 -0700243 if (fPaintFilterCanvas) {
244 fPaintFilterCanvas->addCanvas(canvas);
245 canvas = fPaintFilterCanvas.get();
chudy@google.com830b8792012-08-01 15:57:52 +0000246 }
247
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000248 if (fMegaVizMode) {
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000249 this->markActiveCommands(index);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000250 }
251
kkinnunen26a00de2015-01-13 23:09:19 -0800252 for (int i = 0; i <= index; i++) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000253 if (i == index && fFilter) {
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700254 canvas->clear(0xAAFFFFFF);
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000255 }
256
robertphillips@google.com67baba42013-01-02 20:20:31 +0000257 if (fCommandVector[i]->isVisible()) {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000258 if (fMegaVizMode && fCommandVector[i]->active()) {
commit-bot@chromium.org1643b2c2014-03-03 23:25:41 +0000259 // "active" commands execute their visualization behaviors:
260 // All active saveLayers get replaced with saves so all draws go to the
261 // visible canvas.
262 // All active culls draw their cull box
263 fCommandVector[i]->vizExecute(canvas);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000264 } else {
robertphillips70171682014-10-16 14:28:28 -0700265 fCommandVector[i]->setUserMatrix(fUserMatrix);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000266 fCommandVector[i]->execute(canvas);
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000267 }
chudy@google.com902ebe52012-06-29 14:21:22 +0000268 }
269 }
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000270
271 if (fMegaVizMode) {
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000272 canvas->save();
273 // nuke the CTM
robertphillipsa8d7f0b2014-08-29 08:03:56 -0700274 canvas->resetMatrix();
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000275 // turn off clipping
kkinnunen26e54002015-01-05 12:58:56 -0800276 if (!windowRect.isEmpty()) {
277 SkRect r = windowRect;
278 r.outset(SK_Scalar1, SK_Scalar1);
279 canvas->clipRect(r, SkRegion::kReplace_Op);
280 }
commit-bot@chromium.org768ac852014-03-03 16:32:17 +0000281 // visualize existing clips
282 SkDebugClipVisitor visitor(canvas);
283
284 canvas->replayClips(&visitor);
285
286 canvas->restore();
287 }
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000288 if (pathOpsMode) {
289 this->resetClipStackData();
290 const SkClipStack* clipStack = canvas->getClipStack();
291 SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
292 const SkClipStack::Element* element;
293 SkPath devPath;
294 while ((element = iter.next())) {
295 SkClipStack::Element::Type type = element->getType();
296 SkPath operand;
297 if (type != SkClipStack::Element::kEmpty_Type) {
298 element->asPath(&operand);
299 }
300 SkRegion::Op elementOp = element->getOp();
301 this->addClipStackData(devPath, operand, elementOp);
302 if (elementOp == SkRegion::kReplace_Op) {
303 devPath = operand;
304 } else {
305 Op(devPath, operand, (SkPathOp) elementOp, &devPath);
306 }
307 }
308 this->lastClipStackData(devPath);
309 }
chudy@google.coma9e937c2012-08-03 17:32:05 +0000310 fMatrix = canvas->getTotalMatrix();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +0000311 if (!canvas->getClipDeviceBounds(&fClip)) {
312 fClip.setEmpty();
313 }
kkinnunen26a00de2015-01-13 23:09:19 -0800314
315 canvas->restoreToCount(saveCount);
fmalita65cdb572015-03-26 07:24:48 -0700316
317 if (fPaintFilterCanvas) {
318 fPaintFilterCanvas->removeAll();
319 }
chudy@google.com902ebe52012-06-29 14:21:22 +0000320}
321
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000322void SkDebugCanvas::deleteDrawCommandAt(int index) {
323 SkASSERT(index < fCommandVector.count());
324 delete fCommandVector[index];
325 fCommandVector.remove(index);
326}
327
chudy@google.com902ebe52012-06-29 14:21:22 +0000328SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000329 SkASSERT(index < fCommandVector.count());
330 return fCommandVector[index];
chudy@google.com902ebe52012-06-29 14:21:22 +0000331}
332
robertphillips@google.com50c84da2013-04-01 18:18:49 +0000333void SkDebugCanvas::setDrawCommandAt(int index, SkDrawCommand* command) {
334 SkASSERT(index < fCommandVector.count());
335 delete fCommandVector[index];
336 fCommandVector[index] = command;
337}
338
fmalita8c89c522014-11-08 16:18:56 -0800339const SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) const {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000340 SkASSERT(index < fCommandVector.count());
341 return fCommandVector[index]->Info();
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000342}
chudy@google.com902ebe52012-06-29 14:21:22 +0000343
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000344bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000345 SkASSERT(index < fCommandVector.count());
346 return fCommandVector[index]->isVisible();
chudy@google.com902ebe52012-06-29 14:21:22 +0000347}
348
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000349const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000350 return fCommandVector;
chudy@google.com902ebe52012-06-29 14:21:22 +0000351}
352
robertphillips@google.comfebc0ec2013-03-11 22:53:11 +0000353SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() {
354 return fCommandVector;
355}
356
fmalita65cdb572015-03-26 07:24:48 -0700357void SkDebugCanvas::updatePaintFilterCanvas() {
358 if (!fOverdrawViz && !fOverrideFilterQuality) {
359 fPaintFilterCanvas.reset(NULL);
360 return;
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000361 }
362
fmalita65cdb572015-03-26 07:24:48 -0700363 const SkImageInfo info = this->imageInfo();
364 fPaintFilterCanvas.reset(SkNEW_ARGS(DebugPaintFilterCanvas, (info.width(),
365 info.height(),
366 fOverdrawViz,
367 fOverrideFilterQuality,
368 fFilterQuality)));
369}
370
371void SkDebugCanvas::setOverdrawViz(bool overdrawViz) {
372 if (fOverdrawViz == overdrawViz) {
373 return;
374 }
375
376 fOverdrawViz = overdrawViz;
377 this->updatePaintFilterCanvas();
378}
379
380void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkFilterQuality quality) {
381 if (fOverrideFilterQuality == overrideTexFiltering && fFilterQuality == quality) {
382 return;
383 }
384
385 fOverrideFilterQuality = overrideTexFiltering;
386 fFilterQuality = quality;
387 this->updatePaintFilterCanvas();
robertphillips@google.com32bbcf82013-10-17 17:56:10 +0000388}
389
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000390void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
391 this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle));
chudy@google.com902ebe52012-06-29 14:21:22 +0000392}
393
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000394void SkDebugCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
395 this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle));
chudy@google.com902ebe52012-06-29 14:21:22 +0000396}
397
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000398void SkDebugCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
399 this->addDrawCommand(new SkClipRRectCommand(rrect, op, kSoft_ClipEdgeStyle == edgeStyle));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000400}
401
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000402void SkDebugCanvas::onClipRegion(const SkRegion& region, SkRegion::Op op) {
403 this->addDrawCommand(new SkClipRegionCommand(region, op));
chudy@google.com902ebe52012-06-29 14:21:22 +0000404}
405
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000406void SkDebugCanvas::didConcat(const SkMatrix& matrix) {
robertphillips9bafc302015-02-13 11:13:00 -0800407 this->addDrawCommand(new SkConcatCommand(matrix));
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000408 this->INHERITED::didConcat(matrix);
chudy@google.com902ebe52012-06-29 14:21:22 +0000409}
410
reed41af9662015-01-05 07:49:08 -0800411void SkDebugCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar left,
412 SkScalar top, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000413 this->addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000414}
415
reed41af9662015-01-05 07:49:08 -0800416void SkDebugCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700417 const SkPaint* paint, SrcRectConstraint constraint) {
reeda5517e22015-07-14 10:54:12 -0700418 this->addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint,
419 (SrcRectConstraint)constraint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000420}
421
reed41af9662015-01-05 07:49:08 -0800422void SkDebugCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
423 const SkRect& dst, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000424 this->addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000425}
426
reed41af9662015-01-05 07:49:08 -0800427void SkDebugCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
428 const SkPaint* paint) {
fmalita651c9202015-07-22 10:23:01 -0700429 this->addDrawCommand(new SkDrawImageCommand(image, left, top, paint));
reed41af9662015-01-05 07:49:08 -0800430}
431
432void SkDebugCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed562fe472015-07-28 07:35:14 -0700433 const SkPaint* paint, SrcRectConstraint constraint) {
fmalita651c9202015-07-22 10:23:01 -0700434 this->addDrawCommand(new SkDrawImageRectCommand(image, src, dst, paint, constraint));
reed41af9662015-01-05 07:49:08 -0800435}
436
reed41af9662015-01-05 07:49:08 -0800437void SkDebugCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000438 this->addDrawCommand(new SkDrawOvalCommand(oval, paint));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000439}
440
reed41af9662015-01-05 07:49:08 -0800441void SkDebugCanvas::onDrawPaint(const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000442 this->addDrawCommand(new SkDrawPaintCommand(paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000443}
444
reed41af9662015-01-05 07:49:08 -0800445void SkDebugCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000446 this->addDrawCommand(new SkDrawPathCommand(path, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000447}
448
mtkleinf0f14112014-12-12 08:46:25 -0800449void SkDebugCanvas::onDrawPicture(const SkPicture* picture,
450 const SkMatrix* matrix,
robertphillipsb3f319f2014-08-13 10:46:23 -0700451 const SkPaint* paint) {
fmalita160ebb22015-04-01 20:58:37 -0700452 this->addDrawCommand(new SkBeginDrawPictureCommand(picture, matrix, paint));
453 this->INHERITED::onDrawPicture(picture, matrix, paint);
454 this->addDrawCommand(new SkEndDrawPictureCommand(SkToBool(matrix) || SkToBool(paint)));
chudy@google.com902ebe52012-06-29 14:21:22 +0000455}
456
reed41af9662015-01-05 07:49:08 -0800457void SkDebugCanvas::onDrawPoints(PointMode mode, size_t count,
458 const SkPoint pts[], const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000459 this->addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000460}
461
reed@google.come0d9ce82014-04-23 04:00:17 +0000462void SkDebugCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
463 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000464 this->addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000465}
466
reed@google.come0d9ce82014-04-23 04:00:17 +0000467void SkDebugCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
468 SkScalar constY, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000469 this->addDrawCommand(
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000470 new SkDrawPosTextHCommand(text, byteLength, xpos, constY, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000471}
472
reed41af9662015-01-05 07:49:08 -0800473void SkDebugCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
chudy@google.com902ebe52012-06-29 14:21:22 +0000474 // NOTE(chudy): Messing up when renamed to DrawRect... Why?
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000475 addDrawCommand(new SkDrawRectCommand(rect, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000476}
477
reed41af9662015-01-05 07:49:08 -0800478void SkDebugCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000479 this->addDrawCommand(new SkDrawRRectCommand(rrect, paint));
robertphillips@google.com67baba42013-01-02 20:20:31 +0000480}
481
commit-bot@chromium.orgab582732014-02-21 12:20:45 +0000482void SkDebugCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
483 const SkPaint& paint) {
commit-bot@chromium.org3d305202014-02-24 17:28:55 +0000484 this->addDrawCommand(new SkDrawDRRectCommand(outer, inner, paint));
commit-bot@chromium.orgab582732014-02-21 12:20:45 +0000485}
486
reed41af9662015-01-05 07:49:08 -0800487void SkDebugCanvas::onDrawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000488 this->addDrawCommand(new SkDrawSpriteCommand(bitmap, left, top, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000489}
490
reed@google.come0d9ce82014-04-23 04:00:17 +0000491void SkDebugCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
492 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000493 this->addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000494}
495
reed@google.come0d9ce82014-04-23 04:00:17 +0000496void SkDebugCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
497 const SkMatrix* matrix, const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000498 this->addDrawCommand(
commit-bot@chromium.org7a115912013-06-18 20:20:55 +0000499 new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000500}
501
fmalitab7425172014-08-26 07:56:44 -0700502void SkDebugCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
503 const SkPaint& paint) {
504 this->addDrawCommand(new SkDrawTextBlobCommand(blob, x, y, paint));
505}
506
robertphillips9bafc302015-02-13 11:13:00 -0800507void SkDebugCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
508 const SkPoint texCoords[4], SkXfermode* xmode,
509 const SkPaint& paint) {
510 this->addDrawCommand(new SkDrawPatchCommand(cubics, colors, texCoords, xmode, paint));
511}
512
reed41af9662015-01-05 07:49:08 -0800513void SkDebugCanvas::onDrawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
514 const SkPoint texs[], const SkColor colors[],
515 SkXfermode*, const uint16_t indices[], int indexCount,
516 const SkPaint& paint) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000517 this->addDrawCommand(new SkDrawVerticesCommand(vmode, vertexCount, vertices,
518 texs, colors, NULL, indices, indexCount, paint));
chudy@google.com902ebe52012-06-29 14:21:22 +0000519}
520
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000521void SkDebugCanvas::willRestore() {
522 this->addDrawCommand(new SkRestoreCommand());
523 this->INHERITED::willRestore();
chudy@google.com902ebe52012-06-29 14:21:22 +0000524}
525
Florin Malita5f6102d2014-06-30 10:13:28 -0400526void SkDebugCanvas::willSave() {
527 this->addDrawCommand(new SkSaveCommand());
528 this->INHERITED::willSave();
chudy@google.com902ebe52012-06-29 14:21:22 +0000529}
530
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000531SkCanvas::SaveLayerStrategy SkDebugCanvas::willSaveLayer(const SkRect* bounds, const SkPaint* paint,
532 SaveFlags flags) {
533 this->addDrawCommand(new SkSaveLayerCommand(bounds, paint, flags));
534 this->INHERITED::willSaveLayer(bounds, paint, flags);
535 // No need for a full layer.
536 return kNoLayer_SaveLayerStrategy;
chudy@google.com902ebe52012-06-29 14:21:22 +0000537}
538
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000539void SkDebugCanvas::didSetMatrix(const SkMatrix& matrix) {
commit-bot@chromium.org57f74e02014-03-25 23:31:33 +0000540 this->addDrawCommand(new SkSetMatrixCommand(matrix));
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000541 this->INHERITED::didSetMatrix(matrix);
chudy@google.com902ebe52012-06-29 14:21:22 +0000542}
543
chudy@google.com902ebe52012-06-29 14:21:22 +0000544void SkDebugCanvas::toggleCommand(int index, bool toggle) {
robertphillips@google.com67baba42013-01-02 20:20:31 +0000545 SkASSERT(index < fCommandVector.count());
546 fCommandVector[index]->setVisible(toggle);
chudy@google.com902ebe52012-06-29 14:21:22 +0000547}
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000548
549static const char* gFillTypeStrs[] = {
550 "kWinding_FillType",
551 "kEvenOdd_FillType",
552 "kInverseWinding_FillType",
553 "kInverseEvenOdd_FillType"
554};
555
556static const char* gOpStrs[] = {
scroggo5965b732015-04-07 06:53:21 -0700557 "kDifference_PathOp",
558 "kIntersect_PathOp",
559 "kUnion_PathOp",
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000560 "kXor_PathOp",
scroggo5965b732015-04-07 06:53:21 -0700561 "kReverseDifference_PathOp",
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +0000562};
563
564static const char kHTML4SpaceIndent[] = "&nbsp;&nbsp;&nbsp;&nbsp;";
565
566void SkDebugCanvas::outputScalar(SkScalar num) {
567 if (num == (int) num) {
568 fClipStackData.appendf("%d", (int) num);
569 } else {
570 SkString str;
571 str.printf("%1.9g", num);
572 int width = (int) str.size();
573 const char* cStr = str.c_str();
574 while (cStr[width - 1] == '0') {
575 --width;
576 }
577 str.resize(width);
578 fClipStackData.appendf("%sf", str.c_str());
579 }
580}
581
582void SkDebugCanvas::outputPointsCommon(const SkPoint* pts, int count) {
583 for (int index = 0; index < count; ++index) {
584 this->outputScalar(pts[index].fX);
585 fClipStackData.appendf(", ");
586 this->outputScalar(pts[index].fY);
587 if (index + 1 < count) {
588 fClipStackData.appendf(", ");
589 }
590 }
591}
592
593void SkDebugCanvas::outputPoints(const SkPoint* pts, int count) {
594 this->outputPointsCommon(pts, count);
595 fClipStackData.appendf(");<br>");
596}
597
598void SkDebugCanvas::outputConicPoints(const SkPoint* pts, SkScalar weight) {
599 this->outputPointsCommon(pts, 2);
600 fClipStackData.appendf(", ");
601 this->outputScalar(weight);
602 fClipStackData.appendf(");<br>");
603}
604
605void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) {
606 SkPath::RawIter iter(path);
607 SkPath::FillType fillType = path.getFillType();
608 fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName);
609 fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceIndent, pathName,
610 gFillTypeStrs[fillType]);
611 iter.setPath(path);
612 uint8_t verb;
613 SkPoint pts[4];
614 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
615 switch (verb) {
616 case SkPath::kMove_Verb:
617 fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathName);
618 this->outputPoints(&pts[0], 1);
619 continue;
620 case SkPath::kLine_Verb:
621 fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathName);
622 this->outputPoints(&pts[1], 1);
623 break;
624 case SkPath::kQuad_Verb:
625 fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathName);
626 this->outputPoints(&pts[1], 2);
627 break;
628 case SkPath::kConic_Verb:
629 fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathName);
630 this->outputConicPoints(&pts[1], iter.conicWeight());
631 break;
632 case SkPath::kCubic_Verb:
633 fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathName);
634 this->outputPoints(&pts[1], 3);
635 break;
636 case SkPath::kClose_Verb:
637 fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, pathName);
638 break;
639 default:
640 SkDEBUGFAIL("bad verb");
641 return;
642 }
643 }
644}
645
646void SkDebugCanvas::addClipStackData(const SkPath& devPath, const SkPath& operand,
647 SkRegion::Op elementOp) {
648 if (elementOp == SkRegion::kReplace_Op) {
649 if (!lastClipStackData(devPath)) {
650 fSaveDevPath = operand;
651 }
652 fCalledAddStackData = false;
653 } else {
654 fClipStackData.appendf("<br>static void test(skiatest::Reporter* reporter,"
655 " const char* filename) {<br>");
656 addPathData(fCalledAddStackData ? devPath : fSaveDevPath, "path");
657 addPathData(operand, "pathB");
658 fClipStackData.appendf("%stestPathOp(reporter, path, pathB, %s, filename);<br>",
659 kHTML4SpaceIndent, gOpStrs[elementOp]);
660 fClipStackData.appendf("}<br>");
661 fCalledAddStackData = true;
662 }
663}
664
665bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) {
666 if (fCalledAddStackData) {
667 fClipStackData.appendf("<br>");
668 addPathData(devPath, "pathOut");
669 return true;
670 }
671 return false;
672}