1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* fttrigon.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* FreeType trigonometric functions (body). */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Copyright 2001-2005, 2012-2013 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This is a fixed-point CORDIC implementation of trigonometric */ 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* functions as well as transformations between Cartesian and polar */ 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* coordinates. The angles are represented as 16.16 fixed-point values */ 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that */ 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* only vectors longer than 2^16*180/pi (or at least 22 bits) on a */ 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* discrete Cartesian grid can have the same or better angular */ 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* resolution. Therefore, to maintain this precision, some functions */ 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* require an interim upscaling of the vectors, whereas others operate */ 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* with 24-bit long vectors directly. */ 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h" 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftobjs.h" 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftcalc.h" 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/fttrigon.h" 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the Cordic shrink factor 0.858785336480436 * 2^32 */ 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRIG_SCALE 0xDBD95B16UL 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the highest bit in overflow-safe vector components, */ 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRIG_SAFE_MSB 29 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this table was generated for FT_PI = 180L << 16, i.e. degrees */ 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRIG_MAX_ITERS 23 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const FT_Fixed 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_arctan_table[] = 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 57L, 29L, 14L, 7L, 4L, 2L, 1L 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_LONG64 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* multiply a given value by the CORDIC shrink factor */ 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Fixed 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_downscale( FT_Fixed val ) 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed s; 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int64 v; 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov s = val; 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = FT_ABS( val ); 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL; 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Fixed)( v >> 32 ); 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ( s >= 0 ) ? val : -val; 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* !FT_LONG64 */ 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* multiply a given value by the CORDIC shrink factor */ 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Fixed 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_downscale( FT_Fixed val ) 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed s; 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3; 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov s = val; 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = FT_ABS( val ); 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v1 = (FT_UInt32)val >> 16; 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v2 = (FT_UInt32)( val & 0xFFFFL ); 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov k1 = (FT_UInt32)FT_TRIG_SCALE >> 16; /* constant */ 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov k2 = (FT_UInt32)( FT_TRIG_SCALE & 0xFFFFL ); /* constant */ 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hi = k1 * v1; 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lo1 = k1 * v2 + k2 * v1; /* can't overflow */ 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lo2 = ( k2 * v2 ) >> 16; 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lo3 = FT_MAX( lo1, lo2 ); 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lo1 += lo2; 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hi += lo1 >> 16; 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( lo1 < lo3 ) 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov hi += (FT_UInt32)0x10000UL; 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov val = (FT_Fixed)hi; 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ( s >= 0 ) ? val : -val; 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* !FT_LONG64 */ 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static FT_Int 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_prenorm( FT_Vector* vec ) 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Pos x, y; 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int shift; 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = vec->x; 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = vec->y; 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) ); 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( shift <= FT_TRIG_SAFE_MSB ) 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = FT_TRIG_SAFE_MSB - shift; 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = (FT_Pos)( (FT_ULong)x << shift ); 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = (FT_Pos)( (FT_ULong)y << shift ); 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift -= FT_TRIG_SAFE_MSB; 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = x >> shift; 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = y >> shift; 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = -shift; 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return shift; 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_rotate( FT_Vector* vec, 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle theta ) 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i; 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed x, y, xtemp, b; 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Fixed *arctanptr; 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = vec->x; 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = vec->y; 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Rotate inside [-PI/4,PI/4] sector */ 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( theta < -FT_ANGLE_PI4 ) 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = y; 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = -x; 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta += FT_ANGLE_PI2; 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( theta > FT_ANGLE_PI4 ) 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = -y; 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = x; 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta -= FT_ANGLE_PI2; 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arctanptr = ft_trig_arctan_table; 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Pseudorotations, with right shifts */ 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ ) 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( theta < 0 ) 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = x + ( ( y + b ) >> i ); 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = y - ( ( x + b ) >> i ); 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta += *arctanptr++; 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = x - ( ( y + b ) >> i ); 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = y + ( ( x + b ) >> i ); 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta -= *arctanptr++; 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = x; 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = y; 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_polarize( FT_Vector* vec ) 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle theta; 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int i; 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed x, y, xtemp, b; 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Fixed *arctanptr; 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = vec->x; 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = vec->y; 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Get the vector into [-PI/4,PI/4] sector */ 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > x ) 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > -x ) 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta = FT_ANGLE_PI2; 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = y; 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = -x; 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta = y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI; 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = -x; 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = -y; 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < -x ) 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta = -FT_ANGLE_PI2; 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = -y; 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = x; 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta = 0; 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arctanptr = ft_trig_arctan_table; 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Pseudorotations, with right shifts */ 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ ) 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > 0 ) 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = x + ( ( y + b ) >> i ); 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = y - ( ( x + b ) >> i ); 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta += *arctanptr++; 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov xtemp = x - ( ( y + b ) >> i ); 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = y + ( ( x + b ) >> i ); 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = xtemp; 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta -= *arctanptr++; 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* round theta */ 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( theta >= 0 ) 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta = FT_PAD_ROUND( theta, 32 ); 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov theta = -FT_PAD_ROUND( -theta, 32 ); 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = x; 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = theta; 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Fixed ) 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Cos( FT_Angle angle ) 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v; 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.x = FT_TRIG_SCALE >> 8; 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.y = 0; 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_rotate( &v, angle ); 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ( v.x + 0x80L ) >> 8; 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Fixed ) 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Sin( FT_Angle angle ) 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_Cos( FT_ANGLE_PI2 - angle ); 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Fixed ) 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Tan( FT_Angle angle ) 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v; 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.x = FT_TRIG_SCALE >> 8; 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.y = 0; 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_rotate( &v, angle ); 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_DivFix( v.y, v.x ); 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Angle ) 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Atan2( FT_Fixed dx, 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed dy ) 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v; 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dx == 0 && dy == 0 ) 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.x = dx; 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.y = dy; 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_prenorm( &v ); 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_polarize( &v ); 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return v.y; 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Unit( FT_Vector* vec, 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle angle ) 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = FT_TRIG_SCALE >> 8; 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = 0; 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_rotate( vec, angle ); 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = ( vec->x + 0x80L ) >> 8; 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = ( vec->y + 0x80L ) >> 8; 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* these macros return 0 for positive numbers, 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov and -1 for negative ones */ 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) ) 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) ) 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_INT32( x ) ( (x) >> 31 ) 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_INT16( x ) ( (x) >> 15 ) 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Rotate( FT_Vector* vec, 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle angle ) 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int shift; 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v; 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.x = vec->x; 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.y = vec->y; 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( angle && ( v.x != 0 || v.y != 0 ) ) 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = ft_trig_prenorm( &v ); 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_rotate( &v, angle ); 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.x = ft_trig_downscale( v.x ); 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.y = ft_trig_downscale( v.y ); 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( shift > 0 ) 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int32 half = (FT_Int32)1L << ( shift - 1 ); 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift; 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift; 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = -shift; 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = (FT_Pos)( (FT_ULong)v.x << shift ); 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = (FT_Pos)( (FT_ULong)v.y << shift ); 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Fixed ) 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Length( FT_Vector* vec ) 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int shift; 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v; 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v = *vec; 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* handle trivial cases */ 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( v.x == 0 ) 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_ABS( v.y ); 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( v.y == 0 ) 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_ABS( v.x ); 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* general case */ 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = ft_trig_prenorm( &v ); 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_polarize( &v ); 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.x = ft_trig_downscale( v.x ); 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( shift > 0 ) 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift; 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return (FT_Fixed)( (FT_UInt32)v.x << -shift ); 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Polarize( FT_Vector* vec, 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed *length, 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle *angle ) 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Int shift; 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v; 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v = *vec; 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( v.x == 0 && v.y == 0 ) 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = ft_trig_prenorm( &v ); 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_trig_pseudo_polarize( &v ); 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v.x = ft_trig_downscale( v.x ); 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *length = ( shift >= 0 ) ? ( v.x >> shift ) 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : (FT_Fixed)( (FT_UInt32)v.x << -shift ); 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *angle = v.y; 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( void ) 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_From_Polar( FT_Vector* vec, 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Fixed length, 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle angle ) 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->x = length; 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec->y = 0; 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector_Rotate( vec, angle ); 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* documentation is in fttrigon.h */ 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_EXPORT_DEF( FT_Angle ) 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle_Diff( FT_Angle angle1, 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle angle2 ) 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Angle delta = angle2 - angle1; 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta %= FT_ANGLE_2PI; 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( delta < 0 ) 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta += FT_ANGLE_2PI; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( delta > FT_ANGLE_PI ) 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta -= FT_ANGLE_2PI; 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return delta; 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 493