Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(595)

Unified Diff: src/pdf/SkPDFDevice.cpp

Issue 12466008: PDF: add support for named destinations (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/gpu/SkGpuDevice.cpp ('k') | src/pdf/SkPDFDocument.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pdf/SkPDFDevice.cpp
===================================================================
--- src/pdf/SkPDFDevice.cpp (revision 7989)
+++ src/pdf/SkPDFDevice.cpp (working copy)
@@ -645,6 +645,7 @@
fShaderResources.unrefAll();
SkSafeUnref(fAnnotations);
SkSafeUnref(fResourceDict);
+ fNamedDestinations.deleteAll();
if (clearFontUsage) {
fFontGlyphUsage->reset();
@@ -703,6 +704,10 @@
return;
}
+ if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) {
+ return;
+ }
+
// SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
// We only use this when there's a path effect because of the overhead
// of multiple calls to setUpContentEntry it causes.
@@ -791,7 +796,7 @@
return;
}
- if (handleAnnotations(r, *d.fMatrix, paint)) {
+ if (handleRectAnnotation(r, *d.fMatrix, paint)) {
return;
}
@@ -847,7 +852,7 @@
return;
}
- if (handleAnnotations(pathPtr->getBounds(), *d.fMatrix, paint)) {
+ if (handleRectAnnotation(pathPtr->getBounds(), *d.fMatrix, paint)) {
return;
}
@@ -1286,19 +1291,43 @@
return data.copyToData();
}
-bool SkPDFDevice::handleAnnotations(const SkRect& r, const SkMatrix& matrix,
- const SkPaint& p) {
+bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
+ const SkPaint& p) {
SkAnnotation* annotationInfo = p.getAnnotation();
if (!annotationInfo) {
return false;
}
SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key());
- if (!urlData) {
+ if (urlData) {
+ handleLinkToURL(urlData, r, matrix);
+ return p.isNoDrawAnnotation();
+ }
+ SkData* linkToName = annotationInfo->find(SkAnnotationKeys::Link_Named_Dest_Key());
+ if (linkToName) {
+ handleLinkToNamedDest(linkToName, r, matrix);
+ return p.isNoDrawAnnotation();
+ }
+ return false;
+}
+
+bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
+ const SkMatrix& matrix,
+ const SkPaint& paint) {
+ SkAnnotation* annotationInfo = paint.getAnnotation();
+ if (!annotationInfo) {
return false;
}
+ SkData* nameData = annotationInfo->find(SkAnnotationKeys::Define_Named_Dest_Key());
+ if (nameData) {
+ for (size_t i = 0; i < count; i++) {
+ defineNamedDestination(nameData, points[i], matrix);
+ }
+ return paint.isNoDrawAnnotation();
+ }
+ return false;
+}
- SkString url(static_cast<const char *>(urlData->data()),
- urlData->size() - 1);
+SkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r, const SkMatrix& matrix) {
SkMatrix transform = matrix;
transform.postConcat(fInitialTransform);
SkRect translatedRect;
@@ -1307,18 +1336,18 @@
if (NULL == fAnnotations) {
fAnnotations = SkNEW(SkPDFArray);
}
- SkAutoTUnref<SkPDFDict> annotation(new SkPDFDict("Annot"));
+ SkPDFDict* annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
annotation->insertName("Subtype", "Link");
- fAnnotations->append(annotation.get());
+ fAnnotations->append(annotation);
- SkAutoTUnref<SkPDFArray> border(new SkPDFArray);
+ SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray));
border->reserve(3);
border->appendInt(0); // Horizontal corner radius.
border->appendInt(0); // Vertical corner radius.
border->appendInt(0); // Width, 0 = no border.
annotation->insert("Border", border.get());
- SkAutoTUnref<SkPDFArray> rect(new SkPDFArray);
+ SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
rect->reserve(4);
rect->appendScalar(translatedRect.fLeft);
rect->appendScalar(translatedRect.fTop);
@@ -1326,14 +1355,68 @@
rect->appendScalar(translatedRect.fBottom);
annotation->insert("Rect", rect.get());
- SkAutoTUnref<SkPDFDict> action(new SkPDFDict("Action"));
+ return annotation;
+}
+
+void SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r,
+ const SkMatrix& matrix) {
+ SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
+
+ SkString url(static_cast<const char *>(urlData->data()),
+ urlData->size() - 1);
+ SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
action->insertName("S", "URI");
- action->insert("URI", new SkPDFString(url))->unref();
+ action->insert("URI", SkNEW_ARGS(SkPDFString, (url)))->unref();
annotation->insert("A", action.get());
+}
- return p.isNoDrawAnnotation();
+void SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r,
+ const SkMatrix& matrix) {
+ SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
+ SkString name(static_cast<const char *>(nameData->data()),
+ nameData->size() - 1);
+ annotation->insert("Dest", SkNEW_ARGS(SkPDFString, (name)))->unref();
}
+struct NamedDestination {
+ const SkData* nameData;
+ SkPoint point;
+
+ NamedDestination(const SkData* nameData, const SkPoint& point)
+ : nameData(nameData), point(point) {
+ nameData->ref();
+ }
+
+ ~NamedDestination() {
+ nameData->unref();
+ }
+};
+
+void SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point,
+ const SkMatrix& matrix) {
+ SkMatrix transform = matrix;
+ transform.postConcat(fInitialTransform);
+ SkPoint translatedPoint;
+ transform.mapXY(point.x(), point.y(), &translatedPoint);
+ fNamedDestinations.push(
+ SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
+}
+
+void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) {
+ int nDest = fNamedDestinations.count();
+ for (int i = 0; i < nDest; i++) {
+ NamedDestination* dest = fNamedDestinations[i];
+ SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray));
+ pdfDest->reserve(5);
+ pdfDest->append(SkNEW_ARGS(SkPDFObjRef, (page)))->unref();
+ pdfDest->appendName("XYZ");
+ pdfDest->appendInt(dest->point.x());
+ pdfDest->appendInt(dest->point.y());
+ pdfDest->appendInt(0); // Leave zoom unchanged
+ dict->insert(static_cast<const char *>(dest->nameData->data()), pdfDest);
+ }
+}
+
SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() {
SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this));
// We always draw the form xobjects that we create back into the device, so
« no previous file with comments | « src/gpu/SkGpuDevice.cpp ('k') | src/pdf/SkPDFDocument.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698