summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Soegtrop <MSoegtrop@yahoo.de>2016-05-23 20:36:18 +0000
committerMichael Soegtrop <MSoegtrop@yahoo.de>2016-05-23 20:36:18 +0000
commit9b667f5ad22543b88067107425ec55ef972e2ff0 (patch)
tree933384cbb74b5bca4c94417e1ebd6270688bbb9a /src
parentAdded bool LPE (diff)
parentFix regression: restore order in resources (e.g. pattern list) (diff)
downloadinkscape-9b667f5ad22543b88067107425ec55ef972e2ff0.tar.gz
inkscape-9b667f5ad22543b88067107425ec55ef972e2ff0.zip
Fixed Bool LPE review issues
(bzr r14876.2.2)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/elliptical-arc.cpp4
-rw-r--r--src/color-profile.cpp4
-rw-r--r--src/document-private.h2
-rw-r--r--src/document.cpp17
-rw-r--r--src/document.h2
-rw-r--r--src/gradient-chemistry.cpp4
-rw-r--r--src/gradient-drag.cpp4
-rw-r--r--src/layer-manager.cpp10
-rw-r--r--src/live_effects/effect.cpp4
-rw-r--r--src/live_effects/lpe-bool.cpp596
-rw-r--r--src/live_effects/lpe-bool.h41
-rw-r--r--src/live_effects/lpe-mirror_symmetry.cpp330
-rw-r--r--src/live_effects/lpe-mirror_symmetry.h37
-rw-r--r--src/main.cpp79
-rw-r--r--src/profile-manager.cpp5
-rw-r--r--src/pure-transform.cpp38
-rw-r--r--src/pure-transform.h12
-rw-r--r--src/resource-manager.cpp8
-rw-r--r--src/sp-flowtext.h5
-rw-r--r--src/sp-guide.cpp2
-rw-r--r--src/splivarot.cpp5
-rw-r--r--src/ui/dialog/color-item.cpp2
-rw-r--r--src/ui/dialog/document-properties.cpp32
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp4
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp4
-rw-r--r--src/ui/dialog/svg-fonts-dialog.cpp4
-rw-r--r--src/ui/dialog/swatches.cpp17
-rw-r--r--src/ui/interface.cpp4
-rw-r--r--src/ui/previewholder.cpp4
-rw-r--r--src/ui/tool/path-manipulator.cpp2
-rw-r--r--src/ui/tools/freehand-base.cpp5
-rw-r--r--src/ui/widget/color-icc-selector.cpp4
-rw-r--r--src/ui/widget/color-preview.cpp1
-rw-r--r--src/ui/widget/dock.cpp1
-rw-r--r--src/ui/widget/layer-selector.cpp2
-rw-r--r--src/ui/widget/panel.cpp6
-rw-r--r--src/ui/widget/selected-style.cpp1
-rw-r--r--src/ui/widget/style-swatch.cpp2
-rw-r--r--src/widgets/desktop-widget.cpp129
-rw-r--r--src/widgets/eraser-toolbar.cpp4
-rw-r--r--src/widgets/gradient-toolbar.cpp4
-rw-r--r--src/widgets/gradient-vector.cpp4
-rw-r--r--src/widgets/paint-selector.cpp4
-rw-r--r--src/widgets/ruler.cpp4
-rw-r--r--src/widgets/toolbox.cpp9
-rw-r--r--src/xml/rebase-hrefs.cpp4
46 files changed, 912 insertions, 554 deletions
diff --git a/src/2geom/elliptical-arc.cpp b/src/2geom/elliptical-arc.cpp
index a0e379a21..ec62b4be2 100644
--- a/src/2geom/elliptical-arc.cpp
+++ b/src/2geom/elliptical-arc.cpp
@@ -570,13 +570,13 @@ void EllipticalArc::_filterIntersections(std::vector<ShapeIntersection> &xs, boo
std::vector<ShapeIntersection>::reverse_iterator i = xs.rbegin(), last = xs.rend();
while (i != last) {
Coord &t = is_first ? i->first : i->second;
- assert(are_near(_ellipse.pointAt(t), i->point(), 1e-6));
+ assert(are_near(_ellipse.pointAt(t), i->point(), 1e-5));
t = timeAtAngle(t);
if (!unit.contains(t)) {
xs.erase((++i).base());
continue;
} else {
- assert(are_near(pointAt(t), i->point(), 1e-6));
+ assert(are_near(pointAt(t), i->point(), 1e-5));
++i;
}
}
diff --git a/src/color-profile.cpp b/src/color-profile.cpp
index bcefe994a..523026aa5 100644
--- a/src/color-profile.cpp
+++ b/src/color-profile.cpp
@@ -489,8 +489,8 @@ static int getLcmsIntent( guint svgIntent )
static SPObject* bruteFind( SPDocument* document, gchar const* name )
{
SPObject* result = 0;
- std::set<SPObject *> current = document->getResourceList("iccprofile");
- for (std::set<SPObject *>::const_iterator it = current.begin(); (!result) && (it != current.end()); ++it) {
+ std::vector<SPObject *> current = document->getResourceList("iccprofile");
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); (!result) && (it != current.end()); ++it) {
if ( IS_COLORPROFILE(*it) ) {
ColorProfile* prof = COLORPROFILE(*it);
if ( prof ) {
diff --git a/src/document-private.h b/src/document-private.h
index eaed0020e..9cac8fac6 100644
--- a/src/document-private.h
+++ b/src/document-private.h
@@ -49,7 +49,7 @@ struct SPDocumentPrivate {
IDChangedSignalMap id_changed_signals;
/* Resources */
- std::map<std::string, std::set<SPObject *> > resources;
+ std::map<std::string, std::vector<SPObject *> > resources;
ResourcesChangedSignalMap resources_changed_signals;
sigc::signal<void> destroySignal;
diff --git a/src/document.cpp b/src/document.cpp
index 7086fc0be..2500a5cee 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -1541,9 +1541,9 @@ bool SPDocument::addResource(gchar const *key, SPObject *object)
bool result = false;
if ( !object->cloned ) {
- std::set<SPObject *> rlist = priv->resources[key];
- g_return_val_if_fail(rlist.find(object) == rlist.end(), false);
- priv->resources[key].insert(object);
+ std::vector<SPObject *> rlist = priv->resources[key];
+ g_return_val_if_fail(std::find(rlist.begin(),rlist.end(),object) == rlist.end(), false);
+ priv->resources[key].insert(priv->resources[key].begin(),object);
GQuark q = g_quark_from_string(key);
@@ -1572,10 +1572,11 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object)
bool result = false;
if ( !object->cloned ) {
- std::set<SPObject *> rlist = priv->resources[key];
+ std::vector<SPObject *> rlist = priv->resources[key];
g_return_val_if_fail(!rlist.empty(), false);
- g_return_val_if_fail(rlist.find(object) != rlist.end(), false);
- priv->resources[key].erase(object);
+ std::vector<SPObject*>::iterator it = std::find(priv->resources[key].begin(),priv->resources[key].end(),object);
+ g_return_val_if_fail(it != rlist.end(), false);
+ priv->resources[key].erase(it);
GQuark q = g_quark_from_string(key);
priv->resources_changed_signals[q].emit();
@@ -1586,9 +1587,9 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object)
return result;
}
-std::set<SPObject *> const SPDocument::getResourceList(gchar const *key) const
+std::vector<SPObject *> const SPDocument::getResourceList(gchar const *key) const
{
- std::set<SPObject *> emptyset;
+ std::vector<SPObject *> emptyset;
g_return_val_if_fail(key != NULL, emptyset);
g_return_val_if_fail(*key != '\0', emptyset);
diff --git a/src/document.h b/src/document.h
index 825049cd5..653e9d0db 100644
--- a/src/document.h
+++ b/src/document.h
@@ -260,7 +260,7 @@ public:
int ensureUpToDate();
bool addResource(char const *key, SPObject *object);
bool removeResource(char const *key, SPObject *object);
- const std::set<SPObject *> getResourceList(char const *key) const;
+ const std::vector<SPObject *> getResourceList(char const *key) const;
std::vector<SPItem*> getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const;
std::vector<SPItem*> getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups = false) const;
SPItem *getItemAtPoint(unsigned int key, Geom::Point const &p, bool into_groups, SPItem *upto = NULL) const;
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 7b4c0ac20..edeb523d7 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -1612,8 +1612,8 @@ void sp_gradient_unset_swatch(SPDesktop *desktop, std::string id)
SPDocument *doc = desktop ? desktop->doc() : 0;
if (doc) {
- const std::set<SPObject *> gradients = doc->getResourceList("gradient");
- for (std::set<SPObject *>::const_iterator i = gradients.begin(); i != gradients.end(); ++i) {
+ const std::vector<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::vector<SPObject *>::const_iterator i = gradients.begin(); i != gradients.end(); ++i) {
SPGradient* grad = SP_GRADIENT(*i);
if ( id == grad->getId() ) {
grad->setSwatch(false);
diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp
index 8fd997121..613dc2fc1 100644
--- a/src/gradient-drag.cpp
+++ b/src/gradient-drag.cpp
@@ -208,8 +208,8 @@ Glib::ustring GrDrag::makeStopSafeColor( gchar const *str, bool &isNull )
Glib::ustring::size_type pos = colorStr.find("url(#");
if ( pos != Glib::ustring::npos ) {
Glib::ustring targetName = colorStr.substr(pos + 5, colorStr.length() - 6);
- std::set<SPObject *> gradients = desktop->doc()->getResourceList("gradient");
- for (std::set<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) {
+ std::vector<SPObject *> gradients = desktop->doc()->getResourceList("gradient");
+ for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) {
SPGradient* grad = SP_GRADIENT(*it);
if ( targetName == grad->getId() ) {
SPGradient *vect = grad->getVector();
diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp
index c0fe95dd7..19c4b890c 100644
--- a/src/layer-manager.cpp
+++ b/src/layer-manager.cpp
@@ -191,10 +191,10 @@ Glib::ustring LayerManager::getNextLayerName( SPObject* obj, gchar const *label)
}
std::set<Glib::ustring> currentNames;
- std::set<SPObject *> layers = _document->getResourceList("layer");
+ std::vector<SPObject *> layers = _document->getResourceList("layer");
SPObject *root=_desktop->currentRoot();
if ( root ) {
- for (std::set<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter) {
+ for (std::vector<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter) {
if (*iter != obj)
currentNames.insert( (*iter)->label() ? Glib::ustring((*iter)->label()) : Glib::ustring() );
}
@@ -260,7 +260,7 @@ void LayerManager::_rebuild() {
if (!_document) // http://sourceforge.net/mailarchive/forum.php?thread_name=5747bce9a7ed077c1b4fc9f0f4f8a5e0%40localhost&forum_name=inkscape-devel
return;
- std::set<SPObject *> layers = _document->getResourceList("layer");
+ std::vector<SPObject *> layers = _document->getResourceList("layer");
SPObject *root=_desktop->currentRoot();
if ( root ) {
@@ -268,7 +268,7 @@ void LayerManager::_rebuild() {
std::set<SPGroup*> layersToAdd;
- for ( std::set<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter ) {
+ for ( std::vector<SPObject *>::const_iterator iter = layers.begin(); iter != layers.end(); ++iter ) {
SPObject *layer = *iter;
// Debug::EventTracker<DebugLayerNote> tracker(Util::format("Examining %s", layer->label()));
bool needsAdd = false;
@@ -281,7 +281,7 @@ void LayerManager::_rebuild() {
SPGroup* group = SP_GROUP(curr);
if ( group->layerMode() == SPGroup::LAYER ) {
// If we have a layer-group as the one or a parent, ensure it is listed as a valid layer.
- needsAdd &= ( layers.find(curr) != layers.end() );
+ needsAdd &= ( std::find(layers.begin(),layers.end(),curr) != layers.end() );
// XML Tree being used here directly while it shouldn't be...
if ( (!(group->getRepr())) || (!(group->getRepr()->parent())) ) {
needsAdd = false;
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index b03671027..0d28836ca 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -105,7 +105,6 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{EXTRUDE, N_("Extrude"), "extrude"},
{LATTICE, N_("Lattice Deformation"), "lattice"},
{LINE_SEGMENT, N_("Line Segment"), "line_segment"},
- {MIRROR_SYMMETRY, N_("Mirror symmetry"), "mirror_symmetry"},
{OFFSET, N_("Offset"), "offset"},
{PARALLEL, N_("Parallel"), "parallel"},
{PATH_LENGTH, N_("Path length"), "path_length"},
@@ -114,6 +113,7 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"},
{TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"},
{TEXT_LABEL, N_("Text label"), "text_label"},
+ {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"},
#endif
/* 0.46 */
{BEND_PATH, N_("Bend"), "bend_path"},
@@ -137,7 +137,6 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{SIMPLIFY, N_("Simplify"), "simplify"},
{LATTICE2, N_("Lattice Deformation 2"), "lattice2"},
{PERSPECTIVE_ENVELOPE, N_("Perspective/Envelope"), "perspective-envelope"},
- {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"},
{INTERPOLATE_POINTS, N_("Interpolate points"), "interpolate_points"},
{TRANSFORM_2PTS, N_("Transform by 2 points"), "transform_2pts"},
{SHOW_HANDLES, N_("Show handles"), "show_handles"},
@@ -145,6 +144,7 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{BSPLINE, N_("BSpline"), "bspline"},
{JOIN_TYPE, N_("Join type"), "join_type"},
{TAPER_STROKE, N_("Taper stroke"), "taper_stroke"},
+ {MIRROR_SYMMETRY, N_("Mirror symmetry"), "mirror_symmetry"},
{COPY_ROTATE, N_("Rotate copies"), "copy_rotate"},
/* Ponyscape -> Inkscape 0.92*/
{ATTACH_PATH, N_("Attach path"), "attach_path"},
diff --git a/src/live_effects/lpe-bool.cpp b/src/live_effects/lpe-bool.cpp
index 902bb081b..6c9830fbd 100644
--- a/src/live_effects/lpe-bool.cpp
+++ b/src/live_effects/lpe-bool.cpp
@@ -34,53 +34,55 @@ namespace LivePathEffect {
// Define an extended boolean operation type
static const Util::EnumData<LPEBool::bool_op_ex> BoolOpData[LPEBool::bool_op_ex_count] = {
- { LPEBool::bool_op_ex_union, N_("union"), "union" },
- { LPEBool::bool_op_ex_inters, N_("intersection"), "inters" },
- { LPEBool::bool_op_ex_diff, N_("difference"), "diff" },
- { LPEBool::bool_op_ex_symdiff, N_("symmetric difference"), "symdiff" },
- { LPEBool::bool_op_ex_cut, N_("cut"), "cut" },
- { LPEBool::bool_op_ex_slice, N_("slice, keep inner contours"), "slice" },
- { LPEBool::bool_op_ex_slice_inside, N_("slice inside, keep inner contours"), "slice-inside" },
- { LPEBool::bool_op_ex_slice_outside, N_("slice outside, keep inner contours"), "slice-outside" },
- { LPEBool::bool_op_ex_slice_rmv_inner, N_("slice, remove inner contours"), "slice-rmv-inner" },
- { LPEBool::bool_op_ex_slice_inside_rmv_inner, N_("slice inside, remove inner contours"), "slice-inside-rmv-inner" },
- { LPEBool::bool_op_ex_slice_outside_rmv_inner, N_("slice outside, remove inner contours"), "slice-outside-rmv-inner" }
+ { LPEBool::bool_op_ex_union, N_("union"), "union" },
+ { LPEBool::bool_op_ex_inters, N_("intersection"), "inters" },
+ { LPEBool::bool_op_ex_diff, N_("difference"), "diff" },
+ { LPEBool::bool_op_ex_symdiff, N_("symmetric difference"), "symdiff" },
+ { LPEBool::bool_op_ex_cut, N_("division"), "cut" },
+ // Note on naming of operations:
+ // bool_op_cut is called "Division" in the manu, see sp_selected_path_cut
+ // bool_op_slice is called "Cut path" in the menu, see sp_selected_path_slice
+ { LPEBool::bool_op_ex_slice, N_("cut"), "slice" },
+ { LPEBool::bool_op_ex_slice_inside, N_("cut inside"), "slice-inside" },
+ { LPEBool::bool_op_ex_slice_outside, N_("cut outside"), "slice-outside" },
};
-static const Util::EnumDataConverter<LPEBool::bool_op_ex> BoolOpConverter(BoolOpData, sizeof(BoolOpData)/sizeof(*BoolOpData));
+static const Util::EnumDataConverter<LPEBool::bool_op_ex> BoolOpConverter(BoolOpData, sizeof(BoolOpData) / sizeof(*BoolOpData));
static const Util::EnumData<fill_typ> FillTypeData[] = {
- { fill_oddEven, N_("odd-even"), "oddeven" },
- { fill_nonZero, N_("non-zero"), "nonzero" },
- { fill_positive, N_("positive"), "positive" },
- { fill_justDont, N_("from curve"), "from-curve" }
+ { fill_oddEven, N_("odd-even"), "oddeven" },
+ { fill_nonZero, N_("non-zero"), "nonzero" },
+ { fill_positive, N_("positive"), "positive" },
+ { fill_justDont, N_("from curve"), "from-curve" }
};
-static const Util::EnumDataConverter<fill_typ> FillTypeConverter(FillTypeData, sizeof(FillTypeData)/sizeof(*FillTypeData));
+static const Util::EnumDataConverter<fill_typ> FillTypeConverter(FillTypeData, sizeof(FillTypeData) / sizeof(*FillTypeData));
static const Util::EnumData<fill_typ> FillTypeDataThis[] = {
- { fill_oddEven, N_("odd-even"), "oddeven" },
- { fill_nonZero, N_("non-zero"), "nonzero" },
- { fill_positive, N_("positive"), "positive" }
+ { fill_oddEven, N_("odd-even"), "oddeven" },
+ { fill_nonZero, N_("non-zero"), "nonzero" },
+ { fill_positive, N_("positive"), "positive" }
};
-static const Util::EnumDataConverter<fill_typ> FillTypeConverterThis(FillTypeDataThis, sizeof(FillTypeDataThis)/sizeof(*FillTypeDataThis));
+static const Util::EnumDataConverter<fill_typ> FillTypeConverterThis(FillTypeDataThis, sizeof(FillTypeDataThis) / sizeof(*FillTypeDataThis));
LPEBool::LPEBool(LivePathEffectObject *lpeobject) :
- Effect(lpeobject),
- operand_path(_("Operand path:"), _("Operand for the boolean operation"), "operand-path", &wr, this),
- bool_operation(_("Operation:"), _("Boolean Operation"), "operation", BoolOpConverter, &wr, this, bool_op_ex_union),
- swap_operands(_("Swap operands:"), _("Swap operands (useful e.g. for difference)"), "swap-operands", &wr, this),
- fill_type_this(_("Fill type this:"), _("Fill type (winding mode) for this path"), "filltype-this", FillTypeConverterThis, &wr, this, fill_oddEven),
- fill_type_operand(_("Fill type operand:"), _("Fill type (winding mode) for operand path"), "filltype-operand", FillTypeConverter, &wr, this, fill_justDont)
+ Effect(lpeobject),
+ operand_path(_("Operand path:"), _("Operand for the boolean operation"), "operand-path", &wr, this),
+ bool_operation(_("Operation:"), _("Boolean Operation"), "operation", BoolOpConverter, &wr, this, bool_op_ex_union),
+ swap_operands(_("Swap operands:"), _("Swap operands (useful e.g. for difference)"), "swap-operands", &wr, this),
+ rmv_inner(_("Remove inner:"), _("For cut operations: remove inner (non-contour) lines of cutting path to avoid invisible extra points"), "rmv-inner", &wr, this),
+ fill_type_this(_("Fill type this:"), _("Fill type (winding mode) for this path"), "filltype-this", FillTypeConverterThis, &wr, this, fill_oddEven),
+ fill_type_operand(_("Fill type operand:"), _("Fill type (winding mode) for operand path"), "filltype-operand", FillTypeConverter, &wr, this, fill_justDont)
{
- registerParameter(&operand_path);
- registerParameter(&bool_operation);
- registerParameter(&swap_operands);
- registerParameter(&fill_type_this);
- registerParameter(&fill_type_operand);
-
- show_orig_path = true;
+ registerParameter(&operand_path);
+ registerParameter(&bool_operation);
+ registerParameter(&swap_operands);
+ registerParameter(&rmv_inner);
+ registerParameter(&fill_type_this);
+ registerParameter(&fill_type_operand);
+
+ show_orig_path = true;
}
LPEBool::~LPEBool()
@@ -92,231 +94,222 @@ void LPEBool::resetDefaults(SPItem const * /*item*/)
{
}
-bool cmp_cut_position( const Path::cut_position &a, const Path::cut_position &b )
+bool cmp_cut_position(const Path::cut_position &a, const Path::cut_position &b)
{
- return a.piece==b.piece ? a.t<b.t : a.piece<b.piece;
+ return a.piece == b.piece ? a.t < b.t : a.piece < b.piece;
}
Geom::PathVector
sp_pathvector_boolop_slice_intersect(Geom::PathVector const &pathva, Geom::PathVector const &pathvb, bool inside, fill_typ fra, fill_typ frb)
{
- // This is similar to sp_pathvector_boolop/bool_op_slice, but keeps only edges inside the cutter area.
- // The code is also based on sp_pathvector_boolop_slice.
- //
- // We have two paths on input
- // - a closed area which is used to cut out pieces from a contour (called area below)
- // - a contour which is cut into pieces by the border of thr area (called contour below)
- //
- // The code below works in the following steps
- // (a) Convert the area to a shape, so that we can ask the winding number for any point
- // (b) Add both, the contour and the area to a single shape and intersect them
- // (c) Find the intersection points between area border and contour (vector toCut)
- // (d) Split the original contour at the intersection points
- // (e) check for each contour edge in combined shape if its center is inside the area - if not discard it
- // (f) create a vector of all inside edges
- // (g) convert the piece numbers to the piece numbers after applying the cuts
- // (h) fill a bool vector with information which pieces are in
- // (i) filter the descr_cmd of the result path with this bool vector
- //
- // The main inefficieny here is step (e) because I use a winding function of the area-shape which goes
- // through teh complete edge list for each point I ask for, so effort is n-edges-contour * n-edges-area.
- // It is tricky to improve this without building into the livarot code.
- // One way might be to decide at the intersection points which edges touching the intersection points are
- // in by making a loop through all edges on the intersection vertex. Since this is a directed non intersecting
- // graph, this should provide sufficient information.
- // But since I anyway will change this to the new mechanism some time speed is fairly ok, I didn't look into this.
-
-
- // extract the livarot Paths from the source objects
- // also get the winding rule specified in the style
- // Livarot's outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly.
- Path *contour_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers( pathva) );
- Path *area_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers( pathvb) );
-
- // Shapes from above paths
- Shape *area_shape = new Shape;
- Shape *combined_shape = new Shape;
- Shape *combined_inters = new Shape;
-
- // Add the area (process to intersection free shape)
- area_path->ConvertWithBackData(1.0);
- area_path->Fill(combined_shape, 1);
-
- // Convert this to a shape with full winding information
- area_shape->ConvertToShape(combined_shape, frb);
-
- // Add the contour to the combined path (just add, no winding processing)
- contour_path->ConvertWithBackData(1.0);
- contour_path->Fill(combined_shape, 0,true,false,false);
-
- // Intersect the area and the contour - no fill processing
- combined_inters->ConvertToShape(combined_shape, fill_justDont);
-
- // Result path
- Path *result_path = new Path;
- result_path->SetBackData(false);
-
- // Cutting positions for contour
- std::vector<Path::cut_position> toCut;
-
- if ( combined_inters->hasBackData() ) {
- // should always be the case, but ya never know
- {
- for (int i = 0; i < combined_inters->numberOfPoints(); i++) {
- if ( combined_inters->getPoint(i).totalDegree() > 2 ) {
- // possibly an intersection
- // we need to check that at least one edge from the source path is incident to it
- // before we declare it's an intersection
- int cb = combined_inters->getPoint(i).incidentEdge[FIRST];
- int nbOrig=0;
- int nbOther=0;
- int piece=-1;
- float t=0.0;
- while ( cb >= 0 && cb < combined_inters->numberOfEdges() ) {
- if ( combined_inters->ebData[cb].pathID == 0 ) {
- // the source has an edge incident to the point, get its position on the path
- piece=combined_inters->ebData[cb].pieceID;
- if ( combined_inters->getEdge(cb).st == i ) {
- t=combined_inters->ebData[cb].tSt;
- } else {
- t=combined_inters->ebData[cb].tEn;
- }
- nbOrig++;
- }
- if ( combined_inters->ebData[cb].pathID == 1 ) nbOther++; // the cut is incident to this point
- cb=combined_inters->NextAt(i, cb);
- }
- if ( nbOrig > 0 && nbOther > 0 ) {
- // point incident to both path and cut: an intersection
- // note that you only keep one position on the source; you could have degenerate
- // cases where the source crosses itself at this point, and you wouyld miss an intersection
- Path::cut_position cutpos;
- cutpos.piece=piece;
- cutpos.t=t;
- toCut.push_back( cutpos );
- }
- }
- }
- }
- {
- // remove the edges from the intersection polygon
- int i = combined_inters->numberOfEdges() - 1;
- for (;i>=0;i--) {
- if ( combined_inters->ebData[i].pathID == 1 ) {
- combined_inters->SubEdge(i);
- } else {
- const Shape::dg_arete &edge = combined_inters->getEdge(i);
- const Shape::dg_point &start = combined_inters->getPoint(edge.st);
- const Shape::dg_point &end = combined_inters->getPoint(edge.en);
- Geom::Point mid = 0.5*(start.x+end.x);
- int wind = area_shape->PtWinding( mid );
- if ( wind==0 ) {
- combined_inters->SubEdge(i);
- }
- }
- }
- }
- }
-
- // create a vector of pieces, which are in the intersection
- std::vector<Path::cut_position> inside_pieces( combined_inters->numberOfEdges() );
- for( int i=0; i<combined_inters->numberOfEdges(); i++ ) {
- inside_pieces[i].piece = combined_inters->ebData[i].pieceID;
- // Use the t middle point, this is safe to compare with values from toCut in the presence of roundoff errors
- inside_pieces[i].t = 0.5 * (combined_inters->ebData[i].tSt + combined_inters->ebData[i].tEn);
- }
- std::sort( inside_pieces.begin(), inside_pieces.end(), cmp_cut_position );
-
- // sort cut positions
- std::sort( toCut.begin(), toCut.end(), cmp_cut_position );
-
- // Compute piece ids after ConvertPositionsToMoveTo
- {
- int idIncr=0;
- std::vector<Path::cut_position>::iterator itPiece=inside_pieces.begin();
- std::vector<Path::cut_position>::iterator itCut=toCut.begin();
- while( itPiece!=inside_pieces.end() )
- {
- while( itCut!=toCut.end() && cmp_cut_position( *itCut, *itPiece ) )
- {
- ++itCut;
- idIncr+=2;
- }
- itPiece->piece += idIncr;
- ++itPiece;
- }
- }
-
- // Copy the original path to result and cut at the intersection points
- result_path->Copy( contour_path );
- result_path->ConvertPositionsToMoveTo( toCut.size(), toCut.data() ); // cut where you found intersections
-
- // Create an array of bools which states which pieces are in
- std::vector<bool> inside_flags(result_path->descr_cmd.size(), false );
- for( std::vector<Path::cut_position>::iterator itPiece=inside_pieces.begin(); itPiece!=inside_pieces.end(); ++itPiece )
- {
- inside_flags[ itPiece->piece ] = true;
- // also enable the element -1 to get the MoveTo
- if( itPiece->piece>=1 )
- {
- inside_flags[ itPiece->piece-1 ] = true;
- }
- }
+ // This is similar to sp_pathvector_boolop/bool_op_slice, but keeps only edges inside the cutter area.
+ // The code is also based on sp_pathvector_boolop_slice.
+ //
+ // We have two paths on input
+ // - a closed area which is used to cut out pieces from a contour (called area below)
+ // - a contour which is cut into pieces by the border of thr area (called contour below)
+ //
+ // The code below works in the following steps
+ // (a) Convert the area to a shape, so that we can ask the winding number for any point
+ // (b) Add both, the contour and the area to a single shape and intersect them
+ // (c) Find the intersection points between area border and contour (vector toCut)
+ // (d) Split the original contour at the intersection points
+ // (e) check for each contour edge in combined shape if its center is inside the area - if not discard it
+ // (f) create a vector of all inside edges
+ // (g) convert the piece numbers to the piece numbers after applying the cuts
+ // (h) fill a bool vector with information which pieces are in
+ // (i) filter the descr_cmd of the result path with this bool vector
+ //
+ // The main inefficieny here is step (e) because I use a winding function of the area-shape which goes
+ // through teh complete edge list for each point I ask for, so effort is n-edges-contour * n-edges-area.
+ // It is tricky to improve this without building into the livarot code.
+ // One way might be to decide at the intersection points which edges touching the intersection points are
+ // in by making a loop through all edges on the intersection vertex. Since this is a directed non intersecting
+ // graph, this should provide sufficient information.
+ // But since I anyway will change this to the new mechanism some time speed is fairly ok, I didn't look into this.
+
+
+ // extract the livarot Paths from the source objects
+ // also get the winding rule specified in the style
+ // Livarot's outline of arcs is broken. So convert the path to linear and cubics only, for which the outline is created correctly.
+ Path *contour_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers(pathva));
+ Path *area_path = Path_for_pathvector(pathv_to_linear_and_cubic_beziers(pathvb));
+
+ // Shapes from above paths
+ Shape *area_shape = new Shape;
+ Shape *combined_shape = new Shape;
+ Shape *combined_inters = new Shape;
+
+ // Add the area (process to intersection free shape)
+ area_path->ConvertWithBackData(1.0);
+ area_path->Fill(combined_shape, 1);
+
+ // Convert this to a shape with full winding information
+ area_shape->ConvertToShape(combined_shape, frb);
+
+ // Add the contour to the combined path (just add, no winding processing)
+ contour_path->ConvertWithBackData(1.0);
+ contour_path->Fill(combined_shape, 0, true, false, false);
+
+ // Intersect the area and the contour - no fill processing
+ combined_inters->ConvertToShape(combined_shape, fill_justDont);
+
+ // Result path
+ Path *result_path = new Path;
+ result_path->SetBackData(false);
+
+ // Cutting positions for contour
+ std::vector<Path::cut_position> toCut;
+
+ if (combined_inters->hasBackData()) {
+ // should always be the case, but ya never know
+ {
+ for (int i = 0; i < combined_inters->numberOfPoints(); i++) {
+ if (combined_inters->getPoint(i).totalDegree() > 2) {
+ // possibly an intersection
+ // we need to check that at least one edge from the source path is incident to it
+ // before we declare it's an intersection
+ int cb = combined_inters->getPoint(i).incidentEdge[FIRST];
+ int nbOrig = 0;
+ int nbOther = 0;
+ int piece = -1;
+ float t = 0.0;
+ while (cb >= 0 && cb < combined_inters->numberOfEdges()) {
+ if (combined_inters->ebData[cb].pathID == 0) {
+ // the source has an edge incident to the point, get its position on the path
+ piece = combined_inters->ebData[cb].pieceID;
+ if (combined_inters->getEdge(cb).st == i) {
+ t = combined_inters->ebData[cb].tSt;
+ } else {
+ t = combined_inters->ebData[cb].tEn;
+ }
+ nbOrig++;
+ }
+ if (combined_inters->ebData[cb].pathID == 1) {
+ nbOther++; // the cut is incident to this point
+ }
+ cb = combined_inters->NextAt(i, cb);
+ }
+ if (nbOrig > 0 && nbOther > 0) {
+ // point incident to both path and cut: an intersection
+ // note that you only keep one position on the source; you could have degenerate
+ // cases where the source crosses itself at this point, and you wouyld miss an intersection
+ Path::cut_position cutpos;
+ cutpos.piece = piece;
+ cutpos.t = t;
+ toCut.push_back(cutpos);
+ }
+ }
+ }
+ }
+ {
+ // remove the edges from the intersection polygon
+ int i = combined_inters->numberOfEdges() - 1;
+ for (; i >= 0; i--) {
+ if (combined_inters->ebData[i].pathID == 1) {
+ combined_inters->SubEdge(i);
+ } else {
+ const Shape::dg_arete &edge = combined_inters->getEdge(i);
+ const Shape::dg_point &start = combined_inters->getPoint(edge.st);
+ const Shape::dg_point &end = combined_inters->getPoint(edge.en);
+ Geom::Point mid = 0.5 * (start.x + end.x);
+ int wind = area_shape->PtWinding(mid);
+ if (wind == 0) {
+ combined_inters->SubEdge(i);
+ }
+ }
+ }
+ }
+ }
+
+ // create a vector of pieces, which are in the intersection
+ std::vector<Path::cut_position> inside_pieces(combined_inters->numberOfEdges());
+ for (int i = 0; i < combined_inters->numberOfEdges(); i++) {
+ inside_pieces[i].piece = combined_inters->ebData[i].pieceID;
+ // Use the t middle point, this is safe to compare with values from toCut in the presence of roundoff errors
+ inside_pieces[i].t = 0.5 * (combined_inters->ebData[i].tSt + combined_inters->ebData[i].tEn);
+ }
+ std::sort(inside_pieces.begin(), inside_pieces.end(), cmp_cut_position);
+
+ // sort cut positions
+ std::sort(toCut.begin(), toCut.end(), cmp_cut_position);
+
+ // Compute piece ids after ConvertPositionsToMoveTo
+ {
+ int idIncr = 0;
+ std::vector<Path::cut_position>::iterator itPiece = inside_pieces.begin();
+ std::vector<Path::cut_position>::iterator itCut = toCut.begin();
+ while (itPiece != inside_pieces.end()) {
+ while (itCut != toCut.end() && cmp_cut_position(*itCut, *itPiece)) {
+ ++itCut;
+ idIncr += 2;
+ }
+ itPiece->piece += idIncr;
+ ++itPiece;
+ }
+ }
+
+ // Copy the original path to result and cut at the intersection points
+ result_path->Copy(contour_path);
+ result_path->ConvertPositionsToMoveTo(toCut.size(), toCut.data()); // cut where you found intersections
+
+ // Create an array of bools which states which pieces are in
+ std::vector<bool> inside_flags(result_path->descr_cmd.size(), false);
+ for (std::vector<Path::cut_position>::iterator itPiece = inside_pieces.begin(); itPiece != inside_pieces.end(); ++itPiece) {
+ inside_flags[ itPiece->piece ] = true;
+ // also enable the element -1 to get the MoveTo
+ if (itPiece->piece >= 1) {
+ inside_flags[ itPiece->piece - 1 ] = true;
+ }
+ }
#if 0 // CONCEPT TESTING
- //Check if the inside/outside verdict is consistent - just for testing the concept
- // Retrieve the pieces
- int nParts=0;
- Path** parts=result_path->SubPaths(nParts,false);
+ //Check if the inside/outside verdict is consistent - just for testing the concept
+ // Retrieve the pieces
+ int nParts = 0;
+ Path **parts = result_path->SubPaths(nParts, false);
// Each piece should be either fully in or fully out
- int iPiece=0;
- for( int iPart=0; iPart<nParts; iPart++ )
- {
- bool andsum=true;
- bool orsum=false;
- for( int iCmd=0; iCmd<parts[iPart]->descr_cmd.size(); iCmd++, iPiece++ )
- {
- andsum = andsum && inside_flags[ iPiece ];
- orsum = andsum || inside_flags[ iPiece ];
- }
-
- if( andsum!=orsum )
- {
- g_warning( "Inconsistent inside/outside verdict for part=%d", iPart );
- }
+ int iPiece = 0;
+ for (int iPart = 0; iPart < nParts; iPart++) {
+ bool andsum = true;
+ bool orsum = false;
+ for (int iCmd = 0; iCmd < parts[iPart]->descr_cmd.size(); iCmd++, iPiece++) {
+ andsum = andsum && inside_flags[ iPiece ];
+ orsum = andsum || inside_flags[ iPiece ];
+ }
+
+ if (andsum != orsum) {
+ g_warning("Inconsistent inside/outside verdict for part=%d", iPart);
+ }
}
- g_free(parts);
+ g_free(parts);
#endif
- // iterate over the commands of a path and keep those which are inside
- int iDest=0;
- for( int iSrc=0; iSrc<result_path->descr_cmd.size(); iSrc++ )
- {
- if( inside_flags[iSrc]==inside )
- {
- result_path->descr_cmd[iDest++] = result_path->descr_cmd[iSrc];
- }
- else
- {
- delete result_path->descr_cmd[iSrc];
- }
- }
- result_path->descr_cmd.resize( iDest );
-
- delete combined_inters;
- delete combined_shape;
- delete area_shape;
- delete contour_path;
- delete area_path;
-
- gchar *result_str = result_path->svg_dump_path();
- Geom::PathVector outres = Geom::parse_svg_path(result_str);
- // CONCEPT TESTING g_warning( "%s", result_str );
- g_free(result_str);
- delete result_path;
-
- return outres;
+ // iterate over the commands of a path and keep those which are inside
+ int iDest = 0;
+ for (int iSrc = 0; iSrc < result_path->descr_cmd.size(); iSrc++) {
+ if (inside_flags[iSrc] == inside) {
+ result_path->descr_cmd[iDest++] = result_path->descr_cmd[iSrc];
+ } else {
+ delete result_path->descr_cmd[iSrc];
+ }
+ }
+ result_path->descr_cmd.resize(iDest);
+
+ delete combined_inters;
+ delete combined_shape;
+ delete area_shape;
+ delete contour_path;
+ delete area_path;
+
+ gchar *result_str = result_path->svg_dump_path();
+ Geom::PathVector outres = Geom::parse_svg_path(result_str);
+ // CONCEPT TESTING g_warning( "%s", result_str );
+ g_free(result_str);
+ delete result_path;
+
+ return outres;
}
// remove inner contours
@@ -324,17 +317,17 @@ Geom::PathVector
sp_pathvector_boolop_remove_inner(Geom::PathVector const &pathva, fill_typ fra)
{
Geom::PathVector patht;
- Path *patha = Path_for_pathvector(pathv_to_linear_and_cubic_beziers( pathva ) );
+ Path *patha = Path_for_pathvector(pathv_to_linear_and_cubic_beziers(pathva));
Shape *shape = new Shape;
Shape *shapeshape = new Shape;
Path *resultp = new Path;
resultp->SetBackData(false);
- patha->ConvertWithBackData(0.1);
- patha->Fill(shape, 0);
- shapeshape->ConvertToShape(shape, fra);
- shapeshape->ConvertToForme(resultp, 1, &patha);
+ patha->ConvertWithBackData(0.1);
+ patha->Fill(shape, 0);
+ shapeshape->ConvertToShape(shape, fra);
+ shapeshape->ConvertToForme(resultp, 1, &patha);
delete shape;
delete shapeshape;
@@ -361,73 +354,46 @@ static fill_typ GetFillTyp(SPItem *item)
}
}
-void LPEBool::doEffect (SPCurve * curve)
+void LPEBool::doEffect(SPCurve *curve)
{
Geom::PathVector path_in = curve->get_pathvector();
- if ( operand_path.linksToPath() && operand_path.getObject() )
- {
- bool_op_ex op = bool_operation.get_value();
- bool swap = swap_operands.get_value();
-
- Geom::PathVector path_a = swap ? operand_path.get_pathvector() : path_in;
- Geom::PathVector path_b = swap ? path_in : operand_path.get_pathvector();
-
- // TODO: I would like to use the original objects fill rule if the UI selected rule is fill_justDont.
- // But it doesn't seem possible to access them from here, because SPCurve is not derived from SPItem.
- // The nearest function in the call stack, where this is available is SPLPEItem::performPathEffect (this is then an SPItem)
- // For the parameter curve, this is possible.
- // fill_typ fill_this = fill_type_this. get_value()!=fill_justDont ? fill_type_this.get_value() : GetFillTyp( curve ) ;
- fill_typ fill_this = fill_type_this.get_value();
- fill_typ fill_operand = fill_type_operand.get_value()!=fill_justDont ? fill_type_operand.get_value() : GetFillTyp( operand_path.getObject() );
-
- fill_typ fill_a = swap ? fill_operand : fill_this;
- fill_typ fill_b = swap ? fill_this : fill_operand;
-
- switch( op )
- {
- case bool_op_ex_slice_rmv_inner:
- op = bool_op_ex_slice;
- path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b );
- break;
-
- case bool_op_ex_slice_inside_rmv_inner:
- op = bool_op_ex_slice_inside;
- path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b );
- break;
-
- case bool_op_ex_slice_outside_rmv_inner:
- op = bool_op_ex_slice_outside;
- path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b );
- break;
- }
-
- Geom::PathVector path_out;
-
- if( op==bool_op_ex_slice || op == bool_op_ex_slice_rmv_inner) {
- if( op==bool_op_ex_slice_rmv_inner )
- {
- path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b );
- }
- path_out = sp_pathvector_boolop( path_b, path_a, to_bool_op(op), fill_b, fill_a);
- }
- else if( op==bool_op_ex_slice_inside || op==bool_op_ex_slice_inside_rmv_inner ) {
- if( op==bool_op_ex_slice_inside_rmv_inner )
- {
- path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b );
- }
- path_out = sp_pathvector_boolop_slice_intersect( path_a, path_b, true, fill_a, fill_b);
- } else if( op==bool_op_ex_slice_outside || op == bool_op_ex_slice_outside_rmv_inner ) {
- if( op==bool_op_ex_slice_outside_rmv_inner )
- {
- path_b = sp_pathvector_boolop_remove_inner( path_b, fill_b );
- }
- path_out = sp_pathvector_boolop_slice_intersect( path_a, path_b, false, fill_a, fill_b);
- } else {
- path_out = sp_pathvector_boolop( path_a, path_b, to_bool_op(op), fill_a, fill_b);
- }
- curve->set_pathvector( path_out );
- }
+ if (operand_path.linksToPath() && operand_path.getObject()) {
+ bool_op_ex op = bool_operation.get_value();
+ bool swap = swap_operands.get_value();
+
+ Geom::PathVector path_a = swap ? operand_path.get_pathvector() : path_in;
+ Geom::PathVector path_b = swap ? path_in : operand_path.get_pathvector();
+
+ // TODO: I would like to use the original objects fill rule if the UI selected rule is fill_justDont.
+ // But it doesn't seem possible to access them from here, because SPCurve is not derived from SPItem.
+ // The nearest function in the call stack, where this is available is SPLPEItem::performPathEffect (this is then an SPItem)
+ // For the parameter curve, this is possible.
+ // fill_typ fill_this = fill_type_this. get_value()!=fill_justDont ? fill_type_this.get_value() : GetFillTyp( curve ) ;
+ fill_typ fill_this = fill_type_this.get_value();
+ fill_typ fill_operand = fill_type_operand.get_value() != fill_justDont ? fill_type_operand.get_value() : GetFillTyp(operand_path.getObject());
+
+ fill_typ fill_a = swap ? fill_operand : fill_this;
+ fill_typ fill_b = swap ? fill_this : fill_operand;
+
+ if (rmv_inner.get_value()) {
+ path_b = sp_pathvector_boolop_remove_inner(path_b, fill_b);
+ }
+
+ Geom::PathVector path_out;
+
+ if (op == bool_op_ex_slice) {
+ // For slicing, the bool op is added to the line group which is sliced, not the cut path. This swapped order is correct.
+ path_out = sp_pathvector_boolop(path_b, path_a, to_bool_op(op), fill_b, fill_a);
+ } else if (op == bool_op_ex_slice_inside) {
+ path_out = sp_pathvector_boolop_slice_intersect(path_a, path_b, true, fill_a, fill_b);
+ } else if (op == bool_op_ex_slice_outside) {
+ path_out = sp_pathvector_boolop_slice_intersect(path_a, path_b, false, fill_a, fill_b);
+ } else {
+ path_out = sp_pathvector_boolop(path_a, path_b, to_bool_op(op), fill_a, fill_b);
+ }
+ curve->set_pathvector(path_out);
+ }
}
} // namespace LivePathEffect
diff --git a/src/live_effects/lpe-bool.h b/src/live_effects/lpe-bool.h
index 12c51b4ec..1c0aa0243 100644
--- a/src/live_effects/lpe-bool.h
+++ b/src/live_effects/lpe-bool.h
@@ -24,40 +24,37 @@ public:
LPEBool(LivePathEffectObject *lpeobject);
virtual ~LPEBool();
- void doEffect (SPCurve * curve);
- virtual void resetDefaults(SPItem const * item);
-
- enum bool_op_ex
- {
- bool_op_ex_union = bool_op_union,
- bool_op_ex_inters = bool_op_inters,
- bool_op_ex_diff = bool_op_diff,
- bool_op_ex_symdiff = bool_op_symdiff,
- bool_op_ex_cut = bool_op_cut,
- bool_op_ex_slice = bool_op_slice,
- bool_op_ex_slice_inside, // like bool_op_slice, but leaves only the contour pieces inside of the cut path
- bool_op_ex_slice_outside, // like bool_op_slice, but leaves only the contour pieces outside of the cut path
- bool_op_ex_slice_rmv_inner, // like bool_op_ex_slice, but remove inner contours
- bool_op_ex_slice_inside_rmv_inner, // like bool_op_ex_slice_inside, but remove inner contours
- bool_op_ex_slice_outside_rmv_inner, // like bool_op_ex_slice_outside, but remove inner contours
- bool_op_ex_count
+ void doEffect(SPCurve *curve);
+ virtual void resetDefaults(SPItem const *item);
+
+ enum bool_op_ex {
+ bool_op_ex_union = bool_op_union,
+ bool_op_ex_inters = bool_op_inters,
+ bool_op_ex_diff = bool_op_diff,
+ bool_op_ex_symdiff = bool_op_symdiff,
+ bool_op_ex_cut = bool_op_cut,
+ bool_op_ex_slice = bool_op_slice,
+ bool_op_ex_slice_inside, // like bool_op_slice, but leaves only the contour pieces inside of the cut path
+ bool_op_ex_slice_outside, // like bool_op_slice, but leaves only the contour pieces outside of the cut path
+ bool_op_ex_count
};
- inline friend bool_op to_bool_op( bool_op_ex val )
+ inline friend bool_op to_bool_op(bool_op_ex val)
{
- assert( val<=bool_op_ex_slice );
- (bool_op) val;
+ assert(val <= bool_op_ex_slice);
+ (bool_op) val;
}
private:
- LPEBool(const LPEBool&);
- LPEBool& operator=(const LPEBool&);
+ LPEBool(const LPEBool &);
+ LPEBool &operator=(const LPEBool &);
OriginalPathParam operand_path;
EnumParam<bool_op_ex> bool_operation;
EnumParam<fill_typ> fill_type_this;
EnumParam<fill_typ> fill_type_operand;
BoolParam swap_operands;
+ BoolParam rmv_inner;
};
}; //namespace LivePathEffect
diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp
index c13cffb6a..9f3070ff4 100644
--- a/src/live_effects/lpe-mirror_symmetry.cpp
+++ b/src/live_effects/lpe-mirror_symmetry.cpp
@@ -6,36 +6,84 @@
* Maximilian Albert
* Johan Engelen
* Abhishek Sharma
+ * Jabiertxof
*
* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
* Copyright (C) Maximilin Albert 2008 <maximilian.albert@gmail.com>
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-
+#include <gtkmm.h>
#include <glibmm/i18n.h>
#include "live_effects/lpe-mirror_symmetry.h"
#include <sp-path.h>
#include <display/curve.h>
#include <svg/path-string.h>
-
+#include "helper/geom.h"
#include <2geom/path.h>
+#include <2geom/path-intersection.h>
#include <2geom/transforms.h>
#include <2geom/affine.h>
+#include "knot-holder-entity.h"
+#include "knotholder.h"
+#include "inkscape.h"
namespace Inkscape {
namespace LivePathEffect {
+static const Util::EnumData<ModeType> ModeTypeData[MT_END] = {
+ { MT_V, N_("Vertical Page Center"), "Vertical Page Center, use select tool to move item instead line" },
+ { MT_H, N_("Horizontal Page Center"), "Horizontal Page Center, use select tool to move item instead line" },
+ { MT_FREE, N_("Free from reflection line"), "Free from path" },
+ { MT_X, N_("X from middle knot"), "X from middle knot" },
+ { MT_Y, N_("Y from middle knot"), "Y from middle knot" }
+};
+static const Util::EnumDataConverter<ModeType>
+MTConverter(ModeTypeData, MT_END);
+
+namespace MS {
+
+class KnotHolderEntityCenterMirrorSymmetry : public LPEKnotHolderEntity {
+public:
+ KnotHolderEntityCenterMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){};
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+};
+
+class KnotHolderEntityStartMirrorSymmetry : public LPEKnotHolderEntity {
+public:
+ KnotHolderEntityStartMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){};
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+};
+
+class KnotHolderEntityEndMirrorSymmetry : public LPEKnotHolderEntity {
+public:
+ KnotHolderEntityEndMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){};
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+};
+
+} // namespace MS
+
LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
+ mode(_("Mode"), _("Symmetry move mode"), "mode", MTConverter, &wr, this, MT_FREE),
discard_orig_path(_("Discard original path?"), _("Check this to only keep the mirrored part of the path"), "discard_orig_path", &wr, this, false),
- reflection_line(_("Reflection line:"), _("Line which serves as 'mirror' for the reflection"), "reflection_line", &wr, this, "M0,0 L100,100")
+ fuse_paths(_("Fuse paths"), _("Fuse original and the reflection into a single path"), "fuse_paths", &wr, this, false),
+ oposite_fuse(_("Opposite fuse"), _("Picks the other side of the mirror as the original"), "oposite_fuse", &wr, this, false),
+ start_point(_("Start mirror line"), _("Start mirror line"), "start_point", &wr, this, "Adjust the start of mirroring"),
+ end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, "Adjust end of mirroring")
{
show_orig_path = true;
+ registerParameter(&mode);
+ registerParameter( &discard_orig_path);
+ registerParameter( &fuse_paths);
+ registerParameter( &oposite_fuse);
+ registerParameter( &start_point);
+ registerParameter( &end_point);
apply_to_clippath_and_mask = true;
- registerParameter( dynamic_cast<Parameter *>(&discard_orig_path) );
- registerParameter( dynamic_cast<Parameter *>(&reflection_line) );
}
LPEMirrorSymmetry::~LPEMirrorSymmetry()
@@ -43,60 +91,276 @@ LPEMirrorSymmetry::~LPEMirrorSymmetry()
}
void
+
+LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem)
+{
+ using namespace Geom;
+
+ Point point_a(boundingbox_X.max(), boundingbox_Y.min());
+ Point point_b(boundingbox_X.max(), boundingbox_Y.max());
+ Point point_c(boundingbox_X.max(), boundingbox_Y.middle());
+ if (mode == MT_Y) {
+ point_a = Geom::Point(boundingbox_X.min(),center_point[Y]);
+ point_b = Geom::Point(boundingbox_X.max(),center_point[Y]);
+ }
+ if (mode == MT_X) {
+ point_a = Geom::Point(center_point[X],boundingbox_Y.min());
+ point_b = Geom::Point(center_point[X],boundingbox_Y.max());
+ }
+ line_separation.setPoints(point_a, point_b);
+ if ( mode == MT_X || mode == MT_Y ) {
+ start_point.param_setValue(point_a);
+ end_point.param_setValue(point_b);
+ center_point = Geom::middle_point(point_a, point_b);
+ } else if ( mode == MT_FREE) {
+ if(!are_near(previous_center,center_point, 0.01)) {
+ Geom::Point trans = center_point - previous_center;
+ start_point.param_setValue(start_point * trans);
+ end_point.param_setValue(end_point * trans);
+ line_separation.setPoints(start_point, end_point);
+ } else {
+ center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point);
+ line_separation.setPoints(start_point, end_point);
+ }
+ } else if ( mode == MT_V){
+ if(SP_ACTIVE_DESKTOP){
+ SPDocument * doc = SP_ACTIVE_DESKTOP->getDocument();
+ Geom::Rect view_box_rect = doc->getViewBox();
+ Geom::Point sp = Geom::Point(view_box_rect.width()/2.0, 0);
+ sp *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse();
+ start_point.param_setValue(sp);
+ Geom::Point ep = Geom::Point(view_box_rect.width()/2.0, view_box_rect.height());
+ ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse();
+ end_point.param_setValue(ep);
+ center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point);
+ line_separation.setPoints(start_point, end_point);
+ }
+ } else { //horizontal page
+ if(SP_ACTIVE_DESKTOP){
+ SPDocument * doc = SP_ACTIVE_DESKTOP->getDocument();
+ Geom::Rect view_box_rect = doc->getViewBox();
+ Geom::Point sp = Geom::Point(0, view_box_rect.height()/2.0);
+ sp *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse();
+ start_point.param_setValue(sp);
+ Geom::Point ep = Geom::Point(view_box_rect.width(), view_box_rect.height()/2.0);
+ ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse();
+ end_point.param_setValue(ep);
+ center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point);
+ line_separation.setPoints(start_point, end_point);
+ }
+ }
+ previous_center = center_point;
+}
+
+void
LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem)
{
using namespace Geom;
- // fixme: what happens if the bbox is empty?
- // fixme: this is probably wrong
- Geom::Affine t = lpeitem->i2dt_affine();
- Geom::Rect bbox = *lpeitem->desktopVisualBounds();
-
- Point A(bbox.left(), bbox.bottom());
- Point B(bbox.left(), bbox.top());
- A *= t;
- B *= t;
- Piecewise<D2<SBasis> > rline = Piecewise<D2<SBasis> >(D2<SBasis>(SBasis(A[X], B[X]), SBasis(A[Y], B[Y])));
- reflection_line.set_new_value(rline, true);
+ original_bbox(lpeitem);
+
+ Point point_a(boundingbox_X.max(), boundingbox_Y.min());
+ Point point_b(boundingbox_X.max(), boundingbox_Y.max());
+ Point point_c(boundingbox_X.max(), boundingbox_Y.middle());
+ start_point.param_setValue(point_a);
+ start_point.param_update_default(point_a);
+ end_point.param_setValue(point_b);
+ end_point.param_update_default(point_b);
+ center_point = point_c;
+ previous_center = center_point;
}
+
Geom::PathVector
LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
{
- // Don't allow empty path parameter:
- if ( reflection_line.get_pathvector().empty() ) {
- return path_in;
- }
-
+ Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in);
Geom::PathVector path_out;
- if (!discard_orig_path) {
- path_out = path_in;
+
+ if (!discard_orig_path && !fuse_paths) {
+ path_out = pathv_to_linear_and_cubic_beziers(path_in);
}
- Geom::PathVector mline(reflection_line.get_pathvector());
- Geom::Point A(mline.front().initialPoint());
- Geom::Point B(mline.back().finalPoint());
+ Geom::Point point_a(line_separation.initialPoint());
+ Geom::Point point_b(line_separation.finalPoint());
- Geom::Affine m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]);
- double hyp = Geom::distance(A, B);
- double c = (B[0] - A[0]) / hyp; // cos(alpha)
- double s = (B[1] - A[1]) / hyp; // sin(alpha)
+ Geom::Translate m1(point_a[0], point_a[1]);
+ double hyp = Geom::distance(point_a, point_b);
+ double c = (point_b[0] - point_a[0]) / hyp; // cos(alpha)
+ double s = (point_b[1] - point_a[1]) / hyp; // sin(alpha)
Geom::Affine m2(c, -s, s, c, 0.0, 0.0);
- Geom::Affine sca(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
+ Geom::Scale sca(1.0, -1.0);
Geom::Affine m = m1.inverse() * m2;
m = m * sca;
m = m * m2.inverse();
m = m * m1;
- for (int i = 0; i < static_cast<int>(path_in.size()); ++i) {
- path_out.push_back(path_in[i] * m);
+ if (fuse_paths && !discard_orig_path) {
+ for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
+ path_it != original_pathv.end(); ++path_it)
+ {
+ if (path_it->empty()) {
+ continue;
+ }
+ Geom::PathVector tmp_path;
+ double time_start = 0.0;
+ int position = 0;
+ bool end_open = false;
+ if (path_it->closed()) {
+ const Geom::Curve &closingline = path_it->back_closed();
+ if (!are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ end_open = true;
+ }
+ }
+ Geom::Path original = *path_it;
+ if (end_open && path_it->closed()) {
+ original.close(false);
+ original.appendNew<Geom::LineSegment>( original.initialPoint() );
+ original.close(true);
+ }
+ Geom::Point s = start_point;
+ Geom::Point e = end_point;
+ double dir = line_separation.angle();
+ double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
+ Geom::Rect bbox(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
+ double size_divider = Geom::distance(center_point, bbox) + diagonal;
+ s = Geom::Point::polar(dir,size_divider) + center_point;
+ e = Geom::Point::polar(dir + Geom::rad_from_deg(180),size_divider) + center_point;
+ Geom::Path divider = Geom::Path(s);
+ divider.appendNew<Geom::LineSegment>(e);
+ Geom::Crossings cs = crossings(original, divider);
+ std::vector<double> crossed;
+ for(unsigned int i = 0; i < cs.size(); i++) {
+ crossed.push_back(cs[i].ta);
+ }
+ std::sort(crossed.begin(), crossed.end());
+ for (unsigned int i = 0; i < crossed.size(); i++) {
+ double time_end = crossed[i];
+ if (time_start != time_end && time_end - time_start > Geom::EPSILON) {
+ Geom::Path portion = original.portion(time_start, time_end);
+ if (!portion.empty()) {
+ Geom::Point middle = portion.pointAt((double)portion.size()/2.0);
+ position = Geom::sgn(Geom::cross(e - s, middle - s));
+ if (!oposite_fuse) {
+ position *= -1;
+ }
+ if (position == 1) {
+ Geom::Path mirror = portion.reversed() * m;
+ mirror.setInitial(portion.finalPoint());
+ portion.append(mirror);
+ if(i!=0) {
+ portion.setFinal(portion.initialPoint());
+ portion.close();
+ }
+ tmp_path.push_back(portion);
+ }
+ portion.clear();
+ }
+ }
+ time_start = time_end;
+ }
+ position = Geom::sgn(Geom::cross(e - s, original.finalPoint() - s));
+ if (!oposite_fuse) {
+ position *= -1;
+ }
+ if (cs.size()!=0 && position == 1) {
+ if (time_start != original.size() && original.size() - time_start > Geom::EPSILON) {
+ Geom::Path portion = original.portion(time_start, original.size());
+ if (!portion.empty()) {
+ portion = portion.reversed();
+ Geom::Path mirror = portion.reversed() * m;
+ mirror.setInitial(portion.finalPoint());
+ portion.append(mirror);
+ portion = portion.reversed();
+ if (!original.closed()) {
+ tmp_path.push_back(portion);
+ } else {
+ if (cs.size() > 1 && tmp_path.size() > 0 && tmp_path[0].size() > 0 ) {
+ portion.setFinal(tmp_path[0].initialPoint());
+ portion.setInitial(tmp_path[0].finalPoint());
+ tmp_path[0].append(portion);
+ } else {
+ tmp_path.push_back(portion);
+ }
+ tmp_path[0].close();
+ }
+ portion.clear();
+ }
+ }
+ }
+ if (cs.size() == 0 && position == 1) {
+ tmp_path.push_back(original);
+ tmp_path.push_back(original * m);
+ }
+ path_out.insert(path_out.end(), tmp_path.begin(), tmp_path.end());
+ tmp_path.clear();
+ }
+ }
+
+ if (!fuse_paths || discard_orig_path) {
+ for (int i = 0; i < static_cast<int>(path_in.size()); ++i) {
+ path_out.push_back(path_in[i] * m);
+ }
}
return path_out;
}
+void
+LPEMirrorSymmetry::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ using namespace Geom;
+ hp_vec.clear();
+ Geom::Path path;
+ Geom::Point s = start_point;
+ Geom::Point e = end_point;
+ path.start( s );
+ path.appendNew<Geom::LineSegment>( e );
+ Geom::PathVector helper;
+ helper.push_back(path);
+ hp_vec.push_back(helper);
+}
+
+void
+LPEMirrorSymmetry::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
+{
+ SPKnotShapeType knot_shape = SP_KNOT_SHAPE_CIRCLE;
+ SPKnotModeType knot_mode = SP_KNOT_MODE_XOR;
+ guint32 knot_color = 0x0000ff00;
+ {
+ KnotHolderEntity *c = new MS::KnotHolderEntityCenterMirrorSymmetry(this);
+ c->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
+ _("Adjust the center"), knot_shape, knot_mode, knot_color );
+ knotholder->add(c);
+ }
+};
+
+namespace MS {
+
+using namespace Geom;
+
+void
+KnotHolderEntityCenterMirrorSymmetry::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
+{
+ LPEMirrorSymmetry* lpe = dynamic_cast<LPEMirrorSymmetry *>(_effect);
+ Geom::Point const s = snap_knot_position(p, state);
+ lpe->center_point = s;
+
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
+}
+
+Geom::Point
+KnotHolderEntityCenterMirrorSymmetry::knot_get() const
+{
+ LPEMirrorSymmetry const *lpe = dynamic_cast<LPEMirrorSymmetry const*>(_effect);
+ return lpe->center_point;
+}
+
+} // namespace CR
+
} //namespace LivePathEffect
} /* namespace Inkscape */
diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h
index 64a72d7b3..3a244cb7e 100644
--- a/src/live_effects/lpe-mirror_symmetry.h
+++ b/src/live_effects/lpe-mirror_symmetry.h
@@ -8,6 +8,7 @@
* Authors:
* Maximilian Albert
* Johan Engelen
+ * Jabiertxof
*
* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
* Copyright (C) Maximilin Albert 2008 <maximilian.albert@gmail.com>
@@ -19,22 +20,50 @@
#include "live_effects/parameter/parameter.h"
#include "live_effects/parameter/point.h"
#include "live_effects/parameter/path.h"
+#include "live_effects/parameter/enum.h"
+#include "live_effects/lpegroupbbox.h"
namespace Inkscape {
namespace LivePathEffect {
-class LPEMirrorSymmetry : public Effect {
+namespace MS {
+// we need a separate namespace to avoid clashes with LPEPerpBisector
+class KnotHolderEntityCenterMirrorSymmetry;
+}
+
+enum ModeType {
+ MT_V,
+ MT_H,
+ MT_FREE,
+ MT_X,
+ MT_Y,
+ MT_END
+};
+
+class LPEMirrorSymmetry : public Effect, GroupBBoxEffect {
public:
LPEMirrorSymmetry(LivePathEffectObject *lpeobject);
virtual ~LPEMirrorSymmetry();
-
virtual void doOnApply (SPLPEItem const* lpeitem);
-
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in);
+ /* the knotholder entity classes must be declared friends */
+ friend class MS::KnotHolderEntityCenterMirrorSymmetry;
+ void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
+
+protected:
+ virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec);
private:
+ EnumParam<ModeType> mode;
BoolParam discard_orig_path;
- PathParam reflection_line;
+ BoolParam fuse_paths;
+ BoolParam oposite_fuse;
+ PointParam start_point;
+ PointParam end_point;
+ Geom::Line line_separation;
+ Geom::Point previous_center;
+ Geom::Point center_point;
LPEMirrorSymmetry(const LPEMirrorSymmetry&);
LPEMirrorSymmetry& operator=(const LPEMirrorSymmetry&);
diff --git a/src/main.cpp b/src/main.cpp
index 99e3ccfe6..8cf52127b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -493,7 +493,7 @@ struct poptOption options[] = {
POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
N_("Remove unused definitions from the defs section(s) of the document"),
NULL},
-
+
#ifdef WITH_DBUS
{"dbus-listen", 0,
POPT_ARG_NONE, &sp_dbus_listen, SP_ARG_DBUS_LISTEN,
@@ -551,7 +551,7 @@ static void _win32_set_inkscape_env(gchar const *exe)
gchar *perl = g_build_filename(exe, "python", NULL);
gchar *pythonlib = g_build_filename(exe, "python", "Lib", NULL);
gchar *pythondll = g_build_filename(exe, "python", "DLLs", NULL);
-
+
// Python 2.x needs short paths in PYTHONPATH.
// Otherwise it doesn't work when Inkscape is installed in Unicode directories.
// g_win32_locale_filename_from_utf8 is the GLib wrapper for GetShortPathName.
@@ -602,14 +602,14 @@ static void _win32_set_inkscape_env(gchar const *exe)
g_free(perl);
g_free(pythonlib);
g_free(pythondll);
-
+
g_free(python_s);
g_free(pythonlib_s);
g_free(pythondll_s);
g_free(new_path);
g_free(new_pythonpath);
-
+
g_free(localepath);
}
#endif
@@ -619,7 +619,7 @@ static void set_extensions_env()
gchar const *pythonpath = g_getenv("PYTHONPATH");
gchar *extdir;
gchar *new_pythonpath;
-
+
#ifdef WIN32
extdir = g_win32_locale_filename_from_utf8(INKSCAPE_EXTENSIONDIR);
#else
@@ -905,7 +905,7 @@ static int sp_common_main( int argc, char const **argv, GSList **flDest )
if ( sp_global_printer )
sp_global_printer_utf8 = g_strdup( sp_global_printer );
}
-
+
#ifdef WITH_DBUS
// Before initializing extensions, we must set the DBus bus name if required
if (sp_dbus_name != NULL) {
@@ -1064,25 +1064,56 @@ sp_main_gui(int argc, char const **argv)
Glib::ustring inkscape_style = INKSCAPE_UIDIR;
inkscape_style += "/style.css";
// std::cout << "CSS Stylesheet Inkscape: " << inkscape_style << std::endl;
- Glib::RefPtr<Gtk::CssProvider> provider = Gtk::CssProvider::create();
- try {
- provider->load_from_path (inkscape_style);
- }
- catch (const Gtk::CssProviderError& ex)
- {
- std::cerr << "CSSProviderError::load_from_path(): failed to load: " << inkscape_style << "\n (" << ex.what() << ")" << std::endl;
+
+ if (g_file_test (inkscape_style.c_str(), G_FILE_TEST_EXISTS)) {
+ Glib::RefPtr<Gtk::CssProvider> provider = Gtk::CssProvider::create();
+
+ // From 3.16, throws an error which we must catch.
+ try {
+ provider->load_from_path (inkscape_style);
+ }
+#if GTK_CHECK_VERSION(3,16,0)
+ // Gtk::CssProviderError not defined until 3.16.
+ catch (const Gtk::CssProviderError& ex)
+ {
+ std::cerr << "CSSProviderError::load_from_path(): failed to load: " << inkscape_style
+ << "\n (" << ex.what() << ")" << std::endl;
+ }
+#else
+ catch (...)
+ {}
+#endif
+
+ Gtk::StyleContext::add_provider_for_screen (screen, provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ } else {
+ std::cerr << "sp_main_gui: Cannot find default style file:\n (" << inkscape_style
+ << ")" << std::endl;
}
- Gtk::StyleContext::add_provider_for_screen (screen, provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
Glib::ustring user_style = Inkscape::Application::profile_path("ui/style.css");
// std::cout << "CSS Stylesheet User: " << user_style << std::endl;
- Glib::RefPtr<Gtk::CssProvider> provider2 = Gtk::CssProvider::create();
- try {
- provider2->load_from_path (user_style);
+
+ if (g_file_test (user_style.c_str(), G_FILE_TEST_EXISTS)) {
+ Glib::RefPtr<Gtk::CssProvider> provider2 = Gtk::CssProvider::create();
+
+ // From 3.16, throws an error which we must catch.
+ try {
+ provider2->load_from_path (user_style);
+ }
+#if GTK_CHECK_VERSION(3,16,0)
+ // Gtk::CssProviderError not defined until 3.16.
+ catch (const Gtk::CssProviderError& ex)
+ {
+ std::cerr << "CSSProviderError::load_from_path(): failed to load: " << user_style
+ << "\n (" << ex.what() << ")" << std::endl;
+ }
+#else
+ catch (...)
+ {}
+#endif
+
+ Gtk::StyleContext::add_provider_for_screen (screen, provider2, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
- catch (const Gtk::CssProviderError& ex)
- {}
- Gtk::StyleContext::add_provider_for_screen (screen, provider2, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
#endif
gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
@@ -1168,7 +1199,7 @@ static int sp_process_file_list(GSList *fl)
if (sp_vacuum_defs) {
doc->vacuumDocument();
}
-
+
// Execute command-line actions (selections and verbs) using our local models
bool has_performed_actions = Inkscape::CmdLineAction::doList(INKSCAPE.active_action_context());
@@ -1679,9 +1710,9 @@ static int sp_do_export_png(SPDocument *doc)
g_print("Background RRGGBBAA: %08x\n", bgcolor);
g_print("Area %g:%g:%g:%g exported to %lu x %lu pixels (%g dpi)\n", area[Geom::X][0], area[Geom::Y][0], area[Geom::X][1], area[Geom::Y][1], width, height, dpi);
-
+
reverse(items.begin(),items.end());
-
+
if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) {
if( sp_export_png_file(doc, path.c_str(), area, width, height, dpi,
dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : std::vector<SPItem*>()) == 1 ) {
@@ -1851,7 +1882,7 @@ static int do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
}
/**
- * Export a document to EMF or WMF
+ * Export a document to EMF or WMF
*
* \param doc Document to export.
* \param uri URI to export to.
diff --git a/src/profile-manager.cpp b/src/profile-manager.cpp
index 035aa6051..26e1cd72c 100644
--- a/src/profile-manager.cpp
+++ b/src/profile-manager.cpp
@@ -34,9 +34,8 @@ void ProfileManager::_resourcesChanged()
{
std::vector<SPObject*> newList;
if (_doc) {
- std::set<SPObject *> current = _doc->getResourceList( "iccprofile" );
- for (std::set<SPObject *>::const_iterator i = current.begin(); i != current.end(); ++i)
- newList.push_back(*i);
+ std::vector<SPObject *> current = _doc->getResourceList( "iccprofile" );
+ newList = current;
}
sort( newList.begin(), newList.end() );
diff --git a/src/pure-transform.cpp b/src/pure-transform.cpp
index 9c7054b9f..db4926258 100644
--- a/src/pure-transform.cpp
+++ b/src/pure-transform.cpp
@@ -63,9 +63,9 @@ void PureTransform::snap(::SnapManager *sm, std::vector<Inkscape::SnapCandidateP
(*j).setSourceNum(0);
first_free_snap = false;
}
+
Inkscape::SnappedPoint snapped_point = snap(sm, *j, (*i).getPoint(), bbox); // Calls the snap() method of the derived classes
- // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl;
snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint()));
/*Find the transformation that describes where the snapped point has
@@ -85,16 +85,22 @@ void PureTransform::snap(::SnapManager *sm, std::vector<Inkscape::SnapCandidateP
// We might still need to apply a constraint though, if we tried a constrained snap. And
// in case of a free snap we might have use for the transformed point, so let's return that
// point, whether it's constrained or not
- if (best_snapped_point.isOtherSnapBetter(snapped_point, true) || points.size() == 1) {
- // .. so we must keep track of the best non-snapped constrained point
+
+ if (best_snapped_point.isOtherSnapBetter(snapped_point, true) ) {
+ // .. so we must keep track of the best non-snapped constrained point.. but what
+ // is the best? There is no best, or is there? We cannot compare on snapped distance
+ // because neither has snapped, and both have their snapped distance set to infinity.
+ // There might be a difference in "constrainedness" though, 1D vs 2D snapping
store_best_snap = true;
}
}
}
- if (store_best_snap) {
+ if (store_best_snap || i == points.begin()) {
best_original_point = (*i);
- best_snapped_point = snapped_point;
+ best_snapped_point = snapped_point; // Can be a point that didn't snap, but then at least we
+ // return something meaningful; we might have use for the transformation. The default
+ // snapped_point, as initialized before this loop, is not very meaningful at all.
}
++j;
@@ -119,7 +125,7 @@ Geom::Point PureTranslate::getTransformedPoint(SnapCandidatePoint const &p) cons
return p.getPoint() + _vector;
}
-void PureTranslate::storeTransform(SnapCandidatePoint const original_point, SnappedPoint const snapped_point) {
+void PureTranslate::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) {
/* Consider the case in which a box is almost aligned with a grid in both
* horizontal and vertical directions. The distance to the intersection of
* the grid lines will always be larger then the distance to a single grid
@@ -156,7 +162,7 @@ Geom::Point PureScale::getTransformedPoint(SnapCandidatePoint const &p) const {
return (p.getPoint() - _origin) * _scale + _origin;
}
-void PureScale::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) {
+void PureScale::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) {
_scale_snapped = Geom::Scale(Geom::infinity(), Geom::infinity());
// If this point *i is horizontally or vertically aligned with
// the origin of the scaling, then it will scale purely in X or Y
@@ -174,6 +180,14 @@ void PureScale::storeTransform(SnapCandidatePoint const original_point, SnappedP
// we might have left result[1-index] = Geom::infinity() if scaling didn't occur in the other direction
}
}
+
+ if (_scale_snapped == Geom::Scale(Geom::infinity(), Geom::infinity())) {
+ // This point must have been at the origin, so we cannot possibly snap; it won't scale (i.e. won't move while dragging)
+ snapped_point.setSnapDistance(Geom::infinity());
+ snapped_point.setSecondSnapDistance(Geom::infinity());
+ return;
+ }
+
if (_uniform) {
// Lock the scaling the be uniform, but keep the sign such that we don't change which quadrant we have dragged into
if (fabs(_scale_snapped[0]) < fabs(_scale_snapped[1])) {
@@ -253,16 +267,16 @@ SnappedPoint PureStretchConstrained::snap(::SnapManager *sm, SnapCandidatePoint
return sm->constrainedSnap(p, dedicated_constraint, bbox_to_snap);
}
-void PureStretchConstrained::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) {
+void PureStretchConstrained::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) {
Geom::Point const a = snapped_point.getPoint() - _origin; // vector to snapped point
Geom::Point const b = original_point.getPoint() - _origin; // vector to original point (not the transformed point!)
_stretch_snapped = Geom::Scale(Geom::infinity(), Geom::infinity());
- if (fabs(b[_direction]) > 1e-6) { // if STRETCHING will occur for this point
+ if (fabs(b[_direction]) > 1e-4) { // if STRETCHING will occur for this point
_stretch_snapped[_direction] = a[_direction] / b[_direction];
_stretch_snapped[1-_direction] = _uniform ? _stretch_snapped[_direction] : 1;
} else { // STRETCHING might occur for this point, but only when the stretching is uniform
- if (_uniform && fabs(b[1-_direction]) > 1e-6) {
+ if (_uniform && fabs(b[1-_direction]) > 1e-4) {
_stretch_snapped[1-_direction] = a[1-_direction] / b[1-_direction];
_stretch_snapped[_direction] = _stretch_snapped[1-_direction];
}
@@ -304,7 +318,7 @@ SnappedPoint PureSkewConstrained::snap(::SnapManager *sm, SnapCandidatePoint con
return sm->constrainedSnap(p, Inkscape::Snapper::SnapConstraint(constraint_vector), bbox_to_snap);
}
-void PureSkewConstrained::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) {
+void PureSkewConstrained::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) {
Geom::Point const b = original_point.getPoint() - _origin; // vector to original point (not the transformed point!)
_skew_snapped = (snapped_point.getPoint()[_direction] - (original_point.getPoint())[_direction]) / b[1 - _direction]; // skew factor
@@ -335,7 +349,7 @@ SnappedPoint PureRotateConstrained::snap(::SnapManager *sm, SnapCandidatePoint c
return sm->constrainedSnap(p, dedicated_constraint, bbox_to_snap);
}
-void PureRotateConstrained::storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) {
+void PureRotateConstrained::storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) {
Geom::Point const a = snapped_point.getPoint() - _origin; // vector to snapped point
Geom::Point const b = (original_point.getPoint() - _origin); // vector to original point (not the transformed point!)
// a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b
diff --git a/src/pure-transform.h b/src/pure-transform.h
index f973a95b1..98aa9772a 100644
--- a/src/pure-transform.h
+++ b/src/pure-transform.h
@@ -26,7 +26,7 @@ class PureTransform {
protected:
virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const = 0;
virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const = 0;
- virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point) = 0;
+ virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point) = 0;
public:
//PureTransform();
@@ -48,7 +48,7 @@ protected:
virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const;
virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const;
- virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point);
+ virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point);
public:
// PureTranslate(); // Default constructor
@@ -90,7 +90,7 @@ protected:
virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const;
virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const;
- virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point);
+ virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point);
public:
// PureScale(); // Default constructor
@@ -135,7 +135,7 @@ protected:
virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const;
virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const;
- virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point);
+ virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point);
public:
virtual ~PureStretchConstrained() {};
@@ -172,7 +172,7 @@ protected:
virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const;
Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const;
- virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point);
+ virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point);
public:
virtual ~PureSkewConstrained() {};
@@ -203,7 +203,7 @@ protected:
virtual SnappedPoint snap(::SnapManager *sm, SnapCandidatePoint const &p, Geom::Point pt_orig, Geom::OptRect const &bbox_to_snap) const;
virtual Geom::Point getTransformedPoint(SnapCandidatePoint const &p) const;
- virtual void storeTransform(SnapCandidatePoint const original_point, SnappedPoint snapped_point);
+ virtual void storeTransform(SnapCandidatePoint const &original_point, SnappedPoint &snapped_point);
public:
// PureRotate(); // Default constructor
diff --git a/src/resource-manager.cpp b/src/resource-manager.cpp
index 18d7c6ba2..09b9364c6 100644
--- a/src/resource-manager.cpp
+++ b/src/resource-manager.cpp
@@ -179,8 +179,8 @@ std::vector<Glib::ustring> ResourceManagerImpl::findBrokenLinks( SPDocument *doc
std::set<Glib::ustring> uniques;
if ( doc ) {
- std::set<SPObject *> images = doc->getResourceList("image");
- for (std::set<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) {
+ std::vector<SPObject *> images = doc->getResourceList("image");
+ for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) {
Inkscape::XML::Node *ir = (*it)->getRepr();
gchar const *href = ir->attribute("xlink:href");
@@ -306,8 +306,8 @@ bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc)
bool savedUndoState = DocumentUndo::getUndoSensitive(doc);
DocumentUndo::setUndoSensitive(doc, true);
- std::set<SPObject *> images = doc->getResourceList("image");
- for (std::set<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) {
+ std::vector<SPObject *> images = doc->getResourceList("image");
+ for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) {
Inkscape::XML::Node *ir = (*it)->getRepr();
gchar const *href = ir->attribute("xlink:href");
diff --git a/src/sp-flowtext.h b/src/sp-flowtext.h
index 9e6046469..9ee676893 100644
--- a/src/sp-flowtext.h
+++ b/src/sp-flowtext.h
@@ -49,6 +49,11 @@ public:
bool _optimizeScaledText;
+ /** Converts the text object to its component curves */
+ SPCurve *getNormalizedBpath() const {
+ return layout.convertToCurves();
+ }
+
/** Optimize scaled flow text on next set_transform. */
void optimizeScaledText()
{_optimizeScaledText = true;}
diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp
index 17a1a9ff1..c80fc7122 100644
--- a/src/sp-guide.cpp
+++ b/src/sp-guide.cpp
@@ -264,7 +264,7 @@ void sp_guide_create_guides_around_page(SPDesktop *dt)
void sp_guide_delete_all_guides(SPDesktop *dt)
{
SPDocument *doc=dt->getDocument();
- std::set<SPObject *> current = doc->getResourceList("guide");
+ std::vector<SPObject *> current = doc->getResourceList("guide");
while (!current.empty()){
SPGuide* guide = SP_GUIDE(*(current.begin()));
sp_guide_remove(guide);
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index c37df151c..1bc6da3e1 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -1776,11 +1776,14 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset)
SPItem *item = *l;
SPCurve *curve = NULL;
- if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item))
+ if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item) && !SP_IS_FLOWTEXT(item))
continue;
else if (SP_IS_SHAPE(item)) {
curve = SP_SHAPE(item)->getCurve();
}
+ else if (SP_IS_FLOWTEXT(item)) {
+ curve = SP_FLOWTEXT(item)->getNormalizedBpath();
+ }
else { // Item must be SP_TEXT
curve = SP_TEXT(item)->getNormalizedBpath();
}
diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp
index 6603d5c69..34cdb92e3 100644
--- a/src/ui/dialog/color-item.cpp
+++ b/src/ui/dialog/color-item.cpp
@@ -571,6 +571,8 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS
widget = lbl;
} else {
GtkWidget* eekWidget = eek_preview_new();
+ gtk_widget_set_name( eekWidget, "ColorItemPreview" );
+
EekPreview * preview = EEK_PREVIEW(eekWidget);
Gtk::Widget* newBlot = Glib::wrap(eekWidget);
_regenPreview(preview);
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index c2c5c5005..12eaba72a 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -492,8 +492,8 @@ void DocumentProperties::linkSelectedProfile()
std::vector<std::pair<Glib::ustring, Glib::ustring> > pairs = ColorProfile::getProfileFilesWithNames();
Glib::ustring file = pairs[row].first;
Glib::ustring name = pairs[row].second;
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject* obj = *it;
Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
if (!strcmp(prof->href, file.c_str()))
@@ -532,11 +532,11 @@ void DocumentProperties::linkSelectedProfile()
void DocumentProperties::populate_linked_profiles_box()
{
_LinkedProfilesListStore->clear();
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
if (! current.empty()) {
_emb_profiles_observer.set((*(current.begin()))->parent);
}
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject* obj = *it;
Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
Gtk::TreeModel::Row row = *(_LinkedProfilesListStore->append());
@@ -614,8 +614,8 @@ void DocumentProperties::removeSelectedProfile(){
return;
}
}
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject* obj = *it;
Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
if (!name.compare(prof->name)){
@@ -738,7 +738,7 @@ void DocumentProperties::build_cms()
_LinkedProfilesList.signal_button_release_event().connect_notify(sigc::mem_fun(*this, &DocumentProperties::linked_profiles_list_button_release));
cms_create_popup_menu(_LinkedProfilesList, sigc::mem_fun(*this, &DocumentProperties::removeSelectedProfile));
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "defs" );
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "defs" );
if (!current.empty()) {
_emb_profiles_observer.set((*(current.begin()))->parent);
}
@@ -975,7 +975,7 @@ void DocumentProperties::build_scripting()
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
//TODO: review this observers code:
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
if (! current.empty()) {
_scripts_observer.set((*(current.begin()))->parent);
}
@@ -1190,8 +1190,8 @@ void DocumentProperties::removeExternalScript(){
}
}
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject* obj = *it;
if (obj) {
SPScript* script = dynamic_cast<SPScript *>(obj);
@@ -1268,8 +1268,8 @@ void DocumentProperties::changeEmbeddedScript(){
}
bool voidscript=true;
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject* obj = *it;
if (id == obj->getId()){
@@ -1313,8 +1313,8 @@ void DocumentProperties::editEmbeddedScript(){
}
Inkscape::XML::Document *xml_doc = SP_ACTIVE_DOCUMENT->getReprDoc();
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject* obj = *it;
if (id == obj->getId()){
@@ -1337,13 +1337,13 @@ void DocumentProperties::editEmbeddedScript(){
void DocumentProperties::populate_script_lists(){
_ExternalScriptsListStore->clear();
_EmbeddedScriptsListStore->clear();
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
if (!current.empty()) {
SPObject *obj = *(current.begin());
g_assert(obj != NULL);
_scripts_observer.set(obj->parent);
}
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject* obj = *it;
SPScript* script = dynamic_cast<SPScript *>(obj);
g_assert(script != NULL);
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index ce08ed1f7..d3ad5d1da 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -1591,11 +1591,11 @@ void FilterEffectsDialog::FilterModifier::update_filters()
SPDesktop* desktop = _dialog.getDesktop();
SPDocument* document = desktop->getDocument();
- std::set<SPObject *> filters = document->getResourceList( "filter" );
+ std::vector<SPObject *> filters = document->getResourceList( "filter" );
_model->clear();
- for (std::set<SPObject *>::const_iterator it = filters.begin(); it != filters.end(); ++it) {
+ for (std::vector<SPObject *>::const_iterator it = filters.begin(); it != filters.end(); ++it) {
Gtk::TreeModel::Row row = *_model->append();
SPFilter* f = SP_FILTER(*it);
row[_columns.filter] = f;
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index c7a168dee..30bbd95c9 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -210,8 +210,8 @@ void InkscapePreferences::AddBaseSimplifySpinbutton(DialogPage &p, Glib::ustring
{
PrefSpinButton* sb = Gtk::manage( new PrefSpinButton);
sb->init ( prefs_path + "/base-simplify", 0.0, 100.0, 1.0, 10.0, def_value, false, false);
- p.add_line( false, _("Base simplify:"), *sb, _("on dinamic LPE simplify"),
- _("Base simplify of dinamic LPE based simplify"),
+ p.add_line( false, _("Base simplify:"), *sb, _("on dynamic LPE simplify"),
+ _("Base simplify of dynamic LPE based simplify"),
false );
}
diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp
index 46e045c14..790c0e5fb 100644
--- a/src/ui/dialog/svg-fonts-dialog.cpp
+++ b/src/ui/dialog/svg-fonts-dialog.cpp
@@ -266,10 +266,10 @@ void SvgFontsDialog::update_fonts()
{
SPDesktop* desktop = this->getDesktop();
SPDocument* document = desktop->getDocument();
- std::set<SPObject *> fonts = document->getResourceList( "fonts" );
+ std::vector<SPObject *> fonts = document->getResourceList( "fonts" );
_model->clear();
- for (std::set<SPObject *>::const_iterator it = fonts.begin(); it != fonts.end(); ++it) {
+ for (std::vector<SPObject *>::const_iterator it = fonts.begin(); it != fonts.end(); ++it) {
Gtk::TreeModel::Row row = *_model->append();
SPFont* f = SP_FONT(*it);
row[_columns.spfont] = f;
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 924ebe03d..6577c8d4e 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -171,8 +171,8 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
SPDocument *doc = desktop ? desktop->doc() : 0;
if (doc) {
std::string targetName(bounceTarget->def.descr);
- std::set<SPObject *> gradients = doc->getResourceList("gradient");
- for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ std::vector<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
SPGradient* grad = SP_GRADIENT(*item);
if ( targetName == grad->getId() ) {
editGradientImpl( desktop, grad );
@@ -192,8 +192,8 @@ void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer us
gint index = GPOINTER_TO_INT(userData);
if ( doc && (index >= 0) && (static_cast<guint>(index) < popupItems.size()) ) {
Glib::ustring targetName = popupItems[index];
- std::set<SPObject *> gradients = doc->getResourceList("gradient");
- for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ std::vector<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
SPGradient* grad = SP_GRADIENT(*item);
if ( targetName == grad->getId() ) {
@@ -326,9 +326,9 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g
SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt);
if ( dtw && dtw->desktop ) {
// Pick up all gradients with vectors
- std::set<SPObject *> gradients = (dtw->desktop->doc())->getResourceList("gradient");
+ std::vector<SPObject *> gradients = (dtw->desktop->doc())->getResourceList("gradient");
gint index = 0;
- for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
SPGradient* grad = SP_GRADIENT(*item);
if ( grad->hasStops() && !grad->isSwatch() ) {
//gl = g_slist_prepend(gl, curr->data);
@@ -594,6 +594,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) :
_currentDesktop(0),
_currentDocument(0)
{
+ set_name( "SwatchesPanel" );
Gtk::RadioMenuItem* hotItem = 0;
_holder = new PreviewHolder();
_clear = new ColorItem( ege::PaintDef::CLEAR );
@@ -924,8 +925,8 @@ static void recalcSwatchContents(SPDocument* doc,
std::map<ColorItem*, SPGradient*> &gradMappings)
{
std::vector<SPGradient*> newList;
- std::set<SPObject *> gradients = doc->getResourceList("gradient");
- for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ std::vector<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
SPGradient* grad = SP_GRADIENT(*item);
if ( grad->isSwatch() ) {
newList.push_back(SP_GRADIENT(*item));
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 3e2a2004c..ab29471ed 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -1128,8 +1128,8 @@ sp_ui_drag_data_received(GtkWidget *widget,
unsigned int b = color.getB();
SPGradient* matches = 0;
- std::set<SPObject *> gradients = doc->getResourceList("gradient");
- for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ std::vector<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::vector<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
SPGradient* grad = SP_GRADIENT(*item);
if ( color.descr == grad->getId() ) {
if ( grad->hasStops() ) {
diff --git a/src/ui/previewholder.cpp b/src/ui/previewholder.cpp
index beb83f35c..5e75179a3 100644
--- a/src/ui/previewholder.cpp
+++ b/src/ui/previewholder.cpp
@@ -49,16 +49,20 @@ PreviewHolder::PreviewHolder() :
_wrap(false),
_border(BORDER_NONE)
{
+ set_name( "PreviewHolder" );
_scroller = Gtk::manage(new Gtk::ScrolledWindow());
+ _scroller->set_name( "PreviewHolderScroller" );
((Gtk::ScrolledWindow *)_scroller)->set_policy(Gtk::POLICY_AUTOMATIC,
Gtk::POLICY_AUTOMATIC);
#if WITH_GTKMM_3_0
_insides = Gtk::manage(new Gtk::Grid());
+ _insides->set_name( "PreviewHolderGrid" );
_insides->set_column_spacing(8);
// Add a container with the scroller and a spacer
Gtk::Grid* spaceHolder = Gtk::manage(new Gtk::Grid());
+ spaceHolder->set_name( "PreviewHolderSpaceHolder" );
_scroller->set_hexpand();
_scroller->set_vexpand();
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index 3b25439f3..de071dad3 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -1292,7 +1292,7 @@ double PathManipulator::_bsplineHandlePosition(Handle *h, bool check_other)
line_inside_nodes->moveto(n->position());
line_inside_nodes->lineto(next_node->position());
if(!are_near(h->position(), n->position())){
- pos = Geom::nearest_time(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] + HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment());
+ pos = Geom::nearest_time(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] - HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment());
}
}
if (pos == NO_POWER && check_other){
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index 613857626..c98ecb686 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -43,6 +43,7 @@
#include "snap.h"
#include "sp-path.h"
#include "sp-use.h"
+#include "sp-item-group.h"
#include "sp-namedview.h"
#include "live_effects/lpe-powerstroke.h"
#include "style.h"
@@ -432,7 +433,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){
gchar const *svgd = item->getRepr()->attribute("d");
bend_item = dc->selection->singleItem();
- if(bend_item){
+ if(bend_item && (SP_IS_SHAPE(bend_item) || SP_IS_GROUP(bend_item))){
bend_item->moveTo(item,false);
bend_item->transform.setTranslation(Geom::Point());
spdc_apply_bend_shape(svgd, dc, bend_item);
@@ -440,9 +441,11 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
shape = BEND_CLIPBOARD;
} else {
+ bend_item = NULL;
shape = NONE;
}
} else {
+ bend_item = NULL;
shape = NONE;
}
break;
diff --git a/src/ui/widget/color-icc-selector.cpp b/src/ui/widget/color-icc-selector.cpp
index ec2e69fb3..2e30a48b5 100644
--- a/src/ui/widget/color-icc-selector.cpp
+++ b/src/ui/widget/color-icc-selector.cpp
@@ -687,8 +687,8 @@ void ColorICCSelectorImpl::_profilesChanged(std::string const &name)
gtk_combo_box_set_active(combo, 0);
int index = 1;
- std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile");
- for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ std::vector<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile");
+ for (std::vector<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
SPObject *obj = *it;
Inkscape::ColorProfile *prof = reinterpret_cast<Inkscape::ColorProfile *>(obj);
diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp
index 5bcd16528..62c7cca1d 100644
--- a/src/ui/widget/color-preview.cpp
+++ b/src/ui/widget/color-preview.cpp
@@ -23,6 +23,7 @@ ColorPreview::ColorPreview (guint32 rgba)
{
_rgba = rgba;
set_has_window(false);
+ set_name("ColorPreview");
}
void
diff --git a/src/ui/widget/dock.cpp b/src/ui/widget/dock.cpp
index c5e14d4f0..fda647182 100644
--- a/src/ui/widget/dock.cpp
+++ b/src/ui/widget/dock.cpp
@@ -56,6 +56,7 @@ Dock::Dock(Gtk::Orientation orientation)
#endif
_scrolled_window (Gtk::manage(new Gtk::ScrolledWindow))
{
+ _scrolled_window->set_name("Dock");
#if WITH_GDL_3_6
gtk_orientable_set_orientation(GTK_ORIENTABLE(_gdl_dock_bar),
static_cast<GtkOrientation>(orientation));
diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp
index 2a1fa352b..1a9ce617f 100644
--- a/src/ui/widget/layer-selector.cpp
+++ b/src/ui/widget/layer-selector.cpp
@@ -45,6 +45,7 @@ public:
AlternateIcons(Inkscape::IconSize size, gchar const *a, gchar const *b)
: _a(NULL), _b(NULL)
{
+ set_name("AlternateIcons");
if (a) {
_a = Gtk::manage(sp_icon_get_icon(a, size));
_a->set_no_show_all(true);
@@ -94,6 +95,7 @@ private:
LayerSelector::LayerSelector(SPDesktop *desktop)
: _desktop(NULL), _layer(NULL)
{
+ set_name("LayerSelector");
AlternateIcons *label;
label = Gtk::manage(new AlternateIcons(Inkscape::ICON_SIZE_DECORATION,
diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp
index 5d4a25a68..ab13577d7 100644
--- a/src/ui/widget/panel.cpp
+++ b/src/ui/widget/panel.cpp
@@ -73,6 +73,7 @@ Panel::Panel(Glib::ustring const &label, gchar const *prefs_path,
_action_area(0),
_fillable(0)
{
+ set_name( "InkscapePanel" );
#if WITH_GTKMM_3_0
set_orientation( Gtk::ORIENTATION_VERTICAL );
#endif
@@ -284,7 +285,10 @@ void Panel::_init()
pack_start(_top_bar, false, false);
Gtk::HBox* boxy = Gtk::manage(new Gtk::HBox());
-
+ boxy->set_name( "PanelBoxY" );
+ _contents.set_name( "PanelContents" );
+ _right_bar.set_name( "PanelRightBar" );
+ _top_bar.set_name( "PanelTopBar" );
boxy->pack_start(_contents, true, true);
boxy->pack_start(_right_bar, false, true);
diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp
index 87cf0b8c4..f7fd63f51 100644
--- a/src/ui/widget/selected-style.cpp
+++ b/src/ui/widget/selected-style.cpp
@@ -155,6 +155,7 @@ SelectedStyle::SelectedStyle(bool /*layout*/)
_unit_mis(NULL),
_sw_unit(NULL)
{
+ set_name("SelectedStyle");
_drop[0] = _drop[1] = 0;
_dropEnabled[0] = _dropEnabled[1] = false;
diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp
index fa8543c46..188be705d 100644
--- a/src/ui/widget/style-swatch.cpp
+++ b/src/ui/widget/style-swatch.cpp
@@ -124,6 +124,8 @@ StyleSwatch::StyleSwatch(SPCSSAttr *css, gchar const *main_tip)
#endif
_sw_unit(NULL)
{
+ set_name("StyleSwatch");
+
_label[SS_FILL].set_markup(_("Fill:"));
_label[SS_STROKE].set_markup(_("Stroke:"));
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 1a4fcccf4..164a06910 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -249,7 +249,7 @@ SPDesktopWidget::setMessage (Inkscape::MessageType type, const gchar *message)
gdk_window_process_updates(gtk_widget_get_window(GTK_WIDGET(sb)), TRUE);
}
- gtk_widget_set_tooltip_text (this->select_status_eventbox, gtk_label_get_text (sb));
+ gtk_widget_set_tooltip_text (this->select_status, gtk_label_get_text (sb));
}
Geom::Point
@@ -346,6 +346,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
/* Main table */
#if GTK_CHECK_VERSION(3,0,0)
dtw->vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_name(dtw->vbox, "DesktopMainTable");
#else
dtw->vbox = gtk_vbox_new (FALSE, 0);
#endif
@@ -353,6 +354,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#if GTK_CHECK_VERSION(3,0,0)
dtw->statusbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_name(dtw->statusbar, "DesktopStatusBar");
#else
dtw->statusbar = gtk_hbox_new (FALSE, 0);
#endif
@@ -364,7 +366,6 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
dtw->panels = new SwatchesPanel("/embedded/swatches" /*false*/);
dtw->panels->setOrientation(SP_ANCHOR_SOUTH);
-
#if GTK_CHECK_VERSION(3,0,0)
dtw->panels->set_vexpand(false);
#endif
@@ -374,6 +375,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#if GTK_CHECK_VERSION(3,0,0)
dtw->hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_name(dtw->hbox, "DesktopHbox");
#else
dtw->hbox = gtk_hbox_new(FALSE, 0);
#endif
@@ -404,7 +406,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
Glib::RefPtr<Gtk::CssProvider> guides_lock_style_provider = Gtk::CssProvider::create();
guides_lock_style_provider->load_from_data("GtkWidget { padding-left: 0; padding-right: 0; padding-top: 0; padding-bottom: 0; }");
Gtk::Widget * wnd = Glib::wrap(dtw->guides_lock);
- wnd->set_name("guides_lock");
+ wnd->set_name("LockGuides");
Glib::RefPtr<Gtk::StyleContext> context = wnd->get_style_context();
context->add_provider(guides_lock_style_provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
#endif
@@ -412,6 +414,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
/* Horizontal ruler */
GtkWidget *eventbox = gtk_event_box_new ();
dtw->hruler = sp_ruler_new(GTK_ORIENTATION_HORIZONTAL);
+ gtk_widget_set_name(dtw->hruler, "HorizontalRuler");
dtw->hruler_box = eventbox;
Inkscape::Util::Unit const *pt = unit_table.getUnit("pt");
sp_ruler_set_unit(SP_RULER(dtw->hruler), pt);
@@ -422,13 +425,15 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
g_signal_connect (G_OBJECT (eventbox), "motion_notify_event", G_CALLBACK (sp_dt_hruler_event), dtw);
#if GTK_CHECK_VERSION(3,0,0)
- GtkWidget *tbl = gtk_grid_new();
+ GtkWidget *tbl_wrapper = gtk_grid_new(); // Is this widget really needed?
+ gtk_widget_set_name(tbl_wrapper, "CanvasTableWrapper");
dtw->canvas_tbl = gtk_grid_new();
+ gtk_widget_set_name(dtw->canvas_tbl, "CanvasTable");
gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), dtw->guides_lock, 0, 0, 1, 1);
gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), eventbox, 1, 0, 1, 1);
#else
- GtkWidget *tbl = gtk_table_new(2, 3, FALSE);
+ GtkWidget *tbl_wrapper = gtk_table_new(2, 3, FALSE);
dtw->canvas_tbl = gtk_table_new(3, 3, FALSE);
gtk_table_attach(GTK_TABLE(dtw->canvas_tbl),
@@ -443,11 +448,12 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
0, 0);
#endif
g_signal_connect (G_OBJECT (dtw->guides_lock), "toggled", G_CALLBACK (sp_update_guides_lock), dtw);
- gtk_box_pack_start( GTK_BOX(dtw->hbox), tbl, TRUE, TRUE, 1 );
+ gtk_box_pack_start( GTK_BOX(dtw->hbox), tbl_wrapper, TRUE, TRUE, 1 );
/* Vertical ruler */
eventbox = gtk_event_box_new ();
dtw->vruler = sp_ruler_new(GTK_ORIENTATION_VERTICAL);
+ gtk_widget_set_name(dtw->vruler, "VerticalRuler");
/* Vertical ruler */
dtw->vruler_box = eventbox;
@@ -472,11 +478,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
// Horizontal scrollbar
dtw->hadj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0));
-
-
-
#if GTK_CHECK_VERSION(3,0,0)
dtw->hscrollbar = gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (dtw->hadj));
+ gtk_widget_set_name(dtw->hscrollbar, "HorizontalScrollbar");
gtk_grid_attach(GTK_GRID(dtw->canvas_tbl), dtw->hscrollbar, 1, 2, 1, 1);
dtw->vscrollbar_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
#else
@@ -493,6 +497,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
NULL,
INKSCAPE_ICON("zoom-original"),
_("Zoom drawing if window size changes"));
+ gtk_widget_set_name(dtw->sticky_zoom, "StickyZoom");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dtw->sticky_zoom), prefs->getBool("/options/stickyzoom/value"));
gtk_box_pack_start (GTK_BOX (dtw->vscrollbar_box), dtw->sticky_zoom, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (dtw->sticky_zoom), "toggled", G_CALLBACK (sp_dtw_sticky_zoom_toggled), dtw);
@@ -502,6 +507,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#if GTK_CHECK_VERSION(3,0,0)
dtw->vscrollbar = gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(dtw->vadj));
+ gtk_widget_set_name(dtw->vscrollbar, "VerticalScrollbar");
#else
dtw->vscrollbar = gtk_vscrollbar_new (GTK_ADJUSTMENT (dtw->vadj));
#endif
@@ -529,6 +535,8 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
NULL,
INKSCAPE_ICON("color-management"),
tip );
+ gtk_widget_set_name(dtw->cms_adjust, "CMS_Adjust");
+
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
{
Glib::ustring current = prefs->getString("/options/displayprofile/uri");
@@ -608,9 +616,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
if (create_dock) {
dtw->dock = new Inkscape::UI::Widget::Dock();
-
#if WITH_GTKMM_3_0
Gtk::Paned *paned = new Gtk::Paned();
+ paned->set_name("Canvas_and_Dock");
#else
Gtk::HPaned *paned = new Gtk::HPaned();
#endif
@@ -627,9 +635,9 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#if GTK_CHECK_VERSION(3,0,0)
gtk_widget_set_hexpand(GTK_WIDGET(paned->gobj()), TRUE);
gtk_widget_set_vexpand(GTK_WIDGET(paned->gobj()), TRUE);
- gtk_grid_attach(GTK_GRID(tbl), GTK_WIDGET (paned->gobj()), 1, 1, 1, 1);
+ gtk_grid_attach(GTK_GRID(tbl_wrapper), GTK_WIDGET (paned->gobj()), 1, 1, 1, 1);
#else
- gtk_table_attach (GTK_TABLE (tbl), GTK_WIDGET (paned->gobj()), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ gtk_table_attach (GTK_TABLE (tbl_wrapper), GTK_WIDGET (paned->gobj()), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0);
#endif
@@ -637,17 +645,26 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#if GTK_CHECK_VERSION(3,0,0)
gtk_widget_set_hexpand(GTK_WIDGET(dtw->canvas_tbl), TRUE);
gtk_widget_set_vexpand(GTK_WIDGET(dtw->canvas_tbl), TRUE);
- gtk_grid_attach(GTK_GRID(tbl), GTK_WIDGET (dtw->canvas_tbl), 1, 1, 1, 1);
+ gtk_grid_attach(GTK_GRID(tbl_wrapper), GTK_WIDGET (dtw->canvas_tbl), 1, 1, 1, 1);
#else
- gtk_table_attach (GTK_TABLE (tbl), GTK_WIDGET (dtw->canvas_tbl), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
+ gtk_table_attach (GTK_TABLE (tbl_wrapper), GTK_WIDGET (dtw->canvas_tbl), 1, 2, 1, 2, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 0, 0);
#endif
}
+ // connect scrollbar signals
+ g_signal_connect (G_OBJECT (dtw->hadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw);
+ g_signal_connect (G_OBJECT (dtw->vadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw);
+
+
+ // --------------- Status Tool Bar ------------------//
+
+ // Selected Style (Fill/Stroke/Opacity)
dtw->selected_style = new Inkscape::UI::Widget::SelectedStyle(true);
GtkHBox *ss_ = dtw->selected_style->gobj();
gtk_box_pack_start (GTK_BOX (dtw->statusbar), GTK_WIDGET(ss_), FALSE, FALSE, 0);
+ // Separator
gtk_box_pack_start(GTK_BOX(dtw->statusbar),
#if GTK_CHECK_VERSION(3,0,0)
gtk_separator_new(GTK_ORIENTATION_VERTICAL),
@@ -656,15 +673,39 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#endif
FALSE, FALSE, 0);
- // connect scrollbar signals
- g_signal_connect (G_OBJECT (dtw->hadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw);
- g_signal_connect (G_OBJECT (dtw->vadj), "value-changed", G_CALLBACK (sp_desktop_widget_adjustment_value_changed), dtw);
+ // Layer Selector
+ dtw->layer_selector = new Inkscape::Widgets::LayerSelector(NULL);
+ // FIXME: need to unreference on container destruction to avoid leak
+ dtw->layer_selector->reference();
+ //dtw->layer_selector->set_size_request(-1, SP_ICON_SIZE_BUTTON);
+ gtk_box_pack_start(GTK_BOX(dtw->statusbar), GTK_WIDGET(dtw->layer_selector->gobj()), FALSE, FALSE, 1);
+
+ // Select Status
+ dtw->select_status = gtk_label_new (NULL);
+ gtk_widget_set_name( dtw->select_status, "SelectStatus");
+ gtk_label_set_ellipsize (GTK_LABEL(dtw->select_status), PANGO_ELLIPSIZE_END);
+#if GTK_CHECK_VERSION(3,10,0)
+ gtk_label_set_line_wrap (GTK_LABEL(dtw->select_status), true);
+ gtk_label_set_lines (GTK_LABEL(dtw->select_status), 2);
+#endif
- GtkWidget *statusbar_tail=gtk_statusbar_new();
- gtk_box_pack_end (GTK_BOX (dtw->statusbar), statusbar_tail, FALSE, FALSE, 0);
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign(dtw->select_status, GTK_ALIGN_START);
+#else
+ gtk_misc_set_alignment (GTK_MISC (dtw->select_status), 0.0, 0.5);
+#endif
- // zoom status spinbutton
+ gtk_widget_set_size_request (dtw->select_status, 1, -1);
+
+ // Display the initial welcome message in the statusbar
+ gtk_label_set_markup (GTK_LABEL (dtw->select_status), _("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them."));
+
+ gtk_box_pack_start (GTK_BOX (dtw->statusbar), dtw->select_status, TRUE, TRUE, 0);
+
+
+ // Zoom status spinbutton
dtw->zoom_status = gtk_spin_button_new_with_range (log(SP_DESKTOP_ZOOM_MIN)/log(2), log(SP_DESKTOP_ZOOM_MAX)/log(2), 0.1);
+ gtk_widget_set_name(dtw->zoom_status, "ZoomStatus");
gtk_widget_set_tooltip_text (dtw->zoom_status, _("Zoom"));
gtk_widget_set_size_request (dtw->zoom_status, STATUS_ZOOM_WIDTH, -1);
gtk_entry_set_width_chars (GTK_ENTRY (dtw->zoom_status), 6);
@@ -678,12 +719,14 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
dtw->zoom_update = g_signal_connect (G_OBJECT (dtw->zoom_status), "value_changed", G_CALLBACK (sp_dtw_zoom_value_changed), dtw);
dtw->zoom_update = g_signal_connect (G_OBJECT (dtw->zoom_status), "populate_popup", G_CALLBACK (sp_dtw_zoom_populate_popup), dtw);
- // cursor coordinates
+ // Cursor coordinates
#if GTK_CHECK_VERSION(3,0,0)
dtw->coord_status = gtk_grid_new();
+ gtk_widget_set_name(dtw->coord_status, "CoordinateAndZStatus");
gtk_grid_set_row_spacing(GTK_GRID(dtw->coord_status), 0);
gtk_grid_set_column_spacing(GTK_GRID(dtw->coord_status), 2);
GtkWidget* sep = gtk_separator_new(GTK_ORIENTATION_VERTICAL);
+ gtk_widget_set_name(sep, "CoordinateSeparator");
gtk_grid_attach(GTK_GRID(dtw->coord_status),
GTK_WIDGET(sep),
0, 0, 1, 2);
@@ -697,9 +740,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
GTK_FILL, GTK_FILL, 0, 0);
#endif
- eventbox = gtk_event_box_new ();
- gtk_container_add (GTK_CONTAINER (eventbox), dtw->coord_status);
- gtk_widget_set_tooltip_text (eventbox, _("Cursor coordinates"));
+ gtk_widget_set_tooltip_text (dtw->coord_status, _("Cursor coordinates"));
GtkWidget *label_x = gtk_label_new(_("X:"));
GtkWidget *label_y = gtk_label_new(_("Y:"));
@@ -721,6 +762,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
gtk_label_set_markup( GTK_LABEL(dtw->coord_status_y), "<tt> 0.00 </tt>" );
GtkWidget* label_z = gtk_label_new(_("Z:"));
+ gtk_widget_set_name(label_z, "ZLabel");
#if GTK_CHECK_VERSION(3,0,0)
gtk_widget_set_halign(dtw->coord_status_x, GTK_ALIGN_END);
@@ -739,14 +781,10 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#endif
sp_set_font_size_smaller (dtw->coord_status);
- gtk_box_pack_end (GTK_BOX (statusbar_tail), eventbox, FALSE, FALSE, 1);
- dtw->layer_selector = new Inkscape::Widgets::LayerSelector(NULL);
- // FIXME: need to unreference on container destruction to avoid leak
- dtw->layer_selector->reference();
- //dtw->layer_selector->set_size_request(-1, SP_ICON_SIZE_BUTTON);
- gtk_box_pack_start(GTK_BOX(dtw->statusbar), GTK_WIDGET(dtw->layer_selector->gobj()), FALSE, FALSE, 1);
+ gtk_box_pack_end (GTK_BOX (dtw->statusbar), dtw->coord_status, FALSE, FALSE, 0);
+ // --------------- Color Management ---------------- //
dtw->_tracker = ege_color_prof_tracker_new(GTK_WIDGET(dtw->layer_selector->gobj()));
#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display");
@@ -761,30 +799,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
g_signal_connect( G_OBJECT(dtw->_tracker), "changed", G_CALLBACK(sp_dtw_color_profile_event), dtw );
- dtw->select_status_eventbox = gtk_event_box_new ();
- dtw->select_status = gtk_label_new (NULL);
- gtk_label_set_ellipsize (GTK_LABEL(dtw->select_status), PANGO_ELLIPSIZE_END);
-
-#if GTK_CHECK_VERSION(3,0,0)
- gtk_widget_set_halign(dtw->select_status, GTK_ALIGN_START);
-#else
- gtk_misc_set_alignment (GTK_MISC (dtw->select_status), 0.0, 0.5);
-#endif
-
- gtk_widget_set_size_request (dtw->select_status, 1, -1);
- // display the initial welcome message in the statusbar
- gtk_label_set_markup (GTK_LABEL (dtw->select_status), _("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them."));
- // space label 2 pixels from left edge
- gtk_container_add (GTK_CONTAINER (dtw->select_status_eventbox), dtw->select_status);
-#if GTK_CHECK_VERSION(3,0,0)
- gtk_box_pack_start(GTK_BOX(dtw->statusbar),
- gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0),
- FALSE, FALSE, 2);
-#else
- gtk_box_pack_start (GTK_BOX (dtw->statusbar), gtk_hbox_new(FALSE, 0), FALSE, FALSE, 2);
-#endif
- gtk_box_pack_start (GTK_BOX (dtw->statusbar), dtw->select_status_eventbox, TRUE, TRUE, 0);
-
+ // ------------------ Finish Up -------------------- //
gtk_widget_show_all (dtw->vbox);
gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas));
@@ -1453,6 +1468,7 @@ bool SPDesktopWidget::showInfoDialog( Glib::ustring const &message )
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"%s", message.c_str());
+ gtk_widget_set_name(dialog, "InfoDialog");
gtk_window_set_title( GTK_WINDOW(dialog), _("Note:")); // probably want to take this as a parameter.
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
@@ -1765,6 +1781,7 @@ SPDesktopWidget* SPDesktopWidget::createInstance(SPNamedView *namedview)
dtw->layer_selector->setDesktop(dtw->desktop);
dtw->menubar = sp_ui_main_menubar (dtw->desktop);
+ gtk_widget_set_name(dtw->menubar, "MenuBar");
gtk_widget_show_all (dtw->menubar);
gtk_box_pack_start (GTK_BOX (dtw->vbox), dtw->menubar, FALSE, FALSE, 0);
@@ -1885,8 +1902,8 @@ bool SPDesktopWidget::onFocusInEvent(GdkEventFocus*)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (prefs->getBool("/options/bitmapautoreload/value", true)) {
- std::set<SPObject *> imageList = (desktop->doc())->getResourceList("image");
- for (std::set<SPObject *>::const_iterator it = imageList.begin(); it != imageList.end(); ++it) {
+ std::vector<SPObject *> imageList = (desktop->doc())->getResourceList("image");
+ for (std::vector<SPObject *>::const_iterator it = imageList.begin(); it != imageList.end(); ++it) {
SPImage* image = SP_IMAGE(*it);
sp_image_refresh_if_outdated( image );
}
diff --git a/src/widgets/eraser-toolbar.cpp b/src/widgets/eraser-toolbar.cpp
index 45989936f..bb553f4e6 100644
--- a/src/widgets/eraser-toolbar.cpp
+++ b/src/widgets/eraser-toolbar.cpp
@@ -183,8 +183,8 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb
/* Overlap */
{
InkToggleAction* act = ink_toggle_action_new( "EraserBreakAppart",
- _("Break appart cutted items"),
- _("Break appart cutted itemss"),
+ _("Break apart cut items"),
+ _("Break apart cut items"),
INKSCAPE_ICON("distribute-randomize"),
secondarySize );
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/eraser/break_apart", false) );
diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp
index 858aa05db..a44e9962e 100644
--- a/src/widgets/gradient-toolbar.cpp
+++ b/src/widgets/gradient-toolbar.cpp
@@ -140,8 +140,8 @@ gboolean gr_vector_list(GtkWidget *combo_box, SPDesktop *desktop, bool selection
gtk_list_store_clear(store);
std::vector<SPObject *> gl;
- std::set<SPObject *> gradients = document->getResourceList( "gradient" );
- for (std::set<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) {
+ std::vector<SPObject *> gradients = document->getResourceList( "gradient" );
+ for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) {
SPGradient *grad = SP_GRADIENT(*it);
if ( grad->hasStops() && !grad->isSolid() ) {
gl.push_back(*it);
diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp
index 3aa44c90a..97e65141f 100644
--- a/src/widgets/gradient-vector.cpp
+++ b/src/widgets/gradient-vector.cpp
@@ -298,8 +298,8 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs)
/* Pick up all gradients with vectors */
GSList *gl = NULL;
if (gvs->gr) {
- std::set<SPObject *> gradients = gvs->gr->document->getResourceList("gradient");
- for (std::set<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) {
+ std::vector<SPObject *> gradients = gvs->gr->document->getResourceList("gradient");
+ for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) {
SPGradient* grad = SP_GRADIENT(*it);
if ( grad->hasStops() && (grad->isSwatch() == gvs->swatched) ) {
gl = g_slist_prepend(gl, *it);
diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp
index 602cad3c3..aafa6bd1e 100644
--- a/src/widgets/paint-selector.cpp
+++ b/src/widgets/paint-selector.cpp
@@ -844,8 +844,8 @@ ink_pattern_list_get (SPDocument *source)
return NULL;
GSList *pl = NULL;
- std::set<SPObject *> patterns = source->getResourceList("pattern");
- for (std::set<SPObject *>::const_iterator it = patterns.begin(); it != patterns.end(); ++it) {
+ std::vector<SPObject *> patterns = source->getResourceList("pattern");
+ for (std::vector<SPObject *>::const_iterator it = patterns.begin(); it != patterns.end(); ++it) {
if (SP_PATTERN(*it) == SP_PATTERN(*it)->rootPattern()) { // only if this is a root pattern
pl = g_slist_prepend(pl, *it);
}
diff --git a/src/widgets/ruler.cpp b/src/widgets/ruler.cpp
index bcab535f9..deffd384a 100644
--- a/src/widgets/ruler.cpp
+++ b/src/widgets/ruler.cpp
@@ -168,6 +168,10 @@ sp_ruler_class_init (SPRulerClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+#if GTK_CHECK_VERSION(3,20,0)
+ gtk_widget_class_set_css_name (widget_class, "ruler-widget");
+#endif
+
object_class->dispose = sp_ruler_dispose;
object_class->set_property = sp_ruler_set_property;
object_class->get_property = sp_ruler_get_property;
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 0697ff0fb..f7b5e585f 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -999,6 +999,7 @@ static GtkWidget* toolboxNewCommon( GtkWidget* tb, BarId id, GtkPositionType /*h
gtk_widget_set_sensitive(tb, FALSE);
GtkWidget *hb = gtk_event_box_new(); // A simple, neutral container.
+ gtk_widget_set_name(hb, "ToolboxCommon");
gtk_container_add(GTK_CONTAINER(hb), tb);
gtk_widget_show(GTK_WIDGET(tb));
@@ -1016,6 +1017,7 @@ GtkWidget *ToolboxFactory::createToolToolbox()
{
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_name(tb, "ToolToolbox");
gtk_box_set_homogeneous(GTK_BOX(tb), FALSE);
#else
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
@@ -1028,6 +1030,7 @@ GtkWidget *ToolboxFactory::createAuxToolbox()
{
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_name(tb, "AuxToolbox");
gtk_box_set_homogeneous(GTK_BOX(tb), FALSE);
#else
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
@@ -1044,6 +1047,7 @@ GtkWidget *ToolboxFactory::createCommandsToolbox()
{
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_name(tb, "CommandsToolbox");
gtk_box_set_homogeneous(GTK_BOX(tb), FALSE);
#else
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
@@ -1056,6 +1060,7 @@ GtkWidget *ToolboxFactory::createSnapToolbox()
{
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *tb = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_set_name(tb, "SnapToolbox");
gtk_box_set_homogeneous(GTK_BOX(tb), FALSE);
#else
GtkWidget *tb = gtk_vbox_new(FALSE, 0);
@@ -1406,6 +1411,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
// converted to GtkActions and UIManager
GtkWidget* kludge = gtk_toolbar_new();
+ gtk_widget_set_name( kludge, "Kludge" );
g_object_set_data( G_OBJECT(kludge), "dtw", desktop->canvas);
g_object_set_data( G_OBJECT(kludge), "desktop", desktop);
dataHolders[aux_toolboxes[i].type_name] = kludge;
@@ -1418,7 +1424,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
} else {
sub_toolbox = aux_toolboxes[i].create_func(desktop);
}
-
+ gtk_widget_set_name( sub_toolbox, "SubToolBox" );
gtk_size_group_add_widget( grouper, sub_toolbox );
gtk_container_add(GTK_CONTAINER(toolbox), sub_toolbox);
@@ -1436,6 +1442,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop)
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget* holder = gtk_grid_new();
+ gtk_widget_set_name( holder, "ToolbarHolder" );
gtk_grid_attach( GTK_GRID(holder), kludge, 2, 0, 1, 1);
#else
GtkWidget* holder = gtk_table_new( 1, 3, FALSE );
diff --git a/src/xml/rebase-hrefs.cpp b/src/xml/rebase-hrefs.cpp
index 2bcae5d81..a8ac3b4cc 100644
--- a/src/xml/rebase-hrefs.cpp
+++ b/src/xml/rebase-hrefs.cpp
@@ -220,8 +220,8 @@ void Inkscape::XML::rebase_hrefs(SPDocument *const doc, gchar const *const new_b
*
* Note also that Inkscape only supports fragment hrefs (href="#pattern257") for many of these
* cases. */
- std::set<SPObject *> images = doc->getResourceList("image");
- for (std::set<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) {
+ std::vector<SPObject *> images = doc->getResourceList("image");
+ for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) {
Inkscape::XML::Node *ir = (*it)->getRepr();
std::string uri;