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        /* only add digit if we don't overflow */
254        if ( divider < 0xCCCCCCCL && decimal < 0xCCCCCCCL )
255        {
256          decimal = decimal * 10 + c;
257
258          if ( !integral && power_ten > 0 )
259            power_ten--;
260          else
261            divider *= 10;
262        }
263      }
264    }
265
266    /* read exponent, if any */
267    if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
268    {
269      FT_Long  exponent;
270
271
272      p++;
273
274      curp     = p;
275      exponent = PS_Conv_ToInt( &p, limit );
276
277      if ( curp == p )
278        return 0;
279
280      /* arbitrarily limit exponent */
281      if ( exponent > 1000 )
282        have_overflow = 1;
283      else if ( exponent < -1000 )
284        have_underflow = 1;
285      else
286        power_ten += exponent;
287    }
288
289    *cursor = p;
290
291    if ( !integral && !decimal )
292      return 0;
293
294    if ( have_overflow )
295      goto Overflow;
296    if ( have_underflow )
297      goto Underflow;
298
299    while ( power_ten > 0 )
300    {
301      if ( integral >= 0xCCCCCCCL )
302        goto Overflow;
303      integral *= 10;
304
305      if ( decimal >= 0xCCCCCCCL )
306      {
307        if ( divider == 1 )
308          goto Overflow;
309        divider /= 10;
310      }
311      else
312        decimal *= 10;
313
314      power_ten--;
315    }
316
317    while ( power_ten < 0 )
318    {
319      integral /= 10;
320      if ( divider < 0xCCCCCCCL )
321        divider *= 10;
322      else
323        decimal /= 10;
324
325      if ( !integral && !decimal )
326        goto Underflow;
327
328      power_ten++;
329    }
330
331    if ( decimal )
332    {
333      decimal = FT_DivFix( decimal, divider );
334      /* it's not necessary to check this addition for overflow */
335      /* due to the structure of the real number representation */
336      integral += decimal;
337    }
338
339  Exit:
340    if ( sign )
341      integral = -integral;
342
343    return integral;
344
345  Bad:
346    FT_TRACE4(( "!!!END OF DATA:!!!" ));
347    return 0;
348
349  Overflow:
350    integral = 0x7FFFFFFFL;
351    FT_TRACE4(( "!!!OVERFLOW:!!!" ));
352    goto Exit;
353
354  Underflow:
355    FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
356    return 0;
357  }
358
359
360#if 0
361  FT_LOCAL_DEF( FT_UInt )
362  PS_Conv_StringDecode( FT_Byte**  cursor,
363                        FT_Byte*   limit,
364                        FT_Byte*   buffer,
365                        FT_Offset  n )
366  {
367    FT_Byte*  p;
368    FT_UInt   r = 0;
369
370
371    for ( p = *cursor; r < n && p < limit; p++ )
372    {
373      FT_Byte  b;
374
375
376      if ( *p != '\\' )
377      {
378        buffer[r++] = *p;
379
380        continue;
381      }
382
383      p++;
384
385      switch ( *p )
386      {
387      case 'n':
388        b = '\n';
389        break;
390      case 'r':
391        b = '\r';
392        break;
393      case 't':
394        b = '\t';
395        break;
396      case 'b':
397        b = '\b';
398        break;
399      case 'f':
400        b = '\f';
401        break;
402      case '\r':
403        p++;
404        if ( *p != '\n' )
405        {
406          b = *p;
407
408          break;
409        }
410        /* no break */
411      case '\n':
412        continue;
413        break;
414      default:
415        if ( IS_PS_DIGIT( *p ) )
416        {
417          b = *p - '0';
418
419          p++;
420
421          if ( IS_PS_DIGIT( *p ) )
422          {
423            b = b * 8 + *p - '0';
424
425            p++;
426
427            if ( IS_PS_DIGIT( *p ) )
428              b = b * 8 + *p - '0';
429            else
430            {
431              buffer[r++] = b;
432              b = *p;
433            }
434          }
435          else
436          {
437            buffer[r++] = b;
438            b = *p;
439          }
440        }
441        else
442          b = *p;
443        break;
444      }
445
446      buffer[r++] = b;
447    }
448
449    *cursor = p;
450
451    return r;
452  }
453#endif /* 0 */
454
455
456  FT_LOCAL_DEF( FT_UInt )
457  PS_Conv_ASCIIHexDecode( FT_Byte**  cursor,
458                          FT_Byte*   limit,
459                          FT_Byte*   buffer,
460                          FT_Offset  n )
461  {
462    FT_Byte*  p;
463    FT_UInt   r   = 0;
464    FT_UInt   w   = 0;
465    FT_UInt   pad = 0x01;
466
467
468    n *= 2;
469
470#if 1
471
472    p = *cursor;
473
474    if ( p >= limit )
475      return 0;
476
477    if ( n > (FT_UInt)( limit - p ) )
478      n = (FT_UInt)( limit - p );
479
480    /* we try to process two nibbles at a time to be as fast as possible */
481    for ( ; r < n; r++ )
482    {
483      FT_UInt  c = p[r];
484
485
486      if ( IS_PS_SPACE( c ) )
487        continue;
488
489      if ( c OP 0x80 )
490        break;
491
492      c = ft_char_table[c & 0x7F];
493      if ( (unsigned)c >= 16 )
494        break;
495
496      pad = ( pad << 4 ) | c;
497      if ( pad & 0x100 )
498      {
499        buffer[w++] = (FT_Byte)pad;
500        pad         = 0x01;
501      }
502    }
503
504    if ( pad != 0x01 )
505      buffer[w++] = (FT_Byte)( pad << 4 );
506
507    *cursor = p + r;
508
509    return w;
510
511#else /* 0 */
512
513    for ( r = 0; r < n; r++ )
514    {
515      FT_Char  c;
516
517
518      if ( IS_PS_SPACE( *p ) )
519        continue;
520
521      if ( *p OP 0x80 )
522        break;
523
524      c = ft_char_table[*p & 0x7f];
525
526      if ( (unsigned)c >= 16 )
527        break;
528
529      if ( r & 1 )
530      {
531        *buffer = (FT_Byte)(*buffer + c);
532        buffer++;
533      }
534      else
535        *buffer = (FT_Byte)(c << 4);
536
537      r++;
538    }
539
540    *cursor = p;
541
542    return ( r + 1 ) / 2;
543
544#endif /* 0 */
545
546  }
547
548
549  FT_LOCAL_DEF( FT_UInt )
550  PS_Conv_EexecDecode( FT_Byte**   cursor,
551                       FT_Byte*    limit,
552                       FT_Byte*    buffer,
553                       FT_Offset   n,
554                       FT_UShort*  seed )
555  {
556    FT_Byte*  p;
557    FT_UInt   r;
558    FT_UInt   s = *seed;
559
560
561#if 1
562
563    p = *cursor;
564
565    if ( p >= limit )
566      return 0;
567
568    if ( n > (FT_UInt)(limit - p) )
569      n = (FT_UInt)(limit - p);
570
571    for ( r = 0; r < n; r++ )
572    {
573      FT_UInt  val = p[r];
574      FT_UInt  b   = ( val ^ ( s >> 8 ) );
575
576
577      s         = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
578      buffer[r] = (FT_Byte) b;
579    }
580
581    *cursor = p + n;
582    *seed   = (FT_UShort)s;
583
584#else /* 0 */
585
586    for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
587    {
588      FT_Byte  b = (FT_Byte)( *p ^ ( s >> 8 ) );
589
590
591      s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
592      *buffer++ = b;
593    }
594    *cursor = p;
595    *seed   = s;
596
597#endif /* 0 */
598
599    return r;
600  }
601
602
603/* END */
604