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 "SkAnnotation.h" | 10 #include "SkAnnotation.h" |
11 #include "SkColor.h" | 11 #include "SkColor.h" |
12 #include "SkClipStack.h" | 12 #include "SkClipStack.h" |
13 #include "SkData.h" | 13 #include "SkData.h" |
14 #include "SkDraw.h" | 14 #include "SkDraw.h" |
15 #include "SkGlyphCache.h" | 15 #include "SkGlyphCache.h" |
16 #include "SkPaint.h" | 16 #include "SkPaint.h" |
17 #include "SkPath.h" | 17 #include "SkPath.h" |
18 #include "SkPathOps.h" | 18 #include "SkPathOps.h" |
19 #include "SkPDFBitmap.h" | 19 #include "SkPDFBitmap.h" |
20 #include "SkPDFFont.h" | 20 #include "SkPDFFont.h" |
21 #include "SkPDFFormXObject.h" | 21 #include "SkPDFFormXObject.h" |
22 #include "SkPDFGraphicState.h" | 22 #include "SkPDFGraphicState.h" |
23 #include "SkPDFResourceDict.h" | 23 #include "SkPDFResourceDict.h" |
24 #include "SkPDFShader.h" | 24 #include "SkPDFShader.h" |
25 #include "SkPDFStream.h" | 25 #include "SkPDFStream.h" |
26 #include "SkPDFTypes.h" | 26 #include "SkPDFTypes.h" |
27 #include "SkPDFUtils.h" | 27 #include "SkPDFUtils.h" |
| 28 #include "SkRasterClip.h" |
28 #include "SkRect.h" | 29 #include "SkRect.h" |
29 #include "SkRRect.h" | 30 #include "SkRRect.h" |
30 #include "SkString.h" | 31 #include "SkString.h" |
31 #include "SkSurface.h" | 32 #include "SkSurface.h" |
32 #include "SkTextFormatParams.h" | 33 #include "SkTextFormatParams.h" |
33 #include "SkTemplates.h" | 34 #include "SkTemplates.h" |
34 #include "SkTypefacePriv.h" | 35 #include "SkTypefacePriv.h" |
35 #include "SkXfermodeInterpretation.h" | 36 #include "SkXfermodeInterpretation.h" |
36 | 37 |
37 #define DPI_FOR_RASTER_SCALE_ONE 72 | 38 #define DPI_FOR_RASTER_SCALE_ONE 72 |
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 } | 696 } |
696 }; | 697 }; |
697 | 698 |
698 //////////////////////////////////////////////////////////////////////////////// | 699 //////////////////////////////////////////////////////////////////////////////// |
699 | 700 |
700 SkPDFDevice::SkPDFDevice(SkISize pageSize, SkScalar rasterDpi, SkPDFCanon* canon
, bool flip) | 701 SkPDFDevice::SkPDFDevice(SkISize pageSize, SkScalar rasterDpi, SkPDFCanon* canon
, bool flip) |
701 : INHERITED(SkSurfaceProps(0, kUnknown_SkPixelGeometry)) | 702 : INHERITED(SkSurfaceProps(0, kUnknown_SkPixelGeometry)) |
702 , fPageSize(pageSize) | 703 , fPageSize(pageSize) |
703 , fContentSize(pageSize) | 704 , fContentSize(pageSize) |
704 , fExistingClipRegion(SkIRect::MakeSize(pageSize)) | 705 , fExistingClipRegion(SkIRect::MakeSize(pageSize)) |
705 , fAnnotations(nullptr) | |
706 , fLastContentEntry(nullptr) | 706 , fLastContentEntry(nullptr) |
707 , fLastMarginContentEntry(nullptr) | 707 , fLastMarginContentEntry(nullptr) |
708 , fDrawingArea(kContent_DrawingArea) | 708 , fDrawingArea(kContent_DrawingArea) |
709 , fClipStack(nullptr) | 709 , fClipStack(nullptr) |
710 , fFontGlyphUsage(new SkPDFGlyphSetMap) | 710 , fFontGlyphUsage(new SkPDFGlyphSetMap) |
711 , fRasterDpi(rasterDpi) | 711 , fRasterDpi(rasterDpi) |
712 , fCanon(canon) { | 712 , fCanon(canon) { |
713 SkASSERT(pageSize.width() > 0); | 713 SkASSERT(pageSize.width() > 0); |
714 SkASSERT(pageSize.height() > 0); | 714 SkASSERT(pageSize.height() > 0); |
715 fLegacyBitmap.setInfo( | 715 fLegacyBitmap.setInfo( |
716 SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height())); | 716 SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height())); |
717 if (flip) { | 717 if (flip) { |
718 // Skia generally uses the top left as the origin but PDF | 718 // Skia generally uses the top left as the origin but PDF |
719 // natively has the origin at the bottom left. This matrix | 719 // natively has the origin at the bottom left. This matrix |
720 // corrects for that. But that only needs to be done once, we | 720 // corrects for that. But that only needs to be done once, we |
721 // don't do it when layering. | 721 // don't do it when layering. |
722 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); | 722 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); |
723 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); | 723 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); |
724 } else { | 724 } else { |
725 fInitialTransform.setIdentity(); | 725 fInitialTransform.setIdentity(); |
726 } | 726 } |
727 } | 727 } |
728 | 728 |
729 SkPDFDevice::~SkPDFDevice() { | 729 SkPDFDevice::~SkPDFDevice() { |
730 this->cleanUp(true); | 730 this->cleanUp(true); |
731 } | 731 } |
732 | 732 |
733 void SkPDFDevice::init() { | 733 void SkPDFDevice::init() { |
734 fAnnotations = nullptr; | |
735 fContentEntries.free(); | 734 fContentEntries.free(); |
736 fLastContentEntry = nullptr; | 735 fLastContentEntry = nullptr; |
737 fMarginContentEntries.free(); | 736 fMarginContentEntries.free(); |
738 fLastMarginContentEntry = nullptr; | 737 fLastMarginContentEntry = nullptr; |
739 fDrawingArea = kContent_DrawingArea; | 738 fDrawingArea = kContent_DrawingArea; |
740 if (fFontGlyphUsage.get() == nullptr) { | 739 if (fFontGlyphUsage.get() == nullptr) { |
741 fFontGlyphUsage.reset(new SkPDFGlyphSetMap); | 740 fFontGlyphUsage.reset(new SkPDFGlyphSetMap); |
742 } | 741 } |
743 } | 742 } |
744 | 743 |
745 void SkPDFDevice::cleanUp(bool clearFontUsage) { | 744 void SkPDFDevice::cleanUp(bool clearFontUsage) { |
746 fGraphicStateResources.unrefAll(); | 745 fGraphicStateResources.unrefAll(); |
747 fXObjectResources.unrefAll(); | 746 fXObjectResources.unrefAll(); |
748 fFontResources.unrefAll(); | 747 fFontResources.unrefAll(); |
749 fShaderResources.unrefAll(); | 748 fShaderResources.unrefAll(); |
750 SkSafeUnref(fAnnotations); | 749 fLinkToURLs.deleteAll(); |
| 750 fLinkToDestinations.deleteAll(); |
751 fNamedDestinations.deleteAll(); | 751 fNamedDestinations.deleteAll(); |
752 | 752 |
753 if (clearFontUsage) { | 753 if (clearFontUsage) { |
754 fFontGlyphUsage->reset(); | 754 fFontGlyphUsage->reset(); |
755 } | 755 } |
756 } | 756 } |
757 | 757 |
758 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { | 758 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { |
759 SkPaint newPaint = paint; | 759 SkPaint newPaint = paint; |
760 replace_srcmode_on_opaque_paint(&newPaint); | 760 replace_srcmode_on_opaque_paint(&newPaint); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 &content.entry()->fContent); | 869 &content.entry()->fContent); |
870 SkPDFUtils::ClosePath(&content.entry()->fContent); | 870 SkPDFUtils::ClosePath(&content.entry()->fContent); |
871 SkPDFUtils::StrokePath(&content.entry()->fContent); | 871 SkPDFUtils::StrokePath(&content.entry()->fContent); |
872 } | 872 } |
873 break; | 873 break; |
874 default: | 874 default: |
875 SkASSERT(false); | 875 SkASSERT(false); |
876 } | 876 } |
877 } | 877 } |
878 | 878 |
879 static SkPath transform_and_clip_path(const SkDraw& d, | |
880 const SkPath& region, | |
881 const SkMatrix& initialTransform) { | |
882 SkPath path = region; | |
883 SkMatrix transform = *d.fMatrix; | |
884 transform.postConcat(initialTransform); | |
885 path.transform(transform); | |
886 if (const SkClipStack* clipStack = d.fClipStack) { | |
887 SkPath clip; | |
888 (void)clipStack->asPath(&clip); | |
889 clip.transform(initialTransform); | |
890 Op(clip, path, SkPathOp::kIntersect_SkPathOp, &path); | |
891 } | |
892 return path; | |
893 } | |
894 | |
895 static SkPDFDict* create_link_annotation(const SkRect& translatedRect) { | 879 static SkPDFDict* create_link_annotation(const SkRect& translatedRect) { |
896 SkAutoTUnref<SkPDFDict> annotation(new SkPDFDict("Annot")); | 880 SkAutoTUnref<SkPDFDict> annotation(new SkPDFDict("Annot")); |
897 annotation->insertName("Subtype", "Link"); | 881 annotation->insertName("Subtype", "Link"); |
898 | 882 |
899 SkAutoTUnref<SkPDFArray> border(new SkPDFArray); | 883 SkAutoTUnref<SkPDFArray> border(new SkPDFArray); |
900 border->reserve(3); | 884 border->reserve(3); |
901 border->appendInt(0); // Horizontal corner radius. | 885 border->appendInt(0); // Horizontal corner radius. |
902 border->appendInt(0); // Vertical corner radius. | 886 border->appendInt(0); // Vertical corner radius. |
903 border->appendInt(0); // Width, 0 = no border. | 887 border->appendInt(0); // Width, 0 = no border. |
904 annotation->insertObject("Border", border.detach()); | 888 annotation->insertObject("Border", border.detach()); |
905 | 889 |
906 SkAutoTUnref<SkPDFArray> rect(new SkPDFArray); | 890 SkAutoTUnref<SkPDFArray> rect(new SkPDFArray); |
907 rect->reserve(4); | 891 rect->reserve(4); |
908 rect->appendScalar(translatedRect.fLeft); | 892 rect->appendScalar(translatedRect.fLeft); |
909 rect->appendScalar(translatedRect.fTop); | 893 rect->appendScalar(translatedRect.fTop); |
910 rect->appendScalar(translatedRect.fRight); | 894 rect->appendScalar(translatedRect.fRight); |
911 rect->appendScalar(translatedRect.fBottom); | 895 rect->appendScalar(translatedRect.fBottom); |
912 annotation->insertObject("Rect", rect.detach()); | 896 annotation->insertObject("Rect", rect.detach()); |
913 | 897 |
914 return annotation.detach(); | 898 return annotation.detach(); |
915 } | 899 } |
916 | 900 |
917 static SkPDFDict* create_link_to_url(SkData* urlData, const SkRect& r) { | 901 static SkPDFDict* create_link_to_url(const SkData* urlData, const SkRect& r) { |
918 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); | 902 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); |
919 | 903 |
920 SkString url(static_cast<const char *>(urlData->data()), | 904 SkString url(static_cast<const char *>(urlData->data()), |
921 urlData->size() - 1); | 905 urlData->size() - 1); |
922 SkAutoTUnref<SkPDFDict> action(new SkPDFDict("Action")); | 906 SkAutoTUnref<SkPDFDict> action(new SkPDFDict("Action")); |
923 action->insertName("S", "URI"); | 907 action->insertName("S", "URI"); |
924 action->insertString("URI", url); | 908 action->insertString("URI", url); |
925 annotation->insertObject("A", action.detach()); | 909 annotation->insertObject("A", action.detach()); |
926 return annotation.detach(); | 910 return annotation.detach(); |
927 } | 911 } |
928 | 912 |
929 static SkPDFDict* create_link_named_dest(SkData* nameData, const SkRect& r) { | 913 static SkPDFDict* create_link_named_dest(const SkData* nameData, |
| 914 const SkRect& r) { |
930 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); | 915 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); |
931 SkString name(static_cast<const char *>(nameData->data()), | 916 SkString name(static_cast<const char *>(nameData->data()), |
932 nameData->size() - 1); | 917 nameData->size() - 1); |
933 annotation->insertName("Dest", name); | 918 annotation->insertName("Dest", name); |
934 return annotation.detach(); | 919 return annotation.detach(); |
935 } | 920 } |
936 | 921 |
937 static SkPDFDict* create_rect_annotation(const SkRect& r, | |
938 SkAnnotation* annotation) { | |
939 SkASSERT(annotation); | |
940 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); | |
941 if (urlData) { | |
942 return create_link_to_url(urlData, r); | |
943 } | |
944 SkData* linkToName = | |
945 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); | |
946 if (linkToName) { | |
947 return create_link_named_dest(linkToName, r); | |
948 } | |
949 return nullptr; | |
950 } | |
951 | |
952 void SkPDFDevice::drawRect(const SkDraw& d, | 922 void SkPDFDevice::drawRect(const SkDraw& d, |
953 const SkRect& rect, | 923 const SkRect& rect, |
954 const SkPaint& srcPaint) { | 924 const SkPaint& srcPaint) { |
955 SkPaint paint = srcPaint; | 925 SkPaint paint = srcPaint; |
956 replace_srcmode_on_opaque_paint(&paint); | 926 replace_srcmode_on_opaque_paint(&paint); |
957 SkRect r = rect; | 927 SkRect r = rect; |
958 r.sort(); | 928 r.sort(); |
959 | 929 |
960 if (paint.getPathEffect()) { | 930 if (paint.getPathEffect()) { |
961 if (d.fClip->isEmpty()) { | 931 if (d.fClip->isEmpty()) { |
962 return; | 932 return; |
963 } | 933 } |
964 SkPath path; | 934 SkPath path; |
965 path.addRect(r); | 935 path.addRect(r); |
966 drawPath(d, path, paint, nullptr, true); | 936 drawPath(d, path, paint, nullptr, true); |
967 return; | 937 return; |
968 } | 938 } |
969 | 939 |
970 if (SkAnnotation* annotation = paint.getAnnotation()) { | 940 if (SkAnnotation* annotation = paint.getAnnotation()) { |
971 SkPath path; | 941 SkPath path; |
972 path.addRect(rect); | 942 path.addRect(rect); |
973 SkRect transformedRect = | 943 if (handlePathAnnotation(path, d, annotation)) { |
974 transform_and_clip_path(d, path, fInitialTransform).getBounds(); | |
975 SkAutoTUnref<SkPDFDict> annot( | |
976 create_rect_annotation(transformedRect, annotation)); | |
977 if (annot) { | |
978 this->addAnnotation(annot.detach()); | |
979 return; | 944 return; |
980 } | 945 } |
981 } | 946 } |
982 | 947 |
983 ScopedContentEntry content(this, d, paint); | 948 ScopedContentEntry content(this, d, paint); |
984 if (!content.entry()) { | 949 if (!content.entry()) { |
985 return; | 950 return; |
986 } | 951 } |
987 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); | 952 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); |
988 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, | 953 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 } | 1017 } |
1053 drawPath(d, *pathPtr, noEffectPaint, nullptr, true); | 1018 drawPath(d, *pathPtr, noEffectPaint, nullptr, true); |
1054 return; | 1019 return; |
1055 } | 1020 } |
1056 | 1021 |
1057 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { | 1022 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { |
1058 return; | 1023 return; |
1059 } | 1024 } |
1060 | 1025 |
1061 if (SkAnnotation* annotation = paint.getAnnotation()) { | 1026 if (SkAnnotation* annotation = paint.getAnnotation()) { |
1062 SkRect transformedRect = | 1027 if (handlePathAnnotation(*pathPtr, d, annotation)) { |
1063 transform_and_clip_path(d, *pathPtr, fInitialTransform) | |
1064 .getBounds(); | |
1065 SkAutoTUnref<SkPDFDict> annot( | |
1066 create_rect_annotation(transformedRect, annotation)); | |
1067 if (annot) { | |
1068 this->addAnnotation(annot.detach()); | |
1069 return; | 1028 return; |
1070 } | 1029 } |
1071 } | 1030 } |
1072 | 1031 |
1073 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); | 1032 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); |
1074 if (!content.entry()) { | 1033 if (!content.entry()) { |
1075 return; | 1034 return; |
1076 } | 1035 } |
1077 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), | 1036 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), |
1078 &content.entry()->fContent); | 1037 &content.entry()->fContent); |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1320 int vertexCount, const SkPoint verts[], | 1279 int vertexCount, const SkPoint verts[], |
1321 const SkPoint texs[], const SkColor colors[], | 1280 const SkPoint texs[], const SkColor colors[], |
1322 SkXfermode* xmode, const uint16_t indices[], | 1281 SkXfermode* xmode, const uint16_t indices[], |
1323 int indexCount, const SkPaint& paint) { | 1282 int indexCount, const SkPaint& paint) { |
1324 if (d.fClip->isEmpty()) { | 1283 if (d.fClip->isEmpty()) { |
1325 return; | 1284 return; |
1326 } | 1285 } |
1327 // TODO: implement drawVertices | 1286 // TODO: implement drawVertices |
1328 } | 1287 } |
1329 | 1288 |
| 1289 struct RectWithData { |
| 1290 SkRect rect; |
| 1291 SkAutoTUnref<const SkData> data; |
| 1292 |
| 1293 RectWithData(const SkRect& rect, const SkData* data) |
| 1294 : rect(rect), data(SkRef(data)) {} |
| 1295 }; |
| 1296 |
| 1297 struct NamedDestination { |
| 1298 SkAutoTUnref<const SkData> nameData; |
| 1299 SkPoint point; |
| 1300 |
| 1301 NamedDestination(const SkData* nameData, const SkPoint& point) |
| 1302 : nameData(SkRef(nameData)), point(point) {} |
| 1303 }; |
| 1304 |
1330 void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, | 1305 void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, |
1331 int x, int y, const SkPaint& paint) { | 1306 int x, int y, const SkPaint& paint) { |
1332 // our onCreateCompatibleDevice() always creates SkPDFDevice subclasses. | 1307 // our onCreateCompatibleDevice() always creates SkPDFDevice subclasses. |
1333 SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); | 1308 SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); |
| 1309 |
| 1310 SkScalar scalarX = SkIntToScalar(x); |
| 1311 SkScalar scalarY = SkIntToScalar(y); |
| 1312 for (RectWithData* link : pdfDevice->fLinkToURLs) { |
| 1313 fLinkToURLs.push(new RectWithData( |
| 1314 link->rect.makeOffset(scalarX, scalarY), link->data)); |
| 1315 } |
| 1316 for (RectWithData* link : pdfDevice->fLinkToDestinations) { |
| 1317 fLinkToDestinations.push(new RectWithData( |
| 1318 link->rect.makeOffset(scalarX, scalarY), link->data)); |
| 1319 } |
| 1320 for (NamedDestination* d : pdfDevice->fNamedDestinations) { |
| 1321 fNamedDestinations.push(new NamedDestination( |
| 1322 d->nameData, d->point + SkPoint::Make(scalarX, scalarY))); |
| 1323 } |
| 1324 |
1334 if (pdfDevice->isContentEmpty()) { | 1325 if (pdfDevice->isContentEmpty()) { |
1335 return; | 1326 return; |
1336 } | 1327 } |
1337 | 1328 |
1338 SkMatrix matrix; | 1329 SkMatrix matrix; |
1339 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); | 1330 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); |
1340 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); | 1331 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); |
1341 if (!content.entry()) { | 1332 if (!content.entry()) { |
1342 return; | 1333 return; |
1343 } | 1334 } |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 paint.getStrokeWidth() + SK_Scalar1); | 1541 paint.getStrokeWidth() + SK_Scalar1); |
1551 | 1542 |
1552 if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) { | 1543 if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) { |
1553 return false; | 1544 return false; |
1554 } | 1545 } |
1555 | 1546 |
1556 drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true); | 1547 drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true); |
1557 return true; | 1548 return true; |
1558 } | 1549 } |
1559 | 1550 |
1560 struct NamedDestination { | |
1561 SkAutoTUnref<const SkData> nameData; | |
1562 SkPoint point; | |
1563 | |
1564 NamedDestination(const SkData* nameData, const SkPoint& point) | |
1565 : nameData(SkRef(nameData)), point(point) {} | |
1566 }; | |
1567 | |
1568 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, | 1551 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, |
1569 const SkMatrix& matrix, | 1552 const SkMatrix& matrix, |
1570 SkAnnotation* annotationInfo) { | 1553 SkAnnotation* annotationInfo) { |
1571 SkData* nameData = annotationInfo->find( | 1554 SkData* nameData = annotationInfo->find( |
1572 SkAnnotationKeys::Define_Named_Dest_Key()); | 1555 SkAnnotationKeys::Define_Named_Dest_Key()); |
1573 if (nameData) { | 1556 if (nameData) { |
1574 SkMatrix transform = matrix; | |
1575 transform.postConcat(fInitialTransform); | |
1576 for (size_t i = 0; i < count; i++) { | 1557 for (size_t i = 0; i < count; i++) { |
1577 SkPoint translatedPoint; | 1558 SkPoint transformedPoint; |
1578 transform.mapXY(points[i].x(), points[i].y(), &translatedPoint); | 1559 matrix.mapXY(points[i].x(), points[i].y(), &transformedPoint); |
1579 fNamedDestinations.push(new NamedDestination(nameData, translatedPoi
nt)); | 1560 fNamedDestinations.push(new NamedDestination(nameData, transformedPo
int)); |
1580 } | 1561 } |
1581 return true; | 1562 return true; |
1582 } | 1563 } |
1583 return false; | 1564 return false; |
1584 } | 1565 } |
1585 | 1566 |
1586 void SkPDFDevice::addAnnotation(SkPDFDict* annotation) { | 1567 bool SkPDFDevice::handlePathAnnotation(const SkPath& path, |
1587 if (nullptr == fAnnotations) { | 1568 const SkDraw& d, |
1588 fAnnotations = new SkPDFArray; | 1569 SkAnnotation* annotation) { |
| 1570 SkASSERT(annotation); |
| 1571 |
| 1572 SkPath transformedPath = path; |
| 1573 transformedPath.transform(*d.fMatrix); |
| 1574 SkRasterClip clip = *d.fRC; |
| 1575 clip.op(transformedPath, SkISize::Make(width(), height()), SkRegion::kInters
ect_Op, false); |
| 1576 SkRect transformedRect = SkRect::Make(clip.getBounds()); |
| 1577 |
| 1578 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); |
| 1579 if (urlData) { |
| 1580 if (!transformedRect.isEmpty()) { |
| 1581 fLinkToURLs.push(new RectWithData(transformedRect, urlData)); |
| 1582 } |
| 1583 return true; |
1589 } | 1584 } |
1590 fAnnotations->appendObject(annotation); | 1585 |
| 1586 SkData* linkToDestination = |
| 1587 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); |
| 1588 if (linkToDestination) { |
| 1589 if (!transformedRect.isEmpty()) { |
| 1590 fLinkToDestinations.push(new RectWithData(transformedRect, linkToDes
tination)); |
| 1591 } |
| 1592 return true; |
| 1593 } |
| 1594 |
| 1595 return false; |
1591 } | 1596 } |
1592 | 1597 |
| 1598 void SkPDFDevice::appendAnnotations(SkPDFArray* array) const { |
| 1599 array->reserve(fLinkToURLs.count() + fLinkToDestinations.count()); |
| 1600 for (RectWithData* rectWithURL : fLinkToURLs) { |
| 1601 SkRect r; |
| 1602 fInitialTransform.mapRect(&r, rectWithURL->rect); |
| 1603 array->appendObject(create_link_to_url(rectWithURL->data, r)); |
| 1604 } |
| 1605 for (RectWithData* linkToDestination : fLinkToDestinations) { |
| 1606 SkRect r; |
| 1607 fInitialTransform.mapRect(&r, linkToDestination->rect); |
| 1608 array->appendObject(create_link_named_dest(linkToDestination->data, r)); |
| 1609 } |
| 1610 } |
1593 | 1611 |
1594 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { | 1612 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { |
1595 int nDest = fNamedDestinations.count(); | 1613 for (NamedDestination* dest : fNamedDestinations) { |
1596 for (int i = 0; i < nDest; i++) { | |
1597 NamedDestination* dest = fNamedDestinations[i]; | |
1598 SkAutoTUnref<SkPDFArray> pdfDest(new SkPDFArray); | 1614 SkAutoTUnref<SkPDFArray> pdfDest(new SkPDFArray); |
1599 pdfDest->reserve(5); | 1615 pdfDest->reserve(5); |
1600 pdfDest->appendObjRef(SkRef(page)); | 1616 pdfDest->appendObjRef(SkRef(page)); |
1601 pdfDest->appendName("XYZ"); | 1617 pdfDest->appendName("XYZ"); |
1602 pdfDest->appendScalar(dest->point.x()); | 1618 SkPoint p = fInitialTransform.mapXY(dest->point.x(), dest->point.y()); |
1603 pdfDest->appendScalar(dest->point.y()); | 1619 pdfDest->appendScalar(p.x()); |
| 1620 pdfDest->appendScalar(p.y()); |
1604 pdfDest->appendInt(0); // Leave zoom unchanged | 1621 pdfDest->appendInt(0); // Leave zoom unchanged |
1605 SkString name(static_cast<const char*>(dest->nameData->data())); | 1622 SkString name(static_cast<const char*>(dest->nameData->data())); |
1606 dict->insertObject(name, pdfDest.detach()); | 1623 dict->insertObject(name, pdfDest.detach()); |
1607 } | 1624 } |
1608 } | 1625 } |
1609 | 1626 |
1610 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { | 1627 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { |
1611 SkPDFFormXObject* xobject = new SkPDFFormXObject(this); | 1628 SkPDFFormXObject* xobject = new SkPDFFormXObject(this); |
1612 // We always draw the form xobjects that we create back into the device, so | 1629 // We always draw the form xobjects that we create back into the device, so |
1613 // we simply preserve the font usage instead of pulling it out and merging | 1630 // we simply preserve the font usage instead of pulling it out and merging |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2190 return; | 2207 return; |
2191 } | 2208 } |
2192 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); | 2209 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); |
2193 if (!image) { | 2210 if (!image) { |
2194 return; | 2211 return; |
2195 } | 2212 } |
2196 | 2213 |
2197 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), | 2214 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), |
2198 &content.entry()->fContent); | 2215 &content.entry()->fContent); |
2199 } | 2216 } |
OLD | NEW |