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 #include "SkPdfImageDictionary_autogen.h" |
| 8 |
| 9 // TODO(edisonn): perf!!! |
| 10 // there could be 0s between start and end! but not in the needle. |
| 11 static char* strrstrk(char* hayStart, char* hayEnd, const char* needle) { |
| 12 int needleLen = strlen(needle); |
| 13 if ((isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || (hayStart+needl
eLen == hayEnd)) && |
| 14 strncmp(hayStart, needle, needleLen) == 0) { |
| 15 return hayStart; |
| 16 } |
| 17 |
| 18 hayStart++; |
| 19 |
| 20 while (hayStart < hayEnd) { |
| 21 if (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart-1)) && |
| 22 (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || (haySta
rt+needleLen == hayEnd)) && |
| 23 strncmp(hayStart, needle, needleLen) == 0) { |
| 24 return hayStart; |
| 25 } |
| 26 hayStart++; |
| 27 } |
| 28 return NULL; |
| 29 } |
| 30 |
7 | 31 |
8 static unsigned char* skipPdfWhiteSpaces(unsigned char* start, unsigned char* en
d) { | 32 static unsigned char* skipPdfWhiteSpaces(unsigned char* start, unsigned char* en
d) { |
9 while (start < end && isPdfWhiteSpace(*start)) { | 33 while (start < end && isPdfWhiteSpace(*start)) { |
10 if (*start == kComment_PdfDelimiter) { | 34 if (*start == kComment_PdfDelimiter) { |
11 // skip the comment until end of line | 35 // skip the comment until end of line |
12 while (start < end && !isPdfEOL(*start)) { | 36 while (start < end && !isPdfEOL(*start)) { |
13 *start = '\0'; | 37 *start = '\0'; |
14 start++; | 38 start++; |
15 } | 39 } |
16 } else { | 40 } else { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 // TODO(edisonn): perf/memory: put the variables on the stack, and flush
them on the array only when | 85 // TODO(edisonn): perf/memory: put the variables on the stack, and flush
them on the array only when |
62 // we are sure they are not references! | 86 // we are sure they are not references! |
63 if (newObj->isKeywordReference() && array->size() >= 2 && array->objAtAI
ndex(array->size() - 1)->isInteger() && array->objAtAIndex(array->size() - 2)->i
sInteger()) { | 87 if (newObj->isKeywordReference() && array->size() >= 2 && array->objAtAI
ndex(array->size() - 1)->isInteger() && array->objAtAIndex(array->size() - 2)->i
sInteger()) { |
64 SkPdfObject* gen = array->removeLastInArray(); | 88 SkPdfObject* gen = array->removeLastInArray(); |
65 SkPdfObject* id = array->removeLastInArray(); | 89 SkPdfObject* id = array->removeLastInArray(); |
66 newObj->reset(); | 90 newObj->reset(); |
67 SkPdfObject::makeReference((unsigned int)id->intValue(), (unsigned i
nt)gen->intValue(), newObj); | 91 SkPdfObject::makeReference((unsigned int)id->intValue(), (unsigned i
nt)gen->intValue(), newObj); |
68 } | 92 } |
69 array->appendInArray(newObj); | 93 array->appendInArray(newObj); |
70 } | 94 } |
| 95 printf("break;\n"); // DO NOT SUBMIT! |
71 // TODO(edisonn): report not reached, we should never get here | 96 // TODO(edisonn): report not reached, we should never get here |
72 // TODO(edisonn): there might be a bug here, enable an assert and run it on
files | 97 // TODO(edisonn): there might be a bug here, enable an assert and run it on
files |
73 // or it might be that the files were actually corrupted | 98 // or it might be that the files were actually corrupted |
74 return start; | 99 return start; |
75 } | 100 } |
76 | 101 |
77 // When we read strings we will rewrite the string so we will reuse the memory | 102 // When we read strings we will rewrite the string so we will reuse the memory |
78 // when we start to read the string, we already consumed the opened bracket | 103 // when we start to read the string, we already consumed the opened bracket |
79 static unsigned char* readString(unsigned char* start, unsigned char* end, SkPdf
Object* str) { | 104 static unsigned char* readString(unsigned char* start, unsigned char* end, SkPdf
Object* str) { |
80 unsigned char* out = start; | 105 unsigned char* out = start; |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 if (!(start[0] == 's' && start[1] == 't' && start[2] == 'r' && start[3] == '
e' && start[4] == 'a' && start[5] == 'm')) { | 476 if (!(start[0] == 's' && start[1] == 't' && start[2] == 'r' && start[3] == '
e' && start[4] == 'a' && start[5] == 'm')) { |
452 // no stream. return. | 477 // no stream. return. |
453 return start; | 478 return start; |
454 } | 479 } |
455 | 480 |
456 start += 6; // strlen("stream") | 481 start += 6; // strlen("stream") |
457 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) { | 482 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) { |
458 start += 2; | 483 start += 2; |
459 } else if (start[0] == kLF_PdfWhiteSpace) { | 484 } else if (start[0] == kLF_PdfWhiteSpace) { |
460 start += 1; | 485 start += 1; |
| 486 } else if (isPdfWhiteSpace(start[0])) { |
| 487 start += 1; |
| 488 } else { |
| 489 // TODO(edisonn): warn it should be isPdfDelimiter(start[0])) ? |
| 490 // TODO(edisonn): warning? |
461 } | 491 } |
462 | 492 |
463 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*) dict; | 493 SkPdfStreamCommonDictionary* stream = (SkPdfStreamCommonDictionary*) dict; |
464 // TODO(edisonn): load Length | 494 // TODO(edisonn): load Length |
465 int64_t length = -1; | 495 int64_t length = -1; |
466 | 496 |
467 // TODO(edisonn): very basic implementation | 497 // TODO(edisonn): very basic implementation |
468 if (stream->has_Length() && stream->Length(doc) > 0) { | 498 if (stream->has_Length() && stream->Length(doc) > 0) { |
469 length = stream->Length(doc); | 499 length = stream->Length(doc); |
470 } | 500 } |
471 | 501 |
472 // TODO(edisonn): laod external streams | 502 // TODO(edisonn): laod external streams |
473 // TODO(edisonn): look at the last filter, to determione how to deal with po
ssible issue | 503 // TODO(edisonn): look at the last filter, to determione how to deal with po
ssible issue |
474 | 504 |
475 if (length < 0) { | 505 if (length < 0) { |
476 // scan the buffer, until we find first endstream | 506 // scan the buffer, until we find first endstream |
477 // TODO(edisonn): all buffers must have a 0 at the end now, | 507 // TODO(edisonn): all buffers must have a 0 at the end now, |
478 // TODO(edisonn): hack (mark end of content with 0) | 508 unsigned char* endstream = (unsigned char*)strrstrk((char*)start, (char*
)end, "endstream"); |
479 unsigned char lastCh = *end; | |
480 *end = '\0'; | |
481 //SkASSERT(*end == '\0'); | |
482 unsigned char* endstream = (unsigned char*)strstr((const char*)start, "e
ndstream"); | |
483 *end = lastCh; | |
484 | 509 |
485 if (endstream) { | 510 if (endstream) { |
486 length = endstream - start; | 511 length = endstream - start; |
487 if (*(endstream-1) == kLF_PdfWhiteSpace) length--; | 512 if (*(endstream-1) == kLF_PdfWhiteSpace) length--; |
488 if (*(endstream-1) == kCR_PdfWhiteSpace) length--; | 513 if (*(endstream-2) == kCR_PdfWhiteSpace) length--; |
489 } | 514 } |
490 } | 515 } |
491 if (length >= 0) { | 516 if (length >= 0) { |
492 unsigned char* endstream = start + length; | 517 unsigned char* endstream = start + length; |
493 | 518 |
494 if (endstream[0] == kCR_PdfWhiteSpace && endstream[1] == kLF_PdfWhiteSpa
ce) { | 519 if (endstream[0] == kCR_PdfWhiteSpace && endstream[1] == kLF_PdfWhiteSpa
ce) { |
495 endstream += 2; | 520 endstream += 2; |
496 } else if (endstream[0] == kLF_PdfWhiteSpace) { | 521 } else if (endstream[0] == kLF_PdfWhiteSpace) { |
497 endstream += 1; | 522 endstream += 1; |
498 } | 523 } |
499 | 524 |
500 // TODO(edisonn): verify the next bytes are "endstream" | 525 // TODO(edisonn): verify the next bytes are "endstream" |
501 | 526 |
502 endstream += strlen("endstream"); | 527 endstream += strlen("endstream"); |
503 // TODO(edisonn): Assert? report error/warning? | 528 // TODO(edisonn): Assert? report error/warning? |
504 dict->addStream(start, (size_t)length); | 529 dict->addStream(start, (size_t)length); |
505 return endstream; | 530 return endstream; |
506 } | 531 } |
507 return start; | 532 return start; |
508 } | 533 } |
509 | 534 |
| 535 static unsigned char* readInlineImageStream(unsigned char* start, unsigned char*
end, SkPdfImageDictionary* inlineImage, SkNativeParsedPDF* doc) { |
| 536 // We already processed ID keyword, and we should be positioned immediately
after it |
| 537 |
| 538 // TODO(edisonn): security: read after end check, or make buffers with extra
2 bytes |
| 539 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) { |
| 540 start += 2; |
| 541 } else if (start[0] == kLF_PdfWhiteSpace) { |
| 542 start += 1; |
| 543 } else if (isPdfWhiteSpace(start[0])) { |
| 544 start += 1; |
| 545 } else { |
| 546 SkASSERT(isPdfDelimiter(start[0])); |
| 547 // TODO(edisonn): warning? |
| 548 } |
| 549 |
| 550 unsigned char* endstream = (unsigned char*)strrstrk((char*)start, (char*)end
, "EI"); |
| 551 unsigned char* endEI = endstream ? endstream + 2 : NULL; // 2 == strlen("EI
") |
| 552 |
| 553 if (endstream) { |
| 554 int length = endstream - start; |
| 555 if (*(endstream-1) == kLF_PdfWhiteSpace) length--; |
| 556 if (*(endstream-2) == kCR_PdfWhiteSpace) length--; |
| 557 inlineImage->addStream(start, (size_t)length); |
| 558 } else { |
| 559 // TODO(edisonn): report error in inline image stream (ID-EI) section |
| 560 // TODO(edisonn): based on filter, try to ignore a missing EI, and read
data properly |
| 561 return end; |
| 562 } |
| 563 return endEI; |
| 564 } |
| 565 |
510 static unsigned char* readDictionary(unsigned char* start, unsigned char* end, S
kPdfObject* dict, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) { | 566 static unsigned char* readDictionary(unsigned char* start, unsigned char* end, S
kPdfObject* dict, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) { |
511 SkPdfObject::makeEmptyDictionary(dict); | 567 SkPdfObject::makeEmptyDictionary(dict); |
512 | 568 |
513 start = skipPdfWhiteSpaces(start, end); | 569 start = skipPdfWhiteSpaces(start, end); |
514 | 570 |
515 while (start < end && *start == kNamed_PdfDelimiter) { | 571 while (start < end && *start == kNamed_PdfDelimiter) { |
516 SkPdfObject key; | 572 SkPdfObject key; |
517 *start = '\0'; | 573 *start = '\0'; |
518 start++; | 574 start++; |
519 start = readName(start, end, &key); | 575 start = readName(start, end, &key); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 } else { | 612 } else { |
557 dict->set(&key, &SkPdfObject::kNull); | 613 dict->set(&key, &SkPdfObject::kNull); |
558 return end; | 614 return end; |
559 } | 615 } |
560 } | 616 } |
561 | 617 |
562 // TODO(edisonn): options to ignore these errors | 618 // TODO(edisonn): options to ignore these errors |
563 | 619 |
564 // now we should expect >> | 620 // now we should expect >> |
565 start = skipPdfWhiteSpaces(start, end); | 621 start = skipPdfWhiteSpaces(start, end); |
566 start = endOfPdfToken(start, end); // > | 622 if (*start != kClosedInequityBracket_PdfDelimiter) { |
567 start = endOfPdfToken(start, end); // > | 623 // TODO(edisonn): report/warning |
568 | 624 } |
569 // TODO(edisonn): read stream ... put dict and stream in a struct, and have
a pointer to struct ... | 625 *start = '\0'; |
570 // or alocate 2 objects, and if there is no stream, free it to be used by so
meone else? or just leave it ? | 626 start++; // skip > |
| 627 if (*start != kClosedInequityBracket_PdfDelimiter) { |
| 628 // TODO(edisonn): report/warning |
| 629 } |
| 630 *start = '\0'; |
| 631 start++; // skip > |
571 | 632 |
572 start = readStream(start, end, dict, doc); | 633 start = readStream(start, end, dict, doc); |
573 | 634 |
574 return start; | 635 return start; |
575 } | 636 } |
576 | 637 |
577 unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject*
token, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) { | 638 unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject*
token, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) { |
578 unsigned char* current; | 639 unsigned char* current; |
579 | 640 |
580 // skip white spaces | 641 // skip white spaces |
(...skipping 16 matching lines...) Expand all Loading... |
597 SkPdfObject::makeEmptyArray(token); | 658 SkPdfObject::makeEmptyArray(token); |
598 return readArray(current, end, token, allocator, doc); | 659 return readArray(current, end, token, allocator, doc); |
599 | 660 |
600 case kOpenedRoundBracket_PdfDelimiter: | 661 case kOpenedRoundBracket_PdfDelimiter: |
601 *start = '\0'; | 662 *start = '\0'; |
602 return readString(start, end, token); | 663 return readString(start, end, token); |
603 | 664 |
604 case kOpenedInequityBracket_PdfDelimiter: | 665 case kOpenedInequityBracket_PdfDelimiter: |
605 *start = '\0'; | 666 *start = '\0'; |
606 if (end > start + 1 && start[1] == kOpenedInequityBracket_PdfDel
imiter) { | 667 if (end > start + 1 && start[1] == kOpenedInequityBracket_PdfDel
imiter) { |
| 668 start[1] = '\0'; // optional |
607 // TODO(edisonn): pass here the length somehow? | 669 // TODO(edisonn): pass here the length somehow? |
608 return readDictionary(start + 2, end, token, allocator, doc)
; // skip << | 670 return readDictionary(start + 2, end, token, allocator, doc)
; // skip << |
609 } else { | 671 } else { |
610 return readHexString(start + 1, end, token); // skip < | 672 return readHexString(start + 1, end, token); // skip < |
611 } | 673 } |
612 | 674 |
613 case kNamed_PdfDelimiter: | 675 case kNamed_PdfDelimiter: |
614 *start = '\0'; | 676 *start = '\0'; |
615 return readName(start + 1, end, token); | 677 return readName(start + 1, end, token); |
616 | 678 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 fCurrentUsed++; | 743 fCurrentUsed++; |
682 return &fCurrent[fCurrentUsed - 1]; | 744 return &fCurrent[fCurrentUsed - 1]; |
683 } | 745 } |
684 | 746 |
685 // TODO(edisonn): perf: do no copy the buffers, but use them, and mark cache the
result, so there is no need of a second pass | 747 // TODO(edisonn): perf: do no copy the buffers, but use them, and mark cache the
result, so there is no need of a second pass |
686 SkPdfNativeTokenizer::SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkP
dfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) : fDoc(doc)
, fMapper(mapper), fAllocator(allocator), fUncompressedStream(NULL), fUncompress
edStreamEnd(NULL), fEmpty(false), fHasPutBack(false) { | 748 SkPdfNativeTokenizer::SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkP
dfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) : fDoc(doc)
, fMapper(mapper), fAllocator(allocator), fUncompressedStream(NULL), fUncompress
edStreamEnd(NULL), fEmpty(false), fHasPutBack(false) { |
687 unsigned char* buffer = NULL; | 749 unsigned char* buffer = NULL; |
688 size_t len = 0; | 750 size_t len = 0; |
689 objWithStream->GetFilteredStreamRef(&buffer, &len, fAllocator); | 751 objWithStream->GetFilteredStreamRef(&buffer, &len, fAllocator); |
690 // TODO(edisonn): hack, find end of object | 752 // TODO(edisonn): hack, find end of object |
691 char* endobj = strstr((char*)buffer, "endobj"); | 753 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj"); |
692 if (endobj) { | 754 if (endobj) { |
693 len = endobj - (char*)buffer + strlen("endobj"); | 755 len = endobj - (char*)buffer + strlen("endobj"); |
694 } | 756 } |
695 fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator-
>alloc(len); | 757 fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator-
>alloc(len); |
696 fUncompressedStreamEnd = fUncompressedStream + len; | 758 fUncompressedStreamEnd = fUncompressedStream + len; |
697 memcpy(fUncompressedStream, buffer, len); | 759 memcpy(fUncompressedStream, buffer, len); |
698 } | 760 } |
699 | 761 |
700 SkPdfNativeTokenizer::SkPdfNativeTokenizer(unsigned char* buffer, int len, const
SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) : fDoc(
doc), fMapper(mapper), fAllocator(allocator), fEmpty(false), fHasPutBack(false)
{ | 762 SkPdfNativeTokenizer::SkPdfNativeTokenizer(unsigned char* buffer, int len, const
SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) : fDoc(
doc), fMapper(mapper), fAllocator(allocator), fEmpty(false), fHasPutBack(false)
{ |
701 // TODO(edisonn): hack, find end of object | 763 // TODO(edisonn): hack, find end of object |
702 char* endobj = strstr((char*)buffer, "endobj"); | 764 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj"); |
703 if (endobj) { | 765 if (endobj) { |
704 len = endobj - (char*)buffer + strlen("endobj"); | 766 len = endobj - (char*)buffer + strlen("endobj"); |
705 } | 767 } |
706 fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator-
>alloc(len); | 768 fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator-
>alloc(len); |
707 fUncompressedStreamEnd = fUncompressedStream + len; | 769 fUncompressedStreamEnd = fUncompressedStream + len; |
708 memcpy(fUncompressedStream, buffer, len); | 770 memcpy(fUncompressedStream, buffer, len); |
709 } | 771 } |
710 | 772 |
711 SkPdfNativeTokenizer::~SkPdfNativeTokenizer() { | 773 SkPdfNativeTokenizer::~SkPdfNativeTokenizer() { |
712 } | 774 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 | 830 |
769 if (fEmpty) { | 831 if (fEmpty) { |
770 #ifdef PDF_TRACE | 832 #ifdef PDF_TRACE |
771 printf("EMPTY TOKENIZER\n"); | 833 printf("EMPTY TOKENIZER\n"); |
772 #endif | 834 #endif |
773 return false; | 835 return false; |
774 } | 836 } |
775 | 837 |
776 return readTokenCore(token); | 838 return readTokenCore(token); |
777 } | 839 } |
| 840 |
| 841 #define DECLARE_PDF_NAME(longName) SkPdfName longName((char*)#longName) |
| 842 |
| 843 // keys |
| 844 DECLARE_PDF_NAME(BitsPerComponent); |
| 845 DECLARE_PDF_NAME(ColorSpace); |
| 846 DECLARE_PDF_NAME(Decode); |
| 847 DECLARE_PDF_NAME(DecodeParms); |
| 848 DECLARE_PDF_NAME(Filter); |
| 849 DECLARE_PDF_NAME(Height); |
| 850 DECLARE_PDF_NAME(ImageMask); |
| 851 DECLARE_PDF_NAME(Intent); // PDF 1.1 - the key, or the abreviations? |
| 852 DECLARE_PDF_NAME(Interpolate); |
| 853 DECLARE_PDF_NAME(Width); |
| 854 |
| 855 // values |
| 856 DECLARE_PDF_NAME(DeviceGray); |
| 857 DECLARE_PDF_NAME(DeviceRGB); |
| 858 DECLARE_PDF_NAME(DeviceCMYK); |
| 859 DECLARE_PDF_NAME(Indexed); |
| 860 DECLARE_PDF_NAME(ASCIIHexDecode); |
| 861 DECLARE_PDF_NAME(ASCII85Decode); |
| 862 DECLARE_PDF_NAME(LZWDecode); |
| 863 DECLARE_PDF_NAME(FlateDecode); // PDF 1.2 |
| 864 DECLARE_PDF_NAME(RunLengthDecode); |
| 865 DECLARE_PDF_NAME(CCITTFaxDecode); |
| 866 DECLARE_PDF_NAME(DCTDecode); |
| 867 |
| 868 #define HANDLE_NAME_ABBR(obj,longName,shortName) if (obj->isName(#shortName)) re
turn &longName; |
| 869 |
| 870 |
| 871 static SkPdfObject* inlineImageKeyAbbreviationExpand(SkPdfObject* key) { |
| 872 if (!key || !key->isName()) { |
| 873 return key; |
| 874 } |
| 875 |
| 876 // TODO(edisonn): use autogenerated code! |
| 877 HANDLE_NAME_ABBR(key, BitsPerComponent, BPC); |
| 878 HANDLE_NAME_ABBR(key, ColorSpace, CS); |
| 879 HANDLE_NAME_ABBR(key, Decode, D); |
| 880 HANDLE_NAME_ABBR(key, DecodeParms, DP); |
| 881 HANDLE_NAME_ABBR(key, Filter, F); |
| 882 HANDLE_NAME_ABBR(key, Height, H); |
| 883 HANDLE_NAME_ABBR(key, ImageMask, IM); |
| 884 // HANDLE_NAME_ABBR(key, Intent, ); |
| 885 HANDLE_NAME_ABBR(key, Interpolate, I); |
| 886 HANDLE_NAME_ABBR(key, Width, W); |
| 887 |
| 888 return key; |
| 889 } |
| 890 |
| 891 static SkPdfObject* inlineImageValueAbbreviationExpand(SkPdfObject* value) { |
| 892 if (!value || !value->isName()) { |
| 893 return value; |
| 894 } |
| 895 |
| 896 // TODO(edisonn): use autogenerated code! |
| 897 HANDLE_NAME_ABBR(value, DeviceGray, G); |
| 898 HANDLE_NAME_ABBR(value, DeviceRGB, RGB); |
| 899 HANDLE_NAME_ABBR(value, DeviceCMYK, CMYK); |
| 900 HANDLE_NAME_ABBR(value, Indexed, I); |
| 901 HANDLE_NAME_ABBR(value, ASCIIHexDecode, AHx); |
| 902 HANDLE_NAME_ABBR(value, ASCII85Decode, A85); |
| 903 HANDLE_NAME_ABBR(value, LZWDecode, LZW); |
| 904 HANDLE_NAME_ABBR(value, FlateDecode, Fl); // (PDF 1.2) |
| 905 HANDLE_NAME_ABBR(value, RunLengthDecode, RL); |
| 906 HANDLE_NAME_ABBR(value, CCITTFaxDecode, CCF); |
| 907 HANDLE_NAME_ABBR(value, DCTDecode, DCT); |
| 908 |
| 909 return value; |
| 910 } |
| 911 |
| 912 SkPdfImageDictionary* SkPdfNativeTokenizer::readInlineImage() { |
| 913 // BI already processed |
| 914 fUncompressedStream = skipPdfWhiteSpaces(fUncompressedStream, fUncompressedS
treamEnd); |
| 915 if (fUncompressedStream >= fUncompressedStreamEnd) { |
| 916 return NULL; |
| 917 } |
| 918 |
| 919 SkPdfImageDictionary* inlineImage = (SkPdfImageDictionary*)fAllocator->alloc
Object(); |
| 920 SkPdfObject::makeEmptyDictionary(inlineImage); |
| 921 |
| 922 while (fUncompressedStream < fUncompressedStreamEnd) { |
| 923 SkPdfObject* key = fAllocator->allocObject(); |
| 924 fUncompressedStream = nextObject(fUncompressedStream, fUncompressedStrea
mEnd, key, fAllocator, fDoc); |
| 925 |
| 926 if (key->isKeyword() && key->len() == 2 && key->c_str()[0] == 'I' && key
->c_str()[1] == 'D') { // ID |
| 927 fUncompressedStream = readInlineImageStream(fUncompressedStream, fUn
compressedStreamEnd, inlineImage, fDoc); |
| 928 return inlineImage; |
| 929 } else { |
| 930 SkPdfObject* obj = fAllocator->allocObject(); |
| 931 fUncompressedStream = nextObject(fUncompressedStream, fUncompressedS
treamEnd, obj, fAllocator, fDoc); |
| 932 // TODO(edisonn): perf maybe we should not expand abreviation like t
his |
| 933 inlineImage->set(inlineImageKeyAbbreviationExpand(key), |
| 934 inlineImageValueAbbreviationExpand(obj)); |
| 935 } |
| 936 } |
| 937 // TODO(edisonn): report end of data with inline image without an EI |
| 938 return inlineImage; |
| 939 } |
OLD | NEW |