Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / modules / freetype2 / src / base / ftcalc.c
blob549427a863c45ec7ce1bf0c614596dd87eba370f
1 /***************************************************************************/
2 /* */
3 /* ftcalc.c */
4 /* */
5 /* Arithmetic computations (body). */
6 /* */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 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 /***************************************************************************/
18 /*************************************************************************/
19 /* */
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. */
22 /* */
23 /*************************************************************************/
25 /*************************************************************************/
26 /* */
27 /* Implementing basic computation routines. */
28 /* */
29 /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(), */
30 /* and FT_FloorFix() are declared in freetype.h. */
31 /* */
32 /*************************************************************************/
35 #include <ft2build.h>
36 #include FT_GLYPH_H
37 #include FT_INTERNAL_CALC_H
38 #include FT_INTERNAL_DEBUG_H
39 #include FT_INTERNAL_OBJECTS_H
42 /* we need to define a 64-bits data type here */
44 #ifdef FT_LONG64
46 typedef FT_INT64 FT_Int64;
48 #else
50 typedef struct FT_Int64_
52 FT_UInt32 lo;
53 FT_UInt32 hi;
55 } FT_Int64;
57 #endif /* FT_LONG64 */
60 /*************************************************************************/
61 /* */
62 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
63 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
64 /* messages during execution. */
65 /* */
66 #undef FT_COMPONENT
67 #define FT_COMPONENT trace_calc
70 /* The following three functions are available regardless of whether */
71 /* FT_LONG64 is defined. */
73 /* documentation is in freetype.h */
75 FT_EXPORT_DEF( FT_Fixed )
76 FT_RoundFix( FT_Fixed a )
78 return ( a >= 0 ) ? ( a + 0x8000L ) & ~0xFFFFL
79 : -((-a + 0x8000L ) & ~0xFFFFL );
83 /* documentation is in freetype.h */
85 FT_EXPORT_DEF( FT_Fixed )
86 FT_CeilFix( FT_Fixed a )
88 return ( a >= 0 ) ? ( a + 0xFFFFL ) & ~0xFFFFL
89 : -((-a + 0xFFFFL ) & ~0xFFFFL );
93 /* documentation is in freetype.h */
95 FT_EXPORT_DEF( FT_Fixed )
96 FT_FloorFix( FT_Fixed a )
98 return ( a >= 0 ) ? a & ~0xFFFFL
99 : -((-a) & ~0xFFFFL );
103 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
105 /* documentation is in ftcalc.h */
107 FT_EXPORT_DEF( FT_Int32 )
108 FT_Sqrt32( FT_Int32 x )
110 FT_ULong val, root, newroot, mask;
113 root = 0;
114 mask = 0x40000000L;
115 val = (FT_ULong)x;
119 newroot = root + mask;
120 if ( newroot <= val )
122 val -= newroot;
123 root = newroot + mask;
126 root >>= 1;
127 mask >>= 2;
129 } while ( mask != 0 );
131 return root;
134 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
137 #ifdef FT_LONG64
140 /* documentation is in freetype.h */
142 FT_EXPORT_DEF( FT_Long )
143 FT_MulDiv( FT_Long a,
144 FT_Long b,
145 FT_Long c )
147 FT_Int s;
148 FT_Long d;
151 s = 1;
152 if ( a < 0 ) { a = -a; s = -1; }
153 if ( b < 0 ) { b = -b; s = -s; }
154 if ( c < 0 ) { c = -c; s = -s; }
156 d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
157 : 0x7FFFFFFFL );
159 return ( s > 0 ) ? d : -d;
163 #ifdef TT_USE_BYTECODE_INTERPRETER
165 /* documentation is in ftcalc.h */
167 FT_BASE_DEF( FT_Long )
168 FT_MulDiv_No_Round( FT_Long a,
169 FT_Long b,
170 FT_Long c )
172 FT_Int s;
173 FT_Long d;
176 s = 1;
177 if ( a < 0 ) { a = -a; s = -1; }
178 if ( b < 0 ) { b = -b; s = -s; }
179 if ( c < 0 ) { c = -c; s = -s; }
181 d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
182 : 0x7FFFFFFFL );
184 return ( s > 0 ) ? d : -d;
187 #endif /* TT_USE_BYTECODE_INTERPRETER */
190 /* documentation is in freetype.h */
192 FT_EXPORT_DEF( FT_Long )
193 FT_MulFix( FT_Long a,
194 FT_Long b )
196 FT_Int s = 1;
197 FT_Long c;
200 if ( a < 0 ) { a = -a; s = -1; }
201 if ( b < 0 ) { b = -b; s = -s; }
203 c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
204 return ( s > 0 ) ? c : -c ;
208 /* documentation is in freetype.h */
210 FT_EXPORT_DEF( FT_Long )
211 FT_DivFix( FT_Long a,
212 FT_Long b )
214 FT_Int32 s;
215 FT_UInt32 q;
217 s = 1;
218 if ( a < 0 ) { a = -a; s = -1; }
219 if ( b < 0 ) { b = -b; s = -s; }
221 if ( b == 0 )
222 /* check for division by 0 */
223 q = 0x7FFFFFFFL;
224 else
225 /* compute result directly */
226 q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );
228 return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
232 #else /* !FT_LONG64 */
235 static void
236 ft_multo64( FT_UInt32 x,
237 FT_UInt32 y,
238 FT_Int64 *z )
240 FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2;
243 lo1 = x & 0x0000FFFFU; hi1 = x >> 16;
244 lo2 = y & 0x0000FFFFU; hi2 = y >> 16;
246 lo = lo1 * lo2;
247 i1 = lo1 * hi2;
248 i2 = lo2 * hi1;
249 hi = hi1 * hi2;
251 /* Check carry overflow of i1 + i2 */
252 i1 += i2;
253 hi += (FT_UInt32)( i1 < i2 ) << 16;
255 hi += i1 >> 16;
256 i1 = i1 << 16;
258 /* Check carry overflow of i1 + lo */
259 lo += i1;
260 hi += ( lo < i1 );
262 z->lo = lo;
263 z->hi = hi;
267 static FT_UInt32
268 ft_div64by32( FT_UInt32 hi,
269 FT_UInt32 lo,
270 FT_UInt32 y )
272 FT_UInt32 r, q;
273 FT_Int i;
276 q = 0;
277 r = hi;
279 if ( r >= y )
280 return (FT_UInt32)0x7FFFFFFFL;
282 i = 32;
285 r <<= 1;
286 q <<= 1;
287 r |= lo >> 31;
289 if ( r >= (FT_UInt32)y )
291 r -= y;
292 q |= 1;
294 lo <<= 1;
295 } while ( --i );
297 return q;
301 static void
302 FT_Add64( FT_Int64* x,
303 FT_Int64* y,
304 FT_Int64 *z )
306 register FT_UInt32 lo, hi;
309 lo = x->lo + y->lo;
310 hi = x->hi + y->hi + ( lo < x->lo );
312 z->lo = lo;
313 z->hi = hi;
317 /* documentation is in freetype.h */
319 /* The FT_MulDiv function has been optimized thanks to ideas from */
320 /* Graham Asher. The trick is to optimize computation when everything */
321 /* fits within 32-bits (a rather common case). */
322 /* */
323 /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */
324 /* */
325 /* 46340 is FLOOR(SQRT(2^31-1)). */
326 /* */
327 /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */
328 /* */
329 /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */
330 /* */
331 /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */
332 /* */
333 /* and 2*0x157F0 = 176096 */
334 /* */
336 FT_EXPORT_DEF( FT_Long )
337 FT_MulDiv( FT_Long a,
338 FT_Long b,
339 FT_Long c )
341 long s;
344 if ( a == 0 || b == c )
345 return a;
347 s = a; a = FT_ABS( a );
348 s ^= b; b = FT_ABS( b );
349 s ^= c; c = FT_ABS( c );
351 if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
352 a = ( a * b + ( c >> 1 ) ) / c;
354 else if ( c > 0 )
356 FT_Int64 temp, temp2;
359 ft_multo64( a, b, &temp );
361 temp2.hi = 0;
362 temp2.lo = (FT_UInt32)(c >> 1);
363 FT_Add64( &temp, &temp2, &temp );
364 a = ft_div64by32( temp.hi, temp.lo, c );
366 else
367 a = 0x7FFFFFFFL;
369 return ( s < 0 ? -a : a );
373 #ifdef TT_USE_BYTECODE_INTERPRETER
375 FT_BASE_DEF( FT_Long )
376 FT_MulDiv_No_Round( FT_Long a,
377 FT_Long b,
378 FT_Long c )
380 long s;
383 if ( a == 0 || b == c )
384 return a;
386 s = a; a = FT_ABS( a );
387 s ^= b; b = FT_ABS( b );
388 s ^= c; c = FT_ABS( c );
390 if ( a <= 46340L && b <= 46340L && c > 0 )
391 a = a * b / c;
393 else if ( c > 0 )
395 FT_Int64 temp;
398 ft_multo64( a, b, &temp );
399 a = ft_div64by32( temp.hi, temp.lo, c );
401 else
402 a = 0x7FFFFFFFL;
404 return ( s < 0 ? -a : a );
407 #endif /* TT_USE_BYTECODE_INTERPRETER */
410 /* documentation is in freetype.h */
412 FT_EXPORT_DEF( FT_Long )
413 FT_MulFix( FT_Long a,
414 FT_Long b )
416 /* use inline assembly to speed up things a bit */
418 #if defined( __GNUC__ ) && defined( i386 )
420 FT_Long result;
423 __asm__ __volatile__ (
424 "imul %%edx\n"
425 "movl %%edx, %%ecx\n"
426 "sarl $31, %%ecx\n"
427 "addl $0x8000, %%ecx\n"
428 "addl %%ecx, %%eax\n"
429 "adcl $0, %%edx\n"
430 "shrl $16, %%eax\n"
431 "shll $16, %%edx\n"
432 "addl %%edx, %%eax\n"
433 "mov %%eax, %0\n"
434 : "=a"(result), "+d"(b)
435 : "a"(a)
436 : "%ecx"
438 return result;
440 #elif 1
442 FT_Long sa, sb;
443 FT_ULong ua, ub;
446 if ( a == 0 || b == 0x10000L )
447 return a;
449 sa = ( a >> ( sizeof ( a ) * 8 - 1 ) );
450 a = ( a ^ sa ) - sa;
451 sb = ( b >> ( sizeof ( b ) * 8 - 1 ) );
452 b = ( b ^ sb ) - sb;
454 ua = (FT_ULong)a;
455 ub = (FT_ULong)b;
457 if ( ua <= 2048 && ub <= 1048576L )
458 ua = ( ua * ub + 0x8000U ) >> 16;
459 else
461 FT_ULong al = ua & 0xFFFFU;
464 ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
465 ( ( al * ( ub & 0xFFFFU ) + 0x8000U ) >> 16 );
468 sa ^= sb,
469 ua = (FT_ULong)(( ua ^ sa ) - sa);
471 return (FT_Long)ua;
473 #else /* 0 */
475 FT_Long s;
476 FT_ULong ua, ub;
479 if ( a == 0 || b == 0x10000L )
480 return a;
482 s = a; a = FT_ABS( a );
483 s ^= b; b = FT_ABS( b );
485 ua = (FT_ULong)a;
486 ub = (FT_ULong)b;
488 if ( ua <= 2048 && ub <= 1048576L )
489 ua = ( ua * ub + 0x8000UL ) >> 16;
490 else
492 FT_ULong al = ua & 0xFFFFUL;
495 ua = ( ua >> 16 ) * ub + al * ( ub >> 16 ) +
496 ( ( al * ( ub & 0xFFFFUL ) + 0x8000UL ) >> 16 );
499 return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
501 #endif /* 0 */
506 /* documentation is in freetype.h */
508 FT_EXPORT_DEF( FT_Long )
509 FT_DivFix( FT_Long a,
510 FT_Long b )
512 FT_Int32 s;
513 FT_UInt32 q;
516 s = a; a = FT_ABS( a );
517 s ^= b; b = FT_ABS( b );
519 if ( b == 0 )
521 /* check for division by 0 */
522 q = 0x7FFFFFFFL;
524 else if ( ( a >> 16 ) == 0 )
526 /* compute result directly */
527 q = (FT_UInt32)( (a << 16) + (b >> 1) ) / (FT_UInt32)b;
529 else
531 /* we need more bits; we have to do it by hand */
532 FT_Int64 temp, temp2;
534 temp.hi = (FT_Int32) (a >> 16);
535 temp.lo = (FT_UInt32)(a << 16);
536 temp2.hi = 0;
537 temp2.lo = (FT_UInt32)( b >> 1 );
538 FT_Add64( &temp, &temp2, &temp );
539 q = ft_div64by32( temp.hi, temp.lo, b );
542 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
546 #if 0
548 /* documentation is in ftcalc.h */
550 FT_EXPORT_DEF( void )
551 FT_MulTo64( FT_Int32 x,
552 FT_Int32 y,
553 FT_Int64 *z )
555 FT_Int32 s;
558 s = x; x = FT_ABS( x );
559 s ^= y; y = FT_ABS( y );
561 ft_multo64( x, y, z );
563 if ( s < 0 )
565 z->lo = (FT_UInt32)-(FT_Int32)z->lo;
566 z->hi = ~z->hi + !( z->lo );
571 /* apparently, the second version of this code is not compiled correctly */
572 /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */
574 #if 1
576 FT_EXPORT_DEF( FT_Int32 )
577 FT_Div64by32( FT_Int64* x,
578 FT_Int32 y )
580 FT_Int32 s;
581 FT_UInt32 q, r, i, lo;
584 s = x->hi;
585 if ( s < 0 )
587 x->lo = (FT_UInt32)-(FT_Int32)x->lo;
588 x->hi = ~x->hi + !x->lo;
590 s ^= y; y = FT_ABS( y );
592 /* Shortcut */
593 if ( x->hi == 0 )
595 if ( y > 0 )
596 q = x->lo / y;
597 else
598 q = 0x7FFFFFFFL;
600 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
603 r = x->hi;
604 lo = x->lo;
606 if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
607 return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
608 /* Return Max/Min Int32 if division overflow. */
609 /* This includes division by zero! */
610 q = 0;
611 for ( i = 0; i < 32; i++ )
613 r <<= 1;
614 q <<= 1;
615 r |= lo >> 31;
617 if ( r >= (FT_UInt32)y )
619 r -= y;
620 q |= 1;
622 lo <<= 1;
625 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
628 #else /* 0 */
630 FT_EXPORT_DEF( FT_Int32 )
631 FT_Div64by32( FT_Int64* x,
632 FT_Int32 y )
634 FT_Int32 s;
635 FT_UInt32 q;
638 s = x->hi;
639 if ( s < 0 )
641 x->lo = (FT_UInt32)-(FT_Int32)x->lo;
642 x->hi = ~x->hi + !x->lo;
644 s ^= y; y = FT_ABS( y );
646 /* Shortcut */
647 if ( x->hi == 0 )
649 if ( y > 0 )
650 q = ( x->lo + ( y >> 1 ) ) / y;
651 else
652 q = 0x7FFFFFFFL;
654 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
657 q = ft_div64by32( x->hi, x->lo, y );
659 return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
662 #endif /* 0 */
664 #endif /* 0 */
667 #endif /* FT_LONG64 */
670 /* documentation is in ftglyph.h */
672 FT_EXPORT_DEF( void )
673 FT_Matrix_Multiply( const FT_Matrix* a,
674 FT_Matrix *b )
676 FT_Fixed xx, xy, yx, yy;
679 if ( !a || !b )
680 return;
682 xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
683 xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
684 yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
685 yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
687 b->xx = xx; b->xy = xy;
688 b->yx = yx; b->yy = yy;
692 /* documentation is in ftglyph.h */
694 FT_EXPORT_DEF( FT_Error )
695 FT_Matrix_Invert( FT_Matrix* matrix )
697 FT_Pos delta, xx, yy;
700 if ( !matrix )
701 return FT_Err_Invalid_Argument;
703 /* compute discriminant */
704 delta = FT_MulFix( matrix->xx, matrix->yy ) -
705 FT_MulFix( matrix->xy, matrix->yx );
707 if ( !delta )
708 return FT_Err_Invalid_Argument; /* matrix can't be inverted */
710 matrix->xy = - FT_DivFix( matrix->xy, delta );
711 matrix->yx = - FT_DivFix( matrix->yx, delta );
713 xx = matrix->xx;
714 yy = matrix->yy;
716 matrix->xx = FT_DivFix( yy, delta );
717 matrix->yy = FT_DivFix( xx, delta );
719 return FT_Err_Ok;
723 /* documentation is in ftcalc.h */
725 FT_BASE_DEF( void )
726 FT_Matrix_Multiply_Scaled( const FT_Matrix* a,
727 FT_Matrix *b,
728 FT_Long scaling )
730 FT_Fixed xx, xy, yx, yy;
732 FT_Long val = 0x10000L * scaling;
735 if ( !a || !b )
736 return;
738 xx = FT_MulDiv( a->xx, b->xx, val ) + FT_MulDiv( a->xy, b->yx, val );
739 xy = FT_MulDiv( a->xx, b->xy, val ) + FT_MulDiv( a->xy, b->yy, val );
740 yx = FT_MulDiv( a->yx, b->xx, val ) + FT_MulDiv( a->yy, b->yx, val );
741 yy = FT_MulDiv( a->yx, b->xy, val ) + FT_MulDiv( a->yy, b->yy, val );
743 b->xx = xx; b->xy = xy;
744 b->yx = yx; b->yy = yy;
748 /* documentation is in ftcalc.h */
750 FT_BASE_DEF( void )
751 FT_Vector_Transform_Scaled( FT_Vector* vector,
752 const FT_Matrix* matrix,
753 FT_Long scaling )
755 FT_Pos xz, yz;
757 FT_Long val = 0x10000L * scaling;
760 if ( !vector || !matrix )
761 return;
763 xz = FT_MulDiv( vector->x, matrix->xx, val ) +
764 FT_MulDiv( vector->y, matrix->xy, val );
766 yz = FT_MulDiv( vector->x, matrix->yx, val ) +
767 FT_MulDiv( vector->y, matrix->yy, val );
769 vector->x = xz;
770 vector->y = yz;
774 /* documentation is in ftcalc.h */
776 FT_BASE_DEF( FT_Int32 )
777 FT_SqrtFixed( FT_Int32 x )
779 FT_UInt32 root, rem_hi, rem_lo, test_div;
780 FT_Int count;
783 root = 0;
785 if ( x > 0 )
787 rem_hi = 0;
788 rem_lo = x;
789 count = 24;
792 rem_hi = ( rem_hi << 2 ) | ( rem_lo >> 30 );
793 rem_lo <<= 2;
794 root <<= 1;
795 test_div = ( root << 1 ) + 1;
797 if ( rem_hi >= test_div )
799 rem_hi -= test_div;
800 root += 1;
802 } while ( --count );
805 return (FT_Int32)root;
809 /* documentation is in ftcalc.h */
811 FT_BASE_DEF( FT_Int )
812 ft_corner_orientation( FT_Pos in_x,
813 FT_Pos in_y,
814 FT_Pos out_x,
815 FT_Pos out_y )
817 FT_Int result;
820 /* deal with the trivial cases quickly */
821 if ( in_y == 0 )
823 if ( in_x >= 0 )
824 result = out_y;
825 else
826 result = -out_y;
828 else if ( in_x == 0 )
830 if ( in_y >= 0 )
831 result = -out_x;
832 else
833 result = out_x;
835 else if ( out_y == 0 )
837 if ( out_x >= 0 )
838 result = in_y;
839 else
840 result = -in_y;
842 else if ( out_x == 0 )
844 if ( out_y >= 0 )
845 result = -in_x;
846 else
847 result = in_x;
849 else /* general case */
851 #ifdef FT_LONG64
853 FT_Int64 delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
856 if ( delta == 0 )
857 result = 0;
858 else
859 result = 1 - 2 * ( delta < 0 );
861 #else
863 FT_Int64 z1, z2;
866 ft_multo64( in_x, out_y, &z1 );
867 ft_multo64( in_y, out_x, &z2 );
869 if ( z1.hi > z2.hi )
870 result = +1;
871 else if ( z1.hi < z2.hi )
872 result = -1;
873 else if ( z1.lo > z2.lo )
874 result = +1;
875 else if ( z1.lo < z2.lo )
876 result = -1;
877 else
878 result = 0;
880 #endif
883 return result;
887 /* documentation is in ftcalc.h */
889 FT_BASE_DEF( FT_Int )
890 ft_corner_is_flat( FT_Pos in_x,
891 FT_Pos in_y,
892 FT_Pos out_x,
893 FT_Pos out_y )
895 FT_Pos ax = in_x;
896 FT_Pos ay = in_y;
898 FT_Pos d_in, d_out, d_corner;
901 if ( ax < 0 )
902 ax = -ax;
903 if ( ay < 0 )
904 ay = -ay;
905 d_in = ax + ay;
907 ax = out_x;
908 if ( ax < 0 )
909 ax = -ax;
910 ay = out_y;
911 if ( ay < 0 )
912 ay = -ay;
913 d_out = ax + ay;
915 ax = out_x + in_x;
916 if ( ax < 0 )
917 ax = -ax;
918 ay = out_y + in_y;
919 if ( ay < 0 )
920 ay = -ay;
921 d_corner = ax + ay;
923 return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
927 /* END */