[base] Reintroduce `FT_SqrtFixed`.

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.
This commit is contained in:
Alexei Podtelezhnikov 2023-09-19 22:26:32 -04:00
parent babe6af167
commit 95b0fe2a6d
2 changed files with 54 additions and 24 deletions

View File

@ -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 */

View File

@ -913,39 +913,72 @@
}
#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 */
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;
}
}
#endif /* 0 */
/* documentation is in ftcalc.h */