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.
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "ui/gfx/geometry/rect_base.h"
11 // This file provides the implementation for RectBaese template and
12 // used to instantiate the base class for Rect and RectF classes.
13 #if !defined(GFX_IMPLEMENTATION)
14 #error "This file is intended for UI implementation only"
19 template<typename Type
>
20 void AdjustAlongAxis(Type dst_origin
, Type dst_size
, Type
* origin
, Type
* size
) {
21 *size
= std::min(dst_size
, *size
);
22 if (*origin
< dst_origin
)
25 *origin
= std::min(dst_origin
+ dst_size
, *origin
+ *size
) - *size
;
32 template<typename Class
,
38 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
39 SetRect(Type x
, Type y
, Type width
, Type height
) {
40 origin_
.SetPoint(x
, y
);
45 template<typename Class
,
51 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
52 Inset(const InsetsClass
& insets
) {
53 Inset(insets
.left(), insets
.top(), insets
.right(), insets
.bottom());
56 template<typename Class
,
62 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
63 Inset(Type left
, Type top
, Type right
, Type bottom
) {
64 origin_
+= VectorClass(left
, top
);
65 set_width(std::max(width() - left
- right
, static_cast<Type
>(0)));
66 set_height(std::max(height() - top
- bottom
, static_cast<Type
>(0)));
69 template<typename Class
,
75 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
76 Offset(Type horizontal
, Type vertical
) {
77 origin_
+= VectorClass(horizontal
, vertical
);
80 template<typename Class
,
86 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
87 operator+=(const VectorClass
& offset
) {
91 template<typename Class
,
97 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
98 operator-=(const VectorClass
& offset
) {
102 template<typename Class
,
105 typename InsetsClass
,
106 typename VectorClass
,
108 bool RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
109 operator<(const Class
& other
) const {
110 if (origin_
== other
.origin_
) {
111 if (width() == other
.width()) {
112 return height() < other
.height();
114 return width() < other
.width();
117 return origin_
< other
.origin_
;
121 template<typename Class
,
124 typename InsetsClass
,
125 typename VectorClass
,
127 bool RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
128 Contains(Type point_x
, Type point_y
) const {
129 return (point_x
>= x()) && (point_x
< right()) &&
130 (point_y
>= y()) && (point_y
< bottom());
133 template<typename Class
,
136 typename InsetsClass
,
137 typename VectorClass
,
139 bool RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
140 Contains(const Class
& rect
) const {
141 return (rect
.x() >= x() && rect
.right() <= right() &&
142 rect
.y() >= y() && rect
.bottom() <= bottom());
145 template<typename Class
,
148 typename InsetsClass
,
149 typename VectorClass
,
151 bool RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
152 Intersects(const Class
& rect
) const {
153 return !(IsEmpty() || rect
.IsEmpty() ||
154 rect
.x() >= right() || rect
.right() <= x() ||
155 rect
.y() >= bottom() || rect
.bottom() <= y());
158 template<typename Class
,
161 typename InsetsClass
,
162 typename VectorClass
,
164 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
165 Intersect(const Class
& rect
) {
166 if (IsEmpty() || rect
.IsEmpty()) {
171 Type rx
= std::max(x(), rect
.x());
172 Type ry
= std::max(y(), rect
.y());
173 Type rr
= std::min(right(), rect
.right());
174 Type rb
= std::min(bottom(), rect
.bottom());
176 if (rx
>= rr
|| ry
>= rb
)
177 rx
= ry
= rr
= rb
= 0; // non-intersecting
179 SetRect(rx
, ry
, rr
- rx
, rb
- ry
);
182 template<typename Class
,
185 typename InsetsClass
,
186 typename VectorClass
,
188 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
189 Union(const Class
& rect
) {
197 Type rx
= std::min(x(), rect
.x());
198 Type ry
= std::min(y(), rect
.y());
199 Type rr
= std::max(right(), rect
.right());
200 Type rb
= std::max(bottom(), rect
.bottom());
202 SetRect(rx
, ry
, rr
- rx
, rb
- ry
);
205 template<typename Class
,
208 typename InsetsClass
,
209 typename VectorClass
,
211 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
212 Subtract(const Class
& rect
) {
213 if (!Intersects(rect
))
215 if (rect
.Contains(*static_cast<const Class
*>(this))) {
225 if (rect
.y() <= y() && rect
.bottom() >= bottom()) {
226 // complete intersection in the y-direction
227 if (rect
.x() <= x()) {
229 } else if (rect
.right() >= right()) {
232 } else if (rect
.x() <= x() && rect
.right() >= right()) {
233 // complete intersection in the x-direction
234 if (rect
.y() <= y()) {
236 } else if (rect
.bottom() >= bottom()) {
240 SetRect(rx
, ry
, rr
- rx
, rb
- ry
);
243 template<typename Class
,
246 typename InsetsClass
,
247 typename VectorClass
,
249 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
250 AdjustToFit(const Class
& rect
) {
253 Type new_width
= width();
254 Type new_height
= height();
255 AdjustAlongAxis(rect
.x(), rect
.width(), &new_x
, &new_width
);
256 AdjustAlongAxis(rect
.y(), rect
.height(), &new_y
, &new_height
);
257 SetRect(new_x
, new_y
, new_width
, new_height
);
260 template<typename Class
,
263 typename InsetsClass
,
264 typename VectorClass
,
266 PointClass RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
,
267 Type
>::CenterPoint() const {
268 return PointClass(x() + width() / 2, y() + height() / 2);
271 template<typename Class
,
274 typename InsetsClass
,
275 typename VectorClass
,
277 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
278 ClampToCenteredSize(const SizeClass
& size
) {
279 Type new_width
= std::min(width(), size
.width());
280 Type new_height
= std::min(height(), size
.height());
281 Type new_x
= x() + (width() - new_width
) / 2;
282 Type new_y
= y() + (height() - new_height
) / 2;
283 SetRect(new_x
, new_y
, new_width
, new_height
);
286 template<typename Class
,
289 typename InsetsClass
,
290 typename VectorClass
,
292 void RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
293 SplitVertically(Class
* left_half
, Class
* right_half
) const {
297 left_half
->SetRect(x(), y(), width() / 2, height());
298 right_half
->SetRect(left_half
->right(),
300 width() - left_half
->width(),
304 template<typename Class
,
307 typename InsetsClass
,
308 typename VectorClass
,
310 bool RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
311 SharesEdgeWith(const Class
& rect
) const {
312 return (y() == rect
.y() && height() == rect
.height() &&
313 (x() == rect
.right() || right() == rect
.x())) ||
314 (x() == rect
.x() && width() == rect
.width() &&
315 (y() == rect
.bottom() || bottom() == rect
.y()));
318 template<typename Class
,
321 typename InsetsClass
,
322 typename VectorClass
,
324 Type RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
325 ManhattanDistanceToPoint(const PointClass
& point
) const {
326 Type x_distance
= std::max
<Type
>(0, std::max(
327 x() - point
.x(), point
.x() - right()));
328 Type y_distance
= std::max
<Type
>(0, std::max(
329 y() - point
.y(), point
.y() - bottom()));
331 return x_distance
+ y_distance
;
334 template<typename Class
,
337 typename InsetsClass
,
338 typename VectorClass
,
340 Type RectBase
<Class
, PointClass
, SizeClass
, InsetsClass
, VectorClass
, Type
>::
341 ManhattanInternalDistance(const Class
& rect
) const {
342 Class
c(x(), y(), width(), height());
345 static const Type kEpsilon
= std::numeric_limits
<Type
>::is_integer
347 : std::numeric_limits
<Type
>::epsilon();
349 Type x
= std::max
<Type
>(0, c
.width() - width() - rect
.width() + kEpsilon
);
350 Type y
= std::max
<Type
>(0, c
.height() - height() - rect
.height() + kEpsilon
);