summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2014-02-28 18:36:08 +0000
committerJabiertxof <jtx@jtx.marker.es>2014-02-28 18:36:08 +0000
commit5974e91ff387b44b30434d3a2ede5f1ea6791a7c (patch)
tree93c062f10f51d6ea670d716d49b5c5883181e055 /src
parentupdate to trunk (diff)
parentSpray tool: (diff)
downloadinkscape-5974e91ff387b44b30434d3a2ede5f1ea6791a7c.tar.gz
inkscape-5974e91ff387b44b30434d3a2ede5f1ea6791a7c.zip
update to trunk
(bzr r11950.1.259)
Diffstat (limited to 'src')
-rw-r--r--src/desktop.cpp18
-rw-r--r--src/display/curve.cpp1
-rw-r--r--src/display/nr-filter.cpp23
-rw-r--r--src/display/sp-canvas.cpp24
-rw-r--r--src/extension/dbus/doc/spec-to-docbook.xsl2
-rw-r--r--src/selection-chemistry.cpp110
-rw-r--r--src/seltrans.cpp6
-rw-r--r--src/sp-filter.cpp28
-rw-r--r--src/sp-root.cpp18
-rw-r--r--src/sp-root.h1
-rw-r--r--src/sp-use.cpp17
-rw-r--r--src/sp-use.h1
-rw-r--r--src/ui/dialog/swatches.cpp13
-rw-r--r--src/ui/tools/spray-tool.cpp98
-rw-r--r--src/ui/widget/selected-style.cpp5
-rw-r--r--src/widgets/desktop-widget.cpp5
-rw-r--r--src/widgets/spray-toolbar.cpp8
17 files changed, 271 insertions, 107 deletions
diff --git a/src/desktop.cpp b/src/desktop.cpp
index 364b5e930..a02baeac8 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -52,6 +52,7 @@
#include "display/sp-canvas.h"
#include "display/sp-canvas-util.h"
#include "document.h"
+#include "document-undo.h"
#include "event-log.h"
#include "helper/action-context.h"
#include "interface.h"
@@ -167,8 +168,23 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid
canvas = aCanvas;
SPDocument *document = namedview->document;
- /* Kill flicker */
+ /* XXX:
+ * ensureUpToDate() sends a 'modified' signal to the root element.
+ * This is reportedly required to prevent flickering after the document
+ * loads. However, many SPObjects write to their repr in response
+ * to this signal. This is apparently done to support live path effects,
+ * which rewrite their result paths after each modification of the base object.
+ * This causes the generation of an incomplete undo transaction,
+ * which causes problems down the line, including crashes in the
+ * Undo History dialog.
+ *
+ * For now, this is handled by disabling undo tracking during this call.
+ * A proper fix would involve modifying the way ensureUpToDate() works,
+ * so that the LPE results are not rewritten.
+ */
+ Inkscape::DocumentUndo::setUndoSensitive(document, false);
document->ensureUpToDate();
+ Inkscape::DocumentUndo::setUndoSensitive(document, true);
/* Setup Dialog Manager */
_dlg_mgr = &Inkscape::UI::Dialog::DialogManager::getInstance();
diff --git a/src/display/curve.cpp b/src/display/curve.cpp
index ae243853e..50f4c8954 100644
--- a/src/display/curve.cpp
+++ b/src/display/curve.cpp
@@ -34,7 +34,6 @@ SPCurve::SPCurve()
: _refcount(1),
_pathv()
{
- _pathv.clear();
}
SPCurve::SPCurve(Geom::PathVector const& pathv)
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 11984ba76..90b233fbc 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -222,14 +222,19 @@ void Filter::area_enlarge(Geom::IntRect &bbox, Inkscape::DrawingItem const *item
Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
{
Geom::Point minp, maxp;
- double len_x = bbox ? bbox->width() : 0;
- double len_y = bbox ? bbox->height() : 0;
- /* TODO: fetch somehow the object ex and em lengths */
- _region_x.update(12, 6, len_x);
- _region_y.update(12, 6, len_y);
- _region_width.update(12, 6, len_x);
- _region_height.update(12, 6, len_y);
+
if (_filter_units == SP_FILTER_UNITS_OBJECTBOUNDINGBOX) {
+
+ double len_x = bbox ? bbox->width() : 0;
+ double len_y = bbox ? bbox->height() : 0;
+ /* TODO: fetch somehow the object ex and em lengths */
+
+ // Update for em, ex, and % values
+ _region_x.update(12, 6, len_x);
+ _region_y.update(12, 6, len_y);
+ _region_width.update(12, 6, len_x);
+ _region_height.update(12, 6, len_y);
+
if (!bbox) return Geom::OptRect();
if (_region_x.unit == SVGLength::PERCENT) {
@@ -254,7 +259,7 @@ Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
maxp[Y] = minp[Y] + _region_height.computed * len_y;
}
} else if (_filter_units == SP_FILTER_UNITS_USERSPACEONUSE) {
- /* TODO: make sure bbox and fe region are in same coordinate system */
+ // Region already set in sp-filter.cpp
minp[X] = _region_x.computed;
maxp[X] = minp[X] + _region_width.computed;
minp[Y] = _region_y.computed;
@@ -262,7 +267,9 @@ Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
} else {
g_warning("Error in Inkscape::Filters::Filter::filter_effect_area: unrecognized value of _filter_units");
}
+
Geom::OptRect area(minp, maxp);
+ // std::cout << "Filter::filter_effect_area: area: " << *area << std::endl;
return area;
}
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index d9640f763..c502daf64 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -1387,8 +1387,13 @@ void SPCanvasImpl::realize(GtkWidget *widget)
gdk_window_set_user_data (window, widget);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if ( prefs->getBool("/options/useextinput/value", true) )
+ if (prefs->getBool("/options/useextinput/value", true)) {
gtk_widget_set_events(widget, attributes.event_mask);
+#if !GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_extension_events(widget, GDK_EXTENSION_EVENTS_ALL);
+ // TODO: Extension event stuff has been deprecated in GTK+ 3
+#endif
+ }
#if !GTK_CHECK_VERSION(3,0,0)
// This does nothing in GTK+ 3
@@ -1524,23 +1529,22 @@ int SPCanvasImpl::emitEvent(SPCanvas *canvas, GdkEvent *event)
// Convert to world coordinates -- we have two cases because of different
// offsets of the fields in the event structures.
- //
- GdkEvent ev = *event;
+ GdkEvent *ev = gdk_event_copy(event);
- switch (ev.type) {
+ switch (ev->type) {
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
- ev.crossing.x += canvas->x0;
- ev.crossing.y += canvas->y0;
+ ev->crossing.x += canvas->x0;
+ ev->crossing.y += canvas->y0;
break;
case GDK_MOTION_NOTIFY:
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
- ev.motion.x += canvas->x0;
- ev.motion.y += canvas->y0;
+ ev->motion.x += canvas->x0;
+ ev->motion.y += canvas->y0;
break;
default:
break;
@@ -1593,12 +1597,14 @@ int SPCanvasImpl::emitEvent(SPCanvas *canvas, GdkEvent *event)
while (item && !finished) {
g_object_ref (item);
- g_signal_emit (G_OBJECT (item), item_signals[ITEM_EVENT], 0, &ev, &finished);
+ g_signal_emit (G_OBJECT (item), item_signals[ITEM_EVENT], 0, ev, &finished);
SPCanvasItem *parent = item->parent;
g_object_unref (item);
item = parent;
}
+ gdk_event_free(ev);
+
return finished;
}
diff --git a/src/extension/dbus/doc/spec-to-docbook.xsl b/src/extension/dbus/doc/spec-to-docbook.xsl
index e200a05e0..a4e792df0 100644
--- a/src/extension/dbus/doc/spec-to-docbook.xsl
+++ b/src/extension/dbus/doc/spec-to-docbook.xsl
@@ -491,7 +491,7 @@ See also:
<xsl:template name="pad-spaces">
<xsl:param name="width"/>
- <xsl:variable name="spaces" xml:space="preserve"> </xsl:variable>
+ <xsl:variable name="spaces" select="' '" ></xsl:variable>
<xsl:value-of select="substring($spaces,1,$width)"/>
</xsl:template>
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index c3d37af72..76be086a2 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -53,6 +53,7 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
#include "sp-ellipse.h"
#include "sp-star.h"
#include "sp-spiral.h"
+#include "sp-switch.h"
#include "sp-polyline.h"
#include "sp-line.h"
#include "text-editing.h"
@@ -767,57 +768,95 @@ void sp_selection_group(Inkscape::Selection *selection, SPDesktop *desktop)
Inkscape::GC::release(group);
}
+static gint clone_depth_descending(gconstpointer a, gconstpointer b) {
+ SPUse *use_a = static_cast<SPUse *>(const_cast<gpointer>(a));
+ SPUse *use_b = static_cast<SPUse *>(const_cast<gpointer>(b));
+ int depth_a = use_a->cloneDepth();
+ int depth_b = use_b->cloneDepth();
+ if (depth_a < depth_b) {
+ return 1;
+ } else if (depth_a == depth_b) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
void sp_selection_ungroup(Inkscape::Selection *selection, SPDesktop *desktop)
{
if (selection->isEmpty()) {
selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select a <b>group</b> to ungroup."));
+ }
+
+ // first check whether there is anything to ungroup
+ GSList *old_select = const_cast<GSList *>(selection->itemList());
+ GSList *new_select = NULL;
+ GSList *groups = NULL;
+ for (GSList *item = old_select; item; item = item->next) {
+ SPItem *obj = static_cast<SPItem*>(item->data);
+ if (SP_IS_GROUP(obj) && !SP_IS_SWITCH(obj)) {
+ groups = g_slist_prepend(groups, obj);
+ }
+ }
+
+ if (groups == NULL) {
+ selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("<b>No groups</b> to ungroup in the selection."));
+ g_slist_free(groups);
return;
}
- GSList *items = g_slist_copy(const_cast<GSList *>(selection->itemList()));
+ GSList *items = g_slist_copy(old_select);
selection->clear();
- // Get a copy of current selection.
- GSList *new_select = NULL;
- bool ungrouped = false;
- for (GSList *i = items;
- i != NULL;
- i = i->next)
- {
- SPItem *group = static_cast<SPItem *>(i->data);
+ // If any of the clones refer to the groups, unlink them and replace them with successors
+ // in the items list.
+ GSList *clones_to_unlink = NULL;
+ for (GSList *item = items; item; item = item->next) {
+ SPUse *use = dynamic_cast<SPUse *>(static_cast<SPItem *>(item->data));
- // when ungrouping cloned groups with their originals, some objects that were selected may no more exist due to unlinking
- if (!SP_IS_OBJECT(group) || !group->getRepr()) {
- continue;
+ SPItem *original = use;
+ while (SP_IS_USE(original)) {
+ original = SP_USE(original)->get_original();
}
- // This check reflects the g_return_if_fail in sp_item_group_ungroup and
- // may be a redundent. It also allows ungrouping of 'a' tags and we dont
- if (strcmp(group->getRepr()->name(), "svg:g") && strcmp(group->getRepr()->name(), "svg:switch") &&
- strcmp(group->getRepr()->name(), "svg:svg")) {
- // keep the non-group item in the new selection
- new_select = g_slist_append(new_select, group);
- continue;
+ if (g_slist_find(groups, original) != NULL) {
+ clones_to_unlink = g_slist_prepend(clones_to_unlink, item->data);
}
-
- GSList *children = NULL;
- /* This is not strictly required, but is nicer to rely on group ::destroy (lauris) */
- sp_item_group_ungroup(SP_GROUP(group), &children, false);
- ungrouped = true;
- // Add ungrouped items to the new selection.
- new_select = g_slist_concat(new_select, children);
}
- if (new_select) { // Set new selection.
- selection->addList(new_select);
- g_slist_free(new_select);
+ // Unlink clones beginning from those with highest clone depth.
+ // This way we can be sure than no additional automatic unlinking happens,
+ // and the items in the list remain valid
+ clones_to_unlink = g_slist_sort(clones_to_unlink, clone_depth_descending);
+
+ for (GSList *item = clones_to_unlink; item; item = item->next) {
+ SPUse *use = static_cast<SPUse *>(item->data);
+ GSList *items_node = g_slist_find(items, item->data);
+ items_node->data = use->unlink();
}
- if (!ungrouped) {
- selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("<b>No groups</b> to ungroup in the selection."));
+ g_slist_free(clones_to_unlink);
+
+ // do the actual work
+ for (GSList *item = items; item; item = item->next) {
+ SPItem *obj = static_cast<SPItem *>(item->data);
+
+ // ungroup only the groups marked earlier
+ if (g_slist_find(groups, item->data) != NULL) {
+ GSList *children = NULL;
+ sp_item_group_ungroup(SP_GROUP(obj), &children, false);
+ // add the items resulting from ungrouping to the selection
+ new_select = g_slist_concat(new_select, children);
+ item->data = NULL; // zero out the original pointer, which is no longer valid
+ } else {
+ // if not a group, keep in the selection
+ new_select = g_slist_append(new_select, item->data);
+ }
}
+ selection->addList(new_select);
+ g_slist_free(new_select);
g_slist_free(items);
-
+
DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_UNGROUP,
_("Ungroup"));
}
@@ -1458,6 +1497,13 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
SPItem *item = SP_ITEM(l->data);
+ if( SP_IS_ROOT(item) ) {
+ // An SVG element cannot have a transform. We could change 'x' and 'y' in response
+ // to a translation... but leave that for another day.
+ selection->desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Cannot transform an embedded SVG."));
+ break;
+ }
+
Geom::Point old_center(0,0);
if (set_i2d && item->isCenterSet())
old_center = item->getCenter();
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 78d9958c4..a55bc3c0d 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -29,11 +29,13 @@
#include "desktop-handles.h"
#include "desktop-style.h"
#include "knot.h"
+#include "message-stack.h"
#include "snap.h"
#include "selection.h"
#include "ui/tools/select-tool.h"
#include "sp-item.h"
#include "sp-item-transform.h"
+#include "sp-root.h"
#include "seltrans-handles.h"
#include "seltrans.h"
#include "selection-chemistry.h"
@@ -381,6 +383,10 @@ void Inkscape::SelTrans::transform(Geom::Affine const &rel_affine, Geom::Point c
// update the content
for (unsigned i = 0; i < _items.size(); i++) {
SPItem &item = *_items[i];
+ if( SP_IS_ROOT(&item) ) {
+ _desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Cannot transform an embedded SVG."));
+ break;
+ }
Geom::Affine const &prev_transform = _items_affines[i];
item.set_i2d_affine(prev_transform * affine);
}
diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp
index c3e7d217e..0e3d2d5ce 100644
--- a/src/sp-filter.cpp
+++ b/src/sp-filter.cpp
@@ -28,6 +28,7 @@ using std::pair;
#include "sp-filter.h"
#include "sp-filter-reference.h"
#include "sp-filter-primitive.h"
+#include "sp-item.h"
#include "uri.h"
#include "xml/repr.h"
#include <cstring>
@@ -206,6 +207,33 @@ void SPFilter::update(SPCtx *ctx, guint flags) {
if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
+ SPItemCtx *ictx = (SPItemCtx *) ctx;
+
+ // Do here since we know viewport (Bounding box case handled during rendering)
+ // Note: This only works for root viewport since this routine is not called after
+ // setting a new viewport. A true fix requires a strategy like SPItemView or SPMarkerView.
+ if(this->filterUnits == SP_FILTER_UNITS_USERSPACEONUSE) {
+ std::cout << " userSpaceOnUse" << std::endl;
+ if (this->x.unit == SVGLength::PERCENT) {
+ this->x._set = true;
+ this->x.computed = this->x.value * ictx->viewport.width();
+ }
+
+ if (this->y.unit == SVGLength::PERCENT) {
+ this->y._set = true;
+ this->y.computed = this->y.value * ictx->viewport.height();
+ }
+
+ if (this->width.unit == SVGLength::PERCENT) {
+ this->width._set = true;
+ this->width.computed = this->width.value * ictx->viewport.width();
+ }
+
+ if (this->height.unit == SVGLength::PERCENT) {
+ this->height._set = true;
+ this->height.computed = this->height.value * ictx->viewport.height();
+ }
+ }
/* do something to trigger redisplay, updates? */
}
diff --git a/src/sp-root.cpp b/src/sp-root.cpp
index bc870b116..12570e03e 100644
--- a/src/sp-root.cpp
+++ b/src/sp-root.cpp
@@ -221,7 +221,7 @@ void SPRoot::remove_child(Inkscape::XML::Node *child)
void SPRoot::update(SPCtx *ctx, guint flags)
{
- SPItemCtx *ictx = (SPItemCtx *) ctx;
+ SPItemCtx const *ictx = (SPItemCtx const *) ctx;
if( !this->parent ) {
@@ -288,10 +288,17 @@ void SPRoot::update(SPCtx *ctx, guint flags)
this->height.computed = this->height.value * ictx->viewport.height();
}
+ // std::cout << "SPRoot::update: final:"
+ // << " x: " << x.computed
+ // << " y: " << y.computed
+ // << " width: " << width.computed
+ // << " height: " << height.computed << std::endl;
+
// Calculate new viewport
- ictx->viewport = Geom::Rect::from_xywh( this->x.computed, this->y.computed,
- this->width.computed, this->height.computed );
- SPItemCtx rctx = get_rctx( ictx );
+ SPItemCtx rctx = *ictx;
+ rctx.viewport = Geom::Rect::from_xywh( this->x.computed, this->y.computed,
+ this->width.computed, this->height.computed );
+ rctx = get_rctx( &rctx );
/* And invoke parent method */
SPGroup::update((SPCtx *) &rctx, flags);
@@ -380,6 +387,9 @@ void SPRoot::print(SPPrintContext *ctx)
sp_print_release(ctx);
}
+const char *SPRoot::displayName() const {
+ return "SVG"; // Do not translate
+}
/*
Local Variables:
diff --git a/src/sp-root.h b/src/sp-root.h
index 1c9faed9b..0e5d87133 100644
--- a/src/sp-root.h
+++ b/src/sp-root.h
@@ -63,6 +63,7 @@ public:
virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
virtual void print(SPPrintContext *ctx);
+ virtual const char* displayName() const;
};
#endif /* !SP_ROOT_H_SEEN */
diff --git a/src/sp-use.cpp b/src/sp-use.cpp
index b2a51b8d9..e394e84c2 100644
--- a/src/sp-use.cpp
+++ b/src/sp-use.cpp
@@ -300,6 +300,23 @@ SPItem const *SPUse::root() const {
}
/**
+ * Get the number of dereferences or calls to get_original() needed to get an object
+ * which is not an svg:use. Returns -1 if there is no original object.
+ */
+int SPUse::cloneDepth() const {
+ unsigned depth = 1;
+ SPItem *orig = this->child;
+
+ while (orig && SP_IS_USE(orig)) {
+ ++depth;
+ orig = SP_USE(orig)->child;
+ }
+
+ if (!orig) return -1;
+ return depth;
+}
+
+/**
* Returns the effective transform that goes from the ultimate original to given SPUse, both ends
* included.
*/
diff --git a/src/sp-use.h b/src/sp-use.h
index 31a52c1a1..604040d59 100644
--- a/src/sp-use.h
+++ b/src/sp-use.h
@@ -66,6 +66,7 @@ public:
SPItem *root();
SPItem const *root() const;
+ int cloneDepth() const;
SPItem *unlink();
SPItem *get_original();
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 3f161ad28..807618b4d 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -746,7 +746,7 @@ class DocTrack
{
public:
DocTrack(SPDocument *doc, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) :
- doc(doc),
+ doc(doc->doRef()),
updatePending(false),
lastGradientUpdate(0.0),
gradientRsrcChanged(gradientRsrcChanged),
@@ -776,6 +776,8 @@ public:
gradientRsrcChanged.disconnect();
defsChanged.disconnect();
defsModified.disconnect();
+ doc->doUnref();
+ doc = NULL;
}
}
@@ -858,7 +860,7 @@ bool DocTrack::queueUpdateIfNeeded( SPDocument *doc )
void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document )
{
- SPDocument *oldDoc = 0;
+ SPDocument *oldDoc = NULL;
if (docPerPanel.find(panel) != docPerPanel.end()) {
oldDoc = docPerPanel[panel];
if (!oldDoc) {
@@ -867,7 +869,7 @@ void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document )
}
if (oldDoc != document) {
if (oldDoc) {
- docPerPanel[panel] = 0;
+ docPerPanel[panel] = NULL;
bool found = false;
for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) {
found = (it->second == document);
@@ -905,11 +907,6 @@ void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document )
}
}
}
-
- std::set<SPDocument*> docs;
- for (std::map<SwatchesPanel*, SPDocument*>::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) {
- docs.insert(it->second);
- }
}
void SwatchesPanel::_setDocument( SPDocument *document )
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 2fc3f1c91..e43b6575e 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)
@@ -189,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() {
@@ -420,6 +425,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
did = true;
}
}
+#ifdef ENABLE_SPRAY_MODE_SINGLE_PATH
} else if (mode == SPRAY_MODE_SINGLE_PATH) {
SPItem *parent_item = NULL; // Initial object
@@ -475,6 +481,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
did = true;
}
}
+#endif
} else if (mode == SPRAY_MODE_CLONE) {
Geom::OptRect a = item->documentVisualBounds();
if (a) {
@@ -516,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;
@@ -541,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));
}
}
@@ -735,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)) {
@@ -742,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)) {
@@ -854,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;
diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
index d29554c41..042a6614e 100644
--- a/src/ui/widget/selected-style.cpp
+++ b/src/ui/widget/selected-style.cpp
@@ -1267,6 +1267,11 @@ RotateableSwatch::color_adjust(float *hsla, double by, guint32 cc, guint modifie
} else if (modifier == 3) { // alpha
double old = hsla[3];
hsla[3] += by/2;
+ if (hsla[3] < 0) {
+ hsla[3] = 0;
+ } else if (hsla[3] > 1) {
+ hsla[3] = 1;
+ }
diff = hsla[3] - old;
} else { // hue
double old = hsla[0];
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index cf6a908b6..583dbec85 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -552,11 +552,6 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
GtkStyle *style = gtk_style_copy(gtk_widget_get_style(GTK_WIDGET(dtw->canvas)));
style->bg[GTK_STATE_NORMAL] = style->white;
gtk_widget_set_style (GTK_WIDGET (dtw->canvas), style);
-
- // TODO: Extension event stuff has been removed from public API in GTK+ 3
- // Need to check that this hasn't broken anything
- if ( prefs->getBool("/options/useextinput/value", true) )
- gtk_widget_set_extension_events(GTK_WIDGET (dtw->canvas) , GDK_EXTENSION_EVENTS_ALL); //set extension events for tablets, unless disabled in preferences
#endif
g_signal_connect (G_OBJECT (dtw->canvas), "event", G_CALLBACK (sp_desktop_widget_event), dtw);
diff --git a/src/widgets/spray-toolbar.cpp b/src/widgets/spray-toolbar.cpp
index 2a8c85475..49406d564 100644
--- a/src/widgets/spray-toolbar.cpp
+++ b/src/widgets/spray-toolbar.cpp
@@ -60,6 +60,10 @@ using Inkscape::DocumentUndo;
using Inkscape::UI::ToolboxFactory;
using Inkscape::UI::PrefPusher;
+// 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
//########################
//## Spray ##
@@ -186,14 +190,14 @@ void sp_spray_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObj
1, _("Spray clones of the initial selection"),
2, INKSCAPE_ICON("spray-mode-clone"),
-1 );
-
+#ifdef ENABLE_SPRAY_MODE_SINGLE_PATH
gtk_list_store_append( model, &iter );
gtk_list_store_set( model, &iter,
0, _("Spray single path"),
1, _("Spray objects in a single path"),
2, INKSCAPE_ICON("spray-mode-union"),
-1 );
-
+#endif
EgeSelectOneAction* act = ege_select_one_action_new( "SprayModeAction", _("Mode"), (""), NULL, GTK_TREE_MODEL(model) );
g_object_set( act, "short_label", _("Mode:"), NULL );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );