summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiam P. White <inkscapebrony@gmail.com>2014-08-08 15:04:56 +0000
committerLiam P. White <inkscapebrony@gmail.com>2014-08-08 15:04:56 +0000
commitca8023872ae0d9f7b99688502b9bdba232ec5627 (patch)
tree73092b0aa6ea3e697da66d1d6316d3a2d78a4f3e /src
parentUpdate to experimental r13440 (diff)
parentSmall tweak to bbox calculation (diff)
downloadinkscape-ca8023872ae0d9f7b99688502b9bdba232ec5627.tar.gz
inkscape-ca8023872ae0d9f7b99688502b9bdba232ec5627.zip
Update to experimental r13464
(bzr r13341.5.14)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/path.cpp2
-rw-r--r--src/2geom/svg-path-parser.cpp37
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile_insert1
-rw-r--r--src/attributes.cpp12
-rw-r--r--src/attributes.h33
-rw-r--r--src/box3d.cpp19
-rw-r--r--src/connection-pool.h128
-rw-r--r--src/desktop-events.cpp5
-rw-r--r--src/display/cairo-utils.cpp91
-rw-r--r--src/display/drawing-item.cpp14
-rw-r--r--src/display/drawing-item.h2
-rw-r--r--src/display/drawing-text.cpp23
-rw-r--r--src/document-undo.cpp1
-rw-r--r--src/extension/internal/emf-inout.cpp22
-rw-r--r--src/extension/internal/emf-print.cpp6
-rw-r--r--src/extension/internal/emf-print.h2
-rw-r--r--src/extension/internal/text_reassemble.c20
-rw-r--r--src/extension/internal/wmf-inout.cpp27
-rw-r--r--src/extension/internal/wmf-print.cpp2
-rw-r--r--src/extension/internal/wmf-print.h2
-rw-r--r--src/gradient-chemistry.cpp12
-rw-r--r--src/gradient-drag.cpp9
-rw-r--r--src/helper/geom.cpp53
-rw-r--r--src/knot-holder-entity.cpp18
-rw-r--r--src/knot-holder-entity.h10
-rw-r--r--src/knot-ptr.cpp25
-rw-r--r--src/knot-ptr.h8
-rw-r--r--src/knot.cpp8
-rw-r--r--src/knotholder.cpp32
-rw-r--r--src/live_effects/CMakeLists.txt2
-rw-r--r--src/live_effects/Makefile_insert2
-rw-r--r--src/live_effects/effect-enum.h1
-rw-r--r--src/live_effects/effect.cpp5
-rw-r--r--src/live_effects/lpe-fillet-chamfer.cpp6
-rw-r--r--src/live_effects/lpe-roughen.cpp389
-rw-r--r--src/live_effects/lpe-roughen.h57
-rw-r--r--src/live_effects/parameter/path.cpp2
-rw-r--r--src/object-edit.cpp4
-rw-r--r--src/object-snapper.cpp4
-rw-r--r--src/selection-chemistry.cpp7
-rw-r--r--src/seltrans.cpp7
-rw-r--r--src/shape-editor.cpp202
-rw-r--r--src/shape-editor.h54
-rw-r--r--src/sp-flowregion.cpp7
-rw-r--r--src/sp-flowtext.cpp4
-rw-r--r--src/sp-gradient.cpp2
-rw-r--r--src/sp-item-group.cpp5
-rw-r--r--src/sp-item.cpp22
-rw-r--r--src/sp-item.h11
-rw-r--r--src/sp-lpe-item.cpp2
-rw-r--r--src/sp-offset.cpp5
-rw-r--r--src/sp-path.cpp5
-rw-r--r--src/sp-shape.cpp2
-rw-r--r--src/sp-star.cpp8
-rw-r--r--src/sp-string.cpp120
-rw-r--r--src/sp-text.cpp36
-rw-r--r--src/sp-text.h6
-rw-r--r--src/sp-tref.cpp7
-rw-r--r--src/sp-tspan.cpp5
-rw-r--r--src/sp-use.cpp13
-rw-r--r--src/style-enums.h17
-rw-r--r--src/style-internal.cpp27
-rw-r--r--src/style-internal.h2
-rw-r--r--src/style.cpp41
-rw-r--r--src/style.h43
-rw-r--r--src/ui/clipboard.cpp9
-rw-r--r--src/ui/dialog/clonetiler.cpp18
-rw-r--r--src/ui/dialog/dialog-manager.cpp6
-rw-r--r--src/ui/dialog/document-properties.cpp1
-rw-r--r--src/ui/dialog/layers.cpp12
-rw-r--r--src/ui/dialog/template-widget.cpp2
-rw-r--r--src/ui/tool/path-manipulator.cpp6
-rw-r--r--src/ui/tools/arc-tool.cpp6
-rw-r--r--src/ui/tools/box3d-tool.cpp6
-rw-r--r--src/ui/tools/flood-tool.cpp6
-rw-r--r--src/ui/tools/freehand-base.cpp73
-rw-r--r--src/ui/tools/lpe-tool.cpp7
-rw-r--r--src/ui/tools/node-tool.cpp15
-rw-r--r--src/ui/tools/node-tool.h2
-rw-r--r--src/ui/tools/pen-tool.cpp44
-rw-r--r--src/ui/tools/rect-tool.cpp6
-rw-r--r--src/ui/tools/spiral-tool.cpp6
-rw-r--r--src/ui/tools/spray-tool.cpp2
-rw-r--r--src/ui/tools/star-tool.cpp6
-rw-r--r--src/ui/tools/text-tool.cpp6
-rw-r--r--src/ui/tools/tool-base.cpp11
-rw-r--r--src/ui/widget/style-swatch.cpp2
-rw-r--r--src/widgets/desktop-widget.cpp4
-rw-r--r--src/widgets/pencil-toolbar.cpp1
-rw-r--r--src/widgets/ruler.cpp2
-rw-r--r--src/widgets/text-toolbar.cpp45
92 files changed, 1408 insertions, 654 deletions
diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp
index fc4d72028..3558af3b3 100644
--- a/src/2geom/path.cpp
+++ b/src/2geom/path.cpp
@@ -110,7 +110,7 @@ Path &Path::operator*=(Translate const &m) {
Sequence::iterator it;
Point prev;
for (it = get_curves().begin() ; it != last ; ++it) {
- //*(const_cast<Curve*>(&**it)) *= m;
+ // *(const_cast<Curve*>(&**it)) *= m;
const_cast<Curve*>(it->get())->operator*=(m);
if ( it != get_curves().begin() && (*it)->initialPoint() != prev ) {
THROW_CONTINUITYERROR();
diff --git a/src/2geom/svg-path-parser.cpp b/src/2geom/svg-path-parser.cpp
index ccc383920..932f95829 100644
--- a/src/2geom/svg-path-parser.cpp
+++ b/src/2geom/svg-path-parser.cpp
@@ -1,5 +1,3 @@
-
-#line 1 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
/**
* \file
* \brief parse SVG path specifications
@@ -130,6 +128,9 @@ private:
void _arcTo(double rx, double ry, double angle,
bool large_arc, bool sweep, Point p)
{
+ if (are_near(_current, p)) {
+ return;
+ }
_quad_tangent = _cubic_tangent = _current = p;
_sink.arcTo(rx, ry, angle, large_arc, sweep, p);
}
@@ -141,7 +142,6 @@ private:
};
-#line 145 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
static const char _svg_path_actions[] = {
0, 1, 0, 1, 1, 1, 2, 1,
3, 1, 4, 1, 5, 1, 15, 1,
@@ -1147,9 +1147,6 @@ static const int svg_path_first_final = 270;
//static const int svg_path_en_main = 1;
-#line 144 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
-
-
void Parser::parse(char const *str)
throw(SVGPathParseError)
{
@@ -1159,13 +1156,11 @@ throw(SVGPathParseError)
_reset();
-
-#line 1164 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
{
cs = svg_path_start;
}
-#line 1169 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
+
{
int _klen;
unsigned int _trans;
@@ -1238,13 +1233,12 @@ _match:
switch ( *_acts++ )
{
case 0:
-#line 156 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
start = p;
}
break;
case 1:
-#line 160 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
char const *end=p;
std::string buf(start, end);
@@ -1253,55 +1247,49 @@ _match:
}
break;
case 2:
-#line 167 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
_push(1.0);
}
break;
case 3:
-#line 171 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
_push(0.0);
}
break;
case 4:
-#line 175 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
+
{
_absolute = true;
}
break;
case 5:
-#line 179 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_absolute = false;
}
break;
case 6:
-#line 183 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_moveTo(_pop_point());
}
break;
case 7:
-#line 187 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_lineTo(_pop_point());
}
break;
case 8:
-#line 191 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_hlineTo(Point(_pop_coord(X), _current[Y]));
}
break;
case 9:
-#line 195 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_vlineTo(Point(_current[X], _pop_coord(Y)));
}
break;
case 10:
-#line 199 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c1 = _pop_point();
@@ -1310,7 +1298,6 @@ _match:
}
break;
case 11:
-#line 206 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c1 = _pop_point();
@@ -1318,7 +1305,6 @@ _match:
}
break;
case 12:
-#line 212 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
Point c = _pop_point();
@@ -1326,14 +1312,12 @@ _match:
}
break;
case 13:
-#line 218 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point p = _pop_point();
_quadTo(_quad_tangent, p);
}
break;
case 14:
-#line 223 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
Point point = _pop_point();
bool sweep = _pop_flag();
@@ -1346,16 +1330,13 @@ _match:
}
break;
case 15:
-#line 234 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{
_closePath();
}
break;
case 16:
-#line 370 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
{{p++; goto _out; }}
break;
-#line 1359 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.cpp"
}
}
@@ -1367,8 +1348,6 @@ _again:
_out: {}
}
-#line 380 "/home/tweenk/src/lib2geom/src/2geom/svg-path-parser.rl"
-
if ( cs < svg_path_first_final ) {
throw SVGPathParseError();
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3dcbb8e94..2d293020e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -218,6 +218,7 @@ set(inkscape_SRC
knot-holder-entity.cpp
knot.cpp
knotholder.cpp
+ knot-ptr.cpp
layer-fns.cpp
layer-manager.cpp
layer-model.cpp
@@ -355,6 +356,7 @@ set(inkscape_SRC
knot-holder-entity.h
knot.h
knotholder.h
+ knot-ptr.h
layer-fns.h
layer-manager.h
layer-model.h
diff --git a/src/Makefile_insert b/src/Makefile_insert
index 2f28233d5..f1185e96d 100644
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
@@ -80,6 +80,7 @@ ink_common_sources += \
knot-enums.h \
knotholder.cpp knotholder.h \
knot-holder-entity.h knot-holder-entity.cpp \
+ knot-ptr.h knot-ptr.cpp \
layer-fns.cpp layer-fns.h \
layer-manager.cpp layer-manager.h \
layer-model.cpp layer-model.h \
diff --git a/src/attributes.cpp b/src/attributes.cpp
index da7b25f03..2474e4abe 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -413,10 +413,6 @@ static SPStyleProp const props[] = {
/* Text */
{SP_PROP_TEXT_INDENT, "text-indent"},
{SP_PROP_TEXT_ALIGN, "text-align"},
- {SP_PROP_TEXT_DECORATION, "text-decoration"},
- {SP_PROP_TEXT_DECORATION_LINE, "text-decoration-line"},
- {SP_PROP_TEXT_DECORATION_STYLE,"text-decoration-style"},
- {SP_PROP_TEXT_DECORATION_COLOR,"text-decoration-color"},
{SP_PROP_LINE_HEIGHT, "line-height"},
{SP_PROP_LETTER_SPACING, "letter-spacing"},
{SP_PROP_WORD_SPACING, "word-spacing"},
@@ -433,6 +429,12 @@ static SPStyleProp const props[] = {
{SP_PROP_GLYPH_ORIENTATION_VERTICAL, "glyph-orientation-vertical"},
{SP_PROP_KERNING, "kerning"},
{SP_PROP_TEXT_ANCHOR, "text-anchor"},
+ {SP_PROP_WHITE_SPACE, "white-space"},
+ /* Text Decoration */
+ {SP_PROP_TEXT_DECORATION, "text-decoration"},
+ {SP_PROP_TEXT_DECORATION_LINE, "text-decoration-line"},
+ {SP_PROP_TEXT_DECORATION_STYLE,"text-decoration-style"},
+ {SP_PROP_TEXT_DECORATION_COLOR,"text-decoration-color"},
/* Misc */
{SP_PROP_CLIP, "clip"},
{SP_PROP_COLOR, "color"},
@@ -440,7 +442,7 @@ static SPStyleProp const props[] = {
{SP_PROP_DISPLAY, "display"},
{SP_PROP_OVERFLOW, "overflow"},
{SP_PROP_VISIBILITY, "visibility"},
- {SP_PROP_BLEND_MODE, "mix-blend-mode"}, // CSS Blending and Compositing
+ {SP_PROP_MIX_BLEND_MODE, "mix-blend-mode"}, // CSS Blending and Compositing
{SP_PROP_ISOLATION, "isolation"},
/* SVG */
/* Clip/Mask */
diff --git a/src/attributes.h b/src/attributes.h
index 82e7ca8a6..7f18cb5ea 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -399,9 +399,11 @@ enum SPAttributeEnum {
SP_ATTR_TEXT_EXCLUDE,
SP_ATTR_LAYOUT_OPTIONS,
- /* CSS2 */
- /* Custom full font name because Font stuff below is inadequate */
+ /* CSS & SVG Properties */
+
+ /* Custom full font name because Font stuff below is inadequate REMOVE ME */
SP_PROP_INKSCAPE_FONT_SPEC,
+
/* Font */
SP_PROP_FONT,
SP_PROP_FONT_FAMILY,
@@ -411,18 +413,16 @@ enum SPAttributeEnum {
SP_PROP_FONT_STYLE,
SP_PROP_FONT_VARIANT,
SP_PROP_FONT_WEIGHT,
- /* Text */
+
+ /* Text Layout */
SP_PROP_TEXT_INDENT,
SP_PROP_TEXT_ALIGN,
- SP_PROP_TEXT_DECORATION, /* SVG 1 underline etc.( no color or style) OR SVG2 with _LINE, _STYLE, _COLOR values */
- SP_PROP_TEXT_DECORATION_LINE, /* SVG 2 underline etc. */
- SP_PROP_TEXT_DECORATION_STYLE, /* SVG 2 proposed solid [SVG 1], dotted, etc.)*/
- SP_PROP_TEXT_DECORATION_COLOR, /* SVG 2 proposed same as text [SVG 1], specified*/
+
SP_PROP_LINE_HEIGHT,
SP_PROP_LETTER_SPACING,
SP_PROP_WORD_SPACING,
SP_PROP_TEXT_TRANSFORM,
- /* text (css3) */
+
SP_PROP_DIRECTION,
SP_PROP_BLOCK_PROGRESSION,
SP_PROP_WRITING_MODE,
@@ -434,6 +434,14 @@ enum SPAttributeEnum {
SP_PROP_GLYPH_ORIENTATION_VERTICAL,
SP_PROP_KERNING,
SP_PROP_TEXT_ANCHOR,
+ SP_PROP_WHITE_SPACE,
+
+ /* Text Decoration */
+ SP_PROP_TEXT_DECORATION, /* SVG 1 underline etc.( no color or style) OR SVG2 with _LINE, _STYLE, _COLOR values */
+ SP_PROP_TEXT_DECORATION_LINE, /* SVG 2 underline etc. */
+ SP_PROP_TEXT_DECORATION_STYLE, /* SVG 2 proposed solid [SVG 1], dotted, etc.)*/
+ SP_PROP_TEXT_DECORATION_COLOR, /* SVG 2 proposed same as text [SVG 1], specified*/
+
/* Misc */
SP_PROP_CLIP,
SP_PROP_COLOR,
@@ -441,26 +449,31 @@ enum SPAttributeEnum {
SP_PROP_DISPLAY,
SP_PROP_OVERFLOW,
SP_PROP_VISIBILITY,
- SP_PROP_BLEND_MODE,
+ SP_PROP_MIX_BLEND_MODE,
SP_PROP_ISOLATION,
+
/* SVG */
/* Clip/Mask */
SP_PROP_CLIP_PATH,
SP_PROP_CLIP_RULE,
SP_PROP_MASK,
SP_PROP_OPACITY,
+
/* Filter */
SP_PROP_ENABLE_BACKGROUND,
SP_PROP_FILTER,
SP_PROP_FLOOD_COLOR,
SP_PROP_FLOOD_OPACITY,
SP_PROP_LIGHTING_COLOR,
+
/* Gradient */
SP_PROP_STOP_COLOR,
SP_PROP_STOP_OPACITY,
SP_PROP_STOP_PATH,
+
/* Interactivity */
SP_PROP_POINTER_EVENTS,
+
/* Paint */
SP_PROP_COLOR_INTERPOLATION,
SP_PROP_COLOR_INTERPOLATION_FILTERS,
@@ -487,10 +500,12 @@ enum SPAttributeEnum {
SP_PROP_STROKE_OPACITY,
SP_PROP_STROKE_WIDTH,
SP_PROP_TEXT_RENDERING,
+
/* Conditional */
SP_PROP_SYSTEM_LANGUAGE,
SP_PROP_REQUIRED_FEATURES,
SP_PROP_REQUIRED_EXTENSIONS,
+
/* LivePathEffect */
SP_PROP_PATH_EFFECT,
};
diff --git a/src/box3d.cpp b/src/box3d.cpp
index a47dce1b3..5598bc83d 100644
--- a/src/box3d.cpp
+++ b/src/box3d.cpp
@@ -672,15 +672,6 @@ box3d_aux_set_z_orders (int z_orders[6], int a, int b, int c, int d, int e, int
z_orders[5] = f;
}
-static inline void
-box3d_swap_z_orders (int z_orders[6]) {
- int tmp;
- for (int i = 0; i < 3; ++i) {
- tmp = z_orders[i];
- z_orders[i] = z_orders[5-i];
- z_orders[5-i] = tmp;
- }
-}
/*
* In standard perspective we have:
@@ -695,11 +686,6 @@ box3d_swap_z_orders (int z_orders[6]) {
/* All VPs infinite */
static void
box3d_set_new_z_orders_case0 (SPBox3D *box, int z_orders[6], Box3D::Axis central_axis) {
- Persp3D *persp = box3d_get_perspective(box);
- Geom::Point xdir(persp3d_get_infinite_dir(persp, Proj::X));
- Geom::Point ydir(persp3d_get_infinite_dir(persp, Proj::Y));
- Geom::Point zdir(persp3d_get_infinite_dir(persp, Proj::Z));
-
bool swapped = box3d_XY_axes_are_swapped(box);
switch(central_axis) {
@@ -811,12 +797,7 @@ box3d_set_new_z_orders_case1 (SPBox3D *box, int z_orders[6], Box3D::Axis central
/* Precisely 2 finite VPs */
static void
box3d_set_new_z_orders_case2 (SPBox3D *box, int z_orders[6], Box3D::Axis central_axis, Box3D::Axis /*infinite_axis*/) {
- Persp3D *persp = box3d_get_perspective(box);
-
Geom::Point c3(box3d_get_corner_screen(box, 3, false));
- Geom::Point xdir(persp3d_get_PL_dir_from_pt(persp, c3, Proj::X));
- Geom::Point ydir(persp3d_get_PL_dir_from_pt(persp, c3, Proj::Y));
- Geom::Point zdir(persp3d_get_PL_dir_from_pt(persp, c3, Proj::Z));
bool swapped = box3d_XY_axes_are_swapped(box);
diff --git a/src/connection-pool.h b/src/connection-pool.h
index b1ac6f07a..4637a3cc1 100644
--- a/src/connection-pool.h
+++ b/src/connection-pool.h
@@ -1,84 +1,100 @@
+/*
+ * Author:
+ * mderezynski <mderezynski@users.sourceforge.net>
+ *
+ * Copyright (C) 2006 Author
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
#ifndef CONNECTION_POOL_H
#define CONNECTION_POOL_H
-#include <map>
#include <glib-object.h>
-#include <stddef.h>
-#include <string>
#include <sigc++/sigc++.h>
-namespace Inkscape
-{
-class ConnectionPool
-{
- public:
+#include <map>
+#include <stddef.h>
+#include <string>
+#include <exception>
+
+namespace Inkscape {
+
+/**
+ * @class ConnectionPool
+ * an auxilliary class to manage sigc::connections as if the referred object
+ * were a GObject; in that way, the class that holds a ConnectionPool does not
+ * need to also hold several sigc::connection objects
+ */
+class ConnectionPool {
+public:
+ typedef std::map<std::string, sigc::connection*> ConnectionMap;
- enum Exception
- {
- NAME_EXISTS,
- NAME_DOES_NOT_EXIST
+ struct NameExistsException : public std::exception {
+ virtual const char* what() const throw() { return "Inkscape::ConnectionPool: name exists"; }
+ };
+ struct NameDoesNotExistException : public std::exception {
+ virtual const char* what() const throw() { return "Inkscape::ConnectionPool: name doesn't exist"; }
};
- typedef std::map<std::string, sigc::connection*> ConnectionMap;
-
- virtual ~ConnectionPool ()
- {
- for (ConnectionMap::iterator iter = map.begin (), end = map.end (); iter != end; ++iter) {
- sigc::connection* connection = (*iter).second;
- connection->disconnect ();
- delete connection;
+ void add_connection(std::string name, sigc::connection* connection) {
+ if (_map.find(name) != _map.end()) {
+ throw NameExistsException();
}
+ _map.insert(std::make_pair(name, connection));
}
- void
- add_connection (std::string name, sigc::connection* connection)
- {
- if (map.find (name) != map.end ()) throw NAME_EXISTS;
- map.insert (std::make_pair (name, connection));
- }
-
- void
- del_connection (std::string name)
- {
- ConnectionMap::iterator iter = map.find (name);
- if (iter == map.end ()) throw NAME_DOES_NOT_EXIST;
- sigc::connection* connection = (*iter).second;
- connection->disconnect ();
- delete connection;
+ void del_connection(std::string name) {
+ ConnectionMap::iterator iter = _map.find(name);
+ if (iter == _map.end()) {
+ throw NameDoesNotExistException();
+ }
+ sigc::connection* connection = (*iter).second;
+ connection->disconnect();
+ delete connection;
}
- static Inkscape::ConnectionPool*
- new_connection_pool (std::string name)
- {
- return new ConnectionPool (name);
+ static Inkscape::ConnectionPool* new_connection_pool(std::string name) {
+ return new ConnectionPool(name);
}
- static void
- del_connection_pool (Inkscape::ConnectionPool* pool)
- {
- delete pool;
+ static void del_connection_pool(ConnectionPool* pool) {
+ delete pool;
}
- static void
- connect_destroy (GObject *obj, Inkscape::ConnectionPool *pool)
- {
- g_object_connect (obj, "swapped-signal::destroy", G_CALLBACK (del_connection_pool), pool, NULL);
+ static void connect_destroy(GObject *obj, ConnectionPool *pool) {
+ g_object_connect (obj, "swapped-signal::destroy", G_CALLBACK(del_connection_pool), pool, NULL);
}
- operator std::string ()
- {
- return name;
+ operator std::string() {
+ return _name;
}
- private:
-
- ConnectionPool (std::string name) : name (name)
- {}
+private:
+ ConnectionPool(std::string name) : _name(name) {}
+ virtual ~ConnectionPool() {
+ for (ConnectionMap::iterator iter = _map.begin(), end = _map.end(); iter != end; ++iter) {
+ sigc::connection* connection = (*iter).second;
+ connection->disconnect();
+ delete connection;
+ }
+ }
- ConnectionMap map;
- std::string name;
+ ConnectionMap _map;
+ std::string _name;
};
}
#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index 0129a382d..8be5e001b 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -365,7 +365,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
if (event->motion.state & GDK_CONTROL_MASK) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
unsigned const snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
- bool const relative_snaps = abs(prefs->getBool("/options/relativeguiderotationsnap/value", false));
+ bool const relative_snaps = prefs->getBool("/options/relativeguiderotationsnap/value", false);
if (snaps) {
if (relative_snaps) {
Geom::Angle orig_angle(guide->normal_to_line);
@@ -442,7 +442,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
if (event->motion.state & GDK_CONTROL_MASK) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
unsigned const snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
- bool const relative_snaps = abs(prefs->getBool("/options/relativeguiderotationsnap/value", false));
+ bool const relative_snaps = prefs->getBool("/options/relativeguiderotationsnap/value", false);
if (snaps) {
if (relative_snaps) {
Geom::Angle orig_angle(guide->normal_to_line);
@@ -491,7 +491,6 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
// set move or rotate cursor
Geom::Point const event_w(event->crossing.x, event->crossing.y);
- Geom::Point const event_dt(desktop->w2d(event_w));
if ((event->crossing.state & GDK_SHIFT_MASK) && (drag_type != SP_DRAG_MOVE_ORIGIN)) {
GdkCursor *guide_cursor;
diff --git a/src/display/cairo-utils.cpp b/src/display/cairo-utils.cpp
index 5b358ade7..d6ff7b2f0 100644
--- a/src/display/cairo-utils.cpp
+++ b/src/display/cairo-utils.cpp
@@ -19,6 +19,7 @@
#include <glibmm/fileutils.h>
#include <2geom/pathvector.h>
#include <2geom/bezier-curve.h>
+#include <2geom/elliptical-arc.h>
#include <2geom/hvlinesegment.h>
#include <2geom/affine.h>
#include <2geom/point.h>
@@ -502,7 +503,17 @@ void Pixbuf::ensurePixelFormat(PixelFormat fmt)
static void
feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & trans, Geom::Rect view, bool optimize_stroke)
{
- if( is_straight_curve(c) )
+ using Geom::X;
+ using Geom::Y;
+
+ unsigned order = 0;
+ if (Geom::BezierCurve const* b = dynamic_cast<Geom::BezierCurve const*>(&c)) {
+ order = b->order();
+ }
+
+ // handle the three typical curve cases
+ switch (order) {
+ case 1:
{
Geom::Point end_tr = c.finalPoint() * trans;
if (!optimize_stroke) {
@@ -516,57 +527,97 @@ feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & tran
}
}
}
- else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c)) {
+ break;
+ case 2:
+ {
+ Geom::QuadraticBezier const *quadratic_bezier = static_cast<Geom::QuadraticBezier const*>(&c);
std::vector<Geom::Point> points = quadratic_bezier->points();
points[0] *= trans;
points[1] *= trans;
points[2] *= trans;
+ // degree-elevate to cubic Bezier, since Cairo doesn't do quadratic Beziers
Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]);
Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]);
if (!optimize_stroke) {
- cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]);
+ cairo_curve_to(cr, b1[X], b1[Y], b2[X], b2[Y], points[2][X], points[2][Y]);
} else {
Geom::Rect swept(points[0], points[2]);
swept.expandTo(points[1]);
if (swept.intersects(view)) {
- cairo_curve_to(cr, b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]);
+ cairo_curve_to(cr, b1[X], b1[Y], b2[X], b2[Y], points[2][X], points[2][Y]);
} else {
- cairo_move_to(cr, points[2][0], points[2][1]);
+ cairo_move_to(cr, points[2][X], points[2][Y]);
}
}
}
- else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const*>(&c)) {
+ break;
+ case 3:
+ {
+ Geom::CubicBezier const *cubic_bezier = static_cast<Geom::CubicBezier const*>(&c);
std::vector<Geom::Point> points = cubic_bezier->points();
//points[0] *= trans; // don't do this one here for fun: it is only needed for optimized strokes
points[1] *= trans;
points[2] *= trans;
points[3] *= trans;
if (!optimize_stroke) {
- cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
+ cairo_curve_to(cr, points[1][X], points[1][Y], points[2][X], points[2][Y], points[3][X], points[3][Y]);
} else {
points[0] *= trans; // didn't transform this point yet
Geom::Rect swept(points[0], points[3]);
swept.expandTo(points[1]);
swept.expandTo(points[2]);
if (swept.intersects(view)) {
- cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
+ cairo_curve_to(cr, points[1][X], points[1][Y], points[2][X], points[2][Y], points[3][X], points[3][Y]);
} else {
- cairo_move_to(cr, points[3][0], points[3][1]);
+ cairo_move_to(cr, points[3][X], points[3][Y]);
}
}
}
-// else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc *>(c)) {
-// //TODO: get at the innards and spit them out to cairo
-// }
- else {
- //this case handles sbasis as well as all other curve types
- Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
-
- //recurse to convert the new path resulting from the sbasis to svgd
- for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
- feed_curve_to_cairo(cr, *iter, trans, view, optimize_stroke);
+ break;
+ default:
+ {
+ if (Geom::EllipticalArc const *a = dynamic_cast<Geom::EllipticalArc const*>(&c)) {
+ //if (!optimize_stroke || a->boundsFast().intersects(view)) {
+ Geom::Affine xform = a->unitCircleTransform() * trans;
+ Geom::Point ang(a->initialAngle().radians(), a->finalAngle().radians());
+
+ // Apply the transformation to the current context
+ cairo_matrix_t cm;
+ cm.xx = xform[0];
+ cm.xy = xform[2];
+ cm.x0 = xform[4];
+ cm.yx = xform[1];
+ cm.yy = xform[3];
+ cm.y0 = xform[5];
+
+ cairo_save(cr);
+ cairo_transform(cr, &cm);
+
+ // Draw the circle
+ if (a->sweep()) {
+ cairo_arc(cr, 0, 0, 1, ang[0], ang[1]);
+ } else {
+ cairo_arc_negative(cr, 0, 0, 1, ang[0], ang[1]);
+ }
+ // Revert the current context
+ cairo_restore(cr);
+ //} else {
+ // Geom::Point f = a->finalPoint() * trans;
+ // cairo_move_to(cr, f[X], f[Y]);
+ //}
+ } else {
+ // handles sbasis as well as all other curve types
+ // this is very slow
+ Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
+
+ // recurse to convert the new path resulting from the sbasis to svgd
+ for (Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
+ feed_curve_to_cairo(cr, *iter, trans, view, optimize_stroke);
+ }
}
}
+ break;
+ }
}
@@ -579,7 +630,7 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path)
cairo_move_to(ct, path.initialPoint()[0], path.initialPoint()[1] );
- for(Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
+ for (Geom::Path::const_iterator cit = path.begin(); cit != path.end_open(); ++cit) {
feed_curve_to_cairo(ct, *cit, Geom::identity(), Geom::Rect(), false); // optimize_stroke is false, so the view rect is not used
}
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
index 0bfb00b62..80eb69546 100644
--- a/src/display/drawing-item.cpp
+++ b/src/display/drawing-item.cpp
@@ -127,7 +127,7 @@ DrawingItem::DrawingItem(Drawing &drawing)
, _pick_children(0)
, _antialias(1)
, _isolation(SP_CSS_ISOLATION_AUTO)
- , _blend_mode(SP_CSS_BLEND_NORMAL)
+ , _mix_blend_mode(SP_CSS_BLEND_NORMAL)
{}
DrawingItem::~DrawingItem()
@@ -291,10 +291,10 @@ DrawingItem::setIsolation(unsigned isolation)
}
void
-DrawingItem::setBlendMode(unsigned blend_mode)
+DrawingItem::setBlendMode(unsigned mix_blend_mode)
{
- _blend_mode = blend_mode;
- //if( blend_mode != 0 ) std::cout << "setBlendMode: " << blend_mode << std::endl;
+ _mix_blend_mode = mix_blend_mode;
+ //if( mix_blend_mode != 0 ) std::cout << "setBlendMode: " << mix_blend_mode << std::endl;
_markForRendering();
}
@@ -592,7 +592,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag
if (_cached) {
if (_cache) {
_cache->prepare();
- set_cairo_blend_operator( dc, _blend_mode );
+ set_cairo_blend_operator( dc, _mix_blend_mode );
_cache->paintFromCache(dc, carea);
if (!carea) return RENDER_OK;
@@ -622,7 +622,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag
nir |= (_filter != NULL && render_filters); // 3. it has a filter
nir |= needs_opacity; // 4. it is non-opaque
nir |= (_cache != NULL); // 5. it is cached
- nir |= (_blend_mode != SP_CSS_BLEND_NORMAL); // 6. Blend mode not normal
+ nir |= (_mix_blend_mode != SP_CSS_BLEND_NORMAL); // 6. Blend mode not normal
nir |= (_isolation == SP_CSS_ISOLATION_ISOLATE); // 7. Explicit isolatiom
/* How the rendering is done.
@@ -735,7 +735,7 @@ DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flag
}
dc.rectangle(*carea);
dc.setSource(&intermediate);
- set_cairo_blend_operator( dc, _blend_mode );
+ set_cairo_blend_operator( dc, _mix_blend_mode );
dc.fill();
dc.setSource(0,0,0,0);
// the call above is to clear a ref on the intermediate surface held by dc
diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h
index d89299eeb..925bcbddb 100644
--- a/src/display/drawing-item.h
+++ b/src/display/drawing-item.h
@@ -209,7 +209,7 @@ protected:
unsigned _antialias : 1; ///< Whether to use antialiasing
unsigned _isolation : 1;
- unsigned _blend_mode : 4;
+ unsigned _mix_blend_mode : 4;
friend class Drawing;
};
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
index 05a2c3c2a..9f3b447df 100644
--- a/src/display/drawing-text.cpp
+++ b/src/display/drawing-text.cpp
@@ -150,25 +150,26 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext
return STATE_ALL;
}
-DrawingItem *
-DrawingGlyphs::_pickItem(Geom::Point const &p, double delta, unsigned /*flags*/)
+DrawingItem *DrawingGlyphs::_pickItem(Geom::Point const &p, double /*delta*/, unsigned /*flags*/)
{
DrawingText *ggroup = dynamic_cast<DrawingText *>(_parent);
if (!ggroup) {
throw InvalidItemException();
}
+ DrawingItem *result = NULL;
bool invisible = (ggroup->_nrstyle.fill.type == NRStyle::PAINT_NONE) &&
(ggroup->_nrstyle.stroke.type == NRStyle::PAINT_NONE);
- if (!_font || !_bbox || (!_drawing.outline() && invisible) ) {
- return NULL;
- }
- // With text we take a simple approach: pick if the point is in a character bbox
- Geom::Rect expanded(_pick_bbox);
- // FIXME, why expand by delta? When is the next line needed?
- // expanded.expandBy(delta);
- if (expanded.contains(p)) return this;
- return NULL;
+ if (_font && _bbox && (_drawing.outline() || !invisible) ) {
+ // With text we take a simple approach: pick if the point is in a character bbox
+ Geom::Rect expanded(_pick_bbox);
+ // FIXME, why expand by delta? When is the next line needed?
+ // expanded.expandBy(delta);
+ if (expanded.contains(p)) {
+ result = this;
+ }
+ }
+ return result;
}
diff --git a/src/document-undo.cpp b/src/document-undo.cpp
index 0bce4420a..679223da6 100644
--- a/src/document-undo.cpp
+++ b/src/document-undo.cpp
@@ -254,6 +254,7 @@ gboolean Inkscape::DocumentUndo::undo(SPDocument *doc)
Inkscape::Event *log=(Inkscape::Event *)doc->priv->undo->data;
doc->priv->undo = g_slist_remove (doc->priv->undo, log);
sp_repr_undo_log (log->event);
+ doc->_updateDocument();
doc->priv->redo = g_slist_prepend (doc->priv->redo, log);
doc->setModifiedSinceSave();
diff --git a/src/extension/internal/emf-inout.cpp b/src/extension/internal/emf-inout.cpp
index 863d1e006..084fbcd58 100644
--- a/src/extension/internal/emf-inout.cpp
+++ b/src/extension/internal/emf-inout.cpp
@@ -1641,11 +1641,19 @@ int Emf::myEnhMetaFileProc(char *contents, unsigned int length, PEMF_CALLBACK_DA
// next record is valid type and forces pending text to be drawn immediately
if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((emr_mask != U_EMR_INVALID) && (emr_mask & U_DRAW_TEXT) && d->tri->dirty)){
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipEmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
SVGOStringStream ts;
ts << d->tri->out;
d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
if(d->dc[d->level].dirty){ //Apply the delayed background changes, clear the flag
d->dc[d->level].bkMode = tbkMode;
@@ -2524,8 +2532,8 @@ std::cout << "BEFORE DRAW"
double cx = pix_to_x_point( d, (rclBox.left + rclBox.right)/2.0, (rclBox.bottom + rclBox.top)/2.0 );
double cy = pix_to_y_point( d, (rclBox.left + rclBox.right)/2.0, (rclBox.bottom + rclBox.top)/2.0 );
- double rx = pix_to_abs_size( d, fabs(rclBox.right - rclBox.left )/2.0 );
- double ry = pix_to_abs_size( d, fabs(rclBox.top - rclBox.bottom)/2.0 );
+ double rx = pix_to_abs_size( d, std::abs(rclBox.right - rclBox.left )/2.0 );
+ double ry = pix_to_abs_size( d, std::abs(rclBox.top - rclBox.bottom)/2.0 );
SVGOStringStream tmp_ellipse;
tmp_ellipse << "cx=\"" << cx << "\" ";
@@ -3141,11 +3149,19 @@ std::cout << "BEFORE DRAW"
int status = trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ori is actually escapement
if(status==-1){ // change of escapement, emit what we have and reset
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipEmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
ts << d->tri->out;
d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
(void) trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ignore return status, it must work
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
g_free(escaped_text);
@@ -3479,7 +3495,7 @@ Emf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
if (d.pDesc){ free( d.pDesc ); }
-// std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
+// std::cout << "SVG Output: " << std::endl << d.outsvg << std::endl;
SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg.c_str(), strlen(d.outsvg.c_str()), TRUE);
diff --git a/src/extension/internal/emf-print.cpp b/src/extension/internal/emf-print.cpp
index 9c68e40a4..e054829b5 100644
--- a/src/extension/internal/emf-print.cpp
+++ b/src/extension/internal/emf-print.cpp
@@ -977,8 +977,8 @@ unsigned int PrintEmf::fill(
using Geom::X;
using Geom::Y;
- SPItem *item = SP_ITEM(style->object);
- SPClipPath *scp = (item->clip_ref ? item->clip_ref->getObject() : NULL);
+ //SPItem *item = SP_ITEM(style->object);
+ //SPClipPath *scp = (item->clip_ref ? item->clip_ref->getObject() : NULL);
Geom::Affine tf = m_tr_stack.top();
@@ -1882,7 +1882,7 @@ unsigned int PrintEmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
fix90n = 1; //assume vertical
rot = (double)(((int) round(rot)) - irem);
rotb = rot * M_PI / 1800.0;
- if (abs(rot) == 900.0) {
+ if (std::abs(rot) == 900.0) {
fix90n = 2;
}
}
diff --git a/src/extension/internal/emf-print.h b/src/extension/internal/emf-print.h
index 1e4970a46..9a1251b38 100644
--- a/src/extension/internal/emf-print.h
+++ b/src/extension/internal/emf-print.h
@@ -29,7 +29,7 @@ namespace Internal {
class PrintEmf : public PrintMetafile
{
- uint32_t hbrush, hbrushOld, hpen, hpenOld;
+ uint32_t hbrush, hbrushOld, hpen;
unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform);
bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Affine &transform);
diff --git a/src/extension/internal/text_reassemble.c b/src/extension/internal/text_reassemble.c
index 810e3f8cc..4dfc49420 100644
--- a/src/extension/internal/text_reassemble.c
+++ b/src/extension/internal/text_reassemble.c
@@ -67,8 +67,8 @@ Optional compiler switches for development:
File: text_reassemble.c
-Version: 0.0.14
-Date: 25-MAR-2014
+Version: 0.0.15
+Date: 24-JUL-2014
Author: David Mathog, Biology Division, Caltech
email: mathog@caltech.edu
Copyright: 2014 David Mathog and California Institute of Technology (Caltech)
@@ -550,7 +550,7 @@ int TR_check_set_vadvance(TR_INFO *tri, int src, int lines){
See if the line to be added is compatible.
All text fields in a complex have the same advance, so just set/check the first one.
vadvance must be within 1% or do not add a new line */
- if(fabs(1.0 - (tpi->chunks[trec].vadvance/newV) > 0.01)){
+ if(fabs(1.0 - (tpi->chunks[trec].vadvance/newV)) > 0.01){
status = 1;
}
else { /* recalculate the weighted vadvance */
@@ -1820,7 +1820,9 @@ printf("Face idx:%d bbox: xMax/Min:%ld,%ld yMax/Min:%ld,%ld UpEM:%d asc/des:%d,%
fasc = ((double) (fsp->face->ascender) )/64.0;
fdsc = ((double) (fsp->face->descender))/64.0;
- if(tri->load_flags & FT_LOAD_NO_SCALE) xe *= tsp->fs/32.0;
+ /* originally the denominator was just 32.0, but it broke when units_per_EM wasn't 2048 */
+ double fixscale = tsp->fs/(((double) fsp->face->units_per_EM)/64.0);
+ if(tri->load_flags & FT_LOAD_NO_SCALE) xe *= fixscale;
/* now place the rectangle using ALN information */
if( taln & ALIHORI & ALILEFT ){
@@ -1837,11 +1839,11 @@ printf("Face idx:%d bbox: xMax/Min:%ld,%ld yMax/Min:%ld,%ld UpEM:%d asc/des:%d,%
}
tpi->chunks[current].ldir = tsp->ldir;
- if(tri->load_flags & FT_LOAD_NO_SCALE){
- asc *= tsp->fs/32.0;
- dsc *= tsp->fs/32.0;
- fasc *= tsp->fs/32.0;
- fdsc *= tsp->fs/32.0;
+ if(tri->load_flags & FT_LOAD_NO_SCALE){
+ asc *= fixscale;
+ dsc *= fixscale;
+ fasc *= fixscale;
+ fdsc *= fixscale;
}
diff --git a/src/extension/internal/wmf-inout.cpp b/src/extension/internal/wmf-inout.cpp
index 85060470b..5ccad678a 100644
--- a/src/extension/internal/wmf-inout.cpp
+++ b/src/extension/internal/wmf-inout.cpp
@@ -63,7 +63,6 @@ namespace Extension {
namespace Internal {
-static U_RECT16 rc_old;
static bool clipset = false;
static uint32_t BLTmode=0;
@@ -671,7 +670,7 @@ void Wmf::add_clips(PWMF_CALLBACK_DATA d, const char *clippath, unsigned int log
SVGOStringStream tmp_clippath;
tmp_clippath << "\n<clipPath";
tmp_clippath << "\n\tclipPathUnits=\"userSpaceOnUse\" ";
- tmp_clippath << "\n\tid=\"clipEmfPath" << d->dc[d->level].clip_id << "\"";
+ tmp_clippath << "\n\tid=\"clipWmfPath" << d->dc[d->level].clip_id << "\"";
tmp_clippath << " >";
tmp_clippath << "\n\t<path d=\"";
tmp_clippath << combined;
@@ -896,7 +895,7 @@ Wmf::output_style(PWMF_CALLBACK_DATA d)
}
tmp_style << "\" ";
if (d->dc[d->level].clip_id)
- tmp_style << "\n\tclip-path=\"url(#clipEmfPath" << d->dc[d->level].clip_id << ")\" ";
+ tmp_style << "\n\tclip-path=\"url(#clipWmfPath" << d->dc[d->level].clip_id << ")\" ";
d->outsvg += tmp_style.str().c_str();
}
@@ -1689,11 +1688,19 @@ int Wmf::myMetaFileProc(const char *contents, unsigned int length, PWMF_CALLBACK
// next record is valid type and forces pending text to be drawn immediately
if ((d->dc[d->level].dirty & DIRTY_TEXT) || ((wmr_mask != U_WMR_INVALID) && (wmr_mask & U_DRAW_TEXT) && d->tri->dirty)){
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipWmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
SVGOStringStream ts;
ts << d->tri->out;
d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
if(d->dc[d->level].dirty){ //Apply the delayed background changes, clear the flag
d->dc[d->level].bkMode = tbkMode;
@@ -2054,8 +2061,8 @@ std::cout << "BEFORE DRAW"
double cx = pix_to_x_point( d, (rc.left + rc.right)/2.0, (rc.bottom + rc.top)/2.0 );
double cy = pix_to_y_point( d, (rc.left + rc.right)/2.0, (rc.bottom + rc.top)/2.0 );
- double rx = pix_to_abs_size( d, fabs(rc.right - rc.left )/2.0 );
- double ry = pix_to_abs_size( d, fabs(rc.top - rc.bottom)/2.0 );
+ double rx = pix_to_abs_size( d, std::abs(rc.right - rc.left )/2.0 );
+ double ry = pix_to_abs_size( d, std::abs(rc.top - rc.bottom)/2.0 );
SVGOStringStream tmp_ellipse;
tmp_ellipse << "cx=\"" << cx << "\" ";
@@ -2591,11 +2598,19 @@ std::cout << "BEFORE DRAW"
status = trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ori is actually escapement
if(status==-1){ // change of escapement, emit what we have and reset
TR_layout_analyze(d->tri);
+ if (d->dc[d->level].clip_id){
+ SVGOStringStream tmp_clip;
+ tmp_clip << "\n<g\n\tclip-path=\"url(#clipWmfPath" << d->dc[d->level].clip_id << ")\"\n>";
+ d->outsvg += tmp_clip.str().c_str();
+ }
TR_layout_2_svg(d->tri);
ts << d->tri->out;
d->outsvg += ts.str().c_str();
d->tri = trinfo_clear(d->tri);
(void) trinfo_load_textrec(d->tri, &tsp, tsp.ori,TR_EMFBOT); // ignore return status, it must work
+ if (d->dc[d->level].clip_id){
+ d->outsvg += "\n</g>\n";
+ }
}
g_free(escaped_text);
@@ -3072,7 +3087,7 @@ Wmf::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri )
(void) myMetaFileProc(contents,length, &d);
free(contents);
-// std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl;
+// std::cout << "SVG Output: " << std::endl << d.outsvg << std::endl;
SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg.c_str(), strlen(d.outsvg.c_str()), TRUE);
diff --git a/src/extension/internal/wmf-print.cpp b/src/extension/internal/wmf-print.cpp
index 55ad5da5f..e5ff34009 100644
--- a/src/extension/internal/wmf-print.cpp
+++ b/src/extension/internal/wmf-print.cpp
@@ -1396,7 +1396,7 @@ unsigned int PrintWmf::text(Inkscape::Extension::Print * /*mod*/, char const *te
fix90n = 1; //assume vertical
rot = (double)(((int) round(rot)) - irem);
rotb = rot * M_PI / 1800.0;
- if (abs(rot) == 900.0) {
+ if (std::abs(rot) == 900.0) {
fix90n = 2;
}
}
diff --git a/src/extension/internal/wmf-print.h b/src/extension/internal/wmf-print.h
index 1e5d4c323..e4cf19184 100644
--- a/src/extension/internal/wmf-print.h
+++ b/src/extension/internal/wmf-print.h
@@ -28,7 +28,7 @@ namespace Internal {
class PrintWmf : public PrintMetafile
{
- uint32_t hbrush, hpen, hpenOld, hbrush_null, hpen_null;
+ uint32_t hbrush, hpen, hbrush_null, hpen_null;
uint32_t hmiterlimit; // used to minimize redundant records that set this
unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform);
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 89b7968fc..27f4d7a98 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -1296,6 +1296,10 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
break;
case POINT_LG_MID:
{
+ if (lg->vector.stops.size() < point_i) {
+ g_message("POINT_LG_MID bug trigger, see LP bug #453067");
+ break;
+ }
gdouble offset = lg->vector.stops.at(point_i).offset;
p = (1-offset) * Geom::Point(lg->x1.computed, lg->y1.computed) + offset * Geom::Point(lg->x2.computed, lg->y2.computed);
}
@@ -1321,12 +1325,20 @@ Geom::Point getGradientCoords(SPItem *item, GrPointType point_type, guint point_
break;
case POINT_RG_MID1:
{
+ if (rg->vector.stops.size() < point_i) {
+ g_message("POINT_RG_MID1 bug trigger, see LP bug #453067");
+ break;
+ }
gdouble offset = rg->vector.stops.at(point_i).offset;
p = (1-offset) * Geom::Point (rg->cx.computed, rg->cy.computed) + offset * Geom::Point(rg->cx.computed + rg->r.computed, rg->cy.computed);
}
break;
case POINT_RG_MID2:
{
+ if (rg->vector.stops.size() < point_i) {
+ g_message("POINT_RG_MID2 bug trigger, see LP bug #453067");
+ break;
+ }
gdouble offset = rg->vector.stops.at(point_i).offset;
p = (1-offset) * Geom::Point (rg->cx.computed, rg->cy.computed) + offset * Geom::Point(rg->cx.computed, rg->cy.computed - rg->r.computed);
}
diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp
index ee4c1bc8c..a14220cfa 100644
--- a/src/gradient-drag.cpp
+++ b/src/gradient-drag.cpp
@@ -21,7 +21,6 @@
#include <glibmm/i18n.h>
#include <cstring>
#include <string>
-//#include <2geom/bezier-curve.h>
#include "desktop-handles.h"
#include "selection.h"
@@ -38,6 +37,7 @@
#include "svg/css-ostringstream.h"
#include "svg/svg.h"
#include "preferences.h"
+#include "inkscape.h"
#include "sp-item.h"
#include "style.h"
#include "knot.h"
@@ -55,6 +55,7 @@
#include "verbs.h"
#include "display/sp-canvas.h"
#include "ui/control-manager.h"
+#include "ui/tools/tool-base.h"
using Inkscape::ControlManager;
using Inkscape::CtrlLineType;
@@ -783,6 +784,9 @@ static void gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, gui
dragger->parent->draggers = g_list_remove (dragger->parent->draggers, dragger);
delete dragger;
+ // throw out delayed snap context
+ Inkscape::UI::Tools::sp_event_context_discard_delayed_snap_event(SP_ACTIVE_DESKTOP->event_context);
+
// update the new merged dragger
d_new->fireDraggables(true, false, true);
d_new->parent->updateLines();
@@ -790,8 +794,7 @@ static void gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, gui
d_new->updateKnotShape ();
d_new->updateTip ();
d_new->updateDependencies(true);
- DocumentUndo::done(sp_desktop_document (d_new->parent->desktop), SP_VERB_CONTEXT_GRADIENT,
- _("Merge gradient handles"));
+ DocumentUndo::done(sp_desktop_document (d_new->parent->desktop), SP_VERB_CONTEXT_GRADIENT, _("Merge gradient handles"));
return;
}
}
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index c9148a634..6eba6e949 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -168,24 +168,25 @@ bounds_exact_transformed(Geom::PathVector const & pv, Geom::Affine const & t)
for (Geom::Path::const_iterator cit = it->begin(); cit != it->end_open(); ++cit) {
Geom::Curve const &c = *cit;
- if( is_straight_curve(c) )
- {
- bbox.expandTo( c.finalPoint() * t );
- }
- else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const *>(&c))
- {
- Geom::Point c0 = (*cubic_bezier)[0] * t;
- Geom::Point c1 = (*cubic_bezier)[1] * t;
- Geom::Point c2 = (*cubic_bezier)[2] * t;
- Geom::Point c3 = (*cubic_bezier)[3] * t;
- cubic_bbox( c0[0], c0[1],
- c1[0], c1[1],
- c2[0], c2[1],
- c3[0], c3[1],
- bbox );
+ unsigned order = 0;
+ if (Geom::BezierCurve const* b = dynamic_cast<Geom::BezierCurve const*>(&c)) {
+ order = b->order();
}
- else
- {
+
+ if (order == 1) { // line segment
+ bbox.expandTo(c.finalPoint() * t);
+
+ // TODO: we can make the case for quadratics faster by degree elevating them to
+ // cubic and then taking the bbox of that.
+
+ } else if (order == 3) { // cubic bezier
+ Geom::CubicBezier const &cubic_bezier = static_cast<Geom::CubicBezier const&>(c);
+ Geom::Point c0 = cubic_bezier[0] * t;
+ Geom::Point c1 = cubic_bezier[1] * t;
+ Geom::Point c2 = cubic_bezier[2] * t;
+ Geom::Point c3 = cubic_bezier[3] * t;
+ cubic_bbox(c0[0], c0[1], c1[0], c1[1], c2[0], c2[1], c3[0], c3[1], bbox);
+ } else {
// should handle all not-so-easy curves:
Geom::Curve *ctemp = cit->transformed(t);
bbox.unionWith( ctemp->boundsExact());
@@ -356,8 +357,11 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m,
Geom::Coord tolerance, Geom::Rect const *viewbox,
Geom::Point &p0) // pass p0 through as it represents the last endpoint added (the finalPoint of last curve)
{
- if( is_straight_curve(c) )
- {
+ unsigned order = 0;
+ if (Geom::BezierCurve const* b = dynamic_cast<Geom::BezierCurve const*>(&c)) {
+ order = b->order();
+ }
+ if (order == 1) {
Geom::Point pe = c.finalPoint() * m;
if (bbox) {
bbox->expandTo(pe);
@@ -373,10 +377,11 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m,
}
p0 = pe;
}
- else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const *>(&c)) {
- Geom::Point p1 = (*cubic_bezier)[1] * m;
- Geom::Point p2 = (*cubic_bezier)[2] * m;
- Geom::Point p3 = (*cubic_bezier)[3] * m;
+ else if (order == 3) {
+ Geom::CubicBezier const& cubic_bezier = static_cast<Geom::CubicBezier const&>(c);
+ Geom::Point p1 = cubic_bezier[1] * m;
+ Geom::Point p2 = cubic_bezier[2] * m;
+ Geom::Point p3 = cubic_bezier[3] * m;
// get approximate bbox from handles (convex hull property of beziers):
Geom::Rect swept(p0, p3);
@@ -402,7 +407,7 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m,
Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
//recurse to convert the new path resulting from the sbasis to svgd
- for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
+ for (Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
geom_curve_bbox_wind_distance(*iter, m, pt, bbox, wind, dist, tolerance, viewbox, p0);
}
}
diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp
index 6af5c6a56..b66156b09 100644
--- a/src/knot-holder-entity.cpp
+++ b/src/knot-holder-entity.cpp
@@ -158,7 +158,7 @@ static Geom::Point sp_pattern_extract_trans(SPPattern const *pat)
void
PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
{
- SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
Geom::Point p_snapped = snap_knot_position(p, state);
@@ -173,7 +173,7 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori
if (state) {
Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat);
- item->adjust_pattern(Geom::Affine(Geom::Translate(q)));
+ item->adjust_pattern(Geom::Translate(q), false, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
}
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -182,14 +182,14 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori
Geom::Point
PatternKnotHolderEntityXY::knot_get() const
{
- SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
return sp_pattern_extract_trans(pat);
}
Geom::Point
PatternKnotHolderEntityAngle::knot_get() const
{
- SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
gdouble x = pattern_width(pat);
gdouble y = 0;
@@ -207,7 +207,7 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const &
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
- SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// get the angle from pattern 0,0 to the cursor pos
Geom::Point delta = p - sp_pattern_extract_trans(pat);
@@ -223,14 +223,14 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const &
Geom::Point const t = sp_pattern_extract_trans(pat);
rot[4] = t[Geom::X];
rot[5] = t[Geom::Y];
- item->adjust_pattern(rot, true);
+ item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
void
PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
{
- SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
// FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
Geom::Point p_snapped = snap_knot_position(p, state);
@@ -257,7 +257,7 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &
Geom::Point const t = sp_pattern_extract_trans(pat);
rot[4] = t[Geom::X];
rot[5] = t[Geom::Y];
- item->adjust_pattern(rot, true);
+ item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
@@ -265,7 +265,7 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &
Geom::Point
PatternKnotHolderEntityScale::knot_get() const
{
- SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
+ SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
gdouble x = pattern_width(pat);
gdouble y = pattern_height(pat);
diff --git a/src/knot-holder-entity.h b/src/knot-holder-entity.h
index a9268d396..dde60f515 100644
--- a/src/knot-holder-entity.h
+++ b/src/knot-holder-entity.h
@@ -101,20 +101,30 @@ protected:
class PatternKnotHolderEntityXY : public KnotHolderEntity {
public:
+ PatternKnotHolderEntityXY(bool fill) : KnotHolderEntity(), _fill(fill) {}
virtual Geom::Point knot_get() const;
virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+private:
+ // true if the entity tracks fill, false for stroke
+ bool _fill;
};
class PatternKnotHolderEntityAngle : public KnotHolderEntity {
public:
+ PatternKnotHolderEntityAngle(bool fill) : KnotHolderEntity(), _fill(fill) {}
virtual Geom::Point knot_get() const;
virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+private:
+ bool _fill;
};
class PatternKnotHolderEntityScale : public KnotHolderEntity {
public:
+ PatternKnotHolderEntityScale(bool fill) : KnotHolderEntity(), _fill(fill) {}
virtual Geom::Point knot_get() const;
virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+private:
+ bool _fill;
};
#endif /* !SEEN_KNOT_HOLDER_ENTITY_H */
diff --git a/src/knot-ptr.cpp b/src/knot-ptr.cpp
new file mode 100644
index 000000000..de8118ba7
--- /dev/null
+++ b/src/knot-ptr.cpp
@@ -0,0 +1,25 @@
+#include <algorithm>
+#include <glib.h>
+#include <list>
+#include "knot-ptr.h"
+
+static std::list<void*> deleted_knots;
+
+void knot_deleted_callback(void* knot) {
+ if (std::find(deleted_knots.begin(), deleted_knots.end(), knot) == deleted_knots.end()) {
+ deleted_knots.push_back(knot);
+ }
+}
+
+void knot_created_callback(void* knot) {
+ std::list<void*>::iterator it = std::find(deleted_knots.begin(), deleted_knots.end(), knot);
+ if (it != deleted_knots.end()) {
+ deleted_knots.erase(it);
+ }
+}
+
+void check_if_knot_deleted(void* knot) {
+ if (std::find(deleted_knots.begin(), deleted_knots.end(), knot) != deleted_knots.end()) {
+ g_warning("Accessed knot after it was freed at %p", knot);
+ }
+}
diff --git a/src/knot-ptr.h b/src/knot-ptr.h
new file mode 100644
index 000000000..5895dfd2e
--- /dev/null
+++ b/src/knot-ptr.h
@@ -0,0 +1,8 @@
+#ifndef KNOT_PTR_DETECTOR
+#define KNOT_PTR_DETECTOR
+
+void knot_deleted_callback(void* knot);
+void knot_created_callback(void* knot);
+void check_if_knot_deleted(void* knot);
+
+#endif
diff --git a/src/knot.cpp b/src/knot.cpp
index 61d0dff39..6205af26a 100644
--- a/src/knot.cpp
+++ b/src/knot.cpp
@@ -21,6 +21,7 @@
#include "desktop.h"
#include "desktop-handles.h"
#include "knot.h"
+#include "knot-ptr.h"
#include "document.h"
#include "document-undo.h"
#include "preferences.h"
@@ -118,6 +119,7 @@ SPKnot::SPKnot(SPDesktop *desktop, gchar const *tip)
this->_event_handler_id = g_signal_connect(G_OBJECT(this->item), "event",
G_CALLBACK(sp_knot_handler), this);
+ knot_created_callback(this);
}
SPKnot::~SPKnot() {
@@ -162,6 +164,10 @@ SPKnot::~SPKnot() {
g_free(this->tip);
this->tip = NULL;
}
+
+ // FIXME: cannot snap to destroyed knot (lp:1309050)
+ //sp_event_context_discard_delayed_snap_event(this->desktop->event_context);
+ knot_deleted_callback(this);
}
void SPKnot::startDragging(Geom::Point const &p, gint x, gint y, guint32 etime) {
@@ -282,7 +288,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot
knot->setFlag(SP_KNOT_DRAGGING, TRUE);
}
- sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, (gpointer) knot, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::KNOT_HANDLER);
+ sp_event_context_snap_delay_handler(knot->desktop->event_context, NULL, knot, (GdkEventMotion *)event, Inkscape::UI::Tools::DelayedSnapEvent::KNOT_HANDLER);
sp_knot_handler_request_position(event, knot);
moved = TRUE;
}
diff --git a/src/knotholder.cpp b/src/knotholder.cpp
index cf87423d4..f0e69716b 100644
--- a/src/knotholder.cpp
+++ b/src/knotholder.cpp
@@ -247,12 +247,32 @@ void KnotHolder::add(KnotHolderEntity *e)
void KnotHolder::add_pattern_knotholder()
{
- if ((item->style->fill.isPaintserver())
- && SP_IS_PATTERN(item->style->getFillPaintServer()))
- {
- PatternKnotHolderEntityXY *entity_xy = new PatternKnotHolderEntityXY();
- PatternKnotHolderEntityAngle *entity_angle = new PatternKnotHolderEntityAngle();
- PatternKnotHolderEntityScale *entity_scale = new PatternKnotHolderEntityScale();
+ if ((item->style->fill.isPaintserver()) && SP_IS_PATTERN(item->style->getFillPaintServer())) {
+ PatternKnotHolderEntityXY *entity_xy = new PatternKnotHolderEntityXY(true);
+ PatternKnotHolderEntityAngle *entity_angle = new PatternKnotHolderEntityAngle(true);
+ PatternKnotHolderEntityScale *entity_scale = new PatternKnotHolderEntityScale(true);
+ entity_xy->create(desktop, item, this, Inkscape::CTRL_TYPE_POINT,
+ // TRANSLATORS: This refers to the pattern that's inside the object
+ _("<b>Move</b> the pattern fill inside the object"),
+ SP_KNOT_SHAPE_CROSS);
+
+ entity_scale->create(desktop, item, this, Inkscape::CTRL_TYPE_SIZER,
+ _("<b>Scale</b> the pattern fill; uniformly if with <b>Ctrl</b>"),
+ SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR);
+
+ entity_angle->create(desktop, item, this, Inkscape::CTRL_TYPE_ROTATE,
+ _("<b>Rotate</b> the pattern fill; with <b>Ctrl</b> to snap angle"),
+ SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR);
+
+ entity.push_back(entity_xy);
+ entity.push_back(entity_angle);
+ entity.push_back(entity_scale);
+ }
+
+ if ((item->style->stroke.isPaintserver()) && SP_IS_PATTERN(item->style->getStrokePaintServer())) {
+ PatternKnotHolderEntityXY *entity_xy = new PatternKnotHolderEntityXY(false);
+ PatternKnotHolderEntityAngle *entity_angle = new PatternKnotHolderEntityAngle(false);
+ PatternKnotHolderEntityScale *entity_scale = new PatternKnotHolderEntityScale(false);
entity_xy->create(desktop, item, this, Inkscape::CTRL_TYPE_POINT,
// TRANSLATORS: This refers to the pattern that's inside the object
_("<b>Move</b> the pattern fill inside the object"),
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt
index a4d35b339..3c64e5c8e 100644
--- a/src/live_effects/CMakeLists.txt
+++ b/src/live_effects/CMakeLists.txt
@@ -35,6 +35,7 @@ set(live_effects_SRC
# lpe-skeleton.cpp
lpe-sketch.cpp
lpe-spiro.cpp
+ lpe-roughen.cpp
lpe-tangent_to_curve.cpp
lpe-test-doEffect-stack.cpp
lpe-bspline.cpp
@@ -101,6 +102,7 @@ set(live_effects_SRC
lpe-skeleton.h
lpe-sketch.h
lpe-spiro.h
+ lpe-roughen.h
lpe-tangent_to_curve.h
lpe-test-doEffect-stack.h
lpe-bspline.h
diff --git a/src/live_effects/Makefile_insert b/src/live_effects/Makefile_insert
index 263b33b3c..91651a7c8 100644
--- a/src/live_effects/Makefile_insert
+++ b/src/live_effects/Makefile_insert
@@ -46,6 +46,8 @@ ink_common_sources += \
live_effects/lpe-lattice.h \
live_effects/lpe-lattice2.cpp \
live_effects/lpe-lattice2.h \
+ live_effects/lpe-roughen.cpp \
+ live_effects/lpe-roughen.h \
live_effects/lpe-simplify.cpp \
live_effects/lpe-simplify.h \
live_effects/lpe-envelope.cpp \
diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h
index 942ef5891..dac44981c 100644
--- a/src/live_effects/effect-enum.h
+++ b/src/live_effects/effect-enum.h
@@ -29,6 +29,7 @@ enum EffectType {
SPIRO,
LATTICE,
LATTICE2,
+ ROUGHEN,
SIMPLIFY,
ENVELOPE,
CONSTRUCT_GRID,
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index 0e9f92d09..5a9b6c7a2 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -27,6 +27,7 @@
#include "live_effects/lpe-spiro.h"
#include "live_effects/lpe-lattice.h"
#include "live_effects/lpe-lattice2.h"
+#include "live_effects/lpe-roughen.h"
#include "live_effects/lpe-simplify.h"
#include "live_effects/lpe-envelope.h"
#include "live_effects/lpe-constructgrid.h"
@@ -125,6 +126,7 @@ const Util::EnumData<EffectType> LPETypeData[] = {
/* 0.91 */
{POWERSTROKE, N_("Power stroke"), "powerstroke"},
{CLONE_ORIGINAL, N_("Clone original path"), "clone_original"},
+ {ROUGHEN, N_("Roughen"), "roughen"},
{BSPLINE, N_("BSpline"), "bspline"},
{SIMPLIFY, N_("Simplify"), "simplify"},
{LATTICE2, N_("Lattice Deformation 2"), "lattice2"},
@@ -269,6 +271,9 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
case FILLET_CHAMFER:
neweffect = static_cast<Effect*> ( new LPEFilletChamfer(lpeobj) );
break;
+ case ROUGHEN:
+ neweffect = static_cast<Effect*> ( new LPERoughen(lpeobj) );
+ break;
default:
g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
neweffect = NULL;
diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp
index 98557196d..bfb2c3ba4 100644
--- a/src/live_effects/lpe-fillet-chamfer.cpp
+++ b/src/live_effects/lpe-fillet-chamfer.cpp
@@ -517,6 +517,8 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
counter - counterCurves,
filletChamferData[counter - counterCurves][X]),
&intpart);
+ } else if (!path_it->closed() && curve_it2 == curve_endit){
+ time_it2 = 0;
} else {
time_it2 = modf(fillet_chamfer_values.to_time(
counter + 1, filletChamferData[counter + 1][X]),
@@ -529,6 +531,8 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
it1_length + fillet_chamfer_values.to_len(
counter - counterCurves,
filletChamferData[counter - counterCurves][X]);
+ } else if (!path_it->closed() && curve_it2 == curve_endit){
+ resultLenght = 0;
} else {
resultLenght =
it1_length + fillet_chamfer_values.to_len(
@@ -607,6 +611,8 @@ LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
int type = 0;
if(path_it->closed() && curve_it2 == curve_endit){
type = abs(filletChamferData[counter - counterCurves][Y]);
+ } else if (!path_it->closed() && curve_it2 == curve_endit){
+ //0
} else {
type = abs(filletChamferData[counter + 1][Y]);
}
diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp
new file mode 100644
index 000000000..9af849530
--- /dev/null
+++ b/src/live_effects/lpe-roughen.cpp
@@ -0,0 +1,389 @@
+/*
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <gtkmm.h>
+
+#include "live_effects/lpe-roughen.h"
+#include "display/curve.h"
+#include "live_effects/parameter/parameter.h"
+#include "helper/geom.h"
+#include <glibmm/i18n.h>
+#include <cmath>
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+static const Util::EnumData<DivisionMethod> DivisionMethodData[DM_END] = {
+ { DM_SEGMENTS, N_("By number of segments"), "segments" },
+ { DM_SIZE, N_("By max. segment size"), "size" }
+};
+static const Util::EnumDataConverter<DivisionMethod>
+ DMConverter(DivisionMethodData, DM_END);
+
+LPERoughen::LPERoughen(LivePathEffectObject *lpeobject)
+ : Effect(lpeobject),
+ // initialise your parameters here:
+ unit(_("Unit:"), _("Unit"), "unit", &wr, this),
+ method(_("Method:"), _("Division method"), "method", DMConverter, &wr,
+ this, DM_SEGMENTS),
+ maxSegmentSize(_("Max. segment size:"), _("Max. segment size"),
+ "maxSegmentSize", &wr, this, 10.),
+ segments(_("Number of segments:"), _("Number of segments"), "segments",
+ &wr, this, 2),
+ displaceX(_("Max. displacement in X:"), _("Max. displacement in X"),
+ "displaceX", &wr, this, 10.),
+ displaceY(_("Max. displacement in Y:"), _("Max. displacement in Y"),
+ "displaceY", &wr, this, 10.),
+ shiftNodes(_("Shift nodes"), _("Shift nodes"), "shiftNodes", &wr, this,
+ true),
+ shiftNodeHandles(_("Shift node handles"), _("Shift node handles"),
+ "shiftNodeHandles", &wr, this, true) {
+ registerParameter(dynamic_cast<Parameter *>(&unit));
+ registerParameter(dynamic_cast<Parameter *>(&method));
+ registerParameter(dynamic_cast<Parameter *>(&maxSegmentSize));
+ registerParameter(dynamic_cast<Parameter *>(&segments));
+ registerParameter(dynamic_cast<Parameter *>(&displaceX));
+ registerParameter(dynamic_cast<Parameter *>(&displaceY));
+ registerParameter(dynamic_cast<Parameter *>(&shiftNodes));
+ registerParameter(dynamic_cast<Parameter *>(&shiftNodeHandles));
+ displaceX.param_set_range(0., Geom::infinity());
+ displaceY.param_set_range(0., Geom::infinity());
+ maxSegmentSize.param_set_range(0., Geom::infinity());
+ maxSegmentSize.param_set_increments(1, 1);
+ maxSegmentSize.param_set_digits(1);
+ segments.param_set_range(1, Geom::infinity());
+ segments.param_set_increments(1, 1);
+ segments.param_set_digits(0);
+}
+
+LPERoughen::~LPERoughen() {}
+
+void LPERoughen::doBeforeEffect(SPLPEItem const */*lpeitem*/) {
+ displaceX.resetRandomizer();
+ displaceY.resetRandomizer();
+ srand(1);
+}
+
+Gtk::Widget *LPERoughen::newWidget() {
+ // use manage here, because after deletion of Effect object, others might
+ // still be pointing to this widget.
+ Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
+ vbox->set_border_width(5);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(2);
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter *param = *it;
+ Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
+ if (param->param_key == "unit") {
+ Gtk::Label *unitLabel = Gtk::manage(new Gtk::Label(
+ Glib::ustring(_("<b>Roughen unit</b>")), Gtk::ALIGN_START));
+ unitLabel->set_use_markup(true);
+ vbox->pack_start(*unitLabel, false, false, 2);
+ vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
+ Gtk::PACK_EXPAND_WIDGET);
+ }
+ if (param->param_key == "method") {
+ Gtk::Label *methodLabel = Gtk::manage(new Gtk::Label(
+ Glib::ustring(_("<b>Add nodes</b> Subdivide each segment")),
+ Gtk::ALIGN_START));
+ methodLabel->set_use_markup(true);
+ vbox->pack_start(*methodLabel, false, false, 2);
+ vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
+ Gtk::PACK_EXPAND_WIDGET);
+ }
+ if (param->param_key == "displaceX") {
+ Gtk::Label *displaceXLabel = Gtk::manage(new Gtk::Label(
+ Glib::ustring(_("<b>Jitter nodes</b> Move nodes/handles")),
+ Gtk::ALIGN_START));
+ displaceXLabel->set_use_markup(true);
+ vbox->pack_start(*displaceXLabel, false, false, 2);
+ vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
+ Gtk::PACK_EXPAND_WIDGET);
+ }
+ Glib::ustring *tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+double LPERoughen::sign(double randNumber) {
+ if (rand() % 100 < 49) {
+ randNumber *= -1.;
+ }
+ return randNumber;
+}
+
+Geom::Point LPERoughen::randomize() {
+ double displaceXParsed = Inkscape::Util::Quantity::convert(
+ displaceX, unit.get_abbreviation(), "px");
+ double displaceYParsed = Inkscape::Util::Quantity::convert(
+ displaceY, unit.get_abbreviation(), "px");
+ //maybe is better divide this point by 2...
+ Geom::Point output =
+ Geom::Point(sign(displaceXParsed), sign(displaceYParsed));
+ return output;
+}
+
+void LPERoughen::doEffect(SPCurve *curve) {
+ Geom::PathVector const original_pathv =
+ pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
+ curve->reset();
+
+ //Recorremos todos los paths a los que queremos aplicar el efecto, hasta el
+ //penúltimo
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
+ path_it != original_pathv.end(); ++path_it) {
+ //Si está vacío...
+ if (path_it->empty())
+ continue;
+ //Itreadores
+
+ Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve
+ Geom::Path::const_iterator curve_it2 =
+ ++(path_it->begin()); // outgoing curve
+ Geom::Path::const_iterator curve_endit =
+ path_it->end_default(); // this determines when the loop has to stop
+ //Creamos las lineas rectas que unen todos los puntos del trazado y donde se
+ //calcularán
+ //los puntos clave para los manejadores.
+ //Esto hace que la curva BSpline no pierda su condición aunque se trasladen
+ //dichos manejadores
+ SPCurve *nCurve = new SPCurve();
+ if (path_it->closed()) {
+ // if the path is closed, maybe we have to stop a bit earlier because the
+ // closing line segment has zerolength.
+ const Geom::Curve &closingline =
+ path_it->back_closed(); // the closing line segment is always of type
+ // Geom::LineSegment.
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ // closingline.isDegenerate() did not work, because it only checks for
+ // *exact* zero length, which goes wrong for relative coordinates and
+ // rounding errors...
+ // the closing line segment has zero-length. So stop before that one!
+ curve_endit = path_it->end_open();
+ }
+ }
+ //Si la curva está cerrada calculamos el punto donde
+ //deveria estar el nodo BSpline de cierre/inicio de la curva
+ //en posible caso de que se cierre con una linea recta creando un nodo
+ //BSPline
+ Geom::Point initialMove(0, 0);
+ if (shiftNodes) {
+ initialMove = randomize();
+ }
+ Geom::Point initialPoint = curve_it1->initialPoint() + initialMove;
+ nCurve->moveto(initialPoint);
+ Geom::Point A0(0, 0);
+ Geom::Point A1(0, 0);
+ Geom::Point A2(0, 0);
+ Geom::Point A3(0, 0);
+ while (curve_it2 != curve_endit) {
+ //aumentamos los valores para el siguiente paso en el bucle
+ //Recorremos todos los segmentos menos el último
+ Geom::CubicBezier const *cubic = NULL;
+ A0 = curve_it1->initialPoint();
+ A1 = curve_it1->initialPoint();
+ A2 = curve_it1->finalPoint();
+ A3 = curve_it1->finalPoint();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ A1 = (*cubic)[1];
+ if (shiftNodes) {
+ A1 = (*cubic)[1] + initialMove;
+ }
+ A2 = (*cubic)[2];
+ nCurve->curveto(A1, A2, A3);
+ } else {
+ nCurve->lineto(A3);
+ }
+ double length = Inkscape::Util::Quantity::convert(
+ curve_it1->length(0.001), "px", unit.get_abbreviation());
+ unsigned int splits = 0;
+ if (method == DM_SEGMENTS) {
+ splits = segments;
+ } else {
+ splits = ceil(length / maxSegmentSize);
+ }
+ for (unsigned int t = splits; t >= 1; t--) {
+ if (t == 1 && splits != 1) {
+ continue;
+ }
+ const SPCurve *tmp;
+ if (splits == 1) {
+ tmp = jitter(nCurve->last_segment());
+ } else {
+ tmp = addNodesAndJitter(nCurve->last_segment(), 1. / t);
+ }
+ if (nCurve->get_segment_count() > 1) {
+ nCurve->backspace();
+ nCurve->append_continuous(tmp, 0.001);
+ } else {
+ nCurve = tmp->copy();
+ }
+ delete tmp;
+ }
+ ++curve_it1;
+ ++curve_it2;
+ }
+ Geom::CubicBezier const *cubic = NULL;
+ A0 = curve_it1->initialPoint();
+ A1 = curve_it1->initialPoint();
+ A2 = curve_it1->finalPoint();
+ A3 = curve_it1->finalPoint();
+ cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
+ if (cubic) {
+ A1 = (*cubic)[1];
+ A2 = (*cubic)[2];
+ if (path_it->closed()) {
+ A2 = A2 + initialMove;
+ A3 = initialPoint;
+ }
+ nCurve->curveto(A1, A2, A3);
+ } else {
+ if (path_it->closed()) {
+ A3 = initialPoint;
+ }
+ nCurve->lineto(A3);
+ }
+ double length = Inkscape::Util::Quantity::convert(
+ curve_it1->length(0.001), "px", unit.get_abbreviation());
+ unsigned int splits = 0;
+ if (method == DM_SEGMENTS) {
+ splits = segments;
+ } else {
+ splits = ceil(length / maxSegmentSize);
+ }
+ for (unsigned int t = splits; t >= 1; t--) {
+ if (t == 1 && splits != 1) {
+ continue;
+ }
+ const SPCurve *tmp;
+ if (splits == 1) {
+ tmp = jitter(nCurve->last_segment());
+ } else {
+ tmp = addNodesAndJitter(nCurve->last_segment(), 1. / t);
+ }
+ if (nCurve->get_segment_count() > 1) {
+ nCurve->backspace();
+ nCurve->append_continuous(tmp, 0.001);
+ } else {
+ nCurve = tmp->copy();
+ }
+ delete tmp;
+ }
+ //y cerramos la curva
+ if (path_it->closed()) {
+ nCurve->closepath_current();
+ }
+ curve->append(nCurve, false);
+ nCurve->reset();
+ delete nCurve;
+ }
+}
+
+SPCurve *LPERoughen::addNodesAndJitter(const Geom::Curve *A, double t) {
+ SPCurve *out = new SPCurve();
+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
+ Geom::Point A1(0, 0);
+ Geom::Point A2(0, 0);
+ Geom::Point A3(0, 0);
+ Geom::Point B1(0, 0);
+ Geom::Point B2(0, 0);
+ Geom::Point B3(0, 0);
+ if (shiftNodes) {
+ A3 = randomize();
+ B3 = randomize();
+ }
+ if (shiftNodeHandles) {
+ A1 = randomize();
+ A2 = randomize();
+ B1 = randomize();
+ B2 = randomize();
+ } else {
+ A2 = A3;
+ B1 = A3;
+ B2 = B3;
+ }
+ if (cubic) {
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
+ std::vector<Geom::Point> seg1 = div.first.points(),
+ seg2 = div.second.points();
+ out->moveto(seg1[0]);
+ out->curveto(seg1[1] + A1, seg1[2] + A2, seg1[3] + A3);
+ out->curveto(seg2[1] + B1, seg2[2], seg2[3]);
+ } else if (shiftNodeHandles) {
+ out->moveto(A->initialPoint());
+ out->curveto(A->pointAt(t / 3) + A1, A->pointAt((t / 3) * 2) + A2,
+ A->pointAt(t) + A3);
+ out->curveto(A->pointAt(t + (t / 3)) + B1, A->pointAt(t + ((t / 3) * 2)),
+ A->finalPoint());
+ } else {
+ out->moveto(A->initialPoint());
+ out->lineto(A->pointAt(t) + A3);
+ out->lineto(A->finalPoint());
+ }
+ return out;
+}
+
+SPCurve *LPERoughen::jitter(const Geom::Curve *A) {
+ SPCurve *out = new SPCurve();
+ Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
+ Geom::Point A1(0, 0);
+ Geom::Point A2(0, 0);
+ Geom::Point A3(0, 0);
+ if (shiftNodes) {
+ A3 = randomize();
+ }
+ if (shiftNodeHandles) {
+ A1 = randomize();
+ A2 = randomize();
+ } else {
+ A2 = A3;
+ }
+ if (cubic) {
+ out->moveto((*cubic)[0]);
+ out->curveto((*cubic)[1] + A1, (*cubic)[2] + A2, (*cubic)[3] + A3);
+ } else if (shiftNodeHandles) {
+ out->moveto(A->initialPoint());
+ out->curveto(A->pointAt(0.3333) + A1, A->pointAt(0.6666) + A2,
+ A->finalPoint() + A3);
+ } else {
+ out->moveto(A->initialPoint());
+ out->lineto(A->finalPoint() + A3);
+ }
+ return out;
+}
+
+Geom::Point LPERoughen::tpoint(Geom::Point A, Geom::Point B, double t) {
+ using Geom::X;
+ using Geom::Y;
+ return Geom::Point(A[X] + t * (B[X] - A[X]), A[Y] + t * (B[Y] - A[Y]));
+}
+
+}; //namespace LivePathEffect
+}; /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h
new file mode 100644
index 000000000..cc7784dc0
--- /dev/null
+++ b/src/live_effects/lpe-roughen.h
@@ -0,0 +1,57 @@
+#ifndef INKSCAPE_LPE_ROUGHEN_H
+#define INKSCAPE_LPE_ROUGHEN_H
+
+/*
+ * Inkscape::LPERoughen
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+#include "live_effects/parameter/enum.h"
+#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/path.h"
+#include "live_effects/parameter/bool.h"
+#include "live_effects/parameter/unit.h"
+#include "live_effects/parameter/random.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+enum DivisionMethod {
+ DM_SEGMENTS,
+ DM_SIZE,
+ DM_END
+};
+
+class LPERoughen : public Effect {
+
+public:
+ LPERoughen(LivePathEffectObject *lpeobject);
+ virtual ~LPERoughen();
+
+ virtual void doEffect(SPCurve *curve);
+ virtual double sign(double randNumber);
+ virtual Geom::Point randomize();
+ virtual void doBeforeEffect(SPLPEItem const */*lpeitem*/);
+ virtual SPCurve *addNodesAndJitter(const Geom::Curve *A, double t);
+ virtual SPCurve *jitter(const Geom::Curve *A);
+ virtual Geom::Point tpoint(Geom::Point A, Geom::Point B, double t = 0.5);
+ virtual Gtk::Widget *newWidget();
+
+private:
+ UnitParam unit;
+ EnumParam<DivisionMethod> method;
+ ScalarParam maxSegmentSize;
+ ScalarParam segments;
+ RandomParam displaceX;
+ RandomParam displaceY;
+ BoolParam shiftNodes;
+ BoolParam shiftNodeHandles;
+ LPERoughen(const LPERoughen &);
+ LPERoughen &operator=(const LPERoughen &);
+
+};
+
+}; //namespace LivePathEffect
+}; //namespace Inkscape
+#endif
diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp
index 44d414942..8095056b7 100644
--- a/src/live_effects/parameter/path.cpp
+++ b/src/live_effects/parameter/path.cpp
@@ -197,7 +197,7 @@ PathParam::param_newWidget()
pButton->show();
pButton->signal_clicked().connect(sigc::mem_fun(*this, &PathParam::on_link_button_click));
static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true);
- pButton->set_tooltip_text(_("Link to path"));
+ pButton->set_tooltip_text(_("Link to path on clipboard"));
static_cast<Gtk::HBox*>(_widget)->show_all_children();
diff --git a/src/object-edit.cpp b/src/object-edit.cpp
index e9b183eca..fe22f6c1c 100644
--- a/src/object-edit.cpp
+++ b/src/object-edit.cpp
@@ -79,8 +79,8 @@ KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop)
knotholder = new OffsetKnotHolder(desktop, item, NULL);
} else if (SP_IS_FLOWTEXT(item) && SP_FLOWTEXT(item)->has_internal_frame()) {
knotholder = new FlowtextKnotHolder(desktop, SP_FLOWTEXT(item)->get_frame(NULL), NULL);
- } else if ((item->style->fill.isPaintserver())
- && SP_IS_PATTERN(item->style->getFillPaintServer())) {
+ } else if ((item->style->fill.isPaintserver() && SP_IS_PATTERN(item->style->getFillPaintServer())) ||
+ (item->style->stroke.isPaintserver() && SP_IS_PATTERN(item->style->getStrokePaintServer()))) {
knotholder = new KnotHolder(desktop, item, NULL);
knotholder->add_pattern_knotholder();
}
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 3b8956bc8..0f7aa6368 100644
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
@@ -147,6 +147,10 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
// For debugging: print the id of the candidate to the console
// SPObject *obj = (SPObject*)item;
// std::cout << "Snap candidate added: " << obj->getId() << std::endl;
+ if (_candidates->size() > 200) { // This makes Inkscape crawl already
+ std::cout << "Warning: limit of 200 snap target paths reached, some will be ignored" << std::endl;
+ break;
+ }
}
}
}
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 8837fbdb1..d77c06a95 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -1621,10 +1621,13 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons
item->doWriteTransform(item->getRepr(), item->transform, NULL, compensate);
}
- // if we're moving the actual object, not just updating the repr, we can transform the
+ // if we're transforming the actual object, not just updating the repr, we can transform the
// center by the same matrix (only necessary for non-translations)
if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) {
- item->setCenter(old_center * affine);
+ // If there's a viewbox, we might have an affine with a translation component;
+ // we will only apply the scaling/skewing components, not the translations
+ // because otherwise the center will move relative to the item
+ item->setCenter(old_center * affine.withoutTranslation());
item->updateRepr();
}
}
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index d6f31f073..6b8cd19bb 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -304,6 +304,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
/* Snapping a huge number of nodes will take way too long, so limit the number of snappable nodes
A typical user would rarely ever try to snap such a large number of nodes anyway, because
(s)he would hardly be able to discern which node would be snapping */
+ std::cout << "Warning: limit of 200 snap sources reached, some will be ignored" << std::endl;
_snap_points.resize(200);
// Unfortunately, by now we will have lost the font-baseline snappoints :-(
}
@@ -377,12 +378,6 @@ void Inkscape::SelTrans::transform(Geom::Affine const &rel_affine, Geom::Point c
g_return_if_fail(_grabbed);
g_return_if_fail(!_empty);
- // E.g. scaling a perfectly vertical line in horizontal direction will not work, and will produce an identity affine
-
- if (rel_affine.isIdentity()) {
- return;
- }
-
Geom::Affine const affine( Geom::Translate(-norm) * rel_affine * Geom::Translate(norm) );
if (_show == SHOW_CONTENT) {
diff --git a/src/shape-editor.cpp b/src/shape-editor.cpp
index bf53e8bc3..7915fe533 100644
--- a/src/shape-editor.cpp
+++ b/src/shape-editor.cpp
@@ -14,24 +14,15 @@
#include <string.h>
#include <glibmm/i18n.h>
-#include "sp-object.h"
-#include "sp-item.h"
-#include "sp-lpe-item.h"
-#include "live_effects/lpeobject.h"
-#include "selection.h"
-#include "desktop.h"
-#include "document.h"
#include "desktop-handles.h"
+#include "document.h"
+#include "gc-anchored.h"
#include "knotholder.h"
-#include "live_effects/parameter/point.h"
-#include "xml/node-event-vector.h"
-#include "preferences.h"
#include "object-edit.h"
-#include "style.h"
-#include "display/curve.h"
-#include <2geom/pathvector.h>
-
+#include "sp-item.h"
+#include "sp-object.h"
#include "shape-editor.h"
+#include "xml/node-event-vector.h"
using Inkscape::createKnotHolder;
@@ -44,133 +35,80 @@ ShapeEditor::ShapeEditor(SPDesktop *dt) {
}
ShapeEditor::~ShapeEditor() {
- unset_item(SH_KNOTHOLDER);
+ unset_item();
}
-void ShapeEditor::unset_item(SubType type, bool keep_knotholder) {
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if (this->knotholder) {
- Inkscape::XML::Node *old_repr = this->knotholder->repr;
- if (old_repr && old_repr == knotholder_listener_attached_for) {
- sp_repr_remove_listener_by_data(old_repr, this);
- Inkscape::GC::release(old_repr);
- knotholder_listener_attached_for = NULL;
- }
-
- if (!keep_knotholder) {
- delete this->knotholder;
- this->knotholder = NULL;
- }
- }
- break;
- }
-}
+void ShapeEditor::unset_item(bool keep_knotholder) {
+ if (this->knotholder) {
+ Inkscape::XML::Node *old_repr = this->knotholder->repr;
+ if (old_repr && old_repr == knotholder_listener_attached_for) {
+ sp_repr_remove_listener_by_data(old_repr, this);
+ Inkscape::GC::release(old_repr);
+ knotholder_listener_attached_for = NULL;
+ }
-bool ShapeEditor::has_nodepath () {
- return false;
+ if (!keep_knotholder) {
+ delete this->knotholder;
+ this->knotholder = NULL;
+ }
+ }
}
-bool ShapeEditor::has_knotholder () {
- return (this->knotholder != NULL);
+bool ShapeEditor::has_knotholder() {
+ return this->knotholder != NULL;
}
-void ShapeEditor::update_knotholder () {
+void ShapeEditor::update_knotholder() {
if (this->knotholder)
this->knotholder->update_knots();
}
-bool ShapeEditor::has_local_change (SubType type) {
- switch (type) {
- case SH_NODEPATH:
- // defunct
- return false;
- case SH_KNOTHOLDER:
- return (this->knotholder && this->knotholder->local_change != 0);
- default:
- g_assert_not_reached();
- }
+bool ShapeEditor::has_local_change() {
+ return (this->knotholder && this->knotholder->local_change != 0);
}
-void ShapeEditor::decrement_local_change (SubType type) {
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if (this->knotholder) {
- this->knotholder->local_change = FALSE;
- }
- break;
- default:
- g_assert_not_reached();
+void ShapeEditor::decrement_local_change() {
+ if (this->knotholder) {
+ this->knotholder->local_change = FALSE;
}
}
-const SPItem *ShapeEditor::get_item (SubType type) {
+const SPItem *ShapeEditor::get_item() {
const SPItem *item = NULL;
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if (this->has_knotholder()) {
- item = this->knotholder->getItem();
- }
- break;
+ if (this->has_knotholder()) {
+ item = this->knotholder->getItem();
}
return item;
}
-GList *ShapeEditor::save_nodepath_selection () {
- // defunct stub
- return NULL;
-}
-
-void ShapeEditor::restore_nodepath_selection (GList */*saved*/) {
- // defunct stub
-}
-
-void ShapeEditor::shapeeditor_event_attr_changed(gchar const *name)
+void ShapeEditor::event_attr_changed(Inkscape::XML::Node *, gchar const *name, gchar const *, gchar const *, bool, void *data)
{
- gboolean changed_kh = FALSE;
+ g_assert(data);
+ ShapeEditor *sh = static_cast<ShapeEditor *>(data);
+ bool changed_kh = false;
- if (has_knotholder())
+ if (sh->has_knotholder())
{
- changed_kh = !has_local_change(SH_KNOTHOLDER);
- decrement_local_change(SH_KNOTHOLDER);
+ changed_kh = !sh->has_local_change();
+ sh->decrement_local_change();
if (changed_kh) {
// this can happen if an LPEItem's knotholder handle was dragged, in which case we want
// to keep the knotholder; in all other cases (e.g., if the LPE itself changes) we delete it
- reset_item(SH_KNOTHOLDER, !strcmp(name, "d"));
+ sh->reset_item(!strcmp(name, "d"));
}
}
}
-
-static void shapeeditor_event_attr_changed(Inkscape::XML::Node */*repr*/, gchar const *name,
- gchar const */*old_value*/, gchar const */*new_value*/,
- bool /*is_interactive*/, gpointer data)
-{
- g_assert(data);
- ShapeEditor *sh = static_cast<ShapeEditor *>(data);
-
- sh->shapeeditor_event_attr_changed(name);
-}
-
static Inkscape::XML::NodeEventVector shapeeditor_repr_events = {
NULL, /* child_added */
NULL, /* child_removed */
- shapeeditor_event_attr_changed,
+ ShapeEditor::event_attr_changed,
NULL, /* content_changed */
NULL /* order_changed */
};
-void ShapeEditor::set_item(SPItem *item, SubType type, bool keep_knotholder) {
+void ShapeEditor::set_item(SPItem *item, bool keep_knotholder) {
if (_blockSetItem) {
return;
}
@@ -178,60 +116,38 @@ void ShapeEditor::set_item(SPItem *item, SubType type, bool keep_knotholder) {
// this happens (and should only happen) when for an LPEItem having both knotholder and
// nodepath the knotholder is adapted; in this case we don't want to delete the knotholder
// since this freezes the handles
- unset_item(type, keep_knotholder);
+ unset_item(keep_knotholder);
if (item) {
Inkscape::XML::Node *repr;
- switch(type) {
- case SH_NODEPATH:
- // defunct
- break;
-
- case SH_KNOTHOLDER:
- if (!this->knotholder) {
- // only recreate knotholder if none is present
- this->knotholder = createKnotHolder(item, desktop);
- }
- if (this->knotholder) {
- this->knotholder->update_knots();
- // setting new listener
- repr = this->knotholder->repr;
- if (repr != knotholder_listener_attached_for) {
- Inkscape::GC::anchor(repr);
- sp_repr_add_listener(repr, &shapeeditor_repr_events, this);
- knotholder_listener_attached_for = repr;
- }
- }
- break;
+ if (!this->knotholder) {
+ // only recreate knotholder if none is present
+ this->knotholder = createKnotHolder(item, desktop);
+ }
+ if (this->knotholder) {
+ this->knotholder->update_knots();
+ // setting new listener
+ repr = this->knotholder->repr;
+ if (repr != knotholder_listener_attached_for) {
+ Inkscape::GC::anchor(repr);
+ sp_repr_add_listener(repr, &shapeeditor_repr_events, this);
+ knotholder_listener_attached_for = repr;
+ }
}
}
}
/** FIXME: This thing is only called when the item needs to be updated in response to repr change.
- Why not make a reload function in NodePath and in KnotHolder? */
-void ShapeEditor::reset_item (SubType type, bool keep_knotholder)
+ Why not make a reload function in KnotHolder? */
+void ShapeEditor::reset_item(bool keep_knotholder)
{
- switch (type) {
- case SH_NODEPATH:
- // defunct
- break;
- case SH_KNOTHOLDER:
- if ( knotholder ) {
- SPObject *obj = sp_desktop_document(desktop)->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject.
- set_item(SP_ITEM(obj), SH_KNOTHOLDER, keep_knotholder);
- }
- break;
+ if (knotholder) {
+ SPObject *obj = sp_desktop_document(desktop)->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject.
+ set_item(SP_ITEM(obj), keep_knotholder);
}
}
-void ShapeEditor::nodepath_destroyed () {
-}
-
-bool ShapeEditor::has_selection() {
- return false; // so far, knotholder cannot have selection
-}
-
/**
* Returns true if this ShapeEditor has a knot above which the mouse currently hovers.
*/
diff --git a/src/shape-editor.h b/src/shape-editor.h
index ec4b50fa3..df0dbfa3a 100644
--- a/src/shape-editor.h
+++ b/src/shape-editor.h
@@ -4,8 +4,8 @@
/*
* Inkscape::ShapeEditor
*
- * This is a container class which contains either knotholder (for shapes) or nodepath (for
- * paths). It is attached to a single item so only one of these is active at a time.
+ * This is a container class which contains a knotholder for shapes.
+ * It is attached to a single item.
*
* Authors:
* bulia byak <buliabyak@users.sf.net>
@@ -14,27 +14,12 @@
#include <glib.h>
-#include <2geom/forward.h>
-
-
-namespace Inkscape { namespace NodePath { class Path; } }
namespace Inkscape { namespace XML { class Node; } }
class KnotHolder;
class LivePathEffectObject;
class SPDesktop;
class SPItem;
-class SPNodeContext;
-class ShapeEditorsCollective;
-
-#include <2geom/point.h>
-#include <boost/optional.hpp>
-#include <vector>
-
-enum SubType{
- SH_NODEPATH,
- SH_KNOTHOLDER
-};
class ShapeEditor {
public:
@@ -42,36 +27,25 @@ public:
ShapeEditor(SPDesktop *desktop);
~ShapeEditor();
- void set_item (SPItem *item, SubType type, bool keep_knotholder = false);
- void unset_item (SubType type, bool keep_knotholder = false);
-
- bool has_nodepath (); //((deprecated))
- void update_knotholder (); //((deprecated))
+ void set_item(SPItem *item, bool keep_knotholder = false);
+ void unset_item(bool keep_knotholder = false);
- bool has_local_change (SubType type);
- void decrement_local_change (SubType type);
+ void update_knotholder(); //((deprecated))
- GList *save_nodepath_selection ();
- void restore_nodepath_selection (GList *saved);
-
- void nodepath_destroyed ();
-
- bool has_selection ();
-
- Inkscape::NodePath::Path *get_nodepath() {return NULL;} //((deprecated))
- ShapeEditorsCollective *get_container() {return NULL;}
-
- // this one is only public because it's called from non-C++ repr changed callback
- void shapeeditor_event_attr_changed(gchar const *name);
+ bool has_local_change();
+ void decrement_local_change();
bool knot_mouseover() const;
- static void blockSetItem(bool b) {_blockSetItem = b;}
+ static void blockSetItem(bool b) { _blockSetItem = b; } // kludge?
+ static void event_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const *name, gchar const * /*old_value*/,
+ gchar const * /*new_value*/, bool /*is_interactive*/, void *data);
private:
- bool has_knotholder ();
- void reset_item (SubType type, bool keep_knotholder = true);
- const SPItem *get_item (SubType type);
+ bool has_knotholder();
+ void reset_item (bool keep_knotholder = true);
+ const SPItem *get_item();
+
static bool _blockSetItem;
SPDesktop *desktop;
diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp
index 709e9e464..32d3b0f60 100644
--- a/src/sp-flowregion.cpp
+++ b/src/sp-flowregion.cpp
@@ -42,15 +42,12 @@ static void GetDest(SPObject* child,Shape **computed);
SPFlowregion::SPFlowregion() : SPItem() {
- //new (&this->computed) std::vector<Shape*>;
}
SPFlowregion::~SPFlowregion() {
for (std::vector<Shape*>::iterator it = this->computed.begin() ; it != this->computed.end() ; ++it) {
delete *it;
}
-
- //this->computed.~vector<Shape*>();
}
void SPFlowregion::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) {
@@ -185,6 +182,8 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc
SPItem::write(xml_doc, repr, flags);
+ this->UpdateComputed(); // copied from update(), see LP Bug 1339305
+
return repr;
}
@@ -372,6 +371,8 @@ static void GetDest(SPObject* child,Shape **computed)
tr_mat = SP_ITEM(u_child)->transform;
}
if ( SP_IS_SHAPE (u_child) ) {
+ if (!(SP_SHAPE(u_child)->_curve))
+ SP_SHAPE (u_child)->set_shape ();
curve = SP_SHAPE (u_child)->getCurve ();
} else if ( SP_IS_TEXT (u_child) ) {
curve = SP_TEXT (u_child)->getNormalizedBpath ();
diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp
index b4fd54ee4..7de65ccc3 100644
--- a/src/sp-flowtext.cpp
+++ b/src/sp-flowtext.cpp
@@ -46,11 +46,9 @@ namespace {
SPFlowtext::SPFlowtext() : SPItem() {
this->par_indent = 0;
- //new (&this->layout) Inkscape::Text::Layout();
}
SPFlowtext::~SPFlowtext() {
- //this->layout.~Layout();
}
void SPFlowtext::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref) {
@@ -255,6 +253,8 @@ Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::X
}
}
+ this->rebuildLayout(); // copied from update(), see LP Bug 1339305
+
SPItem::write(doc, repr, flags);
return repr;
diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp
index 1479acd69..70c54451a 100644
--- a/src/sp-gradient.cpp
+++ b/src/sp-gradient.cpp
@@ -262,8 +262,6 @@ SPGradient::SPGradient() : SPPaintServer(), units(),
this->vector.built = false;
this->vector.stops.clear();
-
- //new (&this->modified_connection) sigc::connection();
}
SPGradient::~SPGradient() {
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index 2cfe97db8..657aca692 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -70,11 +70,9 @@ namespace {
SPGroup::SPGroup() : SPLPEItem() {
this->_layer_mode = SPGroup::GROUP;
- //new (&this->_display_modes) std::map<unsigned int, SPGroup::LayerMode>();
}
SPGroup::~SPGroup() {
- //this->_display_modes.~map();
}
void SPGroup::build(SPDocument *document, Inkscape::XML::Node *repr) {
@@ -664,7 +662,8 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p)
Geom::Point old_center(0,0);
if (item->isCenterSet()) {
- old_center = item->getCenter();
+ item->scaleCenter(sc.inverse()); // Convert the old relative center position to the new coordinates already now
+ old_center = item->getCenter(); // because getCenter() will use the bbox midpoint, which is also already in the new coordinates
}
gchar const *conn_type = NULL;
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 0f068a914..251825299 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -118,10 +118,6 @@ SPItem::SPItem() : SPObject() {
mask_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(mask_ref_changed), this));
avoidRef = new SPAvoidRef(this);
-
- //new (&constraints) std::vector<SPGuideConstraint>();
-
- //new (&_transformed_signal) sigc::signal<void, Geom::Affine const *, SPItem *>();
}
SPItem::~SPItem() {
@@ -271,6 +267,11 @@ Geom::Point SPItem::getCenter() const {
}
}
+void
+SPItem::scaleCenter(Geom::Scale const &sc) {
+ transform_center_x *= sc[Geom::X];
+ transform_center_y *= sc[Geom::Y];
+}
namespace {
@@ -601,7 +602,7 @@ void SPItem::update(SPCtx* /*ctx*/, guint flags) {
v->arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(object->style->opacity.value));
v->arenaitem->setAntialiasing(object->style->shape_rendering.computed != SP_CSS_SHAPE_RENDERING_CRISPEDGES);
v->arenaitem->setIsolation( object->style->isolation.value );
- v->arenaitem->setBlendMode( object->style->blend_mode.value );
+ v->arenaitem->setBlendMode( object->style->mix_blend_mode.value );
v->arenaitem->setVisible(!item->isHidden());
}
}
@@ -777,6 +778,7 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const
bbox = const_cast<SPItem*>(this)->bbox(transform, SPItem::VISUAL_BBOX);
}
if (clip_ref->getObject()) {
+ SP_ITEM(clip_ref->getOwner())->bbox_valid = FALSE; // LP Bug 1349018
bbox.intersectWith(SP_CLIPPATH(clip_ref->getObject())->geometricBounds(transform));
}
@@ -1027,7 +1029,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned
ai->setTransform(transform);
ai->setOpacity(SP_SCALE24_TO_FLOAT(style->opacity.value));
ai->setIsolation( style->isolation.value );
- ai->setBlendMode( style->blend_mode.value );
+ ai->setBlendMode( style->mix_blend_mode.value );
//ai->setCompositeOperator( style->composite_op.value );
ai->setVisible(!isHidden());
ai->setSensitive(sensitive);
@@ -1108,9 +1110,10 @@ void SPItem::invoke_hide(unsigned key)
// Adjusters
-void SPItem::adjust_pattern (Geom::Affine const &postmul, bool set)
+void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransform pt)
{
- if (style && (style->fill.isPaintserver())) {
+ bool fill = (pt == TRANSFORM_FILL || pt == TRANSFORM_BOTH);
+ if (fill && style && (style->fill.isPaintserver())) {
SPObject *server = style->getFillPaintServer();
if ( SP_IS_PATTERN(server) ) {
SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "fill");
@@ -1118,7 +1121,8 @@ void SPItem::adjust_pattern (Geom::Affine const &postmul, bool set)
}
}
- if (style && (style->stroke.isPaintserver())) {
+ bool stroke = (pt == TRANSFORM_STROKE || pt == TRANSFORM_BOTH);
+ if (stroke && style && (style->stroke.isPaintserver())) {
SPObject *server = style->getStrokePaintServer();
if ( SP_IS_PATTERN(server) ) {
SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "stroke");
diff --git a/src/sp-item.h b/src/sp-item.h
index d605c99b9..15784d041 100644
--- a/src/sp-item.h
+++ b/src/sp-item.h
@@ -51,6 +51,14 @@ enum {
SP_EVENT_MOUSEOUT
};
+// TODO make a completely new function that transforms either the fill or
+// stroke of any SPItem without adding an extra parameter to adjust_pattern.
+enum PatternTransform {
+ TRANSFORM_BOTH,
+ TRANSFORM_FILL,
+ TRANSFORM_STROKE
+};
+
/**
* Event structure.
*
@@ -159,6 +167,7 @@ public:
void unsetCenter();
bool isCenterSet() const;
Geom::Point getCenter() const;
+ void scaleCenter(Geom::Scale const &sc);
bool isVisibleAndUnlocked() const;
@@ -198,7 +207,7 @@ public:
Inkscape::DrawingItem *invoke_show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
void invoke_hide(unsigned int key);
void getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs=0) const;
- void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
+ void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false, PatternTransform = TRANSFORM_BOTH);
void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false);
void adjust_stroke(gdouble ex);
void adjust_stroke_width_recursive(gdouble ex);
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index 439e44508..bb7d9f273 100644
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
@@ -340,6 +340,7 @@ static void
sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
{
g_return_if_fail(lpeitem != NULL);
+
if (SP_IS_GROUP(lpeitem)) {
GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
for ( GSList const *iter = item_list; iter; iter = iter->next ) {
@@ -361,6 +362,7 @@ static void
sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem)
{
g_return_if_fail(lpeitem != NULL);
+
if (SP_IS_GROUP(lpeitem)) {
GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
for ( GSList const *iter = item_list; iter; iter = iter->next ) {
diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp
index c6a4b730d..3aa1e4eb6 100644
--- a/src/sp-offset.cpp
+++ b/src/sp-offset.cpp
@@ -107,11 +107,6 @@ SPOffset::SPOffset() : SPShape() {
this->sourceRepr = NULL;
this->sourceObject = NULL;
- new (&this->_modified_connection) sigc::connection();
- new (&this->_delete_connection) sigc::connection();
- new (&this->_changed_connection) sigc::connection();
- new (&this->_transformed_connection) sigc::connection();
-
// set up the uri reference
this->sourceRef = new SPUseReference(this);
this->_changed_connection = this->sourceRef->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_offset_href_changed), this));
diff --git a/src/sp-path.cpp b/src/sp-path.cpp
index d1fb850e1..5c076b7cb 100644
--- a/src/sp-path.cpp
+++ b/src/sp-path.cpp
@@ -140,10 +140,10 @@ void SPPath::build(SPDocument *document, Inkscape::XML::Node *repr) {
SPShape::build(document, repr);
- //this->readAttr( "inkscape:original-d" ); //lp1299948
+ // this->readAttr( "inkscape:original-d" ); // lp1299948
if (gchar const* s = this->getRepr()->attribute("inkscape:original-d"))
{
- //write it to XML, and to my curve, but don't update patheffects
+ // write it to XML, and to my curve, but don't update patheffects
Geom::PathVector pv = sp_svg_read_pathv(s);
SPCurve *curve = new SPCurve(pv);
@@ -154,7 +154,6 @@ void SPPath::build(SPDocument *document, Inkscape::XML::Node *repr) {
if (curve) {
_curve_before_lpe = curve->ref();
}
- //this->getRepr()->setAttribute("inkscape:original-d", s);
}
this->readAttr( "d" );
diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp
index 61d35e6ff..de9103dee 100644
--- a/src/sp-shape.cpp
+++ b/src/sp-shape.cpp
@@ -57,8 +57,6 @@ static void sp_shape_update_marker_view (SPShape *shape, Inkscape::DrawingItem *
SPShape::SPShape() : SPLPEItem() {
for ( int i = 0 ; i < SP_MARKER_LOC_QTY ; i++ ) {
- new (&this->_release_connect[i]) sigc::connection();
- new (&this->_modified_connect[i]) sigc::connection();
this->_marker[i] = NULL;
}
diff --git a/src/sp-star.cpp b/src/sp-star.cpp
index eac33ed7b..712029468 100644
--- a/src/sp-star.cpp
+++ b/src/sp-star.cpp
@@ -513,10 +513,12 @@ void SPStar::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::
}
}
-Geom::Affine SPStar::set_transform(Geom::Affine const &xform)
+Geom::Affine SPStar::set_transform(Geom::Affine const &tform)
{
+ Geom::Affine xform = (randomized == 0 ? tform.withoutTranslation() : tform);
+
// Only set transform with proportional scaling
- if (!xform.withoutTranslation().isUniformScale()) {
+ if (!xform.isUniformScale()) {
return xform;
}
@@ -530,7 +532,7 @@ Geom::Affine SPStar::set_transform(Geom::Affine const &xform)
/* This function takes care of translation and scaling, we return whatever parts we can't
handle. */
- Geom::Affine ret(Geom::Affine(xform).withoutTranslation());
+ Geom::Affine ret(xform);
gdouble const s = hypot(ret[0], ret[1]);
if (s > 1e-9) {
ret[0] /= s;
diff --git a/src/sp-string.cpp b/src/sp-string.cpp
index 08755a5fc..b561187d0 100644
--- a/src/sp-string.cpp
+++ b/src/sp-string.cpp
@@ -30,10 +30,14 @@
#include "sp-string.h"
+#include "style.h"
+
#include "xml/repr.h"
#include "sp-factory.h"
+#include <iostream>
+
namespace {
SPObject* createString() {
return new SPString();
@@ -47,7 +51,6 @@ namespace {
#####################################################*/
SPString::SPString() : SPObject() {
- //new (&this->string) Glib::ustring();
}
SPString::~SPString() {
@@ -66,45 +69,110 @@ void SPString::release() {
void SPString::read_content() {
- SPString* object = this;
+ SPString* object = this;
SPString *string = SP_STRING(object);
string->string.clear();
//XML Tree being used directly here while it shouldn't be.
gchar const *xml_string = string->getRepr()->content();
- // see algorithms described in svg 1.1 section 10.15
- if (object->xml_space.value == SP_XML_SPACE_PRESERVE) {
- for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
- gunichar c = g_utf8_get_char(xml_string);
- if ((c == 0xa) || (c == 0xd) || (c == '\t')) {
- c = ' ';
- }
- string->string += c;
+
+ // std::cout << ">" << (xml_string?xml_string:"Null") << "<" << std::endl;
+
+ // SVG2/CSS Text Level 3 'white-space' has five values.
+ // See: http://dev.w3.org/csswg/css-text/#white-space
+ // | New Lines | Spaces/Tabs | Text Wrapping
+ // ---------|------------|--------------|--------------
+ // normal | Collapes | Collapse | Wrap
+ // pre | Preserve | Preserve | No Wrap
+ // nowrap | Collapse | Collapse | No Wrap
+ // pre-wrap | Preserve | Preserve | Wrap
+ // pre-line | Preserve | Collapse | Wrap
+
+ // 'xml:space' has two values:
+ // 'default' which corresponds to 'normal' (without wrapping).
+ // 'preserve' which corresponds to 'pre' except new lines are converted to spaces.
+ // See algorithms described in svg 1.1 section 10.15
+
+ bool collapse_space = true;
+ bool collapse_line = true;
+ bool is_css = false;
+
+ // Strings don't have style, check parent for style
+ if( object->parent && object->parent->style ) {
+ if( object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRELINE ) {
+ collapse_line = false;
+ }
+ if( object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PRE ||
+ object->parent->style->white_space.computed == SP_CSS_WHITE_SPACE_PREWRAP ) {
+ collapse_space = false;
+ }
+ if( object->parent->style->white_space.computed != SP_CSS_WHITE_SPACE_NORMAL ) {
+ is_css = true; // If white-space not normal, we assume white-space is set.
}
}
- else {
- bool whitespace = false;
- for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
- gunichar c = g_utf8_get_char(xml_string);
- if ((c == 0xa) || (c == 0xd)) {
+ if( !is_css ) {
+ // SVG 2: Use 'xml:space' only if 'white-space' not 'normal'.
+ if (object->xml_space.value == SP_XML_SPACE_PRESERVE) {
+ collapse_space = false;
+ }
+ }
+
+ bool white_space = false;
+ for ( ; *xml_string ; xml_string = g_utf8_next_char(xml_string) ) {
+
+ gunichar c = g_utf8_get_char(xml_string);
+ switch (c) {
+ case 0xd: // Carriage return
+ // XML Parsers convert 0xa, 0xd, 0xD 0xA to 0xA. CSS also follows this rule so we
+ // should never see 0xd.
+ std::cerr << "SPString: Carriage Return found! Argh!" << std::endl;
continue;
- }
- if ((c == ' ') || (c == '\t')) {
- whitespace = true;
- } else {
- if (whitespace && (!string->string.empty() || (object->getPrev() != NULL))) {
+ break;
+ case 0xa: // Line feed
+ if( collapse_line ) {
+ if( !is_css && collapse_space ) continue; // xml:space == 'default' strips LFs.
+ white_space = true; // Convert to space and collapse
+ } else {
+ string->string += c; // Preserve line feed
+ continue;
+ }
+ break;
+ case '\t': // Tab
+ if( collapse_space ) {
+ white_space = true; // Convert to space and collapse
+ } else {
+ string->string += c; // Preserve tab
+ continue;
+ }
+ break;
+ case ' ': // Space
+ if( collapse_space ) {
+ white_space = true; // Collapse white space
+ } else {
+ string->string += c; // Preserve space
+ continue;
+ }
+ break;
+ default:
+ if( white_space && (!string->string.empty() || (object->getPrev() != NULL))) {
string->string += ' ';
}
string->string += c;
- whitespace = false;
- }
- }
- if (whitespace && object->getRepr()->next() != NULL) { // can't use SPObject::getNext() when the SPObject tree is still being built
- string->string += ' ';
- }
+ white_space = false;
+
+ } // End switch
+ } // End loop
+
+ // Insert white space at end if more text follows
+ if (white_space && object->getRepr()->next() != NULL) { // can't use SPObject::getNext() when the SPObject tree is still being built
+ string->string += ' ';
}
+
+ // std::cout << ">" << string->string << "<" << std::endl;
object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
diff --git a/src/sp-text.cpp b/src/sp-text.cpp
index bbc7ec43d..3bb1e16d0 100644
--- a/src/sp-text.cpp
+++ b/src/sp-text.cpp
@@ -70,8 +70,6 @@ namespace {
# SPTEXT
#####################################################*/
SPText::SPText() : SPItem() {
- //new (&this->layout) Inkscape::Text::Layout;
- //new (&this->attributes) TextTagAttributes;
}
SPText::~SPText() {
@@ -84,19 +82,22 @@ void SPText::build(SPDocument *doc, Inkscape::XML::Node *repr) {
this->readAttr( "dy" );
this->readAttr( "rotate" );
+ // SVG 2 Auto wrapped text
+ this->readAttr( "width" );
+ this->readAttr( "height" );
+
SPItem::build(doc, repr);
this->readAttr( "sodipodi:linespacing" ); // has to happen after the styles are read
}
void SPText::release() {
- //this->attributes.~TextTagAttributes();
- //this->layout.~Layout();
-
SPItem::release();
}
void SPText::set(unsigned int key, const gchar* value) {
+ //std::cout << "SPText::set: " << sp_attribute_name( key ) << ": " << (value?value:"Null") << std::endl;
+
if (this->attributes.readSingleAttribute(key, value)) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
} else {
@@ -114,6 +115,22 @@ void SPText::set(unsigned int key, const gchar* value) {
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG);
break;
+ case SP_ATTR_WIDTH:
+ if (!this->width.read(value) || this->width.value < 0.0) {
+ this->width.unset();
+ }
+
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
+ case SP_ATTR_HEIGHT:
+ if (!this->height.read(value) || this->height.value < 0.0) {
+ this->height.unset();
+ }
+
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+
default:
SPItem::set(key, value);
break;
@@ -278,6 +295,7 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X
}
this->attributes.writeTo(repr);
+ this->rebuildLayout(); // copied from update(), see LP Bug 1339305
// deprecated attribute, but keep it around for backwards compatibility
if (this->style->line_height.set && !this->style->line_height.inherit && !this->style->line_height.normal && this->style->line_height.unit == SP_CSS_UNIT_PERCENT) {
@@ -288,6 +306,14 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X
this->getRepr()->setAttribute("sodipodi:linespacing", NULL);
}
+ // SVG 2 Auto-wrapped text
+ if( this->width.computed > 0.0 ) {
+ sp_repr_set_svg_double(repr, "width", this->width.computed);
+ }
+ if( this->height.computed > 0.0 ) {
+ sp_repr_set_svg_double(repr, "height", this->height.computed);
+ }
+
SPItem::write(xml_doc, repr, flags);
return repr;
diff --git a/src/sp-text.h b/src/sp-text.h
index 5f0485083..b9ae745c9 100644
--- a/src/sp-text.h
+++ b/src/sp-text.h
@@ -45,7 +45,11 @@ public:
//semiprivate: (need to be accessed by the C-style functions still)
TextTagAttributes attributes;
Inkscape::Text::Layout layout;
-
+
+ // SVG 2 Auto-wrapped text
+ SVGLength width;
+ SVGLength height;
+
/** when the object is transformed it's nicer to change the font size
and coordinates when we can, rather than just applying a matrix
transform. is_root is used to indicate to the function that it should
diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp
index edbb9faa7..0f6eb106f 100644
--- a/src/sp-tref.cpp
+++ b/src/sp-tref.cpp
@@ -64,12 +64,8 @@ static void sp_tref_delete_self(SPObject *deleted, SPTRef *self);
SPTRef::SPTRef() : SPItem() {
this->stringChild = NULL;
- //new (&this->attributes) TextTagAttributes;
-
this->href = NULL;
this->uriOriginalRef = new SPTRefReference(this);
- //new (&this->_delete_connection) sigc::connection();
- //new (&this->_changed_connection) sigc::connection();
this->_changed_connection =
this->uriOriginalRef->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_tref_href_changed), this));
@@ -77,9 +73,6 @@ SPTRef::SPTRef() : SPItem() {
SPTRef::~SPTRef() {
delete this->uriOriginalRef;
-
- //this->_delete_connection.~connection();
- //this->_changed_connection.~connection();
}
void SPTRef::build(SPDocument *document, Inkscape::XML::Node *repr) {
diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp
index 8c4105777..c3f7689e7 100644
--- a/src/sp-tspan.cpp
+++ b/src/sp-tspan.cpp
@@ -63,7 +63,6 @@ namespace {
#####################################################*/
SPTSpan::SPTSpan() : SPItem() {
this->role = SP_TSPAN_ROLE_UNSPECIFIED;
- //new (&this->attributes) TextTagAttributes;
}
SPTSpan::~SPTSpan() {
@@ -81,8 +80,6 @@ void SPTSpan::build(SPDocument *doc, Inkscape::XML::Node *repr) {
}
void SPTSpan::release() {
- //this->attributes.~TextTagAttributes();
-
SPItem::release();
}
@@ -227,8 +224,6 @@ const char* SPTSpan::displayName() const {
void refresh_textpath_source(SPTextPath* offset);
SPTextPath::SPTextPath() : SPItem() {
- //new (&this->attributes) TextTagAttributes;
-
this->startOffset._set = false;
this->originalPath = NULL;
this->isUpdating=false;
diff --git a/src/sp-use.cpp b/src/sp-use.cpp
index e8fe3687f..e3fcd252a 100644
--- a/src/sp-use.cpp
+++ b/src/sp-use.cpp
@@ -37,6 +37,9 @@
#include "sp-symbol.h"
#include "sp-use.h"
#include "sp-use-reference.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "sp-flowtext.h"
namespace {
SPObject* createUse() {
@@ -176,6 +179,16 @@ Inkscape::XML::Node* SPUse::write(Inkscape::XML::Document *xml_doc, Inkscape::XM
g_free(uri_string);
}
+ if (SP_IS_SHAPE(this->child)) {
+ SP_SHAPE(this->child)->set_shape(); // evaluate SPCurve of child
+ } else if (SP_IS_TEXT(this->child)) {
+ SP_TEXT(this->child)->rebuildLayout(); // refresh Layout, LP Bug 1339305
+ } else if (SP_IS_FLOWTEXT(this->child)) {
+ if (SP_IS_FLOWREGION(SP_FLOWTEXT(this->child)->firstChild()))
+ SP_FLOWREGION(SP_FLOWTEXT(this->child)->firstChild())->UpdateComputed();
+ SP_FLOWTEXT(this->child)->rebuildLayout();
+ }
+
return repr;
}
diff --git a/src/style-enums.h b/src/style-enums.h
index 356029a40..024943458 100644
--- a/src/style-enums.h
+++ b/src/style-enums.h
@@ -113,6 +113,14 @@ enum SPTextAnchor {
SP_CSS_TEXT_ANCHOR_END
};
+enum SPWhiteSpace {
+ SP_CSS_WHITE_SPACE_NORMAL,
+ SP_CSS_WHITE_SPACE_PRE,
+ SP_CSS_WHITE_SPACE_NOWRAP,
+ SP_CSS_WHITE_SPACE_PREWRAP,
+ SP_CSS_WHITE_SPACE_PRELINE
+};
+
enum SPCSSBaselineShift {
SP_CSS_BASELINE_SHIFT_BASELINE,
SP_CSS_BASELINE_SHIFT_SUB,
@@ -326,6 +334,15 @@ static SPStyleEnum const enum_text_anchor[] = {
{NULL, -1}
};
+static SPStyleEnum const enum_white_space[] = {
+ {"normal", SP_CSS_WHITE_SPACE_NORMAL },
+ {"pre", SP_CSS_WHITE_SPACE_PRE },
+ {"nowrap", SP_CSS_WHITE_SPACE_NOWRAP },
+ {"pre-wrap", SP_CSS_WHITE_SPACE_PREWRAP},
+ {"pre-line", SP_CSS_WHITE_SPACE_PRELINE},
+ {NULL, -1}
+};
+
static SPStyleEnum const enum_direction[] = {
{"ltr", SP_CSS_DIRECTION_LTR},
{"rtl", SP_CSS_DIRECTION_RTL},
diff --git a/src/style-internal.cpp b/src/style-internal.cpp
index c686a1807..2212f8fff 100644
--- a/src/style-internal.cpp
+++ b/src/style-internal.cpp
@@ -270,18 +270,18 @@ SPILength::read( gchar const *str ) {
} else if (!strcmp(e, "em")) {
/* EM square */
unit = SP_CSS_UNIT_EM;
- if( style && &style->font_size ) {
+ if( style ) {
computed = value * style->font_size.computed;
} else {
- computed = value * style->font_size.font_size_default;
+ computed = value * SPIFontSize::font_size_default;
}
} else if (!strcmp(e, "ex")) {
/* ex square */
unit = SP_CSS_UNIT_EX;
- if( style && &style->font_size ) {
+ if( style ) {
computed = value * style->font_size.computed * 0.5; // FIXME
} else {
- computed = value * style->font_size.font_size_default * 0.5;
+ computed = value * SPIFontSize::font_size_default * 0.5;
}
} else if (!strcmp(e, "%")) {
/* Percentage */
@@ -1390,13 +1390,13 @@ SPIFilter::read( gchar const *str ) {
}
}
-const Glib::ustring
-SPIFilter::write( guint const flags, SPIBase const *const base) const {
-
+const Glib::ustring SPIFilter::write( guint const flags, SPIBase const *const /*base*/) const
+{
// TODO: fix base
//SPILength const *const my_base = dynamic_cast<const SPILength*>(base);
if ( (flags & SP_STYLE_FLAG_ALWAYS) ||
- ((flags & SP_STYLE_FLAG_IFSET) && this->set))
+ ((flags & SP_STYLE_FLAG_IFSET) && this->set) ||
+ ((flags & SP_STYLE_FLAG_IFDIFF) && this->set))
{
if (this->inherit) {
return (name + ":inherit;");
@@ -1440,7 +1440,7 @@ SPIFilter::cascade( const SPIBase* const parent ) {
void
SPIFilter::merge( const SPIBase* const parent ) {
if( const SPIFilter* p = dynamic_cast<const SPIFilter*>(parent) ) {
- // The "correct" thing to due is to combine the filter primitives.
+ // The "correct" thing to do is to combine the filter primitives.
// The next best thing is to keep any filter on this object. If there
// is no filter on this object, then use any filter on the parent.
if( (!set || inherit) && p->href && p->href->getObject() ) { // is the getObject() needed?
@@ -1453,9 +1453,11 @@ SPIFilter::merge( const SPIBase* const parent ) {
}
} else {
// If we don't have an href, create it
- if( &style->document ) { // FIXME
+ if( style->document ) { // FIXME
href = new SPFilterReference(style->document);
//href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style));
+ } else if (style->object) {
+ href = new SPFilterReference(style->object);
}
}
if( href ) {
@@ -1921,9 +1923,8 @@ SPIFont::read( gchar const *str ) {
}
}
-const Glib::ustring
-SPIFont::write( guint const flags, SPIBase const *const base) const {
-
+const Glib::ustring SPIFont::write( guint const /*flags*/, SPIBase const *const /*base*/) const
+{
// At the moment, do nothing. We could add a preference to write out
// 'font' shorthand rather than longhand properties.
diff --git a/src/style-internal.h b/src/style-internal.h
index e76f9faaf..b549bb8ef 100644
--- a/src/style-internal.h
+++ b/src/style-internal.h
@@ -340,7 +340,7 @@ class SPIEnum : public SPIBase {
public:
SPIEnum() :
SPIBase( "anonymous_enum" ), enums( NULL ), value(0), computed(0) {};
- SPIEnum( Glib::ustring name, SPStyleEnum const *enums, unsigned value = 0, bool inherits = true ) :
+ SPIEnum( Glib::ustring const name, SPStyleEnum const *enums, unsigned value = 0, bool inherits = true ) :
SPIBase( name, inherits ), enums( enums ), value(value), computed(value),
value_default(value), computed_default(value) {};
// Following is needed for font-weight
diff --git a/src/style.cpp b/src/style.cpp
index 3691a3e48..66672e949 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -121,10 +121,6 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
// Text related properties
text_indent( "text-indent", 0.0 ), // SPILength
text_align( "text-align", enum_text_align, SP_CSS_TEXT_ALIGN_START ),
- text_decoration(),
- text_decoration_line(),
- text_decoration_style(),
- text_decoration_color( "text-decoration-color" ), // SPIColor
letter_spacing( "letter-spacing", 0.0 ), // SPILengthOrNormal
word_spacing( "word-spacing", 0.0 ), // SPILengthOrNormal
@@ -135,6 +131,12 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
writing_mode( "writing-mode", enum_writing_mode, SP_CSS_WRITING_MODE_LR_TB ),
baseline_shift(),
text_anchor( "text-anchor", enum_text_anchor, SP_CSS_TEXT_ANCHOR_START ),
+ white_space( "white-space", enum_white_space, SP_CSS_WHITE_SPACE_NORMAL ),
+
+ text_decoration(),
+ text_decoration_line(),
+ text_decoration_style(),
+ text_decoration_color( "text-decoration-color" ), // SPIColor
// General visual properties
clip_rule( "clip-rule", enum_clip_rule, SP_WIND_RULE_NONZERO ),
@@ -144,7 +146,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
opacity( "opacity", SP_SCALE24_MAX, false ),
isolation( "isolation", enum_isolation, SP_CSS_ISOLATION_AUTO ),
- blend_mode( "blend_mode", enum_blend_mode, SP_CSS_BLEND_NORMAL ),
+ mix_blend_mode( "mix-blend-mode", enum_blend_mode, SP_CSS_BLEND_NORMAL ),
paint_order(), // SPIPaintOrder
@@ -189,7 +191,6 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
image_rendering( "image-rendering", enum_image_rendering, SP_CSS_IMAGE_RENDERING_AUTO),
shape_rendering( "shape-rendering", enum_shape_rendering, SP_CSS_SHAPE_RENDERING_AUTO),
text_rendering( "text-rendering", enum_text_rendering, SP_CSS_TEXT_RENDERING_AUTO )
-
{
// std::cout << "SPStyle::SPStyle( SPDocument ): Entrance: (" << _count << ")" << std::endl;
// std::cout << " Document: " << (document_in?"present":"null") << std::endl;
@@ -231,11 +232,6 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
document = document_in;
}
- new (&release_connection) sigc::connection();
- new (&filter_modified_connection) sigc::connection();
- new (&fill_ps_modified_connection) sigc::connection();
- new (&stroke_ps_modified_connection) sigc::connection();
-
// 'font' shorthand requires access to included properties.
font.setStylePointer( this );
@@ -302,6 +298,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
_properties.push_back( &writing_mode );
_properties.push_back( &baseline_shift );
_properties.push_back( &text_anchor );
+ _properties.push_back( &white_space );
_properties.push_back( &clip_rule );
_properties.push_back( &display );
@@ -310,7 +307,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
_properties.push_back( &opacity );
_properties.push_back( &isolation );
- _properties.push_back( &blend_mode );
+ _properties.push_back( &mix_blend_mode );
_properties.push_back( &color_interpolation );
_properties.push_back( &color_interpolation_filters );
@@ -384,6 +381,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
// _propmap.insert( std::make_pair( writing_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::writing_mode ) ) );
// _propmap.insert( std::make_pair( baseline_shift.name, reinterpret_cast<SPIBasePtr>(&SPStyle::baseline_shift ) ) );
// _propmap.insert( std::make_pair( text_anchor.name, reinterpret_cast<SPIBasePtr>(&SPStyle::text_anchor ) ) );
+ // _propmap.insert( std::make_pair( white_space.name, reinterpret_cast<SPIBasePtr>(&SPStyle::white_space ) ) );
// _propmap.insert( std::make_pair( clip_rule.name, reinterpret_cast<SPIBasePtr>(&SPStyle::clip_rule ) ) );
// _propmap.insert( std::make_pair( display.name, reinterpret_cast<SPIBasePtr>(&SPStyle::display ) ) );
@@ -392,7 +390,7 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) :
// _propmap.insert( std::make_pair( opacity.name, reinterpret_cast<SPIBasePtr>(&SPStyle::opacity ) ) );
// _propmap.insert( std::make_pair( isolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::isolation ) ) );
- // _propmap.insert( std::make_pair( blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::blend_mode ) ) );
+ // _propmap.insert( std::make_pair( mix_blend_mode.name, reinterpret_cast<SPIBasePtr>(&SPStyle::mix_blend_mode ) ) );
// _propmap.insert( std::make_pair( color_interpolation.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation ) ) );
// _propmap.insert( std::make_pair( color_interpolation_filters.name, reinterpret_cast<SPIBasePtr>(&SPStyle::color_interpolation_filters ) ) );
@@ -442,7 +440,6 @@ SPStyle::~SPStyle() {
// Remove connections
release_connection.disconnect();
- release_connection.~connection();
// The following shoud be moved into SPIPaint and SPIFilter
if (fill.value.href) {
@@ -457,12 +454,7 @@ SPStyle::~SPStyle() {
filter_modified_connection.disconnect();
}
- filter_modified_connection.~connection();
- fill_ps_modified_connection.~connection();
- stroke_ps_modified_connection.~connection();
-
_properties.clear();
- //_propmap.clear();
// std::cout << "SPStyle::~SPstyle(): Exit\n" << std::endl;
}
@@ -681,6 +673,9 @@ SPStyle::readIfUnset( gint id, gchar const *val ) {
case SP_PROP_TEXT_ANCHOR:
text_anchor.readIfUnset( val );
break;
+ case SP_PROP_WHITE_SPACE:
+ white_space.readIfUnset( val );
+ break;
case SP_PROP_BASELINE_SHIFT:
baseline_shift.readIfUnset( val );
break;
@@ -724,8 +719,8 @@ SPStyle::readIfUnset( gint id, gchar const *val ) {
case SP_PROP_ISOLATION:
isolation.readIfUnset( val );
break;
- case SP_PROP_BLEND_MODE:
- blend_mode.readIfUnset( val );
+ case SP_PROP_MIX_BLEND_MODE:
+ mix_blend_mode.readIfUnset( val );
break;
/* SVG */
@@ -1634,6 +1629,9 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->text_anchor.set) {
repr->setAttribute("text-anchor", NULL);
}
+ if (style->white_space.set) {
+ repr->setAttribute("white_space", NULL);
+ }
if (style->writing_mode.set) {
repr->setAttribute("writing_mode", NULL);
}
@@ -1723,6 +1721,7 @@ sp_css_attr_unset_text(SPCSSAttr *css)
sp_repr_css_set_property(css, "block-progression", NULL);
sp_repr_css_set_property(css, "writing-mode", NULL);
sp_repr_css_set_property(css, "text-anchor", NULL);
+ sp_repr_css_set_property(css, "white_space", NULL);
sp_repr_css_set_property(css, "kerning", NULL); // not implemented yet
sp_repr_css_set_property(css, "dominant-baseline", NULL); // not implemented yet
sp_repr_css_set_property(css, "alignment-baseline", NULL); // not implemented yet
diff --git a/src/style.h b/src/style.h
index eb8a3ed91..01a9d4b84 100644
--- a/src/style.h
+++ b/src/style.h
@@ -92,8 +92,10 @@ private:
public:
/* ----------------------- THE PROPERTIES ------------------------- */
+ /* Match order in style.cpp. */
+
+ /* Font ---------------------------- */
- /* Font */
/** Font style */
SPIEnum font_style;
/** Which substyle of the font */
@@ -113,23 +115,13 @@ public:
/** Full font name, as font_factory::ConstructFontSpecification would give, for internal use. */
SPIString font_specification;
+ /* Text ----------------------------- */
+
/** First line indent of paragraphs (css2 16.1) */
SPILength text_indent;
/** text alignment (css2 16.2) (not to be confused with text-anchor) */
SPIEnum text_align;
- /** text decoration (css2 16.3.1) */
- SPITextDecoration text_decoration;
- /** CSS 3 2.1, 2.2, 2.3 */
- /** Not done yet, test_decoration3 = css3 2.4*/
- SPITextDecorationLine text_decoration_line;
- SPITextDecorationStyle text_decoration_style; // SPIEnum? Only one can be set at time.
- SPIColor text_decoration_color;
- // used to implement text_decoration, not saved to or read from SVG file
- SPITextDecorationData text_decoration_data;
-
- // 16.3.2 is text-shadow. That's complicated.
-
/** letter spacing (css2 16.4) */
SPILengthOrNormal letter_spacing;
/** word spacing (also css2 16.4) */
@@ -151,6 +143,25 @@ public:
/** Anchor of the text (svg1.1 10.9.1) */
SPIEnum text_anchor;
+ /** white space (svg2) */
+ SPIEnum white_space;
+
+ /* Text Decoration ----------------------- */
+
+ /** text decoration (css2 16.3.1) */
+ SPITextDecoration text_decoration;
+ /** CSS 3 2.1, 2.2, 2.3 */
+ /** Not done yet, test_decoration3 = css3 2.4*/
+ SPITextDecorationLine text_decoration_line;
+ SPITextDecorationStyle text_decoration_style; // SPIEnum? Only one can be set at time.
+ SPIColor text_decoration_color;
+ // used to implement text_decoration, not saved to or read from SVG file
+ SPITextDecorationData text_decoration_data;
+
+ // 16.3.2 is text-shadow. That's complicated.
+
+ /* General visual properties ------------- */
+
/** clip-rule: 0 nonzero, 1 evenodd */
SPIEnum clip_rule;
@@ -168,8 +179,7 @@ public:
/** mix-blend-mode: CSS Compositing and Blending Level 1 */
SPIEnum isolation;
- // Could be shared with Filter blending mode
- SPIEnum blend_mode;
+ SPIEnum mix_blend_mode;
SPIPaintOrder paint_order;
@@ -216,6 +226,8 @@ public:
SPIString marker_end;
SPIString* marker_ptrs[SP_MARKER_LOC_QTY];
+ /* Filter effects ------------------------ */
+
/** Filter effect */
SPIFilter filter;
/** Filter blend mode */
@@ -226,6 +238,7 @@ public:
/** enable-background, used for defining where filter effects get their background image */
SPIEnum enable_background;
+ /* Rendering hints ----------------------- */
/** hints on how to render: e.g. speed vs. accuracy.
* As of April, 2013, only image_rendering used. */
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index 8e2502545..1209b19cd 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -601,6 +601,12 @@ Glib::ustring ClipboardManagerImpl::getPathParameter(SPDesktop* desktop)
*/
Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
{
+ // https://bugs.launchpad.net/inkscape/+bug/1293979
+ // basically, when we do a depth-first search, we're stopping
+ // at the first object to be <svg:path> or <svg:text>.
+ // but that could then return the id of the object's
+ // clip path or mask, not the original path!
+
SPDocument *tempdoc = _retrieveClipboard(); // any target will do here
if ( tempdoc == NULL ) {
_userWarn(desktop, _("Nothing on the clipboard."));
@@ -608,6 +614,9 @@ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
}
Inkscape::XML::Node *root = tempdoc->getReprRoot();
+ // 1293979: strip out the defs of the document
+ root->removeChild(tempdoc->getDefs()->getRepr());
+
Inkscape::XML::Node *repr = sp_repr_lookup_name(root, "svg:path", -1); // unlimited search depth
if ( repr == NULL ) {
repr = sp_repr_lookup_name(root, "svg:text", -1);
diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp
index a435c5583..dd6be2604 100644
--- a/src/ui/dialog/clonetiler.cpp
+++ b/src/ui/dialog/clonetiler.cpp
@@ -2242,6 +2242,8 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
clonetiler_remove (NULL, dlg, false);
+ double scale_units = Inkscape::Util::Quantity::convert(1, "px", sp_desktop_document(desktop)->getDefaultUnit());
+
double shiftx_per_i = 0.01 * prefs->getDoubleLimited(prefs_path + "shiftx_per_i", 0, -10000, 10000);
double shifty_per_i = 0.01 * prefs->getDoubleLimited(prefs_path + "shifty_per_i", 0, -10000, 10000);
double shiftx_per_j = 0.01 * prefs->getDoubleLimited(prefs_path + "shiftx_per_j", 0, -10000, 10000);
@@ -2311,8 +2313,8 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
int jmax = prefs->getInt(prefs_path + "jmax", 2);
bool fillrect = prefs->getBool(prefs_path + "fillrect");
- double fillwidth = prefs->getDoubleLimited(prefs_path + "fillwidth", 50, 0, 1e6);
- double fillheight = prefs->getDoubleLimited(prefs_path + "fillheight", 50, 0, 1e6);
+ double fillwidth = scale_units*prefs->getDoubleLimited(prefs_path + "fillwidth", 50, 0, 1e6);
+ double fillheight = scale_units*prefs->getDoubleLimited(prefs_path + "fillheight", 50, 0, 1e6);
bool dotrace = prefs->getBool(prefs_path + "dotrace");
int pick = prefs->getInt(prefs_path + "pick");
@@ -2358,11 +2360,11 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
SPItem::VISUAL_BBOX : SPItem::GEOMETRIC_BBOX );
Geom::OptRect r = item->documentBounds(bbox_type);
if (r) {
- w = r->dimensions()[Geom::X];
- h = r->dimensions()[Geom::Y];
- x0 = r->min()[Geom::X];
- y0 = r->min()[Geom::Y];
- center = desktop->dt2doc(item->getCenter());
+ w = scale_units*r->dimensions()[Geom::X];
+ h = scale_units*r->dimensions()[Geom::Y];
+ x0 = scale_units*r->min()[Geom::X];
+ y0 = scale_units*r->min()[Geom::Y];
+ center = scale_units*desktop->dt2doc(item->getCenter());
sp_repr_set_svg_double(obj_repr, "inkscape:tile-cx", center[Geom::X]);
sp_repr_set_svg_double(obj_repr, "inkscape:tile-cy", center[Geom::Y]);
@@ -2578,7 +2580,7 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
Geom::Point new_center;
bool center_set = false;
if (obj_repr->attribute("inkscape:transform-center-x") || obj_repr->attribute("inkscape:transform-center-y")) {
- new_center = desktop->dt2doc(item->getCenter()) * t;
+ new_center = scale_units*desktop->dt2doc(item->getCenter()) * t;
center_set = true;
}
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index d427e3590..7e69e439a 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -251,7 +251,7 @@ void DialogManager::showDialog(gchar const *name, bool grabfocus) {
/**
* Shows the named dialog, creating it if necessary.
*/
-void DialogManager::showDialog(GQuark name, bool grabfocus) {
+void DialogManager::showDialog(GQuark name, bool /*grabfocus*/) {
bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false);
GTimer *timer = (wantTiming) ? g_timer_new() : 0; // if needed, must be created/started before getDialog()
Dialog *dialog = getDialog(name);
@@ -262,8 +262,8 @@ void DialogManager::showDialog(GQuark name, bool grabfocus) {
tracker->setAutodelete(true);
timer = 0;
}
- if (grabfocus)
- dialog->present();
+ // should check for grabfocus, but lp:1348927 prevents it
+ dialog->present();
}
if ( timer ) {
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index ce3b1314c..00b54017c 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -596,6 +596,7 @@ void DocumentProperties::removeSelectedProfile(){
//XML Tree being used directly here while it shouldn't be.
sp_repr_unparent(obj->getRepr());
DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_COLOR_PROFILE, _("Remove linked color profile"));
+ break; // removing the color profile likely invalidates part of the traversed list, stop traversing here.
}
current = g_slist_next(current);
}
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index b5dac0595..65351cb68 100644
--- a/src/ui/dialog/layers.cpp
+++ b/src/ui/dialog/layers.cpp
@@ -926,9 +926,8 @@ LayersPanel::LayersPanel() :
// -------------------------------------------------------
{
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
- _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
@@ -944,9 +943,14 @@ LayersPanel::LayersPanel() :
_popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
- _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, INKSCAPE_ICON("go-up"), "Up", (int)BUTTON_UP ) );
- _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, INKSCAPE_ICON("go-down"), "Down", (int)BUTTON_DOWN ) );
+ _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, INKSCAPE_ICON("layer-raise"), "Up", (int)BUTTON_UP ) );
+ _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, INKSCAPE_ICON("layer-lower"), "Down", (int)BUTTON_DOWN ) );
+ _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem()));
+
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
+ _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DELETE, 0, "Delete", (int)BUTTON_DELETE ) );
+
_popupMenu.show_all_children();
}
// -------------------------------------------------------
diff --git a/src/ui/dialog/template-widget.cpp b/src/ui/dialog/template-widget.cpp
index ef91962d4..9758b35ac 100644
--- a/src/ui/dialog/template-widget.cpp
+++ b/src/ui/dialog/template-widget.cpp
@@ -120,7 +120,7 @@ void TemplateWidget::_displayTemplateDetails()
if (_current_template.long_description != "")
message += _("Description: ") + _current_template.long_description + "\n\n";
- if (~_current_template.keywords.empty()){
+ if (!_current_template.keywords.empty()){
message += _("Keywords: ");
for (std::set<Glib::ustring>::iterator it = _current_template.keywords.begin(); it != _current_template.keywords.end(); ++it)
message += *it + " ";
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index 01cff5ad7..9839be437 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -1219,6 +1219,7 @@ double PathManipulator::BSplineHandlePosition(Handle *h, Handle *h2){
h = h2;
}
double pos = 0.0000;
+ const double handleCubicGap = 0.01;
Node *n = h->parent();
Node * nextNode = NULL;
nextNode = n->nodeToward(h);
@@ -1226,7 +1227,7 @@ double PathManipulator::BSplineHandlePosition(Handle *h, Handle *h2){
SPCurve *lineInsideNodes = new SPCurve();
lineInsideNodes->moveto(n->position());
lineInsideNodes->lineto(nextNode->position());
- pos = Geom::nearest_point(h->position(),*lineInsideNodes->first_segment());
+ pos = Geom::nearest_point(Geom::Point(h->position()[X] - handleCubicGap,h->position()[Y] - handleCubicGap),*lineInsideNodes->first_segment());
}
if (pos == 0.0000 && !h2){
return BSplineHandlePosition(h, h->other());
@@ -1244,6 +1245,7 @@ Geom::Point PathManipulator::BSplineHandleReposition(Handle *h, Handle *h2){
Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){
using Geom::X;
using Geom::Y;
+ const double handleCubicGap = 0.01;
Geom::Point ret = h->position();
Node *n = h->parent();
Geom::D2< Geom::SBasis > SBasisInsideNodes;
@@ -1255,7 +1257,7 @@ Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){
lineInsideNodes->lineto(nextNode->position());
SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
ret = SBasisInsideNodes.valueAt(pos);
- ret = Geom::Point(ret[X] + 0.005,ret[Y] + 0.005);
+ ret = Geom::Point(ret[X] + handleCubicGap,ret[Y] + handleCubicGap);
}else{
if(pos == 0.0000){
ret = n->position();
diff --git a/src/ui/tools/arc-tool.cpp b/src/ui/tools/arc-tool.cpp
index 43f8eb9e1..9fd68f1b9 100644
--- a/src/ui/tools/arc-tool.cpp
+++ b/src/ui/tools/arc-tool.cpp
@@ -102,8 +102,8 @@ ArcTool::~ArcTool() {
* destroys old and creates new knotholder.
*/
void ArcTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void ArcTool::setup() {
@@ -115,7 +115,7 @@ void ArcTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/box3d-tool.cpp b/src/ui/tools/box3d-tool.cpp
index e00894d55..b998267c2 100644
--- a/src/ui/tools/box3d-tool.cpp
+++ b/src/ui/tools/box3d-tool.cpp
@@ -112,8 +112,8 @@ Box3dTool::~Box3dTool() {
* destroys old and creates new knotholder.
*/
void Box3dTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
if (selection->perspList().size() == 1) {
// selecting a single box changes the current perspective
@@ -147,7 +147,7 @@ void Box3dTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp
index d74848dc6..3fb56b2ad 100644
--- a/src/ui/tools/flood-tool.cpp
+++ b/src/ui/tools/flood-tool.cpp
@@ -119,8 +119,8 @@ FloodTool::~FloodTool() {
* destroys old and creates new knotholder.
*/
void FloodTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void FloodTool::setup() {
@@ -130,7 +130,7 @@ void FloodTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index 1c5b7b8e3..aad924844 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -44,6 +44,8 @@
#include "live_effects/lpe-powerstroke.h"
#include "style.h"
#include "ui/control-manager.h"
+// clipboard support
+#include "ui/clipboard.h"
#include "ui/tools/freehand-base.h"
#include <gdk/gdkkeysyms.h>
@@ -238,6 +240,31 @@ static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points
Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
static_cast<LPEPowerStroke*>(lpe)->offset_points.param_set_and_write_new_value(points);
+ // find out stroke width (TODO: is there an easier way??)
+ SPDesktop *desktop = dc->desktop;
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
+ Inkscape::GC::release(repr);
+
+ char const* tool = SP_IS_PEN_CONTEXT(dc) ? "/tools/freehand/pen" : "/tools/freehand/pencil";
+
+ // apply the tool's current style
+ sp_desktop_apply_style_tool(desktop, repr, tool, false);
+
+ double stroke_width = 1.0;
+ char const *style_str = NULL;
+ style_str = repr->attribute("style");
+ if (style_str) {
+ SPStyle *style = sp_style_new(SP_ACTIVE_DOCUMENT);
+ sp_style_merge_from_style_string(style, style_str);
+ stroke_width = style->stroke_width.computed;
+ style->stroke_width.computed = 0;
+ sp_style_unref(style);
+ }
+
+ char * width_str = new char[50];
+ sprintf(width_str, "0,%f", stroke_width / 2.);
+
// write powerstroke parameters:
lpe->getRepr()->setAttribute("start_linecap_type", "zerowidth");
lpe->getRepr()->setAttribute("end_linecap_type", "zerowidth");
@@ -245,6 +272,9 @@ static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points
lpe->getRepr()->setAttribute("sort_points", "true");
lpe->getRepr()->setAttribute("interpolator_type", "CubicBezierJohan");
lpe->getRepr()->setAttribute("interpolator_beta", "0.2");
+ lpe->getRepr()->setAttribute("offset_points", width_str);
+
+ delete [] width_str;
}
static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, SPCurve *curve)
@@ -261,7 +291,13 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
Effect::createAndApply(BSPLINE, dc->desktop->doc(), item);
}
- int shape = prefs->getInt(tool_name(dc) + "/shape", 0);
+ //Store the clipboard path to apply in the future without the use of clipboard
+ static Geom::PathVector previous_shape_pathv;
+ enum shapeType { NONE, TRIANGLE_IN, TRIANGLE_OUT, ELLIPSE, CLIPBOARD, LAST_APPLIED };
+ static shapeType previous_shape_type = NONE;
+
+
+ shapeType shape = (shapeType)prefs->getInt(tool_name(dc) + "/shape", 0);
bool shape_applied = false;
SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
const char *cstroke = sp_repr_css_property(css_item, "stroke", "none");
@@ -269,11 +305,18 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
#define SHAPE_LENGTH 10
#define SHAPE_HEIGHT 10
+ if(shape == LAST_APPLIED){
+ shape = previous_shape_type;
+ if(shape == CLIPBOARD){
+ shape = LAST_APPLIED;
+ }
+ }
+
switch (shape) {
- case 0:
+ case NONE:
// don't apply any shape
break;
- case 1:
+ case TRIANGLE_IN:
{
// "triangle in"
std::vector<Geom::Point> points(1);
@@ -283,7 +326,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
shape_applied = true;
break;
}
- case 2:
+ case TRIANGLE_OUT:
{
// "triangle out"
guint curve_length = curve->get_segment_count();
@@ -294,7 +337,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
shape_applied = true;
break;
}
- case 3:
+ case ELLIPSE:
{
// "ellipse"
SPCurve *c = new SPCurve();
@@ -307,22 +350,40 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
c->closepath();
spdc_paste_curve_as_freehand_shape(c, dc, item);
c->unref();
+
shape_applied = true;
break;
}
- case 4:
+ case CLIPBOARD:
{
// take shape from clipboard; TODO: catch the case where clipboard is empty
Effect::createAndApply(PATTERN_ALONG_PATH, dc->desktop->doc(), item);
Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
static_cast<LPEPatternAlongPath*>(lpe)->pattern.on_paste_button_click();
+ Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
+ Glib::ustring svgd = cm->getPathParameter(SP_ACTIVE_DESKTOP);
+ previous_shape_pathv = sp_svg_read_pathv(svgd.data());
shape_applied = true;
break;
}
+ case LAST_APPLIED:
+ {
+ if(previous_shape_pathv.size() != 0){
+ SPCurve * c = new SPCurve();
+ c->set_pathvector(previous_shape_pathv);
+ spdc_paste_curve_as_freehand_shape(c, dc, item);
+ c->unref();
+
+ shape_applied = true;
+ }
+ break;
+ }
default:
break;
}
+ previous_shape_type = shape;
+
if (shape_applied) {
// apply original stroke color as fill and unset stroke; then return
SPCSSAttr *css = sp_repr_css_attr_new();
diff --git a/src/ui/tools/lpe-tool.cpp b/src/ui/tools/lpe-tool.cpp
index 9ab6d7814..e9b9421f1 100644
--- a/src/ui/tools/lpe-tool.cpp
+++ b/src/ui/tools/lpe-tool.cpp
@@ -129,8 +129,7 @@ void LpeTool::setup() {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (item) {
- this->shape_editor->set_item(item, SH_NODEPATH);
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
if (prefs->getBool("/tools/lpetool/selcue")) {
@@ -146,9 +145,9 @@ void sp_lpetool_context_selection_changed(Inkscape::Selection *selection, gpoint
{
LpeTool *lc = SP_LPETOOL_CONTEXT(data);
- lc->shape_editor->unset_item(SH_KNOTHOLDER);
+ lc->shape_editor->unset_item();
SPItem *item = selection->singleItem();
- lc->shape_editor->set_item(item, SH_KNOTHOLDER);
+ lc->shape_editor->set_item(item);
}
void LpeTool::set(const Inkscape::Preferences::Entry& val) {
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index ce487831d..d2584ee74 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -19,6 +19,7 @@
#include "display/curve.h"
#include "display/sp-canvas.h"
#include "document.h"
+#include "live_effects/effect.h"
#include "live_effects/lpeobject.h"
#include "message-context.h"
#include "selection.h"
@@ -168,6 +169,9 @@ NodeTool::~NodeTool() {
if (this->flash_tempitem) {
this->desktop->remove_temporary_canvasitem(this->flash_tempitem);
}
+ if (this->helperpath_tmpitem) {
+ this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
+ }
if (this->helperpath_tmpitem) {
this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
@@ -252,6 +256,7 @@ void NodeTool::setup() {
)))
);
+ this->helperpath_tmpitem = NULL;
this->cursor_drag = false;
this->show_transform_handles = true;
this->single_node_transform_handles = false;
@@ -288,12 +293,15 @@ void NodeTool::setup() {
this->update_helperpath();
}
-void NodeTool::update_helperpath(){
+// show helper paths of the applied LPE, if any
+void NodeTool::update_helperpath () {
Inkscape::Selection *selection = sp_desktop_selection (this->desktop);
+
if (this->helperpath_tmpitem) {
this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem);
this->helperpath_tmpitem = NULL;
}
+
if (SP_IS_LPE_ITEM(selection->singleItem())) {
Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(selection->singleItem())->getCurrentLPE();
if (lpe && lpe->isVisible()/* && lpe->showOrigPath()*/) {
@@ -310,7 +318,7 @@ void NodeTool::update_helperpath(){
c->transform(selection->singleItem()->i2dt_affine());
SPCanvasItem *helperpath = sp_canvas_bpath_new(sp_desktop_tempgroup(this->desktop), c);
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(helperpath),
- 0x0000ff9A, 1.0,
+ 0x0000ff9A, 1.0,
SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(helperpath), 0, SP_WIND_RULE_NONZERO);
this->helperpath_tmpitem = this->desktop->add_temporary_canvasitem(helperpath,0);
@@ -438,7 +446,7 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) {
this->_shape_editors.find(r.item) == this->_shape_editors.end())
{
ShapeEditor *si = new ShapeEditor(this->desktop);
- si->set_item(r.item, SH_KNOTHOLDER);
+ si->set_item(r.item);
this->_shape_editors.insert(const_cast<SPItem*&>(r.item), si);
}
}
@@ -474,6 +482,7 @@ bool NodeTool::root_handler(GdkEvent* event) {
switch (event->type)
{
case GDK_MOTION_NOTIFY: {
+ this->update_helperpath();
combine_motion_events(desktop->canvas, event->motion, 0);
this->update_helperpath();
SPItem *over_item = sp_event_context_find_item (desktop, event_point(event->button),
diff --git a/src/ui/tools/node-tool.h b/src/ui/tools/node-tool.h
index 9f0c40aa8..ab72f3632 100644
--- a/src/ui/tools/node-tool.h
+++ b/src/ui/tools/node-tool.h
@@ -66,8 +66,8 @@ private:
sigc::connection _sizeUpdatedConn;
SPItem *flashed_item;
- Inkscape::Display::TemporaryItem *flash_tempitem;
Inkscape::Display::TemporaryItem *helperpath_tmpitem;
+ Inkscape::Display::TemporaryItem *flash_tempitem;
Inkscape::UI::Selector* _selector;
Inkscape::UI::PathSharedData* _path_data;
SPCanvasGroup *_transform_handle_group;
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index 56bcbef0d..9a73d497f 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -84,17 +84,17 @@ namespace Tools {
static Geom::Point pen_drag_origin_w(0, 0);
static bool pen_within_tolerance = false;
static int pen_last_paraxial_dir = 0; // last used direction in horizontal/vertical mode; 0 = horizontal, 1 = vertical
-
+const double handleCubicGap = 0.01;
namespace {
- ToolBase* createPenContext() {
- return new PenTool();
- }
+ ToolBase* createPenContext() {
+ return new PenTool();
+ }
- bool penContextRegistered = ToolFactory::instance().registerObject("/tools/freehand/pen", createPenContext);
+ bool penContextRegistered = ToolFactory::instance().registerObject("/tools/freehand/pen", createPenContext);
}
const std::string& PenTool::getPrefsPath() {
- return PenTool::prefsPath;
+ return PenTool::prefsPath;
}
const std::string PenTool::prefsPath = "/tools/freehand/pen";
@@ -321,7 +321,7 @@ bool PenTool::item_handler(SPItem* item, GdkEvent* event) {
}
if (!ret) {
- ret = FreehandBase::item_handler(item, event);
+ ret = FreehandBase::item_handler(item, event);
}
return ret;
@@ -359,7 +359,7 @@ bool PenTool::root_handler(GdkEvent* event) {
}
if (!ret) {
- ret = FreehandBase::root_handler(event);
+ ret = FreehandBase::root_handler(event);
}
return ret;
@@ -1268,15 +1268,15 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
}
// asign the value in a third of the distance of the last segment.
- if(this->bspline){
+ if (this->bspline){
this->p[1] = this->p[0] + (1./3)*(this->p[3] - this->p[0]);
}
Geom::Point const pt( (this->npoints < 4) ? crv->finalPoint() : this->p[3] );
-
+
this->npoints = 2;
// delete the last segment of the green curve
- if( this->green_curve->get_segment_count() == 1){
+ if (this->green_curve->get_segment_count() == 1) {
this->npoints = 5;
if (this->green_bpaths) {
if (this->green_bpaths->data) {
@@ -1285,11 +1285,12 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data);
}
this->green_curve->reset();
- }else{
+ } else {
this->green_curve->backspace();
}
+
// assign the value of this->p[1] to the oposite of the green line last segment
- if(this->spiro){
+ if (this->spiro){
Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(this->green_curve->last_segment());
if ( cubic ) {
this->p[1] = (*cubic)[3] + (*cubic)[3] - (*cubic)[2];
@@ -1298,6 +1299,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) {
this->p[1] = this->p[0];
}
}
+
sp_canvas_item_hide(this->c0);
sp_canvas_item_hide(this->c1);
sp_canvas_item_hide(this->cl0);
@@ -1452,7 +1454,7 @@ void PenTool::_bspline_spiro_on()
this->p[0] = this->red_curve->first_segment()->initialPoint();
this->p[3] = this->red_curve->first_segment()->finalPoint();
this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
- this->p[2] = Geom::Point(this->p[2][X] + 0.005,this->p[2][Y] + 0.005);
+ this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
}
}
@@ -1520,7 +1522,7 @@ void PenTool::_bspline_spiro_start_anchor_on()
Geom::Point A = tmpCurve->last_segment()->initialPoint();
Geom::Point D = tmpCurve->last_segment()->finalPoint();
Geom::Point C = D + (1./3)*(A - D);
- C = Geom::Point(C[X] + 0.005,C[Y] + 0.005);
+ C = Geom::Point(C[X] + handleCubicGap,C[Y] + handleCubicGap);
if(cubic){
lastSeg->moveto(A);
lastSeg->curveto((*cubic)[1],C,D);
@@ -1578,10 +1580,10 @@ void PenTool::_bspline_spiro_motion(bool shift){
this->npoints = 5;
SPCurve *tmpCurve = new SPCurve();
this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
- this->p[2] = Geom::Point(this->p[2][X] + 0.005,this->p[2][Y] + 0.005);
+ this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
if(this->green_curve->is_empty() && !this->sa){
this->p[1] = this->p[0] + (1./3)*(this->p[3] - this->p[0]);
- this->p[1] = Geom::Point(this->p[1][X] + 0.005,this->p[1][Y] + 0.005);
+ this->p[1] = Geom::Point(this->p[1][X] + handleCubicGap,this->p[1][Y] + handleCubicGap);
}else if(!this->green_curve->is_empty()){
tmpCurve = this->green_curve->copy();
}else{
@@ -1606,7 +1608,7 @@ void PenTool::_bspline_spiro_motion(bool shift){
WPower->reset();
this->p[1] = SBasisWPower.valueAt(WP);
if(!Geom::are_near(this->p[1],this->p[0]))
- this->p[1] = Geom::Point(this->p[1][X] + 0.005,this->p[1][Y] + 0.005);
+ this->p[1] = Geom::Point(this->p[1][X] + handleCubicGap,this->p[1][Y] + handleCubicGap);
if(shift)
this->p[2] = this->p[3];
}else{
@@ -1636,7 +1638,7 @@ void PenTool::_bspline_spiro_end_anchor_on()
using Geom::X;
using Geom::Y;
this->p[2] = this->p[3] + (1./3)*(this->p[0] - this->p[3]);
- this->p[2] = Geom::Point(this->p[2][X] + 0.005,this->p[2][Y] + 0.005);
+ this->p[2] = Geom::Point(this->p[2][X] + handleCubicGap,this->p[2][Y] + handleCubicGap);
SPCurve *tmpCurve = new SPCurve();
SPCurve *lastSeg = new SPCurve();
Geom::Point C(0,0);
@@ -1659,7 +1661,7 @@ void PenTool::_bspline_spiro_end_anchor_on()
Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const*>(&*tmpCurve->last_segment());
if(this->bspline){
C = tmpCurve->last_segment()->finalPoint() + (1./3)*(tmpCurve->last_segment()->initialPoint() - tmpCurve->last_segment()->finalPoint());
- C = Geom::Point(C[X] + 0.005,C[Y] + 0.005);
+ C = Geom::Point(C[X] + handleCubicGap,C[Y] + handleCubicGap);
}else{
C = this->p[3] + this->p[3] - this->p[2];
}
@@ -2084,7 +2086,7 @@ void PenTool::_setSubsequentPoint(Geom::Point const p, bool statusbar, guint sta
// we are drawing horizontal/vertical lines and hit an anchor;
Geom::Point const origin = this->p[0];
// if the previous point and the anchor are not aligned either horizontally or vertically...
- if ((abs(p[Geom::X] - origin[Geom::X]) > 1e-9) && (abs(p[Geom::Y] - origin[Geom::Y]) > 1e-9)) {
+ if ((std::abs(p[Geom::X] - origin[Geom::X]) > 1e-9) && (std::abs(p[Geom::Y] - origin[Geom::Y]) > 1e-9)) {
// ...then we should draw an L-shaped path, consisting of two paraxial segments
Geom::Point intermed = p;
this->_setToNearestHorizVert(intermed, status, false);
diff --git a/src/ui/tools/rect-tool.cpp b/src/ui/tools/rect-tool.cpp
index 39f422c1a..819671dd6 100644
--- a/src/ui/tools/rect-tool.cpp
+++ b/src/ui/tools/rect-tool.cpp
@@ -102,8 +102,8 @@ RectTool::~RectTool() {
* destroys old and creates new knotholder.
*/
void RectTool::selection_changed(Inkscape::Selection* selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void RectTool::setup() {
@@ -113,7 +113,7 @@ void RectTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection.disconnect();
diff --git a/src/ui/tools/spiral-tool.cpp b/src/ui/tools/spiral-tool.cpp
index 5ae229df8..83712457a 100644
--- a/src/ui/tools/spiral-tool.cpp
+++ b/src/ui/tools/spiral-tool.cpp
@@ -104,8 +104,8 @@ SpiralTool::~SpiralTool() {
* destroys old and creates new knotholder.
*/
void SpiralTool::selection_changed(Inkscape::Selection *selection) {
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void SpiralTool::setup() {
@@ -119,7 +119,7 @@ void SpiralTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
Inkscape::Selection *selection = sp_desktop_selection(this->desktop);
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index 08d3119a1..29f1b9a73 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -677,7 +677,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
desktop->setToolboxAdjustmentValue("population", this->population * 100);
Geom::Point const scroll_w(event->button.x, event->button.y);
Geom::Point const scroll_dt = desktop->point();;
- Geom::Point motion_doc(desktop->dt2doc(scroll_dt));
+
switch (event->scroll.direction) {
case GDK_SCROLL_DOWN:
case GDK_SCROLL_UP: {
diff --git a/src/ui/tools/star-tool.cpp b/src/ui/tools/star-tool.cpp
index 68f998920..ed28c0a8d 100644
--- a/src/ui/tools/star-tool.cpp
+++ b/src/ui/tools/star-tool.cpp
@@ -112,8 +112,8 @@ StarTool::~StarTool() {
void StarTool::selection_changed(Inkscape::Selection* selection) {
g_assert (selection != NULL);
- this->shape_editor->unset_item(SH_KNOTHOLDER);
- this->shape_editor->set_item(selection->singleItem(), SH_KNOTHOLDER);
+ this->shape_editor->unset_item();
+ this->shape_editor->set_item(selection->singleItem());
}
void StarTool::setup() {
@@ -129,7 +129,7 @@ void StarTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
Inkscape::Selection *selection = sp_desktop_selection(this->desktop);
diff --git a/src/ui/tools/text-tool.cpp b/src/ui/tools/text-tool.cpp
index ac830fe6b..b60a39e5d 100644
--- a/src/ui/tools/text-tool.cpp
+++ b/src/ui/tools/text-tool.cpp
@@ -177,7 +177,7 @@ void TextTool::setup() {
SPItem *item = sp_desktop_selection(this->desktop)->singleItem();
if (item && SP_IS_FLOWTEXT(item) && SP_FLOWTEXT(item)->has_internal_frame()) {
- this->shape_editor->set_item(item, SH_KNOTHOLDER);
+ this->shape_editor->set_item(item);
}
this->sel_changed_connection = sp_desktop_selection(desktop)->connectChangedFirst(
@@ -1411,10 +1411,10 @@ void TextTool::_selectionChanged(Inkscape::Selection *selection)
ToolBase *ec = SP_EVENT_CONTEXT(this);
- ec->shape_editor->unset_item(SH_KNOTHOLDER);
+ ec->shape_editor->unset_item();
SPItem *item = selection->singleItem();
if (item && SP_IS_FLOWTEXT(item) && SP_FLOWTEXT(item)->has_internal_frame()) {
- ec->shape_editor->set_item(item, SH_KNOTHOLDER);
+ ec->shape_editor->set_item(item);
}
if (this->text && (item != this->text)) {
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 4195c9eb2..c23da87c0 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -58,6 +58,7 @@
#include "sp-guide.h"
#include "color.h"
#include "knot.h"
+#include "knot-ptr.h"
// globals for temporary switching to selector by space
static bool selector_toggled = FALSE;
@@ -1289,8 +1290,7 @@ void sp_event_context_snap_delay_handler(ToolBase *ec,
// now, just in case there's no future motion event that drops under the speed limit (when
// stopping abruptly)
delete ec->_delayed_snap_event;
- ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2,
- event, origin); // watchdog is reset, i.e. pushed forward in time
+ ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2, event, origin); // watchdog is reset, i.e. pushed forward in time
// If the watchdog expires before a new motion event is received, we will snap (as explained
// above). This means however that when the timer is too short, we will always snap and that the
// speed threshold is ineffective. In the extreme case the delay is set to zero, and snapping will
@@ -1301,15 +1301,13 @@ void sp_event_context_snap_delay_handler(ToolBase *ec,
// snap, and set a new watchdog again.
if (ec->_delayed_snap_event == NULL) { // no watchdog has been set
// it might have already expired, so we'll set a new one; the snapping frequency will be limited this way
- ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item,
- dse_item2, event, origin);
+ ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2, event, origin);
} // else: watchdog has been set before and we'll wait for it to expire
}
} else {
// This is the first GDK_MOTION_NOTIFY event, so postpone snapping and set the watchdog
g_assert(ec->_delayed_snap_event == NULL);
- ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2,
- event, origin);
+ ec->_delayed_snap_event = new DelayedSnapEvent(ec, dse_item, dse_item2, event, origin);
}
prev_pos = event_pos;
@@ -1362,6 +1360,7 @@ gboolean sp_event_context_snap_watchdog_callback(gpointer data) {
break;
case DelayedSnapEvent::KNOT_HANDLER: {
gpointer knot = dse->getItem2();
+ check_if_knot_deleted(knot);
if (knot && SP_IS_KNOT(knot)) {
sp_knot_handler_request_position(dse->getEvent(), SP_KNOT(knot));
}
diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp
index a33c1d09f..98f4e47cd 100644
--- a/src/ui/widget/style-swatch.cpp
+++ b/src/ui/widget/style-swatch.cpp
@@ -261,7 +261,7 @@ void StyleSwatch::setStyle(SPCSSAttr *css)
Glib::ustring css_string;
sp_repr_css_write_string (_css, css_string);
SPStyle *temp_spstyle = sp_style_new(SP_ACTIVE_DOCUMENT);
- if (~css_string.empty()) {
+ if (!css_string.empty()) {
sp_style_merge_from_style_string (temp_spstyle, css_string.c_str());
}
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 09b5d24a9..7717a304d 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -1247,8 +1247,8 @@ SPDesktopWidget::shutdown()
void
SPDesktopWidget::requestCanvasUpdate() {
// ^^ also this->desktop != 0
- g_return_if_fail (this->desktop != NULL);
- g_return_if_fail (this->desktop->main != NULL);
+ g_return_if_fail(this->desktop != NULL);
+ g_return_if_fail(this->desktop->main != NULL);
gtk_widget_queue_draw (GTK_WIDGET (SP_CANVAS_ITEM (this->desktop->main)->canvas));
}
diff --git a/src/widgets/pencil-toolbar.cpp b/src/widgets/pencil-toolbar.cpp
index 772107101..cf09a4d34 100644
--- a/src/widgets/pencil-toolbar.cpp
+++ b/src/widgets/pencil-toolbar.cpp
@@ -162,6 +162,7 @@ static GList * freehand_shape_dropdown_items_list() {
glist = g_list_append (glist, _("Triangle out"));
glist = g_list_append (glist, _("Ellipse"));
glist = g_list_append (glist, _("From clipboard"));
+ glist = g_list_append (glist, _("Last applied"));
return glist;
}
diff --git a/src/widgets/ruler.cpp b/src/widgets/ruler.cpp
index 5d5151343..8e818843d 100644
--- a/src/widgets/ruler.cpp
+++ b/src/widgets/ruler.cpp
@@ -1394,7 +1394,7 @@ sp_ruler_draw_ticks (SPRuler *ruler)
(label_spacing_px > 6*digit_height || tick_index%2 == 0 || cur == 0) &&
(label_spacing_px > 3*digit_height || tick_index%4 == 0 || cur == 0))
{
- if (fabs((int)cur) >= 2000 && (((int) cur)/1000)*1000 == ((int) cur))
+ if (std::abs((int)cur) >= 2000 && (((int) cur)/1000)*1000 == ((int) cur))
sprintf (unit_str, "%dk", ((int) cur)/1000);
else
sprintf (unit_str, "%d", (int) cur);
diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp
index 64a7cd5e7..36a151c52 100644
--- a/src/widgets/text-toolbar.cpp
+++ b/src/widgets/text-toolbar.cpp
@@ -31,7 +31,6 @@
#include "libnrtype/font-lister.h"
#include <glibmm/i18n.h>
#include "text-toolbar.h"
-#include "connection-pool.h"
#include "desktop-handles.h"
#include "desktop-style.h"
#include "desktop.h"
@@ -54,6 +53,7 @@
#include "toolbox.h"
#include "ui/icon-names.h"
#include "ui/tools/text-tool.h"
+#include "ui/tools/tool-base.h"
#include "verbs.h"
#include "xml/repr.h"
@@ -1200,6 +1200,7 @@ static void sp_text_toolbox_select_cb( GtkEntry* entry, GtkEntryIconPosition /*p
selection->setList(selectList);
}
+static void text_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder);
// Define all the "widgets" in the toolbar.
void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
@@ -1622,31 +1623,35 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje
// Is this necessary to call? Shouldn't hurt.
sp_text_toolbox_selection_changed(sp_desktop_selection(desktop), holder);
- // Watch selection
- Inkscape::ConnectionPool* pool = Inkscape::ConnectionPool::new_connection_pool ("ISTextToolboxGTK");
-
- sigc::connection *c_selection_changed =
- new sigc::connection (sp_desktop_selection (desktop)->connectChanged
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_changed), holder)));
- pool->add_connection ("selection-changed", c_selection_changed);
-
- sigc::connection *c_selection_modified =
- new sigc::connection (sp_desktop_selection (desktop)->connectModified
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_selection_modified), holder)));
- pool->add_connection ("selection-modified", c_selection_modified);
-
- sigc::connection *c_subselection_changed =
- new sigc::connection (desktop->connectToolSubselectionChanged
- (sigc::bind (sigc::ptr_fun (sp_text_toolbox_subselection_changed), holder)));
- pool->add_connection ("tool-subselection-changed", c_subselection_changed);
-
- Inkscape::ConnectionPool::connect_destroy (G_OBJECT (holder), pool);
+ desktop->connectEventContextChanged(sigc::bind(sigc::ptr_fun(text_toolbox_watch_ec), holder));
g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
}
+static void text_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder) {
+ using sigc::connection;
+ using sigc::bind;
+ using sigc::ptr_fun;
+ static connection c_selection_changed;
+ static connection c_selection_modified;
+ static connection c_subselection_changed;
+
+ if (SP_IS_TEXT_CONTEXT(ec)) {
+ // Watch selection
+ c_selection_changed = sp_desktop_selection(desktop)->connectChanged(bind(ptr_fun(sp_text_toolbox_selection_changed), holder));
+ c_selection_modified = sp_desktop_selection (desktop)->connectModified(bind(ptr_fun(sp_text_toolbox_selection_modified), holder));
+ c_subselection_changed = desktop->connectToolSubselectionChanged(bind(ptr_fun(sp_text_toolbox_subselection_changed), holder));
+ } else {
+ if (c_selection_changed)
+ c_selection_changed.disconnect();
+ if (c_selection_modified)
+ c_selection_modified.disconnect();
+ if (c_subselection_changed)
+ c_subselection_changed.disconnect();
+ }
+}
/*
Local Variables:
mode:c++