1/***************************************************************************/
2/*                                                                         */
3/*  ftcalc.h                                                               */
4/*                                                                         */
5/*    Arithmetic computations (specification).                             */
6/*                                                                         */
7/*  Copyright 1996-2015 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/***************************************************************************/
17
18
19#ifndef __FTCALC_H__
20#define __FTCALC_H__
21
22
23#include <ft2build.h>
24#include FT_FREETYPE_H
25
26
27FT_BEGIN_HEADER
28
29
30  /*************************************************************************/
31  /*                                                                       */
32  /* FT_MulDiv() and FT_MulFix() are declared in freetype.h.               */
33  /*                                                                       */
34  /*************************************************************************/
35
36#ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
37  /* Provide assembler fragments for performance-critical functions. */
38  /* These must be defined `static __inline__' with GCC.             */
39
40#if defined( __CC_ARM ) || defined( __ARMCC__ )  /* RVCT */
41
42#define FT_MULFIX_ASSEMBLER  FT_MulFix_arm
43
44  /* documentation is in freetype.h */
45
46  static __inline FT_Int32
47  FT_MulFix_arm( FT_Int32  a,
48                 FT_Int32  b )
49  {
50    register FT_Int32  t, t2;
51
52
53    __asm
54    {
55      smull t2, t,  b,  a           /* (lo=t2,hi=t) = a*b */
56      mov   a,  t,  asr #31         /* a   = (hi >> 31) */
57      add   a,  a,  #0x8000         /* a  += 0x8000 */
58      adds  t2, t2, a               /* t2 += a */
59      adc   t,  t,  #0              /* t  += carry */
60      mov   a,  t2, lsr #16         /* a   = t2 >> 16 */
61      orr   a,  a,  t,  lsl #16     /* a  |= t << 16 */
62    }
63    return a;
64  }
65
66#endif /* __CC_ARM || __ARMCC__ */
67
68
69#ifdef __GNUC__
70
71#if defined( __arm__ )                                 && \
72    ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \
73    !( defined( __CC_ARM ) || defined( __ARMCC__ ) )
74
75#define FT_MULFIX_ASSEMBLER  FT_MulFix_arm
76
77  /* documentation is in freetype.h */
78
79  static __inline__ FT_Int32
80  FT_MulFix_arm( FT_Int32  a,
81                 FT_Int32  b )
82  {
83    register FT_Int32  t, t2;
84
85
86    __asm__ __volatile__ (
87      "smull  %1, %2, %4, %3\n\t"       /* (lo=%1,hi=%2) = a*b */
88      "mov    %0, %2, asr #31\n\t"      /* %0  = (hi >> 31) */
89#if defined( __clang__ ) && defined( __thumb2__ )
90      "add.w  %0, %0, #0x8000\n\t"      /* %0 += 0x8000 */
91#else
92      "add    %0, %0, #0x8000\n\t"      /* %0 += 0x8000 */
93#endif
94      "adds   %1, %1, %0\n\t"           /* %1 += %0 */
95      "adc    %2, %2, #0\n\t"           /* %2 += carry */
96      "mov    %0, %1, lsr #16\n\t"      /* %0  = %1 >> 16 */
97      "orr    %0, %0, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
98      : "=r"(a), "=&r"(t2), "=&r"(t)
99      : "r"(a), "r"(b)
100      : "cc" );
101    return a;
102  }
103
104#endif /* __arm__                      && */
105       /* ( __thumb2__ || !__thumb__ ) && */
106       /* !( __CC_ARM || __ARMCC__ )      */
107
108
109#if defined( __i386__ )
110
111#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386
112
113  /* documentation is in freetype.h */
114
115  static __inline__ FT_Int32
116  FT_MulFix_i386( FT_Int32  a,
117                  FT_Int32  b )
118  {
119    register FT_Int32  result;
120
121
122    __asm__ __volatile__ (
123      "imul  %%edx\n"
124      "movl  %%edx, %%ecx\n"
125      "sarl  $31, %%ecx\n"
126      "addl  $0x8000, %%ecx\n"
127      "addl  %%ecx, %%eax\n"
128      "adcl  $0, %%edx\n"
129      "shrl  $16, %%eax\n"
130      "shll  $16, %%edx\n"
131      "addl  %%edx, %%eax\n"
132      : "=a"(result), "=d"(b)
133      : "a"(a), "d"(b)
134      : "%ecx", "cc" );
135    return result;
136  }
137
138#endif /* i386 */
139
140#endif /* __GNUC__ */
141
142
143#ifdef _MSC_VER /* Visual C++ */
144
145#ifdef _M_IX86
146
147#define FT_MULFIX_ASSEMBLER  FT_MulFix_i386
148
149  /* documentation is in freetype.h */
150
151  static __inline FT_Int32
152  FT_MulFix_i386( FT_Int32  a,
153                  FT_Int32  b )
154  {
155    register FT_Int32  result;
156
157    __asm
158    {
159      mov eax, a
160      mov edx, b
161      imul edx
162      mov ecx, edx
163      sar ecx, 31
164      add ecx, 8000h
165      add eax, ecx
166      adc edx, 0
167      shr eax, 16
168      shl edx, 16
169      add eax, edx
170      mov result, eax
171    }
172    return result;
173  }
174
175#endif /* _M_IX86 */
176
177#endif /* _MSC_VER */
178
179
180#if defined( __GNUC__ ) && defined( __x86_64__ )
181
182#define FT_MULFIX_ASSEMBLER  FT_MulFix_x86_64
183
184  static __inline__ FT_Int32
185  FT_MulFix_x86_64( FT_Int32  a,
186                    FT_Int32  b )
187  {
188    /* Temporarily disable the warning that C90 doesn't support */
189    /* `long long'.                                             */
190#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 )
191#pragma GCC diagnostic push
192#pragma GCC diagnostic ignored "-Wlong-long"
193#endif
194
195#if 1
196    /* Technically not an assembly fragment, but GCC does a really good */
197    /* job at inlining it and generating good machine code for it.      */
198    long long  ret, tmp;
199
200
201    ret  = (long long)a * b;
202    tmp  = ret >> 63;
203    ret += 0x8000 + tmp;
204
205    return (FT_Int32)( ret >> 16 );
206#else
207
208    /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine  */
209    /* code from the lines below.  The main issue is that `wide_a' is not  */
210    /* properly initialized by sign-extending `a'.  Instead, the generated */
211    /* machine code assumes that the register that contains `a' on input   */
212    /* can be used directly as a 64-bit value, which is wrong most of the  */
213    /* time.                                                               */
214    long long  wide_a = (long long)a;
215    long long  wide_b = (long long)b;
216    long long  result;
217
218
219    __asm__ __volatile__ (
220      "imul %2, %1\n"
221      "mov %1, %0\n"
222      "sar $63, %0\n"
223      "lea 0x8000(%1, %0), %0\n"
224      "sar $16, %0\n"
225      : "=&r"(result), "=&r"(wide_a)
226      : "r"(wide_b)
227      : "cc" );
228
229    return (FT_Int32)result;
230#endif
231
232#if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 )
233#pragma GCC diagnostic pop
234#endif
235  }
236
237#endif /* __GNUC__ && __x86_64__ */
238
239#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
240
241
242#ifdef FT_CONFIG_OPTION_INLINE_MULFIX
243#ifdef FT_MULFIX_ASSEMBLER
244#define FT_MulFix( a, b )  FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) )
245#endif
246#endif
247
248
249  /*************************************************************************/
250  /*                                                                       */
251  /* <Function>                                                            */
252  /*    FT_MulDiv_No_Round                                                 */
253  /*                                                                       */
254  /* <Description>                                                         */
255  /*    A very simple function used to perform the computation `(a*b)/c'   */
256  /*    (without rounding) with maximum accuracy (it uses a 64-bit         */
257  /*    intermediate integer whenever necessary).                          */
258  /*                                                                       */
259  /*    This function isn't necessarily as fast as some processor specific */
260  /*    operations, but is at least completely portable.                   */
261  /*                                                                       */
262  /* <Input>                                                               */
263  /*    a :: The first multiplier.                                         */
264  /*    b :: The second multiplier.                                        */
265  /*    c :: The divisor.                                                  */
266  /*                                                                       */
267  /* <Return>                                                              */
268  /*    The result of `(a*b)/c'.  This function never traps when trying to */
269  /*    divide by zero; it simply returns `MaxInt' or `MinInt' depending   */
270  /*    on the signs of `a' and `b'.                                       */
271  /*                                                                       */
272  FT_BASE( FT_Long )
273  FT_MulDiv_No_Round( FT_Long  a,
274                      FT_Long  b,
275                      FT_Long  c );
276
277
278  /*
279   *  A variant of FT_Matrix_Multiply which scales its result afterwards.
280   *  The idea is that both `a' and `b' are scaled by factors of 10 so that
281   *  the values are as precise as possible to get a correct result during
282   *  the 64bit multiplication.  Let `sa' and `sb' be the scaling factors of
283   *  `a' and `b', respectively, then the scaling factor of the result is
284   *  `sa*sb'.
285   */
286  FT_BASE( void )
287  FT_Matrix_Multiply_Scaled( const FT_Matrix*  a,
288                             FT_Matrix        *b,
289                             FT_Long           scaling );
290
291
292  /*
293   *  A variant of FT_Vector_Transform.  See comments for
294   *  FT_Matrix_Multiply_Scaled.
295   */
296  FT_BASE( void )
297  FT_Vector_Transform_Scaled( FT_Vector*        vector,
298                              const FT_Matrix*  matrix,
299                              FT_Long           scaling );
300
301
302  /*
303   *  Return -1, 0, or +1, depending on the orientation of a given corner.
304   *  We use the Cartesian coordinate system, with positive vertical values
305   *  going upwards.  The function returns +1 if the corner turns to the
306   *  left, -1 to the right, and 0 for undecidable cases.
307   */
308  FT_BASE( FT_Int )
309  ft_corner_orientation( FT_Pos  in_x,
310                         FT_Pos  in_y,
311                         FT_Pos  out_x,
312                         FT_Pos  out_y );
313
314
315  /*
316   *  Return TRUE if a corner is flat or nearly flat.  This is equivalent to
317   *  saying that the corner point is close to its neighbors, or inside an
318   *  ellipse defined by the neighbor focal points to be more precise.
319   */
320  FT_BASE( FT_Int )
321  ft_corner_is_flat( FT_Pos  in_x,
322                     FT_Pos  in_y,
323                     FT_Pos  out_x,
324                     FT_Pos  out_y );
325
326
327  /*
328   *  Return the most significant bit index.
329   */
330
331#ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
332#if defined( __GNUC__ )                                          && \
333    ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )
334
335#if FT_SIZEOF_INT == 4
336
337#define FT_MSB( x )  ( 31 - __builtin_clz( x ) )
338
339#elif FT_SIZEOF_LONG == 4
340
341#define FT_MSB( x )  ( 31 - __builtin_clzl( x ) )
342
343#endif
344
345#endif /* __GNUC__ */
346#endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
347
348#ifndef FT_MSB
349
350  FT_BASE( FT_Int )
351  FT_MSB( FT_UInt32  z );
352
353#endif
354
355
356  /*
357   *  Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
358   *  two fixed-point arguments instead.
359   */
360  FT_BASE( FT_Fixed )
361  FT_Hypot( FT_Fixed  x,
362            FT_Fixed  y );
363
364
365#if 0
366
367  /*************************************************************************/
368  /*                                                                       */
369  /* <Function>                                                            */
370  /*    FT_SqrtFixed                                                       */
371  /*                                                                       */
372  /* <Description>                                                         */
373  /*    Computes the square root of a 16.16 fixed-point value.             */
374  /*                                                                       */
375  /* <Input>                                                               */
376  /*    x :: The value to compute the root for.                            */
377  /*                                                                       */
378  /* <Return>                                                              */
379  /*    The result of `sqrt(x)'.                                           */
380  /*                                                                       */
381  /* <Note>                                                                */
382  /*    This function is not very fast.                                    */
383  /*                                                                       */
384  FT_BASE( FT_Int32 )
385  FT_SqrtFixed( FT_Int32  x );
386
387#endif /* 0 */
388
389
390#define INT_TO_F26DOT6( x )    ( (FT_Long)(x) << 6  )
391#define INT_TO_F2DOT14( x )    ( (FT_Long)(x) << 14 )
392#define INT_TO_FIXED( x )      ( (FT_Long)(x) << 16 )
393#define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) << 2  )
394#define FLOAT_TO_FIXED( x )    ( (FT_Long)( x * 65536.0 ) )
395#define FIXED_TO_INT( x )      ( FT_RoundFix( x ) >> 16 )
396
397#define ROUND_F26DOT6( x )     ( x >= 0 ? (    ( (x) + 32 ) & -64 )     \
398                                        : ( -( ( 32 - (x) ) & -64 ) ) )
399
400
401FT_END_HEADER
402
403#endif /* __FTCALC_H__ */
404
405
406/* END */
407