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