diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp
index d7b703d1adbc70269657cf795f5a61ba6ce7a5fc..624c5ae181ad7513a2200cac5e1c79373270043a 100644 (file)
--- a/src/sp-spiral.cpp
+++ b/src/sp-spiral.cpp
#include "svg/svg.h"
#include "attributes.h"
-#include "display/bezier-utils.h"
+#include <2geom/bezier-utils.h>
#include "display/curve.h"
#include <glibmm/i18n.h>
#include "xml/repr.h"
+#include "document.h"
#include "sp-spiral.h"
static void sp_spiral_init (SPSpiral *spiral);
static void sp_spiral_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr);
-static Inkscape::XML::Node *sp_spiral_write (SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static Inkscape::XML::Node *sp_spiral_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static void sp_spiral_set (SPObject *object, unsigned int key, const gchar *value);
static void sp_spiral_update (SPObject *object, SPCtx *ctx, guint flags);
static gchar * sp_spiral_description (SPItem * item);
-static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p);
+static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs);
+
static void sp_spiral_set_shape (SPShape *shape);
+static void sp_spiral_update_patheffect (SPLPEItem *lpeitem, bool write);
-static NR::Point sp_spiral_get_tangent (SPSpiral const *spiral, gdouble t);
+static Geom::Point sp_spiral_get_tangent (SPSpiral const *spiral, gdouble t);
static SPShapeClass *parent_class;
GObjectClass * gobject_class;
SPObjectClass * sp_object_class;
SPItemClass * item_class;
+ SPLPEItemClass * lpe_item_class;
SPShapeClass *shape_class;
gobject_class = (GObjectClass *) klass;
sp_object_class = (SPObjectClass *) klass;
item_class = (SPItemClass *) klass;
+ lpe_item_class = (SPLPEItemClass *) klass;
shape_class = (SPShapeClass *) klass;
parent_class = (SPShapeClass *)g_type_class_ref (SP_TYPE_SHAPE);
item_class->description = sp_spiral_description;
item_class->snappoints = sp_spiral_snappoints;
- shape_class->set_shape = sp_spiral_set_shape;
+ lpe_item_class->update_patheffect = sp_spiral_update_patheffect;
+
+ shape_class->set_shape = sp_spiral_set_shape;
}
/**
@@ -134,12 +141,12 @@ sp_spiral_build (SPObject * object, SPDocument * document, Inkscape::XML::Node *
* Virtual write: write spiral attributes to corresponding repr.
*/
static Inkscape::XML::Node *
-sp_spiral_write (SPObject *object, Inkscape::XML::Node *repr, guint flags)
+sp_spiral_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
SPSpiral *spiral = SP_SPIRAL (object);
if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = sp_repr_new ("svg:path");
+ repr = xml_doc->createElement("svg:path");
}
if (flags & SP_OBJECT_WRITE_EXT) {
sp_repr_set_svg_double(repr, "sodipodi:t0", spiral->t0);
}
- //Duplicate the path
- SPCurve *curve = ((SPShape *) spiral)->curve;
- //Nulls might be possible if this called iteratively
- if ( !curve ) {
- //g_warning("sp_spiral_write(): No path to copy\n");
- return NULL;
- }
- NArtBpath *bpath = curve->bpath;
- if ( !bpath ) {
- //g_warning("sp_spiral_write(): No path to copy\n");
- return NULL;
- }
- char *d = sp_svg_write_path ( bpath );
- repr->setAttribute("d", d);
- g_free (d);
+ // make sure the curve is rebuilt with all up-to-date parameters
+ sp_spiral_set_shape ((SPShape *) spiral);
+
+ //Duplicate the path
+ SPCurve *curve = ((SPShape *) spiral)->curve;
+ //Nulls might be possible if this called iteratively
+ if ( !curve ) {
+ //g_warning("sp_spiral_write(): No path to copy\n");
+ return NULL;
+ }
+ char *d = sp_svg_write_path ( curve->get_pathvector() );
+ repr->setAttribute("d", d);
+ g_free (d);
- if (((SPObjectClass *) (parent_class))->write)
- ((SPObjectClass *) (parent_class))->write (object, repr, flags | SP_SHAPE_WRITE_PATH);
+ if (((SPObjectClass *) (parent_class))->write)
+ ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr, flags | SP_SHAPE_WRITE_PATH);
- return repr;
+ return repr;
}
/**
((SPObjectClass *) parent_class)->update (object, ctx, flags);
}
+static void
+sp_spiral_update_patheffect(SPLPEItem *lpeitem, bool write)
+{
+ SPShape *shape = (SPShape *) lpeitem;
+ sp_spiral_set_shape(shape);
+
+ if (write) {
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
+ if ( shape->curve != NULL ) {
+ gchar *str = sp_svg_write_path(shape->curve->get_pathvector());
+ repr->setAttribute("d", str);
+ g_free(str);
+ } else {
+ repr->setAttribute("d", NULL);
+ }
+ }
+
+ ((SPObject *)shape)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+}
+
/**
* Return textual description of spiral.
*/
sp_spiral_fit_and_draw (SPSpiral const *spiral,
SPCurve *c,
double dstep,
- NR::Point darray[],
- NR::Point const &hat1,
- NR::Point &hat2,
+ Geom::Point darray[],
+ Geom::Point const &hat1,
+ Geom::Point &hat2,
double *t)
{
#define BEZIER_SIZE 4
g_assert (dstep > 0);
g_assert (is_unit_vector (hat1));
- NR::Point bezier[BEZIER_LENGTH];
+ Geom::Point bezier[BEZIER_LENGTH];
double d;
int depth, i;
/** \todo
* We should use better algorithm to specify maximum error.
*/
- depth = sp_bezier_fit_cubic_full (bezier, NULL, darray, SAMPLE_SIZE,
+ depth = Geom::bezier_fit_cubic_full (bezier, NULL, darray, SAMPLE_SIZE,
hat1, hat2,
SPIRAL_TOLERANCE*SPIRAL_TOLERANCE,
FITTING_MAX_BEZIERS);
#endif
if (depth != -1) {
for (i = 0; i < 4*depth; i += 4) {
- sp_curve_curveto (c,
- bezier[i + 1],
+ c->curveto(bezier[i + 1],
bezier[i + 2],
bezier[i + 3]);
}
g_print ("cant_fit_cubic: t=%g\n", *t);
#endif
for (i = 1; i < SAMPLE_SIZE; i++)
- sp_curve_lineto (c, darray[i]);
+ c->lineto(darray[i]);
}
*t = next_t;
g_assert (is_unit_vector (hat2));
static void
sp_spiral_set_shape (SPShape *shape)
{
- NR::Point darray[SAMPLE_SIZE + 1];
+ Geom::Point darray[SAMPLE_SIZE + 1];
double t;
SPSpiral *spiral = SP_SPIRAL(shape);
SP_OBJECT (spiral)->requestModified(SP_OBJECT_MODIFIED_FLAG);
- SPCurve *c = sp_curve_new ();
-
+ SPCurve *c = new SPCurve ();
+
#ifdef SPIRAL_VERBOSE
g_print ("cx=%g, cy=%g, exp=%g, revo=%g, rad=%g, arg=%g, t0=%g\n",
spiral->cx,
#endif
/* Initial moveto. */
- sp_curve_moveto(c, sp_spiral_get_xy(spiral, spiral->t0));
+ c->moveto(sp_spiral_get_xy(spiral, spiral->t0));
double const tstep = SAMPLE_STEP / spiral->revo;
double const dstep = tstep / (SAMPLE_SIZE - 1);
- NR::Point hat1 = sp_spiral_get_tangent (spiral, spiral->t0);
- NR::Point hat2;
+ Geom::Point hat1 = sp_spiral_get_tangent (spiral, spiral->t0);
+ Geom::Point hat2;
for (t = spiral->t0; t < (1.0 - tstep);) {
sp_spiral_fit_and_draw (spiral, c, dstep, darray, hat1, hat2, &t);
sp_spiral_fit_and_draw (spiral, c, (1.0 - t)/(SAMPLE_SIZE - 1.0),
darray, hat1, hat2, &t);
- sp_shape_set_curve_insync ((SPShape *) spiral, c, TRUE);
- sp_curve_unref (c);
+ /* Reset the shape'scurve to the "original_curve"
+ * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
+ sp_shape_set_curve_insync (shape, c, TRUE);
+ if (sp_lpe_item_has_path_effect(SP_LPE_ITEM(shape)) && sp_lpe_item_path_effects_enabled(SP_LPE_ITEM(shape))) {
+ SPCurve *c_lpe = c->copy();
+ bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM (shape), c_lpe);
+ if (success) {
+ sp_shape_set_curve_insync (shape, c_lpe, TRUE);
+ }
+ c_lpe->unref();
+ }
+ c->unref();
}
/**
spiral->rad = MAX (rad, 0.001);
spiral->arg = arg;
spiral->t0 = CLAMP(t0, 0.0, 0.999);
-
+
((SPObject *)spiral)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
/**
* Virtual snappoints callback.
*/
-static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p)
+static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs)
{
+ // We will determine the spiral's midpoint ourselves, instead of trusting on the base class
+ // Therefore setSnapObjectMidpoints() is set to false temporarily
+ Inkscape::SnapPreferences local_snapprefs = *snapprefs;
+ local_snapprefs.setSnapObjectMidpoints(false);
+
if (((SPItemClass *) parent_class)->snappoints) {
- ((SPItemClass *) parent_class)->snappoints (item, p);
+ ((SPItemClass *) parent_class)->snappoints (item, p, &local_snapprefs);
+ }
+
+ // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes
+ if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) {
+ return;
+ }
+
+ if (snapprefs->getSnapObjectMidpoints()) {
+ Geom::Matrix const i2d (sp_item_i2d_affine (item));
+ SPSpiral *spiral = SP_SPIRAL(item);
+ *p = Geom::Point(spiral->cx, spiral->cy) * i2d;
+ // This point is the start-point of the spiral, which is also returned when _snap_to_itemnode has been set
+ // in the object snapper. In that case we will get a duplicate!
}
}
* than 1.0, though some callers go slightly beyond 1.0 for curve-fitting
* purposes.)
*/
-NR::Point sp_spiral_get_xy (SPSpiral const *spiral, gdouble t)
+Geom::Point sp_spiral_get_xy (SPSpiral const *spiral, gdouble t)
{
g_assert (spiral != NULL);
g_assert (SP_IS_SPIRAL(spiral));
double const rad = spiral->rad * pow(t, (double) spiral->exp);
double const arg = 2.0 * M_PI * spiral->revo * t + spiral->arg;
- return NR::Point(rad * cos (arg) + spiral->cx,
- rad * sin (arg) + spiral->cy);
+ return Geom::Point(rad * cos (arg) + spiral->cx,
+ rad * sin (arg) + spiral->cy);
}
* \pre p != NULL.
* \post is_unit_vector(*p).
*/
-static NR::Point
+static Geom::Point
sp_spiral_get_tangent (SPSpiral const *spiral, gdouble t)
{
- NR::Point ret(1.0, 0.0);
+ Geom::Point ret(1.0, 0.0);
g_return_val_if_fail (( ( spiral != NULL )
&& SP_IS_SPIRAL(spiral) ),
ret);
double const c = cos (arg);
if (spiral->exp == 0.0) {
- ret = NR::Point(-s, c);
+ ret = Geom::Point(-s, c);
} else if (t_scaled == 0.0) {
- ret = NR::Point(c, s);
+ ret = Geom::Point(c, s);
} else {
- NR::Point unrotated(spiral->exp, t_scaled);
+ Geom::Point unrotated(spiral->exp, t_scaled);
double const s_len = L2 (unrotated);
g_assert (s_len != 0);
/** \todo
/* ret = spiral->exp * (c, s) + t_scaled * (-s, c);
alternatively ret = (spiral->exp, t_scaled) * (( c, s),
(-s, c)).*/
- ret = NR::Point(dot(unrotated, NR::Point(c, -s)),
- dot(unrotated, NR::Point(s, c)));
+ ret = Geom::Point(dot(unrotated, Geom::Point(c, -s)),
+ dot(unrotated, Geom::Point(s, c)));
/* ret should already be approximately normalized: the
matrix ((c, -s), (s, c)) is orthogonal (it just
rotates by arg), and unrotated has been normalized,