17#include <gdk/gdkkeysyms.h>
18#include <glibmm/i18n.h>
58#define DDC_RED_RGBA 0xff0000ff
60#define DYNA_MIN_WIDTH 1.0e-6
66 , pressure(TC_DEFAULT_PRESSURE)
101 if (prefs->
getBool(
"/tools/tweak/selcue")) {
104 if (prefs->
getBool(
"/tools/tweak/gradientdrag")) {
131 gchar *sel_message =
nullptr;
135 sel_message = g_strdup_printf(ngettext(
"<b>%i</b> object selected",
"<b>%i</b> objects selected",
num),
num);
137 sel_message = g_strdup_printf(
"%s", _(
"<b>Nothing</b> selected"));
140 switch (this->
mode) {
168 this->
set_cursor(
"tweak-rotate-counterclockwise.svg");
170 this->
set_cursor(
"tweak-rotate-clockwise.svg");
236 if (path ==
"width") {
238 }
else if (path ==
"mode") {
241 }
else if (path ==
"fidelity") {
243 }
else if (path ==
"force") {
245 }
else if (path ==
"usepressure") {
247 }
else if (path ==
"doh") {
249 }
else if (path ==
"dos") {
251 }
else if (path ==
"dol") {
253 }
else if (path ==
"doo") {
280 force += 4 * (force - 3);
282 return force * tc->
force;
289 return force * tc->
force;
298 auto box = cast<SPBox3D>(
item);
301 item = box->convert_to_group();
306 if (is<SPText>(
item) || is<SPFlowtext>(
item)) {
307 std::vector<SPItem*>
items;
309 std::vector<SPItem*> selected;
310 std::vector<Inkscape::XML::Node*> to_select;
314 item = cast<SPItem>(newObj);
315 g_assert(
item !=
nullptr);
319 if (is<SPGroup>(
item) && !is<SPBox3D>(
item)) {
320 std::vector<SPItem *> children;
322 if (is<SPItem>(&
child)) {
323 children.push_back(cast<SPItem>(&
child));
327 for (
auto i = children.rbegin(); i!= children.rend(); ++i) {
329 g_assert(
child !=
nullptr);
339 double x =
Geom::L2(a->midpoint() - p)/radius;
342 Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) * vector;
352 double x =
Geom::L2(a->midpoint() - p)/radius;
355 Geom::Point move = force * 0.5 * (cos(M_PI * x) + 1) *
356 (reverse? (a->midpoint() - p) : (p - a->midpoint()));
366 double dp = g_random_double_range(0, M_PI*2);
367 double dr = g_random_double_range(0, radius);
368 double x =
Geom::L2(a->midpoint() - p)/radius;
381 double x =
Geom::L2(a->midpoint() - p)/radius;
384 double scale = 1 + (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1);
394 double x =
Geom::L2(a->midpoint() - p)/radius;
397 double angle = (reverse? force : -force) * 0.05 * (cos(M_PI * x) + 1) * M_PI;
408 double x =
Geom::L2(a->midpoint() - p)/radius;
411 double prob = force * 0.5 * (cos(M_PI * x) + 1);
412 double chance = g_random_double_range(0, 1);
413 if (chance <= prob) {
426 selection->
add(new_obj);
435 }
else if (is<SPPath>(
item) || is<SPShape>(
item)) {
440 char const *
id =
nullptr;
441 if (!is<SPPath>(
item)) {
458 bbox->expandBy(radius);
476 orig->ConvertWithBackData((0.08 - (0.07 * fidelity)) / i2doc.
descrim());
477 orig->Fill(theShape, 0);
481 if (val && strcmp(val,
"nonzero") == 0) {
483 }
else if (val && strcmp(val,
"evenodd") == 0) {
490 vector = 1/
Geom::L2(vector) * vector;
493 bool did_this =
false;
496 reverse? force : -force,
502 reverse? force : -force,
510 true, p, force*2*vector, radius, &i2doc) == 0)
527 double th_max = (0.6 - 0.59*sqrt(fidelity)) / i2doc.
descrim();
528 double threshold =
MAX(th_max, th_max*force);
545 parent->addChildAtPos(newrepr, pos);
548 selection->
add(newrepr);
556 auto lpeitem = cast<SPLPEItem>(
item);
557 if (lpeitem && lpeitem->hasPathEffectRecursive()) {
591 unsigned int pin = (do_h * 1) + (do_s * 2) + (do_l * 4);
593 hsl->
average(goal, force, pin);
595 hsl->jitter(force, pin);
597 if (
auto copy = hsl->converted(color.
getSpace()))
613 double opacity = SP_SCALE24_TO_FLOAT (style_opacity->
value);
616 double d = opacity_goal - opacity;
617 opacity += d * force;
619 opacity += g_random_double_range(-opacity, 1 - opacity) * force;
622 style_opacity->
value = SP_SCALE24_FROM_FLOAT(opacity);
632 double x = dist / radius;
639 return (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5);
645 bool do_h,
bool do_s,
bool do_l,
bool )
658 auto lg = cast<SPLinearGradient>(gradient);
659 auto rg = cast<SPRadialGradient>(gradient);
688 r = radius / rg->r.computed;
701 if (pos > 1 || pos < 0) {
702 pos_e = pos -
floor(pos);
705 if (pos > 1 || pos < 0) {
706 bool odd = ((int)(
floor(pos)) % 2 == 1);
707 pos_e = pos -
floor(pos);
720 auto stop = cast<SPStop>(&
child);
725 offset_h = stop->offset;
728 auto prevStop = cast<SPStop>(child_prev);
729 g_assert(prevStop !=
nullptr);
731 if (offset_h - offset_l > r && pos_e >= offset_l && pos_e <= offset_h) {
737 force * (pos_e - offset_l) / (offset_h - offset_l),
740 force * (offset_h - pos_e) / (offset_h - offset_l),
748 if (offset_l <= pos_e && offset_l > pos_e - r) {
755 if (offset_h >= pos_e && offset_h < pos_e + r) {
769 auto mg = cast<SPMeshGradient>(gradient);
771 auto mg_array = cast<SPMeshGradient>(mg->getArray());
774 for(
unsigned i=0; i < array->
nodes.size(); i+=3 ) {
775 for(
unsigned j=0; j < array->
nodes[i].size(); j+=3 ) {
789 std::optional<Color> &fill_goal, std::optional<Color> &stroke_goal,
790 float opacity_goal,
bool do_opacity,
791 bool do_blur,
bool reverse,
793 bool do_h,
bool do_s,
bool do_l,
bool do_o)
797 if (is<SPGroup>(
item)) {
799 auto childItem = cast<SPItem>(&
child);
802 fill_goal, stroke_goal,
803 opacity_goal, do_opacity,
805 p, radius, force, do_h, do_s, do_l, do_o)) {
827 if (
item == item_at_point) {
842 if (this_force > 0.002) {
855 auto primitive = cast<SPFilterPrimitive>(&primitive_obj);
858 auto spblur = cast<SPGaussianBlur>(primitive);
860 float num = spblur->get_std_deviation().getNumber();
866 double perimeter = bbox->dimensions()[
Geom::X] + bbox->dimensions()[
Geom::Y];
867 blur_now = blur_now / perimeter;
871 blur_new = blur_now - 0.06 * force;
873 blur_new = blur_now + 0.06 * force;
875 if (blur_new < 0.0005 && blur_new < blur_now) {
881 double radius = blur_new * perimeter;
889 if (style->
fill.isPaintserver()) {
890 tweak_colors_in_gradient(
item,
Inkscape::FOR_FILL, *fill_goal, p, radius, this_force,
mode, do_h, do_s, do_l, do_o);
892 }
else if (style->
fill.isColor()) {
899 if (style->
stroke.isPaintserver()) {
900 tweak_colors_in_gradient(
item,
Inkscape::FOR_STROKE, *stroke_goal, p, radius, this_force,
mode, do_h, do_s, do_l, do_o);
902 }
else if (style->
stroke.isColor()) {
908 if (do_opacity && do_o) {
933 bool do_opacity =
false;
941 stroke_goal->invert();
942 opacity_goal = 1 - opacity_goal;
946 if (radius == 0 || path_force == 0) {
950 double color_force =
MIN(sqrt(path_force)/20.0, 1);
953 std::vector<SPItem*>
items(selection->
items().begin(), selection->
items().end());
956 if (fill_goal || stroke_goal || do_opacity) {
958 fill_goal, stroke_goal,
959 opacity_goal, do_opacity,
999 std::cerr <<
"Could not access Tweak toolbar" << std::endl;
1012 gint now_mode = prefs->
getInt(
"/tools/tweak/mode", 0);
1019 std::cerr <<
"Could not access Tweak toolbar" << std::endl;
1023 prefs->
setInt(
"/tools/tweak/mode", now_mode);
1041 if (event.num_press == 1 && event.button == 1) {
1108 text = _(
"Move tweak");
1111 text = _(
"Move in/out tweak");
1114 text = _(
"Move jitter tweak");
1117 text = _(
"Scale tweak");
1120 text = _(
"Rotate tweak");
1123 text = _(
"Duplicate/delete tweak");
1126 text = _(
"Push path tweak");
1129 text = _(
"Shrink/grow path tweak");
1132 text = _(
"Attract/repel path tweak");
1135 text = _(
"Roughen path tweak");
1138 text = _(
"Color paint tweak");
1141 text = _(
"Color jitter tweak");
1144 text = _(
"Blur tweak");
1178 case GDK_KEY_greater:
1179 case GDK_KEY_period:
1186 case GDK_KEY_bracketright:
1187 case GDK_KEY_bracketleft:
1268 case GDK_KEY_KP_Down:
1279 case GDK_KEY_KP_Right:
1291 case GDK_KEY_KP_Left:
1303 case GDK_KEY_KP_Home:
1310 case GDK_KEY_KP_End:
1324 case GDK_KEY_Shift_L:
1325 case GDK_KEY_Shift_R:
1329 case GDK_KEY_Control_L:
1330 case GDK_KEY_Control_R:
1333 case GDK_KEY_Delete:
1334 case GDK_KEY_KP_Delete:
1335 case GDK_KEY_BackSpace:
1346 case GDK_KEY_Shift_L:
1347 case GDK_KEY_Shift_R:
1350 case GDK_KEY_Control_L:
1351 case GDK_KEY_Control_R:
TODO: insert short description here.
double distance(Shape const *s, Geom::Point const &p)
TODO: insert short description here.
3x3 matrix representing an affine transformation.
Coord descrim() const
Calculate the descriminant.
Affine inverse() const
Compute the inverse matrix.
Affine withoutTranslation() const
Set of all points at a fixed distance from the center.
bool contains(CRect const &r) const
Check whether the rectangle includes all points in the given rectangle.
bool intersects(CRect const &r) const
Check whether the rectangles have any common points.
Axis-aligned rectangle that can be empty.
Sequence of contiguous curves, aka spline.
Two-dimensional point that doubles as a vector.
Axis aligned, non-empty rectangle.
Rotation around the origin.
std::optional< Color > converted(Color const &other) const
Return a copy of this color converted to the same format as the other color.
void average(Color const &other, double pos=0.5, unsigned int pin=0)
std::shared_ptr< Space::AnySpace > const & getSpace() const
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
SPDesktop * desktop()
Returns the desktop the selection is bound to.
SPItemRange items()
Returns a range of selected SPItems.
bool isEmpty()
Returns true if no items are selected.
Data type representing a typeless value of a preference.
double getDouble(double def=0.0, Glib::ustring const &unit="") const
Interpret the preference as a floating point value.
Glib::ustring getEntryName() const
Get the last component of the preference's path.
bool getBool(bool def=false) const
Interpret the preference as a Boolean value.
int getInt(int def=0) const
Interpret the preference as an integer.
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
void setStyle(Glib::ustring const &pref_path, SPCSSAttr *style)
Set a CSS style.
static Preferences * get()
Access the singleton Preferences object.
int getInt(Glib::ustring const &pref_path, int def=0)
Retrieve an integer.
void setInt(Glib::ustring const &pref_path, int value)
Set an integer value.
The set of selected SPObjects for a given document and layer model.
void add(XML::Node *repr)
Add an XML node's SPObject to the set of selected objects.
void remove(XML::Node *repr)
Removes an item from the set of selected objects.
bool includes(XML::Node *repr, bool anyAncestor=false)
Returns true if the given item is selected.
Interface for refcounted XML nodes.
virtual Node * parent()=0
Get the parent of this node.
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual Node * duplicate(Document *doc) const =0
Create a duplicate of this node.
virtual unsigned position() const =0
Get the index of this node in parent's child order.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
Path and its polyline approximation.
void SetBackData(bool nVal)
Sets the back variable to the value passed in and clears the polyline approximation.
std::string svg_dump_path() const
void ConvertEvenLines(double treshhold)
Creates a polyline approximation of the path.
std::vector< PathDescr * > descr_cmd
void Simplify(double treshhold)
Simplify the path.
void Reset()
Clears all stored path commands and resets flags that are used by command functions while adding path...
To do: update description of desktop.
double current_zoom() const
SPDocument * getDocument() const
void setToolboxFocusTo(char const *label)
Inkscape::CanvasItemGroup * getCanvasSketch() const
Geom::Affine const & dt2doc() const
Geom::Point point() const
Returns the mouse point in desktop coordinates; if mouse is outside the canvas, returns the center of...
SPItem * getItemAtPoint(Geom::Point const &p, bool into_groups, SPItem *upto=nullptr) const
Gtk::Widget * get_toolbar_by_name(Glib::ustring const &name)
Inkscape::Selection * getSelection() const
sigc::connection connectSetStyle(F &&slot)
void setToolboxAdjustmentValue(char const *id, double val)
Geom::Affine const & doc2dt() const
Geom::Affine const & w2d() const
Transformation from window to desktop coordinates (zoom/rotate).
Typed SVG document implementation.
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
SPObject * getObjectByRepr(Inkscape::XML::Node *repr) const
Geom::Affine gradientTransform
gradientTransform attribute
SPGradientSpread getSpread() const
24 bit data type internal to SPStyle.
Base class for visual SVG elements.
void scale_rel(Geom::Scale const &scale)
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
Geom::OptRect documentVisualBounds() const
Get item's visual bbox in document coordinate system.
Geom::OptRect documentGeometricBounds() const
Get item's geometric bbox in document coordinate system.
void rotate_rel(Geom::Rotate const &rotation)
void move_rel(Geom::Translate const &tr)
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
std::vector< std::vector< SPMeshNode * > > nodes
SPObject is an abstract base class of all of the document nodes at the SVG document level.
void setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
void deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
void setColor(Inkscape::Colors::Color const &color)
Sets the stop color and stop opacity in the style attribute.
Inkscape::Colors::Color getColor() const
T< SPAttr::FILL, SPIPaint > fill
fill
T< SPAttr::STROKE, SPIPaint > stroke
stroke
T< SPAttr::OPACITY, SPIScale24 > opacity
opacity
T< SPAttr::FILTER, SPIFilter > filter
Filter effect.
A class to store/manipulate directed graphs.
void ConvertToForme(Path *dest)
Extract contours from a directed graph.
int MakeTweak(int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Affine *i2doc)
int ConvertToShape(Shape *a, FillRule directed=fill_nonZero, bool invert=false)
Using a given fill rule, find all intersections in the shape given, create a new intersection free sh...
std::shared_ptr< Css const > css
double sp_desktop_get_master_opacity_tool(SPDesktop *desktop, Glib::ustring const &tool, bool *has_opacity)
std::optional< Color > sp_desktop_get_color_tool(SPDesktop *desktop, Glib::ustring const &tool, bool is_fill)
Editable view implementation.
static char const *const parent
TODO: insert short description here.
void remove_filter(SPObject *item, bool recursive)
SPFilter * modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *item, gdouble radius)
Modifies the gaussian blur applied to the item.
SVG Gaussian blur filter effect.
SPGradient * sp_gradient_get_forked_vector_if_necessary(SPGradient *gradient, bool force_vector)
Obtain the vector from the gradient.
SPGradient * getGradient(SPItem *item, Inkscape::PaintTarget fill_or_stroke)
Fetches either the fill or the stroke gradient from the given item.
auto floor(Geom::Rect const &rect)
Macro for icon names used in Inkscape.
Interface for locally managing a current status message.
SBasis L2(D2< SBasis > const &a, unsigned k)
static R & release(R &r)
Decrements the reference count of a anchored object.
void inspect_event(E &&event, Fs... funcs)
Perform pattern-matching on a CanvasEvent.
bool mod_ctrl_only(unsigned modifiers)
bool mod_shift_only(unsigned modifiers)
bool mod_shift(unsigned modifiers)
bool mod_alt_only(unsigned modifiers)
bool have_viable_layer(SPDesktop *desktop, MessageContext *message)
Check to see if the current layer is both unhidden and unlocked.
Inkscape::XML::Node * sp_selected_item_to_curved_repr(SPItem *item, guint32)
bool sp_item_list_to_curves(const std::vector< SPItem * > &items, std::vector< SPItem * > &selected, std::vector< Inkscape::XML::Node * > &to_select, bool skip_all_lpeitems)
std::unique_ptr< Path > Path_for_item(SPItem *item, bool doTransformation, bool transformFull)
Creates a Livarot Path object from an SPItem.
SPCSSAttr * sp_repr_css_attr(Node const *repr, gchar const *attr)
Creates a new SPCSSAttr with one attribute (i.e.
char const * sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval)
Returns a character string of the value of a given style property or a default value if the attribute...
TODO: insert short description here.
@ SP_GRADIENT_SPREAD_REPEAT
@ SP_GRADIENT_SPREAD_REFLECT
TODO: insert short description here.
TODO: insert short description here.
TODO: insert short description here.
TODO: insert short description here.
Abstract base class for events.
unsigned modifiers
The modifiers mask immediately before the event.
The pointer has entered a widget or item.
The pointer has exited a widget or item.
Movement of the mouse pointer.
Interface for XML documents.
void sp_style_set_property_url(SPObject *item, gchar const *property, SPObject *linked, bool recursive)
SPCSSAttr * sp_css_attr_unset_uris(SPCSSAttr *css)
Unset any properties that contain URI values.
SPStyle - a style object for SPItem objects.