aboutsummaryrefslogtreecommitdiffstats
path: root/include/core/SkScalar.h
blob: ebe621be4f5ca31932aa6bf02ebccabbbd54909b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SkScalar_DEFINED
#define SkScalar_DEFINED

#include "SkFixed.h"

/** \file SkScalar.h

    Types and macros for the data type SkScalar. This is the fractional numeric type
    that, depending on the compile-time flag SK_SCALAR_IS_FLOAT, may be implemented
    either as an IEEE float, or as a 16.16 SkFixed. The macros in this file are written
    to allow the calling code to manipulate SkScalar values without knowing which representation
    is in effect.
*/

#ifdef SK_SCALAR_IS_FLOAT
    #include "SkFloatingPoint.h"

    /** SkScalar is our type for fractional values and coordinates. Depending on
        compile configurations, it is either represented as an IEEE float, or
        as a 16.16 fixed point integer.
    */
    typedef float   SkScalar;
    extern const uint32_t gIEEENotANumber;
    extern const uint32_t gIEEEInfinity;

    /** SK_Scalar1 is defined to be 1.0 represented as an SkScalar
    */
    #define SK_Scalar1              (1.0f)
    /** SK_Scalar1 is defined to be 1/2 represented as an SkScalar
    */
    #define SK_ScalarHalf           (0.5f)
    /** SK_ScalarInfinity is defined to be infinity as an SkScalar
    */
    #define SK_ScalarInfinity           (*(const float*)&gIEEEInfinity)
    /** SK_ScalarMax is defined to be the largest value representable as an SkScalar
    */
    #define SK_ScalarMax            (3.402823466e+38f)
    /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar
    */
    #define SK_ScalarMin            (-SK_ScalarMax)
    /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar
    */
    #define SK_ScalarNaN      (*(const float*)(const void*)&gIEEENotANumber)
    /** SkScalarIsNaN(n) returns true if argument is not a number
    */
    static inline bool SkScalarIsNaN(float x) { return x != x; }
    /** Returns true if x is not NaN and not infinite */
    static inline bool SkScalarIsFinite(float x) {
        uint32_t bits = SkFloat2Bits(x);    // need unsigned for our shifts
        int exponent = bits << 1 >> 24;
        return exponent != 0xFF;
    }
    /** SkIntToScalar(n) returns its integer argument as an SkScalar
    */
    #define SkIntToScalar(n)        ((float)(n))
    /** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar
    */
    #define SkFixedToScalar(x)      SkFixedToFloat(x)
    /** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed
    */
    #define SkScalarToFixed(x)      SkFloatToFixed(x)

    #define SkScalarToFloat(n)      (n)
    #define SkFloatToScalar(n)      (n)

    #define SkScalarToDouble(n)      (double)(n)
    #define SkDoubleToScalar(n)      (float)(n)

    /** SkScalarFraction(x) returns the signed fractional part of the argument
    */
    #define SkScalarFraction(x)     sk_float_mod(x, 1.0f)
    /** Rounds the SkScalar to the nearest integer value
    */
    #define SkScalarRound(x)        sk_float_round2int(x)
    /** Returns the smallest integer that is >= the specified SkScalar
    */
    #define SkScalarCeil(x)         sk_float_ceil2int(x)
    /** Returns the largest integer that is <= the specified SkScalar
    */
    #define SkScalarFloor(x)        sk_float_floor2int(x)
    /** Returns the absolute value of the specified SkScalar
    */
    #define SkScalarAbs(x)          sk_float_abs(x)
    /** Return x with the sign of y
     */
    #define SkScalarCopySign(x, y)  sk_float_copysign(x, y)
    /** Returns the value pinned between 0 and max inclusive
    */
    inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) {
        return x < 0 ? 0 : x > max ? max : x;
    }
    /** Returns the value pinned between min and max inclusive
    */
    inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) {
        return x < min ? min : x > max ? max : x;
    }
    /** Returns the specified SkScalar squared (x*x)
    */
    inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
    /** Returns the product of two SkScalars
    */
    #define SkScalarMul(a, b)       ((float)(a) * (b))
    /** Returns the product of two SkScalars plus a third SkScalar
    */
    #define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c))
    /** Returns the product of a SkScalar and an int rounded to the nearest integer value
    */
    #define SkScalarMulRound(a, b) SkScalarRound((float)(a) * (b))
    /** Returns the product of a SkScalar and an int promoted to the next larger int
    */
    #define SkScalarMulCeil(a, b) SkScalarCeil((float)(a) * (b))
    /** Returns the product of a SkScalar and an int truncated to the next smaller int
    */
    #define SkScalarMulFloor(a, b) SkScalarFloor((float)(a) * (b))
    /** Returns the quotient of two SkScalars (a/b)
    */
    #define SkScalarDiv(a, b)       ((float)(a) / (b))
    /** Returns the mod of two SkScalars (a mod b)
    */
    #define SkScalarMod(x,y)        sk_float_mod(x,y)
    /** Returns the product of the first two arguments, divided by the third argument
    */
    #define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c))
    /** Returns the multiplicative inverse of the SkScalar (1/x)
    */
    #define SkScalarInvert(x)       (SK_Scalar1 / (x))
    #define SkScalarFastInvert(x)   (SK_Scalar1 / (x))
    /** Returns the square root of the SkScalar
    */
    #define SkScalarSqrt(x)         sk_float_sqrt(x)
    /** Returns the average of two SkScalars (a+b)/2
    */
    #define SkScalarAve(a, b)       (((a) + (b)) * 0.5f)
    /** Returns the geometric mean of two SkScalars
    */
    #define SkScalarMean(a, b)      sk_float_sqrt((float)(a) * (b))
    /** Returns one half of the specified SkScalar
    */
    #define SkScalarHalf(a)         ((a) * 0.5f)

    #define SK_ScalarSqrt2          1.41421356f
    #define SK_ScalarPI             3.14159265f
    #define SK_ScalarTanPIOver8     0.414213562f
    #define SK_ScalarRoot2Over2     0.707106781f

    #define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
    float SkScalarSinCos(SkScalar radians, SkScalar* cosValue);
    #define SkScalarSin(radians)    (float)sk_float_sin(radians)
    #define SkScalarCos(radians)    (float)sk_float_cos(radians)
    #define SkScalarTan(radians)    (float)sk_float_tan(radians)
    #define SkScalarASin(val)   (float)sk_float_asin(val)
    #define SkScalarACos(val)   (float)sk_float_acos(val)
    #define SkScalarATan2(y, x) (float)sk_float_atan2(y,x)
    #define SkScalarExp(x)  (float)sk_float_exp(x)
    #define SkScalarLog(x)  (float)sk_float_log(x)

    inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; }
    inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; }

    static inline bool SkScalarIsInt(SkScalar x) {
        return x == (float)(int)x;
    }
