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