1 /* 2 * Copyright 2008 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkCanvas.h" 9 #include "SkCanvasPriv.h" 10 #include "SkBitmapDevice.h" 11 #include "SkColorFilter.h" 12 #include "SkDeviceImageFilterProxy.h" 13 #include "SkDraw.h" 14 #include "SkDrawable.h" 15 #include "SkDrawFilter.h" 16 #include "SkDrawLooper.h" 17 #include "SkErrorInternals.h" 18 #include "SkImage.h" 19 #include "SkMetaData.h" 20 #include "SkPathOps.h" 21 #include "SkPatchUtils.h" 22 #include "SkPicture.h" 23 #include "SkRasterClip.h" 24 #include "SkReadPixelsRec.h" 25 #include "SkRRect.h" 26 #include "SkSmallAllocator.h" 27 #include "SkSurface_Base.h" 28 #include "SkTemplates.h" 29 #include "SkTextBlob.h" 30 #include "SkTextFormatParams.h" 31 #include "SkTLazy.h" 32 #include "SkTraceEvent.h" 33 #include "SkUtils.h" 34 35 #if SK_SUPPORT_GPU 36 #include "GrRenderTarget.h" 37 #endif 38 39 static bool gIgnoreSaveLayerBounds; 40 void SkCanvas::Internal_Private_SetIgnoreSaveLayerBounds(bool ignore) { 41 gIgnoreSaveLayerBounds = ignore; 42 } 43 bool SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds() { 44 return gIgnoreSaveLayerBounds; 45 } 46 47 static bool gTreatSpriteAsBitmap; 48 void SkCanvas::Internal_Private_SetTreatSpriteAsBitmap(bool spriteAsBitmap) { 49 gTreatSpriteAsBitmap = spriteAsBitmap; 50 } 51 bool SkCanvas::Internal_Private_GetTreatSpriteAsBitmap() { 52 return gTreatSpriteAsBitmap; 53 } 54 55 // experimental for faster tiled drawing... 56 //#define SK_ENABLE_CLIP_QUICKREJECT 57 58 //#define SK_TRACE_SAVERESTORE 59 60 #ifdef SK_TRACE_SAVERESTORE 61 static int gLayerCounter; 62 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 63 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 64 65 static int gRecCounter; 66 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 67 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 68 69 static int gCanvasCounter; 70 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 71 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 72 #else 73 #define inc_layer() 74 #define dec_layer() 75 #define inc_rec() 76 #define dec_rec() 77 #define inc_canvas() 78 #define dec_canvas() 79 #endif 80 81 typedef SkTLazy<SkPaint> SkLazyPaint; 82 83 void SkCanvas::predrawNotify() { 84 if (fSurfaceBase) { 85 fSurfaceBase->aboutToDraw(SkSurface::kRetain_ContentChangeMode); 86 } 87 } 88 89 /////////////////////////////////////////////////////////////////////////////// 90 91 static uint32_t filter_paint_flags(const SkSurfaceProps& props, uint32_t flags) { 92 const uint32_t propFlags = props.flags(); 93 if (propFlags & SkSurfaceProps::kDisallowDither_Flag) { 94 flags &= ~SkPaint::kDither_Flag; 95 } 96 if (propFlags & SkSurfaceProps::kDisallowAntiAlias_Flag) { 97 flags &= ~SkPaint::kAntiAlias_Flag; 98 } 99 return flags; 100 } 101 102 /////////////////////////////////////////////////////////////////////////////// 103 104 /* This is the record we keep for each SkBaseDevice that the user installs. 105 The clip/matrix/proc are fields that reflect the top of the save/restore 106 stack. Whenever the canvas changes, it marks a dirty flag, and then before 107 these are used (assuming we're not on a layer) we rebuild these cache 108 values: they reflect the top of the save stack, but translated and clipped 109 by the device's XY offset and bitmap-bounds. 110 */ 111 struct DeviceCM { 112 DeviceCM* fNext; 113 SkBaseDevice* fDevice; 114 SkRasterClip fClip; 115 SkPaint* fPaint; // may be null (in the future) 116 const SkMatrix* fMatrix; 117 SkMatrix fMatrixStorage; 118 const bool fDeviceIsBitmapDevice; 119 120 DeviceCM(SkBaseDevice* device, const SkPaint* paint, SkCanvas* canvas, 121 bool conservativeRasterClip, bool deviceIsBitmapDevice) 122 : fNext(NULL) 123 , fClip(conservativeRasterClip) 124 , fDeviceIsBitmapDevice(deviceIsBitmapDevice) 125 { 126 if (NULL != device) { 127 device->ref(); 128 device->onAttachToCanvas(canvas); 129 } 130 fDevice = device; 131 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 132 } 133 134 ~DeviceCM() { 135 if (fDevice) { 136 fDevice->onDetachFromCanvas(); 137 fDevice->unref(); 138 } 139 SkDELETE(fPaint); 140 } 141 142 void reset(const SkIRect& bounds) { 143 SkASSERT(!fPaint); 144 SkASSERT(!fNext); 145 SkASSERT(fDevice); 146 fClip.setRect(bounds); 147 } 148 149 void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 150 const SkClipStack& clipStack, SkRasterClip* updateClip) { 151 int x = fDevice->getOrigin().x(); 152 int y = fDevice->getOrigin().y(); 153 int width = fDevice->width(); 154 int height = fDevice->height(); 155 156 if ((x | y) == 0) { 157 fMatrix = &totalMatrix; 158 fClip = totalClip; 159 } else { 160 fMatrixStorage = totalMatrix; 161 fMatrixStorage.postTranslate(SkIntToScalar(-x), 162 SkIntToScalar(-y)); 163 fMatrix = &fMatrixStorage; 164 165 totalClip.translate(-x, -y, &fClip); 166 } 167 168 fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 169 170 // intersect clip, but don't translate it (yet) 171 172 if (updateClip) { 173 updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 174 SkRegion::kDifference_Op); 175 } 176 177 fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 178 179 #ifdef SK_DEBUG 180 if (!fClip.isEmpty()) { 181 SkIRect deviceR; 182 deviceR.set(0, 0, width, height); 183 SkASSERT(deviceR.contains(fClip.getBounds())); 184 } 185 #endif 186 } 187 }; 188 189 /* This is the record we keep for each save/restore level in the stack. 190 Since a level optionally copies the matrix and/or stack, we have pointers 191 for these fields. If the value is copied for this level, the copy is 192 stored in the ...Storage field, and the pointer points to that. If the 193 value is not copied for this level, we ignore ...Storage, and just point 194 at the corresponding value in the previous level in the stack. 195 */ 196 class SkCanvas::MCRec { 197 public: 198 SkDrawFilter* fFilter; // the current filter (or null) 199 DeviceCM* fLayer; 200 /* If there are any layers in the stack, this points to the top-most 201 one that is at or below this level in the stack (so we know what 202 bitmap/device to draw into from this level. This value is NOT 203 reference counted, since the real owner is either our fLayer field, 204 or a previous one in a lower level.) 205 */ 206 DeviceCM* fTopLayer; 207 SkRasterClip fRasterClip; 208 SkMatrix fMatrix; 209 int fDeferredSaveCount; 210 211 MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) { 212 fFilter = NULL; 213 fLayer = NULL; 214 fTopLayer = NULL; 215 fMatrix.reset(); 216 fDeferredSaveCount = 0; 217 218 // don't bother initializing fNext 219 inc_rec(); 220 } 221 MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) { 222 fFilter = SkSafeRef(prev.fFilter); 223 fLayer = NULL; 224 fTopLayer = prev.fTopLayer; 225 fDeferredSaveCount = 0; 226 227 // don't bother initializing fNext 228 inc_rec(); 229 } 230 ~MCRec() { 231 SkSafeUnref(fFilter); 232 SkDELETE(fLayer); 233 dec_rec(); 234 } 235 236 void reset(const SkIRect& bounds) { 237 SkASSERT(fLayer); 238 SkASSERT(fDeferredSaveCount == 0); 239 240 fMatrix.reset(); 241 fRasterClip.setRect(bounds); 242 fLayer->reset(bounds); 243 } 244 }; 245 246 class SkDrawIter : public SkDraw { 247 public: 248 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 249 canvas = canvas->canvasForDrawIter(); 250 fCanvas = canvas; 251 canvas->updateDeviceCMCache(); 252 253 fClipStack = canvas->fClipStack; 254 fCurrLayer = canvas->fMCRec->fTopLayer; 255 fSkipEmptyClips = skipEmptyClips; 256 } 257 258 bool next() { 259 // skip over recs with empty clips 260 if (fSkipEmptyClips) { 261 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 262 fCurrLayer = fCurrLayer->fNext; 263 } 264 } 265 266 const DeviceCM* rec = fCurrLayer; 267 if (rec && rec->fDevice) { 268 269 fMatrix = rec->fMatrix; 270 fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW(); 271 fRC = &rec->fClip; 272 fDevice = rec->fDevice; 273 fBitmap = &fDevice->accessBitmap(true); 274 fPaint = rec->fPaint; 275 SkDEBUGCODE(this->validate();) 276 277 fCurrLayer = rec->fNext; 278 // fCurrLayer may be NULL now 279 280 return true; 281 } 282 return false; 283 } 284 285 SkBaseDevice* getDevice() const { return fDevice; } 286 int getX() const { return fDevice->getOrigin().x(); } 287 int getY() const { return fDevice->getOrigin().y(); } 288 const SkMatrix& getMatrix() const { return *fMatrix; } 289 const SkRegion& getClip() const { return *fClip; } 290 const SkPaint* getPaint() const { return fPaint; } 291 292 private: 293 SkCanvas* fCanvas; 294 const DeviceCM* fCurrLayer; 295 const SkPaint* fPaint; // May be null. 296 SkBool8 fSkipEmptyClips; 297 298 typedef SkDraw INHERITED; 299 }; 300 301 ///////////////////////////////////////////////////////////////////////////// 302 303 static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) { 304 return lazy->isValid() ? lazy->get() : lazy->set(orig); 305 } 306 307 /** 308 * If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that 309 * colorfilter, else return NULL. 310 */ 311 static SkColorFilter* image_to_color_filter(const SkPaint& paint) { 312 SkImageFilter* imgf = paint.getImageFilter(); 313 if (!imgf) { 314 return NULL; 315 } 316 317 SkColorFilter* imgCF; 318 if (!imgf->asAColorFilter(&imgCF)) { 319 return NULL; 320 } 321 322 SkColorFilter* paintCF = paint.getColorFilter(); 323 if (NULL == paintCF) { 324 // there is no existing paint colorfilter, so we can just return the imagefilter's 325 return imgCF; 326 } 327 328 // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF) 329 // and we need to combine them into a single colorfilter. 330 SkAutoTUnref<SkColorFilter> autoImgCF(imgCF); 331 return SkColorFilter::CreateComposeFilter(imgCF, paintCF); 332 } 333 334 class AutoDrawLooper { 335 public: 336 AutoDrawLooper(SkCanvas* canvas, const SkSurfaceProps& props, const SkPaint& paint, 337 bool skipLayerForImageFilter = false, 338 const SkRect* bounds = NULL) : fOrigPaint(paint) { 339 fCanvas = canvas; 340 fFilter = canvas->getDrawFilter(); 341 fPaint = &fOrigPaint; 342 fSaveCount = canvas->getSaveCount(); 343 fTempLayerForImageFilter = false; 344 fDone = false; 345 346 SkColorFilter* simplifiedCF = image_to_color_filter(fOrigPaint); 347 if (simplifiedCF) { 348 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint); 349 paint->setColorFilter(simplifiedCF)->unref(); 350 paint->setImageFilter(NULL); 351 fPaint = paint; 352 } 353 354 if (!skipLayerForImageFilter && fPaint->getImageFilter()) { 355 /** 356 * We implement ImageFilters for a given draw by creating a layer, then applying the 357 * imagefilter to the pixels of that layer (its backing surface/image), and then 358 * we call restore() to xfer that layer to the main canvas. 359 * 360 * 1. SaveLayer (with a paint containing the current imagefilter and xfermode) 361 * 2. Generate the src pixels: 362 * Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper) 363 * return (fPaint). We then draw the primitive (using srcover) into a cleared 364 * buffer/surface. 365 * 3. Restore the layer created in #1 366 * The imagefilter is passed the buffer/surface from the layer (now filled with the 367 * src pixels of the primitive). It returns a new "filtered" buffer, which we 368 * draw onto the previous layer using the xfermode from the original paint. 369 */ 370 SkPaint tmp; 371 tmp.setImageFilter(fPaint->getImageFilter()); 372 tmp.setXfermode(fPaint->getXfermode()); 373 (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, 374 SkCanvas::kFullLayer_SaveLayerStrategy); 375 fTempLayerForImageFilter = true; 376 // we remove the imagefilter/xfermode inside doNext() 377 } 378 379 if (SkDrawLooper* looper = paint.getLooper()) { 380 void* buffer = fLooperContextAllocator.reserveT<SkDrawLooper::Context>( 381 looper->contextSize()); 382 fLooperContext = looper->createContext(canvas, buffer); 383 fIsSimple = false; 384 } else { 385 fLooperContext = NULL; 386 // can we be marked as simple? 387 fIsSimple = !fFilter && !fTempLayerForImageFilter; 388 } 389 390 uint32_t oldFlags = paint.getFlags(); 391 fNewPaintFlags = filter_paint_flags(props, oldFlags); 392 if (fIsSimple && (fNewPaintFlags != oldFlags)) { 393 SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint); 394 paint->setFlags(fNewPaintFlags); 395 fPaint = paint; 396 // if we're not simple, doNext() will take care of calling setFlags() 397 } 398 } 399 400 ~AutoDrawLooper() { 401 if (fTempLayerForImageFilter) { 402 fCanvas->internalRestore(); 403 } 404 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 405 } 406 407 const SkPaint& paint() const { 408 SkASSERT(fPaint); 409 return *fPaint; 410 } 411 412 bool next(SkDrawFilter::Type drawType) { 413 if (fDone) { 414 return false; 415 } else if (fIsSimple) { 416 fDone = true; 417 return !fPaint->nothingToDraw(); 418 } else { 419 return this->doNext(drawType); 420 } 421 } 422 423 private: 424 SkLazyPaint fLazyPaintInit; // base paint storage in case we need to modify it 425 SkLazyPaint fLazyPaintPerLooper; // per-draw-looper storage, so the looper can modify it 426 SkCanvas* fCanvas; 427 const SkPaint& fOrigPaint; 428 SkDrawFilter* fFilter; 429 const SkPaint* fPaint; 430 int fSaveCount; 431 uint32_t fNewPaintFlags; 432 bool fTempLayerForImageFilter; 433 bool fDone; 434 bool fIsSimple; 435 SkDrawLooper::Context* fLooperContext; 436 SkSmallAllocator<1, 32> fLooperContextAllocator; 437 438 bool doNext(SkDrawFilter::Type drawType); 439 }; 440 441 bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { 442 fPaint = NULL; 443 SkASSERT(!fIsSimple); 444 SkASSERT(fLooperContext || fFilter || fTempLayerForImageFilter); 445 446 SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ? 447 *fLazyPaintInit.get() : fOrigPaint); 448 paint->setFlags(fNewPaintFlags); 449 450 if (fTempLayerForImageFilter) { 451 paint->setImageFilter(NULL); 452 paint->setXfermode(NULL); 453 } 454 455 if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { 456 fDone = true; 457 return false; 458 } 459 if (fFilter) { 460 if (!fFilter->filter(paint, drawType)) { 461 fDone = true; 462 return false; 463 } 464 if (NULL == fLooperContext) { 465 // no looper means we only draw once 466 fDone = true; 467 } 468 } 469 fPaint = paint; 470 471 // if we only came in here for the imagefilter, mark us as done 472 if (!fLooperContext && !fFilter) { 473 fDone = true; 474 } 475 476 // call this after any possible paint modifiers 477 if (fPaint->nothingToDraw()) { 478 fPaint = NULL; 479 return false; 480 } 481 return true; 482 } 483 484 ////////// macros to place around the internal draw calls ////////////////// 485 486 #define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ 487 this->predrawNotify(); \ 488 AutoDrawLooper looper(this, fProps, paint, true); \ 489 while (looper.next(type)) { \ 490 SkDrawIter iter(this); 491 492 #define LOOPER_BEGIN(paint, type, bounds) \ 493 this->predrawNotify(); \ 494 AutoDrawLooper looper(this, fProps, paint, false, bounds); \ 495 while (looper.next(type)) { \ 496 SkDrawIter iter(this); 497 498 #define LOOPER_END } 499 500 //////////////////////////////////////////////////////////////////////////// 501 502 void SkCanvas::resetForNextPicture(const SkIRect& bounds) { 503 this->restoreToCount(1); 504 fCachedLocalClipBounds.setEmpty(); 505 fCachedLocalClipBoundsDirty = true; 506 fClipStack->reset(); 507 fMCRec->reset(bounds); 508 509 // We're peering through a lot of structs here. Only at this scope do we 510 // know that the device is an SkBitmapDevice (really an SkNoPixelsBitmapDevice). 511 static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size()); 512 } 513 514 SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { 515 fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag); 516 fCachedLocalClipBounds.setEmpty(); 517 fCachedLocalClipBoundsDirty = true; 518 fAllowSoftClip = true; 519 fAllowSimplifyClip = false; 520 fDeviceCMDirty = true; 521 fSaveCount = 1; 522 fMetaData = NULL; 523 524 fClipStack.reset(SkNEW(SkClipStack)); 525 526 fMCRec = (MCRec*)fMCStack.push_back(); 527 new (fMCRec) MCRec(fConservativeRasterClip); 528 529 SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage)); 530 fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage; 531 new (fDeviceCMStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip, false); 532 533 fMCRec->fTopLayer = fMCRec->fLayer; 534 535 fSurfaceBase = NULL; 536 537 if (device) { 538 device->initForRootLayer(fProps.pixelGeometry()); 539 if (device->forceConservativeRasterClip()) { 540 fConservativeRasterClip = true; 541 } 542 device->onAttachToCanvas(this); 543 fMCRec->fLayer->fDevice = SkRef(device); 544 fMCRec->fRasterClip.setRect(device->getGlobalBounds()); 545 } 546 return device; 547 } 548 549 SkCanvas::SkCanvas() 550 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 551 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 552 { 553 inc_canvas(); 554 555 this->init(NULL, kDefault_InitFlags); 556 } 557 558 static SkBitmap make_nopixels(int width, int height) { 559 SkBitmap bitmap; 560 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); 561 return bitmap; 562 } 563 564 class SkNoPixelsBitmapDevice : public SkBitmapDevice { 565 public: 566 SkNoPixelsBitmapDevice(const SkIRect& bounds) 567 : INHERITED(make_nopixels(bounds.width(), bounds.height())) 568 { 569 this->setOrigin(bounds.x(), bounds.y()); 570 } 571 572 private: 573 574 typedef SkBitmapDevice INHERITED; 575 }; 576 577 SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props) 578 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 579 , fProps(SkSurfacePropsCopyOrDefault(props)) 580 { 581 inc_canvas(); 582 583 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, 584 (SkIRect::MakeWH(width, height))), kDefault_InitFlags)->unref(); 585 } 586 587 SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags) 588 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 589 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 590 { 591 inc_canvas(); 592 593 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (bounds)), flags)->unref(); 594 } 595 596 SkCanvas::SkCanvas(SkBaseDevice* device, const SkSurfaceProps* props, InitFlags flags) 597 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 598 , fProps(SkSurfacePropsCopyOrDefault(props)) 599 { 600 inc_canvas(); 601 602 this->init(device, flags); 603 } 604 605 SkCanvas::SkCanvas(SkBaseDevice* device) 606 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 607 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 608 { 609 inc_canvas(); 610 611 this->init(device, kDefault_InitFlags); 612 } 613 614 SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) 615 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 616 , fProps(props) 617 { 618 inc_canvas(); 619 620 SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); 621 this->init(device, kDefault_InitFlags); 622 } 623 624 SkCanvas::SkCanvas(const SkBitmap& bitmap) 625 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) 626 , fProps(SkSurfaceProps::kLegacyFontHost_InitType) 627 { 628 inc_canvas(); 629 630 SkAutoTUnref<SkBaseDevice> device(SkNEW_ARGS(SkBitmapDevice, (bitmap))); 631 this->init(device, kDefault_InitFlags); 632 } 633 634 SkCanvas::~SkCanvas() { 635 // free up the contents of our deque 636 this->restoreToCount(1); // restore everything but the last 637 638 this->internalRestore(); // restore the last, since we're going away 639 640 SkDELETE(fMetaData); 641 642 dec_canvas(); 643 } 644 645 SkDrawFilter* SkCanvas::getDrawFilter() const { 646 return fMCRec->fFilter; 647 } 648 649 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 650 this->checkForDeferredSave(); 651 SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 652 return filter; 653 } 654 655 SkMetaData& SkCanvas::getMetaData() { 656 // metadata users are rare, so we lazily allocate it. If that changes we 657 // can decide to just make it a field in the device (rather than a ptr) 658 if (NULL == fMetaData) { 659 fMetaData = new SkMetaData; 660 } 661 return *fMetaData; 662 } 663 664 /////////////////////////////////////////////////////////////////////////////// 665 666 void SkCanvas::flush() { 667 SkBaseDevice* device = this->getDevice(); 668 if (device) { 669 device->flush(); 670 } 671 } 672 673 SkISize SkCanvas::getTopLayerSize() const { 674 SkBaseDevice* d = this->getTopDevice(); 675 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 676 } 677 678 SkIPoint SkCanvas::getTopLayerOrigin() const { 679 SkBaseDevice* d = this->getTopDevice(); 680 return d ? d->getOrigin() : SkIPoint::Make(0, 0); 681 } 682 683 SkISize SkCanvas::getBaseLayerSize() const { 684 SkBaseDevice* d = this->getDevice(); 685 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 686 } 687 688 SkBaseDevice* SkCanvas::getDevice() const { 689 // return root device 690 MCRec* rec = (MCRec*) fMCStack.front(); 691 SkASSERT(rec && rec->fLayer); 692 return rec->fLayer->fDevice; 693 } 694 695 SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const { 696 if (updateMatrixClip) { 697 const_cast<SkCanvas*>(this)->updateDeviceCMCache(); 698 } 699 return fMCRec->fTopLayer->fDevice; 700 } 701 702 bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) { 703 if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) { 704 return false; 705 } 706 707 bool weAllocated = false; 708 if (NULL == bitmap->pixelRef()) { 709 if (!bitmap->tryAllocPixels()) { 710 return false; 711 } 712 weAllocated = true; 713 } 714 715 SkBitmap bm(*bitmap); 716 bm.lockPixels(); 717 if (bm.getPixels() && this->readPixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y)) { 718 return true; 719 } 720 721 if (weAllocated) { 722 bitmap->setPixelRef(NULL); 723 } 724 return false; 725 } 726 727 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 728 SkIRect r = srcRect; 729 const SkISize size = this->getBaseLayerSize(); 730 if (!r.intersect(0, 0, size.width(), size.height())) { 731 bitmap->reset(); 732 return false; 733 } 734 735 if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) { 736 // bitmap will already be reset. 737 return false; 738 } 739 if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) { 740 bitmap->reset(); 741 return false; 742 } 743 return true; 744 } 745 746 bool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) { 747 SkBaseDevice* device = this->getDevice(); 748 if (!device) { 749 return false; 750 } 751 const SkISize size = this->getBaseLayerSize(); 752 753 SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y); 754 if (!rec.trim(size.width(), size.height())) { 755 return false; 756 } 757 758 // The device can assert that the requested area is always contained in its bounds 759 return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY); 760 } 761 762 bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 763 if (bitmap.getTexture()) { 764 return false; 765 } 766 SkBitmap bm(bitmap); 767 bm.lockPixels(); 768 if (bm.getPixels()) { 769 return this->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y); 770 } 771 return false; 772 } 773 774 bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes, 775 int x, int y) { 776 switch (origInfo.colorType()) { 777 case kUnknown_SkColorType: 778 case kIndex_8_SkColorType: 779 return false; 780 default: 781 break; 782 } 783 if (NULL == pixels || rowBytes < origInfo.minRowBytes()) { 784 return false; 785 } 786 787 const SkISize size = this->getBaseLayerSize(); 788 SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height()); 789 if (!target.intersect(0, 0, size.width(), size.height())) { 790 return false; 791 } 792 793 SkBaseDevice* device = this->getDevice(); 794 if (!device) { 795 return false; 796 } 797 798 // the intersect may have shrunk info's logical size 799 const SkImageInfo info = origInfo.makeWH(target.width(), target.height()); 800 801 // if x or y are negative, then we have to adjust pixels 802 if (x > 0) { 803 x = 0; 804 } 805 if (y > 0) { 806 y = 0; 807 } 808 // here x,y are either 0 or negative 809 pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel()); 810 811 // Tell our owning surface to bump its generation ID 812 this->predrawNotify(); 813 814 // The device can assert that the requested area is always contained in its bounds 815 return device->writePixels(info, pixels, rowBytes, target.x(), target.y()); 816 } 817 818 SkCanvas* SkCanvas::canvasForDrawIter() { 819 return this; 820 } 821 822 ////////////////////////////////////////////////////////////////////////////// 823 824 void SkCanvas::updateDeviceCMCache() { 825 if (fDeviceCMDirty) { 826 const SkMatrix& totalMatrix = this->getTotalMatrix(); 827 const SkRasterClip& totalClip = fMCRec->fRasterClip; 828 DeviceCM* layer = fMCRec->fTopLayer; 829 830 if (NULL == layer->fNext) { // only one layer 831 layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL); 832 } else { 833 SkRasterClip clip(totalClip); 834 do { 835 layer->updateMC(totalMatrix, clip, *fClipStack, &clip); 836 } while ((layer = layer->fNext) != NULL); 837 } 838 fDeviceCMDirty = false; 839 } 840 } 841 842 /////////////////////////////////////////////////////////////////////////////// 843 844 void SkCanvas::checkForDeferredSave() { 845 if (fMCRec->fDeferredSaveCount > 0) { 846 this->doSave(); 847 } 848 } 849 850 int SkCanvas::getSaveCount() const { 851 #ifdef SK_DEBUG 852 int count = 0; 853 SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart); 854 for (;;) { 855 const MCRec* rec = (const MCRec*)iter.next(); 856 if (!rec) { 857 break; 858 } 859 count += 1 + rec->fDeferredSaveCount; 860 } 861 SkASSERT(count == fSaveCount); 862 #endif 863 return fSaveCount; 864 } 865 866 int SkCanvas::save() { 867 fSaveCount += 1; 868 fMCRec->fDeferredSaveCount += 1; 869 return this->getSaveCount() - 1; // return our prev value 870 } 871 872 void SkCanvas::doSave() { 873 this->willSave(); 874 875 SkASSERT(fMCRec->fDeferredSaveCount > 0); 876 fMCRec->fDeferredSaveCount -= 1; 877 this->internalSave(); 878 } 879 880 void SkCanvas::restore() { 881 if (fMCRec->fDeferredSaveCount > 0) { 882 SkASSERT(fSaveCount > 1); 883 fSaveCount -= 1; 884 fMCRec->fDeferredSaveCount -= 1; 885 } else { 886 // check for underflow 887 if (fMCStack.count() > 1) { 888 this->willRestore(); 889 SkASSERT(fSaveCount > 1); 890 fSaveCount -= 1; 891 this->internalRestore(); 892 this->didRestore(); 893 } 894 } 895 } 896 897 void SkCanvas::restoreToCount(int count) { 898 // sanity check 899 if (count < 1) { 900 count = 1; 901 } 902 903 int n = this->getSaveCount() - count; 904 for (int i = 0; i < n; ++i) { 905 this->restore(); 906 } 907 } 908 909 void SkCanvas::internalSave() { 910 MCRec* newTop = (MCRec*)fMCStack.push_back(); 911 new (newTop) MCRec(*fMCRec); // balanced in restore() 912 fMCRec = newTop; 913 914 fClipStack->save(); 915 } 916 917 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 918 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 919 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 920 #else 921 return true; 922 #endif 923 } 924 925 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, 926 SkIRect* intersection, const SkImageFilter* imageFilter) { 927 SkIRect clipBounds; 928 if (!this->getClipDeviceBounds(&clipBounds)) { 929 return false; 930 } 931 932 const SkMatrix& ctm = fMCRec->fMatrix; // this->getTotalMatrix() 933 934 if (imageFilter) { 935 imageFilter->filterBounds(clipBounds, ctm, &clipBounds); 936 } 937 SkIRect ir; 938 if (bounds) { 939 SkRect r; 940 941 ctm.mapRect(&r, *bounds); 942 r.roundOut(&ir); 943 // early exit if the layer's bounds are clipped out 944 if (!ir.intersect(clipBounds)) { 945 if (bounds_affects_clip(flags)) { 946 fCachedLocalClipBoundsDirty = true; 947 fMCRec->fRasterClip.setEmpty(); 948 } 949 return false; 950 } 951 } else { // no user bounds, so just use the clip 952 ir = clipBounds; 953 } 954 SkASSERT(!ir.isEmpty()); 955 956 if (bounds_affects_clip(flags)) { 957 // Simplify the current clips since they will be applied properly during restore() 958 fCachedLocalClipBoundsDirty = true; 959 fClipStack->clipDevRect(ir, SkRegion::kReplace_Op); 960 fMCRec->fRasterClip.setRect(ir); 961 } 962 963 if (intersection) { 964 *intersection = ir; 965 } 966 return true; 967 } 968 969 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) { 970 if (gIgnoreSaveLayerBounds) { 971 bounds = NULL; 972 } 973 SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag); 974 fSaveCount += 1; 975 this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy); 976 return this->getSaveCount() - 1; 977 } 978 979 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) { 980 if (gIgnoreSaveLayerBounds) { 981 bounds = NULL; 982 } 983 SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags); 984 fSaveCount += 1; 985 this->internalSaveLayer(bounds, paint, flags, strategy); 986 return this->getSaveCount() - 1; 987 } 988 989 void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags, 990 SaveLayerStrategy strategy) { 991 #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 992 flags |= kClipToLayer_SaveFlag; 993 #endif 994 995 // do this before we create the layer. We don't call the public save() since 996 // that would invoke a possibly overridden virtual 997 this->internalSave(); 998 999 fDeviceCMDirty = true; 1000 1001 SkIRect ir; 1002 if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) { 1003 return; 1004 } 1005 1006 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 1007 // the clipRectBounds() call above? 1008 if (kNoLayer_SaveLayerStrategy == strategy) { 1009 return; 1010 } 1011 1012 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); 1013 SkPixelGeometry geo = fProps.pixelGeometry(); 1014 if (paint) { 1015 // TODO: perhaps add a query to filters so we might preserve opaqueness... 1016 if (paint->getImageFilter() || paint->getColorFilter()) { 1017 isOpaque = false; 1018 geo = kUnknown_SkPixelGeometry; 1019 } 1020 } 1021 SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(), 1022 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 1023 1024 SkBaseDevice* device = this->getTopDevice(); 1025 if (NULL == device) { 1026 SkDebugf("Unable to find device for layer."); 1027 return; 1028 } 1029 1030 bool forceSpriteOnRestore = false; 1031 { 1032 const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage; 1033 const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo); 1034 SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint); 1035 if (NULL == newDev) { 1036 // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint) 1037 newDev = SkBitmapDevice::Create(createInfo.fInfo); 1038 if (NULL == newDev) { 1039 SkErrorInternals::SetError(kInternalError_SkError, 1040 "Unable to create device for layer."); 1041 return; 1042 } 1043 forceSpriteOnRestore = true; 1044 } 1045 device = newDev; 1046 } 1047 1048 device->setOrigin(ir.fLeft, ir.fTop); 1049 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip, 1050 forceSpriteOnRestore)); 1051 device->unref(); 1052 1053 layer->fNext = fMCRec->fTopLayer; 1054 fMCRec->fLayer = layer; 1055 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 1056 } 1057 1058 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 1059 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); 1060 } 1061 1062 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 1063 SaveFlags flags) { 1064 if (0xFF == alpha) { 1065 return this->saveLayer(bounds, NULL, flags); 1066 } else { 1067 SkPaint tmpPaint; 1068 tmpPaint.setAlpha(alpha); 1069 return this->saveLayer(bounds, &tmpPaint, flags); 1070 } 1071 } 1072 1073 void SkCanvas::internalRestore() { 1074 SkASSERT(fMCStack.count() != 0); 1075 1076 fDeviceCMDirty = true; 1077 fCachedLocalClipBoundsDirty = true; 1078 1079 fClipStack->restore(); 1080 1081 // reserve our layer (if any) 1082 DeviceCM* layer = fMCRec->fLayer; // may be null 1083 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 1084 fMCRec->fLayer = NULL; 1085 1086 // now do the normal restore() 1087 fMCRec->~MCRec(); // balanced in save() 1088 fMCStack.pop_back(); 1089 fMCRec = (MCRec*)fMCStack.back(); 1090 1091 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1092 since if we're being recorded, we don't want to record this (the 1093 recorder will have already recorded the restore). 1094 */ 1095 if (layer) { 1096 if (layer->fNext) { 1097 const SkIPoint& origin = layer->fDevice->getOrigin(); 1098 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1099 layer->fPaint, layer->fDeviceIsBitmapDevice); 1100 // reset this, since internalDrawDevice will have set it to true 1101 fDeviceCMDirty = true; 1102 SkDELETE(layer); 1103 } else { 1104 // we're at the root 1105 SkASSERT(layer == (void*)fDeviceCMStorage); 1106 layer->~DeviceCM(); 1107 } 1108 } 1109 } 1110 1111 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 1112 if (NULL == props) { 1113 props = &fProps; 1114 } 1115 return this->onNewSurface(info, *props); 1116 } 1117 1118 SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 1119 SkBaseDevice* dev = this->getDevice(); 1120 return dev ? dev->newSurface(info, props) : NULL; 1121 } 1122 1123 SkImageInfo SkCanvas::imageInfo() const { 1124 SkBaseDevice* dev = this->getDevice(); 1125 if (dev) { 1126 return dev->imageInfo(); 1127 } else { 1128 return SkImageInfo::MakeUnknown(0, 0); 1129 } 1130 } 1131 1132 const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1133 return this->onPeekPixels(info, rowBytes); 1134 } 1135 1136 const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) { 1137 SkBaseDevice* dev = this->getDevice(); 1138 return dev ? dev->peekPixels(info, rowBytes) : NULL; 1139 } 1140 1141 void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) { 1142 void* pixels = this->onAccessTopLayerPixels(info, rowBytes); 1143 if (pixels && origin) { 1144 *origin = this->getTopDevice(false)->getOrigin(); 1145 } 1146 return pixels; 1147 } 1148 1149 void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) { 1150 SkBaseDevice* dev = this->getTopDevice(); 1151 return dev ? dev->accessPixels(info, rowBytes) : NULL; 1152 } 1153 1154 SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) { 1155 fAddr = canvas->peekPixels(&fInfo, &fRowBytes); 1156 if (NULL == fAddr) { 1157 fInfo = canvas->imageInfo(); 1158 if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) { 1159 return; // failure, fAddr is NULL 1160 } 1161 if (!canvas->readPixels(&fBitmap, 0, 0)) { 1162 return; // failure, fAddr is NULL 1163 } 1164 fAddr = fBitmap.getPixels(); 1165 fRowBytes = fBitmap.rowBytes(); 1166 } 1167 SkASSERT(fAddr); // success 1168 } 1169 1170 bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const { 1171 if (fAddr) { 1172 return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes); 1173 } else { 1174 bitmap->reset(); 1175 return false; 1176 } 1177 } 1178 1179 ///////////////////////////////////////////////////////////////////////////// 1180 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 1181 const SkMatrix& matrix, const SkPaint* paint) { 1182 if (bitmap.drawsNothing()) { 1183 return; 1184 } 1185 1186 SkLazyPaint lazy; 1187 if (NULL == paint) { 1188 paint = lazy.init(); 1189 } 1190 1191 SkDEBUGCODE(bitmap.validate();) 1192 1193 SkRect storage; 1194 const SkRect* bounds = NULL; 1195 if (paint && paint->canComputeFastBounds()) { 1196 bitmap.getBounds(&storage); 1197 matrix.mapRect(&storage); 1198 bounds = &paint->computeFastBounds(storage, &storage); 1199 } 1200 1201 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1202 1203 while (iter.next()) { 1204 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 1205 } 1206 1207 LOOPER_END 1208 } 1209 1210 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 1211 const SkPaint* paint, bool deviceIsBitmapDevice) { 1212 SkPaint tmp; 1213 if (NULL == paint) { 1214 paint = &tmp; 1215 } 1216 1217 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1218 while (iter.next()) { 1219 SkBaseDevice* dstDev = iter.fDevice; 1220 paint = &looper.paint(); 1221 SkImageFilter* filter = paint->getImageFilter(); 1222 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1223 if (filter && !dstDev->canHandleImageFilter(filter)) { 1224 SkDeviceImageFilterProxy proxy(dstDev, fProps); 1225 SkBitmap dst; 1226 SkIPoint offset = SkIPoint::Make(0, 0); 1227 const SkBitmap& src = srcDev->accessBitmap(false); 1228 SkMatrix matrix = *iter.fMatrix; 1229 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1230 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height()); 1231 SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache()); 1232 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1233 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) { 1234 SkPaint tmpUnfiltered(*paint); 1235 tmpUnfiltered.setImageFilter(NULL); 1236 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1237 tmpUnfiltered); 1238 } 1239 } else if (deviceIsBitmapDevice) { 1240 const SkBitmap& src = srcDev->accessBitmap(false); 1241 dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint); 1242 } else { 1243 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 1244 } 1245 } 1246 LOOPER_END 1247 } 1248 1249 void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) { 1250 if (gTreatSpriteAsBitmap) { 1251 this->save(); 1252 this->resetMatrix(); 1253 this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint); 1254 this->restore(); 1255 return; 1256 } 1257 1258 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()"); 1259 if (bitmap.drawsNothing()) { 1260 return; 1261 } 1262 SkDEBUGCODE(bitmap.validate();) 1263 1264 SkPaint tmp; 1265 if (NULL == paint) { 1266 paint = &tmp; 1267 } 1268 1269 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1270 1271 while (iter.next()) { 1272 paint = &looper.paint(); 1273 SkImageFilter* filter = paint->getImageFilter(); 1274 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1275 if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 1276 SkDeviceImageFilterProxy proxy(iter.fDevice, fProps); 1277 SkBitmap dst; 1278 SkIPoint offset = SkIPoint::Make(0, 0); 1279 SkMatrix matrix = *iter.fMatrix; 1280 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1281 const SkIRect clipBounds = bitmap.bounds(); 1282 SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache()); 1283 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1284 if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) { 1285 SkPaint tmpUnfiltered(*paint); 1286 tmpUnfiltered.setImageFilter(NULL); 1287 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1288 tmpUnfiltered); 1289 } 1290 } else { 1291 iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 1292 } 1293 } 1294 LOOPER_END 1295 } 1296 1297 ///////////////////////////////////////////////////////////////////////////// 1298 void SkCanvas::translate(SkScalar dx, SkScalar dy) { 1299 SkMatrix m; 1300 m.setTranslate(dx, dy); 1301 this->concat(m); 1302 } 1303 1304 void SkCanvas::scale(SkScalar sx, SkScalar sy) { 1305 SkMatrix m; 1306 m.setScale(sx, sy); 1307 this->concat(m); 1308 } 1309 1310 void SkCanvas::rotate(SkScalar degrees) { 1311 SkMatrix m; 1312 m.setRotate(degrees); 1313 this->concat(m); 1314 } 1315 1316 void SkCanvas::skew(SkScalar sx, SkScalar sy) { 1317 SkMatrix m; 1318 m.setSkew(sx, sy); 1319 this->concat(m); 1320 } 1321 1322 void SkCanvas::concat(const SkMatrix& matrix) { 1323 if (matrix.isIdentity()) { 1324 return; 1325 } 1326 1327 this->checkForDeferredSave(); 1328 fDeviceCMDirty = true; 1329 fCachedLocalClipBoundsDirty = true; 1330 fMCRec->fMatrix.preConcat(matrix); 1331 1332 this->didConcat(matrix); 1333 } 1334 1335 void SkCanvas::setMatrix(const SkMatrix& matrix) { 1336 this->checkForDeferredSave(); 1337 fDeviceCMDirty = true; 1338 fCachedLocalClipBoundsDirty = true; 1339 fMCRec->fMatrix = matrix; 1340 this->didSetMatrix(matrix); 1341 } 1342 1343 void SkCanvas::resetMatrix() { 1344 SkMatrix matrix; 1345 1346 matrix.reset(); 1347 this->setMatrix(matrix); 1348 } 1349 1350 ////////////////////////////////////////////////////////////////////////////// 1351 1352 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1353 this->checkForDeferredSave(); 1354 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1355 this->onClipRect(rect, op, edgeStyle); 1356 } 1357 1358 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1359 #ifdef SK_ENABLE_CLIP_QUICKREJECT 1360 if (SkRegion::kIntersect_Op == op) { 1361 if (fMCRec->fRasterClip.isEmpty()) { 1362 return false; 1363 } 1364 1365 if (this->quickReject(rect)) { 1366 fDeviceCMDirty = true; 1367 fCachedLocalClipBoundsDirty = true; 1368 1369 fClipStack->clipEmpty(); 1370 return fMCRec->fRasterClip.setEmpty(); 1371 } 1372 } 1373 #endif 1374 1375 AutoValidateClip avc(this); 1376 1377 fDeviceCMDirty = true; 1378 fCachedLocalClipBoundsDirty = true; 1379 if (!fAllowSoftClip) { 1380 edgeStyle = kHard_ClipEdgeStyle; 1381 } 1382 1383 if (fMCRec->fMatrix.rectStaysRect()) { 1384 // for these simpler matrices, we can stay a rect even after applying 1385 // the matrix. This means we don't have to a) make a path, and b) tell 1386 // the region code to scan-convert the path, only to discover that it 1387 // is really just a rect. 1388 SkRect r; 1389 1390 fMCRec->fMatrix.mapRect(&r, rect); 1391 fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); 1392 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle); 1393 } else { 1394 // since we're rotated or some such thing, we convert the rect to a path 1395 // and clip against that, since it can handle any matrix. However, to 1396 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1397 // we explicitly call "our" version of clipPath. 1398 SkPath path; 1399 1400 path.addRect(rect); 1401 this->SkCanvas::onClipPath(path, op, edgeStyle); 1402 } 1403 } 1404 1405 static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath, 1406 SkRegion::Op op, bool doAA) { 1407 rc->op(devPath, canvas->getBaseLayerSize(), op, doAA); 1408 } 1409 1410 void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1411 this->checkForDeferredSave(); 1412 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1413 if (rrect.isRect()) { 1414 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1415 } else { 1416 this->onClipRRect(rrect, op, edgeStyle); 1417 } 1418 } 1419 1420 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1421 SkRRect transformedRRect; 1422 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1423 AutoValidateClip avc(this); 1424 1425 fDeviceCMDirty = true; 1426 fCachedLocalClipBoundsDirty = true; 1427 if (!fAllowSoftClip) { 1428 edgeStyle = kHard_ClipEdgeStyle; 1429 } 1430 1431 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); 1432 1433 SkPath devPath; 1434 devPath.addRRect(transformedRRect); 1435 1436 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1437 return; 1438 } 1439 1440 SkPath path; 1441 path.addRRect(rrect); 1442 // call the non-virtual version 1443 this->SkCanvas::onClipPath(path, op, edgeStyle); 1444 } 1445 1446 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1447 this->checkForDeferredSave(); 1448 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1449 SkRect r; 1450 if (!path.isInverseFillType() && path.isRect(&r)) { 1451 this->onClipRect(r, op, edgeStyle); 1452 } else { 1453 this->onClipPath(path, op, edgeStyle); 1454 } 1455 } 1456 1457 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1458 #ifdef SK_ENABLE_CLIP_QUICKREJECT 1459 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1460 if (fMCRec->fRasterClip.isEmpty()) { 1461 return false; 1462 } 1463 1464 if (this->quickReject(path.getBounds())) { 1465 fDeviceCMDirty = true; 1466 fCachedLocalClipBoundsDirty = true; 1467 1468 fClipStack->clipEmpty(); 1469 return fMCRec->fRasterClip.setEmpty(); 1470 } 1471 } 1472 #endif 1473 1474 AutoValidateClip avc(this); 1475 1476 fDeviceCMDirty = true; 1477 fCachedLocalClipBoundsDirty = true; 1478 if (!fAllowSoftClip) { 1479 edgeStyle = kHard_ClipEdgeStyle; 1480 } 1481 1482 SkPath devPath; 1483 path.transform(fMCRec->fMatrix, &devPath); 1484 1485 // Check if the transfomation, or the original path itself 1486 // made us empty. Note this can also happen if we contained NaN 1487 // values. computing the bounds detects this, and will set our 1488 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1489 if (devPath.getBounds().isEmpty()) { 1490 // resetting the path will remove any NaN or other wanky values 1491 // that might upset our scan converter. 1492 devPath.reset(); 1493 } 1494 1495 // if we called path.swap() we could avoid a deep copy of this path 1496 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1497 1498 if (fAllowSimplifyClip) { 1499 bool clipIsAA = getClipStack()->asPath(&devPath); 1500 if (clipIsAA) { 1501 edgeStyle = kSoft_ClipEdgeStyle; 1502 } 1503 1504 op = SkRegion::kReplace_Op; 1505 } 1506 1507 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); 1508 } 1509 1510 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1511 this->checkForDeferredSave(); 1512 this->onClipRegion(rgn, op); 1513 } 1514 1515 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1516 AutoValidateClip avc(this); 1517 1518 fDeviceCMDirty = true; 1519 fCachedLocalClipBoundsDirty = true; 1520 1521 // todo: signal fClipStack that we have a region, and therefore (I guess) 1522 // we have to ignore it, and use the region directly? 1523 fClipStack->clipDevRect(rgn.getBounds(), op); 1524 1525 fMCRec->fRasterClip.op(rgn, op); 1526 } 1527 1528 #ifdef SK_DEBUG 1529 void SkCanvas::validateClip() const { 1530 // construct clipRgn from the clipstack 1531 const SkBaseDevice* device = this->getDevice(); 1532 if (!device) { 1533 SkASSERT(this->isClipEmpty()); 1534 return; 1535 } 1536 1537 SkIRect ir; 1538 ir.set(0, 0, device->width(), device->height()); 1539 SkRasterClip tmpClip(ir, fConservativeRasterClip); 1540 1541 SkClipStack::B2TIter iter(*fClipStack); 1542 const SkClipStack::Element* element; 1543 while ((element = iter.next()) != NULL) { 1544 switch (element->getType()) { 1545 case SkClipStack::Element::kRect_Type: 1546 element->getRect().round(&ir); 1547 tmpClip.op(ir, element->getOp()); 1548 break; 1549 case SkClipStack::Element::kEmpty_Type: 1550 tmpClip.setEmpty(); 1551 break; 1552 default: { 1553 SkPath path; 1554 element->asPath(&path); 1555 rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA()); 1556 break; 1557 } 1558 } 1559 } 1560 } 1561 #endif 1562 1563 void SkCanvas::replayClips(ClipVisitor* visitor) const { 1564 SkClipStack::B2TIter iter(*fClipStack); 1565 const SkClipStack::Element* element; 1566 1567 while ((element = iter.next()) != NULL) { 1568 element->replay(visitor); 1569 } 1570 } 1571 1572 /////////////////////////////////////////////////////////////////////////////// 1573 1574 bool SkCanvas::isClipEmpty() const { 1575 return fMCRec->fRasterClip.isEmpty(); 1576 } 1577 1578 bool SkCanvas::isClipRect() const { 1579 return fMCRec->fRasterClip.isRect(); 1580 } 1581 1582 bool SkCanvas::quickReject(const SkRect& rect) const { 1583 if (!rect.isFinite()) 1584 return true; 1585 1586 if (fMCRec->fRasterClip.isEmpty()) { 1587 return true; 1588 } 1589 1590 if (fMCRec->fMatrix.hasPerspective()) { 1591 SkRect dst; 1592 fMCRec->fMatrix.mapRect(&dst, rect); 1593 return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds()); 1594 } else { 1595 const SkRect& clipR = this->getLocalClipBounds(); 1596 1597 // for speed, do the most likely reject compares first 1598 // TODO: should we use | instead, or compare all 4 at once? 1599 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1600 return true; 1601 } 1602 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1603 return true; 1604 } 1605 return false; 1606 } 1607 } 1608 1609 bool SkCanvas::quickReject(const SkPath& path) const { 1610 return path.isEmpty() || this->quickReject(path.getBounds()); 1611 } 1612 1613 bool SkCanvas::getClipBounds(SkRect* bounds) const { 1614 SkIRect ibounds; 1615 if (!this->getClipDeviceBounds(&ibounds)) { 1616 return false; 1617 } 1618 1619 SkMatrix inverse; 1620 // if we can't invert the CTM, we can't return local clip bounds 1621 if (!fMCRec->fMatrix.invert(&inverse)) { 1622 if (bounds) { 1623 bounds->setEmpty(); 1624 } 1625 return false; 1626 } 1627 1628 if (bounds) { 1629 SkRect r; 1630 // adjust it outwards in case we are antialiasing 1631 const int inset = 1; 1632 1633 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1634 ibounds.fRight + inset, ibounds.fBottom + inset); 1635 inverse.mapRect(bounds, r); 1636 } 1637 return true; 1638 } 1639 1640 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1641 const SkRasterClip& clip = fMCRec->fRasterClip; 1642 if (clip.isEmpty()) { 1643 if (bounds) { 1644 bounds->setEmpty(); 1645 } 1646 return false; 1647 } 1648 1649 if (bounds) { 1650 *bounds = clip.getBounds(); 1651 } 1652 return true; 1653 } 1654 1655 const SkMatrix& SkCanvas::getTotalMatrix() const { 1656 return fMCRec->fMatrix; 1657 } 1658 1659 const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1660 return fMCRec->fRasterClip.forceGetBW(); 1661 } 1662 1663 GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() { 1664 SkBaseDevice* dev = this->getTopDevice(); 1665 return dev ? dev->accessRenderTarget() : NULL; 1666 } 1667 1668 GrContext* SkCanvas::getGrContext() { 1669 #if SK_SUPPORT_GPU 1670 SkBaseDevice* device = this->getTopDevice(); 1671 if (device) { 1672 GrRenderTarget* renderTarget = device->accessRenderTarget(); 1673 if (renderTarget) { 1674 return renderTarget->getContext(); 1675 } 1676 } 1677 #endif 1678 1679 return NULL; 1680 1681 } 1682 1683 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1684 const SkPaint& paint) { 1685 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()"); 1686 if (outer.isEmpty()) { 1687 return; 1688 } 1689 if (inner.isEmpty()) { 1690 this->drawRRect(outer, paint); 1691 return; 1692 } 1693 1694 // We don't have this method (yet), but technically this is what we should 1695 // be able to assert... 1696 // SkASSERT(outer.contains(inner)); 1697 // 1698 // For now at least check for containment of bounds 1699 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1700 1701 this->onDrawDRRect(outer, inner, paint); 1702 } 1703 1704 // These need to stop being virtual -- clients need to override the onDraw... versions 1705 1706 void SkCanvas::drawPaint(const SkPaint& paint) { 1707 this->onDrawPaint(paint); 1708 } 1709 1710 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1711 this->onDrawRect(r, paint); 1712 } 1713 1714 void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) { 1715 this->onDrawOval(r, paint); 1716 } 1717 1718 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1719 this->onDrawRRect(rrect, paint); 1720 } 1721 1722 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { 1723 this->onDrawPoints(mode, count, pts, paint); 1724 } 1725 1726 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], 1727 const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, 1728 const uint16_t indices[], int indexCount, const SkPaint& paint) { 1729 this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode, 1730 indices, indexCount, paint); 1731 } 1732 1733 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1734 this->onDrawPath(path, paint); 1735 } 1736 1737 void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 1738 this->onDrawImage(image, x, y, paint); 1739 } 1740 1741 void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 1742 const SkPaint* paint) { 1743 if (dst.isEmpty()) { 1744 return; 1745 } 1746 this->onDrawImageRect(image, src, dst, paint); 1747 } 1748 1749 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) { 1750 if (bitmap.empty()) { 1751 return; 1752 } 1753 this->onDrawBitmap(bitmap, dx, dy, paint); 1754 } 1755 1756 void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 1757 const SkPaint* paint, DrawBitmapRectFlags flags) { 1758 if (bitmap.empty()) { 1759 return; 1760 } 1761 this->onDrawBitmapRect(bitmap, src, dst, paint, flags); 1762 } 1763 1764 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 1765 const SkPaint* paint) { 1766 if (bitmap.empty()) { 1767 return; 1768 } 1769 this->onDrawBitmapNine(bitmap, center, dst, paint); 1770 } 1771 1772 void SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { 1773 if (bitmap.empty()) { 1774 return; 1775 } 1776 this->onDrawSprite(bitmap, left, top, paint); 1777 } 1778 1779 ////////////////////////////////////////////////////////////////////////////// 1780 // These are the virtual drawing methods 1781 ////////////////////////////////////////////////////////////////////////////// 1782 1783 void SkCanvas::onDiscard() { 1784 if (fSurfaceBase) { 1785 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 1786 } 1787 } 1788 1789 void SkCanvas::onDrawPaint(const SkPaint& paint) { 1790 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); 1791 this->internalDrawPaint(paint); 1792 } 1793 1794 void SkCanvas::internalDrawPaint(const SkPaint& paint) { 1795 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) 1796 1797 while (iter.next()) { 1798 iter.fDevice->drawPaint(iter, looper.paint()); 1799 } 1800 1801 LOOPER_END 1802 } 1803 1804 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 1805 const SkPaint& paint) { 1806 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count)); 1807 if ((long)count <= 0) { 1808 return; 1809 } 1810 1811 SkRect r, storage; 1812 const SkRect* bounds = NULL; 1813 if (paint.canComputeFastBounds()) { 1814 // special-case 2 points (common for drawing a single line) 1815 if (2 == count) { 1816 r.set(pts[0], pts[1]); 1817 } else { 1818 r.set(pts, SkToInt(count)); 1819 } 1820 bounds = &paint.computeFastStrokeBounds(r, &storage); 1821 if (this->quickReject(*bounds)) { 1822 return; 1823 } 1824 } 1825 1826 SkASSERT(pts != NULL); 1827 1828 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 1829 1830 while (iter.next()) { 1831 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1832 } 1833 1834 LOOPER_END 1835 } 1836 1837 void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { 1838 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()"); 1839 SkRect storage; 1840 const SkRect* bounds = NULL; 1841 if (paint.canComputeFastBounds()) { 1842 // Skia will draw an inverted rect, because it explicitly "sorts" it downstream. 1843 // To prevent accidental rejecting at this stage, we have to sort it before we check. 1844 SkRect tmp(r); 1845 tmp.sort(); 1846 1847 bounds = &paint.computeFastBounds(tmp, &storage); 1848 if (this->quickReject(*bounds)) { 1849 return; 1850 } 1851 } 1852 1853 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) 1854 1855 while (iter.next()) { 1856 iter.fDevice->drawRect(iter, r, looper.paint()); 1857 } 1858 1859 LOOPER_END 1860 } 1861 1862 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { 1863 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 1864 SkRect storage; 1865 const SkRect* bounds = NULL; 1866 if (paint.canComputeFastBounds()) { 1867 bounds = &paint.computeFastBounds(oval, &storage); 1868 if (this->quickReject(*bounds)) { 1869 return; 1870 } 1871 } 1872 1873 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 1874 1875 while (iter.next()) { 1876 iter.fDevice->drawOval(iter, oval, looper.paint()); 1877 } 1878 1879 LOOPER_END 1880 } 1881 1882 void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 1883 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 1884 SkRect storage; 1885 const SkRect* bounds = NULL; 1886 if (paint.canComputeFastBounds()) { 1887 bounds = &paint.computeFastBounds(rrect.getBounds(), &storage); 1888 if (this->quickReject(*bounds)) { 1889 return; 1890 } 1891 } 1892 1893 if (rrect.isRect()) { 1894 // call the non-virtual version 1895 this->SkCanvas::drawRect(rrect.getBounds(), paint); 1896 return; 1897 } else if (rrect.isOval()) { 1898 // call the non-virtual version 1899 this->SkCanvas::drawOval(rrect.getBounds(), paint); 1900 return; 1901 } 1902 1903 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1904 1905 while (iter.next()) { 1906 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1907 } 1908 1909 LOOPER_END 1910 } 1911 1912 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 1913 const SkPaint& paint) { 1914 SkRect storage; 1915 const SkRect* bounds = NULL; 1916 if (paint.canComputeFastBounds()) { 1917 bounds = &paint.computeFastBounds(outer.getBounds(), &storage); 1918 if (this->quickReject(*bounds)) { 1919 return; 1920 } 1921 } 1922 1923 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1924 1925 while (iter.next()) { 1926 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 1927 } 1928 1929 LOOPER_END 1930 } 1931 1932 void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 1933 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 1934 if (!path.isFinite()) { 1935 return; 1936 } 1937 1938 SkRect storage; 1939 const SkRect* bounds = NULL; 1940 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1941 const SkRect& pathBounds = path.getBounds(); 1942 bounds = &paint.computeFastBounds(pathBounds, &storage); 1943 if (this->quickReject(*bounds)) { 1944 return; 1945 } 1946 } 1947 1948 const SkRect& r = path.getBounds(); 1949 if (r.width() <= 0 && r.height() <= 0) { 1950 if (path.isInverseFillType()) { 1951 this->internalDrawPaint(paint); 1952 } 1953 return; 1954 } 1955 1956 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 1957 1958 while (iter.next()) { 1959 iter.fDevice->drawPath(iter, path, looper.paint()); 1960 } 1961 1962 LOOPER_END 1963 } 1964 1965 void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 1966 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 1967 SkRect bounds = SkRect::MakeXYWH(x, y, 1968 SkIntToScalar(image->width()), SkIntToScalar(image->height())); 1969 if (NULL == paint || paint->canComputeFastBounds()) { 1970 if (paint) { 1971 paint->computeFastBounds(bounds, &bounds); 1972 } 1973 if (this->quickReject(bounds)) { 1974 return; 1975 } 1976 } 1977 1978 SkLazyPaint lazy; 1979 if (NULL == paint) { 1980 paint = lazy.init(); 1981 } 1982 1983 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds) 1984 1985 while (iter.next()) { 1986 iter.fDevice->drawImage(iter, image, x, y, looper.paint()); 1987 } 1988 1989 LOOPER_END 1990 } 1991 1992 void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 1993 const SkPaint* paint) { 1994 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 1995 SkRect storage; 1996 const SkRect* bounds = &dst; 1997 if (NULL == paint || paint->canComputeFastBounds()) { 1998 if (paint) { 1999 bounds = &paint->computeFastBounds(dst, &storage); 2000 } 2001 if (this->quickReject(*bounds)) { 2002 return; 2003 } 2004 } 2005 SkLazyPaint lazy; 2006 if (NULL == paint) { 2007 paint = lazy.init(); 2008 } 2009 2010 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 2011 2012 while (iter.next()) { 2013 iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint()); 2014 } 2015 2016 LOOPER_END 2017 } 2018 2019 void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { 2020 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 2021 SkDEBUGCODE(bitmap.validate();) 2022 2023 if (NULL == paint || paint->canComputeFastBounds()) { 2024 SkRect bounds = { 2025 x, y, 2026 x + SkIntToScalar(bitmap.width()), 2027 y + SkIntToScalar(bitmap.height()) 2028 }; 2029 if (paint) { 2030 (void)paint->computeFastBounds(bounds, &bounds); 2031 } 2032 if (this->quickReject(bounds)) { 2033 return; 2034 } 2035 } 2036 2037 SkMatrix matrix; 2038 matrix.setTranslate(x, y); 2039 this->internalDrawBitmap(bitmap, matrix, paint); 2040 } 2041 2042 // this one is non-virtual, so it can be called safely by other canvas apis 2043 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 2044 const SkRect& dst, const SkPaint* paint, 2045 DrawBitmapRectFlags flags) { 2046 if (bitmap.drawsNothing() || dst.isEmpty()) { 2047 return; 2048 } 2049 2050 SkRect storage; 2051 const SkRect* bounds = &dst; 2052 if (NULL == paint || paint->canComputeFastBounds()) { 2053 if (paint) { 2054 bounds = &paint->computeFastBounds(dst, &storage); 2055 } 2056 if (this->quickReject(*bounds)) { 2057 return; 2058 } 2059 } 2060 2061 SkLazyPaint lazy; 2062 if (NULL == paint) { 2063 paint = lazy.init(); 2064 } 2065 2066 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 2067 2068 while (iter.next()) { 2069 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 2070 } 2071 2072 LOOPER_END 2073 } 2074 2075 void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2076 const SkPaint* paint, DrawBitmapRectFlags flags) { 2077 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 2078 SkDEBUGCODE(bitmap.validate();) 2079 this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 2080 } 2081 2082 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 2083 const SkIRect& center, const SkRect& dst, 2084 const SkPaint* paint) { 2085 if (bitmap.drawsNothing()) { 2086 return; 2087 } 2088 if (NULL == paint || paint->canComputeFastBounds()) { 2089 SkRect storage; 2090 const SkRect* bounds = &dst; 2091 if (paint) { 2092 bounds = &paint->computeFastBounds(dst, &storage); 2093 } 2094 if (this->quickReject(*bounds)) { 2095 return; 2096 } 2097 } 2098 2099 const int32_t w = bitmap.width(); 2100 const int32_t h = bitmap.height(); 2101 2102 SkIRect c = center; 2103 // pin center to the bounds of the bitmap 2104 c.fLeft = SkMax32(0, center.fLeft); 2105 c.fTop = SkMax32(0, center.fTop); 2106 c.fRight = SkPin32(center.fRight, c.fLeft, w); 2107 c.fBottom = SkPin32(center.fBottom, c.fTop, h); 2108 2109 const SkScalar srcX[4] = { 2110 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 2111 }; 2112 const SkScalar srcY[4] = { 2113 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 2114 }; 2115 SkScalar dstX[4] = { 2116 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 2117 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 2118 }; 2119 SkScalar dstY[4] = { 2120 dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 2121 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 2122 }; 2123 2124 if (dstX[1] > dstX[2]) { 2125 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 2126 dstX[2] = dstX[1]; 2127 } 2128 2129 if (dstY[1] > dstY[2]) { 2130 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 2131 dstY[2] = dstY[1]; 2132 } 2133 2134 for (int y = 0; y < 3; y++) { 2135 SkRect s, d; 2136 2137 s.fTop = srcY[y]; 2138 s.fBottom = srcY[y+1]; 2139 d.fTop = dstY[y]; 2140 d.fBottom = dstY[y+1]; 2141 for (int x = 0; x < 3; x++) { 2142 s.fLeft = srcX[x]; 2143 s.fRight = srcX[x+1]; 2144 d.fLeft = dstX[x]; 2145 d.fRight = dstX[x+1]; 2146 this->internalDrawBitmapRect(bitmap, &s, d, paint, 2147 kNone_DrawBitmapRectFlag); 2148 } 2149 } 2150 } 2151 2152 void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 2153 const SkPaint* paint) { 2154 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 2155 SkDEBUGCODE(bitmap.validate();) 2156 2157 // Need a device entry-point, so gpu can use a mesh 2158 this->internalDrawBitmapNine(bitmap, center, dst, paint); 2159 } 2160 2161 class SkDeviceFilteredPaint { 2162 public: 2163 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2164 uint32_t filteredFlags = device->filterTextFlags(paint); 2165 if (filteredFlags != paint.getFlags()) { 2166 SkPaint* newPaint = fLazy.set(paint); 2167 newPaint->setFlags(filteredFlags); 2168 fPaint = newPaint; 2169 } else { 2170 fPaint = &paint; 2171 } 2172 } 2173 2174 const SkPaint& paint() const { return *fPaint; } 2175 2176 private: 2177 const SkPaint* fPaint; 2178 SkLazyPaint fLazy; 2179 }; 2180 2181 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2182 const SkRect& r, SkScalar textSize) { 2183 if (paint.getStyle() == SkPaint::kFill_Style) { 2184 draw.fDevice->drawRect(draw, r, paint); 2185 } else { 2186 SkPaint p(paint); 2187 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2188 draw.fDevice->drawRect(draw, r, p); 2189 } 2190 } 2191 2192 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2193 const char text[], size_t byteLength, 2194 SkScalar x, SkScalar y) { 2195 SkASSERT(byteLength == 0 || text != NULL); 2196 2197 // nothing to draw 2198 if (text == NULL || byteLength == 0 || 2199 draw.fClip->isEmpty() || 2200 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 2201 return; 2202 } 2203 2204 SkScalar width = 0; 2205 SkPoint start; 2206 2207 start.set(0, 0); // to avoid warning 2208 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2209 SkPaint::kStrikeThruText_Flag)) { 2210 width = paint.measureText(text, byteLength); 2211 2212 SkScalar offsetX = 0; 2213 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2214 offsetX = SkScalarHalf(width); 2215 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2216 offsetX = width; 2217 } 2218 start.set(x - offsetX, y); 2219 } 2220 2221 if (0 == width) { 2222 return; 2223 } 2224 2225 uint32_t flags = paint.getFlags(); 2226 2227 if (flags & (SkPaint::kUnderlineText_Flag | 2228 SkPaint::kStrikeThruText_Flag)) { 2229 SkScalar textSize = paint.getTextSize(); 2230 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2231 SkRect r; 2232 2233 r.fLeft = start.fX; 2234 r.fRight = start.fX + width; 2235 2236 if (flags & SkPaint::kUnderlineText_Flag) { 2237 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2238 start.fY); 2239 r.fTop = offset; 2240 r.fBottom = offset + height; 2241 DrawRect(draw, paint, r, textSize); 2242 } 2243 if (flags & SkPaint::kStrikeThruText_Flag) { 2244 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2245 start.fY); 2246 r.fTop = offset; 2247 r.fBottom = offset + height; 2248 DrawRect(draw, paint, r, textSize); 2249 } 2250 } 2251 } 2252 2253 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2254 const SkPaint& paint) { 2255 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2256 2257 while (iter.next()) { 2258 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2259 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2260 DrawTextDecorations(iter, dfp.paint(), 2261 static_cast<const char*>(text), byteLength, x, y); 2262 } 2263 2264 LOOPER_END 2265 } 2266 2267 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2268 const SkPaint& paint) { 2269 SkPoint textOffset = SkPoint::Make(0, 0); 2270 2271 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2272 2273 while (iter.next()) { 2274 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2275 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2276 dfp.paint()); 2277 } 2278 2279 LOOPER_END 2280 } 2281 2282 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2283 SkScalar constY, const SkPaint& paint) { 2284 2285 SkPoint textOffset = SkPoint::Make(0, constY); 2286 2287 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2288 2289 while (iter.next()) { 2290 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2291 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2292 dfp.paint()); 2293 } 2294 2295 LOOPER_END 2296 } 2297 2298 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2299 const SkMatrix* matrix, const SkPaint& paint) { 2300 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2301 2302 while (iter.next()) { 2303 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2304 matrix, looper.paint()); 2305 } 2306 2307 LOOPER_END 2308 } 2309 2310 void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2311 const SkPaint& paint) { 2312 2313 SkRect storage; 2314 const SkRect* bounds = NULL; 2315 if (paint.canComputeFastBounds()) { 2316 storage = blob->bounds().makeOffset(x, y); 2317 bounds = &paint.computeFastBounds(storage, &storage); 2318 2319 if (this->quickReject(*bounds)) { 2320 return; 2321 } 2322 } 2323 2324 // We cannot filter in the looper as we normally do, because the paint is 2325 // incomplete at this point (text-related attributes are embedded within blob run paints). 2326 SkDrawFilter* drawFilter = fMCRec->fFilter; 2327 fMCRec->fFilter = NULL; 2328 2329 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) 2330 2331 while (iter.next()) { 2332 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2333 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter); 2334 } 2335 2336 LOOPER_END 2337 2338 fMCRec->fFilter = drawFilter; 2339 } 2340 2341 // These will become non-virtual, so they always call the (virtual) onDraw... method 2342 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2343 const SkPaint& paint) { 2344 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2345 this->onDrawText(text, byteLength, x, y, paint); 2346 } 2347 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2348 const SkPaint& paint) { 2349 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2350 this->onDrawPosText(text, byteLength, pos, paint); 2351 } 2352 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2353 SkScalar constY, const SkPaint& paint) { 2354 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2355 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2356 } 2357 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2358 const SkMatrix* matrix, const SkPaint& paint) { 2359 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2360 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2361 } 2362 void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2363 const SkPaint& paint) { 2364 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2365 if (blob) { 2366 this->onDrawTextBlob(blob, x, y, paint); 2367 } 2368 } 2369 2370 void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount, 2371 const SkPoint verts[], const SkPoint texs[], 2372 const SkColor colors[], SkXfermode* xmode, 2373 const uint16_t indices[], int indexCount, 2374 const SkPaint& paint) { 2375 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2376 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2377 2378 while (iter.next()) { 2379 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2380 colors, xmode, indices, indexCount, 2381 looper.paint()); 2382 } 2383 2384 LOOPER_END 2385 } 2386 2387 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2388 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2389 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2390 if (NULL == cubics) { 2391 return; 2392 } 2393 2394 // Since a patch is always within the convex hull of the control points, we discard it when its 2395 // bounding rectangle is completely outside the current clip. 2396 SkRect bounds; 2397 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2398 if (this->quickReject(bounds)) { 2399 return; 2400 } 2401 2402 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2403 } 2404 2405 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2406 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2407 2408 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2409 2410 while (iter.next()) { 2411 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2412 } 2413 2414 LOOPER_END 2415 } 2416 2417 void SkCanvas::drawDrawable(SkDrawable* dr) { 2418 if (dr && !this->quickReject(dr->getBounds())) { 2419 this->onDrawDrawable(dr); 2420 } 2421 } 2422 2423 void SkCanvas::onDrawDrawable(SkDrawable* dr) { 2424 dr->draw(this); 2425 } 2426 2427 ////////////////////////////////////////////////////////////////////////////// 2428 // These methods are NOT virtual, and therefore must call back into virtual 2429 // methods, rather than actually drawing themselves. 2430 ////////////////////////////////////////////////////////////////////////////// 2431 2432 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2433 SkXfermode::Mode mode) { 2434 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 2435 SkPaint paint; 2436 2437 paint.setARGB(a, r, g, b); 2438 if (SkXfermode::kSrcOver_Mode != mode) { 2439 paint.setXfermodeMode(mode); 2440 } 2441 this->drawPaint(paint); 2442 } 2443 2444 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2445 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 2446 SkPaint paint; 2447 2448 paint.setColor(c); 2449 if (SkXfermode::kSrcOver_Mode != mode) { 2450 paint.setXfermodeMode(mode); 2451 } 2452 this->drawPaint(paint); 2453 } 2454 2455 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2456 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 2457 SkPoint pt; 2458 2459 pt.set(x, y); 2460 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2461 } 2462 2463 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2464 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 2465 SkPoint pt; 2466 SkPaint paint; 2467 2468 pt.set(x, y); 2469 paint.setColor(color); 2470 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2471 } 2472 2473 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 2474 const SkPaint& paint) { 2475 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 2476 SkPoint pts[2]; 2477 2478 pts[0].set(x0, y0); 2479 pts[1].set(x1, y1); 2480 this->drawPoints(kLines_PointMode, 2, pts, paint); 2481 } 2482 2483 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2484 SkScalar right, SkScalar bottom, 2485 const SkPaint& paint) { 2486 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 2487 SkRect r; 2488 2489 r.set(left, top, right, bottom); 2490 this->drawRect(r, paint); 2491 } 2492 2493 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 2494 const SkPaint& paint) { 2495 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 2496 if (radius < 0) { 2497 radius = 0; 2498 } 2499 2500 SkRect r; 2501 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2502 this->drawOval(r, paint); 2503 } 2504 2505 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2506 const SkPaint& paint) { 2507 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 2508 if (rx > 0 && ry > 0) { 2509 if (paint.canComputeFastBounds()) { 2510 SkRect storage; 2511 if (this->quickReject(paint.computeFastBounds(r, &storage))) { 2512 return; 2513 } 2514 } 2515 SkRRect rrect; 2516 rrect.setRectXY(r, rx, ry); 2517 this->drawRRect(rrect, paint); 2518 } else { 2519 this->drawRect(r, paint); 2520 } 2521 } 2522 2523 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2524 SkScalar sweepAngle, bool useCenter, 2525 const SkPaint& paint) { 2526 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2527 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 2528 this->drawOval(oval, paint); 2529 } else { 2530 SkPath path; 2531 if (useCenter) { 2532 path.moveTo(oval.centerX(), oval.centerY()); 2533 } 2534 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 2535 if (useCenter) { 2536 path.close(); 2537 } 2538 this->drawPath(path, paint); 2539 } 2540 } 2541 2542 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2543 const SkPath& path, SkScalar hOffset, 2544 SkScalar vOffset, const SkPaint& paint) { 2545 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 2546 SkMatrix matrix; 2547 2548 matrix.setTranslate(hOffset, vOffset); 2549 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2550 } 2551 2552 /////////////////////////////////////////////////////////////////////////////// 2553 2554 /** 2555 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, 2556 * against the playback cost of recursing into the subpicture to get at its actual ops. 2557 * 2558 * For now we pick a conservatively small value, though measurement (and other heuristics like 2559 * the type of ops contained) may justify changing this value. 2560 */ 2561 #define kMaxPictureOpsToUnrollInsteadOfRef 1 2562 2563 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 2564 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 2565 if (picture) { 2566 if (matrix && matrix->isIdentity()) { 2567 matrix = NULL; 2568 } 2569 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) { 2570 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2571 picture->playback(this); 2572 } else { 2573 this->onDrawPicture(picture, matrix, paint); 2574 } 2575 } 2576 } 2577 2578 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2579 const SkPaint* paint) { 2580 SkBaseDevice* device = this->getTopDevice(); 2581 if (device) { 2582 // Canvas has to first give the device the opportunity to render 2583 // the picture itself. 2584 if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) { 2585 return; // the device has rendered the entire picture 2586 } 2587 } 2588 2589 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2590 picture->playback(this); 2591 } 2592 2593 /////////////////////////////////////////////////////////////////////////////// 2594 /////////////////////////////////////////////////////////////////////////////// 2595 2596 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2597 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 2598 2599 SkASSERT(canvas); 2600 2601 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 2602 fDone = !fImpl->next(); 2603 } 2604 2605 SkCanvas::LayerIter::~LayerIter() { 2606 fImpl->~SkDrawIter(); 2607 } 2608 2609 void SkCanvas::LayerIter::next() { 2610 fDone = !fImpl->next(); 2611 } 2612 2613 SkBaseDevice* SkCanvas::LayerIter::device() const { 2614 return fImpl->getDevice(); 2615 } 2616 2617 const SkMatrix& SkCanvas::LayerIter::matrix() const { 2618 return fImpl->getMatrix(); 2619 } 2620 2621 const SkPaint& SkCanvas::LayerIter::paint() const { 2622 const SkPaint* paint = fImpl->getPaint(); 2623 if (NULL == paint) { 2624 paint = &fDefaultPaint; 2625 } 2626 return *paint; 2627 } 2628 2629 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 2630 int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 2631 int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2632 2633 /////////////////////////////////////////////////////////////////////////////// 2634 2635 SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 2636 2637 /////////////////////////////////////////////////////////////////////////////// 2638 2639 static bool supported_for_raster_canvas(const SkImageInfo& info) { 2640 switch (info.alphaType()) { 2641 case kPremul_SkAlphaType: 2642 case kOpaque_SkAlphaType: 2643 break; 2644 default: 2645 return false; 2646 } 2647 2648 switch (info.colorType()) { 2649 case kAlpha_8_SkColorType: 2650 case kRGB_565_SkColorType: 2651 case kN32_SkColorType: 2652 break; 2653 default: 2654 return false; 2655 } 2656 2657 return true; 2658 } 2659 2660 SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 2661 if (!supported_for_raster_canvas(info)) { 2662 return NULL; 2663 } 2664 2665 SkBitmap bitmap; 2666 if (!bitmap.installPixels(info, pixels, rowBytes)) { 2667 return NULL; 2668 } 2669 return SkNEW_ARGS(SkCanvas, (bitmap)); 2670 } 2671 2672 /////////////////////////////////////////////////////////////////////////////// 2673 2674 SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 2675 const SkPaint* paint, const SkRect& bounds) 2676 : fCanvas(canvas) 2677 , fSaveCount(canvas->getSaveCount()) 2678 { 2679 if (paint) { 2680 SkRect newBounds = bounds; 2681 if (matrix) { 2682 matrix->mapRect(&newBounds); 2683 } 2684 canvas->saveLayer(&newBounds, paint); 2685 } else if (matrix) { 2686 canvas->save(); 2687 } 2688 2689 if (matrix) { 2690 canvas->concat(*matrix); 2691 } 2692 } 2693 2694 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2695 fCanvas->restoreToCount(fSaveCount); 2696 } 2697