| 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 |