Code

Translations. POTFILES.in cleanup and inkscape.pot update.
[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"
13 #include <algorithm>
15 NRRect::NRRect(NR::Rect const &rect)
16 : x0(rect.min()[NR::X]), y0(rect.min()[NR::Y]),
17   x1(rect.max()[NR::X]), y1(rect.max()[NR::Y])
18 {}
20 NRRect::NRRect(boost::optional<NR::Rect> const &rect) {
21     if (rect) {
22         x0 = rect->min()[NR::X];
23         y0 = rect->min()[NR::Y];
24         x1 = rect->max()[NR::X];
25         y1 = rect->max()[NR::Y];
26     } else {
27         nr_rect_d_set_empty(this);
28     }
29 }
31 NRRect::NRRect(Geom::OptRect const &rect) {
32     if (rect) {
33         x0 = rect->min()[Geom::X];
34         y0 = rect->min()[Geom::Y];
35         x1 = rect->max()[Geom::X];
36         y1 = rect->max()[Geom::Y];
37     } else {
38         nr_rect_d_set_empty(this);
39     }
40 }
42 boost::optional<NR::Rect> NRRect::upgrade() const {
43     if (nr_rect_d_test_empty_ptr(this)) {
44         return boost::optional<NR::Rect>();
45     } else {
46         return NR::Rect(NR::Point(x0, y0), NR::Point(x1, y1));
47     }
48 }
50 Geom::OptRect NRRect::upgrade_2geom() const {
51     if (nr_rect_d_test_empty_ptr(this)) {
52         return Geom::OptRect();
53     } else {
54         return Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1));
55     }
56 }
58 /**
59  *    \param r0 Rectangle.
60  *    \param r1 Another rectangle.
61  *    \param d Filled in with the intersection of r0 and r1.
62  *    \return d.
63  */
65 NRRectL *nr_rect_l_intersect(NRRectL *d, const NRRectL *r0, const NRRectL *r1)
66 {
67   NR::ICoord t;
68   t = std::max(r0->x0, r1->x0);
69   d->x1 = std::min(r0->x1, r1->x1);
70   d->x0 = t;
71   t = std::max(r0->y0, r1->y0);
72   d->y1 = std::min(r0->y1, r1->y1);
73   d->y0 = t;
74         
75   return d;
76 }
78 NRRect *
79 nr_rect_d_intersect (NRRect *d, const NRRect *r0, const NRRect *r1)
80 {
81         NR::Coord t;
82         t = MAX (r0->x0, r1->x0);
83         d->x1 = MIN (r0->x1, r1->x1);
84         d->x0 = t;
85         t = MAX (r0->y0, r1->y0);
86         d->y1 = MIN (r0->y1, r1->y1);
87         d->y0 = t;
88         
89         return d;
90 }
92 // returns minimal rect which covers all of r0 not covered by r1
93 NRRectL *
94 nr_rect_l_subtract(NRRectL *d, NRRectL const *r0, NRRectL const *r1)
95 {
96     bool inside1 = nr_rect_l_test_inside(r1, r0->x0, r0->y0);
97     bool inside2 = nr_rect_l_test_inside(r1, r0->x1, r0->y0);
98     bool inside3 = nr_rect_l_test_inside(r1, r0->x1, r0->y1);
99     bool inside4 = nr_rect_l_test_inside(r1, r0->x0, r0->y1);
101     if (inside1 && inside2 && inside3) {
102         nr_rect_l_set_empty (d);
104     } else if (inside1 && inside2) {
105         d->x0 = r0->x0;
106         d->y0 = r1->y1;
108         d->x1 = r0->x1;
109         d->y1 = r0->y1;
110     } else if (inside2 && inside3) {
111         d->x0 = r0->x0;
112         d->y0 = r0->y0;
114         d->x1 = r1->x0;
115         d->y1 = r0->y1;
116     } else if (inside3 && inside4) {
117         d->x0 = r0->x0;
118         d->y0 = r0->y0;
120         d->x1 = r0->x1;
121         d->y1 = r1->y0;
122     } else if (inside4 && inside1) {
123         d->x0 = r1->x1;
124         d->y0 = r0->y0;
126         d->x1 = r0->x1;
127         d->y1 = r0->y1;
128     } else {
129         d->x0 = r0->x0;
130         d->y0 = r0->y0;
132         d->x1 = r0->x1;
133         d->y1 = r0->y1;
134     }
135     return d;
138 NR::ICoord nr_rect_l_area(NRRectL *r)
140   if (!r || NR_RECT_DFLS_TEST_EMPTY (r)) {
141       return 0;
142   }
143   return ((r->x1 - r->x0) * (r->y1 - r->y0));
146 NRRect *
147 nr_rect_d_union (NRRect *d, const NRRect *r0, const NRRect *r1)
149         if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
150                 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
151                         nr_rect_d_set_empty (d);
152                 } else {
153                         *d = *r1;
154                 }
155         } else {
156                 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
157                         *d = *r0;
158                 } else {
159                         NR::Coord t;
160                         t = MIN (r0->x0, r1->x0);
161                         d->x1 = MAX (r0->x1, r1->x1);
162                         d->x0 = t;
163                         t = MIN (r0->y0, r1->y0);
164                         d->y1 = MAX (r0->y1, r1->y1);
165                         d->y0 = t;
166                 }
167         }
168         return d;
171 NRRectL *
172 nr_rect_l_union (NRRectL *d, const NRRectL *r0, const NRRectL *r1)
174         if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
175                 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
176                         nr_rect_l_set_empty (d);
177                 } else {
178                         *d = *r1;
179                 }
180         } else {
181                 if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
182                         *d = *r0;
183                 } else {
184                         NR::ICoord t;
185                         t = MIN (r0->x0, r1->x0);
186                         d->x1 = MAX (r0->x1, r1->x1);
187                         d->x0 = t;
188                         t = MIN (r0->y0, r1->y0);
189                         d->y1 = MAX (r0->y1, r1->y1);
190                         d->y0 = t;
191                 }
192         }
193         return d;
196 NRRect *
197 nr_rect_union_pt(NRRect *dst, NR::Point const &p)
199         using NR::X;
200         using NR::Y;
202         return nr_rect_d_union_xy(dst, p[X], p[Y]);
205 NRRect *
206 nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
208         if ((d->x0 <= d->x1) && (d->y0 <= d->y1)) {
209                 d->x0 = MIN (d->x0, x);
210                 d->y0 = MIN (d->y0, y);
211                 d->x1 = MAX (d->x1, x);
212                 d->y1 = MAX (d->y1, y);
213         } else {
214                 d->x0 = d->x1 = x;
215                 d->y0 = d->y1 = y;
216         }
217         return d;
220 NRRect *
221 nr_rect_d_matrix_transform(NRRect *d, NRRect const *const s, NR::Matrix const &m)
223     using NR::X;
224     using NR::Y;
226     if (nr_rect_d_test_empty_ptr(s)) {
227         nr_rect_d_set_empty(d);
228     } else {
229         NR::Point const c00(NR::Point(s->x0, s->y0) * m);
230         NR::Point const c01(NR::Point(s->x0, s->y1) * m);
231         NR::Point const c10(NR::Point(s->x1, s->y0) * m);
232         NR::Point const c11(NR::Point(s->x1, s->y1) * m);
233         d->x0 = std::min(std::min(c00[X], c01[X]),
234                          std::min(c10[X], c11[X]));
235         d->y0 = std::min(std::min(c00[Y], c01[Y]),
236                          std::min(c10[Y], c11[Y]));
237         d->x1 = std::max(std::max(c00[X], c01[X]),
238                          std::max(c10[X], c11[X]));
239         d->y1 = std::max(std::max(c00[Y], c01[Y]),
240                          std::max(c10[Y], c11[Y]));
241     }
242     return d;
245 NRRect *
246 nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NR::Matrix const *m)
248     return nr_rect_d_matrix_transform(d, s, *m);
251 /** Enlarges the rectangle given amount of pixels to all directions */
252 NRRectL *
253 nr_rect_l_enlarge(NRRectL *d, int amount)
255     d->x0 -= amount;
256     d->y0 -= amount;
257     d->x1 += amount;
258     d->y1 += amount;
259     return d;
262 namespace NR {
264 Rect::Rect(const Point &p0, const Point &p1)
265 : _min(std::min(p0[X], p1[X]), std::min(p0[Y], p1[Y])),
266   _max(std::max(p0[X], p1[X]), std::max(p0[Y], p1[Y]))
267 {}
269 /** returns the four corners of the rectangle in the correct winding order */
270 Point Rect::corner(unsigned i) const {
271         switch (i % 4) {
272         case 0:
273                 return _min;
274         case 1:
275                 return Point(_max[X], _min[Y]);
276         case 2:
277                 return _max;
278         default: /* i.e. 3 */
279                 return Point(_min[X], _max[Y]);
280         }
283 /** returns the midpoint of this rectangle */
284 Point Rect::midpoint() const {
285         return ( _min + _max ) / 2;
288 Point Rect::cornerFarthestFrom(Point const &p) const {
289     Point m = midpoint();
290     unsigned i = 0;
291     if (p[X] < m[X]) {
292         i = 1;
293     }
294     if (p[Y] < m[Y]) {
295         i = 3 - i;
296     }
297     return corner(i);
300 /** returns a vector from topleft to bottom right. */
301 Point Rect::dimensions() const {
302         return _max - _min;
305 /** Translates the rectangle by p. */
306 void Rect::offset(Point p) {
307         _min += p;
308         _max += p;
311 /** Makes this rectangle large enough to include the point p. */
312 void Rect::expandTo(Point p) {
313         for ( int i=0 ; i < 2 ; i++ ) {
314                 _min[i] = std::min(_min[i], p[i]);
315                 _max[i] = std::max(_max[i], p[i]);
316         }
319 void Rect::growBy(double size) {
320   for ( unsigned d = 0 ; d < 2 ; d++ ) {
321     _min[d] -= size;
322     _max[d] += size;
323     if ( _min[d] > _max[d] ) {
324       _min[d] = _max[d] = ( _min[d] + _max[d] ) / 2;
325     }
326   }
327
329 /** Returns the set of points shared by both rectangles. */
330 boost::optional<Rect> intersection(boost::optional<Rect> const & a, boost::optional<Rect> const & b) {
331     if ( !a || !b ) {
332         return boost::optional<Rect>();
333     } else {
334         Rect r;
335         for ( int i=0 ; i < 2 ; i++ ) {
336             r._min[i] = std::max(a->_min[i], b->_min[i]);
337             r._max[i] = std::min(a->_max[i], b->_max[i]);
338             if ( r._min[i] > r._max[i] ) {
339             return boost::optional<Rect>();
340         }
341         }
342         return r;
343     }
346 /** returns the smallest rectangle containing both rectangles */
347 Rect union_bounds(Rect const &a, Rect const &b) {
348     Rect r;
349     for ( int i=0 ; i < 2 ; i++ ) {
350         r._min[i] = std::min(a._min[i], b._min[i]);
351         r._max[i] = std::max(a._max[i], b._max[i]);
352     }
353     return r;
356 }  // namespace NR
359 /*
360   Local Variables:
361   mode:c++
362   c-file-style:"stroustrup"
363   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
364   indent-tabs-mode:nil
365   fill-column:99
366   End:
367 */
368 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :