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 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 35 Rect::Rect() { 36 } 37 38 Rect::Rect(int width, int height) { 39 set_width(width); 40 set_height(height); 41 } 42 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 49 Rect::Rect(const gfx::Point& origin, const gfx::Size& size) 50 : origin_(origin), size_(size) { 51 } 52 53 #if defined(OS_WIN) 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 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) 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 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) 80 Rect::Rect(const GdkRectangle& r) 81 : origin_(r.x, r.y) { 82 set_width(r.width); 83 set_height(r.height); 84 } 85 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 94 void Rect::set_width(int width) { 95 size_.set_width(width); 96 } 97 void Rect::set_height(int height) { 98 size_.set_height(height); 99 } 100 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 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 113 void Rect::Offset(int horizontal, int vertical) { 114 set_x(x() + horizontal); 115 set_y(y() + vertical); 116 } 117 118 bool Rect::operator==(const Rect& other) const { 119 return origin_ == other.origin_ && size_ == other.size_; 120 } 121 122 #if defined(OS_WIN) 123 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) 132 CGRect Rect::ToCGRect() const { 133 return CGRectMake(x(), y(), width(), height()); 134 } 135 #elif defined(OS_POSIX) 136 GdkRectangle Rect::ToGdkRectangle() const { 137 GdkRectangle r = {x(), y(), width(), height()}; 138 return r; 139 } 140 #endif 141 142 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 147 bool Rect::Contains(const Rect& rect) const { 148 return (rect.x() >= x() && rect.right() <= right() && 149 rect.y() >= y() && rect.bottom() <= bottom()); 150 } 151 152 bool Rect::Intersects(const Rect& rect) const { 153 return !(rect.x() >= right() || rect.right() <= x() || 154 rect.y() >= bottom() || rect.bottom() <= y()); 155 } 156 157 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 169 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 184 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 214 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 224 Point Rect::CenterPoint() const { 225 return Point(x() + (width() + 1) / 2, y() + (height() + 1) / 2); 226 } 227 228 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 237 std::ostream& operator<<(std::ostream& out, const gfx::Rect& r) { 238 return out << r.origin() << " " << r.size(); 239 } 240