add a use_alsa gyp setting
[chromium-blink-merge.git] / cc / transform_operation.cc
blob2c3b632f28c25a6a801050aecc122e7ece8dc70a
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 <cmath>
6 #include <limits>
8 #include "cc/transform_operation.h"
9 #include "ui/gfx/vector3d_f.h"
11 namespace {
12 const double kAngleEpsilon = 1e-4;
15 namespace cc {
17 bool TransformOperation::IsIdentity() const {
18 return matrix.IsIdentity();
21 static bool IsOperationIdentity(const TransformOperation* operation) {
22 return !operation || operation->IsIdentity();
25 static bool ShareSameAxis(const TransformOperation* from,
26 const TransformOperation* to,
27 double& axis_x, double& axis_y, double& axis_z,
28 double& angle_from) {
29 if (IsOperationIdentity(from) && IsOperationIdentity(to))
30 return false;
32 if (IsOperationIdentity(from) && !IsOperationIdentity(to)) {
33 axis_x = to->rotate.axis.x;
34 axis_y = to->rotate.axis.y;
35 axis_z = to->rotate.axis.z;
36 angle_from = 0;
37 return true;
40 if (!IsOperationIdentity(from) && IsOperationIdentity(to)) {
41 axis_x = from->rotate.axis.x;
42 axis_y = from->rotate.axis.y;
43 axis_z = from->rotate.axis.z;
44 angle_from = from->rotate.angle;
45 return true;
48 double length_2 = from->rotate.axis.x * from->rotate.axis.x +
49 from->rotate.axis.y * from->rotate.axis.y +
50 from->rotate.axis.z * from->rotate.axis.z;
51 double other_length_2 = to->rotate.axis.x * to->rotate.axis.x +
52 to->rotate.axis.y * to->rotate.axis.y +
53 to->rotate.axis.z * to->rotate.axis.z;
55 if (length_2 <= kAngleEpsilon || other_length_2 <= kAngleEpsilon)
56 return false;
58 double dot = to->rotate.axis.x * from->rotate.axis.x +
59 to->rotate.axis.y * from->rotate.axis.y +
60 to->rotate.axis.z * from->rotate.axis.z;
61 double error = std::fabs(1.0 - (dot * dot) / (length_2 * other_length_2));
62 bool result = error < kAngleEpsilon;
63 if (result) {
64 axis_x = to->rotate.axis.x;
65 axis_y = to->rotate.axis.y;
66 axis_z = to->rotate.axis.z;
67 // If the axes are pointing in opposite directions, we need to reverse
68 // the angle.
69 angle_from = dot > 0 ? from->rotate.angle : -from->rotate.angle;
71 return result;
74 static double BlendDoubles(double from, double to, double progress) {
75 if (progress <= 0.0)
76 return from;
78 if (progress >= 1.0)
79 return to;
81 return from * (1 - progress) + to * progress;
84 bool TransformOperation::BlendTransformOperations(
85 const TransformOperation* from,
86 const TransformOperation* to,
87 double progress,
88 gfx::Transform& result) {
89 if (IsOperationIdentity(from) && IsOperationIdentity(to))
90 return true;
92 TransformOperation::Type interpolation_type =
93 TransformOperation::TransformOperationIdentity;
94 if (IsOperationIdentity(to))
95 interpolation_type = from->type;
96 else
97 interpolation_type = to->type;
99 switch (interpolation_type) {
100 case TransformOperation::TransformOperationTranslate: {
101 double from_x = IsOperationIdentity(from) ? 0 : from->translate.x;
102 double from_y = IsOperationIdentity(from) ? 0 : from->translate.y;
103 double from_z = IsOperationIdentity(from) ? 0 : from->translate.z;
104 double to_x = IsOperationIdentity(to) ? 0 : to->translate.x;
105 double to_y = IsOperationIdentity(to) ? 0 : to->translate.y;
106 double to_z = IsOperationIdentity(to) ? 0 : to->translate.z;
107 result.Translate3d(BlendDoubles(from_x, to_x, progress),
108 BlendDoubles(from_y, to_y, progress),
109 BlendDoubles(from_z, to_z, progress));
110 break;
112 case TransformOperation::TransformOperationRotate: {
113 double axis_x = 0;
114 double axis_y = 0;
115 double axis_z = 1;
116 double from_angle = 0;
117 double to_angle = IsOperationIdentity(to) ? 0 : to->rotate.angle;
118 if (ShareSameAxis(from, to, axis_x, axis_y, axis_z, from_angle))
119 result.RotateAbout(gfx::Vector3dF(axis_x, axis_y, axis_z),
120 BlendDoubles(from_angle, to_angle, progress));
121 else {
122 gfx::Transform to_matrix;
123 if (!IsOperationIdentity(to))
124 to_matrix = to->matrix;
125 gfx::Transform from_matrix;
126 if (!IsOperationIdentity(from))
127 from_matrix = from->matrix;
128 result = to_matrix;
129 if (!result.Blend(from_matrix, progress))
130 return false;
132 break;
134 case TransformOperation::TransformOperationScale: {
135 double from_x = IsOperationIdentity(from) ? 1 : from->scale.x;
136 double from_y = IsOperationIdentity(from) ? 1 : from->scale.y;
137 double from_z = IsOperationIdentity(from) ? 1 : from->scale.z;
138 double to_x = IsOperationIdentity(to) ? 1 : to->scale.x;
139 double to_y = IsOperationIdentity(to) ? 1 : to->scale.y;
140 double to_z = IsOperationIdentity(to) ? 1 : to->scale.z;
141 result.Scale3d(BlendDoubles(from_x, to_x, progress),
142 BlendDoubles(from_y, to_y, progress),
143 BlendDoubles(from_z, to_z, progress));
144 break;
146 case TransformOperation::TransformOperationSkew: {
147 double from_x = IsOperationIdentity(from) ? 0 : from->skew.x;
148 double from_y = IsOperationIdentity(from) ? 0 : from->skew.y;
149 double to_x = IsOperationIdentity(to) ? 0 : to->skew.x;
150 double to_y = IsOperationIdentity(to) ? 0 : to->skew.y;
151 result.SkewX(BlendDoubles(from_x, to_x, progress));
152 result.SkewY(BlendDoubles(from_y, to_y, progress));
153 break;
155 case TransformOperation::TransformOperationPerspective: {
156 double from_perspective_depth = IsOperationIdentity(from) ?
157 std::numeric_limits<double>::max() : from->perspective_depth;
158 double to_perspective_depth = IsOperationIdentity(to) ?
159 std::numeric_limits<double>::max() : to->perspective_depth;
160 result.ApplyPerspectiveDepth(
161 BlendDoubles(from_perspective_depth, to_perspective_depth, progress));
162 break;
164 case TransformOperation::TransformOperationMatrix: {
165 gfx::Transform to_matrix;
166 if (!IsOperationIdentity(to))
167 to_matrix = to->matrix;
168 gfx::Transform from_matrix;
169 if (!IsOperationIdentity(from))
170 from_matrix = from->matrix;
171 result = to_matrix;
172 if (!result.Blend(from_matrix, progress))
173 return false;
174 break;
176 case TransformOperation::TransformOperationIdentity:
177 // Do nothing.
178 break;
181 return true;
184 } // namespace cc