xref: /haiku/headers/private/interface/clipping.h (revision 171057c06a47bcf66bc66e9925775ca6b0c8970b)
1 /*
2  * Copyright 2001-2004, Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  *	Authors:
6  *		Stefano Ceccherini, burton666@libero.it
7  */
8 #ifndef __CLIPPING_H
9 #define __CLIPPING_H
10 
11 #include <Region.h>
12 #include <SupportDefs.h>
13 
14 
15 /*	Some methods to manipulate clipping_rects.
16 	basically you can do almost everything you do with
17 	BRects, just that clipping_rects can only have integer
18 	coordinates (a thing that makes these perfect for drawing
19 	calculations).
20 */
21 
22 
23 // Returns the union of the given rects.
24 static inline clipping_rect
union_rect(const clipping_rect & r1,const clipping_rect & r2)25 union_rect(const clipping_rect &r1, const clipping_rect &r2)
26 {
27 	clipping_rect rect;
28 
29 	rect.left = min_c(r1.left, r2.left);
30 	rect.top = min_c(r1.top, r2.top);
31 	rect.right = max_c(r1.right, r2.right);
32 	rect.bottom = max_c(r1.bottom, r2.bottom);
33 
34 	return rect;
35 }
36 
37 
38 // Returns the intersection of the given rects.
39 // The caller should check if the returned rect is valid. If it isn't valid,
40 // then the two rectangles don't intersect.
41 static inline clipping_rect
sect_rect(const clipping_rect & r1,const clipping_rect & r2)42 sect_rect(const clipping_rect &r1, const clipping_rect &r2)
43 {
44 	clipping_rect rect;
45 
46 	rect.left = max_c(r1.left, r2.left);
47 	rect.top = max_c(r1.top, r2.top);
48 	rect.right = min_c(r1.right, r2.right);
49 	rect.bottom = min_c(r1.bottom, r2.bottom);
50 
51 	return rect;
52 }
53 
54 
55 // Adds the given offsets to the given rect.
56 static inline void
offset_rect(clipping_rect & rect,int32 x,int32 y)57 offset_rect(clipping_rect &rect, int32 x, int32 y)
58 {
59 	rect.left += x;
60 	rect.top += y;
61 	rect.right += x;
62 	rect.bottom += y;
63 }
64 
65 
66 static inline void
scale_rect(clipping_rect & rect,float x,float y)67 scale_rect(clipping_rect& rect, float x, float y)
68 {
69 	rect.left = (int)(rect.left * x);
70 	rect.top = (int)(rect.top * y);
71 	rect.right = (int)((rect.right + 1) * x) - 1;
72 	rect.bottom = (int)((rect.bottom + 1) * y) - 1;
73 }
74 
75 
76 // Converts the given clipping_rect to a BRect
77 static inline BRect
to_BRect(const clipping_rect & rect)78 to_BRect(const clipping_rect &rect)
79 {
80 	return BRect((float)rect.left, (float)rect.top,
81 				 (float)rect.right, (float)rect.bottom);
82 }
83 
84 
85 // Converts the given BRect to a clipping_rect.
86 static inline clipping_rect
to_clipping_rect(const BRect & rect)87 to_clipping_rect(const BRect &rect)
88 {
89 	clipping_rect clipRect;
90 
91 // NOTE: test fractional coords BRects -> BRegion on R5
92 // and compare with this implementation...
93 //	clipRect.left = (int32)floorf(rect.left);
94 //	clipRect.top = (int32)floorf(rect.top);
95 //	clipRect.right = (int32)ceilf(rect.right);
96 //	clipRect.bottom = (int32)ceilf(rect.bottom);
97 
98 	// NOTE: clipping_rects are used as "pixel indices"
99 	// therefor, it should be ok to convert them like this:
100 	clipRect.left = (int32)rect.left;
101 	clipRect.top = (int32)rect.top;
102 	clipRect.right = (int32)rect.right;
103 	clipRect.bottom = (int32)rect.bottom;
104 
105 	return clipRect;
106 }
107 
108 
109 // Checks if the given point lies in the given rect's area
110 static inline bool
point_in(const clipping_rect & rect,int32 px,int32 py)111 point_in(const clipping_rect &rect, int32 px, int32 py)
112 {
113 	if (px >= rect.left && px <= rect.right
114 			&& py >= rect.top && py <= rect.bottom)
115 		return true;
116 	return false;
117 }
118 
119 
120 // Same as above, but it accepts a BPoint parameter
121 static inline bool
point_in(const clipping_rect & rect,const BPoint & pt)122 point_in(const clipping_rect &rect, const BPoint &pt)
123 {
124 	if (pt.x >= rect.left && pt.x <= rect.right
125 			&& pt.y >= rect.top && pt.y <= rect.bottom)
126 		return true;
127 	return false;
128 }
129 
130 
131 static inline bool
rect_contains(const clipping_rect & rect,const clipping_rect & testRect)132 rect_contains(const clipping_rect &rect, const clipping_rect &testRect)
133 {
134 	return rect.top <= testRect.top && rect.bottom >= testRect.bottom
135 			&& rect.left <= testRect.left && rect.right >= testRect.right;
136 }
137 
138 
139 // Checks if the rect is valid
140 static inline bool
valid_rect(const clipping_rect & rect)141 valid_rect(const clipping_rect &rect)
142 {
143 	if (rect.left <= rect.right && rect.top <= rect.bottom)
144 		return true;
145 	return false;
146 }
147 
148 
149 // Checks if the two rects intersect.
150 static inline bool
rects_intersect(const clipping_rect & rectA,const clipping_rect & rectB)151 rects_intersect(const clipping_rect &rectA, const clipping_rect &rectB)
152 {
153 	// We behave like BRect::Intersects() does:
154 	// we return false if one of the two rects is not valid
155 	if (!valid_rect(rectA) || !valid_rect(rectB))
156 		return false;
157 
158 	// TODO: Is there a better algorithm ?
159 	// the one we used is faster than
160 	// ' return valid_rect(sect_rect(rectA, rectB)); ', though.
161 
162 	return !(rectA.left > rectB.right || rectA.top > rectB.bottom
163 			|| rectA.right < rectB.left || rectA.bottom < rectB.top);
164 }
165 
166 
167 // Returns the width of the given rect.
168 static inline int32
rect_width(const clipping_rect & rect)169 rect_width(const clipping_rect &rect)
170 {
171 	return rect.right - rect.left;
172 }
173 
174 
175 // Returns the height of the given rect.
176 static inline int32
rect_height(const clipping_rect & rect)177 rect_height(const clipping_rect &rect)
178 {
179 	return rect.bottom - rect.top;
180 }
181 
182 #endif // __CLIPPING_H
183