/**************************************************************************** * * fttrigon.c * * FreeType trigonometric functions (body). * * Copyright (C) 2001-2023 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. * */ /************************************************************************** * * This is a fixed-point CORDIC implementation of trigonometric * functions as well as transformations between Cartesian and polar * coordinates. The angles are represented as 16.16 fixed-point values * in degrees, i.e., the angular resolution is 2^-16 degrees. Note that * only vectors longer than 2^16*180/pi (or at least 22 bits) on a * discrete Cartesian grid can have the same or better angular * resolution. Therefore, to maintain this precision, some functions * require an interim upscaling of the vectors, whereas others operate * with 24-bit long vectors directly. * */ #include <freetype/internal/ftobjs.h> #include <freetype/internal/ftcalc.h> #include <freetype/fttrigon.h> /* the Cordic shrink factor 0.858785336480436 * 2^32 */ #define FT_TRIG_SCALE … /* the highest bit in overflow-safe vector components, */ /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ #define FT_TRIG_SAFE_MSB … /* this table was generated for FT_PI = 180L << 16, i.e. degrees */ #define FT_TRIG_MAX_ITERS … static const FT_Angle ft_trig_arctan_table[] = …; #ifdef FT_INT64 /* multiply a given value by the CORDIC shrink factor */ static FT_Fixed ft_trig_downscale( FT_Fixed val ) { … } #else /* !FT_INT64 */ /* multiply a given value by the CORDIC shrink factor */ static FT_Fixed ft_trig_downscale( FT_Fixed val ) { FT_Int s = 1; FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; if ( val < 0 ) { val = -val; s = -1; } lo1 = (FT_UInt32)val & 0x0000FFFFU; hi1 = (FT_UInt32)val >> 16; lo2 = FT_TRIG_SCALE & 0x0000FFFFU; hi2 = FT_TRIG_SCALE >> 16; lo = lo1 * lo2; i1 = lo1 * hi2; i2 = lo2 * hi1; hi = hi1 * hi2; /* Check carry overflow of i1 + i2 */ i1 += i2; hi += (FT_UInt32)( i1 < i2 ) << 16; hi += i1 >> 16; i1 = i1 << 16; /* Check carry overflow of i1 + lo */ lo += i1; hi += ( lo < i1 ); /* 0x40000000 comes from regression analysis between true */ /* and CORDIC hypotenuse, so it minimizes the error */ /* Check carry overflow of lo + 0x40000000 */ lo += 0x40000000UL; hi += ( lo < 0x40000000UL ); val = (FT_Fixed)hi; return s < 0 ? -val : val; } #endif /* !FT_INT64 */ /* undefined and never called for zero vector */ static FT_Int ft_trig_prenorm( FT_Vector* vec ) { … } static void ft_trig_pseudo_rotate( FT_Vector* vec, FT_Angle theta ) { … } static void ft_trig_pseudo_polarize( FT_Vector* vec ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( FT_Fixed ) FT_Cos( FT_Angle angle ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( FT_Fixed ) FT_Sin( FT_Angle angle ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( FT_Fixed ) FT_Tan( FT_Angle angle ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( FT_Angle ) FT_Atan2( FT_Fixed dx, FT_Fixed dy ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( void ) FT_Vector_Unit( FT_Vector* vec, FT_Angle angle ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( void ) FT_Vector_Rotate( FT_Vector* vec, FT_Angle angle ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( FT_Fixed ) FT_Vector_Length( FT_Vector* vec ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( void ) FT_Vector_Polarize( FT_Vector* vec, FT_Fixed *length, FT_Angle *angle ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( void ) FT_Vector_From_Polar( FT_Vector* vec, FT_Fixed length, FT_Angle angle ) { … } /* documentation is in fttrigon.h */ FT_EXPORT_DEF( FT_Angle ) FT_Angle_Diff( FT_Angle angle1, FT_Angle angle2 ) { … } /* END */