Code

Switch selection bounds and center to use NR::Maybe, addressing most of the
authormental <mental@users.sourceforge.net>
Sun, 11 Mar 2007 19:57:07 +0000 (19:57 +0000)
committermental <mental@users.sourceforge.net>
Sun, 11 Mar 2007 19:57:07 +0000 (19:57 +0000)
recent bbox regressions.

17 files changed:
src/desktop.cpp
src/dialogs/export.cpp
src/dialogs/object-properties.cpp
src/dialogs/tiledialog.cpp
src/extension/internal/grid.cpp
src/file.cpp
src/interface.cpp
src/selection-chemistry.cpp
src/selection.cpp
src/selection.h
src/seltrans.cpp
src/seltrans.h
src/splivarot.cpp
src/ui/dialog/align-and-distribute.cpp
src/ui/dialog/transformation.cpp
src/verbs.cpp
src/widgets/select-toolbar.cpp

index d159fbc78d236df8f3996087c59092ea28bfc74f..5fa251842cdb926d16176aac62ce0a23f0c4a76c 100644 (file)
@@ -855,13 +855,13 @@ SPDesktop::zoom_page_width()
 void
 SPDesktop::zoom_selection()
 {
-    NR::Rect const d = selection->bounds();
+    NR::Maybe<NR::Rect> const d = selection->bounds();
 
-    if (d.dimensions()[NR::X] < 0.1 || d.dimensions()[NR::Y] < 0.1) {
+    if ( !d || d->dimensions()[NR::X] < 0.1 || d->dimensions()[NR::Y] < 0.1) {
         return;
     }
 
-    set_display_area(d, 10);
+    set_display_area(*d, 10);
 }
 
 /**
index 4dfdbbb5e3e11b34c93d26186889ed11c21e383a..c6d7e89d82a5d7a75e6ba099d749a0c0c1ee5db3 100644 (file)
@@ -1402,10 +1402,10 @@ sp_export_detect_size(GtkObject * base) {
         switch (this_test[i]) {
             case SELECTION_SELECTION:
                 if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) {
-                    NR::Rect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds();
+                    NR::Maybe<NR::Rect> bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds();
 
                     //std::cout << "Selection " << bbox;
-                    if (sp_export_bbox_equal(bbox,current_bbox)) {
+                    if ( bbox && sp_export_bbox_equal(*bbox,current_bbox)) {
                         key = SELECTION_SELECTION;
                     }
                 }
index 53b9aa8cc989cf04dc01359a94c25e1d1223460f..4db82385afcaca5b140128d6e53ff90bffca1248 100644 (file)
@@ -342,13 +342,15 @@ sp_fillstroke_selection_changed ( Inkscape::Application *inkscape,
         case QUERY_STYLE_SINGLE:
         case QUERY_STYLE_MULTIPLE_AVERAGED:
         case QUERY_STYLE_MULTIPLE_SAME: 
-            NR::Rect bbox = sp_desktop_selection(SP_ACTIVE_DESKTOP)->bounds();
-            double perimeter = bbox.extent(NR::X) + bbox.extent(NR::Y);
-            gtk_widget_set_sensitive (b, TRUE);
-            //update blur widget value
-            float radius = query->filter_gaussianBlur_deviation.value;
-            float percent = radius * 400 / perimeter; // so that for a square, 100% == half side
-            gtk_adjustment_set_value(bluradjustment, percent);
+            NR::Maybe<NR::Rect> bbox = sp_desktop_selection(SP_ACTIVE_DESKTOP)->bounds();
+            if (bbox) {
+                double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y);
+                gtk_widget_set_sensitive (b, TRUE);
+                //update blur widget value
+                float radius = query->filter_gaussianBlur_deviation.value;
+                float percent = radius * 400 / perimeter; // so that for a square, 100% == half side
+                gtk_adjustment_set_value(bluradjustment, percent);
+            }
             break;
     }
     
@@ -411,13 +413,17 @@ sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *base)
     
     //get current selection
     Inkscape::Selection *selection = sp_desktop_selection (desktop);
+
+    NR::Maybe<NR::Rect> bbox = selection->bounds();
+    if (!bbox) {
+        return;
+    }
     //get list of selected items
     GSList const *items = selection->itemList();
     //get current document
     SPDocument *document = sp_desktop_document (desktop);
 
-    NR::Rect bbox = selection->bounds();
-    double perimeter = bbox.extent(NR::X) + bbox.extent(NR::Y);
+    double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y);
     double radius = a->value * perimeter / 400;
         
     //apply created filter to every selected item
index b10f952da5848d9a9dc3e578c274eb14fd7a41fe..75311ddd03dc3fa3b837a9ea02ffe0fce9817240 100644 (file)
@@ -268,14 +268,14 @@ void TileDialog::Grid_Arrange ()
     }
 
 
+    NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
     // Fit to bbox, calculate padding between rows accordingly.
-    if (!SpaceManualRadioButton.get_active()){
-        NR::Rect b = selection->bounds();
+    if ( sel_bbox && !SpaceManualRadioButton.get_active() ){
 #ifdef DEBUG_GRID_ARRANGE
 g_print("\n row = %f     col = %f selection x= %f selection y = %f", total_row_height,total_col_width, b.extent(NR::X), b.extent(NR::Y));
 #endif
-        paddingx = (b.extent(NR::X) - total_col_width) / (NoOfCols -1);
-        paddingy = (b.extent(NR::Y) - total_row_height) / (NoOfRows -1);
+        paddingx = (sel_bbox->extent(NR::X) - total_col_width) / (NoOfCols -1);
+        paddingy = (sel_bbox->extent(NR::Y) - total_row_height) / (NoOfRows -1);
     }
 
 /*
index 87e0c14ac09b6562b804d2e4aabe73d61099c434..061035eace22f8e733b9b25606f33c372771a8cd 100644 (file)
@@ -86,7 +86,10 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc
                                  NR::Point(sp_document_width(doc),
                                            sp_document_height(doc)));
     } else {
-        bounding_area = selection->bounds();
+        NR::Maybe<NR::Rect> bounds = selection->bounds();
+        if (bounds) {
+            bounding_area = *bounds;
+        }
 
         gdouble doc_height  =  sp_document_height(document->doc());
         NR::Rect temprec = NR::Rect(NR::Point(bounding_area.min()[NR::X], doc_height - bounding_area.min()[NR::Y]),
index f4630719b27eb88f0343c1f25c6d3a6814c99483..c1d03554566a1bd244d71d3e042515d68e53716e 100644 (file)
@@ -834,8 +834,11 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
                 int const saved_pref = prefs_get_int_attribute("options.transform", "pattern", 1);
                 prefs_set_int_attribute("options.transform", "pattern", 1);
                 sp_document_ensure_up_to_date(sp_desktop_document(desktop));
-                NR::Point m( desktop->point() - selection->bounds().midpoint() );
-                sp_selection_move_relative(selection, m);
+                NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
+                if (sel_bbox) {
+                    NR::Point m( desktop->point() - sel_bbox->midpoint() );
+                    sp_selection_move_relative(selection, m);
+                }
                 prefs_set_int_attribute("options.transform", "pattern", saved_pref);
             }
         }
index 83f4ac3c8ffdc6708a4deb26e44a06be23fcebd0..dad1146c04d5ec94abd94e184bceff13c0c2bd1b 100644 (file)
@@ -1130,8 +1130,11 @@ sp_ui_drag_data_received(GtkWidget *widget,
                 int const saved_pref = prefs_get_int_attribute("options.transform", "pattern", 1);
                 prefs_set_int_attribute("options.transform", "pattern", 1);
                 sp_document_ensure_up_to_date(sp_desktop_document(desktop));
-                NR::Point m( desktop->point() - selection->bounds().midpoint() );
-                sp_selection_move_relative(selection, m);
+                NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
+                if (sel_bbox) {
+                    NR::Point m( desktop->point() - sel_bbox->midpoint() );
+                    sp_selection_move_relative(selection, m);
+                }
                 prefs_set_int_attribute("options.transform", "pattern", saved_pref);
             }
 
index 171928865403b2ff9b000ccfc4888942571308d6..5fa5b0d7ed83bff3c052cfe146571290b7ca83b5 100644 (file)
@@ -81,7 +81,7 @@ using NR::Y;
 GSList *clipboard = NULL;
 GSList *defs_clipboard = NULL;
 SPCSSAttr *style_clipboard = NULL;
-NR::Rect size_clipboard(NR::Point(0,0), NR::Point(0,0));
+NR::Maybe<NR::Rect> size_clipboard;
 
 static void sp_copy_stuff_used_by_item(GSList **defs_clip, SPItem *item, const GSList *items);
 
@@ -1128,7 +1128,11 @@ void sp_selection_paste(bool in_place)
     if (!in_place) {
         sp_document_ensure_up_to_date(document);
 
-        NR::Point m( desktop->point() - selection->bounds().midpoint() );
+        NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
+        NR::Point m( desktop->point() );
+        if (sel_bbox) {
+            m -= sel_bbox->midpoint();
+        }
 
         /* Snap the offset of the new item(s) to the grid */
         /* FIXME: this gridsnap fiddling is a hack. */
@@ -1179,7 +1183,7 @@ void sp_selection_paste_size (bool apply_x, bool apply_y)
     Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is in the clipboard
-    if (size_clipboard.extent(NR::X) < 1e-6 || size_clipboard.extent(NR::Y) < 1e-6) {
+    if (!size_clipboard) {
         desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing on the clipboard."));
         return;
     }
@@ -1190,15 +1194,15 @@ void sp_selection_paste_size (bool apply_x, bool apply_y)
         return;
     }
 
-    NR::Rect current = selection->bounds();
-    if (current.extent(NR::X) < 1e-6 || current.extent(NR::Y) < 1e-6) {
+    NR::Maybe<NR::Rect> current = selection->bounds();
+    if ( !current || current->extent(NR::X) < 1e-6 || current->extent(NR::Y) < 1e-6 ) {
         return;
     }
 
-    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_selection_scale_relative (selection, current.midpoint(), 
+    sp_selection_scale_relative (selection, current->midpoint(),
                                  NR::scale(
                                      apply_x? scale_x : (desktop->isToolboxButtonActive ("lock")? scale_y : 1.0),
                                      apply_y? scale_y : (desktop->isToolboxButtonActive ("lock")? scale_x : 1.0)));
@@ -1215,7 +1219,7 @@ void sp_selection_paste_size_separately (bool apply_x, bool apply_y)
     Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     // check if something is in the clipboard
-    if (size_clipboard.extent(NR::X) < 1e-6 || size_clipboard.extent(NR::Y) < 1e-6) {
+    if ( !size_clipboard ) {
         desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing on the clipboard."));
         return;
     }
@@ -1234,8 +1238,8 @@ void sp_selection_paste_size_separately (bool apply_x, bool apply_y)
             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(
@@ -1522,16 +1526,16 @@ sp_selection_scale_absolute(Inkscape::Selection *selection,
     if (selection->isEmpty())
         return;
 
-    NR::Rect const bbox(selection->bounds());
-    if (bbox.isEmpty()) {
+    NR::Maybe<NR::Rect> const bbox(selection->bounds());
+    if ( !bbox || bbox->isEmpty() ) {
         return;
     }
 
-    NR::translate const p2o(-bbox.min());
+    NR::translate const p2o(-bbox->min());
 
     NR::scale const newSize(x1 - x0,
                             y1 - y0);
-    NR::scale const scale( newSize / NR::scale(bbox.dimensions()) );
+    NR::scale const scale( newSize / NR::scale(bbox->dimensions()) );
     NR::translate const o2n(x0, y0);
     NR::Matrix const final( p2o * scale * o2n );
 
@@ -1544,15 +1548,15 @@ void sp_selection_scale_relative(Inkscape::Selection *selection, NR::Point const
     if (selection->isEmpty())
         return;
 
-    NR::Rect const bbox(selection->bounds());
+    NR::Maybe<NR::Rect> const bbox(selection->bounds());
 
-    if (bbox.isEmpty()) {
+    if ( !bbox || bbox->isEmpty() ) {
         return;
     }
 
     // FIXME: ARBITRARY LIMIT: don't try to scale above 1 Mpx, it won't display properly and will crash sooner or later anyway
-    if ( bbox.extent(NR::X) * scale[NR::X] > 1e6  ||
-         bbox.extent(NR::Y) * scale[NR::Y] > 1e6 )
+    if ( bbox->extent(NR::X) * scale[NR::X] > 1e6  ||
+         bbox->extent(NR::Y) * scale[NR::Y] > 1e6 )
     {
         return;
     }
@@ -1657,9 +1661,12 @@ sp_selection_rotate(Inkscape::Selection *selection, gdouble const angle_degrees)
     if (selection->isEmpty())
         return;
 
-    NR::Point center = selection->center();
+    NR::Maybe<NR::Point> center = selection->center();
+    if (!center) {
+        return;
+    }
 
-    sp_selection_rotate_relative(selection, center, angle_degrees);
+    sp_selection_rotate_relative(selection, *center, angle_degrees);
 
     sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( ( angle_degrees > 0 )
@@ -1678,17 +1685,20 @@ sp_selection_rotate_screen(Inkscape::Selection *selection, gdouble angle)
     if (selection->isEmpty())
         return;
 
-    NR::Rect const bbox(selection->bounds());
+    NR::Maybe<NR::Rect> const bbox(selection->bounds());
+    NR::Maybe<NR::Point> center = selection->center();
 
-    NR::Point center = selection->center();
+    if ( !bbox || !center ) {
+        return;
+    }
 
     gdouble const zoom = selection->desktop()->current_zoom();
     gdouble const zmove = angle / zoom;
-    gdouble const r = NR::L2(bbox.max() - center);
+    gdouble const r = NR::L2(bbox->max() - *center);
 
     gdouble const zangle = 180 * atan2(zmove, r) / M_PI;
 
-    sp_selection_rotate_relative(selection, center, zangle);
+    sp_selection_rotate_relative(selection, *center, zangle);
 
     sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( (angle > 0)
@@ -1704,11 +1714,15 @@ sp_selection_scale(Inkscape::Selection *selection, gdouble grow)
     if (selection->isEmpty())
         return;
 
-    NR::Rect const bbox(selection->bounds());
-    NR::Point const center(bbox.midpoint());
-    double const max_len = bbox.maxExtent();
+    NR::Maybe<NR::Rect> const bbox(selection->bounds());
+    if (!bbox) {
+        return;
+    }
+
+    NR::Point const center(bbox->midpoint());
 
     // you can't scale "do nizhe pola" (below zero)
+    double const max_len = bbox->maxExtent();
     if ( max_len + grow <= 1e-3 ) {
         return;
     }
@@ -1737,7 +1751,13 @@ sp_selection_scale_times(Inkscape::Selection *selection, gdouble times)
     if (selection->isEmpty())
         return;
 
-    NR::Point const center(selection->bounds().midpoint());
+    NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
+
+    if (!sel_bbox) {
+        return;
+    }
+
+    NR::Point const center(sel_bbox->midpoint());
     sp_selection_scale_relative(selection, center, NR::scale(times, times));
     sp_document_done(sp_desktop_document(selection->desktop()), SP_VERB_CONTEXT_SELECT, 
                      _("Scale by whole factor"));
@@ -2181,13 +2201,13 @@ sp_selection_tile(bool apply)
     }
 
     sp_document_ensure_up_to_date(document);
-    NR::Rect r = selection->bounds();
-    if (r.isEmpty()) {
+    NR::Maybe<NR::Rect> r = selection->bounds();
+    if ( !r || r->isEmpty() ) {
         return;
     }
 
     // calculate the transform to be applied to objects to move them to 0,0
-    NR::Point move_p = NR::Point(0, sp_document_height(document)) - (r.min() + NR::Point (0, r.extent(NR::Y)));
+    NR::Point move_p = NR::Point(0, sp_document_height(document)) - (r->min() + NR::Point (0, r->extent(NR::Y)));
     move_p[NR::Y] = -move_p[NR::Y];
     NR::Matrix move = NR::Matrix (NR::translate (move_p));
 
@@ -2210,7 +2230,7 @@ sp_selection_tile(bool apply)
         repr_copies = g_slist_prepend (repr_copies, dup);
     }
 
-    NR::Rect bounds(desktop->dt2doc(r.min()), desktop->dt2doc(r.max()));
+    NR::Rect bounds(desktop->dt2doc(r->min()), desktop->dt2doc(r->max()));
 
     if (apply) {
         // delete objects so that their clones don't get alerted; this object will be restored shortly
@@ -2227,7 +2247,7 @@ sp_selection_tile(bool apply)
     prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
 
     const gchar *pat_id = pattern_tile (repr_copies, bounds, document,
-                                        NR::Matrix(NR::translate(desktop->dt2doc(NR::Point(r.min()[NR::X], r.max()[NR::Y])))) * parent_transform.inverse(), parent_transform * move);
+                                        NR::Matrix(NR::translate(desktop->dt2doc(NR::Point(r->min()[NR::X], r->max()[NR::Y])))) * parent_transform.inverse(), parent_transform * move);
 
     // restore compensation setting
     prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
index d39086e8c60e56174a42d6f697026307de4d7109..c6b307c3b0ddd0918411f374e2852f560e0988ed 100644 (file)
@@ -306,15 +306,11 @@ Inkscape::XML::Node *Selection::singleRepr() {
 NRRect *Selection::bounds(NRRect *bbox) const
 {
     g_return_val_if_fail (bbox != NULL, NULL);
-    NR::Rect const b = bounds();
-    bbox->x0 = b.min()[NR::X];
-    bbox->y0 = b.min()[NR::Y];
-    bbox->x1 = b.max()[NR::X];
-    bbox->y1 = b.max()[NR::Y];
+    *bbox = NRRect(bounds());
     return bbox;
 }
 
-NR::Rect Selection::bounds() const
+NR::Maybe<NR::Rect> Selection::bounds() const
 {
     GSList const *items = const_cast<Selection *>(this)->itemList();
 
@@ -322,13 +318,7 @@ NR::Rect Selection::bounds() const
     for ( GSList const *i = items ; i != NULL ; i = i->next ) {
         bbox = NR::union_bounds(bbox, sp_item_bbox_desktop(SP_ITEM(i->data)));
     }
-
-    // TODO: return NR::Maybe<NR::Rect>
-    if (bbox) {
-        return *bbox;
-    } else {
-        return NR::Rect(NR::Point(0, 0), NR::Point(0, 0));
-    }
+    return bbox;
 }
 
 NRRect *Selection::boundsInDocument(NRRect *bbox) const {
@@ -352,32 +342,27 @@ NRRect *Selection::boundsInDocument(NRRect *bbox) const {
     return bbox;
 }
 
-NR::Rect Selection::boundsInDocument() const {
+NR::Maybe<NR::Rect> Selection::boundsInDocument() const {
     NRRect r;
-    NR::Maybe<NR::Rect> rect(boundsInDocument(&r)->upgrade());
-    if (rect) {
-        return *rect;
-    } else {
-        // FIXME
-        return NR::Rect(NR::Point(0, 0), NR::Point(0, 0));
-    }
+    return boundsInDocument(&r)->upgrade();
 }
 
 /** Extract the position of the center from the first selected object */
-NR::Point Selection::center() const {
+NR::Maybe<NR::Point> Selection::center() const {
     GSList *items = (GSList *) const_cast<Selection *>(this)->itemList();
     NR::Point center;
     if (items) {
         SPItem *first = reinterpret_cast<SPItem*>(g_slist_last(items)->data); // from the first item in selection
         if (first->isCenterSet()) { // only if set explicitly
-            center = first->getCenter();
-        } else {
-            center = bounds().midpoint();
+            return first->getCenter();
         }
+    }
+    NR::Maybe<NR::Rect> bbox = bounds();
+    if (bbox) {
+        return bounds()->midpoint();
     } else {
-        center = bounds().midpoint();
+        return NR::Nothing();
     }
-    return center;
 }
 
 /**
@@ -417,28 +402,6 @@ std::vector<NR::Point> Selection::getSnapPointsConvexHull() const {
     return pHull;
 }
 
-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::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;
-}
-
-std::vector<NR::Point> Selection::getBBoxPointsOuter() const {
-    std::vector<NR::Point> p;
-    NR::Rect bbox = bounds();
-    p.push_back(bbox.min());
-    p.push_back(bbox.max());
-    return p;
-}
-
 void Selection::_removeObjectDescendants(SPObject *obj) {
     GSList *iter, *next;
     for ( iter = _objs ; iter ; iter = next ) {
index bae368e8149461633866d43967deec77247e35a6..f9368f5eef5e5898e72460f2abf218057b84151e 100644 (file)
@@ -233,7 +233,7 @@ public:
     /** @brief Returns the bounding rectangle of the selection */
     NRRect *bounds(NRRect *dest) const;
     /** @brief Returns the bounding rectangle of the selection */
-    ::NR::Rect bounds() const;
+    NR::Maybe<NR::Rect> bounds() const;
 
     /**
      * @brief Returns the bounding rectangle of the selection
@@ -247,12 +247,12 @@ public:
      *
      * \todo how is this different from bounds()?
      */
-    ::NR::Rect boundsInDocument() const;
+    NR::Maybe<NR::Rect> boundsInDocument() const;
 
     /**
      * @brief Returns the rotation/skew center of the selection
      */
-    ::NR::Point center() const;
+    NR::Maybe<NR::Point> center() const;
 
     /**
      * @brief Gets the selection's snap points.
@@ -266,18 +266,6 @@ public:
      */
     std::vector<NR::Point> getSnapPointsConvexHull() const;
 
-    /**
-     * @return A vector containing the top-left and bottom-right
-     * corners of each selected object's bounding box.
-     */
-    std::vector<NR::Point> getBBoxPoints() const;
-
-    /**
-     * @return A vector containing the 2 (bottom-left and upper-right)
-     * corners of the selection bounding box.
-     */
-    std::vector<NR::Point> getBBoxPointsOuter() const;
-
     /**
      * @brief Connects a slot to be notified of selection changes
      *
index 5368628b84c1dfdc029f219d330aa6df60bd492a..a1a200282490f7e85c2652e19974eabe4ccd8b6e 100644 (file)
@@ -88,7 +88,7 @@ Inkscape::SelTrans::SelTrans(SPDesktop *desktop) :
     _show(SHOW_CONTENT),
     _grabbed(false),
     _show_handles(true),
-    _box(NR::Point(0,0), NR::Point(0,0)),
+    _box(NR::Nothing()),
     _chandle(NULL),
     _stamp_cache(NULL),
     _message_context(desktop->messageStack())
@@ -256,25 +256,33 @@ void Inkscape::SelTrans::grab(NR::Point const &p, gdouble x, gdouble y, bool sho
     _point = p;
 
     _snap_points = selection->getSnapPointsConvexHull();
-    _bbox_points = selection->getBBoxPointsOuter();
-    _bbox_4points = _bbox_points;
-    _bbox_4points.push_back(NR::Point(_bbox_points[0][NR::X], _bbox_points[1][NR::Y]));
-    _bbox_4points.push_back(NR::Point(_bbox_points[1][NR::X], _bbox_points[0][NR::Y]));
+    _box = selection->bounds();
+    _bbox_points.clear();
+    if (_box) {
+        for ( unsigned i = 0 ; i < 4 ; i++ ) {
+            _bbox_points.push_back(_box->corner(i));
+        }
+    }
 
     gchar const *scale_origin = prefs_get_string_attribute("tools.select", "scale_origin");
     bool const origin_on_bbox = (scale_origin == NULL || !strcmp(scale_origin, "bbox"));
-    NR::Rect op_box = _box;
-    if (origin_on_bbox == false && _snap_points.empty() == false) {
-        std::vector<NR::Point>::iterator i = _snap_points.begin();
-        op_box = NR::Rect(*i, *i);
-        i++;
-        while (i != _snap_points.end()) {
-            op_box.expandTo(*i);
+
+    if (_box) {
+        NR::Rect op_box = *_box;
+        // FIXME: should be using ConvexHull here
+        if (origin_on_bbox == false && _snap_points.empty() == false) {
+            std::vector<NR::Point>::iterator i = _snap_points.begin();
+            op_box = NR::Rect(*i, *i);
             i++;
+            while (i != _snap_points.end()) {
+                op_box.expandTo(*i);
+                i++;
+            }
         }
+
+        _opposite = ( op_box.min() + ( op_box.dimensions() * NR::scale(1-x, 1-y) ) );
     }
 
-    _opposite = ( op_box.min() + ( op_box.dimensions() * NR::scale(1-x, 1-y) ) );
 
     if ((x != -1) && (y != -1)) {
         sp_canvas_item_show(_norm);
@@ -286,7 +294,6 @@ void Inkscape::SelTrans::grab(NR::Point const &p, gdouble x, gdouble y, bool sho
             sp_canvas_item_show(_l[i]);
     }
 
-
     _updateHandles();
     g_return_if_fail(_stamp_cache == NULL);
 }
@@ -306,13 +313,15 @@ void Inkscape::SelTrans::transform(NR::Matrix const &rel_affine, NR::Point const
             sp_item_set_i2d_affine(&item, prev_transform * affine);
         }
     } else {
-        NR::Point p[4];
-        /* update the outline */
-        for (unsigned i = 0 ; i < 4 ; i++) {
-            p[i] = _box.corner(i) * affine;
-        }
-        for (unsigned i = 0 ; i < 4 ; i++) {
-            sp_ctrlline_set_coords(SP_CTRLLINE(_l[i]), p[i], p[(i+1)%4]);
+        if (_box) {
+            NR::Point p[4];
+            /* update the outline */
+            for (unsigned i = 0 ; i < 4 ; i++) {
+                p[i] = _box->corner(i) * affine;
+            }
+            for (unsigned i = 0 ; i < 4 ; i++) {
+                sp_ctrlline_set_coords(SP_CTRLLINE(_l[i]), p[i], p[(i+1)%4]);
+            }
         }
     }
 
@@ -351,8 +360,10 @@ void Inkscape::SelTrans::ungrab()
 
     if (!_empty && _changed) {
         sp_selection_apply_affine(selection, _current, (_show == SHOW_OUTLINE)? true : false);
-        _center *= _current;
-        _center_is_set = true;
+        if (_center) {
+            *_center *= _current;
+            _center_is_set = true;
+        }
 
 // If dragging showed content live, sp_selection_apply_affine cannot change the centers
 // appropriately - it does not know the original positions of the centers (all objects already have
@@ -458,8 +469,8 @@ void Inkscape::SelTrans::stamp()
 
             sp_item_write_transform(copy_item, copy_repr, *new_affine);
 
-            if (copy_item->isCenterSet()) {
-                copy_item->setCenter(_center * _current);
+            if ( copy_item->isCenterSet() && _center ) {
+                copy_item->setCenter(*_center * _current);
             }
 
             Inkscape::GC::release(copy_repr);
@@ -529,11 +540,11 @@ void Inkscape::SelTrans::_updateHandles()
         _center_is_set = true;
     }
 
-    if ( _state == STATE_SCALE ) {
+    if ( _state == STATE_SCALE || !_center ) {
         sp_knot_hide(_chandle);
     } else {
         sp_knot_show(_chandle);
-        sp_knot_moveto(_chandle, &_center);
+        sp_knot_moveto(_chandle, &*_center);
     }
 }
 
@@ -547,7 +558,7 @@ void Inkscape::SelTrans::_updateVolatileState()
     }
 
     _box = selection->bounds();
-    if (_box.isEmpty()) {
+    if (!_box) {
         _empty = true;
         return;
     }
@@ -595,8 +606,10 @@ void Inkscape::SelTrans::_showHandles(SPKnot *knot[], SPSelTransHandle const han
         sp_knot_show(knot[i]);
 
         NR::Point const handle_pt(handle[i].x, handle[i].y);
-        NR::Point p( _box.min()
-                     + ( _box.dimensions()
+        // shouldn't have nullary bbox, but knots
+        g_assert(_box);
+        NR::Point p( _box->min()
+                     + ( _box->dimensions()
                          * NR::scale(handle_pt) ) );
 
         sp_knot_moveto(knot[i], &p);
@@ -715,8 +728,11 @@ gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, NR::Point *position, gu
 
     if ((!(state & GDK_SHIFT_MASK) == !(_state == STATE_ROTATE)) && (&handle != &handle_center)) {
         _origin = _opposite;
+    } else if (_center) {
+        _origin = *_center;
     } else {
-        _origin = _center;
+        // FIXME
+        return TRUE;
     }
     if (handle.request(this, handle, *position, state)) {
         sp_knot_set_position(knot, position, state);
@@ -870,7 +886,7 @@ gboolean Inkscape::SelTrans::scaleRequest(NR::Point &pt, guint state)
         /* Scale aspect ratio is unlocked */
         
         std::pair<NR::scale, bool> bb = m.freeSnapScale(Snapper::BBOX_POINT,
-                                                        _bbox_4points,
+                                                        _bbox_points,
                                                         it,
                                                         s,
                                                         _origin);
@@ -1169,22 +1185,21 @@ gboolean Inkscape::SelTrans::centerRequest(NR::Point &pt, guint state)
         }
     }
 
-    if (!(state & GDK_SHIFT_MASK)) {
+    if ( !(state & GDK_SHIFT_MASK) && _box ) {
         // screen pixels to snap center to bbox
 #define SNAP_DIST 5
         // FIXME: take from prefs
         double snap_dist = SNAP_DIST / _desktop->current_zoom();
 
         for (int i = 0; i < 2; i++) {
-
-            if (fabs(pt[i] - _box.min()[i]) < snap_dist) {
-                pt[i] = _box.min()[i];
+            if (fabs(pt[i] - _box->min()[i]) < snap_dist) {
+                pt[i] = _box->min()[i];
             }
-            if (fabs(pt[i] - _box.midpoint()[i]) < snap_dist) {
-                pt[i] = _box.midpoint()[i];
+            if (fabs(pt[i] - _box->midpoint()[i]) < snap_dist) {
+                pt[i] = _box->midpoint()[i];
             }
-            if (fabs(pt[i] - _box.max()[i]) < snap_dist) {
-                pt[i] = _box.max()[i];
+            if (fabs(pt[i] - _box->max()[i]) < snap_dist) {
+                pt[i] = _box->max()[i];
             }
         }
     }
@@ -1264,11 +1279,15 @@ void Inkscape::SelTrans::stretch(SPSelTransHandle const &handle, NR::Point &pt,
         s[!dim] = fabs(s[dim]);
     }
 
-    NR::Point new_bbox_min = _box.min() * (NR::translate(-scale_origin) * NR::Matrix(s) * NR::translate(scale_origin));
-    NR::Point new_bbox_max = _box.max() * (NR::translate(-scale_origin) * NR::Matrix(s) * NR::translate(scale_origin));
+    if (!_box) {
+        return;
+    }
+
+    NR::Point new_bbox_min = _box->min() * (NR::translate(-scale_origin) * NR::Matrix(s) * NR::translate(scale_origin));
+    NR::Point new_bbox_max = _box->max() * (NR::translate(-scale_origin) * NR::Matrix(s) * NR::translate(scale_origin));
 
     int transform_stroke = prefs_get_int_attribute ("options.transform", "stroke", 1);
-    NR::Matrix scaler = get_scale_transform_with_stroke (_box, _strokewidth, transform_stroke,
+    NR::Matrix scaler = get_scale_transform_with_stroke (*_box, _strokewidth, transform_stroke,
                    new_bbox_min[NR::X], new_bbox_min[NR::Y], new_bbox_max[NR::X], new_bbox_max[NR::Y]);
 
     transform(scaler, NR::Point(0, 0)); // we have already accounted for origin, so pass 0,0
@@ -1276,6 +1295,10 @@ void Inkscape::SelTrans::stretch(SPSelTransHandle const &handle, NR::Point &pt,
 
 void Inkscape::SelTrans::scale(NR::Point &pt, guint state)
 {
+    if (!_box) {
+        return;
+    }
+
     NR::Point const offset = _point - _origin;
 
     NR::scale s (1, 1);
@@ -1285,11 +1308,11 @@ void Inkscape::SelTrans::scale(NR::Point &pt, guint state)
         if (fabs(s[i]) < 1e-9)
             s[i] = 1e-9;
     }
-    NR::Point new_bbox_min = _box.min() * (NR::translate(-_origin) * NR::Matrix(s) * NR::translate(_origin));
-    NR::Point new_bbox_max = _box.max() * (NR::translate(-_origin) * NR::Matrix(s) * NR::translate(_origin));
+    NR::Point new_bbox_min = _box->min() * (NR::translate(-_origin) * NR::Matrix(s) * NR::translate(_origin));
+    NR::Point new_bbox_max = _box->max() * (NR::translate(-_origin) * NR::Matrix(s) * NR::translate(_origin));
 
     int transform_stroke = prefs_get_int_attribute ("options.transform", "stroke", 1);
-    NR::Matrix scaler = get_scale_transform_with_stroke (_box, _strokewidth, transform_stroke,
+    NR::Matrix scaler = get_scale_transform_with_stroke (*_box, _strokewidth, transform_stroke,
                    new_bbox_min[NR::X], new_bbox_min[NR::Y], new_bbox_max[NR::X], new_bbox_max[NR::Y]);
 
     transform(scaler, NR::Point(0, 0)); // we have already accounted for origin, so pass 0,0
@@ -1416,7 +1439,7 @@ void Inkscape::SelTrans::moveTo(NR::Point const &xy, guint state)
             /* Snap to things with no constraint */
 
             s.push_back(m.freeSnapTranslation(Inkscape::Snapper::BBOX_POINT,
-                                              _bbox_4points, it, dxy));
+                                              _bbox_points, it, dxy));
             s.push_back(m.freeSnapTranslation(Inkscape::Snapper::SNAP_POINT,
                                               _snap_points, it, dxy));
         }
index 8d527ca5c76d05979147d6e4d799fd8f5eddcce4..e8aee252ec4175c7db574bf55810d828f66773f3 100644 (file)
@@ -105,7 +105,6 @@ private:
     
     std::vector<NR::Point> _snap_points;
     std::vector<NR::Point> _bbox_points;
-    std::vector<NR::Point> _bbox_4points;
     
     Inkscape::SelCue _selcue;
 
@@ -118,12 +117,12 @@ private:
     bool _empty;
     bool _changed;
 
-    NR::Rect _box;
+    NR::Maybe<NR::Rect> _box;
     gdouble _strokewidth;
     NR::Matrix _current;
     NR::Point _opposite; ///< opposite point to where a scale is taking place
 
-    NR::Point _center;
+    NR::Maybe<NR::Point> _center;
     bool _center_is_set; ///< we've already set _center, no need to reread it from items
 
     SPKnot *_shandle[8];
index cf07fba16b84db6b4ca11007eaee96dc355df654..f5f0a6481fa8e159c493b2674f1840ec9d83e8d5 100644 (file)
@@ -1555,8 +1555,11 @@ sp_selected_path_simplify_items(SPDesktop *desktop,
 
   bool didSomething = false;
 
-  NR::Rect selectionBbox = selection->bounds();
-  gdouble selectionSize  = L2(selectionBbox.dimensions());
+  NR::Maybe<NR::Rect> selectionBbox = selection->bounds();
+  if (!selectionBbox) {
+    return false;
+  }
+  gdouble selectionSize  = L2(selectionBbox->dimensions());
 
   gdouble simplifySize  = selectionSize;
   
index c1f4a10a11620a9124eeeef7eb4866abc8441906..7c5908e5853ff654df4232544547bc48e417de4b 100644 (file)
@@ -183,9 +183,13 @@ private :
 
         case AlignAndDistribute::SELECTION:
         {
-            NR::Rect b =  selection->bounds();
-            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 =  selection->bounds();
+            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;
         }
 
@@ -590,11 +594,16 @@ private :
         //Check 2 or more selected objects
         if (selected.size() < 2) return;
 
+        NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
+        if (!sel_bbox) {
+            return;
+        }
+
         // This bbox is cached between calls to randomize, so that there's no growth nor shrink
         // nor drift on sequential randomizations. Discard cache on global (or better active
         // desktop's) selection_change signal.
         if (!_dialog.randomize_bbox_set) {
-            _dialog.randomize_bbox = selection->bounds();
+            _dialog.randomize_bbox = *sel_bbox;
             _dialog.randomize_bbox_set = true;
         }
 
index 90cac7425c8e66324b7599a9cf0358a57e431f51..98623849fb6705781288495de129659034b89581 100644 (file)
@@ -455,13 +455,14 @@ Transformation::updatePageMove(Inkscape::Selection *selection)
 {
     if (selection && !selection->isEmpty()) {
         if (!_check_move_relative.get_active()) {
+            NR::Maybe<NR::Rect> bbox = selection->bounds();
+            if (bbox) {
+                double x = bbox->min()[NR::X];
+                double y = bbox->min()[NR::Y];
 
-            NR::Rect bbox = selection->bounds();
-            double x = bbox.min()[NR::X];
-            double y = bbox.min()[NR::Y];
-
-            _scalar_move_horizontal.setValue(x, "px");
-            _scalar_move_vertical.setValue(y, "px");
+                _scalar_move_horizontal.setValue(x, "px");
+                _scalar_move_vertical.setValue(y, "px");
+            }
         } else {
             // do nothing, so you can apply the same relative move to many objects in turn
         }
@@ -475,13 +476,17 @@ void
 Transformation::updatePageScale(Inkscape::Selection *selection)
 {
     if (selection && !selection->isEmpty()) {
-        NR::Rect bbox = selection->bounds();
-        double w = bbox.extent(NR::X);
-        double h = bbox.extent(NR::Y);
-        _scalar_scale_horizontal.setHundredPercent(w);
-        _scalar_scale_vertical.setHundredPercent(h);
-        onScaleXValueChanged(); // to update x/y proportionality if switch is on
-        _page_scale.set_sensitive(true);
+        NR::Maybe<NR::Rect> bbox = selection->bounds();
+        if (bbox) {
+            double w = bbox->extent(NR::X);
+            double h = bbox->extent(NR::Y);
+            _scalar_scale_horizontal.setHundredPercent(w);
+            _scalar_scale_vertical.setHundredPercent(h);
+            onScaleXValueChanged(); // to update x/y proportionality if switch is on
+            _page_scale.set_sensitive(true);
+        } else {
+            _page_scale.set_sensitive(false);
+        }
     } else {
         _page_scale.set_sensitive(false);
     }
@@ -586,9 +591,11 @@ Transformation::applyPageMove(Inkscape::Selection *selection)
     if (_check_move_relative.get_active()) {
         sp_selection_move_relative(selection, x, y);
     } else {
-        NR::Rect bbox = selection->bounds();
-        sp_selection_move_relative(selection,
-            x - bbox.min()[NR::X], y - bbox.min()[NR::Y]);
+        NR::Maybe<NR::Rect> bbox = selection->bounds();
+        if (bbox) {
+            sp_selection_move_relative(selection,
+                x - bbox->min()[NR::X], y - bbox->min()[NR::Y]);
+        }
     }
 
     sp_document_done ( sp_desktop_document (selection->desktop()) , SP_VERB_DIALOG_TRANSFORM, 
@@ -625,24 +632,26 @@ Transformation::applyPageScale(Inkscape::Selection *selection)
             sp_item_scale_rel (item, scale);
         }
     } else {
-        NR::Rect  bbox(selection->bounds());
-        NR::Point center(bbox.midpoint()); // use rotation center?
-        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;
-            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;
-            double new_height = 100 + scaleY;
-            if (new_height < 1e-6) new_height = 1e-6;
-            scale = NR::scale(new_width / 100.0, new_height / 100.0);
+        NR::Maybe<NR::Rect> bbox(selection->bounds());
+        if (bbox) {
+            NR::Point center(bbox->midpoint()); // use rotation center?
+            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;
+                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;
+                double new_height = 100 + scaleY;
+                if (new_height < 1e-6) new_height = 1e-6;
+                scale = NR::scale(new_width / 100.0, new_height / 100.0);
+            }
+            sp_selection_scale_relative(selection, center, scale);
         }
-        sp_selection_scale_relative(selection, center, scale);
     }
 
     sp_document_done(sp_desktop_document(selection->desktop()), SP_VERB_DIALOG_TRANSFORM, 
@@ -660,8 +669,10 @@ Transformation::applyPageRotate(Inkscape::Selection *selection)
             sp_item_rotate_rel(item, NR::rotate (angle*M_PI/180.0));
         }
     } else {
-        NR::Point center = selection->center();
-        sp_selection_rotate_relative(selection, center, angle);
+        NR::Maybe<NR::Point> center = selection->center();
+        if (center) {
+            sp_selection_rotate_relative(selection, *center, angle);
+        }
     }
 
     sp_document_done(sp_desktop_document(selection->desktop()), SP_VERB_DIALOG_TRANSFORM, 
@@ -690,32 +701,35 @@ Transformation::applyPageSkew(Inkscape::Selection *selection)
                 double skewY = _scalar_skew_vertical.getValue("px");
                 NR::Maybe<NR::Rect> bbox(sp_item_bbox_desktop(item));
                 if (bbox) {
-                    double width = bbox->dimensions()[NR::X];
-                    double height = bbox->dimensions()[NR::Y];
+                    double width = bbox->extent(NR::X);
+                    double height = bbox->extent(NR::Y);
                     sp_item_skew_rel (item, skewX/height, skewY/width);
                 }
             }
         }
     } else { // transform whole selection
-        NR::Rect bbox = selection->bounds();
-        double width  = bbox.max()[NR::X] - bbox.min()[NR::X];
-        double height = bbox.max()[NR::Y] - bbox.min()[NR::Y];
-        NR::Point center = selection->center();
-
-        if (!_units_skew.isAbsolute()) { // percentage
-            double skewX = _scalar_skew_horizontal.getValue("%");
-            double skewY = _scalar_skew_vertical.getValue("%");
-            sp_selection_skew_relative(selection, center, 0.01*skewX, 0.01*skewY);
-        } else if (_units_skew.isRadial()) { //deg or rad
-            double angleX = _scalar_skew_horizontal.getValue("rad");
-            double angleY = _scalar_skew_vertical.getValue("rad");
-            double skewX = tan(-angleX);
-            double skewY = tan(angleY);
-            sp_selection_skew_relative(selection, center, skewX, skewY);
-        } else { // absolute displacement
-            double skewX = _scalar_skew_horizontal.getValue("px");
-            double skewY = _scalar_skew_vertical.getValue("px");
-            sp_selection_skew_relative(selection, center, skewX/height, skewY/width);
+        NR::Maybe<NR::Rect> bbox = selection->bounds();
+        NR::Maybe<NR::Point> center = selection->center();
+
+        if ( bbox && center ) {
+            double width  = bbox->extent(NR::X);
+            double height = bbox->extent(NR::Y);
+
+            if (!_units_skew.isAbsolute()) { // percentage
+                double skewX = _scalar_skew_horizontal.getValue("%");
+                double skewY = _scalar_skew_vertical.getValue("%");
+                sp_selection_skew_relative(selection, *center, 0.01*skewX, 0.01*skewY);
+            } else if (_units_skew.isRadial()) { //deg or rad
+                double angleX = _scalar_skew_horizontal.getValue("rad");
+                double angleY = _scalar_skew_vertical.getValue("rad");
+                double skewX = tan(-angleX);
+                double skewY = tan(angleY);
+                sp_selection_skew_relative(selection, *center, skewX, skewY);
+            } else { // absolute displacement
+                double skewX = _scalar_skew_horizontal.getValue("px");
+                double skewY = _scalar_skew_vertical.getValue("px");
+                sp_selection_skew_relative(selection, *center, skewX/height, skewY/width);
+            }
         }
     }
 
@@ -777,19 +791,20 @@ Transformation::onMoveRelativeToggled()
 
     //g_message("onMoveRelativeToggled: %f, %f px\n", x, y);
 
-    NR::Rect bbox = selection->bounds();
+    NR::Maybe<NR::Rect> bbox = selection->bounds();
 
-    if (_check_move_relative.get_active()) {
-        // From absolute to relative
-        _scalar_move_horizontal.setValue(x - bbox.min()[NR::X], "px");
-        _scalar_move_vertical.setValue(  y - bbox.min()[NR::Y], "px");
-    } else {
-        // From relative to absolute
-        _scalar_move_horizontal.setValue(bbox.min()[NR::X] + x, "px");
-        _scalar_move_vertical.setValue(  bbox.min()[NR::Y] + y, "px");
+    if (bbox) {
+        if (_check_move_relative.get_active()) {
+            // From absolute to relative
+            _scalar_move_horizontal.setValue(x - bbox->min()[NR::X], "px");
+            _scalar_move_vertical.setValue(  y - bbox->min()[NR::Y], "px");
+        } else {
+            // From relative to absolute
+            _scalar_move_horizontal.setValue(bbox->min()[NR::X] + x, "px");
+            _scalar_move_vertical.setValue(  bbox->min()[NR::Y] + y, "px");
+        }
     }
 
-
     set_response_sensitive(Gtk::RESPONSE_APPLY, true);
 }
 
@@ -916,9 +931,11 @@ Transformation::onClear()
             _scalar_move_horizontal.setValue(0);
             _scalar_move_vertical.setValue(0);
         } else {
-            NR::Rect bbox = selection->bounds();
-            _scalar_move_horizontal.setValue(bbox.min()[NR::X], "px");
-            _scalar_move_vertical.setValue(bbox.min()[NR::Y], "px");
+            NR::Maybe<NR::Rect> bbox = selection->bounds();
+            if (bbox) {
+                _scalar_move_horizontal.setValue(bbox->min()[NR::X], "px");
+                _scalar_move_vertical.setValue(bbox->min()[NR::Y], "px");
+            }
         }
         break;
     }
index 25c805c3c30a62490d16c10183170dafbf77def0..cc01706eacd3ba47297a1fa7373c2066946eb313 100644 (file)
@@ -1257,7 +1257,11 @@ ObjectVerb::perform( SPAction *action, void *data, void *pdata )
     if (sel->isEmpty())
         return;
 
-    NR::Point const center(sel->bounds().midpoint());
+    NR::Maybe<NR::Rect> bbox = sel->bounds();
+    if (!bbox) {
+        return;
+    }
+    NR::Point const center(bbox->midpoint());
 
     switch (reinterpret_cast<std::size_t>(data)) {
         case SP_VERB_OBJECT_ROTATE_90_CW:
index ebdc267c1c606148ac09148221790f476b1055bc..fce5ff9b9d2d1a299e0a4702f32bffd12ec8070d 100644 (file)
@@ -58,9 +58,8 @@ sp_selection_layout_widget_update(SPWidget *spw, Inkscape::Selection *sel)
     using NR::X;
     using NR::Y;
     if ( sel && !sel->isEmpty() ) {
-        NR::Rect const bbox(sel->bounds());
-        NR::Point const dimensions(bbox.dimensions());
-        if ((dimensions[X] > 1e-6) || (dimensions[Y] > 1e-6)) {
+        NR::Maybe<NR::Rect> const bbox(sel->bounds());
+        if ( bbox && ( bbox->extent(X) > 1e-6 || bbox->extent(Y) > 1e-6 ) ) {
             GtkWidget *us = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(spw), "units");
             SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(us));
 
@@ -73,10 +72,10 @@ sp_selection_layout_widget_update(SPWidget *spw, Inkscape::Selection *sel)
                 }
             } else {
                 struct { char const *key; double val; } const keyval[] = {
-                    { "X", bbox.min()[X] },
-                    { "Y", bbox.min()[Y] },
-                    { "width", dimensions[X] },
-                    { "height", dimensions[Y] }
+                    { "X", bbox->min()[X] },
+                    { "Y", bbox->min()[Y] },
+                    { "width", bbox->extent(X) },
+                    { "height", bbox->extent(Y) }
                 };
                 for (unsigned i = 0; i < G_N_ELEMENTS(keyval); ++i) {
                     GtkAdjustment *a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), keyval[i].key);
@@ -140,9 +139,9 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw)
     SPDocument *document = sp_desktop_document(desktop);
 
     sp_document_ensure_up_to_date (document);
-    NR::Rect bbox = selection->bounds();
+    NR::Maybe<NR::Rect> bbox = selection->bounds();
 
-    if (!((bbox.max()[NR::X] - bbox.min()[NR::X] > 1e-6) || (bbox.max()[NR::Y] - bbox.min()[NR::Y] > 1e-6))) {
+    if ( !bbox || bbox->extent(NR::X) < 1e-6 || bbox->extent(NR::Y) < 1e-6 ) {
         return;
     }
 
@@ -158,41 +157,41 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw)
         y0 = sp_units_get_pixels (a->value, unit);
         a_w = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "width");
         x1 = x0 + sp_units_get_pixels (a_w->value, unit);
-        xrel = sp_units_get_pixels (a_w->value, unit) / bbox.extent(NR::X);
+        xrel = sp_units_get_pixels (a_w->value, unit) / bbox->extent(NR::X);
         a_h = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "height");
         y1 = y0 + sp_units_get_pixels (a_h->value, unit);
-        yrel = sp_units_get_pixels (a_h->value, unit) / bbox.extent(NR::Y);
+        yrel = sp_units_get_pixels (a_h->value, unit) / bbox->extent(NR::Y);
     } else {
         GtkAdjustment *a;
         a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "X");
         double const x0_propn = a->value * unit.unittobase;
-        x0 = bbox.min()[NR::X] * x0_propn;
+        x0 = bbox->min()[NR::X] * x0_propn;
         a = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "Y");
         double const y0_propn = a->value * unit.unittobase;
-        y0 = y0_propn * bbox.min()[NR::Y];
+        y0 = y0_propn * bbox->min()[NR::Y];
         a_w = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "width");
         xrel = a_w->value * unit.unittobase;
-        x1 = x0 + xrel * bbox.extent(NR::X);
+        x1 = x0 + xrel * bbox->extent(NR::X);
         a_h = (GtkAdjustment *) gtk_object_get_data(GTK_OBJECT(spw), "height");
         yrel = a_h->value * unit.unittobase;
-        y1 = y0 + yrel * bbox.extent(NR::Y);
+        y1 = y0 + yrel * bbox->extent(NR::Y);
     }
 
     // Keep proportions if lock is on
     GtkWidget *lock = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(spw), "lock"));
     if (SP_BUTTON_IS_DOWN(lock)) {
         if (adj == a_h) {
-            x1 = x0 + yrel * bbox.extent(NR::X);
+            x1 = x0 + yrel * bbox->extent(NR::X);
         } else if (adj == a_w) {
-            y1 = y0 + xrel * bbox.extent(NR::Y);
+            y1 = y0 + xrel * bbox->extent(NR::Y);
         }
     }
 
     // scales and moves, in px
-    double mh = fabs(x0 - bbox.min()[NR::X]);
-    double sh = fabs(x1 - bbox.max()[NR::X]);
-    double mv = fabs(y0 - bbox.min()[NR::Y]);
-    double sv = fabs(y1 - bbox.max()[NR::Y]);
+    double mh = fabs(x0 - bbox->min()[NR::X]);
+    double sh = fabs(x1 - bbox->max()[NR::X]);
+    double mv = fabs(y0 - bbox->min()[NR::Y]);
+    double sv = fabs(y1 - bbox->max()[NR::Y]);
 
     // unless the unit is %, convert the scales and moves to the unit
     if (unit.base == SP_UNIT_ABSOLUTE || unit.base == SP_UNIT_DEVICE) {
@@ -220,7 +219,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw)
         gdouble strokewidth = stroke_average_width (selection->itemList());
         int transform_stroke = prefs_get_int_attribute ("options.transform", "stroke", 1);
 
-        NR::Matrix scaler = get_scale_transform_with_stroke (bbox, strokewidth, transform_stroke, x0, y0, x1, y1);
+        NR::Matrix scaler = get_scale_transform_with_stroke (*bbox, strokewidth, transform_stroke, x0, y0, x1, y1);
 
         sp_selection_apply_affine(selection, scaler);
         sp_document_maybe_done (document, actionkey, SP_VERB_CONTEXT_SELECT, 
@@ -289,6 +288,11 @@ static gboolean aux_set_unit(SPUnitSelector *,
         && (new_units->base == SP_UNIT_DIMENSIONLESS))
     {
 
+        NR::Maybe<NR::Rect> bbox = selection->bounds();
+        if (!bbox) {
+            return FALSE;
+        }
+
         /* Absolute to percentage */
         g_object_set_data(dlg, "update", GUINT_TO_POINTER(TRUE));
 
@@ -302,18 +306,21 @@ static gboolean aux_set_unit(SPUnitSelector *,
         double const w = sp_units_get_pixels (aw->value, *old);
         double const h = sp_units_get_pixels (ah->value, *old);
 
-        NR::Rect bbox = selection->bounds();
-
-        gtk_adjustment_set_value(ax, fabs(bbox.min()[NR::X]) > 1e-6? 100.0 * x / bbox.min()[NR::X] : 100.0);
-        gtk_adjustment_set_value(ay, fabs(bbox.min()[NR::Y]) > 1e-6? 100.0 * y / bbox.min()[NR::Y] : 100.0);
-        gtk_adjustment_set_value(aw, fabs(bbox.extent(NR::X)) > 1e-6? 100.0 * w / bbox.extent(NR::X) : 100.0);
-        gtk_adjustment_set_value(ah, fabs(bbox.extent(NR::Y)) > 1e-6? 100.0 * h / bbox.extent(NR::Y) : 100.0);
+        gtk_adjustment_set_value(ax, fabs(bbox->min()[NR::X]) > 1e-6? 100.0 * x / bbox->min()[NR::X] : 100.0);
+        gtk_adjustment_set_value(ay, fabs(bbox->min()[NR::Y]) > 1e-6? 100.0 * y / bbox->min()[NR::Y] : 100.0);
+        gtk_adjustment_set_value(aw, fabs(bbox->extent(NR::X)) > 1e-6? 100.0 * w / bbox->extent(NR::X) : 100.0);
+        gtk_adjustment_set_value(ah, fabs(bbox->extent(NR::Y)) > 1e-6? 100.0 * h / bbox->extent(NR::Y) : 100.0);
 
         g_object_set_data(dlg, "update", GUINT_TO_POINTER(FALSE));
         return TRUE;
     } else if ((old->base == SP_UNIT_DIMENSIONLESS)
                && (new_units->base == SP_UNIT_ABSOLUTE || new_units->base == SP_UNIT_DEVICE)) {
 
+        NR::Maybe<NR::Rect> bbox = selection->bounds();
+        if (!bbox) {
+            return FALSE;
+        }
+
         /* Percentage to absolute */
         g_object_set_data(dlg, "update", GUINT_TO_POINTER(TRUE));
 
@@ -322,12 +329,10 @@ static gboolean aux_set_unit(SPUnitSelector *,
         GtkAdjustment *aw = GTK_ADJUSTMENT(g_object_get_data(dlg, "width"));
         GtkAdjustment *ah = GTK_ADJUSTMENT(g_object_get_data(dlg, "height"));
 
-        NR::Rect bbox = selection->bounds();
-
-        gtk_adjustment_set_value(ax, sp_pixels_get_units(0.01 * ax->value * bbox.min()[NR::X], *new_units));
-        gtk_adjustment_set_value(ay, sp_pixels_get_units(0.01 * ay->value * bbox.min()[NR::Y], *new_units));
-        gtk_adjustment_set_value(aw, sp_pixels_get_units(0.01 * aw->value * bbox.extent(NR::X), *new_units));
-        gtk_adjustment_set_value(ah, sp_pixels_get_units(0.01 * ah->value * bbox.extent(NR::Y), *new_units));
+        gtk_adjustment_set_value(ax, sp_pixels_get_units(0.01 * ax->value * bbox->min()[NR::X], *new_units));
+        gtk_adjustment_set_value(ay, sp_pixels_get_units(0.01 * ay->value * bbox->min()[NR::Y], *new_units));
+        gtk_adjustment_set_value(aw, sp_pixels_get_units(0.01 * aw->value * bbox->extent(NR::X), *new_units));
+        gtk_adjustment_set_value(ah, sp_pixels_get_units(0.01 * ah->value * bbox->extent(NR::Y), *new_units));
 
         g_object_set_data(dlg, "update", GUINT_TO_POINTER(FALSE));
         return TRUE;