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