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 "SkBitmapDevice.h" | 8 #include "SkBitmapDevice.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkCanvasPriv.h" | 10 #include "SkCanvasPriv.h" |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 | 335 |
336 ~SkDrawIter() { | 336 ~SkDrawIter() { |
337 if (fMultiDeviceCS) { | 337 if (fMultiDeviceCS) { |
338 fMultiDeviceCS->restore(); | 338 fMultiDeviceCS->restore(); |
339 } | 339 } |
340 } | 340 } |
341 | 341 |
342 bool next() { | 342 bool next() { |
343 if (fMultiDeviceCS && fDevice) { | 343 if (fMultiDeviceCS && fDevice) { |
344 // remove the previous device's bounds | 344 // remove the previous device's bounds |
345 fMultiDeviceCS->clipDevRect(compute_device_bounds(fDevice), | 345 fMultiDeviceCS->clipDevRect(compute_device_bounds(fDevice), SkCanvas
::kDifference_Op); |
346 SkRegion::kDifference_Op); | |
347 } | 346 } |
348 | 347 |
349 // skip over recs with empty clips | 348 // skip over recs with empty clips |
350 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { | 349 while (fCurrLayer && fCurrLayer->fClip.isEmpty()) { |
351 fCurrLayer = fCurrLayer->fNext; | 350 fCurrLayer = fCurrLayer->fNext; |
352 } | 351 } |
353 | 352 |
354 const DeviceCM* rec = fCurrLayer; | 353 const DeviceCM* rec = fCurrLayer; |
355 if (rec && rec->fDevice) { | 354 if (rec && rec->fDevice) { |
356 | 355 |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 } | 1100 } |
1102 return false; | 1101 return false; |
1103 } | 1102 } |
1104 } else { // no user bounds, so just use the clip | 1103 } else { // no user bounds, so just use the clip |
1105 ir = clipBounds; | 1104 ir = clipBounds; |
1106 } | 1105 } |
1107 SkASSERT(!ir.isEmpty()); | 1106 SkASSERT(!ir.isEmpty()); |
1108 | 1107 |
1109 if (BoundsAffectsClip(saveLayerFlags)) { | 1108 if (BoundsAffectsClip(saveLayerFlags)) { |
1110 // Simplify the current clips since they will be applied properly during
restore() | 1109 // Simplify the current clips since they will be applied properly during
restore() |
1111 fClipStack->clipDevRect(ir, SkRegion::kReplace_Op); | 1110 fClipStack->clipDevRect(ir, kReplace_Op); |
1112 fMCRec->fRasterClip.setRect(ir); | 1111 fMCRec->fRasterClip.setRect(ir); |
1113 fDeviceClipBounds = qr_clip_bounds(ir); | 1112 fDeviceClipBounds = qr_clip_bounds(ir); |
1114 } | 1113 } |
1115 | 1114 |
1116 if (intersection) { | 1115 if (intersection) { |
1117 *intersection = ir; | 1116 *intersection = ir; |
1118 } | 1117 } |
1119 return true; | 1118 return true; |
1120 } | 1119 } |
1121 | 1120 |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1533 this->fLights = lights; | 1532 this->fLights = lights; |
1534 } | 1533 } |
1535 | 1534 |
1536 sk_sp<SkLights> SkCanvas::getLights() const { | 1535 sk_sp<SkLights> SkCanvas::getLights() const { |
1537 return this->fLights; | 1536 return this->fLights; |
1538 } | 1537 } |
1539 #endif | 1538 #endif |
1540 | 1539 |
1541 ////////////////////////////////////////////////////////////////////////////// | 1540 ////////////////////////////////////////////////////////////////////////////// |
1542 | 1541 |
1543 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) { | 1542 void SkCanvas::clipRect(const SkRect& rect, ClipOp op, bool doAA) { |
1544 if (!fAllowSoftClip) { | 1543 if (!fAllowSoftClip) { |
1545 doAA = false; | 1544 doAA = false; |
1546 } | 1545 } |
1547 | 1546 |
1548 this->checkForDeferredSave(); | 1547 this->checkForDeferredSave(); |
1549 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; | 1548 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; |
1550 this->onClipRect(rect, op, edgeStyle); | 1549 this->onClipRect(rect, op, edgeStyle); |
1551 } | 1550 } |
1552 | 1551 |
1553 void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edg
eStyle) { | 1552 void SkCanvas::onClipRect(const SkRect& rect, ClipOp op, ClipEdgeStyle edgeStyle
) { |
1554 const bool isScaleTrans = fMCRec->fMatrix.isScaleTranslate(); | 1553 const bool isScaleTrans = fMCRec->fMatrix.isScaleTranslate(); |
1555 SkRect devR; | 1554 SkRect devR; |
1556 if (isScaleTrans) { | 1555 if (isScaleTrans) { |
1557 fMCRec->fMatrix.mapRectScaleTranslate(&devR, rect); | 1556 fMCRec->fMatrix.mapRectScaleTranslate(&devR, rect); |
1558 } | 1557 } |
1559 | 1558 |
1560 if (SkRegion::kIntersect_Op == op && | 1559 if (kIntersect_Op == op && kHard_ClipEdgeStyle == edgeStyle && isScaleTrans)
{ |
1561 kHard_ClipEdgeStyle == edgeStyle | |
1562 && isScaleTrans) | |
1563 { | |
1564 if (devR.round().contains(fMCRec->fRasterClip.getBounds())) { | 1560 if (devR.round().contains(fMCRec->fRasterClip.getBounds())) { |
1565 #if 0 | 1561 #if 0 |
1566 SkDebugf("------- ignored clipRect [%g %g %g %g]\n", | 1562 SkDebugf("------- ignored clipRect [%g %g %g %g]\n", |
1567 rect.left(), rect.top(), rect.right(), rect.bottom()); | 1563 rect.left(), rect.top(), rect.right(), rect.bottom()); |
1568 #endif | 1564 #endif |
1569 return; | 1565 return; |
1570 } | 1566 } |
1571 } | 1567 } |
1572 | 1568 |
1573 AutoValidateClip avc(this); | 1569 AutoValidateClip avc(this); |
1574 | 1570 |
1575 fDeviceCMDirty = true; | 1571 fDeviceCMDirty = true; |
1576 | 1572 |
1577 if (isScaleTrans) { | 1573 if (isScaleTrans) { |
1578 const bool isAA = kSoft_ClipEdgeStyle == edgeStyle; | 1574 const bool isAA = kSoft_ClipEdgeStyle == edgeStyle; |
1579 fClipStack->clipDevRect(devR, op, isAA); | 1575 fClipStack->clipDevRect(devR, op, isAA); |
1580 fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), op, isAA); | 1576 fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), (SkRegion::Op)op
, isAA); |
1581 } else { | 1577 } else { |
1582 // since we're rotated or some such thing, we convert the rect to a path | 1578 // since we're rotated or some such thing, we convert the rect to a path |
1583 // and clip against that, since it can handle any matrix. However, to | 1579 // and clip against that, since it can handle any matrix. However, to |
1584 // avoid recursion in the case where we are subclassed (e.g. Pictures) | 1580 // avoid recursion in the case where we are subclassed (e.g. Pictures) |
1585 // we explicitly call "our" version of clipPath. | 1581 // we explicitly call "our" version of clipPath. |
1586 SkPath path; | 1582 SkPath path; |
1587 | 1583 |
1588 path.addRect(rect); | 1584 path.addRect(rect); |
1589 path.setIsVolatile(true); | 1585 path.setIsVolatile(true); |
1590 this->SkCanvas::onClipPath(path, op, edgeStyle); | 1586 this->SkCanvas::onClipPath(path, op, edgeStyle); |
1591 } | 1587 } |
1592 | 1588 |
1593 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); | 1589 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); |
1594 } | 1590 } |
1595 | 1591 |
1596 void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) { | 1592 void SkCanvas::clipRRect(const SkRRect& rrect, ClipOp op, bool doAA) { |
1597 this->checkForDeferredSave(); | 1593 this->checkForDeferredSave(); |
1598 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; | 1594 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; |
1599 if (rrect.isRect()) { | 1595 if (rrect.isRect()) { |
1600 this->onClipRect(rrect.getBounds(), op, edgeStyle); | 1596 this->onClipRect(rrect.getBounds(), op, edgeStyle); |
1601 } else { | 1597 } else { |
1602 this->onClipRRect(rrect, op, edgeStyle); | 1598 this->onClipRRect(rrect, op, edgeStyle); |
1603 } | 1599 } |
1604 } | 1600 } |
1605 | 1601 |
1606 void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle
edgeStyle) { | 1602 void SkCanvas::onClipRRect(const SkRRect& rrect, ClipOp op, ClipEdgeStyle edgeSt
yle) { |
1607 SkRRect transformedRRect; | 1603 SkRRect transformedRRect; |
1608 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { | 1604 if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) { |
1609 AutoValidateClip avc(this); | 1605 AutoValidateClip avc(this); |
1610 | 1606 |
1611 fDeviceCMDirty = true; | 1607 fDeviceCMDirty = true; |
1612 if (!fAllowSoftClip) { | 1608 if (!fAllowSoftClip) { |
1613 edgeStyle = kHard_ClipEdgeStyle; | 1609 edgeStyle = kHard_ClipEdgeStyle; |
1614 } | 1610 } |
1615 | 1611 |
1616 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == ed
geStyle); | 1612 fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == ed
geStyle); |
1617 | 1613 |
1618 fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), op, | 1614 fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), (SkR
egion::Op)op, |
1619 kSoft_ClipEdgeStyle == edgeStyle); | 1615 kSoft_ClipEdgeStyle == edgeStyle); |
1620 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); | 1616 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); |
1621 return; | 1617 return; |
1622 } | 1618 } |
1623 | 1619 |
1624 SkPath path; | 1620 SkPath path; |
1625 path.addRRect(rrect); | 1621 path.addRRect(rrect); |
1626 path.setIsVolatile(true); | 1622 path.setIsVolatile(true); |
1627 // call the non-virtual version | 1623 // call the non-virtual version |
1628 this->SkCanvas::onClipPath(path, op, edgeStyle); | 1624 this->SkCanvas::onClipPath(path, op, edgeStyle); |
1629 } | 1625 } |
1630 | 1626 |
1631 void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) { | 1627 void SkCanvas::clipPath(const SkPath& path, ClipOp op, bool doAA) { |
1632 this->checkForDeferredSave(); | 1628 this->checkForDeferredSave(); |
1633 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; | 1629 ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle; |
1634 | 1630 |
1635 if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) { | 1631 if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) { |
1636 SkRect r; | 1632 SkRect r; |
1637 if (path.isRect(&r)) { | 1633 if (path.isRect(&r)) { |
1638 this->onClipRect(r, op, edgeStyle); | 1634 this->onClipRect(r, op, edgeStyle); |
1639 return; | 1635 return; |
1640 } | 1636 } |
1641 SkRRect rrect; | 1637 SkRRect rrect; |
1642 if (path.isOval(&r)) { | 1638 if (path.isOval(&r)) { |
1643 rrect.setOval(r); | 1639 rrect.setOval(r); |
1644 this->onClipRRect(rrect, op, edgeStyle); | 1640 this->onClipRRect(rrect, op, edgeStyle); |
1645 return; | 1641 return; |
1646 } | 1642 } |
1647 if (path.isRRect(&rrect)) { | 1643 if (path.isRRect(&rrect)) { |
1648 this->onClipRRect(rrect, op, edgeStyle); | 1644 this->onClipRRect(rrect, op, edgeStyle); |
1649 return; | 1645 return; |
1650 } | 1646 } |
1651 } | 1647 } |
1652 | 1648 |
1653 this->onClipPath(path, op, edgeStyle); | 1649 this->onClipPath(path, op, edgeStyle); |
1654 } | 1650 } |
1655 | 1651 |
1656 void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg
eStyle) { | 1652 void SkCanvas::onClipPath(const SkPath& path, ClipOp op, ClipEdgeStyle edgeStyle
) { |
1657 AutoValidateClip avc(this); | 1653 AutoValidateClip avc(this); |
1658 | 1654 |
1659 fDeviceCMDirty = true; | 1655 fDeviceCMDirty = true; |
1660 if (!fAllowSoftClip) { | 1656 if (!fAllowSoftClip) { |
1661 edgeStyle = kHard_ClipEdgeStyle; | 1657 edgeStyle = kHard_ClipEdgeStyle; |
1662 } | 1658 } |
1663 | 1659 |
1664 SkPath devPath; | 1660 SkPath devPath; |
1665 if (fMCRec->fMatrix.isIdentity()) { | 1661 if (fMCRec->fMatrix.isIdentity()) { |
1666 devPath = path; | 1662 devPath = path; |
(...skipping 14 matching lines...) Expand all Loading... |
1681 | 1677 |
1682 // if we called path.swap() we could avoid a deep copy of this path | 1678 // if we called path.swap() we could avoid a deep copy of this path |
1683 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); | 1679 fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); |
1684 | 1680 |
1685 if (fAllowSimplifyClip) { | 1681 if (fAllowSimplifyClip) { |
1686 bool clipIsAA = getClipStack()->asPath(&devPath); | 1682 bool clipIsAA = getClipStack()->asPath(&devPath); |
1687 if (clipIsAA) { | 1683 if (clipIsAA) { |
1688 edgeStyle = kSoft_ClipEdgeStyle; | 1684 edgeStyle = kSoft_ClipEdgeStyle; |
1689 } | 1685 } |
1690 | 1686 |
1691 op = SkRegion::kReplace_Op; | 1687 op = kReplace_Op; |
1692 } | 1688 } |
1693 | 1689 |
1694 fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), op, edgeStyle); | 1690 fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), (SkRegion::Op)op,
edgeStyle); |
1695 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); | 1691 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); |
1696 } | 1692 } |
1697 | 1693 |
1698 void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1694 void SkCanvas::clipRegion(const SkRegion& rgn, ClipOp op) { |
1699 this->checkForDeferredSave(); | 1695 this->checkForDeferredSave(); |
1700 this->onClipRegion(rgn, op); | 1696 this->onClipRegion(rgn, op); |
1701 } | 1697 } |
1702 | 1698 |
1703 void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { | 1699 void SkCanvas::onClipRegion(const SkRegion& rgn, ClipOp op) { |
1704 AutoValidateClip avc(this); | 1700 AutoValidateClip avc(this); |
1705 | 1701 |
1706 fDeviceCMDirty = true; | 1702 fDeviceCMDirty = true; |
1707 | 1703 |
1708 // todo: signal fClipStack that we have a region, and therefore (I guess) | 1704 // todo: signal fClipStack that we have a region, and therefore (I guess) |
1709 // we have to ignore it, and use the region directly? | 1705 // we have to ignore it, and use the region directly? |
1710 fClipStack->clipDevRect(rgn.getBounds(), op); | 1706 fClipStack->clipDevRect(rgn.getBounds(), op); |
1711 | 1707 |
1712 fMCRec->fRasterClip.op(rgn, op); | 1708 fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op); |
1713 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); | 1709 fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds()); |
1714 } | 1710 } |
1715 | 1711 |
1716 #ifdef SK_DEBUG | 1712 #ifdef SK_DEBUG |
1717 void SkCanvas::validateClip() const { | 1713 void SkCanvas::validateClip() const { |
1718 // construct clipRgn from the clipstack | 1714 // construct clipRgn from the clipstack |
1719 const SkBaseDevice* device = this->getDevice(); | 1715 const SkBaseDevice* device = this->getDevice(); |
1720 if (!device) { | 1716 if (!device) { |
1721 SkASSERT(this->isClipEmpty()); | 1717 SkASSERT(this->isClipEmpty()); |
1722 return; | 1718 return; |
1723 } | 1719 } |
1724 | 1720 |
1725 SkIRect ir; | 1721 SkIRect ir; |
1726 ir.set(0, 0, device->width(), device->height()); | 1722 ir.set(0, 0, device->width(), device->height()); |
1727 SkRasterClip tmpClip(ir, fConservativeRasterClip); | 1723 SkRasterClip tmpClip(ir, fConservativeRasterClip); |
1728 | 1724 |
1729 SkClipStack::B2TIter iter(*fClipStack); | 1725 SkClipStack::B2TIter iter(*fClipStack); |
1730 const SkClipStack::Element* element; | 1726 const SkClipStack::Element* element; |
1731 while ((element = iter.next()) != nullptr) { | 1727 while ((element = iter.next()) != nullptr) { |
1732 switch (element->getType()) { | 1728 switch (element->getType()) { |
1733 case SkClipStack::Element::kRect_Type: | 1729 case SkClipStack::Element::kRect_Type: |
1734 element->getRect().round(&ir); | 1730 element->getRect().round(&ir); |
1735 tmpClip.op(ir, element->getOp()); | 1731 tmpClip.op(ir, (SkRegion::Op)element->getOp()); |
1736 break; | 1732 break; |
1737 case SkClipStack::Element::kEmpty_Type: | 1733 case SkClipStack::Element::kEmpty_Type: |
1738 tmpClip.setEmpty(); | 1734 tmpClip.setEmpty(); |
1739 break; | 1735 break; |
1740 default: { | 1736 default: { |
1741 SkPath path; | 1737 SkPath path; |
1742 element->asPath(&path); | 1738 element->asPath(&path); |
1743 tmpClip.op(path, this->getTopLayerBounds(), element->getOp(), el
ement->isAA()); | 1739 tmpClip.op(path, this->getTopLayerBounds(), (SkRegion::Op)elemen
t->getOp(), |
| 1740 element->isAA()); |
1744 break; | 1741 break; |
1745 } | 1742 } |
1746 } | 1743 } |
1747 } | 1744 } |
1748 } | 1745 } |
1749 #endif | 1746 #endif |
1750 | 1747 |
1751 void SkCanvas::replayClips(ClipVisitor* visitor) const { | 1748 void SkCanvas::replayClips(ClipVisitor* visitor) const { |
1752 SkClipStack::B2TIter iter(*fClipStack); | 1749 SkClipStack::B2TIter iter(*fClipStack); |
1753 const SkClipStack::Element* element; | 1750 const SkClipStack::Element* element; |
(...skipping 1690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3444 | 3441 |
3445 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { | 3442 SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() { |
3446 fCanvas->restoreToCount(fSaveCount); | 3443 fCanvas->restoreToCount(fSaveCount); |
3447 } | 3444 } |
3448 | 3445 |
3449 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API | 3446 #ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API |
3450 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p
rops) { | 3447 SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* p
rops) { |
3451 return this->makeSurface(info, props).release(); | 3448 return this->makeSurface(info, props).release(); |
3452 } | 3449 } |
3453 #endif | 3450 #endif |
| 3451 |
| 3452 ///////////////////////////////// |
| 3453 |
| 3454 const SkCanvas::ClipOp SkCanvas::kDifference_Op; |
| 3455 const SkCanvas::ClipOp SkCanvas::kIntersect_Op; |
| 3456 const SkCanvas::ClipOp SkCanvas::kUnion_Op; |
| 3457 const SkCanvas::ClipOp SkCanvas::kXOR_Op; |
| 3458 const SkCanvas::ClipOp SkCanvas::kReverseDifference_Op; |
| 3459 const SkCanvas::ClipOp SkCanvas::kReplace_Op; |
| 3460 |
| 3461 static_assert((int)SkRegion::kDifference_Op == (int)kDifference_SkClipOp
, ""); |
| 3462 static_assert((int)SkRegion::kIntersect_Op == (int)kIntersect_SkClipOp,
""); |
| 3463 static_assert((int)SkRegion::kUnion_Op == (int)kUnion_SkClipOp, "")
; |
| 3464 static_assert((int)SkRegion::kXOR_Op == (int)kXOR_SkClipOp, ""); |
| 3465 static_assert((int)SkRegion::kReverseDifference_Op == (int)kReverseDifference_S
kClipOp, ""); |
| 3466 static_assert((int)SkRegion::kReplace_Op == (int)kReplace_SkClipOp, "
"); |
OLD | NEW |