X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Ftweak-context.cpp;h=13299b5a4004fef123cb90f05cc659879cd7ca24;hb=99f8079bc0a32aef279e4af06de4cbf4bd853563;hp=c18f89d2efc409c8ee5e1cc659fc4db4abf76b1c;hpb=c651830c7a4b9bf01531370a13958adca17cfd6a;p=inkscape.git diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index c18f89d2e..13299b5a4 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -21,7 +21,6 @@ #include "svg/svg.h" #include "display/canvas-bpath.h" -#include "display/bezier-utils.h" #include #include "macros.h" @@ -30,7 +29,6 @@ #include "desktop.h" #include "desktop-events.h" #include "desktop-handles.h" -#include "desktop-affine.h" #include "desktop-style.h" #include "message-context.h" #include "pixmaps/cursor-tweak-move.xpm" @@ -57,7 +55,6 @@ #include "path-chemistry.h" #include "sp-gradient.h" #include "sp-stop.h" -#include "sp-stop-fns.h" #include "sp-gradient-reference.h" #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" @@ -68,11 +65,15 @@ #include "display/canvas-arena.h" #include "display/curve.h" #include "livarot/Shape.h" -#include "2geom/isnan.h" -#include "prefs-utils.h" +#include <2geom/isnan.h> +#include <2geom/transforms.h> +#include "preferences.h" #include "style.h" #include "box3d.h" #include "sp-item-transform.h" +#include "filter-chemistry.h" +#include "sp-gaussian-blur-fns.h" +#include "sp-gaussian-blur.h" #include "tweak-context.h" @@ -85,7 +86,7 @@ static void sp_tweak_context_init(SPTweakContext *ddc); static void sp_tweak_context_dispose(GObject *object); static void sp_tweak_context_setup(SPEventContext *ec); -static void sp_tweak_context_set(SPEventContext *ec, gchar const *key, gchar const *val); +static void sp_tweak_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val); static gint sp_tweak_context_root_handler(SPEventContext *ec, GdkEvent *event); static SPEventContextClass *parent_class; @@ -184,7 +185,7 @@ bool is_transform_mode (gint mode) bool is_color_mode (gint mode) { - return (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER); + return (mode == TWEAK_MODE_COLORPAINT || mode == TWEAK_MODE_COLORJITTER || mode == TWEAK_MODE_BLUR); } void @@ -197,7 +198,7 @@ sp_tweak_update_cursor (SPTweakContext *tc, bool with_shift) gchar *sel_message = NULL; if (!desktop->selection->isEmpty()) { num = g_slist_length((GSList *) desktop->selection->itemList()); - sel_message = g_strdup_printf(_("%i objects selected"), num); + sel_message = g_strdup_printf(ngettext("%i object selected","%i objects selected",num), num); } else { sel_message = g_strdup_printf(_("Nothing selected")); } @@ -206,23 +207,27 @@ sp_tweak_update_cursor (SPTweakContext *tc, bool with_shift) switch (tc->mode) { case TWEAK_MODE_MOVE: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag to move."), sel_message); - break; event_context->cursor_shape = cursor_tweak_move_xpm; break; case TWEAK_MODE_MOVE_IN_OUT: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to move in; with Shift to move out."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; case TWEAK_MODE_MOVE_JITTER: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to move randomly."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; case TWEAK_MODE_SCALE: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to scale down; with Shift to scale up."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; case TWEAK_MODE_ROTATE: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to rotate clockwise; with Shift, counterclockwise."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; case TWEAK_MODE_MORELESS: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to duplicate; with Shift, delete."), sel_message); + event_context->cursor_shape = cursor_tweak_move_xpm; break; case TWEAK_MODE_PUSH: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag to push paths."), sel_message); @@ -250,11 +255,16 @@ sp_tweak_update_cursor (SPTweakContext *tc, bool with_shift) break; case TWEAK_MODE_COLORPAINT: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to paint objects with color."), sel_message); + event_context->cursor_shape = cursor_color_xpm; break; case TWEAK_MODE_COLORJITTER: tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to randomize colors."), sel_message); event_context->cursor_shape = cursor_color_xpm; break; + case TWEAK_MODE_BLUR: + tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag or click to increase blur; with Shift to decrease."), sel_message); + event_context->cursor_shape = cursor_color_xpm; + break; } sp_event_context_update_cursor(event_context); g_free(sel_message); @@ -266,9 +276,8 @@ sp_tweak_context_style_set(SPCSSAttr const *css, SPTweakContext *tc) if (tc->mode == TWEAK_MODE_COLORPAINT) { // intercept color setting only in this mode // we cannot store properties with uris css = sp_css_attr_unset_uris ((SPCSSAttr *) css); - - sp_repr_css_change (inkscape_get_repr (INKSCAPE, "tools.tweak"), (SPCSSAttr *) css, "style"); - + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setStyle("/tools/tweak/style", const_cast(css)); return true; } return false; @@ -317,44 +326,42 @@ sp_tweak_context_setup(SPEventContext *ec) tc->style_set_connection = ec->desktop->connectSetStyle( // catch style-setting signal in this tool sigc::bind(sigc::ptr_fun(&sp_tweak_context_style_set), tc) ); - - if (prefs_get_int_attribute("tools.tweak", "selcue", 0) != 0) { + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/tools/tweak/selcue")) { ec->enableSelectionCue(); } - if (prefs_get_int_attribute("tools.tweak", "gradientdrag", 0) != 0) { + if (prefs->getBool("/tools/tweak/gradientdrag")) { ec->enableGrDrag(); } } static void -sp_tweak_context_set(SPEventContext *ec, gchar const *key, gchar const *val) +sp_tweak_context_set(SPEventContext *ec, Inkscape::Preferences::Entry *val) { SPTweakContext *tc = SP_TWEAK_CONTEXT(ec); + Glib::ustring path = val->getEntryName(); - if (!strcmp(key, "width")) { - double const dval = ( val ? g_ascii_strtod (val, NULL) : 0.1 ); - tc->width = CLAMP(dval, -1000.0, 1000.0); - } else if (!strcmp(key, "mode")) { - gint64 const dval = ( val ? g_ascii_strtoll (val, NULL, 10) : 0 ); - tc->mode = dval; + if (path == "width") { + tc->width = CLAMP(val->getDouble(0.1), -1000.0, 1000.0); + } else if (path == "mode") { + tc->mode = val->getInt(); sp_tweak_update_cursor(tc, false); - } else if (!strcmp(key, "fidelity")) { - double const dval = ( val ? g_ascii_strtod (val, NULL) : 0.0 ); - tc->fidelity = CLAMP(dval, 0.0, 1.0); - } else if (!strcmp(key, "force")) { - double const dval = ( val ? g_ascii_strtod (val, NULL) : 1.0 ); - tc->force = CLAMP(dval, 0, 1.0); - } else if (!strcmp(key, "usepressure")) { - tc->usepressure = (val && strcmp(val, "0")); - } else if (!strcmp(key, "doh")) { - tc->do_h = (val && strcmp(val, "0")); - } else if (!strcmp(key, "dos")) { - tc->do_s = (val && strcmp(val, "0")); - } else if (!strcmp(key, "dol")) { - tc->do_l = (val && strcmp(val, "0")); - } else if (!strcmp(key, "doo")) { - tc->do_o = (val && strcmp(val, "0")); + } else if (path == "fidelity") { + tc->fidelity = CLAMP(val->getDouble(), 0.0, 1.0); + } else if (path == "force") { + tc->force = CLAMP(val->getDouble(1.0), 0, 1.0); + } else if (path == "usepressure") { + tc->usepressure = val->getBool(); + } else if (path == "doh") { + tc->do_h = val->getBool(); + } else if (path == "dos") { + tc->do_s = val->getBool(); + } else if (path == "dol") { + tc->do_l = val->getBool(); + } else if (path == "doo") { + tc->do_o = val->getBool(); } } @@ -393,7 +400,7 @@ get_move_force (SPTweakContext *tc) } bool -sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Point p, NR::Point vector, gint mode, double radius, double force, double fidelity, bool reverse) +sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::Point p, Geom::Point vector, gint mode, double radius, double force, double fidelity, bool reverse) { bool did = false; @@ -403,20 +410,41 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi selection->add(item); } - if (SP_IS_GROUP(item)) { + if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { + GSList *items = g_slist_prepend (NULL, item); + GSList *selected = NULL; + GSList *to_select = NULL; + SPDocument *doc = SP_OBJECT_DOCUMENT(item); + sp_item_list_to_curves (items, &selected, &to_select); + g_slist_free (items); + SPObject* newObj = doc->getObjectByRepr((Inkscape::XML::Node *) to_select->data); + g_slist_free (to_select); + item = (SPItem *) newObj; + selection->add(item); + } + + if (SP_IS_GROUP(item) && !SP_IS_BOX3D(item)) { + GSList *children = NULL; for (SPObject *child = sp_object_first_child(SP_OBJECT(item)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) { if (SP_IS_ITEM(child)) { - if (sp_tweak_dilate_recursive (selection, SP_ITEM(child), p, vector, mode, radius, force, fidelity, reverse)) - did = true; + children = g_slist_prepend(children, child); } } + for (GSList *i = children; i; i = i->next) { + SPItem *child = SP_ITEM(i->data); + if (sp_tweak_dilate_recursive (selection, SP_ITEM(child), p, vector, mode, radius, force, fidelity, reverse)) + did = true; + } + + g_slist_free(children); + } else { if (mode == TWEAK_MODE_MOVE) { - boost::optional a = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item)); if (a) { - double x = NR::L2(a->midpoint() - p)/radius; + double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * vector; @@ -427,9 +455,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi } else if (mode == TWEAK_MODE_MOVE_IN_OUT) { - boost::optional a = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item)); if (a) { - double x = NR::L2(a->midpoint() - p)/radius; + double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * @@ -441,14 +469,14 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi } else if (mode == TWEAK_MODE_MOVE_JITTER) { - boost::optional a = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item)); if (a) { double dp = g_random_double_range(0, M_PI*2); double dr = g_random_double_range(0, radius); - double x = NR::L2(a->midpoint() - p)/radius; + double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { - Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * NR::Point(cos(dp)*dr, sin(dp)*dr); + Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * Geom::Point(cos(dp)*dr, sin(dp)*dr); sp_item_move_rel(item, Geom::Translate(move[Geom::X], -move[Geom::Y])); did = true; } @@ -456,9 +484,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi } else if (mode == TWEAK_MODE_SCALE) { - boost::optional a = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item)); if (a) { - double x = NR::L2(a->midpoint() - p)/radius; + double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { double scale = 1 + (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1); @@ -469,9 +497,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi } else if (mode == TWEAK_MODE_ROTATE) { - boost::optional a = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item)); if (a) { - double x = NR::L2(a->midpoint() - p)/radius; + double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { double angle = (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1) * M_PI; @@ -482,9 +510,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi } else if (mode == TWEAK_MODE_MORELESS) { - boost::optional a = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect a = item->getBounds(sp_item_i2doc_affine(item)); if (a) { - double x = NR::L2(a->midpoint() - p)/radius; + double x = Geom::L2(a->midpoint() - p)/radius; if (a->contains(p)) x = 0; if (x < 1) { double prob = force * 0.5 * (cos(M_PI * x) + 1); @@ -498,16 +526,22 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi SPDocument *doc = SP_OBJECT_DOCUMENT(item); Inkscape::XML::Document* xml_doc = sp_document_repr_doc(doc); Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item); + SPObject *old_obj = doc->getObjectByRepr(old_repr); Inkscape::XML::Node *parent = old_repr->parent(); Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); parent->appendChild(copy); + SPObject *new_obj = doc->getObjectByRepr(copy); + if (selection->includes(old_obj)) { + selection->add(new_obj); + } Inkscape::GC::release(copy); } + did = true; } } } - } else if (SP_IS_PATH(item) || SP_IS_SHAPE(item) || SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { + } else if (SP_IS_PATH(item) || SP_IS_SHAPE(item)) { Inkscape::XML::Node *newrepr = NULL; gint pos = 0; @@ -528,9 +562,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi // skip those paths whose bboxes are entirely out of reach with our radius - boost::optional bbox = item->getBounds(sp_item_i2doc_affine(item)); + Geom::OptRect bbox = item->getBounds(sp_item_i2doc_affine(item)); if (bbox) { - bbox->growBy(radius); + bbox->expandBy(radius); if (!bbox->contains(p)) { return false; } @@ -566,21 +600,21 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi theRes->ConvertToShape(theShape, fill_nonZero); } - if (NR::L2(vector) != 0) - vector = 1/NR::L2(vector) * vector; + if (Geom::L2(vector) != 0) + vector = 1/Geom::L2(vector) * vector; bool did_this = false; if (mode == TWEAK_MODE_SHRINK_GROW) { if (theShape->MakeTweak(tweak_mode_grow, theRes, reverse? force : -force, join_straight, 4.0, - true, p, NR::Point(0,0), radius, &i2doc) == 0) // 0 means the shape was actually changed + true, p, Geom::Point(0,0), radius, &i2doc) == 0) // 0 means the shape was actually changed did_this = true; } else if (mode == TWEAK_MODE_ATTRACT_REPEL) { if (theShape->MakeTweak(tweak_mode_repel, theRes, reverse? force : -force, join_straight, 4.0, - true, p, NR::Point(0,0), radius, &i2doc) == 0) + true, p, Geom::Point(0,0), radius, &i2doc) == 0) did_this = true; } else if (mode == TWEAK_MODE_PUSH) { if (theShape->MakeTweak(tweak_mode_push, theRes, @@ -592,7 +626,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi if (theShape->MakeTweak(tweak_mode_roughen, theRes, force, join_straight, 4.0, - true, p, NR::Point(0,0), radius, &i2doc) == 0) + true, p, Geom::Point(0,0), radius, &i2doc) == 0) did_this = true; } @@ -759,7 +793,7 @@ tweak_profile (double dist, double radius) void tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, - guint32 const rgb_goal, NR::Point p_w, double radius, double force, guint mode, + guint32 const rgb_goal, Geom::Point p_w, double radius, double force, guint mode, bool do_h, bool do_s, bool do_l, bool /*do_o*/) { SPGradient *gradient = sp_item_gradient (item, fill_or_stroke); @@ -767,8 +801,8 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, if (!gradient || !SP_IS_GRADIENT(gradient)) return; - NR::Matrix i2d (sp_item_i2doc_affine (item)); - NR::Point p = p_w * i2d.inverse(); + Geom::Matrix i2d (sp_item_i2doc_affine (item)); + Geom::Point p = p_w * i2d.inverse(); p *= (gradient->gradientTransform).inverse(); // now p is in gradient's original coordinates @@ -777,27 +811,27 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, if (SP_IS_LINEARGRADIENT(gradient)) { SPLinearGradient *lg = SP_LINEARGRADIENT(gradient); - NR::Point p1(lg->x1.computed, lg->y1.computed); - NR::Point p2(lg->x2.computed, lg->y2.computed); - NR::Point pdiff(p2 - p1); - double vl = NR::L2(pdiff); + Geom::Point p1(lg->x1.computed, lg->y1.computed); + Geom::Point p2(lg->x2.computed, lg->y2.computed); + Geom::Point pdiff(p2 - p1); + double vl = Geom::L2(pdiff); // This is the matrix which moves and rotates the gradient line // so it's oriented along the X axis: - NR::Matrix norm = NR::Matrix(NR::translate(-p1)) * NR::Matrix(NR::rotate(-atan2(pdiff[NR::Y], pdiff[NR::X]))); + Geom::Matrix norm = Geom::Matrix(Geom::Translate(-p1)) * Geom::Matrix(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X]))); // Transform the mouse point by it to find out its projection onto the gradient line: - NR::Point pnorm = p * norm; + Geom::Point pnorm = p * norm; // Scale its X coordinate to match the length of the gradient line: - pos = pnorm[NR::X] / vl; + pos = pnorm[Geom::X] / vl; // Calculate radius in lenfth-of-gradient-line units r = radius / vl; } else if (SP_IS_RADIALGRADIENT(gradient)) { SPRadialGradient *rg = SP_RADIALGRADIENT(gradient); - NR::Point c (rg->cx.computed, rg->cy.computed); - pos = NR::L2(p - c) / rg->r.computed; + Geom::Point c (rg->cx.computed, rg->cy.computed); + pos = Geom::L2(p - c) / rg->r.computed; r = radius / rg->r.computed; } @@ -878,7 +912,8 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, guint32 fill_goal, bool do_fill, guint32 stroke_goal, bool do_stroke, float opacity_goal, bool do_opacity, - NR::Point p, double radius, double force, + bool do_blur, bool reverse, + Geom::Point p, double radius, double force, bool do_h, bool do_s, bool do_l, bool do_o) { bool did = false; @@ -890,6 +925,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, fill_goal, do_fill, stroke_goal, do_stroke, opacity_goal, do_opacity, + do_blur, reverse, p, radius, force, do_h, do_s, do_l, do_o)) did = true; } @@ -900,15 +936,15 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, if (!style) { return false; } - boost::optional bbox = item->getBounds(sp_item_i2doc_affine(item), + Geom::OptRect bbox = item->getBounds(sp_item_i2doc_affine(item), SPItem::GEOMETRIC_BBOX); if (!bbox) { return false; } - NR::Rect brush(p - NR::Point(radius, radius), p + NR::Point(radius, radius)); + Geom::Rect brush(p - Geom::Point(radius, radius), p + Geom::Point(radius, radius)); - NR::Point center = bbox->midpoint(); + Geom::Point center = bbox->midpoint(); double this_force; // if item == item_at_point, use max force @@ -924,11 +960,59 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, // else if object > 0.5 brush: test 4 corners of bbox and center on being in the brush, choose max // else if still smaller, then check only the object center: } else { - this_force = force * tweak_profile (NR::L2 (p - center), radius); + this_force = force * tweak_profile (Geom::L2 (p - center), radius); } if (this_force > 0.002) { + if (do_blur) { + Geom::OptRect bbox = item->getBounds(sp_item_i2doc_affine(item), + SPItem::GEOMETRIC_BBOX); + if (!bbox) { + return did; + } + + double blur_now = 0; + Geom::Matrix i2d = sp_item_i2d_affine (item); + if (style->filter.set && style->getFilter()) { + //cycle through filter primitives + SPObject *primitive_obj = style->getFilter()->children; + while (primitive_obj) { + if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) { + SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj); + //if primitive is gaussianblur + if(SP_IS_GAUSSIANBLUR(primitive)) { + SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive); + float num = spblur->stdDeviation.getNumber(); + blur_now += num * i2d.descrim(); // sum all blurs in the filter + } + } + primitive_obj = primitive_obj->next; + } + } + double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; + blur_now = blur_now / perimeter; + + double blur_new; + if (reverse) + blur_new = blur_now - 0.06 * force; + else + blur_new = blur_now + 0.06 * force; + if (blur_new < 0.0005 && blur_new < blur_now) { + blur_new = 0; + } + + if (blur_new == 0) { + remove_filter(item, false); + } else { + double radius = blur_new * perimeter; + SPFilter *filter = modify_filter_gaussian_blur_from_item(SP_OBJECT_DOCUMENT(item), item, radius); + + sp_style_set_property_url(item, "filter", filter, false); + } + return true; // do not do colors, blur is a separate mode + } + if (do_fill) { if (style->fill.isPaintserver()) { tweak_colors_in_gradient (item, true, fill_goal, p, radius, this_force, mode, do_h, do_s, do_l, do_o); @@ -960,7 +1044,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, bool -sp_tweak_dilate (SPTweakContext *tc, NR::Point event_p, NR::Point p, NR::Point vector, bool reverse) +sp_tweak_dilate (SPTweakContext *tc, Geom::Point event_p, Geom::Point p, Geom::Point vector, bool reverse) { Inkscape::Selection *selection = sp_desktop_selection(SP_EVENT_CONTEXT(tc)->desktop); SPDesktop *desktop = SP_EVENT_CONTEXT(tc)->desktop; @@ -975,9 +1059,41 @@ sp_tweak_dilate (SPTweakContext *tc, NR::Point event_p, NR::Point p, NR::Point v SPItem *item_at_point = SP_EVENT_CONTEXT(tc)->desktop->item_at_point(event_p, TRUE); bool do_fill = false, do_stroke = false, do_opacity = false; - guint32 fill_goal = sp_desktop_get_color_tool(desktop, "tools.tweak", true, &do_fill); - guint32 stroke_goal = sp_desktop_get_color_tool(desktop, "tools.tweak", false, &do_stroke); - double opacity_goal = sp_desktop_get_master_opacity_tool(desktop, "tools.tweak", &do_opacity); + guint32 fill_goal = sp_desktop_get_color_tool(desktop, "/tools/tweak", true, &do_fill); + guint32 stroke_goal = sp_desktop_get_color_tool(desktop, "/tools/tweak", false, &do_stroke); + double opacity_goal = sp_desktop_get_master_opacity_tool(desktop, "/tools/tweak", &do_opacity); + if (reverse) { +#if 0 + // HSL inversion + float hsv[3]; + float rgb[3]; + sp_color_rgb_to_hsv_floatv (hsv, + SP_RGBA32_R_F(fill_goal), + SP_RGBA32_G_F(fill_goal), + SP_RGBA32_B_F(fill_goal)); + sp_color_hsv_to_rgb_floatv (rgb, hsv[0]<.5? hsv[0]+.5 : hsv[0]-.5, 1 - hsv[1], 1 - hsv[2]); + fill_goal = SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1); + sp_color_rgb_to_hsv_floatv (hsv, + SP_RGBA32_R_F(stroke_goal), + SP_RGBA32_G_F(stroke_goal), + SP_RGBA32_B_F(stroke_goal)); + sp_color_hsv_to_rgb_floatv (rgb, hsv[0]<.5? hsv[0]+.5 : hsv[0]-.5, 1 - hsv[1], 1 - hsv[2]); + stroke_goal = SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1); +#else + // RGB inversion + fill_goal = SP_RGBA32_U_COMPOSE( + (255 - SP_RGBA32_R_U(fill_goal)), + (255 - SP_RGBA32_G_U(fill_goal)), + (255 - SP_RGBA32_B_U(fill_goal)), + (255 - SP_RGBA32_A_U(fill_goal))); + stroke_goal = SP_RGBA32_U_COMPOSE( + (255 - SP_RGBA32_R_U(stroke_goal)), + (255 - SP_RGBA32_G_U(stroke_goal)), + (255 - SP_RGBA32_B_U(stroke_goal)), + (255 - SP_RGBA32_A_U(stroke_goal))); +#endif + opacity_goal = 1 - opacity_goal; + } double path_force = get_path_force(tc); if (radius == 0 || path_force == 0) { @@ -998,6 +1114,7 @@ sp_tweak_dilate (SPTweakContext *tc, NR::Point event_p, NR::Point p, NR::Point v fill_goal, do_fill, stroke_goal, do_stroke, opacity_goal, do_opacity, + tc->mode == TWEAK_MODE_BLUR, reverse, p, radius, color_force, tc->do_h, tc->do_s, tc->do_l, tc->do_o)) did = true; } @@ -1017,7 +1134,7 @@ void sp_tweak_update_area (SPTweakContext *tc) { double radius = get_dilate_radius(tc); - NR::Matrix const sm (NR::scale(radius, radius) * NR::translate(SP_EVENT_CONTEXT(tc)->desktop->point())); + Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point())); sp_canvas_item_affine_absolute(tc->dilate_area, sm); sp_canvas_item_show(tc->dilate_area); } @@ -1034,11 +1151,12 @@ sp_tweak_switch_mode (SPTweakContext *tc, gint mode, bool with_shift) void sp_tweak_switch_mode_temporarily (SPTweakContext *tc, gint mode, bool with_shift) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); // Juggling about so that prefs have the old value but tc->mode and the button show new mode: - gint now_mode = prefs_get_int_attribute("tools.tweak", "mode", 0); + gint now_mode = prefs->getInt("/tools/tweak/mode", 0); SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("tweak_tool_mode", mode); // button has changed prefs, restore - prefs_set_int_attribute("tools.tweak", "mode", now_mode); + prefs->setInt("/tools/tweak/mode", now_mode); // changing prefs changed tc->mode, restore back :) tc->mode = mode; sp_tweak_update_cursor (tc, with_shift); @@ -1067,9 +1185,9 @@ sp_tweak_context_root_handler(SPEventContext *event_context, return TRUE; } - NR::Point const button_w(event->button.x, + Geom::Point const button_w(event->button.x, event->button.y); - NR::Point const button_dt(desktop->w2d(button_w)); + Geom::Point const button_dt(desktop->w2d(button_w)); tc->last_push = desktop->dt2doc(button_dt); sp_tweak_extinput(tc, event); @@ -1084,15 +1202,15 @@ sp_tweak_context_root_handler(SPEventContext *event_context, break; case GDK_MOTION_NOTIFY: { - NR::Point const motion_w(event->motion.x, + Geom::Point const motion_w(event->motion.x, event->motion.y); - NR::Point motion_dt(desktop->w2d(motion_w)); - NR::Point motion_doc(desktop->dt2doc(motion_dt)); + Geom::Point motion_dt(desktop->w2d(motion_w)); + Geom::Point motion_doc(desktop->dt2doc(motion_dt)); sp_tweak_extinput(tc, event); // draw the dilating cursor double radius = get_dilate_radius(tc); - NR::Matrix const sm (NR::scale(radius, radius) * NR::translate(desktop->w2d(motion_w))); + Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(desktop->w2d(motion_w))); sp_canvas_item_affine_absolute(tc->dilate_area, sm); sp_canvas_item_show(tc->dilate_area); @@ -1120,8 +1238,8 @@ sp_tweak_context_root_handler(SPEventContext *event_context, case GDK_BUTTON_RELEASE: { - NR::Point const motion_w(event->button.x, event->button.y); - NR::Point const motion_dt(desktop->w2d(motion_w)); + Geom::Point const motion_w(event->button.x, event->button.y); + Geom::Point const motion_dt(desktop->w2d(motion_w)); sp_canvas_end_forced_full_redraws(desktop->canvas); tc->is_drawing = false; @@ -1130,7 +1248,7 @@ sp_tweak_context_root_handler(SPEventContext *event_context, if (!tc->has_dilated) { // if we did not rub, do a light tap tc->pressure = 0.03; - sp_tweak_dilate (tc, motion_w, desktop->dt2doc(motion_dt), NR::Point(0,0), MOD__SHIFT); + sp_tweak_dilate (tc, motion_w, desktop->dt2doc(motion_dt), Geom::Point(0,0), MOD__SHIFT); } tc->is_dilating = false; tc->has_dilated = false; @@ -1183,6 +1301,10 @@ sp_tweak_context_root_handler(SPEventContext *event_context, sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), SP_VERB_CONTEXT_TWEAK, _("Color jitter tweak")); break; + case TWEAK_MODE_BLUR: + sp_document_done(sp_desktop_document(SP_EVENT_CONTEXT(tc)->desktop), + SP_VERB_CONTEXT_TWEAK, _("Blur tweak")); + break; } } break; @@ -1286,6 +1408,13 @@ sp_tweak_context_root_handler(SPEventContext *event_context, ret = TRUE; } break; + case GDK_b: + case GDK_B: + if (MOD__SHIFT_ONLY) { + sp_tweak_switch_mode(tc, TWEAK_MODE_BLUR, MOD__SHIFT); + ret = TRUE; + } + break; case GDK_Up: case GDK_KP_Up: @@ -1365,7 +1494,8 @@ sp_tweak_context_root_handler(SPEventContext *event_context, } break; - case GDK_KEY_RELEASE: + case GDK_KEY_RELEASE: { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); switch (get_group0_keyval(&event->key)) { case GDK_Shift_L: case GDK_Shift_R: @@ -1373,13 +1503,14 @@ sp_tweak_context_root_handler(SPEventContext *event_context, break; case GDK_Control_L: case GDK_Control_R: - sp_tweak_switch_mode (tc, prefs_get_int_attribute("tools.tweak", "mode", 0), MOD__SHIFT); + sp_tweak_switch_mode (tc, prefs->getInt("/tools/tweak/mode"), MOD__SHIFT); tc->_message_context->clear(); break; default: - sp_tweak_switch_mode (tc, prefs_get_int_attribute("tools.tweak", "mode", 0), MOD__SHIFT); + sp_tweak_switch_mode (tc, prefs->getInt("/tools/tweak/mode"), MOD__SHIFT); break; } + } default: break;