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 bool conservativeRasterClip) | 85 : fNext(NULL) { |
86 : fNext(NULL) | 86 if (device) { |
87 , fClip(conservativeRasterClip) | |
88 { | |
89 if (NULL != device) { | |
90 device->ref(); | 87 device->ref(); |
91 device->onAttachToCanvas(canvas); | 88 device->onAttachToCanvas(canvas); |
92 } | 89 } |
93 fDevice = device; | 90 fDevice = device; |
94 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; | 91 fPaint = paint ? SkNEW_ARGS(SkPaint, (*paint)) : NULL; |
95 } | 92 } |
96 | 93 |
97 ~DeviceCM() { | 94 ~DeviceCM() { |
98 if (fDevice) { | 95 if (fDevice) { |
99 fDevice->onDetachFromCanvas(); | 96 fDevice->onDetachFromCanvas(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 144 |
148 /* This is the record we keep for each save/restore level in the stack. | 145 /* This is the record we keep for each save/restore level in the stack. |
149 Since a level optionally copies the matrix and/or stack, we have pointers | 146 Since a level optionally copies the matrix and/or stack, we have pointers |
150 for these fields. If the value is copied for this level, the copy is | 147 for these fields. If the value is copied for this level, the copy is |
151 stored in the ...Storage field, and the pointer points to that. If the | 148 stored in the ...Storage field, and the pointer points to that. If the |
152 value is not copied for this level, we ignore ...Storage, and just point | 149 value is not copied for this level, we ignore ...Storage, and just point |
153 at the corresponding value in the previous level in the stack. | 150 at the corresponding value in the previous level in the stack. |
154 */ | 151 */ |
155 class SkCanvas::MCRec { | 152 class SkCanvas::MCRec { |
156 public: | 153 public: |
| 154 SkMatrix fMatrix; |
157 SkRasterClip fRasterClip; | 155 SkRasterClip fRasterClip; |
158 SkMatrix fMatrix; | |
159 SkDrawFilter* fFilter; // the current filter (or null) | 156 SkDrawFilter* fFilter; // the current filter (or null) |
160 DeviceCM* fLayer; | 157 |
| 158 DeviceCM* fLayer; |
161 /* If there are any layers in the stack, this points to the top-most | 159 /* If there are any layers in the stack, this points to the top-most |
162 one that is at or below this level in the stack (so we know what | 160 one that is at or below this level in the stack (so we know what |
163 bitmap/device to draw into from this level. This value is NOT | 161 bitmap/device to draw into from this level. This value is NOT |
164 reference counted, since the real owner is either our fLayer field, | 162 reference counted, since the real owner is either our fLayer field, |
165 or a previous one in a lower level.) | 163 or a previous one in a lower level.) |
166 */ | 164 */ |
167 DeviceCM* fTopLayer; | 165 DeviceCM* fTopLayer; |
168 | 166 |
169 MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) { | 167 MCRec(const MCRec* prev) { |
170 fMatrix.reset(); | 168 if (prev) { |
171 fFilter = NULL; | 169 fMatrix = prev->fMatrix; |
172 fLayer = NULL; | 170 fRasterClip = prev->fRasterClip; |
173 fTopLayer = NULL; | 171 |
174 | 172 fFilter = prev->fFilter; |
| 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 |
175 // don't bother initializing fNext | 183 // don't bother initializing fNext |
176 inc_rec(); | 184 inc_rec(); |
177 } | 185 } |
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 } | |
187 ~MCRec() { | 186 ~MCRec() { |
188 SkSafeUnref(fFilter); | 187 SkSafeUnref(fFilter); |
189 SkDELETE(fLayer); | 188 SkDELETE(fLayer); |
190 dec_rec(); | 189 dec_rec(); |
191 } | 190 } |
192 }; | 191 }; |
193 | 192 |
194 class SkDrawIter : public SkDraw { | 193 class SkDrawIter : public SkDraw { |
195 public: | 194 public: |
196 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { | 195 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 #define LOOPER_BEGIN(paint, type, bounds) \ | 374 #define LOOPER_BEGIN(paint, type, bounds) \ |
376 this->predrawNotify(); \ | 375 this->predrawNotify(); \ |
377 AutoDrawLooper looper(this, paint, false, bounds); \ | 376 AutoDrawLooper looper(this, paint, false, bounds); \ |
378 while (looper.next(type)) { \ | 377 while (looper.next(type)) { \ |
379 SkDrawIter iter(this); | 378 SkDrawIter iter(this); |
380 | 379 |
381 #define LOOPER_END } | 380 #define LOOPER_END } |
382 | 381 |
383 //////////////////////////////////////////////////////////////////////////// | 382 //////////////////////////////////////////////////////////////////////////// |
384 | 383 |
385 SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { | 384 SkBaseDevice* SkCanvas::init(SkBaseDevice* device) { |
386 fConservativeRasterClip = SkToBool(flags & kConservativeRasterClip_InitFlag)
; | |
387 fCachedLocalClipBounds.setEmpty(); | 385 fCachedLocalClipBounds.setEmpty(); |
388 fCachedLocalClipBoundsDirty = true; | 386 fCachedLocalClipBoundsDirty = true; |
389 fAllowSoftClip = true; | 387 fAllowSoftClip = true; |
390 fAllowSimplifyClip = false; | 388 fAllowSimplifyClip = false; |
391 fDeviceCMDirty = true; | 389 fDeviceCMDirty = true; |
392 fSaveLayerCount = 0; | 390 fSaveLayerCount = 0; |
393 fCullCount = 0; | 391 fCullCount = 0; |
394 fMetaData = NULL; | 392 fMetaData = NULL; |
395 | 393 |
396 if (device && device->forceConservativeRasterClip()) { | |
397 fConservativeRasterClip = true; | |
398 } | |
399 | |
400 fMCRec = (MCRec*)fMCStack.push_back(); | 394 fMCRec = (MCRec*)fMCStack.push_back(); |
401 new (fMCRec) MCRec(fConservativeRasterClip); | 395 new (fMCRec) MCRec(NULL); |
402 | 396 |
403 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservative
RasterClip)); | 397 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL)); |
404 fMCRec->fTopLayer = fMCRec->fLayer; | 398 fMCRec->fTopLayer = fMCRec->fLayer; |
405 | 399 |
406 fSurfaceBase = NULL; | 400 fSurfaceBase = NULL; |
407 | 401 |
408 if (device) { | 402 if (device) { |
409 device->onAttachToCanvas(this); | 403 device->onAttachToCanvas(this); |
410 fMCRec->fLayer->fDevice = SkRef(device); | 404 fMCRec->fLayer->fDevice = SkRef(device); |
411 fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->hei
ght())); | 405 fMCRec->fRasterClip.setRect(SkIRect::MakeWH(device->width(), device->hei
ght())); |
412 } | 406 } |
413 return device; | 407 return device; |
414 } | 408 } |
415 | 409 |
416 SkCanvas::SkCanvas() | 410 SkCanvas::SkCanvas() |
417 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 411 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
418 { | 412 { |
419 inc_canvas(); | 413 inc_canvas(); |
420 | 414 |
421 this->init(NULL, kDefault_InitFlags); | 415 this->init(NULL); |
422 } | 416 } |
423 | 417 |
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 | |
439 SkCanvas::SkCanvas(int width, int height) | 418 SkCanvas::SkCanvas(int width, int height) |
440 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 419 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
441 { | 420 { |
442 inc_canvas(); | 421 inc_canvas(); |
443 | |
444 this->init(SkNEW_ARGS(SkNoPixelsBitmapDevice, (width, height)), kDefault_Ini
tFlags)->unref(); | |
445 } | |
446 | 422 |
447 SkCanvas::SkCanvas(int width, int height, InitFlags flags) | 423 SkBitmap bitmap; |
448 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 424 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); |
449 { | 425 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); |
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); | |
461 } | 426 } |
462 | 427 |
463 SkCanvas::SkCanvas(SkBaseDevice* device) | 428 SkCanvas::SkCanvas(SkBaseDevice* device) |
464 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 429 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
465 { | 430 { |
466 inc_canvas(); | 431 inc_canvas(); |
467 | 432 |
468 this->init(device, kDefault_InitFlags); | 433 this->init(device); |
469 } | 434 } |
470 | 435 |
471 SkCanvas::SkCanvas(const SkBitmap& bitmap) | 436 SkCanvas::SkCanvas(const SkBitmap& bitmap) |
472 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) | 437 : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) |
473 { | 438 { |
474 inc_canvas(); | 439 inc_canvas(); |
475 | 440 |
476 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)), kDefault_InitFlags)->unref(
); | 441 this->init(SkNEW_ARGS(SkBitmapDevice, (bitmap)))->unref(); |
477 } | 442 } |
478 | 443 |
479 SkCanvas::~SkCanvas() { | 444 SkCanvas::~SkCanvas() { |
480 // free up the contents of our deque | 445 // free up the contents of our deque |
481 this->restoreToCount(1); // restore everything but the last | 446 this->restoreToCount(1); // restore everything but the last |
482 SkASSERT(0 == fSaveLayerCount); | 447 SkASSERT(0 == fSaveLayerCount); |
483 | 448 |
484 this->internalRestore(); // restore the last, since we're going away | 449 this->internalRestore(); // restore the last, since we're going away |
485 | 450 |
486 SkDELETE(fMetaData); | 451 SkDELETE(fMetaData); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 fDeviceCMDirty = false; | 727 fDeviceCMDirty = false; |
763 } | 728 } |
764 } | 729 } |
765 | 730 |
766 /////////////////////////////////////////////////////////////////////////////// | 731 /////////////////////////////////////////////////////////////////////////////// |
767 | 732 |
768 int SkCanvas::internalSave() { | 733 int SkCanvas::internalSave() { |
769 int saveCount = this->getSaveCount(); // record this before the actual save | 734 int saveCount = this->getSaveCount(); // record this before the actual save |
770 | 735 |
771 MCRec* newTop = (MCRec*)fMCStack.push_back(); | 736 MCRec* newTop = (MCRec*)fMCStack.push_back(); |
772 new (newTop) MCRec(*fMCRec); // balanced in restore() | 737 new (newTop) MCRec(fMCRec); // balanced in restore() |
773 fMCRec = newTop; | 738 fMCRec = newTop; |
774 | 739 |
775 fClipStack.save(); | 740 fClipStack.save(); |
776 | 741 |
777 return saveCount; | 742 return saveCount; |
778 } | 743 } |
779 | 744 |
780 int SkCanvas::save() { | 745 int SkCanvas::save() { |
781 this->willSave(); | 746 this->willSave(); |
782 return this->internalSave(); | 747 return this->internalSave(); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 } | 859 } |
895 } else { | 860 } else { |
896 device = this->createLayerDevice(info); | 861 device = this->createLayerDevice(info); |
897 } | 862 } |
898 if (NULL == device) { | 863 if (NULL == device) { |
899 SkDebugf("Unable to create device for layer."); | 864 SkDebugf("Unable to create device for layer."); |
900 return count; | 865 return count; |
901 } | 866 } |
902 | 867 |
903 device->setOrigin(ir.fLeft, ir.fTop); | 868 device->setOrigin(ir.fLeft, ir.fTop); |
904 DeviceCM* layer = SkNEW_ARGS(DeviceCM, | 869 DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint, th
is)); |
905 (device, ir.fLeft, ir.fTop, paint, this, fConse
rvativeRasterClip)); | |
906 device->unref(); | 870 device->unref(); |
907 | 871 |
908 layer->fNext = fMCRec->fTopLayer; | 872 layer->fNext = fMCRec->fTopLayer; |
909 fMCRec->fLayer = layer; | 873 fMCRec->fLayer = layer; |
910 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer | 874 fMCRec->fTopLayer = layer; // this field is NOT an owner of layer |
911 | 875 |
912 fSaveLayerCount += 1; | 876 fSaveLayerCount += 1; |
913 return count; | 877 return count; |
914 } | 878 } |
915 | 879 |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1315 | 1279 |
1316 if (fMCRec->fMatrix.rectStaysRect()) { | 1280 if (fMCRec->fMatrix.rectStaysRect()) { |
1317 // for these simpler matrices, we can stay a rect even after applying | 1281 // for these simpler matrices, we can stay a rect even after applying |
1318 // the matrix. This means we don't have to a) make a path, and b) tell | 1282 // the matrix. This means we don't have to a) make a path, and b) tell |
1319 // the region code to scan-convert the path, only to discover that it | 1283 // the region code to scan-convert the path, only to discover that it |
1320 // is really just a rect. | 1284 // is really just a rect. |
1321 SkRect r; | 1285 SkRect r; |
1322 | 1286 |
1323 fMCRec->fMatrix.mapRect(&r, rect); | 1287 fMCRec->fMatrix.mapRect(&r, rect); |
1324 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); | 1288 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); |
1325 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeSt
yle == edgeStyle); | 1289 fMCRec->fRasterClip.op(r, op, kSoft_ClipEdgeStyle == edgeStyle); |
1326 } else { | 1290 } else { |
1327 // since we're rotated or some such thing, we convert the rect to a path | 1291 // since we're rotated or some such thing, we convert the rect to a path |
1328 // and clip against that, since it can handle any matrix. However, to | 1292 // and clip against that, since it can handle any matrix. However, to |
1329 // avoid recursion in the case where we are subclassed (e.g. Pictures) | 1293 // avoid recursion in the case where we are subclassed (e.g. Pictures) |
1330 // we explicitly call "our" version of clipPath. | 1294 // we explicitly call "our" version of clipPath. |
1331 SkPath path; | 1295 SkPath path; |
1332 | 1296 |
1333 path.addRect(rect); | 1297 path.addRect(rect); |
1334 this->SkCanvas::onClipPath(path, op, edgeStyle); | 1298 this->SkCanvas::onClipPath(path, op, edgeStyle); |
1335 } | 1299 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1450 if (element->isAA()) { | 1414 if (element->isAA()) { |
1451 edgeStyle = kSoft_ClipEdgeStyle; | 1415 edgeStyle = kSoft_ClipEdgeStyle; |
1452 } | 1416 } |
1453 } | 1417 } |
1454 op = SkRegion::kReplace_Op; | 1418 op = SkRegion::kReplace_Op; |
1455 } | 1419 } |
1456 | 1420 |
1457 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); | 1421 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); |
1458 } | 1422 } |
1459 | 1423 |
| 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 |
1460 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1500 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { |
1461 this->onClipRegion(rgn, op); | 1501 this->onClipRegion(rgn, op); |
1462 } | 1502 } |
1463 | 1503 |
1464 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1504 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { |
1465 AutoValidateClip avc(this); | 1505 AutoValidateClip avc(this); |
1466 | 1506 |
1467 fDeviceCMDirty = true; | 1507 fDeviceCMDirty = true; |
1468 fCachedLocalClipBoundsDirty = true; | 1508 fCachedLocalClipBoundsDirty = true; |
1469 | 1509 |
1470 // todo: signal fClipStack that we have a region, and therefore (I guess) | 1510 // todo: signal fClipStack that we have a region, and therefore (I guess) |
1471 // we have to ignore it, and use the region directly? | 1511 // we have to ignore it, and use the region directly? |
1472 fClipStack.clipDevRect(rgn.getBounds(), op); | 1512 fClipStack.clipDevRect(rgn.getBounds(), op); |
1473 | 1513 |
1474 fMCRec->fRasterClip.op(rgn, op); | 1514 fMCRec->fRasterClip.op(rgn, op); |
1475 } | 1515 } |
1476 | 1516 |
1477 #ifdef SK_DEBUG | 1517 #ifdef SK_DEBUG |
1478 void SkCanvas::validateClip() const { | 1518 void SkCanvas::validateClip() const { |
1479 // construct clipRgn from the clipstack | 1519 // construct clipRgn from the clipstack |
1480 const SkBaseDevice* device = this->getDevice(); | 1520 const SkBaseDevice* device = this->getDevice(); |
1481 if (!device) { | 1521 if (!device) { |
1482 SkASSERT(this->isClipEmpty()); | 1522 SkASSERT(this->isClipEmpty()); |
1483 return; | 1523 return; |
1484 } | 1524 } |
1485 | 1525 |
1486 SkIRect ir; | 1526 SkIRect ir; |
1487 ir.set(0, 0, device->width(), device->height()); | 1527 ir.set(0, 0, device->width(), device->height()); |
1488 SkRasterClip tmpClip(ir, fConservativeRasterClip); | 1528 SkRasterClip tmpClip(ir); |
1489 | 1529 |
1490 SkClipStack::B2TIter iter(fClipStack); | 1530 SkClipStack::B2TIter iter(fClipStack); |
1491 const SkClipStack::Element* element; | 1531 const SkClipStack::Element* element; |
1492 while ((element = iter.next()) != NULL) { | 1532 while ((element = iter.next()) != NULL) { |
1493 switch (element->getType()) { | 1533 switch (element->getType()) { |
1494 case SkClipStack::Element::kRect_Type: | 1534 case SkClipStack::Element::kRect_Type: |
1495 element->getRect().round(&ir); | 1535 element->getRect().round(&ir); |
1496 tmpClip.op(ir, element->getOp()); | 1536 tmpClip.op(ir, element->getOp()); |
1497 break; | 1537 break; |
1498 case SkClipStack::Element::kEmpty_Type: | 1538 case SkClipStack::Element::kEmpty_Type: |
(...skipping 23 matching lines...) Expand all Loading... |
1522 | 1562 |
1523 bool SkCanvas::isClipEmpty() const { | 1563 bool SkCanvas::isClipEmpty() const { |
1524 return fMCRec->fRasterClip.isEmpty(); | 1564 return fMCRec->fRasterClip.isEmpty(); |
1525 } | 1565 } |
1526 | 1566 |
1527 bool SkCanvas::isClipRect() const { | 1567 bool SkCanvas::isClipRect() const { |
1528 return fMCRec->fRasterClip.isRect(); | 1568 return fMCRec->fRasterClip.isRect(); |
1529 } | 1569 } |
1530 | 1570 |
1531 bool SkCanvas::quickReject(const SkRect& rect) const { | 1571 bool SkCanvas::quickReject(const SkRect& rect) const { |
| 1572 |
1532 if (!rect.isFinite()) | 1573 if (!rect.isFinite()) |
1533 return true; | 1574 return true; |
1534 | 1575 |
1535 if (fMCRec->fRasterClip.isEmpty()) { | 1576 if (fMCRec->fRasterClip.isEmpty()) { |
1536 return true; | 1577 return true; |
1537 } | 1578 } |
1538 | 1579 |
1539 if (fMCRec->fMatrix.hasPerspective()) { | 1580 if (fMCRec->fMatrix.hasPerspective()) { |
1540 SkRect dst; | 1581 SkRect dst; |
1541 fMCRec->fMatrix.mapRect(&dst, rect); | 1582 fMCRec->fMatrix.mapRect(&dst, rect); |
(...skipping 949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2491 } | 2532 } |
2492 | 2533 |
2493 if (matrix) { | 2534 if (matrix) { |
2494 canvas->concat(*matrix); | 2535 canvas->concat(*matrix); |
2495 } | 2536 } |
2496 } | 2537 } |
2497 | 2538 |
2498 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 2539 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
2499 fCanvas->restoreToCount(fSaveCount); | 2540 fCanvas->restoreToCount(fSaveCount); |
2500 } | 2541 } |
OLD | NEW |