| Index: src/pdf/SkPDFDevice.cpp
|
| diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
|
| index b6ad6fe0da97738cce22cde836a84913f060e170..7062e66752e25b9d45e14c66f77594f0404ae4cc 100644
|
| --- a/src/pdf/SkPDFDevice.cpp
|
| +++ b/src/pdf/SkPDFDevice.cpp
|
| @@ -803,8 +803,10 @@ void SkPDFDevice::drawPoints(const SkDraw& d,
|
| return;
|
| }
|
|
|
| - if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) {
|
| - return;
|
| + if (SkAnnotation* annotation = passedPaint.getAnnotation()) {
|
| + if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) {
|
| + return;
|
| + }
|
| }
|
|
|
| // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
|
| @@ -883,6 +885,78 @@ void SkPDFDevice::drawPoints(const SkDraw& d,
|
| }
|
| }
|
|
|
| +static SkPath transform_and_clip_path(const SkDraw& d,
|
| + const SkPath& region,
|
| + const SkMatrix& initialTransform) {
|
| + SkPath path = region;
|
| + SkMatrix transform = *d.fMatrix;
|
| + transform.postConcat(initialTransform);
|
| + path.transform(transform);
|
| + if (const SkClipStack* clipStack = d.fClipStack) {
|
| + SkPath clip;
|
| + (void)clipStack->asPath(&clip);
|
| + Op(clip, path, SkPathOp::kIntersect_SkPathOp, &path);
|
| + }
|
| + return path;
|
| +}
|
| +
|
| +static SkPDFDict* create_link_annotation(const SkRect& translatedRect) {
|
| + SkAutoTUnref<SkPDFDict> annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
|
| + annotation->insertName("Subtype", "Link");
|
| +
|
| + 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->insertObject("Border", border.detach());
|
| +
|
| + SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
|
| + rect->reserve(4);
|
| + rect->appendScalar(translatedRect.fLeft);
|
| + rect->appendScalar(translatedRect.fTop);
|
| + rect->appendScalar(translatedRect.fRight);
|
| + rect->appendScalar(translatedRect.fBottom);
|
| + annotation->insertObject("Rect", rect.detach());
|
| +
|
| + return annotation.detach();
|
| +}
|
| +
|
| +static SkPDFDict* create_link_to_url(SkData* urlData, const SkRect& r) {
|
| + SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r));
|
| +
|
| + SkString url(static_cast<const char *>(urlData->data()),
|
| + urlData->size() - 1);
|
| + SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
|
| + action->insertName("S", "URI");
|
| + action->insertString("URI", url);
|
| + annotation->insertObject("A", action.detach());
|
| + return annotation.detach();
|
| +}
|
| +
|
| +static SkPDFDict* create_link_named_dest(SkData* nameData, const SkRect& r) {
|
| + SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r));
|
| + SkString name(static_cast<const char *>(nameData->data()),
|
| + nameData->size() - 1);
|
| + annotation->insertName("Dest", name);
|
| + return annotation.detach();
|
| +}
|
| +
|
| +static SkPDFDict* create_rect_annotation(const SkRect& r,
|
| + SkAnnotation* annotation) {
|
| + SkASSERT(annotation);
|
| + SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key());
|
| + if (urlData) {
|
| + return create_link_to_url(urlData, r);
|
| + }
|
| + SkData* linkToName =
|
| + annotation->find(SkAnnotationKeys::Link_Named_Dest_Key());
|
| + if (linkToName) {
|
| + return create_link_named_dest(linkToName, r);
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| void SkPDFDevice::drawRect(const SkDraw& d,
|
| const SkRect& rect,
|
| const SkPaint& srcPaint) {
|
| @@ -901,8 +975,17 @@ void SkPDFDevice::drawRect(const SkDraw& d,
|
| return;
|
| }
|
|
|
| - if (handleRectAnnotation(r, *d.fMatrix, paint)) {
|
| - return;
|
| + if (SkAnnotation* annotation = paint.getAnnotation()) {
|
| + SkPath path;
|
| + path.addRect(rect);
|
| + SkRect transformedRect =
|
| + transform_and_clip_path(d, path, fInitialTransform).getBounds();
|
| + SkAutoTUnref<SkPDFDict> annot(
|
| + create_rect_annotation(transformedRect, annotation));
|
| + if (annot) {
|
| + this->addAnnotation(annot.detach());
|
| + return;
|
| + }
|
| }
|
|
|
| ScopedContentEntry content(this, d, paint);
|
| @@ -983,8 +1066,16 @@ void SkPDFDevice::drawPath(const SkDraw& d,
|
| return;
|
| }
|
|
|
| - if (handleRectAnnotation(pathPtr->getBounds(), matrix, paint)) {
|
| - return;
|
| + if (SkAnnotation* annotation = paint.getAnnotation()) {
|
| + SkRect transformedRect =
|
| + transform_and_clip_path(d, *pathPtr, fInitialTransform)
|
| + .getBounds();
|
| + SkAutoTUnref<SkPDFDict> annot(
|
| + create_rect_annotation(transformedRect, annotation));
|
| + if (annot) {
|
| + this->addAnnotation(annot.detach());
|
| + return;
|
| + }
|
| }
|
|
|
| ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
|
| @@ -1475,40 +1566,30 @@ bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath,
|
| return true;
|
| }
|
|
|
| -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) {
|
| - handleLinkToURL(urlData, r, matrix);
|
| - return p.getAnnotation() != NULL;
|
| - }
|
| - SkData* linkToName = annotationInfo->find(
|
| - SkAnnotationKeys::Link_Named_Dest_Key());
|
| - if (linkToName) {
|
| - handleLinkToNamedDest(linkToName, r, matrix);
|
| - return p.getAnnotation() != NULL;
|
| - }
|
| - return false;
|
| -}
|
| +struct NamedDestination {
|
| + SkAutoTUnref<const SkData> nameData;
|
| + SkPoint point;
|
| +
|
| + NamedDestination(const SkData* nameData, const SkPoint& point)
|
| + : nameData(SkRef(nameData)), point(point) {}
|
| +};
|
|
|
| bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
|
| const SkMatrix& matrix,
|
| - const SkPaint& paint) {
|
| - SkAnnotation* annotationInfo = paint.getAnnotation();
|
| - if (!annotationInfo) {
|
| - return false;
|
| - }
|
| + SkAnnotation* annotationInfo) {
|
| SkData* nameData = annotationInfo->find(
|
| SkAnnotationKeys::Define_Named_Dest_Key());
|
| if (nameData) {
|
| + SkMatrix transform = matrix;
|
| + transform.postConcat(fInitialTransform);
|
| for (size_t i = 0; i < count; i++) {
|
| - defineNamedDestination(nameData, points[i], matrix);
|
| + SkPoint translatedPoint;
|
| + transform.mapXY(points[i].x(), points[i].y(), &translatedPoint);
|
| + fNamedDestinations.push(
|
| + SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
|
| +
|
| }
|
| - return paint.getAnnotation() != NULL;
|
| + return true;
|
| }
|
| return false;
|
| }
|
| @@ -1520,80 +1601,6 @@ void SkPDFDevice::addAnnotation(SkPDFDict* annotation) {
|
| fAnnotations->appendObject(annotation);
|
| }
|
|
|
| -static SkPDFDict* create_link_annotation(const SkRect& r,
|
| - const SkMatrix& initialTransform,
|
| - const SkMatrix& matrix) {
|
| - SkMatrix transform = matrix;
|
| - transform.postConcat(initialTransform);
|
| - SkRect translatedRect;
|
| - transform.mapRect(&translatedRect, r);
|
| -
|
| - SkAutoTUnref<SkPDFDict> annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
|
| - annotation->insertName("Subtype", "Link");
|
| -
|
| - 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->insertObject("Border", border.detach());
|
| -
|
| - SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
|
| - rect->reserve(4);
|
| - rect->appendScalar(translatedRect.fLeft);
|
| - rect->appendScalar(translatedRect.fTop);
|
| - rect->appendScalar(translatedRect.fRight);
|
| - rect->appendScalar(translatedRect.fBottom);
|
| - annotation->insertObject("Rect", rect.detach());
|
| -
|
| - return annotation.detach();
|
| -}
|
| -
|
| -void SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r,
|
| - const SkMatrix& matrix) {
|
| - SkAutoTUnref<SkPDFDict> annotation(
|
| - create_link_annotation(r, fInitialTransform, matrix));
|
| -
|
| - SkString url(static_cast<const char *>(urlData->data()),
|
| - urlData->size() - 1);
|
| - SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
|
| - action->insertName("S", "URI");
|
| - action->insertString("URI", url);
|
| - annotation->insertObject("A", action.detach());
|
| - this->addAnnotation(annotation.detach());
|
| -}
|
| -
|
| -void SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r,
|
| - const SkMatrix& matrix) {
|
| - SkAutoTUnref<SkPDFDict> annotation(
|
| - create_link_annotation(r, fInitialTransform, matrix));
|
| - SkString name(static_cast<const char *>(nameData->data()),
|
| - nameData->size() - 1);
|
| - annotation->insertName("Dest", name);
|
| - this->addAnnotation(annotation.detach());
|
| -}
|
| -
|
| -struct NamedDestination {
|
| - const SkData* nameData;
|
| - SkPoint point;
|
| -
|
| - NamedDestination(const SkData* nameData, const SkPoint& point)
|
| - : nameData(SkRef(nameData)), point(point) {}
|
| -
|
| - ~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) const {
|
| int nDest = fNamedDestinations.count();
|
|
|