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/transform_operations.h"
6 #include "ui/gfx/transform_util.h"
7 #include "ui/gfx/vector3d_f.h"
11 TransformOperations::TransformOperations()
12 : decomposed_transform_dirty_(true) {
15 TransformOperations::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()));
24 TransformOperations::~TransformOperations() {
27 gfx::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
);
34 gfx::Transform
TransformOperations::Blend(
35 const TransformOperations
& from
, double progress
) const {
36 gfx::Transform to_return
;
37 BlendInternal(from
, progress
, &to_return
);
41 bool TransformOperations::MatchesTypes(const TransformOperations
& other
) const {
42 if (IsIdentity() || other
.IsIdentity())
45 if (operations_
.size() != other
.operations_
.size())
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())
58 bool TransformOperations::CanBlendWith(
59 const TransformOperations
& other
) const {
61 return BlendInternal(other
, 0.5, &dummy
);
64 void 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;
75 void TransformOperations::AppendRotate(double x
, double y
, double z
,
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;
88 void 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
;
95 operations_
.push_back(to_add
);
96 decomposed_transform_dirty_
= true;
99 void 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
;
106 operations_
.push_back(to_add
);
107 decomposed_transform_dirty_
= true;
110 void 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;
119 void 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;
127 void TransformOperations::AppendIdentity() {
128 operations_
.push_back(TransformOperation());
131 bool TransformOperations::IsIdentity() const {
132 for (size_t i
= 0; i
< operations_
.size(); ++i
) {
133 if (!operations_
[i
].IsIdentity())
139 bool TransformOperations::BlendInternal(const TransformOperations
& from
,
141 gfx::Transform
* result
) const {
142 bool from_identity
= from
.IsIdentity();
143 bool to_identity
= IsIdentity();
144 if (from_identity
&& to_identity
)
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
],
159 result
->PreconcatTransform(blended
);
164 if (progress
<= 0.0) {
165 *result
= from
.Apply();
169 if (progress
>= 1.0) {
174 if (!ComputeDecomposedTransform() || !from
.ComputeDecomposedTransform())
177 gfx::DecomposedTransform to_return
;
178 if (!gfx::BlendDecomposedTransforms(&to_return
,
179 *decomposed_transform_
.get(),
180 *from
.decomposed_transform_
.get(),
184 *result
= ComposeTransform(to_return
);
188 bool 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
))
195 decomposed_transform_dirty_
= false;