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 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 //////////////////////////////////////////////////////////////////////////////// | 706 //////////////////////////////////////////////////////////////////////////////// |
706 | 707 |
707 SkPDFDevice::SkPDFDevice(SkISize pageSize, | 708 SkPDFDevice::SkPDFDevice(SkISize pageSize, |
708 SkScalar rasterDpi, | 709 SkScalar rasterDpi, |
709 SkPDFCanon* canon, | 710 SkPDFCanon* canon, |
710 bool flip) | 711 bool flip) |
711 : INHERITED(SkSurfaceProps(0, kUnknown_SkPixelGeometry)) | 712 : INHERITED(SkSurfaceProps(0, kUnknown_SkPixelGeometry)) |
712 , fPageSize(pageSize) | 713 , fPageSize(pageSize) |
713 , fContentSize(pageSize) | 714 , fContentSize(pageSize) |
714 , fExistingClipRegion(SkIRect::MakeSize(pageSize)) | 715 , fExistingClipRegion(SkIRect::MakeSize(pageSize)) |
715 , fAnnotations(NULL) | |
716 , fLastContentEntry(NULL) | 716 , fLastContentEntry(NULL) |
717 , fLastMarginContentEntry(NULL) | 717 , fLastMarginContentEntry(NULL) |
718 , fDrawingArea(kContent_DrawingArea) | 718 , fDrawingArea(kContent_DrawingArea) |
719 , fClipStack(NULL) | 719 , fClipStack(NULL) |
720 , fFontGlyphUsage(SkNEW(SkPDFGlyphSetMap)) | 720 , fFontGlyphUsage(SkNEW(SkPDFGlyphSetMap)) |
721 , fRasterDpi(rasterDpi) | 721 , fRasterDpi(rasterDpi) |
722 , fCanon(canon) { | 722 , fCanon(canon) { |
723 SkASSERT(pageSize.width() > 0); | 723 SkASSERT(pageSize.width() > 0); |
724 SkASSERT(pageSize.height() > 0); | 724 SkASSERT(pageSize.height() > 0); |
725 fLegacyBitmap.setInfo( | 725 fLegacyBitmap.setInfo( |
726 SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height())); | 726 SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height())); |
727 if (flip) { | 727 if (flip) { |
728 // Skia generally uses the top left as the origin but PDF | 728 // Skia generally uses the top left as the origin but PDF |
729 // natively has the origin at the bottom left. This matrix | 729 // natively has the origin at the bottom left. This matrix |
730 // corrects for that. But that only needs to be done once, we | 730 // corrects for that. But that only needs to be done once, we |
731 // don't do it when layering. | 731 // don't do it when layering. |
732 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); | 732 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); |
733 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); | 733 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); |
734 } else { | 734 } else { |
735 fInitialTransform.setIdentity(); | 735 fInitialTransform.setIdentity(); |
736 } | 736 } |
737 } | 737 } |
738 | 738 |
739 SkPDFDevice::~SkPDFDevice() { | 739 SkPDFDevice::~SkPDFDevice() { |
740 this->cleanUp(true); | 740 this->cleanUp(true); |
741 } | 741 } |
742 | 742 |
743 void SkPDFDevice::init() { | 743 void SkPDFDevice::init() { |
744 fAnnotations = NULL; | |
745 fContentEntries.free(); | 744 fContentEntries.free(); |
746 fLastContentEntry = NULL; | 745 fLastContentEntry = NULL; |
747 fMarginContentEntries.free(); | 746 fMarginContentEntries.free(); |
748 fLastMarginContentEntry = NULL; | 747 fLastMarginContentEntry = NULL; |
749 fDrawingArea = kContent_DrawingArea; | 748 fDrawingArea = kContent_DrawingArea; |
750 if (fFontGlyphUsage.get() == NULL) { | 749 if (fFontGlyphUsage.get() == NULL) { |
751 fFontGlyphUsage.reset(SkNEW(SkPDFGlyphSetMap)); | 750 fFontGlyphUsage.reset(SkNEW(SkPDFGlyphSetMap)); |
752 } | 751 } |
753 } | 752 } |
754 | 753 |
755 void SkPDFDevice::cleanUp(bool clearFontUsage) { | 754 void SkPDFDevice::cleanUp(bool clearFontUsage) { |
756 fGraphicStateResources.unrefAll(); | 755 fGraphicStateResources.unrefAll(); |
757 fXObjectResources.unrefAll(); | 756 fXObjectResources.unrefAll(); |
758 fFontResources.unrefAll(); | 757 fFontResources.unrefAll(); |
759 fShaderResources.unrefAll(); | 758 fShaderResources.unrefAll(); |
760 SkSafeUnref(fAnnotations); | 759 fLinkToURLs.deleteAll(); |
| 760 fLinkToDestinations.deleteAll(); |
761 fNamedDestinations.deleteAll(); | 761 fNamedDestinations.deleteAll(); |
762 | 762 |
763 if (clearFontUsage) { | 763 if (clearFontUsage) { |
764 fFontGlyphUsage->reset(); | 764 fFontGlyphUsage->reset(); |
765 } | 765 } |
766 } | 766 } |
767 | 767 |
768 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { | 768 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { |
769 SkPaint newPaint = paint; | 769 SkPaint newPaint = paint; |
770 replace_srcmode_on_opaque_paint(&newPaint); | 770 replace_srcmode_on_opaque_paint(&newPaint); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
879 &content.entry()->fContent); | 879 &content.entry()->fContent); |
880 SkPDFUtils::ClosePath(&content.entry()->fContent); | 880 SkPDFUtils::ClosePath(&content.entry()->fContent); |
881 SkPDFUtils::StrokePath(&content.entry()->fContent); | 881 SkPDFUtils::StrokePath(&content.entry()->fContent); |
882 } | 882 } |
883 break; | 883 break; |
884 default: | 884 default: |
885 SkASSERT(false); | 885 SkASSERT(false); |
886 } | 886 } |
887 } | 887 } |
888 | 888 |
889 static SkPath transform_and_clip_path(const SkDraw& d, | |
890 const SkPath& region, | |
891 const SkMatrix& initialTransform) { | |
892 SkPath path = region; | |
893 SkMatrix transform = *d.fMatrix; | |
894 transform.postConcat(initialTransform); | |
895 path.transform(transform); | |
896 if (const SkClipStack* clipStack = d.fClipStack) { | |
897 SkPath clip; | |
898 (void)clipStack->asPath(&clip); | |
899 clip.transform(initialTransform); | |
900 Op(clip, path, SkPathOp::kIntersect_SkPathOp, &path); | |
901 } | |
902 return path; | |
903 } | |
904 | |
905 static SkPDFDict* create_link_annotation(const SkRect& translatedRect) { | 889 static SkPDFDict* create_link_annotation(const SkRect& translatedRect) { |
906 SkAutoTUnref<SkPDFDict> annotation(SkNEW_ARGS(SkPDFDict, ("Annot"))); | 890 SkAutoTUnref<SkPDFDict> annotation(SkNEW_ARGS(SkPDFDict, ("Annot"))); |
907 annotation->insertName("Subtype", "Link"); | 891 annotation->insertName("Subtype", "Link"); |
908 | 892 |
909 SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray)); | 893 SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray)); |
910 border->reserve(3); | 894 border->reserve(3); |
911 border->appendInt(0); // Horizontal corner radius. | 895 border->appendInt(0); // Horizontal corner radius. |
912 border->appendInt(0); // Vertical corner radius. | 896 border->appendInt(0); // Vertical corner radius. |
913 border->appendInt(0); // Width, 0 = no border. | 897 border->appendInt(0); // Width, 0 = no border. |
914 annotation->insertObject("Border", border.detach()); | 898 annotation->insertObject("Border", border.detach()); |
915 | 899 |
916 SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray)); | 900 SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray)); |
917 rect->reserve(4); | 901 rect->reserve(4); |
918 rect->appendScalar(translatedRect.fLeft); | 902 rect->appendScalar(translatedRect.fLeft); |
919 rect->appendScalar(translatedRect.fTop); | 903 rect->appendScalar(translatedRect.fTop); |
920 rect->appendScalar(translatedRect.fRight); | 904 rect->appendScalar(translatedRect.fRight); |
921 rect->appendScalar(translatedRect.fBottom); | 905 rect->appendScalar(translatedRect.fBottom); |
922 annotation->insertObject("Rect", rect.detach()); | 906 annotation->insertObject("Rect", rect.detach()); |
923 | 907 |
924 return annotation.detach(); | 908 return annotation.detach(); |
925 } | 909 } |
926 | 910 |
927 static SkPDFDict* create_link_to_url(SkData* urlData, const SkRect& r) { | 911 static SkPDFDict* create_link_to_url(const SkData* urlData, const SkRect& r) { |
928 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); | 912 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); |
929 | 913 |
930 SkString url(static_cast<const char *>(urlData->data()), | 914 SkString url(static_cast<const char *>(urlData->data()), |
931 urlData->size() - 1); | 915 urlData->size() - 1); |
932 SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action"))); | 916 SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action"))); |
933 action->insertName("S", "URI"); | 917 action->insertName("S", "URI"); |
934 action->insertString("URI", url); | 918 action->insertString("URI", url); |
935 annotation->insertObject("A", action.detach()); | 919 annotation->insertObject("A", action.detach()); |
936 return annotation.detach(); | 920 return annotation.detach(); |
937 } | 921 } |
938 | 922 |
939 static SkPDFDict* create_link_named_dest(SkData* nameData, const SkRect& r) { | 923 static SkPDFDict* create_link_named_dest(const SkData* nameData, |
| 924 const SkRect& r) { |
940 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); | 925 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r)); |
941 SkString name(static_cast<const char *>(nameData->data()), | 926 SkString name(static_cast<const char *>(nameData->data()), |
942 nameData->size() - 1); | 927 nameData->size() - 1); |
943 annotation->insertName("Dest", name); | 928 annotation->insertName("Dest", name); |
944 return annotation.detach(); | 929 return annotation.detach(); |
945 } | 930 } |
946 | 931 |
947 static SkPDFDict* create_rect_annotation(const SkRect& r, | |
948 SkAnnotation* annotation) { | |
949 SkASSERT(annotation); | |
950 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); | |
951 if (urlData) { | |
952 return create_link_to_url(urlData, r); | |
953 } | |
954 SkData* linkToName = | |
955 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); | |
956 if (linkToName) { | |
957 return create_link_named_dest(linkToName, r); | |
958 } | |
959 return NULL; | |
960 } | |
961 | |
962 void SkPDFDevice::drawRect(const SkDraw& d, | 932 void SkPDFDevice::drawRect(const SkDraw& d, |
963 const SkRect& rect, | 933 const SkRect& rect, |
964 const SkPaint& srcPaint) { | 934 const SkPaint& srcPaint) { |
965 SkPaint paint = srcPaint; | 935 SkPaint paint = srcPaint; |
966 replace_srcmode_on_opaque_paint(&paint); | 936 replace_srcmode_on_opaque_paint(&paint); |
967 SkRect r = rect; | 937 SkRect r = rect; |
968 r.sort(); | 938 r.sort(); |
969 | 939 |
970 if (paint.getPathEffect()) { | 940 if (paint.getPathEffect()) { |
971 if (d.fClip->isEmpty()) { | 941 if (d.fClip->isEmpty()) { |
972 return; | 942 return; |
973 } | 943 } |
974 SkPath path; | 944 SkPath path; |
975 path.addRect(r); | 945 path.addRect(r); |
976 drawPath(d, path, paint, NULL, true); | 946 drawPath(d, path, paint, NULL, true); |
977 return; | 947 return; |
978 } | 948 } |
979 | 949 |
980 if (SkAnnotation* annotation = paint.getAnnotation()) { | 950 if (SkAnnotation* annotation = paint.getAnnotation()) { |
981 SkPath path; | 951 SkPath path; |
982 path.addRect(rect); | 952 path.addRect(rect); |
983 SkRect transformedRect = | 953 if (handlePathAnnotation(path, d, annotation)) { |
984 transform_and_clip_path(d, path, fInitialTransform).getBounds(); | |
985 SkAutoTUnref<SkPDFDict> annot( | |
986 create_rect_annotation(transformedRect, annotation)); | |
987 if (annot) { | |
988 this->addAnnotation(annot.detach()); | |
989 return; | 954 return; |
990 } | 955 } |
991 } | 956 } |
992 | 957 |
993 ScopedContentEntry content(this, d, paint); | 958 ScopedContentEntry content(this, d, paint); |
994 if (!content.entry()) { | 959 if (!content.entry()) { |
995 return; | 960 return; |
996 } | 961 } |
997 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); | 962 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); |
998 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, | 963 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1062 } | 1027 } |
1063 drawPath(d, *pathPtr, noEffectPaint, NULL, true); | 1028 drawPath(d, *pathPtr, noEffectPaint, NULL, true); |
1064 return; | 1029 return; |
1065 } | 1030 } |
1066 | 1031 |
1067 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { | 1032 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { |
1068 return; | 1033 return; |
1069 } | 1034 } |
1070 | 1035 |
1071 if (SkAnnotation* annotation = paint.getAnnotation()) { | 1036 if (SkAnnotation* annotation = paint.getAnnotation()) { |
1072 SkRect transformedRect = | 1037 if (handlePathAnnotation(*pathPtr, d, annotation)) { |
1073 transform_and_clip_path(d, *pathPtr, fInitialTransform) | |
1074 .getBounds(); | |
1075 SkAutoTUnref<SkPDFDict> annot( | |
1076 create_rect_annotation(transformedRect, annotation)); | |
1077 if (annot) { | |
1078 this->addAnnotation(annot.detach()); | |
1079 return; | 1038 return; |
1080 } | 1039 } |
1081 } | 1040 } |
1082 | 1041 |
1083 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); | 1042 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); |
1084 if (!content.entry()) { | 1043 if (!content.entry()) { |
1085 return; | 1044 return; |
1086 } | 1045 } |
1087 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), | 1046 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), |
1088 &content.entry()->fContent); | 1047 &content.entry()->fContent); |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 int vertexCount, const SkPoint verts[], | 1289 int vertexCount, const SkPoint verts[], |
1331 const SkPoint texs[], const SkColor colors[], | 1290 const SkPoint texs[], const SkColor colors[], |
1332 SkXfermode* xmode, const uint16_t indices[], | 1291 SkXfermode* xmode, const uint16_t indices[], |
1333 int indexCount, const SkPaint& paint) { | 1292 int indexCount, const SkPaint& paint) { |
1334 if (d.fClip->isEmpty()) { | 1293 if (d.fClip->isEmpty()) { |
1335 return; | 1294 return; |
1336 } | 1295 } |
1337 // TODO: implement drawVertices | 1296 // TODO: implement drawVertices |
1338 } | 1297 } |
1339 | 1298 |
| 1299 struct RectWithData { |
| 1300 SkRect rect; |
| 1301 SkAutoTUnref<const SkData> data; |
| 1302 |
| 1303 RectWithData(const SkRect& rect, const SkData* data) |
| 1304 : rect(rect), data(SkRef(data)) {} |
| 1305 }; |
| 1306 |
| 1307 struct NamedDestination { |
| 1308 SkAutoTUnref<const SkData> nameData; |
| 1309 SkPoint point; |
| 1310 |
| 1311 NamedDestination(const SkData* nameData, const SkPoint& point) |
| 1312 : nameData(SkRef(nameData)), point(point) {} |
| 1313 }; |
| 1314 |
1340 void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, | 1315 void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, |
1341 int x, int y, const SkPaint& paint) { | 1316 int x, int y, const SkPaint& paint) { |
1342 // our onCreateCompatibleDevice() always creates SkPDFDevice subclasses. | 1317 // our onCreateCompatibleDevice() always creates SkPDFDevice subclasses. |
1343 SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); | 1318 SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); |
| 1319 |
| 1320 SkScalar scalarX = SkIntToScalar(x); |
| 1321 SkScalar scalarY = SkIntToScalar(y); |
| 1322 for (RectWithData* link : pdfDevice->fLinkToURLs) { |
| 1323 fLinkToURLs.push(SkNEW_ARGS( |
| 1324 RectWithData, |
| 1325 (link->rect.makeOffset(scalarX, scalarY), link->data))); |
| 1326 } |
| 1327 for (RectWithData* link : pdfDevice->fLinkToDestinations) { |
| 1328 fLinkToDestinations.push(SkNEW_ARGS( |
| 1329 RectWithData, |
| 1330 (link->rect.makeOffset(scalarX, scalarY), link->data))); |
| 1331 } |
| 1332 for (NamedDestination* d : pdfDevice->fNamedDestinations) { |
| 1333 fNamedDestinations.push(SkNEW_ARGS( |
| 1334 NamedDestination, |
| 1335 (d->nameData, d->point + SkPoint::Make(scalarX, scalarY)))); |
| 1336 } |
| 1337 |
1344 if (pdfDevice->isContentEmpty()) { | 1338 if (pdfDevice->isContentEmpty()) { |
1345 return; | 1339 return; |
1346 } | 1340 } |
1347 | 1341 |
1348 SkMatrix matrix; | 1342 SkMatrix matrix; |
1349 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); | 1343 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); |
1350 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); | 1344 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); |
1351 if (!content.entry()) { | 1345 if (!content.entry()) { |
1352 return; | 1346 return; |
1353 } | 1347 } |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1560 paint.getStrokeWidth() + SK_Scalar1); | 1554 paint.getStrokeWidth() + SK_Scalar1); |
1561 | 1555 |
1562 if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) { | 1556 if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) { |
1563 return false; | 1557 return false; |
1564 } | 1558 } |
1565 | 1559 |
1566 drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true); | 1560 drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true); |
1567 return true; | 1561 return true; |
1568 } | 1562 } |
1569 | 1563 |
1570 struct NamedDestination { | |
1571 SkAutoTUnref<const SkData> nameData; | |
1572 SkPoint point; | |
1573 | |
1574 NamedDestination(const SkData* nameData, const SkPoint& point) | |
1575 : nameData(SkRef(nameData)), point(point) {} | |
1576 }; | |
1577 | |
1578 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, | 1564 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, |
1579 const SkMatrix& matrix, | 1565 const SkMatrix& matrix, |
1580 SkAnnotation* annotationInfo) { | 1566 SkAnnotation* annotationInfo) { |
1581 SkData* nameData = annotationInfo->find( | 1567 SkData* nameData = annotationInfo->find( |
1582 SkAnnotationKeys::Define_Named_Dest_Key()); | 1568 SkAnnotationKeys::Define_Named_Dest_Key()); |
1583 if (nameData) { | 1569 if (nameData) { |
1584 SkMatrix transform = matrix; | |
1585 transform.postConcat(fInitialTransform); | |
1586 for (size_t i = 0; i < count; i++) { | 1570 for (size_t i = 0; i < count; i++) { |
1587 SkPoint translatedPoint; | 1571 SkPoint transformedPoint; |
1588 transform.mapXY(points[i].x(), points[i].y(), &translatedPoint); | 1572 matrix.mapXY(points[i].x(), points[i].y(), &transformedPoint); |
1589 fNamedDestinations.push( | 1573 fNamedDestinations.push( |
1590 SkNEW_ARGS(NamedDestination, (nameData, translatedPoint))); | 1574 SkNEW_ARGS(NamedDestination, (nameData, transformedPoint))); |
1591 | |
1592 } | 1575 } |
1593 return true; | 1576 return true; |
1594 } | 1577 } |
1595 return false; | 1578 return false; |
1596 } | 1579 } |
1597 | 1580 |
1598 void SkPDFDevice::addAnnotation(SkPDFDict* annotation) { | 1581 bool SkPDFDevice::handlePathAnnotation(const SkPath& path, |
1599 if (NULL == fAnnotations) { | 1582 const SkDraw& d, |
1600 fAnnotations = SkNEW(SkPDFArray); | 1583 SkAnnotation* annotation) { |
| 1584 SkASSERT(annotation); |
| 1585 |
| 1586 SkPath transformedPath = path; |
| 1587 transformedPath.transform(*d.fMatrix); |
| 1588 SkRasterClip clip = *d.fRC; |
| 1589 clip.op(transformedPath, SkISize::Make(width(), height()), SkRegion::kInters
ect_Op, false); |
| 1590 SkRect transformedRect = SkRect::Make(clip.getBounds()); |
| 1591 |
| 1592 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); |
| 1593 if (urlData) { |
| 1594 if (!transformedRect.isEmpty()) { |
| 1595 fLinkToURLs.push(SkNEW_ARGS( |
| 1596 RectWithData, (transformedRect, urlData))); |
| 1597 } |
| 1598 return true; |
1601 } | 1599 } |
1602 fAnnotations->appendObject(annotation); | 1600 |
| 1601 SkData* linkToDestination = |
| 1602 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); |
| 1603 if (linkToDestination) { |
| 1604 if (!transformedRect.isEmpty()) { |
| 1605 fLinkToDestinations.push(SkNEW_ARGS( |
| 1606 RectWithData, (transformedRect, linkToDestination))); |
| 1607 } |
| 1608 return true; |
| 1609 } |
| 1610 |
| 1611 return false; |
1603 } | 1612 } |
1604 | 1613 |
| 1614 void SkPDFDevice::appendAnnotations(SkPDFArray* array) const { |
| 1615 array->reserve(fLinkToURLs.count() + fLinkToDestinations.count()); |
| 1616 for (RectWithData* rectWithURL : fLinkToURLs) { |
| 1617 SkRect r; |
| 1618 fInitialTransform.mapRect(&r, rectWithURL->rect); |
| 1619 array->appendObject(create_link_to_url(rectWithURL->data, r)); |
| 1620 } |
| 1621 for (RectWithData* linkToDestination : fLinkToDestinations) { |
| 1622 SkRect r; |
| 1623 fInitialTransform.mapRect(&r, linkToDestination->rect); |
| 1624 array->appendObject(create_link_named_dest(linkToDestination->data, r)); |
| 1625 } |
| 1626 } |
1605 | 1627 |
1606 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { | 1628 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { |
1607 int nDest = fNamedDestinations.count(); | 1629 for (NamedDestination* dest : fNamedDestinations) { |
1608 for (int i = 0; i < nDest; i++) { | |
1609 NamedDestination* dest = fNamedDestinations[i]; | |
1610 SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray)); | 1630 SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray)); |
1611 pdfDest->reserve(5); | 1631 pdfDest->reserve(5); |
1612 pdfDest->appendObjRef(SkRef(page)); | 1632 pdfDest->appendObjRef(SkRef(page)); |
1613 pdfDest->appendName("XYZ"); | 1633 pdfDest->appendName("XYZ"); |
1614 pdfDest->appendScalar(dest->point.x()); | 1634 SkPoint p = fInitialTransform.mapXY(dest->point.x(), dest->point.y()); |
1615 pdfDest->appendScalar(dest->point.y()); | 1635 pdfDest->appendScalar(p.x()); |
| 1636 pdfDest->appendScalar(p.y()); |
1616 pdfDest->appendInt(0); // Leave zoom unchanged | 1637 pdfDest->appendInt(0); // Leave zoom unchanged |
1617 SkString name(static_cast<const char*>(dest->nameData->data())); | 1638 SkString name(static_cast<const char*>(dest->nameData->data())); |
1618 dict->insertObject(name, pdfDest.detach()); | 1639 dict->insertObject(name, pdfDest.detach()); |
1619 } | 1640 } |
1620 } | 1641 } |
1621 | 1642 |
1622 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { | 1643 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { |
1623 SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this)); | 1644 SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this)); |
1624 // We always draw the form xobjects that we create back into the device, so | 1645 // We always draw the form xobjects that we create back into the device, so |
1625 // we simply preserve the font usage instead of pulling it out and merging | 1646 // 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... |
2202 return; | 2223 return; |
2203 } | 2224 } |
2204 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); | 2225 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); |
2205 if (!image) { | 2226 if (!image) { |
2206 return; | 2227 return; |
2207 } | 2228 } |
2208 | 2229 |
2209 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), | 2230 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), |
2210 &content.entry()->fContent); | 2231 &content.entry()->fContent); |
2211 } | 2232 } |
OLD | NEW |