1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  ftcalc.c                                                               */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    Arithmetic computations (body).                                      */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Copyright 1996-2006, 2008, 2012-2013 by                                */
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  This file is part of the FreeType project, and may only be used,       */
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  modified, and distributed under the terms of the FreeType project      */
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  this file you indicate that you have read the license and              */
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  understand and accept it fully.                                        */
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Support for 1-complement arithmetic has been totally dropped in this  */
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* release.  You can still write your own code if you need it.           */
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Implementing basic computation routines.                              */
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* FT_MulDiv(), FT_MulFix(), FT_DivFix(), FT_RoundFix(), FT_CeilFix(),   */
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* and FT_FloorFix() are declared in freetype.h.                         */
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h"
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/ftglyph.h"
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/fttrigon.h"
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftcalc.h"
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h"
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftobjs.h"
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* we need to emulate a 64-bit data type if a real one isn't available */
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_LONG64
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  typedef struct  FT_Int64_
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  lo;
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  hi;
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  } FT_Int64;
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* !FT_LONG64 */
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* messages during execution.                                            */
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef  FT_COMPONENT
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT  trace_calc
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* The following three functions are available regardless of whether */
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* FT_LONG64 is defined.                                             */
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Fixed )
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_RoundFix( FT_Fixed  a )
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( a >= 0 ) ?   ( a + 0x8000L ) & ~0xFFFFL
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      : -((-a + 0x8000L ) & ~0xFFFFL );
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Fixed )
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_CeilFix( FT_Fixed  a )
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( a >= 0 ) ?   ( a + 0xFFFFL ) & ~0xFFFFL
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      : -((-a + 0xFFFFL ) & ~0xFFFFL );
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Fixed )
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_FloorFix( FT_Fixed  a )
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( a >= 0 ) ?   a & ~0xFFFFL
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      : -((-a) & ~0xFFFFL );
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF ( FT_Int )
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MSB( FT_UInt32 z )
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int shift = 0;
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* determine msb bit index in `shift' */
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( z >= ( 1L << 16 ) )
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      z     >>= 16;
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift  += 16;
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( z >= ( 1L << 8 ) )
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      z     >>= 8;
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift  += 8;
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( z >= ( 1L << 4 ) )
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      z     >>= 4;
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift  += 4;
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( z >= ( 1L << 2 ) )
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      z     >>= 2;
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift  += 2;
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( z >= ( 1L << 1 ) )
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      z     >>= 1;
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift  += 1;
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return shift;
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Fixed )
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Hypot( FT_Fixed  x,
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Fixed  y )
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector  v;
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.x = x;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.y = y;
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Vector_Length( &v );
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_LONG64
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Long )
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MulDiv( FT_Long  a,
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  b,
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  c )
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int   s;
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long  d;
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s = 1;
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a < 0 ) { a = -a; s = -1; }
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( b < 0 ) { b = -b; s = -s; }
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( c < 0 ) { c = -c; s = -s; }
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         : 0x7FFFFFFFL );
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s > 0 ) ? d : -d;
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Long )
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MulDiv_No_Round( FT_Long  a,
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      FT_Long  b,
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      FT_Long  c )
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int   s;
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long  d;
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s = 1;
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a < 0 ) { a = -a; s = -1; }
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( b < 0 ) { b = -b; s = -s; }
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( c < 0 ) { c = -c; s = -s; }
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         : 0x7FFFFFFFL );
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s > 0 ) ? d : -d;
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   /* if defined FT_MULFIX_INLINED, use the inline FT_MULFIX_ASSEMBLER function. */
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_MULFIX_INLINED
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Long )
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MulFix( FT_Long  a,
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  b )
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_MULFIX_ASSEMBLER
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_MULFIX_ASSEMBLER( a, b );
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int   s = 1;
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long  c;
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a < 0 )
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = -a;
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      s = -1;
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( b < 0 )
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      b = -b;
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      s = -s;
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    c = (FT_Long)( ( (FT_Int64)a * b + 0x8000L ) >> 16 );
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s > 0 ) ? c : -c;
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_MULFIX_ASSEMBLER */
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  #endif/* FT_MULFIX_INLINED */
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Long )
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_DivFix( FT_Long  a,
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  b )
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int32   s;
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  q;
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s = 1;
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a < 0 )
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = -a;
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      s = -1;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( b < 0 )
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      b = -b;
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      s = -s;
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( b == 0 )
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* check for division by 0 */
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      q = 0x7FFFFFFFL;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* compute result directly */
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      q = (FT_UInt32)( ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b );
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* !FT_LONG64 */
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_multo64( FT_UInt32  x,
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_UInt32  y,
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_Int64  *z )
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo1 = x & 0x0000FFFFU;  hi1 = x >> 16;
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo2 = y & 0x0000FFFFU;  hi2 = y >> 16;
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo = lo1 * lo2;
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    i1 = lo1 * hi2;
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    i2 = lo2 * hi1;
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hi = hi1 * hi2;
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Check carry overflow of i1 + i2 */
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    i1 += i2;
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hi += (FT_UInt32)( i1 < i2 ) << 16;
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hi += i1 >> 16;
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    i1  = i1 << 16;
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Check carry overflow of i1 + lo */
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo += i1;
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hi += ( lo < i1 );
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z->lo = lo;
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z->hi = hi;
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_UInt32
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_div64by32( FT_UInt32  hi,
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_UInt32  lo,
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_UInt32  y )
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  r, q;
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int     i;
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    q = 0;
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    r = hi;
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( r >= y )
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return (FT_UInt32)0x7FFFFFFFL;
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    i = 32;
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    do
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      r <<= 1;
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      q <<= 1;
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      r  |= lo >> 31;
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( r >= y )
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        r -= y;
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        q |= 1;
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      lo <<= 1;
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } while ( --i );
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return q;
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Add64( FT_Int64*  x,
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Int64*  y,
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Int64  *z )
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    register FT_UInt32  lo, hi;
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo = x->lo + y->lo;
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hi = x->hi + y->hi + ( lo < x->lo );
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z->lo = lo;
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    z->hi = hi;
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* The FT_MulDiv function has been optimized thanks to ideas from      */
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* Graham Asher.  The trick is to optimize computation when everything */
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* fits within 32-bits (a rather common case).                         */
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*  we compute 'a*b+c/2', then divide it by 'c'. (positive values)     */
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*  46340 is FLOOR(SQRT(2^31-1)).                                      */
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*  if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 )         */
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*  0x7FFFFFFF - 0x7FFEA810 = 0x157F0                                  */
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*  if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF )                */
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*  and 2*0x157F0 = 176096                                             */
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                     */
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Long )
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MulDiv( FT_Long  a,
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  b,
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  c )
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    long  s;
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* XXX: this function does not allow 64-bit arguments */
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a == 0 || b == c )
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return a;
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s  = a; a = FT_ABS( a );
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= b; b = FT_ABS( b );
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= c; c = FT_ABS( c );
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a <= 46340L && b <= 46340L && c <= 176095L && c > 0 )
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = ( a * b + ( c >> 1 ) ) / c;
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( (FT_Int32)c > 0 )
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int64  temp, temp2;
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp2.hi = 0;
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp2.lo = (FT_UInt32)(c >> 1);
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Add64( &temp, &temp2, &temp );
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = 0x7FFFFFFFL;
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s < 0 ? -a : a );
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Long )
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MulDiv_No_Round( FT_Long  a,
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      FT_Long  b,
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      FT_Long  c )
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    long  s;
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a == 0 || b == c )
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return a;
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s  = a; a = FT_ABS( a );
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= b; b = FT_ABS( b );
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= c; c = FT_ABS( c );
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a <= 46340L && b <= 46340L && c > 0 )
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = a * b / c;
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( (FT_Int32)c > 0 )
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int64  temp;
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ft_multo64( (FT_Int32)a, (FT_Int32)b, &temp );
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = ft_div64by32( temp.hi, temp.lo, (FT_Int32)c );
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      a = 0x7FFFFFFFL;
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s < 0 ? -a : a );
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  #ifndef FT_MULFIX_INLINED
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Long )
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MulFix( FT_Long  a,
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  b )
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_MULFIX_ASSEMBLER
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_MULFIX_ASSEMBLER( a, b );
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#elif 0
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /*
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  This code is nonportable.  See comment below.
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  However, on a platform where right-shift of a signed quantity fills
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  the leftmost bits by copying the sign bit, it might be faster.
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     */
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long   sa, sb;
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  ua, ub;
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a == 0 || b == 0x10000L )
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return a;
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /*
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  This is a clever way of converting a signed number `a' into its
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  absolute value (stored back into `a') and its sign.  The sign is
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  stored in `sa'; 0 means `a' was positive or zero, and -1 means `a'
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  was negative.  (Similarly for `b' and `sb').
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  Unfortunately, it doesn't work (at least not portably).
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  It makes the assumption that right-shift on a negative signed value
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  fills the leftmost bits by copying the sign bit.  This is wrong.
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  According to K&R 2nd ed, section `A7.8 Shift Operators' on page 206,
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  the result of right-shift of a negative signed value is
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  implementation-defined.  At least one implementation fills the
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  leftmost bits with 0s (i.e., it is exactly the same as an unsigned
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  right shift).  This means that when `a' is negative, `sa' ends up
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  with the value 1 rather than -1.  After that, everything else goes
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *  wrong.
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     */
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    sa = ( a >> ( sizeof ( a ) * 8 - 1 ) );
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    a  = ( a ^ sa ) - sa;
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    sb = ( b >> ( sizeof ( b ) * 8 - 1 ) );
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    b  = ( b ^ sb ) - sb;
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ua = (FT_ULong)a;
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ub = (FT_ULong)b;
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ua <= 2048 && ub <= 1048576L )
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ua = ( ua * ub + 0x8000U ) >> 16;
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ULong  al = ua & 0xFFFFU;
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ua = ( ua >> 16 ) * ub +  al * ( ub >> 16 ) +
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           ( ( al * ( ub & 0xFFFFU ) + 0x8000U ) >> 16 );
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    sa ^= sb,
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ua  = (FT_ULong)(( ua ^ sa ) - sa);
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (FT_Long)ua;
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* 0 */
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long   s;
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_ULong  ua, ub;
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( a == 0 || b == 0x10000L )
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return a;
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s  = a; a = FT_ABS( a );
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= b; b = FT_ABS( b );
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ua = (FT_ULong)a;
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ub = (FT_ULong)b;
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ua <= 2048 && ub <= 1048576L )
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ua = ( ua * ub + 0x8000UL ) >> 16;
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_ULong  al = ua & 0xFFFFUL;
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ua = ( ua >> 16 ) * ub +  al * ( ub >> 16 ) +
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           ( ( al * ( ub & 0xFFFFUL ) + 0x8000UL ) >> 16 );
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s < 0 ? -(FT_Long)ua : (FT_Long)ua );
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* 0 */
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in freetype.h */
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Long )
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_DivFix( FT_Long  a,
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             FT_Long  b )
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int32   s;
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  q;
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* XXX: this function does not allow 64-bit arguments */
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s  = (FT_Int32)a; a = FT_ABS( a );
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= (FT_Int32)b; b = FT_ABS( b );
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( (FT_UInt32)b == 0 )
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* check for division by 0 */
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      q = (FT_UInt32)0x7FFFFFFFL;
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( ( a >> 16 ) == 0 )
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* compute result directly */
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      q = (FT_UInt32)( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / (FT_UInt32)b;
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* we need more bits; we have to do it by hand */
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int64  temp, temp2;
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp.hi  = (FT_Int32)( a >> 16 );
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp.lo  = (FT_UInt32)a << 16;
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp2.hi = 0;
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      temp2.lo = (FT_UInt32)( b >> 1 );
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Add64( &temp, &temp2, &temp );
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      q = ft_div64by32( temp.hi, temp.lo, (FT_Int32)b );
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if 0
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_MulTo64( FT_Int32   x,
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_Int32   y,
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              FT_Int64  *z )
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int32  s;
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s  = x; x = FT_ABS( x );
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= y; y = FT_ABS( y );
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_multo64( x, y, z );
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( s < 0 )
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      z->lo = (FT_UInt32)-(FT_Int32)z->lo;
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      z->hi = ~z->hi + !( z->lo );
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* apparently, the second version of this code is not compiled correctly */
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* on Mac machines with the MPW C compiler..  tsk, tsk, tsk...           */
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if 1
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Int32 )
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Div64by32( FT_Int64*  x,
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_Int32   y )
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int32   s;
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  q, r, i, lo;
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s  = x->hi;
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( s < 0 )
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      x->lo = (FT_UInt32)-(FT_Int32)x->lo;
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      x->hi = ~x->hi + !x->lo;
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= y;  y = FT_ABS( y );
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Shortcut */
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( x->hi == 0 )
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( y > 0 )
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        q = x->lo / y;
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        q = 0x7FFFFFFFL;
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    r  = x->hi;
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo = x->lo;
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL );
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             /* Return Max/Min Int32 if division overflow. */
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             /* This includes division by zero!            */
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    q = 0;
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( i = 0; i < 32; i++ )
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      r <<= 1;
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      q <<= 1;
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      r  |= lo >> 31;
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( r >= (FT_UInt32)y )
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        r -= y;
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        q |= 1;
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      lo <<= 1;
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* 0 */
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Int32 )
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Div64by32( FT_Int64*  x,
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                FT_Int32   y )
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int32   s;
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  q;
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s  = x->hi;
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( s < 0 )
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      x->lo = (FT_UInt32)-(FT_Int32)x->lo;
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      x->hi = ~x->hi + !x->lo;
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s ^= y;  y = FT_ABS( y );
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Shortcut */
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( x->hi == 0 )
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( y > 0 )
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        q = ( x->lo + ( y >> 1 ) ) / y;
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        q = 0x7FFFFFFFL;
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    q = ft_div64by32( x->hi, x->lo, y );
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s < 0 ? -(FT_Int32)q : (FT_Int32)q );
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* 0 */
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* 0 */
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_LONG64 */
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftglyph.h */
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Matrix_Multiply( const FT_Matrix*  a,
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      FT_Matrix        *b )
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed  xx, xy, yx, yy;
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !a || !b )
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return;
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    b->xx = xx;  b->xy = xy;
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    b->yx = yx;  b->yy = yy;
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftglyph.h */
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Error )
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Matrix_Invert( FT_Matrix*  matrix )
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pos  delta, xx, yy;
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !matrix )
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return FT_THROW( Invalid_Argument );
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* compute discriminant */
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    delta = FT_MulFix( matrix->xx, matrix->yy ) -
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_MulFix( matrix->xy, matrix->yx );
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !delta )
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return FT_THROW( Invalid_Argument );  /* matrix can't be inverted */
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    matrix->xy = - FT_DivFix( matrix->xy, delta );
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    matrix->yx = - FT_DivFix( matrix->yx, delta );
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xx = matrix->xx;
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    yy = matrix->yy;
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    matrix->xx = FT_DivFix( yy, delta );
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    matrix->yy = FT_DivFix( xx, delta );
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Err_Ok;
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( void )
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Matrix_Multiply_Scaled( const FT_Matrix*  a,
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             FT_Matrix        *b,
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             FT_Long           scaling )
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed  xx, xy, yx, yy;
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long   val = 0x10000L * scaling;
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !a || !b )
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return;
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xx = FT_MulDiv( a->xx, b->xx, val ) + FT_MulDiv( a->xy, b->yx, val );
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xy = FT_MulDiv( a->xx, b->xy, val ) + FT_MulDiv( a->xy, b->yy, val );
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    yx = FT_MulDiv( a->yx, b->xx, val ) + FT_MulDiv( a->yy, b->yx, val );
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    yy = FT_MulDiv( a->yx, b->xy, val ) + FT_MulDiv( a->yy, b->yy, val );
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    b->xx = xx;  b->xy = xy;
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    b->yx = yx;  b->yy = yy;
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( void )
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Vector_Transform_Scaled( FT_Vector*        vector,
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              const FT_Matrix*  matrix,
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              FT_Long           scaling )
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pos   xz, yz;
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long  val = 0x10000L * scaling;
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( !vector || !matrix )
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return;
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xz = FT_MulDiv( vector->x, matrix->xx, val ) +
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         FT_MulDiv( vector->y, matrix->xy, val );
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    yz = FT_MulDiv( vector->x, matrix->yx, val ) +
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         FT_MulDiv( vector->y, matrix->yy, val );
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vector->x = xz;
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vector->y = yz;
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Int32 )
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_SqrtFixed( FT_Int32  x )
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  root, rem_hi, rem_lo, test_div;
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int     count;
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    root = 0;
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( x > 0 )
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      rem_hi = 0;
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      rem_lo = x;
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      count  = 24;
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      do
834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rem_lo <<= 2;
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        root   <<= 1;
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        test_div = ( root << 1 ) + 1;
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ( rem_hi >= test_div )
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        {
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          rem_hi -= test_div;
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          root   += 1;
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      } while ( --count );
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (FT_Int32)root;
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Int )
855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_corner_orientation( FT_Pos  in_x,
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         FT_Pos  in_y,
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         FT_Pos  out_x,
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         FT_Pos  out_y )
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Long  result; /* avoid overflow on 16-bit system */
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* deal with the trivial cases quickly */
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( in_y == 0 )
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( in_x >= 0 )
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = out_y;
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = -out_y;
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( in_x == 0 )
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( in_y >= 0 )
874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = -out_x;
875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = out_x;
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( out_y == 0 )
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( out_x >= 0 )
881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = in_y;
882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = -in_y;
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( out_x == 0 )
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( out_y >= 0 )
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = -in_x;
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result =  in_x;
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else /* general case */
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_LONG64
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int64  delta = (FT_Int64)in_x * out_y - (FT_Int64)in_y * out_x;
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( delta == 0 )
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = 0;
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = 1 - 2 * ( delta < 0 );
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      FT_Int64  z1, z2;
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      /* XXX: this function does not allow 64-bit arguments */
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ft_multo64( (FT_Int32)in_x, (FT_Int32)out_y, &z1 );
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ft_multo64( (FT_Int32)in_y, (FT_Int32)out_x, &z2 );
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( z1.hi > z2.hi )
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = +1;
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( z1.hi < z2.hi )
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = -1;
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( z1.lo > z2.lo )
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = +1;
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else if ( z1.lo < z2.lo )
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = -1;
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        result = 0;
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* XXX: only the sign of return value, +1/0/-1 must be used */
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (FT_Int)result;
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in ftcalc.h */
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_BASE_DEF( FT_Int )
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_corner_is_flat( FT_Pos  in_x,
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_Pos  in_y,
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_Pos  out_x,
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     FT_Pos  out_y )
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pos  ax = in_x;
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pos  ay = in_y;
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pos  d_in, d_out, d_corner;
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ax < 0 )
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ax = -ax;
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ay < 0 )
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ay = -ay;
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    d_in = ax + ay;
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ax = out_x;
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ax < 0 )
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ax = -ax;
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ay = out_y;
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ay < 0 )
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ay = -ay;
958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    d_out = ax + ay;
959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ax = out_x + in_x;
961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ax < 0 )
962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ax = -ax;
963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ay = out_y + in_y;
964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( ay < 0 )
965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ay = -ay;
966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    d_corner = ax + ay;
967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );
969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */
973