summaryrefslogtreecommitdiffstats
path: root/src/ui/tools/spray-tool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/tools/spray-tool.cpp')
-rw-r--r--src/ui/tools/spray-tool.cpp225
1 files changed, 119 insertions, 106 deletions
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 0ded1e44b..08d3119a1 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -79,6 +79,11 @@ using namespace std;
#define DDC_RED_RGBA 0xff0000ff
#define DYNA_MIN_WIDTH 1.0e-6
+// Disabled in 0.91 because of Bug #1274831 (crash, spraying an object
+// with the mode: spray object in single path)
+// Please enable again when working on 1.0
+#define ENABLE_SPRAY_MODE_SINGLE_PATH
+
#include "tool-factory.h"
namespace Inkscape {
@@ -86,15 +91,15 @@ namespace UI {
namespace Tools {
namespace {
- ToolBase* createSprayContext() {
- return new SprayTool();
- }
+ ToolBase* createSprayContext() {
+ return new SprayTool();
+ }
- bool sprayContextRegistered = ToolFactory::instance().registerObject("/tools/spray", createSprayContext);
+ bool sprayContextRegistered = ToolFactory::instance().registerObject("/tools/spray", createSprayContext);
}
const std::string& SprayTool::getPrefsPath() {
- return SprayTool::prefsPath;
+ return SprayTool::prefsPath;
}
const std::string SprayTool::prefsPath = "/tools/spray";
@@ -114,9 +119,9 @@ inline double NormalDistribution(double mu, double sigma)
static void sp_spray_rotate_rel(Geom::Point c, SPDesktop */*desktop*/, SPItem *item, Geom::Rotate const &rotation)
{
Geom::Translate const s(c);
- Geom::Affine affine = Geom::Affine(s).inverse() * Geom::Affine(rotation) * Geom::Affine(s);
+ Geom::Affine affine = s.inverse() * rotation * s;
// Rotate item.
- item->set_i2d_affine(item->i2dt_affine() * (Geom::Affine)affine);
+ item->set_i2d_affine(item->i2dt_affine() * affine);
// Use each item's own transform writer, consistent with sp_selection_apply_affine()
item->doWriteTransform(item->getRepr(), item->transform);
// Restore the center position (it's changed because the bbox center changed)
@@ -134,35 +139,30 @@ static void sp_spray_scale_rel(Geom::Point c, SPDesktop */*desktop*/, SPItem *it
item->doWriteTransform(item->getRepr(), item->transform);
}
-SprayTool::SprayTool() : ToolBase() {
- this->usetilt = 0;
- this->dilate_area = 0;
- this->usetext = false;
- this->population = 0;
- this->is_drawing = false;
- this->mode = 0;
- this->usepressure = 0;
-
- this->cursor_shape = cursor_spray_xpm;
- this->hot_x = 4;
- this->hot_y = 4;
-
- /* attributes */
- this->dragging = FALSE;
- this->distrib = 1;
- this->width = 0.2;
- this->force = 0.2;
- this->ratio = 0;
- this->tilt = 0;
- this->mean = 0.2;
- this->rotation_variation = 0;
- this->standard_deviation = 0.2;
- this->scale = 1;
- this->scale_variation = 1;
- this->pressure = TC_DEFAULT_PRESSURE;
-
- this->is_dilating = false;
- this->has_dilated = false;
+SprayTool::SprayTool()
+ : ToolBase(cursor_spray_xpm, 4, 4, false)
+ , pressure(TC_DEFAULT_PRESSURE)
+ , dragging(false)
+ , usepressure(0)
+ , usetilt(0)
+ , usetext(false)
+ , width(0.2)
+ , ratio(0)
+ , tilt(0)
+ , rotation_variation(0)
+ , force(0.2)
+ , population(0)
+ , scale_variation(1)
+ , scale(1)
+ , mean(0.2)
+ , standard_deviation(0.2)
+ , distrib(1)
+ , mode(0)
+ , is_drawing(false)
+ , is_dilating(false)
+ , has_dilated(false)
+ , dilate_area(NULL)
+{
}
SprayTool::~SprayTool() {
@@ -194,22 +194,22 @@ void SprayTool::update_cursor(bool /*with_shift*/) {
sel_message = g_strdup_printf("%s", _("<b>Nothing</b> selected"));
}
- switch (this->mode) {
- case SPRAY_MODE_COPY:
- this->message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or click and scroll to spray <b>copies</b> of the initial selection."), sel_message);
- break;
- case SPRAY_MODE_CLONE:
- this->message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or click and scroll to spray <b>clones</b> of the initial selection."), sel_message);
- break;
- case SPRAY_MODE_SINGLE_PATH:
- this->message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or click and scroll to spray in a <b>single path</b> of the initial selection."), sel_message);
- break;
- default:
- break;
- }
-
- this->sp_event_context_update_cursor();
- g_free(sel_message);
+ switch (this->mode) {
+ case SPRAY_MODE_COPY:
+ this->message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or click and scroll to spray <b>copies</b> of the initial selection."), sel_message);
+ break;
+ case SPRAY_MODE_CLONE:
+ this->message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or click and scroll to spray <b>clones</b> of the initial selection."), sel_message);
+ break;
+ case SPRAY_MODE_SINGLE_PATH:
+ this->message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or click and scroll to spray in a <b>single path</b> of the initial selection."), sel_message);
+ break;
+ default:
+ break;
+ }
+
+ this->sp_event_context_update_cursor();
+ g_free(sel_message);
}
void SprayTool::setup() {
@@ -404,7 +404,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
SPItem *item_copied;
if(_fid <= population)
{
- // duplicate
+ // Duplicate
SPDocument *doc = item->document;
Inkscape::XML::Document* xml_doc = doc->getReprDoc();
Inkscape::XML::Node *old_repr = item->getRepr();
@@ -413,24 +413,24 @@ static bool sp_spray_recursive(SPDesktop *desktop,
parent->appendChild(copy);
SPObject *new_obj = doc->getObjectByRepr(copy);
- item_copied = SP_ITEM(new_obj); //convertion object->item
+ item_copied = SP_ITEM(new_obj); // Convertion object->item
Geom::Point center=item->getCenter();
sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(_scale,_scale));
sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(scale,scale));
sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle));
- //Move the cursor p
+ // Move the cursor p
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
did = true;
}
}
+#ifdef ENABLE_SPRAY_MODE_SINGLE_PATH
} else if (mode == SPRAY_MODE_SINGLE_PATH) {
- SPItem *father = NULL; //initial Object
- SPItem *item_copied = NULL; //Projected Object
- SPItem *unionResult = NULL; //previous union
- SPItem *son = NULL; //father copy
+ SPItem *parent_item = NULL; // Initial object
+ SPItem *item_copied = NULL; // Projected object
+ SPItem *unionResult = NULL; // Previous union
int i=1;
for (GSList *items = g_slist_copy(const_cast<GSList *>(selection->itemList()));
@@ -439,55 +439,49 @@ static bool sp_spray_recursive(SPDesktop *desktop,
SPItem *item1 = SP_ITEM(items->data);
if (i == 1) {
- father = item1;
+ parent_item = item1;
}
if (i == 2) {
unionResult = item1;
}
i++;
}
- SPDocument *doc = father->document;
+ SPDocument *doc = parent_item->document;
Inkscape::XML::Document* xml_doc = doc->getReprDoc();
- Inkscape::XML::Node *old_repr = father->getRepr();
+ Inkscape::XML::Node *old_repr = parent_item->getRepr();
Inkscape::XML::Node *parent = old_repr->parent();
- Geom::OptRect a = father->documentVisualBounds();
+ Geom::OptRect a = parent_item->documentVisualBounds();
if (a) {
- if (i == 2) {
- Inkscape::XML::Node *copy1 = old_repr->duplicate(xml_doc);
- parent->appendChild(copy1);
- SPObject *new_obj1 = doc->getObjectByRepr(copy1);
- son = SP_ITEM(new_obj1); // conversion object->item
- unionResult = son;
- Inkscape::GC::release(copy1);
- }
-
if (_fid <= population) { // Rules the population of objects sprayed
- // duplicates the father
- Inkscape::XML::Node *copy2 = old_repr->duplicate(xml_doc);
- parent->appendChild(copy2);
- SPObject *new_obj2 = doc->getObjectByRepr(copy2);
- item_copied = SP_ITEM(new_obj2);
+ // Duplicates the parent item
+ Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
+ parent->appendChild(copy);
+ SPObject *new_obj = doc->getObjectByRepr(copy);
+ item_copied = SP_ITEM(new_obj);
// Move around the cursor
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
- Geom::Point center=father->getCenter();
+ Geom::Point center = parent_item->getCenter();
sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale));
sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(scale, scale));
sp_spray_rotate_rel(center, desktop, item_copied, Geom::Rotate(angle));
sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
- // union and duplication
+ // Union and duplication
selection->clear();
selection->add(item_copied);
- selection->add(unionResult);
+ if (unionResult) { // No need to add the very first item (initialized with NULL).
+ selection->add(unionResult);
+ }
sp_selected_path_union_skip_undo(selection, selection->desktop());
- selection->add(father);
- Inkscape::GC::release(copy2);
+ selection->add(parent_item);
+ Inkscape::GC::release(copy);
did = true;
}
}
+#endif
} else if (mode == SPRAY_MODE_CLONE) {
Geom::OptRect a = item->documentVisualBounds();
if (a) {
@@ -500,15 +494,15 @@ static bool sp_spray_recursive(SPDesktop *desktop,
// Creation of the clone
Inkscape::XML::Node *clone = xml_doc->createElement("svg:use");
- // Ad the clone to the list of the father's sons
+ // Ad the clone to the list of the parent's children
parent->appendChild(clone);
- // Generates the link between father and son attributes
+ // Generates the link between parent and child attributes
gchar *href_str = g_strdup_printf("#%s", old_repr->attribute("id"));
clone->setAttribute("xlink:href", href_str, false);
g_free(href_str);
SPObject *clone_object = doc->getObjectByRepr(clone);
- // conversion object->item
+ // Conversion object->item
item_copied = SP_ITEM(clone_object);
Geom::Point center = item->getCenter();
sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale));
@@ -529,8 +523,8 @@ static bool sp_spray_recursive(SPDesktop *desktop,
static bool sp_spray_dilate(SprayTool *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;
+ SPDesktop *desktop = tc->desktop;
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
if (selection->isEmpty()) {
return false;
@@ -554,18 +548,35 @@ static bool sp_spray_dilate(SprayTool *tc, Geom::Point /*event_p*/, Geom::Point
double move_mean = get_move_mean(tc);
double move_standard_deviation = get_move_standard_deviation(tc);
- for (GSList *items = g_slist_copy(const_cast<GSList *>(selection->itemList()));
- items != NULL;
- items = items->next) {
+ {
+ GSList *const original_selection = g_slist_copy(const_cast<GSList *>(selection->itemList()));
- SPItem *item = SP_ITEM(items->data);
+ for (GSList *items = original_selection;
+ items != NULL;
+ items = items->next) {
+ sp_object_ref(SP_ITEM(items->data));
+ }
- if (is_transform_modes(tc->mode)) {
- if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, move_force, tc->population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib))
- did = true;
- } else {
- if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, path_force, tc->population, tc->scale, tc->scale_variation, reverse, path_mean, path_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib))
- did = true;
+ for (GSList *items = original_selection;
+ items != NULL;
+ items = items->next) {
+ SPItem *item = SP_ITEM(items->data);
+
+ if (is_transform_modes(tc->mode)) {
+ if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, move_force, tc->population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib)) {
+ did = true;
+ }
+ } else {
+ if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, path_force, tc->population, tc->scale, tc->scale_variation, reverse, path_mean, path_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib)) {
+ did = true;
+ }
+ }
+ }
+
+ for (GSList *items = original_selection;
+ items != NULL;
+ items = items->next) {
+ sp_object_unref(SP_ITEM(items->data));
}
}
@@ -582,9 +593,9 @@ static void sp_spray_update_area(SprayTool *tc)
static void sp_spray_switch_mode(SprayTool *tc, gint mode, bool with_shift)
{
- // select the button mode
+ // Select the button mode
SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue("spray_tool_mode", mode);
- // need to set explicitly, because the prefs may not have changed by the previous
+ // Need to set explicitly, because the prefs may not have changed by the previous
tc->mode = mode;
tc->update_cursor(with_shift);
}
@@ -631,7 +642,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
Geom::Point motion_doc(desktop->dt2doc(motion_dt));
sp_spray_extinput(this, event);
- // draw the dilating cursor
+ // Draw the dilating cursor
double radius = get_dilate_radius(this);
Geom::Affine const sm (Geom::Scale(radius/(1-this->ratio), radius/(1+this->ratio)) );
sp_canvas_item_affine_absolute(this->dilate_area, (sm*Geom::Rotate(this->tilt))*Geom::Translate(desktop->w2d(motion_w)));
@@ -645,19 +656,19 @@ bool SprayTool::root_handler(GdkEvent* event) {
this->message_context->flash(Inkscape::ERROR_MESSAGE, _("<b>Nothing selected!</b> Select objects to spray."));
}
- // dilating:
+ // Dilating:
if (this->is_drawing && ( event->motion.state & GDK_BUTTON1_MASK )) {
sp_spray_dilate(this, motion_w, motion_doc, motion_doc - this->last_push, event->button.state & GDK_SHIFT_MASK? true : false);
//this->last_push = motion_doc;
this->has_dilated = true;
- // it's slow, so prevent clogging up with events
+ // It's slow, so prevent clogging up with events
gobble_motion_events(GDK_BUTTON1_MASK);
return TRUE;
}
}
break;
- /*Spray with the scroll*/
+ /* Spray with the scroll */
case GDK_SCROLL: {
if (event->scroll.state & GDK_BUTTON1_MASK) {
double temp ;
@@ -708,7 +719,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
if (this->is_dilating && event->button.button == 1 && !this->space_panning) {
if (!this->has_dilated) {
- // if we did not rub, do a light tap
+ // If we did not rub, do a light tap
this->pressure = 0.03;
sp_spray_dilate(this, motion_w, desktop->dt2doc(motion_dt), Geom::Point(0,0), MOD__SHIFT(event));
}
@@ -748,6 +759,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
ret = TRUE;
}
break;
+#ifdef ENABLE_SPRAY_MODE_SINGLE_PATH
case GDK_KEY_l:
case GDK_KEY_L:
if (MOD__SHIFT_ONLY(event)) {
@@ -755,6 +767,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
ret = TRUE;
}
break;
+#endif
case GDK_KEY_Up:
case GDK_KEY_KP_Up:
if (!MOD__CTRL_ONLY(event)) {
@@ -784,7 +797,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
if (this->width > 1.0) {
this->width = 1.0;
}
- // the same spinbutton is for alt+x
+ // The same spinbutton is for alt+x
desktop->setToolboxAdjustmentValue("altx-spray", this->width * 100);
sp_spray_update_area(this);
ret = TRUE;
@@ -867,7 +880,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
// if ((SP_EVENT_CONTEXT_CLASS(sp_spray_context_parent_class))->root_handler) {
// ret = (SP_EVENT_CONTEXT_CLASS(sp_spray_context_parent_class))->root_handler(event_context, event);
// }
- ret = ToolBase::root_handler(event);
+ ret = ToolBase::root_handler(event);
}
return ret;