Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkFDot6_DEFINED
      9 #define SkFDot6_DEFINED
     10 
     11 #include "SkFixed.h"
     12 #include "SkMath.h"
     13 #include "SkScalar.h"
     14 #include "SkTo.h"
     15 
     16 typedef int32_t SkFDot6;
     17 
     18 /* This uses the magic number approach suggested here:
     19  * http://stereopsis.com/sree/fpu2006.html and used in
     20  * _cairo_fixed_from_double. It does banker's rounding
     21  * (i.e. round to nearest even)
     22  */
     23 inline SkFDot6 SkScalarRoundToFDot6(SkScalar x, int shift = 0)
     24 {
     25     union {
     26         double  fDouble;
     27         int32_t fBits[2];
     28     } tmp;
     29     int fractionalBits = 6 + shift;
     30     double magic = (1LL << (52 - (fractionalBits))) * 1.5;
     31 
     32     tmp.fDouble = SkScalarToDouble(x) + magic;
     33 #ifdef SK_CPU_BENDIAN
     34     return tmp.fBits[1];
     35 #else
     36     return tmp.fBits[0];
     37 #endif
     38 }
     39 
     40 #define SK_FDot6One         (64)
     41 #define SK_FDot6Half        (32)
     42 
     43 #ifdef SK_DEBUG
     44     inline SkFDot6 SkIntToFDot6(int x) {
     45         SkASSERT(SkToS16(x) == x);
     46         return x << 6;
     47     }
     48 #else
     49     #define SkIntToFDot6(x) ((x) << 6)
     50 #endif
     51 
     52 #define SkFDot6Floor(x)     ((x) >> 6)
     53 #define SkFDot6Ceil(x)      (((x) + 63) >> 6)
     54 #define SkFDot6Round(x)     (((x) + 32) >> 6)
     55 
     56 #define SkFixedToFDot6(x)   ((x) >> 10)
     57 
     58 inline SkFixed SkFDot6ToFixed(SkFDot6 x) {
     59     SkASSERT((SkLeftShift(x, 10) >> 10) == x);
     60 
     61     return SkLeftShift(x, 10);
     62 }
     63 
     64 #define SkScalarToFDot6(x)  (SkFDot6)((x) * 64)
     65 #define SkFDot6ToScalar(x)  ((SkScalar)(x) * 0.015625f)
     66 #define SkFDot6ToFloat      SkFDot6ToScalar
     67 
     68 inline SkFixed SkFDot6Div(SkFDot6 a, SkFDot6 b) {
     69     SkASSERT(b != 0);
     70 
     71     if (a == (int16_t)a) {
     72         return SkLeftShift(a, 16) / b;
     73     } else {
     74         return SkFixedDiv(a, b);
     75     }
     76 }
     77 
     78 #endif
     79