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