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

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

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