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