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 |