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