1 // Copyright (c) 2009 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 "base/gfx/rect.h"
6
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #elif defined(OS_MACOSX)
10 #include <CoreGraphics/CGGeometry.h>
11 #elif defined(OS_POSIX)
12 #include <gdk/gdk.h>
13 #endif
14
15 #include <iostream>
16
17 #include "base/logging.h"
18
19 namespace {
20
AdjustAlongAxis(int dst_origin,int dst_size,int * origin,int * size)21 void AdjustAlongAxis(int dst_origin, int dst_size, int* origin, int* size) {
22 if (*origin < dst_origin) {
23 *origin = dst_origin;
24 *size = std::min(dst_size, *size);
25 } else {
26 *size = std::min(dst_size, *size);
27 *origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
28 }
29 }
30
31 } // namespace
32
33 namespace gfx {
34
Rect()35 Rect::Rect() {
36 }
37
Rect(int width,int height)38 Rect::Rect(int width, int height) {
39 set_width(width);
40 set_height(height);
41 }
42
Rect(int x,int y,int width,int height)43 Rect::Rect(int x, int y, int width, int height)
44 : origin_(x, y) {
45 set_width(width);
46 set_height(height);
47 }
48
Rect(const gfx::Point & origin,const gfx::Size & size)49 Rect::Rect(const gfx::Point& origin, const gfx::Size& size)
50 : origin_(origin), size_(size) {
51 }
52
53 #if defined(OS_WIN)
Rect(const RECT & r)54 Rect::Rect(const RECT& r)
55 : origin_(r.left, r.top) {
56 set_width(r.right - r.left);
57 set_height(r.bottom - r.top);
58 }
59
operator =(const RECT & r)60 Rect& Rect::operator=(const RECT& r) {
61 origin_.SetPoint(r.left, r.top);
62 set_width(r.right - r.left);
63 set_height(r.bottom - r.top);
64 return *this;
65 }
66 #elif defined(OS_MACOSX)
Rect(const CGRect & r)67 Rect::Rect(const CGRect& r)
68 : origin_(r.origin.x, r.origin.y) {
69 set_width(r.size.width);
70 set_height(r.size.height);
71 }
72
operator =(const CGRect & r)73 Rect& Rect::operator=(const CGRect& r) {
74 origin_.SetPoint(r.origin.x, r.origin.y);
75 set_width(r.size.width);
76 set_height(r.size.height);
77 return *this;
78 }
79 #elif defined(OS_POSIX)
Rect(const GdkRectangle & r)80 Rect::Rect(const GdkRectangle& r)
81 : origin_(r.x, r.y) {
82 set_width(r.width);
83 set_height(r.height);
84 }
85
operator =(const GdkRectangle & r)86 Rect& Rect::operator=(const GdkRectangle& r) {
87 origin_.SetPoint(r.x, r.y);
88 set_width(r.width);
89 set_height(r.height);
90 return *this;
91 }
92 #endif
93
set_width(int width)94 void Rect::set_width(int width) {
95 size_.set_width(width);
96 }
set_height(int height)97 void Rect::set_height(int height) {
98 size_.set_height(height);
99 }
100
SetRect(int x,int y,int width,int height)101 void Rect::SetRect(int x, int y, int width, int height) {
102 origin_.SetPoint(x, y);
103 set_width(width);
104 set_height(height);
105 }
106
Inset(int left,int top,int right,int bottom)107 void Rect::Inset(int left, int top, int right, int bottom) {
108 Offset(left, top);
109 set_width(std::max(width() - left - right, 0));
110 set_height(std::max(height() - top - bottom, 0));
111 }
112
Offset(int horizontal,int vertical)113 void Rect::Offset(int horizontal, int vertical) {
114 set_x(x() + horizontal);
115 set_y(y() + vertical);
116 }
117
operator ==(const Rect & other) const118 bool Rect::operator==(const Rect& other) const {
119 return origin_ == other.origin_ && size_ == other.size_;
120 }
121
122 #if defined(OS_WIN)
ToRECT() const123 RECT Rect::ToRECT() const {
124 RECT r;
125 r.left = x();
126 r.right = right();
127 r.top = y();
128 r.bottom = bottom();
129 return r;
130 }
131 #elif defined(OS_MACOSX)
ToCGRect() const132 CGRect Rect::ToCGRect() const {
133 return CGRectMake(x(), y(), width(), height());
134 }
135 #elif defined(OS_POSIX)
ToGdkRectangle() const136 GdkRectangle Rect::ToGdkRectangle() const {
137 GdkRectangle r = {x(), y(), width(), height()};
138 return r;
139 }
140 #endif
141
Contains(int point_x,int point_y) const142 bool Rect::Contains(int point_x, int point_y) const {
143 return (point_x >= x()) && (point_x < right()) &&
144 (point_y >= y()) && (point_y < bottom());
145 }
146
Contains(const Rect & rect) const147 bool Rect::Contains(const Rect& rect) const {
148 return (rect.x() >= x() && rect.right() <= right() &&
149 rect.y() >= y() && rect.bottom() <= bottom());
150 }
151
Intersects(const Rect & rect) const152 bool Rect::Intersects(const Rect& rect) const {
153 return !(rect.x() >= right() || rect.right() <= x() ||
154 rect.y() >= bottom() || rect.bottom() <= y());
155 }
156
Intersect(const Rect & rect) const157 Rect Rect::Intersect(const Rect& rect) const {
158 int rx = std::max(x(), rect.x());
159 int ry = std::max(y(), rect.y());
160 int rr = std::min(right(), rect.right());
161 int rb = std::min(bottom(), rect.bottom());
162
163 if (rx >= rr || ry >= rb)
164 rx = ry = rr = rb = 0; // non-intersecting
165
166 return Rect(rx, ry, rr - rx, rb - ry);
167 }
168
Union(const Rect & rect) const169 Rect Rect::Union(const Rect& rect) const {
170 // special case empty rects...
171 if (IsEmpty())
172 return rect;
173 if (rect.IsEmpty())
174 return *this;
175
176 int rx = std::min(x(), rect.x());
177 int ry = std::min(y(), rect.y());
178 int rr = std::max(right(), rect.right());
179 int rb = std::max(bottom(), rect.bottom());
180
181 return Rect(rx, ry, rr - rx, rb - ry);
182 }
183
Subtract(const Rect & rect) const184 Rect Rect::Subtract(const Rect& rect) const {
185 // boundary cases:
186 if (!Intersects(rect))
187 return *this;
188 if (rect.Contains(*this))
189 return Rect();
190
191 int rx = x();
192 int ry = y();
193 int rr = right();
194 int rb = bottom();
195
196 if (rect.y() <= y() && rect.bottom() >= bottom()) {
197 // complete intersection in the y-direction
198 if (rect.x() <= x()) {
199 rx = rect.right();
200 } else {
201 rr = rect.x();
202 }
203 } else if (rect.x() <= x() && rect.right() >= right()) {
204 // complete intersection in the x-direction
205 if (rect.y() <= y()) {
206 ry = rect.bottom();
207 } else {
208 rb = rect.y();
209 }
210 }
211 return Rect(rx, ry, rr - rx, rb - ry);
212 }
213
AdjustToFit(const Rect & rect) const214 Rect Rect::AdjustToFit(const Rect& rect) const {
215 int new_x = x();
216 int new_y = y();
217 int new_width = width();
218 int new_height = height();
219 AdjustAlongAxis(rect.x(), rect.width(), &new_x, &new_width);
220 AdjustAlongAxis(rect.y(), rect.height(), &new_y, &new_height);
221 return Rect(new_x, new_y, new_width, new_height);
222 }
223
CenterPoint() const224 Point Rect::CenterPoint() const {
225 return Point(x() + (width() + 1) / 2, y() + (height() + 1) / 2);
226 }
227
SharesEdgeWith(const gfx::Rect & rect) const228 bool Rect::SharesEdgeWith(const gfx::Rect& rect) const {
229 return (y() == rect.y() && height() == rect.height() &&
230 (x() == rect.right() || right() == rect.x())) ||
231 (x() == rect.x() && width() == rect.width() &&
232 (y() == rect.bottom() || bottom() == rect.y()));
233 }
234
235 } // namespace gfx
236
operator <<(std::ostream & out,const gfx::Rect & r)237 std::ostream& operator<<(std::ostream& out, const gfx::Rect& r) {
238 return out << r.origin() << " " << r.size();
239 }
240