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