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 /**
15 * \param r0 Rectangle.
16 * \param r1 Another rectangle.
17 * \param d Filled in with the intersection of r0 and r1.
18 * \return d.
19 */
21 NRRectL *nr_rect_l_intersect(NRRectL *d, const NRRectL *r0, const NRRectL *r1)
22 {
23 NR::ICoord t;
24 t = std::max(r0->x0, r1->x0);
25 d->x1 = std::min(r0->x1, r1->x1);
26 d->x0 = t;
27 t = std::max(r0->y0, r1->y0);
28 d->y1 = std::min(r0->y1, r1->y1);
29 d->y0 = t;
31 return d;
32 }
34 NRRect *
35 nr_rect_d_intersect (NRRect *d, const NRRect *r0, const NRRect *r1)
36 {
37 NR::Coord t;
38 t = MAX (r0->x0, r1->x0);
39 d->x1 = MIN (r0->x1, r1->x1);
40 d->x0 = t;
41 t = MAX (r0->y0, r1->y0);
42 d->y1 = MIN (r0->y1, r1->y1);
43 d->y0 = t;
45 return d;
46 }
48 NRRect *
49 nr_rect_d_union (NRRect *d, const NRRect *r0, const NRRect *r1)
50 {
51 if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
52 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
53 nr_rect_d_set_empty (d);
54 } else {
55 *d = *r1;
56 }
57 } else {
58 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
59 *d = *r0;
60 } else {
61 NR::Coord t;
62 t = MIN (r0->x0, r1->x0);
63 d->x1 = MAX (r0->x1, r1->x1);
64 d->x0 = t;
65 t = MIN (r0->y0, r1->y0);
66 d->y1 = MAX (r0->y1, r1->y1);
67 d->y0 = t;
68 }
69 }
70 return d;
71 }
73 NRRectL *
74 nr_rect_l_union (NRRectL *d, const NRRectL *r0, const NRRectL *r1)
75 {
76 if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
77 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
78 nr_rect_l_set_empty (d);
79 } else {
80 *d = *r1;
81 }
82 } else {
83 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
84 *d = *r0;
85 } else {
86 NR::ICoord t;
87 t = MIN (r0->x0, r1->x0);
88 d->x1 = MAX (r0->x1, r1->x1);
89 d->x0 = t;
90 t = MIN (r0->y0, r1->y0);
91 d->y1 = MAX (r0->y1, r1->y1);
92 d->y0 = t;
93 }
94 }
95 return d;
96 }
98 NRRect *
99 nr_rect_union_pt(NRRect *dst, NR::Point const &p)
100 {
101 using NR::X;
102 using NR::Y;
104 return nr_rect_d_union_xy(dst, p[X], p[Y]);
105 }
107 NRRect *
108 nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
109 {
110 if ((d->x0 <= d->x1) && (d->y0 <= d->y1)) {
111 d->x0 = MIN (d->x0, x);
112 d->y0 = MIN (d->y0, y);
113 d->x1 = MAX (d->x1, x);
114 d->y1 = MAX (d->y1, y);
115 } else {
116 d->x0 = d->x1 = x;
117 d->y0 = d->y1 = y;
118 }
119 return d;
120 }
122 NRRect *
123 nr_rect_d_matrix_transform(NRRect *d, NRRect const *const s, NR::Matrix const &m)
124 {
125 using NR::X;
126 using NR::Y;
128 if (nr_rect_d_test_empty(s)) {
129 nr_rect_d_set_empty(d);
130 } else {
131 NR::Point const c00(NR::Point(s->x0, s->y0) * m);
132 NR::Point const c01(NR::Point(s->x0, s->y1) * m);
133 NR::Point const c10(NR::Point(s->x1, s->y0) * m);
134 NR::Point const c11(NR::Point(s->x1, s->y1) * m);
135 d->x0 = std::min(std::min(c00[X], c01[X]),
136 std::min(c10[X], c11[X]));
137 d->y0 = std::min(std::min(c00[Y], c01[Y]),
138 std::min(c10[Y], c11[Y]));
139 d->x1 = std::max(std::max(c00[X], c01[X]),
140 std::max(c10[X], c11[X]));
141 d->y1 = std::max(std::max(c00[Y], c01[Y]),
142 std::max(c10[Y], c11[Y]));
143 }
144 return d;
145 }
147 NRRect *
148 nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NRMatrix const *m)
149 {
150 return nr_rect_d_matrix_transform(d, s, *m);
151 }
153 namespace NR {
155 Rect::Rect(const Point &p0, const Point &p1)
156 : _min(MIN(p0[X], p1[X]), MIN(p0[Y], p1[Y])),
157 _max(MAX(p0[X], p1[X]), MAX(p0[Y], p1[Y])) {}
159 /** returns the four corners of the rectangle in the correct winding order */
160 Point Rect::corner(unsigned i) const {
161 switch (i % 4) {
162 case 0:
163 return _min;
164 case 1:
165 return Point(_max[X], _min[Y]);
166 case 2:
167 return _max;
168 default: /* i.e. 3 */
169 return Point(_min[X], _max[Y]);
170 }
171 }
173 /** returns the midpoint of this rectangle */
174 Point Rect::midpoint() const {
175 return ( _min + _max ) / 2;
176 }
178 /** returns a vector from topleft to bottom right. */
179 Point Rect::dimensions() const {
180 return _max - _min;
181 }
183 /** Translates the rectangle by p. */
184 void Rect::offset(Point p) {
185 _min += p;
186 _max += p;
187 }
189 /** Makes this rectangle large enough to include the point p. */
190 void Rect::expandTo(Point p) {
191 for ( int i=0 ; i < 2 ; i++ ) {
192 _min[i] = MIN(_min[i], p[i]);
193 _max[i] = MAX(_max[i], p[i]);
194 }
195 }
197 /** Returns the set of points shared by both rectangles. */
198 Maybe<Rect> Rect::intersection(const Rect &a, const Rect &b) {
199 Rect r;
200 for ( int i=0 ; i < 2 ; i++ ) {
201 r._min[i] = MAX(a._min[i], b._min[i]);
202 r._max[i] = MIN(a._max[i], b._max[i]);
204 if ( r._min[i] > r._max[i] ) {
205 return Nothing();
206 }
207 }
208 return r;
209 }
211 /** returns the smallest rectangle containing both rectangles */
212 Rect Rect::union_bounds(const Rect &a, const Rect &b) {
213 Rect r;
214 for ( int i=0; i < 2 ; i++ ) {
215 r._min[i] = MIN(a._min[i], b._min[i]);
216 r._max[i] = MAX(a._max[i], b._max[i]);
217 }
218 return r;
219 }
221 } // namespace NR
224 /*
225 Local Variables:
226 mode:c++
227 c-file-style:"stroustrup"
228 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
229 indent-tabs-mode:nil
230 fill-column:99
231 End:
232 */
233 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :