X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fobject-edit.cpp;h=27e75afab1340151367e3dd5db22cdc65f5446ef;hb=5a43b2bbcb81ab7da396dad781d3f9b7854eb002;hp=edb1a0134da11e8c0f462d5cc036e5318bbe1f1c;hpb=513e838dc4544bcc2398b4c1c62a226474f0db31;p=inkscape.git diff --git a/src/object-edit.cpp b/src/object-edit.cpp index edb1a0134..27e75afab 100644 --- a/src/object-edit.cpp +++ b/src/object-edit.cpp @@ -1,5 +1,3 @@ -#define __SP_OBJECT_EDIT_C__ - /* * Node editing extension to objects * @@ -7,6 +5,7 @@ * Lauris Kaplinski * Mitsuru Oka * Maximilian Albert + * Abhishek Sharma * * Licensed under GNU GPL */ @@ -26,7 +25,6 @@ #include "sp-offset.h" #include "sp-flowtext.h" #include "preferences.h" -#include "desktop-affine.h" #include "style.h" #include "desktop.h" #include "desktop-handles.h" @@ -142,14 +140,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::SnapConstraint(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[Geom::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[Geom::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; } @@ -172,7 +171,6 @@ RectKnotHolderEntityRX::knot_click(guint state) SP_OBJECT_REPR(rect)->setAttribute("ry", SP_OBJECT_REPR(rect)->attribute("rx")); } - update_knot(); } Geom::Point @@ -191,18 +189,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::SnapConstraint(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[Geom::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[Geom::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[Geom::Y] - rect->y.computed, + rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, rect->height.computed / 2.0); } @@ -257,7 +257,8 @@ 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 @@ -265,40 +266,55 @@ RectKnotHolderEntityWH::set_internal(Geom::Point const &p, Geom::Point const &or 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[Geom::X] - origin[Geom::X]; - gdouble const miny = s[Geom::Y] - origin[Geom::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::SnapConstraint(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::SnapConstraint(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::SnapConstraint(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::SnapConstraint(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 + 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; @@ -337,52 +353,65 @@ RectKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin 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[Geom::X] - origin[Geom::X]; - gdouble miny = s[Geom::Y] - origin[Geom::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[Geom::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 + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(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 + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(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[Geom::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 + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(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 + s = snap_knot_position_constrained(p, Inkscape::Snapper::SnapConstraint(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 + 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[Geom::Y], opposite_y); @@ -452,7 +481,7 @@ Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom g_assert(item != NULL); SPBox3D *box = SP_BOX3D(item); - Geom::Matrix const i2d (sp_item_i2d_affine (item)); + Geom::Matrix const i2d (item->i2d_affine ()); Box3D::Axis movement; if ((knot_id < 4) != (state & GDK_SHIFT_MASK)) { @@ -628,7 +657,7 @@ Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point co Geom::Point const s = snap_knot_position(new_pos); SPBox3D *box = SP_BOX3D(item); - Geom::Matrix const i2d (sp_item_i2d_affine (item)); + Geom::Matrix const i2d (item->i2d_affine ()); box3d_set_center (SP_BOX3D(item), s * i2d, origin * i2d, !(state & GDK_SHIFT_MASK) ? Box3D::XY : Box3D::Z, state & GDK_CONTROL_MASK); @@ -899,7 +928,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, @@ -1080,7 +1109,7 @@ 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) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); @@ -1090,10 +1119,16 @@ SpiralKnotHolderEntityInner::knot_set(Geom::Point const &p, Geom::Point const &/ 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; @@ -1328,4 +1363,4 @@ FlowtextKnotHolder::FlowtextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotH fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :