blob: f6c8082c2da1a9205ae2310845f6c7ef180d4fe5 [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"
13
reed@google.com6ae24e02012-09-26 13:44:13 +000014static SkBitmap make_noconfig_bm(int width, int height) {
15 SkBitmap bm;
16 bm.setConfig(SkBitmap::kNo_Config, width, height);
17 return bm;
18}
19
20SkDebugCanvas::SkDebugCanvas(int width, int height)
21 : INHERITED(make_noconfig_bm(width, height)) {
chudy@google.com902ebe52012-06-29 14:21:22 +000022 // TODO(chudy): Free up memory from all draw commands in destructor.
chudy@google.com80a4a602012-07-30 18:54:07 +000023 fWidth = width;
24 fHeight = height;
reed@google.com6ae24e02012-09-26 13:44:13 +000025 // do we need fBm anywhere?
chudy@google.comb9ddd4e2012-07-10 14:14:50 +000026 fBm.setConfig(SkBitmap::kNo_Config, fWidth, fHeight);
chudy@google.com902ebe52012-06-29 14:21:22 +000027 fFilter = false;
chudy@google.com830b8792012-08-01 15:57:52 +000028 fIndex = 0;
29 fUserOffset.set(0,0);
30 fUserScale = 1.0;
chudy@google.com902ebe52012-06-29 14:21:22 +000031}
32
chudy@google.com9cda6f72012-08-07 15:08:33 +000033SkDebugCanvas::~SkDebugCanvas() {
chudy@google.com97cee972012-08-07 20:41:37 +000034 commandVector.deleteAll();
chudy@google.com9cda6f72012-08-07 15:08:33 +000035}
chudy@google.com902ebe52012-06-29 14:21:22 +000036
37void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) {
chudy@google.com97cee972012-08-07 20:41:37 +000038 commandVector.push(command);
chudy@google.com902ebe52012-06-29 14:21:22 +000039}
40
41void SkDebugCanvas::draw(SkCanvas* canvas) {
chudy@google.com97cee972012-08-07 20:41:37 +000042 if(!commandVector.isEmpty()) {
43 for (int i = 0; i < commandVector.count(); i++) {
44 if (commandVector[i]->isVisible()) {
45 commandVector[i]->execute(canvas);
chudy@google.com0ab03392012-07-28 20:16:11 +000046 }
chudy@google.com902ebe52012-06-29 14:21:22 +000047 }
48 }
chudy@google.com97cee972012-08-07 20:41:37 +000049 fIndex = commandVector.count() - 1;
chudy@google.com902ebe52012-06-29 14:21:22 +000050}
51
chudy@google.com830b8792012-08-01 15:57:52 +000052void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) {
skia.committer@gmail.com04ba4482012-09-07 02:01:30 +000053 canvas->translate(SkIntToScalar(fUserOffset.fX),
robertphillips@google.com94acc702012-09-06 18:43:21 +000054 SkIntToScalar(fUserOffset.fY));
chudy@google.com830b8792012-08-01 15:57:52 +000055 if (fUserScale < 0) {
robertphillips@google.com94acc702012-09-06 18:43:21 +000056 canvas->scale((1.0f / -fUserScale), (1.0f / -fUserScale));
chudy@google.com830b8792012-08-01 15:57:52 +000057 } else if (fUserScale > 0) {
58 canvas->scale(fUserScale, fUserScale);
59 }
60}
61
62int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +000063 SkBitmap bitmap;
64 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
65 bitmap.allocPixels();
chudy@google.com902ebe52012-06-29 14:21:22 +000066
chudy@google.com0b5bbb02012-07-31 19:55:32 +000067 SkCanvas canvas(bitmap);
robertphillips@google.com94acc702012-09-06 18:43:21 +000068 canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
chudy@google.com830b8792012-08-01 15:57:52 +000069 applyUserTransform(&canvas);
chudy@google.com0b5bbb02012-07-31 19:55:32 +000070
71 int layer = 0;
chudy@google.com751961d2012-07-31 20:07:42 +000072 SkColor prev = bitmap.getColor(0,0);
chudy@google.com0b5bbb02012-07-31 19:55:32 +000073 for (int i = 0; i < index; i++) {
74 if (commandVector[i]->isVisible()) {
75 commandVector[i]->execute(&canvas);
76 }
77 if (prev != bitmap.getColor(0,0)) {
78 layer = i;
79 }
80 prev = bitmap.getColor(0,0);
81 }
82 return layer;
83}
84
85void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
86 int counter = 0;
chudy@google.com97cee972012-08-07 20:41:37 +000087 SkASSERT(!commandVector.isEmpty());
88 SkASSERT(index < commandVector.count());
chudy@google.com830b8792012-08-01 15:57:52 +000089 int i;
90
91 // This only works assuming the canvas and device are the same ones that
92 // were previously drawn into because they need to preserve all saves
93 // and restores.
94 if (fIndex < index) {
95 i = fIndex + 1;
96 } else {
97 i = 0;
98 canvas->clear(0);
99 canvas->resetMatrix();
skia.committer@gmail.com04ba4482012-09-07 02:01:30 +0000100 SkRect rect = SkRect::MakeWH(SkIntToScalar(fWidth),
robertphillips@google.com94acc702012-09-06 18:43:21 +0000101 SkIntToScalar(fHeight));
chudy@google.com4c7962e2012-08-14 19:38:31 +0000102 canvas->clipRect(rect, SkRegion::kReplace_Op );
chudy@google.com830b8792012-08-01 15:57:52 +0000103 applyUserTransform(canvas);
104 }
105
106 for (; i <= index; i++) {
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000107 if (i == index && fFilter) {
108 SkPaint p;
109 p.setColor(0xAAFFFFFF);
110 canvas->save();
111 canvas->resetMatrix();
112 SkRect mask;
113 mask.set(SkIntToScalar(0), SkIntToScalar(0),
114 SkIntToScalar(fWidth), SkIntToScalar(fHeight));
115 canvas->clipRect(mask, SkRegion::kReplace_Op, false);
116 canvas->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
117 SkIntToScalar(fWidth), SkIntToScalar(fHeight), p);
118 canvas->restore();
119 }
120
121 if (commandVector[i]->isVisible()) {
122 commandVector[i]->execute(canvas);
chudy@google.com902ebe52012-06-29 14:21:22 +0000123 }
124 }
chudy@google.coma9e937c2012-08-03 17:32:05 +0000125 fMatrix = canvas->getTotalMatrix();
126 fClip = canvas->getTotalClip().getBounds();
chudy@google.com830b8792012-08-01 15:57:52 +0000127 fIndex = index;
chudy@google.com902ebe52012-06-29 14:21:22 +0000128}
129
130SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) {
chudy@google.com97cee972012-08-07 20:41:37 +0000131 SkASSERT(index < commandVector.count());
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000132 return commandVector[index];
chudy@google.com902ebe52012-06-29 14:21:22 +0000133}
134
chudy@google.com97cee972012-08-07 20:41:37 +0000135SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) {
136 SkASSERT(index < commandVector.count());
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000137 return commandVector[index]->Info();
138}
chudy@google.com902ebe52012-06-29 14:21:22 +0000139
chudy@google.com7e4cfbf2012-07-17 15:40:51 +0000140bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) {
chudy@google.com97cee972012-08-07 20:41:37 +0000141 SkASSERT(index < commandVector.count());
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000142 return commandVector[index]->isVisible();
chudy@google.com902ebe52012-06-29 14:21:22 +0000143}
144
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000145const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const {
chudy@google.com902ebe52012-06-29 14:21:22 +0000146 return commandVector;
147}
148
149// TODO(chudy): Free command string memory.
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000150SkTArray<SkString>* SkDebugCanvas::getDrawCommandsAsStrings() const {
151 SkTArray<SkString>* commandString = new SkTArray<SkString>(commandVector.count());
chudy@google.com97cee972012-08-07 20:41:37 +0000152 if (!commandVector.isEmpty()) {
153 for (int i = 0; i < commandVector.count(); i ++) {
robertphillips@google.com8a1cdae2012-11-19 20:44:29 +0000154 commandString->push_back() = commandVector[i]->toString();
chudy@google.com902ebe52012-06-29 14:21:22 +0000155 }
156 }
157 return commandString;
158}
159
160void SkDebugCanvas::toggleFilter(bool toggle) {
161 fFilter = toggle;
162}
163
164void SkDebugCanvas::clear(SkColor color) {
165 addDrawCommand(new Clear(color));
166}
167
168bool SkDebugCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
169 addDrawCommand(new ClipPath(path, op, doAA));
170 return true;
171}
172
173bool SkDebugCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
174 addDrawCommand(new ClipRect(rect, op, doAA));
175 return true;
176}
177
178bool SkDebugCanvas::clipRegion(const SkRegion& region, SkRegion::Op op) {
179 addDrawCommand(new ClipRegion(region, op));
180 return true;
181}
182
183bool SkDebugCanvas::concat(const SkMatrix& matrix) {
184 addDrawCommand(new Concat(matrix));
185 return true;
186}
187
188void SkDebugCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left,
189 SkScalar top, const SkPaint* paint = NULL) {
190 addDrawCommand(new DrawBitmap(bitmap, left, top, paint));
191}
192
reed@google.com71121732012-09-18 15:14:33 +0000193void SkDebugCanvas::drawBitmapRectToRect(const SkBitmap& bitmap,
194 const SkRect* src, const SkRect& dst, const SkPaint* paint) {
chudy@google.com902ebe52012-06-29 14:21:22 +0000195 addDrawCommand(new DrawBitmapRect(bitmap, src, dst, paint));
196}
197
198void SkDebugCanvas::drawBitmapMatrix(const SkBitmap& bitmap,
199 const SkMatrix& matrix, const SkPaint* paint) {
200 addDrawCommand(new DrawBitmapMatrix(bitmap, matrix, paint));
201}
202
203void SkDebugCanvas::drawBitmapNine(const SkBitmap& bitmap,
204 const SkIRect& center, const SkRect& dst, const SkPaint* paint) {
205 addDrawCommand(new DrawBitmapNine(bitmap, center, dst, paint));
206}
207
208void SkDebugCanvas::drawData(const void* data, size_t length) {
209 addDrawCommand(new DrawData(data, length));
210}
211
212void SkDebugCanvas::drawPaint(const SkPaint& paint) {
213 addDrawCommand(new DrawPaint(paint));
214}
215
216void SkDebugCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
217 addDrawCommand(new DrawPath(path, paint));
218}
219
220void SkDebugCanvas::drawPicture(SkPicture& picture) {
221 addDrawCommand(new DrawPicture(picture));
222}
223
224void SkDebugCanvas::drawPoints(PointMode mode, size_t count,
225 const SkPoint pts[], const SkPaint& paint) {
226 addDrawCommand(new DrawPoints(mode, count, pts, paint));
227}
228
229void SkDebugCanvas::drawPosText(const void* text, size_t byteLength,
230 const SkPoint pos[], const SkPaint& paint) {
231 addDrawCommand(new DrawPosText(text, byteLength, pos, paint));
232}
233
234void SkDebugCanvas::drawPosTextH(const void* text, size_t byteLength,
235 const SkScalar xpos[], SkScalar constY, const SkPaint& paint) {
236 addDrawCommand(new DrawPosTextH(text, byteLength, xpos, constY, paint));
237}
238
239void SkDebugCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
240 // NOTE(chudy): Messing up when renamed to DrawRect... Why?
241 addDrawCommand(new DrawRectC(rect, paint));
242}
243
244void SkDebugCanvas::drawSprite(const SkBitmap& bitmap, int left, int top,
245 const SkPaint* paint = NULL) {
246 addDrawCommand(new DrawSprite(bitmap, left, top, paint));
247}
248
249void SkDebugCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
250 SkScalar y, const SkPaint& paint) {
251 addDrawCommand(new DrawTextC(text, byteLength, x, y, paint));
252}
253
254void SkDebugCanvas::drawTextOnPath(const void* text, size_t byteLength,
255 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) {
256 addDrawCommand(new DrawTextOnPath(text, byteLength, path, matrix, paint));
257}
258
259void SkDebugCanvas::drawVertices(VertexMode vmode, int vertexCount,
260 const SkPoint vertices[], const SkPoint texs[], const SkColor colors[],
261 SkXfermode*, const uint16_t indices[], int indexCount,
262 const SkPaint& paint) {
263 addDrawCommand(new DrawVertices(vmode, vertexCount, vertices, texs, colors,
264 NULL, indices, indexCount, paint));
265}
266
267void SkDebugCanvas::restore() {
268 addDrawCommand(new Restore());
269}
270
271bool SkDebugCanvas::rotate(SkScalar degrees) {
272 addDrawCommand(new Rotate(degrees));
273 return true;
274}
275
276int SkDebugCanvas::save(SaveFlags flags) {
277 addDrawCommand(new Save(flags));
278 return true;
279}
280
281int SkDebugCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
282 SaveFlags flags) {
283 addDrawCommand(new SaveLayer(bounds, paint, flags));
284 return true;
285}
286
287bool SkDebugCanvas::scale(SkScalar sx, SkScalar sy) {
288 addDrawCommand(new Scale(sx, sy));
289 return true;
290}
291
292void SkDebugCanvas::setMatrix(const SkMatrix& matrix) {
293 addDrawCommand(new SetMatrix(matrix));
294}
295
296bool SkDebugCanvas::skew(SkScalar sx, SkScalar sy) {
297 addDrawCommand(new Skew(sx, sy));
298 return true;
299}
300
301bool SkDebugCanvas::translate(SkScalar dx, SkScalar dy) {
302 addDrawCommand(new Translate(dx, dy));
303 return true;
304}
305
chudy@google.com902ebe52012-06-29 14:21:22 +0000306void SkDebugCanvas::toggleCommand(int index, bool toggle) {
chudy@google.com97cee972012-08-07 20:41:37 +0000307 SkASSERT(index < commandVector.count());
chudy@google.com0b5bbb02012-07-31 19:55:32 +0000308 commandVector[index]->setVisible(toggle);
chudy@google.com902ebe52012-06-29 14:21:22 +0000309}