| 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 |