diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c index 544ca0e5e..3440e427f 100644 --- a/src/base/ftcalc.c +++ b/src/base/ftcalc.c @@ -35,6 +35,25 @@ #include /* for ABS() */ +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + static const FT_Long ft_square_roots[63] = + { + 1, 1, 2, 3, 4, 5, 8, 11, + 16, 22, 32, 45, 64, 90, 128, 181, + 256, 362, 512, 724, 1024, 1448, 2048, 2896, + 4096, 5892, 8192, 11585, 16384, 23170, 32768, 46340, + + 65536, 92681, 131072, 185363, 262144, 370727, + 524288, 741455, 1048576, 1482910, 2097152, 2965820, + 4194304, 5931641, 8388608, 11863283, 16777216, 23726566, + + 33554432, 47453132, 67108864, 94906265, + 134217728, 189812531, 268435456, 379625062, + 536870912, 759250125, 1073741824, 1518500250, + 2147483647 + }; +#else /*************************************************************************/ /* */ /* */ @@ -50,7 +69,7 @@ /* */ /* The result of `sqrt(x)'. */ /* */ - BASE_FUNC + EXPORT_FUNC FT_Int32 FT_Sqrt32( FT_Int32 x ) { FT_ULong val, root, newroot, mask; @@ -76,7 +95,7 @@ return root; } - +#endif /* OLD_CALCS */ #ifdef LONG64 @@ -211,6 +230,60 @@ } +#ifdef FT_CONFIG_OPTION_OLD_CALCS + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* Computes the square root of a 64-bits value ! Yeah, that sounds */ + /* stupid, but it's needed to obtain maximum accuracy in the */ + /* TrueType bytecode interpreter.. */ + /* */ + /* */ + /* l :: 64-bits integer */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + + static + int ft_order64( FT_Int64 z ) + { + int j = 0; + + while ( z ) + { + z = (unsigned INT64)z >> 1; + j++; + } + return j - 1; + } + + + EXPORT_FUNC + FT_Int32 FT_Sqrt64( FT_Int64 l ) + { + FT_Int64 r, s; + + if ( l <= 0 ) return 0; + if ( l == 1 ) return 1; + + r = ft_square_roots[ft_order64( l )]; + + do + { + s = r; + r = ( r + l/r ) >> 1; + } + while ( r > s || r*r > l ); + + return r; + } +#endif + + #else /* LONG64 */ @@ -437,7 +510,7 @@ /* */ /* Will be wrapped by the ADD_64() macro. */ /* */ - BASE_FUNC + EXPORT_FUNC void FT_Add64( FT_Int64* x, FT_Int64* y, FT_Int64* z ) @@ -470,7 +543,7 @@ /* */ /* Will be wrapped by the MUL_64() macro. */ /* */ - BASE_FUNC + EXPORT_FUNC void FT_MulTo64( FT_Int32 x, FT_Int32 y, FT_Int64* z ) @@ -536,7 +609,7 @@ /* */ /* Will be wrapped by the DIV_64() macro. */ /* */ - BASE_FUNC + EXPORT_FUNC FT_Int32 FT_Div64by32( FT_Int64* x, FT_Int32 y ) { @@ -585,6 +658,88 @@ } +#ifdef FT_CONFIG_OPTION_OLD_CALCS + + static + void FT_Sub64( FT_Int64* x, FT_Int64* y, FT_Int64* z ) + { + register FT_Word32 lo, hi; + + + lo = x->lo - y->lo; + hi = x->hi - y->hi - ( (FT_Int32)lo < 0 ); + + z->lo = lo; + z->hi = hi; + } + + /*************************************************************************/ + /* */ + /* */ + /* FT_Sqrt64 */ + /* */ + /* */ + /* Computes the square root of a 64-bits value ! Yeah, that sounds */ + /* stupid, but it's needed to obtain maximum accuracy in the */ + /* TrueType bytecode interpreter.. */ + /* */ + /* */ + /* z :: pointer to 64-bits integer */ + /* */ + /* */ + /* The 32-bit square-root. */ + /* */ + + static + int ft_order64( FT_Int64* z ) + { + FT_Word32 i; + int j; + + i = z->lo; + j = 0; + if ( z->hi ) + { + i = z->hi; + j = 32; + } + + while ( i > 0 ) + { + i >>= 1; + j++; + } + return j-1; + } + + EXPORT_FUNC + FT_Int32 FT_Sqrt64( FT_Int64* l ) + { + FT_Int64 l2; + FT_Int32 r, s; + + + if ( (FT_Int32)l->hi < 0 || + (l->hi == 0 && l->lo == 0) ) return 0; + + s = ft_order64( l ); + if ( s == 0 ) return 1; + + r = ft_square_roots[s]; + do + { + s = r; + r = ( r + FT_Div64by32(l,r) ) >> 1; + FT_MulTo64( r, r, &l2 ); + FT_Sub64 ( l, &l2, &l2 ); + } + while ( r > s || (FT_Int32)l2.hi < 0 ); + + return r; + } + +#endif /* FT_CONFIG_OPTION_OLD_CALCS */ + #endif /* LONG64 */ diff --git a/src/base/ftcalc.h b/src/base/ftcalc.h index 020b2189d..cbc2e70d7 100644 --- a/src/base/ftcalc.h +++ b/src/base/ftcalc.h @@ -37,6 +37,15 @@ #define DIV_64( x, y ) ( (x) / (y) ) +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( z ) + + EXPORT_DEF + FT_Int32 FT_Sqrt64( FT_Int64 x ); + +#endif /* OLD_CALCS */ + #else /* LONG64 */ typedef struct FT_Int64_ @@ -50,21 +59,34 @@ #define MUL_64( x, y, z ) FT_MulTo64( x, y, &z ) #define DIV_64( x, y ) FT_Div64by32( &x, y ) - BASE_DEF + EXPORT_DEF void FT_Add64 ( FT_Int64* x, FT_Int64* y, FT_Int64* z ); - BASE_DEF + + EXPORT_DEF void FT_MulTo64 ( FT_Int32 x, FT_Int32 y, FT_Int64* z ); - BASE_DEF + + EXPORT_DEF FT_Int32 FT_Div64by32( FT_Int64* x, FT_Int32 y ); +#ifdef FT_CONFIG_OPTION_OLD_CALCS + +#define SQRT_64( z ) FT_Sqrt64( &z ) + + EXPORT_DEF + FT_Int32 FT_Sqrt64( FT_Int64* x ); + +#endif /* OLD_CALC */ #endif /* LONG64 */ +#ifndef FT_CONFIG_OPTION_OLD_CALCS + #define SQRT_32( x ) FT_Sqrt32( x ) BASE_DEF FT_Int32 FT_Sqrt32( FT_Int32 l ); +#endif /*************************************************************************/ /* */