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

Side by Side Diff: cc/math_util.cc

Issue 11308153: Migrate most of cc/ from WebKit::WebTransformationMatrix to gfx::Transform (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased to tip of tree and addressed feedback Created 8 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/math_util.h" 5 #include "cc/math_util.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <limits> 8 #include <limits>
9 9
10 #include "ui/gfx/quad_f.h" 10 #include "ui/gfx/quad_f.h"
11 #include "ui/gfx/rect.h" 11 #include "ui/gfx/rect.h"
12 #include "ui/gfx/rect_conversions.h" 12 #include "ui/gfx/rect_conversions.h"
13 #include "ui/gfx/rect_f.h" 13 #include "ui/gfx/rect_f.h"
14 #include "ui/gfx/transform.h"
14 #include "ui/gfx/vector2d_f.h" 15 #include "ui/gfx/vector2d_f.h"
15 #include <public/WebTransformationMatrix.h>
16 16
17 using WebKit::WebTransformationMatrix; 17 using gfx::Transform;
18 18
19 namespace cc { 19 namespace cc {
20 20
21 const double MathUtil::PI_DOUBLE = 3.14159265358979323846; 21 const double MathUtil::PI_DOUBLE = 3.14159265358979323846;
22 const float MathUtil::PI_FLOAT = 3.14159265358979323846f; 22 const float MathUtil::PI_FLOAT = 3.14159265358979323846f;
23 const double MathUtil::EPSILON = 1e-9; 23 const double MathUtil::EPSILON = 1e-9;
24 24
25 static HomogeneousCoordinate projectHomogeneousPoint(const WebTransformationMatr ix& transform, const gfx::PointF& p) 25 static HomogeneousCoordinate projectHomogeneousPoint(const Transform& transform, const gfx::PointF& p)
26 { 26 {
27 // In this case, the layer we are trying to project onto is perpendicular to ray 27 // In this case, the layer we are trying to project onto is perpendicular to ray
28 // (point p and z-axis direction) that we are trying to project. This happen s when the 28 // (point p and z-axis direction) that we are trying to project. This happen s when the
29 // layer is rotated so that it is infinitesimally thin, or when it is co-pla nar with 29 // layer is rotated so that it is infinitesimally thin, or when it is co-pla nar with
30 // the camera origin -- i.e. when the layer is invisible anyway. 30 // the camera origin -- i.e. when the layer is invisible anyway.
31 if (!transform.m33()) 31 if (!transform.matrix().getDouble(2, 2))
32 return HomogeneousCoordinate(0, 0, 0, 1); 32 return HomogeneousCoordinate(0, 0, 0, 1);
33 33
34 double x = p.x(); 34 double x = p.x();
35 double y = p.y(); 35 double y = p.y();
36 double z = -(transform.m13() * x + transform.m23() * y + transform.m43()) / transform.m33(); 36 double z = -(transform.matrix().getDouble(2, 0) * x + transform.matrix().get Double(2, 1) * y + transform.matrix().getDouble(2, 3)) / transform.matrix().getD ouble(2, 2);
37 // implicit definition of w = 1; 37 // implicit definition of w = 1;
38 38
39 double outX = x * transform.m11() + y * transform.m21() + z * transform.m31( ) + transform.m41(); 39 double outX = x * transform.matrix().getDouble(0, 0) + y * transform.matrix( ).getDouble(0, 1) + z * transform.matrix().getDouble(0, 2) + transform.matrix(). getDouble(0, 3);
40 double outY = x * transform.m12() + y * transform.m22() + z * transform.m32( ) + transform.m42(); 40 double outY = x * transform.matrix().getDouble(1, 0) + y * transform.matrix( ).getDouble(1, 1) + z * transform.matrix().getDouble(1, 2) + transform.matrix(). getDouble(1, 3);
41 double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33( ) + transform.m43(); 41 double outZ = x * transform.matrix().getDouble(2, 0) + y * transform.matrix( ).getDouble(2, 1) + z * transform.matrix().getDouble(2, 2) + transform.matrix(). getDouble(2, 3);
42 double outW = x * transform.m14() + y * transform.m24() + z * transform.m34( ) + transform.m44(); 42 double outW = x * transform.matrix().getDouble(3, 0) + y * transform.matrix( ).getDouble(3, 1) + z * transform.matrix().getDouble(3, 2) + transform.matrix(). getDouble(3, 3);
43 43
44 return HomogeneousCoordinate(outX, outY, outZ, outW); 44 return HomogeneousCoordinate(outX, outY, outZ, outW);
45 } 45 }
46 46
47 static HomogeneousCoordinate mapHomogeneousPoint(const WebTransformationMatrix& transform, const gfx::Point3F& p) 47 static HomogeneousCoordinate mapHomogeneousPoint(const Transform& transform, con st gfx::Point3F& p)
48 { 48 {
49 double x = p.x(); 49 double x = p.x();
50 double y = p.y(); 50 double y = p.y();
51 double z = p.z(); 51 double z = p.z();
52 // implicit definition of w = 1; 52 // implicit definition of w = 1;
53 53
54 double outX = x * transform.m11() + y * transform.m21() + z * transform.m31( ) + transform.m41(); 54 double outX = x * transform.matrix().getDouble(0, 0) + y * transform.matrix( ).getDouble(0, 1) + z * transform.matrix().getDouble(0, 2) + transform.matrix(). getDouble(0, 3);
55 double outY = x * transform.m12() + y * transform.m22() + z * transform.m32( ) + transform.m42(); 55 double outY = x * transform.matrix().getDouble(1, 0) + y * transform.matrix( ).getDouble(1, 1) + z * transform.matrix().getDouble(1, 2) + transform.matrix(). getDouble(1, 3);
56 double outZ = x * transform.m13() + y * transform.m23() + z * transform.m33( ) + transform.m43(); 56 double outZ = x * transform.matrix().getDouble(2, 0) + y * transform.matrix( ).getDouble(2, 1) + z * transform.matrix().getDouble(2, 2) + transform.matrix(). getDouble(2, 3);
57 double outW = x * transform.m14() + y * transform.m24() + z * transform.m34( ) + transform.m44(); 57 double outW = x * transform.matrix().getDouble(3, 0) + y * transform.matrix( ).getDouble(3, 1) + z * transform.matrix().getDouble(3, 2) + transform.matrix(). getDouble(3, 3);
58 58
59 return HomogeneousCoordinate(outX, outY, outZ, outW); 59 return HomogeneousCoordinate(outX, outY, outZ, outW);
60 } 60 }
61 61
62 static HomogeneousCoordinate computeClippedPointForEdge(const HomogeneousCoordin ate& h1, const HomogeneousCoordinate& h2) 62 static HomogeneousCoordinate computeClippedPointForEdge(const HomogeneousCoordin ate& h1, const HomogeneousCoordinate& h2)
63 { 63 {
64 // Points h1 and h2 form a line in 4d, and any point on that line can be rep resented 64 // Points h1 and h2 form a line in 4d, and any point on that line can be rep resented
65 // as an interpolation between h1 and h2: 65 // as an interpolation between h1 and h2:
66 // p = (1-t) h1 + (t) h2 66 // p = (1-t) h1 + (t) h2
67 // 67 //
(...skipping 27 matching lines...) Expand all
95 ymin = std::min(p.y(), ymin); 95 ymin = std::min(p.y(), ymin);
96 ymax = std::max(p.y(), ymax); 96 ymax = std::max(p.y(), ymax);
97 } 97 }
98 98
99 static inline void addVertexToClippedQuad(const gfx::PointF& newVertex, gfx::Poi ntF clippedQuad[8], int& numVerticesInClippedQuad) 99 static inline void addVertexToClippedQuad(const gfx::PointF& newVertex, gfx::Poi ntF clippedQuad[8], int& numVerticesInClippedQuad)
100 { 100 {
101 clippedQuad[numVerticesInClippedQuad] = newVertex; 101 clippedQuad[numVerticesInClippedQuad] = newVertex;
102 numVerticesInClippedQuad++; 102 numVerticesInClippedQuad++;
103 } 103 }
104 104
105 gfx::Rect MathUtil::mapClippedRect(const WebTransformationMatrix& transform, con st gfx::Rect& srcRect) 105 gfx::Rect MathUtil::mapClippedRect(const Transform& transform, const gfx::Rect& srcRect)
106 { 106 {
107 return gfx::ToEnclosingRect(mapClippedRect(transform, gfx::RectF(srcRect))); 107 return gfx::ToEnclosingRect(mapClippedRect(transform, gfx::RectF(srcRect)));
108 } 108 }
109 109
110 gfx::RectF MathUtil::mapClippedRect(const WebTransformationMatrix& transform, co nst gfx::RectF& srcRect) 110 gfx::RectF MathUtil::mapClippedRect(const Transform& transform, const gfx::RectF & srcRect)
111 { 111 {
112 if (transform.isIdentityOrTranslation()) 112 if (MathUtil::isIdentityOrTranslation(transform))
113 return srcRect + gfx::Vector2dF(static_cast<float>(transform.m41()), sta tic_cast<float>(transform.m42())); 113 return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().ge tDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3)));
114 114
115 // Apply the transform, but retain the result in homogeneous coordinates. 115 // Apply the transform, but retain the result in homogeneous coordinates.
116 gfx::QuadF q = gfx::QuadF(srcRect); 116 gfx::QuadF q = gfx::QuadF(srcRect);
117 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( ))); 117 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( )));
118 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( ))); 118 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( )));
119 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( ))); 119 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( )));
120 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( ))); 120 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( )));
121 121
122 return computeEnclosingClippedRect(h1, h2, h3, h4); 122 return computeEnclosingClippedRect(h1, h2, h3, h4);
123 } 123 }
124 124
125 gfx::RectF MathUtil::projectClippedRect(const WebTransformationMatrix& transform , const gfx::RectF& srcRect) 125 gfx::RectF MathUtil::projectClippedRect(const Transform& transform, const gfx::R ectF& srcRect)
126 { 126 {
127 if (transform.isIdentityOrTranslation()) 127 if (MathUtil::isIdentityOrTranslation(transform))
128 return srcRect + gfx::Vector2dF(static_cast<float>(transform.m41()), sta tic_cast<float>(transform.m42())); 128 return srcRect + gfx::Vector2dF(static_cast<float>(transform.matrix().ge tDouble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3)));
129 129
130 // Perform the projection, but retain the result in homogeneous coordinates. 130 // Perform the projection, but retain the result in homogeneous coordinates.
131 gfx::QuadF q = gfx::QuadF(srcRect); 131 gfx::QuadF q = gfx::QuadF(srcRect);
132 HomogeneousCoordinate h1 = projectHomogeneousPoint(transform, q.p1()); 132 HomogeneousCoordinate h1 = projectHomogeneousPoint(transform, q.p1());
133 HomogeneousCoordinate h2 = projectHomogeneousPoint(transform, q.p2()); 133 HomogeneousCoordinate h2 = projectHomogeneousPoint(transform, q.p2());
134 HomogeneousCoordinate h3 = projectHomogeneousPoint(transform, q.p3()); 134 HomogeneousCoordinate h3 = projectHomogeneousPoint(transform, q.p3());
135 HomogeneousCoordinate h4 = projectHomogeneousPoint(transform, q.p4()); 135 HomogeneousCoordinate h4 = projectHomogeneousPoint(transform, q.p4());
136 136
137 return computeEnclosingClippedRect(h1, h2, h3, h4); 137 return computeEnclosingClippedRect(h1, h2, h3, h4);
138 } 138 }
139 139
140 void MathUtil::mapClippedQuad(const WebTransformationMatrix& transform, const gf x::QuadF& srcQuad, gfx::PointF clippedQuad[8], int& numVerticesInClippedQuad) 140 void MathUtil::mapClippedQuad(const Transform& transform, const gfx::QuadF& srcQ uad, gfx::PointF clippedQuad[8], int& numVerticesInClippedQuad)
141 { 141 {
142 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p1())); 142 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p1()));
143 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p2())); 143 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p2()));
144 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p3())); 144 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p3()));
145 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p4())); 145 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(srcQu ad.p4()));
146 146
147 // The order of adding the vertices to the array is chosen so that clockwise / counter-clockwise orientation is retained. 147 // The order of adding the vertices to the array is chosen so that clockwise / counter-clockwise orientation is retained.
148 148
149 numVerticesInClippedQuad = 0; 149 numVerticesInClippedQuad = 0;
150 150
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 234
235 if (!h4.shouldBeClipped()) 235 if (!h4.shouldBeClipped())
236 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d() ); 236 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d() );
237 237
238 if (h4.shouldBeClipped() ^ h1.shouldBeClipped()) 238 if (h4.shouldBeClipped() ^ h1.shouldBeClipped())
239 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointFo rEdge(h4, h1).cartesianPoint2d()); 239 expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointFo rEdge(h4, h1).cartesianPoint2d());
240 240
241 return gfx::RectF(gfx::PointF(xmin, ymin), gfx::SizeF(xmax - xmin, ymax - ym in)); 241 return gfx::RectF(gfx::PointF(xmin, ymin), gfx::SizeF(xmax - xmin, ymax - ym in));
242 } 242 }
243 243
244 gfx::QuadF MathUtil::mapQuad(const WebTransformationMatrix& transform, const gfx ::QuadF& q, bool& clipped) 244 gfx::QuadF MathUtil::mapQuad(const Transform& transform, const gfx::QuadF& q, bo ol& clipped)
245 { 245 {
246 if (transform.isIdentityOrTranslation()) { 246 if (MathUtil::isIdentityOrTranslation(transform)) {
247 gfx::QuadF mappedQuad(q); 247 gfx::QuadF mappedQuad(q);
248 mappedQuad += gfx::Vector2dF(static_cast<float>(transform.m41()), static _cast<float>(transform.m42())); 248 mappedQuad += gfx::Vector2dF(static_cast<float>(transform.matrix().getDo uble(0, 3)), static_cast<float>(transform.matrix().getDouble(1, 3)));
249 clipped = false; 249 clipped = false;
250 return mappedQuad; 250 return mappedQuad;
251 } 251 }
252 252
253 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( ))); 253 HomogeneousCoordinate h1 = mapHomogeneousPoint(transform, gfx::Point3F(q.p1( )));
254 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( ))); 254 HomogeneousCoordinate h2 = mapHomogeneousPoint(transform, gfx::Point3F(q.p2( )));
255 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( ))); 255 HomogeneousCoordinate h3 = mapHomogeneousPoint(transform, gfx::Point3F(q.p3( )));
256 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( ))); 256 HomogeneousCoordinate h4 = mapHomogeneousPoint(transform, gfx::Point3F(q.p4( )));
257 257
258 clipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped () || h4.shouldBeClipped(); 258 clipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped () || h4.shouldBeClipped();
259 259
260 // Result will be invalid if clipped == true. But, compute it anyway just in case, to emulate existing behavior. 260 // Result will be invalid if clipped == true. But, compute it anyway just in case, to emulate existing behavior.
261 return gfx::QuadF(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesian Point2d(), h4.cartesianPoint2d()); 261 return gfx::QuadF(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesian Point2d(), h4.cartesianPoint2d());
262 } 262 }
263 263
264 gfx::PointF MathUtil::mapPoint(const WebTransformationMatrix& transform, const g fx::PointF& p, bool& clipped) 264 gfx::PointF MathUtil::mapPoint(const Transform& transform, const gfx::PointF& p, bool& clipped)
265 { 265 {
266 HomogeneousCoordinate h = mapHomogeneousPoint(transform, gfx::Point3F(p)); 266 HomogeneousCoordinate h = mapHomogeneousPoint(transform, gfx::Point3F(p));
267 267
268 if (h.w > 0) { 268 if (h.w > 0) {
269 clipped = false; 269 clipped = false;
270 return h.cartesianPoint2d(); 270 return h.cartesianPoint2d();
271 } 271 }
272 272
273 // The cartesian coordinates will be invalid after dividing by w. 273 // The cartesian coordinates will be invalid after dividing by w.
274 clipped = true; 274 clipped = true;
275 275
276 // Avoid dividing by w if w == 0. 276 // Avoid dividing by w if w == 0.
277 if (!h.w) 277 if (!h.w)
278 return gfx::PointF(); 278 return gfx::PointF();
279 279
280 // This return value will be invalid because clipped == true, but (1) users of this 280 // This return value will be invalid because clipped == true, but (1) users of this
281 // code should be ignoring the return value when clipped == true anyway, and (2) this 281 // code should be ignoring the return value when clipped == true anyway, and (2) this
282 // behavior is more consistent with existing behavior of WebKit transforms i f the user 282 // behavior is more consistent with existing behavior of WebKit transforms i f the user
283 // really does not ignore the return value. 283 // really does not ignore the return value.
284 return h.cartesianPoint2d(); 284 return h.cartesianPoint2d();
285 } 285 }
286 286
287 gfx::Point3F MathUtil::mapPoint(const WebTransformationMatrix& transform, const gfx::Point3F& p, bool& clipped) 287 gfx::Point3F MathUtil::mapPoint(const Transform& transform, const gfx::Point3F& p, bool& clipped)
288 { 288 {
289 HomogeneousCoordinate h = mapHomogeneousPoint(transform, p); 289 HomogeneousCoordinate h = mapHomogeneousPoint(transform, p);
290 290
291 if (h.w > 0) { 291 if (h.w > 0) {
292 clipped = false; 292 clipped = false;
293 return h.cartesianPoint3d(); 293 return h.cartesianPoint3d();
294 } 294 }
295 295
296 // The cartesian coordinates will be invalid after dividing by w. 296 // The cartesian coordinates will be invalid after dividing by w.
297 clipped = true; 297 clipped = true;
298 298
299 // Avoid dividing by w if w == 0. 299 // Avoid dividing by w if w == 0.
300 if (!h.w) 300 if (!h.w)
301 return gfx::Point3F(); 301 return gfx::Point3F();
302 302
303 // This return value will be invalid because clipped == true, but (1) users of this 303 // This return value will be invalid because clipped == true, but (1) users of this
304 // code should be ignoring the return value when clipped == true anyway, and (2) this 304 // code should be ignoring the return value when clipped == true anyway, and (2) this
305 // behavior is more consistent with existing behavior of WebKit transforms i f the user 305 // behavior is more consistent with existing behavior of WebKit transforms i f the user
306 // really does not ignore the return value. 306 // really does not ignore the return value.
307 return h.cartesianPoint3d(); 307 return h.cartesianPoint3d();
308 } 308 }
309 309
310 gfx::QuadF MathUtil::projectQuad(const WebTransformationMatrix& transform, const gfx::QuadF& q, bool& clipped) 310 gfx::QuadF MathUtil::projectQuad(const Transform& transform, const gfx::QuadF& q , bool& clipped)
311 { 311 {
312 gfx::QuadF projectedQuad; 312 gfx::QuadF projectedQuad;
313 bool clippedPoint; 313 bool clippedPoint;
314 projectedQuad.set_p1(projectPoint(transform, q.p1(), clippedPoint)); 314 projectedQuad.set_p1(projectPoint(transform, q.p1(), clippedPoint));
315 clipped = clippedPoint; 315 clipped = clippedPoint;
316 projectedQuad.set_p2(projectPoint(transform, q.p2(), clippedPoint)); 316 projectedQuad.set_p2(projectPoint(transform, q.p2(), clippedPoint));
317 clipped |= clippedPoint; 317 clipped |= clippedPoint;
318 projectedQuad.set_p3(projectPoint(transform, q.p3(), clippedPoint)); 318 projectedQuad.set_p3(projectPoint(transform, q.p3(), clippedPoint));
319 clipped |= clippedPoint; 319 clipped |= clippedPoint;
320 projectedQuad.set_p4(projectPoint(transform, q.p4(), clippedPoint)); 320 projectedQuad.set_p4(projectPoint(transform, q.p4(), clippedPoint));
321 clipped |= clippedPoint; 321 clipped |= clippedPoint;
322 322
323 return projectedQuad; 323 return projectedQuad;
324 } 324 }
325 325
326 gfx::PointF MathUtil::projectPoint(const WebTransformationMatrix& transform, con st gfx::PointF& p, bool& clipped) 326 gfx::PointF MathUtil::projectPoint(const Transform& transform, const gfx::PointF & p, bool& clipped)
327 { 327 {
328 HomogeneousCoordinate h = projectHomogeneousPoint(transform, p); 328 HomogeneousCoordinate h = projectHomogeneousPoint(transform, p);
329 329
330 if (h.w > 0) { 330 if (h.w > 0) {
331 // The cartesian coordinates will be valid in this case. 331 // The cartesian coordinates will be valid in this case.
332 clipped = false; 332 clipped = false;
333 return h.cartesianPoint2d(); 333 return h.cartesianPoint2d();
334 } 334 }
335 335
336 // The cartesian coordinates will be invalid after dividing by w. 336 // The cartesian coordinates will be invalid after dividing by w.
337 clipped = true; 337 clipped = true;
338 338
339 // Avoid dividing by w if w == 0. 339 // Avoid dividing by w if w == 0.
340 if (!h.w) 340 if (!h.w)
341 return gfx::PointF(); 341 return gfx::PointF();
342 342
343 // This return value will be invalid because clipped == true, but (1) users of this 343 // This return value will be invalid because clipped == true, but (1) users of this
344 // code should be ignoring the return value when clipped == true anyway, and (2) this 344 // code should be ignoring the return value when clipped == true anyway, and (2) this
345 // behavior is more consistent with existing behavior of WebKit transforms i f the user 345 // behavior is more consistent with existing behavior of WebKit transforms i f the user
346 // really does not ignore the return value. 346 // really does not ignore the return value.
347 return h.cartesianPoint2d(); 347 return h.cartesianPoint2d();
348 } 348 }
349 349
350 void MathUtil::flattenTransformTo2d(WebTransformationMatrix& transform) 350 void MathUtil::flattenTransformTo2d(Transform& transform)
351 { 351 {
352 // Set both the 3rd row and 3rd column to (0, 0, 1, 0). 352 // Set both the 3rd row and 3rd column to (0, 0, 1, 0).
353 // 353 //
354 // One useful interpretation of doing this operation: 354 // One useful interpretation of doing this operation:
355 // - For x and y values, the new transform behaves effectively like an orth ographic 355 // - For x and y values, the new transform behaves effectively like an orth ographic
356 // projection was added to the matrix sequence. 356 // projection was added to the matrix sequence.
357 // - For z values, the new transform overrides any effect that the transfor m had on 357 // - For z values, the new transform overrides any effect that the transfor m had on
358 // z, and instead it preserves the z value for any points that are transf ormed. 358 // z, and instead it preserves the z value for any points that are transf ormed.
359 // - Because of linearity of transforms, this flattened transform also pres erves the 359 // - Because of linearity of transforms, this flattened transform also pres erves the
360 // effect that any subsequent (post-multiplied) transforms would have on z values. 360 // effect that any subsequent (post-multiplied) transforms would have on z values.
361 // 361 //
362 transform.setM13(0); 362 transform.matrix().setDouble(2, 0, 0);
363 transform.setM23(0); 363 transform.matrix().setDouble(2, 1, 0);
364 transform.setM31(0); 364 transform.matrix().setDouble(0, 2, 0);
365 transform.setM32(0); 365 transform.matrix().setDouble(1, 2, 0);
366 transform.setM33(1); 366 transform.matrix().setDouble(2, 2, 1);
367 transform.setM34(0); 367 transform.matrix().setDouble(3, 2, 0);
368 transform.setM43(0); 368 transform.matrix().setDouble(2, 3, 0);
369 } 369 }
370 370
371 static inline float scaleOnAxis(double a, double b, double c) 371 static inline float scaleOnAxis(double a, double b, double c)
372 { 372 {
373 return std::sqrt(a * a + b * b + c * c); 373 return std::sqrt(a * a + b * b + c * c);
374 } 374 }
375 375
376 gfx::Vector2dF MathUtil::computeTransform2dScaleComponents(const WebTransformati onMatrix& transform) 376 gfx::Vector2dF MathUtil::computeTransform2dScaleComponents(const Transform& tran sform)
377 { 377 {
378 if (transform.hasPerspective()) 378 if (hasPerspective(transform))
379 return gfx::Vector2dF(1, 1); 379 return gfx::Vector2dF(1, 1);
380 float xScale = scaleOnAxis(transform.m11(), transform.m12(), transform.m13() ); 380 float xScale = scaleOnAxis(transform.matrix().getDouble(0, 0), transform.mat rix().getDouble(1, 0), transform.matrix().getDouble(2, 0));
381 float yScale = scaleOnAxis(transform.m21(), transform.m22(), transform.m23() ); 381 float yScale = scaleOnAxis(transform.matrix().getDouble(0, 1), transform.mat rix().getDouble(1, 1), transform.matrix().getDouble(2, 1));
382 return gfx::Vector2dF(xScale, yScale); 382 return gfx::Vector2dF(xScale, yScale);
383 } 383 }
384 384
385 float MathUtil::smallestAngleBetweenVectors(gfx::Vector2dF v1, gfx::Vector2dF v2 ) 385 float MathUtil::smallestAngleBetweenVectors(gfx::Vector2dF v1, gfx::Vector2dF v2 )
386 { 386 {
387 double dotProduct = gfx::DotProduct(v1, v2) / v1.Length() / v2.Length(); 387 double dotProduct = gfx::DotProduct(v1, v2) / v1.Length() / v2.Length();
388 // Clamp to compensate for rounding errors. 388 // Clamp to compensate for rounding errors.
389 dotProduct = std::max(-1.0, std::min(1.0, dotProduct)); 389 dotProduct = std::max(-1.0, std::min(1.0, dotProduct));
390 return static_cast<float>(Rad2Deg(std::acos(dotProduct))); 390 return static_cast<float>(Rad2Deg(std::acos(dotProduct)));
391 } 391 }
392 392
393 gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des tination) 393 gfx::Vector2dF MathUtil::projectVector(gfx::Vector2dF source, gfx::Vector2dF des tination)
394 { 394 {
395 float projectedLength = gfx::DotProduct(source, destination) / destination.L engthSquared(); 395 float projectedLength = gfx::DotProduct(source, destination) / destination.L engthSquared();
396 return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * d estination.y()); 396 return gfx::Vector2dF(projectedLength * destination.x(), projectedLength * d estination.y());
397 } 397 }
398 398
399 bool MathUtil::isInvertible(const gfx::Transform& transform) 399 bool MathUtil::isBackFaceVisible(const gfx::Transform& transform)
400 { 400 {
401 const SkMatrix44& matrix = transform.matrix(); 401 // Compute whether a layer with a forward-facing normal of (0, 0, 1) would
402 double determinant = matrix.determinant(); 402 // have its back face visible after applying the transform.
403 return abs(determinant) > EPSILON; 403 //
404 } 404 // This is done by transforming the normal and seeing if the resulting z
405 // value is positive or negative. However, note that transforming a normal
406 // actually requires using the inverse-transpose of the original transform.
405 407
406 bool MathUtil::isBackFaceVisible(const gfx::Transform&) 408 // TODO (shawnsingh) make this perform more efficiently - we do not
407 { 409 // actually need to instantiate/invert/transpose any matrices, exploiting th e
408 // TODO (shawnsingh): to be implemented in a follow up patch very soon. 410 // fact that we only need to transform (0, 0, 1, 0).
409 NOTREACHED(); 411 gfx::Transform inverseTransform = MathUtil::inverse(transform);
410 return false; 412 const SkMatrix44& mInv = inverseTransform.matrix();
411 }
412 413
413 bool MathUtil::isIdentity(const gfx::Transform& transform) 414 return mInv.getDouble(2, 2) < 0;
danakj 2012/11/24 02:34:54 This is a lot simpler than WebCore::Transformation
shawnsingh 2012/11/24 02:56:14 The difference is in the TODO. We should be able
danakj 2012/11/24 03:20:09 I see, okay.
414 {
415 return transform.matrix().isIdentity();
416 } 415 }
417 416
418 bool MathUtil::isIdentityOrTranslation(const gfx::Transform& transform) 417 bool MathUtil::isIdentityOrTranslation(const gfx::Transform& transform)
419 { 418 {
420 const SkMatrix44& matrix = transform.matrix(); 419 const SkMatrix44& matrix = transform.matrix();
421 420
422 bool hasNoPerspective = !matrix.getDouble(3, 0) && !matrix.getDouble(3, 1) & & !matrix.getDouble(3, 2) && (matrix.getDouble(3, 3) == 1); 421 bool hasNoPerspective = !matrix.getDouble(3, 0) && !matrix.getDouble(3, 1) & & !matrix.getDouble(3, 2) && (matrix.getDouble(3, 3) == 1);
423 bool hasNoRotationOrSkew = !matrix.getDouble(0, 1) && !matrix.getDouble(0, 2 ) && !matrix.getDouble(1, 0) && 422 bool hasNoRotationOrSkew = !matrix.getDouble(0, 1) && !matrix.getDouble(0, 2 ) && !matrix.getDouble(1, 0) &&
424 !matrix.getDouble(1, 2) && !matrix.getDouble(2, 0) && !matrix.getDouble( 2, 1); 423 !matrix.getDouble(1, 2) && !matrix.getDouble(2, 0) && !matrix.getDouble( 2, 1);
425 bool hasNoScale = matrix.getDouble(0, 0) == 1 && matrix.getDouble(1, 1) == 1 && matrix.getDouble(2, 2) == 1; 424 bool hasNoScale = matrix.getDouble(0, 0) == 1 && matrix.getDouble(1, 1) == 1 && matrix.getDouble(2, 2) == 1;
426 425
427 return hasNoPerspective && hasNoRotationOrSkew && hasNoScale; 426 return hasNoPerspective && hasNoRotationOrSkew && hasNoScale;
428 } 427 }
429 428
430 bool MathUtil::hasPerspective(const gfx::Transform& transform) 429 bool MathUtil::hasPerspective(const gfx::Transform& transform)
431 { 430 {
432 // Mathematically it is a bit too strict to expect the 4th element to be 431 // Mathematically it is a bit too strict to expect the 4th element to be
433 // equal to 1. However, the only non-perspective case where this element 432 // equal to 1. However, the only non-perspective case where this element
434 // becomes non-1 is when it was explicitly initialized. In that case it 433 // becomes non-1 is when it was explicitly initialized. In that case it
435 // still causes us to have a nontrivial divide-by-w, so we count it as 434 // still causes us to have a nontrivial divide-by-w, so we count it as
436 // being perspective here. 435 // being perspective here.
437 const SkMatrix44& matrix = transform.matrix(); 436 const SkMatrix44& matrix = transform.matrix();
438 return matrix.getDouble(3, 0) || matrix.getDouble(3, 1) || matrix.getDouble( 3, 2) || (matrix.getDouble(3, 3) != 1); 437 return matrix.getDouble(3, 0) || matrix.getDouble(3, 1) || matrix.getDouble( 3, 2) || (matrix.getDouble(3, 3) != 1);
439 } 438 }
440 439
441 void MathUtil::makeIdentity(gfx::Transform* transform)
442 {
443 transform->matrix().setIdentity();
444 }
445
446 void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, doubl e eulerY, double eulerZ) 440 void MathUtil::rotateEulerAngles(gfx::Transform* transform, double eulerX, doubl e eulerY, double eulerZ)
447 { 441 {
448 // TODO (shawnsingh): make this implementation faster and more accurate by 442 // TODO (shawnsingh): make this implementation faster and more accurate by
449 // hard-coding each matrix instead of calling rotateAxisAngle(). 443 // hard-coding each matrix instead of calling rotateAxisAngle().
450 gfx::Transform rotationAboutX; 444 gfx::Transform rotationAboutX;
451 gfx::Transform rotationAboutY; 445 gfx::Transform rotationAboutY;
452 gfx::Transform rotationAboutZ; 446 gfx::Transform rotationAboutZ;
453 447
454 MathUtil::rotateAxisAngle(&rotationAboutX, 1, 0, 0, eulerX); 448 MathUtil::rotateAxisAngle(&rotationAboutX, 1, 0, 0, eulerX);
455 MathUtil::rotateAxisAngle(&rotationAboutY, 0, 1, 0, eulerY); 449 MathUtil::rotateAxisAngle(&rotationAboutY, 0, 1, 0, eulerY);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 541
548 gfx::Transform operator*(const gfx::Transform& A, const gfx::Transform& B) 542 gfx::Transform operator*(const gfx::Transform& A, const gfx::Transform& B)
549 { 543 {
550 // Compute A * B. 544 // Compute A * B.
551 gfx::Transform result = A; 545 gfx::Transform result = A;
552 result.PreconcatTransform(B); 546 result.PreconcatTransform(B);
553 return result; 547 return result;
554 } 548 }
555 549
556 } // namespace cc 550 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698