1 2 /* 3 * Copyright 2008 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkCanvas.h" 11 #include "SkBounder.h" 12 #include "SkDevice.h" 13 #include "SkDraw.h" 14 #include "SkDrawFilter.h" 15 #include "SkDrawLooper.h" 16 #include "SkPicture.h" 17 #include "SkRasterClip.h" 18 #include "SkScalarCompare.h" 19 #include "SkTemplates.h" 20 #include "SkTextFormatParams.h" 21 #include "SkTLazy.h" 22 #include "SkUtils.h" 23 24 //#define SK_TRACE_SAVERESTORE 25 26 #ifdef SK_TRACE_SAVERESTORE 27 static int gLayerCounter; 28 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 29 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 30 31 static int gRecCounter; 32 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 33 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 34 35 static int gCanvasCounter; 36 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 37 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 38 #else 39 #define inc_layer() 40 #define dec_layer() 41 #define inc_rec() 42 #define dec_rec() 43 #define inc_canvas() 44 #define dec_canvas() 45 #endif 46 47 typedef SkTLazy<SkPaint> SkLazyPaint; 48 49 /////////////////////////////////////////////////////////////////////////////// 50 // Helpers for computing fast bounds for quickReject tests 51 52 static SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) { 53 return paint != NULL && paint->isAntiAlias() ? 54 SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType; 55 } 56 57 /////////////////////////////////////////////////////////////////////////////// 58 59 /* This is the record we keep for each SkDevice that the user installs. 60 The clip/matrix/proc are fields that reflect the top of the save/restore 61 stack. Whenever the canvas changes, it marks a dirty flag, and then before 62 these are used (assuming we're not on a layer) we rebuild these cache 63 values: they reflect the top of the save stack, but translated and clipped 64 by the device's XY offset and bitmap-bounds. 65 */ 66 struct DeviceCM { 67 DeviceCM* fNext; 68 SkDevice* fDevice; 69 SkRasterClip fClip; 70 const SkMatrix* fMatrix; 71 SkPaint* fPaint; // may be null (in the future) 72 // optional, related to canvas' external matrix 73 const SkMatrix* fMVMatrix; 74 const SkMatrix* fExtMatrix; 75 76 DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint) 77 : fNext(NULL) { 78 if (NULL != device) { 79 device->ref(); 80 device->lockPixels(); 81 } 82 fDevice = device; 83 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 84 } 85 86 ~DeviceCM() { 87 if (NULL != fDevice) { 88 fDevice->unlockPixels(); 89 fDevice->unref(); 90 } 91 SkDELETE(fPaint); 92 } 93 94 void updateMC(const SkMatrix& totalMatrix, const SkRasterClip& totalClip, 95 const SkClipStack& clipStack, SkRasterClip* updateClip) { 96 int x = fDevice->getOrigin().x(); 97 int y = fDevice->getOrigin().y(); 98 int width = fDevice->width(); 99 int height = fDevice->height(); 100 101 if ((x | y) == 0) { 102 fMatrix = &totalMatrix; 103 fClip = totalClip; 104 } else { 105 fMatrixStorage = totalMatrix; 106 fMatrixStorage.postTranslate(SkIntToScalar(-x), 107 SkIntToScalar(-y)); 108 fMatrix = &fMatrixStorage; 109 110 totalClip.translate(-x, -y, &fClip); 111 } 112 113 fClip.op(SkIRect::MakeWH(width, height), SkRegion::kIntersect_Op); 114 115 // intersect clip, but don't translate it (yet) 116 117 if (updateClip) { 118 updateClip->op(SkIRect::MakeXYWH(x, y, width, height), 119 SkRegion::kDifference_Op); 120 } 121 122 fDevice->setMatrixClip(*fMatrix, fClip.forceGetBW(), clipStack); 123 124 #ifdef SK_DEBUG 125 if (!fClip.isEmpty()) { 126 SkIRect deviceR; 127 deviceR.set(0, 0, width, height); 128 SkASSERT(deviceR.contains(fClip.getBounds())); 129 } 130 #endif 131 // default is to assume no external matrix 132 fMVMatrix = NULL; 133 fExtMatrix = NULL; 134 } 135 136 // can only be called after calling updateMC() 137 void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) { 138 fMVMatrixStorage.setConcat(extI, *fMatrix); 139 fMVMatrix = &fMVMatrixStorage; 140 fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas) 141 } 142 143 private: 144 SkMatrix fMatrixStorage, fMVMatrixStorage; 145 }; 146 147 /* This is the record we keep for each save/restore level in the stack. 148 Since a level optionally copies the matrix and/or stack, we have pointers 149 for these fields. If the value is copied for this level, the copy is 150 stored in the ...Storage field, and the pointer points to that. If the 151 value is not copied for this level, we ignore ...Storage, and just point 152 at the corresponding value in the previous level in the stack. 153 */ 154 class SkCanvas::MCRec { 155 public: 156 MCRec* fNext; 157 SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 158 SkRasterClip* fRasterClip; // points to either fRegionStorage or prev MCRec 159 SkDrawFilter* fFilter; // the current filter (or null) 160 161 DeviceCM* fLayer; 162 /* If there are any layers in the stack, this points to the top-most 163 one that is at or below this level in the stack (so we know what 164 bitmap/device to draw into from this level. This value is NOT 165 reference counted, since the real owner is either our fLayer field, 166 or a previous one in a lower level.) 167 */ 168 DeviceCM* fTopLayer; 169 170 MCRec(const MCRec* prev, int flags) { 171 if (NULL != prev) { 172 if (flags & SkCanvas::kMatrix_SaveFlag) { 173 fMatrixStorage = *prev->fMatrix; 174 fMatrix = &fMatrixStorage; 175 } else { 176 fMatrix = prev->fMatrix; 177 } 178 179 if (flags & SkCanvas::kClip_SaveFlag) { 180 fRasterClipStorage = *prev->fRasterClip; 181 fRasterClip = &fRasterClipStorage; 182 } else { 183 fRasterClip = prev->fRasterClip; 184 } 185 186 fFilter = prev->fFilter; 187 SkSafeRef(fFilter); 188 189 fTopLayer = prev->fTopLayer; 190 } else { // no prev 191 fMatrixStorage.reset(); 192 193 fMatrix = &fMatrixStorage; 194 fRasterClip = &fRasterClipStorage; 195 fFilter = NULL; 196 fTopLayer = NULL; 197 } 198 fLayer = NULL; 199 200 // don't bother initializing fNext 201 inc_rec(); 202 } 203 ~MCRec() { 204 SkSafeUnref(fFilter); 205 SkDELETE(fLayer); 206 dec_rec(); 207 } 208 209 private: 210 SkMatrix fMatrixStorage; 211 SkRasterClip fRasterClipStorage; 212 }; 213 214 class SkDrawIter : public SkDraw { 215 public: 216 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 217 canvas = canvas->canvasForDrawIter(); 218 fCanvas = canvas; 219 canvas->updateDeviceCMCache(); 220 221 fClipStack = &canvas->getTotalClipStack(); 222 fBounder = canvas->getBounder(); 223 fCurrLayer = canvas->fMCRec->fTopLayer; 224 fSkipEmptyClips = skipEmptyClips; 225 } 226 227 bool next() { 228 // skip over recs with empty clips 229 if (fSkipEmptyClips) { 230 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 231 fCurrLayer = fCurrLayer->fNext; 232 } 233 } 234 235 const DeviceCM* rec = fCurrLayer; 236 if (rec && rec->fDevice) { 237 238 fMatrix = rec->fMatrix; 239 fClip = &((SkRasterClip*)&rec->fClip)->forceGetBW(); 240 fRC = &rec->fClip; 241 fDevice = rec->fDevice; 242 fBitmap = &fDevice->accessBitmap(true); 243 fPaint = rec->fPaint; 244 fMVMatrix = rec->fMVMatrix; 245 fExtMatrix = rec->fExtMatrix; 246 SkDEBUGCODE(this->validate();) 247 248 fCurrLayer = rec->fNext; 249 if (fBounder) { 250 fBounder->setClip(fClip); 251 } 252 // fCurrLayer may be NULL now 253 254 fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip, *fClipStack); 255 return true; 256 } 257 return false; 258 } 259 260 SkDevice* getDevice() const { return fDevice; } 261 int getX() const { return fDevice->getOrigin().x(); } 262 int getY() const { return fDevice->getOrigin().y(); } 263 const SkMatrix& getMatrix() const { return *fMatrix; } 264 const SkRegion& getClip() const { return *fClip; } 265 const SkPaint* getPaint() const { return fPaint; } 266 267 private: 268 SkCanvas* fCanvas; 269 const DeviceCM* fCurrLayer; 270 const SkPaint* fPaint; // May be null. 271 SkBool8 fSkipEmptyClips; 272 273 typedef SkDraw INHERITED; 274 }; 275 276 ///////////////////////////////////////////////////////////////////////////// 277 278 class AutoDrawLooper { 279 public: 280 AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint) : fOrigPaint(paint) { 281 fCanvas = canvas; 282 fLooper = paint.getLooper(); 283 fFilter = canvas->getDrawFilter(); 284 fPaint = NULL; 285 fSaveCount = canvas->getSaveCount(); 286 fDone = false; 287 288 if (fLooper) { 289 fLooper->init(canvas); 290 } 291 } 292 293 ~AutoDrawLooper() { 294 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 295 } 296 297 const SkPaint& paint() const { 298 SkASSERT(fPaint); 299 return *fPaint; 300 } 301 302 bool next(SkDrawFilter::Type drawType); 303 304 private: 305 SkLazyPaint fLazyPaint; 306 SkCanvas* fCanvas; 307 const SkPaint& fOrigPaint; 308 SkDrawLooper* fLooper; 309 SkDrawFilter* fFilter; 310 const SkPaint* fPaint; 311 int fSaveCount; 312 bool fDone; 313 }; 314 315 bool AutoDrawLooper::next(SkDrawFilter::Type drawType) { 316 fPaint = NULL; 317 if (fDone) { 318 return false; 319 } 320 321 if (fLooper || fFilter) { 322 SkPaint* paint = fLazyPaint.set(fOrigPaint); 323 if (fLooper && !fLooper->next(fCanvas, paint)) { 324 fDone = true; 325 return false; 326 } 327 if (fFilter) { 328 fFilter->filter(paint, drawType); 329 if (NULL == fLooper) { 330 // no looper means we only draw once 331 fDone = true; 332 } 333 } 334 fPaint = paint; 335 } else { 336 fDone = true; 337 fPaint = &fOrigPaint; 338 } 339 340 // call this after any possible paint modifiers 341 if (fPaint->nothingToDraw()) { 342 fPaint = NULL; 343 return false; 344 } 345 return true; 346 } 347 348 /* Stack helper for managing a SkBounder. In the destructor, if we were 349 given a bounder, we call its commit() method, signifying that we are 350 done accumulating bounds for that draw. 351 */ 352 class SkAutoBounderCommit { 353 public: 354 SkAutoBounderCommit(SkBounder* bounder) : fBounder(bounder) {} 355 ~SkAutoBounderCommit() { 356 if (NULL != fBounder) { 357 fBounder->commit(); 358 } 359 } 360 private: 361 SkBounder* fBounder; 362 }; 363 364 #include "SkColorPriv.h" 365 366 class AutoValidator { 367 public: 368 AutoValidator(SkDevice* device) : fDevice(device) {} 369 ~AutoValidator() { 370 #ifdef SK_DEBUG 371 const SkBitmap& bm = fDevice->accessBitmap(false); 372 if (bm.config() == SkBitmap::kARGB_4444_Config) { 373 for (int y = 0; y < bm.height(); y++) { 374 const SkPMColor16* p = bm.getAddr16(0, y); 375 for (int x = 0; x < bm.width(); x++) { 376 SkPMColor16 c = p[x]; 377 SkPMColor16Assert(c); 378 } 379 } 380 } 381 #endif 382 } 383 private: 384 SkDevice* fDevice; 385 }; 386 387 ////////// macros to place around the internal draw calls ////////////////// 388 389 #define LOOPER_BEGIN(paint, type) \ 390 /* AutoValidator validator(fMCRec->fTopLayer->fDevice); */ \ 391 AutoDrawLooper looper(this, paint); \ 392 while (looper.next(type)) { \ 393 SkAutoBounderCommit ac(fBounder); \ 394 SkDrawIter iter(this); 395 396 #define LOOPER_END } 397 398 //////////////////////////////////////////////////////////////////////////// 399 400 SkDevice* SkCanvas::init(SkDevice* device) { 401 fBounder = NULL; 402 fLocalBoundsCompareType.setEmpty(); 403 fLocalBoundsCompareTypeDirty = true; 404 fLocalBoundsCompareTypeBW.setEmpty(); 405 fLocalBoundsCompareTypeDirtyBW = true; 406 fLastDeviceToGainFocus = NULL; 407 fDeviceCMDirty = false; 408 fLayerCount = 0; 409 410 fMCRec = (MCRec*)fMCStack.push_back(); 411 new (fMCRec) MCRec(NULL, 0); 412 413 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL)); 414 fMCRec->fTopLayer = fMCRec->fLayer; 415 fMCRec->fNext = NULL; 416 417 fExternalMatrix.reset(); 418 fExternalInverse.reset(); 419 fUseExternalMatrix = false; 420 421 return this->setDevice(device); 422 } 423 424 SkCanvas::SkCanvas() 425 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 426 inc_canvas(); 427 428 this->init(NULL); 429 } 430 431 SkCanvas::SkCanvas(SkDevice* device) 432 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 433 inc_canvas(); 434 435 this->init(device); 436 } 437 438 SkCanvas::SkCanvas(const SkBitmap& bitmap) 439 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 440 inc_canvas(); 441 442 this->init(SkNEW_ARGS(SkDevice, (bitmap)))->unref(); 443 } 444 445 SkCanvas::~SkCanvas() { 446 // free up the contents of our deque 447 this->restoreToCount(1); // restore everything but the last 448 SkASSERT(0 == fLayerCount); 449 450 this->internalRestore(); // restore the last, since we're going away 451 452 SkSafeUnref(fBounder); 453 454 dec_canvas(); 455 } 456 457 SkBounder* SkCanvas::setBounder(SkBounder* bounder) { 458 SkRefCnt_SafeAssign(fBounder, bounder); 459 return bounder; 460 } 461 462 SkDrawFilter* SkCanvas::getDrawFilter() const { 463 return fMCRec->fFilter; 464 } 465 466 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 467 SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 468 return filter; 469 } 470 471 /////////////////////////////////////////////////////////////////////////////// 472 473 void SkCanvas::flush() { 474 SkDevice* device = this->getDevice(); 475 if (device) { 476 device->flush(); 477 } 478 } 479 480 SkISize SkCanvas::getDeviceSize() const { 481 SkDevice* d = this->getDevice(); 482 return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0); 483 } 484 485 SkDevice* SkCanvas::getDevice() const { 486 // return root device 487 SkDeque::F2BIter iter(fMCStack); 488 MCRec* rec = (MCRec*)iter.next(); 489 SkASSERT(rec && rec->fLayer); 490 return rec->fLayer->fDevice; 491 } 492 493 SkDevice* SkCanvas::getTopDevice() const { 494 return fMCRec->fTopLayer->fDevice; 495 } 496 497 SkDevice* SkCanvas::setDevice(SkDevice* device) { 498 // return root device 499 SkDeque::F2BIter iter(fMCStack); 500 MCRec* rec = (MCRec*)iter.next(); 501 SkASSERT(rec && rec->fLayer); 502 SkDevice* rootDevice = rec->fLayer->fDevice; 503 504 if (rootDevice == device) { 505 return device; 506 } 507 508 /* Notify the devices that they are going in/out of scope, so they can do 509 things like lock/unlock their pixels, etc. 510 */ 511 if (device) { 512 device->lockPixels(); 513 } 514 if (rootDevice) { 515 rootDevice->unlockPixels(); 516 } 517 518 SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 519 rootDevice = device; 520 521 fDeviceCMDirty = true; 522 523 /* Now we update our initial region to have the bounds of the new device, 524 and then intersect all of the clips in our stack with these bounds, 525 to ensure that we can't draw outside of the device's bounds (and trash 526 memory). 527 528 NOTE: this is only a partial-fix, since if the new device is larger than 529 the previous one, we don't know how to "enlarge" the clips in our stack, 530 so drawing may be artificially restricted. Without keeping a history of 531 all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 532 reconstruct the correct clips, so this approximation will have to do. 533 The caller really needs to restore() back to the base if they want to 534 accurately take advantage of the new device bounds. 535 */ 536 537 if (NULL == device) { 538 rec->fRasterClip->setEmpty(); 539 while ((rec = (MCRec*)iter.next()) != NULL) { 540 (void)rec->fRasterClip->setEmpty(); 541 } 542 fClipStack.reset(); 543 } else { 544 // compute our total bounds for all devices 545 SkIRect bounds; 546 547 bounds.set(0, 0, device->width(), device->height()); 548 549 // now jam our 1st clip to be bounds, and intersect the rest with that 550 rec->fRasterClip->setRect(bounds); 551 while ((rec = (MCRec*)iter.next()) != NULL) { 552 (void)rec->fRasterClip->op(bounds, SkRegion::kIntersect_Op); 553 } 554 } 555 return device; 556 } 557 558 SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) { 559 SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap))); 560 device->unref(); 561 return device; 562 } 563 564 bool SkCanvas::readPixels(SkBitmap* bitmap, 565 int x, int y, 566 Config8888 config8888) { 567 SkDevice* device = this->getDevice(); 568 if (!device) { 569 return false; 570 } 571 return device->readPixels(bitmap, x, y, config8888); 572 } 573 574 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 575 SkDevice* device = this->getDevice(); 576 if (!device) { 577 return false; 578 } 579 580 SkIRect bounds; 581 bounds.set(0, 0, device->width(), device->height()); 582 if (!bounds.intersect(srcRect)) { 583 return false; 584 } 585 586 SkBitmap tmp; 587 tmp.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), 588 bounds.height()); 589 if (this->readPixels(&tmp, bounds.fLeft, bounds.fTop)) { 590 bitmap->swap(tmp); 591 return true; 592 } else { 593 return false; 594 } 595 } 596 597 void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y, 598 Config8888 config8888) { 599 SkDevice* device = this->getDevice(); 600 if (device) { 601 device->writePixels(bitmap, x, y, config8888); 602 } 603 } 604 605 SkCanvas* SkCanvas::canvasForDrawIter() { 606 return this; 607 } 608 609 ////////////////////////////////////////////////////////////////////////////// 610 611 void SkCanvas::updateDeviceCMCache() { 612 if (fDeviceCMDirty) { 613 const SkMatrix& totalMatrix = this->getTotalMatrix(); 614 const SkRasterClip& totalClip = *fMCRec->fRasterClip; 615 DeviceCM* layer = fMCRec->fTopLayer; 616 617 if (NULL == layer->fNext) { // only one layer 618 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 619 if (fUseExternalMatrix) { 620 layer->updateExternalMatrix(fExternalMatrix, 621 fExternalInverse); 622 } 623 } else { 624 SkRasterClip clip(totalClip); 625 do { 626 layer->updateMC(totalMatrix, clip, fClipStack, &clip); 627 if (fUseExternalMatrix) { 628 layer->updateExternalMatrix(fExternalMatrix, 629 fExternalInverse); 630 } 631 } while ((layer = layer->fNext) != NULL); 632 } 633 fDeviceCMDirty = false; 634 } 635 } 636 637 void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix, 638 const SkRegion& clip, 639 const SkClipStack& clipStack) { 640 SkASSERT(device); 641 if (fLastDeviceToGainFocus != device) { 642 device->gainFocus(this, matrix, clip, clipStack); 643 fLastDeviceToGainFocus = device; 644 } 645 } 646 647 /////////////////////////////////////////////////////////////////////////////// 648 649 int SkCanvas::internalSave(SaveFlags flags) { 650 int saveCount = this->getSaveCount(); // record this before the actual save 651 652 MCRec* newTop = (MCRec*)fMCStack.push_back(); 653 new (newTop) MCRec(fMCRec, flags); // balanced in restore() 654 655 newTop->fNext = fMCRec; 656 fMCRec = newTop; 657 658 fClipStack.save(); 659 SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 660 661 return saveCount; 662 } 663 664 int SkCanvas::save(SaveFlags flags) { 665 // call shared impl 666 return this->internalSave(flags); 667 } 668 669 #define C32MASK (1 << SkBitmap::kARGB_8888_Config) 670 #define C16MASK (1 << SkBitmap::kRGB_565_Config) 671 #define C8MASK (1 << SkBitmap::kA8_Config) 672 673 static SkBitmap::Config resolve_config(SkCanvas* canvas, 674 const SkIRect& bounds, 675 SkCanvas::SaveFlags flags, 676 bool* isOpaque) { 677 *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 678 679 #if 0 680 // loop through and union all the configs we may draw into 681 uint32_t configMask = 0; 682 for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 683 { 684 SkDevice* device = canvas->getLayerDevice(i); 685 if (device->intersects(bounds)) 686 configMask |= 1 << device->config(); 687 } 688 689 // if the caller wants alpha or fullcolor, we can't return 565 690 if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 691 SkCanvas::kHasAlphaLayer_SaveFlag)) 692 configMask &= ~C16MASK; 693 694 switch (configMask) { 695 case C8MASK: // if we only have A8, return that 696 return SkBitmap::kA8_Config; 697 698 case C16MASK: // if we only have 565, return that 699 return SkBitmap::kRGB_565_Config; 700 701 default: 702 return SkBitmap::kARGB_8888_Config; // default answer 703 } 704 #else 705 return SkBitmap::kARGB_8888_Config; // default answer 706 #endif 707 } 708 709 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 710 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 711 } 712 713 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, 714 SkIRect* intersection) { 715 SkIRect clipBounds; 716 if (!this->getClipDeviceBounds(&clipBounds)) { 717 return false; 718 } 719 SkIRect ir; 720 if (NULL != bounds) { 721 SkRect r; 722 723 this->getTotalMatrix().mapRect(&r, *bounds); 724 r.roundOut(&ir); 725 // early exit if the layer's bounds are clipped out 726 if (!ir.intersect(clipBounds)) { 727 if (bounds_affects_clip(flags)) { 728 fMCRec->fRasterClip->setEmpty(); 729 } 730 return false; 731 } 732 } else { // no user bounds, so just use the clip 733 ir = clipBounds; 734 } 735 736 fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op); 737 738 // early exit if the clip is now empty 739 if (bounds_affects_clip(flags) && 740 !fMCRec->fRasterClip->op(ir, SkRegion::kIntersect_Op)) { 741 return false; 742 } 743 744 if (intersection) { 745 *intersection = ir; 746 } 747 return true; 748 } 749 750 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 751 SaveFlags flags) { 752 // do this before we create the layer. We don't call the public save() since 753 // that would invoke a possibly overridden virtual 754 int count = this->internalSave(flags); 755 756 fDeviceCMDirty = true; 757 758 SkIRect ir; 759 if (!this->clipRectBounds(bounds, flags, &ir)) { 760 return count; 761 } 762 763 // Kill the imagefilter if our device doesn't allow it 764 SkLazyPaint lazyP; 765 if (paint && paint->getImageFilter()) { 766 if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { 767 SkPaint* p = lazyP.set(*paint); 768 p->setImageFilter(NULL); 769 paint = p; 770 } 771 } 772 773 bool isOpaque; 774 SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 775 776 SkDevice* device; 777 if (paint && paint->getImageFilter()) { 778 device = this->createCompatibleDevice(config, ir.width(), ir.height(), 779 isOpaque); 780 } else { 781 device = this->createLayerDevice(config, ir.width(), ir.height(), 782 isOpaque); 783 } 784 if (NULL == device) { 785 SkDebugf("Unable to create device for layer."); 786 return count; 787 } 788 789 device->setOrigin(ir.fLeft, ir.fTop); 790 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); 791 device->unref(); 792 793 layer->fNext = fMCRec->fTopLayer; 794 fMCRec->fLayer = layer; 795 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 796 797 fLayerCount += 1; 798 return count; 799 } 800 801 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 802 SaveFlags flags) { 803 if (0xFF == alpha) { 804 return this->saveLayer(bounds, NULL, flags); 805 } else { 806 SkPaint tmpPaint; 807 tmpPaint.setAlpha(alpha); 808 return this->saveLayer(bounds, &tmpPaint, flags); 809 } 810 } 811 812 void SkCanvas::restore() { 813 // check for underflow 814 if (fMCStack.count() > 1) { 815 this->internalRestore(); 816 } 817 } 818 819 void SkCanvas::internalRestore() { 820 SkASSERT(fMCStack.count() != 0); 821 822 fDeviceCMDirty = true; 823 fLocalBoundsCompareTypeDirty = true; 824 fLocalBoundsCompareTypeDirtyBW = true; 825 826 fClipStack.restore(); 827 // reserve our layer (if any) 828 DeviceCM* layer = fMCRec->fLayer; // may be null 829 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 830 fMCRec->fLayer = NULL; 831 832 // now do the normal restore() 833 fMCRec->~MCRec(); // balanced in save() 834 fMCStack.pop_back(); 835 fMCRec = (MCRec*)fMCStack.back(); 836 837 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 838 since if we're being recorded, we don't want to record this (the 839 recorder will have already recorded the restore). 840 */ 841 if (NULL != layer) { 842 if (layer->fNext) { 843 const SkIPoint& origin = layer->fDevice->getOrigin(); 844 this->drawDevice(layer->fDevice, origin.x(), origin.y(), 845 layer->fPaint); 846 // reset this, since drawDevice will have set it to true 847 fDeviceCMDirty = true; 848 849 SkASSERT(fLayerCount > 0); 850 fLayerCount -= 1; 851 } 852 SkDELETE(layer); 853 } 854 855 SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 856 } 857 858 int SkCanvas::getSaveCount() const { 859 return fMCStack.count(); 860 } 861 862 void SkCanvas::restoreToCount(int count) { 863 // sanity check 864 if (count < 1) { 865 count = 1; 866 } 867 868 int n = this->getSaveCount() - count; 869 for (int i = 0; i < n; ++i) { 870 this->restore(); 871 } 872 } 873 874 bool SkCanvas::isDrawingToLayer() const { 875 return fLayerCount > 0; 876 } 877 878 ///////////////////////////////////////////////////////////////////////////// 879 880 // can't draw it if its empty, or its too big for a fixed-point width or height 881 static bool reject_bitmap(const SkBitmap& bitmap) { 882 return bitmap.width() <= 0 || bitmap.height() <= 0 883 #ifndef SK_ALLOW_OVER_32K_BITMAPS 884 || bitmap.width() > 32767 || bitmap.height() > 32767 885 #endif 886 ; 887 } 888 889 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 890 const SkMatrix& matrix, const SkPaint* paint) { 891 if (reject_bitmap(bitmap)) { 892 return; 893 } 894 895 SkLazyPaint lazy; 896 if (NULL == paint) { 897 paint = lazy.init(); 898 } 899 this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); 900 } 901 902 #include "SkImageFilter.h" 903 904 class DeviceImageFilterProxy : public SkImageFilter::Proxy { 905 public: 906 DeviceImageFilterProxy(SkDevice* device) : fDevice(device) {} 907 908 virtual SkDevice* createDevice(int w, int h) SK_OVERRIDE; 909 virtual bool filterImage(SkImageFilter*, const SkBitmap& src, 910 const SkMatrix& ctm, 911 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE; 912 913 private: 914 SkDevice* fDevice; 915 }; 916 917 SkDevice* DeviceImageFilterProxy::createDevice(int w, int h) { 918 return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config, 919 w, h, false); 920 } 921 922 bool DeviceImageFilterProxy::filterImage(SkImageFilter* filter, 923 const SkBitmap& src, 924 const SkMatrix& ctm, 925 SkBitmap* result, 926 SkIPoint* offset) { 927 return fDevice->filterImage(filter, src, ctm, result, offset); 928 } 929 930 void SkCanvas::drawDevice(SkDevice* srcDev, int x, int y, 931 const SkPaint* paint) { 932 SkPaint tmp; 933 if (NULL == paint) { 934 tmp.setDither(true); 935 paint = &tmp; 936 } 937 938 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 939 while (iter.next()) { 940 SkDevice* dstDev = iter.fDevice; 941 paint = &looper.paint(); 942 SkImageFilter* filter = paint->getImageFilter(); 943 SkIPoint pos = { x - iter.getX(), y - iter.getY() }; 944 if (filter) { 945 DeviceImageFilterProxy proxy(dstDev); 946 SkBitmap dst; 947 const SkBitmap& src = srcDev->accessBitmap(false); 948 if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) { 949 SkPaint tmp(*paint); 950 tmp.setImageFilter(NULL); 951 dstDev->drawSprite(iter, dst, pos.x(), pos.y(), tmp); 952 } 953 } else { 954 dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint); 955 } 956 } 957 LOOPER_END 958 } 959 960 ///////////////////////////////////////////////////////////////////////////// 961 962 bool SkCanvas::translate(SkScalar dx, SkScalar dy) { 963 fDeviceCMDirty = true; 964 fLocalBoundsCompareTypeDirty = true; 965 fLocalBoundsCompareTypeDirtyBW = true; 966 return fMCRec->fMatrix->preTranslate(dx, dy); 967 } 968 969 bool SkCanvas::scale(SkScalar sx, SkScalar sy) { 970 fDeviceCMDirty = true; 971 fLocalBoundsCompareTypeDirty = true; 972 fLocalBoundsCompareTypeDirtyBW = true; 973 return fMCRec->fMatrix->preScale(sx, sy); 974 } 975 976 bool SkCanvas::rotate(SkScalar degrees) { 977 fDeviceCMDirty = true; 978 fLocalBoundsCompareTypeDirty = true; 979 fLocalBoundsCompareTypeDirtyBW = true; 980 return fMCRec->fMatrix->preRotate(degrees); 981 } 982 983 bool SkCanvas::skew(SkScalar sx, SkScalar sy) { 984 fDeviceCMDirty = true; 985 fLocalBoundsCompareTypeDirty = true; 986 fLocalBoundsCompareTypeDirtyBW = true; 987 return fMCRec->fMatrix->preSkew(sx, sy); 988 } 989 990 bool SkCanvas::concat(const SkMatrix& matrix) { 991 fDeviceCMDirty = true; 992 fLocalBoundsCompareTypeDirty = true; 993 fLocalBoundsCompareTypeDirtyBW = true; 994 return fMCRec->fMatrix->preConcat(matrix); 995 } 996 997 void SkCanvas::setMatrix(const SkMatrix& matrix) { 998 fDeviceCMDirty = true; 999 fLocalBoundsCompareTypeDirty = true; 1000 fLocalBoundsCompareTypeDirtyBW = true; 1001 *fMCRec->fMatrix = matrix; 1002 } 1003 1004 // this is not virtual, so it must call a virtual method so that subclasses 1005 // will see its action 1006 void SkCanvas::resetMatrix() { 1007 SkMatrix matrix; 1008 1009 matrix.reset(); 1010 this->setMatrix(matrix); 1011 } 1012 1013 ////////////////////////////////////////////////////////////////////////////// 1014 1015 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 1016 AutoValidateClip avc(this); 1017 1018 fDeviceCMDirty = true; 1019 fLocalBoundsCompareTypeDirty = true; 1020 fLocalBoundsCompareTypeDirtyBW = true; 1021 1022 if (fMCRec->fMatrix->rectStaysRect()) { 1023 // for these simpler matrices, we can stay a rect ever after applying 1024 // the matrix. This means we don't have to a) make a path, and b) tell 1025 // the region code to scan-convert the path, only to discover that it 1026 // is really just a rect. 1027 SkRect r; 1028 1029 fMCRec->fMatrix->mapRect(&r, rect); 1030 fClipStack.clipDevRect(r, op, doAA); 1031 return fMCRec->fRasterClip->op(r, op, doAA); 1032 } else { 1033 // since we're rotate or some such thing, we convert the rect to a path 1034 // and clip against that, since it can handle any matrix. However, to 1035 // avoid recursion in the case where we are subclassed (e.g. Pictures) 1036 // we explicitly call "our" version of clipPath. 1037 SkPath path; 1038 1039 path.addRect(rect); 1040 return this->SkCanvas::clipPath(path, op, doAA); 1041 } 1042 } 1043 1044 static bool clipPathHelper(const SkCanvas* canvas, SkRasterClip* currClip, 1045 const SkPath& devPath, SkRegion::Op op, bool doAA) { 1046 // base is used to limit the size (and therefore memory allocation) of the 1047 // region that results from scan converting devPath. 1048 SkRegion base; 1049 1050 if (SkRegion::kIntersect_Op == op) { 1051 // since we are intersect, we can do better (tighter) with currRgn's 1052 // bounds, than just using the device. However, if currRgn is complex, 1053 // our region blitter may hork, so we do that case in two steps. 1054 if (currClip->isRect()) { 1055 return currClip->setPath(devPath, *currClip, doAA); 1056 } else { 1057 base.setRect(currClip->getBounds()); 1058 SkRasterClip clip; 1059 clip.setPath(devPath, base, doAA); 1060 return currClip->op(clip, op); 1061 } 1062 } else { 1063 const SkDevice* device = canvas->getDevice(); 1064 if (!device) { 1065 return currClip->setEmpty(); 1066 } 1067 1068 base.setRect(0, 0, device->width(), device->height()); 1069 1070 if (SkRegion::kReplace_Op == op) { 1071 return currClip->setPath(devPath, base, doAA); 1072 } else { 1073 SkRasterClip clip; 1074 clip.setPath(devPath, base, doAA); 1075 return currClip->op(clip, op); 1076 } 1077 } 1078 } 1079 1080 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { 1081 AutoValidateClip avc(this); 1082 1083 fDeviceCMDirty = true; 1084 fLocalBoundsCompareTypeDirty = true; 1085 fLocalBoundsCompareTypeDirtyBW = true; 1086 1087 SkPath devPath; 1088 path.transform(*fMCRec->fMatrix, &devPath); 1089 1090 // Check if the transfomation, or the original path itself 1091 // made us empty. Note this can also happen if we contained NaN 1092 // values. computing the bounds detects this, and will set our 1093 // bounds to empty if that is the case. (see SkRect::set(pts, count)) 1094 if (devPath.getBounds().isEmpty()) { 1095 // resetting the path will remove any NaN or other wanky values 1096 // that might upset our scan converter. 1097 devPath.reset(); 1098 } 1099 1100 // if we called path.swap() we could avoid a deep copy of this path 1101 fClipStack.clipDevPath(devPath, op, doAA); 1102 1103 return clipPathHelper(this, fMCRec->fRasterClip, devPath, op, doAA); 1104 } 1105 1106 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 1107 AutoValidateClip avc(this); 1108 1109 fDeviceCMDirty = true; 1110 fLocalBoundsCompareTypeDirty = true; 1111 fLocalBoundsCompareTypeDirtyBW = true; 1112 1113 // todo: signal fClipStack that we have a region, and therefore (I guess) 1114 // we have to ignore it, and use the region directly? 1115 fClipStack.clipDevRect(rgn.getBounds()); 1116 1117 return fMCRec->fRasterClip->op(rgn, op); 1118 } 1119 1120 #ifdef SK_DEBUG 1121 void SkCanvas::validateClip() const { 1122 // construct clipRgn from the clipstack 1123 const SkDevice* device = this->getDevice(); 1124 if (!device) { 1125 SkASSERT(this->getTotalClip().isEmpty()); 1126 return; 1127 } 1128 1129 SkIRect ir; 1130 ir.set(0, 0, device->width(), device->height()); 1131 SkRasterClip tmpClip(ir); 1132 1133 SkClipStack::B2FIter iter(fClipStack); 1134 const SkClipStack::B2FIter::Clip* clip; 1135 while ((clip = iter.next()) != NULL) { 1136 if (clip->fPath) { 1137 clipPathHelper(this, &tmpClip, *clip->fPath, clip->fOp, clip->fDoAA); 1138 } else if (clip->fRect) { 1139 clip->fRect->round(&ir); 1140 tmpClip.op(ir, clip->fOp); 1141 } else { 1142 tmpClip.setEmpty(); 1143 } 1144 } 1145 1146 #if 0 // enable this locally for testing 1147 // now compare against the current rgn 1148 const SkRegion& rgn = this->getTotalClip(); 1149 SkASSERT(rgn == tmpClip); 1150 #endif 1151 } 1152 #endif 1153 1154 /////////////////////////////////////////////////////////////////////////////// 1155 1156 void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const { 1157 SkRect r; 1158 SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType : 1159 fLocalBoundsCompareTypeBW; 1160 1161 if (!this->getClipBounds(&r, et)) { 1162 rCompare.setEmpty(); 1163 } else { 1164 rCompare.set(SkScalarToCompareType(r.fLeft), 1165 SkScalarToCompareType(r.fTop), 1166 SkScalarToCompareType(r.fRight), 1167 SkScalarToCompareType(r.fBottom)); 1168 } 1169 } 1170 1171 /* current impl ignores edgetype, and relies on 1172 getLocalClipBoundsCompareType(), which always returns a value assuming 1173 antialiasing (worst case) 1174 */ 1175 bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const { 1176 1177 if (!rect.isFinite()) 1178 return true; 1179 1180 if (fMCRec->fRasterClip->isEmpty()) { 1181 return true; 1182 } 1183 1184 if (fMCRec->fMatrix->hasPerspective()) { 1185 SkRect dst; 1186 fMCRec->fMatrix->mapRect(&dst, rect); 1187 SkIRect idst; 1188 dst.roundOut(&idst); 1189 return !SkIRect::Intersects(idst, fMCRec->fRasterClip->getBounds()); 1190 } else { 1191 const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et); 1192 1193 // for speed, do the most likely reject compares first 1194 SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 1195 SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 1196 if (userT >= clipR.fBottom || userB <= clipR.fTop) { 1197 return true; 1198 } 1199 SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 1200 SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 1201 if (userL >= clipR.fRight || userR <= clipR.fLeft) { 1202 return true; 1203 } 1204 return false; 1205 } 1206 } 1207 1208 bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const { 1209 return path.isEmpty() || this->quickReject(path.getBounds(), et); 1210 } 1211 1212 static inline int pinIntForScalar(int x) { 1213 #ifdef SK_SCALAR_IS_FIXED 1214 if (x < SK_MinS16) { 1215 x = SK_MinS16; 1216 } else if (x > SK_MaxS16) { 1217 x = SK_MaxS16; 1218 } 1219 #endif 1220 return x; 1221 } 1222 1223 bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const { 1224 SkIRect ibounds; 1225 if (!getClipDeviceBounds(&ibounds)) { 1226 return false; 1227 } 1228 1229 SkMatrix inverse; 1230 // if we can't invert the CTM, we can't return local clip bounds 1231 if (!fMCRec->fMatrix->invert(&inverse)) { 1232 if (bounds) { 1233 bounds->setEmpty(); 1234 } 1235 return false; 1236 } 1237 1238 if (NULL != bounds) { 1239 SkRect r; 1240 // adjust it outwards if we are antialiasing 1241 int inset = (kAA_EdgeType == et); 1242 1243 // SkRect::iset() will correctly assert if we pass a value out of range 1244 // (when SkScalar==fixed), so we pin to legal values. This does not 1245 // really returnt the correct answer, but its the best we can do given 1246 // that we've promised to return SkRect (even though we support devices 1247 // that can be larger than 32K in width or height). 1248 r.iset(pinIntForScalar(ibounds.fLeft - inset), 1249 pinIntForScalar(ibounds.fTop - inset), 1250 pinIntForScalar(ibounds.fRight + inset), 1251 pinIntForScalar(ibounds.fBottom + inset)); 1252 inverse.mapRect(bounds, r); 1253 } 1254 return true; 1255 } 1256 1257 bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const { 1258 const SkRasterClip& clip = *fMCRec->fRasterClip; 1259 if (clip.isEmpty()) { 1260 if (bounds) { 1261 bounds->setEmpty(); 1262 } 1263 return false; 1264 } 1265 1266 if (NULL != bounds) { 1267 *bounds = clip.getBounds(); 1268 } 1269 return true; 1270 } 1271 1272 const SkMatrix& SkCanvas::getTotalMatrix() const { 1273 return *fMCRec->fMatrix; 1274 } 1275 1276 SkCanvas::ClipType SkCanvas::getClipType() const { 1277 if (fMCRec->fRasterClip->isEmpty()) return kEmpty_ClipType; 1278 if (fMCRec->fRasterClip->isRect()) return kRect_ClipType; 1279 return kComplex_ClipType; 1280 } 1281 1282 const SkRegion& SkCanvas::getTotalClip() const { 1283 return fMCRec->fRasterClip->forceGetBW(); 1284 } 1285 1286 const SkClipStack& SkCanvas::getTotalClipStack() const { 1287 return fClipStack; 1288 } 1289 1290 void SkCanvas::setExternalMatrix(const SkMatrix* matrix) { 1291 if (NULL == matrix || matrix->isIdentity()) { 1292 if (fUseExternalMatrix) { 1293 fDeviceCMDirty = true; 1294 } 1295 fUseExternalMatrix = false; 1296 } else { 1297 fUseExternalMatrix = true; 1298 fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix) 1299 1300 fExternalMatrix = *matrix; 1301 matrix->invert(&fExternalInverse); 1302 } 1303 } 1304 1305 SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, 1306 int width, int height, 1307 bool isOpaque) { 1308 SkDevice* device = this->getTopDevice(); 1309 if (device) { 1310 return device->createCompatibleDeviceForSaveLayer(config, width, height, 1311 isOpaque); 1312 } else { 1313 return NULL; 1314 } 1315 } 1316 1317 SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config, 1318 int width, int height, 1319 bool isOpaque) { 1320 SkDevice* device = this->getDevice(); 1321 if (device) { 1322 return device->createCompatibleDevice(config, width, height, isOpaque); 1323 } else { 1324 return NULL; 1325 } 1326 } 1327 1328 1329 ////////////////////////////////////////////////////////////////////////////// 1330 // These are the virtual drawing methods 1331 ////////////////////////////////////////////////////////////////////////////// 1332 1333 void SkCanvas::clear(SkColor color) { 1334 SkDrawIter iter(this); 1335 1336 while (iter.next()) { 1337 iter.fDevice->clear(color); 1338 } 1339 } 1340 1341 void SkCanvas::drawPaint(const SkPaint& paint) { 1342 this->internalDrawPaint(paint); 1343 } 1344 1345 void SkCanvas::internalDrawPaint(const SkPaint& paint) { 1346 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type) 1347 1348 while (iter.next()) { 1349 iter.fDevice->drawPaint(iter, looper.paint()); 1350 } 1351 1352 LOOPER_END 1353 } 1354 1355 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 1356 const SkPaint& paint) { 1357 if ((long)count <= 0) { 1358 return; 1359 } 1360 1361 SkASSERT(pts != NULL); 1362 1363 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type) 1364 1365 while (iter.next()) { 1366 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1367 } 1368 1369 LOOPER_END 1370 } 1371 1372 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1373 if (paint.canComputeFastBounds()) { 1374 SkRect storage; 1375 if (this->quickReject(paint.computeFastBounds(r, &storage), 1376 paint2EdgeType(&paint))) { 1377 return; 1378 } 1379 } 1380 1381 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type) 1382 1383 while (iter.next()) { 1384 iter.fDevice->drawRect(iter, r, looper.paint()); 1385 } 1386 1387 LOOPER_END 1388 } 1389 1390 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1391 if (!path.isInverseFillType() && paint.canComputeFastBounds()) { 1392 SkRect storage; 1393 const SkRect& bounds = path.getBounds(); 1394 if (this->quickReject(paint.computeFastBounds(bounds, &storage), 1395 paint2EdgeType(&paint))) { 1396 return; 1397 } 1398 } 1399 if (path.isEmpty()) { 1400 if (path.isInverseFillType()) { 1401 this->internalDrawPaint(paint); 1402 } 1403 return; 1404 } 1405 1406 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 1407 1408 while (iter.next()) { 1409 iter.fDevice->drawPath(iter, path, looper.paint()); 1410 } 1411 1412 LOOPER_END 1413 } 1414 1415 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 1416 const SkPaint* paint) { 1417 SkDEBUGCODE(bitmap.validate();) 1418 1419 if (NULL == paint || paint->canComputeFastBounds()) { 1420 SkRect bounds = { 1421 x, y, 1422 x + SkIntToScalar(bitmap.width()), 1423 y + SkIntToScalar(bitmap.height()) 1424 }; 1425 if (paint) { 1426 (void)paint->computeFastBounds(bounds, &bounds); 1427 } 1428 if (this->quickReject(bounds, paint2EdgeType(paint))) { 1429 return; 1430 } 1431 } 1432 1433 SkMatrix matrix; 1434 matrix.setTranslate(x, y); 1435 this->internalDrawBitmap(bitmap, NULL, matrix, paint); 1436 } 1437 1438 // this one is non-virtual, so it can be called safely by other canvas apis 1439 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 1440 const SkRect& dst, const SkPaint* paint) { 1441 if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 1442 return; 1443 } 1444 1445 // do this now, to avoid the cost of calling extract for RLE bitmaps 1446 if (NULL == paint || paint->canComputeFastBounds()) { 1447 SkRect storage; 1448 const SkRect* bounds = &dst; 1449 if (paint) { 1450 bounds = &paint->computeFastBounds(dst, &storage); 1451 } 1452 if (this->quickReject(*bounds, paint2EdgeType(paint))) { 1453 return; 1454 } 1455 } 1456 1457 const SkBitmap* bitmapPtr = &bitmap; 1458 1459 SkMatrix matrix; 1460 SkRect tmpSrc; 1461 if (src) { 1462 tmpSrc.set(*src); 1463 // if the extract process clipped off the top or left of the 1464 // original, we adjust for that here to get the position right. 1465 if (tmpSrc.fLeft > 0) { 1466 tmpSrc.fRight -= tmpSrc.fLeft; 1467 tmpSrc.fLeft = 0; 1468 } 1469 if (tmpSrc.fTop > 0) { 1470 tmpSrc.fBottom -= tmpSrc.fTop; 1471 tmpSrc.fTop = 0; 1472 } 1473 } else { 1474 tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), 1475 SkIntToScalar(bitmap.height())); 1476 } 1477 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 1478 1479 // ensure that src is "valid" before we pass it to our internal routines 1480 // and to SkDevice. i.e. sure it is contained inside the original bitmap. 1481 SkIRect tmpISrc; 1482 if (src) { 1483 tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); 1484 if (!tmpISrc.intersect(*src)) { 1485 return; 1486 } 1487 src = &tmpISrc; 1488 } 1489 this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); 1490 } 1491 1492 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 1493 const SkRect& dst, const SkPaint* paint) { 1494 SkDEBUGCODE(bitmap.validate();) 1495 this->internalDrawBitmapRect(bitmap, src, dst, paint); 1496 } 1497 1498 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 1499 const SkPaint* paint) { 1500 SkDEBUGCODE(bitmap.validate();) 1501 this->internalDrawBitmap(bitmap, NULL, matrix, paint); 1502 } 1503 1504 void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 1505 const SkMatrix& matrix, const SkPaint& paint) { 1506 SkDEBUGCODE(bitmap.validate();) 1507 1508 LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) 1509 1510 while (iter.next()) { 1511 iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); 1512 } 1513 1514 LOOPER_END 1515 } 1516 1517 void SkCanvas::internalDrawBitmapNine(const SkBitmap& bitmap, 1518 const SkIRect& center, const SkRect& dst, 1519 const SkPaint* paint) { 1520 if (NULL == paint || paint->canComputeFastBounds()) { 1521 SkRect storage; 1522 const SkRect* bounds = &dst; 1523 if (paint) { 1524 bounds = &paint->computeFastBounds(dst, &storage); 1525 } 1526 if (this->quickReject(*bounds, paint2EdgeType(paint))) { 1527 return; 1528 } 1529 } 1530 1531 const int32_t w = bitmap.width(); 1532 const int32_t h = bitmap.height(); 1533 1534 SkIRect c = center; 1535 // pin center to the bounds of the bitmap 1536 c.fLeft = SkMax32(0, center.fLeft); 1537 c.fTop = SkMax32(0, center.fTop); 1538 c.fRight = SkPin32(center.fRight, c.fLeft, w); 1539 c.fBottom = SkPin32(center.fBottom, c.fTop, h); 1540 1541 const int32_t srcX[4] = { 0, c.fLeft, c.fRight, w }; 1542 const int32_t srcY[4] = { 0, c.fTop, c.fBottom, h }; 1543 SkScalar dstX[4] = { 1544 dst.fLeft, dst.fLeft + SkIntToScalar(c.fLeft), 1545 dst.fRight - SkIntToScalar(w - c.fRight), dst.fRight 1546 }; 1547 SkScalar dstY[4] = { 1548 dst.fTop, dst.fTop + SkIntToScalar(c.fTop), 1549 dst.fBottom - SkIntToScalar(h - c.fBottom), dst.fBottom 1550 }; 1551 1552 if (dstX[1] > dstX[2]) { 1553 dstX[1] = dstX[0] + (dstX[3] - dstX[0]) * c.fLeft / (w - c.width()); 1554 dstX[2] = dstX[1]; 1555 } 1556 1557 if (dstY[1] > dstY[2]) { 1558 dstY[1] = dstY[0] + (dstY[3] - dstY[0]) * c.fTop / (h - c.height()); 1559 dstY[2] = dstY[1]; 1560 } 1561 1562 SkIRect s; 1563 SkRect d; 1564 for (int y = 0; y < 3; y++) { 1565 s.fTop = srcY[y]; 1566 s.fBottom = srcY[y+1]; 1567 d.fTop = dstY[y]; 1568 d.fBottom = dstY[y+1]; 1569 for (int x = 0; x < 3; x++) { 1570 s.fLeft = srcX[x]; 1571 s.fRight = srcX[x+1]; 1572 d.fLeft = dstX[x]; 1573 d.fRight = dstX[x+1]; 1574 this->internalDrawBitmapRect(bitmap, &s, d, paint); 1575 } 1576 } 1577 } 1578 1579 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, 1580 const SkRect& dst, const SkPaint* paint) { 1581 SkDEBUGCODE(bitmap.validate();) 1582 1583 // Need a device entry-point, so gpu can use a mesh 1584 this->internalDrawBitmapNine(bitmap, center, dst, paint); 1585 } 1586 1587 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 1588 const SkPaint* paint) { 1589 SkDEBUGCODE(bitmap.validate();) 1590 1591 if (reject_bitmap(bitmap)) { 1592 return; 1593 } 1594 1595 SkPaint tmp; 1596 if (NULL == paint) { 1597 paint = &tmp; 1598 } 1599 1600 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 1601 1602 while (iter.next()) { 1603 iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), 1604 looper.paint()); 1605 } 1606 LOOPER_END 1607 } 1608 1609 class SkDeviceFilteredPaint { 1610 public: 1611 SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) { 1612 SkDevice::TextFlags flags; 1613 if (device->filterTextFlags(paint, &flags)) { 1614 SkPaint* newPaint = fLazy.set(paint); 1615 newPaint->setFlags(flags.fFlags); 1616 newPaint->setHinting(flags.fHinting); 1617 fPaint = newPaint; 1618 } else { 1619 fPaint = &paint; 1620 } 1621 } 1622 1623 const SkPaint& paint() const { return *fPaint; } 1624 1625 private: 1626 const SkPaint* fPaint; 1627 SkLazyPaint fLazy; 1628 }; 1629 1630 void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint, 1631 const SkRect& r, SkScalar textSize) { 1632 if (paint.getStyle() == SkPaint::kFill_Style) { 1633 draw.fDevice->drawRect(draw, r, paint); 1634 } else { 1635 SkPaint p(paint); 1636 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 1637 draw.fDevice->drawRect(draw, r, p); 1638 } 1639 } 1640 1641 void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, 1642 const char text[], size_t byteLength, 1643 SkScalar x, SkScalar y) { 1644 SkASSERT(byteLength == 0 || text != NULL); 1645 1646 // nothing to draw 1647 if (text == NULL || byteLength == 0 || 1648 draw.fClip->isEmpty() || 1649 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 1650 return; 1651 } 1652 1653 SkScalar width = 0; 1654 SkPoint start; 1655 1656 start.set(0, 0); // to avoid warning 1657 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 1658 SkPaint::kStrikeThruText_Flag)) { 1659 width = paint.measureText(text, byteLength); 1660 1661 SkScalar offsetX = 0; 1662 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1663 offsetX = SkScalarHalf(width); 1664 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 1665 offsetX = width; 1666 } 1667 start.set(x - offsetX, y); 1668 } 1669 1670 if (0 == width) { 1671 return; 1672 } 1673 1674 uint32_t flags = paint.getFlags(); 1675 1676 if (flags & (SkPaint::kUnderlineText_Flag | 1677 SkPaint::kStrikeThruText_Flag)) { 1678 SkScalar textSize = paint.getTextSize(); 1679 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 1680 SkRect r; 1681 1682 r.fLeft = start.fX; 1683 r.fRight = start.fX + width; 1684 1685 if (flags & SkPaint::kUnderlineText_Flag) { 1686 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 1687 start.fY); 1688 r.fTop = offset; 1689 r.fBottom = offset + height; 1690 DrawRect(draw, paint, r, textSize); 1691 } 1692 if (flags & SkPaint::kStrikeThruText_Flag) { 1693 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 1694 start.fY); 1695 r.fTop = offset; 1696 r.fBottom = offset + height; 1697 DrawRect(draw, paint, r, textSize); 1698 } 1699 } 1700 } 1701 1702 void SkCanvas::drawText(const void* text, size_t byteLength, 1703 SkScalar x, SkScalar y, const SkPaint& paint) { 1704 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1705 1706 while (iter.next()) { 1707 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1708 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 1709 DrawTextDecorations(iter, dfp.paint(), 1710 static_cast<const char*>(text), byteLength, x, y); 1711 } 1712 1713 LOOPER_END 1714 } 1715 1716 void SkCanvas::drawPosText(const void* text, size_t byteLength, 1717 const SkPoint pos[], const SkPaint& paint) { 1718 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1719 1720 while (iter.next()) { 1721 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1722 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 1723 dfp.paint()); 1724 } 1725 1726 LOOPER_END 1727 } 1728 1729 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, 1730 const SkScalar xpos[], SkScalar constY, 1731 const SkPaint& paint) { 1732 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1733 1734 while (iter.next()) { 1735 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1736 iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 1737 dfp.paint()); 1738 } 1739 1740 LOOPER_END 1741 } 1742 1743 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 1744 const SkPath& path, const SkMatrix* matrix, 1745 const SkPaint& paint) { 1746 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1747 1748 while (iter.next()) { 1749 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 1750 matrix, looper.paint()); 1751 } 1752 1753 LOOPER_END 1754 } 1755 1756 #ifdef SK_BUILD_FOR_ANDROID 1757 void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, 1758 const SkPoint pos[], const SkPaint& paint, 1759 const SkPath& path, const SkMatrix* matrix) { 1760 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1761 1762 while (iter.next()) { 1763 iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, 1764 looper.paint(), path, matrix); 1765 } 1766 1767 LOOPER_END 1768 } 1769 #endif 1770 1771 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 1772 const SkPoint verts[], const SkPoint texs[], 1773 const SkColor colors[], SkXfermode* xmode, 1774 const uint16_t indices[], int indexCount, 1775 const SkPaint& paint) { 1776 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 1777 1778 while (iter.next()) { 1779 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 1780 colors, xmode, indices, indexCount, 1781 looper.paint()); 1782 } 1783 1784 LOOPER_END 1785 } 1786 1787 void SkCanvas::drawData(const void* data, size_t length) { 1788 // do nothing. Subclasses may do something with the data 1789 } 1790 1791 ////////////////////////////////////////////////////////////////////////////// 1792 // These methods are NOT virtual, and therefore must call back into virtual 1793 // methods, rather than actually drawing themselves. 1794 ////////////////////////////////////////////////////////////////////////////// 1795 1796 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 1797 SkXfermode::Mode mode) { 1798 SkPaint paint; 1799 1800 paint.setARGB(a, r, g, b); 1801 if (SkXfermode::kSrcOver_Mode != mode) { 1802 paint.setXfermodeMode(mode); 1803 } 1804 this->drawPaint(paint); 1805 } 1806 1807 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 1808 SkPaint paint; 1809 1810 paint.setColor(c); 1811 if (SkXfermode::kSrcOver_Mode != mode) { 1812 paint.setXfermodeMode(mode); 1813 } 1814 this->drawPaint(paint); 1815 } 1816 1817 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 1818 SkPoint pt; 1819 1820 pt.set(x, y); 1821 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 1822 } 1823 1824 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 1825 SkPoint pt; 1826 SkPaint paint; 1827 1828 pt.set(x, y); 1829 paint.setColor(color); 1830 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 1831 } 1832 1833 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 1834 const SkPaint& paint) { 1835 SkPoint pts[2]; 1836 1837 pts[0].set(x0, y0); 1838 pts[1].set(x1, y1); 1839 this->drawPoints(kLines_PointMode, 2, pts, paint); 1840 } 1841 1842 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 1843 SkScalar right, SkScalar bottom, 1844 const SkPaint& paint) { 1845 SkRect r; 1846 1847 r.set(left, top, right, bottom); 1848 this->drawRect(r, paint); 1849 } 1850 1851 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 1852 const SkPaint& paint) { 1853 if (radius < 0) { 1854 radius = 0; 1855 } 1856 1857 SkRect r; 1858 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 1859 1860 if (paint.canComputeFastBounds()) { 1861 SkRect storage; 1862 if (this->quickReject(paint.computeFastBounds(r, &storage), 1863 paint2EdgeType(&paint))) { 1864 return; 1865 } 1866 } 1867 1868 SkPath path; 1869 path.addOval(r); 1870 this->drawPath(path, paint); 1871 } 1872 1873 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 1874 const SkPaint& paint) { 1875 if (rx > 0 && ry > 0) { 1876 if (paint.canComputeFastBounds()) { 1877 SkRect storage; 1878 if (this->quickReject(paint.computeFastBounds(r, &storage), 1879 paint2EdgeType(&paint))) { 1880 return; 1881 } 1882 } 1883 1884 SkPath path; 1885 path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 1886 this->drawPath(path, paint); 1887 } else { 1888 this->drawRect(r, paint); 1889 } 1890 } 1891 1892 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 1893 if (paint.canComputeFastBounds()) { 1894 SkRect storage; 1895 if (this->quickReject(paint.computeFastBounds(oval, &storage), 1896 paint2EdgeType(&paint))) { 1897 return; 1898 } 1899 } 1900 1901 SkPath path; 1902 path.addOval(oval); 1903 this->drawPath(path, paint); 1904 } 1905 1906 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 1907 SkScalar sweepAngle, bool useCenter, 1908 const SkPaint& paint) { 1909 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 1910 this->drawOval(oval, paint); 1911 } else { 1912 SkPath path; 1913 if (useCenter) { 1914 path.moveTo(oval.centerX(), oval.centerY()); 1915 } 1916 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 1917 if (useCenter) { 1918 path.close(); 1919 } 1920 this->drawPath(path, paint); 1921 } 1922 } 1923 1924 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 1925 const SkPath& path, SkScalar hOffset, 1926 SkScalar vOffset, const SkPaint& paint) { 1927 SkMatrix matrix; 1928 1929 matrix.setTranslate(hOffset, vOffset); 1930 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 1931 } 1932 1933 /////////////////////////////////////////////////////////////////////////////// 1934 1935 void SkCanvas::drawPicture(SkPicture& picture) { 1936 int saveCount = save(); 1937 picture.draw(this); 1938 restoreToCount(saveCount); 1939 } 1940 1941 /////////////////////////////////////////////////////////////////////////////// 1942 /////////////////////////////////////////////////////////////////////////////// 1943 1944 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 1945 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 1946 1947 SkASSERT(canvas); 1948 1949 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 1950 fDone = !fImpl->next(); 1951 } 1952 1953 SkCanvas::LayerIter::~LayerIter() { 1954 fImpl->~SkDrawIter(); 1955 } 1956 1957 void SkCanvas::LayerIter::next() { 1958 fDone = !fImpl->next(); 1959 } 1960 1961 SkDevice* SkCanvas::LayerIter::device() const { 1962 return fImpl->getDevice(); 1963 } 1964 1965 const SkMatrix& SkCanvas::LayerIter::matrix() const { 1966 return fImpl->getMatrix(); 1967 } 1968 1969 const SkPaint& SkCanvas::LayerIter::paint() const { 1970 const SkPaint* paint = fImpl->getPaint(); 1971 if (NULL == paint) { 1972 paint = &fDefaultPaint; 1973 } 1974 return *paint; 1975 } 1976 1977 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 1978 int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 1979 int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 1980