diff options
author | wangxianzhu <wangxianzhu@chromium.org> | 2015-07-17 17:23:15 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-17 17:23:15 -0700 |
commit | d76665da1c93372720506ce7763cc810223ee9ee (patch) | |
tree | 4bc7faa02e7a47c18893e844f3ba9dd5f0b6d3fa | |
parent | 97a26d04e2a9324e7fc84c8a78d399e3484c9f50 (diff) |
Reland "SkPDF: Annotations are clipped by canvas clip stack."
Original patch was created by halcanary@google.com, and was reverted
because it triggered crbug.com/503541.
This patch fixes a bug in the original patch about clip path
transformation.
> Also, remove some SkPDFDevice functions.
> Will fix this GM: http://crrev.com/1159273003
> BUG=skia:3872
> Review URL: https://codereview.chromium.org/1148263005
BUG=skia:3872
BUG=503514
Review URL: https://codereview.chromium.org/1238503007
-rw-r--r-- | gm/annotated_text.cpp | 2 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 220 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 10 |
3 files changed, 116 insertions, 116 deletions
diff --git a/gm/annotated_text.cpp b/gm/annotated_text.cpp index ab7e816126..7126206eeb 100644 --- a/gm/annotated_text.cpp +++ b/gm/annotated_text.cpp @@ -27,7 +27,7 @@ static void draw_url_annotated_text_with_box( DEF_SIMPLE_GM(annotated_text, canvas, 512, 512) { SkAutoCanvasRestore autoCanvasRestore(canvas, true); canvas->clear(SK_ColorWHITE); - canvas->clipRect(SkRect::MakeXYWH(64, 64, 384, 384)); + canvas->clipRect(SkRect::MakeXYWH(64, 64, 256, 256)); canvas->clear(0xFFEEEEEE); SkPaint p; p.setTextSize(40); diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 7ca6c2200e..957480d5df 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -804,8 +804,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. @@ -884,6 +886,79 @@ 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); + clip.transform(initialTransform); + 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) { @@ -902,8 +977,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); @@ -984,8 +1068,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); @@ -1476,40 +1568,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; } @@ -1521,80 +1603,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 bb12a3f6dc..5c391c3ccd 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -292,17 +292,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; |