diff options
Diffstat (limited to 'src/3rdparty/freetype/src/base/ftcalc.c')
-rw-r--r-- | src/3rdparty/freetype/src/base/ftcalc.c | 134 |
1 files changed, 107 insertions, 27 deletions
diff --git a/src/3rdparty/freetype/src/base/ftcalc.c b/src/3rdparty/freetype/src/base/ftcalc.c index c69b9f6c8..04295a693 100644 --- a/src/3rdparty/freetype/src/base/ftcalc.c +++ b/src/3rdparty/freetype/src/base/ftcalc.c @@ -33,10 +33,14 @@ #include <ft2build.h> +#include FT_GLYPH_H #include FT_INTERNAL_CALC_H #include FT_INTERNAL_DEBUG_H #include FT_INTERNAL_OBJECTS_H +#ifdef FT_MULFIX_INLINED +#undef FT_MulFix +#endif /* we need to define a 64-bits data type here */ @@ -192,15 +196,33 @@ FT_MulFix( FT_Long a, FT_Long b ) { +#ifdef FT_MULFIX_ASSEMBLER + + return FT_MULFIX_ASSEMBLER( a, b ); + +#else + FT_Int s = 1; FT_Long c; - if ( a < 0 ) { a = -a; s = -1; } - if ( b < 0 ) { b = -b; s = -s; } + if ( a < 0 ) + { + a = -a; + s = -1; + } + + if ( b < 0 ) + { + b = -b; + s = -s; + } c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 ); - return ( s > 0 ) ? c : -c ; + + return ( s > 0 ) ? c : -c; + +#endif /* FT_MULFIX_ASSEMBLER */ } @@ -412,31 +434,18 @@ FT_MulFix( FT_Long a, FT_Long b ) { - /* use inline assembly to speed up things a bit */ - -#if defined( __GNUC__ ) && defined( i386 ) - - FT_Long result; - - - __asm__ __volatile__ ( - "imul %%edx\n" - "movl %%edx, %%ecx\n" - "sarl $31, %%ecx\n" - "addl $0x8000, %%ecx\n" - "addl %%ecx, %%eax\n" - "adcl $0, %%edx\n" - "shrl $16, %%eax\n" - "shll $16, %%edx\n" - "addl %%edx, %%eax\n" - "mov %%eax, %0\n" - : "=a"(result), "+d"(b) - : "a"(a) - : "%ecx" - ); - return result; +#ifdef FT_MULFIX_ASSEMBLER -#elif 1 + return FT_MULFIX_ASSEMBLER( a, b ); + +#elif 0 + + /* + * This code is nonportable. See comment below. + * + * However, on a platform where right-shift of a signed quantity fills + * the leftmost bits by copying the sign bit, it might be faster. + */ FT_Long sa, sb; FT_ULong ua, ub; @@ -445,6 +454,24 @@ if ( a == 0 || b == 0x10000L ) return a; + /* + * This is a clever way of converting a signed number `a' into its + * absolute value (stored back into `a') and its sign. The sign is + * stored in `sa'; 0 means `a' was positive or zero, and -1 means `a' + * was negative. (Similarly for `b' and `sb'). + * + * Unfortunately, it doesn't work (at least not portably). + * + * It makes the assumption that right-shift on a negative signed value + * fills the leftmost bits by copying the sign bit. This is wrong. + * According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206, + * the result of right-shift of a negative signed value is + * implementation-defined. At least one implementation fills the + * leftmost bits with 0s (i.e., it is exactly the same as an unsigned + * right shift). This means that when `a' is negative, `sa' ends up + * with the value 1 rather than -1. After that, everything else goes + * wrong. + */ sa = ( a >> ( sizeof ( a ) * 8 - 1 ) ); a = ( a ^ sa ) - sa; sb = ( b >> ( sizeof ( b ) * 8 - 1 ) ); @@ -666,6 +693,59 @@ #endif /* FT_LONG64 */ + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( void ) + FT_Matrix_Multiply( const FT_Matrix* a, + FT_Matrix *b ) + { + FT_Fixed xx, xy, yx, yy; + + + if ( !a || !b ) + return; + + xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx ); + xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy ); + yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx ); + yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy ); + + b->xx = xx; b->xy = xy; + b->yx = yx; b->yy = yy; + } + + + /* documentation is in ftglyph.h */ + + FT_EXPORT_DEF( FT_Error ) + FT_Matrix_Invert( FT_Matrix* matrix ) + { + FT_Pos delta, xx, yy; + + + if ( !matrix ) + return FT_Err_Invalid_Argument; + + /* compute discriminant */ + delta = FT_MulFix( matrix->xx, matrix->yy ) - + FT_MulFix( matrix->xy, matrix->yx ); + + if ( !delta ) + return FT_Err_Invalid_Argument; /* matrix can't be inverted */ + + matrix->xy = - FT_DivFix( matrix->xy, delta ); + matrix->yx = - FT_DivFix( matrix->yx, delta ); + + xx = matrix->xx; + yy = matrix->yy; + + matrix->xx = FT_DivFix( yy, delta ); + matrix->yy = FT_DivFix( xx, delta ); + + return FT_Err_Ok; + } + + /* documentation is in ftcalc.h */ FT_BASE_DEF( void ) |