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