| 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 |