OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPdfConfig.h" | 8 #include "SkPdfConfig.h" |
9 #include "SkPdfDiffEncoder.h" | 9 #include "SkPdfDiffEncoder.h" |
10 #include "SkPdfNativeObject.h" | 10 #include "SkPdfNativeObject.h" |
11 #include "SkPdfNativeTokenizer.h" | 11 #include "SkPdfNativeTokenizer.h" |
12 #include "SkPdfUtils.h" | 12 #include "SkPdfUtils.h" |
13 | 13 |
14 // TODO(edisonn): mac builder does not find the header ... but from headers is o
k | 14 // TODO(edisonn): mac builder does not find the header ... but from headers is o
k |
15 //#include "SkPdfStreamCommonDictionary_autogen.h" | 15 //#include "SkPdfStreamCommonDictionary_autogen.h" |
16 //#include "SkPdfImageDictionary_autogen.h" | 16 //#include "SkPdfImageDictionary_autogen.h" |
17 #include "SkPdfHeaders_autogen.h" | 17 #include "SkPdfHeaders_autogen.h" |
18 | 18 |
19 | 19 |
20 // TODO(edisonn): Perf, Make this function run faster. | 20 // TODO(edisonn): Perf, Make this function run faster. |
21 // There could be 0s between start and end. | 21 // There could be 0s between start and end. |
22 // needle will not contain 0s. | 22 // needle will not contain 0s. |
23 static char* strrstrk(char* hayStart, char* hayEnd, const char* needle) { | 23 static char* strrstrk(char* hayStart, char* hayEnd, const char* needle) { |
24 int needleLen = strlen(needle); | 24 size_t needleLen = strlen(needle); |
25 if ((isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || (hayStart+needl
eLen == hayEnd)) && | 25 if ((isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || (hayStart+needl
eLen == hayEnd)) && |
26 strncmp(hayStart, needle, needleLen) == 0) { | 26 strncmp(hayStart, needle, needleLen) == 0) { |
27 return hayStart; | 27 return hayStart; |
28 } | 28 } |
29 | 29 |
30 hayStart++; | 30 hayStart++; |
31 | 31 |
32 while (hayStart < hayEnd) { | 32 while (hayStart < hayEnd) { |
33 if (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart-1)) && | 33 if (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart-1)) && |
34 (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || | 34 (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 | 98 |
99 if (endOfToken == start + 1 && *start == kClosedSquareBracket_PdfDelimit
er) { | 99 if (endOfToken == start + 1 && *start == kClosedSquareBracket_PdfDelimit
er) { |
100 return endOfToken; | 100 return endOfToken; |
101 } | 101 } |
102 | 102 |
103 SkPdfNativeObject* newObj = allocator->allocObject(); | 103 SkPdfNativeObject* newObj = allocator->allocObject(); |
104 start = nextObject(start, end, newObj, allocator, doc); | 104 start = nextObject(start, end, newObj, allocator, doc); |
105 // TODO(edisonn): perf/memory: put the variables on the stack, and flush
them on the array | 105 // TODO(edisonn): perf/memory: put the variables on the stack, and flush
them on the array |
106 // only when we are sure they are not references! | 106 // only when we are sure they are not references! |
107 if (newObj->isKeywordReference() && array->size() >= 2 && | 107 if (newObj->isKeywordReference() && array->size() >= 2 && |
108 array->objAtAIndex(array->size() - 1)->isInteger() && | 108 array->objAtAIndex(SkToInt(array->size() - 1))->isInteger() && |
109 array->objAtAIndex(array->size() - 2)->isInteger()) { | 109 array->objAtAIndex(SkToInt(array->size() - 2))->isInteger()) { |
110 SkPdfNativeObject* gen = array->removeLastInArray(); | 110 SkPdfNativeObject* gen = array->removeLastInArray(); |
111 SkPdfNativeObject* id = array->removeLastInArray(); | 111 SkPdfNativeObject* id = array->removeLastInArray(); |
112 | 112 |
113 SkPdfNativeObject::resetAndMakeReference((unsigned int)id->intValue(
), | 113 SkPdfNativeObject::resetAndMakeReference((unsigned int)id->intValue(
), |
114 (unsigned int)gen->intValue
(), newObj); | 114 (unsigned int)gen->intValue
(), newObj); |
115 // newObj PUT_TRACK_PARAMETERS_OBJ2(id, newObj) - store end, as now | 115 // newObj PUT_TRACK_PARAMETERS_OBJ2(id, newObj) - store end, as now |
116 } | 116 } |
117 array->appendInArray(newObj); | 117 array->appendInArray(newObj); |
118 } | 118 } |
119 // TODO(edisonn): report not reached, we should never get here | 119 // TODO(edisonn): report not reached, we should never get here |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 } | 234 } |
235 | 235 |
236 if (hasOut) { | 236 if (hasOut) { |
237 return in; // consumed already ) at the end of the string | 237 return in; // consumed already ) at the end of the string |
238 } else { | 238 } else { |
239 // return where the string would end if we reuse the string | 239 // return where the string would end if we reuse the string |
240 return start + (out - (const unsigned char*)NULL); | 240 return start + (out - (const unsigned char*)NULL); |
241 } | 241 } |
242 } | 242 } |
243 | 243 |
244 static int readStringLength(const unsigned char* start, const unsigned char* end
) { | 244 static size_t readStringLength(const unsigned char* start, const unsigned char*
end) { |
245 return readString(start, end, NULL) - start; | 245 return readString(start, end, NULL) - start; |
246 } | 246 } |
247 | 247 |
248 static const unsigned char* readString(const unsigned char* start, const unsigne
d char* end, | 248 static const unsigned char* readString(const unsigned char* start, const unsigne
d char* end, |
249 SkPdfNativeObject* str, SkPdfAllocator* a
llocator) { | 249 SkPdfNativeObject* str, SkPdfAllocator* a
llocator) { |
250 if (!allocator) { | 250 if (!allocator) { |
251 // TODO(edisonn): report error/warn/assert | 251 // TODO(edisonn): report error/warn/assert |
252 return end; | 252 return end; |
253 } | 253 } |
254 | 254 |
255 int outLength = readStringLength(start, end); | 255 size_t outLength = readStringLength(start, end); |
256 unsigned char* out = (unsigned char*)allocator->alloc(outLength); | 256 unsigned char* out = (unsigned char*)allocator->alloc(outLength); |
257 const unsigned char* now = readString(start, end, out); | 257 const unsigned char* now = readString(start, end, out); |
258 SkPdfNativeObject::makeString(out, out + outLength, str); | 258 SkPdfNativeObject::makeString(out, out + outLength, str); |
259 // PUT_TRACK_STREAM(str, start, now) | 259 // PUT_TRACK_STREAM(str, start, now) |
260 TRACE_STRING(out, out + outLength); | 260 TRACE_STRING(out, out + outLength); |
261 return now; // consumed already ) at the end of the string | 261 return now; // consumed already ) at the end of the string |
262 } | 262 } |
263 | 263 |
264 static const unsigned char* readHexString(const unsigned char* start, const unsi
gned char* end, | 264 static const unsigned char* readHexString(const unsigned char* start, const unsi
gned char* end, |
265 unsigned char* out) { | 265 unsigned char* out) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 } | 384 } |
385 | 385 |
386 if (hasOut) { | 386 if (hasOut) { |
387 return in; // consumed already ) at the end of the string | 387 return in; // consumed already ) at the end of the string |
388 } else { | 388 } else { |
389 // return where the string would end if we reuse the string | 389 // return where the string would end if we reuse the string |
390 return start + (out - (const unsigned char*)NULL); | 390 return start + (out - (const unsigned char*)NULL); |
391 } | 391 } |
392 } | 392 } |
393 | 393 |
394 static int readHexStringLength(const unsigned char* start, const unsigned char*
end) { | 394 static size_t readHexStringLength(const unsigned char* start, const unsigned cha
r* end) { |
395 return readHexString(start, end, NULL) - start; | 395 return readHexString(start, end, NULL) - start; |
396 } | 396 } |
397 | 397 |
398 static const unsigned char* readHexString(const unsigned char* start, const unsi
gned char* end, SkPdfNativeObject* str, SkPdfAllocator* allocator) { | 398 static const unsigned char* readHexString(const unsigned char* start, const unsi
gned char* end, SkPdfNativeObject* str, SkPdfAllocator* allocator) { |
399 if (!allocator) { | 399 if (!allocator) { |
400 // TODO(edisonn): report error/warn/assert | 400 // TODO(edisonn): report error/warn/assert |
401 return end; | 401 return end; |
402 } | 402 } |
403 int outLength = readHexStringLength(start, end); | 403 size_t outLength = readHexStringLength(start, end); |
404 unsigned char* out = (unsigned char*)allocator->alloc(outLength); | 404 unsigned char* out = (unsigned char*)allocator->alloc(outLength); |
405 const unsigned char* now = readHexString(start, end, out); | 405 const unsigned char* now = readHexString(start, end, out); |
406 SkPdfNativeObject::makeHexString(out, out + outLength, str); | 406 SkPdfNativeObject::makeHexString(out, out + outLength, str); |
407 // str PUT_TRACK_STREAM(start, now) | 407 // str PUT_TRACK_STREAM(start, now) |
408 TRACE_HEXSTRING(out, out + outLength); | 408 TRACE_HEXSTRING(out, out + outLength); |
409 return now; // consumed already > at the end of the string | 409 return now; // consumed already > at the end of the string |
410 } | 410 } |
411 | 411 |
412 // TODO(edisonn): add version parameter, before PDF 1.2 name could not have spec
ial characters. | 412 // TODO(edisonn): add version parameter, before PDF 1.2 name could not have spec
ial characters. |
413 static const unsigned char* readName(const unsigned char* start, const unsigned
char* end, | 413 static const unsigned char* readName(const unsigned char* start, const unsigned
char* end, |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 } | 511 } |
512 | 512 |
513 if (hasOut) { | 513 if (hasOut) { |
514 return in; // consumed already ) at the end of the string | 514 return in; // consumed already ) at the end of the string |
515 } else { | 515 } else { |
516 // return where the string would end if we reuse the string | 516 // return where the string would end if we reuse the string |
517 return start + (out - (const unsigned char*)NULL); | 517 return start + (out - (const unsigned char*)NULL); |
518 } | 518 } |
519 } | 519 } |
520 | 520 |
521 static int readNameLength(const unsigned char* start, const unsigned char* end)
{ | 521 static size_t readNameLength(const unsigned char* start, const unsigned char* en
d) { |
522 return readName(start, end, NULL) - start; | 522 return readName(start, end, NULL) - start; |
523 } | 523 } |
524 | 524 |
525 static const unsigned char* readName(const unsigned char* start, const unsigned
char* end, | 525 static const unsigned char* readName(const unsigned char* start, const unsigned
char* end, |
526 SkPdfNativeObject* name, SkPdfAllocator* al
locator) { | 526 SkPdfNativeObject* name, SkPdfAllocator* al
locator) { |
527 if (!allocator) { | 527 if (!allocator) { |
528 // TODO(edisonn): report error/warn/assert | 528 // TODO(edisonn): report error/warn/assert |
529 return end; | 529 return end; |
530 } | 530 } |
531 int outLength = readNameLength(start, end); | 531 size_t outLength = readNameLength(start, end); |
532 unsigned char* out = (unsigned char*)allocator->alloc(outLength); | 532 unsigned char* out = (unsigned char*)allocator->alloc(outLength); |
533 const unsigned char* now = readName(start, end, out); | 533 const unsigned char* now = readName(start, end, out); |
534 SkPdfNativeObject::makeName(out, out + outLength, name); | 534 SkPdfNativeObject::makeName(out, out + outLength, name); |
535 //PUT_TRACK_STREAM(start, now) | 535 //PUT_TRACK_STREAM(start, now) |
536 TRACE_NAME(out, out + outLength); | 536 TRACE_NAME(out, out + outLength); |
537 return now; | 537 return now; |
538 } | 538 } |
539 | 539 |
540 // TODO(edisonn): pdf spec let Length to be an indirect object define after the
stream | 540 // TODO(edisonn): pdf spec let Length to be an indirect object define after the
stream |
541 // that makes for an interesting scenario, where the stream itself contains ends
tream, together | 541 // that makes for an interesting scenario, where the stream itself contains ends
tream, together |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 start += 1; | 664 start += 1; |
665 } else { | 665 } else { |
666 SkASSERT(isPdfDelimiter(start[0])); | 666 SkASSERT(isPdfDelimiter(start[0])); |
667 // TODO(edisonn): warning? | 667 // TODO(edisonn): warning? |
668 } | 668 } |
669 | 669 |
670 const unsigned char* endstream = (const unsigned char*)strrstrk((char*)start
, (char*)end, "EI"); | 670 const unsigned char* endstream = (const unsigned char*)strrstrk((char*)start
, (char*)end, "EI"); |
671 const unsigned char* endEI = endstream ? endstream + 2 : NULL; // 2 == strl
en("EI") | 671 const unsigned char* endEI = endstream ? endstream + 2 : NULL; // 2 == strl
en("EI") |
672 | 672 |
673 if (endstream) { | 673 if (endstream) { |
674 int length = endstream - start; | 674 size_t length = endstream - start; |
675 if (*(endstream-1) == kLF_PdfWhiteSpace) length--; | 675 if (*(endstream-1) == kLF_PdfWhiteSpace) length--; |
676 if (*(endstream-2) == kCR_PdfWhiteSpace) length--; | 676 if (*(endstream-2) == kCR_PdfWhiteSpace) length--; |
677 inlineImage->addStream(start, (size_t)length); | 677 inlineImage->addStream(start, (size_t)length); |
678 } else { | 678 } else { |
679 // TODO(edisonn): report error in inline image stream (ID-EI) section | 679 // TODO(edisonn): report error in inline image stream (ID-EI) section |
680 // TODO(edisonn): based on filter, try to ignore a missing EI, and read
data properly | 680 // TODO(edisonn): based on filter, try to ignore a missing EI, and read
data properly |
681 return end; | 681 return end; |
682 } | 682 } |
683 return endEI; | 683 return endEI; |
684 } | 684 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 return end; | 779 return end; |
780 } | 780 } |
781 | 781 |
782 current = endOfPdfToken(start, end); | 782 current = endOfPdfToken(start, end); |
783 | 783 |
784 // no token, len would be 0 | 784 // no token, len would be 0 |
785 if (current == start || current == end) { | 785 if (current == start || current == end) { |
786 return end; | 786 return end; |
787 } | 787 } |
788 | 788 |
789 int tokenLen = current - start; | 789 size_t tokenLen = current - start; |
790 | 790 |
791 if (tokenLen == 1) { | 791 if (tokenLen == 1) { |
792 // start array | 792 // start array |
793 switch (*start) { | 793 switch (*start) { |
794 case kOpenedSquareBracket_PdfDelimiter: | 794 case kOpenedSquareBracket_PdfDelimiter: |
795 return readArray(current, end, token, allocator, doc); | 795 return readArray(current, end, token, allocator, doc); |
796 | 796 |
797 case kOpenedRoundBracket_PdfDelimiter: | 797 case kOpenedRoundBracket_PdfDelimiter: |
798 return readString(start + 1, end, token, allocator); | 798 return readString(start + 1, end, token, allocator); |
799 | 799 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 SkPdfAllocator* allocator, | 915 SkPdfAllocator* allocator, |
916 SkPdfNativeDoc* doc) : fDoc(doc) | 916 SkPdfNativeDoc* doc) : fDoc(doc) |
917 , fAllocator(all
ocator) | 917 , fAllocator(all
ocator) |
918 , fEmpty(false) | 918 , fEmpty(false) |
919 , fHasPutBack(fa
lse) { | 919 , fHasPutBack(fa
lse) { |
920 // TODO(edisonn): really bad hack, find end of object (endobj might be in a
comment!) | 920 // TODO(edisonn): really bad hack, find end of object (endobj might be in a
comment!) |
921 // we need to do now for perf, and our generated pdfs do not have comments, | 921 // we need to do now for perf, and our generated pdfs do not have comments, |
922 // but we need to remove this hack for pdfs in the wild | 922 // but we need to remove this hack for pdfs in the wild |
923 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj"); | 923 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj"); |
924 if (endobj) { | 924 if (endobj) { |
925 len = endobj - (char*)buffer + strlen("endobj"); | 925 len = SkToInt(endobj - (char*)buffer + strlen("endobj")); |
926 } | 926 } |
927 fUncompressedStreamStart = fUncompressedStream = buffer; | 927 fUncompressedStreamStart = fUncompressedStream = buffer; |
928 fUncompressedStreamEnd = fUncompressedStream + len; | 928 fUncompressedStreamEnd = fUncompressedStream + len; |
929 } | 929 } |
930 | 930 |
931 SkPdfNativeTokenizer::~SkPdfNativeTokenizer() { | 931 SkPdfNativeTokenizer::~SkPdfNativeTokenizer() { |
932 } | 932 } |
933 | 933 |
934 bool SkPdfNativeTokenizer::readTokenCore(PdfToken* token) { | 934 bool SkPdfNativeTokenizer::readTokenCore(PdfToken* token) { |
935 #ifdef PDF_TRACE_READ_TOKEN | 935 #ifdef PDF_TRACE_READ_TOKEN |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 fAllocator, fDoc); | 1116 fAllocator, fDoc); |
1117 // PUT_TRACK_STREAM_ARGS_EXPL2(fStreamId, fUncompressedStreamStart)
s | 1117 // PUT_TRACK_STREAM_ARGS_EXPL2(fStreamId, fUncompressedStreamStart)
s |
1118 // TODO(edisonn): perf maybe we should not expand abBreviation like
this | 1118 // TODO(edisonn): perf maybe we should not expand abBreviation like
this |
1119 inlineImage->set(inlineImageKeyAbbreviationExpand(key), | 1119 inlineImage->set(inlineImageKeyAbbreviationExpand(key), |
1120 inlineImageValueAbbreviationExpand(obj)); | 1120 inlineImageValueAbbreviationExpand(obj)); |
1121 } | 1121 } |
1122 } | 1122 } |
1123 // TODO(edisonn): report end of data with inline image without an EI | 1123 // TODO(edisonn): report end of data with inline image without an EI |
1124 return inlineImage; | 1124 return inlineImage; |
1125 } | 1125 } |
OLD | NEW |