| OLD | NEW |
| 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" |
| 11 #include "SkColor.h" | 11 #include "SkColor.h" |
| 12 #include "SkColorFilter.h" | 12 #include "SkColorFilter.h" |
| 13 #include "SkClipStack.h" | 13 #include "SkClipStack.h" |
| 14 #include "SkData.h" | |
| 15 #include "SkDraw.h" | 14 #include "SkDraw.h" |
| 16 #include "SkGlyphCache.h" | 15 #include "SkGlyphCache.h" |
| 17 #include "SkPaint.h" | 16 #include "SkPaint.h" |
| 18 #include "SkPath.h" | 17 #include "SkPath.h" |
| 19 #include "SkPathOps.h" | 18 #include "SkPathOps.h" |
| 20 #include "SkPDFBitmap.h" | 19 #include "SkPDFBitmap.h" |
| 21 #include "SkPDFCanon.h" | 20 #include "SkPDFCanon.h" |
| 22 #include "SkPDFFont.h" | 21 #include "SkPDFFont.h" |
| 23 #include "SkPDFFormXObject.h" | 22 #include "SkPDFFormXObject.h" |
| 24 #include "SkPDFGraphicState.h" | 23 #include "SkPDFGraphicState.h" |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 if (fFontGlyphUsage.get() == nullptr) { | 740 if (fFontGlyphUsage.get() == nullptr) { |
| 742 fFontGlyphUsage.reset(new SkPDFGlyphSetMap); | 741 fFontGlyphUsage.reset(new SkPDFGlyphSetMap); |
| 743 } | 742 } |
| 744 } | 743 } |
| 745 | 744 |
| 746 void SkPDFDevice::cleanUp(bool clearFontUsage) { | 745 void SkPDFDevice::cleanUp(bool clearFontUsage) { |
| 747 fGraphicStateResources.unrefAll(); | 746 fGraphicStateResources.unrefAll(); |
| 748 fXObjectResources.unrefAll(); | 747 fXObjectResources.unrefAll(); |
| 749 fFontResources.unrefAll(); | 748 fFontResources.unrefAll(); |
| 750 fShaderResources.unrefAll(); | 749 fShaderResources.unrefAll(); |
| 751 fLinkToURLs.deleteAll(); | |
| 752 fLinkToDestinations.deleteAll(); | |
| 753 fNamedDestinations.deleteAll(); | |
| 754 | 750 |
| 755 if (clearFontUsage) { | 751 if (clearFontUsage) { |
| 756 fFontGlyphUsage->reset(); | 752 fFontGlyphUsage->reset(); |
| 757 } | 753 } |
| 758 } | 754 } |
| 759 | 755 |
| 760 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { | 756 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { |
| 761 SkPaint newPaint = paint; | 757 SkPaint newPaint = paint; |
| 762 replace_srcmode_on_opaque_paint(&newPaint); | 758 replace_srcmode_on_opaque_paint(&newPaint); |
| 763 | 759 |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 int vertexCount, const SkPoint verts[], | 1409 int vertexCount, const SkPoint verts[], |
| 1414 const SkPoint texs[], const SkColor colors[], | 1410 const SkPoint texs[], const SkColor colors[], |
| 1415 SkXfermode* xmode, const uint16_t indices[], | 1411 SkXfermode* xmode, const uint16_t indices[], |
| 1416 int indexCount, const SkPaint& paint) { | 1412 int indexCount, const SkPaint& paint) { |
| 1417 if (d.fClip->isEmpty()) { | 1413 if (d.fClip->isEmpty()) { |
| 1418 return; | 1414 return; |
| 1419 } | 1415 } |
| 1420 // TODO: implement drawVertices | 1416 // TODO: implement drawVertices |
| 1421 } | 1417 } |
| 1422 | 1418 |
| 1423 struct RectWithData { | |
| 1424 SkRect rect; | |
| 1425 SkAutoTUnref<const SkData> data; | |
| 1426 | |
| 1427 RectWithData(const SkRect& rect, const SkData* data) | |
| 1428 : rect(rect), data(SkRef(data)) {} | |
| 1429 }; | |
| 1430 | |
| 1431 struct NamedDestination { | |
| 1432 SkAutoTUnref<const SkData> nameData; | |
| 1433 SkPoint point; | |
| 1434 | |
| 1435 NamedDestination(const SkData* nameData, const SkPoint& point) | |
| 1436 : nameData(SkRef(nameData)), point(point) {} | |
| 1437 }; | |
| 1438 | |
| 1439 void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, | 1419 void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, |
| 1440 int x, int y, const SkPaint& paint) { | 1420 int x, int y, const SkPaint& paint) { |
| 1441 // our onCreateCompatibleDevice() always creates SkPDFDevice subclasses. | 1421 // our onCreateCompatibleDevice() always creates SkPDFDevice subclasses. |
| 1442 SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); | 1422 SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device); |
| 1443 | 1423 |
| 1444 SkScalar scalarX = SkIntToScalar(x); | 1424 SkScalar scalarX = SkIntToScalar(x); |
| 1445 SkScalar scalarY = SkIntToScalar(y); | 1425 SkScalar scalarY = SkIntToScalar(y); |
| 1446 for (RectWithData* link : pdfDevice->fLinkToURLs) { | 1426 for (const RectWithData& l : pdfDevice->fLinkToURLs) { |
| 1447 fLinkToURLs.push(new RectWithData( | 1427 SkRect r = l.rect.makeOffset(scalarX, scalarY); |
| 1448 link->rect.makeOffset(scalarX, scalarY), link->data)); | 1428 fLinkToURLs.emplace_back(r, l.data); |
| 1449 } | 1429 } |
| 1450 for (RectWithData* link : pdfDevice->fLinkToDestinations) { | 1430 for (const RectWithData& l : pdfDevice->fLinkToDestinations) { |
| 1451 fLinkToDestinations.push(new RectWithData( | 1431 SkRect r = l.rect.makeOffset(scalarX, scalarY); |
| 1452 link->rect.makeOffset(scalarX, scalarY), link->data)); | 1432 fLinkToDestinations.emplace_back(r, l.data); |
| 1453 } | 1433 } |
| 1454 for (NamedDestination* d : pdfDevice->fNamedDestinations) { | 1434 for (const NamedDestination& d : pdfDevice->fNamedDestinations) { |
| 1455 fNamedDestinations.push(new NamedDestination( | 1435 SkPoint p = d.point + SkPoint::Make(scalarX, scalarY); |
| 1456 d->nameData, d->point + SkPoint::Make(scalarX, scalarY))); | 1436 fNamedDestinations.emplace_back(d.nameData, p); |
| 1457 } | 1437 } |
| 1458 | 1438 |
| 1459 if (pdfDevice->isContentEmpty()) { | 1439 if (pdfDevice->isContentEmpty()) { |
| 1460 return; | 1440 return; |
| 1461 } | 1441 } |
| 1462 | 1442 |
| 1463 SkMatrix matrix; | 1443 SkMatrix matrix; |
| 1464 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); | 1444 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); |
| 1465 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); | 1445 ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint); |
| 1466 if (!content.entry()) { | 1446 if (!content.entry()) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1686 | 1666 |
| 1687 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, | 1667 bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count, |
| 1688 const SkMatrix& matrix, | 1668 const SkMatrix& matrix, |
| 1689 SkAnnotation* annotationInfo) { | 1669 SkAnnotation* annotationInfo) { |
| 1690 SkData* nameData = annotationInfo->find( | 1670 SkData* nameData = annotationInfo->find( |
| 1691 SkAnnotationKeys::Define_Named_Dest_Key()); | 1671 SkAnnotationKeys::Define_Named_Dest_Key()); |
| 1692 if (nameData) { | 1672 if (nameData) { |
| 1693 for (size_t i = 0; i < count; i++) { | 1673 for (size_t i = 0; i < count; i++) { |
| 1694 SkPoint transformedPoint; | 1674 SkPoint transformedPoint; |
| 1695 matrix.mapXY(points[i].x(), points[i].y(), &transformedPoint); | 1675 matrix.mapXY(points[i].x(), points[i].y(), &transformedPoint); |
| 1696 fNamedDestinations.push(new NamedDestination(nameData, transformedPo
int)); | 1676 fNamedDestinations.emplace_back(nameData, transformedPoint); |
| 1697 } | 1677 } |
| 1698 return true; | 1678 return true; |
| 1699 } | 1679 } |
| 1700 return false; | 1680 return false; |
| 1701 } | 1681 } |
| 1702 | 1682 |
| 1703 bool SkPDFDevice::handlePathAnnotation(const SkPath& path, | 1683 bool SkPDFDevice::handlePathAnnotation(const SkPath& path, |
| 1704 const SkDraw& d, | 1684 const SkDraw& d, |
| 1705 SkAnnotation* annotation) { | 1685 SkAnnotation* annotation) { |
| 1706 SkASSERT(annotation); | 1686 SkASSERT(annotation); |
| 1707 | 1687 |
| 1708 SkPath transformedPath = path; | 1688 SkPath transformedPath = path; |
| 1709 transformedPath.transform(*d.fMatrix); | 1689 transformedPath.transform(*d.fMatrix); |
| 1710 SkRasterClip clip = *d.fRC; | 1690 SkRasterClip clip = *d.fRC; |
| 1711 clip.op(transformedPath, SkIRect::MakeWH(width(), height()), SkRegion::kInte
rsect_Op, | 1691 clip.op(transformedPath, SkIRect::MakeWH(width(), height()), SkRegion::kInte
rsect_Op, |
| 1712 false); | 1692 false); |
| 1713 SkRect transformedRect = SkRect::Make(clip.getBounds()); | 1693 SkRect transformedRect = SkRect::Make(clip.getBounds()); |
| 1714 | 1694 |
| 1715 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); | 1695 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); |
| 1716 if (urlData) { | 1696 if (urlData) { |
| 1717 if (!transformedRect.isEmpty()) { | 1697 if (!transformedRect.isEmpty()) { |
| 1718 fLinkToURLs.push(new RectWithData(transformedRect, urlData)); | 1698 fLinkToURLs.emplace_back(transformedRect, urlData); |
| 1719 } | 1699 } |
| 1720 return true; | 1700 return true; |
| 1721 } | 1701 } |
| 1722 | 1702 |
| 1723 SkData* linkToDestination = | 1703 SkData* linkToDestination = |
| 1724 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); | 1704 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); |
| 1725 if (linkToDestination) { | 1705 if (linkToDestination) { |
| 1726 if (!transformedRect.isEmpty()) { | 1706 if (!transformedRect.isEmpty()) { |
| 1727 fLinkToDestinations.push(new RectWithData(transformedRect, linkToDes
tination)); | 1707 fLinkToDestinations.emplace_back(transformedRect, linkToDestination)
; |
| 1728 } | 1708 } |
| 1729 return true; | 1709 return true; |
| 1730 } | 1710 } |
| 1731 | 1711 |
| 1732 return false; | 1712 return false; |
| 1733 } | 1713 } |
| 1734 | 1714 |
| 1735 void SkPDFDevice::appendAnnotations(SkPDFArray* array) const { | 1715 void SkPDFDevice::appendAnnotations(SkPDFArray* array) const { |
| 1736 array->reserve(fLinkToURLs.count() + fLinkToDestinations.count()); | 1716 array->reserve(fLinkToURLs.count() + fLinkToDestinations.count()); |
| 1737 for (RectWithData* rectWithURL : fLinkToURLs) { | 1717 for (const RectWithData& rectWithURL : fLinkToURLs) { |
| 1738 SkRect r; | 1718 SkRect r; |
| 1739 fInitialTransform.mapRect(&r, rectWithURL->rect); | 1719 fInitialTransform.mapRect(&r, rectWithURL.rect); |
| 1740 array->appendObject(create_link_to_url(rectWithURL->data, r)); | 1720 array->appendObject(create_link_to_url(rectWithURL.data, r)); |
| 1741 } | 1721 } |
| 1742 for (RectWithData* linkToDestination : fLinkToDestinations) { | 1722 for (const RectWithData& linkToDestination : fLinkToDestinations) { |
| 1743 SkRect r; | 1723 SkRect r; |
| 1744 fInitialTransform.mapRect(&r, linkToDestination->rect); | 1724 fInitialTransform.mapRect(&r, linkToDestination.rect); |
| 1745 array->appendObject(create_link_named_dest(linkToDestination->data, r)); | 1725 array->appendObject(create_link_named_dest(linkToDestination.data, r)); |
| 1746 } | 1726 } |
| 1747 } | 1727 } |
| 1748 | 1728 |
| 1749 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { | 1729 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { |
| 1750 for (NamedDestination* dest : fNamedDestinations) { | 1730 for (const NamedDestination& dest : fNamedDestinations) { |
| 1751 SkAutoTUnref<SkPDFArray> pdfDest(new SkPDFArray); | 1731 SkAutoTUnref<SkPDFArray> pdfDest(new SkPDFArray); |
| 1752 pdfDest->reserve(5); | 1732 pdfDest->reserve(5); |
| 1753 pdfDest->appendObjRef(SkRef(page)); | 1733 pdfDest->appendObjRef(SkRef(page)); |
| 1754 pdfDest->appendName("XYZ"); | 1734 pdfDest->appendName("XYZ"); |
| 1755 SkPoint p = fInitialTransform.mapXY(dest->point.x(), dest->point.y()); | 1735 SkPoint p = fInitialTransform.mapXY(dest.point.x(), dest.point.y()); |
| 1756 pdfDest->appendScalar(p.x()); | 1736 pdfDest->appendScalar(p.x()); |
| 1757 pdfDest->appendScalar(p.y()); | 1737 pdfDest->appendScalar(p.y()); |
| 1758 pdfDest->appendInt(0); // Leave zoom unchanged | 1738 pdfDest->appendInt(0); // Leave zoom unchanged |
| 1759 SkString name(static_cast<const char*>(dest->nameData->data())); | 1739 SkString name(static_cast<const char*>(dest.nameData->data())); |
| 1760 dict->insertObject(name, pdfDest.detach()); | 1740 dict->insertObject(name, pdfDest.detach()); |
| 1761 } | 1741 } |
| 1762 } | 1742 } |
| 1763 | 1743 |
| 1764 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { | 1744 SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() { |
| 1765 SkPDFFormXObject* xobject = new SkPDFFormXObject(this); | 1745 SkPDFFormXObject* xobject = new SkPDFFormXObject(this); |
| 1766 // We always draw the form xobjects that we create back into the device, so | 1746 // We always draw the form xobjects that we create back into the device, so |
| 1767 // we simply preserve the font usage instead of pulling it out and merging | 1747 // we simply preserve the font usage instead of pulling it out and merging |
| 1768 // it back in later. | 1748 // it back in later. |
| 1769 cleanUp(false); // Reset this device to have no content. | 1749 cleanUp(false); // Reset this device to have no content. |
| (...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2365 pdfimage.reset(SkPDFCreateBitmapObject( | 2345 pdfimage.reset(SkPDFCreateBitmapObject( |
| 2366 image, fCanon->fPixelSerializer)); | 2346 image, fCanon->fPixelSerializer)); |
| 2367 if (!pdfimage) { | 2347 if (!pdfimage) { |
| 2368 return; | 2348 return; |
| 2369 } | 2349 } |
| 2370 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); | 2350 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); |
| 2371 } | 2351 } |
| 2372 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), | 2352 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), |
| 2373 &content.entry()->fContent); | 2353 &content.entry()->fContent); |
| 2374 } | 2354 } |
| OLD | NEW |