54#define FT_COMPONENT calc
59#define FT_MOVE_SIGN( utype, x, x_unsigned, s ) \
63 x_unsigned = 0U - (utype)x; \
67 x_unsigned = (utype)x; \
75 FT_EXPORT_DEF( FT_Fixed )
76 FT_RoundFix( FT_Fixed a )
78 return ADD_LONG( a, 0x8000L - ( a < 0 ) ) & ~0xFFFFL;
84 FT_EXPORT_DEF( FT_Fixed )
85 FT_CeilFix( FT_Fixed a )
87 return ADD_LONG( a, 0xFFFFL ) & ~0xFFFFL;
93 FT_EXPORT_DEF( FT_Fixed )
94 FT_FloorFix( FT_Fixed a )
101 FT_BASE_DEF( FT_Int )
102 FT_MSB( FT_UInt32 z )
108 if ( z & 0xFFFF0000UL )
113 if ( z & 0x0000FF00UL )
118 if ( z & 0x000000F0UL )
123 if ( z & 0x0000000CUL )
128 if ( z & 0x00000002UL )
142 FT_BASE_DEF( FT_Fixed )
143 FT_Hypot( FT_Fixed x,
152 return FT_Vector_Length( &v );
161 FT_EXPORT_DEF( FT_Long )
162 FT_MulDiv( FT_Long a_,
167 FT_UInt64 a, b, c, d;
171 FT_MOVE_SIGN( FT_UInt64, a_, a, s );
172 FT_MOVE_SIGN( FT_UInt64, b_, b, s );
173 FT_MOVE_SIGN( FT_UInt64, c_, c, s );
175 d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
180 return s < 0 ? NEG_LONG( d_ ) : d_;
186 FT_BASE_DEF( FT_Long )
187 FT_MulDiv_No_Round( FT_Long a_,
192 FT_UInt64 a, b, c, d;
196 FT_MOVE_SIGN( FT_UInt64, a_, a, s );
197 FT_MOVE_SIGN( FT_UInt64, b_, b, s );
198 FT_MOVE_SIGN( FT_UInt64, c_, c, s );
200 d = c > 0 ? a * b / c
205 return s < 0 ? NEG_LONG( d_ ) : d_;
211 FT_EXPORT_DEF( FT_Long )
212 FT_MulFix( FT_Long a_,
215#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
217 return FT_MulFix_64( a_, b_ );
221 FT_Int64 ab = MUL_INT64( a_, b_ );
224 return (FT_Long)( ( ab + 0x8000L + ( ab >> 63 ) ) >> 16 );
232 FT_EXPORT_DEF( FT_Long )
233 FT_DivFix( FT_Long a_,
241 FT_MOVE_SIGN( FT_UInt64, a_, a, s );
242 FT_MOVE_SIGN( FT_UInt64, b_, b, s );
244 q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
249 return s < 0 ? NEG_LONG( q_ ) : q_;
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;
274 hi += (FT_UInt32)( i1 < i2 ) << 16;
289 ft_div64by32( FT_UInt32 hi,
298 return (FT_UInt32)0x7FFFFFFFL;
305 i = 31 - FT_MSB( hi );
306 r = ( hi << i ) | ( lo >> ( 32 - i ) ); lo <<= i;
314 r = ( r << 1 ) | ( lo >> 31 ); lo <<= 1;
328 FT_Add64( FT_Int64* x,
336 hi = x->hi + y->hi + ( lo < x->lo );
392 FT_EXPORT_DEF( FT_Long )
393 FT_MulDiv( FT_Long a_,
403 FT_MOVE_SIGN( FT_UInt32, a_, a, s );
404 FT_MOVE_SIGN( FT_UInt32, b_, b, s );
405 FT_MOVE_SIGN( FT_UInt32, c_, c, s );
410 else if ( a + b <= 129894UL - ( c >> 17 ) )
411 a = ( a * b + ( c >> 1 ) ) / c;
415 FT_Int64 temp, temp2;
418 ft_multo64( a, b, &temp );
423 FT_Add64( &temp, &temp2, &temp );
426 a = ( temp.hi == 0 ) ? temp.lo / c
427 : ft_div64by32( temp.hi, temp.lo, c );
432 return s < 0 ? NEG_LONG( a_ ) : a_;
436 FT_BASE_DEF( FT_Long )
437 FT_MulDiv_No_Round( FT_Long a_,
447 FT_MOVE_SIGN( FT_UInt32, a_, a, s );
448 FT_MOVE_SIGN( FT_UInt32, b_, b, s );
449 FT_MOVE_SIGN( FT_UInt32, c_, c, s );
454 else if ( a + b <= 131071UL )
462 ft_multo64( a, b, &temp );
465 a = ( temp.hi == 0 ) ? temp.lo / c
466 : ft_div64by32( temp.hi, temp.lo, c );
471 return s < 0 ? NEG_LONG( a_ ) : a_;
477 FT_EXPORT_DEF( FT_Long )
478 FT_MulFix( FT_Long a_,
481#ifdef FT_MULFIX_ASSEMBLER
483 return FT_MULFIX_ASSEMBLER( a_, b_ );
516 sa = ( a_ >> (
sizeof ( a_ ) * 8 - 1 ) );
517 a = ( a_ ^ sa ) - sa;
518 sb = ( b_ >> (
sizeof ( b_ ) * 8 - 1 ) );
519 b = ( b_ ^ sb ) - sb;
524 if ( a + ( b >> 8 ) <= 8190UL )
525 a = ( a * b + 0x8000U ) >> 16;
528 FT_UInt32 al = a & 0xFFFFUL;
531 a = ( a >> 16 ) * b + al * ( b >> 16 ) +
532 ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
548 FT_MOVE_SIGN( FT_UInt32, a_, a, s );
549 FT_MOVE_SIGN( FT_UInt32, b_, b, s );
551 if ( a + ( b >> 8 ) <= 8190UL )
552 a = ( a * b + 0x8000UL ) >> 16;
555 FT_UInt32 al = a & 0xFFFFUL;
558 a = ( a >> 16 ) * b + al * ( b >> 16 ) +
559 ( ( al * ( b & 0xFFFFUL ) + 0x8000UL ) >> 16 );
564 return s < 0 ? NEG_LONG( a_ ) : a_;
573 FT_EXPORT_DEF( FT_Long )
574 FT_DivFix( FT_Long a_,
584 FT_MOVE_SIGN( FT_UInt32, a_, a, s );
585 FT_MOVE_SIGN( FT_UInt32, b_, b, s );
592 else if ( a <= 65535UL - ( b >> 17 ) )
595 q = ( ( a << 16 ) + ( b >> 1 ) ) / b;
600 FT_Int64 temp, temp2;
608 FT_Add64( &temp, &temp2, &temp );
609 q = ft_div64by32( temp.hi, temp.lo, b );
614 return s < 0 ? NEG_LONG( q_ ) : q_;
623 FT_EXPORT_DEF(
void )
624 FT_Matrix_Multiply(
const FT_Matrix* a,
627 FT_Fixed xx, xy, yx, yy;
633 xx = ADD_LONG( FT_MulFix( a->xx, b->xx ),
634 FT_MulFix( a->xy, b->yx ) );
635 xy = ADD_LONG( FT_MulFix( a->xx, b->xy ),
636 FT_MulFix( a->xy, b->yy ) );
637 yx = ADD_LONG( FT_MulFix( a->yx, b->xx ),
638 FT_MulFix( a->yy, b->yx ) );
639 yy = ADD_LONG( FT_MulFix( a->yx, b->xy ),
640 FT_MulFix( a->yy, b->yy ) );
651 FT_EXPORT_DEF( FT_Error )
652 FT_Matrix_Invert( FT_Matrix* matrix )
654 FT_Pos delta, xx, yy;
658 return FT_THROW( Invalid_Argument );
661 delta = FT_MulFix( matrix->xx, matrix->yy ) -
662 FT_MulFix( matrix->xy, matrix->yx );
665 return FT_THROW( Invalid_Argument );
667 matrix->xy = -FT_DivFix( matrix->xy, delta );
668 matrix->yx = -FT_DivFix( matrix->yx, delta );
673 matrix->xx = FT_DivFix( yy, delta );
674 matrix->yy = FT_DivFix( xx, delta );
683 FT_Matrix_Multiply_Scaled(
const FT_Matrix* a,
687 FT_Fixed xx, xy, yx, yy;
689 FT_Long val = 0x10000L * scaling;
695 xx = ADD_LONG( FT_MulDiv( a->xx, b->xx, val ),
696 FT_MulDiv( a->xy, b->yx, val ) );
697 xy = ADD_LONG( FT_MulDiv( a->xx, b->xy, val ),
698 FT_MulDiv( a->xy, b->yy, val ) );
699 yx = ADD_LONG( FT_MulDiv( a->yx, b->xx, val ),
700 FT_MulDiv( a->yy, b->yx, val ) );
701 yy = ADD_LONG( FT_MulDiv( a->yx, b->xy, val ),
702 FT_MulDiv( a->yy, b->yy, val ) );
713 FT_BASE_DEF( FT_Bool )
714 FT_Matrix_Check(
const FT_Matrix* matrix )
716 FT_Fixed xx, xy, yx, yy;
719 FT_ULong temp1, temp2;
729 val = FT_ABS( xx ) | FT_ABS( xy ) | FT_ABS( yx ) | FT_ABS( yy );
732 if ( !val || val > 0x7FFFFFFFL )
738 shift = FT_MSB( val ) - 12;
748 temp1 = 32U * (FT_ULong)FT_ABS( xx * yy - xy * yx );
749 temp2 = (FT_ULong)( xx * xx ) + (FT_ULong)( xy * xy ) +
750 (FT_ULong)( yx * yx ) + (FT_ULong)( yy * yy );
752 if ( temp1 <= temp2 )
762 FT_Vector_Transform_Scaled( FT_Vector* vector,
763 const FT_Matrix* matrix,
768 FT_Long val = 0x10000L * scaling;
771 if ( !vector || !matrix )
774 xz = ADD_LONG( FT_MulDiv( vector->x, matrix->xx, val ),
775 FT_MulDiv( vector->y, matrix->xy, val ) );
776 yz = ADD_LONG( FT_MulDiv( vector->x, matrix->yx, val ),
777 FT_MulDiv( vector->y, matrix->yy, val ) );
786 FT_BASE_DEF( FT_UInt32 )
787 FT_Vector_NormLen( FT_Vector* vector )
789 FT_Int32 x_ = vector->x;
790 FT_Int32 y_ = vector->y;
792 FT_UInt32 x, y, u, v, l;
793 FT_Int sx = 1, sy = 1, shift;
796 FT_MOVE_SIGN( FT_UInt32, x_, x, sx );
797 FT_MOVE_SIGN( FT_UInt32, y_, y, sy );
803 vector->y = sy * 0x10000;
809 vector->x = sx * 0x10000;
817 l = x > y ? x + ( y >> 1 )
820 shift = 31 - FT_MSB( l );
821 shift -= 15 + ( l >= ( 0xAAAAAAAAUL >> shift ) );
829 l = x > y ? x + ( y >> 1 )
840 b = 0x10000 - (FT_Int32)l;
848 u = (FT_UInt32)( x_ + ( x_ * b >> 16 ) );
849 v = (FT_UInt32)( y_ + ( y_ * b >> 16 ) );
854 z = -(FT_Int32)( u * u + v * v ) / 0x200;
855 z = z * ( ( 0x10000 + b ) >> 8 ) / 0x10000;
861 vector->x = sx < 0 ? -(FT_Pos)u : (FT_Pos)u;
862 vector->y = sy < 0 ? -(FT_Pos)v : (FT_Pos)v;
867 l = (FT_UInt32)( 0x10000 + (FT_Int32)( u * x + v * y ) / 0x10000 );
869 l = ( l + ( 1 << ( shift - 1 ) ) ) >> shift;
879 FT_BASE_DEF( FT_UInt32 )
880 FT_SqrtFixed( FT_UInt32 v )
892 else if ( v > 0x10000U )
894 FT_UInt32 r = v >> 1;
895 FT_UInt32 q = ( v & 1 ) << 15;
896 FT_UInt32 b = 0x20000000;
911 }
while ( b > 0x10 );
913 return ( q + 0x40 ) >> 7;
917 FT_UInt32 r = ( v << 16 ) - 1;
923 FT_UInt64 r = ( (FT_UInt64)v << 16 ) - 1;
927 FT_UInt32 q = 1 << ( ( 17 + FT_MSB( v ) ) >> 1 );
935 q = ( t + (FT_UInt32)( r / t ) + 1 ) >> 1;
946 FT_BASE_DEF( FT_Int )
947 ft_corner_orientation( FT_Pos in_x,
957 FT_Int64 delta = SUB_INT64( MUL_INT64( in_x, out_y ),
958 MUL_INT64( in_y, out_x ) );
961 return ( delta > 0 ) - ( delta < 0 );
969 if ( (FT_ULong)FT_ABS( in_x ) + (FT_ULong)FT_ABS( out_y ) <= 92681UL )
971 z1.lo = (FT_UInt32)in_x * (FT_UInt32)out_y;
972 z1.hi = (FT_UInt32)( (FT_Int32)z1.lo >> 31 );
975 ft_multo64( (FT_UInt32)in_x, (FT_UInt32)out_y, &z1 );
977 if ( (FT_ULong)FT_ABS( in_y ) + (FT_ULong)FT_ABS( out_x ) <= 92681UL )
979 z2.lo = (FT_UInt32)in_y * (FT_UInt32)out_x;
980 z2.hi = (FT_UInt32)( (FT_Int32)z2.lo >> 31 );
983 ft_multo64( (FT_UInt32)in_y, (FT_UInt32)out_x, &z2 );
985 if ( (FT_Int32)z1.hi > (FT_Int32)z2.hi )
987 else if ( (FT_Int32)z1.hi < (FT_Int32)z2.hi )
989 else if ( z1.lo > z2.lo )
991 else if ( z1.lo < z2.lo )
1005 FT_BASE_DEF( FT_Int )
1006 ft_corner_is_flat( FT_Pos in_x,
1011 FT_Pos ax = in_x + out_x;
1012 FT_Pos ay = in_y + out_y;
1014 FT_Pos d_in, d_out, d_hypot;
1036 d_in = FT_HYPOT( in_x, in_y );
1037 d_out = FT_HYPOT( out_x, out_y );
1038 d_hypot = FT_HYPOT( ax, ay );
1044 return ( d_in + d_out - d_hypot ) < ( d_hypot >> 4 );