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

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

Issue 12466008: PDF: add support for named destinations (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « src/gpu/SkGpuDevice.cpp ('k') | src/pdf/SkPDFDocument.cpp » ('j') | 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 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkPDFDevice.h" 10 #include "SkPDFDevice.h"
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 } 638 }
639 } 639 }
640 640
641 void SkPDFDevice::cleanUp(bool clearFontUsage) { 641 void SkPDFDevice::cleanUp(bool clearFontUsage) {
642 fGraphicStateResources.unrefAll(); 642 fGraphicStateResources.unrefAll();
643 fXObjectResources.unrefAll(); 643 fXObjectResources.unrefAll();
644 fFontResources.unrefAll(); 644 fFontResources.unrefAll();
645 fShaderResources.unrefAll(); 645 fShaderResources.unrefAll();
646 SkSafeUnref(fAnnotations); 646 SkSafeUnref(fAnnotations);
647 SkSafeUnref(fResourceDict); 647 SkSafeUnref(fResourceDict);
648 fNamedDestinations.deleteAll();
648 649
649 if (clearFontUsage) { 650 if (clearFontUsage) {
650 fFontGlyphUsage->reset(); 651 fFontGlyphUsage->reset();
651 } 652 }
652 } 653 }
653 654
654 uint32_t SkPDFDevice::getDeviceCapabilities() { 655 uint32_t SkPDFDevice::getDeviceCapabilities() {
655 return kVector_Capability; 656 return kVector_Capability;
656 } 657 }
657 658
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 &contentEntry->fContent); 697 &contentEntry->fContent);
697 } 698 }
698 699
699 void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, 700 void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
700 size_t count, const SkPoint* points, 701 size_t count, const SkPoint* points,
701 const SkPaint& passedPaint) { 702 const SkPaint& passedPaint) {
702 if (count == 0) { 703 if (count == 0) {
703 return; 704 return;
704 } 705 }
705 706
707 if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) {
708 return;
709 }
710
706 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 711 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
707 // We only use this when there's a path effect because of the overhead 712 // We only use this when there's a path effect because of the overhead
708 // of multiple calls to setUpContentEntry it causes. 713 // of multiple calls to setUpContentEntry it causes.
709 if (passedPaint.getPathEffect()) { 714 if (passedPaint.getPathEffect()) {
710 if (d.fClip->isEmpty()) { 715 if (d.fClip->isEmpty()) {
711 return; 716 return;
712 } 717 }
713 SkDraw pointDraw(d); 718 SkDraw pointDraw(d);
714 pointDraw.fDevice = this; 719 pointDraw.fDevice = this;
715 pointDraw.drawPoints(mode, count, points, passedPaint, true); 720 pointDraw.drawPoints(mode, count, points, passedPaint, true);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 if (paint.getPathEffect()) { 789 if (paint.getPathEffect()) {
785 if (d.fClip->isEmpty()) { 790 if (d.fClip->isEmpty()) {
786 return; 791 return;
787 } 792 }
788 SkPath path; 793 SkPath path;
789 path.addRect(r); 794 path.addRect(r);
790 drawPath(d, path, paint, NULL, true); 795 drawPath(d, path, paint, NULL, true);
791 return; 796 return;
792 } 797 }
793 798
794 if (handleAnnotations(r, *d.fMatrix, paint)) { 799 if (handleRectAnnotation(r, *d.fMatrix, paint)) {
795 return; 800 return;
796 } 801 }
797 802
798 ScopedContentEntry content(this, d, paint); 803 ScopedContentEntry content(this, d, paint);
799 if (!content.entry()) { 804 if (!content.entry()) {
800 return; 805 return;
801 } 806 }
802 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); 807 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
803 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 808 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
804 &content.entry()->fContent); 809 &content.entry()->fContent);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 if (fill) { 845 if (fill) {
841 noEffectPaint.setStyle(SkPaint::kFill_Style); 846 noEffectPaint.setStyle(SkPaint::kFill_Style);
842 } else { 847 } else {
843 noEffectPaint.setStyle(SkPaint::kStroke_Style); 848 noEffectPaint.setStyle(SkPaint::kStroke_Style);
844 noEffectPaint.setStrokeWidth(0); 849 noEffectPaint.setStrokeWidth(0);
845 } 850 }
846 drawPath(d, *pathPtr, noEffectPaint, NULL, true); 851 drawPath(d, *pathPtr, noEffectPaint, NULL, true);
847 return; 852 return;
848 } 853 }
849 854
850 if (handleAnnotations(pathPtr->getBounds(), *d.fMatrix, paint)) { 855 if (handleRectAnnotation(pathPtr->getBounds(), *d.fMatrix, paint)) {
851 return; 856 return;
852 } 857 }
853 858
854 ScopedContentEntry content(this, d, paint); 859 ScopedContentEntry content(this, d, paint);
855 if (!content.entry()) { 860 if (!content.entry()) {
856 return; 861 return;
857 } 862 }
858 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), 863 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
859 &content.entry()->fContent); 864 &content.entry()->fContent);
860 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(), 865 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 emit_clip(NULL, &r, &data); 1284 emit_clip(NULL, &r, &data);
1280 } 1285 }
1281 1286
1282 SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), &data); 1287 SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), &data);
1283 1288
1284 // potentially we could cache this SkData, and only rebuild it if we 1289 // potentially we could cache this SkData, and only rebuild it if we
1285 // see that our state has changed. 1290 // see that our state has changed.
1286 return data.copyToData(); 1291 return data.copyToData();
1287 } 1292 }
1288 1293
1289 bool SkPDFDevice::handleAnnotations(const SkRect& r, const SkMatrix& matrix, 1294 bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
1290 const SkPaint& p) { 1295 const SkPaint& p) {
1291 SkAnnotation* annotationInfo = p.getAnnotation(); 1296 SkAnnotation* annotationInfo = p.getAnnotation();
1292 if (!annotationInfo) { 1297 if (!annotationInfo) {
1293 return false; 1298 return false;
1294 } 1299 }
1295 SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key()); 1300 SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key());
1296 if (!urlData) { 1301 if (urlData) {
1302 handleLinkToURL(urlData, r, matrix);
1303 return p.isNoDrawAnnotation();
1304 }
1305 SkData* linkToName = annotationInfo->find(SkAnnotationKeys::Link_Named_Dest_ Key());
1306 if (linkToName) {
1307 handleLinkToNamedDest(linkToName, r, matrix);
1308 return p.isNoDrawAnnotation();
1309 }
1310 return false;
1311 }
1312
1313 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
1314 const SkMatrix& matrix,
1315 const SkPaint& paint) {
1316 SkAnnotation* annotationInfo = paint.getAnnotation();
1317 if (!annotationInfo) {
1297 return false; 1318 return false;
1298 } 1319 }
1320 SkData* nameData = annotationInfo->find(SkAnnotationKeys::Define_Named_Dest_ Key());
1321 if (nameData) {
1322 for (size_t i = 0; i < count; i++) {
1323 defineNamedDestination(nameData, points[i], matrix);
1324 }
1325 return paint.isNoDrawAnnotation();
1326 }
1327 return false;
1328 }
1299 1329
1300 SkString url(static_cast<const char *>(urlData->data()), 1330 SkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r, const SkMatrix& ma trix) {
1301 urlData->size() - 1);
1302 SkMatrix transform = matrix; 1331 SkMatrix transform = matrix;
1303 transform.postConcat(fInitialTransform); 1332 transform.postConcat(fInitialTransform);
1304 SkRect translatedRect; 1333 SkRect translatedRect;
1305 transform.mapRect(&translatedRect, r); 1334 transform.mapRect(&translatedRect, r);
1306 1335
1307 if (NULL == fAnnotations) { 1336 if (NULL == fAnnotations) {
1308 fAnnotations = SkNEW(SkPDFArray); 1337 fAnnotations = SkNEW(SkPDFArray);
1309 } 1338 }
1310 SkAutoTUnref<SkPDFDict> annotation(new SkPDFDict("Annot")); 1339 SkPDFDict* annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
1311 annotation->insertName("Subtype", "Link"); 1340 annotation->insertName("Subtype", "Link");
1312 fAnnotations->append(annotation.get()); 1341 fAnnotations->append(annotation);
1313 1342
1314 SkAutoTUnref<SkPDFArray> border(new SkPDFArray); 1343 SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray));
1315 border->reserve(3); 1344 border->reserve(3);
1316 border->appendInt(0); // Horizontal corner radius. 1345 border->appendInt(0); // Horizontal corner radius.
1317 border->appendInt(0); // Vertical corner radius. 1346 border->appendInt(0); // Vertical corner radius.
1318 border->appendInt(0); // Width, 0 = no border. 1347 border->appendInt(0); // Width, 0 = no border.
1319 annotation->insert("Border", border.get()); 1348 annotation->insert("Border", border.get());
1320 1349
1321 SkAutoTUnref<SkPDFArray> rect(new SkPDFArray); 1350 SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
1322 rect->reserve(4); 1351 rect->reserve(4);
1323 rect->appendScalar(translatedRect.fLeft); 1352 rect->appendScalar(translatedRect.fLeft);
1324 rect->appendScalar(translatedRect.fTop); 1353 rect->appendScalar(translatedRect.fTop);
1325 rect->appendScalar(translatedRect.fRight); 1354 rect->appendScalar(translatedRect.fRight);
1326 rect->appendScalar(translatedRect.fBottom); 1355 rect->appendScalar(translatedRect.fBottom);
1327 annotation->insert("Rect", rect.get()); 1356 annotation->insert("Rect", rect.get());
1328 1357
1329 SkAutoTUnref<SkPDFDict> action(new SkPDFDict("Action")); 1358 return annotation;
1359 }
1360
1361 void SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r,
1362 const SkMatrix& matrix) {
1363 SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
1364
1365 SkString url(static_cast<const char *>(urlData->data()),
1366 urlData->size() - 1);
1367 SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
1330 action->insertName("S", "URI"); 1368 action->insertName("S", "URI");
1331 action->insert("URI", new SkPDFString(url))->unref(); 1369 action->insert("URI", SkNEW_ARGS(SkPDFString, (url)))->unref();
1332 annotation->insert("A", action.get()); 1370 annotation->insert("A", action.get());
1371 }
1333 1372
1334 return p.isNoDrawAnnotation(); 1373 void SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r,
1374 const SkMatrix& matrix) {
1375 SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
1376 SkString name(static_cast<const char *>(nameData->data()),
1377 nameData->size() - 1);
1378 annotation->insert("Dest", SkNEW_ARGS(SkPDFString, (name)))->unref();
1379 }
1380
1381 struct NamedDestination {
1382 const SkData* nameData;
1383 SkPoint point;
1384
1385 NamedDestination(const SkData* nameData, const SkPoint& point)
1386 : nameData(nameData), point(point) {
1387 nameData->ref();
1388 }
1389
1390 ~NamedDestination() {
1391 nameData->unref();
1392 }
1393 };
1394
1395 void SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point,
1396 const SkMatrix& matrix) {
1397 SkMatrix transform = matrix;
1398 transform.postConcat(fInitialTransform);
1399 SkPoint translatedPoint;
1400 transform.mapXY(point.x(), point.y(), &translatedPoint);
1401 fNamedDestinations.push(
1402 SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
1403 }
1404
1405 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) {
1406 int nDest = fNamedDestinations.count();
1407 for (int i = 0; i < nDest; i++) {
1408 NamedDestination* dest = fNamedDestinations[i];
1409 SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray));
1410 pdfDest->reserve(5);
1411 pdfDest->append(SkNEW_ARGS(SkPDFObjRef, (page)))->unref();
1412 pdfDest->appendName("XYZ");
1413 pdfDest->appendInt(dest->point.x());
1414 pdfDest->appendInt(dest->point.y());
1415 pdfDest->appendInt(0); // Leave zoom unchanged
1416 dict->insert(static_cast<const char *>(dest->nameData->data()), pdfDest) ;
1417 }
1335 } 1418 }
1336 1419
1337 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { 1420 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() {
1338 SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this)); 1421 SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this));
1339 // We always draw the form xobjects that we create back into the device, so 1422 // We always draw the form xobjects that we create back into the device, so
1340 // we simply preserve the font usage instead of pulling it out and merging 1423 // we simply preserve the font usage instead of pulling it out and merging
1341 // it back in later. 1424 // it back in later.
1342 cleanUp(false); // Reset this device to have no content. 1425 cleanUp(false); // Reset this device to have no content.
1343 init(); 1426 init();
1344 return xobject; 1427 return xobject;
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
1720 } 1803 }
1721 1804
1722 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, 1805 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y,
1723 SkCanvas::Config8888) { 1806 SkCanvas::Config8888) {
1724 return false; 1807 return false;
1725 } 1808 }
1726 1809
1727 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { 1810 bool SkPDFDevice::allowImageFilter(SkImageFilter*) {
1728 return false; 1811 return false;
1729 } 1812 }
OLDNEW
« no previous file with comments | « src/gpu/SkGpuDevice.cpp ('k') | src/pdf/SkPDFDocument.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698