From d414fe3e051a6fced9010f6b610fdca5c7285304 Mon Sep 17 00:00:00 2001 From: mental Date: Sun, 11 Mar 2007 19:57:07 +0000 Subject: [PATCH] Switch selection bounds and center to use NR::Maybe, addressing most of the recent bbox regressions. --- src/desktop.cpp | 6 +- src/dialogs/export.cpp | 4 +- src/dialogs/object-properties.cpp | 24 ++-- src/dialogs/tiledialog.cpp | 8 +- src/extension/internal/grid.cpp | 5 +- src/file.cpp | 7 +- src/interface.cpp | 7 +- src/selection-chemistry.cpp | 88 ++++++++------ src/selection.cpp | 61 ++-------- src/selection.h | 18 +-- src/seltrans.cpp | 117 +++++++++++-------- src/seltrans.h | 5 +- src/splivarot.cpp | 7 +- src/ui/dialog/align-and-distribute.cpp | 17 ++- src/ui/dialog/transformation.cpp | 155 ++++++++++++++----------- src/verbs.cpp | 6 +- src/widgets/select-toolbar.cpp | 73 ++++++------ 17 files changed, 327 insertions(+), 281 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index d159fbc78..5fa251842 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -855,13 +855,13 @@ SPDesktop::zoom_page_width() void SPDesktop::zoom_selection() { - NR::Rect const d = selection->bounds(); + NR::Maybe 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); } /** diff --git a/src/dialogs/export.cpp b/src/dialogs/export.cpp index 4dfdbbb5e..c6d7e89d8 100644 --- a/src/dialogs/export.cpp +++ b/src/dialogs/export.cpp @@ -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 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; } } diff --git a/src/dialogs/object-properties.cpp b/src/dialogs/object-properties.cpp index 53b9aa8cc..4db82385a 100644 --- a/src/dialogs/object-properties.cpp +++ b/src/dialogs/object-properties.cpp @@ -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 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 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 diff --git a/src/dialogs/tiledialog.cpp b/src/dialogs/tiledialog.cpp index b10f952da..75311ddd0 100644 --- a/src/dialogs/tiledialog.cpp +++ b/src/dialogs/tiledialog.cpp @@ -268,14 +268,14 @@ void TileDialog::Grid_Arrange () } + NR::Maybe 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); } /* diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index 87e0c14ac..061035eac 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -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 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]), diff --git a/src/file.cpp b/src/file.cpp index f4630719b..c1d035545 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -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 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); } } diff --git a/src/interface.cpp b/src/interface.cpp index 83f4ac3c8..dad1146c0 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -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 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); } diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 171928865..5fa5b0d7e 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -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 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 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 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 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 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 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 const bbox(selection->bounds()); + NR::Maybe 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 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 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 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); diff --git a/src/selection.cpp b/src/selection.cpp index d39086e8c..c6b307c3b 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -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 Selection::bounds() const { GSList const *items = const_cast(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 - 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 Selection::boundsInDocument() const { NRRect r; - NR::Maybe 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 Selection::center() const { GSList *items = (GSList *) const_cast(this)->itemList(); NR::Point center; if (items) { SPItem *first = reinterpret_cast(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 bbox = bounds(); + if (bbox) { + return bounds()->midpoint(); } else { - center = bounds().midpoint(); + return NR::Nothing(); } - return center; } /** @@ -417,28 +402,6 @@ std::vector Selection::getSnapPointsConvexHull() const { return pHull; } -std::vector Selection::getBBoxPoints() const { - GSList const *items = const_cast(this)->itemList(); - std::vector p; - for (GSList const *iter = items; iter != NULL; iter = iter->next) { - NR::Maybe 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 Selection::getBBoxPointsOuter() const { - std::vector 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 ) { diff --git a/src/selection.h b/src/selection.h index bae368e81..f9368f5ee 100644 --- a/src/selection.h +++ b/src/selection.h @@ -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 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 boundsInDocument() const; /** * @brief Returns the rotation/skew center of the selection */ - ::NR::Point center() const; + NR::Maybe center() const; /** * @brief Gets the selection's snap points. @@ -266,18 +266,6 @@ public: */ std::vector getSnapPointsConvexHull() const; - /** - * @return A vector containing the top-left and bottom-right - * corners of each selected object's bounding box. - */ - std::vector getBBoxPoints() const; - - /** - * @return A vector containing the 2 (bottom-left and upper-right) - * corners of the selection bounding box. - */ - std::vector getBBoxPointsOuter() const; - /** * @brief Connects a slot to be notified of selection changes * diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 5368628b8..a1a200282 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -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::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::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 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)); } diff --git a/src/seltrans.h b/src/seltrans.h index 8d527ca5c..e8aee252e 100644 --- a/src/seltrans.h +++ b/src/seltrans.h @@ -105,7 +105,6 @@ private: std::vector _snap_points; std::vector _bbox_points; - std::vector _bbox_4points; Inkscape::SelCue _selcue; @@ -118,12 +117,12 @@ private: bool _empty; bool _changed; - NR::Rect _box; + NR::Maybe _box; gdouble _strokewidth; NR::Matrix _current; NR::Point _opposite; ///< opposite point to where a scale is taking place - NR::Point _center; + NR::Maybe _center; bool _center_is_set; ///< we've already set _center, no need to reread it from items SPKnot *_shandle[8]; diff --git a/src/splivarot.cpp b/src/splivarot.cpp index cf07fba16..f5f0a6481 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -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 selectionBbox = selection->bounds(); + if (!selectionBbox) { + return false; + } + gdouble selectionSize = L2(selectionBbox->dimensions()); gdouble simplifySize = selectionSize; diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index c1f4a10a1..7c5908e58 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -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 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 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; } diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index 90cac7425..98623849f 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -455,13 +455,14 @@ Transformation::updatePageMove(Inkscape::Selection *selection) { if (selection && !selection->isEmpty()) { if (!_check_move_relative.get_active()) { + NR::Maybe 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 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 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 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 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 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 bbox = selection->bounds(); + NR::Maybe 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 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 bbox = selection->bounds(); + if (bbox) { + _scalar_move_horizontal.setValue(bbox->min()[NR::X], "px"); + _scalar_move_vertical.setValue(bbox->min()[NR::Y], "px"); + } } break; } diff --git a/src/verbs.cpp b/src/verbs.cpp index 25c805c3c..cc01706ea 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -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 bbox = sel->bounds(); + if (!bbox) { + return; + } + NR::Point const center(bbox->midpoint()); switch (reinterpret_cast(data)) { case SP_VERB_OBJECT_ROTATE_90_CW: diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp index ebdc267c1..fce5ff9b9 100644 --- a/src/widgets/select-toolbar.cpp +++ b/src/widgets/select-toolbar.cpp @@ -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 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 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 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 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; -- 2.30.2