Pass CreateDirectory errors up to IndexedDB.
[chromium-blink-merge.git] / cc / animation / transform_operation.cc
blob854901dee4a59eada47fd9541ece0bc2a6164b3e
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/animation/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,
28 double* axis_y,
29 double* axis_z,
30 double* angle_from) {
31 if (IsOperationIdentity(from) && IsOperationIdentity(to))
32 return false;
34 if (IsOperationIdentity(from) && !IsOperationIdentity(to)) {
35 *axis_x = to->rotate.axis.x;
36 *axis_y = to->rotate.axis.y;
37 *axis_z = to->rotate.axis.z;
38 *angle_from = 0;
39 return true;
42 if (!IsOperationIdentity(from) && IsOperationIdentity(to)) {
43 *axis_x = from->rotate.axis.x;
44 *axis_y = from->rotate.axis.y;
45 *axis_z = from->rotate.axis.z;
46 *angle_from = from->rotate.angle;
47 return true;
50 double length_2 = from->rotate.axis.x * from->rotate.axis.x +
51 from->rotate.axis.y * from->rotate.axis.y +
52 from->rotate.axis.z * from->rotate.axis.z;
53 double other_length_2 = to->rotate.axis.x * to->rotate.axis.x +
54 to->rotate.axis.y * to->rotate.axis.y +
55 to->rotate.axis.z * to->rotate.axis.z;
57 if (length_2 <= kAngleEpsilon || other_length_2 <= kAngleEpsilon)
58 return false;
60 double dot = to->rotate.axis.x * from->rotate.axis.x +
61 to->rotate.axis.y * from->rotate.axis.y +
62 to->rotate.axis.z * from->rotate.axis.z;
63 double error = std::fabs(1.0 - (dot * dot) / (length_2 * other_length_2));
64 bool result = error < kAngleEpsilon;
65 if (result) {
66 *axis_x = to->rotate.axis.x;
67 *axis_y = to->rotate.axis.y;
68 *axis_z = to->rotate.axis.z;
69 // If the axes are pointing in opposite directions, we need to reverse
70 // the angle.
71 *angle_from = dot > 0 ? from->rotate.angle : -from->rotate.angle;
73 return result;
76 static double BlendDoubles(double from, double to, double progress) {
77 return from * (1 - progress) + to * progress;
80 bool TransformOperation::BlendTransformOperations(
81 const TransformOperation* from,
82 const TransformOperation* to,
83 double progress,
84 gfx::Transform* result) {
85 if (IsOperationIdentity(from) && IsOperationIdentity(to))
86 return true;
88 TransformOperation::Type interpolation_type =
89 TransformOperation::TransformOperationIdentity;
90 if (IsOperationIdentity(to))
91 interpolation_type = from->type;
92 else
93 interpolation_type = to->type;
95 switch (interpolation_type) {
96 case TransformOperation::TransformOperationTranslate: {
97 double from_x = IsOperationIdentity(from) ? 0 : from->translate.x;
98 double from_y = IsOperationIdentity(from) ? 0 : from->translate.y;
99 double from_z = IsOperationIdentity(from) ? 0 : from->translate.z;
100 double to_x = IsOperationIdentity(to) ? 0 : to->translate.x;
101 double to_y = IsOperationIdentity(to) ? 0 : to->translate.y;
102 double to_z = IsOperationIdentity(to) ? 0 : to->translate.z;
103 result->Translate3d(BlendDoubles(from_x, to_x, progress),
104 BlendDoubles(from_y, to_y, progress),
105 BlendDoubles(from_z, to_z, progress));
106 break;
108 case TransformOperation::TransformOperationRotate: {
109 double axis_x = 0;
110 double axis_y = 0;
111 double axis_z = 1;
112 double from_angle = 0;
113 double to_angle = IsOperationIdentity(to) ? 0 : to->rotate.angle;
114 if (ShareSameAxis(from, to, &axis_x, &axis_y, &axis_z, &from_angle)) {
115 result->RotateAbout(gfx::Vector3dF(axis_x, axis_y, axis_z),
116 BlendDoubles(from_angle, to_angle, progress));
117 } else {
118 gfx::Transform to_matrix;
119 if (!IsOperationIdentity(to))
120 to_matrix = to->matrix;
121 gfx::Transform from_matrix;
122 if (!IsOperationIdentity(from))
123 from_matrix = from->matrix;
124 *result = to_matrix;
125 if (!result->Blend(from_matrix, progress))
126 return false;
128 break;
130 case TransformOperation::TransformOperationScale: {
131 double from_x = IsOperationIdentity(from) ? 1 : from->scale.x;
132 double from_y = IsOperationIdentity(from) ? 1 : from->scale.y;
133 double from_z = IsOperationIdentity(from) ? 1 : from->scale.z;
134 double to_x = IsOperationIdentity(to) ? 1 : to->scale.x;
135 double to_y = IsOperationIdentity(to) ? 1 : to->scale.y;
136 double to_z = IsOperationIdentity(to) ? 1 : to->scale.z;
137 result->Scale3d(BlendDoubles(from_x, to_x, progress),
138 BlendDoubles(from_y, to_y, progress),
139 BlendDoubles(from_z, to_z, progress));
140 break;
142 case TransformOperation::TransformOperationSkew: {
143 double from_x = IsOperationIdentity(from) ? 0 : from->skew.x;
144 double from_y = IsOperationIdentity(from) ? 0 : from->skew.y;
145 double to_x = IsOperationIdentity(to) ? 0 : to->skew.x;
146 double to_y = IsOperationIdentity(to) ? 0 : to->skew.y;
147 result->SkewX(BlendDoubles(from_x, to_x, progress));
148 result->SkewY(BlendDoubles(from_y, to_y, progress));
149 break;
151 case TransformOperation::TransformOperationPerspective: {
152 double from_perspective_depth = IsOperationIdentity(from) ?
153 std::numeric_limits<double>::max() : from->perspective_depth;
154 double to_perspective_depth = IsOperationIdentity(to) ?
155 std::numeric_limits<double>::max() : to->perspective_depth;
156 result->ApplyPerspectiveDepth(
157 BlendDoubles(from_perspective_depth, to_perspective_depth, progress));
158 break;
160 case TransformOperation::TransformOperationMatrix: {
161 gfx::Transform to_matrix;
162 if (!IsOperationIdentity(to))
163 to_matrix = to->matrix;
164 gfx::Transform from_matrix;
165 if (!IsOperationIdentity(from))
166 from_matrix = from->matrix;
167 *result = to_matrix;
168 if (!result->Blend(from_matrix, progress))
169 return false;
170 break;
172 case TransformOperation::TransformOperationIdentity:
173 // Do nothing.
174 break;
177 return true;
180 } // namespace cc