From 6e3576be211b59b7d8a9e7afe3493d961c053b75 Mon Sep 17 00:00:00 2001 From: mental Date: Sat, 10 Mar 2007 20:54:38 +0000 Subject: [PATCH] Merge further bbox work --- src/connector-context.cpp | 14 ++-- src/desktop.cpp | 14 ++-- src/dialogs/export.cpp | 34 +++++----- src/document.cpp | 4 +- src/extension/internal/odf.cpp | 30 +++++---- src/filter-chemistry.cpp | 13 +++- src/gradient-drag.cpp | 18 +++--- src/graphlayout/graphlayout.cpp | 12 ++-- src/object-snapper.cpp | 4 +- src/removeoverlap/removeoverlap.cpp | 75 ++++++++++----------- src/selcue.cpp | 58 ++++++++--------- src/selection-chemistry.cpp | 52 ++++++++------- src/selection.cpp | 8 ++- src/sp-item-transform.cpp | 11 ++-- src/sp-item.cpp | 10 +-- src/sp-item.h | 2 +- src/sp-offset.cpp | 6 +- src/text-context.cpp | 10 ++- src/ui/dialog/align-and-distribute.cpp | 90 +++++++++++++++----------- src/ui/dialog/transformation.cpp | 24 ++++--- src/ui/view/edit-widget.cpp | 10 +-- src/widgets/desktop-widget.cpp | 8 +-- 22 files changed, 273 insertions(+), 234 deletions(-) diff --git a/src/connector-context.cpp b/src/connector-context.cpp index 367917915..89d38bace 100644 --- a/src/connector-context.cpp +++ b/src/connector-context.cpp @@ -1145,12 +1145,14 @@ static void cc_set_active_shape(SPConnectorContext *cc, SPItem *item) } - NR::Rect bbox = sp_item_bbox_desktop(cc->active_shape); - NR::Point center = bbox.midpoint(); - sp_knot_set_position(cc->connpthandle, ¢er, 0); - - sp_knot_show(cc->connpthandle); - + NR::Maybe bbox = sp_item_bbox_desktop(cc->active_shape); + if (bbox) { + NR::Point center = bbox->midpoint(); + sp_knot_set_position(cc->connpthandle, ¢er, 0); + sp_knot_show(cc->connpthandle); + } else { + sp_knot_hide(cc->connpthandle); + } } diff --git a/src/desktop.cpp b/src/desktop.cpp index e1cc23083..471ac2a19 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -430,8 +430,12 @@ bool SPDesktop::isLayer(SPObject *object) const { bool SPDesktop::isWithinViewport (SPItem *item) const { NR::Rect const viewport = get_display_area(); - NR::Rect const bbox = sp_item_bbox_desktop(item); - return viewport.contains(bbox); + NR::Maybe const bbox = sp_item_bbox_desktop(item); + if (bbox) { + return viewport.contains(*bbox); + } else { + return true; + } } /// @@ -881,16 +885,16 @@ SPDesktop::zoom_drawing() SPItem *docitem = SP_ITEM (sp_document_root (doc())); g_return_if_fail (docitem != NULL); - NR::Rect d = sp_item_bbox_desktop(docitem); + NR::Maybe d = sp_item_bbox_desktop(docitem); /* Note that the second condition here indicates that ** there are no items in the drawing. */ - if ( d.dimensions()[NR::X] < 1.0 || d.dimensions()[NR::Y] < 1.0 ) { + if ( !d || d->dimensions()[NR::X] < 1.0 || d->dimensions()[NR::Y] < 1.0 ) { return; } - set_display_area(d, 10); + set_display_area(*d, 10); } /** diff --git a/src/dialogs/export.cpp b/src/dialogs/export.cpp index 8c06f83cd..4dfdbbb5e 100644 --- a/src/dialogs/export.cpp +++ b/src/dialogs/export.cpp @@ -776,14 +776,12 @@ sp_export_selection_modified ( Inkscape::Application *inkscape, if ( SP_ACTIVE_DESKTOP ) { SPDocument *doc; doc = sp_desktop_document (SP_ACTIVE_DESKTOP); - NR::Rect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); - - if (!(bbox.min()[NR::X] > bbox.max()[NR::X] && - bbox.min()[NR::Y] > bbox.max()[NR::Y])) { - sp_export_set_area (base, bbox.min()[NR::X], - bbox.min()[NR::Y], - bbox.max()[NR::X], - bbox.max()[NR::Y]); + NR::Maybe bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); + if (bbox) { + sp_export_set_area (base, bbox->min()[NR::X], + bbox->min()[NR::Y], + bbox->max()[NR::X], + bbox->max()[NR::Y]); } } break; @@ -837,7 +835,7 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base) if ( SP_ACTIVE_DESKTOP ) { SPDocument *doc; - NR::Rect bbox; + NR::Maybe bbox; doc = sp_desktop_document (SP_ACTIVE_DESKTOP); /* Notice how the switch is used to 'fall through' here to get @@ -860,11 +858,9 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base) * This returns wrong values if the document has a viewBox. */ bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); - /* If the drawing is valid, then we'll use it and break otherwise we drop through to the page settings */ - if (!(bbox.min()[NR::X] > bbox.max()[NR::X] && - bbox.min()[NR::Y] > bbox.max()[NR::Y])) { + if (bbox) { // std::cout << "Using selection: DRAWING" << std::endl; key = SELECTION_DRAWING; break; @@ -886,11 +882,11 @@ sp_export_area_toggled (GtkToggleButton *tb, GtkObject *base) prefs_set_string_attribute ( "dialogs.export.exportarea", "value", selection_names[key]); - if (key != SELECTION_CUSTOM) { - sp_export_set_area (base, bbox.min()[NR::X], - bbox.min()[NR::Y], - bbox.max()[NR::X], - bbox.max()[NR::Y]); + if ( key != SELECTION_CUSTOM && bbox ) { + sp_export_set_area (base, bbox->min()[NR::X], + bbox->min()[NR::Y], + bbox->max()[NR::X], + bbox->max()[NR::Y]); } } // end of if ( SP_ACTIVE_DESKTOP ) @@ -1417,10 +1413,10 @@ sp_export_detect_size(GtkObject * base) { case SELECTION_DRAWING: { SPDocument *doc = sp_desktop_document (SP_ACTIVE_DESKTOP); - NR::Rect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); + NR::Maybe bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc))); // std::cout << "Drawing " << bbox2; - if (sp_export_bbox_equal(bbox,current_bbox)) { + if ( bbox && sp_export_bbox_equal(*bbox,current_bbox) ) { key = SELECTION_DRAWING; } break; diff --git a/src/document.cpp b/src/document.cpp index ab6003167..715bc2ec7 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -837,8 +837,8 @@ static GSList *find_items_in_area(GSList *s, SPGroup *group, unsigned int dkey, s = find_items_in_area(s, SP_GROUP(o), dkey, area, test); } else { SPItem *child = SP_ITEM(o); - NR::Rect box = sp_item_bbox_desktop(child); - if (test(area, box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { + NR::Maybe box = sp_item_bbox_desktop(child); + if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { s = g_slist_append(s, child); } } diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index 48e217bd8..8645205f2 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -958,14 +958,16 @@ static NR::Matrix getODFTransform(const SPItem *item) * Get the bounding box of an item, as mapped onto * an ODF document, in cm. */ -static NR::Rect getODFBoundingBox(const SPItem *item) +static NR::Maybe getODFBoundingBox(const SPItem *item) { - NR::Rect bbox = sp_item_bbox_desktop((SPItem *)item); - double doc_height = sp_document_height(SP_ACTIVE_DOCUMENT); - NR::Matrix doc2dt_tf = NR::Matrix(NR::scale(1.0, -1.0)); - doc2dt_tf = doc2dt_tf * NR::Matrix(NR::translate(0, doc_height)); - bbox = bbox * doc2dt_tf; - bbox = bbox * NR::Matrix(NR::scale(pxToCm)); + NR::Maybe bbox = sp_item_bbox_desktop((SPItem *)item); + if (bbox) { + double doc_height = sp_document_height(SP_ACTIVE_DOCUMENT); + NR::Matrix doc2dt_tf = NR::Matrix(NR::scale(1.0, -1.0)); + doc2dt_tf = doc2dt_tf * NR::Matrix(NR::translate(0, doc_height)); + bbox = *bbox * doc2dt_tf; + bbox = *bbox * NR::Matrix(NR::scale(pxToCm)); + } return bbox; } @@ -1866,11 +1868,15 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts, NR::Matrix tf = getODFTransform(item); //### Get ODF bounding box params for item - NR::Rect bbox = getODFBoundingBox(item); - double bbox_x = bbox.min()[NR::X]; - double bbox_y = bbox.min()[NR::Y]; - double bbox_width = bbox.max()[NR::X] - bbox.min()[NR::X]; - double bbox_height = bbox.max()[NR::Y] - bbox.min()[NR::Y]; + NR::Maybe bbox = getODFBoundingBox(item); + if (!bbox) { + return true; + } + + double bbox_x = bbox->min()[NR::X]; + double bbox_y = bbox->min()[NR::Y]; + double bbox_width = bbox->extent(NR::X); + double bbox_height = bbox->extent(NR::Y); double rotate; double xskew; diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp index 1a26b10ce..164a6594a 100644 --- a/src/filter-chemistry.cpp +++ b/src/filter-chemistry.cpp @@ -96,9 +96,16 @@ new_filter_gaussian_blur (SPDocument *document, gdouble radius, double expansion SPFilter * new_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble radius) { - NR::Rect const r = sp_item_bbox_desktop(item); - double width = r.extent(NR::X); - double height = r.extent(NR::Y); + NR::Maybe const r = sp_item_bbox_desktop(item); + + double width; + double height; + if (r) { + width = r->extent(NR::X); + height= r->extent(NR::Y); + } else { + width = height = 0; + } NR::Matrix i2d = sp_item_i2d_affine (item); diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index c02190df8..4a8f7e8ed 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -1443,14 +1443,16 @@ GrDrag::updateLevels () for (GSList const* i = this->selection->itemList(); i != NULL; i = i->next) { SPItem *item = SP_ITEM(i->data); - NR::Rect rect = sp_item_bbox_desktop (item); - // Remember the edges of the bbox and the center axis - hor_levels.push_back(rect.min()[NR::Y]); - hor_levels.push_back(rect.max()[NR::Y]); - hor_levels.push_back(0.5 * (rect.min()[NR::Y] + rect.max()[NR::Y])); - vert_levels.push_back(rect.min()[NR::X]); - vert_levels.push_back(rect.max()[NR::X]); - vert_levels.push_back(0.5 * (rect.min()[NR::X] + rect.max()[NR::X])); + NR::Maybe rect = sp_item_bbox_desktop (item); + if (rect) { + // Remember the edges of the bbox and the center axis + hor_levels.push_back(rect->min()[NR::Y]); + hor_levels.push_back(rect->max()[NR::Y]); + hor_levels.push_back(0.5 * (rect->min()[NR::Y] + rect->max()[NR::Y])); + vert_levels.push_back(rect->min()[NR::X]); + vert_levels.push_back(rect->max()[NR::X]); + vert_levels.push_back(0.5 * (rect->min()[NR::X] + rect->max()[NR::X])); + } } } diff --git a/src/graphlayout/graphlayout.cpp b/src/graphlayout/graphlayout.cpp index 30085a00f..780532718 100644 --- a/src/graphlayout/graphlayout.cpp +++ b/src/graphlayout/graphlayout.cpp @@ -93,9 +93,10 @@ void graphlayout(GSList const *const items) { ++i) { SPItem *u=*i; - NR::Rect const item_box(sp_item_bbox_desktop(u)); - NR::Point ll(item_box.min()); - NR::Point ur(item_box.max()); + NR::Maybe const item_box(sp_item_bbox_desktop(u)); + g_assert(item_box); + NR::Point ll(item_box->min()); + NR::Point ur(item_box->max()); nodelookup[u->id]=rs.size(); rs.push_back(new Rectangle(ll[0]-spacing,ur[0]+spacing, ll[1]-spacing,ur[1]+spacing)); @@ -188,8 +189,9 @@ void graphlayout(GSList const *const items) { SPItem *u=*it; if(!isConnector(u)) { Rectangle* r=rs[nodelookup[u->id]]; - NR::Rect const item_box(sp_item_bbox_desktop(u)); - NR::Point const curr(item_box.midpoint()); + NR::Maybe item_box(sp_item_bbox_desktop(u)); + g_assert(item_box); + NR::Point const curr(item_box->midpoint()); NR::Point const dest(r->getCentreX(),r->getCentreY()); sp_item_move_rel(u, NR::translate(dest - curr)); } diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 684700b3b..5492fc439 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -53,8 +53,8 @@ void Inkscape::ObjectSnapper::_findCandidates(std::list& c, if (SP_IS_GROUP(o)) { _findCandidates(c, o, it, p); } else { - NR::Rect const b = NR::expand(sp_item_bbox_desktop(SP_ITEM(o)), -getDistance()); - if (b.contains(p)) { + NR::Maybe b = sp_item_bbox_desktop(SP_ITEM(o)); + if ( b && NR::expand(*b, -getDistance()).contains(p) ) { c.push_back(SP_ITEM(o)); } } diff --git a/src/removeoverlap/removeoverlap.cpp b/src/removeoverlap/removeoverlap.cpp index c640fb407..395d4fe0e 100644 --- a/src/removeoverlap/removeoverlap.cpp +++ b/src/removeoverlap/removeoverlap.cpp @@ -14,30 +14,33 @@ #include "sp-item-transform.h" #include "libvpsc/generate-constraints.h" #include "libvpsc/remove_rectangle_overlap.h" +#include using vpsc::Rectangle; +namespace { + struct Record { + SPItem *item; + NR::Point midpoint; + Rectangle *vspc_rect; + + Record() {} + Record(SPItem *i, NR::Point m, Rectangle *r) + : item(i), midpoint(m), vspc_rect(r) {} + }; +} + /** * Takes a list of inkscape items and moves them as little as possible * such that rectangular bounding boxes are separated by at least xGap * horizontally and yGap vertically */ void removeoverlap(GSList const *const items, double const xGap, double const yGap) { - if(!items) { - return; - } - using Inkscape::Util::GSListConstIterator; std::list selected; selected.insert >(selected.end(), items, NULL); - if (selected.empty()) return; - int n=selected.size(); - - //Check 2 or more selected objects - if (n < 2) return; - - Rectangle **rs = new Rectangle*[n]; - int i=0; + std::vector records; + std::vector rs; NR::Point const gap(xGap, yGap); for (std::list::iterator it(selected.begin()); @@ -45,38 +48,26 @@ void removeoverlap(GSList const *const items, double const xGap, double const yG ++it) { using NR::X; using NR::Y; - NR::Rect const item_box(sp_item_bbox_desktop(*it)); - - /* The current algorithm requires widths & heights to be strictly positive. */ - NR::Point min(item_box.min()); - NR::Point max(item_box.max()); - for (unsigned d = 0; d < 2; ++d) { - double const minsize = 1; // arbitrary positive number - if (max[d] - min[d] + gap[d] < minsize) { - double const mid = .5 * (min[d] + max[d]); - min[d] = mid - .5*minsize; - max[d] = mid + .5*minsize; - } else { - min[d] -= .5*gap[d]; - max[d] += .5*gap[d]; - } + NR::Maybe item_box(sp_item_bbox_desktop(*it)); + if (item_box) { + NR::Point min(item_box->min() - .5*gap); + NR::Point max(item_box->max() + .5*gap); + Rectangle *vspc_rect = new Rectangle(min[X], max[X], min[Y], max[Y]); + records.push_back(Record(*it, item_box->midpoint(), vspc_rect)); + rs.push_back(vspc_rect); } - rs[i++] = new Rectangle(min[X], max[X], - min[Y], max[Y]); } - removeRectangleOverlap(n, rs, 0.0, 0.0); - i=0; - for (std::list::iterator it(selected.begin()); - it != selected.end(); - ++it) + if (!rs.empty()) { + removeRectangleOverlap(rs.size(), &rs[0], 0.0, 0.0); + } + for ( std::vector::iterator it = records.begin(); + it != records.end(); + ++it ) { - NR::Rect const item_box(sp_item_bbox_desktop(*it)); - Rectangle *r = rs[i++]; - NR::Point const curr(item_box.midpoint()); - NR::Point const dest(r->getCentreX(), - r->getCentreY()); - sp_item_move_rel(*it, NR::translate(dest - curr)); - delete r; + NR::Point const curr = it->midpoint; + NR::Point const dest(it->vspc_rect->getCentreX(), + it->vspc_rect->getCentreY()); + sp_item_move_rel(it->item, NR::translate(dest - curr)); + delete it->vspc_rect; } - delete [] rs; } diff --git a/src/selcue.cpp b/src/selcue.cpp index 6d3656592..a073f3493 100644 --- a/src/selcue.cpp +++ b/src/selcue.cpp @@ -78,38 +78,38 @@ void Inkscape::SelCue::_updateItemBboxes() for (GSList const *l = _selection->itemList(); l != NULL; l = l->next) { SPItem *item = (SPItem *) l->data; - NR::Rect const b = sp_item_bbox_desktop(item); + NR::Maybe const b = sp_item_bbox_desktop(item); SPCanvasItem* box = NULL; - if (mode == MARK) { - box = sp_canvas_item_new(sp_desktop_controls(_desktop), - SP_TYPE_CTRL, - "mode", SP_CTRL_MODE_XOR, - "shape", SP_CTRL_SHAPE_DIAMOND, - "size", 5.0, - "filled", TRUE, - "fill_color", 0x000000ff, - "stroked", FALSE, - "stroke_color", 0x000000ff, - NULL); - sp_canvas_item_show(box); - SP_CTRL(box)->moveto(NR::Point(b.min()[NR::X], b.max()[NR::Y])); - - sp_canvas_item_move_to_z(box, 0); // just low enough to not get in the way of other draggable knots - - } else if (mode == BBOX) { - box = sp_canvas_item_new( - sp_desktop_controls(_desktop), - SP_TYPE_CTRLRECT, - NULL - ); - - SP_CTRLRECT(box)->setRectangle(b); - SP_CTRLRECT(box)->setColor(0x000000a0, 0, 0); - SP_CTRLRECT(box)->setDashed(true); - - sp_canvas_item_move_to_z(box, 0); + if (b) { + if (mode == MARK) { + box = sp_canvas_item_new(sp_desktop_controls(_desktop), + SP_TYPE_CTRL, + "mode", SP_CTRL_MODE_XOR, + "shape", SP_CTRL_SHAPE_DIAMOND, + "size", 5.0, + "filled", TRUE, + "fill_color", 0x000000ff, + "stroked", FALSE, + "stroke_color", 0x000000ff, + NULL); + sp_canvas_item_show(box); + SP_CTRL(box)->moveto(NR::Point(b->min()[NR::X], b->max()[NR::Y])); + + sp_canvas_item_move_to_z(box, 0); // just low enough to not get in the way of other draggable knots + + } else if (mode == BBOX) { + box = sp_canvas_item_new(sp_desktop_controls(_desktop), + SP_TYPE_CTRLRECT, + NULL); + + SP_CTRLRECT(box)->setRectangle(*b); + SP_CTRLRECT(box)->setColor(0x000000a0, 0, 0); + SP_CTRLRECT(box)->setDashed(true); + + sp_canvas_item_move_to_z(box, 0); + } } if (box) { diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index a65c9b290..171928865 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -654,13 +654,16 @@ sp_selection_raise() // for each selected object, find the next sibling for (SPObject *newref = child->next; newref; newref = newref->next) { // if the sibling is an item AND overlaps our selection, - if (SP_IS_ITEM(newref) && selected->intersects(sp_item_bbox_desktop(SP_ITEM(newref)))) { - // AND if it's not one of our selected objects, - if (!g_slist_find((GSList *) items, newref)) { - // move the selected object after that sibling - grepr->changeOrder(SP_OBJECT_REPR(child), SP_OBJECT_REPR(newref)); + if (SP_IS_ITEM(newref)) { + NR::Maybe newref_bbox = sp_item_bbox_desktop(SP_ITEM(newref)); + if ( newref_bbox && selected->intersects(*newref_bbox) ) { + // AND if it's not one of our selected objects, + if (!g_slist_find((GSList *) items, newref)) { + // move the selected object after that sibling + grepr->changeOrder(SP_OBJECT_REPR(child), SP_OBJECT_REPR(newref)); + } + break; } - break; } } rev = g_slist_remove(rev, child); @@ -747,17 +750,20 @@ sp_selection_lower() // for each selected object, find the prev sibling for (SPObject *newref = prev_sibling(child); newref; newref = prev_sibling(newref)) { // if the sibling is an item AND overlaps our selection, - if (SP_IS_ITEM(newref) && selected->intersects(sp_item_bbox_desktop(SP_ITEM(newref)))) { - // AND if it's not one of our selected objects, - if (!g_slist_find((GSList *) items, newref)) { - // move the selected object before that sibling - SPObject *put_after = prev_sibling(newref); - if (put_after) - grepr->changeOrder(SP_OBJECT_REPR(child), SP_OBJECT_REPR(put_after)); - else - SP_OBJECT_REPR(child)->setPosition(0); + if (SP_IS_ITEM(newref)) { + NR::Maybe ref_bbox = sp_item_bbox_desktop(SP_ITEM(newref)); + if ( ref_bbox && selected->intersects(*ref_bbox) ) { + // AND if it's not one of our selected objects, + if (!g_slist_find((GSList *) items, newref)) { + // move the selected object before that sibling + SPObject *put_after = prev_sibling(newref); + if (put_after) + grepr->changeOrder(SP_OBJECT_REPR(child), SP_OBJECT_REPR(put_after)); + else + SP_OBJECT_REPR(child)->setPosition(0); + } + break; } - break; } } rev = g_slist_remove(rev, child); @@ -1223,13 +1229,13 @@ void sp_selection_paste_size_separately (bool apply_x, bool apply_y) for (GSList const *l = selection->itemList(); l != NULL; l = l->next) { SPItem *item = SP_ITEM(l->data); - NR::Rect current = sp_item_bbox_desktop(item); - if (current.extent(NR::X) < 1e-6 || current.extent(NR::Y) < 1e-6) { + NR::Maybe current = sp_item_bbox_desktop(item); + if ( !current || current->extent(NR::X) < 1e-6 || current->extent(NR::Y) < 1e-6 ) { continue; } - double scale_x = size_clipboard.extent(NR::X) / current.extent(NR::X); - double scale_y = size_clipboard.extent(NR::Y) / current.extent(NR::Y); + double scale_x = size_clipboard.extent(NR::X) / current->extent(NR::X); + double scale_y = size_clipboard.extent(NR::Y) / current->extent(NR::Y); sp_item_scale_rel (item, NR::scale( @@ -1985,10 +1991,10 @@ SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root, void scroll_to_show_item(SPDesktop *desktop, SPItem *item) { NR::Rect dbox = desktop->get_display_area(); - NR::Rect sbox = sp_item_bbox_desktop(item); + NR::Maybe sbox = sp_item_bbox_desktop(item); - if (dbox.contains(sbox) == false) { - NR::Point const s_dt = sbox.midpoint(); + if ( sbox && dbox.contains(*sbox) == false ) { + NR::Point const s_dt = sbox->midpoint(); NR::Point const s_w = desktop->d2w(s_dt); NR::Point const d_dt = dbox.midpoint(); NR::Point const d_w = desktop->d2w(d_dt); diff --git a/src/selection.cpp b/src/selection.cpp index 49934cfd3..d39086e8c 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -421,9 +421,11 @@ std::vector Selection::getBBoxPoints() const { GSList const *items = const_cast(this)->itemList(); std::vector p; for (GSList const *iter = items; iter != NULL; iter = iter->next) { - NR::Rect b = sp_item_bbox_desktop(SP_ITEM(iter->data)); - p.push_back(b.min()); - p.push_back(b.max()); + NR::Maybe b = sp_item_bbox_desktop(SP_ITEM(iter->data)); + if (b) { + p.push_back(b->min()); + p.push_back(b->max()); + } } return p; diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp index d62211245..105a91b4c 100644 --- a/src/sp-item-transform.cpp +++ b/src/sp-item-transform.cpp @@ -46,11 +46,12 @@ sp_item_rotate_rel(SPItem *item, NR::rotate const &rotation) void sp_item_scale_rel (SPItem *item, NR::scale const &scale) { - NR::translate const s(sp_item_bbox_desktop(item).midpoint()); // use getCenter? - - sp_item_set_i2d_affine(item, - sp_item_i2d_affine(item) * inverse(s) * scale * s); - sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform); + NR::Maybe bbox = sp_item_bbox_desktop(item); + if (bbox) { + NR::translate const s(bbox->midpoint()); // use getCenter? + sp_item_set_i2d_affine(item, sp_item_i2d_affine(item) * inverse(s) * scale * s); + sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform); + } } void diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 0f6ea3839..eb3abce16 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -798,17 +798,11 @@ sp_item_bbox_desktop(SPItem *item, NRRect *bbox) sp_item_invoke_bbox(item, bbox, sp_item_i2d_affine(item), TRUE); } -NR::Rect sp_item_bbox_desktop(SPItem *item) +NR::Maybe sp_item_bbox_desktop(SPItem *item) { NRRect ret; sp_item_invoke_bbox(item, &ret, sp_item_i2d_affine(item), TRUE); - NR::Maybe result = ret.upgrade(); - if (result) { - return *result; - } else { - // FIXME - return NR::Rect(NR::Point(0, 0), NR::Point(0, 0)); - } + return ret.upgrade(); } static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p) diff --git a/src/sp-item.h b/src/sp-item.h index 3b5e64b11..eb7043096 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -240,7 +240,7 @@ gint sp_item_event (SPItem *item, SPEvent *event); NRArenaItem *sp_item_get_arenaitem(SPItem *item, unsigned int key); void sp_item_bbox_desktop(SPItem *item, NRRect *bbox) __attribute__ ((deprecated)); -NR::Rect sp_item_bbox_desktop(SPItem *item); +NR::Maybe sp_item_bbox_desktop(SPItem *item); NR::Matrix i2anc_affine(SPObject const *item, SPObject const *ancestor); NR::Matrix i2i_affine(SPObject const *src, SPObject const *dest); diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp index 74382b768..e682f394b 100644 --- a/src/sp-offset.cpp +++ b/src/sp-offset.cpp @@ -584,9 +584,9 @@ sp_offset_set_shape(SPShape *shape) theRes->ConvertToForme (orig, 1, originaux); SPItem *item = shape; - NR::Rect bbox = sp_item_bbox_desktop (item); - if (!bbox.isEmpty()) { - gdouble size = L2(bbox.dimensions()); + NR::Maybe bbox = sp_item_bbox_desktop (item); + if ( bbox && !bbox->isEmpty() ) { + gdouble size = L2(bbox->dimensions()); gdouble const exp = NR::expansion(item->transform); if (exp != 0) size /= exp; diff --git a/src/text-context.cpp b/src/text-context.cpp index b65bcf19f..6a527e544 100644 --- a/src/text-context.cpp +++ b/src/text-context.cpp @@ -436,7 +436,10 @@ sp_text_context_item_handler(SPEventContext *ec, SPItem *item, GdkEvent *event) item_ungrouped = desktop->item_at_point(NR::Point(event->button.x, event->button.y), TRUE); if (SP_IS_TEXT(item_ungrouped) || SP_IS_FLOWTEXT(item_ungrouped)) { sp_canvas_item_show(tc->indicator); - SP_CTRLRECT(tc->indicator)->setRectangle(sp_item_bbox_desktop(item_ungrouped)); + NR::Maybe ibbox = sp_item_bbox_desktop(item_ungrouped); + if (ibbox) { + SP_CTRLRECT(tc->indicator)->setRectangle(*ibbox); + } ec->cursor_shape = cursor_text_insert_xpm; ec->hot_x = 7; @@ -1458,7 +1461,10 @@ sp_text_context_update_cursor(SPTextContext *tc, bool scroll_to_see) SPItem *frame = SP_FLOWTEXT(tc->text)->get_frame (NULL); // first frame only if (frame) { sp_canvas_item_show(tc->frame); - SP_CTRLRECT(tc->frame)->setRectangle(sp_item_bbox_desktop(frame)); + NR::Maybe frame_bbox = sp_item_bbox_desktop(frame); + if (frame_bbox) { + SP_CTRLRECT(tc->frame)->setRectangle(*frame_bbox); + } } SP_EVENT_CONTEXT(tc)->_message_context->set(Inkscape::NORMAL_MESSAGE, _("Type flowed text; Enter to start new paragraph.")); } else { diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index b8f840520..c1f4a10a1 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -153,9 +153,13 @@ private : SPItem * thing = *master; selected.erase(master); //Compute the anchor point - NR::Rect b = sp_item_bbox_desktop (thing); - mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X], - a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]); + NR::Maybe b = sp_item_bbox_desktop (thing); + if (b) { + mp = NR::Point(a.mx0 * b->min()[NR::X] + a.mx1 * b->max()[NR::X], + a.my0 * b->min()[NR::Y] + a.my1 * b->max()[NR::Y]); + } else { + return; + } break; } @@ -166,10 +170,14 @@ private : case AlignAndDistribute::DRAWING: { - NR::Rect b = sp_item_bbox_desktop + NR::Maybe b = sp_item_bbox_desktop ( (SPItem *) sp_document_root (sp_desktop_document (desktop)) ); - mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X], - a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]); + if (b) { + mp = NR::Point(a.mx0 * b->min()[NR::X] + a.mx1 * b->max()[NR::X], + a.my0 * b->min()[NR::Y] + a.my1 * b->max()[NR::Y]); + } else { + return; + } break; } @@ -202,13 +210,15 @@ private : it++) { sp_document_ensure_up_to_date(sp_desktop_document (desktop)); - NR::Rect b = sp_item_bbox_desktop (*it); - NR::Point const sp(a.sx0 * b.min()[NR::X] + a.sx1 * b.max()[NR::X], - a.sy0 * b.min()[NR::Y] + a.sy1 * b.max()[NR::Y]); - NR::Point const mp_rel( mp - sp ); - if (LInfty(mp_rel) > 1e-9) { - sp_item_move_rel(*it, NR::translate(mp_rel)); - changed = true; + NR::Maybe b = sp_item_bbox_desktop (*it); + if (b) { + NR::Point const sp(a.sx0 * b->min()[NR::X] + a.sx1 * b->max()[NR::X], + a.sy0 * b->min()[NR::Y] + a.sy1 * b->max()[NR::Y]); + NR::Point const mp_rel( mp - sp ); + if (LInfty(mp_rel) > 1e-9) { + sp_item_move_rel(*it, NR::translate(mp_rel)); + changed = true; + } } } @@ -246,9 +256,9 @@ struct BBoxSort SPItem *item; float anchor; NR::Rect bbox; - BBoxSort(SPItem *pItem, NR::Dim2 orientation, double kBegin, double kEnd) : + BBoxSort(SPItem *pItem, NR::Rect bounds, NR::Dim2 orientation, double kBegin, double kEnd) : item(pItem), - bbox (sp_item_bbox_desktop (pItem)) + bbox (bounds) { anchor = kBegin * bbox.min()[orientation] + kEnd * bbox.max()[orientation]; } @@ -308,8 +318,10 @@ private : it != selected.end(); ++it) { - BBoxSort b (*it, _orientation, _kBegin, _kEnd); - sorted.push_back(b); + NR::Maybe bbox = sp_item_bbox_desktop(*it); + if (bbox) { + sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd)); + } } //sort bbox by anchors std::sort(sorted.begin(), sorted.end()); @@ -595,15 +607,17 @@ private : ++it) { sp_document_ensure_up_to_date(sp_desktop_document (desktop)); - NR::Rect item_box = sp_item_bbox_desktop (*it); - // find new center, staying within bbox - double x = _dialog.randomize_bbox.min()[NR::X] + item_box.extent(NR::X)/2 + - g_random_double_range (0, _dialog.randomize_bbox.extent(NR::X) - item_box.extent(NR::X)); - double y = _dialog.randomize_bbox.min()[NR::Y] + item_box.extent(NR::Y)/2 + - g_random_double_range (0, _dialog.randomize_bbox.extent(NR::Y) - item_box.extent(NR::Y)); - // displacement is the new center minus old: - NR::Point t = NR::Point (x, y) - 0.5*(item_box.max() + item_box.min()); - sp_item_move_rel(*it, NR::translate(t)); + NR::Maybe item_box = sp_item_bbox_desktop (*it); + if (item_box) { + // find new center, staying within bbox + double x = _dialog.randomize_bbox.min()[NR::X] + item_box->extent(NR::X)/2 + + g_random_double_range (0, _dialog.randomize_bbox.extent(NR::X) - item_box->extent(NR::X)); + double y = _dialog.randomize_bbox.min()[NR::Y] + item_box->extent(NR::Y)/2 + + g_random_double_range (0, _dialog.randomize_bbox.extent(NR::Y) - item_box->extent(NR::Y)); + // displacement is the new center minus old: + NR::Point t = NR::Point (x, y) - 0.5*(item_box->max() + item_box->min()); + sp_item_move_rel(*it, NR::translate(t)); + } } // restore compensation setting @@ -1054,11 +1068,13 @@ std::list::iterator AlignAndDistribute::find_master( std::list::iterator it = list.begin(); it != list.end(); it++) { - NR::Rect b = sp_item_bbox_desktop (*it); - gdouble dim = b.extent(horizontal ? NR::X : NR::Y); - if (dim > max) { - max = dim; - master = it; + NR::Maybe b = sp_item_bbox_desktop (*it); + if (b) { + gdouble dim = b->extent(horizontal ? NR::X : NR::Y); + if (dim > max) { + max = dim; + master = it; + } } } return master; @@ -1069,11 +1085,13 @@ std::list::iterator AlignAndDistribute::find_master( std::list::iterator it = list.begin(); it != list.end(); it++) { - NR::Rect b = sp_item_bbox_desktop (*it); - gdouble dim = b.extent(horizontal ? NR::X : NR::Y); - if (dim < max) { - max = dim; - master = it; + NR::Maybe b = sp_item_bbox_desktop (*it); + if (b) { + gdouble dim = b->extent(horizontal ? NR::X : NR::Y); + if (dim < max) { + max = dim; + master = it; + } } } return master; diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index 99ac56cbd..90cac7425 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -604,15 +604,17 @@ Transformation::applyPageScale(Inkscape::Selection *selection) if (prefs_get_int_attribute_limited ("dialogs.transformation", "applyseparately", 0, 0, 1) == 1) { for (GSList const *l = selection->itemList(); l != NULL; l = l->next) { SPItem *item = SP_ITEM(l->data); - NR::Rect bbox (sp_item_bbox_desktop(item)); NR::scale scale (0,0); // the values are increments! if (_units_scale.isAbsolute()) { - double new_width = bbox.extent(NR::X) + scaleX; - if (new_width < 1e-6) new_width = 1e-6; // not 0, as this would result in a nasty no-bbox object - double new_height = bbox.extent(NR::Y) + scaleY; - if (new_height < 1e-6) new_height = 1e-6; - scale = NR::scale(new_width / bbox.extent(NR::X), new_height / bbox.extent(NR::Y)); + NR::Maybe bbox(sp_item_bbox_desktop(item)); + if (bbox) { + double new_width = bbox->extent(NR::X) + scaleX; + if (new_width < 1e-6) new_width = 1e-6; // not 0, as this would result in a nasty no-bbox object + double new_height = bbox->extent(NR::Y) + scaleY; + if (new_height < 1e-6) new_height = 1e-6; + scale = NR::scale(new_width / bbox->extent(NR::X), new_height / bbox->extent(NR::Y)); + } } else { double new_width = 100 + scaleX; if (new_width < 1e-6) new_width = 1e-6; @@ -686,10 +688,12 @@ Transformation::applyPageSkew(Inkscape::Selection *selection) } else { // absolute displacement double skewX = _scalar_skew_horizontal.getValue("px"); double skewY = _scalar_skew_vertical.getValue("px"); - NR::Rect bbox(sp_item_bbox_desktop(item)); - double width = bbox.dimensions()[NR::X]; - double height = bbox.dimensions()[NR::Y]; - sp_item_skew_rel (item, skewX/height, skewY/width); + NR::Maybe bbox(sp_item_bbox_desktop(item)); + if (bbox) { + double width = bbox->dimensions()[NR::X]; + double height = bbox->dimensions()[NR::Y]; + sp_item_skew_rel (item, skewX/height, skewY/width); + } } } } else { // transform whole selection diff --git a/src/ui/view/edit-widget.cpp b/src/ui/view/edit-widget.cpp index f386aefcc..99fd2fb80 100644 --- a/src/ui/view/edit-widget.cpp +++ b/src/ui/view/edit-widget.cpp @@ -1380,11 +1380,11 @@ EditWidget::updateScrollbars (double scale) /* The desktop region we always show unconditionally */ SPDocument *doc = _desktop->doc(); - NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc))); - NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)), - MIN(r.min()[NR::Y], -sp_document_height(doc))), - NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)), - MAX(r.max()[NR::Y], 2 * sp_document_height(doc)))); + NR::Rect darea = NR::Rect(NR::Point(-sp_document_width(doc), + -sp_document_height(doc)), + NR::Point(2 * sp_document_width(doc), + 2 * sp_document_height(doc))); + darea = NR::union_bounds(darea, sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)))); /* Canvas region we always show unconditionally */ NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64, diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 76313f771..237e4c8e9 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -1274,11 +1274,9 @@ sp_desktop_widget_update_scrollbars (SPDesktopWidget *dtw, double scale) /* The desktop region we always show unconditionally */ SPDocument *doc = dtw->desktop->doc(); - NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc))); - NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)), - MIN(r.min()[NR::Y], -sp_document_height(doc))), - NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)), - MAX(r.max()[NR::Y], 2 * sp_document_height(doc)))); + NR::Rect darea(NR::Point(-sp_document_width(doc), -sp_document_height(doc)), + NR::Point(2 * sp_document_width(doc), 2 * sp_document_height(doc))); + darea = NR::union_bounds(darea, sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)))); /* Canvas region we always show unconditionally */ NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64, -- 2.30.2