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