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 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 delete fAllocator; | 121 delete fAllocator; |
122 } | 122 } |
123 | 123 |
124 unsigned char* SkNativeParsedPDF::readCrossReferenceSection(unsigned char* xrefS
tart, unsigned char* trailerEnd) { | 124 unsigned char* SkNativeParsedPDF::readCrossReferenceSection(unsigned char* xrefS
tart, unsigned char* trailerEnd) { |
125 unsigned char* current = ignoreLine(xrefStart, trailerEnd); // TODO(edisonn
): verify next keyord is "xref", use nextObject here | 125 unsigned char* current = ignoreLine(xrefStart, trailerEnd); // TODO(edisonn
): verify next keyord is "xref", use nextObject here |
126 | 126 |
127 SkPdfObject token; | 127 SkPdfObject token; |
128 while (current < trailerEnd) { | 128 while (current < trailerEnd) { |
129 token.reset(); | 129 token.reset(); |
130 unsigned char* previous = current; | 130 unsigned char* previous = current; |
131 current = nextObject(current, trailerEnd, &token, NULL); | 131 current = nextObject(current, trailerEnd, &token, NULL, NULL); |
132 if (!token.isInteger()) { | 132 if (!token.isInteger()) { |
133 return previous; | 133 return previous; |
134 } | 134 } |
135 | 135 |
136 int startId = (int)token.intValue(); | 136 int startId = (int)token.intValue(); |
137 token.reset(); | 137 token.reset(); |
138 current = nextObject(current, trailerEnd, &token, NULL); | 138 current = nextObject(current, trailerEnd, &token, NULL, NULL); |
139 | 139 |
140 if (!token.isInteger()) { | 140 if (!token.isInteger()) { |
141 // TODO(edisonn): report/warning | 141 // TODO(edisonn): report/warning |
142 return current; | 142 return current; |
143 } | 143 } |
144 | 144 |
145 int entries = (int)token.intValue(); | 145 int entries = (int)token.intValue(); |
146 | 146 |
147 for (int i = 0; i < entries; i++) { | 147 for (int i = 0; i < entries; i++) { |
148 token.reset(); | 148 token.reset(); |
149 current = nextObject(current, trailerEnd, &token, NULL); | 149 current = nextObject(current, trailerEnd, &token, NULL, NULL); |
150 if (!token.isInteger()) { | 150 if (!token.isInteger()) { |
151 // TODO(edisonn): report/warning | 151 // TODO(edisonn): report/warning |
152 return current; | 152 return current; |
153 } | 153 } |
154 int offset = (int)token.intValue(); | 154 int offset = (int)token.intValue(); |
155 | 155 |
156 token.reset(); | 156 token.reset(); |
157 current = nextObject(current, trailerEnd, &token, NULL); | 157 current = nextObject(current, trailerEnd, &token, NULL, NULL); |
158 if (!token.isInteger()) { | 158 if (!token.isInteger()) { |
159 // TODO(edisonn): report/warning | 159 // TODO(edisonn): report/warning |
160 return current; | 160 return current; |
161 } | 161 } |
162 int generation = (int)token.intValue(); | 162 int generation = (int)token.intValue(); |
163 | 163 |
164 token.reset(); | 164 token.reset(); |
165 current = nextObject(current, trailerEnd, &token, NULL); | 165 current = nextObject(current, trailerEnd, &token, NULL, NULL); |
166 if (!token.isKeyword() || token.len() != 1 || (*token.c_str() != 'f'
&& *token.c_str() != 'n')) { | 166 if (!token.isKeyword() || token.len() != 1 || (*token.c_str() != 'f'
&& *token.c_str() != 'n')) { |
167 // TODO(edisonn): report/warning | 167 // TODO(edisonn): report/warning |
168 return current; | 168 return current; |
169 } | 169 } |
170 | 170 |
171 addCrossSectionInfo(startId + i, generation, offset, *token.c_str()
== 'f'); | 171 addCrossSectionInfo(startId + i, generation, offset, *token.c_str()
== 'f'); |
172 } | 172 } |
173 } | 173 } |
174 // TODO(edisonn): it should never get here? there is no trailer? | 174 // TODO(edisonn): it should never get here? there is no trailer? |
175 return current; | 175 return current; |
176 } | 176 } |
177 | 177 |
178 long SkNativeParsedPDF::readTrailer(unsigned char* trailerStart, unsigned char*
trailerEnd, bool storeCatalog) { | 178 long SkNativeParsedPDF::readTrailer(unsigned char* trailerStart, unsigned char*
trailerEnd, bool storeCatalog) { |
179 unsigned char* current = ignoreLine(trailerStart, trailerEnd); // TODO(edis
onn): verify next keyord is "trailer" use nextObject here | 179 unsigned char* current = ignoreLine(trailerStart, trailerEnd); // TODO(edis
onn): verify next keyord is "trailer" use nextObject here |
180 | 180 |
181 SkPdfObject token; | 181 SkPdfObject token; |
182 current = nextObject(current, trailerEnd, &token, fAllocator); | 182 current = nextObject(current, trailerEnd, &token, fAllocator, NULL); |
183 if (!token.isDictionary()) { | 183 if (!token.isDictionary()) { |
184 return -1; | 184 return -1; |
185 } | 185 } |
186 SkPdfFileTrailerDictionary* trailer = (SkPdfFileTrailerDictionary*)&token; | 186 SkPdfFileTrailerDictionary* trailer = (SkPdfFileTrailerDictionary*)&token; |
187 if (!trailer->valid()) { | 187 if (!trailer->valid()) { |
188 return -1; | 188 return -1; |
189 } | 189 } |
190 | 190 |
191 if (storeCatalog) { | 191 if (storeCatalog) { |
192 const SkPdfObject* ref = trailer->Root(NULL); | 192 const SkPdfObject* ref = trailer->Root(NULL); |
(...skipping 14 matching lines...) Expand all Loading... |
207 void SkNativeParsedPDF::addCrossSectionInfo(int id, int generation, int offset,
bool isFreed) { | 207 void SkNativeParsedPDF::addCrossSectionInfo(int id, int generation, int offset,
bool isFreed) { |
208 // TODO(edisonn): security here | 208 // TODO(edisonn): security here |
209 while (fObjects.count() < id + 1) { | 209 while (fObjects.count() < id + 1) { |
210 reset(fObjects.append()); | 210 reset(fObjects.append()); |
211 } | 211 } |
212 | 212 |
213 fObjects[id].fOffset = offset; | 213 fObjects[id].fOffset = offset; |
214 fObjects[id].fObj = NULL; | 214 fObjects[id].fObj = NULL; |
215 } | 215 } |
216 | 216 |
217 SkPdfObject* SkNativeParsedPDF::readObject(int id/*, int expectedGeneration*/) c
onst { | 217 SkPdfObject* SkNativeParsedPDF::readObject(int id/*, int expectedGeneration*/) { |
218 long startOffset = fObjects[id].fOffset; | 218 long startOffset = fObjects[id].fOffset; |
219 //long endOffset = fObjects[id].fOffsetEnd; | 219 //long endOffset = fObjects[id].fOffsetEnd; |
220 // TODO(edisonn): use hinted endOffset | 220 // TODO(edisonn): use hinted endOffset |
221 // TODO(edisonn): current implementation will result in a lot of memory usag
e | 221 // TODO(edisonn): current implementation will result in a lot of memory usag
e |
222 // to decrease memory usage, we wither need to be smart and know where objec
ts end, and we will | 222 // to decrease memory usage, we wither need to be smart and know where objec
ts end, and we will |
223 // alocate only the chancks needed, or the tokenizer will not make copies, b
ut then it needs to | 223 // alocate only the chancks needed, or the tokenizer will not make copies, b
ut then it needs to |
224 // cache the results so it does not go twice on the same buffer | 224 // cache the results so it does not go twice on the same buffer |
225 unsigned char* current = fFileContent + startOffset; | 225 unsigned char* current = fFileContent + startOffset; |
226 unsigned char* end = fFileContent + fContentLength; | 226 unsigned char* end = fFileContent + fContentLength; |
227 | 227 |
228 SkPdfNativeTokenizer tokenizer(current, end - current, fMapper, fAllocator); | 228 SkPdfNativeTokenizer tokenizer(current, end - current, fMapper, fAllocator,
this); |
229 | 229 |
230 SkPdfObject idObj; | 230 SkPdfObject idObj; |
231 SkPdfObject generationObj; | 231 SkPdfObject generationObj; |
232 SkPdfObject objKeyword; | 232 SkPdfObject objKeyword; |
233 SkPdfObject* dict = fAllocator->allocObject(); | 233 SkPdfObject* dict = fAllocator->allocObject(); |
234 | 234 |
235 current = nextObject(current, end, &idObj, NULL); | 235 current = nextObject(current, end, &idObj, NULL, NULL); |
236 if (current >= end) { | 236 if (current >= end) { |
237 // TODO(edisonn): report warning/error | 237 // TODO(edisonn): report warning/error |
238 return NULL; | 238 return NULL; |
239 } | 239 } |
240 | 240 |
241 current = nextObject(current, end, &generationObj, NULL); | 241 current = nextObject(current, end, &generationObj, NULL, NULL); |
242 if (current >= end) { | 242 if (current >= end) { |
243 // TODO(edisonn): report warning/error | 243 // TODO(edisonn): report warning/error |
244 return NULL; | 244 return NULL; |
245 } | 245 } |
246 | 246 |
247 current = nextObject(current, end, &objKeyword, NULL); | 247 current = nextObject(current, end, &objKeyword, NULL, NULL); |
248 if (current >= end) { | 248 if (current >= end) { |
249 // TODO(edisonn): report warning/error | 249 // TODO(edisonn): report warning/error |
250 return NULL; | 250 return NULL; |
251 } | 251 } |
252 | 252 |
253 if (!idObj.isInteger() || !generationObj.isInteger() || id != idObj.intValue
()/* || generation != generationObj.intValue()*/) { | 253 if (!idObj.isInteger() || !generationObj.isInteger() || id != idObj.intValue
()/* || generation != generationObj.intValue()*/) { |
254 // TODO(edisonn): report warning/error | 254 // TODO(edisonn): report warning/error |
255 } | 255 } |
256 | 256 |
257 if (!objKeyword.isKeyword() || strcmp(objKeyword.c_str(), "obj") != 0) { | 257 if (!objKeyword.isKeyword() || strcmp(objKeyword.c_str(), "obj") != 0) { |
258 // TODO(edisonn): report warning/error | 258 // TODO(edisonn): report warning/error |
259 } | 259 } |
260 | 260 |
261 current = nextObject(current, end, dict, fAllocator); | 261 current = nextObject(current, end, dict, fAllocator, this); |
262 | 262 |
263 // TODO(edisonn): report warning/error - verify last token is endobj | 263 // TODO(edisonn): report warning/error - verify last token is endobj |
264 | 264 |
265 return dict; | 265 return dict; |
266 } | 266 } |
267 | 267 |
268 void SkNativeParsedPDF::fillPages(SkPdfPageTreeNodeDictionary* tree) { | 268 void SkNativeParsedPDF::fillPages(SkPdfPageTreeNodeDictionary* tree) { |
269 const SkPdfArray* kids = tree->Kids(this); | 269 const SkPdfArray* kids = tree->Kids(this); |
270 if (kids == NULL) { | 270 if (kids == NULL) { |
271 *fPages.append() = (SkPdfPageObjectDictionary*)tree; | 271 *fPages.append() = (SkPdfPageObjectDictionary*)tree; |
(...skipping 14 matching lines...) Expand all Loading... |
286 | 286 |
287 int SkNativeParsedPDF::pages() const { | 287 int SkNativeParsedPDF::pages() const { |
288 return fPages.count(); | 288 return fPages.count(); |
289 } | 289 } |
290 | 290 |
291 SkPdfResourceDictionary* SkNativeParsedPDF::pageResources(int page) { | 291 SkPdfResourceDictionary* SkNativeParsedPDF::pageResources(int page) { |
292 return fPages[page]->Resources(this); | 292 return fPages[page]->Resources(this); |
293 } | 293 } |
294 | 294 |
295 // TODO(edisonn): Partial implemented. Move the logics directly in the code gene
rator for inheritable and default value? | 295 // TODO(edisonn): Partial implemented. Move the logics directly in the code gene
rator for inheritable and default value? |
296 SkRect SkNativeParsedPDF::MediaBox(int page) const { | 296 SkRect SkNativeParsedPDF::MediaBox(int page) { |
297 SkPdfPageObjectDictionary* current = fPages[page]; | 297 SkPdfPageObjectDictionary* current = fPages[page]; |
298 while (!current->has_MediaBox() && current->has_Parent()) { | 298 while (!current->has_MediaBox() && current->has_Parent()) { |
299 current = (SkPdfPageObjectDictionary*)current->Parent(this); | 299 current = (SkPdfPageObjectDictionary*)current->Parent(this); |
300 } | 300 } |
301 if (current) { | 301 if (current) { |
302 return current->MediaBox(this); | 302 return current->MediaBox(this); |
303 } | 303 } |
304 return SkRect::MakeEmpty(); | 304 return SkRect::MakeEmpty(); |
305 } | 305 } |
306 | 306 |
307 // TODO(edisonn): stream or array ... ? for now only array | 307 // TODO(edisonn): stream or array ... ? for now only array |
308 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfPage(int page) const { | 308 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfPage(int page) { |
309 if (fPages[page]->isContentsAStream(this)) { | 309 if (fPages[page]->isContentsAStream(this)) { |
310 return tokenizerOfStream(fPages[page]->getContentsAsStream(this)); | 310 return tokenizerOfStream(fPages[page]->getContentsAsStream(this)); |
311 } else { | 311 } else { |
312 // TODO(edisonn): NYI, we need to concatenate all streams in the array o
r make the tokenizer smart | 312 // TODO(edisonn): NYI, we need to concatenate all streams in the array o
r make the tokenizer smart |
313 // so we don't allocate new memory | 313 // so we don't allocate new memory |
314 return NULL; | 314 return NULL; |
315 } | 315 } |
316 } | 316 } |
317 | 317 |
318 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfStream(SkPdfObject* stream)
const { | 318 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfStream(SkPdfObject* stream)
{ |
319 if (stream == NULL) { | 319 if (stream == NULL) { |
320 return NULL; | 320 return NULL; |
321 } | 321 } |
322 | 322 |
323 return new SkPdfNativeTokenizer(stream, fMapper, fAllocator); | 323 return new SkPdfNativeTokenizer(stream, fMapper, fAllocator, this); |
324 } | 324 } |
325 | 325 |
326 // TODO(edisonn): NYI | 326 // TODO(edisonn): NYI |
327 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfBuffer(unsigned char* buffer
, size_t len) const { | 327 SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfBuffer(unsigned char* buffer
, size_t len) { |
328 // warning does not track two calls in the same buffer! the buffer is update
d! | 328 // warning does not track two calls in the same buffer! the buffer is update
d! |
329 // make a clean copy if needed! | 329 // make a clean copy if needed! |
330 return new SkPdfNativeTokenizer(buffer, len, fMapper, fAllocator); | 330 return new SkPdfNativeTokenizer(buffer, len, fMapper, fAllocator, this); |
331 } | 331 } |
332 | 332 |
333 size_t SkNativeParsedPDF::objects() const { | 333 size_t SkNativeParsedPDF::objects() const { |
334 return fObjects.count(); | 334 return fObjects.count(); |
335 } | 335 } |
336 | 336 |
337 SkPdfObject* SkNativeParsedPDF::object(int i) { | 337 SkPdfObject* SkNativeParsedPDF::object(int i) { |
338 SkASSERT(!(i < 0 || i > fObjects.count())); | 338 SkASSERT(!(i < 0 || i > fObjects.count())); |
339 | 339 |
340 if (i < 0 || i > fObjects.count()) { | 340 if (i < 0 || i > fObjects.count()) { |
(...skipping 28 matching lines...) Expand all Loading... |
369 SkPdfString* SkNativeParsedPDF::createString(unsigned char* sz, size_t len) cons
t { | 369 SkPdfString* SkNativeParsedPDF::createString(unsigned char* sz, size_t len) cons
t { |
370 SkPdfObject* obj = fAllocator->allocObject(); | 370 SkPdfObject* obj = fAllocator->allocObject(); |
371 SkPdfObject::makeString(sz, len, obj); | 371 SkPdfObject::makeString(sz, len, obj); |
372 return (SkPdfString*)obj; | 372 return (SkPdfString*)obj; |
373 } | 373 } |
374 | 374 |
375 SkPdfAllocator* SkNativeParsedPDF::allocator() const { | 375 SkPdfAllocator* SkNativeParsedPDF::allocator() const { |
376 return fAllocator; | 376 return fAllocator; |
377 } | 377 } |
378 | 378 |
379 SkPdfObject* SkNativeParsedPDF::resolveReference(SkPdfObject* ref) const { | |
380 return (SkPdfObject*)resolveReference((const SkPdfObject*)ref); | |
381 } | |
382 | |
383 // TODO(edisonn): fix infinite loop if ref to itself! | 379 // TODO(edisonn): fix infinite loop if ref to itself! |
384 // TODO(edisonn): perf, fix refs at load, and resolve will simply return fResolv
edReference? | 380 // TODO(edisonn): perf, fix refs at load, and resolve will simply return fResolv
edReference? |
385 SkPdfObject* SkNativeParsedPDF::resolveReference(const SkPdfObject* ref) const { | 381 SkPdfObject* SkNativeParsedPDF::resolveReference(const SkPdfObject* ref) { |
386 if (ref && ref->isReference()) { | 382 if (ref && ref->isReference()) { |
387 int id = ref->referenceId(); | 383 int id = ref->referenceId(); |
388 // TODO(edisonn): generation/updates not supported now | 384 // TODO(edisonn): generation/updates not supported now |
389 //int gen = ref->referenceGeneration(); | 385 //int gen = ref->referenceGeneration(); |
390 | 386 |
391 SkASSERT(!(id < 0 || id > fObjects.count())); | 387 SkASSERT(!(id < 0 || id > fObjects.count())); |
392 | 388 |
393 if (id < 0 || id > fObjects.count()) { | 389 if (id < 0 || id > fObjects.count()) { |
394 return NULL; | 390 return NULL; |
395 } | 391 } |
(...skipping 14 matching lines...) Expand all Loading... |
410 } else { | 406 } else { |
411 fObjects[id].fResolvedReference = resolveReference(fObjects[id].
fObj); | 407 fObjects[id].fResolvedReference = resolveReference(fObjects[id].
fObj); |
412 } | 408 } |
413 } | 409 } |
414 | 410 |
415 return fObjects[id].fResolvedReference; | 411 return fObjects[id].fResolvedReference; |
416 } | 412 } |
417 // TODO(edisonn): fix the mess with const, probably we need to remove it pre
tty much everywhere | 413 // TODO(edisonn): fix the mess with const, probably we need to remove it pre
tty much everywhere |
418 return (SkPdfObject*)ref; | 414 return (SkPdfObject*)ref; |
419 } | 415 } |
OLD | NEW |