sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
ftcalc.h
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * ftcalc.h
4 *
5 * Arithmetic computations (specification).
6 *
7 * Copyright (C) 1996-2025 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
23#ifndef FTCALC_H_
24#define FTCALC_H_
25
26
27#include <freetype/freetype.h>
28
29#include "compiler-macros.h"
30
31FT_BEGIN_HEADER
32
33
34 /*
35 * The following macros have two purposes.
36 *
37 * - Tag places where overflow is expected and harmless.
38 *
39 * - Avoid run-time undefined behavior sanitizer errors.
40 *
41 * Use with care!
42 */
43#define ADD_INT( a, b ) \
44 (FT_Int)( (FT_UInt)(a) + (FT_UInt)(b) )
45#define SUB_INT( a, b ) \
46 (FT_Int)( (FT_UInt)(a) - (FT_UInt)(b) )
47#define MUL_INT( a, b ) \
48 (FT_Int)( (FT_UInt)(a) * (FT_UInt)(b) )
49#define NEG_INT( a ) \
50 (FT_Int)( (FT_UInt)0 - (FT_UInt)(a) )
51
52#define ADD_LONG( a, b ) \
53 (FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) )
54#define SUB_LONG( a, b ) \
55 (FT_Long)( (FT_ULong)(a) - (FT_ULong)(b) )
56#define MUL_LONG( a, b ) \
57 (FT_Long)( (FT_ULong)(a) * (FT_ULong)(b) )
58#define NEG_LONG( a ) \
59 (FT_Long)( (FT_ULong)0 - (FT_ULong)(a) )
60
61#define ADD_INT32( a, b ) \
62 (FT_Int32)( (FT_UInt32)(a) + (FT_UInt32)(b) )
63#define SUB_INT32( a, b ) \
64 (FT_Int32)( (FT_UInt32)(a) - (FT_UInt32)(b) )
65#define MUL_INT32( a, b ) \
66 (FT_Int32)( (FT_UInt32)(a) * (FT_UInt32)(b) )
67#define NEG_INT32( a ) \
68 (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) )
69
70#ifdef FT_INT64
71
72#define ADD_INT64( a, b ) \
73 (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) )
74#define SUB_INT64( a, b ) \
75 (FT_Int64)( (FT_UInt64)(a) - (FT_UInt64)(b) )
76#define MUL_INT64( a, b ) \
77 (FT_Int64)( (FT_UInt64)(a) * (FT_UInt64)(b) )
78#define NEG_INT64( a ) \
79 (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) )
80
81#endif /* FT_INT64 */
82
83
84 /**************************************************************************
85 *
86 * FT_MulDiv() and FT_MulFix() are declared in freetype.h.
87 *
88 */
89
90#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
91
92#ifdef FT_INT64
93
94 static inline FT_Long
95 FT_MulFix_64( FT_Long a,
96 FT_Long b )
97 {
98 FT_Int64 ab = MUL_INT64( a, b );
99
100
101 ab = ADD_INT64( ab, 0x8000 + ( ab >> 63 ) ); /* rounding phase */
102
103 return (FT_Long)( ab >> 16 );
104 }
105
106
107#define FT_MulFix( a, b ) FT_MulFix_64( a, b )
108
109#elif !defined( FT_CONFIG_OPTION_NO_ASSEMBLER )
110 /* Provide 32-bit assembler fragments for optimized FT_MulFix. */
111 /* These must be defined `static __inline__' or similar. */
112
113#if defined( __arm__ ) && \
114 ( defined( __thumb2__ ) || !defined( __thumb__ ) )
115
116#define FT_MULFIX_ASSEMBLER FT_MulFix_arm
117
118 /* documentation is in freetype.h */
119
120 static __inline FT_Int32
121 FT_MulFix_arm( FT_Int32 a,
122 FT_Int32 b )
123 {
124 FT_Int32 t, t2;
125
126#if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */
127
128 __asm
129 {
130 smull t2, t, b, a /* (lo=t2,hi=t) = a*b */
131 mov a, t, asr #31 /* a = (hi >> 31) */
132 add a, a, #0x8000 /* a += 0x8000 */
133 adds t2, t2, a /* t2 += a */
134 adc t, t, #0 /* t += carry */
135 mov a, t2, lsr #16 /* a = t2 >> 16 */
136 orr a, a, t, lsl #16 /* a |= t << 16 */
137 }
138
139#elif defined( __GNUC__ )
140
141 __asm__ __volatile__ (
142 "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */
143 "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */
144#if defined( __clang__ ) && defined( __thumb2__ )
145 "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
146#else
147 "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */
148#endif
149 "adds %1, %1, %0\n\t" /* %1 += %0 */
150 "adc %2, %2, #0\n\t" /* %2 += carry */
151 "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */
152 "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */
153 : "=r"(a), "=&r"(t2), "=&r"(t)
154 : "r"(a), "r"(b)
155 : "cc" );
156
157#endif
158
159 return a;
160 }
161
162#elif defined( __i386__ ) || defined( _M_IX86 )
163
164#define FT_MULFIX_ASSEMBLER FT_MulFix_i386
165
166 /* documentation is in freetype.h */
167
168 static __inline FT_Int32
169 FT_MulFix_i386( FT_Int32 a,
170 FT_Int32 b )
171 {
172 FT_Int32 result;
173
174#if defined( __GNUC__ )
175
176 __asm__ __volatile__ (
177 "imul %%edx\n"
178 "movl %%edx, %%ecx\n"
179 "sarl $31, %%ecx\n"
180 "addl $0x8000, %%ecx\n"
181 "addl %%ecx, %%eax\n"
182 "adcl $0, %%edx\n"
183 "shrl $16, %%eax\n"
184 "shll $16, %%edx\n"
185 "addl %%edx, %%eax\n"
186 : "=a"(result), "=d"(b)
187 : "a"(a), "d"(b)
188 : "%ecx", "cc" );
189
190#elif defined( _MSC_VER )
191
192 __asm
193 {
194 mov eax, a
195 mov edx, b
196 imul edx
197 mov ecx, edx
198 sar ecx, 31
199 add ecx, 8000h
200 add eax, ecx
201 adc edx, 0
202 shr eax, 16
203 shl edx, 16
204 add eax, edx
205 mov result, eax
206 }
207
208#endif
209
210 return result;
211 }
212
213#endif /* __i386__ || _M_IX86 */
214
215#ifdef FT_MULFIX_ASSEMBLER
216#define FT_MulFix( a, b ) FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) )
217#endif
218
219#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
220
221#endif /* FT_CONFIG_OPTION_INLINE_MULFIX */
222
223
224 /**************************************************************************
225 *
226 * @function:
227 * FT_MulDiv_No_Round
228 *
229 * @description:
230 * A very simple function used to perform the computation '(a*b)/c'
231 * (without rounding) with maximum accuracy (it uses a 64-bit
232 * intermediate integer whenever necessary).
233 *
234 * This function isn't necessarily as fast as some processor-specific
235 * operations, but is at least completely portable.
236 *
237 * @input:
238 * a ::
239 * The first multiplier.
240 * b ::
241 * The second multiplier.
242 * c ::
243 * The divisor.
244 *
245 * @return:
246 * The result of '(a*b)/c'. This function never traps when trying to
247 * divide by zero; it simply returns 'MaxInt' or 'MinInt' depending on
248 * the signs of 'a' and 'b'.
249 */
250 FT_BASE( FT_Long )
251 FT_MulDiv_No_Round( FT_Long a,
252 FT_Long b,
253 FT_Long c );
254
255
256 /*
257 * A variant of FT_Matrix_Multiply which scales its result afterwards. The
258 * idea is that both `a' and `b' are scaled by factors of 10 so that the
259 * values are as precise as possible to get a correct result during the
260 * 64bit multiplication. Let `sa' and `sb' be the scaling factors of `a'
261 * and `b', respectively, then the scaling factor of the result is `sa*sb'.
262 */
263 FT_BASE( void )
264 FT_Matrix_Multiply_Scaled( const FT_Matrix* a,
265 FT_Matrix *b,
266 FT_Long scaling );
267
268
269 /*
270 * Check a matrix. If the transformation would lead to extreme shear or
271 * extreme scaling, for example, return 0. If everything is OK, return 1.
272 *
273 * Based on geometric considerations we use the following inequality to
274 * identify a degenerate matrix.
275 *
276 * 32 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
277 *
278 * Value 32 is heuristic.
279 */
280 FT_BASE( FT_Bool )
281 FT_Matrix_Check( const FT_Matrix* matrix );
282
283
284 /*
285 * A variant of FT_Vector_Transform. See comments for
286 * FT_Matrix_Multiply_Scaled.
287 */
288 FT_BASE( void )
289 FT_Vector_Transform_Scaled( FT_Vector* vector,
290 const FT_Matrix* matrix,
291 FT_Long scaling );
292
293
294 /*
295 * This function normalizes a vector and returns its original length. The
296 * normalized vector is a 16.16 fixed-point unit vector with length close
297 * to 0x10000. The accuracy of the returned length is limited to 16 bits
298 * also. The function utilizes quick inverse square root approximation
299 * without divisions and square roots relying on Newton's iterations
300 * instead.
301 */
302 FT_BASE( FT_UInt32 )
303 FT_Vector_NormLen( FT_Vector* vector );
304
305
306 /*
307 * Return -1, 0, or +1, depending on the orientation of a given corner. We
308 * use the Cartesian coordinate system, with positive vertical values going
309 * upwards. The function returns +1 if the corner turns to the left, -1 to
310 * the right, and 0 for undecidable cases.
311 */
312 FT_BASE( FT_Int )
313 ft_corner_orientation( FT_Pos in_x,
314 FT_Pos in_y,
315 FT_Pos out_x,
316 FT_Pos out_y );
317
318
319 /*
320 * Return TRUE if a corner is flat or nearly flat. This is equivalent to
321 * saying that the corner point is close to its neighbors, or inside an
322 * ellipse defined by the neighbor focal points to be more precise.
323 */
324 FT_BASE( FT_Int )
325 ft_corner_is_flat( FT_Pos in_x,
326 FT_Pos in_y,
327 FT_Pos out_x,
328 FT_Pos out_y );
329
330
331 /*
332 * Return the most significant bit index.
333 */
334
335#ifndef FT_CONFIG_OPTION_NO_ASSEMBLER
336
337#if defined( __clang__ ) || ( defined( __GNUC__ ) && \
338 ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) ) )
339
340#if FT_SIZEOF_INT == 4
341
342#define FT_MSB( x ) ( 31 - __builtin_clz( x ) )
343
344#elif FT_SIZEOF_LONG == 4
345
346#define FT_MSB( x ) ( 31 - __builtin_clzl( x ) )
347
348#endif
349
350#elif defined( _MSC_VER ) && _MSC_VER >= 1400
351
352#if defined( _WIN32_WCE )
353
354#include <cmnintrin.h>
355#pragma intrinsic( _CountLeadingZeros )
356
357#define FT_MSB( x ) ( 31 - _CountLeadingZeros( x ) )
358
359#elif defined( _M_ARM64 ) || defined( _M_ARM ) || defined( _M_ARM64EC )
360
361#include <intrin.h>
362#pragma intrinsic( _CountLeadingZeros )
363
364#define FT_MSB( x ) ( 31 - _CountLeadingZeros( x ) )
365
366#elif defined( _M_IX86 ) || defined( _M_AMD64 ) || defined( _M_IA64 )
367
368#include <intrin.h>
369#pragma intrinsic( _BitScanReverse )
370
371 static __inline FT_Int32
372 FT_MSB_i386( FT_UInt32 x )
373 {
374 unsigned long where;
375
376
377 _BitScanReverse( &where, x );
378
379 return (FT_Int32)where;
380 }
381
382#define FT_MSB( x ) FT_MSB_i386( x )
383
384#endif
385
386#elif defined( __WATCOMC__ ) && defined( __386__ )
387
388 extern __inline FT_Int32
389 FT_MSB_i386( FT_UInt32 x );
390
391#pragma aux FT_MSB_i386 = \
392 "bsr eax, eax" \
393 __parm [__eax] __nomemory \
394 __value [__eax] \
395 __modify __exact [__eax] __nomemory;
396
397#define FT_MSB( x ) FT_MSB_i386( x )
398
399#elif defined( __CC_ARM )
400
401#define FT_MSB( x ) ( 31 - __clz( x ) )
402
403#elif defined( __SunOS_5_11 )
404
405#include <string.h>
406
407#define FT_MSB( x ) ( fls( x ) - 1 )
408
409#elif defined( __DECC ) || defined( __DECCXX )
410
411#include <builtins.h>
412
413#define FT_MSB( x ) (FT_Int)( 63 - _leadz( x ) )
414
415#elif defined( _CRAYC )
416
417#include <intrinsics.h>
418
419#define FT_MSB( x ) (FT_Int)( 31 - _leadz32( x ) )
420
421#endif /* FT_MSB macro definitions */
422
423#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
424
425
426#ifndef FT_MSB
427
428 FT_BASE( FT_Int )
429 FT_MSB( FT_UInt32 z );
430
431#endif
432
433
434 /*
435 * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
436 * two fixed-point arguments instead.
437 */
438 FT_BASE( FT_Fixed )
439 FT_Hypot( FT_Fixed x,
440 FT_Fixed y );
441
442
443 /**************************************************************************
444 *
445 * @function:
446 * FT_SqrtFixed
447 *
448 * @description:
449 * Computes the square root of a 16.16 fixed-point value.
450 *
451 * @input:
452 * x ::
453 * The value to compute the root for.
454 *
455 * @return:
456 * The result of 'sqrt(x)'.
457 *
458 * @note:
459 * This function is slow and should be avoided. Consider @FT_Hypot or
460 * @FT_Vector_NormLen instead.
461 */
462 FT_BASE( FT_UInt32 )
463 FT_SqrtFixed( FT_UInt32 x );
464
465
466#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) * 64 ) /* << 6 */
467#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) * 16384 ) /* << 14 */
468#define INT_TO_FIXED( x ) ( (FT_Long)(x) * 65536 ) /* << 16 */
469#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) * 4 ) /* << 2 */
470#define FIXED_TO_INT( x ) ( FT_RoundFix( x ) >> 16 )
471
472#define ROUND_F26DOT6( x ) ( ( (x) + 32 - ( x < 0 ) ) & -64 )
473
474
475FT_END_HEADER
476
477#endif /* FTCALC_H_ */
478
479
480/* END */