Code

svg-filters branch merged back to head
[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 /** Enlarges the rectangle given amount of pixels to all directions */
154 NRRectL *
155 nr_rect_l_enlarge(NRRectL *d, int amount)
157     d->x0 -= amount;
158     d->y0 -= amount;
159     d->x1 += amount;
160     d->y1 += amount;
161     return d;
164 namespace NR {
166 Rect::Rect(const Point &p0, const Point &p1)
167 : _min(MIN(p0[X], p1[X]), MIN(p0[Y], p1[Y])),
168   _max(MAX(p0[X], p1[X]), MAX(p0[Y], p1[Y])) {}
170 /** returns the four corners of the rectangle in the correct winding order */
171 Point Rect::corner(unsigned i) const {
172         switch (i % 4) {
173         case 0:
174                 return _min;
175         case 1:
176                 return Point(_max[X], _min[Y]);
177         case 2:
178                 return _max;
179         default: /* i.e. 3 */
180                 return Point(_min[X], _max[Y]);
181         }
184 /** returns the midpoint of this rectangle */
185 Point Rect::midpoint() const {
186         return ( _min + _max ) / 2;
189 /** returns a vector from topleft to bottom right. */
190 Point Rect::dimensions() const {
191         return _max - _min;
194 /** Translates the rectangle by p. */
195 void Rect::offset(Point p) {
196         _min += p;
197         _max += p;
200 /** Makes this rectangle large enough to include the point p. */
201 void Rect::expandTo(Point p) {
202         for ( int i=0 ; i < 2 ; i++ ) {
203                 _min[i] = MIN(_min[i], p[i]);
204                 _max[i] = MAX(_max[i], p[i]);
205         }
208 /** Returns the set of points shared by both rectangles. */
209 Maybe<Rect> Rect::intersection(const Rect &a, const Rect &b) {
210         Rect r;
211         for ( int i=0 ; i < 2 ; i++ ) {
212                 r._min[i] = MAX(a._min[i], b._min[i]);
213                 r._max[i] = MIN(a._max[i], b._max[i]);
215                 if ( r._min[i] > r._max[i] ) {
216                         return Nothing();
217                 }
218         }
219         return r;
222 /** returns the smallest rectangle containing both rectangles */
223 Rect Rect::union_bounds(const Rect &a, const Rect &b) {
224         Rect r;
225         for ( int i=0; i < 2 ; i++ ) {
226                 r._min[i] = MIN(a._min[i], b._min[i]);
227                 r._max[i] = MAX(a._max[i], b._max[i]);
228         }
229         return r;
232 }  // namespace NR
235 /*
236   Local Variables:
237   mode:c++
238   c-file-style:"stroustrup"
239   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
240   indent-tabs-mode:nil
241   fill-column:99
242   End:
243 */
244 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :