SkOperandIterpolator.cpp revision 0910916c0f7b951ee55c4b7c6358295b9bca0565
1/* libs/graphics/animator/SkOperandIterpolator.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 "SkOperandInterpolator.h"
19#include "SkScript.h"
20
21SkOperandInterpolator::SkOperandInterpolator() {
22    INHERITED::reset(0, 0);
23    fType = SkType_Unknown;
24}
25
26SkOperandInterpolator::SkOperandInterpolator(int elemCount, int frameCount,
27                                             SkDisplayTypes type)
28{
29    this->reset(elemCount, frameCount, type);
30}
31
32void SkOperandInterpolator::reset(int elemCount, int frameCount, SkDisplayTypes type)
33{
34//  SkASSERT(type == SkType_String || type == SkType_Float || type == SkType_Int ||
35//      type == SkType_Displayable || type == SkType_Drawable);
36    INHERITED::reset(elemCount, frameCount);
37    fType = type;
38    fStorage = sk_malloc_throw((sizeof(SkOperand) * elemCount + sizeof(SkTimeCode)) * frameCount);
39    fTimes = (SkTimeCode*) fStorage;
40    fValues = (SkOperand*) ((char*) fStorage + sizeof(SkTimeCode) * frameCount);
41#ifdef SK_DEBUG
42    fTimesArray = (SkTimeCode(*)[10]) fTimes;
43    fValuesArray = (SkOperand(*)[10]) fValues;
44#endif
45}
46
47bool SkOperandInterpolator::setKeyFrame(int index, SkMSec time, const SkOperand values[], SkScalar blend)
48{
49    SkASSERT(values != NULL);
50    blend = SkScalarPin(blend, 0, SK_Scalar1);
51
52    bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, sizeof(SkTimeCode));
53    SkASSERT(success);
54    if (success) {
55        SkTimeCode* timeCode = &fTimes[index];
56        timeCode->fTime = time;
57        timeCode->fBlend[0] = SK_Scalar1 - blend;
58        timeCode->fBlend[1] = 0;
59        timeCode->fBlend[2] = 0;
60        timeCode->fBlend[3] = SK_Scalar1 - blend;
61        SkOperand* dst = &fValues[fElemCount * index];
62        memcpy(dst, values, fElemCount * sizeof(SkOperand));
63    }
64    return success;
65}
66
67SkInterpolatorBase::Result SkOperandInterpolator::timeToValues(SkMSec time, SkOperand values[]) const
68{
69    SkScalar T;
70    int index;
71    SkBool exact;
72    Result result = timeToT(time, &T, &index, &exact);
73    if (values)
74    {
75        const SkOperand* nextSrc = &fValues[index * fElemCount];
76
77        if (exact)
78            memcpy(values, nextSrc, fElemCount * sizeof(SkScalar));
79        else
80        {
81            SkASSERT(index > 0);
82
83            const SkOperand* prevSrc = nextSrc - fElemCount;
84
85            if (fType == SkType_Float || fType == SkType_3D_Point) {
86                for (int i = fElemCount - 1; i >= 0; --i)
87                    values[i].fScalar = SkScalarInterp(prevSrc[i].fScalar, nextSrc[i].fScalar, T);
88            } else if (fType == SkType_Int || fType == SkType_MSec) {
89                for (int i = fElemCount - 1; i >= 0; --i) {
90                    int32_t a = prevSrc[i].fS32;
91                    int32_t b = nextSrc[i].fS32;
92                    values[i].fS32 = a + SkScalarRound((b - a) * T);
93                }
94            } else
95                memcpy(values, prevSrc, sizeof(SkOperand) * fElemCount);
96        }
97    }
98    return result;
99}
100
101///////////////////////////////////////////////////////////////////////////////////////
102///////////////////////////////////////////////////////////////////////////////////////
103
104#ifdef SK_DEBUG
105
106#ifdef SK_SUPPORT_UNITTEST
107    static SkOperand* iset(SkOperand array[3], int a, int b, int c)
108    {
109        array[0].fScalar = SkIntToScalar(a);
110        array[1].fScalar = SkIntToScalar(b);
111        array[2].fScalar = SkIntToScalar(c);
112        return array;
113    }
114#endif
115
116void SkOperandInterpolator::UnitTest()
117{
118#ifdef SK_SUPPORT_UNITTEST
119    SkOperandInterpolator   inter(3, 2, SkType_Float);
120    SkOperand       v1[3], v2[3], v[3], vv[3];
121    Result          result;
122
123    inter.setKeyFrame(0, 100, iset(v1, 10, 20, 30), 0);
124    inter.setKeyFrame(1, 200, iset(v2, 110, 220, 330));
125
126    result = inter.timeToValues(0, v);
127    SkASSERT(result == kFreezeStart_Result);
128    SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
129
130    result = inter.timeToValues(99, v);
131    SkASSERT(result == kFreezeStart_Result);
132    SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
133
134    result = inter.timeToValues(100, v);
135    SkASSERT(result == kNormal_Result);
136    SkASSERT(memcmp(v, v1, sizeof(v)) == 0);
137
138    result = inter.timeToValues(200, v);
139    SkASSERT(result == kNormal_Result);
140    SkASSERT(memcmp(v, v2, sizeof(v)) == 0);
141
142    result = inter.timeToValues(201, v);
143    SkASSERT(result == kFreezeEnd_Result);
144    SkASSERT(memcmp(v, v2, sizeof(v)) == 0);
145
146    result = inter.timeToValues(150, v);
147    SkASSERT(result == kNormal_Result);
148    SkASSERT(memcmp(v, iset(vv, 60, 120, 180), sizeof(v)) == 0);
149
150    result = inter.timeToValues(125, v);
151    SkASSERT(result == kNormal_Result);
152    result = inter.timeToValues(175, v);
153    SkASSERT(result == kNormal_Result);
154#endif
155}
156
157#endif
158
159
160