OLD | NEW |
1 | 1 |
2 #include "SkPdfNativeTokenizer.h" | 2 #include "SkPdfNativeTokenizer.h" |
3 #include "SkPdfObject.h" | 3 #include "SkPdfObject.h" |
4 #include "SkPdfConfig.h" | 4 #include "SkPdfConfig.h" |
5 | 5 |
6 #include "SkPdfStreamCommonDictionary_autogen.h" | 6 #include "SkPdfStreamCommonDictionary_autogen.h" |
7 | 7 |
8 unsigned char* skipPdfWhiteSpaces(unsigned char* start, unsigned char* end) { | 8 static unsigned char* skipPdfWhiteSpaces(unsigned char* start, unsigned char* en
d) { |
9 while (start < end && isPdfWhiteSpace(*start)) { | 9 while (start < end && isPdfWhiteSpace(*start)) { |
10 if (*start == kComment_PdfDelimiter) { | 10 if (*start == kComment_PdfDelimiter) { |
11 // skip the comment until end of line | 11 // skip the comment until end of line |
12 while (start < end && !isPdfEOL(*start)) { | 12 while (start < end && !isPdfEOL(*start)) { |
13 *start = '\0'; | 13 *start = '\0'; |
14 start++; | 14 start++; |
15 } | 15 } |
16 } else { | 16 } else { |
17 *start = '\0'; | 17 *start = '\0'; |
18 start++; | 18 start++; |
19 } | 19 } |
20 } | 20 } |
21 return start; | 21 return start; |
22 } | 22 } |
23 | 23 |
24 // TODO(edisonn) '(' can be used, will it break the string a delimiter or space
inside () ? | 24 // TODO(edisonn) '(' can be used, will it break the string a delimiter or space
inside () ? |
25 unsigned char* endOfPdfToken(unsigned char* start, unsigned char* end) { | 25 static unsigned char* endOfPdfToken(unsigned char* start, unsigned char* end) { |
26 //int opened brackets | 26 //int opened brackets |
27 //TODO(edisonn): what out for special chars, like \n, \032 | 27 //TODO(edisonn): what out for special chars, like \n, \032 |
28 | 28 |
29 SkASSERT(!isPdfWhiteSpace(*start)); | 29 SkASSERT(!isPdfWhiteSpace(*start)); |
30 | 30 |
31 if (start < end && isPdfDelimiter(*start)) { | 31 if (start < end && isPdfDelimiter(*start)) { |
32 start++; | 32 start++; |
33 return start; | 33 return start; |
34 } | 34 } |
35 | 35 |
36 while (start < end && !isPdfWhiteSpaceOrPdfDelimiter(*start)) { | 36 while (start < end && !isPdfWhiteSpaceOrPdfDelimiter(*start)) { |
37 start++; | 37 start++; |
38 } | 38 } |
39 return start; | 39 return start; |
40 } | 40 } |
41 | 41 |
42 unsigned char* skipPdfComment(unsigned char* start, unsigned char* end) { | |
43 SkASSERT(start == end || *start == kComment_PdfDelimiter); | |
44 while (start < end && isPdfEOL(*start)) { | |
45 *start = '\0'; | |
46 start++; | |
47 } | |
48 return start; | |
49 } | |
50 | |
51 // last elem has to be ] | 42 // last elem has to be ] |
52 unsigned char* readArray(unsigned char* start, unsigned char* end, SkPdfObject*
array, SkPdfAllocator* allocator) { | 43 static unsigned char* readArray(unsigned char* start, unsigned char* end, SkPdfO
bject* array, SkPdfAllocator* allocator) { |
53 while (start < end) { | 44 while (start < end) { |
54 // skip white spaces | 45 // skip white spaces |
55 start = skipPdfWhiteSpaces(start, end); | 46 start = skipPdfWhiteSpaces(start, end); |
56 | 47 |
57 unsigned char* endOfToken = endOfPdfToken(start, end); | 48 unsigned char* endOfToken = endOfPdfToken(start, end); |
58 | 49 |
59 if (endOfToken == start) { | 50 if (endOfToken == start) { |
60 // TODO(edisonn): report error in pdf file (end of stream with ] for
end of aray | 51 // TODO(edisonn): report error in pdf file (end of stream with ] for
end of aray |
61 return start; | 52 return start; |
62 } | 53 } |
63 | 54 |
64 if (endOfToken == start + 1 && *start == kClosedSquareBracket_PdfDelimit
er) { | 55 if (endOfToken == start + 1 && *start == kClosedSquareBracket_PdfDelimit
er) { |
65 return endOfToken; | 56 return endOfToken; |
66 } | 57 } |
67 | 58 |
68 SkPdfObject* newObj = allocator->allocObject(); | 59 SkPdfObject* newObj = allocator->allocObject(); |
69 start = nextObject(start, end, newObj, allocator); | 60 start = nextObject(start, end, newObj, allocator); |
70 // TODO(edisonn): perf/memory: put the variables on the stack, and flush
them on the array only when | 61 // TODO(edisonn): perf/memory: put the variables on the stack, and flush
them on the array only when |
71 // we are sure they are not references! | 62 // we are sure they are not references! |
72 if (newObj->isKeywordReference() && array->size() >= 2 && array->objAtAI
ndex(array->size() - 1)->isInteger() && array->objAtAIndex(array->size() - 2)->i
sInteger()) { | 63 if (newObj->isKeywordReference() && array->size() >= 2 && array->objAtAI
ndex(array->size() - 1)->isInteger() && array->objAtAIndex(array->size() - 2)->i
sInteger()) { |
73 SkPdfObject* gen = array->removeLastInArray(); | 64 SkPdfObject* gen = array->removeLastInArray(); |
74 SkPdfObject* id = array->removeLastInArray(); | 65 SkPdfObject* id = array->removeLastInArray(); |
75 newObj->reset(); | 66 newObj->reset(); |
76 SkPdfObject::makeReference(id->intValue(), gen->intValue(), newObj); | 67 SkPdfObject::makeReference((unsigned int)id->intValue(), (unsigned i
nt)gen->intValue(), newObj); |
77 } | 68 } |
78 array->appendInArray(newObj); | 69 array->appendInArray(newObj); |
79 } | 70 } |
80 // TODO(edisonn): report not reached, we should never get here | 71 // TODO(edisonn): report not reached, we should never get here |
81 SkASSERT(false); | 72 SkASSERT(false); |
82 return start; | 73 return start; |
83 } | 74 } |
84 | 75 |
85 // When we read strings we will rewrite the string so we will reuse the memory | 76 // When we read strings we will rewrite the string so we will reuse the memory |
86 // when we start to read the string, we already consumed the opened bracket | 77 // when we start to read the string, we already consumed the opened bracket |
87 unsigned char* readString(unsigned char* start, unsigned char* end, SkPdfObject*
str) { | 78 static unsigned char* readString(unsigned char* start, unsigned char* end, SkPdf
Object* str) { |
88 unsigned char* out = start; | 79 unsigned char* out = start; |
89 unsigned char* in = start; | 80 unsigned char* in = start; |
90 | 81 |
91 int openRoundBrackets = 0; | 82 int openRoundBrackets = 0; |
92 while (in < end && (*in != kClosedRoundBracket_PdfDelimiter || openRoundBrac
kets > 0)) { | 83 while (in < end && (*in != kClosedRoundBracket_PdfDelimiter || openRoundBrac
kets > 0)) { |
93 openRoundBrackets += ((*in) == kOpenedRoundBracket_PdfDelimiter); | 84 openRoundBrackets += ((*in) == kOpenedRoundBracket_PdfDelimiter); |
94 openRoundBrackets -= ((*in) == kClosedRoundBracket_PdfDelimiter); | 85 openRoundBrackets -= ((*in) == kClosedRoundBracket_PdfDelimiter); |
95 if (*in == kEscape_PdfSpecial) { | 86 if (*in == kEscape_PdfSpecial) { |
96 if (in + 1 < end) { | 87 if (in + 1 < end) { |
97 switch (in[1]) { | 88 switch (in[1]) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 in++; | 179 in++; |
189 out++; | 180 out++; |
190 } | 181 } |
191 } | 182 } |
192 | 183 |
193 | 184 |
194 SkPdfObject::makeString(start, out, str); | 185 SkPdfObject::makeString(start, out, str); |
195 return in + 1; // consume ) at the end of the string | 186 return in + 1; // consume ) at the end of the string |
196 } | 187 } |
197 | 188 |
198 unsigned char* readHexString(unsigned char* start, unsigned char* end, SkPdfObje
ct* str) { | 189 static unsigned char* readHexString(unsigned char* start, unsigned char* end, Sk
PdfObject* str) { |
199 unsigned char* out = start; | 190 unsigned char* out = start; |
200 unsigned char* in = start; | 191 unsigned char* in = start; |
201 | 192 |
202 unsigned char code = 0; | 193 unsigned char code = 0; |
203 | 194 |
204 while (in < end) { | 195 while (in < end) { |
205 while (in < end && isPdfWhiteSpace(*in)) { | 196 while (in < end && isPdfWhiteSpace(*in)) { |
206 in++; | 197 in++; |
207 } | 198 } |
208 | 199 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 | 309 |
319 if (out < in) { | 310 if (out < in) { |
320 *out = '\0'; | 311 *out = '\0'; |
321 } | 312 } |
322 | 313 |
323 SkPdfObject::makeHexString(start, out, str); | 314 SkPdfObject::makeHexString(start, out, str); |
324 return in; // consume > at the end of the string | 315 return in; // consume > at the end of the string |
325 } | 316 } |
326 | 317 |
327 // TODO(edisonn): before PDF 1.2 name could not have special characters, add ver
sion parameter | 318 // TODO(edisonn): before PDF 1.2 name could not have special characters, add ver
sion parameter |
328 unsigned char* readName(unsigned char* start, unsigned char* end, SkPdfObject* n
ame) { | 319 static unsigned char* readName(unsigned char* start, unsigned char* end, SkPdfOb
ject* name) { |
329 unsigned char* out = start; | 320 unsigned char* out = start; |
330 unsigned char* in = start; | 321 unsigned char* in = start; |
331 | 322 |
332 unsigned char code = 0; | 323 unsigned char code = 0; |
333 | 324 |
334 while (in < end) { | 325 while (in < end) { |
335 if (isPdfWhiteSpaceOrPdfDelimiter(*in)) { | 326 if (isPdfWhiteSpaceOrPdfDelimiter(*in)) { |
336 break; | 327 break; |
337 } | 328 } |
338 | 329 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 endstream | 436 endstream |
446 8 0 obj #real obj | 437 8 0 obj #real obj |
447 << 100 >> #real obj | 438 << 100 >> #real obj |
448 endobj | 439 endobj |
449 and it could get worse, with multiple object like this | 440 and it could get worse, with multiple object like this |
450 */ | 441 */ |
451 | 442 |
452 // right now implement the silly algorithm that assumes endstream is finishing t
he stream | 443 // right now implement the silly algorithm that assumes endstream is finishing t
he stream |
453 | 444 |
454 | 445 |
455 unsigned char* readStream(unsigned char* start, unsigned char* end, SkPdfObject*
dict) { | 446 static unsigned char* readStream(unsigned char* start, unsigned char* end, SkPdf
Object* dict) { |
456 start = skipPdfWhiteSpaces(start, end); | 447 start = skipPdfWhiteSpaces(start, end); |
457 if (!(start[0] == 's' && start[1] == 't' && start[2] == 'r' && start[3] == '
e' && start[4] == 'a' && start[5] == 'm')) { | 448 if (!(start[0] == 's' && start[1] == 't' && start[2] == 'r' && start[3] == '
e' && start[4] == 'a' && start[5] == 'm')) { |
458 // no stream. return. | 449 // no stream. return. |
459 return start; | 450 return start; |
460 } | 451 } |
461 | 452 |
462 start += 6; // strlen("stream") | 453 start += 6; // strlen("stream") |
463 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) { | 454 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) { |
464 start += 2; | 455 start += 2; |
465 } else if (start[0] == kLF_PdfWhiteSpace) { | 456 } else if (start[0] == kLF_PdfWhiteSpace) { |
466 start += 1; | 457 start += 1; |
467 } | 458 } |
468 | 459 |
469 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*) dict; | 460 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*) dict; |
470 // TODO(edisonn): load Length | 461 // TODO(edisonn): load Length |
471 int length = -1; | 462 int64_t length = -1; |
472 | 463 |
473 // TODO(edisonn): very basic implementation | 464 // TODO(edisonn): very basic implementation |
474 if (stream->has_Length() && stream->Length(NULL) > 0) { | 465 if (stream->has_Length() && stream->Length(NULL) > 0) { |
475 length = stream->Length(NULL); | 466 length = stream->Length(NULL); |
476 } | 467 } |
477 | 468 |
478 // TODO(edisonn): laod external streams | 469 // TODO(edisonn): laod external streams |
479 // TODO(edisonn): look at the last filter, to determione how to deal with po
ssible issue | 470 // TODO(edisonn): look at the last filter, to determione how to deal with po
ssible issue |
480 | 471 |
481 if (length < 0) { | 472 if (length < 0) { |
(...skipping 18 matching lines...) Expand all Loading... |
500 if (endstream[0] == kCR_PdfWhiteSpace && endstream[1] == kLF_PdfWhiteSpa
ce) { | 491 if (endstream[0] == kCR_PdfWhiteSpace && endstream[1] == kLF_PdfWhiteSpa
ce) { |
501 endstream += 2; | 492 endstream += 2; |
502 } else if (endstream[0] == kLF_PdfWhiteSpace) { | 493 } else if (endstream[0] == kLF_PdfWhiteSpace) { |
503 endstream += 1; | 494 endstream += 1; |
504 } | 495 } |
505 | 496 |
506 // TODO(edisonn): verify the next bytes are "endstream" | 497 // TODO(edisonn): verify the next bytes are "endstream" |
507 | 498 |
508 endstream += strlen("endstream"); | 499 endstream += strlen("endstream"); |
509 // TODO(edisonn): Assert? report error/warning? | 500 // TODO(edisonn): Assert? report error/warning? |
510 dict->addStream(start, length); | 501 dict->addStream(start, (size_t)length); |
511 return endstream; | 502 return endstream; |
512 } | 503 } |
513 return start; | 504 return start; |
514 } | 505 } |
515 | 506 |
516 unsigned char* readDictionary(unsigned char* start, unsigned char* end, SkPdfObj
ect* dict, SkPdfAllocator* allocator) { | 507 static unsigned char* readDictionary(unsigned char* start, unsigned char* end, S
kPdfObject* dict, SkPdfAllocator* allocator) { |
517 SkPdfObject::makeEmptyDictionary(dict); | 508 SkPdfObject::makeEmptyDictionary(dict); |
518 | 509 |
519 start = skipPdfWhiteSpaces(start, end); | 510 start = skipPdfWhiteSpaces(start, end); |
520 | 511 |
521 while (start < end && *start == kNamed_PdfDelimiter) { | 512 while (start < end && *start == kNamed_PdfDelimiter) { |
522 SkPdfObject key; | 513 SkPdfObject key; |
523 *start = '\0'; | 514 *start = '\0'; |
524 start++; | 515 start++; |
525 start = readName(start, end, &key); | 516 start = readName(start, end, &key); |
526 start = skipPdfWhiteSpaces(start, end); | 517 start = skipPdfWhiteSpaces(start, end); |
527 | 518 |
528 if (start < end) { | 519 if (start < end) { |
529 SkPdfObject* value = allocator->allocObject(); | 520 SkPdfObject* value = allocator->allocObject(); |
530 start = nextObject(start, end, value, allocator); | 521 start = nextObject(start, end, value, allocator); |
531 | 522 |
532 start = skipPdfWhiteSpaces(start, end); | 523 start = skipPdfWhiteSpaces(start, end); |
533 | 524 |
534 if (start < end) { | 525 if (start < end) { |
535 // seems we have an indirect reference | 526 // seems we have an indirect reference |
536 if (isPdfDigit(*start)) { | 527 if (isPdfDigit(*start)) { |
537 SkPdfObject generation; | 528 SkPdfObject generation; |
538 start = nextObject(start, end, &generation, allocator); | 529 start = nextObject(start, end, &generation, allocator); |
539 | 530 |
540 SkPdfObject keywordR; | 531 SkPdfObject keywordR; |
541 start = nextObject(start, end, &keywordR, allocator); | 532 start = nextObject(start, end, &keywordR, allocator); |
542 | 533 |
543 if (value->isInteger() && generation.isInteger() && keywordR
.isKeywordReference()) { | 534 if (value->isInteger() && generation.isInteger() && keywordR
.isKeywordReference()) { |
544 int64_t id = value->intValue(); | 535 int64_t id = value->intValue(); |
545 value->reset(); | 536 value->reset(); |
546 SkPdfObject::makeReference(id, generation.intValue(), va
lue); | 537 SkPdfObject::makeReference((unsigned int)id, (unsigned i
nt)generation.intValue(), value); |
547 dict->set(&key, value); | 538 dict->set(&key, value); |
548 } else { | 539 } else { |
549 // error, ignore | 540 // error, ignore |
550 dict->set(&key, value); | 541 dict->set(&key, value); |
551 } | 542 } |
552 } else { | 543 } else { |
553 // next elem is not a digit, but it might not be / either! | 544 // next elem is not a digit, but it might not be / either! |
554 dict->set(&key, value); | 545 dict->set(&key, value); |
555 } | 546 } |
556 } else { | 547 } else { |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 | 756 |
766 if (fEmpty) { | 757 if (fEmpty) { |
767 #ifdef PDF_TRACE | 758 #ifdef PDF_TRACE |
768 printf("EMPTY TOKENIZER\n"); | 759 printf("EMPTY TOKENIZER\n"); |
769 #endif | 760 #endif |
770 return false; | 761 return false; |
771 } | 762 } |
772 | 763 |
773 return readTokenCore(token); | 764 return readTokenCore(token); |
774 } | 765 } |
OLD | NEW |