1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOperandInterpolator.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScript.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkOperandInterpolator::SkOperandInterpolator() {
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::reset(0, 0);
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fType = SkType_Unknown;
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comSkOperandInterpolator::SkOperandInterpolator(int elemCount, int frameCount,
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                             SkDisplayTypes type)
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->reset(elemCount, frameCount, type);
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkOperandInterpolator::reset(int elemCount, int frameCount, SkDisplayTypes type)
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  SkASSERT(type == SkType_String || type == SkType_Float || type == SkType_Int ||
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//      type == SkType_Displayable || type == SkType_Drawable);
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    INHERITED::reset(elemCount, frameCount);
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fType = type;
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStorage = sk_malloc_throw((sizeof(SkOperand) * elemCount + sizeof(SkTimeCode)) * frameCount);
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTimes = (SkTimeCode*) fStorage;
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fValues = (SkOperand*) ((char*) fStorage + sizeof(SkTimeCode) * frameCount);
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTimesArray = (SkTimeCode(*)[10]) fTimes;
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fValuesArray = (SkOperand(*)[10]) fValues;
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkOperandInterpolator::setKeyFrame(int index, SkMSec time, const SkOperand values[], SkScalar blend)
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(values != NULL);
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    blend = SkScalarPin(blend, 0, SK_Scalar1);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, sizeof(SkTimeCode));
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(success);
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (success) {
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTimeCode* timeCode = &fTimes[index];
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        timeCode->fTime = time;
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        timeCode->fBlend[0] = SK_Scalar1 - blend;
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        timeCode->fBlend[1] = 0;
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        timeCode->fBlend[2] = 0;
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        timeCode->fBlend[3] = SK_Scalar1 - blend;
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkOperand* dst = &fValues[fElemCount * index];
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(dst, values, fElemCount * sizeof(SkOperand));
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return success;
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkInterpolatorBase::Result SkOperandInterpolator::timeToValues(SkMSec time, SkOperand values[]) const
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar T;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int index;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBool exact;
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Result result = timeToT(time, &T, &index, &exact);
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (values)
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkOperand* nextSrc = &fValues[index * fElemCount];
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (exact)
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            memcpy(values, nextSrc, fElemCount * sizeof(SkScalar));
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        else
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        {
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(index > 0);
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const SkOperand* prevSrc = nextSrc - fElemCount;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (fType == SkType_Float || fType == SkType_3D_Point) {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                for (int i = fElemCount - 1; i >= 0; --i)
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    values[i].fScalar = SkScalarInterp(prevSrc[i].fScalar, nextSrc[i].fScalar, T);
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else if (fType == SkType_Int || fType == SkType_MSec) {
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                for (int i = fElemCount - 1; i >= 0; --i) {
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    int32_t a = prevSrc[i].fS32;
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    int32_t b = nextSrc[i].fS32;
84e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com                    values[i].fS32 = a + SkScalarRoundToInt((b - a) * T);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                memcpy(values, prevSrc, sizeof(SkOperand) * fElemCount);
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return result;
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////////
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////////
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_SUPPORT_UNITTEST
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static SkOperand* iset(SkOperand array[3], int a, int b, int c)
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        array[0].fScalar = SkIntToScalar(a);
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        array[1].fScalar = SkIntToScalar(b);
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        array[2].fScalar = SkIntToScalar(c);
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return array;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkOperandInterpolator::UnitTest()
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_SUPPORT_UNITTEST
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkOperandInterpolator   inter(3, 2, SkType_Float);
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkOperand       v1[3], v2[3], v[3], vv[3];
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Result          result;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inter.setKeyFrame(0, 100, iset(v1, 10, 20, 30), 0);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inter.setKeyFrame(1, 200, iset(v2, 110, 220, 330));
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(0, v);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kFreezeStart_Result);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(99, v);
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kFreezeStart_Result);
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(100, v);
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kNormal_Result);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(200, v);
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kNormal_Result);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(memcmp(v, v2, sizeof(v)) == 0);
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(201, v);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kFreezeEnd_Result);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(memcmp(v, v2, sizeof(v)) == 0);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(150, v);
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kNormal_Result);
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(memcmp(v, iset(vv, 60, 120, 180), sizeof(v)) == 0);
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(125, v);
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kNormal_Result);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    result = inter.timeToValues(175, v);
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(result == kNormal_Result);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
150