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

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

Powered by Google App Engine
This is Rietveld 408576698