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