1 /***************************************************************************/
5 /* Arithmetic computations (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
18 /*************************************************************************/
20 /* Support for 1-complement arithmetic has been totally dropped in this */
21 /* release. You can still write your own code if you need it. */
23 /*************************************************************************/
25 /*************************************************************************/
27 /* Implementing basic computation routines. */
29 /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */
30 /* and FT_FloorFix() are declared in freetype.h. */
32 /*************************************************************************/
37 #include FT_INTERNAL_CALC_H
38 #include FT_INTERNAL_DEBUG_H
39 #include FT_INTERNAL_OBJECTS_H
41 #ifdef FT_MULFIX_INLINED
45 /* we need to define a 64-bits data type here */
49 typedef FT_INT64 FT_Int64
;
53 typedef struct FT_Int64_
60 #endif /* FT_LONG64 */
63 /*************************************************************************/
65 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
66 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
67 /* messages during execution. */
70 #define FT_COMPONENT trace_calc
73 /* The following three functions are available regardless of whether */
74 /* FT_LONG64 is defined. */
76 /* documentation is in freetype.h */
78 FT_EXPORT_DEF( FT_Fixed
)
79 FT_RoundFix( FT_Fixed a
)
81 return ( a
>= 0 ) ? ( a
+ 0x8000L
) & ~0xFFFFL
82 : -((-a
+ 0x8000L
) & ~0xFFFFL
);
86 /* documentation is in freetype.h */
88 FT_EXPORT_DEF( FT_Fixed
)
89 FT_CeilFix( FT_Fixed a
)
91 return ( a
>= 0 ) ? ( a
+ 0xFFFFL
) & ~0xFFFFL
92 : -((-a
+ 0xFFFFL
) & ~0xFFFFL
);
96 /* documentation is in freetype.h */
98 FT_EXPORT_DEF( FT_Fixed
)
99 FT_FloorFix( FT_Fixed a
)
101 return ( a
>= 0 ) ? a
& ~0xFFFFL
102 : -((-a
) & ~0xFFFFL
);
106 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
108 /* documentation is in ftcalc.h */
110 FT_EXPORT_DEF( FT_Int32
)
111 FT_Sqrt32( FT_Int32 x
)
113 FT_UInt32 val
, root
, newroot
, mask
;
117 mask
= (FT_UInt32
)0x40000000UL
;
122 newroot
= root
+ mask
;
123 if ( newroot
<= val
)
126 root
= newroot
+ mask
;
132 } while ( mask
!= 0 );
137 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
143 /* documentation is in freetype.h */
145 FT_EXPORT_DEF( FT_Long
)
146 FT_MulDiv( FT_Long a
,
155 if ( a
< 0 ) { a
= -a
; s
= -1; }
156 if ( b
< 0 ) { b
= -b
; s
= -s
; }
157 if ( c
< 0 ) { c
= -c
; s
= -s
; }
159 d
= (FT_Long
)( c
> 0 ? ( (FT_Int64
)a
* b
+ ( c
>> 1 ) ) / c
162 return ( s
> 0 ) ? d
: -d
;
166 #ifdef TT_USE_BYTECODE_INTERPRETER
168 /* documentation is in ftcalc.h */
170 FT_BASE_DEF( FT_Long
)
171 FT_MulDiv_No_Round( FT_Long a
,
180 if ( a
< 0 ) { a
= -a
; s
= -1; }
181 if ( b
< 0 ) { b
= -b
; s
= -s
; }
182 if ( c
< 0 ) { c
= -c
; s
= -s
; }
184 d
= (FT_Long
)( c
> 0 ? (FT_Int64
)a
* b
/ c
187 return ( s
> 0 ) ? d
: -d
;
190 #endif /* TT_USE_BYTECODE_INTERPRETER */
193 /* documentation is in freetype.h */
195 FT_EXPORT_DEF( FT_Long
)
196 FT_MulFix( FT_Long a
,
199 #ifdef FT_MULFIX_ASSEMBLER
201 return FT_MULFIX_ASSEMBLER( a
, b
);
221 c
= (FT_Long
)( ( (FT_Int64
)a
* b
+ 0x8000L
) >> 16 );
223 return ( s
> 0 ) ? c
: -c
;
225 #endif /* FT_MULFIX_ASSEMBLER */
229 /* documentation is in freetype.h */
231 FT_EXPORT_DEF( FT_Long
)
232 FT_DivFix( FT_Long a
,
239 if ( a
< 0 ) { a
= -a
; s
= -1; }
240 if ( b
< 0 ) { b
= -b
; s
= -s
; }
243 /* check for division by 0 */
246 /* compute result directly */
247 q
= (FT_UInt32
)( ( ( (FT_Int64
)a
<< 16 ) + ( b
>> 1 ) ) / b
);
249 return ( s
< 0 ? -(FT_Long
)q
: (FT_Long
)q
);
253 #else /* !FT_LONG64 */
257 ft_multo64( FT_UInt32 x
,
261 FT_UInt32 lo1
, hi1
, lo2
, hi2
, lo
, hi
, i1
, i2
;
264 lo1
= x
& 0x0000FFFFU
; hi1
= x
>> 16;
265 lo2
= y
& 0x0000FFFFU
; hi2
= y
>> 16;
272 /* Check carry overflow of i1 + i2 */
274 hi
+= (FT_UInt32
)( i1
< i2
) << 16;
279 /* Check carry overflow of i1 + lo */
289 ft_div64by32( FT_UInt32 hi
,
301 return (FT_UInt32
)0x7FFFFFFFL
;
310 if ( r
>= (FT_UInt32
)y
)
323 FT_Add64( FT_Int64
* x
,
327 register FT_UInt32 lo
, hi
;
331 hi
= x
->hi
+ y
->hi
+ ( lo
< x
->lo
);
338 /* documentation is in freetype.h */
340 /* The FT_MulDiv function has been optimized thanks to ideas from */
341 /* Graham Asher. The trick is to optimize computation when everything */
342 /* fits within 32-bits (a rather common case). */
344 /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */
346 /* 46340 is FLOOR(SQRT(2^31-1)). */
348 /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */
350 /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */
352 /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */
354 /* and 2*0x157F0 = 176096 */
357 FT_EXPORT_DEF( FT_Long
)
358 FT_MulDiv( FT_Long a
,
365 /* XXX: this function does not allow 64-bit arguments */
366 if ( a
== 0 || b
== c
)
369 s
= a
; a
= FT_ABS( a
);
370 s
^= b
; b
= FT_ABS( b
);
371 s
^= c
; c
= FT_ABS( c
);
373 if ( a
<= 46340L && b
<= 46340L && c
<= 176095L && c
> 0 )
374 a
= ( a
* b
+ ( c
>> 1 ) ) / c
;
378 FT_Int64 temp
, temp2
;
381 ft_multo64( (FT_Int32
)a
, (FT_Int32
)b
, &temp
);
384 temp2
.lo
= (FT_UInt32
)(c
>> 1);
385 FT_Add64( &temp
, &temp2
, &temp
);
386 a
= ft_div64by32( temp
.hi
, temp
.lo
, (FT_Int32
)c
);
391 return ( s
< 0 ? -a
: a
);
395 #ifdef TT_USE_BYTECODE_INTERPRETER
397 FT_BASE_DEF( FT_Long
)
398 FT_MulDiv_No_Round( FT_Long a
,
405 if ( a
== 0 || b
== c
)
408 s
= a
; a
= FT_ABS( a
);
409 s
^= b
; b
= FT_ABS( b
);
410 s
^= c
; c
= FT_ABS( c
);
412 if ( a
<= 46340L && b
<= 46340L && c
> 0 )
420 ft_multo64( (FT_Int32
)a
, (FT_Int32
)b
, &temp
);
421 a
= ft_div64by32( temp
.hi
, temp
.lo
, (FT_Int32
)c
);
426 return ( s
< 0 ? -a
: a
);
429 #endif /* TT_USE_BYTECODE_INTERPRETER */
432 /* documentation is in freetype.h */
434 FT_EXPORT_DEF( FT_Long
)
435 FT_MulFix( FT_Long a
,
438 #ifdef FT_MULFIX_ASSEMBLER
440 return FT_MULFIX_ASSEMBLER( a
, b
);
445 * This code is nonportable. See comment below.
447 * However, on a platform where right-shift of a signed quantity fills
448 * the leftmost bits by copying the sign bit, it might be faster.
455 if ( a
== 0 || b
== 0x10000L
)
459 * This is a clever way of converting a signed number `a' into its
460 * absolute value (stored back into `a') and its sign. The sign is
461 * stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'
462 * was negative. (Similarly for `b' and `sb').
464 * Unfortunately, it doesn't work (at least not portably).
466 * It makes the assumption that right-shift on a negative signed value
467 * fills the leftmost bits by copying the sign bit. This is wrong.
468 * According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,
469 * the result of right-shift of a negative signed value is
470 * implementation-defined. At least one implementation fills the
471 * leftmost bits with 0s (i.e., it is exactly the same as an unsigned
472 * right shift). This means that when `a' is negative, `sa' ends up
473 * with the value 1 rather than -1. After that, everything else goes
476 sa
= ( a
>> ( sizeof ( a
) * 8 - 1 ) );
478 sb
= ( b
>> ( sizeof ( b
) * 8 - 1 ) );
484 if ( ua
<= 2048 && ub
<= 1048576L )
485 ua
= ( ua
* ub
+ 0x8000U
) >> 16;
488 FT_ULong al
= ua
& 0xFFFFU
;
491 ua
= ( ua
>> 16 ) * ub
+ al
* ( ub
>> 16 ) +
492 ( ( al
* ( ub
& 0xFFFFU
) + 0x8000U
) >> 16 );
496 ua
= (FT_ULong
)(( ua
^ sa
) - sa
);
506 if ( a
== 0 || b
== 0x10000L
)
509 s
= a
; a
= FT_ABS( a
);
510 s
^= b
; b
= FT_ABS( b
);
515 if ( ua
<= 2048 && ub
<= 1048576L )
516 ua
= ( ua
* ub
+ 0x8000UL
) >> 16;
519 FT_ULong al
= ua
& 0xFFFFUL
;
522 ua
= ( ua
>> 16 ) * ub
+ al
* ( ub
>> 16 ) +
523 ( ( al
* ( ub
& 0xFFFFUL
) + 0x8000UL
) >> 16 );
526 return ( s
< 0 ? -(FT_Long
)ua
: (FT_Long
)ua
);
533 /* documentation is in freetype.h */
535 FT_EXPORT_DEF( FT_Long
)
536 FT_DivFix( FT_Long a
,
543 /* XXX: this function does not allow 64-bit arguments */
544 s
= (FT_Int32
)a
; a
= FT_ABS( a
);
545 s
^= (FT_Int32
)b
; b
= FT_ABS( b
);
549 /* check for division by 0 */
550 q
= (FT_UInt32
)0x7FFFFFFFL
;
552 else if ( ( a
>> 16 ) == 0 )
554 /* compute result directly */
555 q
= (FT_UInt32
)( (a
<< 16) + (b
>> 1) ) / (FT_UInt32
)b
;
559 /* we need more bits; we have to do it by hand */
560 FT_Int64 temp
, temp2
;
562 temp
.hi
= (FT_Int32
) (a
>> 16);
563 temp
.lo
= (FT_UInt32
)(a
<< 16);
565 temp2
.lo
= (FT_UInt32
)( b
>> 1 );
566 FT_Add64( &temp
, &temp2
, &temp
);
567 q
= ft_div64by32( temp
.hi
, temp
.lo
, (FT_Int32
)b
);
570 return ( s
< 0 ? -(FT_Int32
)q
: (FT_Int32
)q
);
576 /* documentation is in ftcalc.h */
578 FT_EXPORT_DEF( void )
579 FT_MulTo64( FT_Int32 x
,
586 s
= x
; x
= FT_ABS( x
);
587 s
^= y
; y
= FT_ABS( y
);
589 ft_multo64( x
, y
, z
);
593 z
->lo
= (FT_UInt32
)-(FT_Int32
)z
->lo
;
594 z
->hi
= ~z
->hi
+ !( z
->lo
);
599 /* apparently, the second version of this code is not compiled correctly */
600 /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */
604 FT_EXPORT_DEF( FT_Int32
)
605 FT_Div64by32( FT_Int64
* x
,
609 FT_UInt32 q
, r
, i
, lo
;
615 x
->lo
= (FT_UInt32
)-(FT_Int32
)x
->lo
;
616 x
->hi
= ~x
->hi
+ !x
->lo
;
618 s
^= y
; y
= FT_ABS( y
);
628 return ( s
< 0 ? -(FT_Int32
)q
: (FT_Int32
)q
);
634 if ( r
>= (FT_UInt32
)y
) /* we know y is to be treated as unsigned here */
635 return ( s
< 0 ? 0x80000001UL
: 0x7FFFFFFFUL
);
636 /* Return Max/Min Int32 if division overflow. */
637 /* This includes division by zero! */
639 for ( i
= 0; i
< 32; i
++ )
645 if ( r
>= (FT_UInt32
)y
)
653 return ( s
< 0 ? -(FT_Int32
)q
: (FT_Int32
)q
);
658 FT_EXPORT_DEF( FT_Int32
)
659 FT_Div64by32( FT_Int64
* x
,
669 x
->lo
= (FT_UInt32
)-(FT_Int32
)x
->lo
;
670 x
->hi
= ~x
->hi
+ !x
->lo
;
672 s
^= y
; y
= FT_ABS( y
);
678 q
= ( x
->lo
+ ( y
>> 1 ) ) / y
;
682 return ( s
< 0 ? -(FT_Int32
)q
: (FT_Int32
)q
);
685 q
= ft_div64by32( x
->hi
, x
->lo
, y
);
687 return ( s
< 0 ? -(FT_Int32
)q
: (FT_Int32
)q
);
695 #endif /* FT_LONG64 */
698 /* documentation is in ftglyph.h */
700 FT_EXPORT_DEF( void )
701 FT_Matrix_Multiply( const FT_Matrix
* a
,
704 FT_Fixed xx
, xy
, yx
, yy
;
710 xx
= FT_MulFix( a
->xx
, b
->xx
) + FT_MulFix( a
->xy
, b
->yx
);
711 xy
= FT_MulFix( a
->xx
, b
->xy
) + FT_MulFix( a
->xy
, b
->yy
);
712 yx
= FT_MulFix( a
->yx
, b
->xx
) + FT_MulFix( a
->yy
, b
->yx
);
713 yy
= FT_MulFix( a
->yx
, b
->xy
) + FT_MulFix( a
->yy
, b
->yy
);
715 b
->xx
= xx
; b
->xy
= xy
;
716 b
->yx
= yx
; b
->yy
= yy
;
720 /* documentation is in ftglyph.h */
722 FT_EXPORT_DEF( FT_Error
)
723 FT_Matrix_Invert( FT_Matrix
* matrix
)
725 FT_Pos delta
, xx
, yy
;
729 return FT_Err_Invalid_Argument
;
731 /* compute discriminant */
732 delta
= FT_MulFix( matrix
->xx
, matrix
->yy
) -
733 FT_MulFix( matrix
->xy
, matrix
->yx
);
736 return FT_Err_Invalid_Argument
; /* matrix can't be inverted */
738 matrix
->xy
= - FT_DivFix( matrix
->xy
, delta
);
739 matrix
->yx
= - FT_DivFix( matrix
->yx
, delta
);
744 matrix
->xx
= FT_DivFix( yy
, delta
);
745 matrix
->yy
= FT_DivFix( xx
, delta
);
751 /* documentation is in ftcalc.h */
754 FT_Matrix_Multiply_Scaled( const FT_Matrix
* a
,
758 FT_Fixed xx
, xy
, yx
, yy
;
760 FT_Long val
= 0x10000L
* scaling
;
766 xx
= FT_MulDiv( a
->xx
, b
->xx
, val
) + FT_MulDiv( a
->xy
, b
->yx
, val
);
767 xy
= FT_MulDiv( a
->xx
, b
->xy
, val
) + FT_MulDiv( a
->xy
, b
->yy
, val
);
768 yx
= FT_MulDiv( a
->yx
, b
->xx
, val
) + FT_MulDiv( a
->yy
, b
->yx
, val
);
769 yy
= FT_MulDiv( a
->yx
, b
->xy
, val
) + FT_MulDiv( a
->yy
, b
->yy
, val
);
771 b
->xx
= xx
; b
->xy
= xy
;
772 b
->yx
= yx
; b
->yy
= yy
;
776 /* documentation is in ftcalc.h */
779 FT_Vector_Transform_Scaled( FT_Vector
* vector
,
780 const FT_Matrix
* matrix
,
785 FT_Long val
= 0x10000L
* scaling
;
788 if ( !vector
|| !matrix
)
791 xz
= FT_MulDiv( vector
->x
, matrix
->xx
, val
) +
792 FT_MulDiv( vector
->y
, matrix
->xy
, val
);
794 yz
= FT_MulDiv( vector
->x
, matrix
->yx
, val
) +
795 FT_MulDiv( vector
->y
, matrix
->yy
, val
);
802 /* documentation is in ftcalc.h */
804 FT_BASE_DEF( FT_Int32
)
805 FT_SqrtFixed( FT_Int32 x
)
807 FT_UInt32 root
, rem_hi
, rem_lo
, test_div
;
820 rem_hi
= ( rem_hi
<< 2 ) | ( rem_lo
>> 30 );
823 test_div
= ( root
<< 1 ) + 1;
825 if ( rem_hi
>= test_div
)
833 return (FT_Int32
)root
;
837 /* documentation is in ftcalc.h */
839 FT_BASE_DEF( FT_Int
)
840 ft_corner_orientation( FT_Pos in_x
,
845 FT_Long result
; /* avoid overflow on 16-bit system */
848 /* deal with the trivial cases quickly */
856 else if ( in_x
== 0 )
863 else if ( out_y
== 0 )
870 else if ( out_x
== 0 )
877 else /* general case */
881 FT_Int64 delta
= (FT_Int64
)in_x
* out_y
- (FT_Int64
)in_y
* out_x
;
887 result
= 1 - 2 * ( delta
< 0 );
894 /* XXX: this function does not allow 64-bit arguments */
895 ft_multo64( (FT_Int32
)in_x
, (FT_Int32
)out_y
, &z1
);
896 ft_multo64( (FT_Int32
)in_y
, (FT_Int32
)out_x
, &z2
);
900 else if ( z1
.hi
< z2
.hi
)
902 else if ( z1
.lo
> z2
.lo
)
904 else if ( z1
.lo
< z2
.lo
)
912 /* XXX: only the sign of return value, +1/0/-1 must be used */
913 return (FT_Int
)result
;
917 /* documentation is in ftcalc.h */
919 FT_BASE_DEF( FT_Int
)
920 ft_corner_is_flat( FT_Pos in_x
,
928 FT_Pos d_in
, d_out
, d_corner
;
953 return ( d_in
+ d_out
- d_corner
) < ( d_corner
>> 4 );