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

Side by Side Diff: src/pdf/SkPDFDevice.cpp

Issue 1238503007: Reland "SkPDF: Annotations are clipped by canvas clip stack." (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Modify gm to reproduce the bug Created 5 years, 5 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 unified diff | Download patch
« no previous file with comments | « src/pdf/SkPDFDevice.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkPDFDevice.h" 8 #include "SkPDFDevice.h"
9 9
10 #include "SkAnnotation.h" 10 #include "SkAnnotation.h"
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 size_t count, 797 size_t count,
798 const SkPoint* points, 798 const SkPoint* points,
799 const SkPaint& srcPaint) { 799 const SkPaint& srcPaint) {
800 SkPaint passedPaint = srcPaint; 800 SkPaint passedPaint = srcPaint;
801 replace_srcmode_on_opaque_paint(&passedPaint); 801 replace_srcmode_on_opaque_paint(&passedPaint);
802 802
803 if (count == 0) { 803 if (count == 0) {
804 return; 804 return;
805 } 805 }
806 806
807 if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) { 807 if (SkAnnotation* annotation = passedPaint.getAnnotation()) {
808 return; 808 if (handlePointAnnotation(points, count, *d.fMatrix, annotation)) {
809 return;
810 }
809 } 811 }
810 812
811 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 813 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
812 // We only use this when there's a path effect because of the overhead 814 // We only use this when there's a path effect because of the overhead
813 // of multiple calls to setUpContentEntry it causes. 815 // of multiple calls to setUpContentEntry it causes.
814 if (passedPaint.getPathEffect()) { 816 if (passedPaint.getPathEffect()) {
815 if (d.fClip->isEmpty()) { 817 if (d.fClip->isEmpty()) {
816 return; 818 return;
817 } 819 }
818 SkDraw pointDraw(d); 820 SkDraw pointDraw(d);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 &content.entry()->fContent); 879 &content.entry()->fContent);
878 SkPDFUtils::ClosePath(&content.entry()->fContent); 880 SkPDFUtils::ClosePath(&content.entry()->fContent);
879 SkPDFUtils::StrokePath(&content.entry()->fContent); 881 SkPDFUtils::StrokePath(&content.entry()->fContent);
880 } 882 }
881 break; 883 break;
882 default: 884 default:
883 SkASSERT(false); 885 SkASSERT(false);
884 } 886 }
885 } 887 }
886 888
889 static SkPath transform_and_clip_path(const SkDraw& d,
890 const SkPath& region,
891 const SkMatrix& initialTransform) {
892 SkPath path = region;
893 SkMatrix transform = *d.fMatrix;
894 transform.postConcat(initialTransform);
895 path.transform(transform);
896 if (const SkClipStack* clipStack = d.fClipStack) {
897 SkPath clip;
898 (void)clipStack->asPath(&clip);
899 clip.transform(initialTransform);
900 Op(clip, path, SkPathOp::kIntersect_SkPathOp, &path);
901 }
902 return path;
903 }
904
905 static SkPDFDict* create_link_annotation(const SkRect& translatedRect) {
906 SkAutoTUnref<SkPDFDict> annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
907 annotation->insertName("Subtype", "Link");
908
909 SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray));
910 border->reserve(3);
911 border->appendInt(0); // Horizontal corner radius.
912 border->appendInt(0); // Vertical corner radius.
913 border->appendInt(0); // Width, 0 = no border.
914 annotation->insertObject("Border", border.detach());
915
916 SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
917 rect->reserve(4);
918 rect->appendScalar(translatedRect.fLeft);
919 rect->appendScalar(translatedRect.fTop);
920 rect->appendScalar(translatedRect.fRight);
921 rect->appendScalar(translatedRect.fBottom);
922 annotation->insertObject("Rect", rect.detach());
923
924 return annotation.detach();
925 }
926
927 static SkPDFDict* create_link_to_url(SkData* urlData, const SkRect& r) {
928 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r));
929
930 SkString url(static_cast<const char *>(urlData->data()),
931 urlData->size() - 1);
932 SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
933 action->insertName("S", "URI");
934 action->insertString("URI", url);
935 annotation->insertObject("A", action.detach());
936 return annotation.detach();
937 }
938
939 static SkPDFDict* create_link_named_dest(SkData* nameData, const SkRect& r) {
940 SkAutoTUnref<SkPDFDict> annotation(create_link_annotation(r));
941 SkString name(static_cast<const char *>(nameData->data()),
942 nameData->size() - 1);
943 annotation->insertName("Dest", name);
944 return annotation.detach();
945 }
946
947 static SkPDFDict* create_rect_annotation(const SkRect& r,
948 SkAnnotation* annotation) {
949 SkASSERT(annotation);
950 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key());
951 if (urlData) {
952 return create_link_to_url(urlData, r);
953 }
954 SkData* linkToName =
955 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key());
956 if (linkToName) {
957 return create_link_named_dest(linkToName, r);
958 }
959 return NULL;
960 }
961
887 void SkPDFDevice::drawRect(const SkDraw& d, 962 void SkPDFDevice::drawRect(const SkDraw& d,
888 const SkRect& rect, 963 const SkRect& rect,
889 const SkPaint& srcPaint) { 964 const SkPaint& srcPaint) {
890 SkPaint paint = srcPaint; 965 SkPaint paint = srcPaint;
891 replace_srcmode_on_opaque_paint(&paint); 966 replace_srcmode_on_opaque_paint(&paint);
892 SkRect r = rect; 967 SkRect r = rect;
893 r.sort(); 968 r.sort();
894 969
895 if (paint.getPathEffect()) { 970 if (paint.getPathEffect()) {
896 if (d.fClip->isEmpty()) { 971 if (d.fClip->isEmpty()) {
897 return; 972 return;
898 } 973 }
899 SkPath path; 974 SkPath path;
900 path.addRect(r); 975 path.addRect(r);
901 drawPath(d, path, paint, NULL, true); 976 drawPath(d, path, paint, NULL, true);
902 return; 977 return;
903 } 978 }
904 979
905 if (handleRectAnnotation(r, *d.fMatrix, paint)) { 980 if (SkAnnotation* annotation = paint.getAnnotation()) {
906 return; 981 SkPath path;
982 path.addRect(rect);
983 SkRect transformedRect =
984 transform_and_clip_path(d, path, fInitialTransform).getBounds();
985 SkAutoTUnref<SkPDFDict> annot(
986 create_rect_annotation(transformedRect, annotation));
987 if (annot) {
988 this->addAnnotation(annot.detach());
989 return;
990 }
907 } 991 }
908 992
909 ScopedContentEntry content(this, d, paint); 993 ScopedContentEntry content(this, d, paint);
910 if (!content.entry()) { 994 if (!content.entry()) {
911 return; 995 return;
912 } 996 }
913 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); 997 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
914 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 998 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
915 &content.entry()->fContent); 999 &content.entry()->fContent);
916 } 1000 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 noEffectPaint.setStrokeWidth(0); 1061 noEffectPaint.setStrokeWidth(0);
978 } 1062 }
979 drawPath(d, *pathPtr, noEffectPaint, NULL, true); 1063 drawPath(d, *pathPtr, noEffectPaint, NULL, true);
980 return; 1064 return;
981 } 1065 }
982 1066
983 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { 1067 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) {
984 return; 1068 return;
985 } 1069 }
986 1070
987 if (handleRectAnnotation(pathPtr->getBounds(), matrix, paint)) { 1071 if (SkAnnotation* annotation = paint.getAnnotation()) {
988 return; 1072 SkRect transformedRect =
1073 transform_and_clip_path(d, *pathPtr, fInitialTransform)
1074 .getBounds();
1075 SkAutoTUnref<SkPDFDict> annot(
1076 create_rect_annotation(transformedRect, annotation));
1077 if (annot) {
1078 this->addAnnotation(annot.detach());
1079 return;
1080 }
989 } 1081 }
990 1082
991 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); 1083 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
992 if (!content.entry()) { 1084 if (!content.entry()) {
993 return; 1085 return;
994 } 1086 }
995 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), 1087 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
996 &content.entry()->fContent); 1088 &content.entry()->fContent);
997 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(), 1089 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
998 &content.entry()->fContent); 1090 &content.entry()->fContent);
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 paint.getStrokeWidth() + SK_Scalar1); 1561 paint.getStrokeWidth() + SK_Scalar1);
1470 1562
1471 if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) { 1563 if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) {
1472 return false; 1564 return false;
1473 } 1565 }
1474 1566
1475 drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true); 1567 drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true);
1476 return true; 1568 return true;
1477 } 1569 }
1478 1570
1479 bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, 1571 struct NamedDestination {
1480 const SkPaint& p) { 1572 SkAutoTUnref<const SkData> nameData;
1481 SkAnnotation* annotationInfo = p.getAnnotation(); 1573 SkPoint point;
1482 if (!annotationInfo) { 1574
1483 return false; 1575 NamedDestination(const SkData* nameData, const SkPoint& point)
1484 } 1576 : nameData(SkRef(nameData)), point(point) {}
1485 SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key()); 1577 };
1486 if (urlData) { 1578
1487 handleLinkToURL(urlData, r, matrix); 1579 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
1488 return p.getAnnotation() != NULL; 1580 const SkMatrix& matrix,
1489 } 1581 SkAnnotation* annotationInfo) {
1490 SkData* linkToName = annotationInfo->find( 1582 SkData* nameData = annotationInfo->find(
1491 SkAnnotationKeys::Link_Named_Dest_Key()); 1583 SkAnnotationKeys::Define_Named_Dest_Key());
1492 if (linkToName) { 1584 if (nameData) {
1493 handleLinkToNamedDest(linkToName, r, matrix); 1585 SkMatrix transform = matrix;
1494 return p.getAnnotation() != NULL; 1586 transform.postConcat(fInitialTransform);
1587 for (size_t i = 0; i < count; i++) {
1588 SkPoint translatedPoint;
1589 transform.mapXY(points[i].x(), points[i].y(), &translatedPoint);
1590 fNamedDestinations.push(
1591 SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
1592
1593 }
1594 return true;
1495 } 1595 }
1496 return false; 1596 return false;
1497 } 1597 }
1498
1499 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
1500 const SkMatrix& matrix,
1501 const SkPaint& paint) {
1502 SkAnnotation* annotationInfo = paint.getAnnotation();
1503 if (!annotationInfo) {
1504 return false;
1505 }
1506 SkData* nameData = annotationInfo->find(
1507 SkAnnotationKeys::Define_Named_Dest_Key());
1508 if (nameData) {
1509 for (size_t i = 0; i < count; i++) {
1510 defineNamedDestination(nameData, points[i], matrix);
1511 }
1512 return paint.getAnnotation() != NULL;
1513 }
1514 return false;
1515 }
1516 1598
1517 void SkPDFDevice::addAnnotation(SkPDFDict* annotation) { 1599 void SkPDFDevice::addAnnotation(SkPDFDict* annotation) {
1518 if (NULL == fAnnotations) { 1600 if (NULL == fAnnotations) {
1519 fAnnotations = SkNEW(SkPDFArray); 1601 fAnnotations = SkNEW(SkPDFArray);
1520 } 1602 }
1521 fAnnotations->appendObject(annotation); 1603 fAnnotations->appendObject(annotation);
1522 } 1604 }
1523 1605
1524 static SkPDFDict* create_link_annotation(const SkRect& r,
1525 const SkMatrix& initialTransform,
1526 const SkMatrix& matrix) {
1527 SkMatrix transform = matrix;
1528 transform.postConcat(initialTransform);
1529 SkRect translatedRect;
1530 transform.mapRect(&translatedRect, r);
1531
1532 SkAutoTUnref<SkPDFDict> annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
1533 annotation->insertName("Subtype", "Link");
1534
1535 SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray));
1536 border->reserve(3);
1537 border->appendInt(0); // Horizontal corner radius.
1538 border->appendInt(0); // Vertical corner radius.
1539 border->appendInt(0); // Width, 0 = no border.
1540 annotation->insertObject("Border", border.detach());
1541
1542 SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
1543 rect->reserve(4);
1544 rect->appendScalar(translatedRect.fLeft);
1545 rect->appendScalar(translatedRect.fTop);
1546 rect->appendScalar(translatedRect.fRight);
1547 rect->appendScalar(translatedRect.fBottom);
1548 annotation->insertObject("Rect", rect.detach());
1549
1550 return annotation.detach();
1551 }
1552
1553 void SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r,
1554 const SkMatrix& matrix) {
1555 SkAutoTUnref<SkPDFDict> annotation(
1556 create_link_annotation(r, fInitialTransform, matrix));
1557
1558 SkString url(static_cast<const char *>(urlData->data()),
1559 urlData->size() - 1);
1560 SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
1561 action->insertName("S", "URI");
1562 action->insertString("URI", url);
1563 annotation->insertObject("A", action.detach());
1564 this->addAnnotation(annotation.detach());
1565 }
1566
1567 void SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r,
1568 const SkMatrix& matrix) {
1569 SkAutoTUnref<SkPDFDict> annotation(
1570 create_link_annotation(r, fInitialTransform, matrix));
1571 SkString name(static_cast<const char *>(nameData->data()),
1572 nameData->size() - 1);
1573 annotation->insertName("Dest", name);
1574 this->addAnnotation(annotation.detach());
1575 }
1576
1577 struct NamedDestination {
1578 const SkData* nameData;
1579 SkPoint point;
1580
1581 NamedDestination(const SkData* nameData, const SkPoint& point)
1582 : nameData(SkRef(nameData)), point(point) {}
1583
1584 ~NamedDestination() {
1585 nameData->unref();
1586 }
1587 };
1588
1589 void SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point,
1590 const SkMatrix& matrix) {
1591 SkMatrix transform = matrix;
1592 transform.postConcat(fInitialTransform);
1593 SkPoint translatedPoint;
1594 transform.mapXY(point.x(), point.y(), &translatedPoint);
1595 fNamedDestinations.push(
1596 SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
1597 }
1598 1606
1599 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { 1607 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const {
1600 int nDest = fNamedDestinations.count(); 1608 int nDest = fNamedDestinations.count();
1601 for (int i = 0; i < nDest; i++) { 1609 for (int i = 0; i < nDest; i++) {
1602 NamedDestination* dest = fNamedDestinations[i]; 1610 NamedDestination* dest = fNamedDestinations[i];
1603 SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray)); 1611 SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray));
1604 pdfDest->reserve(5); 1612 pdfDest->reserve(5);
1605 pdfDest->appendObjRef(SkRef(page)); 1613 pdfDest->appendObjRef(SkRef(page));
1606 pdfDest->appendName("XYZ"); 1614 pdfDest->appendName("XYZ");
1607 pdfDest->appendScalar(dest->point.x()); 1615 pdfDest->appendScalar(dest->point.x());
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
2195 return; 2203 return;
2196 } 2204 }
2197 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); 2205 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap));
2198 if (!image) { 2206 if (!image) {
2199 return; 2207 return;
2200 } 2208 }
2201 2209
2202 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), 2210 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
2203 &content.entry()->fContent); 2211 &content.entry()->fContent);
2204 } 2212 }
OLDNEW
« no previous file with comments | « src/pdf/SkPDFDevice.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698