| 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 | 9 |
| 10 #include "SkAnnotationKeys.h" | 10 #include "SkAnnotationKeys.h" |
| (...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 SkPDFUtils::ClosePath(&content.entry()->fContent); | 873 SkPDFUtils::ClosePath(&content.entry()->fContent); |
| 874 SkPDFUtils::StrokePath(&content.entry()->fContent); | 874 SkPDFUtils::StrokePath(&content.entry()->fContent); |
| 875 } | 875 } |
| 876 break; | 876 break; |
| 877 default: | 877 default: |
| 878 SkASSERT(false); | 878 SkASSERT(false); |
| 879 } | 879 } |
| 880 } | 880 } |
| 881 | 881 |
| 882 static SkPDFDict* create_link_annotation(const SkRect& translatedRect) { | 882 static SkPDFDict* create_link_annotation(const SkRect& translatedRect) { |
| 883 SkAutoTUnref<SkPDFDict> annotation(new SkPDFDict("Annot")); | 883 sk_sp<SkPDFDict> annotation(new SkPDFDict("Annot")); |
| 884 annotation->insertName("Subtype", "Link"); | 884 annotation->insertName("Subtype", "Link"); |
| 885 | 885 |
| 886 SkAutoTUnref<SkPDFArray> border(new SkPDFArray); | 886 sk_sp<SkPDFArray> border(new SkPDFArray); |
| 887 border->reserve(3); | 887 border->reserve(3); |
| 888 border->appendInt(0); // Horizontal corner radius. | 888 border->appendInt(0); // Horizontal corner radius. |
| 889 border->appendInt(0); // Vertical corner radius. | 889 border->appendInt(0); // Vertical corner radius. |
| 890 border->appendInt(0); // Width, 0 = no border. | 890 border->appendInt(0); // Width, 0 = no border. |
| 891 annotation->insertObject("Border", border.release()); | 891 annotation->insertObject("Border", border.release()); |
| 892 | 892 |
| 893 SkAutoTUnref<SkPDFArray> rect(new SkPDFArray); | 893 sk_sp<SkPDFArray> rect(new SkPDFArray); |
| 894 rect->reserve(4); | 894 rect->reserve(4); |
| 895 rect->appendScalar(translatedRect.fLeft); | 895 rect->appendScalar(translatedRect.fLeft); |
| 896 rect->appendScalar(translatedRect.fTop); | 896 rect->appendScalar(translatedRect.fTop); |
| 897 rect->appendScalar(translatedRect.fRight); | 897 rect->appendScalar(translatedRect.fRight); |
| 898 rect->appendScalar(translatedRect.fBottom); | 898 rect->appendScalar(translatedRect.fBottom); |
| 899 annotation->insertObject("Rect", rect.release()); | 899 annotation->insertObject("Rect", rect.release()); |
| 900 | 900 |
| 901 return annotation.release(); | 901 return annotation.release(); |
| 902 } | 902 } |
| 903 | 903 |
| 904 static SkPDFDict* create_link_to_url(const SkData* urlData, const SkRect& r) { | 904 static SkPDFDict* create_link_to_url(const SkData* urlData, const SkRect& r) { |
| 905 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); | 905 sk_sp<SkPDFDict> annotation(create_link_annotation(r)); |
| 906 | 906 |
| 907 SkString url(static_cast<const char *>(urlData->data()), | 907 SkString url(static_cast<const char *>(urlData->data()), |
| 908 urlData->size() - 1); | 908 urlData->size() - 1); |
| 909 SkAutoTUnref<SkPDFDict> action(new SkPDFDict("Action")); | 909 sk_sp<SkPDFDict> action(new SkPDFDict("Action")); |
| 910 action->insertName("S", "URI"); | 910 action->insertName("S", "URI"); |
| 911 action->insertString("URI", url); | 911 action->insertString("URI", url); |
| 912 annotation->insertObject("A", action.release()); | 912 annotation->insertObject("A", action.release()); |
| 913 return annotation.release(); | 913 return annotation.release(); |
| 914 } | 914 } |
| 915 | 915 |
| 916 static SkPDFDict* create_link_named_dest(const SkData* nameData, | 916 static SkPDFDict* create_link_named_dest(const SkData* nameData, |
| 917 const SkRect& r) { | 917 const SkRect& r) { |
| 918 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); | 918 sk_sp<SkPDFDict> annotation(create_link_annotation(r)); |
| 919 SkString name(static_cast<const char *>(nameData->data()), | 919 SkString name(static_cast<const char *>(nameData->data()), |
| 920 nameData->size() - 1); | 920 nameData->size() - 1); |
| 921 annotation->insertName("Dest", name); | 921 annotation->insertName("Dest", name); |
| 922 return annotation.release(); | 922 return annotation.release(); |
| 923 } | 923 } |
| 924 | 924 |
| 925 void SkPDFDevice::drawRect(const SkDraw& d, | 925 void SkPDFDevice::drawRect(const SkDraw& d, |
| 926 const SkRect& rect, | 926 const SkRect& rect, |
| 927 const SkPaint& srcPaint) { | 927 const SkPaint& srcPaint) { |
| 928 SkPaint paint = srcPaint; | 928 SkPaint paint = srcPaint; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 // Compute matrix from the two rectangles | 1139 // Compute matrix from the two rectangles |
| 1140 if (src) { | 1140 if (src) { |
| 1141 tmpSrc = *src; | 1141 tmpSrc = *src; |
| 1142 } else { | 1142 } else { |
| 1143 tmpSrc = imageBounds; | 1143 tmpSrc = imageBounds; |
| 1144 } | 1144 } |
| 1145 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); | 1145 matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); |
| 1146 | 1146 |
| 1147 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if | 1147 // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if |
| 1148 // needed (if the src was clipped). No check needed if src==null. | 1148 // needed (if the src was clipped). No check needed if src==null. |
| 1149 SkAutoTUnref<const SkImage> autoImageUnref; | 1149 sk_sp<const SkImage> autoImageUnref; |
| 1150 if (src) { | 1150 if (src) { |
| 1151 if (!imageBounds.contains(*src)) { | 1151 if (!imageBounds.contains(*src)) { |
| 1152 if (!tmpSrc.intersect(imageBounds)) { | 1152 if (!tmpSrc.intersect(imageBounds)) { |
| 1153 return; // nothing to draw | 1153 return; // nothing to draw |
| 1154 } | 1154 } |
| 1155 // recompute dst, based on the smaller tmpSrc | 1155 // recompute dst, based on the smaller tmpSrc |
| 1156 matrix.mapRect(&tmpDst, tmpSrc); | 1156 matrix.mapRect(&tmpDst, tmpSrc); |
| 1157 } | 1157 } |
| 1158 | 1158 |
| 1159 // since we may need to clamp to the borders of the src rect within | 1159 // since we may need to clamp to the borders of the src rect within |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1441 SkPath shape; | 1441 SkPath shape; |
| 1442 shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y), | 1442 shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y), |
| 1443 SkIntToScalar(device->width()), | 1443 SkIntToScalar(device->width()), |
| 1444 SkIntToScalar(device->height()))); | 1444 SkIntToScalar(device->height()))); |
| 1445 content.setShape(shape); | 1445 content.setShape(shape); |
| 1446 } | 1446 } |
| 1447 if (!content.needSource()) { | 1447 if (!content.needSource()) { |
| 1448 return; | 1448 return; |
| 1449 } | 1449 } |
| 1450 | 1450 |
| 1451 SkAutoTUnref<SkPDFFormXObject> xObject(new SkPDFFormXObject(pdfDevice)); | 1451 sk_sp<SkPDFFormXObject> xObject(new SkPDFFormXObject(pdfDevice)); |
| 1452 SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()), | 1452 SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()), |
| 1453 &content.entry()->fContent); | 1453 &content.entry()->fContent); |
| 1454 | 1454 |
| 1455 // Merge glyph sets from the drawn device. | 1455 // Merge glyph sets from the drawn device. |
| 1456 fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage()); | 1456 fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage()); |
| 1457 } | 1457 } |
| 1458 | 1458 |
| 1459 SkImageInfo SkPDFDevice::imageInfo() const { | 1459 SkImageInfo SkPDFDevice::imageInfo() const { |
| 1460 return fLegacyBitmap.info(); | 1460 return fLegacyBitmap.info(); |
| 1461 } | 1461 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1520 &fonts); | 1520 &fonts); |
| 1521 } | 1521 } |
| 1522 | 1522 |
| 1523 const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const { | 1523 const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const { |
| 1524 return fFontResources; | 1524 return fFontResources; |
| 1525 } | 1525 } |
| 1526 | 1526 |
| 1527 SkPDFArray* SkPDFDevice::copyMediaBox() const { | 1527 SkPDFArray* SkPDFDevice::copyMediaBox() const { |
| 1528 // should this be a singleton? | 1528 // should this be a singleton? |
| 1529 | 1529 |
| 1530 SkAutoTUnref<SkPDFArray> mediaBox(new SkPDFArray); | 1530 sk_sp<SkPDFArray> mediaBox(new SkPDFArray); |
| 1531 mediaBox->reserve(4); | 1531 mediaBox->reserve(4); |
| 1532 mediaBox->appendInt(0); | 1532 mediaBox->appendInt(0); |
| 1533 mediaBox->appendInt(0); | 1533 mediaBox->appendInt(0); |
| 1534 mediaBox->appendInt(fPageSize.fWidth); | 1534 mediaBox->appendInt(fPageSize.fWidth); |
| 1535 mediaBox->appendInt(fPageSize.fHeight); | 1535 mediaBox->appendInt(fPageSize.fHeight); |
| 1536 return mediaBox.release(); | 1536 return mediaBox.release(); |
| 1537 } | 1537 } |
| 1538 | 1538 |
| 1539 SkStreamAsset* SkPDFDevice::content() const { | 1539 SkStreamAsset* SkPDFDevice::content() const { |
| 1540 SkDynamicMemoryWStream buffer; | 1540 SkDynamicMemoryWStream buffer; |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 for (const RectWithData& linkToDestination : fLinkToDestinations) { | 1704 for (const RectWithData& linkToDestination : fLinkToDestinations) { |
| 1705 SkRect r; | 1705 SkRect r; |
| 1706 fInitialTransform.mapRect(&r, linkToDestination.rect); | 1706 fInitialTransform.mapRect(&r, linkToDestination.rect); |
| 1707 array->appendObject( | 1707 array->appendObject( |
| 1708 create_link_named_dest(linkToDestination.data.get(), r)); | 1708 create_link_named_dest(linkToDestination.data.get(), r)); |
| 1709 } | 1709 } |
| 1710 } | 1710 } |
| 1711 | 1711 |
| 1712 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { | 1712 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { |
| 1713 for (const NamedDestination& dest : fNamedDestinations) { | 1713 for (const NamedDestination& dest : fNamedDestinations) { |
| 1714 SkAutoTUnref<SkPDFArray> pdfDest(new SkPDFArray); | 1714 sk_sp<SkPDFArray> pdfDest(new SkPDFArray); |
| 1715 pdfDest->reserve(5); | 1715 pdfDest->reserve(5); |
| 1716 pdfDest->appendObjRef(SkRef(page)); | 1716 pdfDest->appendObjRef(SkRef(page)); |
| 1717 pdfDest->appendName("XYZ"); | 1717 pdfDest->appendName("XYZ"); |
| 1718 SkPoint p = fInitialTransform.mapXY(dest.point.x(), dest.point.y()); | 1718 SkPoint p = fInitialTransform.mapXY(dest.point.x(), dest.point.y()); |
| 1719 pdfDest->appendScalar(p.x()); | 1719 pdfDest->appendScalar(p.x()); |
| 1720 pdfDest->appendScalar(p.y()); | 1720 pdfDest->appendScalar(p.y()); |
| 1721 pdfDest->appendInt(0); // Leave zoom unchanged | 1721 pdfDest->appendInt(0); // Leave zoom unchanged |
| 1722 SkString name(static_cast<const char*>(dest.nameData->data())); | 1722 SkString name(static_cast<const char*>(dest.nameData->data())); |
| 1723 dict->insertObject(name, pdfDest.release()); | 1723 dict->insertObject(name, pdfDest.release()); |
| 1724 } | 1724 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1737 void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, | 1737 void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, |
| 1738 SkPDFFormXObject* mask, | 1738 SkPDFFormXObject* mask, |
| 1739 const SkClipStack* clipStack, | 1739 const SkClipStack* clipStack, |
| 1740 const SkRegion& clipRegion, | 1740 const SkRegion& clipRegion, |
| 1741 SkXfermode::Mode mode, | 1741 SkXfermode::Mode mode, |
| 1742 bool invertClip) { | 1742 bool invertClip) { |
| 1743 if (clipRegion.isEmpty() && !invertClip) { | 1743 if (clipRegion.isEmpty() && !invertClip) { |
| 1744 return; | 1744 return; |
| 1745 } | 1745 } |
| 1746 | 1746 |
| 1747 SkAutoTUnref<SkPDFObject> sMaskGS(SkPDFGraphicState::GetSMaskGraphicState( | 1747 sk_sp<SkPDFObject> sMaskGS(SkPDFGraphicState::GetSMaskGraphicState( |
| 1748 mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode)); | 1748 mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode)); |
| 1749 | 1749 |
| 1750 SkMatrix identity; | 1750 SkMatrix identity; |
| 1751 identity.reset(); | 1751 identity.reset(); |
| 1752 SkPaint paint; | 1752 SkPaint paint; |
| 1753 paint.setXfermodeMode(mode); | 1753 paint.setXfermodeMode(mode); |
| 1754 ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); | 1754 ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); |
| 1755 if (!content.entry()) { | 1755 if (!content.entry()) { |
| 1756 return; | 1756 return; |
| 1757 } | 1757 } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1901 // objects which is fine since the xobject will already be clipped. However | 1901 // objects which is fine since the xobject will already be clipped. However |
| 1902 // if source has shape, we need to clip it too, so a copy of the clip is | 1902 // if source has shape, we need to clip it too, so a copy of the clip is |
| 1903 // saved. | 1903 // saved. |
| 1904 SkClipStack clipStack = contentEntries->fState.fClipStack; | 1904 SkClipStack clipStack = contentEntries->fState.fClipStack; |
| 1905 SkRegion clipRegion = contentEntries->fState.fClipRegion; | 1905 SkRegion clipRegion = contentEntries->fState.fClipRegion; |
| 1906 | 1906 |
| 1907 SkMatrix identity; | 1907 SkMatrix identity; |
| 1908 identity.reset(); | 1908 identity.reset(); |
| 1909 SkPaint stockPaint; | 1909 SkPaint stockPaint; |
| 1910 | 1910 |
| 1911 SkAutoTUnref<SkPDFFormXObject> srcFormXObject; | 1911 sk_sp<SkPDFFormXObject> srcFormXObject; |
| 1912 if (isContentEmpty()) { | 1912 if (isContentEmpty()) { |
| 1913 // If nothing was drawn and there's no shape, then the draw was a | 1913 // If nothing was drawn and there's no shape, then the draw was a |
| 1914 // no-op, but dst needs to be restored for that to be true. | 1914 // no-op, but dst needs to be restored for that to be true. |
| 1915 // If there is shape, then an empty source with Src, SrcIn, SrcOut, | 1915 // If there is shape, then an empty source with Src, SrcIn, SrcOut, |
| 1916 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop | 1916 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop |
| 1917 // reduces to Dst. | 1917 // reduces to Dst. |
| 1918 if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode || | 1918 if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode || |
| 1919 xfermode == SkXfermode::kSrcATop_Mode) { | 1919 xfermode == SkXfermode::kSrcATop_Mode) { |
| 1920 ScopedContentEntry content(this, &fExistingClipStack, | 1920 ScopedContentEntry content(this, &fExistingClipStack, |
| 1921 fExistingClipRegion, identity, | 1921 fExistingClipRegion, identity, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1935 // without alpha. | 1935 // without alpha. |
| 1936 if (xfermode == SkXfermode::kSrcATop_Mode) { | 1936 if (xfermode == SkXfermode::kSrcATop_Mode) { |
| 1937 // TODO(vandebo): In order to properly support SrcATop we have to track | 1937 // TODO(vandebo): In order to properly support SrcATop we have to track |
| 1938 // the shape of what's been drawn at all times. It's the intersection of | 1938 // the shape of what's been drawn at all times. It's the intersection of |
| 1939 // the non-transparent parts of the device and the outlines (shape) of | 1939 // the non-transparent parts of the device and the outlines (shape) of |
| 1940 // all images and devices drawn. | 1940 // all images and devices drawn. |
| 1941 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, | 1941 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, |
| 1942 &fExistingClipStack, fExistingClipRegion, | 1942 &fExistingClipStack, fExistingClipRegion, |
| 1943 SkXfermode::kSrcOver_Mode, true); | 1943 SkXfermode::kSrcOver_Mode, true); |
| 1944 } else { | 1944 } else { |
| 1945 SkAutoTUnref<SkPDFFormXObject> dstMaskStorage; | 1945 sk_sp<SkPDFFormXObject> dstMaskStorage; |
| 1946 SkPDFFormXObject* dstMask = srcFormXObject.get(); | 1946 SkPDFFormXObject* dstMask = srcFormXObject.get(); |
| 1947 if (shape != nullptr) { | 1947 if (shape != nullptr) { |
| 1948 // Draw shape into a form-xobject. | 1948 // Draw shape into a form-xobject. |
| 1949 SkDraw d; | 1949 SkDraw d; |
| 1950 d.fMatrix = &identity; | 1950 d.fMatrix = &identity; |
| 1951 d.fClip = &clipRegion; | 1951 d.fClip = &clipRegion; |
| 1952 d.fClipStack = &clipStack; | 1952 d.fClipStack = &clipStack; |
| 1953 SkPaint filledPaint; | 1953 SkPaint filledPaint; |
| 1954 filledPaint.setColor(SK_ColorBLACK); | 1954 filledPaint.setColor(SK_ColorBLACK); |
| 1955 filledPaint.setStyle(SkPaint::kFill_Style); | 1955 filledPaint.setStyle(SkPaint::kFill_Style); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2036 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); | 2036 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); |
| 2037 NOT_IMPLEMENTED(paint.getColorFilter() != nullptr, false); | 2037 NOT_IMPLEMENTED(paint.getColorFilter() != nullptr, false); |
| 2038 | 2038 |
| 2039 entry->fMatrix = matrix; | 2039 entry->fMatrix = matrix; |
| 2040 entry->fClipStack = clipStack; | 2040 entry->fClipStack = clipStack; |
| 2041 entry->fClipRegion = clipRegion; | 2041 entry->fClipRegion = clipRegion; |
| 2042 entry->fColor = SkColorSetA(paint.getColor(), 0xFF); | 2042 entry->fColor = SkColorSetA(paint.getColor(), 0xFF); |
| 2043 entry->fShaderIndex = -1; | 2043 entry->fShaderIndex = -1; |
| 2044 | 2044 |
| 2045 // PDF treats a shader as a color, so we only set one or the other. | 2045 // PDF treats a shader as a color, so we only set one or the other. |
| 2046 SkAutoTUnref<SkPDFObject> pdfShader; | 2046 sk_sp<SkPDFObject> pdfShader; |
| 2047 const SkShader* shader = paint.getShader(); | 2047 const SkShader* shader = paint.getShader(); |
| 2048 SkColor color = paint.getColor(); | 2048 SkColor color = paint.getColor(); |
| 2049 if (shader) { | 2049 if (shader) { |
| 2050 // PDF positions patterns relative to the initial transform, so | 2050 // PDF positions patterns relative to the initial transform, so |
| 2051 // we need to apply the current transform to the shader parameters. | 2051 // we need to apply the current transform to the shader parameters. |
| 2052 SkMatrix transform = matrix; | 2052 SkMatrix transform = matrix; |
| 2053 transform.postConcat(fInitialTransform); | 2053 transform.postConcat(fInitialTransform); |
| 2054 | 2054 |
| 2055 // PDF doesn't support kClamp_TileMode, so we simulate it by making | 2055 // PDF doesn't support kClamp_TileMode, so we simulate it by making |
| 2056 // a pattern the size of the current clip. | 2056 // a pattern the size of the current clip. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2087 gradientInfo.fColorOffsets = nullptr; | 2087 gradientInfo.fColorOffsets = nullptr; |
| 2088 gradientInfo.fColorCount = 1; | 2088 gradientInfo.fColorCount = 1; |
| 2089 if (shader->asAGradient(&gradientInfo) == | 2089 if (shader->asAGradient(&gradientInfo) == |
| 2090 SkShader::kColor_GradientType) { | 2090 SkShader::kColor_GradientType) { |
| 2091 entry->fColor = SkColorSetA(gradientColor, 0xFF); | 2091 entry->fColor = SkColorSetA(gradientColor, 0xFF); |
| 2092 color = gradientColor; | 2092 color = gradientColor; |
| 2093 } | 2093 } |
| 2094 } | 2094 } |
| 2095 } | 2095 } |
| 2096 | 2096 |
| 2097 SkAutoTUnref<SkPDFGraphicState> newGraphicState; | 2097 sk_sp<SkPDFGraphicState> newGraphicState; |
| 2098 if (color == paint.getColor()) { | 2098 if (color == paint.getColor()) { |
| 2099 newGraphicState.reset( | 2099 newGraphicState.reset( |
| 2100 SkPDFGraphicState::GetGraphicStateForPaint(fCanon, paint)); | 2100 SkPDFGraphicState::GetGraphicStateForPaint(fCanon, paint)); |
| 2101 } else { | 2101 } else { |
| 2102 SkPaint newPaint = paint; | 2102 SkPaint newPaint = paint; |
| 2103 newPaint.setColor(color); | 2103 newPaint.setColor(color); |
| 2104 newGraphicState.reset( | 2104 newGraphicState.reset( |
| 2105 SkPDFGraphicState::GetGraphicStateForPaint(fCanon, newPaint)); | 2105 SkPDFGraphicState::GetGraphicStateForPaint(fCanon, newPaint)); |
| 2106 } | 2106 } |
| 2107 int resourceIndex = addGraphicStateResource(newGraphicState.get()); | 2107 int resourceIndex = addGraphicStateResource(newGraphicState.get()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2151 SkPDFResourceDict::kFont_ResourceType, | 2151 SkPDFResourceDict::kFont_ResourceType, |
| 2152 fontIndex).c_str()); | 2152 fontIndex).c_str()); |
| 2153 contentEntry->fContent.writeText(" "); | 2153 contentEntry->fContent.writeText(" "); |
| 2154 SkPDFUtils::AppendScalar(paint.getTextSize(), &contentEntry->fContent); | 2154 SkPDFUtils::AppendScalar(paint.getTextSize(), &contentEntry->fContent); |
| 2155 contentEntry->fContent.writeText(" Tf\n"); | 2155 contentEntry->fContent.writeText(" Tf\n"); |
| 2156 contentEntry->fState.fFont = fFontResources[fontIndex]; | 2156 contentEntry->fState.fFont = fFontResources[fontIndex]; |
| 2157 } | 2157 } |
| 2158 } | 2158 } |
| 2159 | 2159 |
| 2160 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) { | 2160 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) { |
| 2161 SkAutoTUnref<SkPDFFont> newFont( | 2161 sk_sp<SkPDFFont> newFont( |
| 2162 SkPDFFont::GetFontResource(fCanon, typeface, glyphID)); | 2162 SkPDFFont::GetFontResource(fCanon, typeface, glyphID)); |
| 2163 int resourceIndex = fFontResources.find(newFont.get()); | 2163 int resourceIndex = fFontResources.find(newFont.get()); |
| 2164 if (resourceIndex < 0) { | 2164 if (resourceIndex < 0) { |
| 2165 resourceIndex = fFontResources.count(); | 2165 resourceIndex = fFontResources.count(); |
| 2166 fFontResources.push(newFont.get()); | 2166 fFontResources.push(newFont.get()); |
| 2167 newFont.get()->ref(); | 2167 newFont.get()->ref(); |
| 2168 } | 2168 } |
| 2169 return resourceIndex; | 2169 return resourceIndex; |
| 2170 } | 2170 } |
| 2171 | 2171 |
| 2172 static SkSize rect_to_size(const SkRect& r) { | 2172 static SkSize rect_to_size(const SkRect& r) { |
| 2173 return SkSize::Make(r.width(), r.height()); | 2173 return SkSize::Make(r.width(), r.height()); |
| 2174 } | 2174 } |
| 2175 | 2175 |
| 2176 static const SkImage* color_filter(const SkImage* image, | 2176 static const SkImage* color_filter(const SkImage* image, |
| 2177 SkColorFilter* colorFilter) { | 2177 SkColorFilter* colorFilter) { |
| 2178 SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster( | 2178 sk_sp<SkSurface> surface(SkSurface::NewRaster( |
| 2179 SkImageInfo::MakeN32Premul(image->dimensions()))); | 2179 SkImageInfo::MakeN32Premul(image->dimensions()))); |
| 2180 if (!surface) { | 2180 if (!surface) { |
| 2181 return image; | 2181 return image; |
| 2182 } | 2182 } |
| 2183 SkCanvas* canvas = surface->getCanvas(); | 2183 SkCanvas* canvas = surface->getCanvas(); |
| 2184 canvas->clear(SK_ColorTRANSPARENT); | 2184 canvas->clear(SK_ColorTRANSPARENT); |
| 2185 SkPaint paint; | 2185 SkPaint paint; |
| 2186 paint.setColorFilter(colorFilter); | 2186 paint.setColorFilter(colorFilter); |
| 2187 canvas->drawImage(image, 0, 0, &paint); | 2187 canvas->drawImage(image, 0, 0, &paint); |
| 2188 canvas->flush(); | 2188 canvas->flush(); |
| 2189 return surface->newImageSnapshot(); | 2189 return surface->newImageSnapshot(); |
| 2190 } | 2190 } |
| 2191 | 2191 |
| 2192 //////////////////////////////////////////////////////////////////////////////// | 2192 //////////////////////////////////////////////////////////////////////////////// |
| 2193 void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, | 2193 void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, |
| 2194 const SkClipStack* clipStack, | 2194 const SkClipStack* clipStack, |
| 2195 const SkRegion& origClipRegion, | 2195 const SkRegion& origClipRegion, |
| 2196 const SkImage* image, | 2196 const SkImage* image, |
| 2197 const SkIRect* srcRect, | 2197 const SkIRect* srcRect, |
| 2198 const SkPaint& paint) { | 2198 const SkPaint& paint) { |
| 2199 SkASSERT(image); | 2199 SkASSERT(image); |
| 2200 #ifdef SK_PDF_IMAGE_STATS | 2200 #ifdef SK_PDF_IMAGE_STATS |
| 2201 gDrawImageCalls.fetch_add(1); | 2201 gDrawImageCalls.fetch_add(1); |
| 2202 #endif | 2202 #endif |
| 2203 SkMatrix matrix = origMatrix; | 2203 SkMatrix matrix = origMatrix; |
| 2204 SkRegion perspectiveBounds; | 2204 SkRegion perspectiveBounds; |
| 2205 const SkRegion* clipRegion = &origClipRegion; | 2205 const SkRegion* clipRegion = &origClipRegion; |
| 2206 SkAutoTUnref<const SkImage> autoImageUnref; | 2206 sk_sp<const SkImage> autoImageUnref; |
| 2207 | 2207 |
| 2208 if (srcRect) { | 2208 if (srcRect) { |
| 2209 autoImageUnref.reset(image->newSubset(*srcRect)); | 2209 autoImageUnref.reset(image->newSubset(*srcRect)); |
| 2210 if (!autoImageUnref) { | 2210 if (!autoImageUnref) { |
| 2211 return; | 2211 return; |
| 2212 } | 2212 } |
| 2213 image = autoImageUnref.get(); | 2213 image = autoImageUnref.get(); |
| 2214 } | 2214 } |
| 2215 // Rasterize the bitmap using perspective in a new bitmap. | 2215 // Rasterize the bitmap using perspective in a new bitmap. |
| 2216 if (origMatrix.hasPerspective()) { | 2216 if (origMatrix.hasPerspective()) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2247 | 2247 |
| 2248 // TODO(edisonn): A better approach would be to use a bitmap shader | 2248 // TODO(edisonn): A better approach would be to use a bitmap shader |
| 2249 // (in clamp mode) and draw a rect over the entire bounding box. Then | 2249 // (in clamp mode) and draw a rect over the entire bounding box. Then |
| 2250 // intersect perspectiveOutline to the clip. That will avoid introducing | 2250 // intersect perspectiveOutline to the clip. That will avoid introducing |
| 2251 // alpha to the image while still giving good behavior at the edge of | 2251 // alpha to the image while still giving good behavior at the edge of |
| 2252 // the image. Avoiding alpha will reduce the pdf size and generation | 2252 // the image. Avoiding alpha will reduce the pdf size and generation |
| 2253 // CPU time some. | 2253 // CPU time some. |
| 2254 | 2254 |
| 2255 SkISize wh = rect_to_size(physicalPerspectiveBounds).toCeil(); | 2255 SkISize wh = rect_to_size(physicalPerspectiveBounds).toCeil(); |
| 2256 | 2256 |
| 2257 SkAutoTUnref<SkSurface> surface( | 2257 sk_sp<SkSurface> surface( |
| 2258 SkSurface::NewRaster(SkImageInfo::MakeN32Premul(wh))); | 2258 SkSurface::NewRaster(SkImageInfo::MakeN32Premul(wh))); |
| 2259 if (!surface) { | 2259 if (!surface) { |
| 2260 return; | 2260 return; |
| 2261 } | 2261 } |
| 2262 SkCanvas* canvas = surface->getCanvas(); | 2262 SkCanvas* canvas = surface->getCanvas(); |
| 2263 canvas->clear(SK_ColorTRANSPARENT); | 2263 canvas->clear(SK_ColorTRANSPARENT); |
| 2264 | 2264 |
| 2265 SkScalar deltaX = bounds.left(); | 2265 SkScalar deltaX = bounds.left(); |
| 2266 SkScalar deltaY = bounds.top(); | 2266 SkScalar deltaY = bounds.top(); |
| 2267 | 2267 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2316 // TODO(https://bug.skia.org/4378): implement colorfilter on other | 2316 // TODO(https://bug.skia.org/4378): implement colorfilter on other |
| 2317 // draw calls. This code here works for all | 2317 // draw calls. This code here works for all |
| 2318 // drawBitmap*()/drawImage*() calls amd ImageFilters (which | 2318 // drawBitmap*()/drawImage*() calls amd ImageFilters (which |
| 2319 // rasterize a layer on this backend). Fortuanely, this seems | 2319 // rasterize a layer on this backend). Fortuanely, this seems |
| 2320 // to be how Chromium impements most color-filters. | 2320 // to be how Chromium impements most color-filters. |
| 2321 autoImageUnref.reset(color_filter(image, colorFilter)); | 2321 autoImageUnref.reset(color_filter(image, colorFilter)); |
| 2322 image = autoImageUnref.get(); | 2322 image = autoImageUnref.get(); |
| 2323 // TODO(halcanary): de-dupe this by caching filtered images. | 2323 // TODO(halcanary): de-dupe this by caching filtered images. |
| 2324 // (maybe in the resource cache?) | 2324 // (maybe in the resource cache?) |
| 2325 } | 2325 } |
| 2326 SkAutoTUnref<SkPDFObject> pdfimage(SkSafeRef(fCanon->findPDFBitmap(image))); | 2326 sk_sp<SkPDFObject> pdfimage(SkSafeRef(fCanon->findPDFBitmap(image))); |
| 2327 if (!pdfimage) { | 2327 if (!pdfimage) { |
| 2328 pdfimage.reset(SkPDFCreateBitmapObject( | 2328 pdfimage.reset(SkPDFCreateBitmapObject( |
| 2329 image, fCanon->getPixelSerializer())); | 2329 image, fCanon->getPixelSerializer())); |
| 2330 if (!pdfimage) { | 2330 if (!pdfimage) { |
| 2331 return; | 2331 return; |
| 2332 } | 2332 } |
| 2333 fCanon->addPDFBitmap(image->uniqueID(), pdfimage.get()); | 2333 fCanon->addPDFBitmap(image->uniqueID(), pdfimage.get()); |
| 2334 } | 2334 } |
| 2335 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), | 2335 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), |
| 2336 &content.entry()->fContent); | 2336 &content.entry()->fContent); |
| 2337 } | 2337 } |
| OLD | NEW |