Index: src/doc/SkDocument_PDF.cpp |
diff --git a/src/doc/SkDocument_PDF.cpp b/src/doc/SkDocument_PDF.cpp |
index 101214d7ca8ab6c6950231cf060ce4fb26a4b550..7e5e1a8ebaafc2ba0dec1d314939687d0fe04a9c 100644 |
--- a/src/doc/SkDocument_PDF.cpp |
+++ b/src/doc/SkDocument_PDF.cpp |
@@ -31,17 +31,17 @@ |
SkPDFObject* docCatalog, |
int64_t objCount, |
int32_t xRefFileOffset, |
- sk_sp<SkPDFObject> info, |
- sk_sp<SkPDFObject> id) { |
+ SkPDFObject* info /* take ownership */, |
+ SkPDFObject* id /* take ownership */) { |
SkPDFDict trailerDict; |
// TODO(http://crbug.com/80908): Linearized format will take a |
// Prev entry too. |
trailerDict.insertInt("Size", int(objCount)); |
- trailerDict.insertObjRef("Root", sk_sp<SkPDFObject>(SkRef(docCatalog))); |
+ trailerDict.insertObjRef("Root", SkRef(docCatalog)); |
SkASSERT(info); |
- trailerDict.insertObjRef("Info", std::move(info)); |
+ trailerDict.insertObjRef("Info", info); |
if (id) { |
- trailerDict.insertObject("ID", std::move(id)); |
+ trailerDict.insertObject("ID", id); |
} |
stream->writeText("trailer\n"); |
trailerDict.emitObject(stream, objNumMap, substitutes); |
@@ -51,13 +51,13 @@ |
} |
static void perform_font_subsetting( |
- const SkTArray<sk_sp<const SkPDFDevice>>& pageDevices, |
+ const SkTDArray<const SkPDFDevice*>& pageDevices, |
SkPDFSubstituteMap* substituteMap) { |
SkASSERT(substituteMap); |
SkPDFGlyphSetMap usage; |
- for (const sk_sp<const SkPDFDevice>& pageDevice : pageDevices) { |
- usage.merge(pageDevice->getFontGlyphUsage()); |
+ for (int i = 0; i < pageDevices.count(); ++i) { |
+ usage.merge(pageDevices[i]->getFontGlyphUsage()); |
} |
SkPDFGlyphSetMap::F2BIter iterator(usage); |
const SkPDFGlyphSetMap::FontGlyphSetPair* entry = iterator.next(); |
@@ -71,24 +71,27 @@ |
} |
} |
-static sk_sp<SkPDFDict> create_pdf_page(const SkPDFDevice* pageDevice) { |
+static SkPDFObject* create_pdf_page_content(const SkPDFDevice* pageDevice) { |
+ SkAutoTDelete<SkStreamAsset> content(pageDevice->content()); |
+ return new SkPDFStream(content.get()); |
+} |
+ |
+static SkPDFDict* create_pdf_page(const SkPDFDevice* pageDevice) { |
auto page = sk_make_sp<SkPDFDict>("Page"); |
- page->insertObject("Resources", pageDevice->makeResourceDict()); |
+ page->insertObject("Resources", pageDevice->createResourceDict()); |
page->insertObject("MediaBox", pageDevice->copyMediaBox()); |
auto annotations = sk_make_sp<SkPDFArray>(); |
pageDevice->appendAnnotations(annotations.get()); |
if (annotations->size() > 0) { |
- page->insertObject("Annots", std::move(annotations)); |
- } |
- auto content = pageDevice->content(); |
- page->insertObjRef("Contents", sk_make_sp<SkPDFStream>(content.get())); |
- return std::move(page); |
-} |
- |
-// return root node. |
-static sk_sp<SkPDFDict> generate_page_tree( |
- const SkTDArray<SkPDFDict*>& pages, |
- SkTDArray<SkPDFDict*>* pageTree) { |
+ page->insertObject("Annots", annotations.release()); |
+ } |
+ page->insertObjRef("Contents", create_pdf_page_content(pageDevice)); |
+ return page.release(); |
+} |
+ |
+static void generate_page_tree(const SkTDArray<SkPDFDict*>& pages, |
+ SkTDArray<SkPDFDict*>* pageTree, |
+ SkPDFDict** rootNode) { |
// PDF wants a tree describing all the pages in the document. We arbitrary |
// choose 8 (kNodeSize) as the number of allowed children. The internal |
// nodes have type "Pages" with an array of children, a parent pointer, and |
@@ -124,8 +127,8 @@ |
int count = 0; |
for (; i < curNodes.count() && count < kNodeSize; i++, count++) { |
- curNodes[i]->insertObjRef("Parent", newNode); |
- kids->appendObjRef(sk_sp<SkPDFDict>(SkRef(curNodes[i]))); |
+ curNodes[i]->insertObjRef("Parent", SkRef(newNode.get())); |
+ kids->appendObjRef(SkRef(curNodes[i])); |
// TODO(vandebo): put the objects in strict access order. |
// Probably doesn't matter because they are so small. |
@@ -148,7 +151,7 @@ |
pageCount = ((pages.count() - 1) % treeCapacity) + 1; |
} |
newNode->insertInt("Count", pageCount); |
- newNode->insertObject("Kids", std::move(kids)); |
+ newNode->insertObject("Kids", kids.release()); |
nextRoundNodes.push(newNode.release()); // Transfer reference. |
} |
@@ -158,30 +161,34 @@ |
} while (curNodes.count() > 1); |
pageTree->push(curNodes[0]); // Transfer reference. |
- return sk_sp<SkPDFDict>(SkRef(curNodes[0])); |
-} |
- |
-static bool emit_pdf_document(const SkTArray<sk_sp<const SkPDFDevice>>& pageDevices, |
+ if (rootNode) { |
+ *rootNode = curNodes[0]; |
+ } |
+} |
+ |
+static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices, |
const SkPDFMetadata& metadata, |
SkWStream* stream) { |
- if (pageDevices.empty()) { |
+ if (pageDevices.isEmpty()) { |
return false; |
} |
- SkTDArray<SkPDFDict*> pages; // TODO: SkTArray<sk_sp<SkPDFDict>> |
+ SkTDArray<SkPDFDict*> pages; |
auto dests = sk_make_sp<SkPDFDict>(); |
- for (const sk_sp<const SkPDFDevice>& pageDevice : pageDevices) { |
- SkASSERT(pageDevice); |
- SkASSERT(pageDevices[0]->getCanon() == pageDevice->getCanon()); |
- sk_sp<SkPDFDict> page(create_pdf_page(pageDevice.get())); |
- pageDevice->appendDestinations(dests.get(), page.get()); |
+ for (int i = 0; i < pageDevices.count(); i++) { |
+ SkASSERT(pageDevices[i]); |
+ SkASSERT(i == 0 || |
+ pageDevices[i - 1]->getCanon() == pageDevices[i]->getCanon()); |
+ sk_sp<SkPDFDict> page(create_pdf_page(pageDevices[i])); |
+ pageDevices[i]->appendDestinations(dests.get(), page.get()); |
pages.push(page.release()); |
} |
auto docCatalog = sk_make_sp<SkPDFDict>("Catalog"); |
- sk_sp<SkPDFObject> infoDict(metadata.createDocumentInformationDict()); |
+ sk_sp<SkPDFObject> infoDict( |
+ metadata.createDocumentInformationDict()); |
sk_sp<SkPDFObject> id, xmp; |
#ifdef SK_PDF_GENERATE_PDFA |
@@ -193,7 +200,7 @@ |
// works best with reproducible outputs. |
id.reset(SkPDFMetadata::CreatePdfId(uuid, uuid)); |
xmp.reset(metadata.createXMPObject(uuid, uuid)); |
- docCatalog->insertObjRef("Metadata", std::move(xmp)); |
+ docCatalog->insertObjRef("Metadata", xmp.release()); |
// sRGB is specified by HTML, CSS, and SVG. |
auto outputIntent = sk_make_sp<SkPDFDict>("OutputIntent"); |
@@ -202,17 +209,19 @@ |
outputIntent->insertString("OutputConditionIdentifier", |
"sRGB IEC61966-2.1"); |
auto intentArray = sk_make_sp<SkPDFArray>(); |
- intentArray->appendObject(std::move(outputIntent)); |
+ intentArray->appendObject(outputIntent.release()); |
// Don't specify OutputIntents if we are not in PDF/A mode since |
// no one has ever asked for this feature. |
- docCatalog->insertObject("OutputIntents", std::move(intentArray)); |
+ docCatalog->insertObject("OutputIntents", intentArray.release()); |
#endif |
SkTDArray<SkPDFDict*> pageTree; |
- docCatalog->insertObjRef("Pages", generate_page_tree(pages, &pageTree)); |
+ SkPDFDict* pageTreeRoot; |
+ generate_page_tree(pages, &pageTree, &pageTreeRoot); |
+ docCatalog->insertObjRef("Pages", SkRef(pageTreeRoot)); |
if (dests->size() > 0) { |
- docCatalog->insertObjRef("Dests", std::move(dests)); |
+ docCatalog->insertObjRef("Dests", dests.release()); |
} |
// Build font subsetting info before proceeding. |
@@ -253,7 +262,7 @@ |
stream->writeText(" 00000 n \n"); |
} |
emit_pdf_footer(stream, objNumMap, substitutes, docCatalog.get(), objCount, |
- xRefFileOffset, std::move(infoDict), std::move(id)); |
+ xRefFileOffset, infoDict.release(), id.release()); |
// The page tree has both child and parent pointers, so it creates a |
// reference cycle. We must clear that cycle to properly reclaim memory. |
@@ -335,7 +344,7 @@ |
sk_sp<SkPDFDevice> device( |
SkPDFDevice::Create(pageSize, fRasterDpi, &fCanon)); |
fCanvas.reset(new SkCanvas(device.get())); |
- fPageDevices.push_back(std::move(device)); |
+ fPageDevices.push(device.release()); |
fCanvas->clipRect(trimBox); |
fCanvas->translate(trimBox.x(), trimBox.y()); |
return fCanvas.get(); |
@@ -351,13 +360,13 @@ |
SkASSERT(!fCanvas.get()); |
bool success = emit_pdf_document(fPageDevices, fMetadata, stream); |
- fPageDevices.reset(); |
+ fPageDevices.unrefAll(); |
fCanon.reset(); |
return success; |
} |
void onAbort() override { |
- fPageDevices.reset(); |
+ fPageDevices.unrefAll(); |
fCanon.reset(); |
} |
@@ -372,7 +381,7 @@ |
private: |
SkPDFCanon fCanon; |
- SkTArray<sk_sp<const SkPDFDevice>> fPageDevices; |
+ SkTDArray<const SkPDFDevice*> fPageDevices; |
sk_sp<SkCanvas> fCanvas; |
SkScalar fRasterDpi; |
SkPDFMetadata fMetadata; |