transform_operations.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "cc/animation/transform_operations.h" 6#include "ui/gfx/transform_util.h" 7#include "ui/gfx/vector3d_f.h" 8 9namespace cc { 10 11TransformOperations::TransformOperations() 12 : decomposed_transform_dirty_(true) { 13} 14 15TransformOperations::TransformOperations(const TransformOperations& other) { 16 operations_ = other.operations_; 17 decomposed_transform_dirty_ = other.decomposed_transform_dirty_; 18 if (!decomposed_transform_dirty_) { 19 decomposed_transform_.reset( 20 new gfx::DecomposedTransform(*other.decomposed_transform_.get())); 21 } 22} 23 24TransformOperations::~TransformOperations() { 25} 26 27gfx::Transform TransformOperations::Apply() const { 28 gfx::Transform to_return; 29 for (size_t i = 0; i < operations_.size(); ++i) 30 to_return.PreconcatTransform(operations_[i].matrix); 31 return to_return; 32} 33 34gfx::Transform TransformOperations::Blend( 35 const TransformOperations& from, double progress) const { 36 gfx::Transform to_return; 37 BlendInternal(from, progress, &to_return); 38 return to_return; 39} 40 41bool TransformOperations::MatchesTypes(const TransformOperations& other) const { 42 if (IsIdentity() || other.IsIdentity()) 43 return true; 44 45 if (operations_.size() != other.operations_.size()) 46 return false; 47 48 for (size_t i = 0; i < operations_.size(); ++i) { 49 if (operations_[i].type != other.operations_[i].type 50 && !operations_[i].IsIdentity() 51 && !other.operations_[i].IsIdentity()) 52 return false; 53 } 54 55 return true; 56} 57 58bool TransformOperations::CanBlendWith( 59 const TransformOperations& other) const { 60 gfx::Transform dummy; 61 return BlendInternal(other, 0.5, &dummy); 62} 63 64void TransformOperations::AppendTranslate(double x, double y, double z) { 65 TransformOperation to_add; 66 to_add.matrix.Translate3d(x, y, z); 67 to_add.type = TransformOperation::TransformOperationTranslate; 68 to_add.translate.x = x; 69 to_add.translate.y = y; 70 to_add.translate.z = z; 71 operations_.push_back(to_add); 72 decomposed_transform_dirty_ = true; 73} 74 75void TransformOperations::AppendRotate(double x, double y, double z, 76 double degrees) { 77 TransformOperation to_add; 78 to_add.matrix.RotateAbout(gfx::Vector3dF(x, y, z), degrees); 79 to_add.type = TransformOperation::TransformOperationRotate; 80 to_add.rotate.axis.x = x; 81 to_add.rotate.axis.y = y; 82 to_add.rotate.axis.z = z; 83 to_add.rotate.angle = degrees; 84 operations_.push_back(to_add); 85 decomposed_transform_dirty_ = true; 86} 87 88void TransformOperations::AppendScale(double x, double y, double z) { 89 TransformOperation to_add; 90 to_add.matrix.Scale3d(x, y, z); 91 to_add.type = TransformOperation::TransformOperationScale; 92 to_add.scale.x = x; 93 to_add.scale.y = y; 94 to_add.scale.z = z; 95 operations_.push_back(to_add); 96 decomposed_transform_dirty_ = true; 97} 98 99void TransformOperations::AppendSkew(double x, double y) { 100 TransformOperation to_add; 101 to_add.matrix.SkewX(x); 102 to_add.matrix.SkewY(y); 103 to_add.type = TransformOperation::TransformOperationSkew; 104 to_add.skew.x = x; 105 to_add.skew.y = y; 106 operations_.push_back(to_add); 107 decomposed_transform_dirty_ = true; 108} 109 110void TransformOperations::AppendPerspective(double depth) { 111 TransformOperation to_add; 112 to_add.matrix.ApplyPerspectiveDepth(depth); 113 to_add.type = TransformOperation::TransformOperationPerspective; 114 to_add.perspective_depth = depth; 115 operations_.push_back(to_add); 116 decomposed_transform_dirty_ = true; 117} 118 119void TransformOperations::AppendMatrix(const gfx::Transform& matrix) { 120 TransformOperation to_add; 121 to_add.matrix = matrix; 122 to_add.type = TransformOperation::TransformOperationMatrix; 123 operations_.push_back(to_add); 124 decomposed_transform_dirty_ = true; 125} 126 127void TransformOperations::AppendIdentity() { 128 operations_.push_back(TransformOperation()); 129} 130 131bool TransformOperations::IsIdentity() const { 132 for (size_t i = 0; i < operations_.size(); ++i) { 133 if (!operations_[i].IsIdentity()) 134 return false; 135 } 136 return true; 137} 138 139bool TransformOperations::BlendInternal(const TransformOperations& from, 140 double progress, 141 gfx::Transform* result) const { 142 bool from_identity = from.IsIdentity(); 143 bool to_identity = IsIdentity(); 144 if (from_identity && to_identity) 145 return true; 146 147 if (MatchesTypes(from)) { 148 size_t num_operations = 149 std::max(from_identity ? 0 : from.operations_.size(), 150 to_identity ? 0 : operations_.size()); 151 for (size_t i = 0; i < num_operations; ++i) { 152 gfx::Transform blended; 153 if (!TransformOperation::BlendTransformOperations( 154 from_identity ? 0 : &from.operations_[i], 155 to_identity ? 0 : &operations_[i], 156 progress, 157 blended)) 158 return false; 159 result->PreconcatTransform(blended); 160 } 161 return true; 162 } 163 164 if (progress <= 0.0) { 165 *result = from.Apply(); 166 return true; 167 } 168 169 if (progress >= 1.0) { 170 *result = Apply(); 171 return true; 172 } 173 174 if (!ComputeDecomposedTransform() || !from.ComputeDecomposedTransform()) 175 return false; 176 177 gfx::DecomposedTransform to_return; 178 if (!gfx::BlendDecomposedTransforms(&to_return, 179 *decomposed_transform_.get(), 180 *from.decomposed_transform_.get(), 181 progress)) 182 return false; 183 184 *result = ComposeTransform(to_return); 185 return true; 186} 187 188bool TransformOperations::ComputeDecomposedTransform() const { 189 if (decomposed_transform_dirty_) { 190 if (!decomposed_transform_) 191 decomposed_transform_.reset(new gfx::DecomposedTransform()); 192 gfx::Transform transform = Apply(); 193 if (!gfx::DecomposeTransform(decomposed_transform_.get(), transform)) 194 return false; 195 decomposed_transform_dirty_ = false; 196 } 197 return true; 198} 199 200} // namespace cc 201