| 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(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 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 |