1 | /**************************************************************************** |
2 | * |
3 | * psconv.c |
4 | * |
5 | * Some convenience conversions (body). |
6 | * |
7 | * Copyright (C) 2006-2019 by |
8 | * David Turner, Robert Wilhelm, and Werner Lemberg. |
9 | * |
10 | * This file is part of the FreeType project, and may only be used, |
11 | * modified, and distributed under the terms of the FreeType project |
12 | * license, LICENSE.TXT. By continuing to use, modify, or distribute |
13 | * this file you indicate that you have read the license and |
14 | * understand and accept it fully. |
15 | * |
16 | */ |
17 | |
18 | |
19 | #include <ft2build.h> |
20 | #include FT_INTERNAL_POSTSCRIPT_AUX_H |
21 | #include FT_INTERNAL_DEBUG_H |
22 | |
23 | #include "psconv.h" |
24 | #include "psauxerr.h" |
25 | |
26 | |
27 | /************************************************************************** |
28 | * |
29 | * The macro FT_COMPONENT is used in trace mode. It is an implicit |
30 | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
31 | * messages during execution. |
32 | */ |
33 | #undef FT_COMPONENT |
34 | #define FT_COMPONENT psconv |
35 | |
36 | |
37 | /* The following array is used by various functions to quickly convert */ |
38 | /* digits (both decimal and non-decimal) into numbers. */ |
39 | |
40 | #if 'A' == 65 |
41 | /* ASCII */ |
42 | |
43 | static const FT_Char ft_char_table[128] = |
44 | { |
45 | /* 0x00 */ |
46 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
47 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
48 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
49 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, |
50 | -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, |
51 | 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, |
52 | -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, |
53 | 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, |
54 | }; |
55 | |
56 | /* no character >= 0x80 can represent a valid number */ |
57 | #define OP >= |
58 | |
59 | #endif /* 'A' == 65 */ |
60 | |
61 | #if 'A' == 193 |
62 | /* EBCDIC */ |
63 | |
64 | static const FT_Char ft_char_table[128] = |
65 | { |
66 | /* 0x80 */ |
67 | -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, |
68 | -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, |
69 | -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, |
70 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
71 | -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, |
72 | -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, |
73 | -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, |
74 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, |
75 | }; |
76 | |
77 | /* no character < 0x80 can represent a valid number */ |
78 | #define OP < |
79 | |
80 | #endif /* 'A' == 193 */ |
81 | |
82 | |
83 | FT_LOCAL_DEF( FT_Long ) |
84 | PS_Conv_Strtol( FT_Byte** cursor, |
85 | FT_Byte* limit, |
86 | FT_Long base ) |
87 | { |
88 | FT_Byte* p = *cursor; |
89 | |
90 | FT_Long num = 0; |
91 | FT_Bool sign = 0; |
92 | FT_Bool have_overflow = 0; |
93 | |
94 | FT_Long num_limit; |
95 | FT_Char c_limit; |
96 | |
97 | |
98 | if ( p >= limit ) |
99 | goto Bad; |
100 | |
101 | if ( base < 2 || base > 36 ) |
102 | { |
103 | FT_TRACE4(( "!!!INVALID BASE:!!!" )); |
104 | return 0; |
105 | } |
106 | |
107 | if ( *p == '-' || *p == '+' ) |
108 | { |
109 | sign = FT_BOOL( *p == '-' ); |
110 | |
111 | p++; |
112 | if ( p == limit ) |
113 | goto Bad; |
114 | |
115 | /* only a single sign is allowed */ |
116 | if ( *p == '-' || *p == '+' ) |
117 | return 0; |
118 | } |
119 | |
120 | num_limit = 0x7FFFFFFFL / base; |
121 | c_limit = (FT_Char)( 0x7FFFFFFFL % base ); |
122 | |
123 | for ( ; p < limit; p++ ) |
124 | { |
125 | FT_Char c; |
126 | |
127 | |
128 | if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) |
129 | break; |
130 | |
131 | c = ft_char_table[*p & 0x7F]; |
132 | |
133 | if ( c < 0 || c >= base ) |
134 | break; |
135 | |
136 | if ( num > num_limit || ( num == num_limit && c > c_limit ) ) |
137 | have_overflow = 1; |
138 | else |
139 | num = num * base + c; |
140 | } |
141 | |
142 | *cursor = p; |
143 | |
144 | if ( have_overflow ) |
145 | { |
146 | num = 0x7FFFFFFFL; |
147 | FT_TRACE4(( "!!!OVERFLOW:!!!" )); |
148 | } |
149 | |
150 | if ( sign ) |
151 | num = -num; |
152 | |
153 | return num; |
154 | |
155 | Bad: |
156 | FT_TRACE4(( "!!!END OF DATA:!!!" )); |
157 | return 0; |
158 | } |
159 | |
160 | |
161 | FT_LOCAL_DEF( FT_Long ) |
162 | PS_Conv_ToInt( FT_Byte** cursor, |
163 | FT_Byte* limit ) |
164 | |
165 | { |
166 | FT_Byte* p = *cursor; |
167 | FT_Byte* curp; |
168 | |
169 | FT_Long num; |
170 | |
171 | |
172 | curp = p; |
173 | num = PS_Conv_Strtol( &p, limit, 10 ); |
174 | |
175 | if ( p == curp ) |
176 | return 0; |
177 | |
178 | if ( p < limit && *p == '#' ) |
179 | { |
180 | p++; |
181 | |
182 | curp = p; |
183 | num = PS_Conv_Strtol( &p, limit, num ); |
184 | |
185 | if ( p == curp ) |
186 | return 0; |
187 | } |
188 | |
189 | *cursor = p; |
190 | |
191 | return num; |
192 | } |
193 | |
194 | |
195 | FT_LOCAL_DEF( FT_Fixed ) |
196 | PS_Conv_ToFixed( FT_Byte** cursor, |
197 | FT_Byte* limit, |
198 | FT_Long power_ten ) |
199 | { |
200 | FT_Byte* p = *cursor; |
201 | FT_Byte* curp; |
202 | |
203 | FT_Fixed integral = 0; |
204 | FT_Long decimal = 0; |
205 | FT_Long divider = 1; |
206 | |
207 | FT_Bool sign = 0; |
208 | FT_Bool have_overflow = 0; |
209 | FT_Bool have_underflow = 0; |
210 | |
211 | |
212 | if ( p >= limit ) |
213 | goto Bad; |
214 | |
215 | if ( *p == '-' || *p == '+' ) |
216 | { |
217 | sign = FT_BOOL( *p == '-' ); |
218 | |
219 | p++; |
220 | if ( p == limit ) |
221 | goto Bad; |
222 | |
223 | /* only a single sign is allowed */ |
224 | if ( *p == '-' || *p == '+' ) |
225 | return 0; |
226 | } |
227 | |
228 | /* read the integer part */ |
229 | if ( *p != '.' ) |
230 | { |
231 | curp = p; |
232 | integral = PS_Conv_ToInt( &p, limit ); |
233 | |
234 | if ( p == curp ) |
235 | return 0; |
236 | |
237 | if ( integral > 0x7FFF ) |
238 | have_overflow = 1; |
239 | else |
240 | integral = (FT_Fixed)( (FT_UInt32)integral << 16 ); |
241 | } |
242 | |
243 | /* read the decimal part */ |
244 | if ( p < limit && *p == '.' ) |
245 | { |
246 | p++; |
247 | |
248 | for ( ; p < limit; p++ ) |
249 | { |
250 | FT_Char c; |
251 | |
252 | |
253 | if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) |
254 | break; |
255 | |
256 | c = ft_char_table[*p & 0x7F]; |
257 | |
258 | if ( c < 0 || c >= 10 ) |
259 | break; |
260 | |
261 | /* only add digit if we don't overflow */ |
262 | if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL ) |
263 | { |
264 | decimal = decimal * 10 + c; |
265 | |
266 | if ( !integral && power_ten > 0 ) |
267 | power_ten--; |
268 | else |
269 | divider *= 10; |
270 | } |
271 | } |
272 | } |
273 | |
274 | /* read exponent, if any */ |
275 | if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) ) |
276 | { |
277 | FT_Long exponent; |
278 | |
279 | |
280 | p++; |
281 | |
282 | curp = p; |
283 | exponent = PS_Conv_ToInt( &p, limit ); |
284 | |
285 | if ( curp == p ) |
286 | return 0; |
287 | |
288 | /* arbitrarily limit exponent */ |
289 | if ( exponent > 1000 ) |
290 | have_overflow = 1; |
291 | else if ( exponent < -1000 ) |
292 | have_underflow = 1; |
293 | else |
294 | power_ten += exponent; |
295 | } |
296 | |
297 | *cursor = p; |
298 | |
299 | if ( !integral && !decimal ) |
300 | return 0; |
301 | |
302 | if ( have_overflow ) |
303 | goto Overflow; |
304 | if ( have_underflow ) |
305 | goto Underflow; |
306 | |
307 | while ( power_ten > 0 ) |
308 | { |
309 | if ( integral >= 0xCCCCCCCL ) |
310 | goto Overflow; |
311 | integral *= 10; |
312 | |
313 | if ( decimal >= 0xCCCCCCCL ) |
314 | { |
315 | if ( divider == 1 ) |
316 | goto Overflow; |
317 | divider /= 10; |
318 | } |
319 | else |
320 | decimal *= 10; |
321 | |
322 | power_ten--; |
323 | } |
324 | |
325 | while ( power_ten < 0 ) |
326 | { |
327 | integral /= 10; |
328 | if ( divider < 0xCCCCCCCL ) |
329 | divider *= 10; |
330 | else |
331 | decimal /= 10; |
332 | |
333 | if ( !integral && !decimal ) |
334 | goto Underflow; |
335 | |
336 | power_ten++; |
337 | } |
338 | |
339 | if ( decimal ) |
340 | { |
341 | decimal = FT_DivFix( decimal, divider ); |
342 | /* it's not necessary to check this addition for overflow */ |
343 | /* due to the structure of the real number representation */ |
344 | integral += decimal; |
345 | } |
346 | |
347 | Exit: |
348 | if ( sign ) |
349 | integral = -integral; |
350 | |
351 | return integral; |
352 | |
353 | Bad: |
354 | FT_TRACE4(( "!!!END OF DATA:!!!" )); |
355 | return 0; |
356 | |
357 | Overflow: |
358 | integral = 0x7FFFFFFFL; |
359 | FT_TRACE4(( "!!!OVERFLOW:!!!" )); |
360 | goto Exit; |
361 | |
362 | Underflow: |
363 | FT_TRACE4(( "!!!UNDERFLOW:!!!" )); |
364 | return 0; |
365 | } |
366 | |
367 | |
368 | #if 0 |
369 | FT_LOCAL_DEF( FT_UInt ) |
370 | PS_Conv_StringDecode( FT_Byte** cursor, |
371 | FT_Byte* limit, |
372 | FT_Byte* buffer, |
373 | FT_Offset n ) |
374 | { |
375 | FT_Byte* p; |
376 | FT_UInt r = 0; |
377 | |
378 | |
379 | for ( p = *cursor; r < n && p < limit; p++ ) |
380 | { |
381 | FT_Byte b; |
382 | |
383 | |
384 | if ( *p != '\\' ) |
385 | { |
386 | buffer[r++] = *p; |
387 | |
388 | continue; |
389 | } |
390 | |
391 | p++; |
392 | |
393 | switch ( *p ) |
394 | { |
395 | case 'n': |
396 | b = '\n'; |
397 | break; |
398 | case 'r': |
399 | b = '\r'; |
400 | break; |
401 | case 't': |
402 | b = '\t'; |
403 | break; |
404 | case 'b': |
405 | b = '\b'; |
406 | break; |
407 | case 'f': |
408 | b = '\f'; |
409 | break; |
410 | case '\r': |
411 | p++; |
412 | if ( *p != '\n' ) |
413 | { |
414 | b = *p; |
415 | |
416 | break; |
417 | } |
418 | /* no break */ |
419 | case '\n': |
420 | continue; |
421 | break; |
422 | default: |
423 | if ( IS_PS_DIGIT( *p ) ) |
424 | { |
425 | b = *p - '0'; |
426 | |
427 | p++; |
428 | |
429 | if ( IS_PS_DIGIT( *p ) ) |
430 | { |
431 | b = b * 8 + *p - '0'; |
432 | |
433 | p++; |
434 | |
435 | if ( IS_PS_DIGIT( *p ) ) |
436 | b = b * 8 + *p - '0'; |
437 | else |
438 | { |
439 | buffer[r++] = b; |
440 | b = *p; |
441 | } |
442 | } |
443 | else |
444 | { |
445 | buffer[r++] = b; |
446 | b = *p; |
447 | } |
448 | } |
449 | else |
450 | b = *p; |
451 | break; |
452 | } |
453 | |
454 | buffer[r++] = b; |
455 | } |
456 | |
457 | *cursor = p; |
458 | |
459 | return r; |
460 | } |
461 | #endif /* 0 */ |
462 | |
463 | |
464 | FT_LOCAL_DEF( FT_UInt ) |
465 | PS_Conv_ASCIIHexDecode( FT_Byte** cursor, |
466 | FT_Byte* limit, |
467 | FT_Byte* buffer, |
468 | FT_Offset n ) |
469 | { |
470 | FT_Byte* p; |
471 | FT_UInt r = 0; |
472 | FT_UInt w = 0; |
473 | FT_UInt pad = 0x01; |
474 | |
475 | |
476 | n *= 2; |
477 | |
478 | #if 1 |
479 | |
480 | p = *cursor; |
481 | |
482 | if ( p >= limit ) |
483 | return 0; |
484 | |
485 | if ( n > (FT_UInt)( limit - p ) ) |
486 | n = (FT_UInt)( limit - p ); |
487 | |
488 | /* we try to process two nibbles at a time to be as fast as possible */ |
489 | for ( ; r < n; r++ ) |
490 | { |
491 | FT_UInt c = p[r]; |
492 | |
493 | |
494 | if ( IS_PS_SPACE( c ) ) |
495 | continue; |
496 | |
497 | if ( c OP 0x80 ) |
498 | break; |
499 | |
500 | c = (FT_UInt)ft_char_table[c & 0x7F]; |
501 | if ( c >= 16 ) |
502 | break; |
503 | |
504 | pad = ( pad << 4 ) | c; |
505 | if ( pad & 0x100 ) |
506 | { |
507 | buffer[w++] = (FT_Byte)pad; |
508 | pad = 0x01; |
509 | } |
510 | } |
511 | |
512 | if ( pad != 0x01 ) |
513 | buffer[w++] = (FT_Byte)( pad << 4 ); |
514 | |
515 | *cursor = p + r; |
516 | |
517 | return w; |
518 | |
519 | #else /* 0 */ |
520 | |
521 | for ( r = 0; r < n; r++ ) |
522 | { |
523 | FT_Char c; |
524 | |
525 | |
526 | if ( IS_PS_SPACE( *p ) ) |
527 | continue; |
528 | |
529 | if ( *p OP 0x80 ) |
530 | break; |
531 | |
532 | c = ft_char_table[*p & 0x7F]; |
533 | |
534 | if ( (unsigned)c >= 16 ) |
535 | break; |
536 | |
537 | if ( r & 1 ) |
538 | { |
539 | *buffer = (FT_Byte)(*buffer + c); |
540 | buffer++; |
541 | } |
542 | else |
543 | *buffer = (FT_Byte)(c << 4); |
544 | |
545 | r++; |
546 | } |
547 | |
548 | *cursor = p; |
549 | |
550 | return ( r + 1 ) / 2; |
551 | |
552 | #endif /* 0 */ |
553 | |
554 | } |
555 | |
556 | |
557 | FT_LOCAL_DEF( FT_UInt ) |
558 | PS_Conv_EexecDecode( FT_Byte** cursor, |
559 | FT_Byte* limit, |
560 | FT_Byte* buffer, |
561 | FT_Offset n, |
562 | FT_UShort* seed ) |
563 | { |
564 | FT_Byte* p; |
565 | FT_UInt r; |
566 | FT_UInt s = *seed; |
567 | |
568 | |
569 | #if 1 |
570 | |
571 | p = *cursor; |
572 | |
573 | if ( p >= limit ) |
574 | return 0; |
575 | |
576 | if ( n > (FT_UInt)(limit - p) ) |
577 | n = (FT_UInt)(limit - p); |
578 | |
579 | for ( r = 0; r < n; r++ ) |
580 | { |
581 | FT_UInt val = p[r]; |
582 | FT_UInt b = ( val ^ ( s >> 8 ) ); |
583 | |
584 | |
585 | s = ( (val + s)*52845U + 22719 ) & 0xFFFFU; |
586 | buffer[r] = (FT_Byte) b; |
587 | } |
588 | |
589 | *cursor = p + n; |
590 | *seed = (FT_UShort)s; |
591 | |
592 | #else /* 0 */ |
593 | |
594 | for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ ) |
595 | { |
596 | FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) ); |
597 | |
598 | |
599 | s = (FT_UShort)( ( *p + s ) * 52845U + 22719 ); |
600 | *buffer++ = b; |
601 | } |
602 | *cursor = p; |
603 | *seed = s; |
604 | |
605 | #endif /* 0 */ |
606 | |
607 | return r; |
608 | } |
609 | |
610 | |
611 | /* END */ |
612 | |