OLD | NEW |
1 #include "SkNativeParsedPDF.h" | 1 #include "SkNativeParsedPDF.h" |
2 #include "SkPdfNativeTokenizer.h" | 2 #include "SkPdfNativeTokenizer.h" |
3 #include "SkPdfBasics.h" | 3 #include "SkPdfBasics.h" |
4 #include "SkPdfObject.h" | 4 #include "SkPdfObject.h" |
5 | 5 |
6 #include <stdio.h> | 6 #include <stdio.h> |
7 #include <string.h> | 7 #include <string.h> |
8 #include <sys/types.h> | 8 #include <sys/types.h> |
9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
10 | 10 |
11 #include "SkPdfFileTrailerDictionary_autogen.h" | 11 #include "SkPdfFileTrailerDictionary_autogen.h" |
12 #include "SkPdfCatalogDictionary_autogen.h" | 12 #include "SkPdfCatalogDictionary_autogen.h" |
13 #include "SkPdfPageObjectDictionary_autogen.h" | 13 #include "SkPdfPageObjectDictionary_autogen.h" |
14 #include "SkPdfPageTreeNodeDictionary_autogen.h" | 14 #include "SkPdfPageTreeNodeDictionary_autogen.h" |
15 #include "SkPdfMapper_autogen.h" | 15 #include "SkPdfMapper_autogen.h" |
16 | 16 |
17 | 17 |
18 | 18 |
19 static long getFileSize(const char* filename) | 19 static long getFileSize(const char* filename) |
20 { | 20 { |
21 struct stat stat_buf; | 21 struct stat stat_buf; |
22 int rc = stat(filename, &stat_buf); | 22 int rc = stat(filename, &stat_buf); |
23 return rc == 0 ? (long)stat_buf.st_size : -1; | 23 return rc == 0 ? (long)stat_buf.st_size : -1; |
24 } | 24 } |
25 | 25 |
26 static unsigned char* lineHome(unsigned char* start, unsigned char* current) { | 26 static const unsigned char* lineHome(const unsigned char* start, const unsigned
char* current) { |
27 while (current > start && !isPdfEOL(*(current - 1))) { | 27 while (current > start && !isPdfEOL(*(current - 1))) { |
28 current--; | 28 current--; |
29 } | 29 } |
30 return current; | 30 return current; |
31 } | 31 } |
32 | 32 |
33 static unsigned char* previousLineHome(unsigned char* start, unsigned char* curr
ent) { | 33 static const unsigned char* previousLineHome(const unsigned char* start, const u
nsigned char* current) { |
34 if (current > start && isPdfEOL(*(current - 1))) { | 34 if (current > start && isPdfEOL(*(current - 1))) { |
35 current--; | 35 current--; |
36 } | 36 } |
37 | 37 |
38 // allows CR+LF, LF+CR but not two CR+CR or LF+LF | 38 // allows CR+LF, LF+CR but not two CR+CR or LF+LF |
39 if (current > start && isPdfEOL(*(current - 1)) && *current != *(current - 1
)) { | 39 if (current > start && isPdfEOL(*(current - 1)) && *current != *(current - 1
)) { |
40 current--; | 40 current--; |
41 } | 41 } |
42 | 42 |
43 while (current > start && !isPdfEOL(*(current - 1))) { | 43 while (current > start && !isPdfEOL(*(current - 1))) { |
44 current--; | 44 current--; |
45 } | 45 } |
46 | 46 |
47 return current; | 47 return current; |
48 } | 48 } |
49 | 49 |
50 static unsigned char* ignoreLine(unsigned char* current, unsigned char* end) { | 50 static const unsigned char* ignoreLine(const unsigned char* current, const unsig
ned char* end) { |
51 while (current < end && !isPdfEOL(*current)) { | 51 while (current < end && !isPdfEOL(*current)) { |
52 current++; | 52 current++; |
53 } | 53 } |
54 current++; | 54 current++; |
55 if (current < end && isPdfEOL(*current) && *current != *(current - 1)) { | 55 if (current < end && isPdfEOL(*current) && *current != *(current - 1)) { |
56 current++; | 56 current++; |
57 } | 57 } |
58 return current; | 58 return current; |
59 } | 59 } |
60 | 60 |
61 SkNativeParsedPDF* gDoc = NULL; | 61 SkNativeParsedPDF* gDoc = NULL; |
62 | 62 |
63 // TODO(edisonn): NYI | 63 // TODO(edisonn): NYI |
64 // TODO(edisonn): 3 constructuctors from URL, from stream, from file ... | 64 // TODO(edisonn): 3 constructuctors from URL, from stream, from file ... |
65 // TODO(edisonn): write one that accepts errors in the file and ignores/fixis th
em | 65 // TODO(edisonn): write one that accepts errors in the file and ignores/fixis th
em |
66 // TODO(edisonn): testing: | 66 // TODO(edisonn): testing: |
67 // 1) run on a lot of file | 67 // 1) run on a lot of file |
68 // 2) recoverable corupt file: remove endobj, endsteam, remove other keywords, u
se other white spaces, insert comments randomly, ... | 68 // 2) recoverable corupt file: remove endobj, endsteam, remove other keywords, u
se other white spaces, insert comments randomly, ... |
69 // 3) irrecoverable corrupt file | 69 // 3) irrecoverable corrupt file |
70 SkNativeParsedPDF::SkNativeParsedPDF(const char* path) | 70 SkNativeParsedPDF::SkNativeParsedPDF(const char* path) |
71 : fAllocator(new SkPdfAllocator()) | 71 : fAllocator(new SkPdfAllocator()) |
72 , fRootCatalogRef(NULL) | 72 , fRootCatalogRef(NULL) |
73 , fRootCatalog(NULL) { | 73 , fRootCatalog(NULL) { |
74 gDoc = this; | 74 gDoc = this; |
75 FILE* file = fopen(path, "r"); | 75 FILE* file = fopen(path, "r"); |
76 fContentLength = getFileSize(path); | 76 fContentLength = getFileSize(path); |
77 fFileContent = new unsigned char[fContentLength + 1]; | 77 unsigned char* content = new unsigned char[fContentLength + 1]; |
78 bool ok = (0 != fread(fFileContent, fContentLength, 1, file)); | 78 bool ok = (0 != fread(content, fContentLength, 1, file)); |
79 fFileContent[fContentLength] = '\0'; | 79 content[fContentLength] = '\0'; |
| 80 fFileContent = content; |
80 fclose(file); | 81 fclose(file); |
81 file = NULL; | 82 file = NULL; |
82 | 83 |
83 if (!ok) { | 84 if (!ok) { |
84 // TODO(edisonn): report read error | 85 // TODO(edisonn): report read error |
85 return; // Doc will have 0 pages | 86 return; // Doc will have 0 pages |
86 } | 87 } |
87 | 88 |
88 unsigned char* eofLine = lineHome(fFileContent, fFileContent + fContentLengt
h - 1); | 89 const unsigned char* eofLine = lineHome(fFileContent, fFileContent + fConten
tLength - 1); |
89 unsigned char* xrefByteOffsetLine = previousLineHome(fFileContent, eofLine); | 90 const unsigned char* xrefByteOffsetLine = previousLineHome(fFileContent, eof
Line); |
90 unsigned char* xrefstartKeywordLine = previousLineHome(fFileContent, xrefByt
eOffsetLine); | 91 const unsigned char* xrefstartKeywordLine = previousLineHome(fFileContent, x
refByteOffsetLine); |
91 | 92 |
92 if (strcmp((char*)xrefstartKeywordLine, "startxref") != 0) { | 93 if (strcmp((char*)xrefstartKeywordLine, "startxref") != 0) { |
93 // TODO(edisonn): report/issue | 94 // TODO(edisonn): report/issue |
94 } | 95 } |
95 | 96 |
96 long xrefByteOffset = atol((const char*)xrefByteOffsetLine); | 97 long xrefByteOffset = atol((const char*)xrefByteOffsetLine); |
97 | 98 |
98 bool storeCatalog = true; | 99 bool storeCatalog = true; |
99 while (xrefByteOffset >= 0) { | 100 while (xrefByteOffset >= 0) { |
100 unsigned char* trailerStart = readCrossReferenceSection(fFileContent + x
refByteOffset, xrefstartKeywordLine); | 101 const unsigned char* trailerStart = readCrossReferenceSection(fFileConte
nt + xrefByteOffset, xrefstartKeywordLine); |
101 xrefByteOffset = readTrailer(trailerStart, xrefstartKeywordLine, storeCa
talog); | 102 xrefByteOffset = readTrailer(trailerStart, xrefstartKeywordLine, storeCa
talog); |
102 storeCatalog = false; | 103 storeCatalog = false; |
103 } | 104 } |
104 | 105 |
105 // TODO(edisonn): warn/error expect fObjects[fRefCatalogId].fGeneration == f
RefCatalogGeneration | 106 // TODO(edisonn): warn/error expect fObjects[fRefCatalogId].fGeneration == f
RefCatalogGeneration |
106 // TODO(edisonn): security, verify that SkPdfCatalogDictionary is indeed usi
ng mapper | 107 // TODO(edisonn): security, verify that SkPdfCatalogDictionary is indeed usi
ng mapper |
107 // load catalog | 108 // load catalog |
108 | 109 |
109 if (fRootCatalogRef) { | 110 if (fRootCatalogRef) { |
110 fRootCatalog = (SkPdfCatalogDictionary*)resolveReference(fRootCatalogRef
); | 111 fRootCatalog = (SkPdfCatalogDictionary*)resolveReference(fRootCatalogRef
); |
(...skipping 11 matching lines...) Expand all Loading... |
122 // now actually read all objects if we want, or do it lazyly | 123 // now actually read all objects if we want, or do it lazyly |
123 // and resolve references?... or not ... | 124 // and resolve references?... or not ... |
124 } | 125 } |
125 | 126 |
126 // TODO(edisonn): NYI | 127 // TODO(edisonn): NYI |
127 SkNativeParsedPDF::~SkNativeParsedPDF() { | 128 SkNativeParsedPDF::~SkNativeParsedPDF() { |
128 delete[] fFileContent; | 129 delete[] fFileContent; |
129 delete fAllocator; | 130 delete fAllocator; |
130 } | 131 } |
131 | 132 |
132 unsigned char* SkNativeParsedPDF::readCrossReferenceSection(unsigned char* xrefS
tart, unsigned char* trailerEnd) { | 133 const unsigned char* SkNativeParsedPDF::readCrossReferenceSection(const unsigned
char* xrefStart, const unsigned char* trailerEnd) { |
133 unsigned char* current = ignoreLine(xrefStart, trailerEnd); // TODO(edisonn
): verify next keyord is "xref", use nextObject here | 134 const unsigned char* current = ignoreLine(xrefStart, trailerEnd); // TODO(e
disonn): verify next keyord is "xref", use nextObject here |
134 | 135 |
135 SkPdfObject token; | 136 SkPdfObject token; |
136 while (current < trailerEnd) { | 137 while (current < trailerEnd) { |
137 token.reset(); | 138 token.reset(); |
138 unsigned char* previous = current; | 139 const unsigned char* previous = current; |
139 current = nextObject(current, trailerEnd, &token, NULL, NULL); | 140 current = nextObject(0, current, trailerEnd, &token, NULL, NULL); |
140 if (!token.isInteger()) { | 141 if (!token.isInteger()) { |
141 return previous; | 142 return previous; |
142 } | 143 } |
143 | 144 |
144 int startId = (int)token.intValue(); | 145 int startId = (int)token.intValue(); |
145 token.reset(); | 146 token.reset(); |
146 current = nextObject(current, trailerEnd, &token, NULL, NULL); | 147 current = nextObject(0, current, trailerEnd, &token, NULL, NULL); |
147 | 148 |
148 if (!token.isInteger()) { | 149 if (!token.isInteger()) { |
149 // TODO(edisonn): report/warning | 150 // TODO(edisonn): report/warning |
150 return current; | 151 return current; |
151 } | 152 } |
152 | 153 |
153 int entries = (int)token.intValue(); | 154 int entries = (int)token.intValue(); |
154 | 155 |
155 for (int i = 0; i < entries; i++) { | 156 for (int i = 0; i < entries; i++) { |
156 token.reset(); | 157 token.reset(); |
157 current = nextObject(current, trailerEnd, &token, NULL, NULL); | 158 current = nextObject(0, current, trailerEnd, &token, NULL, NULL); |
158 if (!token.isInteger()) { | 159 if (!token.isInteger()) { |
159 // TODO(edisonn): report/warning | 160 // TODO(edisonn): report/warning |
160 return current; | 161 return current; |
161 } | 162 } |
162 int offset = (int)token.intValue(); | 163 int offset = (int)token.intValue(); |
163 | 164 |
164 token.reset(); | 165 token.reset(); |
165 current = nextObject(current, trailerEnd, &token, NULL, NULL); | 166 current = nextObject(0, current, trailerEnd, &token, NULL, NULL); |
166 if (!token.isInteger()) { | 167 if (!token.isInteger()) { |
167 // TODO(edisonn): report/warning | 168 // TODO(edisonn): report/warning |
168 return current; | 169 return current; |
169 } | 170 } |
170 int generation = (int)token.intValue(); | 171 int generation = (int)token.intValue(); |
171 | 172 |
172 token.reset(); | 173 token.reset(); |
173 current = nextObject(current, trailerEnd, &token, NULL, NULL); | 174 current = nextObject(0, current, trailerEnd, &token, NULL, NULL); |
174 if (!token.isKeyword() || token.len() != 1 || (*token.c_str() != 'f'
&& *token.c_str() != 'n')) { | 175 if (!token.isKeyword() || token.len() != 1 || (*token.c_str() != 'f'
&& *token.c_str() != 'n')) { |
175 // TODO(edisonn): report/warning | 176 // TODO(edisonn): report/warning |
176 return current; | 177 return current; |
177 } | 178 } |
178 | 179 |
179 addCrossSectionInfo(startId + i, generation, offset, *token.c_str()
== 'f'); | 180 addCrossSectionInfo(startId + i, generation, offset, *token.c_str()
== 'f'); |
180 } | 181 } |
181 } | 182 } |
182 // TODO(edisonn): it should never get here? there is no trailer? | 183 // TODO(edisonn): it should never get here? there is no trailer? |
183 return current; | 184 return current; |
184 } | 185 } |
185 | 186 |
186 long SkNativeParsedPDF::readTrailer(unsigned char* trailerStart, unsigned char*
trailerEnd, bool storeCatalog) { | 187 long SkNativeParsedPDF::readTrailer(const unsigned char* trailerStart, const uns
igned char* trailerEnd, bool storeCatalog) { |
187 unsigned char* current = ignoreLine(trailerStart, trailerEnd); // TODO(edis
onn): verify next keyord is "trailer" use nextObject here | 188 SkPdfObject trailerKeyword; |
| 189 // TODO(edisonn): use null allocator, and let it just fail if memory |
| 190 // needs allocated (but no crash)! |
| 191 const unsigned char* current = |
| 192 nextObject(0, trailerStart, trailerEnd, &trailerKeyword, fAllocator,
NULL); |
| 193 |
| 194 if (strlen("trailer") != trailerKeyword.len() && |
| 195 strncmp(trailerKeyword.c_str(), "trailer", strlen("trailer")) != 0) { |
| 196 // TODO(edisonn): report warning, rebuild trailer from objects. |
| 197 return -1; |
| 198 } |
188 | 199 |
189 SkPdfObject token; | 200 SkPdfObject token; |
190 current = nextObject(current, trailerEnd, &token, fAllocator, NULL); | 201 current = nextObject(0, current, trailerEnd, &token, fAllocator, NULL); |
191 if (!token.isDictionary()) { | 202 if (!token.isDictionary()) { |
192 return -1; | 203 return -1; |
193 } | 204 } |
194 SkPdfFileTrailerDictionary* trailer = (SkPdfFileTrailerDictionary*)&token; | 205 SkPdfFileTrailerDictionary* trailer = (SkPdfFileTrailerDictionary*)&token; |
195 if (!trailer->valid()) { | 206 if (!trailer->valid()) { |
196 return -1; | 207 return -1; |
197 } | 208 } |
198 | 209 |
199 if (storeCatalog) { | 210 if (storeCatalog) { |
200 const SkPdfObject* ref = trailer->Root(NULL); | 211 const SkPdfObject* ref = trailer->Root(NULL); |
(...skipping 22 matching lines...) Expand all Loading... |
223 } | 234 } |
224 | 235 |
225 SkPdfObject* SkNativeParsedPDF::readObject(int id/*, int expectedGeneration*/) { | 236 SkPdfObject* SkNativeParsedPDF::readObject(int id/*, int expectedGeneration*/) { |
226 long startOffset = fObjects[id].fOffset; | 237 long startOffset = fObjects[id].fOffset; |
227 //long endOffset = fObjects[id].fOffsetEnd; | 238 //long endOffset = fObjects[id].fOffsetEnd; |
228 // TODO(edisonn): use hinted endOffset | 239 // TODO(edisonn): use hinted endOffset |
229 // TODO(edisonn): current implementation will result in a lot of memory usag
e | 240 // TODO(edisonn): current implementation will result in a lot of memory usag
e |
230 // to decrease memory usage, we wither need to be smart and know where objec
ts end, and we will | 241 // to decrease memory usage, we wither need to be smart and know where objec
ts end, and we will |
231 // alocate only the chancks needed, or the tokenizer will not make copies, b
ut then it needs to | 242 // alocate only the chancks needed, or the tokenizer will not make copies, b
ut then it needs to |
232 // cache the results so it does not go twice on the same buffer | 243 // cache the results so it does not go twice on the same buffer |
233 unsigned char* current = fFileContent + startOffset; | 244 const unsigned char* current = fFileContent + startOffset; |
234 unsigned char* end = fFileContent + fContentLength; | 245 const unsigned char* end = fFileContent + fContentLength; |
235 | 246 |
236 SkPdfNativeTokenizer tokenizer(current, end - current, fMapper, fAllocator,
this); | 247 SkPdfNativeTokenizer tokenizer(current, end - current, fMapper, fAllocator,
this); |
237 | 248 |
238 SkPdfObject idObj; | 249 SkPdfObject idObj; |
239 SkPdfObject generationObj; | 250 SkPdfObject generationObj; |
240 SkPdfObject objKeyword; | 251 SkPdfObject objKeyword; |
241 SkPdfObject* dict = fAllocator->allocObject(); | 252 SkPdfObject* dict = fAllocator->allocObject(); |
242 | 253 |
243 current = nextObject(current, end, &idObj, NULL, NULL); | 254 current = nextObject(0, current, end, &idObj, NULL, NULL); |
244 if (current >= end) { | 255 if (current >= end) { |
245 // TODO(edisonn): report warning/error | 256 // TODO(edisonn): report warning/error |
246 return NULL; | 257 return NULL; |
247 } | 258 } |
248 | 259 |
249 current = nextObject(current, end, &generationObj, NULL, NULL); | 260 current = nextObject(0, current, end, &generationObj, NULL, NULL); |
250 if (current >= end) { | 261 if (current >= end) { |
251 // TODO(edisonn): report warning/error | 262 // TODO(edisonn): report warning/error |
252 return NULL; | 263 return NULL; |
253 } | 264 } |
254 | 265 |
255 current = nextObject(current, end, &objKeyword, NULL, NULL); | 266 current = nextObject(0, current, end, &objKeyword, NULL, NULL); |
256 if (current >= end) { | 267 if (current >= end) { |
257 // TODO(edisonn): report warning/error | 268 // TODO(edisonn): report warning/error |
258 return NULL; | 269 return NULL; |
259 } | 270 } |
260 | 271 |
261 if (!idObj.isInteger() || !generationObj.isInteger() || id != idObj.intValue
()/* || generation != generationObj.intValue()*/) { | 272 if (!idObj.isInteger() || !generationObj.isInteger() || id != idObj.intValue
()/* || generation != generationObj.intValue()*/) { |
262 // TODO(edisonn): report warning/error | 273 // TODO(edisonn): report warning/error |
263 } | 274 } |
264 | 275 |
265 if (!objKeyword.isKeyword() || strcmp(objKeyword.c_str(), "obj") != 0) { | 276 if (!objKeyword.isKeyword() || strcmp(objKeyword.c_str(), "obj") != 0) { |
266 // TODO(edisonn): report warning/error | 277 // TODO(edisonn): report warning/error |
267 } | 278 } |
268 | 279 |
269 current = nextObject(current, end, dict, fAllocator, this); | 280 current = nextObject(1, current, end, dict, fAllocator, this); |
270 | 281 |
271 // TODO(edisonn): report warning/error - verify last token is endobj | 282 // TODO(edisonn): report warning/error - verify last token is endobj |
272 | 283 |
273 return dict; | 284 return dict; |
274 } | 285 } |
275 | 286 |
276 void SkNativeParsedPDF::fillPages(SkPdfPageTreeNodeDictionary* tree) { | 287 void SkNativeParsedPDF::fillPages(SkPdfPageTreeNodeDictionary* tree) { |
277 const SkPdfArray* kids = tree->Kids(this); | 288 const SkPdfArray* kids = tree->Kids(this); |
278 if (kids == NULL) { | 289 if (kids == NULL) { |
279 *fPages.append() = (SkPdfPageObjectDictionary*)tree; | 290 *fPages.append() = (SkPdfPageObjectDictionary*)tree; |
(...skipping 26 matching lines...) Expand all Loading... |
306 while (!current->has_MediaBox() && current->has_Parent()) { | 317 while (!current->has_MediaBox() && current->has_Parent()) { |
307 current = (SkPdfPageObjectDictionary*)current->Parent(this); | 318 current = (SkPdfPageObjectDictionary*)current->Parent(this); |
308 } | 319 } |
309 if (current) { | 320 if (current) { |
310 return current->MediaBox(this); | 321 return current->MediaBox(this); |
311 } | 322 } |
312 return SkRect::MakeEmpty(); | 323 return SkRect::MakeEmpty(); |
313 } | 324 } |
314 | 325 |
315 // TODO(edisonn): stream or array ... ? for now only array | 326 // TODO(edisonn): stream or array ... ? for now only array |
316 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfPage(int page) { | 327 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfPage(int page, |
| 328 SkPdfAllocator* allocat
or) { |
317 if (fPages[page]->isContentsAStream(this)) { | 329 if (fPages[page]->isContentsAStream(this)) { |
318 return tokenizerOfStream(fPages[page]->getContentsAsStream(this)); | 330 return tokenizerOfStream(fPages[page]->getContentsAsStream(this), alloca
tor); |
319 } else { | 331 } else { |
320 // TODO(edisonn): NYI, we need to concatenate all streams in the array o
r make the tokenizer smart | 332 // TODO(edisonn): NYI, we need to concatenate all streams in the array o
r make the tokenizer smart |
321 // so we don't allocate new memory | 333 // so we don't allocate new memory |
322 return NULL; | 334 return NULL; |
323 } | 335 } |
324 } | 336 } |
325 | 337 |
326 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfStream(SkPdfObject* stream)
{ | 338 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfStream(SkPdfObject* stream, |
| 339 SkPdfAllocator* alloc
ator) { |
327 if (stream == NULL) { | 340 if (stream == NULL) { |
328 return NULL; | 341 return NULL; |
329 } | 342 } |
330 | 343 |
331 return new SkPdfNativeTokenizer(stream, fMapper, fAllocator, this); | 344 return new SkPdfNativeTokenizer(stream, fMapper, allocator, this); |
332 } | 345 } |
333 | 346 |
334 // TODO(edisonn): NYI | 347 // TODO(edisonn): NYI |
335 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfBuffer(unsigned char* buffer
, size_t len) { | 348 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfBuffer(const unsigned char*
buffer, size_t len, |
| 349 SkPdfAllocator* alloc
ator) { |
336 // warning does not track two calls in the same buffer! the buffer is update
d! | 350 // warning does not track two calls in the same buffer! the buffer is update
d! |
337 // make a clean copy if needed! | 351 // make a clean copy if needed! |
338 return new SkPdfNativeTokenizer(buffer, len, fMapper, fAllocator, this); | 352 return new SkPdfNativeTokenizer(buffer, len, fMapper, allocator, this); |
339 } | 353 } |
340 | 354 |
341 size_t SkNativeParsedPDF::objects() const { | 355 size_t SkNativeParsedPDF::objects() const { |
342 return fObjects.count(); | 356 return fObjects.count(); |
343 } | 357 } |
344 | 358 |
345 SkPdfObject* SkNativeParsedPDF::object(int i) { | 359 SkPdfObject* SkNativeParsedPDF::object(int i) { |
346 SkASSERT(!(i < 0 || i > fObjects.count())); | 360 SkASSERT(!(i < 0 || i > fObjects.count())); |
347 | 361 |
348 if (i < 0 || i > fObjects.count()) { | 362 if (i < 0 || i > fObjects.count()) { |
(...skipping 18 matching lines...) Expand all Loading... |
367 SkPdfObject::makeReal(value, obj); | 381 SkPdfObject::makeReal(value, obj); |
368 return (SkPdfReal*)obj; | 382 return (SkPdfReal*)obj; |
369 } | 383 } |
370 | 384 |
371 SkPdfInteger* SkNativeParsedPDF::createInteger(int value) const { | 385 SkPdfInteger* SkNativeParsedPDF::createInteger(int value) const { |
372 SkPdfObject* obj = fAllocator->allocObject(); | 386 SkPdfObject* obj = fAllocator->allocObject(); |
373 SkPdfObject::makeInteger(value, obj); | 387 SkPdfObject::makeInteger(value, obj); |
374 return (SkPdfInteger*)obj; | 388 return (SkPdfInteger*)obj; |
375 } | 389 } |
376 | 390 |
377 SkPdfString* SkNativeParsedPDF::createString(unsigned char* sz, size_t len) cons
t { | 391 SkPdfString* SkNativeParsedPDF::createString(const unsigned char* sz, size_t len
) const { |
378 SkPdfObject* obj = fAllocator->allocObject(); | 392 SkPdfObject* obj = fAllocator->allocObject(); |
379 SkPdfObject::makeString(sz, len, obj); | 393 SkPdfObject::makeString(sz, len, obj); |
380 return (SkPdfString*)obj; | 394 return (SkPdfString*)obj; |
381 } | 395 } |
382 | 396 |
383 SkPdfAllocator* SkNativeParsedPDF::allocator() const { | 397 SkPdfAllocator* SkNativeParsedPDF::allocator() const { |
384 return fAllocator; | 398 return fAllocator; |
385 } | 399 } |
386 | 400 |
387 // TODO(edisonn): fix infinite loop if ref to itself! | 401 // TODO(edisonn): fix infinite loop if ref to itself! |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 return (SkPdfObject*)ref; | 436 return (SkPdfObject*)ref; |
423 } | 437 } |
424 | 438 |
425 size_t SkNativeParsedPDF::bytesUsed() const { | 439 size_t SkNativeParsedPDF::bytesUsed() const { |
426 return fAllocator->bytesUsed() + | 440 return fAllocator->bytesUsed() + |
427 fContentLength + | 441 fContentLength + |
428 fObjects.count() * sizeof(PublicObjectEntry) + | 442 fObjects.count() * sizeof(PublicObjectEntry) + |
429 fPages.count() * sizeof(SkPdfPageObjectDictionary*) + | 443 fPages.count() * sizeof(SkPdfPageObjectDictionary*) + |
430 sizeof(*this); | 444 sizeof(*this); |
431 } | 445 } |
OLD | NEW |