1/* libs/graphics/animator/SkDisplayMath.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkDisplayMath.h"
19
20enum SkDisplayMath_Properties {
21    SK_PROPERTY(E),
22    SK_PROPERTY(LN10),
23    SK_PROPERTY(LN2),
24    SK_PROPERTY(LOG10E),
25    SK_PROPERTY(LOG2E),
26    SK_PROPERTY(PI),
27    SK_PROPERTY(SQRT1_2),
28    SK_PROPERTY(SQRT2)
29};
30
31const SkScalar SkDisplayMath::gConstants[] = {
32#ifdef SK_SCALAR_IS_FLOAT
33    2.718281828f,   // E
34    2.302585093f,   // LN10
35    0.693147181f,   // LN2
36    0.434294482f,   // LOG10E
37    1.442695041f,   // LOG2E
38    3.141592654f,   // PI
39    0.707106781f,   // SQRT1_2
40    1.414213562f        // SQRT2
41#else
42    0x2B7E1,    // E
43    0x24D76,    // LN10
44    0xB172,     // LN2
45    0x6F2E,     // LOG10E
46    0x17154,    // LOG2E
47    0x3243F,    // PI
48    0xB505,     // SQRT1_2
49    0x16A0A // SQRT2
50#endif
51};
52
53enum SkDisplayMath_Functions {
54    SK_FUNCTION(abs),
55    SK_FUNCTION(acos),
56    SK_FUNCTION(asin),
57    SK_FUNCTION(atan),
58    SK_FUNCTION(atan2),
59    SK_FUNCTION(ceil),
60    SK_FUNCTION(cos),
61    SK_FUNCTION(exp),
62    SK_FUNCTION(floor),
63    SK_FUNCTION(log),
64    SK_FUNCTION(max),
65    SK_FUNCTION(min),
66    SK_FUNCTION(pow),
67    SK_FUNCTION(random),
68    SK_FUNCTION(round),
69    SK_FUNCTION(sin),
70    SK_FUNCTION(sqrt),
71    SK_FUNCTION(tan)
72};
73
74const SkFunctionParamType SkDisplayMath::fFunctionParameters[] = {
75    (SkFunctionParamType) SkType_Float, // abs
76    (SkFunctionParamType) 0,
77    (SkFunctionParamType) SkType_Float, // acos
78    (SkFunctionParamType) 0,
79    (SkFunctionParamType) SkType_Float, // asin
80    (SkFunctionParamType) 0,
81    (SkFunctionParamType) SkType_Float, // atan
82    (SkFunctionParamType) 0,
83    (SkFunctionParamType) SkType_Float, // atan2
84    (SkFunctionParamType) SkType_Float,
85    (SkFunctionParamType) 0,
86    (SkFunctionParamType) SkType_Float, // ceil
87    (SkFunctionParamType) 0,
88    (SkFunctionParamType) SkType_Float, // cos
89    (SkFunctionParamType) 0,
90    (SkFunctionParamType) SkType_Float, // exp
91    (SkFunctionParamType) 0,
92    (SkFunctionParamType) SkType_Float, // floor
93    (SkFunctionParamType) 0,
94    (SkFunctionParamType) SkType_Float, // log
95    (SkFunctionParamType) 0,
96    (SkFunctionParamType) SkType_Array, // max
97    (SkFunctionParamType) 0,
98    (SkFunctionParamType) SkType_Array, // min
99    (SkFunctionParamType) 0,
100    (SkFunctionParamType) SkType_Float, // pow
101    (SkFunctionParamType) SkType_Float,
102    (SkFunctionParamType) 0,
103    (SkFunctionParamType) SkType_Float, // random
104    (SkFunctionParamType) 0,
105    (SkFunctionParamType) SkType_Float, // round
106    (SkFunctionParamType) 0,
107    (SkFunctionParamType) SkType_Float, // sin
108    (SkFunctionParamType) 0,
109    (SkFunctionParamType) SkType_Float, // sqrt
110    (SkFunctionParamType) 0,
111    (SkFunctionParamType) SkType_Float, // tan
112    (SkFunctionParamType) 0
113};
114
115#if SK_USE_CONDENSED_INFO == 0
116
117const SkMemberInfo SkDisplayMath::fInfo[] = {
118    SK_MEMBER_PROPERTY(E, Float),
119    SK_MEMBER_PROPERTY(LN10, Float),
120    SK_MEMBER_PROPERTY(LN2, Float),
121    SK_MEMBER_PROPERTY(LOG10E, Float),
122    SK_MEMBER_PROPERTY(LOG2E, Float),
123    SK_MEMBER_PROPERTY(PI, Float),
124    SK_MEMBER_PROPERTY(SQRT1_2, Float),
125    SK_MEMBER_PROPERTY(SQRT2, Float),
126    SK_MEMBER_FUNCTION(abs, Float),
127    SK_MEMBER_FUNCTION(acos, Float),
128    SK_MEMBER_FUNCTION(asin, Float),
129    SK_MEMBER_FUNCTION(atan, Float),
130    SK_MEMBER_FUNCTION(atan2, Float),
131    SK_MEMBER_FUNCTION(ceil, Float),
132    SK_MEMBER_FUNCTION(cos, Float),
133    SK_MEMBER_FUNCTION(exp, Float),
134    SK_MEMBER_FUNCTION(floor, Float),
135    SK_MEMBER_FUNCTION(log, Float),
136    SK_MEMBER_FUNCTION(max, Float),
137    SK_MEMBER_FUNCTION(min, Float),
138    SK_MEMBER_FUNCTION(pow, Float),
139    SK_MEMBER_FUNCTION(random, Float),
140    SK_MEMBER_FUNCTION(round, Float),
141    SK_MEMBER_FUNCTION(sin, Float),
142    SK_MEMBER_FUNCTION(sqrt, Float),
143    SK_MEMBER_FUNCTION(tan, Float)
144};
145
146#endif
147
148DEFINE_GET_MEMBER(SkDisplayMath);
149
150void SkDisplayMath::executeFunction(SkDisplayable* target, int index,
151        SkTDArray<SkScriptValue>& parameters, SkDisplayTypes type,
152        SkScriptValue* scriptValue) {
153    if (scriptValue == NULL)
154        return;
155    SkASSERT(target == this);
156    SkScriptValue* array = parameters.begin();
157    SkScriptValue* end = parameters.end();
158    SkScalar input = parameters[0].fOperand.fScalar;
159    SkScalar scalarResult;
160    switch (index) {
161        case SK_FUNCTION(abs):
162            scalarResult = SkScalarAbs(input);
163            break;
164        case SK_FUNCTION(acos):
165            scalarResult = SkScalarACos(input);
166            break;
167        case SK_FUNCTION(asin):
168            scalarResult = SkScalarASin(input);
169            break;
170        case SK_FUNCTION(atan):
171            scalarResult = SkScalarATan2(input, SK_Scalar1);
172            break;
173        case SK_FUNCTION(atan2):
174            scalarResult = SkScalarATan2(input, parameters[1].fOperand.fScalar);
175            break;
176        case SK_FUNCTION(ceil):
177            scalarResult = SkIntToScalar(SkScalarCeil(input));
178            break;
179        case SK_FUNCTION(cos):
180            scalarResult = SkScalarCos(input);
181            break;
182        case SK_FUNCTION(exp):
183            scalarResult = SkScalarExp(input);
184            break;
185        case SK_FUNCTION(floor):
186            scalarResult = SkIntToScalar(SkScalarFloor(input));
187            break;
188        case SK_FUNCTION(log):
189            scalarResult = SkScalarLog(input);
190            break;
191        case SK_FUNCTION(max):
192            scalarResult = -SK_ScalarMax;
193            while (array < end) {
194                scalarResult = SkMaxScalar(scalarResult, array->fOperand.fScalar);
195                array++;
196            }
197            break;
198        case SK_FUNCTION(min):
199            scalarResult = SK_ScalarMax;
200            while (array < end) {
201                scalarResult = SkMinScalar(scalarResult, array->fOperand.fScalar);
202                array++;
203            }
204            break;
205        case SK_FUNCTION(pow):
206            // not the greatest -- but use x^y = e^(y * ln(x))
207            scalarResult = SkScalarLog(input);
208            scalarResult = SkScalarMul(parameters[1].fOperand.fScalar, scalarResult);
209            scalarResult = SkScalarExp(scalarResult);
210            break;
211        case SK_FUNCTION(random):
212            scalarResult = fRandom.nextUScalar1();
213            break;
214        case SK_FUNCTION(round):
215            scalarResult = SkIntToScalar(SkScalarRound(input));
216            break;
217        case SK_FUNCTION(sin):
218            scalarResult = SkScalarSin(input);
219            break;
220        case SK_FUNCTION(sqrt): {
221            SkASSERT(parameters.count() == 1);
222            SkASSERT(type == SkType_Float);
223            scalarResult = SkScalarSqrt(input);
224            } break;
225        case SK_FUNCTION(tan):
226            scalarResult = SkScalarTan(input);
227            break;
228        default:
229            SkASSERT(0);
230            scalarResult = SK_ScalarNaN;
231    }
232    scriptValue->fOperand.fScalar = scalarResult;
233    scriptValue->fType = SkType_Float;
234}
235
236const SkFunctionParamType* SkDisplayMath::getFunctionsParameters() {
237    return fFunctionParameters;
238}
239
240bool SkDisplayMath::getProperty(int index, SkScriptValue* value) const {
241    if ((unsigned)index < SK_ARRAY_COUNT(gConstants)) {
242        value->fOperand.fScalar = gConstants[index];
243        value->fType = SkType_Float;
244        return true;
245    }
246    SkASSERT(0);
247    return false;
248}
249