summaryrefslogtreecommitdiffstats
path: root/src/splivarot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/splivarot.cpp')
-rw-r--r--src/splivarot.cpp139
1 files changed, 96 insertions, 43 deletions
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index fe8d8a894..ea035f0ab 100644
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
@@ -19,7 +19,7 @@
#include <cstring>
#include <string>
#include <vector>
-#include <glib/gmem.h>
+#include <glib.h>
#include "xml/repr.h"
#include "svg/svg.h"
#include "sp-path.h"
@@ -45,7 +45,6 @@
#include "xml/repr.h"
#include "xml/repr-sorting.h"
#include <2geom/pathvector.h>
-#include <libnr/nr-scale-matrix-ops.h>
#include "helper/geom.h"
#include "livarot/Path.h"
@@ -607,6 +606,9 @@ void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Affine
{
SPMarker* marker = SP_MARKER (marker_object);
SPItem* marker_item = sp_item_first_item_child(marker_object);
+ if (!marker_item) {
+ return;
+ }
Geom::Affine tr(marker_transform);
@@ -626,32 +628,53 @@ void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Affine
}
static
+void item_outline_add_marker_child( SPItem const *item, Geom::Affine marker_transform, Geom::PathVector* pathv_in )
+{
+ Geom::Affine tr(marker_transform);
+ tr = item->transform * tr;
+
+ // note: a marker child item can be an item group!
+ if (SP_IS_GROUP(item)) {
+ // recurse through all childs:
+ for (SPObject const *o = item->firstChild() ; o ; o = o->getNext() ) {
+ if ( SP_IS_ITEM(o) ) {
+ item_outline_add_marker_child(SP_ITEM(o), tr, pathv_in);
+ }
+ }
+ } else {
+ Geom::PathVector* marker_pathv = item_outline(item);
+
+ if (marker_pathv) {
+ for (unsigned int j=0; j < marker_pathv->size(); j++) {
+ pathv_in->push_back((*marker_pathv)[j] * tr);
+ }
+ delete marker_pathv;
+ }
+ }
+}
+
+static
void item_outline_add_marker( SPObject const *marker_object, Geom::Affine marker_transform,
Geom::Scale stroke_scale, Geom::PathVector* pathv_in )
{
SPMarker const * marker = SP_MARKER(marker_object);
- SPItem const * marker_item = sp_item_first_item_child(marker_object);
Geom::Affine tr(marker_transform);
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
tr = stroke_scale * tr;
}
// total marker transform
- tr = marker_item->transform * marker->c2p * tr;
+ tr = marker->c2p * tr;
- Geom::PathVector* marker_pathv = item_outline(marker_item);
-
- if (marker_pathv) {
- for (unsigned int j=0; j < marker_pathv->size(); j++) {
- pathv_in->push_back((*marker_pathv)[j] * tr);
- }
- delete marker_pathv;
+ SPItem const * marker_item = sp_item_first_item_child(marker_object); // why only consider the first item? can a marker only consist of a single item (that may be a group)?
+ if (marker_item) {
+ item_outline_add_marker_child(marker_item, tr, pathv_in);
}
}
/**
* Returns a pathvector that is the outline of the stroked item, with markers.
- * item must be SPShape of SPText.
+ * item must be SPShape or SPText.
*/
Geom::PathVector* item_outline(SPItem const *item)
{
@@ -1245,7 +1268,7 @@ void
sp_selected_path_offset(SPDesktop *desktop)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- double prefOffset = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0);
+ double prefOffset = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0, "px");
sp_selected_path_do_offset(desktop, true, prefOffset);
}
@@ -1253,7 +1276,7 @@ void
sp_selected_path_inset(SPDesktop *desktop)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- double prefOffset = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0);
+ double prefOffset = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0, "px");
sp_selected_path_do_offset(desktop, false, prefOffset);
}
@@ -1379,7 +1402,7 @@ sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updat
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- o_width = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0);
+ o_width = prefs->getDouble("/options/defaultoffsetwidth/value", 1.0, "px");
}
if (o_width < 0.01)
@@ -1468,6 +1491,7 @@ sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updat
if ( updating ) {
//XML Tree being used directly here while it shouldn't be
+ item->doWriteTransform(item->getRepr(), transform);
char const *id = item->getRepr()->attribute("id");
char const *uri = g_strdup_printf("#%s", id);
repr->setAttribute("xlink:href", uri);
@@ -1486,11 +1510,7 @@ sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updat
SPItem *nitem = (SPItem *) sp_desktop_document(desktop)->getObjectByRepr(repr);
- if ( updating ) {
- // on conserve l'original
- // we reapply the transform to the original (offset will feel it)
- item->doWriteTransform(item->getRepr(), transform);
- } else {
+ if ( !updating ) {
// delete original, apply the transform to the offset
item->deleteObject(false);
nitem->doWriteTransform(repr, transform);
@@ -1788,19 +1808,10 @@ sp_selected_path_simplify_item(SPDesktop *desktop,
false);
}
-
- SPCurve *curve = NULL;
-
- if (SP_IS_SHAPE(item)) {
- curve = SP_SHAPE(item)->getCurve();
- if (!curve)
- return false;
- }
-
- if (SP_IS_TEXT(item)) {
- curve = SP_TEXT(item)->getNormalizedBpath();
- if (!curve)
- return false;
+ // get path to simplify (note that the path *before* LPE calculation is needed)
+ Path *orig = Path_for_item_before_LPE(item, false);
+ if (orig == NULL) {
+ return false;
}
// correct virtual size by full transform (bug #166937)
@@ -1820,14 +1831,6 @@ sp_selected_path_simplify_item(SPDesktop *desktop,
gchar *mask = g_strdup(item->getRepr()->attribute("mask"));
gchar *clip_path = g_strdup(item->getRepr()->attribute("clip-path"));
- Path *orig = Path_for_item(item, false);
- if (orig == NULL) {
- g_free(style);
- curve->unref();
- return false;
- }
-
- curve->unref();
// remember the position of the item
gint pos = item->getRepr()->position();
// remember parent
@@ -1939,7 +1942,7 @@ sp_selected_path_simplify_items(SPDesktop *desktop,
bool didSomething = false;
- Geom::OptRect selectionBbox = selection->bounds();
+ Geom::OptRect selectionBbox = selection->visualBounds();
if (!selectionBbox) {
return false;
}
@@ -1960,7 +1963,7 @@ sp_selected_path_simplify_items(SPDesktop *desktop,
continue;
if (simplifyIndividualPaths) {
- Geom::OptRect itemBbox = item->getBounds(item->i2d_affine());
+ Geom::OptRect itemBbox = item->desktopVisualBounds();
if (itemBbox) {
simplifySize = L2(itemBbox->dimensions());
} else {
@@ -2090,6 +2093,27 @@ Path_for_item(SPItem *item, bool doTransformation, bool transformFull)
return dest;
}
+/**
+ * Obtains an item's Path before the LPE stack has been applied.
+ */
+Path *
+Path_for_item_before_LPE(SPItem *item, bool doTransformation, bool transformFull)
+{
+ SPCurve *curve = curve_for_item_before_LPE(item);
+
+ if (curve == NULL)
+ return NULL;
+
+ Geom::PathVector *pathv = pathvector_for_curve(item, curve, doTransformation, transformFull, Geom::identity(), Geom::identity());
+ curve->unref();
+
+ Path *dest = new Path;
+ dest->LoadPathVector(*pathv);
+ delete pathv;
+
+ return dest;
+}
+
/*
* NOTE: Returns empty pathvector if curve == NULL
* TODO: see if calling this method can be optimized. All the pathvector copying might be slow.
@@ -2116,6 +2140,10 @@ pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool t
return dest;
}
+/**
+ * Obtains an item's curve. For SPPath, it is the path *before* LPE. For SPShapes other than path, it is the path *after* LPE.
+ * So the result is somewhat ill-defined, and probably this method should not be used... See curve_for_item_before_LPE.
+ */
SPCurve* curve_for_item(SPItem *item)
{
if (!item)
@@ -2141,6 +2169,31 @@ SPCurve* curve_for_item(SPItem *item)
return curve; // do not forget to unref the curve at some point!
}
+/**
+ * Obtains an item's curve *before* LPE.
+ * The returned SPCurve should be unreffed by the caller.
+ */
+SPCurve* curve_for_item_before_LPE(SPItem *item)
+{
+ if (!item)
+ return NULL;
+
+ SPCurve *curve = NULL;
+ if (SP_IS_SHAPE(item)) {
+ curve = SP_SHAPE(item)->getCurveBeforeLPE();
+ }
+ else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item))
+ {
+ curve = te_get_layout(item)->convertToCurves();
+ }
+ else if (SP_IS_IMAGE(item))
+ {
+ curve = sp_image_get_curve(SP_IMAGE(item));
+ }
+
+ return curve; // do not forget to unref the curve at some point!
+}
+
boost::optional<Path::cut_position> get_nearest_position_on_Path(Path *path, Geom::Point p, unsigned seg)
{
//get nearest position on path