1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//
17// Based on code from ScummVM - Scumm Interpreter
18// Copyright (C) 2002-2004 The ScummVM project
19//============================================================================
20
21#ifndef RECT_HXX
22#define RECT_HXX
23
24#include <cassert>
25
26#include "bspf.hxx"
27
28namespace Common {
29
30/*
31 This small class is an helper for position and size values.
32*/
33struct Point
34{
35 Int32 x; //!< The horizontal part of the point
36 Int32 y; //!< The vertical part of the point
37
38 Point() : x(0), y(0) { }
39 Point(const Point& p) : x(p.x), y(p.y) { }
40 explicit Point(Int32 x1, Int32 y1) : x(x1), y(y1) { }
41 explicit Point(const string& p) : x(0), y(0) {
42 char c = '\0';
43 istringstream buf(p);
44 buf >> x >> c >> y;
45 if(c != 'x')
46 x = y = 0;
47 }
48 Point& operator=(const Point & p) { x = p.x; y = p.y; return *this; }
49 bool operator==(const Point & p) const { return x == p.x && y == p.y; }
50 bool operator!=(const Point & p) const { return x != p.x || y != p.y; }
51
52 friend ostream& operator<<(ostream& os, const Point& p) {
53 os << p.x << "x" << p.y;
54 return os;
55 }
56};
57
58struct Size
59{
60 uInt32 w; //!< The width part of the size
61 uInt32 h; //!< The height part of the size
62
63 Size() : w(0), h(0) { }
64 Size(const Size& s) : w(s.w), h(s.h) { }
65 explicit Size(uInt32 w1, uInt32 h1) : w(w1), h(h1) { }
66 explicit Size(const string& s) : w(0), h(0) {
67 char c = '\0';
68 istringstream buf(s);
69 buf >> w >> c >> h;
70 if(c != 'x')
71 w = h = 0;
72 }
73 bool valid() const { return w > 0 && h > 0; }
74
75 Size& operator=(const Size& s) { w = s.w; h = s.h; return *this; }
76 bool operator==(const Size& s) const { return w == s.w && h == s.h; }
77 bool operator!=(const Size& s) const { return w != s.w || h != s.h; }
78 bool operator<(const Size& s) const { return w < s.w && h < s.h; }
79 bool operator<=(const Size& s) const { return w <= s.w && h <= s.h; }
80 bool operator>(const Size& s) const { return w > s.w && h > s.h; }
81 bool operator>=(const Size& s) const { return w >= s.w && h >= s.h; }
82
83 friend ostream& operator<<(ostream& os, const Size& s) {
84 os << s.w << "x" << s.h;
85 return os;
86 }
87};
88
89/*
90 This small class is an helper for rectangles.
91 Note: This implementation is built around the assumption that (top,left) is
92 part of the rectangle, but (bottom,right) is not! This is reflected in
93 various methods, including contains(), intersects() and others.
94
95 Another very wide spread approach to rectangle classes treats (bottom,right)
96 also as a part of the rectangle.
97
98 Conceptually, both are sound, but the approach we use saves many intermediate
99 computations (like computing the height in our case is done by doing this:
100 height = bottom - top;
101 while in the alternate system, it would be
102 height = bottom - top + 1;
103
104 When writing code using our Rect class, always keep this principle in mind!
105*/
106struct Rect
107{
108 private:
109 uInt32 top, left; //!< The point at the top left of the rectangle (part of the rect).
110 uInt32 bottom, right; //!< The point at the bottom right of the rectangle (not part of the rect).
111
112 public:
113 Rect() : top(0), left(0), bottom(0), right(0) { assert(valid()); }
114 Rect(const Rect& s) : top(s.top), left(s.left), bottom(s.bottom), right(s.right) { assert(valid()); }
115 Rect(const Size& s) : top(0), left(0), bottom(s.h), right(s.w) { assert(valid()); }
116 Rect& operator=(const Rect&) = default;
117 Rect(uInt32 w, uInt32 h) : top(0), left(0), bottom(h), right(w) { assert(valid()); }
118 Rect(const Point& p, uInt32 w, uInt32 h) : top(p.y), left(p.x), bottom(h), right(w) { assert(valid()); }
119 Rect(uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2) : top(y1), left(x1), bottom(y2), right(x2) { assert(valid()); }
120
121 uInt32 x() const { return left; }
122 uInt32 y() const { return top; }
123 Point point() const { return Point(x(), y()); }
124
125 uInt32 w() const { return right - left; }
126 uInt32 h() const { return bottom - top; }
127 Size size() const { return Size(w(), h()); }
128
129 void setWidth(uInt32 aWidth) { right = left + aWidth; }
130 void setHeight(uInt32 aHeight) { bottom = top + aHeight; }
131 void setSize(const Size& size) { setWidth(size.w); setHeight(size.h); }
132
133 void setBounds(uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2) {
134 top = y1;
135 left = x1;
136 bottom = y2;
137 right = x2;
138 assert(valid());
139 }
140
141 bool valid() const {
142 return (left <= right && top <= bottom);
143 }
144
145 bool empty() const {
146 return top == 0 && left == 0 && bottom == 0 && right == 0;
147 }
148
149 void moveTo(uInt32 x, uInt32 y) {
150 bottom += y - top;
151 right += x - left;
152 top = y;
153 left = x;
154 }
155
156 void moveTo(const Point& p) {
157 moveTo(p.x, p.y);
158 }
159
160 bool contains(uInt32 x, uInt32 y) const {
161 return x >= left && y >= top && x < right && y < bottom;
162 }
163
164 // Tests whether 'r' is completely contained within this rectangle.
165 // If it isn't, then set 'x' and 'y' such that moving 'r' to this
166 // position will make it be contained.
167 bool contains(uInt32& x, uInt32& y, const Rect& r) const {
168 if(r.left < left) x = left;
169 else if(r.right > right) x = r.left - (r.right - right);
170 if(r.top < top) y = top;
171 else if(r.bottom > bottom) y = r.top - (r.bottom - bottom);
172
173 return r.left != x || r.top != y;
174 }
175
176 friend ostream& operator<<(ostream& os, const Rect& r) {
177 os << r.point() << "," << r.size();
178 return os;
179 }
180};
181
182// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
183static const Rect EmptyRect;
184
185} // End of namespace Common
186
187#endif
188