SkDebugCanvas.cpp revision eed779d866e1e239bfb9ebc6a225b7345a41adf9
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 , 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 38SkDebugCanvas::~SkDebugCanvas() { 39 fCommandVector.deleteAll(); 40 SkSafeUnref(fOverdrawFilter); 41} 42 43void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) { 44 fCommandVector.push(command); 45} 46 47void 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 58void SkDebugCanvas::applyUserTransform(SkCanvas* canvas) { 59 canvas->concat(fUserMatrix); 60} 61 62int 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 85static 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 112class OverdrawFilter : public SkDrawFilter { 113public: 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 127protected: 128 SkXfermode* fXferMode; 129 130private: 131 typedef SkDrawFilter INHERITED; 132}; 133 134void 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 199void SkDebugCanvas::deleteDrawCommandAt(int index) { 200 SkASSERT(index < fCommandVector.count()); 201 delete fCommandVector[index]; 202 fCommandVector.remove(index); 203} 204 205SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) { 206 SkASSERT(index < fCommandVector.count()); 207 return fCommandVector[index]; 208} 209 210void SkDebugCanvas::setDrawCommandAt(int index, SkDrawCommand* command) { 211 SkASSERT(index < fCommandVector.count()); 212 delete fCommandVector[index]; 213 fCommandVector[index] = command; 214} 215 216SkTDArray<SkString*>* SkDebugCanvas::getCommandInfo(int index) { 217 SkASSERT(index < fCommandVector.count()); 218 return fCommandVector[index]->Info(); 219} 220 221bool SkDebugCanvas::getDrawCommandVisibilityAt(int index) { 222 SkASSERT(index < fCommandVector.count()); 223 return fCommandVector[index]->isVisible(); 224} 225 226const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const { 227 return fCommandVector; 228} 229 230SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() { 231 return fCommandVector; 232} 233 234// TODO(chudy): Free command string memory. 235SkTArray<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 245void SkDebugCanvas::toggleFilter(bool toggle) { 246 fFilter = toggle; 247} 248 249void SkDebugCanvas::clear(SkColor color) { 250 addDrawCommand(new SkClearCommand(color)); 251} 252 253bool SkDebugCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 254 addDrawCommand(new SkClipPathCommand(path, op, doAA)); 255 return true; 256} 257 258bool SkDebugCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 259 addDrawCommand(new SkClipRectCommand(rect, op, doAA)); 260 return true; 261} 262 263bool SkDebugCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 264 addDrawCommand(new SkClipRRectCommand(rrect, op, doAA)); 265 return true; 266} 267 268bool SkDebugCanvas::clipRegion(const SkRegion& region, SkRegion::Op op) { 269 addDrawCommand(new SkClipRegionCommand(region, op)); 270 return true; 271} 272 273bool SkDebugCanvas::concat(const SkMatrix& matrix) { 274 addDrawCommand(new SkConcatCommand(matrix)); 275 return true; 276} 277 278void SkDebugCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar left, 279 SkScalar top, const SkPaint* paint = NULL) { 280 addDrawCommand(new SkDrawBitmapCommand(bitmap, left, top, paint)); 281} 282 283void SkDebugCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, 284 const SkRect* src, const SkRect& dst, 285 const SkPaint* paint, 286 SkCanvas::DrawBitmapRectFlags flags) { 287 addDrawCommand(new SkDrawBitmapRectCommand(bitmap, src, dst, paint, flags)); 288} 289 290void SkDebugCanvas::drawBitmapMatrix(const SkBitmap& bitmap, 291 const SkMatrix& matrix, const SkPaint* paint) { 292 addDrawCommand(new SkDrawBitmapMatrixCommand(bitmap, matrix, paint)); 293} 294 295void SkDebugCanvas::drawBitmapNine(const SkBitmap& bitmap, 296 const SkIRect& center, const SkRect& dst, const SkPaint* paint) { 297 addDrawCommand(new SkDrawBitmapNineCommand(bitmap, center, dst, paint)); 298} 299 300void SkDebugCanvas::drawData(const void* data, size_t length) { 301 addDrawCommand(new SkDrawDataCommand(data, length)); 302} 303 304void SkDebugCanvas::beginCommentGroup(const char* description) { 305 addDrawCommand(new SkBeginCommentGroupCommand(description)); 306} 307 308void SkDebugCanvas::addComment(const char* kywd, const char* value) { 309 addDrawCommand(new SkCommentCommand(kywd, value)); 310} 311 312void SkDebugCanvas::endCommentGroup() { 313 addDrawCommand(new SkEndCommentGroupCommand()); 314} 315 316void SkDebugCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 317 addDrawCommand(new SkDrawOvalCommand(oval, paint)); 318} 319 320void SkDebugCanvas::drawPaint(const SkPaint& paint) { 321 addDrawCommand(new SkDrawPaintCommand(paint)); 322} 323 324void SkDebugCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 325 addDrawCommand(new SkDrawPathCommand(path, paint)); 326} 327 328void SkDebugCanvas::drawPicture(SkPicture& picture) { 329 addDrawCommand(new SkDrawPictureCommand(picture)); 330} 331 332void SkDebugCanvas::drawPoints(PointMode mode, size_t count, 333 const SkPoint pts[], const SkPaint& paint) { 334 addDrawCommand(new SkDrawPointsCommand(mode, count, pts, paint)); 335} 336 337void SkDebugCanvas::drawPosText(const void* text, size_t byteLength, 338 const SkPoint pos[], const SkPaint& paint) { 339 addDrawCommand(new SkDrawPosTextCommand(text, byteLength, pos, paint)); 340} 341 342void SkDebugCanvas::drawPosTextH(const void* text, size_t byteLength, 343 const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { 344 addDrawCommand( 345 new SkDrawPosTextHCommand(text, byteLength, xpos, constY, paint)); 346} 347 348void SkDebugCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { 349 // NOTE(chudy): Messing up when renamed to DrawRect... Why? 350 addDrawCommand(new SkDrawRectCommand(rect, paint)); 351} 352 353void SkDebugCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 354 addDrawCommand(new SkDrawRRectCommand(rrect, paint)); 355} 356 357void SkDebugCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, 358 const SkPaint* paint = NULL) { 359 addDrawCommand(new SkDrawSpriteCommand(bitmap, left, top, paint)); 360} 361 362void SkDebugCanvas::drawText(const void* text, size_t byteLength, SkScalar x, 363 SkScalar y, const SkPaint& paint) { 364 addDrawCommand(new SkDrawTextCommand(text, byteLength, x, y, paint)); 365} 366 367void SkDebugCanvas::drawTextOnPath(const void* text, size_t byteLength, 368 const SkPath& path, const SkMatrix* matrix, const SkPaint& paint) { 369 addDrawCommand( 370 new SkDrawTextOnPathCommand(text, byteLength, path, matrix, paint)); 371} 372 373void SkDebugCanvas::drawVertices(VertexMode vmode, int vertexCount, 374 const SkPoint vertices[], const SkPoint texs[], const SkColor colors[], 375 SkXfermode*, const uint16_t indices[], int indexCount, 376 const SkPaint& paint) { 377 addDrawCommand(new SkDrawVerticesCommand(vmode, vertexCount, vertices, 378 texs, colors, NULL, indices, indexCount, paint)); 379} 380 381void SkDebugCanvas::restore() { 382 addDrawCommand(new SkRestoreCommand()); 383} 384 385bool SkDebugCanvas::rotate(SkScalar degrees) { 386 addDrawCommand(new SkRotateCommand(degrees)); 387 return true; 388} 389 390int SkDebugCanvas::save(SaveFlags flags) { 391 addDrawCommand(new SkSaveCommand(flags)); 392 return true; 393} 394 395int SkDebugCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 396 SaveFlags flags) { 397 addDrawCommand(new SkSaveLayerCommand(bounds, paint, flags)); 398 return true; 399} 400 401bool SkDebugCanvas::scale(SkScalar sx, SkScalar sy) { 402 addDrawCommand(new SkScaleCommand(sx, sy)); 403 return true; 404} 405 406void SkDebugCanvas::setMatrix(const SkMatrix& matrix) { 407 addDrawCommand(new SkSetMatrixCommand(matrix)); 408} 409 410bool SkDebugCanvas::skew(SkScalar sx, SkScalar sy) { 411 addDrawCommand(new SkSkewCommand(sx, sy)); 412 return true; 413} 414 415bool SkDebugCanvas::translate(SkScalar dx, SkScalar dy) { 416 addDrawCommand(new SkTranslateCommand(dx, dy)); 417 return true; 418} 419 420void SkDebugCanvas::toggleCommand(int index, bool toggle) { 421 SkASSERT(index < fCommandVector.count()); 422 fCommandVector[index]->setVisible(toggle); 423} 424