Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: cc/transform_operations.cc

Issue 11745018: Not for review: Move the implementation of WebTransformOperations into chromium (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: New approach Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/transform_operations.h ('k') | cc/transform_operations_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 <algorithm>
6 #include <cmath>
7 #include <limits>
8 #include <vector>
9
10 #include "cc/transform_operations.h"
11
12 using WebKit::WebTransformationMatrix;
13
14 namespace {
15 const double EPSILON = 1e-4;
jamesr 2013/01/14 22:03:00 use chromium style kEpsilon it's pretty weird for
Ian Vollick 2013/01/15 15:02:38 I used this epsilon when checking if two rotations
16 }
17
18 namespace cc {
19
20 struct TransformOperation {
21 enum Type {
22 TransformOperationTranslate,
23 TransformOperationRotate,
24 TransformOperationScale,
25 TransformOperationSkew,
26 TransformOperationPerspective,
27 TransformOperationMatrix,
28 TransformOperationIdentity
29 };
30
31 TransformOperation()
32 : type(TransformOperationIdentity) {
jamesr 2013/01/14 22:03:00 this should be indented 4 spaces from the previous
33 }
34
35 Type type;
36 WebKit::WebTransformationMatrix matrix;
37
38 union {
39 double perspective_depth;
40
41 struct {
42 double x, y;
43 } skew;
44
45 struct {
46 double x, y, z;
47 } scale;
48
49 struct {
50 double x, y, z;
51 } translate;
52
53 struct {
54 struct {
55 double x, y, z;
56 } axis;
57
58 double angle;
59 } rotate;
60 };
61
62 bool IsIdentity() const { return matrix.isIdentity(); }
63 };
64
65 TransformOperations::TransformOperations() {
66 Initialize();
67 }
68
69 TransformOperations::TransformOperations(const TransformOperations& other) {
70 Initialize(other);
71 }
72
73 TransformOperations::~TransformOperations() {
74 }
75
76 struct TransformOperationsPrivate {
77 std::vector<TransformOperation> operations;
78 };
79
80 WebTransformationMatrix TransformOperations::Apply() const {
81 WebTransformationMatrix to_return;
82 for (size_t i = 0; i < private_->operations.size(); ++i)
83 to_return.multiply(private_->operations[i].matrix);
84 return to_return;
85 }
86
87 static bool IsIdentity(const TransformOperation* operation) {
88 return !operation || operation->IsIdentity();
89 }
90
91 static bool ShareSameAxis(const TransformOperation* from,
92 const TransformOperation* to,
93 double& axis_x, double& axis_y, double& axis_z,
94 double& angle_from) {
95 if (IsIdentity(from) && IsIdentity(to))
96 return false;
97
98 if (IsIdentity(from) && !IsIdentity(to)) {
99 axis_x = to->rotate.axis.x;
100 axis_y = to->rotate.axis.y;
101 axis_z = to->rotate.axis.z;
102 angle_from = 0;
103 return true;
104 }
105
106 if (!IsIdentity(from) && IsIdentity(to)) {
107 axis_x = from->rotate.axis.x;
108 axis_y = from->rotate.axis.y;
109 axis_z = from->rotate.axis.z;
110 angle_from = from->rotate.angle;
111 return true;
112 }
113
114 double length_2 = from->rotate.axis.x * from->rotate.axis.x +
115 from->rotate.axis.y * from->rotate.axis.y +
116 from->rotate.axis.z * from->rotate.axis.z;
117 double other_length_2 = to->rotate.axis.x * to->rotate.axis.x +
118 to->rotate.axis.y * to->rotate.axis.y +
119 to->rotate.axis.z * to->rotate.axis.z;
120
121 if (length_2 <= EPSILON || other_length_2 <= EPSILON)
122 return false;
123
124 double dot = to->rotate.axis.x * from->rotate.axis.x +
125 to->rotate.axis.y * from->rotate.axis.y +
126 to->rotate.axis.z * from->rotate.axis.z;
127 double error = std::fabs(1.0 - (dot * dot) / (length_2 * other_length_2));
128 bool result = error < EPSILON;
129 if (result) {
130 axis_x = to->rotate.axis.x;
131 axis_y = to->rotate.axis.y;
132 axis_z = to->rotate.axis.z;
133 // If the axes are pointing in opposite directions, we need to reverse
134 // the angle.
135 angle_from = dot > 0 ? from->rotate.angle : -from->rotate.angle;
136 }
137 return result;
138 }
139
140 static double BlendDoubles(double from, double to, double progress) {
141 return from * (1 - progress) + to * progress;
142 }
143
144 static bool BlendTransformOperations(const TransformOperation* from,
145 const TransformOperation* to,
146 double progress,
147 WebTransformationMatrix& result) {
148 if (IsIdentity(from) && IsIdentity(to))
149 return true;
150
151 TransformOperation::Type interpolation_type =
152 TransformOperation::TransformOperationIdentity;
153 if (IsIdentity(to))
154 interpolation_type = from->type;
155 else
156 interpolation_type = to->type;
157
158 switch (interpolation_type) {
159 case TransformOperation::TransformOperationTranslate: {
160 double from_x = IsIdentity(from) ? 0 : from->translate.x;
161 double from_y = IsIdentity(from) ? 0 : from->translate.y;
162 double from_z = IsIdentity(from) ? 0 : from->translate.z;
163 double to_x = IsIdentity(to) ? 0 : to->translate.x;
164 double to_y = IsIdentity(to) ? 0 : to->translate.y;
165 double to_z = IsIdentity(to) ? 0 : to->translate.z;
166 result.translate3d(BlendDoubles(from_x, to_x, progress),
167 BlendDoubles(from_y, to_y, progress),
168 BlendDoubles(from_z, to_z, progress));
169 break;
170 }
171 case TransformOperation::TransformOperationRotate: {
172 double axis_x = 0;
173 double axis_y = 0;
174 double axis_z = 1;
175 double from_angle = 0;
176 double to_angle = IsIdentity(to) ? 0 : to->rotate.angle;
177 if (ShareSameAxis(from, to, axis_x, axis_y, axis_z, from_angle))
178 result.rotate3d(axis_x, axis_y, axis_z,
179 BlendDoubles(from_angle, to_angle, progress));
180 else {
181 WebTransformationMatrix to_matrix;
182 if (!IsIdentity(to))
183 to_matrix = to->matrix;
184 WebTransformationMatrix from_matrix;
185 if (!IsIdentity(from))
186 from_matrix = from->matrix;
187 result = to_matrix;
188 if (!result.blend(from_matrix, progress))
189 return false;
190 }
191 break;
192 }
193 case TransformOperation::TransformOperationScale: {
194 double from_x = IsIdentity(from) ? 1 : from->scale.x;
195 double from_y = IsIdentity(from) ? 1 : from->scale.y;
196 double from_z = IsIdentity(from) ? 1 : from->scale.z;
197 double to_x = IsIdentity(to) ? 1 : to->scale.x;
198 double to_y = IsIdentity(to) ? 1 : to->scale.y;
199 double to_z = IsIdentity(to) ? 1 : to->scale.z;
200 result.scale3d(BlendDoubles(from_x, to_x, progress),
201 BlendDoubles(from_y, to_y, progress),
202 BlendDoubles(from_z, to_z, progress));
203 break;
204 }
205 case TransformOperation::TransformOperationSkew: {
206 double from_x = IsIdentity(from) ? 0 : from->skew.x;
207 double from_y = IsIdentity(from) ? 0 : from->skew.y;
208 double to_x = IsIdentity(to) ? 0 : to->skew.x;
209 double to_y = IsIdentity(to) ? 0 : to->skew.y;
210 result.skewX(BlendDoubles(from_x, to_x, progress));
211 result.skewY(BlendDoubles(from_y, to_y, progress));
212 break;
213 }
214 case TransformOperation::TransformOperationPerspective: {
215 double from_perspective_depth = IsIdentity(from) ?
216 std::numeric_limits<double>::max() : from->perspective_depth;
217 double to_perspective_depth = IsIdentity(to) ?
218 std::numeric_limits<double>::max() : to->perspective_depth;
219 result.applyPerspective(
220 BlendDoubles(from_perspective_depth, to_perspective_depth, progress));
221 break;
222 }
223 case TransformOperation::TransformOperationMatrix: {
224 WebTransformationMatrix to_matrix;
225 if (!IsIdentity(to))
226 to_matrix = to->matrix;
227 WebTransformationMatrix from_matrix;
228 if (!IsIdentity(from))
229 from_matrix = from->matrix;
230 result = to_matrix;
231 if (!result.blend(from_matrix, progress))
232 return false;
233 break;
234 }
235 case TransformOperation::TransformOperationIdentity:
236 // Do nothing.
237 break;
238 }
239
240 return true;
241 }
242
243 WebTransformationMatrix TransformOperations::Blend(
244 const TransformOperations& from, double progress) const {
245 WebTransformationMatrix to_return;
246 BlendInternal(from, progress, to_return);
247 return to_return;
248 }
249
250 bool TransformOperations::MatchesTypes(const TransformOperations& other) const {
251 if (IsIdentity() || other.IsIdentity())
252 return true;
253
254 if (private_->operations.size() != other.private_->operations.size())
255 return false;
256
257 for (size_t i = 0; i < private_->operations.size(); ++i) {
258 if (private_->operations[i].type != other.private_->operations[i].type
259 && !private_->operations[i].IsIdentity()
260 && !other.private_->operations[i].IsIdentity())
261 return false;
262 }
263
264 return true;
265 }
266
267 bool TransformOperations::CanBlendWith(
268 const TransformOperations& other) const {
269 WebTransformationMatrix dummy;
270 return BlendInternal(other, 0.5, dummy);
271 }
272
273 void TransformOperations::AppendTranslate(double x, double y, double z) {
274 TransformOperation to_add;
275 to_add.matrix.translate3d(x, y, z);
276 to_add.type = TransformOperation::TransformOperationTranslate;
277 to_add.translate.x = x;
278 to_add.translate.y = y;
279 to_add.translate.z = z;
280 private_->operations.push_back(to_add);
281 }
282
283 void TransformOperations::AppendRotate(double x, double y, double z,
284 double degrees) {
285 TransformOperation to_add;
286 to_add.matrix.rotate3d(x, y, z, degrees);
287 to_add.type = TransformOperation::TransformOperationRotate;
288 to_add.rotate.axis.x = x;
289 to_add.rotate.axis.y = y;
290 to_add.rotate.axis.z = z;
291 to_add.rotate.angle = degrees;
292 private_->operations.push_back(to_add);
293 }
294
295 void TransformOperations::AppendScale(double x, double y, double z) {
296 TransformOperation to_add;
297 to_add.matrix.scale3d(x, y, z);
298 to_add.type = TransformOperation::TransformOperationScale;
299 to_add.scale.x = x;
300 to_add.scale.y = y;
301 to_add.scale.z = z;
302 private_->operations.push_back(to_add);
303 }
304
305 void TransformOperations::AppendSkew(double x, double y) {
306 TransformOperation to_add;
307 to_add.matrix.skewX(x);
308 to_add.matrix.skewY(y);
309 to_add.type = TransformOperation::TransformOperationSkew;
310 to_add.skew.x = x;
311 to_add.skew.y = y;
312 private_->operations.push_back(to_add);
313 }
314
315 void TransformOperations::AppendPerspective(double depth) {
316 TransformOperation to_add;
317 to_add.matrix.applyPerspective(depth);
318 to_add.type = TransformOperation::TransformOperationPerspective;
319 to_add.perspective_depth = depth;
320 private_->operations.push_back(to_add);
321 }
322
323 void TransformOperations::AppendMatrix(const WebTransformationMatrix& matrix) {
324 TransformOperation to_add;
325 to_add.matrix = matrix;
326 to_add.type = TransformOperation::TransformOperationMatrix;
327 private_->operations.push_back(to_add);
328 }
329
330 void TransformOperations::AppendIdentity() {
331 private_->operations.push_back(TransformOperation());
332 }
333
334 bool TransformOperations::IsIdentity() const {
335 for (size_t i = 0; i < private_->operations.size(); ++i) {
336 if (!private_->operations[i].IsIdentity())
337 return false;
338 }
339 return true;
340 }
341
342 void TransformOperations::Initialize() {
343 private_.reset(new TransformOperationsPrivate);
344 }
345
346 void TransformOperations::Initialize(const TransformOperations& other) {
347 if (private_.get() != other.private_.get())
348 private_.reset(new TransformOperationsPrivate(*other.private_.get()));
349 else
350 Initialize();
351 }
352
353 bool TransformOperations::BlendInternal(const TransformOperations& from,
354 double progress,
355 WebTransformationMatrix& result) const {
356 bool from_identity = from.IsIdentity();
357 bool to_identity = IsIdentity();
358 if (from_identity && to_identity)
359 return true;
360
361 if (MatchesTypes(from)) {
362 size_t num_operations =
363 std::max(from_identity ? 0 : from.private_->operations.size(),
364 to_identity ? 0 : private_->operations.size());
365 for (size_t i = 0; i < num_operations; ++i) {
366 WebTransformationMatrix blended;
367 if (!BlendTransformOperations(
368 from_identity ? 0 : &from.private_->operations[i],
369 to_identity ? 0 : &private_->operations[i],
370 progress,
371 blended))
372 return false;
373 result.multiply(blended);
374 }
375 return true;
376 }
377
378 result = Apply();
379 WebTransformationMatrix from_transform = from.Apply();
380 return result.blend(from_transform, progress);
381 }
382
383 } // namespace cc
OLDNEW
« no previous file with comments | « cc/transform_operations.h ('k') | cc/transform_operations_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698