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 |