SkCanvas.cpp revision fa33f5a6b770130acdc55f2ffe19dd545665726a
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 SkImageFilter* imgf = paint ? paint->getImageFilter() : NULL; 996 997 // do this before we create the layer. We don't call the public save() since 998 // that would invoke a possibly overridden virtual 999 this->internalSave(); 1000 1001 fDeviceCMDirty = true; 1002 1003 SkIRect ir; 1004 if (!this->clipRectBounds(bounds, flags, &ir, imgf)) { 1005 return; 1006 } 1007 1008 // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about 1009 // the clipRectBounds() call above? 1010 if (kNoLayer_SaveLayerStrategy == strategy) { 1011 return; 1012 } 1013 1014 bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); 1015 SkPixelGeometry geo = fProps.pixelGeometry(); 1016 if (paint) { 1017 // TODO: perhaps add a query to filters so we might preserve opaqueness... 1018 if (imgf || paint->getColorFilter()) { 1019 isOpaque = false; 1020 geo = kUnknown_SkPixelGeometry; 1021 } 1022 } 1023 SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(), 1024 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); 1025 1026 SkBaseDevice* device = this->getTopDevice(); 1027 if (NULL == device) { 1028 SkDebugf("Unable to find device for layer."); 1029 return; 1030 } 1031 1032 bool forceSpriteOnRestore = false; 1033 { 1034 SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage; 1035 if (imgf && imgf->mayDrawWithMatrix()) { 1036 usage = SkBaseDevice::kPossible_TileUsage; 1037 } 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 newDev = SkBitmapDevice::Create(createInfo.fInfo); 1043 if (NULL == newDev) { 1044 SkErrorInternals::SetError(kInternalError_SkError, 1045 "Unable to create device for layer."); 1046 return; 1047 } 1048 forceSpriteOnRestore = true; 1049 } 1050 device = newDev; 1051 } 1052 1053 device->setOrigin(ir.fLeft, ir.fTop); 1054 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, paint, this, fConservativeRasterClip, 1055 forceSpriteOnRestore)); 1056 device->unref(); 1057 1058 layer->fNext = fMCRec->fTopLayer; 1059 fMCRec->fLayer = layer; 1060 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 1061} 1062 1063int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) { 1064 return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag); 1065} 1066 1067int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 1068 SaveFlags flags) { 1069 if (0xFF == alpha) { 1070 return this->saveLayer(bounds, NULL, flags); 1071 } else { 1072 SkPaint tmpPaint; 1073 tmpPaint.setAlpha(alpha); 1074 return this->saveLayer(bounds, &tmpPaint, flags); 1075 } 1076} 1077 1078void SkCanvas::internalRestore() { 1079 SkASSERT(fMCStack.count() != 0); 1080 1081 fDeviceCMDirty = true; 1082 fCachedLocalClipBoundsDirty = true; 1083 1084 fClipStack->restore(); 1085 1086 // reserve our layer (if any) 1087 DeviceCM* layer = fMCRec->fLayer; // may be null 1088 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 1089 fMCRec->fLayer = NULL; 1090 1091 // now do the normal restore() 1092 fMCRec->~MCRec(); // balanced in save() 1093 fMCStack.pop_back(); 1094 fMCRec = (MCRec*)fMCStack.back(); 1095 1096 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 1097 since if we're being recorded, we don't want to record this (the 1098 recorder will have already recorded the restore). 1099 */ 1100 if (layer) { 1101 if (layer->fNext) { 1102 const SkIPoint& origin = layer->fDevice->getOrigin(); 1103 this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), 1104 layer->fPaint, layer->fDeviceIsBitmapDevice); 1105 // reset this, since internalDrawDevice will have set it to true 1106 fDeviceCMDirty = true; 1107 SkDELETE(layer); 1108 } else { 1109 // we're at the root 1110 SkASSERT(layer == (void*)fDeviceCMStorage); 1111 layer->~DeviceCM(); 1112 } 1113 } 1114} 1115 1116SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) { 1117 if (NULL == props) { 1118 props = &fProps; 1119 } 1120 return this->onNewSurface(info, *props); 1121} 1122 1123SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) { 1124 SkBaseDevice* dev = this->getDevice(); 1125 return dev ? dev->newSurface(info, props) : NULL; 1126} 1127 1128SkImageInfo SkCanvas::imageInfo() const { 1129 SkBaseDevice* dev = this->getDevice(); 1130 if (dev) { 1131 return dev->imageInfo(); 1132 } else { 1133 return SkImageInfo::MakeUnknown(0, 0); 1134 } 1135} 1136 1137const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) { 1138 return this->onPeekPixels(info, rowBytes); 1139} 1140 1141const void* SkCanvas::onPeekPixels(SkImageInfo* info, size_t* rowBytes) { 1142 SkBaseDevice* dev = this->getDevice(); 1143 return dev ? dev->peekPixels(info, rowBytes) : NULL; 1144} 1145 1146void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) { 1147 void* pixels = this->onAccessTopLayerPixels(info, rowBytes); 1148 if (pixels && origin) { 1149 *origin = this->getTopDevice(false)->getOrigin(); 1150 } 1151 return pixels; 1152} 1153 1154void* SkCanvas::onAccessTopLayerPixels(SkImageInfo* info, size_t* rowBytes) { 1155 SkBaseDevice* dev = this->getTopDevice(); 1156 return dev ? dev->accessPixels(info, rowBytes) : NULL; 1157} 1158 1159SkAutoROCanvasPixels::SkAutoROCanvasPixels(SkCanvas* canvas) { 1160 fAddr = canvas->peekPixels(&fInfo, &fRowBytes); 1161 if (NULL == fAddr) { 1162 fInfo = canvas->imageInfo(); 1163 if (kUnknown_SkColorType == fInfo.colorType() || !fBitmap.tryAllocPixels(fInfo)) { 1164 return; // failure, fAddr is NULL 1165 } 1166 if (!canvas->readPixels(&fBitmap, 0, 0)) { 1167 return; // failure, fAddr is NULL 1168 } 1169 fAddr = fBitmap.getPixels(); 1170 fRowBytes = fBitmap.rowBytes(); 1171 } 1172 SkASSERT(fAddr); // success 1173} 1174 1175bool SkAutoROCanvasPixels::asROBitmap(SkBitmap* bitmap) const { 1176 if (fAddr) { 1177 return bitmap->installPixels(fInfo, const_cast<void*>(fAddr), fRowBytes); 1178 } else { 1179 bitmap->reset(); 1180 return false; 1181 } 1182} 1183 1184///////////////////////////////////////////////////////////////////////////// 1185void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, 1186 const SkMatrix& matrix, const SkPaint* paint) { 1187 if (bitmap.drawsNothing()) { 1188 return; 1189 } 1190 1191 SkLazyPaint lazy; 1192 if (NULL == paint) { 1193 paint = lazy.init(); 1194 } 1195 1196 SkDEBUGCODE(bitmap.validate();) 1197 1198 SkRect storage; 1199 const SkRect* bounds = NULL; 1200 if (paint && paint->canComputeFastBounds()) { 1201 bitmap.getBounds(&storage); 1202 matrix.mapRect(&storage); 1203 bounds = &paint->computeFastBounds(storage, &storage); 1204 } 1205 1206 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 1207 1208 while (iter.next()) { 1209 iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); 1210 } 1211 1212 LOOPER_END 1213} 1214 1215void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, 1216 const SkPaint* paint, bool deviceIsBitmapDevice) { 1217 SkPaint tmp; 1218 if (NULL == paint) { 1219 paint = &tmp; 1220 } 1221 1222 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1223 while (iter.next()) { 1224 SkBaseDevice* dstDev = iter.fDevice; 1225 paint = &looper.paint(); 1226 SkImageFilter* filter = paint->getImageFilter(); 1227 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1228 if (filter && !dstDev->canHandleImageFilter(filter)) { 1229 SkDeviceImageFilterProxy proxy(dstDev, fProps); 1230 SkBitmap dst; 1231 SkIPoint offset = SkIPoint::Make(0, 0); 1232 const SkBitmap& src = srcDev->accessBitmap(false); 1233 SkMatrix matrix = *iter.fMatrix; 1234 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1235 SkIRect clipBounds = SkIRect::MakeWH(srcDev->width(), srcDev->height()); 1236 SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache()); 1237 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1238 if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) { 1239 SkPaint tmpUnfiltered(*paint); 1240 tmpUnfiltered.setImageFilter(NULL); 1241 dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1242 tmpUnfiltered); 1243 } 1244 } else if (deviceIsBitmapDevice) { 1245 const SkBitmap& src = srcDev->accessBitmap(false); 1246 dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint); 1247 } else { 1248 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 1249 } 1250 } 1251 LOOPER_END 1252} 1253 1254void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* paint) { 1255 if (gTreatSpriteAsBitmap) { 1256 this->save(); 1257 this->resetMatrix(); 1258 this->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), paint); 1259 this->restore(); 1260 return; 1261 } 1262 1263 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawSprite()"); 1264 if (bitmap.drawsNothing()) { 1265 return; 1266 } 1267 SkDEBUGCODE(bitmap.validate();) 1268 1269 SkPaint tmp; 1270 if (NULL == paint) { 1271 paint = &tmp; 1272 } 1273 1274 LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) 1275 1276 while (iter.next()) { 1277 paint = &looper.paint(); 1278 SkImageFilter* filter = paint->getImageFilter(); 1279 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 1280 if (filter && !iter.fDevice->canHandleImageFilter(filter)) { 1281 SkDeviceImageFilterProxy proxy(iter.fDevice, fProps); 1282 SkBitmap dst; 1283 SkIPoint offset = SkIPoint::Make(0, 0); 1284 SkMatrix matrix = *iter.fMatrix; 1285 matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); 1286 const SkIRect clipBounds = bitmap.bounds(); 1287 SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache()); 1288 SkImageFilter::Context ctx(matrix, clipBounds, cache.get()); 1289 if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) { 1290 SkPaint tmpUnfiltered(*paint); 1291 tmpUnfiltered.setImageFilter(NULL); 1292 iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), 1293 tmpUnfiltered); 1294 } 1295 } else { 1296 iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); 1297 } 1298 } 1299 LOOPER_END 1300} 1301 1302///////////////////////////////////////////////////////////////////////////// 1303void SkCanvas::translate(SkScalar dx, SkScalar dy) { 1304 SkMatrix m; 1305 m.setTranslate(dx, dy); 1306 this->concat(m); 1307} 1308 1309void SkCanvas::scale(SkScalar sx, SkScalar sy) { 1310 SkMatrix m; 1311 m.setScale(sx, sy); 1312 this->concat(m); 1313} 1314 1315void SkCanvas::rotate(SkScalar degrees) { 1316 SkMatrix m; 1317 m.setRotate(degrees); 1318 this->concat(m); 1319} 1320 1321void SkCanvas::skew(SkScalar sx, SkScalar sy) { 1322 SkMatrix m; 1323 m.setSkew(sx, sy); 1324 this->concat(m); 1325} 1326 1327void SkCanvas::concat(const SkMatrix& matrix) { 1328 if (matrix.isIdentity()) { 1329 return; 1330 } 1331 1332 this->checkForDeferredSave(); 1333 fDeviceCMDirty = true; 1334 fCachedLocalClipBoundsDirty = true; 1335 fMCRec->fMatrix.preConcat(matrix); 1336 1337 this->didConcat(matrix); 1338} 1339 1340void SkCanvas::setMatrix(const SkMatrix& matrix) { 1341 this->checkForDeferredSave(); 1342 fDeviceCMDirty = true; 1343 fCachedLocalClipBoundsDirty = true; 1344 fMCRec->fMatrix = matrix; 1345 this->didSetMatrix(matrix); 1346} 1347 1348void SkCanvas::resetMatrix() { 1349 SkMatrix matrix; 1350 1351 matrix.reset(); 1352 this->setMatrix(matrix); 1353} 1354 1355////////////////////////////////////////////////////////////////////////////// 1356 1357void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1358 this->checkForDeferredSave(); 1359 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1360 this->onClipRect(rect, op, edgeStyle); 1361} 1362 1363void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1364#ifdef SK_ENABLE_CLIP_QUICKREJECT 1365 if (SkRegion::kIntersect_Op == op) { 1366 if (fMCRec->fRasterClip.isEmpty()) { 1367 return false; 1368 } 1369 1370 if (this->quickReject(rect)) { 1371 fDeviceCMDirty = true; 1372 fCachedLocalClipBoundsDirty = true; 1373 1374 fClipStack->clipEmpty(); 1375 return fMCRec->fRasterClip.setEmpty(); 1376 } 1377 } 1378#endif 1379 1380 AutoValidateClip avc(this); 1381 1382 fDeviceCMDirty = true; 1383 fCachedLocalClipBoundsDirty = true; 1384 if (!fAllowSoftClip) { 1385 edgeStyle = kHard_ClipEdgeStyle; 1386 } 1387 1388 if (fMCRec->fMatrix.rectStaysRect()) { 1389 // for these simpler matrices, we can stay a rect even after applying 1390 // the matrix. This means we don't have to a) make a path, and b) tell 1391 // the region code to scan-convert the path, only to discover that it 1392 // is really just a rect. 1393 SkRect r; 1394 1395 fMCRec->fMatrix.mapRect(&r, rect); 1396 fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); 1397 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle); 1398 } else { 1399 // since we're rotated or some such thing, we convert the rect to a path 1400 // and clip against that, since it can handle any matrix. However, to 1401 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1402 // we explicitly call "our" version of clipPath. 1403 SkPath path; 1404 1405 path.addRect(rect); 1406 this->SkCanvas::onClipPath(path, op, edgeStyle); 1407 } 1408} 1409 1410static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath, 1411 SkRegion::Op op, bool doAA) { 1412 rc->op(devPath, canvas->getBaseLayerSize(), op, doAA); 1413} 1414 1415void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { 1416 this->checkForDeferredSave(); 1417 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1418 if (rrect.isRect()) { 1419 this->onClipRect(rrect.getBounds(), op, edgeStyle); 1420 } else { 1421 this->onClipRRect(rrect, op, edgeStyle); 1422 } 1423} 1424 1425void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1426 SkRRect transformedRRect; 1427 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { 1428 AutoValidateClip avc(this); 1429 1430 fDeviceCMDirty = true; 1431 fCachedLocalClipBoundsDirty = true; 1432 if (!fAllowSoftClip) { 1433 edgeStyle = kHard_ClipEdgeStyle; 1434 } 1435 1436 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); 1437 1438 SkPath devPath; 1439 devPath.addRRect(transformedRRect); 1440 1441 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1442 return; 1443 } 1444 1445 SkPath path; 1446 path.addRRect(rrect); 1447 // call the non-virtual version 1448 this->SkCanvas::onClipPath(path, op, edgeStyle); 1449} 1450 1451void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1452 this->checkForDeferredSave(); 1453 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; 1454 SkRect r; 1455 if (!path.isInverseFillType() && path.isRect(&r)) { 1456 this->onClipRect(r, op, edgeStyle); 1457 } else { 1458 this->onClipPath(path, op, edgeStyle); 1459 } 1460} 1461 1462void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { 1463#ifdef SK_ENABLE_CLIP_QUICKREJECT 1464 if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) { 1465 if (fMCRec->fRasterClip.isEmpty()) { 1466 return false; 1467 } 1468 1469 if (this->quickReject(path.getBounds())) { 1470 fDeviceCMDirty = true; 1471 fCachedLocalClipBoundsDirty = true; 1472 1473 fClipStack->clipEmpty(); 1474 return fMCRec->fRasterClip.setEmpty(); 1475 } 1476 } 1477#endif 1478 1479 AutoValidateClip avc(this); 1480 1481 fDeviceCMDirty = true; 1482 fCachedLocalClipBoundsDirty = true; 1483 if (!fAllowSoftClip) { 1484 edgeStyle = kHard_ClipEdgeStyle; 1485 } 1486 1487 SkPath devPath; 1488 path.transform(fMCRec->fMatrix, &devPath); 1489 1490 // Check if the transfomation, or the original path itself 1491 // made us empty. Note this can also happen if we contained NaN 1492 // values. computing the bounds detects this, and will set our 1493 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1494 if (devPath.getBounds().isEmpty()) { 1495 // resetting the path will remove any NaN or other wanky values 1496 // that might upset our scan converter. 1497 devPath.reset(); 1498 } 1499 1500 // if we called path.swap() we could avoid a deep copy of this path 1501 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); 1502 1503 if (fAllowSimplifyClip) { 1504 bool clipIsAA = getClipStack()->asPath(&devPath); 1505 if (clipIsAA) { 1506 edgeStyle = kSoft_ClipEdgeStyle; 1507 } 1508 1509 op = SkRegion::kReplace_Op; 1510 } 1511 1512 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); 1513} 1514 1515void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1516 this->checkForDeferredSave(); 1517 this->onClipRegion(rgn, op); 1518} 1519 1520void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { 1521 AutoValidateClip avc(this); 1522 1523 fDeviceCMDirty = true; 1524 fCachedLocalClipBoundsDirty = true; 1525 1526 // todo: signal fClipStack that we have a region, and therefore (I guess) 1527 // we have to ignore it, and use the region directly? 1528 fClipStack->clipDevRect(rgn.getBounds(), op); 1529 1530 fMCRec->fRasterClip.op(rgn, op); 1531} 1532 1533#ifdef SK_DEBUG 1534void SkCanvas::validateClip() const { 1535 // construct clipRgn from the clipstack 1536 const SkBaseDevice* device = this->getDevice(); 1537 if (!device) { 1538 SkASSERT(this->isClipEmpty()); 1539 return; 1540 } 1541 1542 SkIRect ir; 1543 ir.set(0, 0, device->width(), device->height()); 1544 SkRasterClip tmpClip(ir, fConservativeRasterClip); 1545 1546 SkClipStack::B2TIter iter(*fClipStack); 1547 const SkClipStack::Element* element; 1548 while ((element = iter.next()) != NULL) { 1549 switch (element->getType()) { 1550 case SkClipStack::Element::kRect_Type: 1551 element->getRect().round(&ir); 1552 tmpClip.op(ir, element->getOp()); 1553 break; 1554 case SkClipStack::Element::kEmpty_Type: 1555 tmpClip.setEmpty(); 1556 break; 1557 default: { 1558 SkPath path; 1559 element->asPath(&path); 1560 rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA()); 1561 break; 1562 } 1563 } 1564 } 1565} 1566#endif 1567 1568void SkCanvas::replayClips(ClipVisitor* visitor) const { 1569 SkClipStack::B2TIter iter(*fClipStack); 1570 const SkClipStack::Element* element; 1571 1572 while ((element = iter.next()) != NULL) { 1573 element->replay(visitor); 1574 } 1575} 1576 1577/////////////////////////////////////////////////////////////////////////////// 1578 1579bool SkCanvas::isClipEmpty() const { 1580 return fMCRec->fRasterClip.isEmpty(); 1581} 1582 1583bool SkCanvas::isClipRect() const { 1584 return fMCRec->fRasterClip.isRect(); 1585} 1586 1587bool SkCanvas::quickReject(const SkRect& rect) const { 1588 if (!rect.isFinite()) 1589 return true; 1590 1591 if (fMCRec->fRasterClip.isEmpty()) { 1592 return true; 1593 } 1594 1595 if (fMCRec->fMatrix.hasPerspective()) { 1596 SkRect dst; 1597 fMCRec->fMatrix.mapRect(&dst, rect); 1598 return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds()); 1599 } else { 1600 const SkRect& clipR = this->getLocalClipBounds(); 1601 1602 // for speed, do the most likely reject compares first 1603 // TODO: should we use | instead, or compare all 4 at once? 1604 if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) { 1605 return true; 1606 } 1607 if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) { 1608 return true; 1609 } 1610 return false; 1611 } 1612} 1613 1614bool SkCanvas::quickReject(const SkPath& path) const { 1615 return path.isEmpty() || this->quickReject(path.getBounds()); 1616} 1617 1618bool SkCanvas::getClipBounds(SkRect* bounds) const { 1619 SkIRect ibounds; 1620 if (!this->getClipDeviceBounds(&ibounds)) { 1621 return false; 1622 } 1623 1624 SkMatrix inverse; 1625 // if we can't invert the CTM, we can't return local clip bounds 1626 if (!fMCRec->fMatrix.invert(&inverse)) { 1627 if (bounds) { 1628 bounds->setEmpty(); 1629 } 1630 return false; 1631 } 1632 1633 if (bounds) { 1634 SkRect r; 1635 // adjust it outwards in case we are antialiasing 1636 const int inset = 1; 1637 1638 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1639 ibounds.fRight + inset, ibounds.fBottom + inset); 1640 inverse.mapRect(bounds, r); 1641 } 1642 return true; 1643} 1644 1645bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1646 const SkRasterClip& clip = fMCRec->fRasterClip; 1647 if (clip.isEmpty()) { 1648 if (bounds) { 1649 bounds->setEmpty(); 1650 } 1651 return false; 1652 } 1653 1654 if (bounds) { 1655 *bounds = clip.getBounds(); 1656 } 1657 return true; 1658} 1659 1660const SkMatrix& SkCanvas::getTotalMatrix() const { 1661 return fMCRec->fMatrix; 1662} 1663 1664const SkRegion& SkCanvas::internal_private_getTotalClip() const { 1665 return fMCRec->fRasterClip.forceGetBW(); 1666} 1667 1668GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() { 1669 SkBaseDevice* dev = this->getTopDevice(); 1670 return dev ? dev->accessRenderTarget() : NULL; 1671} 1672 1673GrContext* SkCanvas::getGrContext() { 1674#if SK_SUPPORT_GPU 1675 SkBaseDevice* device = this->getTopDevice(); 1676 if (device) { 1677 GrRenderTarget* renderTarget = device->accessRenderTarget(); 1678 if (renderTarget) { 1679 return renderTarget->getContext(); 1680 } 1681 } 1682#endif 1683 1684 return NULL; 1685 1686} 1687 1688void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner, 1689 const SkPaint& paint) { 1690 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()"); 1691 if (outer.isEmpty()) { 1692 return; 1693 } 1694 if (inner.isEmpty()) { 1695 this->drawRRect(outer, paint); 1696 return; 1697 } 1698 1699 // We don't have this method (yet), but technically this is what we should 1700 // be able to assert... 1701 // SkASSERT(outer.contains(inner)); 1702 // 1703 // For now at least check for containment of bounds 1704 SkASSERT(outer.getBounds().contains(inner.getBounds())); 1705 1706 this->onDrawDRRect(outer, inner, paint); 1707} 1708 1709// These need to stop being virtual -- clients need to override the onDraw... versions 1710 1711void SkCanvas::drawPaint(const SkPaint& paint) { 1712 this->onDrawPaint(paint); 1713} 1714 1715void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1716 this->onDrawRect(r, paint); 1717} 1718 1719void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) { 1720 this->onDrawOval(r, paint); 1721} 1722 1723void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) { 1724 this->onDrawRRect(rrect, paint); 1725} 1726 1727void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) { 1728 this->onDrawPoints(mode, count, pts, paint); 1729} 1730 1731void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[], 1732 const SkPoint texs[], const SkColor colors[], SkXfermode* xmode, 1733 const uint16_t indices[], int indexCount, const SkPaint& paint) { 1734 this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode, 1735 indices, indexCount, paint); 1736} 1737 1738void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1739 this->onDrawPath(path, paint); 1740} 1741 1742void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 1743 this->onDrawImage(image, x, y, paint); 1744} 1745 1746void SkCanvas::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 1747 const SkPaint* paint) { 1748 if (dst.isEmpty()) { 1749 return; 1750 } 1751 this->onDrawImageRect(image, src, dst, paint); 1752} 1753 1754void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) { 1755 if (bitmap.empty()) { 1756 return; 1757 } 1758 this->onDrawBitmap(bitmap, dx, dy, paint); 1759} 1760 1761void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 1762 const SkPaint* paint, DrawBitmapRectFlags flags) { 1763 if (bitmap.empty()) { 1764 return; 1765 } 1766 this->onDrawBitmapRect(bitmap, src, dst, paint, flags); 1767} 1768 1769void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 1770 const SkPaint* paint) { 1771 if (bitmap.empty()) { 1772 return; 1773 } 1774 this->onDrawBitmapNine(bitmap, center, dst, paint); 1775} 1776 1777void SkCanvas::drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint) { 1778 if (bitmap.empty()) { 1779 return; 1780 } 1781 this->onDrawSprite(bitmap, left, top, paint); 1782} 1783 1784////////////////////////////////////////////////////////////////////////////// 1785// These are the virtual drawing methods 1786////////////////////////////////////////////////////////////////////////////// 1787 1788void SkCanvas::onDiscard() { 1789 if (fSurfaceBase) { 1790 fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode); 1791 } 1792} 1793 1794void SkCanvas::onDrawPaint(const SkPaint& paint) { 1795 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()"); 1796 this->internalDrawPaint(paint); 1797} 1798 1799void SkCanvas::internalDrawPaint(const SkPaint& paint) { 1800 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type, NULL) 1801 1802 while (iter.next()) { 1803 iter.fDevice->drawPaint(iter, looper.paint()); 1804 } 1805 1806 LOOPER_END 1807} 1808 1809void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], 1810 const SkPaint& paint) { 1811 TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count)); 1812 if ((long)count <= 0) { 1813 return; 1814 } 1815 1816 SkRect r, storage; 1817 const SkRect* bounds = NULL; 1818 if (paint.canComputeFastBounds()) { 1819 // special-case 2 points (common for drawing a single line) 1820 if (2 == count) { 1821 r.set(pts[0], pts[1]); 1822 } else { 1823 r.set(pts, SkToInt(count)); 1824 } 1825 bounds = &paint.computeFastStrokeBounds(r, &storage); 1826 if (this->quickReject(*bounds)) { 1827 return; 1828 } 1829 } 1830 1831 SkASSERT(pts != NULL); 1832 1833 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds) 1834 1835 while (iter.next()) { 1836 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1837 } 1838 1839 LOOPER_END 1840} 1841 1842void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) { 1843 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()"); 1844 SkRect storage; 1845 const SkRect* bounds = NULL; 1846 if (paint.canComputeFastBounds()) { 1847 // Skia will draw an inverted rect, because it explicitly "sorts" it downstream. 1848 // To prevent accidental rejecting at this stage, we have to sort it before we check. 1849 SkRect tmp(r); 1850 tmp.sort(); 1851 1852 bounds = &paint.computeFastBounds(tmp, &storage); 1853 if (this->quickReject(*bounds)) { 1854 return; 1855 } 1856 } 1857 1858 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, bounds) 1859 1860 while (iter.next()) { 1861 iter.fDevice->drawRect(iter, r, looper.paint()); 1862 } 1863 1864 LOOPER_END 1865} 1866 1867void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) { 1868 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()"); 1869 SkRect storage; 1870 const SkRect* bounds = NULL; 1871 if (paint.canComputeFastBounds()) { 1872 bounds = &paint.computeFastBounds(oval, &storage); 1873 if (this->quickReject(*bounds)) { 1874 return; 1875 } 1876 } 1877 1878 LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds) 1879 1880 while (iter.next()) { 1881 iter.fDevice->drawOval(iter, oval, looper.paint()); 1882 } 1883 1884 LOOPER_END 1885} 1886 1887void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { 1888 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()"); 1889 SkRect storage; 1890 const SkRect* bounds = NULL; 1891 if (paint.canComputeFastBounds()) { 1892 bounds = &paint.computeFastBounds(rrect.getBounds(), &storage); 1893 if (this->quickReject(*bounds)) { 1894 return; 1895 } 1896 } 1897 1898 if (rrect.isRect()) { 1899 // call the non-virtual version 1900 this->SkCanvas::drawRect(rrect.getBounds(), paint); 1901 return; 1902 } else if (rrect.isOval()) { 1903 // call the non-virtual version 1904 this->SkCanvas::drawOval(rrect.getBounds(), paint); 1905 return; 1906 } 1907 1908 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1909 1910 while (iter.next()) { 1911 iter.fDevice->drawRRect(iter, rrect, looper.paint()); 1912 } 1913 1914 LOOPER_END 1915} 1916 1917void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, 1918 const SkPaint& paint) { 1919 SkRect storage; 1920 const SkRect* bounds = NULL; 1921 if (paint.canComputeFastBounds()) { 1922 bounds = &paint.computeFastBounds(outer.getBounds(), &storage); 1923 if (this->quickReject(*bounds)) { 1924 return; 1925 } 1926 } 1927 1928 LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds) 1929 1930 while (iter.next()) { 1931 iter.fDevice->drawDRRect(iter, outer, inner, looper.paint()); 1932 } 1933 1934 LOOPER_END 1935} 1936 1937void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { 1938 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()"); 1939 if (!path.isFinite()) { 1940 return; 1941 } 1942 1943 SkRect storage; 1944 const SkRect* bounds = NULL; 1945 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1946 const SkRect& pathBounds = path.getBounds(); 1947 bounds = &paint.computeFastBounds(pathBounds, &storage); 1948 if (this->quickReject(*bounds)) { 1949 return; 1950 } 1951 } 1952 1953 const SkRect& r = path.getBounds(); 1954 if (r.width() <= 0 && r.height() <= 0) { 1955 if (path.isInverseFillType()) { 1956 this->internalDrawPaint(paint); 1957 } 1958 return; 1959 } 1960 1961 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds) 1962 1963 while (iter.next()) { 1964 iter.fDevice->drawPath(iter, path, looper.paint()); 1965 } 1966 1967 LOOPER_END 1968} 1969 1970void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { 1971 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); 1972 SkRect bounds = SkRect::MakeXYWH(x, y, 1973 SkIntToScalar(image->width()), SkIntToScalar(image->height())); 1974 if (NULL == paint || paint->canComputeFastBounds()) { 1975 if (paint) { 1976 paint->computeFastBounds(bounds, &bounds); 1977 } 1978 if (this->quickReject(bounds)) { 1979 return; 1980 } 1981 } 1982 1983 SkLazyPaint lazy; 1984 if (NULL == paint) { 1985 paint = lazy.init(); 1986 } 1987 1988 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds) 1989 1990 while (iter.next()) { 1991 iter.fDevice->drawImage(iter, image, x, y, looper.paint()); 1992 } 1993 1994 LOOPER_END 1995} 1996 1997void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, 1998 const SkPaint* paint) { 1999 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()"); 2000 SkRect storage; 2001 const SkRect* bounds = &dst; 2002 if (NULL == paint || paint->canComputeFastBounds()) { 2003 if (paint) { 2004 bounds = &paint->computeFastBounds(dst, &storage); 2005 } 2006 if (this->quickReject(*bounds)) { 2007 return; 2008 } 2009 } 2010 SkLazyPaint lazy; 2011 if (NULL == paint) { 2012 paint = lazy.init(); 2013 } 2014 2015 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 2016 2017 while (iter.next()) { 2018 iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint()); 2019 } 2020 2021 LOOPER_END 2022} 2023 2024void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) { 2025 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()"); 2026 SkDEBUGCODE(bitmap.validate();) 2027 2028 if (NULL == paint || paint->canComputeFastBounds()) { 2029 SkRect bounds = { 2030 x, y, 2031 x + SkIntToScalar(bitmap.width()), 2032 y + SkIntToScalar(bitmap.height()) 2033 }; 2034 if (paint) { 2035 (void)paint->computeFastBounds(bounds, &bounds); 2036 } 2037 if (this->quickReject(bounds)) { 2038 return; 2039 } 2040 } 2041 2042 SkMatrix matrix; 2043 matrix.setTranslate(x, y); 2044 this->internalDrawBitmap(bitmap, matrix, paint); 2045} 2046 2047// this one is non-virtual, so it can be called safely by other canvas apis 2048void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, 2049 const SkRect& dst, const SkPaint* paint, 2050 DrawBitmapRectFlags flags) { 2051 if (bitmap.drawsNothing() || dst.isEmpty()) { 2052 return; 2053 } 2054 2055 SkRect storage; 2056 const SkRect* bounds = &dst; 2057 if (NULL == paint || paint->canComputeFastBounds()) { 2058 if (paint) { 2059 bounds = &paint->computeFastBounds(dst, &storage); 2060 } 2061 if (this->quickReject(*bounds)) { 2062 return; 2063 } 2064 } 2065 2066 SkLazyPaint lazy; 2067 if (NULL == paint) { 2068 paint = lazy.init(); 2069 } 2070 2071 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) 2072 2073 while (iter.next()) { 2074 iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), flags); 2075 } 2076 2077 LOOPER_END 2078} 2079 2080void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, 2081 const SkPaint* paint, DrawBitmapRectFlags flags) { 2082 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()"); 2083 SkDEBUGCODE(bitmap.validate();) 2084 this->internalDrawBitmapRect(bitmap, src, dst, paint, flags); 2085} 2086 2087void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 2088 const SkIRect& center, const SkRect& dst, 2089 const SkPaint* paint) { 2090 if (bitmap.drawsNothing()) { 2091 return; 2092 } 2093 if (NULL == paint || paint->canComputeFastBounds()) { 2094 SkRect storage; 2095 const SkRect* bounds = &dst; 2096 if (paint) { 2097 bounds = &paint->computeFastBounds(dst, &storage); 2098 } 2099 if (this->quickReject(*bounds)) { 2100 return; 2101 } 2102 } 2103 2104 const int32_t w = bitmap.width(); 2105 const int32_t h = bitmap.height(); 2106 2107 SkIRect c = center; 2108 // pin center to the bounds of the bitmap 2109 c.fLeft = SkMax32(0, center.fLeft); 2110 c.fTop = SkMax32(0, center.fTop); 2111 c.fRight = SkPin32(center.fRight, c.fLeft, w); 2112 c.fBottom = SkPin32(center.fBottom, c.fTop, h); 2113 2114 const SkScalar srcX[4] = { 2115 0, SkIntToScalar(c.fLeft), SkIntToScalar(c.fRight), SkIntToScalar(w) 2116 }; 2117 const SkScalar srcY[4] = { 2118 0, SkIntToScalar(c.fTop), SkIntToScalar(c.fBottom), SkIntToScalar(h) 2119 }; 2120 SkScalar dstX[4] = { 2121 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 2122 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 2123 }; 2124 SkScalar dstY[4] = { 2125 dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 2126 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 2127 }; 2128 2129 if (dstX[1] > dstX[2]) { 2130 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 2131 dstX[2] = dstX[1]; 2132 } 2133 2134 if (dstY[1] > dstY[2]) { 2135 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 2136 dstY[2] = dstY[1]; 2137 } 2138 2139 for (int y = 0; y < 3; y++) { 2140 SkRect s, d; 2141 2142 s.fTop = srcY[y]; 2143 s.fBottom = srcY[y+1]; 2144 d.fTop = dstY[y]; 2145 d.fBottom = dstY[y+1]; 2146 for (int x = 0; x < 3; x++) { 2147 s.fLeft = srcX[x]; 2148 s.fRight = srcX[x+1]; 2149 d.fLeft = dstX[x]; 2150 d.fRight = dstX[x+1]; 2151 this->internalDrawBitmapRect(bitmap, &s, d, paint, 2152 kNone_DrawBitmapRectFlag); 2153 } 2154 } 2155} 2156 2157void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, 2158 const SkPaint* paint) { 2159 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()"); 2160 SkDEBUGCODE(bitmap.validate();) 2161 2162 // Need a device entry-point, so gpu can use a mesh 2163 this->internalDrawBitmapNine(bitmap, center, dst, paint); 2164} 2165 2166class SkDeviceFilteredPaint { 2167public: 2168 SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) { 2169 uint32_t filteredFlags = device->filterTextFlags(paint); 2170 if (filteredFlags != paint.getFlags()) { 2171 SkPaint* newPaint = fLazy.set(paint); 2172 newPaint->setFlags(filteredFlags); 2173 fPaint = newPaint; 2174 } else { 2175 fPaint = &paint; 2176 } 2177 } 2178 2179 const SkPaint& paint() const { return *fPaint; } 2180 2181private: 2182 const SkPaint* fPaint; 2183 SkLazyPaint fLazy; 2184}; 2185 2186void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 2187 const SkRect& r, SkScalar textSize) { 2188 if (paint.getStyle() == SkPaint::kFill_Style) { 2189 draw.fDevice->drawRect(draw, r, paint); 2190 } else { 2191 SkPaint p(paint); 2192 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 2193 draw.fDevice->drawRect(draw, r, p); 2194 } 2195} 2196 2197void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 2198 const char text[], size_t byteLength, 2199 SkScalar x, SkScalar y) { 2200 SkASSERT(byteLength == 0 || text != NULL); 2201 2202 // nothing to draw 2203 if (text == NULL || byteLength == 0 || 2204 draw.fClip->isEmpty() || 2205 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 2206 return; 2207 } 2208 2209 SkScalar width = 0; 2210 SkPoint start; 2211 2212 start.set(0, 0); // to avoid warning 2213 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 2214 SkPaint::kStrikeThruText_Flag)) { 2215 width = paint.measureText(text, byteLength); 2216 2217 SkScalar offsetX = 0; 2218 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 2219 offsetX = SkScalarHalf(width); 2220 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 2221 offsetX = width; 2222 } 2223 start.set(x - offsetX, y); 2224 } 2225 2226 if (0 == width) { 2227 return; 2228 } 2229 2230 uint32_t flags = paint.getFlags(); 2231 2232 if (flags & (SkPaint::kUnderlineText_Flag | 2233 SkPaint::kStrikeThruText_Flag)) { 2234 SkScalar textSize = paint.getTextSize(); 2235 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 2236 SkRect r; 2237 2238 r.fLeft = start.fX; 2239 r.fRight = start.fX + width; 2240 2241 if (flags & SkPaint::kUnderlineText_Flag) { 2242 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 2243 start.fY); 2244 r.fTop = offset; 2245 r.fBottom = offset + height; 2246 DrawRect(draw, paint, r, textSize); 2247 } 2248 if (flags & SkPaint::kStrikeThruText_Flag) { 2249 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 2250 start.fY); 2251 r.fTop = offset; 2252 r.fBottom = offset + height; 2253 DrawRect(draw, paint, r, textSize); 2254 } 2255 } 2256} 2257 2258void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2259 const SkPaint& paint) { 2260 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2261 2262 while (iter.next()) { 2263 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2264 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 2265 DrawTextDecorations(iter, dfp.paint(), 2266 static_cast<const char*>(text), byteLength, x, y); 2267 } 2268 2269 LOOPER_END 2270} 2271 2272void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2273 const SkPaint& paint) { 2274 SkPoint textOffset = SkPoint::Make(0, 0); 2275 2276 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2277 2278 while (iter.next()) { 2279 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2280 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset, 2281 dfp.paint()); 2282 } 2283 2284 LOOPER_END 2285} 2286 2287void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2288 SkScalar constY, const SkPaint& paint) { 2289 2290 SkPoint textOffset = SkPoint::Make(0, constY); 2291 2292 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2293 2294 while (iter.next()) { 2295 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2296 iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset, 2297 dfp.paint()); 2298 } 2299 2300 LOOPER_END 2301} 2302 2303void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2304 const SkMatrix* matrix, const SkPaint& paint) { 2305 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, NULL) 2306 2307 while (iter.next()) { 2308 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 2309 matrix, looper.paint()); 2310 } 2311 2312 LOOPER_END 2313} 2314 2315void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2316 const SkPaint& paint) { 2317 2318 SkRect storage; 2319 const SkRect* bounds = NULL; 2320 if (paint.canComputeFastBounds()) { 2321 storage = blob->bounds().makeOffset(x, y); 2322 bounds = &paint.computeFastBounds(storage, &storage); 2323 2324 if (this->quickReject(*bounds)) { 2325 return; 2326 } 2327 } 2328 2329 // We cannot filter in the looper as we normally do, because the paint is 2330 // incomplete at this point (text-related attributes are embedded within blob run paints). 2331 SkDrawFilter* drawFilter = fMCRec->fFilter; 2332 fMCRec->fFilter = NULL; 2333 2334 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds) 2335 2336 while (iter.next()) { 2337 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 2338 iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter); 2339 } 2340 2341 LOOPER_END 2342 2343 fMCRec->fFilter = drawFilter; 2344} 2345 2346// These will become non-virtual, so they always call the (virtual) onDraw... method 2347void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, 2348 const SkPaint& paint) { 2349 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()"); 2350 this->onDrawText(text, byteLength, x, y, paint); 2351} 2352void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[], 2353 const SkPaint& paint) { 2354 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()"); 2355 this->onDrawPosText(text, byteLength, pos, paint); 2356} 2357void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], 2358 SkScalar constY, const SkPaint& paint) { 2359 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()"); 2360 this->onDrawPosTextH(text, byteLength, xpos, constY, paint); 2361} 2362void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path, 2363 const SkMatrix* matrix, const SkPaint& paint) { 2364 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()"); 2365 this->onDrawTextOnPath(text, byteLength, path, matrix, paint); 2366} 2367void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, 2368 const SkPaint& paint) { 2369 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()"); 2370 if (blob) { 2371 this->onDrawTextBlob(blob, x, y, paint); 2372 } 2373} 2374 2375void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount, 2376 const SkPoint verts[], const SkPoint texs[], 2377 const SkColor colors[], SkXfermode* xmode, 2378 const uint16_t indices[], int indexCount, 2379 const SkPaint& paint) { 2380 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()"); 2381 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2382 2383 while (iter.next()) { 2384 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 2385 colors, xmode, indices, indexCount, 2386 looper.paint()); 2387 } 2388 2389 LOOPER_END 2390} 2391 2392void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4], 2393 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2394 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()"); 2395 if (NULL == cubics) { 2396 return; 2397 } 2398 2399 // Since a patch is always within the convex hull of the control points, we discard it when its 2400 // bounding rectangle is completely outside the current clip. 2401 SkRect bounds; 2402 bounds.set(cubics, SkPatchUtils::kNumCtrlPts); 2403 if (this->quickReject(bounds)) { 2404 return; 2405 } 2406 2407 this->onDrawPatch(cubics, colors, texCoords, xmode, paint); 2408} 2409 2410void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], 2411 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) { 2412 2413 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, NULL) 2414 2415 while (iter.next()) { 2416 iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint); 2417 } 2418 2419 LOOPER_END 2420} 2421 2422void SkCanvas::drawDrawable(SkDrawable* dr) { 2423 if (dr && !this->quickReject(dr->getBounds())) { 2424 this->onDrawDrawable(dr); 2425 } 2426} 2427 2428void SkCanvas::onDrawDrawable(SkDrawable* dr) { 2429 dr->draw(this); 2430} 2431 2432////////////////////////////////////////////////////////////////////////////// 2433// These methods are NOT virtual, and therefore must call back into virtual 2434// methods, rather than actually drawing themselves. 2435////////////////////////////////////////////////////////////////////////////// 2436 2437void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 2438 SkXfermode::Mode mode) { 2439 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); 2440 SkPaint paint; 2441 2442 paint.setARGB(a, r, g, b); 2443 if (SkXfermode::kSrcOver_Mode != mode) { 2444 paint.setXfermodeMode(mode); 2445 } 2446 this->drawPaint(paint); 2447} 2448 2449void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 2450 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); 2451 SkPaint paint; 2452 2453 paint.setColor(c); 2454 if (SkXfermode::kSrcOver_Mode != mode) { 2455 paint.setXfermodeMode(mode); 2456 } 2457 this->drawPaint(paint); 2458} 2459 2460void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 2461 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)"); 2462 SkPoint pt; 2463 2464 pt.set(x, y); 2465 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2466} 2467 2468void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 2469 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)"); 2470 SkPoint pt; 2471 SkPaint paint; 2472 2473 pt.set(x, y); 2474 paint.setColor(color); 2475 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 2476} 2477 2478void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 2479 const SkPaint& paint) { 2480 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()"); 2481 SkPoint pts[2]; 2482 2483 pts[0].set(x0, y0); 2484 pts[1].set(x1, y1); 2485 this->drawPoints(kLines_PointMode, 2, pts, paint); 2486} 2487 2488void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 2489 SkScalar right, SkScalar bottom, 2490 const SkPaint& paint) { 2491 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()"); 2492 SkRect r; 2493 2494 r.set(left, top, right, bottom); 2495 this->drawRect(r, paint); 2496} 2497 2498void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 2499 const SkPaint& paint) { 2500 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()"); 2501 if (radius < 0) { 2502 radius = 0; 2503 } 2504 2505 SkRect r; 2506 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 2507 this->drawOval(r, paint); 2508} 2509 2510void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 2511 const SkPaint& paint) { 2512 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()"); 2513 if (rx > 0 && ry > 0) { 2514 if (paint.canComputeFastBounds()) { 2515 SkRect storage; 2516 if (this->quickReject(paint.computeFastBounds(r, &storage))) { 2517 return; 2518 } 2519 } 2520 SkRRect rrect; 2521 rrect.setRectXY(r, rx, ry); 2522 this->drawRRect(rrect, paint); 2523 } else { 2524 this->drawRect(r, paint); 2525 } 2526} 2527 2528void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 2529 SkScalar sweepAngle, bool useCenter, 2530 const SkPaint& paint) { 2531 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()"); 2532 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 2533 this->drawOval(oval, paint); 2534 } else { 2535 SkPath path; 2536 if (useCenter) { 2537 path.moveTo(oval.centerX(), oval.centerY()); 2538 } 2539 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 2540 if (useCenter) { 2541 path.close(); 2542 } 2543 this->drawPath(path, paint); 2544 } 2545} 2546 2547void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 2548 const SkPath& path, SkScalar hOffset, 2549 SkScalar vOffset, const SkPaint& paint) { 2550 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()"); 2551 SkMatrix matrix; 2552 2553 matrix.setTranslate(hOffset, vOffset); 2554 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 2555} 2556 2557/////////////////////////////////////////////////////////////////////////////// 2558 2559/** 2560 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, 2561 * against the playback cost of recursing into the subpicture to get at its actual ops. 2562 * 2563 * For now we pick a conservatively small value, though measurement (and other heuristics like 2564 * the type of ops contained) may justify changing this value. 2565 */ 2566#define kMaxPictureOpsToUnrollInsteadOfRef 1 2567 2568void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { 2569 TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()"); 2570 if (picture) { 2571 if (matrix && matrix->isIdentity()) { 2572 matrix = NULL; 2573 } 2574 if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) { 2575 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2576 picture->playback(this); 2577 } else { 2578 this->onDrawPicture(picture, matrix, paint); 2579 } 2580 } 2581} 2582 2583void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, 2584 const SkPaint* paint) { 2585 SkBaseDevice* device = this->getTopDevice(); 2586 if (device) { 2587 // Canvas has to first give the device the opportunity to render 2588 // the picture itself. 2589 if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) { 2590 return; // the device has rendered the entire picture 2591 } 2592 } 2593 2594 SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); 2595 picture->playback(this); 2596} 2597 2598/////////////////////////////////////////////////////////////////////////////// 2599/////////////////////////////////////////////////////////////////////////////// 2600 2601SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 2602 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 2603 2604 SkASSERT(canvas); 2605 2606 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 2607 fDone = !fImpl->next(); 2608} 2609 2610SkCanvas::LayerIter::~LayerIter() { 2611 fImpl->~SkDrawIter(); 2612} 2613 2614void SkCanvas::LayerIter::next() { 2615 fDone = !fImpl->next(); 2616} 2617 2618SkBaseDevice* SkCanvas::LayerIter::device() const { 2619 return fImpl->getDevice(); 2620} 2621 2622const SkMatrix& SkCanvas::LayerIter::matrix() const { 2623 return fImpl->getMatrix(); 2624} 2625 2626const SkPaint& SkCanvas::LayerIter::paint() const { 2627 const SkPaint* paint = fImpl->getPaint(); 2628 if (NULL == paint) { 2629 paint = &fDefaultPaint; 2630 } 2631 return *paint; 2632} 2633 2634const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 2635int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 2636int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 2637 2638/////////////////////////////////////////////////////////////////////////////// 2639 2640SkCanvasClipVisitor::~SkCanvasClipVisitor() { } 2641 2642/////////////////////////////////////////////////////////////////////////////// 2643 2644static bool supported_for_raster_canvas(const SkImageInfo& info) { 2645 switch (info.alphaType()) { 2646 case kPremul_SkAlphaType: 2647 case kOpaque_SkAlphaType: 2648 break; 2649 default: 2650 return false; 2651 } 2652 2653 switch (info.colorType()) { 2654 case kAlpha_8_SkColorType: 2655 case kRGB_565_SkColorType: 2656 case kN32_SkColorType: 2657 break; 2658 default: 2659 return false; 2660 } 2661 2662 return true; 2663} 2664 2665SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 2666 if (!supported_for_raster_canvas(info)) { 2667 return NULL; 2668 } 2669 2670 SkBitmap bitmap; 2671 if (!bitmap.installPixels(info, pixels, rowBytes)) { 2672 return NULL; 2673 } 2674 return SkNEW_ARGS(SkCanvas, (bitmap)); 2675} 2676 2677/////////////////////////////////////////////////////////////////////////////// 2678 2679SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix, 2680 const SkPaint* paint, const SkRect& bounds) 2681 : fCanvas(canvas) 2682 , fSaveCount(canvas->getSaveCount()) 2683{ 2684 if (paint) { 2685 SkRect newBounds = bounds; 2686 if (matrix) { 2687 matrix->mapRect(&newBounds); 2688 } 2689 canvas->saveLayer(&newBounds, paint); 2690 } else if (matrix) { 2691 canvas->save(); 2692 } 2693 2694 if (matrix) { 2695 canvas->concat(*matrix); 2696 } 2697} 2698 2699SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { 2700 fCanvas->restoreToCount(fSaveCount); 2701} 2702