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 #include "SkCanvas.h" | 8 #include "SkCanvas.h" |
9 #include "SkCanvasDrawable.h" | 9 #include "SkCanvasDrawable.h" |
10 #include "SkCanvasPriv.h" | 10 #include "SkCanvasPriv.h" |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 } | 225 } |
226 }; | 226 }; |
227 | 227 |
228 class SkDrawIter : public SkDraw { | 228 class SkDrawIter : public SkDraw { |
229 public: | 229 public: |
230 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { | 230 SkDrawIter(SkCanvas* canvas, bool skipEmptyClips = true) { |
231 canvas = canvas->canvasForDrawIter(); | 231 canvas = canvas->canvasForDrawIter(); |
232 fCanvas = canvas; | 232 fCanvas = canvas; |
233 canvas->updateDeviceCMCache(); | 233 canvas->updateDeviceCMCache(); |
234 | 234 |
235 fClipStack = &canvas->fClipStack; | 235 fClipStack = canvas->fClipStack.get(); |
236 fCurrLayer = canvas->fMCRec->fTopLayer; | 236 fCurrLayer = canvas->fMCRec->fTopLayer; |
237 fSkipEmptyClips = skipEmptyClips; | 237 fSkipEmptyClips = skipEmptyClips; |
238 } | 238 } |
239 | 239 |
240 bool next() { | 240 bool next() { |
241 // skip over recs with empty clips | 241 // skip over recs with empty clips |
242 if (fSkipEmptyClips) { | 242 if (fSkipEmptyClips) { |
243 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { | 243 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { |
244 fCurrLayer = fCurrLayer->fNext; | 244 fCurrLayer = fCurrLayer->fNext; |
245 } | 245 } |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 fMetaData = NULL; | 435 fMetaData = NULL; |
436 | 436 |
437 fMCRec = (MCRec*)fMCStack.push_back(); | 437 fMCRec = (MCRec*)fMCStack.push_back(); |
438 new (fMCRec) MCRec(fConservativeRasterClip); | 438 new (fMCRec) MCRec(fConservativeRasterClip); |
439 | 439 |
440 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservative
RasterClip)); | 440 fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservative
RasterClip)); |
441 fMCRec->fTopLayer = fMCRec->fLayer; | 441 fMCRec->fTopLayer = fMCRec->fLayer; |
442 | 442 |
443 fSurfaceBase = NULL; | 443 fSurfaceBase = NULL; |
444 | 444 |
| 445 fClipStack.reset(SkNEW(SkClipStack)); |
| 446 |
445 if (device) { | 447 if (device) { |
446 device->initForRootLayer(fProps.pixelGeometry()); | 448 device->initForRootLayer(fProps.pixelGeometry()); |
447 if (device->forceConservativeRasterClip()) { | 449 if (device->forceConservativeRasterClip()) { |
448 fConservativeRasterClip = true; | 450 fConservativeRasterClip = true; |
449 } | 451 } |
450 device->onAttachToCanvas(this); | 452 device->onAttachToCanvas(this); |
451 fMCRec->fLayer->fDevice = SkRef(device); | 453 fMCRec->fLayer->fDevice = SkRef(device); |
452 fMCRec->fRasterClip.setRect(device->getGlobalBounds()); | 454 fMCRec->fRasterClip.setRect(device->getGlobalBounds()); |
453 } | 455 } |
454 return device; | 456 return device; |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 | 783 |
782 ////////////////////////////////////////////////////////////////////////////// | 784 ////////////////////////////////////////////////////////////////////////////// |
783 | 785 |
784 void SkCanvas::updateDeviceCMCache() { | 786 void SkCanvas::updateDeviceCMCache() { |
785 if (fDeviceCMDirty) { | 787 if (fDeviceCMDirty) { |
786 const SkMatrix& totalMatrix = this->getTotalMatrix(); | 788 const SkMatrix& totalMatrix = this->getTotalMatrix(); |
787 const SkRasterClip& totalClip = fMCRec->fRasterClip; | 789 const SkRasterClip& totalClip = fMCRec->fRasterClip; |
788 DeviceCM* layer = fMCRec->fTopLayer; | 790 DeviceCM* layer = fMCRec->fTopLayer; |
789 | 791 |
790 if (NULL == layer->fNext) { // only one layer | 792 if (NULL == layer->fNext) { // only one layer |
791 layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); | 793 layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL); |
792 } else { | 794 } else { |
793 SkRasterClip clip(totalClip); | 795 SkRasterClip clip(totalClip); |
794 do { | 796 do { |
795 layer->updateMC(totalMatrix, clip, fClipStack, &clip); | 797 layer->updateMC(totalMatrix, clip, *fClipStack, &clip); |
796 } while ((layer = layer->fNext) != NULL); | 798 } while ((layer = layer->fNext) != NULL); |
797 } | 799 } |
798 fDeviceCMDirty = false; | 800 fDeviceCMDirty = false; |
799 } | 801 } |
800 } | 802 } |
801 | 803 |
802 /////////////////////////////////////////////////////////////////////////////// | 804 /////////////////////////////////////////////////////////////////////////////// |
803 | 805 |
804 void SkCanvas::checkForDeferredSave() { | 806 void SkCanvas::checkForDeferredSave() { |
805 if (fMCRec->fDeferredSaveCount > 0) { | 807 if (fMCRec->fDeferredSaveCount > 0) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
862 for (int i = 0; i < n; ++i) { | 864 for (int i = 0; i < n; ++i) { |
863 this->restore(); | 865 this->restore(); |
864 } | 866 } |
865 } | 867 } |
866 | 868 |
867 void SkCanvas::internalSave() { | 869 void SkCanvas::internalSave() { |
868 MCRec* newTop = (MCRec*)fMCStack.push_back(); | 870 MCRec* newTop = (MCRec*)fMCStack.push_back(); |
869 new (newTop) MCRec(*fMCRec); // balanced in restore() | 871 new (newTop) MCRec(*fMCRec); // balanced in restore() |
870 fMCRec = newTop; | 872 fMCRec = newTop; |
871 | 873 |
872 fClipStack.save(); | 874 fClipStack->save(); |
873 } | 875 } |
874 | 876 |
875 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { | 877 static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { |
876 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG | 878 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG |
877 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; | 879 return (flags & SkCanvas::kClipToLayer_SaveFlag) != 0; |
878 #else | 880 #else |
879 return true; | 881 return true; |
880 #endif | 882 #endif |
881 } | 883 } |
882 | 884 |
(...skipping 21 matching lines...) Expand all Loading... |
904 if (bounds_affects_clip(flags)) { | 906 if (bounds_affects_clip(flags)) { |
905 fMCRec->fRasterClip.setEmpty(); | 907 fMCRec->fRasterClip.setEmpty(); |
906 } | 908 } |
907 return false; | 909 return false; |
908 } | 910 } |
909 } else { // no user bounds, so just use the clip | 911 } else { // no user bounds, so just use the clip |
910 ir = clipBounds; | 912 ir = clipBounds; |
911 } | 913 } |
912 | 914 |
913 if (bounds_affects_clip(flags)) { | 915 if (bounds_affects_clip(flags)) { |
914 fClipStack.clipDevRect(ir, op); | 916 fClipStack->clipDevRect(ir, op); |
915 // early exit if the clip is now empty | 917 // early exit if the clip is now empty |
916 if (!fMCRec->fRasterClip.op(ir, op)) { | 918 if (!fMCRec->fRasterClip.op(ir, op)) { |
917 return false; | 919 return false; |
918 } | 920 } |
919 } | 921 } |
920 | 922 |
921 if (intersection) { | 923 if (intersection) { |
922 *intersection = ir; | 924 *intersection = ir; |
923 } | 925 } |
924 return true; | 926 return true; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 return this->saveLayer(bounds, &tmpPaint, flags); | 1028 return this->saveLayer(bounds, &tmpPaint, flags); |
1027 } | 1029 } |
1028 } | 1030 } |
1029 | 1031 |
1030 void SkCanvas::internalRestore() { | 1032 void SkCanvas::internalRestore() { |
1031 SkASSERT(fMCStack.count() != 0); | 1033 SkASSERT(fMCStack.count() != 0); |
1032 | 1034 |
1033 fDeviceCMDirty = true; | 1035 fDeviceCMDirty = true; |
1034 fCachedLocalClipBoundsDirty = true; | 1036 fCachedLocalClipBoundsDirty = true; |
1035 | 1037 |
1036 fClipStack.restore(); | 1038 fClipStack->restore(); |
1037 | 1039 |
1038 // reserve our layer (if any) | 1040 // reserve our layer (if any) |
1039 DeviceCM* layer = fMCRec->fLayer; // may be null | 1041 DeviceCM* layer = fMCRec->fLayer; // may be null |
1040 // now detach it from fMCRec so we can pop(). Gets freed after its drawn | 1042 // now detach it from fMCRec so we can pop(). Gets freed after its drawn |
1041 fMCRec->fLayer = NULL; | 1043 fMCRec->fLayer = NULL; |
1042 | 1044 |
1043 // now do the normal restore() | 1045 // now do the normal restore() |
1044 fMCRec->~MCRec(); // balanced in save() | 1046 fMCRec->~MCRec(); // balanced in save() |
1045 fMCStack.pop_back(); | 1047 fMCStack.pop_back(); |
1046 fMCRec = (MCRec*)fMCStack.back(); | 1048 fMCRec = (MCRec*)fMCStack.back(); |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 } | 1333 } |
1332 | 1334 |
1333 if (fMCRec->fMatrix.rectStaysRect()) { | 1335 if (fMCRec->fMatrix.rectStaysRect()) { |
1334 // for these simpler matrices, we can stay a rect even after applying | 1336 // for these simpler matrices, we can stay a rect even after applying |
1335 // the matrix. This means we don't have to a) make a path, and b) tell | 1337 // the matrix. This means we don't have to a) make a path, and b) tell |
1336 // the region code to scan-convert the path, only to discover that it | 1338 // the region code to scan-convert the path, only to discover that it |
1337 // is really just a rect. | 1339 // is really just a rect. |
1338 SkRect r; | 1340 SkRect r; |
1339 | 1341 |
1340 fMCRec->fMatrix.mapRect(&r, rect); | 1342 fMCRec->fMatrix.mapRect(&r, rect); |
1341 fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); | 1343 fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); |
1342 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeSt
yle == edgeStyle); | 1344 fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeSt
yle == edgeStyle); |
1343 } else { | 1345 } else { |
1344 // since we're rotated or some such thing, we convert the rect to a path | 1346 // since we're rotated or some such thing, we convert the rect to a path |
1345 // and clip against that, since it can handle any matrix. However, to | 1347 // and clip against that, since it can handle any matrix. However, to |
1346 // avoid recursion in the case where we are subclassed (e.g. Pictures) | 1348 // avoid recursion in the case where we are subclassed (e.g. Pictures) |
1347 // we explicitly call "our" version of clipPath. | 1349 // we explicitly call "our" version of clipPath. |
1348 SkPath path; | 1350 SkPath path; |
1349 | 1351 |
1350 path.addRect(rect); | 1352 path.addRect(rect); |
1351 this->SkCanvas::onClipPath(path, op, edgeStyle); | 1353 this->SkCanvas::onClipPath(path, op, edgeStyle); |
(...skipping 19 matching lines...) Expand all Loading... |
1371 SkRRect transformedRRect; | 1373 SkRRect transformedRRect; |
1372 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { | 1374 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { |
1373 AutoValidateClip avc(this); | 1375 AutoValidateClip avc(this); |
1374 | 1376 |
1375 fDeviceCMDirty = true; | 1377 fDeviceCMDirty = true; |
1376 fCachedLocalClipBoundsDirty = true; | 1378 fCachedLocalClipBoundsDirty = true; |
1377 if (!fAllowSoftClip) { | 1379 if (!fAllowSoftClip) { |
1378 edgeStyle = kHard_ClipEdgeStyle; | 1380 edgeStyle = kHard_ClipEdgeStyle; |
1379 } | 1381 } |
1380 | 1382 |
1381 fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edg
eStyle); | 1383 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == ed
geStyle); |
1382 | 1384 |
1383 SkPath devPath; | 1385 SkPath devPath; |
1384 devPath.addRRect(transformedRRect); | 1386 devPath.addRRect(transformedRRect); |
1385 | 1387 |
1386 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeS
tyle == edgeStyle); | 1388 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, kSoft_ClipEdgeS
tyle == edgeStyle); |
1387 return; | 1389 return; |
1388 } | 1390 } |
1389 | 1391 |
1390 SkPath path; | 1392 SkPath path; |
1391 path.addRRect(rrect); | 1393 path.addRRect(rrect); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1436 // made us empty. Note this can also happen if we contained NaN | 1438 // made us empty. Note this can also happen if we contained NaN |
1437 // values. computing the bounds detects this, and will set our | 1439 // values. computing the bounds detects this, and will set our |
1438 // bounds to empty if that is the case. (see SkRect::set(pts, count)) | 1440 // bounds to empty if that is the case. (see SkRect::set(pts, count)) |
1439 if (devPath.getBounds().isEmpty()) { | 1441 if (devPath.getBounds().isEmpty()) { |
1440 // resetting the path will remove any NaN or other wanky values | 1442 // resetting the path will remove any NaN or other wanky values |
1441 // that might upset our scan converter. | 1443 // that might upset our scan converter. |
1442 devPath.reset(); | 1444 devPath.reset(); |
1443 } | 1445 } |
1444 | 1446 |
1445 // if we called path.swap() we could avoid a deep copy of this path | 1447 // if we called path.swap() we could avoid a deep copy of this path |
1446 fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); | 1448 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); |
1447 | 1449 |
1448 if (fAllowSimplifyClip) { | 1450 if (fAllowSimplifyClip) { |
1449 bool clipIsAA = getClipStack()->asPath(&devPath); | 1451 bool clipIsAA = getClipStack()->asPath(&devPath); |
1450 if (clipIsAA) { | 1452 if (clipIsAA) { |
1451 edgeStyle = kSoft_ClipEdgeStyle; | 1453 edgeStyle = kSoft_ClipEdgeStyle; |
1452 } | 1454 } |
1453 | 1455 |
1454 op = SkRegion::kReplace_Op; | 1456 op = SkRegion::kReplace_Op; |
1455 } | 1457 } |
1456 | 1458 |
1457 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); | 1459 rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle); |
1458 } | 1460 } |
1459 | 1461 |
1460 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1462 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { |
1461 this->checkForDeferredSave(); | 1463 this->checkForDeferredSave(); |
1462 this->onClipRegion(rgn, op); | 1464 this->onClipRegion(rgn, op); |
1463 } | 1465 } |
1464 | 1466 |
1465 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1467 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { |
1466 AutoValidateClip avc(this); | 1468 AutoValidateClip avc(this); |
1467 | 1469 |
1468 fDeviceCMDirty = true; | 1470 fDeviceCMDirty = true; |
1469 fCachedLocalClipBoundsDirty = true; | 1471 fCachedLocalClipBoundsDirty = true; |
1470 | 1472 |
1471 // todo: signal fClipStack that we have a region, and therefore (I guess) | 1473 // todo: signal fClipStack that we have a region, and therefore (I guess) |
1472 // we have to ignore it, and use the region directly? | 1474 // we have to ignore it, and use the region directly? |
1473 fClipStack.clipDevRect(rgn.getBounds(), op); | 1475 fClipStack->clipDevRect(rgn.getBounds(), op); |
1474 | 1476 |
1475 fMCRec->fRasterClip.op(rgn, op); | 1477 fMCRec->fRasterClip.op(rgn, op); |
1476 } | 1478 } |
1477 | 1479 |
1478 #ifdef SK_DEBUG | 1480 #ifdef SK_DEBUG |
1479 void SkCanvas::validateClip() const { | 1481 void SkCanvas::validateClip() const { |
1480 // construct clipRgn from the clipstack | 1482 // construct clipRgn from the clipstack |
1481 const SkBaseDevice* device = this->getDevice(); | 1483 const SkBaseDevice* device = this->getDevice(); |
1482 if (!device) { | 1484 if (!device) { |
1483 SkASSERT(this->isClipEmpty()); | 1485 SkASSERT(this->isClipEmpty()); |
1484 return; | 1486 return; |
1485 } | 1487 } |
1486 | 1488 |
1487 SkIRect ir; | 1489 SkIRect ir; |
1488 ir.set(0, 0, device->width(), device->height()); | 1490 ir.set(0, 0, device->width(), device->height()); |
1489 SkRasterClip tmpClip(ir, fConservativeRasterClip); | 1491 SkRasterClip tmpClip(ir, fConservativeRasterClip); |
1490 | 1492 |
1491 SkClipStack::B2TIter iter(fClipStack); | 1493 SkClipStack::B2TIter iter(*fClipStack); |
1492 const SkClipStack::Element* element; | 1494 const SkClipStack::Element* element; |
1493 while ((element = iter.next()) != NULL) { | 1495 while ((element = iter.next()) != NULL) { |
1494 switch (element->getType()) { | 1496 switch (element->getType()) { |
1495 case SkClipStack::Element::kRect_Type: | 1497 case SkClipStack::Element::kRect_Type: |
1496 element->getRect().round(&ir); | 1498 element->getRect().round(&ir); |
1497 tmpClip.op(ir, element->getOp()); | 1499 tmpClip.op(ir, element->getOp()); |
1498 break; | 1500 break; |
1499 case SkClipStack::Element::kEmpty_Type: | 1501 case SkClipStack::Element::kEmpty_Type: |
1500 tmpClip.setEmpty(); | 1502 tmpClip.setEmpty(); |
1501 break; | 1503 break; |
1502 default: { | 1504 default: { |
1503 SkPath path; | 1505 SkPath path; |
1504 element->asPath(&path); | 1506 element->asPath(&path); |
1505 rasterclip_path(&tmpClip, this, path, element->getOp(), element-
>isAA()); | 1507 rasterclip_path(&tmpClip, this, path, element->getOp(), element-
>isAA()); |
1506 break; | 1508 break; |
1507 } | 1509 } |
1508 } | 1510 } |
1509 } | 1511 } |
1510 } | 1512 } |
1511 #endif | 1513 #endif |
1512 | 1514 |
1513 void SkCanvas::replayClips(ClipVisitor* visitor) const { | 1515 void SkCanvas::replayClips(ClipVisitor* visitor) const { |
1514 SkClipStack::B2TIter iter(fClipStack); | 1516 SkClipStack::B2TIter iter(*fClipStack); |
1515 const SkClipStack::Element* element; | 1517 const SkClipStack::Element* element; |
1516 | 1518 |
1517 while ((element = iter.next()) != NULL) { | 1519 while ((element = iter.next()) != NULL) { |
1518 element->replay(visitor); | 1520 element->replay(visitor); |
1519 } | 1521 } |
1520 } | 1522 } |
1521 | 1523 |
1522 /////////////////////////////////////////////////////////////////////////////// | 1524 /////////////////////////////////////////////////////////////////////////////// |
1523 | 1525 |
1524 bool SkCanvas::isClipEmpty() const { | 1526 bool SkCanvas::isClipEmpty() const { |
(...skipping 1032 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2557 } | 2559 } |
2558 | 2560 |
2559 if (matrix) { | 2561 if (matrix) { |
2560 canvas->concat(*matrix); | 2562 canvas->concat(*matrix); |
2561 } | 2563 } |
2562 } | 2564 } |
2563 | 2565 |
2564 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 2566 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
2565 fCanvas->restoreToCount(fSaveCount); | 2567 fCanvas->restoreToCount(fSaveCount); |
2566 } | 2568 } |
OLD | NEW |