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

Unified Diff: src/doc/SkDocument_PDF.cpp

Issue 1007083004: SkPDF: eliminate skpdfpage class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-03-25 (Wednesday) 15:31:19 EDT Created 5 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 | « gyp/pdf.gypi ('k') | src/pdf/SkPDFPage.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/doc/SkDocument_PDF.cpp
diff --git a/src/doc/SkDocument_PDF.cpp b/src/doc/SkDocument_PDF.cpp
index 979cd00e0db5aa249d73158b2f31114992c524eb..ae0386ab1a389272f531eba51c5e29765c60f619 100644
--- a/src/doc/SkDocument_PDF.cpp
+++ b/src/doc/SkDocument_PDF.cpp
@@ -10,7 +10,8 @@
#include "SkPDFCatalog.h"
#include "SkPDFDevice.h"
#include "SkPDFFont.h"
-#include "SkPDFPage.h"
+#include "SkPDFResourceDict.h"
+#include "SkPDFStream.h"
#include "SkPDFTypes.h"
#include "SkStream.h"
@@ -40,13 +41,14 @@ static void emit_pdf_footer(SkWStream* stream,
stream->writeText("\n%%EOF");
}
-static void perform_font_subsetting(SkPDFCatalog* catalog,
- const SkTDArray<SkPDFPage*>& pages) {
+static void perform_font_subsetting(
+ const SkTDArray<const SkPDFDevice*>& pageDevices,
+ SkPDFCatalog* catalog) {
SkASSERT(catalog);
SkPDFGlyphSetMap usage;
- for (int i = 0; i < pages.count(); ++i) {
- usage.merge(pages[i]->getFontGlyphUsage());
+ for (int i = 0; i < pageDevices.count(); ++i) {
+ usage.merge(pageDevices[i]->getFontGlyphUsage());
}
SkPDFGlyphSetMap::F2BIter iterator(usage);
const SkPDFGlyphSetMap::FontGlyphSetPair* entry = iterator.next();
@@ -60,23 +62,125 @@ static void perform_font_subsetting(SkPDFCatalog* catalog,
}
}
+static SkPDFDict* create_pdf_page(const SkPDFDevice* pageDevice) {
+ SkAutoTUnref<SkPDFDict> page(SkNEW_ARGS(SkPDFDict, ("Page")));
+ SkAutoTUnref<SkPDFResourceDict> deviceResourceDict(
+ pageDevice->createResourceDict());
+ page->insert("Resources", deviceResourceDict.get());
+
+ SkAutoTUnref<SkPDFArray> mediaBox(pageDevice->copyMediaBox());
+ page->insert("MediaBox", mediaBox.get());
+
+ SkPDFArray* annots = pageDevice->getAnnotations();
+ if (annots && annots->size() > 0) {
+ page->insert("Annots", annots);
+ }
+
+ SkAutoTDelete<SkStreamAsset> content(pageDevice->content());
+ SkAutoTUnref<SkPDFStream> contentStream(
+ SkNEW_ARGS(SkPDFStream, (content.get())));
+ page->insert("Contents", new SkPDFObjRef(contentStream.get()))->unref();
+ return page.detach();
+}
+
+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
+ // the number of leaves below the node as "Count." The leaves are passed
+ // into the method, have type "Page" and need a parent pointer. This method
+ // builds the tree bottom up, skipping internal nodes that would have only
+ // one child.
+ static const int kNodeSize = 8;
+
+ SkAutoTUnref<SkPDFName> kidsName(new SkPDFName("Kids"));
+ SkAutoTUnref<SkPDFName> countName(new SkPDFName("Count"));
+ SkAutoTUnref<SkPDFName> parentName(new SkPDFName("Parent"));
+
+ // 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]);
+ }
+
+ // nextRoundNodes passes its references to nodes on to curNodes.
+ SkTDArray<SkPDFDict*> nextRoundNodes;
+ nextRoundNodes.setReserve((pages.count() + kNodeSize - 1)/kNodeSize);
+
+ int treeCapacity = kNodeSize;
+ do {
+ for (int i = 0; i < curNodes.count(); ) {
+ if (i > 0 && i + 1 == curNodes.count()) {
+ nextRoundNodes.push(curNodes[i]);
+ break;
+ }
+
+ SkPDFDict* newNode = new SkPDFDict("Pages");
+ SkAutoTUnref<SkPDFObjRef> newNodeRef(new SkPDFObjRef(newNode));
+
+ SkAutoTUnref<SkPDFArray> kids(new SkPDFArray);
+ kids->reserve(kNodeSize);
+
+ int count = 0;
+ for (; i < curNodes.count() && count < kNodeSize; i++, count++) {
+ curNodes[i]->insert(parentName.get(), newNodeRef.get());
+ kids->append(new SkPDFObjRef(curNodes[i]))->unref();
+
+ // 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]);
+ }
+ }
+
+ // treeCapacity is the number of leaf nodes possible for the
+ // current set of subtrees being generated. (i.e. 8, 64, 512, ...).
+ // It is hard to count the number of leaf nodes in the current
+ // subtree. However, by construction, we know that unless it's the
+ // last subtree for the current depth, the leaf count will be
+ // treeCapacity, otherwise it's what ever is left over after
+ // consuming treeCapacity chunks.
+ int pageCount = treeCapacity;
+ if (i == curNodes.count()) {
+ pageCount = ((pages.count() - 1) % treeCapacity) + 1;
+ }
+ newNode->insert(countName.get(), new SkPDFInt(pageCount))->unref();
+ newNode->insert(kidsName.get(), kids.get());
+ nextRoundNodes.push(newNode); // Transfer reference.
+ }
+
+ curNodes = nextRoundNodes;
+ nextRoundNodes.rewind();
+ treeCapacity *= kNodeSize;
+ } while (curNodes.count() > 1);
+
+ pageTree->push(curNodes[0]); // Transfer reference.
+ if (rootNode) {
+ *rootNode = curNodes[0];
+ }
+}
+
static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices,
SkWStream* stream) {
if (pageDevices.isEmpty()) {
return false;
}
- SkTDArray<SkPDFPage*> pages;
+ SkTDArray<SkPDFDict*> pages;
SkAutoTUnref<SkPDFDict> dests(SkNEW(SkPDFDict));
for (int i = 0; i < pageDevices.count(); i++) {
SkASSERT(pageDevices[i]);
SkASSERT(i == 0 ||
pageDevices[i - 1]->getCanon() == pageDevices[i]->getCanon());
- // Reference from new passed to pages.
- SkAutoTUnref<SkPDFPage> page(SkNEW_ARGS(SkPDFPage, (pageDevices[i])));
- page->finalizePage();
- page->appendDestinations(dests);
+ SkAutoTUnref<SkPDFDict> page(create_pdf_page(pageDevices[i]));
+ pageDevices[i]->appendDestinations(dests, page.get());
pages.push(page.detach());
}
SkPDFCatalog catalog;
@@ -85,7 +189,7 @@ static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices,
SkAutoTUnref<SkPDFDict> docCatalog(SkNEW_ARGS(SkPDFDict, ("Catalog")));
SkPDFDict* pageTreeRoot;
- SkPDFPage::GeneratePageTree(pages, &pageTree, &pageTreeRoot);
+ generate_page_tree(pages, &pageTree, &pageTreeRoot);
docCatalog->insert("Pages", new SkPDFObjRef(pageTreeRoot))->unref();
@@ -105,7 +209,7 @@ static bool emit_pdf_document(const SkTDArray<const SkPDFDevice*>& pageDevices,
}
// Build font subsetting info before proceeding.
- perform_font_subsetting(&catalog, pages);
+ perform_font_subsetting(pageDevices, &catalog);
SkTSet<SkPDFObject*> resourceSet;
if (resourceSet.add(docCatalog.get())) {
« no previous file with comments | « gyp/pdf.gypi ('k') | src/pdf/SkPDFPage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698