Home | History | Annotate | Download | only in psaux
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  psconv.c                                                               */
      4 /*                                                                         */
      5 /*    Some convenience conversions (body).                                 */
      6 /*                                                                         */
      7 /*  Copyright 2006, 2008, 2009 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 
     22 #include "psconv.h"
     23 #include "psauxerr.h"
     24 
     25 
     26   /* The following array is used by various functions to quickly convert */
     27   /* digits (both decimal and non-decimal) into numbers.                 */
     28 
     29 #if 'A' == 65
     30   /* ASCII */
     31 
     32   static const FT_Char  ft_char_table[128] =
     33   {
     34     /* 0x00 */
     35     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     36     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     37     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     38      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
     39     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
     40     25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
     41     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
     42     25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
     43   };
     44 
     45   /* no character >= 0x80 can represent a valid number */
     46 #define OP  >=
     47 
     48 #endif /* 'A' == 65 */
     49 
     50 #if 'A' == 193
     51   /* EBCDIC */
     52 
     53   static const FT_Char  ft_char_table[128] =
     54   {
     55     /* 0x80 */
     56     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
     57     -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
     58     -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
     59     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     60     -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
     61     -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
     62     -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
     63      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
     64   };
     65 
     66   /* no character < 0x80 can represent a valid number */
     67 #define OP  <
     68 
     69 #endif /* 'A' == 193 */
     70 
     71 
     72   FT_LOCAL_DEF( FT_Int )
     73   PS_Conv_Strtol( FT_Byte**  cursor,
     74                   FT_Byte*   limit,
     75                   FT_Int     base )
     76   {
     77     FT_Byte*  p = *cursor;
     78     FT_Int    num = 0;
     79     FT_Bool   sign = 0;
     80 
     81 
     82     if ( p == limit || base < 2 || base > 36 )
     83       return 0;
     84 
     85     if ( *p == '-' || *p == '+' )
     86     {
     87       sign = FT_BOOL( *p == '-' );
     88 
     89       p++;
     90       if ( p == limit )
     91         return 0;
     92     }
     93 
     94     for ( ; p < limit; p++ )
     95     {
     96       FT_Char  c;
     97 
     98 
     99       if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
    100         break;
    101 
    102       c = ft_char_table[*p & 0x7f];
    103 
    104       if ( c < 0 || c >= base )
    105         break;
    106 
    107       num = num * base + c;
    108     }
    109 
    110     if ( sign )
    111       num = -num;
    112 
    113     *cursor = p;
    114 
    115     return num;
    116   }
    117 
    118 
    119   FT_LOCAL_DEF( FT_Int )
    120   PS_Conv_ToInt( FT_Byte**  cursor,
    121                  FT_Byte*   limit )
    122 
    123   {
    124     FT_Byte*  p;
    125     FT_Int    num;
    126 
    127 
    128     num = PS_Conv_Strtol( cursor, limit, 10 );
    129     p   = *cursor;
    130 
    131     if ( p < limit && *p == '#' )
    132     {
    133       *cursor = p + 1;
    134 
    135       return PS_Conv_Strtol( cursor, limit, num );
    136     }
    137     else
    138       return num;
    139   }
    140 
    141 
    142   FT_LOCAL_DEF( FT_Fixed )
    143   PS_Conv_ToFixed( FT_Byte**  cursor,
    144                    FT_Byte*   limit,
    145                    FT_Int     power_ten )
    146   {
    147     FT_Byte*  p = *cursor;
    148     FT_Fixed  integral;
    149     FT_Long   decimal = 0, divider = 1;
    150     FT_Bool   sign = 0;
    151 
    152 
    153     if ( p == limit )
    154       return 0;
    155 
    156     if ( *p == '-' || *p == '+' )
    157     {
    158       sign = FT_BOOL( *p == '-' );
    159 
    160       p++;
    161       if ( p == limit )
    162         return 0;
    163     }
    164 
    165     if ( *p != '.' )
    166       integral = PS_Conv_ToInt( &p, limit ) << 16;
    167     else
    168       integral = 0;
    169 
    170     /* read the decimal part */
    171     if ( p < limit && *p == '.' )
    172     {
    173       p++;
    174 
    175       for ( ; p < limit; p++ )
    176       {
    177         FT_Char  c;
    178 
    179 
    180         if ( IS_PS_SPACE( *p ) || *p OP 0x80 )
    181           break;
    182 
    183         c = ft_char_table[*p & 0x7f];
    184 
    185         if ( c < 0 || c >= 10 )
    186           break;
    187 
    188         if ( !integral && power_ten > 0 )
    189         {
    190           power_ten--;
    191           decimal = decimal * 10 + c;
    192         }
    193         else
    194         {
    195           if ( divider < 10000000L )
    196           {
    197             decimal = decimal * 10 + c;
    198             divider *= 10;
    199           }
    200         }
    201       }
    202     }
    203 
    204     /* read exponent, if any */
    205     if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
    206     {
    207       p++;
    208       power_ten += PS_Conv_ToInt( &p, limit );
    209     }
    210 
    211     while ( power_ten > 0 )
    212     {
    213       integral *= 10;
    214       decimal  *= 10;
    215       power_ten--;
    216     }
    217 
    218     while ( power_ten < 0 )
    219     {
    220       integral /= 10;
    221       divider  *= 10;
    222       power_ten++;
    223     }
    224 
    225     if ( decimal )
    226       integral += FT_DivFix( decimal, divider );
    227 
    228     if ( sign )
    229       integral = -integral;
    230 
    231     *cursor = p;
    232 
    233     return integral;
    234   }
    235 
    236 
    237 #if 0
    238   FT_LOCAL_DEF( FT_UInt )
    239   PS_Conv_StringDecode( FT_Byte**  cursor,
    240                         FT_Byte*   limit,
    241                         FT_Byte*   buffer,
    242                         FT_Offset  n )
    243   {
    244     FT_Byte*  p;
    245     FT_UInt   r = 0;
    246 
    247 
    248     for ( p = *cursor; r < n && p < limit; p++ )
    249     {
    250       FT_Byte  b;
    251 
    252 
    253       if ( *p != '\\' )
    254       {
    255         buffer[r++] = *p;
    256 
    257         continue;
    258       }
    259 
    260       p++;
    261 
    262       switch ( *p )
    263       {
    264       case 'n':
    265         b = '\n';
    266         break;
    267       case 'r':
    268         b = '\r';
    269         break;
    270       case 't':
    271         b = '\t';
    272         break;
    273       case 'b':
    274         b = '\b';
    275         break;
    276       case 'f':
    277         b = '\f';
    278         break;
    279       case '\r':
    280         p++;
    281         if ( *p != '\n' )
    282         {
    283           b = *p;
    284 
    285           break;
    286         }
    287         /* no break */
    288       case '\n':
    289         continue;
    290         break;
    291       default:
    292         if ( IS_PS_DIGIT( *p ) )
    293         {
    294           b = *p - '0';
    295 
    296           p++;
    297 
    298           if ( IS_PS_DIGIT( *p ) )
    299           {
    300             b = b * 8 + *p - '0';
    301 
    302             p++;
    303 
    304             if ( IS_PS_DIGIT( *p ) )
    305               b = b * 8 + *p - '0';
    306             else
    307             {
    308               buffer[r++] = b;
    309               b = *p;
    310             }
    311           }
    312           else
    313           {
    314             buffer[r++] = b;
    315             b = *p;
    316           }
    317         }
    318         else
    319           b = *p;
    320         break;
    321       }
    322 
    323       buffer[r++] = b;
    324     }
    325 
    326     *cursor = p;
    327 
    328     return r;
    329   }
    330 #endif /* 0 */
    331 
    332 
    333   FT_LOCAL_DEF( FT_UInt )
    334   PS_Conv_ASCIIHexDecode( FT_Byte**  cursor,
    335                           FT_Byte*   limit,
    336                           FT_Byte*   buffer,
    337                           FT_Offset  n )
    338   {
    339     FT_Byte*  p;
    340     FT_UInt   r   = 0;
    341     FT_UInt   w   = 0;
    342     FT_UInt   pad = 0x01;
    343 
    344 
    345     n *= 2;
    346 
    347 #if 1
    348 
    349     p  = *cursor;
    350     if ( n > (FT_UInt)( limit - p ) )
    351       n = (FT_UInt)( limit - p );
    352 
    353     /* we try to process two nibbles at a time to be as fast as possible */
    354     for ( ; r < n; r++ )
    355     {
    356       FT_UInt  c = p[r];
    357 
    358 
    359       if ( IS_PS_SPACE( c ) )
    360         continue;
    361 
    362       if ( c OP 0x80 )
    363         break;
    364 
    365       c = ft_char_table[c & 0x7F];
    366       if ( (unsigned)c >= 16 )
    367         break;
    368 
    369       pad = ( pad << 4 ) | c;
    370       if ( pad & 0x100 )
    371       {
    372         buffer[w++] = (FT_Byte)pad;
    373         pad         = 0x01;
    374       }
    375     }
    376 
    377     if ( pad != 0x01 )
    378       buffer[w++] = (FT_Byte)( pad << 4 );
    379 
    380     *cursor = p + r;
    381 
    382     return w;
    383 
    384 #else /* 0 */
    385 
    386     for ( r = 0; r < n; r++ )
    387     {
    388       FT_Char  c;
    389 
    390 
    391       if ( IS_PS_SPACE( *p ) )
    392         continue;
    393 
    394       if ( *p OP 0x80 )
    395         break;
    396 
    397       c = ft_char_table[*p & 0x7f];
    398 
    399       if ( (unsigned)c >= 16 )
    400         break;
    401 
    402       if ( r & 1 )
    403       {
    404         *buffer = (FT_Byte)(*buffer + c);
    405         buffer++;
    406       }
    407       else
    408         *buffer = (FT_Byte)(c << 4);
    409 
    410       r++;
    411     }
    412 
    413     *cursor = p;
    414 
    415     return ( r + 1 ) / 2;
    416 
    417 #endif /* 0 */
    418 
    419   }
    420 
    421 
    422   FT_LOCAL_DEF( FT_UInt )
    423   PS_Conv_EexecDecode( FT_Byte**   cursor,
    424                        FT_Byte*    limit,
    425                        FT_Byte*    buffer,
    426                        FT_Offset   n,
    427                        FT_UShort*  seed )
    428   {
    429     FT_Byte*  p;
    430     FT_UInt   r;
    431     FT_UInt   s = *seed;
    432 
    433 
    434 #if 1
    435 
    436     p = *cursor;
    437     if ( n > (FT_UInt)(limit - p) )
    438       n = (FT_UInt)(limit - p);
    439 
    440     for ( r = 0; r < n; r++ )
    441     {
    442       FT_UInt  val = p[r];
    443       FT_UInt  b   = ( val ^ ( s >> 8 ) );
    444 
    445 
    446       s         = ( (val + s)*52845U + 22719 ) & 0xFFFFU;
    447       buffer[r] = (FT_Byte) b;
    448     }
    449 
    450     *cursor = p + n;
    451     *seed   = (FT_UShort)s;
    452 
    453 #else /* 0 */
    454 
    455     for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
    456     {
    457       FT_Byte  b = (FT_Byte)( *p ^ ( s >> 8 ) );
    458 
    459 
    460       s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
    461       *buffer++ = b;
    462     }
    463     *cursor = p;
    464     *seed   = s;
    465 
    466 #endif /* 0 */
    467 
    468     return r;
    469   }
    470 
    471 
    472 /* END */
    473