X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fobject-edit.cpp;h=1d81aa7f5a86ef2854d5b9771d52c117de8969a0;hb=99f8079bc0a32aef279e4af06de4cbf4bd853563;hp=63e404e4b759269304bed8707ec6ff5731eb5527;hpb=90a3966dd44e306d23febc15ebd65cde07d7a4dd;p=inkscape.git diff --git a/src/object-edit.cpp b/src/object-edit.cpp index 63e404e4b..1d81aa7f5 100644 --- a/src/object-edit.cpp +++ b/src/object-edit.cpp @@ -25,8 +25,7 @@ #include "sp-spiral.h" #include "sp-offset.h" #include "sp-flowtext.h" -#include "prefs-utils.h" -#include "desktop-affine.h" +#include "preferences.h" #include "style.h" #include "desktop.h" #include "desktop-handles.h" @@ -142,14 +141,15 @@ RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*orig //In general we cannot just snap this radius to an arbitrary point, as we have only a single //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap //the radius then we should have a constrained snap. snap_knot_position() is unconstrained + Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(-1, 0))); if (state & GDK_CONTROL_MASK) { gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0; - rect->rx.computed = rect->ry.computed = CLAMP(rect->x.computed + rect->width.computed - p[NR::X], 0.0, temp); + rect->rx.computed = rect->ry.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, temp); rect->rx._set = rect->ry._set = true; } else { - rect->rx.computed = CLAMP(rect->x.computed + rect->width.computed - p[NR::X], 0.0, rect->width.computed / 2.0); + rect->rx.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, rect->width.computed / 2.0); rect->rx._set = true; } @@ -191,18 +191,20 @@ RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*orig //In general we cannot just snap this radius to an arbitrary point, as we have only a single //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap //the radius then we should have a constrained snap. snap_knot_position() is unconstrained + Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(0, 1))); - if (state & GDK_CONTROL_MASK) { + if (state & GDK_CONTROL_MASK) { // When holding control then rx will be kept equal to ry, + // resulting in a perfect circle (and not an ellipse) gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0; - rect->rx.computed = rect->ry.computed = CLAMP(p[NR::Y] - rect->y.computed, 0.0, temp); + rect->rx.computed = rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, temp); rect->ry._set = rect->rx._set = true; } else { if (!rect->rx._set || rect->rx.computed == 0) { - rect->ry.computed = CLAMP(p[NR::Y] - rect->y.computed, + rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, MIN(rect->height.computed / 2.0, rect->width.computed / 2.0)); } else { - rect->ry.computed = CLAMP(p[NR::Y] - rect->y.computed, + rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, rect->height.computed / 2.0); } @@ -257,50 +259,66 @@ void RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &origin, guint state) { SPRect *rect = SP_RECT(item); - Geom::Point const s = snap_knot_position(p); + + Geom::Point s = p; if (state & GDK_CONTROL_MASK) { // original width/height when drag started - gdouble const w_orig = (origin[NR::X] - rect->x.computed); - gdouble const h_orig = (origin[NR::Y] - rect->y.computed); + gdouble const w_orig = (origin[Geom::X] - rect->x.computed); + gdouble const h_orig = (origin[Geom::Y] - rect->y.computed); //original ratio - gdouble const ratio = (w_orig / h_orig); + gdouble ratio = (w_orig / h_orig); // mouse displacement since drag started - gdouble const minx = s[NR::X] - origin[NR::X]; - gdouble const miny = s[NR::Y] - origin[NR::Y]; + gdouble minx = p[Geom::X] - origin[Geom::X]; + gdouble miny = p[Geom::Y] - origin[Geom::Y]; - if (fabs(minx) > fabs(miny)) { + Geom::Point p_handle(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed); + if (fabs(minx) > fabs(miny)) { // snap to horizontal or diagonal - rect->width.computed = MAX(w_orig + minx, 0); if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; rect->height.computed = MAX(h_orig + minx / ratio, 0); } else { // closer to the horizontal, change only width, height is h_orig + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; rect->height.computed = MAX(h_orig, 0); } + rect->width.computed = MAX(w_orig + minx, 0); } else { // snap to vertical or diagonal - rect->height.computed = MAX(h_orig + miny, 0); if (miny != 0 && fabs(minx/miny) > 0.5 * ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; rect->width.computed = MAX(w_orig + miny * ratio, 0); } else { // closer to the vertical, change only height, width is w_orig + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; rect->width.computed = MAX(w_orig, 0); } + rect->height.computed = MAX(h_orig + miny, 0); + } rect->width._set = rect->height._set = true; } else { // move freely - rect->width.computed = MAX(s[NR::X] - rect->x.computed, 0); - rect->height.computed = MAX(s[NR::Y] - rect->y.computed, 0); + s = snap_knot_position(p); + rect->width.computed = MAX(s[Geom::X] - rect->x.computed, 0); + rect->height.computed = MAX(s[Geom::Y] - rect->y.computed, 0); rect->width._set = rect->height._set = true; } @@ -334,58 +352,71 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin gdouble opposite_y = (rect->y.computed + rect->height.computed); // original width/height when drag started - gdouble w_orig = opposite_x - origin[NR::X]; - gdouble h_orig = opposite_y - origin[NR::Y]; + gdouble w_orig = opposite_x - origin[Geom::X]; + gdouble h_orig = opposite_y - origin[Geom::Y]; - Geom::Point const s = snap_knot_position(p); + Geom::Point s = p; + Geom::Point p_handle(rect->x.computed, rect->y.computed); // mouse displacement since drag started - gdouble minx = s[NR::X] - origin[NR::X]; - gdouble miny = s[NR::Y] - origin[NR::Y]; + gdouble minx = p[Geom::X] - origin[Geom::X]; + gdouble miny = p[Geom::Y] - origin[Geom::Y]; if (state & GDK_CONTROL_MASK) { //original ratio gdouble ratio = (w_orig / h_orig); if (fabs(minx) > fabs(miny)) { - // snap to horizontal or diagonal - rect->x.computed = MIN(s[NR::X], opposite_x); - rect->width.computed = MAX(w_orig - minx, 0); if (minx != 0 && fabs(miny/minx) > 0.5 * 1/ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio - rect->y.computed = MIN(origin[NR::Y] + minx / ratio, opposite_y); + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; + rect->y.computed = MIN(origin[Geom::Y] + minx / ratio, opposite_y); rect->height.computed = MAX(h_orig - minx / ratio, 0); } else { // closer to the horizontal, change only width, height is h_orig - rect->y.computed = MIN(origin[NR::Y], opposite_y); + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-1, 0))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; + rect->y.computed = MIN(origin[Geom::Y], opposite_y); rect->height.computed = MAX(h_orig, 0); } - + rect->x.computed = MIN(s[Geom::X], opposite_x); + rect->width.computed = MAX(w_orig - minx, 0); } else { - // snap to vertical or diagonal - rect->y.computed = MIN(s[NR::Y], opposite_y); - rect->height.computed = MAX(h_orig - miny, 0); if (miny != 0 && fabs(minx/miny) > 0.5 *ratio && (SGN(minx) == SGN(miny))) { // closer to the diagonal and in same-sign quarters, change both using ratio - rect->x.computed = MIN(origin[NR::X] + miny * ratio, opposite_x); + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(-ratio, -1))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; + rect->x.computed = MIN(origin[Geom::X] + miny * ratio, opposite_x); rect->width.computed = MAX(w_orig - miny * ratio, 0); } else { // closer to the vertical, change only height, width is w_orig - rect->x.computed = MIN(origin[NR::X], opposite_x); + s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(p_handle, Geom::Point(0, -1))); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; + rect->x.computed = MIN(origin[Geom::X], opposite_x); rect->width.computed = MAX(w_orig, 0); } - + rect->y.computed = MIN(s[Geom::Y], opposite_y); + rect->height.computed = MAX(h_orig - miny, 0); } rect->width._set = rect->height._set = rect->x._set = rect->y._set = true; } else { // move freely - rect->x.computed = MIN(s[NR::X], opposite_x); + s = snap_knot_position(p); + minx = s[Geom::X] - origin[Geom::X]; + miny = s[Geom::Y] - origin[Geom::Y]; + + rect->x.computed = MIN(s[Geom::X], opposite_x); rect->width.computed = MAX(w_orig - minx, 0); - rect->y.computed = MIN(s[NR::Y], opposite_y); + rect->y.computed = MIN(s[Geom::Y], opposite_y); rect->height.computed = MAX(h_orig - miny, 0); rect->width._set = rect->height._set = rect->x._set = rect->y._set = true; } @@ -413,11 +444,11 @@ RectKnotHolder::RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRel "to make the horizontal radius the same"), SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR); entity_wh->create(desktop, item, this, - _("Adjust the width and height of the rectangle; with Ctrl" + _("Adjust the width and height of the rectangle; with Ctrl " "to lock ratio or stretch in one dimension only"), SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR); entity_xy->create(desktop, item, this, - _("Adjust the width and height of the rectangle; with Ctrl" + _("Adjust the width and height of the rectangle; with Ctrl " "to lock ratio or stretch in one dimension only"), SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR); entity.push_back(entity_rx); @@ -729,8 +760,8 @@ public: static gint sp_genericellipse_side(SPGenericEllipse *ellipse, Geom::Point const &p) { - gdouble dx = (p[NR::X] - ellipse->cx.computed) / ellipse->rx.computed; - gdouble dy = (p[NR::Y] - ellipse->cy.computed) / ellipse->ry.computed; + gdouble dx = (p[Geom::X] - ellipse->cx.computed) / ellipse->rx.computed; + gdouble dy = (p[Geom::Y] - ellipse->cy.computed) / ellipse->ry.computed; gdouble s = dx * dx + dy * dy; if (s < 1.0) return 1; @@ -741,7 +772,8 @@ sp_genericellipse_side(SPGenericEllipse *ellipse, Geom::Point const &p) void ArcKnotHolderEntityStart::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { - int snaps = prefs_get_int_attribute("options.rotationsnapsperpi", "value", 12); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); SPGenericEllipse *ge = SP_GENERICELLIPSE(item); SPArc *arc = SP_ARC(item); @@ -772,7 +804,8 @@ ArcKnotHolderEntityStart::knot_get() void ArcKnotHolderEntityEnd::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { - int snaps = prefs_get_int_attribute("options.rotationsnapsperpi", "value", 12); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); SPGenericEllipse *ge = SP_GENERICELLIPSE(item); SPArc *arc = SP_ARC(item); @@ -820,7 +853,7 @@ ArcKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*origi Geom::Point const s = snap_knot_position(p); - ge->rx.computed = fabs( ge->cx.computed - s[NR::X] ); + ge->rx.computed = fabs( ge->cx.computed - s[Geom::X] ); if ( state & GDK_CONTROL_MASK ) { ge->ry.computed = ge->rx.computed; @@ -855,7 +888,7 @@ ArcKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*origi Geom::Point const s = snap_knot_position(p); - ge->ry.computed = fabs( ge->cy.computed - s[NR::Y] ); + ge->ry.computed = fabs( ge->cy.computed - s[Geom::Y] ); if ( state & GDK_CONTROL_MASK ) { ge->rx.computed = ge->ry.computed; @@ -897,7 +930,7 @@ ArcKnotHolder::ArcKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderRelea _("Adjust ellipse height, with Ctrl to make circle"), SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR); entity_start->create(desktop, item, this, - _("Position the start point of the arc or segment; with Ctrl" + _("Position the start point of the arc or segment; with Ctrl " "to snap angle; drag inside the ellipse for arc, outside for segment"), SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR); entity_end->create(desktop, item, this, @@ -1078,19 +1111,26 @@ public: * [control] constrain inner arg to round per PI/4 */ void -SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) +SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) { - int snaps = prefs_get_int_attribute("options.rotationsnapsperpi", "value", 12); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); SPSpiral *spiral = SP_SPIRAL(item); - gdouble dx = p[NR::X] - spiral->cx; - gdouble dy = p[NR::Y] - spiral->cy; + gdouble dx = p[Geom::X] - spiral->cx; + gdouble dy = p[Geom::Y] - spiral->cy; + + gdouble moved_y = p[Geom::Y] - origin[Geom::Y]; if (state & GDK_MOD1_MASK) { // adjust divergence by vertical drag, relative to rad - double new_exp = (spiral->rad + dy)/(spiral->rad); - spiral->exp = new_exp > 0? new_exp : 0; + if (spiral->rad > 0) { + double exp_delta = 0.1*moved_y/(spiral->rad); // arbitrary multiplier to slow it down + spiral->exp += exp_delta; + if (spiral->exp < 1e-3) + spiral->exp = 1e-3; + } } else { // roll/unroll from inside gdouble arg_t0; @@ -1122,12 +1162,13 @@ SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &/ void SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { - int snaps = prefs_get_int_attribute("options.rotationsnapsperpi", "value", 12); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); SPSpiral *spiral = SP_SPIRAL(item); - gdouble dx = p[NR::X] - spiral->cx; - gdouble dy = p[NR::Y] - spiral->cy; + gdouble dx = p[Geom::X] - spiral->cx; + gdouble dy = p[Geom::Y] - spiral->cy; if (state & GDK_SHIFT_MASK) { // rotate without roll/unroll spiral->arg = atan2(dy, dx) - 2.0*M_PI*spiral->revo;