1 /***************************************************************************/
   2 /*                                                                         */
   3 /*  ftcalc.h                                                               */
   4 /*                                                                         */
   5 /*    Arithmetic computations (specification).                             */
   6 /*                                                                         */
   7 /*  Copyright 1996-2018 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 
  27 FT_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     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     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     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     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    *  This function normalizes a vector and returns its original length.
 304    *  The normalized vector is a 16.16 fixed-point unit vector with length
 305    *  close to 0x10000.  The accuracy of the returned length is limited to
 306    *  16 bits also.  The function utilizes quick inverse square root
 307    *  approximation without divisions and square roots relying on Newton's
 308    *  iterations instead.
 309    */
 310   FT_BASE( FT_UInt32 )
 311   FT_Vector_NormLen( FT_Vector*  vector );
 312 
 313 
 314   /*
 315    *  Return -1, 0, or +1, depending on the orientation of a given corner.
 316    *  We use the Cartesian coordinate system, with positive vertical values
 317    *  going upwards.  The function returns +1 if the corner turns to the
 318    *  left, -1 to the right, and 0 for undecidable cases.
 319    */
 320   FT_BASE( FT_Int )
 321   ft_corner_orientation( FT_Pos  in_x,
 322                          FT_Pos  in_y,
 323                          FT_Pos  out_x,
 324                          FT_Pos  out_y );
 325 
 326 
 327   /*
 328    *  Return TRUE if a corner is flat or nearly flat.  This is equivalent to
 329    *  saying that the corner point is close to its neighbors, or inside an
 330    *  ellipse defined by the neighbor focal points to be more precise.
 331    */
 332   FT_BASE( FT_Int )
 333   ft_corner_is_flat( FT_Pos  in_x,
 334                      FT_Pos  in_y,
 335                      FT_Pos  out_x,
 336                      FT_Pos  out_y );
 337 
 338 
 339   /*
 340    *  Return the most significant bit index.
 341    */
 342 
 343 #ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
 344 #if defined( __GNUC__ )                                          && \
 345     ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )
 346 
 347 #if FT_SIZEOF_INT == 4
 348 
 349 #define FT_MSB( x )  ( 31 - __builtin_clz( x ) )
 350 
 351 #elif FT_SIZEOF_LONG == 4
 352 
 353 #define FT_MSB( x )  ( 31 - __builtin_clzl( x ) )
 354 
 355 #endif
 356 
 357 #endif /* __GNUC__ */
 358 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
 359 
 360 #ifndef FT_MSB
 361 
 362   FT_BASE( FT_Int )
 363   FT_MSB( FT_UInt32  z );
 364 
 365 #endif
 366 
 367 
 368   /*
 369    *  Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
 370    *  two fixed-point arguments instead.
 371    */
 372   FT_BASE( FT_Fixed )
 373   FT_Hypot( FT_Fixed  x,
 374             FT_Fixed  y );
 375 
 376 
 377 #if 0
 378 
 379   /*************************************************************************/
 380   /*                                                                       */
 381   /* <Function>                                                            */
 382   /*    FT_SqrtFixed                                                       */
 383   /*                                                                       */
 384   /* <Description>                                                         */
 385   /*    Computes the square root of a 16.16 fixed-point value.             */
 386   /*                                                                       */
 387   /* <Input>                                                               */
 388   /*    x :: The value to compute the root for.                            */
 389   /*                                                                       */
 390   /* <Return>                                                              */
 391   /*    The result of `sqrt(x)'.                                           */
 392   /*                                                                       */
 393   /* <Note>                                                                */
 394   /*    This function is not very fast.                                    */
 395   /*                                                                       */
 396   FT_BASE( FT_Int32 )
 397   FT_SqrtFixed( FT_Int32  x );
 398 
 399 #endif /* 0 */
 400 
 401 
 402 #define INT_TO_F26DOT6( x )    ( (FT_Long)(x) * 64  )    /* << 6  */
 403 #define INT_TO_F2DOT14( x )    ( (FT_Long)(x) * 16384 )  /* << 14 */
 404 #define INT_TO_FIXED( x )      ( (FT_Long)(x) * 65536 )  /* << 16 */
 405 #define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) * 4 )      /* << 2  */
 406 #define FIXED_TO_INT( x )      ( FT_RoundFix( x ) >> 16 )
 407 
 408 #define ROUND_F26DOT6( x )     ( x >= 0 ? (    ( (x) + 32 ) & -64 )     \
 409                                         : ( -( ( 32 - (x) ) & -64 ) ) )
 410 
 411   /*
 412    *  The following macros have two purposes.
 413    *
 414    *  . Tag places where overflow is expected and harmless.
 415    *
 416    *  . Avoid run-time sanitizer errors.
 417    *
 418    *  Use with care!
 419    */
 420 #define ADD_LONG( a, b )                             \
 421           (FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) )
 422 #define SUB_LONG( a, b )                             \
 423           (FT_Long)( (FT_ULong)(a) - (FT_ULong)(b) )
 424 #define MUL_LONG( a, b )                             \
 425           (FT_Long)( (FT_ULong)(a) * (FT_ULong)(b) )
 426 #define NEG_LONG( a )                                \
 427           (FT_Long)( (FT_ULong)0 - (FT_ULong)(a) )
 428 
 429 #define ADD_INT32( a, b )                               \
 430           (FT_Int32)( (FT_UInt32)(a) + (FT_UInt32)(b) )
 431 #define SUB_INT32( a, b )                               \
 432           (FT_Int32)( (FT_UInt32)(a) - (FT_UInt32)(b) )
 433 #define MUL_INT32( a, b )                               \
 434           (FT_Int32)( (FT_UInt32)(a) * (FT_UInt32)(b) )
 435 #define NEG_INT32( a )                                  \
 436           (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) )
 437 
 438 
 439 FT_END_HEADER
 440 
 441 #endif /* FTCALC_H_ */
 442 
 443 
 444 /* END */