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