Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(632)

Side by Side Diff: experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp

Issue 19793011: (upload draf code for backup) pdfviewer: improve memory, son't allocate extra buffers, and put the … (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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" 7 #include "SkPdfImageDictionary_autogen.h"
8 8
9 // TODO(edisonn): perf!!! 9 // TODO(edisonn): perf!!!
10 // there could be 0s between start and end! but not in the needle. 10 // there could be 0s between start and end! but not in the needle.
(...skipping 10 matching lines...) Expand all
21 if (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart-1)) && 21 if (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart-1)) &&
22 (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || (haySta rt+needleLen == hayEnd)) && 22 (isPdfWhiteSpaceOrPdfDelimiter(*(hayStart+needleLen)) || (haySta rt+needleLen == hayEnd)) &&
23 strncmp(hayStart, needle, needleLen) == 0) { 23 strncmp(hayStart, needle, needleLen) == 0) {
24 return hayStart; 24 return hayStart;
25 } 25 }
26 hayStart++; 26 hayStart++;
27 } 27 }
28 return NULL; 28 return NULL;
29 } 29 }
30 30
31 #ifdef PDF_TRACE
32 static void TRACE_INDENT(int level, const char* type) {
33 static int id = 0;
34 id++;
35 if (478613 == id) {
36 printf("break;\n");
37 }
38 // all types should have 2 letters, so the text is alligned nicely
39 printf("\n%10i %15s: ", id, type);
40 for (int i = 0 ; i < level; i++) {
41 printf(" ");
42 }
43 }
31 44
32 static unsigned char* skipPdfWhiteSpaces(unsigned char* start, unsigned char* en d) { 45 static void TRACE_COMMENT(char ch) {
46 printf("%c", ch);
47 }
48
49 static void TRACE_TK(char ch) {
50 printf("%c", ch);
51 }
52
53 static void TRACE_NAME(const unsigned char* start, const unsigned char* end) {
54 while (start < end) {
55 printf("%c", *start);
56 start++;
57 }
58 printf("\n");
59 }
60
61 static void TRACE_STRING(const unsigned char* start, const unsigned char* end) {
62 while (start < end) {
63 printf("%c", *start);
64 start++;
65 }
66 printf("\n");
67 }
68
69 static void TRACE_HEXSTRING(const unsigned char* start, const unsigned char* end ) {
70 while (start < end) {
71 printf("%c", *start);
72 start++;
73 }
74 printf("\n");
75 }
76
77 #else
78 #define TRACE_INDENT(level,type)
79 #define TRACE_COMMENT(ch)
80 #define TRACE_TK(ch)
81 #define TRACE_NAME(start,end)
82 #define TRACE_STRING(start,end)
83 #define TRACE_HEXSTRING(start,end)
84 #endif
85
86 static const unsigned char* skipPdfWhiteSpaces(int level, const unsigned char* s tart, const unsigned char* end) {
87 TRACE_INDENT(level, "White Space");
33 while (start < end && isPdfWhiteSpace(*start)) { 88 while (start < end && isPdfWhiteSpace(*start)) {
89 TRACE_COMMENT(*start);
34 if (*start == kComment_PdfDelimiter) { 90 if (*start == kComment_PdfDelimiter) {
35 // skip the comment until end of line 91 // skip the comment until end of line
36 while (start < end && !isPdfEOL(*start)) { 92 while (start < end && !isPdfEOL(*start)) {
37 *start = '\0'; 93 //*start = '\0';
38 start++; 94 start++;
95 TRACE_COMMENT(*start);
39 } 96 }
40 } else { 97 } else {
41 *start = '\0'; 98 //*start = '\0';
42 start++; 99 start++;
43 } 100 }
44 } 101 }
45 return start; 102 return start;
46 } 103 }
47 104
48 // TODO(edisonn) '(' can be used, will it break the string a delimiter or space inside () ? 105 // TODO(edisonn) '(' can be used, will it break the string a delimiter or space inside () ?
49 static unsigned char* endOfPdfToken(unsigned char* start, unsigned char* end) { 106 static const unsigned char* endOfPdfToken(int level, const unsigned char* start, const unsigned char* end) {
50 //int opened brackets 107 //int opened brackets
51 //TODO(edisonn): what out for special chars, like \n, \032 108 //TODO(edisonn): what out for special chars, like \n, \032
109 TRACE_INDENT(level, "Token");
52 110
53 SkASSERT(!isPdfWhiteSpace(*start)); 111 SkASSERT(!isPdfWhiteSpace(*start));
54 112
55 if (start < end && isPdfDelimiter(*start)) { 113 if (start < end && isPdfDelimiter(*start)) {
114 TRACE_TK(*start);
56 start++; 115 start++;
57 return start; 116 return start;
58 } 117 }
59 118
60 while (start < end && !isPdfWhiteSpaceOrPdfDelimiter(*start)) { 119 while (start < end && !isPdfWhiteSpaceOrPdfDelimiter(*start)) {
120 TRACE_TK(*start);
61 start++; 121 start++;
62 } 122 }
63 return start; 123 return start;
64 } 124 }
65 125
66 // last elem has to be ] 126 // last elem has to be ]
67 static unsigned char* readArray(unsigned char* start, unsigned char* end, SkPdfO bject* array, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) { 127 static const unsigned char* readArray(int level, const unsigned char* start, con st unsigned char* end, SkPdfObject* array, SkPdfAllocator* allocator, SkNativePa rsedPDF* doc) {
128 TRACE_INDENT(level, "Array");
68 while (start < end) { 129 while (start < end) {
69 // skip white spaces 130 // skip white spaces
70 start = skipPdfWhiteSpaces(start, end); 131 start = skipPdfWhiteSpaces(level + 1, start, end);
71 132
72 unsigned char* endOfToken = endOfPdfToken(start, end); 133 const unsigned char* endOfToken = endOfPdfToken(level + 1, start, end);
73 134
74 if (endOfToken == start) { 135 if (endOfToken == start) {
75 // TODO(edisonn): report error in pdf file (end of stream with ] for end of aray 136 // TODO(edisonn): report error in pdf file (end of stream with ] for end of aray
76 return start; 137 return start;
77 } 138 }
78 139
79 if (endOfToken == start + 1 && *start == kClosedSquareBracket_PdfDelimit er) { 140 if (endOfToken == start + 1 && *start == kClosedSquareBracket_PdfDelimit er) {
80 return endOfToken; 141 return endOfToken;
81 } 142 }
82 143
83 SkPdfObject* newObj = allocator->allocObject(); 144 SkPdfObject* newObj = allocator->allocObject();
84 start = nextObject(start, end, newObj, allocator, doc); 145 start = nextObject(level + 1, start, end, newObj, allocator, doc);
85 // TODO(edisonn): perf/memory: put the variables on the stack, and flush them on the array only when 146 // TODO(edisonn): perf/memory: put the variables on the stack, and flush them on the array only when
86 // we are sure they are not references! 147 // we are sure they are not references!
87 if (newObj->isKeywordReference() && array->size() >= 2 && array->objAtAI ndex(array->size() - 1)->isInteger() && array->objAtAIndex(array->size() - 2)->i sInteger()) { 148 if (newObj->isKeywordReference() && array->size() >= 2 && array->objAtAI ndex(array->size() - 1)->isInteger() && array->objAtAIndex(array->size() - 2)->i sInteger()) {
88 SkPdfObject* gen = array->removeLastInArray(); 149 SkPdfObject* gen = array->removeLastInArray();
89 SkPdfObject* id = array->removeLastInArray(); 150 SkPdfObject* id = array->removeLastInArray();
90 newObj->reset(); 151 newObj->reset();
91 SkPdfObject::makeReference((unsigned int)id->intValue(), (unsigned i nt)gen->intValue(), newObj); 152 SkPdfObject::makeReference((unsigned int)id->intValue(), (unsigned i nt)gen->intValue(), newObj);
92 } 153 }
93 array->appendInArray(newObj); 154 array->appendInArray(newObj);
94 } 155 }
95 printf("break;\n"); // DO NOT SUBMIT! 156 printf("break;\n"); // DO NOT SUBMIT!
96 // TODO(edisonn): report not reached, we should never get here 157 // TODO(edisonn): report not reached, we should never get here
97 // TODO(edisonn): there might be a bug here, enable an assert and run it on files 158 // TODO(edisonn): there might be a bug here, enable an assert and run it on files
98 // or it might be that the files were actually corrupted 159 // or it might be that the files were actually corrupted
99 return start; 160 return start;
100 } 161 }
101 162
102 // When we read strings we will rewrite the string so we will reuse the memory 163 // When we read strings we will rewrite the string so we will reuse the memory
103 // when we start to read the string, we already consumed the opened bracket 164 // when we start to read the string, we already consumed the opened bracket
104 static unsigned char* readString(unsigned char* start, unsigned char* end, SkPdf Object* str) {
105 unsigned char* out = start;
106 unsigned char* in = start;
107 165
108 int openRoundBrackets = 0; 166 // TODO(edisonn): space: add paramater, taht would report if we need to allocate new buffer, or we can reuse the one we have
109 while (in < end && (*in != kClosedRoundBracket_PdfDelimiter || openRoundBrac kets > 0)) { 167
168 static const unsigned char* readString(int level, const unsigned char* start, co nst unsigned char* end, unsigned char* out) {
169 TRACE_INDENT(level, "String");
170 const unsigned char* in = start;
171 bool hasOut = (out != NULL);
172
173 int openRoundBrackets = 1;
174 while (in < end) {
110 openRoundBrackets += ((*in) == kOpenedRoundBracket_PdfDelimiter); 175 openRoundBrackets += ((*in) == kOpenedRoundBracket_PdfDelimiter);
111 openRoundBrackets -= ((*in) == kClosedRoundBracket_PdfDelimiter); 176 openRoundBrackets -= ((*in) == kClosedRoundBracket_PdfDelimiter);
177 if (openRoundBrackets == 0) {
178 in++; // consumed )
179 break;
180 }
181
112 if (*in == kEscape_PdfSpecial) { 182 if (*in == kEscape_PdfSpecial) {
113 if (in + 1 < end) { 183 if (in + 1 < end) {
114 switch (in[1]) { 184 switch (in[1]) {
115 case 'n': 185 case 'n':
116 *out = kLF_PdfWhiteSpace; 186 if (hasOut) { *out = kLF_PdfWhiteSpace; }
117 out++; 187 out++;
118 in += 2; 188 in += 2;
119 break; 189 break;
120 190
121 case 'r': 191 case 'r':
122 *out = kCR_PdfWhiteSpace; 192 if (hasOut) { *out = kCR_PdfWhiteSpace; }
123 out++; 193 out++;
124 in += 2; 194 in += 2;
125 break; 195 break;
126 196
127 case 't': 197 case 't':
128 *out = kHT_PdfWhiteSpace; 198 if (hasOut) { *out = kHT_PdfWhiteSpace; }
129 out++; 199 out++;
130 in += 2; 200 in += 2;
131 break; 201 break;
132 202
133 case 'b': 203 case 'b':
134 // TODO(edisonn): any special meaning to backspace? 204 // TODO(edisonn): any special meaning to backspace?
135 *out = kBackspace_PdfSpecial; 205 if (hasOut) { *out = kBackspace_PdfSpecial; }
136 out++; 206 out++;
137 in += 2; 207 in += 2;
138 break; 208 break;
139 209
140 case 'f': 210 case 'f':
141 *out = kFF_PdfWhiteSpace; 211 *out = kFF_PdfWhiteSpace;
142 out++; 212 out++;
143 in += 2; 213 in += 2;
144 break; 214 break;
145 215
146 case kOpenedRoundBracket_PdfDelimiter: 216 case kOpenedRoundBracket_PdfDelimiter:
147 *out = kOpenedRoundBracket_PdfDelimiter; 217 if (hasOut) { *out = kOpenedRoundBracket_PdfDelimiter; }
148 out++; 218 out++;
149 in += 2; 219 in += 2;
150 break; 220 break;
151 221
152 case kClosedRoundBracket_PdfDelimiter: 222 case kClosedRoundBracket_PdfDelimiter:
153 *out = kClosedRoundBracket_PdfDelimiter; 223 if (hasOut) { *out = kClosedRoundBracket_PdfDelimiter; }
154 out++; 224 out++;
155 in += 2; 225 in += 2;
156 break; 226 break;
157 227
158 case kEscape_PdfSpecial: 228 case kEscape_PdfSpecial:
159 *out = kEscape_PdfSpecial; 229 if (hasOut) { *out = kEscape_PdfSpecial; }
160 out++; 230 out++;
161 in += 2; 231 in += 2;
162 break; 232 break;
163 233
164 case '0': 234 case '0':
165 case '1': 235 case '1':
166 case '2': 236 case '2':
167 case '3': 237 case '3':
168 case '4': 238 case '4':
169 case '5': 239 case '5':
170 case '6': 240 case '6':
171 case '7': { 241 case '7': {
172 //read octals 242 //read octals
173 in++; // consume backslash 243 in++; // consume backslash
174 244
175 int code = 0; 245 int code = 0;
176 int i = 0; 246 int i = 0;
177 while (in < end && *in >= '0' && *in < '8') { 247 while (in < end && *in >= '0' && *in < '8') {
178 code = (code << 3) + ((*in) - '0'); // code * 8 + d 248 code = (code << 3) + ((*in) - '0'); // code * 8 + d
179 i++; 249 i++;
180 in++; 250 in++;
181 if (i == 3) { 251 if (i == 3) {
182 *out = code & 0xff; 252 if (hasOut) { *out = code & 0xff; }
183 out++; 253 out++;
184 i = 0; 254 i = 0;
185 } 255 }
186 } 256 }
187 if (i > 0) { 257 if (i > 0) {
188 *out = code & 0xff; 258 if (hasOut) { *out = code & 0xff; }
189 out++; 259 out++;
190 } 260 }
191 } 261 }
192 break; 262 break;
193 263
194 default: 264 default:
195 // Per spec, backslash is ignored is escaped ch is unkno wn 265 // Per spec, backslash is ignored is escaped ch is unkno wn
196 in++; 266 in++;
197 break; 267 break;
198 } 268 }
199 } else { 269 } else {
200 in++; 270 in++;
201 } 271 }
202 } else { 272 } else {
203 // TODO(edisonn): perf, avoid copy into itself, maybe first do a sim ple scan until found backslash ? 273 // TODO(edisonn): perf, avoid copy into itself, maybe first do a sim ple scan until found backslash ?
204 // we could have one look that first just inc current, and when we f ind the backslash 274 // we could have one look that first just inc current, and when we f ind the backslash
205 // we go to this loop 275 // we go to this loop
206 *in = *out; 276 if (hasOut) { *out = *in; }
207 in++; 277 in++;
208 out++; 278 out++;
209 } 279 }
210 } 280 }
211 281
212 282 if (hasOut) {
213 SkPdfObject::makeString(start, out, str); 283 return in; // consumed already ) at the end of the string
214 return in + 1; // consume ) at the end of the string 284 } else {
285 return start + (out - (const unsigned char*)NULL); // return where the s tring would end if we reuse the string
286 }
215 } 287 }
216 288
217 static unsigned char* readHexString(unsigned char* start, unsigned char* end, Sk PdfObject* str) { 289 static int readStringLength(int level, const unsigned char* start, const unsigne d char* end) {
218 unsigned char* out = start; 290 return readString(level, start, end, NULL) - start;
219 unsigned char* in = start; 291 }
292
293 static const unsigned char* readString(int level, const unsigned char* start, co nst unsigned char* end, SkPdfObject* str, SkPdfAllocator* allocator) {
294 int outLength = readStringLength(level, start, end);
295 // TODO(edisonn): optimize the allocation, don't allocate new string, but pu t it in a preallocated buffer
296 unsigned char* out = (unsigned char*)allocator->alloc(outLength);
297 start = readString(level, start, end, out);
298 SkPdfObject::makeString(out, out + outLength, str);
299 TRACE_STRING(out, out + outLength);
300 return start; // consumed already ) at the end of the string
301 }
302
303 static const unsigned char* readHexString(int level, const unsigned char* start, const unsigned char* end, unsigned char* out) {
304 TRACE_INDENT(level, "HexString");
305 bool hasOut = (out != NULL);
306 const unsigned char* in = start;
220 307
221 unsigned char code = 0; 308 unsigned char code = 0;
222 309
223 while (in < end) { 310 while (in < end) {
224 while (in < end && isPdfWhiteSpace(*in)) { 311 while (in < end && isPdfWhiteSpace(*in)) {
225 in++; 312 in++;
226 } 313 }
227 314
228 if (*in == kClosedInequityBracket_PdfDelimiter) { 315 if (*in == kClosedInequityBracket_PdfDelimiter) {
229 *in = '\0'; 316 //*in = '\0';
230 in++; 317 in++; // consume >
231 // normal exit 318 // normal exit
232 break; 319 break;
233 } 320 }
234 321
235 if (in >= end) { 322 if (in >= end) {
236 // end too soon 323 // end too soon
237 break; 324 break;
238 } 325 }
239 326
240 switch (*in) { 327 switch (*in) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 } 362 }
276 363
277 in++; // advance 364 in++; // advance
278 365
279 while (in < end && isPdfWhiteSpace(*in)) { 366 while (in < end && isPdfWhiteSpace(*in)) {
280 in++; 367 in++;
281 } 368 }
282 369
283 // TODO(edisonn): report error 370 // TODO(edisonn): report error
284 if (in >= end) { 371 if (in >= end) {
285 *out = code; 372 if (hasOut) { *out = code; }
286 out++; 373 out++;
287 break; 374 break;
288 } 375 }
289 376
290 if (*in == kClosedInequityBracket_PdfDelimiter) { 377 if (*in == kClosedInequityBracket_PdfDelimiter) {
291 *out = code; 378 if (hasOut) { *out = code; }
292 out++; 379 out++;
293 break; 380 break;
294 } 381 }
295 382
296 switch (*in) { 383 switch (*in) {
297 case '0': 384 case '0':
298 case '1': 385 case '1':
299 case '2': 386 case '2':
300 case '3': 387 case '3':
301 case '4': 388 case '4':
(...skipping 21 matching lines...) Expand all
323 case 'E': 410 case 'E':
324 case 'F': 411 case 'F':
325 code += (*in - 'A' + 10); 412 code += (*in - 'A' + 10);
326 break; 413 break;
327 414
328 // TODO(edisonn): spec does not say how to handle this error 415 // TODO(edisonn): spec does not say how to handle this error
329 default: 416 default:
330 break; 417 break;
331 } 418 }
332 419
333 *out = code; 420 if (hasOut) { *out = code; }
334 out++; 421 out++;
335 in++; 422 in++;
336 } 423 }
337 424
338 if (out < in) { 425 if (hasOut) {
339 *out = '\0'; 426 return in; // consumed already > at the end of the string
427 } else {
428 return start + (out - (const unsigned char*)NULL); // return where the s tring would end if we reuse the string
340 } 429 }
430 }
341 431
342 SkPdfObject::makeHexString(start, out, str); 432 static int readHexStringLength(int level, const unsigned char* start, const unsi gned char* end) {
343 return in; // consume > at the end of the string 433 return readHexString(level, start, end, NULL) - start;
434 }
435
436 static const unsigned char* readHexString(int level, const unsigned char* start, const unsigned char* end, SkPdfObject* str, SkPdfAllocator* allocator) {
437 int outLength = readHexStringLength(level, start, end);
438 // TODO(edisonn): optimize the allocation, don't allocate new string, but pu t it in a preallocated buffer
439 unsigned char* out = (unsigned char*)allocator->alloc(outLength);
440 start = readHexString(level, start, end, out);
441 SkPdfObject::makeHexString(out, out + outLength, str);
442 TRACE_HEXSTRING(out, out + outLength);
443 return start; // consumed already > at the end of the string
344 } 444 }
345 445
346 // TODO(edisonn): before PDF 1.2 name could not have special characters, add ver sion parameter 446 // TODO(edisonn): before PDF 1.2 name could not have special characters, add ver sion parameter
347 static unsigned char* readName(unsigned char* start, unsigned char* end, SkPdfOb ject* name) { 447 static const unsigned char* readName(int level, const unsigned char* start, cons t unsigned char* end, unsigned char* out) {
348 unsigned char* out = start; 448 TRACE_INDENT(level, "Name");
349 unsigned char* in = start; 449 bool hasOut = (out != NULL);
450 const unsigned char* in = start;
350 451
351 unsigned char code = 0; 452 unsigned char code = 0;
352 453
353 while (in < end) { 454 while (in < end) {
354 if (isPdfWhiteSpaceOrPdfDelimiter(*in)) { 455 if (isPdfWhiteSpaceOrPdfDelimiter(*in)) {
355 break; 456 break;
356 } 457 }
357 458
358 if (*in == '#' && in + 2 < end) { 459 if (*in == '#' && in + 2 < end) {
359 in++; 460 in++;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 case 'E': 527 case 'E':
427 case 'F': 528 case 'F':
428 code += (*in - 'A' + 10); 529 code += (*in - 'A' + 10);
429 break; 530 break;
430 531
431 // TODO(edisonn): spec does not say how to handle this error 532 // TODO(edisonn): spec does not say how to handle this error
432 default: 533 default:
433 break; 534 break;
434 } 535 }
435 536
436 *out = code; 537 if (hasOut) { *out = code; }
437 out++; 538 out++;
438 in++; 539 in++;
439 } else { 540 } else {
440 *out = *in; 541 if (hasOut) { *out = *in; }
441 out++; 542 out++;
442 in++; 543 in++;
443 } 544 }
444 } 545 }
445 546
446 SkPdfObject::makeName(start, out, name); 547 if (hasOut) {
447 return in; 548 return in;
549 } else {
550 return start + (out - (const unsigned char*)NULL); // return where the s tring would end if we reuse the string
551 }
552 }
553
554 static int readNameLength(int level, const unsigned char* start, const unsigned char* end) {
555 return readName(level, start, end, NULL) - start;
556 }
557
558 static const unsigned char* readName(int level, const unsigned char* start, cons t unsigned char* end, SkPdfObject* name, SkPdfAllocator* allocator) {
559 int outLength = readNameLength(level, start, end);
560 // TODO(edisonn): optimize the allocation, don't allocate new string, but pu t it in a preallocated buffer
561 unsigned char* out = (unsigned char*)allocator->alloc(outLength);
562 start = readName(level, start, end, out);
563 SkPdfObject::makeName(out, out + outLength, name);
564 TRACE_NAME(out, out + outLength);
565 return start;
448 } 566 }
449 567
450 // TODO(edisonn): pdf spec let Length to be an indirect object define after the stream 568 // TODO(edisonn): pdf spec let Length to be an indirect object define after the stream
451 // that makes for an interesting scenario, where the stream itself contains ends tream, together 569 // that makes for an interesting scenario, where the stream itself contains ends tream, together
452 // with a reference object with the length, but the real length object would be somewhere else 570 // with a reference object with the length, but the real length object would be somewhere else
453 // it could confuse the parser 571 // it could confuse the parser
454 /*example: 572 /*example:
455 573
456 7 0 obj 574 7 0 obj
457 << /length 8 0 R>> 575 << /length 8 0 R>>
458 stream 576 stream
459 ............... 577 ...............
460 endstream 578 endstream
461 8 0 obj #we are in stream actually, not a real object 579 8 0 obj #we are in stream actually, not a real object
462 << 10 >> #we are in stream actually, not a real object 580 << 10 >> #we are in stream actually, not a real object
463 endobj 581 endobj
464 endstream 582 endstream
465 8 0 obj #real obj 583 8 0 obj #real obj
466 << 100 >> #real obj 584 << 100 >> #real obj
467 endobj 585 endobj
468 and it could get worse, with multiple object like this 586 and it could get worse, with multiple object like this
469 */ 587 */
470 588
471 // right now implement the silly algorithm that assumes endstream is finishing t he stream 589 // right now implement the silly algorithm that assumes endstream is finishing t he stream
472 590
473 591
474 static unsigned char* readStream(unsigned char* start, unsigned char* end, SkPdf Object* dict, SkNativeParsedPDF* doc) { 592 static const unsigned char* readStream(int level, const unsigned char* start, co nst unsigned char* end, SkPdfObject* dict, SkNativeParsedPDF* doc) {
475 start = skipPdfWhiteSpaces(start, end); 593 TRACE_INDENT(level, "Stream");
594 start = skipPdfWhiteSpaces(level, start, end);
476 if (!(start[0] == 's' && start[1] == 't' && start[2] == 'r' && start[3] == ' e' && start[4] == 'a' && start[5] == 'm')) { 595 if (!(start[0] == 's' && start[1] == 't' && start[2] == 'r' && start[3] == ' e' && start[4] == 'a' && start[5] == 'm')) {
477 // no stream. return. 596 // no stream. return.
478 return start; 597 return start;
479 } 598 }
480 599
481 start += 6; // strlen("stream") 600 start += 6; // strlen("stream")
482 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) { 601 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) {
483 start += 2; 602 start += 2;
484 } else if (start[0] == kLF_PdfWhiteSpace) { 603 } else if (start[0] == kLF_PdfWhiteSpace) {
485 start += 1; 604 start += 1;
(...skipping 12 matching lines...) Expand all
498 if (stream->has_Length() && stream->Length(doc) > 0) { 617 if (stream->has_Length() && stream->Length(doc) > 0) {
499 length = stream->Length(doc); 618 length = stream->Length(doc);
500 } 619 }
501 620
502 // TODO(edisonn): laod external streams 621 // TODO(edisonn): laod external streams
503 // TODO(edisonn): look at the last filter, to determione how to deal with po ssible issue 622 // TODO(edisonn): look at the last filter, to determione how to deal with po ssible issue
504 623
505 if (length < 0) { 624 if (length < 0) {
506 // scan the buffer, until we find first endstream 625 // scan the buffer, until we find first endstream
507 // TODO(edisonn): all buffers must have a 0 at the end now, 626 // TODO(edisonn): all buffers must have a 0 at the end now,
508 unsigned char* endstream = (unsigned char*)strrstrk((char*)start, (char* )end, "endstream"); 627 const unsigned char* endstream = (const unsigned char*)strrstrk((char*)s tart, (char*)end, "endstream");
509 628
510 if (endstream) { 629 if (endstream) {
511 length = endstream - start; 630 length = endstream - start;
512 if (*(endstream-1) == kLF_PdfWhiteSpace) length--; 631 if (*(endstream-1) == kLF_PdfWhiteSpace) length--;
513 if (*(endstream-2) == kCR_PdfWhiteSpace) length--; 632 if (*(endstream-2) == kCR_PdfWhiteSpace) length--;
514 } 633 }
515 } 634 }
516 if (length >= 0) { 635 if (length >= 0) {
517 unsigned char* endstream = start + length; 636 const unsigned char* endstream = start + length;
518 637
519 if (endstream[0] == kCR_PdfWhiteSpace && endstream[1] == kLF_PdfWhiteSpa ce) { 638 if (endstream[0] == kCR_PdfWhiteSpace && endstream[1] == kLF_PdfWhiteSpa ce) {
520 endstream += 2; 639 endstream += 2;
521 } else if (endstream[0] == kLF_PdfWhiteSpace) { 640 } else if (endstream[0] == kLF_PdfWhiteSpace) {
522 endstream += 1; 641 endstream += 1;
523 } 642 }
524 643
525 // TODO(edisonn): verify the next bytes are "endstream" 644 // TODO(edisonn): verify the next bytes are "endstream"
526 645
527 endstream += strlen("endstream"); 646 endstream += strlen("endstream");
528 // TODO(edisonn): Assert? report error/warning? 647 // TODO(edisonn): Assert? report error/warning?
529 dict->addStream(start, (size_t)length); 648 dict->addStream(start, (size_t)length);
530 return endstream; 649 return endstream;
531 } 650 }
532 return start; 651 return start;
533 } 652 }
534 653
535 static unsigned char* readInlineImageStream(unsigned char* start, unsigned char* end, SkPdfImageDictionary* inlineImage, SkNativeParsedPDF* doc) { 654 static const unsigned char* readInlineImageStream(int level, const unsigned char * start, const unsigned char* end, SkPdfImageDictionary* inlineImage, SkNativePa rsedPDF* doc) {
655 TRACE_INDENT(level, "Inline Image");
536 // We already processed ID keyword, and we should be positioned immediately after it 656 // We already processed ID keyword, and we should be positioned immediately after it
537 657
538 // TODO(edisonn): security: read after end check, or make buffers with extra 2 bytes 658 // TODO(edisonn): security: read after end check, or make buffers with extra 2 bytes
539 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) { 659 if (start[0] == kCR_PdfWhiteSpace && start[1] == kLF_PdfWhiteSpace) {
540 start += 2; 660 start += 2;
541 } else if (start[0] == kLF_PdfWhiteSpace) { 661 } else if (start[0] == kLF_PdfWhiteSpace) {
542 start += 1; 662 start += 1;
543 } else if (isPdfWhiteSpace(start[0])) { 663 } else if (isPdfWhiteSpace(start[0])) {
544 start += 1; 664 start += 1;
545 } else { 665 } else {
546 SkASSERT(isPdfDelimiter(start[0])); 666 SkASSERT(isPdfDelimiter(start[0]));
547 // TODO(edisonn): warning? 667 // TODO(edisonn): warning?
548 } 668 }
549 669
550 unsigned char* endstream = (unsigned char*)strrstrk((char*)start, (char*)end , "EI"); 670 const unsigned char* endstream = (const unsigned char*)strrstrk((char*)start , (char*)end, "EI");
551 unsigned char* endEI = endstream ? endstream + 2 : NULL; // 2 == strlen("EI ") 671 const unsigned char* endEI = endstream ? endstream + 2 : NULL; // 2 == strl en("EI")
552 672
553 if (endstream) { 673 if (endstream) {
554 int length = endstream - start; 674 int length = endstream - start;
555 if (*(endstream-1) == kLF_PdfWhiteSpace) length--; 675 if (*(endstream-1) == kLF_PdfWhiteSpace) length--;
556 if (*(endstream-2) == kCR_PdfWhiteSpace) length--; 676 if (*(endstream-2) == kCR_PdfWhiteSpace) length--;
557 inlineImage->addStream(start, (size_t)length); 677 inlineImage->addStream(start, (size_t)length);
558 } else { 678 } else {
559 // TODO(edisonn): report error in inline image stream (ID-EI) section 679 // 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 680 // TODO(edisonn): based on filter, try to ignore a missing EI, and read data properly
561 return end; 681 return end;
562 } 682 }
563 return endEI; 683 return endEI;
564 } 684 }
565 685
566 static unsigned char* readDictionary(unsigned char* start, unsigned char* end, S kPdfObject* dict, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) { 686 static const unsigned char* readDictionary(int level, const unsigned char* start , const unsigned char* end, SkPdfObject* dict, SkPdfAllocator* allocator, SkNati veParsedPDF* doc) {
687 TRACE_INDENT(level, "Dictionary");
567 SkPdfObject::makeEmptyDictionary(dict); 688 SkPdfObject::makeEmptyDictionary(dict);
568 689
569 start = skipPdfWhiteSpaces(start, end); 690 start = skipPdfWhiteSpaces(level, start, end);
691 SkPdfAllocator tmpStorage; // keys will be stored in dict, we can free them immediately after set.
570 692
571 while (start < end && *start == kNamed_PdfDelimiter) { 693 while (start < end && *start == kNamed_PdfDelimiter) {
572 SkPdfObject key; 694 SkPdfObject key;
573 *start = '\0'; 695 //*start = '\0';
574 start++; 696 start++;
575 start = readName(start, end, &key); 697 start = readName(level + 1, start, end, &key, &tmpStorage);
576 start = skipPdfWhiteSpaces(start, end); 698 start = skipPdfWhiteSpaces(level + 1, start, end);
577 699
578 if (start < end) { 700 if (start < end) {
579 SkPdfObject* value = allocator->allocObject(); 701 SkPdfObject* value = allocator->allocObject();
580 start = nextObject(start, end, value, allocator, doc); 702 start = nextObject(level + 1, start, end, value, allocator, doc);
581 703
582 start = skipPdfWhiteSpaces(start, end); 704 start = skipPdfWhiteSpaces(level + 1, start, end);
583 705
584 if (start < end) { 706 if (start < end) {
585 // seems we have an indirect reference 707 // seems we have an indirect reference
586 if (isPdfDigit(*start)) { 708 if (isPdfDigit(*start)) {
587 SkPdfObject generation; 709 SkPdfObject generation;
588 start = nextObject(start, end, &generation, allocator, doc); 710 start = nextObject(level + 1, start, end, &generation, alloc ator, doc);
589 711
590 SkPdfObject keywordR; 712 SkPdfObject keywordR;
591 start = nextObject(start, end, &keywordR, allocator, doc); 713 start = nextObject(level + 1, start, end, &keywordR, allocat or, doc);
592 714
593 if (value->isInteger() && generation.isInteger() && keywordR .isKeywordReference()) { 715 if (value->isInteger() && generation.isInteger() && keywordR .isKeywordReference()) {
594 int64_t id = value->intValue(); 716 int64_t id = value->intValue();
595 value->reset(); 717 value->reset();
596 SkPdfObject::makeReference((unsigned int)id, (unsigned i nt)generation.intValue(), value); 718 SkPdfObject::makeReference((unsigned int)id, (unsigned i nt)generation.intValue(), value);
597 dict->set(&key, value); 719 dict->set(&key, value);
598 } else { 720 } else {
599 // error, ignore 721 // error, ignore
600 dict->set(&key, value); 722 dict->set(&key, value);
601 } 723 }
602 } else { 724 } else {
603 // next elem is not a digit, but it might not be / either! 725 // next elem is not a digit, but it might not be / either!
604 dict->set(&key, value); 726 dict->set(&key, value);
605 } 727 }
606 } else { 728 } else {
607 // /key >> 729 // /key >>
608 dict->set(&key, value); 730 dict->set(&key, value);
609 return end; 731 return end;
610 } 732 }
611 start = skipPdfWhiteSpaces(start, end); 733 start = skipPdfWhiteSpaces(level + 1, start, end);
612 } else { 734 } else {
613 dict->set(&key, &SkPdfObject::kNull); 735 dict->set(&key, &SkPdfObject::kNull);
614 return end; 736 return end;
615 } 737 }
616 } 738 }
617 739
618 // TODO(edisonn): options to ignore these errors 740 // TODO(edisonn): options to ignore these errors
619 741
620 // now we should expect >> 742 // now we should expect >>
621 start = skipPdfWhiteSpaces(start, end); 743 start = skipPdfWhiteSpaces(level, start, end);
622 if (*start != kClosedInequityBracket_PdfDelimiter) { 744 if (*start != kClosedInequityBracket_PdfDelimiter) {
623 // TODO(edisonn): report/warning 745 // TODO(edisonn): report/warning
624 } 746 }
625 *start = '\0'; 747 //*start = '\0';
626 start++; // skip > 748 start++; // skip >
627 if (*start != kClosedInequityBracket_PdfDelimiter) { 749 if (*start != kClosedInequityBracket_PdfDelimiter) {
628 // TODO(edisonn): report/warning 750 // TODO(edisonn): report/warning
629 } 751 }
630 *start = '\0'; 752 //*start = '\0';
631 start++; // skip > 753 start++; // skip >
632 754
633 start = readStream(start, end, dict, doc); 755 start = readStream(level, start, end, dict, doc);
634 756
635 return start; 757 return start;
636 } 758 }
637 759
638 unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject* token, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) { 760 const unsigned char* nextObject(int level, const unsigned char* start, const uns igned char* end, SkPdfObject* token, SkPdfAllocator* allocator, SkNativeParsedPD F* doc) {
639 unsigned char* current; 761 const unsigned char* current;
640 762
641 // skip white spaces 763 // skip white spaces
642 start = skipPdfWhiteSpaces(start, end); 764 start = skipPdfWhiteSpaces(level, start, end);
643 765
644 current = endOfPdfToken(start, end); 766 current = endOfPdfToken(level, start, end);
645 767
646 // no token, len would be 0 768 // no token, len would be 0
647 if (current == start) { 769 if (current == start) {
648 return NULL; 770 return NULL;
649 } 771 }
650 772
651 int tokenLen = current - start; 773 int tokenLen = current - start;
652 774
653 if (tokenLen == 1) { 775 if (tokenLen == 1) {
654 // start array 776 // start array
655 switch (*start) { 777 switch (*start) {
656 case kOpenedSquareBracket_PdfDelimiter: 778 case kOpenedSquareBracket_PdfDelimiter:
657 *start = '\0'; 779 //*start = '\0';
658 SkPdfObject::makeEmptyArray(token); 780 SkPdfObject::makeEmptyArray(token);
659 return readArray(current, end, token, allocator, doc); 781 return readArray(level + 1, current, end, token, allocator, doc) ;
660 782
661 case kOpenedRoundBracket_PdfDelimiter: 783 case kOpenedRoundBracket_PdfDelimiter:
662 *start = '\0'; 784 //*start = '\0';
663 return readString(start, end, token); 785 return readString(level, start + 1, end, token, allocator);
664 786
665 case kOpenedInequityBracket_PdfDelimiter: 787 case kOpenedInequityBracket_PdfDelimiter:
666 *start = '\0'; 788 //*start = '\0';
667 if (end > start + 1 && start[1] == kOpenedInequityBracket_PdfDel imiter) { 789 if (end > start + 1 && start[1] == kOpenedInequityBracket_PdfDel imiter) {
668 start[1] = '\0'; // optional 790 //start[1] = '\0'; // optional
669 // TODO(edisonn): pass here the length somehow? 791 // TODO(edisonn): pass here the length somehow?
670 return readDictionary(start + 2, end, token, allocator, doc) ; // skip << 792 return readDictionary(level + 1, start + 2, end, token, allo cator, doc); // skip <<
671 } else { 793 } else {
672 return readHexString(start + 1, end, token); // skip < 794 return readHexString(level, start + 1, end, token, allocator ); // skip <
673 } 795 }
674 796
675 case kNamed_PdfDelimiter: 797 case kNamed_PdfDelimiter:
676 *start = '\0'; 798 //*start = '\0';
677 return readName(start + 1, end, token); 799 return readName(level, start + 1, end, token, allocator);
678 800
679 // TODO(edisonn): what to do curly brackets? read spec! 801 // TODO(edisonn): what to do curly brackets? read spec!
680 case kOpenedCurlyBracket_PdfDelimiter: 802 case kOpenedCurlyBracket_PdfDelimiter:
681 default: 803 default:
682 break; 804 break;
683 } 805 }
684 806
685 SkASSERT(!isPdfWhiteSpace(*start)); 807 SkASSERT(!isPdfWhiteSpace(*start));
686 if (isPdfDelimiter(*start)) { 808 if (isPdfDelimiter(*start)) {
687 // TODO(edisonn): how stream ] } > ) will be handled? 809 // TODO(edisonn): how stream ] } > ) will be handled?
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 fCurrent = allocBlock(); 861 fCurrent = allocBlock();
740 fCurrentUsed = 0; 862 fCurrentUsed = 0;
741 fSizeInBytes += sizeof(SkPdfObject*); 863 fSizeInBytes += sizeof(SkPdfObject*);
742 } 864 }
743 fCurrentUsed++; 865 fCurrentUsed++;
744 return &fCurrent[fCurrentUsed - 1]; 866 return &fCurrent[fCurrentUsed - 1];
745 } 867 }
746 868
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 869 // 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
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) { 870 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) {
749 unsigned char* buffer = NULL; 871 const unsigned char* buffer = NULL;
750 size_t len = 0; 872 size_t len = 0;
751 objWithStream->GetFilteredStreamRef(&buffer, &len, fAllocator); 873 objWithStream->GetFilteredStreamRef(&buffer, &len);
752 // TODO(edisonn): hack, find end of object 874 // TODO(edisonn): hack, find end of object
753 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj"); 875 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj");
754 if (endobj) { 876 if (endobj) {
755 len = endobj - (char*)buffer + strlen("endobj"); 877 len = endobj - (char*)buffer + strlen("endobj");
756 } 878 }
757 fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator- >alloc(len); 879 fUncompressedStreamStart = fUncompressedStream = buffer;
758 fUncompressedStreamEnd = fUncompressedStream + len; 880 fUncompressedStreamEnd = fUncompressedStream + len;
759 memcpy(fUncompressedStream, buffer, len);
760 } 881 }
761 882
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) { 883 SkPdfNativeTokenizer::SkPdfNativeTokenizer(const unsigned char* buffer, int len, const SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) : fDoc(doc), fMapper(mapper), fAllocator(allocator), fEmpty(false), fHasPutBack(f alse) {
763 // TODO(edisonn): hack, find end of object 884 // TODO(edisonn): hack, find end of object
764 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj"); 885 char* endobj = strrstrk((char*)buffer, (char*)buffer + len, "endobj");
765 if (endobj) { 886 if (endobj) {
766 len = endobj - (char*)buffer + strlen("endobj"); 887 len = endobj - (char*)buffer + strlen("endobj");
767 } 888 }
768 fUncompressedStreamStart = fUncompressedStream = (unsigned char*)fAllocator- >alloc(len); 889 fUncompressedStreamStart = fUncompressedStream = buffer;
769 fUncompressedStreamEnd = fUncompressedStream + len; 890 fUncompressedStreamEnd = fUncompressedStream + len;
770 memcpy(fUncompressedStream, buffer, len);
771 } 891 }
772 892
773 SkPdfNativeTokenizer::~SkPdfNativeTokenizer() { 893 SkPdfNativeTokenizer::~SkPdfNativeTokenizer() {
774 } 894 }
775 895
776 bool SkPdfNativeTokenizer::readTokenCore(PdfToken* token) { 896 bool SkPdfNativeTokenizer::readTokenCore(PdfToken* token) {
777 token->fKeyword = NULL; 897 token->fKeyword = NULL;
778 token->fObject = NULL; 898 token->fObject = NULL;
779 899
780 fUncompressedStream = skipPdfWhiteSpaces(fUncompressedStream, fUncompressedS treamEnd); 900 fUncompressedStream = skipPdfWhiteSpaces(0, fUncompressedStream, fUncompress edStreamEnd);
781 if (fUncompressedStream >= fUncompressedStreamEnd) { 901 if (fUncompressedStream >= fUncompressedStreamEnd) {
782 return false; 902 return false;
783 } 903 }
784 904
785 SkPdfObject obj; 905 SkPdfObject obj;
786 fUncompressedStream = nextObject(fUncompressedStream, fUncompressedStreamEnd , &obj, fAllocator, fDoc); 906 fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedStream End, &obj, fAllocator, fDoc);
787 907
788 // If it is a keyword, we will only get the pointer of the string 908 // If it is a keyword, we will only get the pointer of the string
789 if (obj.type() == SkPdfObject::kKeyword_PdfObjectType) { 909 if (obj.type() == SkPdfObject::kKeyword_PdfObjectType) {
790 token->fKeyword = obj.c_str(); 910 token->fKeyword = obj.c_str();
791 token->fKeywordLength = obj.len(); 911 token->fKeywordLength = obj.len();
792 token->fType = kKeyword_TokenType; 912 token->fType = kKeyword_TokenType;
793 } else { 913 } else {
794 SkPdfObject* pobj = fAllocator->allocObject(); 914 SkPdfObject* pobj = fAllocator->allocObject();
795 *pobj = obj; 915 *pobj = obj;
796 token->fObject = pobj; 916 token->fObject = pobj;
797 token->fType = kObject_TokenType; 917 token->fType = kObject_TokenType;
798 } 918 }
799 919
800 #ifdef PDF_TRACE 920 #ifdef PDF_TRACE_READ_TOKEN
801 static int read_op = 0; 921 static int read_op = 0;
802 read_op++; 922 read_op++;
803 if (548 == read_op) { 923 if (548 == read_op) {
804 printf("break;\n"); 924 printf("break;\n");
805 } 925 }
806 printf("%i READ %s %s\n", read_op, token->fType == kKeyword_TokenType ? "Key word" : "Object", token->fKeyword ? std::string(token->fKeyword, token->fKeyword Length).c_str() : token->fObject->toString().c_str()); 926 printf("%i READ %s %s\n", read_op, token->fType == kKeyword_TokenType ? "Key word" : "Object", token->fKeyword ? std::string(token->fKeyword, token->fKeyword Length).c_str() : token->fObject->toString().c_str());
807 #endif 927 #endif
808 928
809 return true; 929 return true;
810 } 930 }
811 931
812 void SkPdfNativeTokenizer::PutBack(PdfToken token) { 932 void SkPdfNativeTokenizer::PutBack(PdfToken token) {
813 SkASSERT(!fHasPutBack); 933 SkASSERT(!fHasPutBack);
814 fHasPutBack = true; 934 fHasPutBack = true;
815 fPutBack = token; 935 fPutBack = token;
816 #ifdef PDF_TRACE 936 #ifdef PDF_TRACE_READ_TOKEN
817 printf("PUT_BACK %s %s\n", token.fType == kKeyword_TokenType ? "Keyword" : " Object", token.fKeyword ? std::string(token.fKeyword, token.fKeywordLength).c_st r(): token.fObject->toString().c_str()); 937 printf("PUT_BACK %s %s\n", token.fType == kKeyword_TokenType ? "Keyword" : " Object", token.fKeyword ? std::string(token.fKeyword, token.fKeywordLength).c_st r(): token.fObject->toString().c_str());
818 #endif 938 #endif
819 } 939 }
820 940
821 bool SkPdfNativeTokenizer::readToken(PdfToken* token) { 941 bool SkPdfNativeTokenizer::readToken(PdfToken* token) {
822 if (fHasPutBack) { 942 if (fHasPutBack) {
823 *token = fPutBack; 943 *token = fPutBack;
824 fHasPutBack = false; 944 fHasPutBack = false;
825 #ifdef PDF_TRACE 945 #ifdef PDF_TRACE_READ_TOKEN
826 printf("READ_BACK %s %s\n", token->fType == kKeyword_TokenType ? "Keyword" : "Object", token->fKeyword ? std::string(token->fKeyword, token->fKeywordLength) .c_str() : token->fObject->toString().c_str()); 946 printf("READ_BACK %s %s\n", token->fType == kKeyword_TokenType ? "Keyword" : "Object", token->fKeyword ? std::string(token->fKeyword, token->fKeywordLength) .c_str() : token->fObject->toString().c_str());
827 #endif 947 #endif
828 return true; 948 return true;
829 } 949 }
830 950
831 if (fEmpty) { 951 if (fEmpty) {
832 #ifdef PDF_TRACE 952 #ifdef PDF_TRACE_READ_TOKEN
833 printf("EMPTY TOKENIZER\n"); 953 printf("EMPTY TOKENIZER\n");
834 #endif 954 #endif
835 return false; 955 return false;
836 } 956 }
837 957
838 return readTokenCore(token); 958 return readTokenCore(token);
839 } 959 }
840 960
841 #define DECLARE_PDF_NAME(longName) SkPdfName longName((char*)#longName) 961 #define DECLARE_PDF_NAME(longName) SkPdfName longName((char*)#longName)
842 962
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
904 HANDLE_NAME_ABBR(value, FlateDecode, Fl); // (PDF 1.2) 1024 HANDLE_NAME_ABBR(value, FlateDecode, Fl); // (PDF 1.2)
905 HANDLE_NAME_ABBR(value, RunLengthDecode, RL); 1025 HANDLE_NAME_ABBR(value, RunLengthDecode, RL);
906 HANDLE_NAME_ABBR(value, CCITTFaxDecode, CCF); 1026 HANDLE_NAME_ABBR(value, CCITTFaxDecode, CCF);
907 HANDLE_NAME_ABBR(value, DCTDecode, DCT); 1027 HANDLE_NAME_ABBR(value, DCTDecode, DCT);
908 1028
909 return value; 1029 return value;
910 } 1030 }
911 1031
912 SkPdfImageDictionary* SkPdfNativeTokenizer::readInlineImage() { 1032 SkPdfImageDictionary* SkPdfNativeTokenizer::readInlineImage() {
913 // BI already processed 1033 // BI already processed
914 fUncompressedStream = skipPdfWhiteSpaces(fUncompressedStream, fUncompressedS treamEnd); 1034 fUncompressedStream = skipPdfWhiteSpaces(0, fUncompressedStream, fUncompress edStreamEnd);
915 if (fUncompressedStream >= fUncompressedStreamEnd) { 1035 if (fUncompressedStream >= fUncompressedStreamEnd) {
916 return NULL; 1036 return NULL;
917 } 1037 }
918 1038
919 SkPdfImageDictionary* inlineImage = (SkPdfImageDictionary*)fAllocator->alloc Object(); 1039 SkPdfImageDictionary* inlineImage = (SkPdfImageDictionary*)fAllocator->alloc Object();
920 SkPdfObject::makeEmptyDictionary(inlineImage); 1040 SkPdfObject::makeEmptyDictionary(inlineImage);
921 1041
922 while (fUncompressedStream < fUncompressedStreamEnd) { 1042 while (fUncompressedStream < fUncompressedStreamEnd) {
923 SkPdfObject* key = fAllocator->allocObject(); 1043 SkPdfObject* key = fAllocator->allocObject();
924 fUncompressedStream = nextObject(fUncompressedStream, fUncompressedStrea mEnd, key, fAllocator, fDoc); 1044 fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedSt reamEnd, key, fAllocator, fDoc);
925 1045
926 if (key->isKeyword() && key->len() == 2 && key->c_str()[0] == 'I' && key ->c_str()[1] == 'D') { // ID 1046 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); 1047 fUncompressedStream = readInlineImageStream(0, fUncompressedStream, fUncompressedStreamEnd, inlineImage, fDoc);
928 return inlineImage; 1048 return inlineImage;
929 } else { 1049 } else {
930 SkPdfObject* obj = fAllocator->allocObject(); 1050 SkPdfObject* obj = fAllocator->allocObject();
931 fUncompressedStream = nextObject(fUncompressedStream, fUncompressedS treamEnd, obj, fAllocator, fDoc); 1051 fUncompressedStream = nextObject(0, fUncompressedStream, fUncompress edStreamEnd, obj, fAllocator, fDoc);
932 // TODO(edisonn): perf maybe we should not expand abreviation like t his 1052 // TODO(edisonn): perf maybe we should not expand abreviation like t his
933 inlineImage->set(inlineImageKeyAbbreviationExpand(key), 1053 inlineImage->set(inlineImageKeyAbbreviationExpand(key),
934 inlineImageValueAbbreviationExpand(obj)); 1054 inlineImageValueAbbreviationExpand(obj));
935 } 1055 }
936 } 1056 }
937 // TODO(edisonn): report end of data with inline image without an EI 1057 // TODO(edisonn): report end of data with inline image without an EI
938 return inlineImage; 1058 return inlineImage;
939 } 1059 }
OLDNEW
« no previous file with comments | « experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h ('k') | experimental/PdfViewer/pdfparser/native/SkPdfObject.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698