1 #ifndef scr_coord_h
2 #define scr_coord_h
3 
4 #include <assert.h>
5 #include "../dataobj/loadsave.h"
6 #include "../simtypes.h"
7 
8 class koord;
9 
10 // Screen coordinate type
11 typedef sint32 scr_coord_val;
12 
13 // Rectangle relations
14 enum rect_relation_t { RECT_RELATION_INSIDE, RECT_RELATION_OVERLAP, RECT_RELATION_OUTSIDE };
15 
16 // Two dimensional coordinate type
17 class scr_coord
18 {
19 public:
20 	scr_coord_val x;
21 	scr_coord_val y;
22 
23 	// Constructors
scr_coord()24 	scr_coord(  ) { x = y = 0; }
scr_coord(scr_coord_val x_,scr_coord_val y_)25 	scr_coord( scr_coord_val x_, scr_coord_val y_ ) { x = x_; y=y_; }
26 
27 	bool operator ==(const scr_coord& other) const { return ((x-other.x) | (y-other.y)) == 0; }
28 	bool operator !=(const scr_coord& other) const { return !(other == *this ); }
29 	const scr_coord operator +(const scr_coord& other ) const { return scr_coord( other.x + x, other.y + y); }
30 	const scr_coord operator -(const scr_coord& other ) const { return scr_coord( x - other.x, y - other.y ); }
31 
rdwr(loadsave_t * file)32 	void rdwr(loadsave_t *file)
33 	{
34 		xml_tag_t k( file, "koord" );
35 		file->rdwr_long(x);
36 		file->rdwr_long(y);
37 	}
38 
39 	const scr_coord& operator +=(const scr_coord& other ) {
40 		x += other.x;
41 		y += other.y;
42 		return *this;
43 	}
44 
45 	const scr_coord& operator -=(const scr_coord& other ) {
46 		x -= other.x;
47 		y -= other.y;
48 		return *this;
49 	}
50 
add_offset(scr_coord_val delta_x,scr_coord_val delta_y)51 	void add_offset( scr_coord_val delta_x, scr_coord_val delta_y ) {
52 		x += delta_x;
53 		y += delta_y;
54 	}
55 
set(scr_coord_val x_par,scr_coord_val y_par)56 	void set( scr_coord_val x_par, scr_coord_val y_par ) {
57 		x = x_par;
58 		y = y_par;
59 	}
60 
clip_lefttop(scr_coord scr_lefttop)61 	inline void clip_lefttop( scr_coord scr_lefttop )
62 	{
63 		if (x < scr_lefttop.x) {
64 			x = scr_lefttop.x;
65 		}
66 		if (y < scr_lefttop.y) {
67 			y = scr_lefttop.y;
68 		}
69 	}
70 
clip_rightbottom(scr_coord scr_rightbottom)71 	inline void clip_rightbottom( scr_coord scr_rightbottom )
72 	{
73 		if (x > scr_rightbottom.x) {
74 			x = scr_rightbottom.x;
75 		}
76 		if (y > scr_rightbottom.y) {
77 			y = scr_rightbottom.y;
78 		}
79 	}
80 
81 	static const scr_coord invalid;
82 
83 private:
84 	// conversions to/from koord not allowed anymore
85 	scr_coord( const koord);
86 	operator koord() const;
87 };
88 
89 
90 static inline scr_coord operator * (const scr_coord &k, const sint16 m)
91 {
92 	return scr_coord(k.x * m, k.y * m);
93 }
94 
95 
96 static inline scr_coord operator / (const scr_coord &k, const sint16 m)
97 {
98 	return scr_coord(k.x / m, k.y / m);
99 }
100 
101 
102 // Very simple scr_size struct.
103 class scr_size
104 {
105 public:
106 	scr_coord_val w;
107 	scr_coord_val h;
108 
109 	// Constructors
scr_size()110 	scr_size(  ) { w = h = 0; }
scr_size(scr_coord_val w_par,scr_coord_val h_par)111 	scr_size( scr_coord_val w_par, scr_coord_val h_par) { w = w_par; h = h_par; }
scr_size(const scr_size & size)112 	scr_size( const scr_size& size ) { w = size.w; h=size.h; }
113 
scr_coord()114 	operator scr_coord() const { return scr_coord(w,h); }
115 
116 	bool operator ==(const scr_size& other) const { return ((w-other.w) | (h-other.h)) == 0; }
117 	bool operator !=(const scr_size& other) const { return !(other == *this ); }
118 	const scr_size operator +(const scr_size& other ) const { return scr_size( other.w + w, other.h + h); }
119 	const scr_size operator -(const scr_size& other ) const { return scr_size( w - other.w, h - other.h ); }
120 	const scr_size operator +(const scr_coord& other ) const { return scr_size( other.x + w, other.y + h); }
121 	const scr_size operator -(const scr_coord& other ) const { return scr_size( w - other.x, h - other.y ); }
122 
rdwr(loadsave_t * file)123 	void rdwr(loadsave_t *file)
124 	{
125 		xml_tag_t k( file, "koord" );
126 		file->rdwr_long(w);
127 		file->rdwr_long(h);
128 	}
129 
clip_lefttop(scr_coord scr_lefttop)130 	inline void clip_lefttop( scr_coord scr_lefttop )
131 	{
132 		if (w < scr_lefttop.x) {
133 			w = scr_lefttop.x;
134 		}
135 		if (h < scr_lefttop.y) {
136 			h = scr_lefttop.y;
137 		}
138 	}
139 
clip_rightbottom(scr_coord scr_rightbottom)140 	inline void clip_rightbottom( scr_coord scr_rightbottom )
141 	{
142 		if (w > scr_rightbottom.x) {
143 			w = scr_rightbottom.x;
144 		}
145 		if (h > scr_rightbottom.y) {
146 			h = scr_rightbottom.y;
147 		}
148 	}
149 
150 	const scr_size& operator +=(const scr_size& other ) {
151 		w += other.w;
152 		h += other.h;
153 		return *this;
154 	}
155 
156 	const scr_size& operator -=(const scr_size& other ) {
157 		w -= other.w;
158 		h -= other.h;
159 		return *this;
160 	}
161 
162 	const scr_size& operator +=(const scr_coord& other ) {
163 		w += other.x;
164 		h += other.y;
165 		return *this;
166 	}
167 
168 	const scr_size& operator -=(const scr_coord& other ) {
169 		w -= other.x;
170 		h -= other.y;
171 		return *this;
172 	}
173 
174 	static const scr_size invalid;
175 
176 	static const scr_size inf;
177 private:
178 	// conversions to/from koord not allowed anymore
179 	operator koord() const;
180 };
181 
182 
183 // Rectangle type
184 class scr_rect
185 {
186 public:
187 	scr_coord_val x;
188 	scr_coord_val y;
189 	scr_coord_val w;
190 	scr_coord_val h;
191 
192 	// to set it in one line ...
set(scr_coord_val x_par,scr_coord_val y_par,scr_coord_val w_par,scr_coord_val h_par)193 	void set( scr_coord_val x_par, scr_coord_val y_par, scr_coord_val w_par, scr_coord_val h_par ) {
194 		x = x_par;
195 		y = y_par;
196 		w = w_par;
197 		h = h_par;
198 	}
199 
200 	// Constructors
scr_rect()201 	scr_rect() { set(0,0,0,0); }
scr_rect(const scr_coord & pt)202 	scr_rect( const scr_coord& pt ) { set( pt.x, pt.y, 0, 0 ); }
scr_rect(const scr_coord & pt,scr_coord_val w,scr_coord_val h)203 	scr_rect( const scr_coord& pt, scr_coord_val w, scr_coord_val h ) { set( pt.x, pt.y, w, h ); }
scr_rect(const scr_coord & pt,const scr_size & sz)204 	scr_rect( const scr_coord& pt, const scr_size& sz ) { set( pt.x, pt.y, sz.w, sz.h ); }
scr_rect(scr_coord_val x,scr_coord_val y,scr_coord_val w,scr_coord_val h)205 	scr_rect( scr_coord_val x, scr_coord_val y, scr_coord_val w, scr_coord_val h ) { set( x, y, w, h ); }
scr_rect(scr_size size)206 	scr_rect( scr_size size ) { w = size.w; h=size.h; x=0; y=0; }
scr_rect(const scr_coord & point1,const scr_coord & point2)207 	scr_rect( const scr_coord& point1, const scr_coord& point2 ) { set( point1.x, point1.y, point2.x-point1.x, point2.y-point1.y ); }
208 
209 	// Type cast operators
scr_size()210 	operator scr_size()  const { return scr_size (w,h); }
scr_coord()211 	operator scr_coord() const { return scr_coord(x,y); }
212 
213 	// Unary operators
214 	const scr_rect operator +(const scr_coord& other ) const { scr_rect rect(x + other.x, y + other.y, w, h ); return rect; }
215 	const scr_rect operator -(const scr_coord& other ) const { scr_rect rect(x - other.x, y - other.y, w, h ); return rect; }
216 
217 	const scr_rect operator +(const scr_size& sz ) const { return scr_rect(x,y, w+sz.w, h+sz.h ); }
218 	const scr_rect operator -(const scr_size& sz ) const { return scr_rect(x,y, w-sz.w, h-sz.h ); }
219 
220 	// Validation functions
is_empty()221 	bool is_empty() const { return (w|h) == 0;  }
is_valid()222 	bool is_valid() const { return !is_empty(); }
223 
224 	// Helper functions
get_pos()225 	scr_coord get_pos() const {
226 		return scr_coord( x, y );
227 	}
228 
set_pos(const scr_coord point)229 	void set_pos( const scr_coord point ) {
230 		w = (x+w) - point.x;
231 		h = (y+h) - point.y;
232 		x = point.x;
233 		y = point.y;
234 	}
235 
get_bottomright()236 	const scr_coord get_bottomright() const {
237 		return scr_coord( x+w, y+h );
238 	}
239 
set_bottomright(const scr_coord & point)240 	void set_bottomright( const scr_coord& point ) {
241 		w = point.x - x;
242 		h = point.y - y;
243 	}
244 
get_width()245 	scr_coord_val get_width() const { return w; }
246 
get_right()247 	scr_coord_val get_right() const { return x+w; }
248 
get_height()249 	scr_coord_val get_height() const { return h; }
250 
get_bottom()251 	scr_coord_val get_bottom() const { return y+h; }
252 
set_right(scr_coord_val right)253 	void set_right(scr_coord_val right) {
254 		w = right-x;
255 	}
256 
set_bottom(scr_coord_val bottom)257 	void set_bottom(scr_coord_val bottom) {
258 		h = bottom-y;
259 	}
260 
261 	// now just working on two of the four coordinates
move_to(scr_coord_val x_par,scr_coord_val y_par)262 	void move_to( scr_coord_val x_par, scr_coord_val y_par ) {
263 		x = x_par;
264 		y = y_par;
265 	}
266 
move_to(const scr_coord & point)267 	void move_to( const scr_coord& point ) {
268 		move_to( point.x, point.y );
269 	}
270 
271 	// and the other two with the size
get_size()272 	const scr_size get_size() const { return scr_size( w, h ); }
273 
set_size(const scr_size & sz)274 	void set_size( const scr_size &sz ) {
275 		w = sz.w;
276 		h = sz.h;
277 	}
278 
set_size(scr_coord_val width,scr_coord_val height)279 	void set_size( scr_coord_val width, scr_coord_val height) {
280 		w = width;
281 		h = height;
282 	}
283 
284 	// add to left, right and top, bottom
expand(scr_coord_val delta_x_par,scr_coord_val delta_y_par)285 	void expand( scr_coord_val delta_x_par, scr_coord_val delta_y_par ) {
286 		x -= delta_x_par;
287 		y -= delta_y_par;
288 		w += (delta_x_par<<1);
289 		h += (delta_y_par<<1);
290 	}
291 
292 	// Adjust rect to the bounding rect of this and rect.
outer_bounds(const scr_rect & rect)293 	void outer_bounds( const scr_rect &rect ) {
294 		scr_coord pt( min(x,rect.x), min(y,rect.y) );
295 		w = max(x+w,rect.x+rect.w)-pt.x;
296 		h = max(y+h,rect.y+rect.h)-pt.y;
297 		x = pt.x;
298 		y = pt.y;
299 	}
300 
301 	// Enforce a positive width and height
normalize()302 	void normalize() {
303 		if(  w<0  ) {
304 			x -= w;
305 			w = -w;
306 		}
307 		if(  h<0  ) {
308 			y -= h;
309 			h = -h;
310 		}
311 	}
312 
313 	// point in rect; border (x+w) is still counting as contained
contains(const scr_coord & pt)314 	bool contains( const scr_coord& pt ) const {
315 		return (  x <= pt.x  &&  x+w >= pt.x  &&  y <=pt.y  &&  y+h >= pt.y  );
316 	}
317 
318 	// Now rect/rect functions: First check if rect is completely surrounded by this
319 	// maybe surrounds would be a better name, but contains seems more consistent
contains(const scr_rect & rect)320 	bool contains( const scr_rect& rect ) const {
321 		return (  x <= rect.x  &&  x+w >= rect.x+rect.w  &&  y <= rect.y  &&  y+h >= rect.y+rect.h  );
322 	}
323 
is_overlapping(const scr_rect & rect)324 	bool is_overlapping( const scr_rect &rect ) const {
325 		return !( (get_bottomright().x < rect.x) ||
326 		(get_bottomright().y < rect.y) ||
327 		(rect.get_bottomright().x < x) ||
328 		(rect.get_bottomright().y < y) );
329 	}
330 
relation(const scr_rect & rect)331 	rect_relation_t relation( const scr_rect& rect ) const {
332 		if( contains(rect) ) {
333 			return RECT_RELATION_INSIDE;
334 		}
335 		else if( is_overlapping( rect ) ) {
336 			return RECT_RELATION_OVERLAP;
337 		}
338 		return RECT_RELATION_OUTSIDE;
339 	}
340 
341 	/* reduces the current rect to the overlapping area of two rect
342 	 * in case of no overlap the new size is negative
343 	 * (prissi: in my humble opinion this could rather return a new rect)
344 	 */
clip(const scr_rect clip_rect)345 	void clip( const scr_rect clip_rect ) {
346 		x = max(x, clip_rect.x);
347 		set_right( min(x+w, clip_rect.x+clip_rect.w) );
348 		y = max(y, clip_rect.y);
349 		set_bottom( min(y+h, clip_rect.y+clip_rect.h) );
350 	}
351 
352 	bool operator ==(const scr_rect& rect) const {
353 		return ( (x-rect.x) | (y-rect.y) | (w-rect.w) | (h-rect.h) ) == 0;
354 	}
355 
356 	bool operator !=(const scr_rect& rect_par) const {
357 		return !(rect_par==*this);
358 	}
359 private:
360 	// conversions to/from koord not allowed anymore
361 	scr_rect( const koord&);
362 	operator koord() const;
363 };
364 #endif
365