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