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