#else
    typedef SkFixed SkScalar;

    #define SK_Scalar1              SK_Fixed1
    #define SK_ScalarHalf           SK_FixedHalf
    #define SK_ScalarInfinity   SK_FixedMax
    #define SK_ScalarMax            SK_FixedMax
    #define SK_ScalarMin            SK_FixedMin
    #define SK_ScalarNaN            SK_FixedNaN
    #define SkScalarIsNaN(x)        ((x) == SK_FixedNaN)
    #define SkScalarIsFinite(x)     ((x) != SK_FixedNaN)

    #define SkIntToScalar(n)        SkIntToFixed(n)
    #define SkFixedToScalar(x)      (x)
    #define SkScalarToFixed(x)      (x)
    #ifdef SK_CAN_USE_FLOAT
        #define SkScalarToFloat(n)  SkFixedToFloat(n)
        #define SkFloatToScalar(n)  SkFloatToFixed(n)

        #define SkScalarToDouble(n) SkFixedToDouble(n)
        #define SkDoubleToScalar(n) SkDoubleToFixed(n)
    #endif
    #define SkScalarFraction(x)     SkFixedFraction(x)
    #define SkScalarRound(x)        SkFixedRound(x)
    #define SkScalarCeil(x)         SkFixedCeil(x)
    #define SkScalarFloor(x)        SkFixedFloor(x)
    #define SkScalarAbs(x)          SkFixedAbs(x)
    #define SkScalarCopySign(x, y)  SkCopySign32(x, y)
    #define SkScalarClampMax(x, max) SkClampMax(x, max)
    #define SkScalarPin(x, min, max) SkPin32(x, min, max)
    #define SkScalarSquare(x)       SkFixedSquare(x)
    #define SkScalarMul(a, b)       SkFixedMul(a, b)
    #define SkScalarMulAdd(a, b, c) SkFixedMulAdd(a, b, c)
    #define SkScalarMulRound(a, b)  SkFixedMulCommon(a, b, SK_FixedHalf)
    #define SkScalarMulCeil(a, b)   SkFixedMulCommon(a, b, SK_Fixed1 - 1)
    #define SkScalarMulFloor(a, b)  SkFixedMulCommon(a, b, 0)
    #define SkScalarDiv(a, b)       SkFixedDiv(a, b)
    #define SkScalarMod(a, b)       SkFixedMod(a, b)
    #define SkScalarMulDiv(a, b, c) SkMulDiv(a, b, c)
    #define SkScalarInvert(x)       SkFixedInvert(x)
    #define SkScalarFastInvert(x)   SkFixedFastInvert(x)
    #define SkScalarSqrt(x)         SkFixedSqrt(x)
    #define SkScalarAve(a, b)       SkFixedAve(a, b)
    #define SkScalarMean(a, b)      SkFixedMean(a, b)
    #define SkScalarHalf(a)         ((a) >> 1)

    #define SK_ScalarSqrt2          SK_FixedSqrt2
    #define SK_ScalarPI             SK_FixedPI
    #define SK_ScalarTanPIOver8     SK_FixedTanPIOver8
    #define SK_ScalarRoot2Over2     SK_FixedRoot2Over2

    #define SkDegreesToRadians(degrees)     SkFractMul(degrees, SK_FractPIOver180)
    #define SkScalarSinCos(radians, cosPtr) SkFixedSinCos(radians, cosPtr)
    #define SkScalarSin(radians)    SkFixedSin(radians)
    #define SkScalarCos(radians)    SkFixedCos(radians)
    #define SkScalarTan(val)        SkFixedTan(val)
    #define SkScalarASin(val)       SkFixedASin(val)
    #define SkScalarACos(val)       SkFixedACos(val)
    #define SkScalarATan2(y, x)     SkFixedATan2(y,x)
    #define SkScalarExp(x)          SkFixedExp(x)
    #define SkScalarLog(x)          SkFixedLog(x)

    #define SkMaxScalar(a, b)       SkMax32(a, b)
    #define SkMinScalar(a, b)       SkMin32(a, b)

    static inline bool SkScalarIsInt(SkFixed x) {
        return 0 == (x & 0xffff);
    }
