From: mental Date: Mon, 5 Mar 2007 05:50:20 +0000 (+0000) Subject: Separate NRRect and NR::Rect a bit further; the goal is to get to the point where... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=8d10164b2636a9ee8b6ab5c5182143c0e50de3d4;hp=c5da071d6655a73ec0155fa84f89b379fc0bf225;p=inkscape.git Separate NRRect and NR::Rect a bit further; the goal is to get to the point where there is no way to create an empty NR::Rect --- diff --git a/src/document.cpp b/src/document.cpp index 3579c4c91..ab6003167 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -494,7 +494,7 @@ gdouble sp_document_height(SPDocument *document) */ void SPDocument::fitToRect(NRRect const & rect) { - g_return_if_fail(!empty(rect)); + g_return_if_fail(!nr_rect_d_test_empty(&rect)); gdouble w = rect.x1 - rect.x0; gdouble h = rect.y1 - rect.y0; diff --git a/src/libnr/nr-rect.cpp b/src/libnr/nr-rect.cpp index 76d7fff8d..21d3f470a 100644 --- a/src/libnr/nr-rect.cpp +++ b/src/libnr/nr-rect.cpp @@ -11,6 +11,30 @@ #include "nr-rect-l.h" +NRRect::NRRect(NR::Rect const &rect) +: x0(rect.min()[NR::X]), y0(rect.min()[NR::Y]), + x1(rect.max()[NR::X]), y1(rect.max()[NR::Y]) +{} + +NRRect::NRRect(NR::Maybe const &rect) { + if (rect) { + x0 = rect->min()[NR::X]; + y0 = rect->min()[NR::Y]; + x1 = rect->max()[NR::X]; + y1 = rect->max()[NR::Y]; + } else { + nr_rect_d_set_empty(this); + } +} + +NR::Maybe NRRect::upgrade() const { + if (nr_rect_d_test_empty(this)) { + return NR::Nothing(); + } else { + return NR::Rect(NR::Point(x0, y0), NR::Point(x1, y1)); + } +} + /** * \param r0 Rectangle. * \param r1 Another rectangle. diff --git a/src/libnr/nr-rect.h b/src/libnr/nr-rect.h index 115f94e46..dd7caa897 100644 --- a/src/libnr/nr-rect.h +++ b/src/libnr/nr-rect.h @@ -15,6 +15,7 @@ #include +#include #include "libnr/nr-values.h" #include @@ -24,62 +25,8 @@ #include #include -struct NRMatrix; namespace NR { struct Matrix; -} - -/* NULL rect is infinite */ - -struct NRRect { - NR::Coord x0, y0, x1, y1; -}; - -inline bool empty(NRRect const &r) -{ - return ( ( r.x0 > r.x1 ) || - ( r.y0 > r.y1 ) ); -} - -#define nr_rect_d_set_empty(r) (*(r) = NR_RECT_EMPTY) -#define nr_rect_l_set_empty(r) (*(r) = NR_RECT_L_EMPTY) - -#define nr_rect_d_test_empty(r) ((r) && NR_RECT_DFLS_TEST_EMPTY(r)) -#define nr_rect_l_test_empty(r) ((r) && NR_RECT_DFLS_TEST_EMPTY(r)) - -#define nr_rect_d_test_intersect(r0,r1) \ - (!nr_rect_d_test_empty(r0) && !nr_rect_d_test_empty(r1) && \ - !((r0) && (r1) && !NR_RECT_DFLS_TEST_INTERSECT(r0, r1))) -#define nr_rect_l_test_intersect(r0,r1) \ - (!nr_rect_l_test_empty(r0) && !nr_rect_l_test_empty(r1) && \ - !((r0) && (r1) && !NR_RECT_DFLS_TEST_INTERSECT(r0, r1))) - -#define nr_rect_d_point_d_test_inside(r,p) ((p) && (!(r) || (!NR_RECT_DF_TEST_EMPTY(r) && NR_RECT_DF_POINT_DF_TEST_INSIDE(r,p)))) -#define nr_rect_l_point_l_test_inside(r,p) ((p) && (!(r) || (!NR_RECT_DFLS_TEST_EMPTY(r) && NR_RECT_LS_POINT_LS_TEST_INSIDE(r,p)))) -#define nr_rect_l_test_inside(r,x,y) ((!(r) || (!NR_RECT_DFLS_TEST_EMPTY(r) && NR_RECT_LS_TEST_INSIDE(r,x,y)))) - -// returns minimal rect which covers all of r0 not covered by r1 -NRRectL *nr_rect_l_subtract(NRRectL *d, NRRectL const *r0, NRRectL const *r1); - -// returns the area of r -NR::ICoord nr_rect_l_area(NRRectL *r); - -/* NULL values are OK for r0 and r1, but not for d */ -NRRect *nr_rect_d_intersect(NRRect *d, NRRect const *r0, NRRect const *r1); -NRRectL *nr_rect_l_intersect(NRRectL *d, NRRectL const *r0, NRRectL const *r1); - -NRRect *nr_rect_d_union(NRRect *d, NRRect const *r0, NRRect const *r1); -NRRectL *nr_rect_l_union(NRRectL *d, NRRectL const *r0, NRRectL const *r1); - -NRRect *nr_rect_union_pt(NRRect *dst, NR::Point const &p); -NRRect *nr_rect_d_union_xy(NRRect *d, NR::Coord x, NR::Coord y); -NRRectL *nr_rect_l_union_xy(NRRectL *d, NR::ICoord x, NR::ICoord y); - -NRRect *nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NR::Matrix const &m); -NRRect *nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NRMatrix const *m); -NRRectL *nr_rect_l_enlarge(NRRectL *d, int amount); - -namespace NR { /** A rectangle is always aligned to the X and Y axis. This means it * can be defined using only 4 coordinates, and determining @@ -89,9 +36,7 @@ namespace NR { * points. Infinities are also permitted. */ class Rect { public: - Rect() : _min(0.0, 0.0), _max(0.0, 0.0) {} - Rect(NRRect const &r) : _min(r.x0, r.y0), _max(r.x1, r.y1) {} - Rect(Rect const &r) : _min(r._min), _max(r._max) {} + Rect() : _min(-_inf(), -_inf()), _max(_inf(), _inf()) {} Rect(Point const &p0, Point const &p1); Point const &min() const { return _min; } @@ -227,6 +172,9 @@ public: friend inline std::ostream &operator<<(std::ostream &out_file, NR::Rect const &in_rect); private: + static double _inf() { + return std::numeric_limits::infinity(); + } template double extent() const { @@ -273,6 +221,63 @@ inline std::ostream } /* namespace NR */ +/* legacy rect stuff */ + +struct NRMatrix; + +/* NULL rect is infinite */ + +struct NRRect { + NRRect() {} + NRRect(NR::Coord xmin, NR::Coord ymin, NR::Coord xmax, NR::Coord ymax) + : x0(xmin), y0(ymin), x1(xmin), y1(ymin) + {} + explicit NRRect(NR::Rect const &rect); + explicit NRRect(NR::Maybe const &rect); + operator NR::Maybe() const { return upgrade(); } + NR::Maybe upgrade() const; + + NR::Coord x0, y0, x1, y1; +}; + +#define nr_rect_d_set_empty(r) (*(r) = NR_RECT_EMPTY) +#define nr_rect_l_set_empty(r) (*(r) = NR_RECT_L_EMPTY) + +#define nr_rect_d_test_empty(r) ((r) && NR_RECT_DFLS_TEST_EMPTY(r)) +#define nr_rect_l_test_empty(r) ((r) && NR_RECT_DFLS_TEST_EMPTY(r)) + +#define nr_rect_d_test_intersect(r0,r1) \ + (!nr_rect_d_test_empty(r0) && !nr_rect_d_test_empty(r1) && \ + !((r0) && (r1) && !NR_RECT_DFLS_TEST_INTERSECT(r0, r1))) +#define nr_rect_l_test_intersect(r0,r1) \ + (!nr_rect_l_test_empty(r0) && !nr_rect_l_test_empty(r1) && \ + !((r0) && (r1) && !NR_RECT_DFLS_TEST_INTERSECT(r0, r1))) + +#define nr_rect_d_point_d_test_inside(r,p) ((p) && (!(r) || (!NR_RECT_DF_TEST_EMPTY(r) && NR_RECT_DF_POINT_DF_TEST_INSIDE(r,p)))) +#define nr_rect_l_point_l_test_inside(r,p) ((p) && (!(r) || (!NR_RECT_DFLS_TEST_EMPTY(r) && NR_RECT_LS_POINT_LS_TEST_INSIDE(r,p)))) +#define nr_rect_l_test_inside(r,x,y) ((!(r) || (!NR_RECT_DFLS_TEST_EMPTY(r) && NR_RECT_LS_TEST_INSIDE(r,x,y)))) + +// returns minimal rect which covers all of r0 not covered by r1 +NRRectL *nr_rect_l_subtract(NRRectL *d, NRRectL const *r0, NRRectL const *r1); + +// returns the area of r +NR::ICoord nr_rect_l_area(NRRectL *r); + +/* NULL values are OK for r0 and r1, but not for d */ +NRRect *nr_rect_d_intersect(NRRect *d, NRRect const *r0, NRRect const *r1); +NRRectL *nr_rect_l_intersect(NRRectL *d, NRRectL const *r0, NRRectL const *r1); + +NRRect *nr_rect_d_union(NRRect *d, NRRect const *r0, NRRect const *r1); +NRRectL *nr_rect_l_union(NRRectL *d, NRRectL const *r0, NRRectL const *r1); + +NRRect *nr_rect_union_pt(NRRect *dst, NR::Point const &p); +NRRect *nr_rect_d_union_xy(NRRect *d, NR::Coord x, NR::Coord y); +NRRectL *nr_rect_l_union_xy(NRRectL *d, NR::ICoord x, NR::ICoord y); + +NRRect *nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NR::Matrix const &m); +NRRect *nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NRMatrix const *m); +NRRectL *nr_rect_l_enlarge(NRRectL *d, int amount); + #endif /* !LIBNR_NR_RECT_H_SEEN */ diff --git a/src/libnr/nr-values.cpp b/src/libnr/nr-values.cpp index bb310cc49..846a16bb8 100644 --- a/src/libnr/nr-values.cpp +++ b/src/libnr/nr-values.cpp @@ -9,8 +9,7 @@ and comparison. */ NRMatrix NR_MATRIX_IDENTITY = {{1.0, 0.0, 0.0, 1.0, 0.0, 0.0}}; -NRRect NR_RECT_EMPTY = - {NR_HUGE, NR_HUGE, -NR_HUGE, -NR_HUGE}; +NRRect NR_RECT_EMPTY(NR_HUGE, NR_HUGE, -NR_HUGE, -NR_HUGE); NRRectL NR_RECT_L_EMPTY = {NR_HUGE_L, NR_HUGE_L, -NR_HUGE_L, -NR_HUGE_L}; NRRectL NR_RECT_S_EMPTY = diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 34041b204..57fa6bb84 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2807,22 +2807,22 @@ void fit_canvas_to_selection(SPDesktop *desktop) { g_return_if_fail(doc != NULL); g_return_if_fail(desktop->selection != NULL); g_return_if_fail(!desktop->selection->isEmpty()); - NRRect bbox = {0,0,0,0}; + NRRect bbox(0, 0, 0, 0); desktop->selection->bounds(&bbox); - if (!empty(bbox)) { + if (!nr_rect_d_test_empty(&bbox)) { doc->fitToRect(bbox); } }; void fit_canvas_to_drawing(SPDocument *doc) { g_return_if_fail(doc != NULL); - NRRect bbox = {0,0,0,0}; + NRRect bbox(0, 0, 0, 0); sp_document_ensure_up_to_date (doc); sp_item_invoke_bbox(SP_ITEM(doc->root), &bbox, sp_item_i2r_affine(SP_ITEM(doc->root)), TRUE); - if (!empty(bbox)) { + if (!nr_rect_d_test_empty(&bbox)) { doc->fitToRect(bbox); } }; diff --git a/src/selection.cpp b/src/selection.cpp index 82c82b523..5c60e5f41 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -354,7 +354,13 @@ NRRect *Selection::boundsInDocument(NRRect *bbox) const { NR::Rect Selection::boundsInDocument() const { NRRect r; - return NR::Rect(*boundsInDocument(&r)); + NR::Maybe rect(boundsInDocument(&r)->upgrade()); + if (rect) { + return *rect; + } else { + // FIXME + return NR::Rect(NR::Point(0, 0), NR::Point(0, 0)); + } } /** Extract the position of the center from the first selected object */ diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 521d2d1cc..22114cd5b 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -714,11 +714,7 @@ NR::Maybe SPItem::getBounds(NR::Matrix const &transform, { NRRect r; sp_item_invoke_bbox_full(this, &r, transform, type, TRUE); - if (nr_rect_d_test_empty(&r)) { - return NR::Nothing(); - } else { - return NR::Rect(r); - } + return r; } void @@ -804,7 +800,13 @@ NR::Rect sp_item_bbox_desktop(SPItem *item) { NRRect ret; sp_item_invoke_bbox(item, &ret, sp_item_i2d_affine(item), TRUE); - return NR::Rect(ret); + NR::Maybe result = ret.upgrade(); + if (result) { + return *result; + } else { + // FIXME + return NR::Rect(NR::Point(0, 0), NR::Point(0, 0)); + } } static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p)