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