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.
5 #include "cc/animation/transform_operations.h"
9 #include "ui/gfx/transform_util.h"
10 #include "ui/gfx/vector3d_f.h"
14 TransformOperations::TransformOperations()
15 : decomposed_transform_dirty_(true) {
18 TransformOperations::TransformOperations(const TransformOperations
& other
) {
19 operations_
= other
.operations_
;
20 decomposed_transform_dirty_
= other
.decomposed_transform_dirty_
;
21 if (!decomposed_transform_dirty_
) {
22 decomposed_transform_
.reset(
23 new gfx::DecomposedTransform(*other
.decomposed_transform_
.get()));
27 TransformOperations::~TransformOperations() {
30 gfx::Transform
TransformOperations::Apply() const {
31 gfx::Transform to_return
;
32 for (size_t i
= 0; i
< operations_
.size(); ++i
)
33 to_return
.PreconcatTransform(operations_
[i
].matrix
);
37 gfx::Transform
TransformOperations::Blend(
38 const TransformOperations
& from
, double progress
) const {
39 gfx::Transform to_return
;
40 BlendInternal(from
, progress
, &to_return
);
44 bool TransformOperations::MatchesTypes(const TransformOperations
& other
) const {
45 if (IsIdentity() || other
.IsIdentity())
48 if (operations_
.size() != other
.operations_
.size())
51 for (size_t i
= 0; i
< operations_
.size(); ++i
) {
52 if (operations_
[i
].type
!= other
.operations_
[i
].type
53 && !operations_
[i
].IsIdentity()
54 && !other
.operations_
[i
].IsIdentity())
61 bool TransformOperations::CanBlendWith(
62 const TransformOperations
& other
) const {
64 return BlendInternal(other
, 0.5, &dummy
);
67 void TransformOperations::AppendTranslate(double x
, double y
, double z
) {
68 TransformOperation to_add
;
69 to_add
.matrix
.Translate3d(x
, y
, z
);
70 to_add
.type
= TransformOperation::TransformOperationTranslate
;
71 to_add
.translate
.x
= x
;
72 to_add
.translate
.y
= y
;
73 to_add
.translate
.z
= z
;
74 operations_
.push_back(to_add
);
75 decomposed_transform_dirty_
= true;
78 void TransformOperations::AppendRotate(double x
, double y
, double z
,
80 TransformOperation to_add
;
81 to_add
.matrix
.RotateAbout(gfx::Vector3dF(x
, y
, z
), degrees
);
82 to_add
.type
= TransformOperation::TransformOperationRotate
;
83 to_add
.rotate
.axis
.x
= x
;
84 to_add
.rotate
.axis
.y
= y
;
85 to_add
.rotate
.axis
.z
= z
;
86 to_add
.rotate
.angle
= degrees
;
87 operations_
.push_back(to_add
);
88 decomposed_transform_dirty_
= true;
91 void TransformOperations::AppendScale(double x
, double y
, double z
) {
92 TransformOperation to_add
;
93 to_add
.matrix
.Scale3d(x
, y
, z
);
94 to_add
.type
= TransformOperation::TransformOperationScale
;
98 operations_
.push_back(to_add
);
99 decomposed_transform_dirty_
= true;
102 void TransformOperations::AppendSkew(double x
, double y
) {
103 TransformOperation to_add
;
104 to_add
.matrix
.SkewX(x
);
105 to_add
.matrix
.SkewY(y
);
106 to_add
.type
= TransformOperation::TransformOperationSkew
;
109 operations_
.push_back(to_add
);
110 decomposed_transform_dirty_
= true;
113 void TransformOperations::AppendPerspective(double depth
) {
114 TransformOperation to_add
;
115 to_add
.matrix
.ApplyPerspectiveDepth(depth
);
116 to_add
.type
= TransformOperation::TransformOperationPerspective
;
117 to_add
.perspective_depth
= depth
;
118 operations_
.push_back(to_add
);
119 decomposed_transform_dirty_
= true;
122 void TransformOperations::AppendMatrix(const gfx::Transform
& matrix
) {
123 TransformOperation to_add
;
124 to_add
.matrix
= matrix
;
125 to_add
.type
= TransformOperation::TransformOperationMatrix
;
126 operations_
.push_back(to_add
);
127 decomposed_transform_dirty_
= true;
130 void TransformOperations::AppendIdentity() {
131 operations_
.push_back(TransformOperation());
134 bool TransformOperations::IsIdentity() const {
135 for (size_t i
= 0; i
< operations_
.size(); ++i
) {
136 if (!operations_
[i
].IsIdentity())
142 bool TransformOperations::BlendInternal(const TransformOperations
& from
,
144 gfx::Transform
* result
) const {
145 bool from_identity
= from
.IsIdentity();
146 bool to_identity
= IsIdentity();
147 if (from_identity
&& to_identity
)
150 if (MatchesTypes(from
)) {
151 size_t num_operations
=
152 std::max(from_identity
? 0 : from
.operations_
.size(),
153 to_identity
? 0 : operations_
.size());
154 for (size_t i
= 0; i
< num_operations
; ++i
) {
155 gfx::Transform blended
;
156 if (!TransformOperation::BlendTransformOperations(
157 from_identity
? 0 : &from
.operations_
[i
],
158 to_identity
? 0 : &operations_
[i
],
162 result
->PreconcatTransform(blended
);
167 if (progress
<= 0.0) {
168 *result
= from
.Apply();
172 if (progress
>= 1.0) {
177 if (!ComputeDecomposedTransform() || !from
.ComputeDecomposedTransform())
180 gfx::DecomposedTransform to_return
;
181 if (!gfx::BlendDecomposedTransforms(&to_return
,
182 *decomposed_transform_
.get(),
183 *from
.decomposed_transform_
.get(),
187 *result
= ComposeTransform(to_return
);
191 bool TransformOperations::ComputeDecomposedTransform() const {
192 if (decomposed_transform_dirty_
) {
193 if (!decomposed_transform_
)
194 decomposed_transform_
.reset(new gfx::DecomposedTransform());
195 gfx::Transform transform
= Apply();
196 if (!gfx::DecomposeTransform(decomposed_transform_
.get(), transform
))
198 decomposed_transform_dirty_
= false;