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