| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2010 The Android Open Source Project | 3 * Copyright 2010 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkPDFCatalog.h" | 10 #include "SkPDFCatalog.h" |
| 11 #include "SkPDFTypes.h" | |
| 12 #include "SkStream.h" | |
| 13 #include "SkTypes.h" | |
| 14 | 11 |
| 15 SkPDFCatalog::SkPDFCatalog() | 12 SkPDFCatalog::SkPDFCatalog() {} |
| 16 : fFirstPageCount(0) | |
| 17 , fNextObjNum(1) | |
| 18 , fNextFirstPageObjNum(0) {} | |
| 19 | 13 |
| 20 SkPDFCatalog::~SkPDFCatalog() { | 14 SkPDFCatalog::~SkPDFCatalog() { |
| 21 fSubstituteResourcesRemaining.safeUnrefAll(); | 15 fSubstituteMap.foreach( |
| 22 fSubstituteResourcesFirstPage.safeUnrefAll(); | 16 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); }); |
| 23 } | 17 } |
| 24 | 18 |
| 25 SkPDFObject* SkPDFCatalog::addObject(SkPDFObject* obj, bool onFirstPage) { | 19 bool SkPDFCatalog::addObject(SkPDFObject* obj) { |
| 26 if (findObjectIndex(obj) != -1) { // object already added | 20 if (fObjectNumbers.find(obj)) { |
| 27 return obj; | 21 return false; |
| 28 } | 22 } |
| 29 SkASSERT(fNextFirstPageObjNum == 0); | 23 fObjectNumbers.set(obj, fObjectNumbers.count() + 1); |
| 30 if (onFirstPage) { | 24 return true; |
| 31 fFirstPageCount++; | |
| 32 } | |
| 33 | |
| 34 Rec newEntry(obj, onFirstPage); | |
| 35 fCatalog.append(1, &newEntry); | |
| 36 return obj; | |
| 37 } | 25 } |
| 38 | 26 |
| 39 void SkPDFCatalog::setFileOffset(SkPDFObject* obj, off_t offset) { | 27 int32_t SkPDFCatalog::getObjectNumber(SkPDFObject* obj) const { |
| 40 int objIndex = assignObjNum(obj) - 1; | 28 int32_t* objectNumberFound = fObjectNumbers.find(obj); |
| 41 SkASSERT(fCatalog[objIndex].fObjNumAssigned); | 29 SkASSERT(objectNumberFound); |
| 42 SkASSERT(fCatalog[objIndex].fFileOffset == 0); | 30 return *objectNumberFound; |
| 43 fCatalog[objIndex].fFileOffset = offset; | |
| 44 } | |
| 45 | |
| 46 int32_t SkPDFCatalog::getObjectNumber(SkPDFObject* obj) { | |
| 47 return (int32_t)assignObjNum(obj); | |
| 48 } | |
| 49 | |
| 50 int SkPDFCatalog::findObjectIndex(SkPDFObject* obj) { | |
| 51 for (int i = 0; i < fCatalog.count(); i++) { | |
| 52 if (fCatalog[i].fObject == obj) { | |
| 53 return i; | |
| 54 } | |
| 55 } | |
| 56 // If it's not in the main array, check if it's a substitute object. | |
| 57 for (int i = 0; i < fSubstituteMap.count(); ++i) { | |
| 58 if (fSubstituteMap[i].fSubstitute == obj) { | |
| 59 return findObjectIndex(fSubstituteMap[i].fOriginal); | |
| 60 } | |
| 61 } | |
| 62 Rec newEntry(obj, false); | |
| 63 fCatalog.append(1, &newEntry); | |
| 64 return fCatalog.count() - 1; | |
| 65 } | |
| 66 | |
| 67 int SkPDFCatalog::assignObjNum(SkPDFObject* obj) { | |
| 68 int pos = findObjectIndex(obj); | |
| 69 // If this assert fails, it means you probably forgot to add an object | |
| 70 // to the resource list. | |
| 71 SkASSERT(pos >= 0); | |
| 72 uint32_t currentIndex = pos; | |
| 73 if (fCatalog[currentIndex].fObjNumAssigned) { | |
| 74 return currentIndex + 1; | |
| 75 } | |
| 76 | |
| 77 // First assignment. | |
| 78 if (fNextFirstPageObjNum == 0) { | |
| 79 fNextFirstPageObjNum = fCatalog.count() - fFirstPageCount + 1; | |
| 80 } | |
| 81 | |
| 82 uint32_t objNum; | |
| 83 if (fCatalog[currentIndex].fOnFirstPage) { | |
| 84 objNum = fNextFirstPageObjNum; | |
| 85 fNextFirstPageObjNum++; | |
| 86 } else { | |
| 87 objNum = fNextObjNum; | |
| 88 fNextObjNum++; | |
| 89 } | |
| 90 | |
| 91 // When we assign an object an object number, we put it in that array | |
| 92 // offset (minus 1 because object number 0 is reserved). | |
| 93 SkASSERT(!fCatalog[objNum - 1].fObjNumAssigned); | |
| 94 if (objNum - 1 != currentIndex) { | |
| 95 SkTSwap(fCatalog[objNum - 1], fCatalog[currentIndex]); | |
| 96 } | |
| 97 fCatalog[objNum - 1].fObjNumAssigned = true; | |
| 98 return objNum; | |
| 99 } | |
| 100 | |
| 101 int32_t SkPDFCatalog::emitXrefTable(SkWStream* stream, bool firstPage) { | |
| 102 int first = -1; | |
| 103 int last = fCatalog.count() - 1; | |
| 104 // TODO(vandebo): Support linearized format. | |
| 105 // int last = fCatalog.count() - fFirstPageCount - 1; | |
| 106 // if (firstPage) { | |
| 107 // first = fCatalog.count() - fFirstPageCount; | |
| 108 // last = fCatalog.count() - 1; | |
| 109 // } | |
| 110 | |
| 111 stream->writeText("xref\n"); | |
| 112 stream->writeDecAsText(first + 1); | |
| 113 stream->writeText(" "); | |
| 114 stream->writeDecAsText(last - first + 1); | |
| 115 stream->writeText("\n"); | |
| 116 | |
| 117 if (first == -1) { | |
| 118 stream->writeText("0000000000 65535 f \n"); | |
| 119 first++; | |
| 120 } | |
| 121 for (int i = first; i <= last; i++) { | |
| 122 // For 32 bits platforms, the maximum offset has to fit within off_t | |
| 123 // which is a 32 bits signed integer on these platforms. | |
| 124 SkDEBUGCODE(static const off_t kMaxOff = SK_MaxS32;) | |
| 125 SkASSERT(fCatalog[i].fFileOffset > 0); | |
| 126 SkASSERT(fCatalog[i].fFileOffset < kMaxOff); | |
| 127 stream->writeBigDecAsText(fCatalog[i].fFileOffset, 10); | |
| 128 stream->writeText(" 00000 n \n"); | |
| 129 } | |
| 130 | |
| 131 return fCatalog.count() + 1; | |
| 132 } | 31 } |
| 133 | 32 |
| 134 void SkPDFCatalog::setSubstitute(SkPDFObject* original, | 33 void SkPDFCatalog::setSubstitute(SkPDFObject* original, |
| 135 SkPDFObject* substitute) { | 34 SkPDFObject* substitute) { |
| 136 #if defined(SK_DEBUG) | 35 SkASSERT(original != substitute); |
| 137 // Sanity check: is the original already in substitute list? | 36 SkASSERT(!fSubstituteMap.find(original)); |
| 138 for (int i = 0; i < fSubstituteMap.count(); ++i) { | 37 fSubstituteMap.set(original, SkRef(substitute)); |
| 139 if (original == fSubstituteMap[i].fSubstitute || | |
| 140 original == fSubstituteMap[i].fOriginal) { | |
| 141 SkASSERT(false); | |
| 142 return; | |
| 143 } | |
| 144 } | |
| 145 #endif | |
| 146 SubstituteMapping newMapping(original, substitute); | |
| 147 fSubstituteMap.append(1, &newMapping); | |
| 148 } | 38 } |
| 149 | 39 |
| 150 SkPDFObject* SkPDFCatalog::getSubstituteObject(SkPDFObject* object) { | 40 SkPDFObject* SkPDFCatalog::getSubstituteObject(SkPDFObject* object) const { |
| 151 for (int i = 0; i < fSubstituteMap.count(); ++i) { | 41 SkPDFObject** found = fSubstituteMap.find(object); |
| 152 if (object == fSubstituteMap[i].fOriginal) { | 42 return found ? *found : object; |
| 153 return fSubstituteMap[i].fSubstitute; | |
| 154 } | |
| 155 } | |
| 156 return object; | |
| 157 } | 43 } |
| 158 | |
| OLD | NEW |