15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2010 The Android Open Source Project 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * found in the LICENSE file. 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkPDFCatalog.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "SkPDFTypes.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkStream.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "SkTypes.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkPDFCatalog::SkPDFCatalog(SkPDFDocument::Flags flags) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : fFirstPageCount(0), 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fNextObjNum(1), 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fNextFirstPageObjNum(0), 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fDocumentFlags(flags) { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkPDFCatalog::~SkPDFCatalog() { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fSubstituteResourcesRemaining.safeUnrefAll(); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fSubstituteResourcesFirstPage.safeUnrefAll(); 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkPDFObject* SkPDFCatalog::addObject(SkPDFObject* obj, bool onFirstPage) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (findObjectIndex(obj) != -1) { // object already added 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return obj; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(fNextFirstPageObjNum == 0); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (onFirstPage) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fFirstPageCount++; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Rec newEntry(obj, onFirstPage); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCatalog.append(1, &newEntry); 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return obj; 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SkPDFCatalog::setFileOffset(SkPDFObject* obj, off_t offset) { 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int objIndex = assignObjNum(obj) - 1; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkASSERT(fCatalog[objIndex].fObjNumAssigned); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(fCatalog[objIndex].fFileOffset == 0); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCatalog[objIndex].fFileOffset = offset; 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return getSubstituteObject(obj)->getOutputSize(this, true); 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SkPDFCatalog::emitObjectNumber(SkWStream* stream, SkPDFObject* obj) { 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->writeDecAsText(assignObjNum(obj)); 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stream->writeText(" 0"); // Generation number is always 0. 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SkPDFCatalog::getObjectNumberSize(SkPDFObject* obj) { 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SkDynamicMemoryWStream buffer; 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) emitObjectNumber(&buffer, obj); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return buffer.getOffset(); 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int SkPDFCatalog::findObjectIndex(SkPDFObject* obj) const { 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < fCatalog.count(); i++) { 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (fCatalog[i].fObject == obj) { 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return i; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it's not in the main array, check if it's a substitute object. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < fSubstituteMap.count(); ++i) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fSubstituteMap[i].fSubstitute == obj) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return findObjectIndex(fSubstituteMap[i].fOriginal); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SkPDFCatalog::assignObjNum(SkPDFObject* obj) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pos = findObjectIndex(obj); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this assert fails, it means you probably forgot to add an object 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the resource list. 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkASSERT(pos >= 0); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t currentIndex = pos; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fCatalog[currentIndex].fObjNumAssigned) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return currentIndex + 1; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First assignment. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fNextFirstPageObjNum == 0) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fNextFirstPageObjNum = fCatalog.count() - fFirstPageCount + 1; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t objNum; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fCatalog[currentIndex].fOnFirstPage) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) objNum = fNextFirstPageObjNum; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fNextFirstPageObjNum++; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) objNum = fNextObjNum; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fNextObjNum++; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we assign an object an object number, we put it in that array 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // offset (minus 1 because object number 0 is reserved). 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkASSERT(!fCatalog[objNum - 1].fObjNumAssigned); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (objNum - 1 != currentIndex) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkTSwap(fCatalog[objNum - 1], fCatalog[currentIndex]); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fCatalog[objNum - 1].fObjNumAssigned = true; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return objNum; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t SkPDFCatalog::emitXrefTable(SkWStream* stream, bool firstPage) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first = -1; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int last = fCatalog.count() - 1; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(vandebo): Support linearized format. 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // int last = fCatalog.count() - fFirstPageCount - 1; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if (firstPage) { 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // first = fCatalog.count() - fFirstPageCount; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last = fCatalog.count() - 1; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeText("xref\n"); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeDecAsText(first + 1); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeText(" "); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeDecAsText(last - first + 1); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeText("\n"); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (first == -1) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeText("0000000000 65535 f \n"); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first++; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = first; i <= last; i++) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For 32 bits platforms, the maximum offset has to fit within off_t 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is a 32 bits signed integer on these platforms. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkDEBUGCODE(static const off_t kMaxOff = SK_MaxS32;) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(fCatalog[i].fFileOffset > 0); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(fCatalog[i].fFileOffset < kMaxOff); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeBigDecAsText(fCatalog[i].fFileOffset, 10); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream->writeText(" 00000 n \n"); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fCatalog.count() + 1; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkPDFCatalog::setSubstitute(SkPDFObject* original, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPDFObject* substitute) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SK_DEBUG) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sanity check: is the original already in substitute list? 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < fSubstituteMap.count(); ++i) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (original == fSubstituteMap[i].fSubstitute || 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original == fSubstituteMap[i].fOriginal) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(false); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the original is on first page. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool onFirstPage = false; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < fCatalog.count(); ++i) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fCatalog[i].fObject == original) { 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) onFirstPage = fCatalog[i].fOnFirstPage; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(SK_DEBUG) 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (i == fCatalog.count() - 1) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(false); // original not in catalog 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SubstituteMapping newMapping(original, substitute); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fSubstituteMap.append(1, &newMapping); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add resource objects of substitute object to catalog. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkTSet<SkPDFObject*>* targetSet = getSubstituteList(onFirstPage); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkTSet<SkPDFObject*> newResourceObjects; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newMapping.fSubstitute->getResources(*targetSet, &newResourceObjects); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < newResourceObjects.count(); ++i) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addObject(newResourceObjects[i], onFirstPage); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mergeInto returns the number of duplicates. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there are duplicates, there is a bug and we mess ref counting. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkDEBUGCODE(int duplicates =) targetSet->mergeInto(newResourceObjects); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(duplicates == 0); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkPDFObject* SkPDFCatalog::getSubstituteObject(SkPDFObject* object) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < fSubstituteMap.count(); ++i) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (object == fSubstituteMap[i].fOriginal) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fSubstituteMap[i].fSubstitute; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return object; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)off_t SkPDFCatalog::setSubstituteResourcesOffsets(off_t fileOffset, 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool firstPage) { 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SkTSet<SkPDFObject*>* targetSet = getSubstituteList(firstPage); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) off_t offsetSum = fileOffset; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < targetSet->count(); ++i) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offsetSum += setFileOffset((*targetSet)[i], offsetSum); 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return offsetSum - fileOffset; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SkPDFCatalog::emitSubstituteResources(SkWStream *stream, bool firstPage) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkTSet<SkPDFObject*>* targetSet = getSubstituteList(firstPage); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < targetSet->count(); ++i) { 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*targetSet)[i]->emit(stream, this, true); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkTSet<SkPDFObject*>* SkPDFCatalog::getSubstituteList(bool firstPage) { 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return firstPage ? &fSubstituteResourcesFirstPage : 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &fSubstituteResourcesRemaining; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)