OLD | NEW |
---|---|
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/base/math_util.h" | 5 #include "cc/base/math_util.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
75 // p = (1-t) h1 + (t) h2. | 75 // p = (1-t) h1 + (t) h2. |
76 | 76 |
77 // Technically this is a special case of the following assertion, but its a | 77 // Technically this is a special case of the following assertion, but its a |
78 // good idea to keep it an explicit sanity check here. | 78 // good idea to keep it an explicit sanity check here. |
79 DCHECK_NE(h2.w(), h1.w()); | 79 DCHECK_NE(h2.w(), h1.w()); |
80 // Exactly one of h1 or h2 (but not both) must be on the negative side of the | 80 // Exactly one of h1 or h2 (but not both) must be on the negative side of the |
81 // w plane when this is called. | 81 // w plane when this is called. |
82 DCHECK(h1.ShouldBeClipped() ^ h2.ShouldBeClipped()); | 82 DCHECK(h1.ShouldBeClipped() ^ h2.ShouldBeClipped()); |
83 | 83 |
84 // ...or any positive non-zero small epsilon | 84 // ...or any positive non-zero small epsilon |
85 SkMScalar w = 0.00001f; | 85 SkMScalar w = 0.01f; |
enne (OOO)
2014/07/28 23:37:40
Just for the record (and to jog my memory), this w
troyhildebrandt
2014/07/29 19:57:17
It's necessary for the perf tests because without
| |
86 SkMScalar t = (w - h1.w()) / (h2.w() - h1.w()); | 86 SkMScalar t = (w - h1.w()) / (h2.w() - h1.w()); |
87 | 87 |
88 SkMScalar x = (SK_MScalar1 - t) * h1.x() + t * h2.x(); | 88 SkMScalar x = (SK_MScalar1 - t) * h1.x() + t * h2.x(); |
89 SkMScalar y = (SK_MScalar1 - t) * h1.y() + t * h2.y(); | 89 SkMScalar y = (SK_MScalar1 - t) * h1.y() + t * h2.y(); |
90 SkMScalar z = (SK_MScalar1 - t) * h1.z() + t * h2.z(); | 90 SkMScalar z = (SK_MScalar1 - t) * h1.z() + t * h2.z(); |
91 | 91 |
92 return HomogeneousCoordinate(x, y, z, w); | 92 return HomogeneousCoordinate(x, y, z, w); |
93 } | 93 } |
94 | 94 |
95 static inline void ExpandBoundsToIncludePoint(float* xmin, | 95 static inline void ExpandBoundsToIncludePoint(float* xmin, |
96 float* xmax, | 96 float* xmax, |
97 float* ymin, | 97 float* ymin, |
98 float* ymax, | 98 float* ymax, |
99 const gfx::PointF& p) { | 99 const gfx::PointF& p) { |
100 *xmin = std::min(p.x(), *xmin); | 100 *xmin = std::min(p.x(), *xmin); |
101 *xmax = std::max(p.x(), *xmax); | 101 *xmax = std::max(p.x(), *xmax); |
102 *ymin = std::min(p.y(), *ymin); | 102 *ymin = std::min(p.y(), *ymin); |
103 *ymax = std::max(p.y(), *ymax); | 103 *ymax = std::max(p.y(), *ymax); |
104 } | 104 } |
105 | 105 |
106 static inline void AddVertexToClippedQuad(const gfx::PointF& new_vertex, | 106 static inline void AddVertexToClippedQuad(const gfx::PointF& new_vertex, |
107 gfx::PointF clipped_quad[8], | 107 gfx::PointF clipped_quad[8], |
108 int* num_vertices_in_clipped_quad) { | 108 int* num_vertices_in_clipped_quad) { |
109 clipped_quad[*num_vertices_in_clipped_quad] = new_vertex; | 109 clipped_quad[*num_vertices_in_clipped_quad] = new_vertex; |
110 (*num_vertices_in_clipped_quad)++; | 110 (*num_vertices_in_clipped_quad)++; |
111 } | 111 } |
112 | 112 |
113 static inline void AddVertexToClippedQuad3d(const gfx::Point3F& new_vertex, | |
114 gfx::Point3F clipped_quad[8], | |
115 int* num_vertices_in_clipped_quad) { | |
116 clipped_quad[*num_vertices_in_clipped_quad] = new_vertex; | |
117 (*num_vertices_in_clipped_quad)++; | |
118 } | |
119 | |
113 gfx::Rect MathUtil::MapEnclosingClippedRect(const gfx::Transform& transform, | 120 gfx::Rect MathUtil::MapEnclosingClippedRect(const gfx::Transform& transform, |
114 const gfx::Rect& src_rect) { | 121 const gfx::Rect& src_rect) { |
115 if (transform.IsIdentityOrIntegerTranslation()) { | 122 if (transform.IsIdentityOrIntegerTranslation()) { |
116 return src_rect + | 123 return src_rect + |
117 gfx::Vector2d( | 124 gfx::Vector2d( |
118 static_cast<int>(SkMScalarToFloat(transform.matrix().get(0, 3))), | 125 static_cast<int>(SkMScalarToFloat(transform.matrix().get(0, 3))), |
119 static_cast<int>( | 126 static_cast<int>( |
120 SkMScalarToFloat(transform.matrix().get(1, 3)))); | 127 SkMScalarToFloat(transform.matrix().get(1, 3)))); |
121 } | 128 } |
122 return gfx::ToEnclosingRect(MapClippedRect(transform, gfx::RectF(src_rect))); | 129 return gfx::ToEnclosingRect(MapClippedRect(transform, gfx::RectF(src_rect))); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 if (h4.ShouldBeClipped() ^ h1.ShouldBeClipped()) { | 252 if (h4.ShouldBeClipped() ^ h1.ShouldBeClipped()) { |
246 AddVertexToClippedQuad( | 253 AddVertexToClippedQuad( |
247 ComputeClippedPointForEdge(h4, h1).CartesianPoint2d(), | 254 ComputeClippedPointForEdge(h4, h1).CartesianPoint2d(), |
248 clipped_quad, | 255 clipped_quad, |
249 num_vertices_in_clipped_quad); | 256 num_vertices_in_clipped_quad); |
250 } | 257 } |
251 | 258 |
252 DCHECK_LE(*num_vertices_in_clipped_quad, 8); | 259 DCHECK_LE(*num_vertices_in_clipped_quad, 8); |
253 } | 260 } |
254 | 261 |
262 bool MathUtil::MapClippedQuad3d(const gfx::Transform& transform, | |
263 const gfx::QuadF& src_quad, | |
264 gfx::Point3F clipped_quad[8], | |
265 int* num_vertices_in_clipped_quad) { | |
266 HomogeneousCoordinate h1 = | |
267 MapHomogeneousPoint(transform, gfx::Point3F(src_quad.p1())); | |
268 HomogeneousCoordinate h2 = | |
269 MapHomogeneousPoint(transform, gfx::Point3F(src_quad.p2())); | |
270 HomogeneousCoordinate h3 = | |
271 MapHomogeneousPoint(transform, gfx::Point3F(src_quad.p3())); | |
272 HomogeneousCoordinate h4 = | |
273 MapHomogeneousPoint(transform, gfx::Point3F(src_quad.p4())); | |
274 | |
275 // The order of adding the vertices to the array is chosen so that | |
276 // clockwise / counter-clockwise orientation is retained. | |
277 | |
278 *num_vertices_in_clipped_quad = 0; | |
279 | |
280 if (!h1.ShouldBeClipped()) { | |
281 AddVertexToClippedQuad3d( | |
282 h1.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad); | |
283 } | |
284 | |
285 if (h1.ShouldBeClipped() ^ h2.ShouldBeClipped()) { | |
286 AddVertexToClippedQuad3d( | |
287 ComputeClippedPointForEdge(h1, h2).CartesianPoint3d(), | |
288 clipped_quad, | |
289 num_vertices_in_clipped_quad); | |
290 } | |
291 | |
292 if (!h2.ShouldBeClipped()) { | |
293 AddVertexToClippedQuad3d( | |
294 h2.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad); | |
295 } | |
296 | |
297 if (h2.ShouldBeClipped() ^ h3.ShouldBeClipped()) { | |
298 AddVertexToClippedQuad3d( | |
299 ComputeClippedPointForEdge(h2, h3).CartesianPoint3d(), | |
300 clipped_quad, | |
301 num_vertices_in_clipped_quad); | |
302 } | |
303 | |
304 if (!h3.ShouldBeClipped()) { | |
305 AddVertexToClippedQuad3d( | |
306 h3.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad); | |
307 } | |
308 | |
309 if (h3.ShouldBeClipped() ^ h4.ShouldBeClipped()) { | |
310 AddVertexToClippedQuad3d( | |
311 ComputeClippedPointForEdge(h3, h4).CartesianPoint3d(), | |
312 clipped_quad, | |
313 num_vertices_in_clipped_quad); | |
314 } | |
315 | |
316 if (!h4.ShouldBeClipped()) { | |
317 AddVertexToClippedQuad3d( | |
318 h4.CartesianPoint3d(), clipped_quad, num_vertices_in_clipped_quad); | |
319 } | |
320 | |
321 if (h4.ShouldBeClipped() ^ h1.ShouldBeClipped()) { | |
322 AddVertexToClippedQuad3d( | |
323 ComputeClippedPointForEdge(h4, h1).CartesianPoint3d(), | |
324 clipped_quad, | |
325 num_vertices_in_clipped_quad); | |
326 } | |
327 | |
328 DCHECK_LE(*num_vertices_in_clipped_quad, 8); | |
329 return (*num_vertices_in_clipped_quad >= 4); | |
330 } | |
331 | |
255 gfx::RectF MathUtil::ComputeEnclosingRectOfVertices( | 332 gfx::RectF MathUtil::ComputeEnclosingRectOfVertices( |
256 const gfx::PointF vertices[], | 333 const gfx::PointF vertices[], |
257 int num_vertices) { | 334 int num_vertices) { |
258 if (num_vertices < 2) | 335 if (num_vertices < 2) |
259 return gfx::RectF(); | 336 return gfx::RectF(); |
260 | 337 |
261 float xmin = std::numeric_limits<float>::max(); | 338 float xmin = std::numeric_limits<float>::max(); |
262 float xmax = -std::numeric_limits<float>::max(); | 339 float xmax = -std::numeric_limits<float>::max(); |
263 float ymin = std::numeric_limits<float>::max(); | 340 float ymin = std::numeric_limits<float>::max(); |
264 float ymax = -std::numeric_limits<float>::max(); | 341 float ymax = -std::numeric_limits<float>::max(); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
378 h3.ShouldBeClipped() || h4.ShouldBeClipped(); | 455 h3.ShouldBeClipped() || h4.ShouldBeClipped(); |
379 | 456 |
380 // Result will be invalid if clipped == true. But, compute it anyway just in | 457 // Result will be invalid if clipped == true. But, compute it anyway just in |
381 // case, to emulate existing behavior. | 458 // case, to emulate existing behavior. |
382 return gfx::QuadF(h1.CartesianPoint2d(), | 459 return gfx::QuadF(h1.CartesianPoint2d(), |
383 h2.CartesianPoint2d(), | 460 h2.CartesianPoint2d(), |
384 h3.CartesianPoint2d(), | 461 h3.CartesianPoint2d(), |
385 h4.CartesianPoint2d()); | 462 h4.CartesianPoint2d()); |
386 } | 463 } |
387 | 464 |
465 gfx::QuadF MathUtil::MapQuad3d(const gfx::Transform& transform, | |
466 const gfx::QuadF& q, | |
467 gfx::Point3F* p, | |
468 bool* clipped) { | |
469 if (transform.IsIdentityOrTranslation()) { | |
470 gfx::QuadF mapped_quad(q); | |
471 mapped_quad += | |
472 gfx::Vector2dF(SkMScalarToFloat(transform.matrix().get(0, 3)), | |
473 SkMScalarToFloat(transform.matrix().get(1, 3))); | |
474 *clipped = false; | |
475 p[0] = gfx::Point3F(mapped_quad.p1().x(), mapped_quad.p1().y(), 0.0f); | |
476 p[1] = gfx::Point3F(mapped_quad.p2().x(), mapped_quad.p2().y(), 0.0f); | |
477 p[2] = gfx::Point3F(mapped_quad.p3().x(), mapped_quad.p3().y(), 0.0f); | |
478 p[3] = gfx::Point3F(mapped_quad.p4().x(), mapped_quad.p4().y(), 0.0f); | |
479 return mapped_quad; | |
480 } | |
481 | |
482 HomogeneousCoordinate h1 = | |
483 MapHomogeneousPoint(transform, gfx::Point3F(q.p1())); | |
484 HomogeneousCoordinate h2 = | |
485 MapHomogeneousPoint(transform, gfx::Point3F(q.p2())); | |
486 HomogeneousCoordinate h3 = | |
487 MapHomogeneousPoint(transform, gfx::Point3F(q.p3())); | |
488 HomogeneousCoordinate h4 = | |
489 MapHomogeneousPoint(transform, gfx::Point3F(q.p4())); | |
490 | |
491 *clipped = h1.ShouldBeClipped() || h2.ShouldBeClipped() || | |
492 h3.ShouldBeClipped() || h4.ShouldBeClipped(); | |
493 | |
494 // Result will be invalid if clipped == true. But, compute it anyway just in | |
495 // case, to emulate existing behavior. | |
496 p[0] = h1.CartesianPoint3d(); | |
497 p[1] = h2.CartesianPoint3d(); | |
498 p[2] = h3.CartesianPoint3d(); | |
499 p[3] = h4.CartesianPoint3d(); | |
500 | |
501 return gfx::QuadF(h1.CartesianPoint2d(), | |
502 h2.CartesianPoint2d(), | |
503 h3.CartesianPoint2d(), | |
504 h4.CartesianPoint2d()); | |
505 } | |
506 | |
388 gfx::PointF MathUtil::MapPoint(const gfx::Transform& transform, | 507 gfx::PointF MathUtil::MapPoint(const gfx::Transform& transform, |
389 const gfx::PointF& p, | 508 const gfx::PointF& p, |
390 bool* clipped) { | 509 bool* clipped) { |
391 HomogeneousCoordinate h = MapHomogeneousPoint(transform, gfx::Point3F(p)); | 510 HomogeneousCoordinate h = MapHomogeneousPoint(transform, gfx::Point3F(p)); |
392 | 511 |
393 if (h.w() > 0) { | 512 if (h.w() > 0) { |
394 *clipped = false; | 513 *clipped = false; |
395 return h.CartesianPoint2d(); | 514 return h.CartesianPoint2d(); |
396 } | 515 } |
397 | 516 |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
653 return scoped_ptr<base::Value>(new base::FundamentalValue( | 772 return scoped_ptr<base::Value>(new base::FundamentalValue( |
654 std::min(value, std::numeric_limits<double>::max()))); | 773 std::min(value, std::numeric_limits<double>::max()))); |
655 } | 774 } |
656 | 775 |
657 scoped_ptr<base::Value> MathUtil::AsValueSafely(float value) { | 776 scoped_ptr<base::Value> MathUtil::AsValueSafely(float value) { |
658 return scoped_ptr<base::Value>(new base::FundamentalValue( | 777 return scoped_ptr<base::Value>(new base::FundamentalValue( |
659 std::min(value, std::numeric_limits<float>::max()))); | 778 std::min(value, std::numeric_limits<float>::max()))); |
660 } | 779 } |
661 | 780 |
662 } // namespace cc | 781 } // namespace cc |
OLD | NEW |