Code

Merge further bbox work
authormental <mental@users.sourceforge.net>
Sat, 10 Mar 2007 20:54:38 +0000 (20:54 +0000)
committermental <mental@users.sourceforge.net>
Sat, 10 Mar 2007 20:54:38 +0000 (20:54 +0000)
22 files changed:
src/connector-context.cpp
src/desktop.cpp
src/dialogs/export.cpp
src/document.cpp
src/extension/internal/odf.cpp
src/filter-chemistry.cpp
src/gradient-drag.cpp
src/graphlayout/graphlayout.cpp
src/object-snapper.cpp
src/removeoverlap/removeoverlap.cpp
src/selcue.cpp
src/selection-chemistry.cpp
src/selection.cpp
src/sp-item-transform.cpp
src/sp-item.cpp
src/sp-item.h
src/sp-offset.cpp
src/text-context.cpp
src/ui/dialog/align-and-distribute.cpp
src/ui/dialog/transformation.cpp
src/ui/view/edit-widget.cpp
src/widgets/desktop-widget.cpp

index 367917915a6565a40e59d73e6270115edb1fb21b..89d38bace98a69eba99ef7defd7291d058819917 100644 (file)
@@ -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, &center, 0);
-
-    sp_knot_show(cc->connpthandle);
-
+    NR::Maybe<NR::Rect> bbox = sp_item_bbox_desktop(cc->active_shape);
+    if (bbox) {
+        NR::Point center = bbox->midpoint();
+        sp_knot_set_position(cc->connpthandle, &center, 0);
+        sp_knot_show(cc->connpthandle);
+    } else {
+        sp_knot_hide(cc->connpthandle);
+    }
 }
 
 
index e1cc23083eb72ddeb7ded49ec179719b006783a5..471ac2a1949474452e51b546fd7cf973f62d136c 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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);
 }
 
 /**
index 8c06f83cd1eba496f551a84ca4c83094cf2e786e..4dfdbbb5e3e11b34c93d26186889ed11c21e383a 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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<NR::Rect> 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;
index ab60031675c67eee00ccdab75b2706ca21e7b153..715bc2ec7ab1bc9382e3bfa30e6f4c0ac5c6a831 100644 (file)
@@ -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<NR::Rect> box = sp_item_bbox_desktop(child);
+            if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) {
                 s = g_slist_append(s, child);
             }
         }
index 48e217bd83cf7d56f3ea0fd45720eecd97146f4d..8645205f2e388fe50df1425eeeeb980a33e6d4a5 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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<NR::Rect> 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;
index 1a26b10ce7e156aebdbe8dc23088d6117a8970d2..164a6594a71fe16c483f979921c2cd6be995603a 100644 (file)
@@ -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<NR::Rect> 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);
 
index c02190df8ea12c41cba8a14820e16e07922d96b1..4a8f7e8edc97f234bd9e93a0e37b75db9eee31f7 100644 (file)
@@ -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<NR::Rect> 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]));
+        }
     }
 }
 
index 30085a00f90f6774eca248f9e8723c7440b1a6bc..78053271853acd99d045d64ddc237ba2690299a9 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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));
                }
index 684700b3b7f9ad873789bb8eb650ee103b5ecddf..5492fc439cac8465a1e07db5704d32147097c4c9 100644 (file)
@@ -53,8 +53,8 @@ void Inkscape::ObjectSnapper::_findCandidates(std::list<SPItem*>& 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<NR::Rect> b = sp_item_bbox_desktop(SP_ITEM(o));
+                    if ( b && NR::expand(*b, -getDistance()).contains(p) ) {
                         c.push_back(SP_ITEM(o));
                     }
                 }
index c640fb407ad308185562dcd1074715a6e55b60b7..395d4fe0e78ffb4c5a87f4933749b2a27ed1c1b0 100644 (file)
 #include "sp-item-transform.h"
 #include "libvpsc/generate-constraints.h"
 #include "libvpsc/remove_rectangle_overlap.h"
+#include <utility>
 
 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<SPItem *> selected;
        selected.insert<GSListConstIterator<SPItem *> >(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<Record> records;
+       std::vector<Rectangle *> rs;
 
        NR::Point const gap(xGap, yGap);
        for (std::list<SPItem *>::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<NR::Rect> 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<SPItem *>::iterator it(selected.begin());
-               it != selected.end();
-               ++it)
+       if (!rs.empty()) {
+               removeRectangleOverlap(rs.size(), &rs[0], 0.0, 0.0);
+       }
+       for ( std::vector<Record>::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;
 }
index 6d365659206749a1101673d513b85ae1bad81f81..a073f349327aa85b0e6f7a8ed42ce18b453abc0b 100644 (file)
@@ -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<NR::Rect> 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) {
index a65c9b2900bfc2c54ab91a17979034b30c0a5276..171928865403b2ff9b000ccfc4888942571308d6 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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<NR::Rect> 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<NR::Rect> 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);
index 49934cfd39ccb16591d2bcf00d1eae3ca84a542f..d39086e8c60e56174a42d6f697026307de4d7109 100644 (file)
@@ -421,9 +421,11 @@ std::vector<NR::Point> Selection::getBBoxPoints() const {
     GSList const *items = const_cast<Selection *>(this)->itemList();
     std::vector<NR::Point> 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<NR::Rect> b = sp_item_bbox_desktop(SP_ITEM(iter->data));
+        if (b) {
+            p.push_back(b->min());
+            p.push_back(b->max());
+        }
     }
 
     return p;
index d622112453a9b222ea4b610dd9ef382407d94cb5..105a91b4c607798fafff793b90a6b871a000735c 100644 (file)
@@ -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<NR::Rect> 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
index 0f6ea38397b15621eca6b8e75c6a696e43a3e2fb..eb3abce16b618d40e8d098b401f5343ffbc5b901 100644 (file)
@@ -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<NR::Rect> sp_item_bbox_desktop(SPItem *item)
 {
     NRRect ret;
     sp_item_invoke_bbox(item, &ret, sp_item_i2d_affine(item), TRUE);
-    NR::Maybe<NR::Rect> 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)
index 3b5e64b113352c4b71442290e0fd04cc60d62084..eb7043096d45ba1d2ba400252505db27b06acd63 100644 (file)
@@ -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<NR::Rect> 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);
index 74382b7681ba9f1409b63489fbb9c7f94976c005..e682f394bb74c41029ce91c6aec088aa84c729ba 100644 (file)
@@ -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<NR::Rect> 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;
index b65bcf19fa55a3cba768f4a977a5e83e532a536c..6a527e544196b3a74cf6fa8ff6447ca927eee290 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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; <b>Enter</b> to start new paragraph."));
         } else {
index b8f840520ee880420d960f9ee65ba14bd4107bff..c1f4a10a11620a9124eeeef7eb4866abc8441906 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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<NR::Rect> 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<NR::Rect> 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<NR::Rect> 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<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem
     {
         gdouble max = -1e18;
         for (std::list<SPItem *>::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<NR::Rect> 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<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem
     {
         gdouble max = 1e18;
         for (std::list<SPItem *>::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<NR::Rect> 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;
index 99ac56cbd54d76fcd27122983a46db9936f1db03..90cac7425c8e66324b7599a9cf0358a57e431f51 100644 (file)
@@ -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<NR::Rect> 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<NR::Rect> 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
index f386aefcce57e575905f56b19e3676b46537c147..99fd2fb8020bd416997165be65ed62e9295e11de 100644 (file)
@@ -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,
index 76313f7719240e41900072baf39b1bd01e313e35..237e4c8e9f40c5e8519049104157558ecb150e41 100644 (file)
@@ -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,