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 |