1 /* 2 * Copyright (C) 2006-2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "SkCanvas.h" 18 #include "SkBounder.h" 19 #include "SkDevice.h" 20 #include "SkDraw.h" 21 #include "SkDrawFilter.h" 22 #include "SkDrawLooper.h" 23 #include "SkPicture.h" 24 #include "SkScalarCompare.h" 25 #include "SkShape.h" 26 #include "SkTemplates.h" 27 #include "SkTLazy.h" 28 #include "SkUtils.h" 29 #include <new> 30 31 //#define SK_TRACE_SAVERESTORE 32 33 #ifdef SK_TRACE_SAVERESTORE 34 static int gLayerCounter; 35 static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); } 36 static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); } 37 38 static int gRecCounter; 39 static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); } 40 static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); } 41 42 static int gCanvasCounter; 43 static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); } 44 static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); } 45 #else 46 #define inc_layer() 47 #define dec_layer() 48 #define inc_rec() 49 #define dec_rec() 50 #define inc_canvas() 51 #define dec_canvas() 52 #endif 53 54 typedef SkTLazy<SkPaint> SkLazyPaint; 55 56 /////////////////////////////////////////////////////////////////////////////// 57 // Helpers for computing fast bounds for quickReject tests 58 59 static SkCanvas::EdgeType paint2EdgeType(const SkPaint* paint) { 60 return paint != NULL && paint->isAntiAlias() ? 61 SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType; 62 } 63 64 /////////////////////////////////////////////////////////////////////////////// 65 66 /* This is the record we keep for each SkDevice that the user installs. 67 The clip/matrix/proc are fields that reflect the top of the save/restore 68 stack. Whenever the canvas changes, it marks a dirty flag, and then before 69 these are used (assuming we're not on a layer) we rebuild these cache 70 values: they reflect the top of the save stack, but translated and clipped 71 by the device's XY offset and bitmap-bounds. 72 */ 73 struct DeviceCM { 74 DeviceCM* fNext; 75 SkDevice* fDevice; 76 SkRegion fClip; 77 const SkMatrix* fMatrix; 78 SkPaint* fPaint; // may be null (in the future) 79 // optional, related to canvas' external matrix 80 const SkMatrix* fMVMatrix; 81 const SkMatrix* fExtMatrix; 82 83 DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint) 84 : fNext(NULL) { 85 if (NULL != device) { 86 device->ref(); 87 device->lockPixels(); 88 } 89 fDevice = device; 90 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; 91 } 92 93 ~DeviceCM() { 94 if (NULL != fDevice) { 95 fDevice->unlockPixels(); 96 fDevice->unref(); 97 } 98 SkDELETE(fPaint); 99 } 100 101 void updateMC(const SkMatrix& totalMatrix, const SkRegion& totalClip, 102 const SkClipStack& clipStack, SkRegion* updateClip) { 103 int x = fDevice->getOrigin().x(); 104 int y = fDevice->getOrigin().y(); 105 int width = fDevice->width(); 106 int height = fDevice->height(); 107 108 if ((x | y) == 0) { 109 fMatrix = &totalMatrix; 110 fClip = totalClip; 111 } else { 112 fMatrixStorage = totalMatrix; 113 fMatrixStorage.postTranslate(SkIntToScalar(-x), 114 SkIntToScalar(-y)); 115 fMatrix = &fMatrixStorage; 116 117 totalClip.translate(-x, -y, &fClip); 118 } 119 120 fClip.op(0, 0, width, height, SkRegion::kIntersect_Op); 121 122 // intersect clip, but don't translate it (yet) 123 124 if (updateClip) { 125 updateClip->op(x, y, x + width, y + height, 126 SkRegion::kDifference_Op); 127 } 128 129 fDevice->setMatrixClip(*fMatrix, fClip, clipStack); 130 131 #ifdef SK_DEBUG 132 if (!fClip.isEmpty()) { 133 SkIRect deviceR; 134 deviceR.set(0, 0, width, height); 135 SkASSERT(deviceR.contains(fClip.getBounds())); 136 } 137 #endif 138 // default is to assume no external matrix 139 fMVMatrix = NULL; 140 fExtMatrix = NULL; 141 } 142 143 // can only be called after calling updateMC() 144 void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) { 145 fMVMatrixStorage.setConcat(extI, *fMatrix); 146 fMVMatrix = &fMVMatrixStorage; 147 fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas) 148 } 149 150 private: 151 SkMatrix fMatrixStorage, fMVMatrixStorage; 152 }; 153 154 /* This is the record we keep for each save/restore level in the stack. 155 Since a level optionally copies the matrix and/or stack, we have pointers 156 for these fields. If the value is copied for this level, the copy is 157 stored in the ...Storage field, and the pointer points to that. If the 158 value is not copied for this level, we ignore ...Storage, and just point 159 at the corresponding value in the previous level in the stack. 160 */ 161 class SkCanvas::MCRec { 162 public: 163 MCRec* fNext; 164 SkMatrix* fMatrix; // points to either fMatrixStorage or prev MCRec 165 SkRegion* fRegion; // points to either fRegionStorage or prev MCRec 166 SkDrawFilter* fFilter; // the current filter (or null) 167 168 DeviceCM* fLayer; 169 /* If there are any layers in the stack, this points to the top-most 170 one that is at or below this level in the stack (so we know what 171 bitmap/device to draw into from this level. This value is NOT 172 reference counted, since the real owner is either our fLayer field, 173 or a previous one in a lower level.) 174 */ 175 DeviceCM* fTopLayer; 176 177 MCRec(const MCRec* prev, int flags) { 178 if (NULL != prev) { 179 if (flags & SkCanvas::kMatrix_SaveFlag) { 180 fMatrixStorage = *prev->fMatrix; 181 fMatrix = &fMatrixStorage; 182 } else { 183 fMatrix = prev->fMatrix; 184 } 185 186 if (flags & SkCanvas::kClip_SaveFlag) { 187 fRegionStorage = *prev->fRegion; 188 fRegion = &fRegionStorage; 189 } else { 190 fRegion = prev->fRegion; 191 } 192 193 fFilter = prev->fFilter; 194 SkSafeRef(fFilter); 195 196 fTopLayer = prev->fTopLayer; 197 } else { // no prev 198 fMatrixStorage.reset(); 199 200 fMatrix = &fMatrixStorage; 201 fRegion = &fRegionStorage; 202 fFilter = NULL; 203 fTopLayer = NULL; 204 } 205 fLayer = NULL; 206 207 // don't bother initializing fNext 208 inc_rec(); 209 } 210 ~MCRec() { 211 SkSafeUnref(fFilter); 212 SkDELETE(fLayer); 213 dec_rec(); 214 } 215 216 private: 217 SkMatrix fMatrixStorage; 218 SkRegion fRegionStorage; 219 }; 220 221 class SkDrawIter : public SkDraw { 222 public: 223 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { 224 fCanvas = canvas; 225 canvas->updateDeviceCMCache(); 226 227 fClipStack = &canvas->getTotalClipStack(); 228 fBounder = canvas->getBounder(); 229 fCurrLayer = canvas->fMCRec->fTopLayer; 230 fSkipEmptyClips = skipEmptyClips; 231 } 232 233 bool next() { 234 // skip over recs with empty clips 235 if (fSkipEmptyClips) { 236 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { 237 fCurrLayer = fCurrLayer->fNext; 238 } 239 } 240 241 if (NULL != fCurrLayer) { 242 const DeviceCM* rec = fCurrLayer; 243 244 fMatrix = rec->fMatrix; 245 fClip = &rec->fClip; 246 fDevice = rec->fDevice; 247 fBitmap = &fDevice->accessBitmap(true); 248 fPaint = rec->fPaint; 249 fMVMatrix = rec->fMVMatrix; 250 fExtMatrix = rec->fExtMatrix; 251 SkDEBUGCODE(this->validate();) 252 253 fCurrLayer = rec->fNext; 254 if (fBounder) { 255 fBounder->setClip(fClip); 256 } 257 // fCurrLayer may be NULL now 258 259 fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip, *fClipStack); 260 return true; 261 } 262 return false; 263 } 264 265 SkDevice* getDevice() const { return fDevice; } 266 int getX() const { return fDevice->getOrigin().x(); } 267 int getY() const { return fDevice->getOrigin().y(); } 268 const SkMatrix& getMatrix() const { return *fMatrix; } 269 const SkRegion& getClip() const { return *fClip; } 270 const SkPaint* getPaint() const { return fPaint; } 271 272 private: 273 SkCanvas* fCanvas; 274 const DeviceCM* fCurrLayer; 275 const SkPaint* fPaint; // May be null. 276 SkBool8 fSkipEmptyClips; 277 278 typedef SkDraw INHERITED; 279 }; 280 281 ///////////////////////////////////////////////////////////////////////////// 282 283 class AutoDrawLooper { 284 public: 285 AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint) : fOrigPaint(paint) { 286 fCanvas = canvas; 287 fLooper = paint.getLooper(); 288 fFilter = canvas->getDrawFilter(); 289 fPaint = NULL; 290 fSaveCount = canvas->getSaveCount(); 291 fDone = false; 292 293 if (fLooper) { 294 fLooper->init(canvas); 295 } 296 } 297 298 ~AutoDrawLooper() { 299 SkASSERT(fCanvas->getSaveCount() == fSaveCount); 300 } 301 302 const SkPaint& paint() const { 303 SkASSERT(fPaint); 304 return *fPaint; 305 } 306 307 bool next(SkDrawFilter::Type drawType); 308 309 private: 310 SkLazyPaint fLazyPaint; 311 SkCanvas* fCanvas; 312 const SkPaint& fOrigPaint; 313 SkDrawLooper* fLooper; 314 SkDrawFilter* fFilter; 315 const SkPaint* fPaint; 316 int fSaveCount; 317 bool fDone; 318 }; 319 320 bool AutoDrawLooper::next(SkDrawFilter::Type drawType) { 321 if (fDone) { 322 fPaint = NULL; 323 return false; 324 } 325 if (!fLooper && !fFilter) { 326 fDone = true; 327 fPaint = &fOrigPaint; 328 return true; 329 } 330 331 SkPaint* paint = fLazyPaint.set(fOrigPaint); 332 if (fLooper && !fLooper->next(fCanvas, paint)) { 333 fDone = true; 334 fPaint = NULL; 335 return false; 336 } 337 if (fFilter) { 338 fFilter->filter(paint, drawType); 339 if (NULL == fLooper) { 340 // no looper means we only draw once 341 fDone = true; 342 } 343 } 344 fPaint = paint; 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 fLocalBoundsCompareTypeDirty = true; 403 fLocalBoundsCompareTypeDirtyBW = true; 404 fLastDeviceToGainFocus = NULL; 405 fDeviceCMDirty = false; 406 407 fMCRec = (MCRec*)fMCStack.push_back(); 408 new (fMCRec) MCRec(NULL, 0); 409 410 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL)); 411 fMCRec->fTopLayer = fMCRec->fLayer; 412 fMCRec->fNext = NULL; 413 414 fUseExternalMatrix = false; 415 416 return this->setDevice(device); 417 } 418 419 SkCanvas::SkCanvas(SkDeviceFactory* factory) 420 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 421 inc_canvas(); 422 423 if (factory) { 424 factory->ref(); 425 } else { 426 factory = SkNEW(SkRasterDeviceFactory); 427 } 428 fDeviceFactory = factory; 429 430 this->init(NULL); 431 } 432 433 SkCanvas::SkCanvas(SkDevice* device) 434 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 435 inc_canvas(); 436 437 fDeviceFactory = device->getDeviceFactory(); 438 SkASSERT(fDeviceFactory); 439 fDeviceFactory->ref(); 440 441 this->init(device); 442 } 443 444 SkCanvas::SkCanvas(const SkBitmap& bitmap) 445 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { 446 inc_canvas(); 447 448 SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false)); 449 fDeviceFactory = device->getDeviceFactory(); 450 SkASSERT(fDeviceFactory); 451 fDeviceFactory->ref(); 452 453 this->init(device)->unref(); 454 } 455 456 SkCanvas::~SkCanvas() { 457 // free up the contents of our deque 458 this->restoreToCount(1); // restore everything but the last 459 this->internalRestore(); // restore the last, since we're going away 460 461 SkSafeUnref(fBounder); 462 SkSafeUnref(fDeviceFactory); 463 464 dec_canvas(); 465 } 466 467 SkBounder* SkCanvas::setBounder(SkBounder* bounder) { 468 SkRefCnt_SafeAssign(fBounder, bounder); 469 return bounder; 470 } 471 472 SkDrawFilter* SkCanvas::getDrawFilter() const { 473 return fMCRec->fFilter; 474 } 475 476 SkDrawFilter* SkCanvas::setDrawFilter(SkDrawFilter* filter) { 477 SkRefCnt_SafeAssign(fMCRec->fFilter, filter); 478 return filter; 479 } 480 481 /////////////////////////////////////////////////////////////////////////////// 482 483 SkDevice* SkCanvas::getDevice() const { 484 // return root device 485 SkDeque::F2BIter iter(fMCStack); 486 MCRec* rec = (MCRec*)iter.next(); 487 SkASSERT(rec && rec->fLayer); 488 return rec->fLayer->fDevice; 489 } 490 491 SkDevice* SkCanvas::getTopDevice() const { 492 return fMCRec->fTopLayer->fDevice; 493 } 494 495 SkDevice* SkCanvas::setDevice(SkDevice* device) { 496 // return root device 497 SkDeque::F2BIter iter(fMCStack); 498 MCRec* rec = (MCRec*)iter.next(); 499 SkASSERT(rec && rec->fLayer); 500 SkDevice* rootDevice = rec->fLayer->fDevice; 501 502 if (rootDevice == device) { 503 return device; 504 } 505 506 /* Notify the devices that they are going in/out of scope, so they can do 507 things like lock/unlock their pixels, etc. 508 */ 509 if (device) { 510 device->lockPixels(); 511 } 512 if (rootDevice) { 513 rootDevice->unlockPixels(); 514 } 515 516 SkRefCnt_SafeAssign(rec->fLayer->fDevice, device); 517 rootDevice = device; 518 519 fDeviceCMDirty = true; 520 521 /* Now we update our initial region to have the bounds of the new device, 522 and then intersect all of the clips in our stack with these bounds, 523 to ensure that we can't draw outside of the device's bounds (and trash 524 memory). 525 526 NOTE: this is only a partial-fix, since if the new device is larger than 527 the previous one, we don't know how to "enlarge" the clips in our stack, 528 so drawing may be artificially restricted. Without keeping a history of 529 all calls to canvas->clipRect() and canvas->clipPath(), we can't exactly 530 reconstruct the correct clips, so this approximation will have to do. 531 The caller really needs to restore() back to the base if they want to 532 accurately take advantage of the new device bounds. 533 */ 534 535 if (NULL == device) { 536 rec->fRegion->setEmpty(); 537 while ((rec = (MCRec*)iter.next()) != NULL) { 538 (void)rec->fRegion->setEmpty(); 539 } 540 fClipStack.reset(); 541 } else { 542 // compute our total bounds for all devices 543 SkIRect bounds; 544 545 bounds.set(0, 0, device->width(), device->height()); 546 547 // now jam our 1st clip to be bounds, and intersect the rest with that 548 rec->fRegion->setRect(bounds); 549 while ((rec = (MCRec*)iter.next()) != NULL) { 550 (void)rec->fRegion->op(bounds, SkRegion::kIntersect_Op); 551 } 552 fClipStack.clipDevRect(bounds, SkRegion::kIntersect_Op); 553 } 554 return device; 555 } 556 557 SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) { 558 SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer))); 559 device->unref(); 560 return device; 561 } 562 563 bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) { 564 SkDevice* device = this->getDevice(); 565 if (!device) { 566 return false; 567 } 568 return device->readPixels(srcRect, bitmap); 569 } 570 571 SkDeviceFactory* SkCanvas::setDeviceFactory(SkDeviceFactory* factory) { 572 SkRefCnt_SafeAssign(fDeviceFactory, factory); 573 return factory; 574 } 575 576 ////////////////////////////////////////////////////////////////////////////// 577 578 bool SkCanvas::readPixels(SkBitmap* bitmap) { 579 SkDevice* device = this->getDevice(); 580 if (!device) { 581 return false; 582 } 583 SkIRect bounds; 584 bounds.set(0, 0, device->width(), device->height()); 585 return this->readPixels(bounds, bitmap); 586 } 587 588 void SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) { 589 SkDevice* device = this->getDevice(); 590 if (device) { 591 device->writePixels(bitmap, x, y); 592 } 593 } 594 595 ////////////////////////////////////////////////////////////////////////////// 596 597 void SkCanvas::updateDeviceCMCache() { 598 if (fDeviceCMDirty) { 599 const SkMatrix& totalMatrix = this->getTotalMatrix(); 600 const SkRegion& totalClip = this->getTotalClip(); 601 DeviceCM* layer = fMCRec->fTopLayer; 602 603 if (NULL == layer->fNext) { // only one layer 604 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); 605 if (fUseExternalMatrix) { 606 layer->updateExternalMatrix(fExternalMatrix, 607 fExternalInverse); 608 } 609 } else { 610 SkRegion clip; 611 clip = totalClip; // make a copy 612 do { 613 layer->updateMC(totalMatrix, clip, fClipStack, &clip); 614 if (fUseExternalMatrix) { 615 layer->updateExternalMatrix(fExternalMatrix, 616 fExternalInverse); 617 } 618 } while ((layer = layer->fNext) != NULL); 619 } 620 fDeviceCMDirty = false; 621 } 622 } 623 624 void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix, 625 const SkRegion& clip, 626 const SkClipStack& clipStack) { 627 SkASSERT(device); 628 if (fLastDeviceToGainFocus != device) { 629 device->gainFocus(this, matrix, clip, clipStack); 630 fLastDeviceToGainFocus = device; 631 } 632 } 633 634 /////////////////////////////////////////////////////////////////////////////// 635 636 int SkCanvas::internalSave(SaveFlags flags) { 637 int saveCount = this->getSaveCount(); // record this before the actual save 638 639 MCRec* newTop = (MCRec*)fMCStack.push_back(); 640 new (newTop) MCRec(fMCRec, flags); // balanced in restore() 641 642 newTop->fNext = fMCRec; 643 fMCRec = newTop; 644 645 fClipStack.save(); 646 SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 647 648 return saveCount; 649 } 650 651 int SkCanvas::save(SaveFlags flags) { 652 // call shared impl 653 return this->internalSave(flags); 654 } 655 656 #define C32MASK (1 << SkBitmap::kARGB_8888_Config) 657 #define C16MASK (1 << SkBitmap::kRGB_565_Config) 658 #define C8MASK (1 << SkBitmap::kA8_Config) 659 660 static SkBitmap::Config resolve_config(SkCanvas* canvas, 661 const SkIRect& bounds, 662 SkCanvas::SaveFlags flags, 663 bool* isOpaque) { 664 *isOpaque = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) == 0; 665 666 #if 0 667 // loop through and union all the configs we may draw into 668 uint32_t configMask = 0; 669 for (int i = canvas->countLayerDevices() - 1; i >= 0; --i) 670 { 671 SkDevice* device = canvas->getLayerDevice(i); 672 if (device->intersects(bounds)) 673 configMask |= 1 << device->config(); 674 } 675 676 // if the caller wants alpha or fullcolor, we can't return 565 677 if (flags & (SkCanvas::kFullColorLayer_SaveFlag | 678 SkCanvas::kHasAlphaLayer_SaveFlag)) 679 configMask &= ~C16MASK; 680 681 switch (configMask) { 682 case C8MASK: // if we only have A8, return that 683 return SkBitmap::kA8_Config; 684 685 case C16MASK: // if we only have 565, return that 686 return SkBitmap::kRGB_565_Config; 687 688 default: 689 return SkBitmap::kARGB_8888_Config; // default answer 690 } 691 #else 692 return SkBitmap::kARGB_8888_Config; // default answer 693 #endif 694 } 695 696 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { 697 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; 698 } 699 700 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, 701 SaveFlags flags) { 702 // do this before we create the layer. We don't call the public save() since 703 // that would invoke a possibly overridden virtual 704 int count = this->internalSave(flags); 705 706 fDeviceCMDirty = true; 707 708 SkIRect ir; 709 const SkIRect& clipBounds = this->getTotalClip().getBounds(); 710 if (clipBounds.isEmpty()) { 711 return count; 712 } 713 714 if (NULL != bounds) { 715 SkRect r; 716 717 this->getTotalMatrix().mapRect(&r, *bounds); 718 r.roundOut(&ir); 719 // early exit if the layer's bounds are clipped out 720 if (!ir.intersect(clipBounds)) { 721 if (bounds_affects_clip(flags)) 722 fMCRec->fRegion->setEmpty(); 723 return count; 724 } 725 } else { // no user bounds, so just use the clip 726 ir = clipBounds; 727 } 728 729 fClipStack.clipDevRect(ir, SkRegion::kIntersect_Op); 730 // early exit if the clip is now empty 731 if (bounds_affects_clip(flags) && 732 !fMCRec->fRegion->op(ir, SkRegion::kIntersect_Op)) { 733 return count; 734 } 735 736 bool isOpaque; 737 SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); 738 739 SkDevice* device = this->createDevice(config, ir.width(), ir.height(), 740 isOpaque, true); 741 device->setOrigin(ir.fLeft, ir.fTop); 742 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); 743 device->unref(); 744 745 layer->fNext = fMCRec->fTopLayer; 746 fMCRec->fLayer = layer; 747 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer 748 749 return count; 750 } 751 752 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 753 SaveFlags flags) { 754 if (0xFF == alpha) { 755 return this->saveLayer(bounds, NULL, flags); 756 } else { 757 SkPaint tmpPaint; 758 tmpPaint.setAlpha(alpha); 759 return this->saveLayer(bounds, &tmpPaint, flags); 760 } 761 } 762 763 void SkCanvas::restore() { 764 // check for underflow 765 if (fMCStack.count() > 1) { 766 this->internalRestore(); 767 } 768 } 769 770 void SkCanvas::internalRestore() { 771 SkASSERT(fMCStack.count() != 0); 772 773 fDeviceCMDirty = true; 774 fLocalBoundsCompareTypeDirty = true; 775 fLocalBoundsCompareTypeDirtyBW = true; 776 777 fClipStack.restore(); 778 // reserve our layer (if any) 779 DeviceCM* layer = fMCRec->fLayer; // may be null 780 // now detach it from fMCRec so we can pop(). Gets freed after its drawn 781 fMCRec->fLayer = NULL; 782 783 // now do the normal restore() 784 fMCRec->~MCRec(); // balanced in save() 785 fMCStack.pop_back(); 786 fMCRec = (MCRec*)fMCStack.back(); 787 788 /* Time to draw the layer's offscreen. We can't call the public drawSprite, 789 since if we're being recorded, we don't want to record this (the 790 recorder will have already recorded the restore). 791 */ 792 if (NULL != layer) { 793 if (layer->fNext) { 794 const SkIPoint& origin = layer->fDevice->getOrigin(); 795 this->drawDevice(layer->fDevice, origin.x(), origin.y(), 796 layer->fPaint); 797 // reset this, since drawDevice will have set it to true 798 fDeviceCMDirty = true; 799 } 800 SkDELETE(layer); 801 } 802 803 SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); 804 } 805 806 int SkCanvas::getSaveCount() const { 807 return fMCStack.count(); 808 } 809 810 void SkCanvas::restoreToCount(int count) { 811 // sanity check 812 if (count < 1) { 813 count = 1; 814 } 815 while (fMCStack.count() > count) { 816 this->restore(); 817 } 818 } 819 820 ///////////////////////////////////////////////////////////////////////////// 821 822 // can't draw it if its empty, or its too big for a fixed-point width or height 823 static bool reject_bitmap(const SkBitmap& bitmap) { 824 return bitmap.width() <= 0 || bitmap.height() <= 0 825 #ifndef SK_ALLOW_OVER_32K_BITMAPS 826 || bitmap.width() > 32767 || bitmap.height() > 32767 827 #endif 828 ; 829 } 830 831 void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 832 const SkMatrix& matrix, const SkPaint* paint) { 833 if (reject_bitmap(bitmap)) { 834 return; 835 } 836 837 SkLazyPaint lazy; 838 if (NULL == paint) { 839 paint = lazy.init(); 840 } 841 this->commonDrawBitmap(bitmap, srcRect, matrix, *paint); 842 } 843 844 void SkCanvas::drawDevice(SkDevice* device, int x, int y, 845 const SkPaint* paint) { 846 SkPaint tmp; 847 if (NULL == paint) { 848 tmp.setDither(true); 849 paint = &tmp; 850 } 851 852 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 853 while (iter.next()) { 854 iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(), 855 looper.paint()); 856 } 857 LOOPER_END 858 } 859 860 ///////////////////////////////////////////////////////////////////////////// 861 862 bool SkCanvas::translate(SkScalar dx, SkScalar dy) { 863 fDeviceCMDirty = true; 864 fLocalBoundsCompareTypeDirty = true; 865 fLocalBoundsCompareTypeDirtyBW = true; 866 return fMCRec->fMatrix->preTranslate(dx, dy); 867 } 868 869 bool SkCanvas::scale(SkScalar sx, SkScalar sy) { 870 fDeviceCMDirty = true; 871 fLocalBoundsCompareTypeDirty = true; 872 fLocalBoundsCompareTypeDirtyBW = true; 873 return fMCRec->fMatrix->preScale(sx, sy); 874 } 875 876 bool SkCanvas::rotate(SkScalar degrees) { 877 fDeviceCMDirty = true; 878 fLocalBoundsCompareTypeDirty = true; 879 fLocalBoundsCompareTypeDirtyBW = true; 880 return fMCRec->fMatrix->preRotate(degrees); 881 } 882 883 bool SkCanvas::skew(SkScalar sx, SkScalar sy) { 884 fDeviceCMDirty = true; 885 fLocalBoundsCompareTypeDirty = true; 886 fLocalBoundsCompareTypeDirtyBW = true; 887 return fMCRec->fMatrix->preSkew(sx, sy); 888 } 889 890 bool SkCanvas::concat(const SkMatrix& matrix) { 891 fDeviceCMDirty = true; 892 fLocalBoundsCompareTypeDirty = true; 893 fLocalBoundsCompareTypeDirtyBW = true; 894 return fMCRec->fMatrix->preConcat(matrix); 895 } 896 897 void SkCanvas::setMatrix(const SkMatrix& matrix) { 898 fDeviceCMDirty = true; 899 fLocalBoundsCompareTypeDirty = true; 900 fLocalBoundsCompareTypeDirtyBW = true; 901 *fMCRec->fMatrix = matrix; 902 } 903 904 // this is not virtual, so it must call a virtual method so that subclasses 905 // will see its action 906 void SkCanvas::resetMatrix() { 907 SkMatrix matrix; 908 909 matrix.reset(); 910 this->setMatrix(matrix); 911 } 912 913 ////////////////////////////////////////////////////////////////////////////// 914 915 bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) { 916 AutoValidateClip avc(this); 917 918 fDeviceCMDirty = true; 919 fLocalBoundsCompareTypeDirty = true; 920 fLocalBoundsCompareTypeDirtyBW = true; 921 922 if (fMCRec->fMatrix->rectStaysRect()) { 923 // for these simpler matrices, we can stay a rect ever after applying 924 // the matrix. This means we don't have to a) make a path, and b) tell 925 // the region code to scan-convert the path, only to discover that it 926 // is really just a rect. 927 SkRect r; 928 SkIRect ir; 929 930 fMCRec->fMatrix->mapRect(&r, rect); 931 fClipStack.clipDevRect(r, op); 932 r.round(&ir); 933 return fMCRec->fRegion->op(ir, op); 934 } else { 935 // since we're rotate or some such thing, we convert the rect to a path 936 // and clip against that, since it can handle any matrix. However, to 937 // avoid recursion in the case where we are subclassed (e.g. Pictures) 938 // we explicitly call "our" version of clipPath. 939 SkPath path; 940 941 path.addRect(rect); 942 return this->SkCanvas::clipPath(path, op); 943 } 944 } 945 946 static bool clipPathHelper(const SkCanvas* canvas, SkRegion* currRgn, 947 const SkPath& devPath, SkRegion::Op op) { 948 // base is used to limit the size (and therefore memory allocation) of the 949 // region that results from scan converting devPath. 950 SkRegion base; 951 952 if (SkRegion::kIntersect_Op == op) { 953 // since we are intersect, we can do better (tighter) with currRgn's 954 // bounds, than just using the device. However, if currRgn is complex, 955 // our region blitter may hork, so we do that case in two steps. 956 if (currRgn->isRect()) { 957 return currRgn->setPath(devPath, *currRgn); 958 } else { 959 base.setRect(currRgn->getBounds()); 960 SkRegion rgn; 961 rgn.setPath(devPath, base); 962 return currRgn->op(rgn, op); 963 } 964 } else { 965 const SkBitmap& bm = canvas->getDevice()->accessBitmap(false); 966 base.setRect(0, 0, bm.width(), bm.height()); 967 968 if (SkRegion::kReplace_Op == op) { 969 return currRgn->setPath(devPath, base); 970 } else { 971 SkRegion rgn; 972 rgn.setPath(devPath, base); 973 return currRgn->op(rgn, op); 974 } 975 } 976 } 977 978 bool SkCanvas::clipPath(const SkPath& path, SkRegion::Op op) { 979 AutoValidateClip avc(this); 980 981 fDeviceCMDirty = true; 982 fLocalBoundsCompareTypeDirty = true; 983 fLocalBoundsCompareTypeDirtyBW = true; 984 985 SkPath devPath; 986 path.transform(*fMCRec->fMatrix, &devPath); 987 988 // if we called path.swap() we could avoid a deep copy of this path 989 fClipStack.clipDevPath(devPath, op); 990 991 return clipPathHelper(this, fMCRec->fRegion, devPath, op); 992 } 993 994 bool SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { 995 AutoValidateClip avc(this); 996 997 fDeviceCMDirty = true; 998 fLocalBoundsCompareTypeDirty = true; 999 fLocalBoundsCompareTypeDirtyBW = true; 1000 1001 // todo: signal fClipStack that we have a region, and therefore (I guess) 1002 // we have to ignore it, and use the region directly? 1003 fClipStack.clipDevRect(rgn.getBounds()); 1004 1005 return fMCRec->fRegion->op(rgn, op); 1006 } 1007 1008 #ifdef SK_DEBUG 1009 void SkCanvas::validateClip() const { 1010 // construct clipRgn from the clipstack 1011 const SkDevice* device = this->getDevice(); 1012 SkIRect ir; 1013 ir.set(0, 0, device->width(), device->height()); 1014 SkRegion clipRgn(ir); 1015 1016 SkClipStack::B2FIter iter(fClipStack); 1017 const SkClipStack::B2FIter::Clip* clip; 1018 while ((clip = iter.next()) != NULL) { 1019 if (clip->fPath) { 1020 clipPathHelper(this, &clipRgn, *clip->fPath, clip->fOp); 1021 } else if (clip->fRect) { 1022 clip->fRect->round(&ir); 1023 clipRgn.op(ir, clip->fOp); 1024 } else { 1025 clipRgn.setEmpty(); 1026 } 1027 } 1028 1029 #if 0 // enable this locally for testing 1030 // now compare against the current rgn 1031 const SkRegion& rgn = this->getTotalClip(); 1032 SkASSERT(rgn == clipRgn); 1033 #endif 1034 } 1035 #endif 1036 1037 /////////////////////////////////////////////////////////////////////////////// 1038 1039 void SkCanvas::computeLocalClipBoundsCompareType(EdgeType et) const { 1040 SkRect r; 1041 SkRectCompareType& rCompare = et == kAA_EdgeType ? fLocalBoundsCompareType : 1042 fLocalBoundsCompareTypeBW; 1043 1044 if (!this->getClipBounds(&r, et)) { 1045 rCompare.setEmpty(); 1046 } else { 1047 rCompare.set(SkScalarToCompareType(r.fLeft), 1048 SkScalarToCompareType(r.fTop), 1049 SkScalarToCompareType(r.fRight), 1050 SkScalarToCompareType(r.fBottom)); 1051 } 1052 } 1053 1054 /* current impl ignores edgetype, and relies on 1055 getLocalClipBoundsCompareType(), which always returns a value assuming 1056 antialiasing (worst case) 1057 */ 1058 bool SkCanvas::quickReject(const SkRect& rect, EdgeType et) const { 1059 1060 if (!rect.hasValidCoordinates()) 1061 return true; 1062 1063 if (fMCRec->fRegion->isEmpty()) { 1064 return true; 1065 } 1066 1067 if (fMCRec->fMatrix->hasPerspective()) { 1068 SkRect dst; 1069 fMCRec->fMatrix->mapRect(&dst, rect); 1070 SkIRect idst; 1071 dst.roundOut(&idst); 1072 return !SkIRect::Intersects(idst, fMCRec->fRegion->getBounds()); 1073 } else { 1074 const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(et); 1075 1076 // for speed, do the most likely reject compares first 1077 SkScalarCompareType userT = SkScalarToCompareType(rect.fTop); 1078 SkScalarCompareType userB = SkScalarToCompareType(rect.fBottom); 1079 if (userT >= clipR.fBottom || userB <= clipR.fTop) { 1080 return true; 1081 } 1082 SkScalarCompareType userL = SkScalarToCompareType(rect.fLeft); 1083 SkScalarCompareType userR = SkScalarToCompareType(rect.fRight); 1084 if (userL >= clipR.fRight || userR <= clipR.fLeft) { 1085 return true; 1086 } 1087 return false; 1088 } 1089 } 1090 1091 bool SkCanvas::quickReject(const SkPath& path, EdgeType et) const { 1092 return path.isEmpty() || this->quickReject(path.getBounds(), et); 1093 } 1094 1095 bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const { 1096 /* current impl ignores edgetype, and relies on 1097 getLocalClipBoundsCompareType(), which always returns a value assuming 1098 antialiasing (worst case) 1099 */ 1100 1101 if (fMCRec->fRegion->isEmpty()) { 1102 return true; 1103 } 1104 1105 SkScalarCompareType userT = SkScalarToCompareType(top); 1106 SkScalarCompareType userB = SkScalarToCompareType(bottom); 1107 1108 // check for invalid user Y coordinates (i.e. empty) 1109 // reed: why do we need to do this check, since it slows us down? 1110 if (userT >= userB) { 1111 return true; 1112 } 1113 1114 // check if we are above or below the local clip bounds 1115 const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType(); 1116 return userT >= clipR.fBottom || userB <= clipR.fTop; 1117 } 1118 1119 bool SkCanvas::getClipBounds(SkRect* bounds, EdgeType et) const { 1120 const SkRegion& clip = *fMCRec->fRegion; 1121 if (clip.isEmpty()) { 1122 if (bounds) { 1123 bounds->setEmpty(); 1124 } 1125 return false; 1126 } 1127 1128 SkMatrix inverse; 1129 // if we can't invert the CTM, we can't return local clip bounds 1130 if (!fMCRec->fMatrix->invert(&inverse)) { 1131 if (bounds) { 1132 bounds->setEmpty(); 1133 } 1134 return false; 1135 } 1136 1137 if (NULL != bounds) { 1138 SkRect r; 1139 // get the clip's bounds 1140 const SkIRect& ibounds = clip.getBounds(); 1141 // adjust it outwards if we are antialiasing 1142 int inset = (kAA_EdgeType == et); 1143 r.iset(ibounds.fLeft - inset, ibounds.fTop - inset, 1144 ibounds.fRight + inset, ibounds.fBottom + inset); 1145 1146 // invert into local coordinates 1147 inverse.mapRect(bounds, r); 1148 } 1149 return true; 1150 } 1151 1152 const SkMatrix& SkCanvas::getTotalMatrix() const { 1153 return *fMCRec->fMatrix; 1154 } 1155 1156 const SkRegion& SkCanvas::getTotalClip() const { 1157 return *fMCRec->fRegion; 1158 } 1159 1160 const SkClipStack& SkCanvas::getTotalClipStack() const { 1161 return fClipStack; 1162 } 1163 1164 void SkCanvas::setExternalMatrix(const SkMatrix* matrix) { 1165 if (NULL == matrix || matrix->isIdentity()) { 1166 if (fUseExternalMatrix) { 1167 fDeviceCMDirty = true; 1168 } 1169 fUseExternalMatrix = false; 1170 } else { 1171 fUseExternalMatrix = true; 1172 fDeviceCMDirty = true; // |= (fExternalMatrix != *matrix) 1173 1174 fExternalMatrix = *matrix; 1175 matrix->invert(&fExternalInverse); 1176 } 1177 } 1178 1179 SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height, 1180 bool isOpaque, bool forLayer) { 1181 return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer); 1182 } 1183 1184 ////////////////////////////////////////////////////////////////////////////// 1185 // These are the virtual drawing methods 1186 ////////////////////////////////////////////////////////////////////////////// 1187 1188 void SkCanvas::clear(SkColor color) { 1189 SkDrawIter iter(this); 1190 1191 while (iter.next()) { 1192 iter.fDevice->clear(color); 1193 } 1194 } 1195 1196 void SkCanvas::drawPaint(const SkPaint& paint) { 1197 LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type) 1198 1199 while (iter.next()) { 1200 iter.fDevice->drawPaint(iter, looper.paint()); 1201 } 1202 1203 LOOPER_END 1204 } 1205 1206 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], 1207 const SkPaint& paint) { 1208 if ((long)count <= 0) { 1209 return; 1210 } 1211 1212 SkASSERT(pts != NULL); 1213 1214 LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type) 1215 1216 while (iter.next()) { 1217 iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint()); 1218 } 1219 1220 LOOPER_END 1221 } 1222 1223 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) { 1224 if (paint.canComputeFastBounds()) { 1225 SkRect storage; 1226 if (this->quickReject(paint.computeFastBounds(r, &storage), 1227 paint2EdgeType(&paint))) { 1228 return; 1229 } 1230 } 1231 1232 LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type) 1233 1234 while (iter.next()) { 1235 iter.fDevice->drawRect(iter, r, looper.paint()); 1236 } 1237 1238 LOOPER_END 1239 } 1240 1241 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 1242 if (paint.canComputeFastBounds()) { 1243 SkRect storage; 1244 const SkRect& bounds = path.getBounds(); 1245 if (this->quickReject(paint.computeFastBounds(bounds, &storage), 1246 paint2EdgeType(&paint))) { 1247 return; 1248 } 1249 } 1250 1251 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 1252 1253 while (iter.next()) { 1254 iter.fDevice->drawPath(iter, path, looper.paint()); 1255 } 1256 1257 LOOPER_END 1258 } 1259 1260 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, 1261 const SkPaint* paint) { 1262 SkDEBUGCODE(bitmap.validate();) 1263 1264 if (NULL == paint || (paint->getMaskFilter() == NULL)) { 1265 SkRect fastBounds; 1266 fastBounds.set(x, y, 1267 x + SkIntToScalar(bitmap.width()), 1268 y + SkIntToScalar(bitmap.height())); 1269 if (this->quickReject(fastBounds, paint2EdgeType(paint))) { 1270 return; 1271 } 1272 } 1273 1274 SkMatrix matrix; 1275 matrix.setTranslate(x, y); 1276 this->internalDrawBitmap(bitmap, NULL, matrix, paint); 1277 } 1278 1279 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 1280 const SkRect& dst, const SkPaint* paint) { 1281 if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { 1282 return; 1283 } 1284 1285 // do this now, to avoid the cost of calling extract for RLE bitmaps 1286 if (this->quickReject(dst, paint2EdgeType(paint))) { 1287 return; 1288 } 1289 1290 const SkBitmap* bitmapPtr = &bitmap; 1291 1292 SkMatrix matrix; 1293 SkRect tmpSrc; 1294 if (src) { 1295 tmpSrc.set(*src); 1296 // if the extract process clipped off the top or left of the 1297 // original, we adjust for that here to get the position right. 1298 if (tmpSrc.fLeft > 0) { 1299 tmpSrc.fRight -= tmpSrc.fLeft; 1300 tmpSrc.fLeft = 0; 1301 } 1302 if (tmpSrc.fTop > 0) { 1303 tmpSrc.fBottom -= tmpSrc.fTop; 1304 tmpSrc.fTop = 0; 1305 } 1306 } else { 1307 tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), 1308 SkIntToScalar(bitmap.height())); 1309 } 1310 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); 1311 1312 // ensure that src is "valid" before we pass it to our internal routines 1313 // and to SkDevice. i.e. sure it is contained inside the original bitmap. 1314 SkIRect tmpISrc; 1315 if (src) { 1316 tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); 1317 if (!tmpISrc.intersect(*src)) { 1318 return; 1319 } 1320 src = &tmpISrc; 1321 } 1322 this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); 1323 } 1324 1325 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, 1326 const SkPaint* paint) { 1327 SkDEBUGCODE(bitmap.validate();) 1328 this->internalDrawBitmap(bitmap, NULL, matrix, paint); 1329 } 1330 1331 void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect, 1332 const SkMatrix& matrix, const SkPaint& paint) { 1333 SkDEBUGCODE(bitmap.validate();) 1334 1335 LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type) 1336 1337 while (iter.next()) { 1338 iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, looper.paint()); 1339 } 1340 1341 LOOPER_END 1342 } 1343 1344 void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y, 1345 const SkPaint* paint) { 1346 SkDEBUGCODE(bitmap.validate();) 1347 1348 if (reject_bitmap(bitmap)) { 1349 return; 1350 } 1351 1352 SkPaint tmp; 1353 if (NULL == paint) { 1354 paint = &tmp; 1355 } 1356 1357 LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) 1358 1359 while (iter.next()) { 1360 iter.fDevice->drawSprite(iter, bitmap, x - iter.getX(), y - iter.getY(), 1361 looper.paint()); 1362 } 1363 LOOPER_END 1364 } 1365 1366 class SkDeviceFilteredPaint { 1367 public: 1368 SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) { 1369 SkDevice::TextFlags flags; 1370 if (device->filterTextFlags(paint, &flags)) { 1371 SkPaint* newPaint = fLazy.set(paint); 1372 newPaint->setFlags(flags.fFlags); 1373 newPaint->setHinting(flags.fHinting); 1374 fPaint = newPaint; 1375 } else { 1376 fPaint = &paint; 1377 } 1378 } 1379 1380 const SkPaint& paint() const { return *fPaint; } 1381 1382 private: 1383 const SkPaint* fPaint; 1384 SkLazyPaint fLazy; 1385 }; 1386 1387 void SkCanvas::drawText(const void* text, size_t byteLength, 1388 SkScalar x, SkScalar y, const SkPaint& paint) { 1389 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1390 1391 while (iter.next()) { 1392 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1393 iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint()); 1394 } 1395 1396 LOOPER_END 1397 } 1398 1399 void SkCanvas::drawPosText(const void* text, size_t byteLength, 1400 const SkPoint pos[], const SkPaint& paint) { 1401 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1402 1403 while (iter.next()) { 1404 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1405 iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2, 1406 dfp.paint()); 1407 } 1408 1409 LOOPER_END 1410 } 1411 1412 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, 1413 const SkScalar xpos[], SkScalar constY, 1414 const SkPaint& paint) { 1415 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1416 1417 while (iter.next()) { 1418 SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint()); 1419 iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1, 1420 dfp.paint()); 1421 } 1422 1423 LOOPER_END 1424 } 1425 1426 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, 1427 const SkPath& path, const SkMatrix* matrix, 1428 const SkPaint& paint) { 1429 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1430 1431 while (iter.next()) { 1432 iter.fDevice->drawTextOnPath(iter, text, byteLength, path, 1433 matrix, looper.paint()); 1434 } 1435 1436 LOOPER_END 1437 } 1438 1439 #ifdef ANDROID 1440 void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength, 1441 const SkPoint pos[], const SkPaint& paint, 1442 const SkPath& path, const SkMatrix* matrix) { 1443 1444 LOOPER_BEGIN(paint, SkDrawFilter::kText_Type) 1445 1446 while (iter.next()) { 1447 iter.fDevice->drawPosTextOnPath(iter, text, byteLength, pos, 1448 looper.paint(), path, matrix); 1449 } 1450 1451 LOOPER_END 1452 } 1453 #endif 1454 1455 void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, 1456 const SkPoint verts[], const SkPoint texs[], 1457 const SkColor colors[], SkXfermode* xmode, 1458 const uint16_t indices[], int indexCount, 1459 const SkPaint& paint) { 1460 LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type) 1461 1462 while (iter.next()) { 1463 iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs, 1464 colors, xmode, indices, indexCount, 1465 looper.paint()); 1466 } 1467 1468 LOOPER_END 1469 } 1470 1471 void SkCanvas::drawData(const void* data, size_t length) { 1472 // do nothing. Subclasses may do something with the data 1473 } 1474 1475 ////////////////////////////////////////////////////////////////////////////// 1476 // These methods are NOT virtual, and therefore must call back into virtual 1477 // methods, rather than actually drawing themselves. 1478 ////////////////////////////////////////////////////////////////////////////// 1479 1480 void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 1481 SkXfermode::Mode mode) { 1482 SkPaint paint; 1483 1484 paint.setARGB(a, r, g, b); 1485 if (SkXfermode::kSrcOver_Mode != mode) { 1486 paint.setXfermodeMode(mode); 1487 } 1488 this->drawPaint(paint); 1489 } 1490 1491 void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { 1492 SkPaint paint; 1493 1494 paint.setColor(c); 1495 if (SkXfermode::kSrcOver_Mode != mode) { 1496 paint.setXfermodeMode(mode); 1497 } 1498 this->drawPaint(paint); 1499 } 1500 1501 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) { 1502 SkPoint pt; 1503 1504 pt.set(x, y); 1505 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 1506 } 1507 1508 void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) { 1509 SkPoint pt; 1510 SkPaint paint; 1511 1512 pt.set(x, y); 1513 paint.setColor(color); 1514 this->drawPoints(kPoints_PointMode, 1, &pt, paint); 1515 } 1516 1517 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 1518 const SkPaint& paint) { 1519 SkPoint pts[2]; 1520 1521 pts[0].set(x0, y0); 1522 pts[1].set(x1, y1); 1523 this->drawPoints(kLines_PointMode, 2, pts, paint); 1524 } 1525 1526 void SkCanvas::drawRectCoords(SkScalar left, SkScalar top, 1527 SkScalar right, SkScalar bottom, 1528 const SkPaint& paint) { 1529 SkRect r; 1530 1531 r.set(left, top, right, bottom); 1532 this->drawRect(r, paint); 1533 } 1534 1535 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 1536 const SkPaint& paint) { 1537 if (radius < 0) { 1538 radius = 0; 1539 } 1540 1541 SkRect r; 1542 r.set(cx - radius, cy - radius, cx + radius, cy + radius); 1543 1544 if (paint.canComputeFastBounds()) { 1545 SkRect storage; 1546 if (this->quickReject(paint.computeFastBounds(r, &storage), 1547 paint2EdgeType(&paint))) { 1548 return; 1549 } 1550 } 1551 1552 SkPath path; 1553 path.addOval(r); 1554 this->drawPath(path, paint); 1555 } 1556 1557 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry, 1558 const SkPaint& paint) { 1559 if (rx > 0 && ry > 0) { 1560 if (paint.canComputeFastBounds()) { 1561 SkRect storage; 1562 if (this->quickReject(paint.computeFastBounds(r, &storage), 1563 paint2EdgeType(&paint))) { 1564 return; 1565 } 1566 } 1567 1568 SkPath path; 1569 path.addRoundRect(r, rx, ry, SkPath::kCW_Direction); 1570 this->drawPath(path, paint); 1571 } else { 1572 this->drawRect(r, paint); 1573 } 1574 } 1575 1576 void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { 1577 if (paint.canComputeFastBounds()) { 1578 SkRect storage; 1579 if (this->quickReject(paint.computeFastBounds(oval, &storage), 1580 paint2EdgeType(&paint))) { 1581 return; 1582 } 1583 } 1584 1585 SkPath path; 1586 path.addOval(oval); 1587 this->drawPath(path, paint); 1588 } 1589 1590 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle, 1591 SkScalar sweepAngle, bool useCenter, 1592 const SkPaint& paint) { 1593 if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) { 1594 this->drawOval(oval, paint); 1595 } else { 1596 SkPath path; 1597 if (useCenter) { 1598 path.moveTo(oval.centerX(), oval.centerY()); 1599 } 1600 path.arcTo(oval, startAngle, sweepAngle, !useCenter); 1601 if (useCenter) { 1602 path.close(); 1603 } 1604 this->drawPath(path, paint); 1605 } 1606 } 1607 1608 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, 1609 const SkPath& path, SkScalar hOffset, 1610 SkScalar vOffset, const SkPaint& paint) { 1611 SkMatrix matrix; 1612 1613 matrix.setTranslate(hOffset, vOffset); 1614 this->drawTextOnPath(text, byteLength, path, &matrix, paint); 1615 } 1616 1617 /////////////////////////////////////////////////////////////////////////////// 1618 1619 void SkCanvas::drawPicture(SkPicture& picture) { 1620 int saveCount = save(); 1621 picture.draw(this); 1622 restoreToCount(saveCount); 1623 } 1624 1625 void SkCanvas::drawShape(SkShape* shape) { 1626 // shape baseclass takes care of save/restore 1627 shape->draw(this); 1628 } 1629 1630 /////////////////////////////////////////////////////////////////////////////// 1631 /////////////////////////////////////////////////////////////////////////////// 1632 1633 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) { 1634 SK_COMPILE_ASSERT(sizeof(fStorage) >= sizeof(SkDrawIter), fStorage_too_small); 1635 1636 SkASSERT(canvas); 1637 1638 fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips); 1639 fDone = !fImpl->next(); 1640 } 1641 1642 SkCanvas::LayerIter::~LayerIter() { 1643 fImpl->~SkDrawIter(); 1644 } 1645 1646 void SkCanvas::LayerIter::next() { 1647 fDone = !fImpl->next(); 1648 } 1649 1650 SkDevice* SkCanvas::LayerIter::device() const { 1651 return fImpl->getDevice(); 1652 } 1653 1654 const SkMatrix& SkCanvas::LayerIter::matrix() const { 1655 return fImpl->getMatrix(); 1656 } 1657 1658 const SkPaint& SkCanvas::LayerIter::paint() const { 1659 const SkPaint* paint = fImpl->getPaint(); 1660 if (NULL == paint) { 1661 paint = &fDefaultPaint; 1662 } 1663 return *paint; 1664 } 1665 1666 const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); } 1667 int SkCanvas::LayerIter::x() const { return fImpl->getX(); } 1668 int SkCanvas::LayerIter::y() const { return fImpl->getY(); } 1669