| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 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 "SkPDFDevice.h" | 8 #include "SkPDFDevice.h" |
| 9 #include "SkAnnotationKeys.h" | 9 #include "SkAnnotationKeys.h" |
| 10 #include "SkBitmapDevice.h" | 10 #include "SkBitmapDevice.h" |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 * devices have rectangular shape. | 620 * devices have rectangular shape. |
| 621 */ | 621 */ |
| 622 void setShape(const SkPath& shape) { | 622 void setShape(const SkPath& shape) { |
| 623 fShape = shape; | 623 fShape = shape; |
| 624 } | 624 } |
| 625 | 625 |
| 626 private: | 626 private: |
| 627 SkPDFDevice* fDevice; | 627 SkPDFDevice* fDevice; |
| 628 SkPDFDevice::ContentEntry* fContentEntry; | 628 SkPDFDevice::ContentEntry* fContentEntry; |
| 629 SkXfermode::Mode fXfermode; | 629 SkXfermode::Mode fXfermode; |
| 630 SkPDFFormXObject* fDstFormXObject; | 630 SkPDFObject* fDstFormXObject; |
| 631 SkPath fShape; | 631 SkPath fShape; |
| 632 | 632 |
| 633 void init(const SkClipStack* clipStack, const SkRegion& clipRegion, | 633 void init(const SkClipStack* clipStack, const SkRegion& clipRegion, |
| 634 const SkMatrix& matrix, const SkPaint& paint, bool hasText) { | 634 const SkMatrix& matrix, const SkPaint& paint, bool hasText) { |
| 635 // Shape has to be flatten before we get here. | 635 // Shape has to be flatten before we get here. |
| 636 if (matrix.hasPerspective()) { | 636 if (matrix.hasPerspective()) { |
| 637 NOT_IMPLEMENTED(!matrix.hasPerspective(), false); | 637 NOT_IMPLEMENTED(!matrix.hasPerspective(), false); |
| 638 return; | 638 return; |
| 639 } | 639 } |
| 640 if (paint.getXfermode()) { | 640 if (paint.getXfermode()) { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 rect->appendScalar(translatedRect.fLeft); | 828 rect->appendScalar(translatedRect.fLeft); |
| 829 rect->appendScalar(translatedRect.fTop); | 829 rect->appendScalar(translatedRect.fTop); |
| 830 rect->appendScalar(translatedRect.fRight); | 830 rect->appendScalar(translatedRect.fRight); |
| 831 rect->appendScalar(translatedRect.fBottom); | 831 rect->appendScalar(translatedRect.fBottom); |
| 832 annotation->insertObject("Rect", std::move(rect)); | 832 annotation->insertObject("Rect", std::move(rect)); |
| 833 | 833 |
| 834 return annotation; | 834 return annotation; |
| 835 } | 835 } |
| 836 | 836 |
| 837 static sk_sp<SkPDFDict> create_link_to_url(const SkData* urlData, const SkRect&
r) { | 837 static sk_sp<SkPDFDict> create_link_to_url(const SkData* urlData, const SkRect&
r) { |
| 838 auto annotation = create_link_annotation(r); | 838 sk_sp<SkPDFDict> annotation = create_link_annotation(r); |
| 839 SkString url(static_cast<const char *>(urlData->data()), | 839 SkString url(static_cast<const char *>(urlData->data()), |
| 840 urlData->size() - 1); | 840 urlData->size() - 1); |
| 841 auto action = sk_make_sp<SkPDFDict>("Action"); | 841 auto action = sk_make_sp<SkPDFDict>("Action"); |
| 842 action->insertName("S", "URI"); | 842 action->insertName("S", "URI"); |
| 843 action->insertString("URI", url); | 843 action->insertString("URI", url); |
| 844 annotation->insertObject("A", std::move(action)); | 844 annotation->insertObject("A", std::move(action)); |
| 845 return annotation; | 845 return annotation; |
| 846 } | 846 } |
| 847 | 847 |
| 848 static sk_sp<SkPDFDict> create_link_named_dest(const SkData* nameData, | 848 static sk_sp<SkPDFDict> create_link_named_dest(const SkData* nameData, |
| 849 const SkRect& r) { | 849 const SkRect& r) { |
| 850 auto annotation = create_link_annotation(r); | 850 sk_sp<SkPDFDict> annotation = create_link_annotation(r); |
| 851 SkString name(static_cast<const char *>(nameData->data()), | 851 SkString name(static_cast<const char *>(nameData->data()), |
| 852 nameData->size() - 1); | 852 nameData->size() - 1); |
| 853 annotation->insertName("Dest", name); | 853 annotation->insertName("Dest", name); |
| 854 return annotation; | 854 return annotation; |
| 855 } | 855 } |
| 856 | 856 |
| 857 void SkPDFDevice::drawRect(const SkDraw& d, | 857 void SkPDFDevice::drawRect(const SkDraw& d, |
| 858 const SkRect& rect, | 858 const SkRect& rect, |
| 859 const SkPaint& srcPaint) { | 859 const SkPaint& srcPaint) { |
| 860 SkPaint paint = srcPaint; | 860 SkPaint paint = srcPaint; |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 SkPath shape; | 1387 SkPath shape; |
| 1388 shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y), | 1388 shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y), |
| 1389 SkIntToScalar(device->width()), | 1389 SkIntToScalar(device->width()), |
| 1390 SkIntToScalar(device->height()))); | 1390 SkIntToScalar(device->height()))); |
| 1391 content.setShape(shape); | 1391 content.setShape(shape); |
| 1392 } | 1392 } |
| 1393 if (!content.needSource()) { | 1393 if (!content.needSource()) { |
| 1394 return; | 1394 return; |
| 1395 } | 1395 } |
| 1396 | 1396 |
| 1397 auto xObject = sk_make_sp<SkPDFFormXObject>(pdfDevice); | 1397 sk_sp<SkPDFObject> xObject = pdfDevice->makeFormXObjectFromDevice(); |
| 1398 SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()), | 1398 SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()), |
| 1399 &content.entry()->fContent); | 1399 &content.entry()->fContent); |
| 1400 } | 1400 } |
| 1401 | 1401 |
| 1402 SkImageInfo SkPDFDevice::imageInfo() const { | 1402 SkImageInfo SkPDFDevice::imageInfo() const { |
| 1403 SkImageInfo info = SkImageInfo::MakeUnknown(fPageSize.width(), fPageSize.hei
ght()); | 1403 SkImageInfo info = SkImageInfo::MakeUnknown(fPageSize.width(), fPageSize.hei
ght()); |
| 1404 return info; | 1404 return info; |
| 1405 } | 1405 } |
| 1406 | 1406 |
| 1407 sk_sp<SkSurface> SkPDFDevice::makeSurface(const SkImageInfo& info, const SkSurfa
ceProps& props) { | 1407 sk_sp<SkSurface> SkPDFDevice::makeSurface(const SkImageInfo& info, const SkSurfa
ceProps& props) { |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1603 pdfDest->appendName("XYZ"); | 1603 pdfDest->appendName("XYZ"); |
| 1604 SkPoint p = fInitialTransform.mapXY(dest.point.x(), dest.point.y()); | 1604 SkPoint p = fInitialTransform.mapXY(dest.point.x(), dest.point.y()); |
| 1605 pdfDest->appendScalar(p.x()); | 1605 pdfDest->appendScalar(p.x()); |
| 1606 pdfDest->appendScalar(p.y()); | 1606 pdfDest->appendScalar(p.y()); |
| 1607 pdfDest->appendInt(0); // Leave zoom unchanged | 1607 pdfDest->appendInt(0); // Leave zoom unchanged |
| 1608 SkString name(static_cast<const char*>(dest.nameData->data())); | 1608 SkString name(static_cast<const char*>(dest.nameData->data())); |
| 1609 dict->insertObject(name, std::move(pdfDest)); | 1609 dict->insertObject(name, std::move(pdfDest)); |
| 1610 } | 1610 } |
| 1611 } | 1611 } |
| 1612 | 1612 |
| 1613 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { | 1613 sk_sp<SkPDFObject> SkPDFDevice::makeFormXObjectFromDevice() { |
| 1614 SkPDFFormXObject* xobject = new SkPDFFormXObject(this); | 1614 sk_sp<SkPDFObject> xobject = |
| 1615 SkPDFMakeFormXObject(this->content(), this->copyMediaBox(), |
| 1616 this->makeResourceDict(), nullptr); |
| 1615 // We always draw the form xobjects that we create back into the device, so | 1617 // We always draw the form xobjects that we create back into the device, so |
| 1616 // we simply preserve the font usage instead of pulling it out and merging | 1618 // we simply preserve the font usage instead of pulling it out and merging |
| 1617 // it back in later. | 1619 // it back in later. |
| 1618 cleanUp(); // Reset this device to have no content. | 1620 this->cleanUp(); // Reset this device to have no content. |
| 1619 init(); | 1621 this->init(); |
| 1620 return xobject; | 1622 return xobject; |
| 1621 } | 1623 } |
| 1622 | 1624 |
| 1623 void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, | 1625 void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, |
| 1624 SkPDFFormXObject* mask, | 1626 SkPDFObject* mask, |
| 1625 const SkClipStack* clipStack, | 1627 const SkClipStack* clipStack, |
| 1626 const SkRegion& clipRegion, | 1628 const SkRegion& clipRegion, |
| 1627 SkXfermode::Mode mode, | 1629 SkXfermode::Mode mode, |
| 1628 bool invertClip) { | 1630 bool invertClip) { |
| 1629 if (clipRegion.isEmpty() && !invertClip) { | 1631 if (clipRegion.isEmpty() && !invertClip) { |
| 1630 return; | 1632 return; |
| 1631 } | 1633 } |
| 1632 | 1634 |
| 1633 auto sMaskGS = SkPDFGraphicState::GetSMaskGraphicState( | 1635 sk_sp<SkPDFDict> sMaskGS = SkPDFGraphicState::GetSMaskGraphicState( |
| 1634 mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode, fDocument->ca
non()); | 1636 mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode, fDocument->ca
non()); |
| 1635 | 1637 |
| 1636 SkMatrix identity; | 1638 SkMatrix identity; |
| 1637 identity.reset(); | 1639 identity.reset(); |
| 1638 SkPaint paint; | 1640 SkPaint paint; |
| 1639 paint.setXfermodeMode(mode); | 1641 paint.setXfermodeMode(mode); |
| 1640 ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); | 1642 ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); |
| 1641 if (!content.entry()) { | 1643 if (!content.entry()) { |
| 1642 return; | 1644 return; |
| 1643 } | 1645 } |
| 1644 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), | 1646 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), |
| 1645 &content.entry()->fContent); | 1647 &content.entry()->fContent); |
| 1646 SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent); | 1648 SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent); |
| 1647 | 1649 |
| 1648 // Call makeNoSmaskGraphicState() instead of | 1650 // Call makeNoSmaskGraphicState() instead of |
| 1649 // SkPDFGraphicState::MakeNoSmaskGraphicState so that the canon | 1651 // SkPDFGraphicState::MakeNoSmaskGraphicState so that the canon |
| 1650 // can deduplicate. | 1652 // can deduplicate. |
| 1651 sMaskGS = fDocument->canon()->makeNoSmaskGraphicState(); | 1653 sMaskGS = fDocument->canon()->makeNoSmaskGraphicState(); |
| 1652 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), | 1654 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), |
| 1653 &content.entry()->fContent); | 1655 &content.entry()->fContent); |
| 1654 } | 1656 } |
| 1655 | 1657 |
| 1656 SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli
pStack, | 1658 SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli
pStack, |
| 1657 const SkRegion& clipRegion, | 1659 const SkRegion& clipRegion, |
| 1658 const SkMatrix& matrix, | 1660 const SkMatrix& matrix, |
| 1659 const SkPaint& paint, | 1661 const SkPaint& paint, |
| 1660 bool hasText, | 1662 bool hasText, |
| 1661 SkPDFFormXObject** dst) { | 1663 SkPDFObject** dst) { |
| 1662 *dst = nullptr; | 1664 *dst = nullptr; |
| 1663 if (clipRegion.isEmpty()) { | 1665 if (clipRegion.isEmpty()) { |
| 1664 return nullptr; | 1666 return nullptr; |
| 1665 } | 1667 } |
| 1666 | 1668 |
| 1667 // The clip stack can come from an SkDraw where it is technically optional. | 1669 // The clip stack can come from an SkDraw where it is technically optional. |
| 1668 SkClipStack synthesizedClipStack; | 1670 SkClipStack synthesizedClipStack; |
| 1669 if (clipStack == nullptr) { | 1671 if (clipStack == nullptr) { |
| 1670 if (clipRegion == fExistingClipRegion) { | 1672 if (clipRegion == fExistingClipRegion) { |
| 1671 clipStack = &fExistingClipStack; | 1673 clipStack = &fExistingClipStack; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1692 if (xfermode == SkXfermode::kClear_Mode || | 1694 if (xfermode == SkXfermode::kClear_Mode || |
| 1693 xfermode == SkXfermode::kSrc_Mode || | 1695 xfermode == SkXfermode::kSrc_Mode || |
| 1694 xfermode == SkXfermode::kSrcIn_Mode || | 1696 xfermode == SkXfermode::kSrcIn_Mode || |
| 1695 xfermode == SkXfermode::kDstIn_Mode || | 1697 xfermode == SkXfermode::kDstIn_Mode || |
| 1696 xfermode == SkXfermode::kSrcOut_Mode || | 1698 xfermode == SkXfermode::kSrcOut_Mode || |
| 1697 xfermode == SkXfermode::kDstOut_Mode || | 1699 xfermode == SkXfermode::kDstOut_Mode || |
| 1698 xfermode == SkXfermode::kSrcATop_Mode || | 1700 xfermode == SkXfermode::kSrcATop_Mode || |
| 1699 xfermode == SkXfermode::kDstATop_Mode || | 1701 xfermode == SkXfermode::kDstATop_Mode || |
| 1700 xfermode == SkXfermode::kModulate_Mode) { | 1702 xfermode == SkXfermode::kModulate_Mode) { |
| 1701 if (!isContentEmpty()) { | 1703 if (!isContentEmpty()) { |
| 1702 *dst = createFormXObjectFromDevice(); | 1704 // TODO(halcanary): make this safer. |
| 1705 *dst = this->makeFormXObjectFromDevice().release(); |
| 1703 SkASSERT(isContentEmpty()); | 1706 SkASSERT(isContentEmpty()); |
| 1704 } else if (xfermode != SkXfermode::kSrc_Mode && | 1707 } else if (xfermode != SkXfermode::kSrc_Mode && |
| 1705 xfermode != SkXfermode::kSrcOut_Mode) { | 1708 xfermode != SkXfermode::kSrcOut_Mode) { |
| 1706 // Except for Src and SrcOut, if there isn't anything already there, | 1709 // Except for Src and SrcOut, if there isn't anything already there, |
| 1707 // then we're done. | 1710 // then we're done. |
| 1708 return nullptr; | 1711 return nullptr; |
| 1709 } | 1712 } |
| 1710 } | 1713 } |
| 1711 // TODO(vandebo): Figure out how/if we can handle the following modes: | 1714 // TODO(vandebo): Figure out how/if we can handle the following modes: |
| 1712 // Xor, Plus. | 1715 // Xor, Plus. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1723 entry = fContentEntries.emplace_back(); | 1726 entry = fContentEntries.emplace_back(); |
| 1724 } else { | 1727 } else { |
| 1725 entry = fContentEntries.emplace_front(); | 1728 entry = fContentEntries.emplace_front(); |
| 1726 } | 1729 } |
| 1727 populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint, | 1730 populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint, |
| 1728 hasText, &entry->fState); | 1731 hasText, &entry->fState); |
| 1729 return entry; | 1732 return entry; |
| 1730 } | 1733 } |
| 1731 | 1734 |
| 1732 void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode, | 1735 void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode, |
| 1733 SkPDFFormXObject* dst, | 1736 SkPDFObject* dst, |
| 1734 SkPath* shape) { | 1737 SkPath* shape) { |
| 1735 if (xfermode != SkXfermode::kClear_Mode && | 1738 if (xfermode != SkXfermode::kClear_Mode && |
| 1736 xfermode != SkXfermode::kSrc_Mode && | 1739 xfermode != SkXfermode::kSrc_Mode && |
| 1737 xfermode != SkXfermode::kDstOver_Mode && | 1740 xfermode != SkXfermode::kDstOver_Mode && |
| 1738 xfermode != SkXfermode::kSrcIn_Mode && | 1741 xfermode != SkXfermode::kSrcIn_Mode && |
| 1739 xfermode != SkXfermode::kDstIn_Mode && | 1742 xfermode != SkXfermode::kDstIn_Mode && |
| 1740 xfermode != SkXfermode::kSrcOut_Mode && | 1743 xfermode != SkXfermode::kSrcOut_Mode && |
| 1741 xfermode != SkXfermode::kDstOut_Mode && | 1744 xfermode != SkXfermode::kDstOut_Mode && |
| 1742 xfermode != SkXfermode::kSrcATop_Mode && | 1745 xfermode != SkXfermode::kSrcATop_Mode && |
| 1743 xfermode != SkXfermode::kDstATop_Mode && | 1746 xfermode != SkXfermode::kDstATop_Mode && |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1768 // if source has shape, we need to clip it too, so a copy of the clip is | 1771 // if source has shape, we need to clip it too, so a copy of the clip is |
| 1769 // saved. | 1772 // saved. |
| 1770 | 1773 |
| 1771 SkClipStack clipStack = fContentEntries.front()->fState.fClipStack; | 1774 SkClipStack clipStack = fContentEntries.front()->fState.fClipStack; |
| 1772 SkRegion clipRegion = fContentEntries.front()->fState.fClipRegion; | 1775 SkRegion clipRegion = fContentEntries.front()->fState.fClipRegion; |
| 1773 | 1776 |
| 1774 SkMatrix identity; | 1777 SkMatrix identity; |
| 1775 identity.reset(); | 1778 identity.reset(); |
| 1776 SkPaint stockPaint; | 1779 SkPaint stockPaint; |
| 1777 | 1780 |
| 1778 sk_sp<SkPDFFormXObject> srcFormXObject; | 1781 sk_sp<SkPDFObject> srcFormXObject; |
| 1779 if (isContentEmpty()) { | 1782 if (isContentEmpty()) { |
| 1780 // If nothing was drawn and there's no shape, then the draw was a | 1783 // If nothing was drawn and there's no shape, then the draw was a |
| 1781 // no-op, but dst needs to be restored for that to be true. | 1784 // no-op, but dst needs to be restored for that to be true. |
| 1782 // If there is shape, then an empty source with Src, SrcIn, SrcOut, | 1785 // If there is shape, then an empty source with Src, SrcIn, SrcOut, |
| 1783 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop | 1786 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop |
| 1784 // reduces to Dst. | 1787 // reduces to Dst. |
| 1785 if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode || | 1788 if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode || |
| 1786 xfermode == SkXfermode::kSrcATop_Mode) { | 1789 xfermode == SkXfermode::kSrcATop_Mode) { |
| 1787 ScopedContentEntry content(this, &fExistingClipStack, | 1790 ScopedContentEntry content(this, &fExistingClipStack, |
| 1788 fExistingClipRegion, identity, | 1791 fExistingClipRegion, identity, |
| 1789 stockPaint); | 1792 stockPaint); |
| 1790 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst), | 1793 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst), |
| 1791 &content.entry()->fContent); | 1794 &content.entry()->fContent); |
| 1792 return; | 1795 return; |
| 1793 } else { | 1796 } else { |
| 1794 xfermode = SkXfermode::kClear_Mode; | 1797 xfermode = SkXfermode::kClear_Mode; |
| 1795 } | 1798 } |
| 1796 } else { | 1799 } else { |
| 1797 SkASSERT(fContentEntries.count() == 1); | 1800 SkASSERT(fContentEntries.count() == 1); |
| 1798 srcFormXObject.reset(createFormXObjectFromDevice()); | 1801 srcFormXObject = this->makeFormXObjectFromDevice(); |
| 1799 } | 1802 } |
| 1800 | 1803 |
| 1801 // TODO(vandebo) srcFormXObject may contain alpha, but here we want it | 1804 // TODO(vandebo) srcFormXObject may contain alpha, but here we want it |
| 1802 // without alpha. | 1805 // without alpha. |
| 1803 if (xfermode == SkXfermode::kSrcATop_Mode) { | 1806 if (xfermode == SkXfermode::kSrcATop_Mode) { |
| 1804 // TODO(vandebo): In order to properly support SrcATop we have to track | 1807 // TODO(vandebo): In order to properly support SrcATop we have to track |
| 1805 // the shape of what's been drawn at all times. It's the intersection of | 1808 // the shape of what's been drawn at all times. It's the intersection of |
| 1806 // the non-transparent parts of the device and the outlines (shape) of | 1809 // the non-transparent parts of the device and the outlines (shape) of |
| 1807 // all images and devices drawn. | 1810 // all images and devices drawn. |
| 1808 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, | 1811 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, |
| 1809 &fExistingClipStack, fExistingClipRegion, | 1812 &fExistingClipStack, fExistingClipRegion, |
| 1810 SkXfermode::kSrcOver_Mode, true); | 1813 SkXfermode::kSrcOver_Mode, true); |
| 1811 } else { | 1814 } else { |
| 1812 sk_sp<SkPDFFormXObject> dstMaskStorage; | 1815 sk_sp<SkPDFObject> dstMaskStorage; |
| 1813 SkPDFFormXObject* dstMask = srcFormXObject.get(); | 1816 SkPDFObject* dstMask = srcFormXObject.get(); |
| 1814 if (shape != nullptr) { | 1817 if (shape != nullptr) { |
| 1815 // Draw shape into a form-xobject. | 1818 // Draw shape into a form-xobject. |
| 1816 SkRasterClip rc(clipRegion); | 1819 SkRasterClip rc(clipRegion); |
| 1817 SkDraw d; | 1820 SkDraw d; |
| 1818 d.fMatrix = &identity; | 1821 d.fMatrix = &identity; |
| 1819 d.fRC = &rc; | 1822 d.fRC = &rc; |
| 1820 d.fClipStack = &clipStack; | 1823 d.fClipStack = &clipStack; |
| 1821 SkPaint filledPaint; | 1824 SkPaint filledPaint; |
| 1822 filledPaint.setColor(SK_ColorBLACK); | 1825 filledPaint.setColor(SK_ColorBLACK); |
| 1823 filledPaint.setStyle(SkPaint::kFill_Style); | 1826 filledPaint.setStyle(SkPaint::kFill_Style); |
| 1824 this->drawPath(d, *shape, filledPaint, nullptr, true); | 1827 this->drawPath(d, *shape, filledPaint, nullptr, true); |
| 1825 | 1828 |
| 1826 dstMaskStorage.reset(createFormXObjectFromDevice()); | 1829 dstMaskStorage = this->makeFormXObjectFromDevice(); |
| 1827 dstMask = dstMaskStorage.get(); | 1830 dstMask = dstMaskStorage.get(); |
| 1828 } | 1831 } |
| 1829 drawFormXObjectWithMask(addXObjectResource(dst), dstMask, | 1832 drawFormXObjectWithMask(addXObjectResource(dst), dstMask, |
| 1830 &fExistingClipStack, fExistingClipRegion, | 1833 &fExistingClipStack, fExistingClipRegion, |
| 1831 SkXfermode::kSrcOver_Mode, true); | 1834 SkXfermode::kSrcOver_Mode, true); |
| 1832 } | 1835 } |
| 1833 | 1836 |
| 1834 if (xfermode == SkXfermode::kClear_Mode) { | 1837 if (xfermode == SkXfermode::kClear_Mode) { |
| 1835 return; | 1838 return; |
| 1836 } else if (xfermode == SkXfermode::kSrc_Mode || | 1839 } else if (xfermode == SkXfermode::kSrc_Mode || |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2177 // to be how Chromium impements most color-filters. | 2180 // to be how Chromium impements most color-filters. |
| 2178 autoImageUnref = color_filter(imageBitmap, colorFilter); | 2181 autoImageUnref = color_filter(imageBitmap, colorFilter); |
| 2179 imageBitmap = SkImageBitmap(autoImageUnref.get()); | 2182 imageBitmap = SkImageBitmap(autoImageUnref.get()); |
| 2180 // TODO(halcanary): de-dupe this by caching filtered images. | 2183 // TODO(halcanary): de-dupe this by caching filtered images. |
| 2181 // (maybe in the resource cache?) | 2184 // (maybe in the resource cache?) |
| 2182 } | 2185 } |
| 2183 | 2186 |
| 2184 SkBitmapKey key = imageBitmap.getKey(); | 2187 SkBitmapKey key = imageBitmap.getKey(); |
| 2185 sk_sp<SkPDFObject> pdfimage = fDocument->canon()->findPDFBitmap(key); | 2188 sk_sp<SkPDFObject> pdfimage = fDocument->canon()->findPDFBitmap(key); |
| 2186 if (!pdfimage) { | 2189 if (!pdfimage) { |
| 2187 auto img = imageBitmap.makeImage(); | 2190 sk_sp<SkImage> img = imageBitmap.makeImage(); |
| 2188 if (!img) { | 2191 if (!img) { |
| 2189 return; | 2192 return; |
| 2190 } | 2193 } |
| 2191 pdfimage = SkPDFCreateBitmapObject( | 2194 pdfimage = SkPDFCreateBitmapObject( |
| 2192 std::move(img), fDocument->canon()->getPixelSerializer()); | 2195 std::move(img), fDocument->canon()->getPixelSerializer()); |
| 2193 if (!pdfimage) { | 2196 if (!pdfimage) { |
| 2194 return; | 2197 return; |
| 2195 } | 2198 } |
| 2196 fDocument->serialize(pdfimage); // serialize images early. | 2199 fDocument->serialize(pdfimage); // serialize images early. |
| 2197 fDocument->canon()->addPDFBitmap(key, pdfimage); | 2200 fDocument->canon()->addPDFBitmap(key, pdfimage); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 } | 2244 } |
| 2242 | 2245 |
| 2243 sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) { | 2246 sk_sp<SkSpecialImage> SkPDFDevice::makeSpecial(const SkImage* image) { |
| 2244 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image->
height()), | 2247 return SkSpecialImage::MakeFromImage(SkIRect::MakeWH(image->width(), image->
height()), |
| 2245 image->makeNonTextureImage()); | 2248 image->makeNonTextureImage()); |
| 2246 } | 2249 } |
| 2247 | 2250 |
| 2248 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { | 2251 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { |
| 2249 return nullptr; | 2252 return nullptr; |
| 2250 } | 2253 } |
| OLD | NEW |