/***************************************************************************/ /* */ /* psconv.c */ /* */ /* Some convenience conversions (body). */ /* */ /* Copyright 2006, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ /* modified, and distributed under the terms of the FreeType project */ /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ /* this file you indicate that you have read the license and */ /* understand and accept it fully. */ /* */ /***************************************************************************/ #include #include FT_INTERNAL_POSTSCRIPT_AUX_H #include "psconv.h" #include "psauxerr.h" /* The following array is used by various functions to quickly convert */ /* digits (both decimal and non-decimal) into numbers. */ #if 'A' == 65 /* ASCII */ static const FT_Char ft_char_table[128] = { /* 0x00 */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, }; /* no character >= 0x80 can represent a valid number */ #define OP >= #endif /* 'A' == 65 */ #if 'A' == 193 /* EBCDIC */ static const FT_Char ft_char_table[128] = { /* 0x80 */ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1, -1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, -1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, }; /* no character < 0x80 can represent a valid number */ #define OP < #endif /* 'A' == 193 */ FT_LOCAL_DEF( FT_Int ) PS_Conv_Strtol( FT_Byte** cursor, FT_Byte* limit, FT_Int base ) { FT_Byte* p = *cursor; FT_Int num = 0; FT_Bool sign = 0; if ( p == limit || base < 2 || base > 36 ) return 0; if ( *p == '-' || *p == '+' ) { sign = FT_BOOL( *p == '-' ); p++; if ( p == limit ) return 0; } for ( ; p < limit; p++ ) { FT_Char c; if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) break; c = ft_char_table[*p & 0x7f]; if ( c < 0 || c >= base ) break; num = num * base + c; } if ( sign ) num = -num; *cursor = p; return num; } FT_LOCAL_DEF( FT_Int ) PS_Conv_ToInt( FT_Byte** cursor, FT_Byte* limit ) { FT_Byte* p; FT_Int num; num = PS_Conv_Strtol( cursor, limit, 10 ); p = *cursor; if ( p < limit && *p == '#' ) { *cursor = p + 1; return PS_Conv_Strtol( cursor, limit, num ); } else return num; } FT_LOCAL_DEF( FT_Fixed ) PS_Conv_ToFixed( FT_Byte** cursor, FT_Byte* limit, FT_Int power_ten ) { FT_Byte* p = *cursor; FT_Fixed integral; FT_Long decimal = 0, divider = 1; FT_Bool sign = 0; if ( p == limit ) return 0; if ( *p == '-' || *p == '+' ) { sign = FT_BOOL( *p == '-' ); p++; if ( p == limit ) return 0; } if ( *p != '.' ) integral = PS_Conv_ToInt( &p, limit ) << 16; else integral = 0; /* read the decimal part */ if ( p < limit && *p == '.' ) { p++; for ( ; p < limit; p++ ) { FT_Char c; if ( IS_PS_SPACE( *p ) || *p OP 0x80 ) break; c = ft_char_table[*p & 0x7f]; if ( c < 0 || c >= 10 ) break; if ( !integral && power_ten > 0 ) { power_ten--; decimal = decimal * 10 + c; } else { if ( divider < 10000000L ) { decimal = decimal * 10 + c; divider *= 10; } } } } /* read exponent, if any */ if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) ) { p++; power_ten += PS_Conv_ToInt( &p, limit ); } while ( power_ten > 0 ) { integral *= 10; decimal *= 10; power_ten--; } while ( power_ten < 0 ) { integral /= 10; divider *= 10; power_ten++; } if ( decimal ) integral += FT_DivFix( decimal, divider ); if ( sign ) integral = -integral; *cursor = p; return integral; } #if 0 FT_LOCAL_DEF( FT_UInt ) PS_Conv_StringDecode( FT_Byte** cursor, FT_Byte* limit, FT_Byte* buffer, FT_Offset n ) { FT_Byte* p; FT_UInt r = 0; for ( p = *cursor; r < n && p < limit; p++ ) { FT_Byte b; if ( *p != '\\' ) { buffer[r++] = *p; continue; } p++; switch ( *p ) { case 'n': b = '\n'; break; case 'r': b = '\r'; break; case 't': b = '\t'; break; case 'b': b = '\b'; break; case 'f': b = '\f'; break; case '\r': p++; if ( *p != '\n' ) { b = *p; break; } /* no break */ case '\n': continue; break; default: if ( IS_PS_DIGIT( *p ) ) { b = *p - '0'; p++; if ( IS_PS_DIGIT( *p ) ) { b = b * 8 + *p - '0'; p++; if ( IS_PS_DIGIT( *p ) ) b = b * 8 + *p - '0'; else { buffer[r++] = b; b = *p; } } else { buffer[r++] = b; b = *p; } } else b = *p; break; } buffer[r++] = b; } *cursor = p; return r; } #endif /* 0 */ FT_LOCAL_DEF( FT_UInt ) PS_Conv_ASCIIHexDecode( FT_Byte** cursor, FT_Byte* limit, FT_Byte* buffer, FT_Offset n ) { FT_Byte* p; FT_UInt r = 0; FT_UInt w = 0; FT_UInt pad = 0x01; n *= 2; #if 1 p = *cursor; if ( n > (FT_UInt)( limit - p ) ) n = (FT_UInt)( limit - p ); /* we try to process two nibbles at a time to be as fast as possible */ for ( ; r < n; r++ ) { FT_UInt c = p[r]; if ( IS_PS_SPACE( c ) ) continue; if ( c OP 0x80 ) break; c = ft_char_table[c & 0x7F]; if ( (unsigned)c >= 16 ) break; pad = ( pad << 4 ) | c; if ( pad & 0x100 ) { buffer[w++] = (FT_Byte)pad; pad = 0x01; } } if ( pad != 0x01 ) buffer[w++] = (FT_Byte)( pad << 4 ); *cursor = p + r; return w; #else /* 0 */ for ( r = 0; r < n; r++ ) { FT_Char c; if ( IS_PS_SPACE( *p ) ) continue; if ( *p OP 0x80 ) break; c = ft_char_table[*p & 0x7f]; if ( (unsigned)c >= 16 ) break; if ( r & 1 ) { *buffer = (FT_Byte)(*buffer + c); buffer++; } else *buffer = (FT_Byte)(c << 4); r++; } *cursor = p; return ( r + 1 ) / 2; #endif /* 0 */ } FT_LOCAL_DEF( FT_UInt ) PS_Conv_EexecDecode( FT_Byte** cursor, FT_Byte* limit, FT_Byte* buffer, FT_Offset n, FT_UShort* seed ) { FT_Byte* p; FT_UInt r; FT_UInt s = *seed; #if 1 p = *cursor; if ( n > (FT_UInt)(limit - p) ) n = (FT_UInt)(limit - p); for ( r = 0; r < n; r++ ) { FT_UInt val = p[r]; FT_UInt b = ( val ^ ( s >> 8 ) ); s = ( (val + s)*52845U + 22719 ) & 0xFFFFU; buffer[r] = (FT_Byte) b; } *cursor = p + n; *seed = (FT_UShort)s; #else /* 0 */ for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ ) { FT_Byte b = (FT_Byte)( *p ^ ( s >> 8 ) ); s = (FT_UShort)( ( *p + s ) * 52845U + 22719 ); *buffer++ = b; } *cursor = p; *seed = s; #endif /* 0 */ return r; } /* END */