Home | History | Annotate | Line # | Download | only in internal
      1 /****************************************************************************
      2  *
      3  * ftcalc.h
      4  *
      5  *   Arithmetic computations (specification).
      6  *
      7  * Copyright (C) 1996-2020 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 <freetype/freetype.h>
     24 
     25 #include "compiler-macros.h"
     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 ::
    264    *     The first multiplier.
    265    *   b ::
    266    *     The second multiplier.
    267    *   c ::
    268    *     The divisor.
    269    *
    270    * @return:
    271    *   The result of '(a*b)/c'.  This function never traps when trying to
    272    *   divide by zero; it simply returns 'MaxInt' or 'MinInt' depending on
    273    *   the signs of 'a' and 'b'.
    274    */
    275   FT_BASE( FT_Long )
    276   FT_MulDiv_No_Round( FT_Long  a,
    277                       FT_Long  b,
    278                       FT_Long  c );
    279 
    280 
    281   /*
    282    * A variant of FT_Matrix_Multiply which scales its result afterwards.  The
    283    * idea is that both `a' and `b' are scaled by factors of 10 so that the
    284    * values are as precise as possible to get a correct result during the
    285    * 64bit multiplication.  Let `sa' and `sb' be the scaling factors of `a'
    286    * and `b', respectively, then the scaling factor of the result is `sa*sb'.
    287    */
    288   FT_BASE( void )
    289   FT_Matrix_Multiply_Scaled( const FT_Matrix*  a,
    290                              FT_Matrix        *b,
    291                              FT_Long           scaling );
    292 
    293 
    294   /*
    295    * Check a matrix.  If the transformation would lead to extreme shear or
    296    * extreme scaling, for example, return 0.  If everything is OK, return 1.
    297    *
    298    * Based on geometric considerations we use the following inequality to
    299    * identify a degenerate matrix.
    300    *
    301    *   50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
    302    *
    303    * Value 50 is heuristic.
    304    */
    305   FT_BASE( FT_Bool )
    306   FT_Matrix_Check( const FT_Matrix*  matrix );
    307 
    308 
    309   /*
    310    * A variant of FT_Vector_Transform.  See comments for
    311    * FT_Matrix_Multiply_Scaled.
    312    */
    313   FT_BASE( void )
    314   FT_Vector_Transform_Scaled( FT_Vector*        vector,
    315                               const FT_Matrix*  matrix,
    316                               FT_Long           scaling );
    317 
    318 
    319   /*
    320    * This function normalizes a vector and returns its original length.  The
    321    * normalized vector is a 16.16 fixed-point unit vector with length close
    322    * to 0x10000.  The accuracy of the returned length is limited to 16 bits
    323    * also.  The function utilizes quick inverse square root approximation
    324    * without divisions and square roots relying on Newton's iterations
    325    * instead.
    326    */
    327   FT_BASE( FT_UInt32 )
    328   FT_Vector_NormLen( FT_Vector*  vector );
    329 
    330 
    331   /*
    332    * Return -1, 0, or +1, depending on the orientation of a given corner.  We
    333    * use the Cartesian coordinate system, with positive vertical values going
    334    * upwards.  The function returns +1 if the corner turns to the left, -1 to
    335    * the right, and 0 for undecidable cases.
    336    */
    337   FT_BASE( FT_Int )
    338   ft_corner_orientation( FT_Pos  in_x,
    339                          FT_Pos  in_y,
    340                          FT_Pos  out_x,
    341                          FT_Pos  out_y );
    342 
    343 
    344   /*
    345    * Return TRUE if a corner is flat or nearly flat.  This is equivalent to
    346    * saying that the corner point is close to its neighbors, or inside an
    347    * ellipse defined by the neighbor focal points to be more precise.
    348    */
    349   FT_BASE( FT_Int )
    350   ft_corner_is_flat( FT_Pos  in_x,
    351                      FT_Pos  in_y,
    352                      FT_Pos  out_x,
    353                      FT_Pos  out_y );
    354 
    355 
    356   /*
    357    * Return the most significant bit index.
    358    */
    359 
    360 #ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
    361 
    362 #if defined( __GNUC__ )                                          && \
    363     ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )
    364 
    365 #if FT_SIZEOF_INT == 4
    366 
    367 #define FT_MSB( x )  ( 31 - __builtin_clz( x ) )
    368 
    369 #elif FT_SIZEOF_LONG == 4
    370 
    371 #define FT_MSB( x )  ( 31 - __builtin_clzl( x ) )
    372 
    373 #endif /* __GNUC__ */
    374 
    375 
    376 #elif defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
    377 
    378 #if FT_SIZEOF_INT == 4
    379 
    380 #include <intrin.h>
    381 #pragma intrinsic( _BitScanReverse )
    382 
    383   static __inline FT_Int32
    384   FT_MSB_i386( FT_UInt32  x )
    385   {
    386     unsigned long  where;
    387 
    388 
    389     _BitScanReverse( &where, x );
    390 
    391     return (FT_Int32)where;
    392   }
    393 
    394 #define FT_MSB( x )  ( FT_MSB_i386( x ) )
    395 
    396 #endif
    397 
    398 #endif /* _MSC_VER */
    399 
    400 
    401 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
    402 
    403 #ifndef FT_MSB
    404 
    405   FT_BASE( FT_Int )
    406   FT_MSB( FT_UInt32  z );
    407 
    408 #endif
    409 
    410 
    411   /*
    412    * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
    413    * two fixed-point arguments instead.
    414    */
    415   FT_BASE( FT_Fixed )
    416   FT_Hypot( FT_Fixed  x,
    417             FT_Fixed  y );
    418 
    419 
    420 #if 0
    421 
    422   /**************************************************************************
    423    *
    424    * @function:
    425    *   FT_SqrtFixed
    426    *
    427    * @description:
    428    *   Computes the square root of a 16.16 fixed-point value.
    429    *
    430    * @input:
    431    *   x ::
    432    *     The value to compute the root for.
    433    *
    434    * @return:
    435    *   The result of 'sqrt(x)'.
    436    *
    437    * @note:
    438    *   This function is not very fast.
    439    */
    440   FT_BASE( FT_Int32 )
    441   FT_SqrtFixed( FT_Int32  x );
    442 
    443 #endif /* 0 */
    444 
    445 
    446 #define INT_TO_F26DOT6( x )    ( (FT_Long)(x) * 64  )    /* << 6  */
    447 #define INT_TO_F2DOT14( x )    ( (FT_Long)(x) * 16384 )  /* << 14 */
    448 #define INT_TO_FIXED( x )      ( (FT_Long)(x) * 65536 )  /* << 16 */
    449 #define F2DOT14_TO_FIXED( x )  ( (FT_Long)(x) * 4 )      /* << 2  */
    450 #define FIXED_TO_INT( x )      ( FT_RoundFix( x ) >> 16 )
    451 
    452 #define ROUND_F26DOT6( x )     ( ( (x) + 32 - ( x < 0 ) ) & -64 )
    453 
    454   /*
    455    * The following macros have two purposes.
    456    *
    457    * - Tag places where overflow is expected and harmless.
    458    *
    459    * - Avoid run-time sanitizer errors.
    460    *
    461    * Use with care!
    462    */
    463 #define ADD_INT( a, b )                           \
    464           (FT_Int)( (FT_UInt)(a) + (FT_UInt)(b) )
    465 #define SUB_INT( a, b )                           \
    466           (FT_Int)( (FT_UInt)(a) - (FT_UInt)(b) )
    467 #define MUL_INT( a, b )                           \
    468           (FT_Int)( (FT_UInt)(a) * (FT_UInt)(b) )
    469 #define NEG_INT( a )                              \
    470           (FT_Int)( (FT_UInt)0 - (FT_UInt)(a) )
    471 
    472 #define ADD_LONG( a, b )                             \
    473           (FT_Long)( (FT_ULong)(a) + (FT_ULong)(b) )
    474 #define SUB_LONG( a, b )                             \
    475           (FT_Long)( (FT_ULong)(a) - (FT_ULong)(b) )
    476 #define MUL_LONG( a, b )                             \
    477           (FT_Long)( (FT_ULong)(a) * (FT_ULong)(b) )
    478 #define NEG_LONG( a )                                \
    479           (FT_Long)( (FT_ULong)0 - (FT_ULong)(a) )
    480 
    481 #define ADD_INT32( a, b )                               \
    482           (FT_Int32)( (FT_UInt32)(a) + (FT_UInt32)(b) )
    483 #define SUB_INT32( a, b )                               \
    484           (FT_Int32)( (FT_UInt32)(a) - (FT_UInt32)(b) )
    485 #define MUL_INT32( a, b )                               \
    486           (FT_Int32)( (FT_UInt32)(a) * (FT_UInt32)(b) )
    487 #define NEG_INT32( a )                                  \
    488           (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) )
    489 
    490 #ifdef FT_LONG64
    491 
    492 #define ADD_INT64( a, b )                               \
    493           (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) )
    494 #define SUB_INT64( a, b )                               \
    495           (FT_Int64)( (FT_UInt64)(a) - (FT_UInt64)(b) )
    496 #define MUL_INT64( a, b )                               \
    497           (FT_Int64)( (FT_UInt64)(a) * (FT_UInt64)(b) )
    498 #define NEG_INT64( a )                                  \
    499           (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) )
    500 
    501 #endif /* FT_LONG64 */
    502 
    503 
    504 FT_END_HEADER
    505 
    506 #endif /* FTCALC_H_ */
    507 
    508 
    509 /* END */
    510