Code

moving trunk for module inkscape
[inkscape.git] / src / libnr / nr-rect.cpp
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;
30         
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;
44         
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)
101         using NR::X;
102         using NR::Y;
104         return nr_rect_d_union_xy(dst, p[X], p[Y]);
107 NRRect *
108 nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
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;
122 NRRect *
123 nr_rect_d_matrix_transform(NRRect *d, NRRect const *const s, NR::Matrix const &m)
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;
147 NRRect *
148 nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NRMatrix const *m)
150     return nr_rect_d_matrix_transform(d, s, *m);
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         }
173 /** returns the midpoint of this rectangle */
174 Point Rect::midpoint() const {
175         return ( _min + _max ) / 2;
178 /** returns a vector from topleft to bottom right. */
179 Point Rect::dimensions() const {
180         return _max - _min;
183 /** Translates the rectangle by p. */
184 void Rect::offset(Point p) {
185         _min += p;
186         _max += p;
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         }
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;
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;
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 :