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 
SkOperandInterpolator()13 SkOperandInterpolator::SkOperandInterpolator() {
14     INHERITED::reset(0, 0);
15     fType = SkType_Unknown;
16 }
17 
SkOperandInterpolator(int elemCount,int frameCount,SkDisplayTypes type)18 SkOperandInterpolator::SkOperandInterpolator(int elemCount, int frameCount,
19                                              SkDisplayTypes type)
20 {
21     this->reset(elemCount, frameCount, type);
22 }
23 
reset(int elemCount,int frameCount,SkDisplayTypes type)24 void 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 
setKeyFrame(int index,SkMSec time,const SkOperand values[],SkScalar blend)39 bool 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 
timeToValues(SkMSec time,SkOperand values[]) const59 SkInterpolatorBase::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
iset(SkOperand array[3],int a,int b,int c)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 
UnitTest()108 void 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