11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2008 The Android Open Source Project 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkInterpolator.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMath.h" 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTSearch.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkInterpolatorBase::SkInterpolatorBase() { 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStorage = NULL; 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fTimes = NULL; 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(fTimesArray = NULL;) 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkInterpolatorBase::~SkInterpolatorBase() { 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fStorage) { 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_free(fStorage); 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkInterpolatorBase::reset(int elemCount, int frameCount) { 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFlags = 0; 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fElemCount = SkToU8(elemCount); 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFrameCount = SkToS16(frameCount); 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fRepeat = SK_Scalar1; 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fStorage) { 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_free(fStorage); 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStorage = NULL; 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fTimes = NULL; 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(fTimesArray = NULL); 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* Each value[] run is formated as: 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project <time (in msec)> 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project <blend> 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project <data[fElemCount]> 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Totaling fElemCount+2 entries per keyframe 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkInterpolatorBase::getDuration(SkMSec* startTime, SkMSec* endTime) const { 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fFrameCount == 0) { 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startTime) { 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *startTime = fTimes[0].fTime; 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (endTime) { 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *endTime = fTimes[fFrameCount - 1].fTime; 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkInterpolatorBase::ComputeRelativeT(SkMSec time, SkMSec prevTime, 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMSec nextTime, const SkScalar blend[4]) { 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(time > prevTime && time < nextTime); 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar t = SkScalarDiv((SkScalar)(time - prevTime), 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkScalar)(nextTime - prevTime)); 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return blend ? 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkUnitCubicInterp(t, blend[0], blend[1], blend[2], blend[3]) : t; 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkInterpolatorBase::Result SkInterpolatorBase::timeToT(SkMSec time, SkScalar* T, 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int* indexPtr, SkBool* exactPtr) const { 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fFrameCount > 0); 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Result result = kNormal_Result; 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fRepeat != SK_Scalar1) { 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMSec startTime = 0, endTime = 0; // initialize to avoid warning 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getDuration(&startTime, &endTime); 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMSec totalTime = endTime - startTime; 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMSec offsetTime = time - startTime; 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project endTime = SkScalarMulFloor(fRepeat, totalTime); 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (offsetTime >= endTime) { 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar fraction = SkScalarFraction(fRepeat); 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project offsetTime = fraction == 0 && fRepeat > 0 ? totalTime : 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarMulFloor(fraction, totalTime); 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = kFreezeEnd_Result; 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int mirror = fFlags & kMirror; 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project offsetTime = offsetTime % (totalTime << mirror); 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (offsetTime > totalTime) { // can only be true if fMirror is true 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project offsetTime = (totalTime << 1) - offsetTime; 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project time = offsetTime + startTime; 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time, 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sizeof(SkTimeCode)); 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool exact = true; 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index < 0) { 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project index = ~index; 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index == 0) { 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = kFreezeStart_Result; 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else if (index == fFrameCount) { 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fFlags & kReset) { 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project index = 0; 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project index -= 1; 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = kFreezeEnd_Result; 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project exact = false; 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(index < fFrameCount); 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkTimeCode* nextTime = &fTimes[index]; 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMSec nextT = nextTime[0].fTime; 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (exact) { 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *T = 0; 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMSec prevT = nextTime[-1].fTime; 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *T = ComputeRelativeT(time, prevT, nextT, nextTime[-1].fBlend); 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *indexPtr = index; 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *exactPtr = exact; 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return result; 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkInterpolator::SkInterpolator() { 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project INHERITED::reset(0, 0); 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fValues = NULL; 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(fScalarsArray = NULL;) 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkInterpolator::SkInterpolator(int elemCount, int frameCount) { 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(elemCount > 0); 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->reset(elemCount, frameCount); 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkInterpolator::reset(int elemCount, int frameCount) { 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project INHERITED::reset(elemCount, frameCount); 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStorage = sk_malloc_throw((sizeof(SkScalar) * elemCount + 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sizeof(SkTimeCode)) * frameCount); 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fTimes = (SkTimeCode*) fStorage; 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fValues = (SkScalar*) ((char*) fStorage + sizeof(SkTimeCode) * frameCount); 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fTimesArray = (SkTimeCode(*)[10]) fTimes; 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fScalarsArray = (SkScalar(*)[10]) fValues; 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_Fixed1Third (SK_Fixed1/3) 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_Fixed2Third (SK_Fixed1*2/3) 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkScalar gIdentityBlend[4] = { 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FLOAT 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SK_Fixed1Third, SK_Fixed1Third, SK_Fixed2Third, SK_Fixed2Third 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkInterpolator::setKeyFrame(int index, SkMSec time, 1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar values[], const SkScalar blend[4]) { 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(values != NULL); 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (blend == NULL) { 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blend = gIdentityBlend; 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sizeof(SkTimeCode)); 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(success); 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (success) { 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTimeCode* timeCode = &fTimes[index]; 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project timeCode->fTime = time; 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(timeCode->fBlend, blend, sizeof(timeCode->fBlend)); 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar* dst = &fValues[fElemCount * index]; 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(dst, values, fElemCount * sizeof(SkScalar)); 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return success; 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkInterpolator::Result SkInterpolator::timeToValues(SkMSec time, 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar values[]) const { 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar T; 1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index; 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBool exact; 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Result result = timeToT(time, &T, &index, &exact); 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (values) { 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar* nextSrc = &fValues[index * fElemCount]; 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (exact) { 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(values, nextSrc, fElemCount * sizeof(SkScalar)); 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(index > 0); 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar* prevSrc = nextSrc - fElemCount; 2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = fElemCount - 1; i >= 0; --i) { 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project values[i] = SkScalarInterp(prevSrc[i], nextSrc[i], T); 2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return result; 2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttypedef int Dot14; 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define Dot14_ONE (1 << 14) 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define Dot14_HALF (1 << 13) 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define Dot14ToFloat(x) ((x) / 16384.f) 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline Dot14 Dot14Mul(Dot14 a, Dot14 b) { 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (a * b + Dot14_HALF) >> 14; 2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline Dot14 eval_cubic(Dot14 t, Dot14 A, Dot14 B, Dot14 C) { 2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return Dot14Mul(Dot14Mul(Dot14Mul(C, t) + B, t) + A, t); 2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline Dot14 pin_and_convert(SkScalar x) { 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (x <= 0) { 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return 0; 2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (x >= SK_Scalar1) { 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return Dot14_ONE; 2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkScalarToFixed(x) >> 2; 2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by, 2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar cx, SkScalar cy) { 2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // pin to the unit-square, and convert to 2.14 2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 x = pin_and_convert(value); 2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (x == 0) return 0; 2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (x == Dot14_ONE) return SK_Scalar1; 2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 b = pin_and_convert(bx); 2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 c = pin_and_convert(cx); 2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // Now compute our coefficients from the control points 2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // t -> 3b 2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // t^2 -> 3c - 6b 2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // t^3 -> 3b - 3c + 1 2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 A = 3*b; 2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 B = 3*(c - 2*b); 2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 C = 3*(b - c) + Dot14_ONE; 2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // Now search for a t value given x 2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 t = Dot14_HALF; 2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 dt = Dot14_HALF; 2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < 13; i++) { 2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dt >>= 1; 2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Dot14 guess = eval_cubic(t, A, B, C); 2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (x < guess) { 2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project t -= dt; 2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project t += dt; 2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // Now we have t, so compute the coeff for Y and evaluate 2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project b = pin_and_convert(by); 2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project c = pin_and_convert(cy); 2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project A = 3*b; 2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project B = 3*(c - 2*b); 2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project C = 3*(b - c) + Dot14_ONE; 2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkFixedToScalar(eval_cubic(t, A, B, C) << 2); 2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SUPPORT_UNITTEST 2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static SkScalar* iset(SkScalar array[3], int a, int b, int c) { 2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project array[0] = SkIntToScalar(a); 2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project array[1] = SkIntToScalar(b); 2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project array[2] = SkIntToScalar(c); 2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return array; 2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkInterpolator::UnitTest() { 2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SUPPORT_UNITTEST 2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkInterpolator inter(3, 2); 2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar v1[3], v2[3], v[3], vv[3]; 2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Result result; 2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project inter.setKeyFrame(0, 100, iset(v1, 10, 20, 30), 0); 2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project inter.setKeyFrame(1, 200, iset(v2, 110, 220, 330)); 2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(0, v); 3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kFreezeStart_Result); 3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(memcmp(v, v1, sizeof(v)) == 0); 3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(99, v); 3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kFreezeStart_Result); 3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(memcmp(v, v1, sizeof(v)) == 0); 3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(100, v); 3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kNormal_Result); 3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(memcmp(v, v1, sizeof(v)) == 0); 3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(200, v); 3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kNormal_Result); 3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(memcmp(v, v2, sizeof(v)) == 0); 3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(201, v); 3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kFreezeEnd_Result); 3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(memcmp(v, v2, sizeof(v)) == 0); 3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(150, v); 3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kNormal_Result); 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(memcmp(v, iset(vv, 60, 120, 180), sizeof(v)) == 0); 3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(125, v); 3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kNormal_Result); 3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = inter.timeToValues(175, v); 3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(result == kNormal_Result); 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 333