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 "SkPDFTypes.h" 120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkStream.h" 130b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#include "SkTypes.h" 140b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 151cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPDFCatalog::SkPDFCatalog(SkPDFDocument::Flags flags) 160b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger : fFirstPageCount(0), 170b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fNextObjNum(1), 181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fNextFirstPageObjNum(0), 191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fDocumentFlags(flags) { 200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 221cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPDFCatalog::~SkPDFCatalog() { 231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSubstituteResourcesRemaining.safeUnrefAll(); 241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSubstituteResourcesFirstPage.safeUnrefAll(); 251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 270b15698a8c76bb8abc1b555c1d91892669b4118fDerek SollenbergerSkPDFObject* SkPDFCatalog::addObject(SkPDFObject* obj, bool onFirstPage) { 281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (findObjectIndex(obj) != -1) { // object already added 291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return obj; 301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fNextFirstPageObjNum == 0); 321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (onFirstPage) { 330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fFirstPageCount++; 341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger struct Rec newEntry(obj, onFirstPage); 370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fCatalog.append(1, &newEntry); 380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return obj; 390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergersize_t SkPDFCatalog::setFileOffset(SkPDFObject* obj, size_t offset) { 420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int objIndex = assignObjNum(obj) - 1; 430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fCatalog[objIndex].fObjNumAssigned); 440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fCatalog[objIndex].fFileOffset == 0); 450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fCatalog[objIndex].fFileOffset = offset; 460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return getSubstituteObject(obj)->getOutputSize(this, true); 480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 490b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergervoid SkPDFCatalog::emitObjectNumber(SkWStream* stream, SkPDFObject* obj) { 510b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeDecAsText(assignObjNum(obj)); 520b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeText(" 0"); // Generation number is always 0. 530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 540b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 550b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergersize_t SkPDFCatalog::getObjectNumberSize(SkPDFObject* obj) { 560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkDynamicMemoryWStream buffer; 570b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger emitObjectNumber(&buffer, obj); 580b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return buffer.getOffset(); 590b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 600b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerint SkPDFCatalog::findObjectIndex(SkPDFObject* obj) const { 620b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = 0; i < fCatalog.count(); i++) { 631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fCatalog[i].fObject == obj) { 640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return i; 651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // If it's not in the main array, check if it's a substitute object. 681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < fSubstituteMap.count(); ++i) { 691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fSubstituteMap[i].fSubstitute == obj) { 701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return findObjectIndex(fSubstituteMap[i].fOriginal); 711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return -1; 740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerint SkPDFCatalog::assignObjNum(SkPDFObject* obj) { 770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int pos = findObjectIndex(obj); 780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // If this assert fails, it means you probably forgot to add an object 790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // to the resource list. 800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(pos >= 0); 810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger uint32_t currentIndex = pos; 821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fCatalog[currentIndex].fObjNumAssigned) { 830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return currentIndex + 1; 841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 860b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // First assignment. 871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fNextFirstPageObjNum == 0) { 880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fNextFirstPageObjNum = fCatalog.count() - fFirstPageCount + 1; 891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 900b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger uint32_t objNum; 920b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fCatalog[currentIndex].fOnFirstPage) { 930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger objNum = fNextFirstPageObjNum; 940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fNextFirstPageObjNum++; 950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } else { 960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger objNum = fNextObjNum; 970b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fNextObjNum++; 980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 990b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1000b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // When we assign an object an object number, we put it in that array 1010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger // offset (minus 1 because object number 0 is reserved). 1020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(!fCatalog[objNum - 1].fObjNumAssigned); 1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (objNum - 1 != currentIndex) { 1040b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkTSwap(fCatalog[objNum - 1], fCatalog[currentIndex]); 1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1060b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger fCatalog[objNum - 1].fObjNumAssigned = true; 1070b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return objNum; 1080b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1090b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1100b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenbergerint32_t SkPDFCatalog::emitXrefTable(SkWStream* stream, bool firstPage) { 1110b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int first = -1; 1120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger int last = fCatalog.count() - 1; 1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // TODO(vandebo): Support linearized format. 1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // int last = fCatalog.count() - fFirstPageCount - 1; 1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // if (firstPage) { 1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // first = fCatalog.count() - fFirstPageCount; 1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // last = fCatalog.count() - 1; 1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // } 1190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeText("xref\n"); 1210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeDecAsText(first + 1); 1220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeText(" "); 1230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeDecAsText(last - first + 1); 1240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeText("\n"); 1250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (first == -1) { 1270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeText("0000000000 65535 f \n"); 1280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger first++; 1290b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger for (int i = first; i <= last; i++) { 1310b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fCatalog[i].fFileOffset > 0); 1320b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger SkASSERT(fCatalog[i].fFileOffset <= 9999999999LL); 1330b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeBigDecAsText(fCatalog[i].fFileOffset, 10); 1340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger stream->writeText(" 00000 n \n"); 1350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } 1360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 1370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger return fCatalog.count() + 1; 1380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger} 1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPDFCatalog::setSubstitute(SkPDFObject* original, 1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPDFObject* substitute) { 1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if defined(SK_DEBUG) 1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Sanity check: is the original already in substitute list? 1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < fSubstituteMap.count(); ++i) { 1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (original == fSubstituteMap[i].fSubstitute || 1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger original == fSubstituteMap[i].fOriginal) { 1471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(false); 1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 1491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif 1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Check if the original is on first page. 1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool onFirstPage = false; 1541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < fCatalog.count(); ++i) { 1551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fCatalog[i].fObject == original) { 1561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger onFirstPage = fCatalog[i].fOnFirstPage; 1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 1581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if defined(SK_DEBUG) 1601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (i == fCatalog.count() - 1) { 1611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(false); // original not in catalog 1621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif 1651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SubstituteMapping newMapping(original, substitute); 1681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSubstituteMap.append(1, &newMapping); 1691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Add resource objects of substitute object to catalog. 1711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkTDArray<SkPDFObject*>* targetList = getSubstituteList(onFirstPage); 1721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int existingSize = targetList->count(); 1731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger newMapping.fSubstitute->getResources(targetList); 1741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = existingSize; i < targetList->count(); ++i) { 1751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger addObject((*targetList)[i], onFirstPage); 1761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 1781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1791cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPDFObject* SkPDFCatalog::getSubstituteObject(SkPDFObject* object) { 1801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < fSubstituteMap.count(); ++i) { 1811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (object == fSubstituteMap[i].fOriginal) { 1821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return fSubstituteMap[i].fSubstitute; 1831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return object; 1861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 1871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergeroff_t SkPDFCatalog::setSubstituteResourcesOffsets(off_t fileOffset, 1891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool firstPage) { 1901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkTDArray<SkPDFObject*>* targetList = getSubstituteList(firstPage); 1911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger off_t offsetSum = fileOffset; 1921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < targetList->count(); ++i) { 1931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger offsetSum += setFileOffset((*targetList)[i], offsetSum); 1941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return offsetSum - fileOffset; 1961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 1971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPDFCatalog::emitSubstituteResources(SkWStream *stream, bool firstPage) { 1991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkTDArray<SkPDFObject*>* targetList = getSubstituteList(firstPage); 2001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < targetList->count(); ++i) { 2011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger (*targetList)[i]->emit(stream, this, true); 2021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 2031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 2041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2051cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkTDArray<SkPDFObject*>* SkPDFCatalog::getSubstituteList(bool firstPage) { 2061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return firstPage ? &fSubstituteResourcesFirstPage : 2071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger &fSubstituteResourcesRemaining; 2081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 209