From e7738cc5a9b584732fd9c1ac8264cab33f8a27a2 Mon Sep 17 00:00:00 2001 From: dvlierop2 Date: Sun, 6 Jan 2008 20:31:51 +0000 Subject: [PATCH] Fix LP #168684 --- src/sp-item.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++--- src/sp-item.h | 6 +++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 90765fc94..3b9d70504 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -691,17 +691,81 @@ NR::Maybe SPItem::getBounds(NR::Matrix const &transform, SPItem::BBoxType type, unsigned int /*dkey*/) const { - NRRect r; + NR::Maybe r = NR::Nothing(); sp_item_invoke_bbox_full(this, &r, transform, type, TRUE); return r; } +void +sp_item_invoke_bbox(SPItem const *item, NR::Maybe *bbox, NR::Matrix const &transform, unsigned const clear, SPItem::BBoxType type) +{ + sp_item_invoke_bbox_full(item, bbox, transform, type, clear); +} + +// DEPRECATED to phase out the use of NRRect in favor of NR::Maybe void sp_item_invoke_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const clear, SPItem::BBoxType type) { sp_item_invoke_bbox_full(item, bbox, transform, type, clear); } +/** Calls \a item's subclass' bounding box method; clips it by the bbox of clippath, if any; and + * unions the resulting bbox with \a bbox. If \a clear is true, empties \a bbox first. Passes the + * transform and the flags to the actual bbox methods. Note that many of subclasses (e.g. groups, + * clones), in turn, call this function in their bbox methods. */ +void +sp_item_invoke_bbox_full(SPItem const *item, NR::Maybe *bbox, NR::Matrix const &transform, unsigned const flags, unsigned const clear) +{ + g_assert(item != NULL); + g_assert(SP_IS_ITEM(item)); + g_assert(bbox != NULL); + + if (clear) { + *bbox = NR::Nothing(); + } + + // TODO: replace NRRect by NR::Rect, for all SPItemClasses, and for SP_CLIPPATH + + NRRect temp_bbox; + temp_bbox.x0 = temp_bbox.y0 = NR_HUGE; + temp_bbox.x1 = temp_bbox.y1 = -NR_HUGE; + + // call the subclass method + if (((SPItemClass *) G_OBJECT_GET_CLASS(item))->bbox) { + ((SPItemClass *) G_OBJECT_GET_CLASS(item))->bbox(item, &temp_bbox, transform, flags); + } + + // unless this is geometric bbox, crop the bbox by clip path, if any + if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX && item->clip_ref->getObject()) { + NRRect b; + sp_clippath_get_bbox(SP_CLIPPATH(item->clip_ref->getObject()), &b, transform, flags); + nr_rect_d_intersect (&temp_bbox, &temp_bbox, &b); + } + + if (temp_bbox.x0 > temp_bbox.x1 || temp_bbox.y0 > temp_bbox.y1) { + // We'll assume here that when x0 > x1 or y0 > y1, the bbox is "nothing" + // However it has never been explicitely defined this way for NRRects + // (as opposed to NR::Maybe) + *bbox = NR::Nothing(); + return; + } + + if (temp_bbox.x0 == temp_bbox.y0 == NR_HUGE && temp_bbox.x1 == temp_bbox.y1 == -NR_HUGE) { + // The bbox hasn't been touched by the SPItemClass' bbox method + // or it has explicitely been set to be like this (e.g. in sp_shape_bbox) + *bbox = NR::Nothing(); + return; + } + + // Do not use temp_bbox.upgrade() here, because it uses a test that returns NR::Nothing + // for any rectangle with zero area. The geometrical bbox of for example a vertical line + // would therefore be translated into NR::Nothing (see bug https://bugs.launchpad.net/inkscape/+bug/168684) + NR::Maybe temp_bbox_new = NR::Rect(NR::Point(temp_bbox.x0, temp_bbox.y0), NR::Point(temp_bbox.x1, temp_bbox.y1)); + + *bbox = NR::union_bounds(*bbox, temp_bbox_new); +} + +// DEPRECATED to phase out the use of NRRect in favor of NR::Maybe /** Calls \a item's subclass' bounding box method; clips it by the bbox of clippath, if any; and * unions the resulting bbox with \a bbox. If \a clear is true, empties \a bbox first. Passes the * transform and the flags to the actual bbox methods. Note that many of subclasses (e.g. groups, @@ -777,9 +841,9 @@ sp_item_bbox_desktop(SPItem *item, NRRect *bbox, SPItem::BBoxType type) NR::Maybe sp_item_bbox_desktop(SPItem *item, SPItem::BBoxType type) { - NRRect ret; - sp_item_invoke_bbox(item, &ret, sp_item_i2d_affine(item), TRUE, type); - return ret.upgrade(); + NR::Maybe rect = NR::Nothing(); + sp_item_invoke_bbox(item, &rect, sp_item_i2d_affine(item), TRUE, type); + return rect; } static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p) diff --git a/src/sp-item.h b/src/sp-item.h index 9bbaefef1..e87554bfb 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -208,8 +208,10 @@ struct SPItemClass { /* Methods */ -void sp_item_invoke_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); -void sp_item_invoke_bbox_full(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags, unsigned const clear); +void sp_item_invoke_bbox(SPItem const *item, NR::Maybe *bbox, NR::Matrix const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); +void sp_item_invoke_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated)); +void sp_item_invoke_bbox_full(SPItem const *item, NR::Maybe *bbox, NR::Matrix const &transform, unsigned const flags, unsigned const clear); +void sp_item_invoke_bbox_full(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags, unsigned const clear) __attribute__ ((deprecated)); unsigned sp_item_pos_in_parent(SPItem *item); -- 2.30.2