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 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 SkAutoTUnref<SkPDFDict> annotation(new SkPDFDict("Annot")); |
884 annotation->insertName("Subtype", "Link"); | 884 annotation->insertName("Subtype", "Link"); |
885 | 885 |
886 SkAutoTUnref<SkPDFArray> border(new SkPDFArray); | 886 SkAutoTUnref<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.detach()); | 891 annotation->insertObject("Border", border.release()); |
892 | 892 |
893 SkAutoTUnref<SkPDFArray> rect(new SkPDFArray); | 893 SkAutoTUnref<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.detach()); | 899 annotation->insertObject("Rect", rect.release()); |
900 | 900 |
901 return annotation.detach(); | 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 SkAutoTUnref<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 SkAutoTUnref<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.detach()); | 912 annotation->insertObject("A", action.release()); |
913 return annotation.detach(); | 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 SkAutoTUnref<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.detach(); | 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; |
929 replace_srcmode_on_opaque_paint(&paint); | 929 replace_srcmode_on_opaque_paint(&paint); |
930 SkRect r = rect; | 930 SkRect r = rect; |
931 r.sort(); | 931 r.sort(); |
932 | 932 |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |
1160 // the bitmap, we extract a subset. | 1160 // the bitmap, we extract a subset. |
1161 SkIRect srcIR; | 1161 SkIRect srcIR; |
1162 tmpSrc.roundOut(&srcIR); | 1162 tmpSrc.roundOut(&srcIR); |
1163 | 1163 |
1164 autoImageUnref.reset(image->newSubset(srcIR)); | 1164 autoImageUnref.reset(image->newSubset(srcIR)); |
1165 if (!autoImageUnref) { | 1165 if (!autoImageUnref) { |
1166 return; | 1166 return; |
1167 } | 1167 } |
1168 image = autoImageUnref; | 1168 image = autoImageUnref.get(); |
1169 // Since we did an extract, we need to adjust the matrix accordingly | 1169 // Since we did an extract, we need to adjust the matrix accordingly |
1170 SkScalar dx = 0, dy = 0; | 1170 SkScalar dx = 0, dy = 0; |
1171 if (srcIR.fLeft > 0) { | 1171 if (srcIR.fLeft > 0) { |
1172 dx = SkIntToScalar(srcIR.fLeft); | 1172 dx = SkIntToScalar(srcIR.fLeft); |
1173 } | 1173 } |
1174 if (srcIR.fTop > 0) { | 1174 if (srcIR.fTop > 0) { |
1175 dy = SkIntToScalar(srcIR.fTop); | 1175 dy = SkIntToScalar(srcIR.fTop); |
1176 } | 1176 } |
1177 if (dx || dy) { | 1177 if (dx || dy) { |
1178 matrix.preTranslate(dx, dy); | 1178 matrix.preTranslate(dx, dy); |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 SkAutoTUnref<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.detach(); | 1536 return mediaBox.release(); |
1537 } | 1537 } |
1538 | 1538 |
1539 SkStreamAsset* SkPDFDevice::content() const { | 1539 SkStreamAsset* SkPDFDevice::content() const { |
1540 SkDynamicMemoryWStream buffer; | 1540 SkDynamicMemoryWStream buffer; |
1541 this->writeContent(&buffer); | 1541 this->writeContent(&buffer); |
1542 return buffer.bytesWritten() > 0 | 1542 return buffer.bytesWritten() > 0 |
1543 ? buffer.detachAsStream() | 1543 ? buffer.detachAsStream() |
1544 : new SkMemoryStream; | 1544 : new SkMemoryStream; |
1545 } | 1545 } |
1546 | 1546 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1712 for (const NamedDestination& dest : fNamedDestinations) { | 1712 for (const NamedDestination& dest : fNamedDestinations) { |
1713 SkAutoTUnref<SkPDFArray> pdfDest(new SkPDFArray); | 1713 SkAutoTUnref<SkPDFArray> pdfDest(new SkPDFArray); |
1714 pdfDest->reserve(5); | 1714 pdfDest->reserve(5); |
1715 pdfDest->appendObjRef(SkRef(page)); | 1715 pdfDest->appendObjRef(SkRef(page)); |
1716 pdfDest->appendName("XYZ"); | 1716 pdfDest->appendName("XYZ"); |
1717 SkPoint p = fInitialTransform.mapXY(dest.point.x(), dest.point.y()); | 1717 SkPoint p = fInitialTransform.mapXY(dest.point.x(), dest.point.y()); |
1718 pdfDest->appendScalar(p.x()); | 1718 pdfDest->appendScalar(p.x()); |
1719 pdfDest->appendScalar(p.y()); | 1719 pdfDest->appendScalar(p.y()); |
1720 pdfDest->appendInt(0); // Leave zoom unchanged | 1720 pdfDest->appendInt(0); // Leave zoom unchanged |
1721 SkString name(static_cast<const char*>(dest.nameData->data())); | 1721 SkString name(static_cast<const char*>(dest.nameData->data())); |
1722 dict->insertObject(name, pdfDest.detach()); | 1722 dict->insertObject(name, pdfDest.release()); |
1723 } | 1723 } |
1724 } | 1724 } |
1725 | 1725 |
1726 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { | 1726 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { |
1727 SkPDFFormXObject* xobject = new SkPDFFormXObject(this); | 1727 SkPDFFormXObject* xobject = new SkPDFFormXObject(this); |
1728 // We always draw the form xobjects that we create back into the device, so | 1728 // We always draw the form xobjects that we create back into the device, so |
1729 // we simply preserve the font usage instead of pulling it out and merging | 1729 // we simply preserve the font usage instead of pulling it out and merging |
1730 // it back in later. | 1730 // it back in later. |
1731 cleanUp(false); // Reset this device to have no content. | 1731 cleanUp(false); // Reset this device to have no content. |
1732 init(); | 1732 init(); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1848 if (!lastContentEntry) { | 1848 if (!lastContentEntry) { |
1849 contentEntries->reset(entry); | 1849 contentEntries->reset(entry); |
1850 setLastContentEntry(entry); | 1850 setLastContentEntry(entry); |
1851 } else if (xfermode == SkXfermode::kDstOver_Mode) { | 1851 } else if (xfermode == SkXfermode::kDstOver_Mode) { |
1852 entry->fNext.reset(contentEntries->detach()); | 1852 entry->fNext.reset(contentEntries->detach()); |
1853 contentEntries->reset(entry); | 1853 contentEntries->reset(entry); |
1854 } else { | 1854 } else { |
1855 lastContentEntry->fNext.reset(entry); | 1855 lastContentEntry->fNext.reset(entry); |
1856 setLastContentEntry(entry); | 1856 setLastContentEntry(entry); |
1857 } | 1857 } |
1858 newEntry.detach(); | 1858 newEntry.release(); |
1859 return entry; | 1859 return entry; |
1860 } | 1860 } |
1861 | 1861 |
1862 void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode, | 1862 void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode, |
1863 SkPDFFormXObject* dst, | 1863 SkPDFFormXObject* dst, |
1864 SkPath* shape) { | 1864 SkPath* shape) { |
1865 if (xfermode != SkXfermode::kClear_Mode && | 1865 if (xfermode != SkXfermode::kClear_Mode && |
1866 xfermode != SkXfermode::kSrc_Mode && | 1866 xfermode != SkXfermode::kSrc_Mode && |
1867 xfermode != SkXfermode::kDstOver_Mode && | 1867 xfermode != SkXfermode::kDstOver_Mode && |
1868 xfermode != SkXfermode::kSrcIn_Mode && | 1868 xfermode != SkXfermode::kSrcIn_Mode && |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2202 SkMatrix matrix = origMatrix; | 2202 SkMatrix matrix = origMatrix; |
2203 SkRegion perspectiveBounds; | 2203 SkRegion perspectiveBounds; |
2204 const SkRegion* clipRegion = &origClipRegion; | 2204 const SkRegion* clipRegion = &origClipRegion; |
2205 SkAutoTUnref<const SkImage> autoImageUnref; | 2205 SkAutoTUnref<const SkImage> autoImageUnref; |
2206 | 2206 |
2207 if (srcRect) { | 2207 if (srcRect) { |
2208 autoImageUnref.reset(image->newSubset(*srcRect)); | 2208 autoImageUnref.reset(image->newSubset(*srcRect)); |
2209 if (!autoImageUnref) { | 2209 if (!autoImageUnref) { |
2210 return; | 2210 return; |
2211 } | 2211 } |
2212 image = autoImageUnref; | 2212 image = autoImageUnref.get(); |
2213 } | 2213 } |
2214 // Rasterize the bitmap using perspective in a new bitmap. | 2214 // Rasterize the bitmap using perspective in a new bitmap. |
2215 if (origMatrix.hasPerspective()) { | 2215 if (origMatrix.hasPerspective()) { |
2216 if (fRasterDpi == 0) { | 2216 if (fRasterDpi == 0) { |
2217 return; | 2217 return; |
2218 } | 2218 } |
2219 // Transform the bitmap in the new space, without taking into | 2219 // Transform the bitmap in the new space, without taking into |
2220 // account the initial transform. | 2220 // account the initial transform. |
2221 SkPath perspectiveOutline; | 2221 SkPath perspectiveOutline; |
2222 SkRect imageBounds = SkRect::Make(image->bounds()); | 2222 SkRect imageBounds = SkRect::Make(image->bounds()); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2278 // In the new space, we use the identity matrix translated | 2278 // In the new space, we use the identity matrix translated |
2279 // and scaled to reflect DPI. | 2279 // and scaled to reflect DPI. |
2280 matrix.setScale(1 / scaleX, 1 / scaleY); | 2280 matrix.setScale(1 / scaleX, 1 / scaleY); |
2281 matrix.postTranslate(deltaX, deltaY); | 2281 matrix.postTranslate(deltaX, deltaY); |
2282 | 2282 |
2283 perspectiveBounds.setRect(bounds.roundOut()); | 2283 perspectiveBounds.setRect(bounds.roundOut()); |
2284 clipRegion = &perspectiveBounds; | 2284 clipRegion = &perspectiveBounds; |
2285 srcRect = nullptr; | 2285 srcRect = nullptr; |
2286 | 2286 |
2287 autoImageUnref.reset(surface->newImageSnapshot()); | 2287 autoImageUnref.reset(surface->newImageSnapshot()); |
2288 image = autoImageUnref; | 2288 image = autoImageUnref.get(); |
2289 } | 2289 } |
2290 | 2290 |
2291 SkMatrix scaled; | 2291 SkMatrix scaled; |
2292 // Adjust for origin flip. | 2292 // Adjust for origin flip. |
2293 scaled.setScale(SK_Scalar1, -SK_Scalar1); | 2293 scaled.setScale(SK_Scalar1, -SK_Scalar1); |
2294 scaled.postTranslate(0, SK_Scalar1); | 2294 scaled.postTranslate(0, SK_Scalar1); |
2295 // Scale the image up from 1x1 to WxH. | 2295 // Scale the image up from 1x1 to WxH. |
2296 SkIRect subset = image->bounds(); | 2296 SkIRect subset = image->bounds(); |
2297 scaled.postScale(SkIntToScalar(image->width()), | 2297 scaled.postScale(SkIntToScalar(image->width()), |
2298 SkIntToScalar(image->height())); | 2298 SkIntToScalar(image->height())); |
(...skipping 12 matching lines...) Expand all Loading... |
2311 return; | 2311 return; |
2312 } | 2312 } |
2313 | 2313 |
2314 if (SkColorFilter* colorFilter = paint.getColorFilter()) { | 2314 if (SkColorFilter* colorFilter = paint.getColorFilter()) { |
2315 // TODO(https://bug.skia.org/4378): implement colorfilter on other | 2315 // TODO(https://bug.skia.org/4378): implement colorfilter on other |
2316 // draw calls. This code here works for all | 2316 // draw calls. This code here works for all |
2317 // drawBitmap*()/drawImage*() calls amd ImageFilters (which | 2317 // drawBitmap*()/drawImage*() calls amd ImageFilters (which |
2318 // rasterize a layer on this backend). Fortuanely, this seems | 2318 // rasterize a layer on this backend). Fortuanely, this seems |
2319 // to be how Chromium impements most color-filters. | 2319 // to be how Chromium impements most color-filters. |
2320 autoImageUnref.reset(color_filter(image, colorFilter)); | 2320 autoImageUnref.reset(color_filter(image, colorFilter)); |
2321 image = autoImageUnref; | 2321 image = autoImageUnref.get(); |
2322 // TODO(halcanary): de-dupe this by caching filtered images. | 2322 // TODO(halcanary): de-dupe this by caching filtered images. |
2323 // (maybe in the resource cache?) | 2323 // (maybe in the resource cache?) |
2324 } | 2324 } |
2325 SkAutoTUnref<SkPDFObject> pdfimage(SkSafeRef(fCanon->findPDFBitmap(image))); | 2325 SkAutoTUnref<SkPDFObject> pdfimage(SkSafeRef(fCanon->findPDFBitmap(image))); |
2326 if (!pdfimage) { | 2326 if (!pdfimage) { |
2327 pdfimage.reset(SkPDFCreateBitmapObject( | 2327 pdfimage.reset(SkPDFCreateBitmapObject( |
2328 image, fCanon->fPixelSerializer)); | 2328 image, fCanon->getPixelSerializer())); |
2329 if (!pdfimage) { | 2329 if (!pdfimage) { |
2330 return; | 2330 return; |
2331 } | 2331 } |
2332 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); | 2332 fCanon->addPDFBitmap(image->uniqueID(), pdfimage.get()); |
2333 } | 2333 } |
2334 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), | 2334 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), |
2335 &content.entry()->fContent); | 2335 &content.entry()->fContent); |
2336 } | 2336 } |
OLD | NEW |