OLD | NEW |
| (Empty) |
1 // Copyright (c) 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 #include <limits> | |
6 | |
7 #include "ui/gfx/rect_base.h" | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/strings/stringprintf.h" | |
11 | |
12 // This file provides the implementation for RectBaese template and | |
13 // used to instantiate the base class for Rect and RectF classes. | |
14 #if !defined(GFX_IMPLEMENTATION) | |
15 #error "This file is intended for UI implementation only" | |
16 #endif | |
17 | |
18 namespace { | |
19 | |
20 template<typename Type> | |
21 void AdjustAlongAxis(Type dst_origin, Type dst_size, Type* origin, Type* size) { | |
22 *size = std::min(dst_size, *size); | |
23 if (*origin < dst_origin) | |
24 *origin = dst_origin; | |
25 else | |
26 *origin = std::min(dst_origin + dst_size, *origin + *size) - *size; | |
27 } | |
28 | |
29 } // namespace | |
30 | |
31 namespace gfx { | |
32 | |
33 template<typename Class, | |
34 typename PointClass, | |
35 typename SizeClass, | |
36 typename InsetsClass, | |
37 typename VectorClass, | |
38 typename Type> | |
39 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
40 SetRect(Type x, Type y, Type width, Type height) { | |
41 origin_.SetPoint(x, y); | |
42 set_width(width); | |
43 set_height(height); | |
44 } | |
45 | |
46 template<typename Class, | |
47 typename PointClass, | |
48 typename SizeClass, | |
49 typename InsetsClass, | |
50 typename VectorClass, | |
51 typename Type> | |
52 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
53 Inset(const InsetsClass& insets) { | |
54 Inset(insets.left(), insets.top(), insets.right(), insets.bottom()); | |
55 } | |
56 | |
57 template<typename Class, | |
58 typename PointClass, | |
59 typename SizeClass, | |
60 typename InsetsClass, | |
61 typename VectorClass, | |
62 typename Type> | |
63 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
64 Inset(Type left, Type top, Type right, Type bottom) { | |
65 origin_ += VectorClass(left, top); | |
66 set_width(std::max(width() - left - right, static_cast<Type>(0))); | |
67 set_height(std::max(height() - top - bottom, static_cast<Type>(0))); | |
68 } | |
69 | |
70 template<typename Class, | |
71 typename PointClass, | |
72 typename SizeClass, | |
73 typename InsetsClass, | |
74 typename VectorClass, | |
75 typename Type> | |
76 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
77 Offset(Type horizontal, Type vertical) { | |
78 origin_ += VectorClass(horizontal, vertical); | |
79 } | |
80 | |
81 template<typename Class, | |
82 typename PointClass, | |
83 typename SizeClass, | |
84 typename InsetsClass, | |
85 typename VectorClass, | |
86 typename Type> | |
87 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
88 operator+=(const VectorClass& offset) { | |
89 origin_ += offset; | |
90 } | |
91 | |
92 template<typename Class, | |
93 typename PointClass, | |
94 typename SizeClass, | |
95 typename InsetsClass, | |
96 typename VectorClass, | |
97 typename Type> | |
98 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
99 operator-=(const VectorClass& offset) { | |
100 origin_ -= offset; | |
101 } | |
102 | |
103 template<typename Class, | |
104 typename PointClass, | |
105 typename SizeClass, | |
106 typename InsetsClass, | |
107 typename VectorClass, | |
108 typename Type> | |
109 bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
110 operator<(const Class& other) const { | |
111 if (origin_ == other.origin_) { | |
112 if (width() == other.width()) { | |
113 return height() < other.height(); | |
114 } else { | |
115 return width() < other.width(); | |
116 } | |
117 } else { | |
118 return origin_ < other.origin_; | |
119 } | |
120 } | |
121 | |
122 template<typename Class, | |
123 typename PointClass, | |
124 typename SizeClass, | |
125 typename InsetsClass, | |
126 typename VectorClass, | |
127 typename Type> | |
128 bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
129 Contains(Type point_x, Type point_y) const { | |
130 return (point_x >= x()) && (point_x < right()) && | |
131 (point_y >= y()) && (point_y < bottom()); | |
132 } | |
133 | |
134 template<typename Class, | |
135 typename PointClass, | |
136 typename SizeClass, | |
137 typename InsetsClass, | |
138 typename VectorClass, | |
139 typename Type> | |
140 bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
141 Contains(const Class& rect) const { | |
142 return (rect.x() >= x() && rect.right() <= right() && | |
143 rect.y() >= y() && rect.bottom() <= bottom()); | |
144 } | |
145 | |
146 template<typename Class, | |
147 typename PointClass, | |
148 typename SizeClass, | |
149 typename InsetsClass, | |
150 typename VectorClass, | |
151 typename Type> | |
152 bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
153 Intersects(const Class& rect) const { | |
154 return !(IsEmpty() || rect.IsEmpty() || | |
155 rect.x() >= right() || rect.right() <= x() || | |
156 rect.y() >= bottom() || rect.bottom() <= y()); | |
157 } | |
158 | |
159 template<typename Class, | |
160 typename PointClass, | |
161 typename SizeClass, | |
162 typename InsetsClass, | |
163 typename VectorClass, | |
164 typename Type> | |
165 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
166 Intersect(const Class& rect) { | |
167 if (IsEmpty() || rect.IsEmpty()) { | |
168 SetRect(0, 0, 0, 0); | |
169 return; | |
170 } | |
171 | |
172 Type rx = std::max(x(), rect.x()); | |
173 Type ry = std::max(y(), rect.y()); | |
174 Type rr = std::min(right(), rect.right()); | |
175 Type rb = std::min(bottom(), rect.bottom()); | |
176 | |
177 if (rx >= rr || ry >= rb) | |
178 rx = ry = rr = rb = 0; // non-intersecting | |
179 | |
180 SetRect(rx, ry, rr - rx, rb - ry); | |
181 } | |
182 | |
183 template<typename Class, | |
184 typename PointClass, | |
185 typename SizeClass, | |
186 typename InsetsClass, | |
187 typename VectorClass, | |
188 typename Type> | |
189 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
190 Union(const Class& rect) { | |
191 if (IsEmpty()) { | |
192 *this = rect; | |
193 return; | |
194 } | |
195 if (rect.IsEmpty()) | |
196 return; | |
197 | |
198 Type rx = std::min(x(), rect.x()); | |
199 Type ry = std::min(y(), rect.y()); | |
200 Type rr = std::max(right(), rect.right()); | |
201 Type rb = std::max(bottom(), rect.bottom()); | |
202 | |
203 SetRect(rx, ry, rr - rx, rb - ry); | |
204 } | |
205 | |
206 template<typename Class, | |
207 typename PointClass, | |
208 typename SizeClass, | |
209 typename InsetsClass, | |
210 typename VectorClass, | |
211 typename Type> | |
212 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
213 Subtract(const Class& rect) { | |
214 if (!Intersects(rect)) | |
215 return; | |
216 if (rect.Contains(*static_cast<const Class*>(this))) { | |
217 SetRect(0, 0, 0, 0); | |
218 return; | |
219 } | |
220 | |
221 Type rx = x(); | |
222 Type ry = y(); | |
223 Type rr = right(); | |
224 Type rb = bottom(); | |
225 | |
226 if (rect.y() <= y() && rect.bottom() >= bottom()) { | |
227 // complete intersection in the y-direction | |
228 if (rect.x() <= x()) { | |
229 rx = rect.right(); | |
230 } else if (rect.right() >= right()) { | |
231 rr = rect.x(); | |
232 } | |
233 } else if (rect.x() <= x() && rect.right() >= right()) { | |
234 // complete intersection in the x-direction | |
235 if (rect.y() <= y()) { | |
236 ry = rect.bottom(); | |
237 } else if (rect.bottom() >= bottom()) { | |
238 rb = rect.y(); | |
239 } | |
240 } | |
241 SetRect(rx, ry, rr - rx, rb - ry); | |
242 } | |
243 | |
244 template<typename Class, | |
245 typename PointClass, | |
246 typename SizeClass, | |
247 typename InsetsClass, | |
248 typename VectorClass, | |
249 typename Type> | |
250 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
251 AdjustToFit(const Class& rect) { | |
252 Type new_x = x(); | |
253 Type new_y = y(); | |
254 Type new_width = width(); | |
255 Type new_height = height(); | |
256 AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width); | |
257 AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height); | |
258 SetRect(new_x, new_y, new_width, new_height); | |
259 } | |
260 | |
261 template<typename Class, | |
262 typename PointClass, | |
263 typename SizeClass, | |
264 typename InsetsClass, | |
265 typename VectorClass, | |
266 typename Type> | |
267 PointClass RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, | |
268 Type>::CenterPoint() const { | |
269 return PointClass(x() + width() / 2, y() + height() / 2); | |
270 } | |
271 | |
272 template<typename Class, | |
273 typename PointClass, | |
274 typename SizeClass, | |
275 typename InsetsClass, | |
276 typename VectorClass, | |
277 typename Type> | |
278 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
279 ClampToCenteredSize(const SizeClass& size) { | |
280 Type new_width = std::min(width(), size.width()); | |
281 Type new_height = std::min(height(), size.height()); | |
282 Type new_x = x() + (width() - new_width) / 2; | |
283 Type new_y = y() + (height() - new_height) / 2; | |
284 SetRect(new_x, new_y, new_width, new_height); | |
285 } | |
286 | |
287 template<typename Class, | |
288 typename PointClass, | |
289 typename SizeClass, | |
290 typename InsetsClass, | |
291 typename VectorClass, | |
292 typename Type> | |
293 void RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
294 SplitVertically(Class* left_half, Class* right_half) const { | |
295 DCHECK(left_half); | |
296 DCHECK(right_half); | |
297 | |
298 left_half->SetRect(x(), y(), width() / 2, height()); | |
299 right_half->SetRect(left_half->right(), | |
300 y(), | |
301 width() - left_half->width(), | |
302 height()); | |
303 } | |
304 | |
305 template<typename Class, | |
306 typename PointClass, | |
307 typename SizeClass, | |
308 typename InsetsClass, | |
309 typename VectorClass, | |
310 typename Type> | |
311 bool RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
312 SharesEdgeWith(const Class& rect) const { | |
313 return (y() == rect.y() && height() == rect.height() && | |
314 (x() == rect.right() || right() == rect.x())) || | |
315 (x() == rect.x() && width() == rect.width() && | |
316 (y() == rect.bottom() || bottom() == rect.y())); | |
317 } | |
318 | |
319 template<typename Class, | |
320 typename PointClass, | |
321 typename SizeClass, | |
322 typename InsetsClass, | |
323 typename VectorClass, | |
324 typename Type> | |
325 Type RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
326 ManhattanDistanceToPoint(const PointClass& point) const { | |
327 Type x_distance = std::max<Type>(0, std::max( | |
328 x() - point.x(), point.x() - right())); | |
329 Type y_distance = std::max<Type>(0, std::max( | |
330 y() - point.y(), point.y() - bottom())); | |
331 | |
332 return x_distance + y_distance; | |
333 } | |
334 | |
335 template<typename Class, | |
336 typename PointClass, | |
337 typename SizeClass, | |
338 typename InsetsClass, | |
339 typename VectorClass, | |
340 typename Type> | |
341 Type RectBase<Class, PointClass, SizeClass, InsetsClass, VectorClass, Type>:: | |
342 ManhattanInternalDistance(const Class& rect) const { | |
343 Class c(x(), y(), width(), height()); | |
344 c.Union(rect); | |
345 | |
346 static const Type kEpsilon = std::numeric_limits<Type>::is_integer | |
347 ? 1 | |
348 : std::numeric_limits<Type>::epsilon(); | |
349 | |
350 Type x = std::max<Type>(0, c.width() - width() - rect.width() + kEpsilon); | |
351 Type y = std::max<Type>(0, c.height() - height() - rect.height() + kEpsilon); | |
352 return x + y; | |
353 } | |
354 | |
355 } // namespace gfx | |
OLD | NEW |