123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/gfx/interpolated_transform.h"
- #include <cmath>
- #include "base/check.h"
- #include "base/numerics/safe_conversions.h"
- #include "ui/gfx/animation/tween.h"
- namespace {
- static const double EPSILON = 1e-6;
- bool IsMultipleOfNinetyDegrees(double degrees) {
- double remainder = fabs(fmod(degrees, 90.0));
- return remainder < EPSILON || 90.0 - remainder < EPSILON;
- }
- // Returns false if |degrees| is not a multiple of ninety degrees or if
- // |rotation| is NULL. It does not affect |rotation| in this case. Otherwise
- // *rotation is set to be the appropriate sanitized rotation matrix. That is,
- // the rotation matrix corresponding to |degrees| which has entries that are all
- // either 0, 1 or -1.
- bool MassageRotationIfMultipleOfNinetyDegrees(gfx::Transform* rotation,
- float degrees) {
- if (!IsMultipleOfNinetyDegrees(degrees) || !rotation)
- return false;
- gfx::Transform transform;
- float degrees_by_ninety = degrees / 90.0f;
- int n = base::ClampRound(degrees_by_ninety);
- n %= 4;
- if (n < 0)
- n += 4;
- // n should now be in the range [0, 3]
- // clang-format off
- if (n == 1) {
- transform.matrix().setRotateAboutZAxisSinCos(1, 0);
- } else if (n == 2) {
- transform.matrix().setRotateAboutZAxisSinCos(0, -1);
- } else if (n == 3) {
- transform.matrix().setRotateAboutZAxisSinCos(-1, 0);
- }
- // clang-format on
- *rotation = transform;
- return true;
- }
- } // namespace
- namespace ui {
- ///////////////////////////////////////////////////////////////////////////////
- // InterpolatedTransform
- //
- InterpolatedTransform::InterpolatedTransform()
- : start_time_(0.0f),
- end_time_(1.0f),
- reversed_(false) {
- }
- InterpolatedTransform::InterpolatedTransform(float start_time,
- float end_time)
- : start_time_(start_time),
- end_time_(end_time),
- reversed_(false) {
- }
- InterpolatedTransform::~InterpolatedTransform() {}
- gfx::Transform InterpolatedTransform::Interpolate(float t) const {
- if (reversed_)
- t = 1.0f - t;
- gfx::Transform result = InterpolateButDoNotCompose(t);
- if (child_.get()) {
- result.ConcatTransform(child_->Interpolate(t));
- }
- return result;
- }
- void InterpolatedTransform::SetChild(
- std::unique_ptr<InterpolatedTransform> child) {
- child_ = std::move(child);
- }
- inline float InterpolatedTransform::ValueBetween(float time,
- float start_value,
- float end_value) const {
- // can't handle NaN
- DCHECK(time == time && start_time_ == start_time_ && end_time_ == end_time_);
- if (time != time || start_time_ != start_time_ || end_time_ != end_time_)
- return start_value;
- // Ok if equal -- we'll get a step function. Note: if end_time_ ==
- // start_time_ == x, then if none of the numbers are NaN, then it
- // must be true that time < x or time >= x, so we will return early
- // due to one of the following if statements.
- DCHECK(end_time_ >= start_time_);
- if (time < start_time_)
- return start_value;
- if (time >= end_time_)
- return end_value;
- float t = (time - start_time_) / (end_time_ - start_time_);
- return static_cast<float>(
- gfx::Tween::DoubleValueBetween(t, start_value, end_value));
- }
- ///////////////////////////////////////////////////////////////////////////////
- // InterpolatedRotation
- //
- InterpolatedRotation::InterpolatedRotation(float start_degrees,
- float end_degrees)
- : InterpolatedTransform(),
- start_degrees_(start_degrees),
- end_degrees_(end_degrees) {
- }
- InterpolatedRotation::InterpolatedRotation(float start_degrees,
- float end_degrees,
- float start_time,
- float end_time)
- : InterpolatedTransform(start_time, end_time),
- start_degrees_(start_degrees),
- end_degrees_(end_degrees) {
- }
- InterpolatedRotation::~InterpolatedRotation() {}
- gfx::Transform InterpolatedRotation::InterpolateButDoNotCompose(float t) const {
- gfx::Transform result;
- float interpolated_degrees = ValueBetween(t, start_degrees_, end_degrees_);
- result.Rotate(interpolated_degrees);
- if (t == 0.0f || t == 1.0f)
- MassageRotationIfMultipleOfNinetyDegrees(&result, interpolated_degrees);
- return result;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // InterpolatedAxisAngleRotation
- //
- InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation(
- const gfx::Vector3dF& axis,
- float start_degrees,
- float end_degrees)
- : InterpolatedTransform(),
- axis_(axis),
- start_degrees_(start_degrees),
- end_degrees_(end_degrees) {
- }
- InterpolatedAxisAngleRotation::InterpolatedAxisAngleRotation(
- const gfx::Vector3dF& axis,
- float start_degrees,
- float end_degrees,
- float start_time,
- float end_time)
- : InterpolatedTransform(start_time, end_time),
- axis_(axis),
- start_degrees_(start_degrees),
- end_degrees_(end_degrees) {
- }
- InterpolatedAxisAngleRotation::~InterpolatedAxisAngleRotation() {}
- gfx::Transform
- InterpolatedAxisAngleRotation::InterpolateButDoNotCompose(float t) const {
- gfx::Transform result;
- result.RotateAbout(axis_, ValueBetween(t, start_degrees_, end_degrees_));
- return result;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // InterpolatedScale
- //
- InterpolatedScale::InterpolatedScale(float start_scale, float end_scale)
- : InterpolatedTransform(),
- start_scale_(gfx::Point3F(start_scale, start_scale, start_scale)),
- end_scale_(gfx::Point3F(end_scale, end_scale, end_scale)) {
- }
- InterpolatedScale::InterpolatedScale(float start_scale, float end_scale,
- float start_time, float end_time)
- : InterpolatedTransform(start_time, end_time),
- start_scale_(gfx::Point3F(start_scale, start_scale, start_scale)),
- end_scale_(gfx::Point3F(end_scale, end_scale, end_scale)) {
- }
- InterpolatedScale::InterpolatedScale(const gfx::Point3F& start_scale,
- const gfx::Point3F& end_scale)
- : InterpolatedTransform(),
- start_scale_(start_scale),
- end_scale_(end_scale) {
- }
- InterpolatedScale::InterpolatedScale(const gfx::Point3F& start_scale,
- const gfx::Point3F& end_scale,
- float start_time,
- float end_time)
- : InterpolatedTransform(start_time, end_time),
- start_scale_(start_scale),
- end_scale_(end_scale) {
- }
- InterpolatedScale::~InterpolatedScale() {}
- gfx::Transform InterpolatedScale::InterpolateButDoNotCompose(float t) const {
- gfx::Transform result;
- float scale_x = ValueBetween(t, start_scale_.x(), end_scale_.x());
- float scale_y = ValueBetween(t, start_scale_.y(), end_scale_.y());
- float scale_z = ValueBetween(t, start_scale_.z(), end_scale_.z());
- result.Scale3d(scale_x, scale_y, scale_z);
- return result;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // InterpolatedTranslation
- //
- InterpolatedTranslation::InterpolatedTranslation(const gfx::PointF& start_pos,
- const gfx::PointF& end_pos)
- : InterpolatedTransform(), start_pos_(start_pos), end_pos_(end_pos) {}
- InterpolatedTranslation::InterpolatedTranslation(const gfx::PointF& start_pos,
- const gfx::PointF& end_pos,
- float start_time,
- float end_time)
- : InterpolatedTransform(start_time, end_time),
- start_pos_(start_pos),
- end_pos_(end_pos) {}
- InterpolatedTranslation::InterpolatedTranslation(const gfx::Point3F& start_pos,
- const gfx::Point3F& end_pos)
- : InterpolatedTransform(), start_pos_(start_pos), end_pos_(end_pos) {
- }
- InterpolatedTranslation::InterpolatedTranslation(const gfx::Point3F& start_pos,
- const gfx::Point3F& end_pos,
- float start_time,
- float end_time)
- : InterpolatedTransform(start_time, end_time),
- start_pos_(start_pos),
- end_pos_(end_pos) {
- }
- InterpolatedTranslation::~InterpolatedTranslation() {}
- gfx::Transform
- InterpolatedTranslation::InterpolateButDoNotCompose(float t) const {
- gfx::Transform result;
- result.Translate3d(ValueBetween(t, start_pos_.x(), end_pos_.x()),
- ValueBetween(t, start_pos_.y(), end_pos_.y()),
- ValueBetween(t, start_pos_.z(), end_pos_.z()));
- return result;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // InterpolatedConstantTransform
- //
- InterpolatedConstantTransform::InterpolatedConstantTransform(
- const gfx::Transform& transform)
- : InterpolatedTransform(),
- transform_(transform) {
- }
- gfx::Transform
- InterpolatedConstantTransform::InterpolateButDoNotCompose(float t) const {
- return transform_;
- }
- InterpolatedConstantTransform::~InterpolatedConstantTransform() {}
- ///////////////////////////////////////////////////////////////////////////////
- // InterpolatedTransformAboutPivot
- //
- InterpolatedTransformAboutPivot::InterpolatedTransformAboutPivot(
- const gfx::Point& pivot,
- std::unique_ptr<InterpolatedTransform> transform)
- : InterpolatedTransform() {
- Init(pivot, std::move(transform));
- }
- InterpolatedTransformAboutPivot::InterpolatedTransformAboutPivot(
- const gfx::Point& pivot,
- std::unique_ptr<InterpolatedTransform> transform,
- float start_time,
- float end_time)
- : InterpolatedTransform() {
- Init(pivot, std::move(transform));
- }
- InterpolatedTransformAboutPivot::~InterpolatedTransformAboutPivot() {}
- gfx::Transform
- InterpolatedTransformAboutPivot::InterpolateButDoNotCompose(float t) const {
- if (transform_.get()) {
- return transform_->Interpolate(t);
- }
- return gfx::Transform();
- }
- void InterpolatedTransformAboutPivot::Init(
- const gfx::Point& pivot,
- std::unique_ptr<InterpolatedTransform> xform) {
- gfx::Transform to_pivot;
- gfx::Transform from_pivot;
- to_pivot.Translate(SkIntToScalar(-pivot.x()), SkIntToScalar(-pivot.y()));
- from_pivot.Translate(SkIntToScalar(pivot.x()), SkIntToScalar(pivot.y()));
- std::unique_ptr<InterpolatedTransform> pre_transform =
- std::make_unique<InterpolatedConstantTransform>(to_pivot);
- std::unique_ptr<InterpolatedTransform> post_transform =
- std::make_unique<InterpolatedConstantTransform>(from_pivot);
- xform->SetChild(std::move(post_transform));
- pre_transform->SetChild(std::move(xform));
- transform_ = std::move(pre_transform);
- }
- InterpolatedMatrixTransform::InterpolatedMatrixTransform(
- const gfx::Transform& start_transform,
- const gfx::Transform& end_transform)
- : InterpolatedTransform() {
- Init(start_transform, end_transform);
- }
- InterpolatedMatrixTransform::InterpolatedMatrixTransform(
- const gfx::Transform& start_transform,
- const gfx::Transform& end_transform,
- float start_time,
- float end_time)
- : InterpolatedTransform() {
- Init(start_transform, end_transform);
- }
- InterpolatedMatrixTransform::~InterpolatedMatrixTransform() {}
- gfx::Transform
- InterpolatedMatrixTransform::InterpolateButDoNotCompose(float t) const {
- gfx::DecomposedTransform blended =
- gfx::BlendDecomposedTransforms(end_decomp_, start_decomp_, t);
- return gfx::ComposeTransform(blended);
- }
- void InterpolatedMatrixTransform::Init(const gfx::Transform& start_transform,
- const gfx::Transform& end_transform) {
- bool success = gfx::DecomposeTransform(&start_decomp_, start_transform);
- DCHECK(success);
- success = gfx::DecomposeTransform(&end_decomp_, end_transform);
- DCHECK(success);
- }
- } // namespace ui
|