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