#endif

#define SK_ScalarNearlyZero         (SK_Scalar1 / (1 << 12))

/*  <= is slower than < for floats, so we use < for our tolerance test
*/

static inline bool SkScalarNearlyZero(SkScalar x,
                                  SkScalar tolerance = SK_ScalarNearlyZero) {
    SkASSERT(tolerance > 0);
    return SkScalarAbs(x) < tolerance;
}

/** Linearly interpolate between A and B, based on t.
    If t is 0, return A
    If t is 1, return B
    else interpolate.
    t must be [0..SK_Scalar1]
*/
static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
    SkASSERT(t >= 0 && t <= SK_Scalar1);
    return A + SkScalarMul(B - A, t);
}

/** Interpolate along the function described by (keys[length], values[length])
    for the passed searchKey.  SearchKeys outside the range keys[0]-keys[Length]
    clamp to the min or max value.  This function was inspired by a desire
    to change the multiplier for thickness in fakeBold; therefore it assumes
    the number of pairs (length) will be small, and a linear search is used.
    Repeated keys are allowed for discontinuous functions (so long as keys is
    monotonically increasing), and if key is the value of a repeated scalar in
    keys, the first one will be used.  However, that may change if a binary
    search is used.
*/
SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
                            const SkScalar values[], int length);

#endif