9047e4e1c53faa2762b0bffe5b22aeea695800df
1 #define __NR_RECT_C__
3 /*
4 * Pixel buffer rendering library
5 *
6 * Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * This code is in public domain
10 */
12 #include "nr-rect-l.h"
14 NRRect::NRRect(NR::Rect const &rect)
15 : x0(rect.min()[NR::X]), y0(rect.min()[NR::Y]),
16 x1(rect.max()[NR::X]), y1(rect.max()[NR::Y])
17 {}
19 NRRect::NRRect(NR::Maybe<NR::Rect> const &rect) {
20 if (rect) {
21 x0 = rect->min()[NR::X];
22 y0 = rect->min()[NR::Y];
23 x1 = rect->max()[NR::X];
24 y1 = rect->max()[NR::Y];
25 } else {
26 nr_rect_d_set_empty(this);
27 }
28 }
30 NR::Maybe<NR::Rect> NRRect::upgrade() const {
31 if (nr_rect_d_test_empty(this)) {
32 return NR::Nothing();
33 } else {
34 return NR::Rect(NR::Point(x0, y0), NR::Point(x1, y1));
35 }
36 }
38 /**
39 * \param r0 Rectangle.
40 * \param r1 Another rectangle.
41 * \param d Filled in with the intersection of r0 and r1.
42 * \return d.
43 */
45 NRRectL *nr_rect_l_intersect(NRRectL *d, const NRRectL *r0, const NRRectL *r1)
46 {
47 NR::ICoord t;
48 t = std::max(r0->x0, r1->x0);
49 d->x1 = std::min(r0->x1, r1->x1);
50 d->x0 = t;
51 t = std::max(r0->y0, r1->y0);
52 d->y1 = std::min(r0->y1, r1->y1);
53 d->y0 = t;
55 return d;
56 }
58 NRRect *
59 nr_rect_d_intersect (NRRect *d, const NRRect *r0, const NRRect *r1)
60 {
61 NR::Coord t;
62 t = MAX (r0->x0, r1->x0);
63 d->x1 = MIN (r0->x1, r1->x1);
64 d->x0 = t;
65 t = MAX (r0->y0, r1->y0);
66 d->y1 = MIN (r0->y1, r1->y1);
67 d->y0 = t;
69 return d;
70 }
72 // returns minimal rect which covers all of r0 not covered by r1
73 NRRectL *
74 nr_rect_l_subtract(NRRectL *d, NRRectL const *r0, NRRectL const *r1)
75 {
76 bool inside1 = nr_rect_l_test_inside(r1, r0->x0, r0->y0);
77 bool inside2 = nr_rect_l_test_inside(r1, r0->x1, r0->y0);
78 bool inside3 = nr_rect_l_test_inside(r1, r0->x1, r0->y1);
79 bool inside4 = nr_rect_l_test_inside(r1, r0->x0, r0->y1);
81 if (inside1 && inside2 && inside3) {
82 nr_rect_l_set_empty (d);
84 } else if (inside1 && inside2) {
85 d->x0 = r0->x0;
86 d->y0 = r1->y1;
88 d->x1 = r0->x1;
89 d->y1 = r0->y1;
90 } else if (inside2 && inside3) {
91 d->x0 = r0->x0;
92 d->y0 = r0->y0;
94 d->x1 = r1->x0;
95 d->y1 = r0->y1;
96 } else if (inside3 && inside4) {
97 d->x0 = r0->x0;
98 d->y0 = r0->y0;
100 d->x1 = r0->x1;
101 d->y1 = r1->y0;
102 } else if (inside4 && inside1) {
103 d->x0 = r1->x1;
104 d->y0 = r0->y0;
106 d->x1 = r0->x1;
107 d->y1 = r0->y1;
108 } else {
109 d->x0 = r0->x0;
110 d->y0 = r0->y0;
112 d->x1 = r0->x1;
113 d->y1 = r0->y1;
114 }
115 return d;
116 }
118 NR::ICoord nr_rect_l_area(NRRectL *r)
119 {
120 if (!r || NR_RECT_DFLS_TEST_EMPTY (r)) {
121 return 0;
122 }
123 return ((r->x1 - r->x0) * (r->y1 - r->y0));
124 }
126 NRRect *
127 nr_rect_d_union (NRRect *d, const NRRect *r0, const NRRect *r1)
128 {
129 if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
130 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
131 nr_rect_d_set_empty (d);
132 } else {
133 *d = *r1;
134 }
135 } else {
136 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
137 *d = *r0;
138 } else {
139 NR::Coord t;
140 t = MIN (r0->x0, r1->x0);
141 d->x1 = MAX (r0->x1, r1->x1);
142 d->x0 = t;
143 t = MIN (r0->y0, r1->y0);
144 d->y1 = MAX (r0->y1, r1->y1);
145 d->y0 = t;
146 }
147 }
148 return d;
149 }
151 NRRectL *
152 nr_rect_l_union (NRRectL *d, const NRRectL *r0, const NRRectL *r1)
153 {
154 if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
155 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
156 nr_rect_l_set_empty (d);
157 } else {
158 *d = *r1;
159 }
160 } else {
161 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
162 *d = *r0;
163 } else {
164 NR::ICoord t;
165 t = MIN (r0->x0, r1->x0);
166 d->x1 = MAX (r0->x1, r1->x1);
167 d->x0 = t;
168 t = MIN (r0->y0, r1->y0);
169 d->y1 = MAX (r0->y1, r1->y1);
170 d->y0 = t;
171 }
172 }
173 return d;
174 }
176 NRRect *
177 nr_rect_union_pt(NRRect *dst, NR::Point const &p)
178 {
179 using NR::X;
180 using NR::Y;
182 return nr_rect_d_union_xy(dst, p[X], p[Y]);
183 }
185 NRRect *
186 nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
187 {
188 if ((d->x0 <= d->x1) && (d->y0 <= d->y1)) {
189 d->x0 = MIN (d->x0, x);
190 d->y0 = MIN (d->y0, y);
191 d->x1 = MAX (d->x1, x);
192 d->y1 = MAX (d->y1, y);
193 } else {
194 d->x0 = d->x1 = x;
195 d->y0 = d->y1 = y;
196 }
197 return d;
198 }
200 NRRect *
201 nr_rect_d_matrix_transform(NRRect *d, NRRect const *const s, NR::Matrix const &m)
202 {
203 using NR::X;
204 using NR::Y;
206 if (nr_rect_d_test_empty(s)) {
207 nr_rect_d_set_empty(d);
208 } else {
209 NR::Point const c00(NR::Point(s->x0, s->y0) * m);
210 NR::Point const c01(NR::Point(s->x0, s->y1) * m);
211 NR::Point const c10(NR::Point(s->x1, s->y0) * m);
212 NR::Point const c11(NR::Point(s->x1, s->y1) * m);
213 d->x0 = std::min(std::min(c00[X], c01[X]),
214 std::min(c10[X], c11[X]));
215 d->y0 = std::min(std::min(c00[Y], c01[Y]),
216 std::min(c10[Y], c11[Y]));
217 d->x1 = std::max(std::max(c00[X], c01[X]),
218 std::max(c10[X], c11[X]));
219 d->y1 = std::max(std::max(c00[Y], c01[Y]),
220 std::max(c10[Y], c11[Y]));
221 }
222 return d;
223 }
225 NRRect *
226 nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NRMatrix const *m)
227 {
228 return nr_rect_d_matrix_transform(d, s, *m);
229 }
231 /** Enlarges the rectangle given amount of pixels to all directions */
232 NRRectL *
233 nr_rect_l_enlarge(NRRectL *d, int amount)
234 {
235 d->x0 -= amount;
236 d->y0 -= amount;
237 d->x1 += amount;
238 d->y1 += amount;
239 return d;
240 }
242 namespace NR {
244 Rect::Rect(const Point &p0, const Point &p1)
245 : _min(MIN(p0[X], p1[X]), MIN(p0[Y], p1[Y])),
246 _max(MAX(p0[X], p1[X]), MAX(p0[Y], p1[Y])) {}
248 /** returns the four corners of the rectangle in the correct winding order */
249 Point Rect::corner(unsigned i) const {
250 switch (i % 4) {
251 case 0:
252 return _min;
253 case 1:
254 return Point(_max[X], _min[Y]);
255 case 2:
256 return _max;
257 default: /* i.e. 3 */
258 return Point(_min[X], _max[Y]);
259 }
260 }
262 /** returns the midpoint of this rectangle */
263 Point Rect::midpoint() const {
264 return ( _min + _max ) / 2;
265 }
267 /** returns a vector from topleft to bottom right. */
268 Point Rect::dimensions() const {
269 return _max - _min;
270 }
272 /** Translates the rectangle by p. */
273 void Rect::offset(Point p) {
274 _min += p;
275 _max += p;
276 }
278 /** Makes this rectangle large enough to include the point p. */
279 void Rect::expandTo(Point p) {
280 for ( int i=0 ; i < 2 ; i++ ) {
281 _min[i] = MIN(_min[i], p[i]);
282 _max[i] = MAX(_max[i], p[i]);
283 }
284 }
286 /** Returns the set of points shared by both rectangles. */
287 Maybe<Rect> intersection(Maybe<Rect const &> a, Maybe<Rect const &> b) {
288 if ( !a || !b ) {
289 return Nothing();
290 } else {
291 Rect r;
292 for ( int i=0 ; i < 2 ; i++ ) {
293 r._min[i] = MAX(a->_min[i], b->_min[i]);
294 r._max[i] = MIN(a->_max[i], b->_max[i]);
295 if ( r._min[i] > r._max[i] ) {
296 return Nothing();
297 }
298 }
299 return r;
300 }
301 }
303 /** returns the smallest rectangle containing both rectangles */
304 Rect union_bounds(Rect const &a, Rect const &b) {
305 Rect r;
306 for ( int i=0 ; i < 2 ; i++ ) {
307 r._min[i] = MIN(a._min[i], b._min[i]);
308 r._max[i] = MAX(a._max[i], b._max[i]);
309 }
310 return r;
311 }
313 } // namespace NR
316 /*
317 Local Variables:
318 mode:c++
319 c-file-style:"stroustrup"
320 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
321 indent-tabs-mode:nil
322 fill-column:99
323 End:
324 */
325 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :