11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2010 The Android Open Source Project 40b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 70b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger */ 80b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFCatalog.h" 110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFDevice.h" 120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkPDFPage.h" 130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkStream.h" 140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 151cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPDFPage::SkPDFPage(SkPDFDevice* content) 160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger : SkPDFDict("Page"), 170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fDevice(content) { 180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 200b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkPDFPage::~SkPDFPage() {} 210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFPage::finalizePage(SkPDFCatalog* catalog, bool firstPage, 230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTDArray<SkPDFObject*>* resourceObjects) { 240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fContentStream.get() == NULL) { 251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger insert("Resources", fDevice->getResourceDict()); 260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger insert("MediaBox", fDevice->getMediaBox().get()); 270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkStream> content = fDevice->content(); 290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger content->unref(); // SkRefPtr and content() both took a reference. 300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream = new SkPDFStream(content.get()); 310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->unref(); // SkRefPtr and new both took a reference. 320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger insert("Contents", new SkPDFObjRef(fContentStream.get()))->unref(); 330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger catalog->addObject(fContentStream.get(), firstPage); 350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fDevice->getResources(resourceObjects); 360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergeroff_t SkPDFPage::getPageSize(SkPDFCatalog* catalog, off_t fileOffset) { 390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fContentStream.get() != NULL); 400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger catalog->setFileOffset(fContentStream.get(), fileOffset); 410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return fContentStream->getOutputSize(catalog, true); 420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFPage::emitPage(SkWStream* stream, SkPDFCatalog* catalog) { 450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fContentStream.get() != NULL); 460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fContentStream->emitObject(stream, catalog, true); 470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger// static 501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPDFPage::GeneratePageTree(const SkTDArray<SkPDFPage*>& pages, 510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFCatalog* catalog, 520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTDArray<SkPDFDict*>* pageTree, 530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFDict** rootNode) { 540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // PDF wants a tree describing all the pages in the document. We arbitrary 550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // choose 8 (kNodeSize) as the number of allowed children. The internal 560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // nodes have type "Pages" with an array of children, a parent pointer, and 570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // the number of leaves below the node as "Count." The leaves are passed 580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // into the method, have type "Page" and need a parent pointer. This method 590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // builds the tree bottom up, skipping internal nodes that would have only 600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // one child. 610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger static const int kNodeSize = 8; 620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 630b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFName> kidsName = new SkPDFName("Kids"); 640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger kidsName->unref(); // SkRefPtr and new both took a reference. 650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFName> countName = new SkPDFName("Count"); 660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger countName->unref(); // SkRefPtr and new both took a reference. 670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFName> parentName = new SkPDFName("Parent"); 680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger parentName->unref(); // SkRefPtr and new both took a reference. 690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // curNodes takes a reference to its items, which it passes to pageTree. 710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTDArray<SkPDFDict*> curNodes; 720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger curNodes.setReserve(pages.count()); 730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < pages.count(); i++) { 740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkSafeRef(pages[i]); 750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger curNodes.push(pages[i]); 760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // nextRoundNodes passes its references to nodes on to curNodes. 790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTDArray<SkPDFDict*> nextRoundNodes; 800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nextRoundNodes.setReserve((pages.count() + kNodeSize - 1)/kNodeSize); 810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int treeCapacity = kNodeSize; 830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger do { 840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < curNodes.count(); ) { 850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (i > 0 && i + 1 == curNodes.count()) { 860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nextRoundNodes.push(curNodes[i]); 870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger break; 880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 890b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkPDFDict* newNode = new SkPDFDict("Pages"); 910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFObjRef> newNodeRef = new SkPDFObjRef(newNode); 920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newNodeRef->unref(); // SkRefPtr and new both took a reference. 930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkRefPtr<SkPDFArray> kids = new SkPDFArray; 950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger kids->unref(); // SkRefPtr and new both took a reference. 960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger kids->reserve(kNodeSize); 970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int count = 0; 990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (; i < curNodes.count() && count < kNodeSize; i++, count++) { 1000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger curNodes[i]->insert(parentName.get(), newNodeRef.get()); 1010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger kids->append(new SkPDFObjRef(curNodes[i]))->unref(); 1020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // TODO(vandebo): put the objects in strict access order. 1040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // Probably doesn't matter because they are so small. 1050b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (curNodes[i] != pages[0]) { 1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pageTree->push(curNodes[i]); // Transfer reference. 1070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger catalog->addObject(curNodes[i], false); 1080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 1090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkSafeUnref(curNodes[i]); 1101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger catalog->addObject(curNodes[i], true); 1110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newNode->insert(kidsName.get(), kids.get()); 1150b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int pageCount = treeCapacity; 1160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (count < kNodeSize) { 1170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger pageCount = pages.count() % treeCapacity; 1180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger newNode->insert(countName.get(), new SkPDFInt(pageCount))->unref(); 1200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nextRoundNodes.push(newNode); // Transfer reference. 1210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger curNodes = nextRoundNodes; 1240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger nextRoundNodes.rewind(); 1250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger treeCapacity *= kNodeSize; 1261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } while (curNodes.count() > 1); 1270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pageTree->push(curNodes[0]); // Transfer reference. 1290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger catalog->addObject(curNodes[0], false); 1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (rootNode) { 1310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger *rootNode = curNodes[0]; 1321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerconst SkTDArray<SkPDFFont*>& SkPDFPage::getFontResources() const { 1360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return fDevice->getFontResources(); 1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst SkPDFGlyphSetMap& SkPDFPage::getFontGlyphUsage() const { 1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return fDevice->getFontGlyphUsage(); 1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 142