Skip to content
Commits on Source (2)
  • Alexei Podtelezhnikov's avatar
    [base] Reintroduce `FT_SqrtFixed`. · 95b0fe2a
    Alexei Podtelezhnikov authored
    The general square root calculations are not necessary in FreeType.
    For vector normalization or length, FreeType uses special functions.
    It is, however, required in the legacy CFF specifications.
    
    * src/base/ftcalc.c (FT_SqrtFixed): New function that uses either
    Babylonian or bit-wise algorithm, whichever is faster for the given
    situation.
    * include/freetype/internal/ftcalc.h (FT_SqrtFixed): Declare it.
    95b0fe2a
  • Alexei Podtelezhnikov's avatar
    [psaux] Use `FT_SqrtFixed`. · c4073d82
    Alexei Podtelezhnikov authored
    * src/psaux/cffdecode.c <cff_op_sqrt>: Call `FT_SqrtFixed`.
    * src/psaux/psintrp.c <cf2_escSQRT>: Ditto.
    c4073d82
......@@ -489,8 +489,6 @@ FT_BEGIN_HEADER
FT_Fixed y );
#if 0
/**************************************************************************
*
* @function:
......@@ -507,13 +505,12 @@ FT_BEGIN_HEADER
* The result of 'sqrt(x)'.
*
* @note:
* This function is not very fast.
* This function is slow and should be avoided. Consider `FT_Hypot` or
* `FT_Vector_NormLen' instead.
*/
FT_BASE( FT_UInt32 )
FT_SqrtFixed( FT_UInt32 x );
#endif /* 0 */
#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) * 64 ) /* << 6 */
#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) * 16384 ) /* << 14 */
......
......@@ -913,38 +913,71 @@
}
#if 0
/* documentation is in ftcalc.h */
/* Algorithm and code by Christophe Meessen (1993) */
/* with overflow fixed. */
FT_BASE_DEF( FT_UInt32 )
FT_SqrtFixed( FT_UInt32 v )
{
FT_UInt32 r = v >> 1;
FT_UInt32 q = ( v & 1 ) << 15;
FT_UInt32 b = 0x20000000;
FT_UInt32 t;
if ( v == 0 )
return 0;
#ifndef FT_INT64
do
/* Algorithm by Christophe Meessen (1993) with overflow fixed and */
/* rounding added. Any unsigned fixed 16.16 argument is acceptable. */
/* However, this algorithm is slower than the Babylonian method with */
/* a good initial guess. We only use it for large 32-bit values when */
/* 64-bit computations are not desirable. */
else if ( v > 0x10000U )
{
t = q + b;
if ( r >= t )
FT_UInt32 r = v >> 1;
FT_UInt32 q = ( v & 1 ) << 15;
FT_UInt32 b = 0x20000000;
FT_UInt32 t;
do
{
r -= t;
q = t + b; /* equivalent to q += 2*b */
t = q + b;
if ( r >= t )
{
r -= t;
q = t + b; /* equivalent to q += 2*b */
}
r <<= 1;
b >>= 1;
}
r <<= 1;
b >>= 1;
while ( b > 0x10 ); /* exactly 25 cycles */
return ( q + 0x40 ) >> 7;
}
while ( b > 0x20 );
else
{
FT_UInt32 r = ( v << 16 ) - 1;
return q >> 7;
}
#else /* FT_INT64 */
#endif /* 0 */
else
{
FT_UInt64 r = ( (FT_UInt64)v << 16 ) - 1;
#endif /* FT_INT64 */
FT_UInt32 q = 1 << ( ( 17 + FT_MSB( v ) ) >> 1 );
FT_UInt32 t;
/* Babylonian method with rounded-up division */
do
{
t = q;
q = ( t + (FT_UInt32)( r / t ) + 1 ) >> 1;
}
while ( q != t ); /* less than 6 cycles */
return q;
}
}
/* documentation is in ftcalc.h */
......
......@@ -1753,22 +1753,9 @@
/* without upper limit the loop below might not finish */
if ( args[0] > 0x7FFFFFFFL )
args[0] = 0xB504F3L; /* sqrt( 32768.0 ) */
args[0] = 0xB504F4L; /* sqrt( 32768.0044 ) */
else if ( args[0] > 0 )
{
FT_Fixed root = 1 << ( ( 17 + FT_MSB( args[0] ) ) >> 1 );
FT_Fixed new_root;
for (;;)
{
new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
if ( new_root == root )
break;
root = new_root;
}
args[0] = new_root;
}
args[0] = (FT_Fixed)FT_SqrtFixed( args[0] );
else
args[0] = 0;
args++;
......
......@@ -2276,22 +2276,7 @@
arg = cf2_stack_popFixed( opStack );
if ( arg > 0 )
{
/* initial guess based on the most significant bit */
FT_Fixed root = 1 << ( ( 17 + FT_MSB( arg ) ) >> 1 );
FT_Fixed new_root;
/* Babylonian method */
for (;;)
{
new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
if ( new_root == root )
break;
root = new_root;
}
arg = new_root;
}
arg = (CF2_F16Dot16)FT_SqrtFixed( arg );
else
arg = 0;
......