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