[FREETYPE]
[reactos.git] / reactos / lib / 3rdparty / freetype / src / psaux / psconv.c
1 /***************************************************************************/
2 /* */
3 /* psconv.c */
4 /* */
5 /* Some convenience conversions (body). */
6 /* */
7 /* Copyright 2006, 2008, 2009, 2012-2013 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 trace_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
116 num_limit = 0x7FFFFFFFL / base;
117 c_limit = (FT_Char)( 0x7FFFFFFFL % base );
118
119 for ( ; p < limit; p++ )
120 {
121 FT_Char c;
122
123
124 if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
125 break;
126
127 c = ft_char_table[*p & 0x7f];
128
129 if ( c < 0 || c >= base )
130 break;
131
132 if ( num > num_limit || ( num == num_limit && c > c_limit ) )
133 have_overflow = 1;
134 else
135 num = num * base + c;
136 }
137
138 *cursor = p;
139
140 if ( have_overflow )
141 {
142 num = 0x7FFFFFFFL;
143 FT_TRACE4(( "!!!OVERFLOW:!!!" ));
144 }
145
146 if ( sign )
147 num = -num;
148
149 return num;
150
151 Bad:
152 FT_TRACE4(( "!!!END OF DATA:!!!" ));
153 return 0;
154 }
155
156
157 FT_LOCAL_DEF( FT_Long )
158 PS_Conv_ToInt( FT_Byte** cursor,
159 FT_Byte* limit )
160
161 {
162 FT_Byte* p = *cursor;
163 FT_Byte* curp;
164
165 FT_Long num;
166
167
168 curp = p;
169 num = PS_Conv_Strtol( &p, limit, 10 );
170
171 if ( p == curp )
172 return 0;
173
174 if ( p < limit && *p == '#' )
175 {
176 p++;
177
178 curp = p;
179 num = PS_Conv_Strtol( &p, limit, num );
180
181 if ( p == curp )
182 return 0;
183 }
184
185 *cursor = p;
186
187 return num;
188 }
189
190
191 FT_LOCAL_DEF( FT_Fixed )
192 PS_Conv_ToFixed( FT_Byte** cursor,
193 FT_Byte* limit,
194 FT_Long power_ten )
195 {
196 FT_Byte* p = *cursor;
197 FT_Byte* curp;
198
199 FT_Fixed integral = 0;
200 FT_Long decimal = 0;
201 FT_Long divider = 1;
202
203 FT_Bool sign = 0;
204 FT_Bool have_overflow = 0;
205 FT_Bool have_underflow = 0;
206
207
208 if ( p >= limit )
209 goto Bad;
210
211 if ( *p == '-' || *p == '+' )
212 {
213 sign = FT_BOOL( *p == '-' );
214
215 p++;
216 if ( p == limit )
217 goto Bad;
218 }
219
220 /* read the integer part */
221 if ( *p != '.' )
222 {
223 curp = p;
224 integral = PS_Conv_ToInt( &p, limit );
225
226 if ( p == curp )
227 return 0;
228
229 if ( integral > 0x7FFF )
230 have_overflow = 1;
231 else
232 integral = (FT_Fixed)( (FT_UInt32)integral << 16 );
233 }
234
235 /* read the decimal part */
236 if ( p < limit && *p == '.' )
237 {
238 p++;
239
240 for ( ; p < limit; p++ )
241 {
242 FT_Char c;
243
244
245 if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
246 break;
247
248 c = ft_char_table[*p & 0x7f];
249
250 if ( c < 0 || c >= 10 )
251 break;
252
253 if ( decimal < 0xCCCCCCCL )
254 {
255 decimal = decimal * 10 + c;
256
257 if ( !integral && power_ten > 0 )
258 power_ten--;
259 else
260 divider *= 10;
261 }
262 }
263 }
264
265 /* read exponent, if any */
266 if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
267 {
268 FT_Long exponent;
269
270
271 p++;
272
273 curp = p;
274 exponent = PS_Conv_ToInt( &p, limit );
275
276 if ( curp == p )
277 return 0;
278
279 /* arbitrarily limit exponent */
280 if ( exponent > 1000 )
281 have_overflow = 1;
282 else if ( exponent < -1000 )
283 have_underflow = 1;
284 else
285 power_ten += exponent;
286 }
287
288 *cursor = p;
289
290 if ( !integral && !decimal )
291 return 0;
292
293 if ( have_overflow )
294 goto Overflow;
295 if ( have_underflow )
296 goto Underflow;
297
298 while ( power_ten > 0 )
299 {
300 if ( integral >= 0xCCCCCCCL )
301 goto Overflow;
302 integral *= 10;
303
304 if ( decimal >= 0xCCCCCCCL )
305 {
306 if ( divider == 1 )
307 goto Overflow;
308 divider /= 10;
309 }
310 else
311 decimal *= 10;
312
313 power_ten--;
314 }
315
316 while ( power_ten < 0 )
317 {
318 integral /= 10;
319 if ( divider < 0xCCCCCCCL )
320 divider *= 10;
321 else
322 decimal /= 10;
323
324 if ( !integral && !decimal )
325 goto Underflow;
326
327 power_ten++;
328 }
329
330 if ( decimal )
331 {
332 decimal = FT_DivFix( decimal, divider );
333 /* it's not necessary to check this addition for overflow */
334 /* due to the structure of the real number representation */
335 integral += decimal;
336 }
337
338 Exit:
339 if ( sign )
340 integral = -integral;
341
342 return integral;
343
344 Bad:
345 FT_TRACE4(( "!!!END OF DATA:!!!" ));
346 return 0;
347
348 Overflow:
349 integral = 0x7FFFFFFFL;
350 FT_TRACE4(( "!!!OVERFLOW:!!!" ));
351 goto Exit;
352
353 Underflow:
354 FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
355 return 0;
356 }
357
358
359 #if 0
360 FT_LOCAL_DEF( FT_UInt )
361 PS_Conv_StringDecode( FT_Byte** cursor,
362 FT_Byte* limit,
363 FT_Byte* buffer,
364 FT_Offset n )
365 {
366 FT_Byte* p;
367 FT_UInt r = 0;
368
369
370 for ( p = *cursor; r < n && p < limit; p++ )
371 {
372 FT_Byte b;
373
374
375 if ( *p != '\\' )
376 {
377 buffer[r++] = *p;
378
379 continue;
380 }
381
382 p++;
383
384 switch ( *p )
385 {
386 case 'n':
387 b = '\n';
388 break;
389 case 'r':
390 b = '\r';
391 break;
392 case 't':
393 b = '\t';
394 break;
395 case 'b':
396 b = '\b';
397 break;
398 case 'f':
399 b = '\f';
400 break;
401 case '\r':
402 p++;
403 if ( *p != '\n' )
404 {
405 b = *p;
406
407 break;
408 }
409 /* no break */
410 case '\n':
411 continue;
412 break;
413 default:
414 if ( IS_PS_DIGIT( *p ) )
415 {
416 b = *p - '0';
417
418 p++;
419
420 if ( IS_PS_DIGIT( *p ) )
421 {
422 b = b * 8 + *p - '0';
423
424 p++;
425
426 if ( IS_PS_DIGIT( *p ) )
427 b = b * 8 + *p - '0';
428 else
429 {
430 buffer[r++] = b;
431 b = *p;
432 }
433 }
434 else
435 {
436 buffer[r++] = b;
437 b = *p;
438 }
439 }
440 else
441 b = *p;
442 break;
443 }
444
445 buffer[r++] = b;
446 }
447
448 *cursor = p;
449
450 return r;
451 }
452 #endif /* 0 */
453
454
455 FT_LOCAL_DEF( FT_UInt )
456 PS_Conv_ASCIIHexDecode( FT_Byte** cursor,
457 FT_Byte* limit,
458 FT_Byte* buffer,
459 FT_Offset n )
460 {
461 FT_Byte* p;
462 FT_UInt r = 0;
463 FT_UInt w = 0;
464 FT_UInt pad = 0x01;
465
466
467 n *= 2;
468
469 #if 1
470
471 p = *cursor;
472
473 if ( p >= limit )
474 return 0;
475
476 if ( n > (FT_UInt)( limit - p ) )
477 n = (FT_UInt)( limit - p );
478
479 /* we try to process two nibbles at a time to be as fast as possible */
480 for ( ; r < n; r++ )
481 {
482 FT_UInt c = p[r];
483
484
485 if ( IS_PS_SPACE( c ) )
486 continue;
487
488 if ( c OP 0x80 )
489 break;
490
491 c = ft_char_table[c & 0x7F];
492 if ( (unsigned)c >= 16 )
493 break;
494
495 pad = ( pad << 4 ) | c;
496 if ( pad & 0x100 )
497 {
498 buffer[w++] = (FT_Byte)pad;
499 pad = 0x01;
500 }
501 }
502
503 if ( pad != 0x01 )
504 buffer[w++] = (FT_Byte)( pad << 4 );
505
506 *cursor = p + r;
507
508 return w;
509
510 #else /* 0 */
511
512 for ( r = 0; r < n; r++ )
513 {
514 FT_Char c;
515
516
517 if ( IS_PS_SPACE( *p ) )
518 continue;
519
520 if ( *p OP 0x80 )
521 break;
522
523 c = ft_char_table[*p & 0x7f];
524
525 if ( (unsigned)c >= 16 )
526 break;
527
528 if ( r & 1 )
529 {
530 *buffer = (FT_Byte)(*buffer + c);
531 buffer++;
532 }
533 else
534 *buffer = (FT_Byte)(c << 4);
535
536 r++;
537 }
538
539 *cursor = p;
540
541 return ( r + 1 ) / 2;
542
543 #endif /* 0 */
544
545 }
546
547
548 FT_LOCAL_DEF( FT_UInt )
549 PS_Conv_EexecDecode( FT_Byte** cursor,
550 FT_Byte* limit,
551 FT_Byte* buffer,
552 FT_Offset n,
553 FT_UShort* seed )
554 {
555 FT_Byte* p;
556 FT_UInt r;
557 FT_UInt s = *seed;
558
559
560 #if 1
561
562 p = *cursor;
563
564 if ( p >= limit )
565 return 0;
566
567 if ( n > (FT_UInt)(limit - p) )
568 n = (FT_UInt)(limit - p);
569
570 for ( r = 0; r < n; r++ )
571 {
572 FT_UInt val = p[r];
573 FT_UInt b = ( val ^ ( s >> 8 ) );
574
575
576 s = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
577 buffer[r] = (FT_Byte) b;
578 }
579
580 *cursor = p + n;
581 *seed = (FT_UShort)s;
582
583 #else /* 0 */
584
585 for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
586 {
587 FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) );
588
589
590 s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
591 *buffer++ = b;
592 }
593 *cursor = p;
594 *seed = s;
595
596 #endif /* 0 */
597
598 return r;
599 }
600
601
602 /* END */