| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | /***************************************************************************/ | 
					
						
							|  |  |  | /*                                                                         */ | 
					
						
							|  |  |  | /*  fttrigon.c                                                             */ | 
					
						
							|  |  |  | /*                                                                         */ | 
					
						
							|  |  |  | /*    FreeType trigonometric functions (body).                             */ | 
					
						
							|  |  |  | /*                                                                         */ | 
					
						
							|  |  |  | /*  Copyright 2001-2005, 2012-2013 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.                                        */ | 
					
						
							|  |  |  | /*                                                                         */ | 
					
						
							|  |  |  | /***************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #include "plutovg-ft-math.h"
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined(_MSC_VER)
 | 
					
						
							|  |  |  | #include <intrin.h>
 | 
					
						
							|  |  |  | static unsigned int __inline clz(unsigned int x) { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     unsigned long r = 0; | 
					
						
							|  |  |  |     if (x != 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         _BitScanReverse(&r, x); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return  r; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_MSB(x)  (clz(x))
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | #elif defined(__GNUC__)
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_MSB(x)  (31 - __builtin_clz(x))
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | static unsigned int __inline clz(unsigned int x) { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     int c = 31; | 
					
						
							|  |  |  |     x &= ~x + 1; | 
					
						
							|  |  |  |     if (n & 0x0000FFFF) c -= 16; | 
					
						
							|  |  |  |     if (n & 0x00FF00FF) c -= 8; | 
					
						
							|  |  |  |     if (n & 0x0F0F0F0F) c -= 4; | 
					
						
							|  |  |  |     if (n & 0x33333333) c -= 2; | 
					
						
							|  |  |  |     if (n & 0x55555555) c -= 1; | 
					
						
							|  |  |  |     return c; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_MSB(x)  (clz(x))
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_PAD_FLOOR(x, n) ((x) & ~((n)-1))
 | 
					
						
							|  |  |  | #define PVG_FT_PAD_ROUND(x, n) PVG_FT_PAD_FLOOR((x) + ((n) / 2), n)
 | 
					
						
							|  |  |  | #define PVG_FT_PAD_CEIL(x, n) PVG_FT_PAD_FLOOR((x) + ((n)-1), n)
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_BEGIN_STMNT do {
 | 
					
						
							|  |  |  | #define PVG_FT_END_STMNT } while (0)
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* transfer sign leaving a positive number */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_MOVE_SIGN(x, s) \
 | 
					
						
							|  |  |  |     PVG_FT_BEGIN_STMNT         \ | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     if (x < 0) {              \ | 
					
						
							|  |  |  |         x = -x;               \ | 
					
						
							|  |  |  |         s = -s;               \ | 
					
						
							|  |  |  |     }                         \ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_END_STMNT | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Long PVG_FT_MulFix(PVG_FT_Long a, PVG_FT_Long b) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Int  s = 1; | 
					
						
							|  |  |  |     PVG_FT_Long c; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_MOVE_SIGN(a, s); | 
					
						
							|  |  |  |     PVG_FT_MOVE_SIGN(b, s); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     c = (PVG_FT_Long)(((PVG_FT_Int64)a * b + 0x8000L) >> 16); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return (s > 0) ? c : -c; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Long PVG_FT_MulDiv(PVG_FT_Long a, PVG_FT_Long b, PVG_FT_Long c) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Int  s = 1; | 
					
						
							|  |  |  |     PVG_FT_Long d; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_MOVE_SIGN(a, s); | 
					
						
							|  |  |  |     PVG_FT_MOVE_SIGN(b, s); | 
					
						
							|  |  |  |     PVG_FT_MOVE_SIGN(c, s); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     d = (PVG_FT_Long)(c > 0 ? ((PVG_FT_Int64)a * b + (c >> 1)) / c : 0x7FFFFFFFL); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return (s > 0) ? d : -d; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Long PVG_FT_DivFix(PVG_FT_Long a, PVG_FT_Long b) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Int  s = 1; | 
					
						
							|  |  |  |     PVG_FT_Long q; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_MOVE_SIGN(a, s); | 
					
						
							|  |  |  |     PVG_FT_MOVE_SIGN(b, s); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     q = (PVG_FT_Long)(b > 0 ? (((PVG_FT_UInt64)a << 16) + (b >> 1)) / b | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |                            : 0x7FFFFFFFL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (s < 0 ? -q : q); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* 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.                                    */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* the Cordic shrink factor 0.858785336480436 * 2^32 */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_TRIG_SCALE 0xDBD95B16UL
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* the highest bit in overflow-safe vector components, */ | 
					
						
							|  |  |  | /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30         */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | #define PVG_FT_TRIG_SAFE_MSB 29
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | /* this table was generated for PVG_FT_PI = 180L << 16, i.e. degrees */ | 
					
						
							|  |  |  | #define PVG_FT_TRIG_MAX_ITERS 23
 | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | static const PVG_FT_Fixed ft_trig_arctan_table[] = { | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, 14668L, | 
					
						
							|  |  |  |     7334L,    3667L,   1833L,   917L,    458L,    229L,   115L,   57L, | 
					
						
							|  |  |  |     29L,      14L,     7L,      4L,      2L,      1L}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* multiply a given value by the CORDIC shrink factor */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | static PVG_FT_Fixed ft_trig_downscale(PVG_FT_Fixed val) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Fixed s; | 
					
						
							|  |  |  |     PVG_FT_Int64 v; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     s = val; | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     val = PVG_FT_ABS(val); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     v = (val * (PVG_FT_Int64)PVG_FT_TRIG_SCALE) + 0x100000000UL; | 
					
						
							|  |  |  |     val = (PVG_FT_Fixed)(v >> 32); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return (s >= 0) ? val : -val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* undefined and never called for zero vector */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | static PVG_FT_Int ft_trig_prenorm(PVG_FT_Vector* vec) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Pos x, y; | 
					
						
							|  |  |  |     PVG_FT_Int shift; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     x = vec->x; | 
					
						
							|  |  |  |     y = vec->y; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     shift = PVG_FT_MSB(PVG_FT_ABS(x) | PVG_FT_ABS(y)); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     if (shift <= PVG_FT_TRIG_SAFE_MSB) { | 
					
						
							|  |  |  |         shift = PVG_FT_TRIG_SAFE_MSB - shift; | 
					
						
							|  |  |  |         vec->x = (PVG_FT_Pos)((PVG_FT_ULong)x << shift); | 
					
						
							|  |  |  |         vec->y = (PVG_FT_Pos)((PVG_FT_ULong)y << shift); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |         shift -= PVG_FT_TRIG_SAFE_MSB; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |         vec->x = x >> shift; | 
					
						
							|  |  |  |         vec->y = y >> shift; | 
					
						
							|  |  |  |         shift = -shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return shift; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | static void ft_trig_pseudo_rotate(PVG_FT_Vector* vec, PVG_FT_Angle theta) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Int          i; | 
					
						
							|  |  |  |     PVG_FT_Fixed        x, y, xtemp, b; | 
					
						
							|  |  |  |     const PVG_FT_Fixed* arctanptr; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     x = vec->x; | 
					
						
							|  |  |  |     y = vec->y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Rotate inside [-PI/4,PI/4] sector */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     while (theta < -PVG_FT_ANGLE_PI4) { | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |         xtemp = y; | 
					
						
							|  |  |  |         y = -x; | 
					
						
							|  |  |  |         x = xtemp; | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |         theta += PVG_FT_ANGLE_PI2; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     while (theta > PVG_FT_ANGLE_PI4) { | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |         xtemp = -y; | 
					
						
							|  |  |  |         y = x; | 
					
						
							|  |  |  |         x = xtemp; | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |         theta -= PVG_FT_ANGLE_PI2; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     arctanptr = ft_trig_arctan_table; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Pseudorotations, with right shifts */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     for (i = 1, b = 1; i < PVG_FT_TRIG_MAX_ITERS; b <<= 1, i++) { | 
					
						
							|  |  |  |         PVG_FT_Fixed v1 = ((y + b) >> i); | 
					
						
							|  |  |  |         PVG_FT_Fixed v2 = ((x + b) >> i); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |         if (theta < 0) { | 
					
						
							|  |  |  |             xtemp = x + v1; | 
					
						
							|  |  |  |             y = y - v2; | 
					
						
							|  |  |  |             x = xtemp; | 
					
						
							|  |  |  |             theta += *arctanptr++; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             xtemp = x - v1; | 
					
						
							|  |  |  |             y = y + v2; | 
					
						
							|  |  |  |             x = xtemp; | 
					
						
							|  |  |  |             theta -= *arctanptr++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vec->x = x; | 
					
						
							|  |  |  |     vec->y = y; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | static void ft_trig_pseudo_polarize(PVG_FT_Vector* vec) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Angle        theta; | 
					
						
							|  |  |  |     PVG_FT_Int          i; | 
					
						
							|  |  |  |     PVG_FT_Fixed        x, y, xtemp, b; | 
					
						
							|  |  |  |     const PVG_FT_Fixed* arctanptr; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     x = vec->x; | 
					
						
							|  |  |  |     y = vec->y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Get the vector into [-PI/4,PI/4] sector */ | 
					
						
							|  |  |  |     if (y > x) { | 
					
						
							|  |  |  |         if (y > -x) { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |             theta = PVG_FT_ANGLE_PI2; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |             xtemp = y; | 
					
						
							|  |  |  |             y = -x; | 
					
						
							|  |  |  |             x = xtemp; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |             theta = y > 0 ? PVG_FT_ANGLE_PI : -PVG_FT_ANGLE_PI; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |             x = -x; | 
					
						
							|  |  |  |             y = -y; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         if (y < -x) { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |             theta = -PVG_FT_ANGLE_PI2; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |             xtemp = -y; | 
					
						
							|  |  |  |             y = x; | 
					
						
							|  |  |  |             x = xtemp; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             theta = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     arctanptr = ft_trig_arctan_table; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Pseudorotations, with right shifts */ | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     for (i = 1, b = 1; i < PVG_FT_TRIG_MAX_ITERS; b <<= 1, i++) { | 
					
						
							|  |  |  |         PVG_FT_Fixed v1 = ((y + b) >> i); | 
					
						
							|  |  |  |         PVG_FT_Fixed v2 = ((x + b) >> i); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |         if (y > 0) { | 
					
						
							|  |  |  |             xtemp = x + v1; | 
					
						
							|  |  |  |             y = y - v2; | 
					
						
							|  |  |  |             x = xtemp; | 
					
						
							|  |  |  |             theta += *arctanptr++; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             xtemp = x - v1; | 
					
						
							|  |  |  |             y = y + v2; | 
					
						
							|  |  |  |             x = xtemp; | 
					
						
							|  |  |  |             theta -= *arctanptr++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* round theta */ | 
					
						
							|  |  |  |     if (theta >= 0) | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |         theta = PVG_FT_PAD_ROUND(theta, 32); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |         theta = -PVG_FT_PAD_ROUND(-theta, 32); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     vec->x = x; | 
					
						
							|  |  |  |     vec->y = theta; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Fixed PVG_FT_Cos(PVG_FT_Angle angle) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Vector v; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     v.x = PVG_FT_TRIG_SCALE >> 8; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     v.y = 0; | 
					
						
							|  |  |  |     ft_trig_pseudo_rotate(&v, angle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (v.x + 0x80L) >> 8; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Fixed PVG_FT_Sin(PVG_FT_Angle angle) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     return PVG_FT_Cos(PVG_FT_ANGLE_PI2 - angle); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Fixed PVG_FT_Tan(PVG_FT_Angle angle) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Vector v; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     v.x = PVG_FT_TRIG_SCALE >> 8; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     v.y = 0; | 
					
						
							|  |  |  |     ft_trig_pseudo_rotate(&v, angle); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     return PVG_FT_DivFix(v.y, v.x); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Angle PVG_FT_Atan2(PVG_FT_Fixed dx, PVG_FT_Fixed dy) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Vector v; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (dx == 0 && dy == 0) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     v.x = dx; | 
					
						
							|  |  |  |     v.y = dy; | 
					
						
							|  |  |  |     ft_trig_prenorm(&v); | 
					
						
							|  |  |  |     ft_trig_pseudo_polarize(&v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return v.y; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | void PVG_FT_Vector_Unit(PVG_FT_Vector* vec, PVG_FT_Angle angle) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     vec->x = PVG_FT_TRIG_SCALE >> 8; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     vec->y = 0; | 
					
						
							|  |  |  |     ft_trig_pseudo_rotate(vec, angle); | 
					
						
							|  |  |  |     vec->x = (vec->x + 0x80L) >> 8; | 
					
						
							|  |  |  |     vec->y = (vec->y + 0x80L) >> 8; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | void PVG_FT_Vector_Rotate(PVG_FT_Vector* vec, PVG_FT_Angle angle) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Int     shift; | 
					
						
							|  |  |  |     PVG_FT_Vector  v = *vec; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     if ( v.x == 0 && v.y == 0 ) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     shift = ft_trig_prenorm( &v ); | 
					
						
							|  |  |  |     ft_trig_pseudo_rotate( &v, angle ); | 
					
						
							|  |  |  |     v.x = ft_trig_downscale( v.x ); | 
					
						
							|  |  |  |     v.y = ft_trig_downscale( v.y ); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     if ( shift > 0 ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         PVG_FT_Int32  half = (PVG_FT_Int32)1L << ( shift - 1 ); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         vec->x = ( v.x + half - ( v.x < 0 ) ) >> shift; | 
					
						
							|  |  |  |         vec->y = ( v.y + half - ( v.y < 0 ) ) >> shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         shift  = -shift; | 
					
						
							|  |  |  |         vec->x = (PVG_FT_Pos)( (PVG_FT_ULong)v.x << shift ); | 
					
						
							|  |  |  |         vec->y = (PVG_FT_Pos)( (PVG_FT_ULong)v.y << shift ); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Fixed PVG_FT_Vector_Length(PVG_FT_Vector* vec) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Int    shift; | 
					
						
							|  |  |  |     PVG_FT_Vector v; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     v = *vec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* handle trivial cases */ | 
					
						
							|  |  |  |     if (v.x == 0) { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |         return PVG_FT_ABS(v.y); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     } else if (v.y == 0) { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |         return PVG_FT_ABS(v.x); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* general case */ | 
					
						
							|  |  |  |     shift = ft_trig_prenorm(&v); | 
					
						
							|  |  |  |     ft_trig_pseudo_polarize(&v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     v.x = ft_trig_downscale(v.x); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (shift > 0) return (v.x + (1 << (shift - 1))) >> shift; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     return (PVG_FT_Fixed)((PVG_FT_UInt32)v.x << -shift); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | void PVG_FT_Vector_Polarize(PVG_FT_Vector* vec, PVG_FT_Fixed* length, | 
					
						
							|  |  |  |     PVG_FT_Angle* angle) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Int    shift; | 
					
						
							|  |  |  |     PVG_FT_Vector v; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     v = *vec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (v.x == 0 && v.y == 0) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     shift = ft_trig_prenorm(&v); | 
					
						
							|  |  |  |     ft_trig_pseudo_polarize(&v); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     v.x = ft_trig_downscale(v.x); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *length = (shift >= 0) ? (v.x >> shift) | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |                            : (PVG_FT_Fixed)((PVG_FT_UInt32)v.x << -shift); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  |     *angle = v.y; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | void PVG_FT_Vector_From_Polar(PVG_FT_Vector* vec, PVG_FT_Fixed length, | 
					
						
							|  |  |  |     PVG_FT_Angle angle) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     vec->x = length; | 
					
						
							|  |  |  |     vec->y = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Vector_Rotate(vec, angle); | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* documentation is in fttrigon.h */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  | PVG_FT_Angle PVG_FT_Angle_Diff( PVG_FT_Angle  angle1, PVG_FT_Angle  angle2 ) | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     PVG_FT_Angle  delta = angle2 - angle1; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     while ( delta <= -PVG_FT_ANGLE_PI ) | 
					
						
							|  |  |  |         delta += PVG_FT_ANGLE_2PI; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     while ( delta > PVG_FT_ANGLE_PI ) | 
					
						
							|  |  |  |         delta -= PVG_FT_ANGLE_2PI; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 10:31:43 +00:00
										 |  |  |     return delta; | 
					
						
							| 
									
										
										
										
											2022-10-03 16:25:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* END */ |