michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkDisplayMath.h" michael@0: michael@0: enum SkDisplayMath_Properties { michael@0: SK_PROPERTY(E), michael@0: SK_PROPERTY(LN10), michael@0: SK_PROPERTY(LN2), michael@0: SK_PROPERTY(LOG10E), michael@0: SK_PROPERTY(LOG2E), michael@0: SK_PROPERTY(PI), michael@0: SK_PROPERTY(SQRT1_2), michael@0: SK_PROPERTY(SQRT2) michael@0: }; michael@0: michael@0: const SkScalar SkDisplayMath::gConstants[] = { michael@0: 2.718281828f, // E michael@0: 2.302585093f, // LN10 michael@0: 0.693147181f, // LN2 michael@0: 0.434294482f, // LOG10E michael@0: 1.442695041f, // LOG2E michael@0: 3.141592654f, // PI michael@0: 0.707106781f, // SQRT1_2 michael@0: 1.414213562f // SQRT2 michael@0: }; michael@0: michael@0: enum SkDisplayMath_Functions { michael@0: SK_FUNCTION(abs), michael@0: SK_FUNCTION(acos), michael@0: SK_FUNCTION(asin), michael@0: SK_FUNCTION(atan), michael@0: SK_FUNCTION(atan2), michael@0: SK_FUNCTION(ceil), michael@0: SK_FUNCTION(cos), michael@0: SK_FUNCTION(exp), michael@0: SK_FUNCTION(floor), michael@0: SK_FUNCTION(log), michael@0: SK_FUNCTION(max), michael@0: SK_FUNCTION(min), michael@0: SK_FUNCTION(pow), michael@0: SK_FUNCTION(random), michael@0: SK_FUNCTION(round), michael@0: SK_FUNCTION(sin), michael@0: SK_FUNCTION(sqrt), michael@0: SK_FUNCTION(tan) michael@0: }; michael@0: michael@0: const SkFunctionParamType SkDisplayMath::fFunctionParameters[] = { michael@0: (SkFunctionParamType) SkType_Float, // abs michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // acos michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // asin michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // atan michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // atan2 michael@0: (SkFunctionParamType) SkType_Float, michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // ceil michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // cos michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // exp michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // floor michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // log michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Array, // max michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Array, // min michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // pow michael@0: (SkFunctionParamType) SkType_Float, michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // random michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // round michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // sin michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // sqrt michael@0: (SkFunctionParamType) 0, michael@0: (SkFunctionParamType) SkType_Float, // tan michael@0: (SkFunctionParamType) 0 michael@0: }; michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDisplayMath::fInfo[] = { michael@0: SK_MEMBER_PROPERTY(E, Float), michael@0: SK_MEMBER_PROPERTY(LN10, Float), michael@0: SK_MEMBER_PROPERTY(LN2, Float), michael@0: SK_MEMBER_PROPERTY(LOG10E, Float), michael@0: SK_MEMBER_PROPERTY(LOG2E, Float), michael@0: SK_MEMBER_PROPERTY(PI, Float), michael@0: SK_MEMBER_PROPERTY(SQRT1_2, Float), michael@0: SK_MEMBER_PROPERTY(SQRT2, Float), michael@0: SK_MEMBER_FUNCTION(abs, Float), michael@0: SK_MEMBER_FUNCTION(acos, Float), michael@0: SK_MEMBER_FUNCTION(asin, Float), michael@0: SK_MEMBER_FUNCTION(atan, Float), michael@0: SK_MEMBER_FUNCTION(atan2, Float), michael@0: SK_MEMBER_FUNCTION(ceil, Float), michael@0: SK_MEMBER_FUNCTION(cos, Float), michael@0: SK_MEMBER_FUNCTION(exp, Float), michael@0: SK_MEMBER_FUNCTION(floor, Float), michael@0: SK_MEMBER_FUNCTION(log, Float), michael@0: SK_MEMBER_FUNCTION(max, Float), michael@0: SK_MEMBER_FUNCTION(min, Float), michael@0: SK_MEMBER_FUNCTION(pow, Float), michael@0: SK_MEMBER_FUNCTION(random, Float), michael@0: SK_MEMBER_FUNCTION(round, Float), michael@0: SK_MEMBER_FUNCTION(sin, Float), michael@0: SK_MEMBER_FUNCTION(sqrt, Float), michael@0: SK_MEMBER_FUNCTION(tan, Float) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDisplayMath); michael@0: michael@0: void SkDisplayMath::executeFunction(SkDisplayable* target, int index, michael@0: SkTDArray& parameters, SkDisplayTypes type, michael@0: SkScriptValue* scriptValue) { michael@0: if (scriptValue == NULL) michael@0: return; michael@0: SkASSERT(target == this); michael@0: SkScriptValue* array = parameters.begin(); michael@0: SkScriptValue* end = parameters.end(); michael@0: SkScalar input = parameters[0].fOperand.fScalar; michael@0: SkScalar scalarResult; michael@0: switch (index) { michael@0: case SK_FUNCTION(abs): michael@0: scalarResult = SkScalarAbs(input); michael@0: break; michael@0: case SK_FUNCTION(acos): michael@0: scalarResult = SkScalarACos(input); michael@0: break; michael@0: case SK_FUNCTION(asin): michael@0: scalarResult = SkScalarASin(input); michael@0: break; michael@0: case SK_FUNCTION(atan): michael@0: scalarResult = SkScalarATan2(input, SK_Scalar1); michael@0: break; michael@0: case SK_FUNCTION(atan2): michael@0: scalarResult = SkScalarATan2(input, parameters[1].fOperand.fScalar); michael@0: break; michael@0: case SK_FUNCTION(ceil): michael@0: scalarResult = SkScalarCeilToScalar(input); michael@0: break; michael@0: case SK_FUNCTION(cos): michael@0: scalarResult = SkScalarCos(input); michael@0: break; michael@0: case SK_FUNCTION(exp): michael@0: scalarResult = SkScalarExp(input); michael@0: break; michael@0: case SK_FUNCTION(floor): michael@0: scalarResult = SkScalarFloorToScalar(input); michael@0: break; michael@0: case SK_FUNCTION(log): michael@0: scalarResult = SkScalarLog(input); michael@0: break; michael@0: case SK_FUNCTION(max): michael@0: scalarResult = -SK_ScalarMax; michael@0: while (array < end) { michael@0: scalarResult = SkMaxScalar(scalarResult, array->fOperand.fScalar); michael@0: array++; michael@0: } michael@0: break; michael@0: case SK_FUNCTION(min): michael@0: scalarResult = SK_ScalarMax; michael@0: while (array < end) { michael@0: scalarResult = SkMinScalar(scalarResult, array->fOperand.fScalar); michael@0: array++; michael@0: } michael@0: break; michael@0: case SK_FUNCTION(pow): michael@0: // not the greatest -- but use x^y = e^(y * ln(x)) michael@0: scalarResult = SkScalarLog(input); michael@0: scalarResult = SkScalarMul(parameters[1].fOperand.fScalar, scalarResult); michael@0: scalarResult = SkScalarExp(scalarResult); michael@0: break; michael@0: case SK_FUNCTION(random): michael@0: scalarResult = fRandom.nextUScalar1(); michael@0: break; michael@0: case SK_FUNCTION(round): michael@0: scalarResult = SkScalarRoundToScalar(input); michael@0: break; michael@0: case SK_FUNCTION(sin): michael@0: scalarResult = SkScalarSin(input); michael@0: break; michael@0: case SK_FUNCTION(sqrt): { michael@0: SkASSERT(parameters.count() == 1); michael@0: SkASSERT(type == SkType_Float); michael@0: scalarResult = SkScalarSqrt(input); michael@0: } break; michael@0: case SK_FUNCTION(tan): michael@0: scalarResult = SkScalarTan(input); michael@0: break; michael@0: default: michael@0: SkASSERT(0); michael@0: scalarResult = SK_ScalarNaN; michael@0: } michael@0: scriptValue->fOperand.fScalar = scalarResult; michael@0: scriptValue->fType = SkType_Float; michael@0: } michael@0: michael@0: const SkFunctionParamType* SkDisplayMath::getFunctionsParameters() { michael@0: return fFunctionParameters; michael@0: } michael@0: michael@0: bool SkDisplayMath::getProperty(int index, SkScriptValue* value) const { michael@0: if ((unsigned)index < SK_ARRAY_COUNT(gConstants)) { michael@0: value->fOperand.fScalar = gConstants[index]; michael@0: value->fType = SkType_Float; michael@0: return true; michael@0: } michael@0: SkASSERT(0); michael@0: return false; michael@0: }