transform_operations.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 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 "cc/animation/transform_operations.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/transform_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/vector3d_f.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace cc {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TransformOperations::TransformOperations()
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : decomposed_transform_dirty_(true) {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TransformOperations::TransformOperations(const TransformOperations& other) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_ = other.operations_;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomposed_transform_dirty_ = other.decomposed_transform_dirty_;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!decomposed_transform_dirty_) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decomposed_transform_.reset(
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new gfx::DecomposedTransform(*other.decomposed_transform_.get()));
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TransformOperations::~TransformOperations() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform TransformOperations::Apply() const {
31b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  gfx::Transform to_return;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < operations_.size(); ++i)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to_return.PreconcatTransform(operations_[i].matrix);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return to_return;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Transform TransformOperations::Blend(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TransformOperations& from, double progress) const {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Transform to_return;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BlendInternal(from, progress, &to_return);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return to_return;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TransformOperations::MatchesTypes(const TransformOperations& other) const {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsIdentity() || other.IsIdentity())
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (operations_.size() != other.operations_.size())
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < operations_.size(); ++i) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (operations_[i].type != other.operations_[i].type
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && !operations_[i].IsIdentity()
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && !other.operations_[i].IsIdentity())
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TransformOperations::CanBlendWith(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TransformOperations& other) const {
63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  gfx::Transform dummy;
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return BlendInternal(other, 0.5, &dummy);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransformOperations::AppendTranslate(double x, double y, double z) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformOperation to_add;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.matrix.Translate3d(x, y, z);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.type = TransformOperation::TransformOperationTranslate;
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  to_add.translate.x = x;
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  to_add.translate.y = y;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.translate.z = z;
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  operations_.push_back(to_add);
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  decomposed_transform_dirty_ = true;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TransformOperations::AppendRotate(double x, double y, double z,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       double degrees) {
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TransformOperation to_add;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.matrix.RotateAbout(gfx::Vector3dF(x, y, z), degrees);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.type = TransformOperation::TransformOperationRotate;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.rotate.axis.x = x;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.rotate.axis.y = y;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.rotate.axis.z = z;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.rotate.angle = degrees;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_.push_back(to_add);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomposed_transform_dirty_ = true;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransformOperations::AppendScale(double x, double y, double z) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformOperation to_add;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.matrix.Scale3d(x, y, z);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.type = TransformOperation::TransformOperationScale;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.scale.x = x;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.scale.y = y;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.scale.z = z;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_.push_back(to_add);
99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  decomposed_transform_dirty_ = true;
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransformOperations::AppendSkew(double x, double y) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TransformOperation to_add;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  to_add.matrix.SkewX(x);
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  to_add.matrix.SkewY(y);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  to_add.type = TransformOperation::TransformOperationSkew;
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  to_add.skew.x = x;
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  to_add.skew.y = y;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  operations_.push_back(to_add);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomposed_transform_dirty_ = true;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
113b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void TransformOperations::AppendPerspective(double depth) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformOperation to_add;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.matrix.ApplyPerspectiveDepth(depth);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.type = TransformOperation::TransformOperationPerspective;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.perspective_depth = depth;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_.push_back(to_add);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomposed_transform_dirty_ = true;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransformOperations::AppendMatrix(const gfx::Transform& matrix) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransformOperation to_add;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.matrix = matrix;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_add.type = TransformOperation::TransformOperationMatrix;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_.push_back(to_add);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decomposed_transform_dirty_ = true;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TransformOperations::AppendIdentity() {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  operations_.push_back(TransformOperation());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TransformOperations::IsIdentity() const {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < operations_.size(); ++i) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!operations_[i].IsIdentity())
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TransformOperations::BlendInternal(const TransformOperations& from,
143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                        double progress,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        gfx::Transform* result) const {
145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bool from_identity = from.IsIdentity();
146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bool to_identity = IsIdentity();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (from_identity && to_identity)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (MatchesTypes(from)) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t num_operations =
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::max(from_identity ? 0 : from.operations_.size(),
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 to_identity ? 0 : operations_.size());
154b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    for (size_t i = 0; i < num_operations; ++i) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Transform blended;
156      if (!TransformOperation::BlendTransformOperations(
157          from_identity ? 0 : &from.operations_[i],
158          to_identity ? 0 : &operations_[i],
159          progress,
160          &blended))
161          return false;
162      result->PreconcatTransform(blended);
163    }
164    return true;
165  }
166
167  if (!ComputeDecomposedTransform() || !from.ComputeDecomposedTransform())
168    return false;
169
170  gfx::DecomposedTransform to_return;
171  if (!gfx::BlendDecomposedTransforms(&to_return,
172                                      *decomposed_transform_.get(),
173                                      *from.decomposed_transform_.get(),
174                                      progress))
175    return false;
176
177  *result = ComposeTransform(to_return);
178  return true;
179}
180
181bool TransformOperations::ComputeDecomposedTransform() const {
182  if (decomposed_transform_dirty_) {
183    if (!decomposed_transform_)
184      decomposed_transform_.reset(new gfx::DecomposedTransform());
185    gfx::Transform transform = Apply();
186    if (!gfx::DecomposeTransform(decomposed_transform_.get(), transform))
187      return false;
188    decomposed_transform_dirty_ = false;
189  }
190  return true;
191}
192
193}  // namespace cc
194