summaryrefslogtreecommitdiffstats
path: root/src/libnr/nr-rect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnr/nr-rect.cpp')
-rw-r--r--src/libnr/nr-rect.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/libnr/nr-rect.cpp b/src/libnr/nr-rect.cpp
new file mode 100644
index 000000000..0a8287bde
--- /dev/null
+++ b/src/libnr/nr-rect.cpp
@@ -0,0 +1,233 @@
+#define __NR_RECT_C__
+
+/*
+ * Pixel buffer rendering library
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ *
+ * This code is in public domain
+ */
+
+#include "nr-rect-l.h"
+
+/**
+ * \param r0 Rectangle.
+ * \param r1 Another rectangle.
+ * \param d Filled in with the intersection of r0 and r1.
+ * \return d.
+ */
+
+NRRectL *nr_rect_l_intersect(NRRectL *d, const NRRectL *r0, const NRRectL *r1)
+{
+ NR::ICoord t;
+ t = std::max(r0->x0, r1->x0);
+ d->x1 = std::min(r0->x1, r1->x1);
+ d->x0 = t;
+ t = std::max(r0->y0, r1->y0);
+ d->y1 = std::min(r0->y1, r1->y1);
+ d->y0 = t;
+
+ return d;
+}
+
+NRRect *
+nr_rect_d_intersect (NRRect *d, const NRRect *r0, const NRRect *r1)
+{
+ NR::Coord t;
+ t = MAX (r0->x0, r1->x0);
+ d->x1 = MIN (r0->x1, r1->x1);
+ d->x0 = t;
+ t = MAX (r0->y0, r1->y0);
+ d->y1 = MIN (r0->y1, r1->y1);
+ d->y0 = t;
+
+ return d;
+}
+
+NRRect *
+nr_rect_d_union (NRRect *d, const NRRect *r0, const NRRect *r1)
+{
+ if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
+ if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
+ nr_rect_d_set_empty (d);
+ } else {
+ *d = *r1;
+ }
+ } else {
+ if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
+ *d = *r0;
+ } else {
+ NR::Coord t;
+ t = MIN (r0->x0, r1->x0);
+ d->x1 = MAX (r0->x1, r1->x1);
+ d->x0 = t;
+ t = MIN (r0->y0, r1->y0);
+ d->y1 = MAX (r0->y1, r1->y1);
+ d->y0 = t;
+ }
+ }
+ return d;
+}
+
+NRRectL *
+nr_rect_l_union (NRRectL *d, const NRRectL *r0, const NRRectL *r1)
+{
+ if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
+ if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
+ nr_rect_l_set_empty (d);
+ } else {
+ *d = *r1;
+ }
+ } else {
+ if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
+ *d = *r0;
+ } else {
+ NR::ICoord t;
+ t = MIN (r0->x0, r1->x0);
+ d->x1 = MAX (r0->x1, r1->x1);
+ d->x0 = t;
+ t = MIN (r0->y0, r1->y0);
+ d->y1 = MAX (r0->y1, r1->y1);
+ d->y0 = t;
+ }
+ }
+ return d;
+}
+
+NRRect *
+nr_rect_union_pt(NRRect *dst, NR::Point const &p)
+{
+ using NR::X;
+ using NR::Y;
+
+ return nr_rect_d_union_xy(dst, p[X], p[Y]);
+}
+
+NRRect *
+nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
+{
+ if ((d->x0 <= d->x1) && (d->y0 <= d->y1)) {
+ d->x0 = MIN (d->x0, x);
+ d->y0 = MIN (d->y0, y);
+ d->x1 = MAX (d->x1, x);
+ d->y1 = MAX (d->y1, y);
+ } else {
+ d->x0 = d->x1 = x;
+ d->y0 = d->y1 = y;
+ }
+ return d;
+}
+
+NRRect *
+nr_rect_d_matrix_transform(NRRect *d, NRRect const *const s, NR::Matrix const &m)
+{
+ using NR::X;
+ using NR::Y;
+
+ if (nr_rect_d_test_empty(s)) {
+ nr_rect_d_set_empty(d);
+ } else {
+ NR::Point const c00(NR::Point(s->x0, s->y0) * m);
+ NR::Point const c01(NR::Point(s->x0, s->y1) * m);
+ NR::Point const c10(NR::Point(s->x1, s->y0) * m);
+ NR::Point const c11(NR::Point(s->x1, s->y1) * m);
+ d->x0 = std::min(std::min(c00[X], c01[X]),
+ std::min(c10[X], c11[X]));
+ d->y0 = std::min(std::min(c00[Y], c01[Y]),
+ std::min(c10[Y], c11[Y]));
+ d->x1 = std::max(std::max(c00[X], c01[X]),
+ std::max(c10[X], c11[X]));
+ d->y1 = std::max(std::max(c00[Y], c01[Y]),
+ std::max(c10[Y], c11[Y]));
+ }
+ return d;
+}
+
+NRRect *
+nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NRMatrix const *m)
+{
+ return nr_rect_d_matrix_transform(d, s, *m);
+}
+
+namespace NR {
+
+Rect::Rect(const Point &p0, const Point &p1)
+: _min(MIN(p0[X], p1[X]), MIN(p0[Y], p1[Y])),
+ _max(MAX(p0[X], p1[X]), MAX(p0[Y], p1[Y])) {}
+
+/** returns the four corners of the rectangle in the correct winding order */
+Point Rect::corner(unsigned i) const {
+ switch (i % 4) {
+ case 0:
+ return _min;
+ case 1:
+ return Point(_max[X], _min[Y]);
+ case 2:
+ return _max;
+ default: /* i.e. 3 */
+ return Point(_min[X], _max[Y]);
+ }
+}
+
+/** returns the midpoint of this rectangle */
+Point Rect::midpoint() const {
+ return ( _min + _max ) / 2;
+}
+
+/** returns a vector from topleft to bottom right. */
+Point Rect::dimensions() const {
+ return _max - _min;
+}
+
+/** Translates the rectangle by p. */
+void Rect::offset(Point p) {
+ _min += p;
+ _max += p;
+}
+
+/** Makes this rectangle large enough to include the point p. */
+void Rect::expandTo(Point p) {
+ for ( int i=0 ; i < 2 ; i++ ) {
+ _min[i] = MIN(_min[i], p[i]);
+ _max[i] = MAX(_max[i], p[i]);
+ }
+}
+
+/** Returns the set of points shared by both rectangles. */
+Maybe<Rect> Rect::intersection(const Rect &a, const Rect &b) {
+ Rect r;
+ for ( int i=0 ; i < 2 ; i++ ) {
+ r._min[i] = MAX(a._min[i], b._min[i]);
+ r._max[i] = MIN(a._max[i], b._max[i]);
+
+ if ( r._min[i] > r._max[i] ) {
+ return Nothing();
+ }
+ }
+ return r;
+}
+
+/** returns the smallest rectangle containing both rectangles */
+Rect Rect::union_bounds(const Rect &a, const Rect &b) {
+ Rect r;
+ for ( int i=0; i < 2 ; i++ ) {
+ r._min[i] = MIN(a._min[i], b._min[i]);
+ r._max[i] = MAX(a._max[i], b._max[i]);
+ }
+ return r;
+}
+
+} // namespace NR
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :