Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: src/pdf/SkPDFDocument.cpp

Issue 1823683005: SkPDF: Hold page objects, not SkPDFDevices. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2016-03-22 (Tuesday) 17:16:46 EDT Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pdf/SkPDFDocument.h ('k') | src/pdf/SkPDFFont.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pdf/SkPDFDocument.cpp
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index 66635a98fb43a02a2ae845acc586f3e0c2a6a52a..8e884d5e834f20e5859a57ea0a3963168be92733 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -93,45 +93,9 @@ int32_t SkPDFObjectSerializer::offset(SkWStream* wStream) {
return SkToS32(offset - fBaseOffset);
}
-static void perform_font_subsetting(
- const SkTArray<sk_sp<const SkPDFDevice>>& pageDevices,
- SkPDFSubstituteMap* substituteMap) {
- SkASSERT(substituteMap);
-
- SkPDFGlyphSetMap usage;
- for (const sk_sp<const SkPDFDevice>& pageDevice : pageDevices) {
- usage.merge(pageDevice->getFontGlyphUsage());
- }
- SkPDFGlyphSetMap::F2BIter iterator(usage);
- const SkPDFGlyphSetMap::FontGlyphSetPair* entry = iterator.next();
- while (entry) {
- sk_sp<SkPDFFont> subsetFont(
- entry->fFont->getFontSubset(entry->fGlyphSet));
- if (subsetFont) {
- substituteMap->setSubstitute(entry->fFont, subsetFont.get());
- }
- entry = iterator.next();
- }
-}
-
-static sk_sp<SkPDFDict> create_pdf_page(const SkPDFDevice* pageDevice) {
- auto page = sk_make_sp<SkPDFDict>("Page");
- page->insertObject("Resources", pageDevice->makeResourceDict());
- 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 page;
-}
// return root node.
-static sk_sp<SkPDFDict> generate_page_tree(
- SkTDArray<SkPDFDict*>& pages,
- SkTDArray<SkPDFDict*>* pageTree) {
+static sk_sp<SkPDFDict> generate_page_tree(SkTArray<sk_sp<SkPDFDict>>* pages) {
// 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
@@ -142,22 +106,18 @@ static sk_sp<SkPDFDict> generate_page_tree(
static const int kNodeSize = 8;
// curNodes takes a reference to its items, which it passes to pageTree.
- SkTDArray<SkPDFDict*> curNodes;
- curNodes.setReserve(pages.count());
- for (int i = 0; i < pages.count(); i++) {
- SkSafeRef(pages[i]);
- curNodes.push(pages[i]);
- }
+ int totalPageCount = pages->count();
+ SkTArray<sk_sp<SkPDFDict>> curNodes;
+ curNodes.swap(pages);
// nextRoundNodes passes its references to nodes on to curNodes.
- SkTDArray<SkPDFDict*> nextRoundNodes;
- nextRoundNodes.setReserve((pages.count() + kNodeSize - 1)/kNodeSize);
-
int treeCapacity = kNodeSize;
do {
+ SkTArray<sk_sp<SkPDFDict>> nextRoundNodes;
for (int i = 0; i < curNodes.count(); ) {
if (i > 0 && i + 1 == curNodes.count()) {
- nextRoundNodes.push(curNodes[i]);
+ SkASSERT(curNodes[i]);
+ nextRoundNodes.emplace_back(std::move(curNodes[i]));
break;
}
@@ -167,16 +127,9 @@ static sk_sp<SkPDFDict> generate_page_tree(
int count = 0;
for (; i < curNodes.count() && count < kNodeSize; i++, count++) {
+ SkASSERT(curNodes[i]);
curNodes[i]->insertObjRef("Parent", newNode);
- kids->appendObjRef(sk_ref_sp(curNodes[i]));
-
- // TODO(vandebo): put the objects in strict access order.
- // Probably doesn't matter because they are so small.
- if (curNodes[i] != pages[0]) {
- pageTree->push(curNodes[i]); // Transfer reference.
- } else {
- SkSafeUnref(curNodes[i]);
- }
+ kids->appendObjRef(std::move(curNodes[i]));
}
// treeCapacity is the number of leaf nodes possible for the
@@ -188,20 +141,19 @@ static sk_sp<SkPDFDict> generate_page_tree(
// consuming treeCapacity chunks.
int pageCount = treeCapacity;
if (i == curNodes.count()) {
- pageCount = ((pages.count() - 1) % treeCapacity) + 1;
+ pageCount = ((totalPageCount - 1) % treeCapacity) + 1;
}
newNode->insertInt("Count", pageCount);
newNode->insertObject("Kids", std::move(kids));
- nextRoundNodes.push(newNode.release()); // Transfer reference.
+ nextRoundNodes.emplace_back(std::move(newNode));
}
+ SkDEBUGCODE( for (const auto& n : curNodes) { SkASSERT(!n); } );
- curNodes = nextRoundNodes;
- nextRoundNodes.rewind();
+ curNodes.swap(&nextRoundNodes);
+ nextRoundNodes.reset();
treeCapacity *= kNodeSize;
} while (curNodes.count() > 1);
-
- pageTree->push(curNodes[0]); // Transfer reference.
- return sk_ref_sp(curNodes[0]);
+ return std::move(curNodes[0]);
}
#if 0
@@ -269,16 +221,16 @@ void SkPDFDocument::serialize(const sk_sp<SkPDFObject>& object) {
SkCanvas* SkPDFDocument::onBeginPage(SkScalar width, SkScalar height,
const SkRect& trimBox) {
SkASSERT(!fCanvas.get()); // endPage() was called before this.
- if (fPageDevices.empty()) {
+ if (fPages.empty()) {
// if this is the first page if the document.
fObjectSerializer.serializeHeader(this->getStream(), fMetadata);
+ fDests = sk_make_sp<SkPDFDict>();
}
SkISize pageSize = SkISize::Make(
SkScalarRoundToInt(width), SkScalarRoundToInt(height));
- sk_sp<SkPDFDevice> device(
+ fPageDevice.reset(
SkPDFDevice::Create(pageSize, fRasterDpi, this));
- fCanvas = sk_make_sp<SkPDFCanvas>(device);
- fPageDevices.push_back(std::move(device));
+ fCanvas = sk_make_sp<SkPDFCanvas>(fPageDevice);
fCanvas->clipRect(trimBox);
fCanvas->translate(trimBox.x(), trimBox.y());
return fCanvas.get();
@@ -288,11 +240,28 @@ void SkPDFDocument::onEndPage() {
SkASSERT(fCanvas.get());
fCanvas->flush();
fCanvas.reset(nullptr);
+ SkASSERT(fPageDevice);
+ fGlyphUsage.merge(fPageDevice->getFontGlyphUsage());
+ auto page = sk_make_sp<SkPDFDict>("Page");
+ page->insertObject("Resources", fPageDevice->makeResourceDict());
+ page->insertObject("MediaBox", fPageDevice->copyMediaBox());
+ auto annotations = sk_make_sp<SkPDFArray>();
+ fPageDevice->appendAnnotations(annotations.get());
+ if (annotations->size() > 0) {
+ page->insertObject("Annots", std::move(annotations));
+ }
+ auto contentData = fPageDevice->content();
+ auto contentObject = sk_make_sp<SkPDFStream>(contentData.get());
+ this->serialize(contentObject);
+ page->insertObjRef("Contents", std::move(contentObject));
+ fPageDevice->appendDestinations(fDests.get(), page.get());
+ fPages.emplace_back(std::move(page));
+ fPageDevice.reset(nullptr);
}
void SkPDFDocument::onAbort() {
fCanvas.reset(nullptr);
- fPageDevices.reset();
+ fPages.reset();
fCanon.reset();
renew(&fObjectSerializer);
}
@@ -308,25 +277,13 @@ void SkPDFDocument::setMetadata(const SkDocument::Attribute info[],
bool SkPDFDocument::onClose(SkWStream* stream) {
SkASSERT(!fCanvas.get());
- if (fPageDevices.empty()) {
- fPageDevices.reset();
+ if (fPages.empty()) {
+ fPages.reset();
fCanon.reset();
renew(&fObjectSerializer);
return false;
}
- SkTDArray<SkPDFDict*> pages; // TODO: SkTArray<sk_sp<SkPDFDict>>
- auto dests = sk_make_sp<SkPDFDict>();
-
- for (const sk_sp<const SkPDFDevice>& pageDevice : fPageDevices) {
- SkASSERT(pageDevice);
- SkASSERT(fPageDevices[0]->getCanon() == pageDevice->getCanon());
- sk_sp<SkPDFDict> page(create_pdf_page(pageDevice.get()));
- pageDevice->appendDestinations(dests.get(), page.get());
- pages.push(page.release());
- }
-
auto docCatalog = sk_make_sp<SkPDFDict>("Catalog");
-
sk_sp<SkPDFObject> id, xmp;
#ifdef SK_PDF_GENERATE_PDFA
SkPDFMetadata::UUID uuid = metadata.uuid();
@@ -352,24 +309,28 @@ bool SkPDFDocument::onClose(SkWStream* stream) {
docCatalog->insertObject("OutputIntents", std::move(intentArray));
#endif
- SkTDArray<SkPDFDict*> pageTree;
- docCatalog->insertObjRef("Pages", generate_page_tree(pages, &pageTree));
+ docCatalog->insertObjRef("Pages", generate_page_tree(&fPages));
- if (dests->size() > 0) {
- docCatalog->insertObjRef("Dests", std::move(dests));
+ if (fDests->size() > 0) {
+ docCatalog->insertObjRef("Dests", std::move(fDests));
}
// Build font subsetting info before calling addObjectRecursively().
- perform_font_subsetting(fPageDevices, &fObjectSerializer.fSubstituteMap);
+ for (const auto& entry : fGlyphUsage) {
+ sk_sp<SkPDFFont> subsetFont(
+ entry.fFont->getFontSubset(entry.fGlyphSet));
+ if (subsetFont) {
+ fObjectSerializer.fSubstituteMap.setSubstitute(
+ entry.fFont, subsetFont.get());
+ }
+ }
fObjectSerializer.addObjectRecursively(docCatalog);
fObjectSerializer.serializeObjects(this->getStream());
fObjectSerializer.serializeFooter(
this->getStream(), docCatalog, std::move(id));
- pageTree.unrefAll(); // TODO(halcanary): make this unnecesary by
- // refactoring generate_page_tree().
- pages.unrefAll();
- fPageDevices.reset();
+
+ SkASSERT(fPages.count() == 0);
fCanon.reset();
renew(&fObjectSerializer);
return true;
« no previous file with comments | « src/pdf/SkPDFDocument.h ('k') | src/pdf/SkPDFFont.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698