OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2008 The Android Open Source Project | 2 * Copyright 2008 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 | 8 |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkCanvasPriv.h" | 10 #include "SkCanvasPriv.h" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 values: they reflect the top of the save stack, but translated and clipped | 74 values: they reflect the top of the save stack, but translated and clipped |
75 by the device's XY offset and bitmap-bounds. | 75 by the device's XY offset and bitmap-bounds. |
76 */ | 76 */ |
77 struct DeviceCM { | 77 struct DeviceCM { |
78 DeviceCM* fNext; | 78 DeviceCM* fNext; |
79 SkBaseDevice* fDevice; | 79 SkBaseDevice* fDevice; |
80 SkRasterClip fClip; | 80 SkRasterClip fClip; |
81 const SkMatrix* fMatrix; | 81 const SkMatrix* fMatrix; |
82 SkPaint* fPaint; // may be null (in the future) | 82 SkPaint* fPaint; // may be null (in the future) |
83 | 83 |
84 DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas*
canvas) | 84 DeviceCM(SkBaseDevice* device, int x, int y, const SkPaint* paint, SkCanvas*
canvas, |
85 : fNext(NULL) { | 85 bool conservativeRasterClip) |
86 if (device) { | 86 : fNext(NULL) |
| 87 , fClip(conservativeRasterClip) |
| 88 { |
| 89 if (NULL != device) { |
87 device->ref(); | 90 device->ref(); |
88 device->onAttachToCanvas(canvas); | 91 device->onAttachToCanvas(canvas); |
89 } | 92 } |
90 fDevice = device; | 93 fDevice = device; |
91 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; | 94 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; |
92 } | 95 } |
93 | 96 |
94 ~DeviceCM() { | 97 ~DeviceCM() { |
95 if (fDevice) { | 98 if (fDevice) { |
96 fDevice->onDetachFromCanvas(); | 99 fDevice->onDetachFromCanvas(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 147 |
145 /* This is the record we keep for each save/restore level in the stack. | 148 /* This is the record we keep for each save/restore level in the stack. |
146 Since a level optionally copies the matrix and/or stack, we have pointers | 149 Since a level optionally copies the matrix and/or stack, we have pointers |
147 for these fields. If the value is copied for this level, the copy is | 150 for these fields. If the value is copied for this level, the copy is |
148 stored in the ...Storage field, and the pointer points to that. If the | 151 stored in the ...Storage field, and the pointer points to that. If the |
149 value is not copied for this level, we ignore ...Storage, and just point | 152 value is not copied for this level, we ignore ...Storage, and just point |
150 at the corresponding value in the previous level in the stack. | 153 at the corresponding value in the previous level in the stack. |
151 */ | 154 */ |
152 class SkCanvas::MCRec { | 155 class SkCanvas::MCRec { |
153 public: | 156 public: |
| 157 SkRasterClip fRasterClip; |
154 SkMatrix fMatrix; | 158 SkMatrix fMatrix; |
155 SkRasterClip fRasterClip; | |
156 SkDrawFilter* fFilter; // the current filter (or null) | 159 SkDrawFilter* fFilter; // the current filter (or null) |
157 | 160 DeviceCM* fLayer; |
158 DeviceCM* fLayer; | |
159 /* If there are any layers in the stack, this points to the top-most | 161 /* If there are any layers in the stack, this points to the top-most |
160 one that is at or below this level in the stack (so we know what | 162 one that is at or below this level in the stack (so we know what |
161 bitmap/device to draw into from this level. This value is NOT | 163 bitmap/device to draw into from this level. This value is NOT |
162 reference counted, since the real owner is either our fLayer field, | 164 reference counted, since the real owner is either our fLayer field, |
163 or a previous one in a lower level.) | 165 or a previous one in a lower level.) |
164 */ | 166 */ |
165 DeviceCM* fTopLayer; | 167 DeviceCM* fTopLayer; |
166 | 168 |
167 MCRec(const MCRec* prev) { | 169 MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) { |
168 if (prev) { | 170 fMatrix.reset(); |
169 fMatrix = prev->fMatrix; | 171 fFilter = NULL; |
170 fRasterClip = prev->fRasterClip; | 172 fLayer = NULL; |
171 | 173 fTopLayer = NULL; |
172 fFilter = prev->fFilter; | 174 |
173 SkSafeRef(fFilter); | |
174 | |
175 fTopLayer = prev->fTopLayer; | |
176 } else { // no prev | |
177 fMatrix.reset(); | |
178 fFilter = NULL; | |
179 fTopLayer = NULL; | |
180 } | |
181 fLayer = NULL; | |
182 | |
183 // don't bother initializing fNext | 175 // don't bother initializing fNext |
184 inc_rec(); | 176 inc_rec(); |
185 } | 177 } |
| 178 MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) { |
| 179 fMatrix = prev.fMatrix; |
| 180 fFilter = SkSafeRef(prev.fFilter); |
| 181 fLayer = NULL; |
| 182 fTopLayer = prev.fTopLayer; |
| 183 |
| 184 // don't bother initializing fNext |
| 185 inc_rec(); |
| 186 } |
186 ~MCRec() { | 187 ~MCRec() { |
187 SkSafeUnref(fFilter); | 188 SkSafeUnref(fFilter); |
188 SkDELETE(fLayer); | 189 SkDELETE(fLayer); |
189 dec_rec(); | 190 dec_rec(); |
190 } | 191 } |
191 }; | 192 }; |
192 | 193 |
193 class SkDrawIter : public SkDraw { | 194 class SkDrawIter : public SkDraw { |
194 public: | 195 public: |
195 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { | 196 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 #define LOOPER_BEGIN(paint, type, bounds) \ | 375 #define LOOPER_BEGIN(paint, type, bounds) \ |
375 this->predrawNotify(); \ | 376 this->predrawNotify(); \ |
376 AutoDrawLooper looper(this, paint, false, bounds); \ | 377 AutoDrawLooper looper(this, paint, false, bounds); \ |
377 while (looper.next(type)) { \ | 378 while (looper.next(type)) { \ |
378 SkDrawIter iter(this); | 379 SkDrawIter iter(this); |
379 | 380 |
380 #define LOOPER_END } | 381 #define LOOPER_END } |
381 | 382 |
382 //////////////////////////////////////////////////////////////////////////// | 383 //////////////////////////////////////////////////////////////////////////// |
383 | 384 |
384 SkBaseDevice* SkCanvas::init(SkBaseDevice* device) { | 385 SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { |
| 386 fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag)
; |
385 fCachedLocalClipBounds.setEmpty(); | 387 fCachedLocalClipBounds.setEmpty(); |
386 fCachedLocalClipBoundsDirty = true; | 388 fCachedLocalClipBoundsDirty = true; |
387 fAllowSoftClip = true; | 389 fAllowSoftClip = true; |
388 fAllowSimplifyClip = false; | 390 fAllowSimplifyClip = false; |
389 fDeviceCMDirty = true; | 391 fDeviceCMDirty = true; |
390 fSaveLayerCount = 0; | 392 fSaveLayerCount = 0; |
391 fCullCount = 0; | 393 fCullCount = 0; |
392 fMetaData = NULL; | 394 fMetaData = NULL; |
393 | 395 |
| 396 if (device && device->forceConservativeRasterClip()) { |
| 397 fConservativeRasterClip = true; |
| 398 } |
| 399 |
394 fMCRec = (MCRec*)fMCStack.push_back(); | 400 fMCRec = (MCRec*)fMCStack.push_back(); |
395 new (fMCRec) MCRec(NULL); | 401 new (fMCRec) MCRec(fConservativeRasterClip); |
396 | 402 |
397 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL)); | 403 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservative
RasterClip)); |
398 fMCRec->fTopLayer = fMCRec->fLayer; | 404 fMCRec->fTopLayer = fMCRec->fLayer; |
399 | 405 |
400 fSurfaceBase = NULL; | 406 fSurfaceBase = NULL; |
401 | 407 |
402 if (device) { | 408 if (device) { |
403 device->onAttachToCanvas(this); | 409 device->onAttachToCanvas(this); |
404 fMCRec->fLayer->fDevice = SkRef(device); | 410 fMCRec->fLayer->fDevice = SkRef(device); |
405 fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->hei
ght())); | 411 fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->hei
ght())); |
406 } | 412 } |
407 return device; | 413 return device; |
408 } | 414 } |
409 | 415 |
410 SkCanvas::SkCanvas() | 416 SkCanvas::SkCanvas() |
411 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 417 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
412 { | 418 { |
413 inc_canvas(); | 419 inc_canvas(); |
414 | 420 |
415 this->init(NULL); | 421 this->init(NULL, kDefault_InitFlags); |
416 } | 422 } |
417 | 423 |
| 424 static SkBitmap make_nopixels(int width, int height) { |
| 425 SkBitmap bitmap; |
| 426 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); |
| 427 return bitmap; |
| 428 } |
| 429 |
| 430 class SkNoPixelsBitmapDevice : public SkBitmapDevice { |
| 431 public: |
| 432 SkNoPixelsBitmapDevice(int width, int height) : INHERITED(make_nopixels(widt
h, height)) {} |
| 433 |
| 434 private: |
| 435 |
| 436 typedef SkBitmapDevice INHERITED; |
| 437 }; |
| 438 |
418 SkCanvas::SkCanvas(int width, int height) | 439 SkCanvas::SkCanvas(int width, int height) |
419 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 440 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
420 { | 441 { |
421 inc_canvas(); | 442 inc_canvas(); |
| 443 |
| 444 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), kDefault_Ini
tFlags)->unref(); |
| 445 } |
422 | 446 |
423 SkBitmap bitmap; | 447 SkCanvas::SkCanvas(int width, int height, InitFlags flags) |
424 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); | 448 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
425 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); | 449 { |
| 450 inc_canvas(); |
| 451 |
| 452 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), flags)->unre
f(); |
| 453 } |
| 454 |
| 455 SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags) |
| 456 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
| 457 { |
| 458 inc_canvas(); |
| 459 |
| 460 this->init(device, flags); |
426 } | 461 } |
427 | 462 |
428 SkCanvas::SkCanvas(SkBaseDevice* device) | 463 SkCanvas::SkCanvas(SkBaseDevice* device) |
429 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 464 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
430 { | 465 { |
431 inc_canvas(); | 466 inc_canvas(); |
432 | 467 |
433 this->init(device); | 468 this->init(device, kDefault_InitFlags); |
434 } | 469 } |
435 | 470 |
436 SkCanvas::SkCanvas(const SkBitmap& bitmap) | 471 SkCanvas::SkCanvas(const SkBitmap& bitmap) |
437 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 472 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
438 { | 473 { |
439 inc_canvas(); | 474 inc_canvas(); |
440 | 475 |
441 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); | 476 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)), kDefault_InitFlags)->unref(
); |
442 } | 477 } |
443 | 478 |
444 SkCanvas::~SkCanvas() { | 479 SkCanvas::~SkCanvas() { |
445 // free up the contents of our deque | 480 // free up the contents of our deque |
446 this->restoreToCount(1); // restore everything but the last | 481 this->restoreToCount(1); // restore everything but the last |
447 SkASSERT(0 == fSaveLayerCount); | 482 SkASSERT(0 == fSaveLayerCount); |
448 | 483 |
449 this->internalRestore(); // restore the last, since we're going away | 484 this->internalRestore(); // restore the last, since we're going away |
450 | 485 |
451 SkDELETE(fMetaData); | 486 SkDELETE(fMetaData); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 fDeviceCMDirty = false; | 762 fDeviceCMDirty = false; |
728 } | 763 } |
729 } | 764 } |
730 | 765 |
731 /////////////////////////////////////////////////////////////////////////////// | 766 /////////////////////////////////////////////////////////////////////////////// |
732 | 767 |
733 int SkCanvas::internalSave() { | 768 int SkCanvas::internalSave() { |
734 int saveCount = this->getSaveCount(); // record this before the actual save | 769 int saveCount = this->getSaveCount(); // record this before the actual save |
735 | 770 |
736 MCRec* newTop = (MCRec*)fMCStack.push_back(); | 771 MCRec* newTop = (MCRec*)fMCStack.push_back(); |
737 new (newTop) MCRec(fMCRec); // balanced in restore() | 772 new (newTop) MCRec(*fMCRec); // balanced in restore() |
738 fMCRec = newTop; | 773 fMCRec = newTop; |
739 | 774 |
740 fClipStack.save(); | 775 fClipStack.save(); |
741 | 776 |
742 return saveCount; | 777 return saveCount; |
743 } | 778 } |
744 | 779 |
745 int SkCanvas::save() { | 780 int SkCanvas::save() { |
746 this->willSave(); | 781 this->willSave(); |
747 return this->internalSave(); | 782 return this->internalSave(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 } | 894 } |
860 } else { | 895 } else { |
861 device = this->createLayerDevice(info); | 896 device = this->createLayerDevice(info); |
862 } | 897 } |
863 if (NULL == device) { | 898 if (NULL == device) { |
864 SkDebugf("Unable to create device for layer."); | 899 SkDebugf("Unable to create device for layer."); |
865 return count; | 900 return count; |
866 } | 901 } |
867 | 902 |
868 device->setOrigin(ir.fLeft, ir.fTop); | 903 device->setOrigin(ir.fLeft, ir.fTop); |
869 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, th
is)); | 904 DeviceCM* layer = SkNEW_ARGS(DeviceCM, |
| 905 (device, ir.fLeft, ir.fTop, paint, this, fConse
rvativeRasterClip)); |
870 device->unref(); | 906 device->unref(); |
871 | 907 |
872 layer->fNext = fMCRec->fTopLayer; | 908 layer->fNext = fMCRec->fTopLayer; |
873 fMCRec->fLayer = layer; | 909 fMCRec->fLayer = layer; |
874 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer | 910 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer |
875 | 911 |
876 fSaveLayerCount += 1; | 912 fSaveLayerCount += 1; |
877 return count; | 913 return count; |
878 } | 914 } |
879 | 915 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 | 1315 |
1280 if (fMCRec->fMatrix.rectStaysRect()) { | 1316 if (fMCRec->fMatrix.rectStaysRect()) { |
1281 // for these simpler matrices, we can stay a rect even after applying | 1317 // for these simpler matrices, we can stay a rect even after applying |
1282 // the matrix. This means we don't have to a) make a path, and b) tell | 1318 // the matrix. This means we don't have to a) make a path, and b) tell |
1283 // the region code to scan-convert the path, only to discover that it | 1319 // the region code to scan-convert the path, only to discover that it |
1284 // is really just a rect. | 1320 // is really just a rect. |
1285 SkRect r; | 1321 SkRect r; |
1286 | 1322 |
1287 fMCRec->fMatrix.mapRect(&r, rect); | 1323 fMCRec->fMatrix.mapRect(&r, rect); |
1288 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); | 1324 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); |
1289 fMCRec->fRasterClip.op(r, op, kSoft_ClipEdgeStyle == edgeStyle); | 1325 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeSt
yle == edgeStyle); |
1290 } else { | 1326 } else { |
1291 // since we're rotated or some such thing, we convert the rect to a path | 1327 // since we're rotated or some such thing, we convert the rect to a path |
1292 // and clip against that, since it can handle any matrix. However, to | 1328 // and clip against that, since it can handle any matrix. However, to |
1293 // avoid recursion in the case where we are subclassed (e.g. Pictures) | 1329 // avoid recursion in the case where we are subclassed (e.g. Pictures) |
1294 // we explicitly call "our" version of clipPath. | 1330 // we explicitly call "our" version of clipPath. |
1295 SkPath path; | 1331 SkPath path; |
1296 | 1332 |
1297 path.addRect(rect); | 1333 path.addRect(rect); |
1298 this->SkCanvas::onClipPath(path, op, edgeStyle); | 1334 this->SkCanvas::onClipPath(path, op, edgeStyle); |
1299 } | 1335 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1414 if (element->isAA()) { | 1450 if (element->isAA()) { |
1415 edgeStyle = kSoft_ClipEdgeStyle; | 1451 edgeStyle = kSoft_ClipEdgeStyle; |
1416 } | 1452 } |
1417 } | 1453 } |
1418 op = SkRegion::kReplace_Op; | 1454 op = SkRegion::kReplace_Op; |
1419 } | 1455 } |
1420 | 1456 |
1421 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); | 1457 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); |
1422 } | 1458 } |
1423 | 1459 |
1424 void SkCanvas::updateClipConservativelyUsingBounds(const SkRect& bounds, SkRegio
n::Op op, | |
1425 bool inverseFilled) { | |
1426 // This is for updating the clip conservatively using only bounds | |
1427 // information. | |
1428 // Contract: | |
1429 // The current clip must contain the true clip. The true | |
1430 // clip is the clip that would have normally been computed | |
1431 // by calls to clipPath and clipRRect | |
1432 // Objective: | |
1433 // Keep the current clip as small as possible without | |
1434 // breaking the contract, using only clip bounding rectangles | |
1435 // (for performance). | |
1436 | |
1437 // N.B.: This *never* calls back through a virtual on canvas, so subclasses | |
1438 // don't have to worry about getting caught in a loop. Thus anywhere | |
1439 // we call a virtual method, we explicitly prefix it with | |
1440 // SkCanvas:: to be sure to call the base-class. | |
1441 | |
1442 if (inverseFilled) { | |
1443 switch (op) { | |
1444 case SkRegion::kIntersect_Op: | |
1445 case SkRegion::kDifference_Op: | |
1446 // These ops can only shrink the current clip. So leaving | |
1447 // the clip unchanged conservatively respects the contract. | |
1448 break; | |
1449 case SkRegion::kUnion_Op: | |
1450 case SkRegion::kReplace_Op: | |
1451 case SkRegion::kReverseDifference_Op: | |
1452 case SkRegion::kXOR_Op: { | |
1453 // These ops can grow the current clip up to the extents of | |
1454 // the input clip, which is inverse filled, so we just set | |
1455 // the current clip to the device bounds. | |
1456 SkRect deviceBounds; | |
1457 SkIRect deviceIBounds; | |
1458 this->getDevice()->getGlobalBounds(&deviceIBounds); | |
1459 deviceBounds = SkRect::Make(deviceIBounds); | |
1460 | |
1461 // set the clip in device space | |
1462 SkMatrix savedMatrix = this->getTotalMatrix(); | |
1463 this->SkCanvas::setMatrix(SkMatrix::I()); | |
1464 this->SkCanvas::onClipRect(deviceBounds, SkRegion::kReplace_
Op, | |
1465 kHard_ClipEdgeStyle); | |
1466 this->setMatrix(savedMatrix); | |
1467 break; | |
1468 } | |
1469 default: | |
1470 SkASSERT(0); // unhandled op? | |
1471 } | |
1472 } else { | |
1473 // Not inverse filled | |
1474 switch (op) { | |
1475 case SkRegion::kIntersect_Op: | |
1476 case SkRegion::kUnion_Op: | |
1477 case SkRegion::kReplace_Op: | |
1478 this->SkCanvas::onClipRect(bounds, op, kHard_ClipEdgeStyle); | |
1479 break; | |
1480 case SkRegion::kDifference_Op: | |
1481 // Difference can only shrink the current clip. | |
1482 // Leaving clip unchanged conservatively fullfills the contract. | |
1483 break; | |
1484 case SkRegion::kReverseDifference_Op: | |
1485 // To reverse, we swap in the bounds with a replace op. | |
1486 // As with difference, leave it unchanged. | |
1487 this->SkCanvas::onClipRect(bounds, SkRegion::kReplace_Op, kHard_
ClipEdgeStyle); | |
1488 break; | |
1489 case SkRegion::kXOR_Op: | |
1490 // Be conservative, based on (A XOR B) always included in (A uni
on B), | |
1491 // which is always included in (bounds(A) union bounds(B)) | |
1492 this->SkCanvas::onClipRect(bounds, SkRegion::kUnion_Op, kHard_Cl
ipEdgeStyle); | |
1493 break; | |
1494 default: | |
1495 SkASSERT(0); // unhandled op? | |
1496 } | |
1497 } | |
1498 } | |
1499 | |
1500 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1460 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { |
1501 this->onClipRegion(rgn, op); | 1461 this->onClipRegion(rgn, op); |
1502 } | 1462 } |
1503 | 1463 |
1504 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1464 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { |
1505 AutoValidateClip avc(this); | 1465 AutoValidateClip avc(this); |
1506 | 1466 |
1507 fDeviceCMDirty = true; | 1467 fDeviceCMDirty = true; |
1508 fCachedLocalClipBoundsDirty = true; | 1468 fCachedLocalClipBoundsDirty = true; |
1509 | 1469 |
1510 // todo: signal fClipStack that we have a region, and therefore (I guess) | 1470 // todo: signal fClipStack that we have a region, and therefore (I guess) |
1511 // we have to ignore it, and use the region directly? | 1471 // we have to ignore it, and use the region directly? |
1512 fClipStack.clipDevRect(rgn.getBounds(), op); | 1472 fClipStack.clipDevRect(rgn.getBounds(), op); |
1513 | 1473 |
1514 fMCRec->fRasterClip.op(rgn, op); | 1474 fMCRec->fRasterClip.op(rgn, op); |
1515 } | 1475 } |
1516 | 1476 |
1517 #ifdef SK_DEBUG | 1477 #ifdef SK_DEBUG |
1518 void SkCanvas::validateClip() const { | 1478 void SkCanvas::validateClip() const { |
1519 // construct clipRgn from the clipstack | 1479 // construct clipRgn from the clipstack |
1520 const SkBaseDevice* device = this->getDevice(); | 1480 const SkBaseDevice* device = this->getDevice(); |
1521 if (!device) { | 1481 if (!device) { |
1522 SkASSERT(this->isClipEmpty()); | 1482 SkASSERT(this->isClipEmpty()); |
1523 return; | 1483 return; |
1524 } | 1484 } |
1525 | 1485 |
1526 SkIRect ir; | 1486 SkIRect ir; |
1527 ir.set(0, 0, device->width(), device->height()); | 1487 ir.set(0, 0, device->width(), device->height()); |
1528 SkRasterClip tmpClip(ir); | 1488 SkRasterClip tmpClip(ir, fConservativeRasterClip); |
1529 | 1489 |
1530 SkClipStack::B2TIter iter(fClipStack); | 1490 SkClipStack::B2TIter iter(fClipStack); |
1531 const SkClipStack::Element* element; | 1491 const SkClipStack::Element* element; |
1532 while ((element = iter.next()) != NULL) { | 1492 while ((element = iter.next()) != NULL) { |
1533 switch (element->getType()) { | 1493 switch (element->getType()) { |
1534 case SkClipStack::Element::kRect_Type: | 1494 case SkClipStack::Element::kRect_Type: |
1535 element->getRect().round(&ir); | 1495 element->getRect().round(&ir); |
1536 tmpClip.op(ir, element->getOp()); | 1496 tmpClip.op(ir, element->getOp()); |
1537 break; | 1497 break; |
1538 case SkClipStack::Element::kEmpty_Type: | 1498 case SkClipStack::Element::kEmpty_Type: |
(...skipping 23 matching lines...) Expand all Loading... |
1562 | 1522 |
1563 bool SkCanvas::isClipEmpty() const { | 1523 bool SkCanvas::isClipEmpty() const { |
1564 return fMCRec->fRasterClip.isEmpty(); | 1524 return fMCRec->fRasterClip.isEmpty(); |
1565 } | 1525 } |
1566 | 1526 |
1567 bool SkCanvas::isClipRect() const { | 1527 bool SkCanvas::isClipRect() const { |
1568 return fMCRec->fRasterClip.isRect(); | 1528 return fMCRec->fRasterClip.isRect(); |
1569 } | 1529 } |
1570 | 1530 |
1571 bool SkCanvas::quickReject(const SkRect& rect) const { | 1531 bool SkCanvas::quickReject(const SkRect& rect) const { |
1572 | |
1573 if (!rect.isFinite()) | 1532 if (!rect.isFinite()) |
1574 return true; | 1533 return true; |
1575 | 1534 |
1576 if (fMCRec->fRasterClip.isEmpty()) { | 1535 if (fMCRec->fRasterClip.isEmpty()) { |
1577 return true; | 1536 return true; |
1578 } | 1537 } |
1579 | 1538 |
1580 if (fMCRec->fMatrix.hasPerspective()) { | 1539 if (fMCRec->fMatrix.hasPerspective()) { |
1581 SkRect dst; | 1540 SkRect dst; |
1582 fMCRec->fMatrix.mapRect(&dst, rect); | 1541 fMCRec->fMatrix.mapRect(&dst, rect); |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2532 } | 2491 } |
2533 | 2492 |
2534 if (matrix) { | 2493 if (matrix) { |
2535 canvas->concat(*matrix); | 2494 canvas->concat(*matrix); |
2536 } | 2495 } |
2537 } | 2496 } |
2538 | 2497 |
2539 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 2498 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
2540 fCanvas->restoreToCount(fSaveCount); | 2499 fCanvas->restoreToCount(fSaveCount); |
2541 } | 2500 } |
OLD | NEW |