OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef CC_BASE_MATH_UTIL_H_ | |
6 #define CC_BASE_MATH_UTIL_H_ | |
7 | |
8 #include <algorithm> | |
9 #include <cmath> | |
10 #include <vector> | |
11 | |
12 #include "base/logging.h" | |
13 #include "base/memory/scoped_ptr.h" | |
14 #include "ui/gfx/geometry/box_f.h" | |
15 #include "ui/gfx/geometry/point3_f.h" | |
16 #include "ui/gfx/geometry/point_f.h" | |
17 #include "ui/gfx/geometry/scroll_offset.h" | |
18 #include "ui/gfx/geometry/size.h" | |
19 #include "ui/gfx/transform.h" | |
20 | |
21 namespace base { | |
22 class Value; | |
23 namespace trace_event { | |
24 class TracedValue; | |
25 } | |
26 } // namespace base | |
27 | |
28 namespace gfx { | |
29 class QuadF; | |
30 class Rect; | |
31 class RectF; | |
32 class Transform; | |
33 class Vector2dF; | |
34 class Vector2d; | |
35 } | |
36 | |
37 namespace cc { | |
38 | |
39 struct HomogeneousCoordinate { | |
40 HomogeneousCoordinate(SkMScalar x, SkMScalar y, SkMScalar z, SkMScalar w) { | |
41 vec[0] = x; | |
42 vec[1] = y; | |
43 vec[2] = z; | |
44 vec[3] = w; | |
45 } | |
46 | |
47 bool ShouldBeClipped() const { return w() <= 0.0; } | |
48 | |
49 gfx::PointF CartesianPoint2d() const { | |
50 if (w() == SK_MScalar1) | |
51 return gfx::PointF(x(), y()); | |
52 | |
53 // For now, because this code is used privately only by MathUtil, it should | |
54 // never be called when w == 0, and we do not yet need to handle that case. | |
55 DCHECK(w()); | |
56 SkMScalar inv_w = SK_MScalar1 / w(); | |
57 return gfx::PointF(x() * inv_w, y() * inv_w); | |
58 } | |
59 | |
60 gfx::Point3F CartesianPoint3d() const { | |
61 if (w() == SK_MScalar1) | |
62 return gfx::Point3F(x(), y(), z()); | |
63 | |
64 // For now, because this code is used privately only by MathUtil, it should | |
65 // never be called when w == 0, and we do not yet need to handle that case. | |
66 DCHECK(w()); | |
67 SkMScalar inv_w = SK_MScalar1 / w(); | |
68 return gfx::Point3F(x() * inv_w, y() * inv_w, z() * inv_w); | |
69 } | |
70 | |
71 SkMScalar x() const { return vec[0]; } | |
72 SkMScalar y() const { return vec[1]; } | |
73 SkMScalar z() const { return vec[2]; } | |
74 SkMScalar w() const { return vec[3]; } | |
75 | |
76 SkMScalar vec[4]; | |
77 }; | |
78 | |
79 class MathUtil { | |
80 public: | |
81 static const double kPiDouble; | |
82 static const float kPiFloat; | |
83 | |
84 static double Deg2Rad(double deg) { return deg * kPiDouble / 180.0; } | |
85 static double Rad2Deg(double rad) { return rad * 180.0 / kPiDouble; } | |
86 | |
87 static float Deg2Rad(float deg) { return deg * kPiFloat / 180.0f; } | |
88 static float Rad2Deg(float rad) { return rad * 180.0f / kPiFloat; } | |
89 | |
90 static float Round(float f) { | |
91 return (f > 0.f) ? std::floor(f + 0.5f) : std::ceil(f - 0.5f); | |
92 } | |
93 static double Round(double d) { | |
94 return (d > 0.0) ? std::floor(d + 0.5) : std::ceil(d - 0.5); | |
95 } | |
96 | |
97 template <typename T> static T ClampToRange(T value, T min, T max) { | |
98 return std::min(std::max(value, min), max); | |
99 } | |
100 | |
101 // Background: Existing transform code does not do the right thing in | |
102 // MapRect / MapQuad / ProjectQuad when there is a perspective projection that | |
103 // causes one of the transformed vertices to go to w < 0. In those cases, it | |
104 // is necessary to perform clipping in homogeneous coordinates, after applying | |
105 // the transform, before dividing-by-w to convert to cartesian coordinates. | |
106 // | |
107 // These functions return the axis-aligned rect that encloses the correctly | |
108 // clipped, transformed polygon. | |
109 static gfx::Rect MapEnclosingClippedRect(const gfx::Transform& transform, | |
110 const gfx::Rect& rect); | |
111 static gfx::RectF MapClippedRect(const gfx::Transform& transform, | |
112 const gfx::RectF& rect); | |
113 static gfx::Rect ProjectEnclosingClippedRect(const gfx::Transform& transform, | |
114 const gfx::Rect& rect); | |
115 static gfx::RectF ProjectClippedRect(const gfx::Transform& transform, | |
116 const gfx::RectF& rect); | |
117 | |
118 // This function is only valid when the transform preserves 2d axis | |
119 // alignment and the resulting rect will not be clipped. | |
120 static gfx::Rect MapEnclosedRectWith2dAxisAlignedTransform( | |
121 const gfx::Transform& transform, | |
122 const gfx::Rect& rect); | |
123 | |
124 // Returns an array of vertices that represent the clipped polygon. After | |
125 // returning, indexes from 0 to num_vertices_in_clipped_quad are valid in the | |
126 // clipped_quad array. Note that num_vertices_in_clipped_quad may be zero, | |
127 // which means the entire quad was clipped, and none of the vertices in the | |
128 // array are valid. | |
129 static void MapClippedQuad(const gfx::Transform& transform, | |
130 const gfx::QuadF& src_quad, | |
131 gfx::PointF clipped_quad[8], | |
132 int* num_vertices_in_clipped_quad); | |
133 static bool MapClippedQuad3d(const gfx::Transform& transform, | |
134 const gfx::QuadF& src_quad, | |
135 gfx::Point3F clipped_quad[8], | |
136 int* num_vertices_in_clipped_quad); | |
137 | |
138 static gfx::RectF ComputeEnclosingRectOfVertices(const gfx::PointF vertices[], | |
139 int num_vertices); | |
140 static gfx::RectF ComputeEnclosingClippedRect( | |
141 const HomogeneousCoordinate& h1, | |
142 const HomogeneousCoordinate& h2, | |
143 const HomogeneousCoordinate& h3, | |
144 const HomogeneousCoordinate& h4); | |
145 | |
146 // NOTE: These functions do not do correct clipping against w = 0 plane, but | |
147 // they correctly detect the clipped condition via the boolean clipped. | |
148 static gfx::QuadF MapQuad(const gfx::Transform& transform, | |
149 const gfx::QuadF& quad, | |
150 bool* clipped); | |
151 static gfx::QuadF MapQuad3d(const gfx::Transform& transform, | |
152 const gfx::QuadF& q, | |
153 gfx::Point3F* p, | |
154 bool* clipped); | |
155 static gfx::PointF MapPoint(const gfx::Transform& transform, | |
156 const gfx::PointF& point, | |
157 bool* clipped); | |
158 static gfx::Point3F MapPoint(const gfx::Transform&, | |
159 const gfx::Point3F&, | |
160 bool* clipped); | |
161 static gfx::QuadF ProjectQuad(const gfx::Transform& transform, | |
162 const gfx::QuadF& quad, | |
163 bool* clipped); | |
164 static gfx::PointF ProjectPoint(const gfx::Transform& transform, | |
165 const gfx::PointF& point, | |
166 bool* clipped); | |
167 // Identical to the above function, but coerces the homogeneous coordinate to | |
168 // a 3d rather than a 2d point. | |
169 static gfx::Point3F ProjectPoint3D(const gfx::Transform& transform, | |
170 const gfx::PointF& point, | |
171 bool* clipped); | |
172 | |
173 static gfx::Vector2dF ComputeTransform2dScaleComponents(const gfx::Transform&, | |
174 float fallbackValue); | |
175 | |
176 // Makes a rect that has the same relationship to input_outer_rect as | |
177 // scale_inner_rect has to scale_outer_rect. scale_inner_rect should be | |
178 // contained within scale_outer_rect, and likewise the rectangle that is | |
179 // returned will be within input_outer_rect at a similar relative, scaled | |
180 // position. | |
181 static gfx::RectF ScaleRectProportional(const gfx::RectF& input_outer_rect, | |
182 const gfx::RectF& scale_outer_rect, | |
183 const gfx::RectF& scale_inner_rect); | |
184 | |
185 // Returns the smallest angle between the given two vectors in degrees. | |
186 // Neither vector is assumed to be normalized. | |
187 static float SmallestAngleBetweenVectors(const gfx::Vector2dF& v1, | |
188 const gfx::Vector2dF& v2); | |
189 | |
190 // Projects the |source| vector onto |destination|. Neither vector is assumed | |
191 // to be normalized. | |
192 static gfx::Vector2dF ProjectVector(const gfx::Vector2dF& source, | |
193 const gfx::Vector2dF& destination); | |
194 | |
195 // Conversion to value. | |
196 static scoped_ptr<base::Value> AsValue(const gfx::Size& s); | |
197 static scoped_ptr<base::Value> AsValue(const gfx::Rect& r); | |
198 static bool FromValue(const base::Value*, gfx::Rect* out_rect); | |
199 static scoped_ptr<base::Value> AsValue(const gfx::PointF& q); | |
200 | |
201 static void AddToTracedValue(const char* name, | |
202 const gfx::Size& s, | |
203 base::trace_event::TracedValue* res); | |
204 static void AddToTracedValue(const char* name, | |
205 const gfx::SizeF& s, | |
206 base::trace_event::TracedValue* res); | |
207 static void AddToTracedValue(const char* name, | |
208 const gfx::Rect& r, | |
209 base::trace_event::TracedValue* res); | |
210 static void AddToTracedValue(const char* name, | |
211 const gfx::PointF& q, | |
212 base::trace_event::TracedValue* res); | |
213 static void AddToTracedValue(const char* name, | |
214 const gfx::Point3F&, | |
215 base::trace_event::TracedValue* res); | |
216 static void AddToTracedValue(const char* name, | |
217 const gfx::Vector2d& v, | |
218 base::trace_event::TracedValue* res); | |
219 static void AddToTracedValue(const char* name, | |
220 const gfx::Vector2dF& v, | |
221 base::trace_event::TracedValue* res); | |
222 static void AddToTracedValue(const char* name, | |
223 const gfx::ScrollOffset& v, | |
224 base::trace_event::TracedValue* res); | |
225 static void AddToTracedValue(const char* name, | |
226 const gfx::QuadF& q, | |
227 base::trace_event::TracedValue* res); | |
228 static void AddToTracedValue(const char* name, | |
229 const gfx::RectF& rect, | |
230 base::trace_event::TracedValue* res); | |
231 static void AddToTracedValue(const char* name, | |
232 const gfx::Transform& transform, | |
233 base::trace_event::TracedValue* res); | |
234 static void AddToTracedValue(const char* name, | |
235 const gfx::BoxF& box, | |
236 base::trace_event::TracedValue* res); | |
237 | |
238 // Returns a base::Value representation of the floating point value. | |
239 // If the value is inf, returns max double/float representation. | |
240 static double AsDoubleSafely(double value); | |
241 static float AsFloatSafely(float value); | |
242 }; | |
243 | |
244 } // namespace cc | |
245 | |
246 #endif // CC_BASE_MATH_UTIL_H_ | |
OLD | NEW |