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.
24static inline clipping_rect
25union_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.
41static inline clipping_rect
42sect_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.
56static inline void
57offset_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
66static inline void
67scale_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
77static inline BRect
78to_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.
86static inline clipping_rect
87to_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
110static inline bool
111point_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
121static inline bool
122point_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
131static inline bool
132rect_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
140static inline bool
141valid_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.
150static inline bool
151rects_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.
168static inline int32
169rect_width(const clipping_rect &rect)
170{
171	return rect.right - rect.left;
172}
173
174
175// Returns the height of the given rect.
176static inline int32
177rect_height(const clipping_rect &rect)
178{
179	return rect.bottom - rect.top;
180}
181
182#endif // __CLIPPING_H
183