diff options
author | halcanary <halcanary@google.com> | 2015-06-14 11:04:58 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-14 11:04:58 -0700 |
commit | eee0e4e9d343d8b6c5ae2da7f17196f00d8859bc (patch) | |
tree | ab05da4be68da6c016d4113290626de4ccdddb3e /src | |
parent | 245c850034a3c3900ce197fa58df5afbb3d68f06 (diff) |
SkPDF: Annotations are clipped by canvas clip stack.
Also, remove some SkPDFDevice functions.
Will fix this GM: http://crrev.com/1159273003
BUG=skia:3872
Review URL: https://codereview.chromium.org/1148263005
Diffstat (limited to 'src')
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 219 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 10 |
2 files changed, 114 insertions, 115 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index b6ad6fe0da..7062e66752 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(); diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index 18be58de43..e8c287c5fb 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -293,17 +293,9 @@ private: bool handleInversePath(const SkDraw& d, const SkPath& origPath, const SkPaint& paint, bool pathIsMutable, const SkMatrix* prePathMatrix = NULL); - bool handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, - const SkPaint& paint); bool handlePointAnnotation(const SkPoint* points, size_t count, - const SkMatrix& matrix, const SkPaint& paint); + const SkMatrix& matrix, SkAnnotation* annot); void addAnnotation(SkPDFDict*); - void handleLinkToURL(SkData* urlData, const SkRect& r, - const SkMatrix& matrix); - void handleLinkToNamedDest(SkData* nameData, const SkRect& r, - const SkMatrix& matrix); - void defineNamedDestination(SkData* nameData, const SkPoint& point, - const SkMatrix& matrix); typedef SkBaseDevice INHERITED; |