15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/interpolated_transform.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef M_PI
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define M_PI 3.14159265358979323846
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/animation/tween.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const double EPSILON = 1e-6;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsMultipleOfNinetyDegrees(double degrees) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double remainder = fabs(fmod(degrees, 90.0));
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return remainder < EPSILON || 90.0 - remainder < EPSILON;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsApproximatelyZero(double value) {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return fabs(value) < EPSILON;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns false if |degrees| is not a multiple of ninety degrees or if
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |rotation| is NULL. It does not affect |rotation| in this case. Otherwise
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// *rotation is set to be the appropriate sanitized rotation matrix. That is,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the rotation matrix corresponding to |degrees| which has entries that are all
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// either 0, 1 or -1.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MassageRotationIfMultipleOfNinetyDegrees(gfx::Transform* rotation,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              float degrees) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsMultipleOfNinetyDegrees(degrees) || !rotation)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform transform;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkMatrix44& m = transform.matrix();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float degrees_by_ninety = degrees / 90.0f;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = static_cast<int>(degrees_by_ninety > 0
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ? floor(degrees_by_ninety + 0.5f)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ceil(degrees_by_ninety - 0.5f));
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  n %= 4;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (n < 0)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n += 4;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // n should now be in the range [0, 3]
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (n == 1) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m.set3x3( 0,  1,  0,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             -1,  0,  0,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              0,  0,  1);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (n == 2) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m.set3x3(-1,  0,  0,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              0, -1,  0,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              0,  0,  1);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (n == 3) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    m.set3x3( 0, -1,  0,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              1,  0,  0,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              0,  0,  1);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *rotation = transform;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterpolatedTransform
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTransform::InterpolatedTransform()
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : start_time_(0.0f),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_time_(1.0f),
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reversed_(false) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTransform::InterpolatedTransform(float start_time,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             float end_time)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : start_time_(start_time),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_time_(end_time),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reversed_(false) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTransform::~InterpolatedTransform() {}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform InterpolatedTransform::Interpolate(float t) const {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reversed_)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    t = 1.0f - t;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform result = InterpolateButDoNotCompose(t);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (child_.get()) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.ConcatTransform(child_->Interpolate(t));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InterpolatedTransform::SetChild(InterpolatedTransform* child) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  child_.reset(child);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline float InterpolatedTransform::ValueBetween(float time,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 float start_value,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 float end_value) const {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can't handle NaN
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(time == time && start_time_ == start_time_ && end_time_ == end_time_);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (time != time || start_time_ != start_time_ || end_time_ != end_time_)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return start_value;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ok if equal -- we'll get a step function. Note: if end_time_ ==
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // start_time_ == x, then if none of the numbers are NaN, then it
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // must be true that time < x or time >= x, so we will return early
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // due to one of the following if statements.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(end_time_ >= start_time_);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (time < start_time_)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return start_value;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (time >= end_time_)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return end_value;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float t = (time - start_time_) / (end_time_ - start_time_);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<float>(Tween::ValueBetween(t, start_value, end_value));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterpolatedRotation
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedRotation::InterpolatedRotation(float start_degrees,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           float end_degrees)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(),
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_degrees_(start_degrees),
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_degrees_(end_degrees) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedRotation::InterpolatedRotation(float start_degrees,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           float end_degrees,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           float start_time,
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           float end_time)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(start_time, end_time),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_degrees_(start_degrees),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_degrees_(end_degrees) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedRotation::~InterpolatedRotation() {}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform result;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float interpolated_degrees = ValueBetween(t, start_degrees_, end_degrees_);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result.Rotate(interpolated_degrees);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (t == 0.0f || t == 1.0f)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MassageRotationIfMultipleOfNinetyDegrees(&result, interpolated_degrees);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterpolatedAxisAngleRotation
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation(
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Vector3dF& axis,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float start_degrees,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float end_degrees)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(),
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      axis_(axis),
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_degrees_(start_degrees),
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_degrees_(end_degrees) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation(
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Vector3dF& axis,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float start_degrees,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float end_degrees,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float start_time,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float end_time)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(start_time, end_time),
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      axis_(axis),
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_degrees_(start_degrees),
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_degrees_(end_degrees) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedAxisAngleRotation::~InterpolatedAxisAngleRotation() {}
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedAxisAngleRotation::InterpolateButDoNotCompose(float t) const {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform result;
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result.RotateAbout(axis_, ValueBetween(t, start_degrees_, end_degrees_));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterpolatedScale
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedScale::InterpolatedScale(float start_scale, float end_scale)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(),
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_scale_(gfx::Point3F(start_scale, start_scale, start_scale)),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_scale_(gfx::Point3F(end_scale, end_scale, end_scale)) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedScale::InterpolatedScale(float start_scale, float end_scale,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     float start_time, float end_time)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(start_time, end_time),
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_scale_(gfx::Point3F(start_scale, start_scale, start_scale)),
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_scale_(gfx::Point3F(end_scale, end_scale, end_scale)) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedScale::InterpolatedScale(const gfx::Point3F& start_scale,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const gfx::Point3F& end_scale)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(),
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_scale_(start_scale),
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_scale_(end_scale) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedScale::InterpolatedScale(const gfx::Point3F& start_scale,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const gfx::Point3F& end_scale,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     float start_time,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     float end_time)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(start_time, end_time),
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_scale_(start_scale),
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_scale_(end_scale) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedScale::~InterpolatedScale() {}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform InterpolatedScale::InterpolateButDoNotCompose(float t) const {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform result;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float scale_x = ValueBetween(t, start_scale_.x(), end_scale_.x());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float scale_y = ValueBetween(t, start_scale_.y(), end_scale_.y());
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(vollick) 3d xforms.
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result.Scale(scale_x, scale_y);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterpolatedTranslation
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 const gfx::Point& end_pos)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(),
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_pos_(start_pos),
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_pos_(end_pos) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTranslation::InterpolatedTranslation(const gfx::Point& start_pos,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 const gfx::Point& end_pos,
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 float start_time,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 float end_time)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(start_time, end_time),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_pos_(start_pos),
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      end_pos_(end_pos) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTranslation::~InterpolatedTranslation() {}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTranslation::InterpolateButDoNotCompose(float t) const {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform result;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(vollick) 3d xforms.
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result.Translate(ValueBetween(t, start_pos_.x(), end_pos_.x()),
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      ValueBetween(t, start_pos_.y(), end_pos_.y()));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterpolatedConstantTransform
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedConstantTransform::InterpolatedConstantTransform(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Transform& transform)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform(),
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform_(transform) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedConstantTransform::InterpolateButDoNotCompose(float t) const {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transform_;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedConstantTransform::~InterpolatedConstantTransform() {}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InterpolatedTransformAboutPivot
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTransformAboutPivot::InterpolatedTransformAboutPivot(
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Point& pivot,
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InterpolatedTransform* transform)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform() {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(pivot, transform);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTransformAboutPivot::InterpolatedTransformAboutPivot(
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Point& pivot,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InterpolatedTransform* transform,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float start_time,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float end_time)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform() {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(pivot, transform);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTransformAboutPivot::~InterpolatedTransformAboutPivot() {}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InterpolatedTransformAboutPivot::InterpolateButDoNotCompose(float t) const {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transform_.get()) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transform_->Interpolate(t);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return gfx::Transform();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InterpolatedTransformAboutPivot::Init(const gfx::Point& pivot,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           InterpolatedTransform* xform) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform to_pivot;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform from_pivot;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  to_pivot.Translate(-pivot.x(), -pivot.y());
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  from_pivot.Translate(pivot.x(), pivot.y());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<InterpolatedTransform> pre_transform(
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new InterpolatedConstantTransform(to_pivot));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<InterpolatedTransform> post_transform(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new InterpolatedConstantTransform(from_pivot));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pre_transform->SetChild(xform);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xform->SetChild(post_transform.release());
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transform_.reset(pre_transform.release());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InterpolatedMatrixTransform::InterpolatedMatrixTransform(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Transform& start_transform,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Transform& end_transform)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform() {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(start_transform, end_transform);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InterpolatedMatrixTransform::InterpolatedMatrixTransform(
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Transform& start_transform,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Transform& end_transform,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float start_time,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    float end_time)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterpolatedTransform() {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(start_transform, end_transform);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InterpolatedMatrixTransform::~InterpolatedMatrixTransform() {}
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InterpolatedMatrixTransform::InterpolateButDoNotCompose(float t) const {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::DecomposedTransform blended;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = gfx::BlendDecomposedTransforms(&blended,
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                end_decomp_,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                start_decomp_,
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                t);
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(success);
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::ComposeTransform(blended);
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void InterpolatedMatrixTransform::Init(const gfx::Transform& start_transform,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const gfx::Transform& end_transform) {
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool success = gfx::DecomposeTransform(&start_decomp_, start_transform);
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(success);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  success = gfx::DecomposeTransform(&end_decomp_, end_transform);
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(success);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ui
374