OLD | NEW |
| (Empty) |
1 | |
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 "SkColorPriv.h" | |
11 #include "SkDebugCanvas.h" | |
12 #include "SkDrawCommand.h" | |
13 #include "SkDrawFilter.h" | |
14 #include "SkDevice.h" | |
15 #include "SkXfermode.h" | |
16 | |
17 #ifdef SK_BUILD_FOR_WIN | |
18 // iostream includes xlocale which generates warning 4530 because we're comp
iling without | |
19 // exceptions | |
20 #pragma warning(push) | |
21 #pragma warning(disable : 4530) | |
22 #endif | |
23 #include <iostream> | |
24 #ifdef SK_BUILD_FOR_WIN | |
25 #pragma warning(pop) | |
26 #endif | |
27 | |
28 static SkBitmap make_noconfig_bm(int width, int height) { | |
29 SkBitmap bm; | |
30 bm.setConfig(SkBitmap::kNo_Config, width, height); | |
31 return bm; | |
32 } | |
33 | |
34 SkDebugCanvas::SkDebugCanvas(int width, int height) | |
35 : INHERITED(make_noconfig_bm(width, height)) | |
36 , fOverdrawViz(false) | |
37 , fOverdrawFilter(NULL) | |
38 , fOutstandingSaveCount(0) { | |
39 // TODO(chudy): Free up memory from all draw commands in destructor. | |
40 fWidth = width; | |
41 fHeight = height; | |
42 // do we need fBm anywhere? | |
43 fBm.setConfig(SkBitmap::kNo_Config, fWidth, fHeight); | |
44 fFilter = false; | |
45 fIndex = 0; | |
46 fUserMatrix.reset(); | |
47 } | |
48 | |
49 SkDebugCanvas::~SkDebugCanvas() { | |
50 fCommandVector.deleteAll(); | |
51 SkSafeUnref(fOverdrawFilter); | |
52 } | |
53 | |
54 void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) { | |
55 fCommandVector.push(command); | |
56 } | |
57 | |
58 void SkDebugCanvas::draw(SkCanvas* canvas) { | |
59 if(!fCommandVector.isEmpty()) { | |
60 for (int i = 0; i < fCommandVector.count(); i++) { | |
61 if (fCommandVector[i]->isVisible()) { | |
62 fCommandVector[i]->execute(canvas); | |
63 } | |
64 } | |
65 } | |
66 fIndex = fCommandVector.count() - 1; | |
67 } | |
68 | |
69 void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) { | |
70 canvas->concat(fUserMatrix); | |
71 } | |
72 | |
73 int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) { | |
74 SkBitmap bitmap; | |
75 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); | |
76 bitmap.allocPixels(); | |
77 | |
78 SkCanvas canvas(bitmap); | |
79 canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y)); | |
80 applyUserTransform(&canvas); | |
81 | |
82 int layer = 0; | |
83 SkColor prev = bitmap.getColor(0,0); | |
84 for (int i = 0; i < index; i++) { | |
85 if (fCommandVector[i]->isVisible()) { | |
86 fCommandVector[i]->execute(&canvas); | |
87 } | |
88 if (prev != bitmap.getColor(0,0)) { | |
89 layer = i; | |
90 } | |
91 prev = bitmap.getColor(0,0); | |
92 } | |
93 return layer; | |
94 } | |
95 | |
96 static SkPMColor OverdrawXferModeProc(SkPMColor src, SkPMColor dst) { | |
97 // This table encodes the color progression of the overdraw visualization | |
98 static const SkPMColor gTable[] = { | |
99 SkPackARGB32(0x00, 0x00, 0x00, 0x00), | |
100 SkPackARGB32(0xFF, 128, 158, 255), | |
101 SkPackARGB32(0xFF, 170, 185, 212), | |
102 SkPackARGB32(0xFF, 213, 195, 170), | |
103 SkPackARGB32(0xFF, 255, 192, 127), | |
104 SkPackARGB32(0xFF, 255, 185, 85), | |
105 SkPackARGB32(0xFF, 255, 165, 42), | |
106 SkPackARGB32(0xFF, 255, 135, 0), | |
107 SkPackARGB32(0xFF, 255, 95, 0), | |
108 SkPackARGB32(0xFF, 255, 50, 0), | |
109 SkPackARGB32(0xFF, 255, 0, 0) | |
110 }; | |
111 | |
112 for (size_t i = 0; i < SK_ARRAY_COUNT(gTable)-1; ++i) { | |
113 if (gTable[i] == dst) { | |
114 return gTable[i+1]; | |
115 } | |
116 } | |
117 | |
118 return gTable[SK_ARRAY_COUNT(gTable)-1]; | |
119 } | |
120 | |
121 // The OverdrawFilter modifies every paint to use an SkProcXfermode which | |
122 // in turn invokes OverdrawXferModeProc | |
123 class OverdrawFilter : public SkDrawFilter { | |
124 public: | |
125 OverdrawFilter() { | |
126 fXferMode = new SkProcXfermode(OverdrawXferModeProc); | |
127 } | |
128 | |
129 virtual ~OverdrawFilter() { | |
130 delete fXferMode; | |
131 } | |
132 | |
133 virtual bool filter(SkPaint* p, Type) SK_OVERRIDE { | |
134 p->setXfermode(fXferMode); | |
135 return true; | |
136 } | |
137 | |
138 protected: | |
139 SkXfermode* fXferMode; | |
140 | |
141 private: | |
142 typedef SkDrawFilter INHERITED; | |
143 }; | |
144 | |
145 void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) { | |
146 SkASSERT(!fCommandVector.isEmpty()); | |
147 SkASSERT(index < fCommandVector.count()); | |
148 int i; | |
149 | |
150 // This only works assuming the canvas and device are the same ones that | |
151 // were previously drawn into because they need to preserve all saves | |
152 // and restores. | |
153 if (fIndex < index) { | |
154 i = fIndex + 1; | |
155 } else { | |
156 for (int j = 0; j < fOutstandingSaveCount; j++) { | |
157 canvas->restore(); | |
158 } | |
159 i = 0; | |
160 canvas->clear(SK_ColorTRANSPARENT); | |
161 canvas->resetMatrix(); | |
162 SkRect rect = SkRect::MakeWH(SkIntToScalar(fWidth), | |
163 SkIntToScalar(fHeight)); | |
164 canvas->clipRect(rect, SkRegion::kReplace_Op ); | |
165 applyUserTransform(canvas); | |
166 fOutstandingSaveCount = 0; | |
167 | |
168 // The setting of the draw filter has to go here (rather than in | |
169 // SkRasterWidget) due to the canvas restores this class performs. | |
170 // Since the draw filter is stored in the layer stack if we | |
171 // call setDrawFilter on anything but the root layer odd things happen | |
172 if (fOverdrawViz) { | |
173 if (NULL == fOverdrawFilter) { | |
174 fOverdrawFilter = new OverdrawFilter; | |
175 } | |
176 | |
177 if (fOverdrawFilter != canvas->getDrawFilter()) { | |
178 canvas->setDrawFilter(fOverdrawFilter); | |
179 } | |
180 } else { | |
181 canvas->setDrawFilter(NULL); | |
182 } | |
183 } | |
184 | |
185 for (; i <= index; i++) { | |
186 if (i == index && fFilter) { | |
187 SkPaint p; | |
188 p.setColor(0xAAFFFFFF); | |
189 canvas->save(); | |
190 canvas->resetMatrix(); | |
191 SkRect mask; | |
192 mask.set(SkIntToScalar(0), SkIntToScalar(0), | |
193 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); | |
194 canvas->clipRect(mask, SkRegion::kReplace_Op, false); | |
195 canvas->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0), | |
196 SkIntToScalar(fWidth), SkIntToScalar(fHeight), p); | |
197 canvas->restore(); | |
198 } | |
199 | |
200 if (fCommandVector[i]->isVisible()) { | |
201 fCommandVector[i]->execute(canvas); | |
202 fCommandVector[i]->trackSaveState(&fOutstandingSaveCount); | |
203 } | |
204 } | |
205 fMatrix = canvas->getTotalMatrix(); | |
206 fClip = canvas->getTotalClip().getBounds(); | |
207 fIndex = index; | |
208 } | |
209 | |
210 void SkDebugCanvas::deleteDrawCommandAt(int index) { | |
211 SkASSERT(index < fCommandVector.count()); | |
212 delete fCommandVector[index]; | |
213 fCommandVector.remove(index); | |
214 } | |
215 | |
216 SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) { | |
217 SkASSERT(index < fCommandVector.count()); | |
218 return fCommandVector[index]; | |
219 } | |
220 | |
221 void SkDebugCanvas::setDrawCommandAt(int index, SkDrawCommand* command) { | |
222 SkASSERT(index < fCommandVector.count()); | |
223 delete fCommandVector[index]; | |
224 fCommandVector[index] = command; | |
225 } | |
226 | |
227 SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) { | |
228 SkASSERT(index < fCommandVector.count()); | |
229 return fCommandVector[index]->Info(); | |
230 } | |
231 | |
232 bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) { | |
233 SkASSERT(index < fCommandVector.count()); | |
234 return fCommandVector[index]->isVisible(); | |
235 } | |
236 | |
237 const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const { | |
238 return fCommandVector; | |
239 } | |
240 | |
241 SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() { | |
242 return fCommandVector; | |
243 } | |
244 | |
245 // TODO(chudy): Free command string memory. | |
246 SkTArray<SkString>* SkDebugCanvas::getDrawCommandsAsStrings() const { | |
247 SkTArray<SkString>* commandString = new SkTArray<SkString>(fCommandVector.co
unt()); | |
248 if (!fCommandVector.isEmpty()) { | |
249 for (int i = 0; i < fCommandVector.count(); i ++) { | |
250 commandString->push_back() = fCommandVector[i]->toString(); | |
251 } | |
252 } | |
253 return commandString; | |
254 } | |
255 | |
256 void SkDebugCanvas::toggleFilter(bool toggle) { | |
257 fFilter = toggle; | |
258 } | |
259 | |
260 void SkDebugCanvas::clear(SkColor color) { | |
261 addDrawCommand(new Clear(color)); | |
262 } | |
263 | |
264 bool SkDebugCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { | |
265 addDrawCommand(new ClipPath(path, op, doAA)); | |
266 return true; | |
267 } | |
268 | |
269 bool SkDebugCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | |
270 addDrawCommand(new ClipRect(rect, op, doAA)); | |
271 return true; | |
272 } | |
273 | |
274 bool SkDebugCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA)
{ | |
275 addDrawCommand(new ClipRRect(rrect, op, doAA)); | |
276 return true; | |
277 } | |
278 | |
279 bool SkDebugCanvas::clipRegion(const SkRegion& region, SkRegion::Op op) { | |
280 addDrawCommand(new ClipRegion(region, op)); | |
281 return true; | |
282 } | |
283 | |
284 bool SkDebugCanvas::concat(const SkMatrix& matrix) { | |
285 addDrawCommand(new Concat(matrix)); | |
286 return true; | |
287 } | |
288 | |
289 void SkDebugCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left, | |
290 SkScalar top, const SkPaint* paint = NULL) { | |
291 addDrawCommand(new DrawBitmap(bitmap, left, top, paint)); | |
292 } | |
293 | |
294 void SkDebugCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, | |
295 const SkRect* src, const SkRect& dst, const SkPaint* paint) { | |
296 addDrawCommand(new DrawBitmapRect(bitmap, src, dst, paint)); | |
297 } | |
298 | |
299 void SkDebugCanvas::drawBitmapMatrix(const SkBitmap& bitmap, | |
300 const SkMatrix& matrix, const SkPaint* paint) { | |
301 addDrawCommand(new DrawBitmapMatrix(bitmap, matrix, paint)); | |
302 } | |
303 | |
304 void SkDebugCanvas::drawBitmapNine(const SkBitmap& bitmap, | |
305 const SkIRect& center, const SkRect& dst, const SkPaint* paint) { | |
306 addDrawCommand(new DrawBitmapNine(bitmap, center, dst, paint)); | |
307 } | |
308 | |
309 void SkDebugCanvas::drawData(const void* data, size_t length) { | |
310 addDrawCommand(new DrawData(data, length)); | |
311 } | |
312 | |
313 void SkDebugCanvas::beginCommentGroup(const char* description) { | |
314 addDrawCommand(new BeginCommentGroup(description)); | |
315 } | |
316 | |
317 void SkDebugCanvas::addComment(const char* kywd, const char* value) { | |
318 addDrawCommand(new Comment(kywd, value)); | |
319 } | |
320 | |
321 void SkDebugCanvas::endCommentGroup() { | |
322 addDrawCommand(new EndCommentGroup()); | |
323 } | |
324 | |
325 void SkDebugCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { | |
326 addDrawCommand(new DrawOval(oval, paint)); | |
327 } | |
328 | |
329 void SkDebugCanvas::drawPaint(const SkPaint& paint) { | |
330 addDrawCommand(new DrawPaint(paint)); | |
331 } | |
332 | |
333 void SkDebugCanvas::drawPath(const SkPath& path, const SkPaint& paint) { | |
334 addDrawCommand(new DrawPath(path, paint)); | |
335 } | |
336 | |
337 void SkDebugCanvas::drawPicture(SkPicture& picture) { | |
338 addDrawCommand(new DrawPicture(picture)); | |
339 } | |
340 | |
341 void SkDebugCanvas::drawPoints(PointMode mode, size_t count, | |
342 const SkPoint pts[], const SkPaint& paint) { | |
343 addDrawCommand(new DrawPoints(mode, count, pts, paint)); | |
344 } | |
345 | |
346 void SkDebugCanvas::drawPosText(const void* text, size_t byteLength, | |
347 const SkPoint pos[], const SkPaint& paint) { | |
348 addDrawCommand(new DrawPosText(text, byteLength, pos, paint)); | |
349 } | |
350 | |
351 void SkDebugCanvas::drawPosTextH(const void* text, size_t byteLength, | |
352 const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { | |
353 addDrawCommand(new DrawPosTextH(text, byteLength, xpos, constY, paint)); | |
354 } | |
355 | |
356 void SkDebugCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { | |
357 // NOTE(chudy): Messing up when renamed to DrawRect... Why? | |
358 addDrawCommand(new DrawRectC(rect, paint)); | |
359 } | |
360 | |
361 void SkDebugCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { | |
362 addDrawCommand(new DrawRRect(rrect, paint)); | |
363 } | |
364 | |
365 void SkDebugCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, | |
366 const SkPaint* paint = NULL) { | |
367 addDrawCommand(new DrawSprite(bitmap, left, top, paint)); | |
368 } | |
369 | |
370 void SkDebugCanvas::drawText(const void* text, size_t byteLength, SkScalar x, | |
371 SkScalar y, const SkPaint& paint) { | |
372 addDrawCommand(new DrawTextC(text, byteLength, x, y, paint)); | |
373 } | |
374 | |
375 void SkDebugCanvas::drawTextOnPath(const void* text, size_t byteLength, | |
376 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { | |
377 addDrawCommand(new DrawTextOnPath(text, byteLength, path, matrix, paint)); | |
378 } | |
379 | |
380 void SkDebugCanvas::drawVertices(VertexMode vmode, int vertexCount, | |
381 const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], | |
382 SkXfermode*, const uint16_t indices[], int indexCount, | |
383 const SkPaint& paint) { | |
384 addDrawCommand(new DrawVertices(vmode, vertexCount, vertices, texs, colors, | |
385 NULL, indices, indexCount, paint)); | |
386 } | |
387 | |
388 void SkDebugCanvas::restore() { | |
389 addDrawCommand(new Restore()); | |
390 } | |
391 | |
392 bool SkDebugCanvas::rotate(SkScalar degrees) { | |
393 addDrawCommand(new Rotate(degrees)); | |
394 return true; | |
395 } | |
396 | |
397 int SkDebugCanvas::save(SaveFlags flags) { | |
398 addDrawCommand(new Save(flags)); | |
399 return true; | |
400 } | |
401 | |
402 int SkDebugCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, | |
403 SaveFlags flags) { | |
404 addDrawCommand(new SaveLayer(bounds, paint, flags)); | |
405 return true; | |
406 } | |
407 | |
408 bool SkDebugCanvas::scale(SkScalar sx, SkScalar sy) { | |
409 addDrawCommand(new Scale(sx, sy)); | |
410 return true; | |
411 } | |
412 | |
413 void SkDebugCanvas::setMatrix(const SkMatrix& matrix) { | |
414 addDrawCommand(new SetMatrix(matrix)); | |
415 } | |
416 | |
417 bool SkDebugCanvas::skew(SkScalar sx, SkScalar sy) { | |
418 addDrawCommand(new Skew(sx, sy)); | |
419 return true; | |
420 } | |
421 | |
422 bool SkDebugCanvas::translate(SkScalar dx, SkScalar dy) { | |
423 addDrawCommand(new Translate(dx, dy)); | |
424 return true; | |
425 } | |
426 | |
427 void SkDebugCanvas::toggleCommand(int index, bool toggle) { | |
428 SkASSERT(index < fCommandVector.count()); | |
429 fCommandVector[index]->setVisible(toggle); | |
430 } | |
OLD | NEW |