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" | 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |