Home | History | Annotate | Download | only in animator
      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 
     13 SkOperandInterpolator::SkOperandInterpolator() {
     14     INHERITED::reset(0, 0);
     15     fType = SkType_Unknown;
     16 }
     17 
     18 SkOperandInterpolator::SkOperandInterpolator(int elemCount, int frameCount,
     19                                              SkDisplayTypes type)
     20 {
     21     this->reset(elemCount, frameCount, type);
     22 }
     23 
     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 
     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 
     59 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 + SkScalarRound((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 
    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