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