Serenity Operating System
at hosted 342 lines 9.3 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include <AK/Forward.h> 30#include <LibGfx/Orientation.h> 31#include <LibGfx/Point.h> 32#include <LibGfx/Size.h> 33#include <LibGfx/TextAlignment.h> 34#include <LibIPC/Forward.h> 35#include <stdlib.h> 36 37namespace Gfx { 38 39class Rect { 40public: 41 Rect() {} 42 Rect(int x, int y, int width, int height) 43 : m_location(x, y) 44 , m_size(width, height) 45 { 46 } 47 Rect(const Point& location, const Size& size) 48 : m_location(location) 49 , m_size(size) 50 { 51 } 52 53 bool is_null() const 54 { 55 return width() == 0 && height() == 0; 56 } 57 58 bool is_empty() const 59 { 60 return width() <= 0 || height() <= 0; 61 } 62 63 void move_by(int dx, int dy) 64 { 65 m_location.move_by(dx, dy); 66 } 67 68 void move_by(const Point& delta) 69 { 70 m_location.move_by(delta); 71 } 72 73 Point center() const 74 { 75 return { x() + width() / 2, y() + height() / 2 }; 76 } 77 78 void set_location(const Point& location) 79 { 80 m_location = location; 81 } 82 83 void set_size(const Size& size) 84 { 85 m_size = size; 86 } 87 88 void set_size(int width, int height) 89 { 90 m_size.set_width(width); 91 m_size.set_height(height); 92 } 93 94 void inflate(int w, int h) 95 { 96 set_x(x() - w / 2); 97 set_width(width() + w); 98 set_y(y() - h / 2); 99 set_height(height() + h); 100 } 101 102 void shrink(int w, int h) 103 { 104 set_x(x() + w / 2); 105 set_width(width() - w); 106 set_y(y() + h / 2); 107 set_height(height() - h); 108 } 109 110 Rect shrunken(int w, int h) const 111 { 112 Rect rect = *this; 113 rect.shrink(w, h); 114 return rect; 115 } 116 117 Rect inflated(int w, int h) const 118 { 119 Rect rect = *this; 120 rect.inflate(w, h); 121 return rect; 122 } 123 124 Rect translated(int dx, int dy) const 125 { 126 Rect rect = *this; 127 rect.move_by(dx, dy); 128 return rect; 129 } 130 131 Rect translated(const Point& delta) const 132 { 133 Rect rect = *this; 134 rect.move_by(delta); 135 return rect; 136 } 137 138 bool contains_vertically(int y) const 139 { 140 return y >= top() && y <= bottom(); 141 } 142 143 bool contains_horizontally(int x) const 144 { 145 return x >= left() && x <= right(); 146 } 147 148 bool contains(int x, int y) const 149 { 150 return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom(); 151 } 152 153 bool contains(const Point& point) const 154 { 155 return contains(point.x(), point.y()); 156 } 157 158 bool contains(const Rect& other) const 159 { 160 return left() <= other.left() 161 && right() >= other.right() 162 && top() <= other.top() 163 && bottom() >= other.bottom(); 164 } 165 166 int primary_offset_for_orientation(Orientation orientation) const { return m_location.primary_offset_for_orientation(orientation); } 167 void set_primary_offset_for_orientation(Orientation orientation, int value) { m_location.set_primary_offset_for_orientation(orientation, value); } 168 int secondary_offset_for_orientation(Orientation orientation) const { return m_location.secondary_offset_for_orientation(orientation); } 169 void set_secondary_offset_for_orientation(Orientation orientation, int value) { m_location.set_secondary_offset_for_orientation(orientation, value); } 170 171 int primary_size_for_orientation(Orientation orientation) const { return m_size.primary_size_for_orientation(orientation); } 172 int secondary_size_for_orientation(Orientation orientation) const { return m_size.secondary_size_for_orientation(orientation); } 173 void set_primary_size_for_orientation(Orientation orientation, int value) { m_size.set_primary_size_for_orientation(orientation, value); } 174 void set_secondary_size_for_orientation(Orientation orientation, int value) { m_size.set_secondary_size_for_orientation(orientation, value); } 175 176 int first_edge_for_orientation(Orientation orientation) const 177 { 178 if (orientation == Orientation::Vertical) 179 return top(); 180 return left(); 181 } 182 183 int last_edge_for_orientation(Orientation orientation) const 184 { 185 if (orientation == Orientation::Vertical) 186 return bottom(); 187 return right(); 188 } 189 190 int left() const { return x(); } 191 int right() const { return x() + width() - 1; } 192 int top() const { return y(); } 193 int bottom() const { return y() + height() - 1; } 194 195 void set_left(int left) 196 { 197 set_x(left); 198 } 199 200 void set_top(int top) 201 { 202 set_y(top); 203 } 204 205 void set_right(int right) 206 { 207 set_width(right - x() + 1); 208 } 209 210 void set_bottom(int bottom) 211 { 212 set_height(bottom - y() + 1); 213 } 214 215 void set_right_without_resize(int new_right) 216 { 217 int delta = new_right - right(); 218 move_by(delta, 0); 219 } 220 221 void set_bottom_without_resize(int new_bottom) 222 { 223 int delta = new_bottom - bottom(); 224 move_by(0, delta); 225 } 226 227 bool intersects_vertically(const Rect& other) const 228 { 229 return top() <= other.bottom() 230 && other.top() <= bottom(); 231 } 232 233 bool intersects_horizontally(const Rect& other) const 234 { 235 return left() <= other.right() 236 && other.left() <= right(); 237 } 238 239 bool intersects(const Rect& other) const 240 { 241 return left() <= other.right() 242 && other.left() <= right() 243 && top() <= other.bottom() 244 && other.top() <= bottom(); 245 } 246 247 int x() const { return location().x(); } 248 int y() const { return location().y(); } 249 int width() const { return m_size.width(); } 250 int height() const { return m_size.height(); } 251 252 void set_x(int x) { m_location.set_x(x); } 253 void set_y(int y) { m_location.set_y(y); } 254 void set_width(int width) { m_size.set_width(width); } 255 void set_height(int height) { m_size.set_height(height); } 256 257 Point location() const { return m_location; } 258 Size size() const { return m_size; } 259 260 Vector<Rect, 4> shatter(const Rect& hammer) const; 261 262 bool operator==(const Rect& other) const 263 { 264 return m_location == other.m_location 265 && m_size == other.m_size; 266 } 267 268 bool operator!=(const Rect& other) const 269 { 270 return !(*this == other); 271 } 272 273 void intersect(const Rect&); 274 275 static Rect from_two_points(const Point& a, const Point& b) 276 { 277 return { min(a.x(), b.x()), min(a.y(), b.y()), abs(a.x() - b.x()), abs(a.y() - b.y()) }; 278 } 279 280 static Rect intersection(const Rect& a, const Rect& b) 281 { 282 Rect r(a); 283 r.intersect(b); 284 return r; 285 } 286 287 Rect intersected(const Rect& other) const 288 { 289 return intersection(*this, other); 290 } 291 292 Rect united(const Rect&) const; 293 294 Point top_left() const { return { left(), top() }; } 295 Point top_right() const { return { right(), top() }; } 296 Point bottom_left() const { return { left(), bottom() }; } 297 Point bottom_right() const { return { right(), bottom() }; } 298 299 void align_within(const Rect&, TextAlignment); 300 301 void center_within(const Rect& other) 302 { 303 center_horizontally_within(other); 304 center_vertically_within(other); 305 } 306 307 void center_horizontally_within(const Rect& other) 308 { 309 set_x(other.center().x() - width() / 2); 310 } 311 312 void center_vertically_within(const Rect& other) 313 { 314 set_y(other.center().y() - height() / 2); 315 } 316 317 String to_string() const; 318 319private: 320 Point m_location; 321 Size m_size; 322}; 323 324inline void Point::constrain(const Rect& rect) 325{ 326 if (x() < rect.left()) 327 set_x(rect.left()); 328 else if (x() > rect.right()) 329 set_x(rect.right()); 330 if (y() < rect.top()) 331 set_y(rect.top()); 332 else if (y() > rect.bottom()) 333 set_y(rect.bottom()); 334} 335 336const LogStream& operator<<(const LogStream&, const Rect&); 337 338} 339 340namespace IPC { 341bool decode(Decoder&, Gfx::Rect&); 342}