OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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(SkPDFName, (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->appendScalar(dest->point.x()); |
| 1414 pdfDest->appendScalar(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 Loading... |
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 } |
OLD | NEW |