blob: a0d5eb3c40529b5acf492537bc31d2e05d020cc2 [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
10#include <iostream>
11#include "SkDebugCanvas.h"
12#include "SkDrawCommand.h"
robertphillips@google.com6dec8fc2012-11-21 17:11:02 +000013#include "SkDevice.h"
14#include "SkImageWidget.h"
chudy@google.com902ebe52012-06-29 14:21:22 +000015
reed@google.com6ae24e02012-09-26 13:44:13 +000016static SkBitmap make_noconfig_bm(int width, int height) {
17 SkBitmap bm;
18 bm.setConfig(SkBitmap::kNo_Config, width, height);
19 return bm;
20}
21
22SkDebugCanvas::SkDebugCanvas(int width, int height)
23 : INHERITED(make_noconfig_bm(width, height)) {
chudy@google.com902ebe52012-06-29 14:21:22 +000024 // TODO(chudy): Free up memory from all draw commands in destructor.
chudy@google.com80a4a602012-07-30 18:54:07 +000025 fWidth = width;
26 fHeight = height;
reed@google.com6ae24e02012-09-26 13:44:13 +000027 // do we need fBm anywhere?
chudy@google.comb9ddd4e2012-07-10 14:14:50 +000028 fBm.setConfig(SkBitmap::kNo_Config, fWidth, fHeight);
chudy@google.com902ebe52012-06-29 14:21:22 +000029 fFilter = false;
chudy@google.com830b8792012-08-01 15:57:52 +000030 fIndex = 0;
31 fUserOffset.set(0,0);
32 fUserScale = 1.0;
chudy@google.com902ebe52012-06-29 14:21:22 +000033}
34
chudy@google.com9cda6f72012-08-07 15:08:33 +000035SkDebugCanvas::~SkDebugCanvas() {
chudy@google.com97cee972012-08-07 20:41:37 +000036 commandVector.deleteAll();
chudy@google.com9cda6f72012-08-07 15:08:33 +000037}
chudy@google.com902ebe52012-06-29 14:21:22 +000038
39void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
chudy@google.com97cee972012-08-07 20:41:37 +000040 commandVector.push(command);
chudy@google.com902ebe52012-06-29 14:21:22 +000041}
42
43void SkDebugCanvas::draw(SkCanvas* canvas) {
chudy@google.com97cee972012-08-07 20:41:37 +000044 if(!commandVector.isEmpty()) {
45 for (int i = 0; i < commandVector.count(); i++) {
46 if (commandVector[i]->isVisible()) {
47 commandVector[i]->execute(canvas);
chudy@google.com0ab03392012-07-28 20:16:11 +000048 }
chudy@google.com902ebe52012-06-29 14:21:22 +000049 }
50 }
chudy@google.com97cee972012-08-07 20:41:37 +000051 fIndex = commandVector.count() - 1;
chudy@google.com902ebe52012-06-29 14:21:22 +000052}
53
chudy@google.com830b8792012-08-01 15:57:52 +000054void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
skia.committer@gmail.com04ba4482012-09-07 02:01:30 +000055 canvas->translate(SkIntToScalar(fUserOffset.fX),
robertphillips@google.com94acc702012-09-06 18:43:21 +000056 SkIntToScalar(fUserOffset.fY));
chudy@google.com830b8792012-08-01 15:57:52 +000057 if (fUserScale < 0) {
robertphillips@google.com94acc702012-09-06 18:43:21 +000058 canvas->scale((1.0f / -fUserScale), (1.0f / -fUserScale));
chudy@google.com830b8792012-08-01 15:57:52 +000059 } else if (fUserScale > 0) {
60 canvas->scale(fUserScale, fUserScale);
61 }
62}
63
64int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +000065 SkBitmap bitmap;
66 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
67 bitmap.allocPixels();
chudy@google.com902ebe52012-06-29 14:21:22 +000068
chudy@google.com0b5bbb02012-07-31 19:55:32 +000069 SkCanvas canvas(bitmap);
robertphillips@google.com94acc702012-09-06 18:43:21 +000070 canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
chudy@google.com830b8792012-08-01 15:57:52 +000071 applyUserTransform(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +000072
73 int layer = 0;
chudy@google.com751961d2012-07-31 20:07:42 +000074 SkColor prev = bitmap.getColor(0,0);
chudy@google.com0b5bbb02012-07-31 19:55:32 +000075 for (int i = 0; i < index; i++) {
76 if (commandVector[i]->isVisible()) {
77 commandVector[i]->execute(&canvas);
78 }
79 if (prev != bitmap.getColor(0,0)) {
80 layer = i;
81 }
82 prev = bitmap.getColor(0,0);
83 }
84 return layer;
85}
86
87void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
88 int counter = 0;
chudy@google.com97cee972012-08-07 20:41:37 +000089 SkASSERT(!commandVector.isEmpty());
90 SkASSERT(index < commandVector.count());
chudy@google.com830b8792012-08-01 15:57:52 +000091 int i;
92
93 // This only works assuming the canvas and device are the same ones that
94 // were previously drawn into because they need to preserve all saves
95 // and restores.
96 if (fIndex < index) {
97 i = fIndex + 1;
98 } else {
99 i = 0;
100 canvas->clear(0);
101 canvas->resetMatrix();
skia.committer@gmail.com04ba4482012-09-07 02:01:30 +0000102 SkRect rect = SkRect::MakeWH(SkIntToScalar(fWidth),
robertphillips@google.com94acc702012-09-06 18:43:21 +0000103 SkIntToScalar(fHeight));
chudy@google.com4c7962e2012-08-14 19:38:31 +0000104 canvas->clipRect(rect, SkRegion::kReplace_Op );
chudy@google.com830b8792012-08-01 15:57:52 +0000105 applyUserTransform(canvas);
106 }
107
108 for (; i <= index; i++) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000109 if (i == index && fFilter) {
110 SkPaint p;
111 p.setColor(0xAAFFFFFF);
112 canvas->save();
113 canvas->resetMatrix();
114 SkRect mask;
115 mask.set(SkIntToScalar(0), SkIntToScalar(0),
116 SkIntToScalar(fWidth), SkIntToScalar(fHeight));
117 canvas->clipRect(mask, SkRegion::kReplace_Op, false);
118 canvas->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
119 SkIntToScalar(fWidth), SkIntToScalar(fHeight), p);
120 canvas->restore();
121 }
122
123 if (commandVector[i]->isVisible()) {
124 commandVector[i]->execute(canvas);
chudy@google.com902ebe52012-06-29 14:21:22 +0000125 }
126 }
chudy@google.coma9e937c2012-08-03 17:32:05 +0000127 fMatrix = canvas->getTotalMatrix();
128 fClip = canvas->getTotalClip().getBounds();
chudy@google.com830b8792012-08-01 15:57:52 +0000129 fIndex = index;
chudy@google.com902ebe52012-06-29 14:21:22 +0000130}
131
132SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
chudy@google.com97cee972012-08-07 20:41:37 +0000133 SkASSERT(index < commandVector.count());
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000134 return commandVector[index];
chudy@google.com902ebe52012-06-29 14:21:22 +0000135}
136
chudy@google.com97cee972012-08-07 20:41:37 +0000137SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) {
138 SkASSERT(index < commandVector.count());
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000139 return commandVector[index]->Info();
140}
chudy@google.com902ebe52012-06-29 14:21:22 +0000141
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000142bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) {
chudy@google.com97cee972012-08-07 20:41:37 +0000143 SkASSERT(index < commandVector.count());
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000144 return commandVector[index]->isVisible();
chudy@google.com902ebe52012-06-29 14:21:22 +0000145}
146
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000147const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const {
chudy@google.com902ebe52012-06-29 14:21:22 +0000148 return commandVector;
149}
150
151// TODO(chudy): Free command string memory.
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000152SkTArray<SkString>* SkDebugCanvas::getDrawCommandsAsStrings() const {
153 SkTArray<SkString>* commandString = new SkTArray<SkString>(commandVector.count());
chudy@google.com97cee972012-08-07 20:41:37 +0000154 if (!commandVector.isEmpty()) {
155 for (int i = 0; i < commandVector.count(); i ++) {
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000156 commandString->push_back() = commandVector[i]->toString();
chudy@google.com902ebe52012-06-29 14:21:22 +0000157 }
158 }
159 return commandString;
160}
161
162void SkDebugCanvas::toggleFilter(bool toggle) {
163 fFilter = toggle;
164}
165
166void SkDebugCanvas::clear(SkColor color) {
167 addDrawCommand(new Clear(color));
168}
169
robertphillips@google.com6dec8fc2012-11-21 17:11:02 +0000170static SkBitmap createBitmap(const SkPath& path) {
171 SkBitmap bitmap;
skia.committer@gmail.com1c9c0d32012-11-22 02:02:41 +0000172 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
173 SkImageWidget::kImageWidgetWidth,
robertphillips@google.com6dec8fc2012-11-21 17:11:02 +0000174 SkImageWidget::kImageWidgetHeight);
175 bitmap.allocPixels();
176 bitmap.eraseColor(SK_ColorWHITE);
177 SkDevice* device = new SkDevice(bitmap);
178
179 SkCanvas canvas(device);
180 device->unref();
181
182 const SkRect& bounds = path.getBounds();
183
184 if (bounds.width() > bounds.height()) {
skia.committer@gmail.com1c9c0d32012-11-22 02:02:41 +0000185 canvas.scale(SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetWidth)/bounds.width()),
robertphillips@google.com6dec8fc2012-11-21 17:11:02 +0000186 SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetHeight)/bounds.width()));
187 } else {
skia.committer@gmail.com1c9c0d32012-11-22 02:02:41 +0000188 canvas.scale(SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetWidth)/bounds.height()),
robertphillips@google.com6dec8fc2012-11-21 17:11:02 +0000189 SkDoubleToScalar((0.9*SkImageWidget::kImageWidgetHeight)/bounds.height()));
190 }
191 canvas.translate(-bounds.fLeft+2, -bounds.fTop+2);
192
193 SkPaint p;
194 p.setColor(SK_ColorBLACK);
195 p.setStyle(SkPaint::kStroke_Style);
196
197 canvas.drawPath(path, p);
198
199 return bitmap;
200}
201
chudy@google.com902ebe52012-06-29 14:21:22 +0000202bool SkDebugCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
rmistry@google.com44737652012-11-21 18:37:58 +0000203 SkBitmap bitmap = createBitmap(path);
204 addDrawCommand(new ClipPath(path, op, doAA, bitmap));
chudy@google.com902ebe52012-06-29 14:21:22 +0000205 return true;
206}
207
208bool SkDebugCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
209 addDrawCommand(new ClipRect(rect, op, doAA));
210 return true;
211}
212
213bool SkDebugCanvas::clipRegion(const SkRegion& region, SkRegion::Op op) {
214 addDrawCommand(new ClipRegion(region, op));
215 return true;
216}
217
218bool SkDebugCanvas::concat(const SkMatrix& matrix) {
219 addDrawCommand(new Concat(matrix));
220 return true;
221}
222
223void SkDebugCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
224 SkScalar top, const SkPaint* paint = NULL) {
225 addDrawCommand(new DrawBitmap(bitmap, left, top, paint));
226}
227
reed@google.com71121732012-09-18 15:14:33 +0000228void SkDebugCanvas::drawBitmapRectToRect(const SkBitmap& bitmap,
229 const SkRect* src, const SkRect& dst, const SkPaint* paint) {
chudy@google.com902ebe52012-06-29 14:21:22 +0000230 addDrawCommand(new DrawBitmapRect(bitmap, src, dst, paint));
231}
232
233void SkDebugCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
234 const SkMatrix& matrix, const SkPaint* paint) {
235 addDrawCommand(new DrawBitmapMatrix(bitmap, matrix, paint));
236}
237
238void SkDebugCanvas::drawBitmapNine(const SkBitmap& bitmap,
239 const SkIRect& center, const SkRect& dst, const SkPaint* paint) {
240 addDrawCommand(new DrawBitmapNine(bitmap, center, dst, paint));
241}
242
243void SkDebugCanvas::drawData(const void* data, size_t length) {
244 addDrawCommand(new DrawData(data, length));
245}
246
247void SkDebugCanvas::drawPaint(const SkPaint& paint) {
248 addDrawCommand(new DrawPaint(paint));
249}
250
251void SkDebugCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
rmistry@google.com44737652012-11-21 18:37:58 +0000252 SkBitmap bitmap = createBitmap(path);
253 addDrawCommand(new DrawPath(path, paint, bitmap));
chudy@google.com902ebe52012-06-29 14:21:22 +0000254}
255
256void SkDebugCanvas::drawPicture(SkPicture& picture) {
257 addDrawCommand(new DrawPicture(picture));
258}
259
260void SkDebugCanvas::drawPoints(PointMode mode, size_t count,
261 const SkPoint pts[], const SkPaint& paint) {
262 addDrawCommand(new DrawPoints(mode, count, pts, paint));
263}
264
265void SkDebugCanvas::drawPosText(const void* text, size_t byteLength,
266 const SkPoint pos[], const SkPaint& paint) {
267 addDrawCommand(new DrawPosText(text, byteLength, pos, paint));
268}
269
270void SkDebugCanvas::drawPosTextH(const void* text, size_t byteLength,
271 const SkScalar xpos[], SkScalar constY, const SkPaint& paint) {
272 addDrawCommand(new DrawPosTextH(text, byteLength, xpos, constY, paint));
273}
274
275void SkDebugCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
276 // NOTE(chudy): Messing up when renamed to DrawRect... Why?
277 addDrawCommand(new DrawRectC(rect, paint));
278}
279
280void SkDebugCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
281 const SkPaint* paint = NULL) {
282 addDrawCommand(new DrawSprite(bitmap, left, top, paint));
283}
284
285void SkDebugCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
286 SkScalar y, const SkPaint& paint) {
287 addDrawCommand(new DrawTextC(text, byteLength, x, y, paint));
288}
289
290void SkDebugCanvas::drawTextOnPath(const void* text, size_t byteLength,
291 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {
292 addDrawCommand(new DrawTextOnPath(text, byteLength, path, matrix, paint));
293}
294
295void SkDebugCanvas::drawVertices(VertexMode vmode, int vertexCount,
296 const SkPoint vertices[], const SkPoint texs[], const SkColor colors[],
297 SkXfermode*, const uint16_t indices[], int indexCount,
298 const SkPaint& paint) {
299 addDrawCommand(new DrawVertices(vmode, vertexCount, vertices, texs, colors,
300 NULL, indices, indexCount, paint));
301}
302
303void SkDebugCanvas::restore() {
304 addDrawCommand(new Restore());
305}
306
307bool SkDebugCanvas::rotate(SkScalar degrees) {
308 addDrawCommand(new Rotate(degrees));
309 return true;
310}
311
312int SkDebugCanvas::save(SaveFlags flags) {
313 addDrawCommand(new Save(flags));
314 return true;
315}
316
317int SkDebugCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
318 SaveFlags flags) {
319 addDrawCommand(new SaveLayer(bounds, paint, flags));
320 return true;
321}
322
323bool SkDebugCanvas::scale(SkScalar sx, SkScalar sy) {
324 addDrawCommand(new Scale(sx, sy));
325 return true;
326}
327
328void SkDebugCanvas::setMatrix(const SkMatrix& matrix) {
329 addDrawCommand(new SetMatrix(matrix));
330}
331
332bool SkDebugCanvas::skew(SkScalar sx, SkScalar sy) {
333 addDrawCommand(new Skew(sx, sy));
334 return true;
335}
336
337bool SkDebugCanvas::translate(SkScalar dx, SkScalar dy) {
338 addDrawCommand(new Translate(dx, dy));
339 return true;
340}
341
chudy@google.com902ebe52012-06-29 14:21:22 +0000342void SkDebugCanvas::toggleCommand(int index, bool toggle) {
chudy@google.com97cee972012-08-07 20:41:37 +0000343 SkASSERT(index < commandVector.count());
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000344 commandVector[index]->setVisible(toggle);
chudy@google.com902ebe52012-06-29 14:21:22 +0000345}