X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsp-path.cpp;h=04ad386d9a0fb18cf63726c96d3d9b8397452abe;hb=f24714b30a73cad9fb6b5522e51bc1e50a55fc27;hp=654edcc610a88410c741fc2bb38bdab60f96e973;hpb=ab150ded0b7670ddc64583904f69bd26a1c4d1fc;p=inkscape.git diff --git a/src/sp-path.cpp b/src/sp-path.cpp index 654edcc61..04ad386d9 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -20,13 +20,17 @@ #include +#include "live_effects/effect.h" +#include "live_effects/lpeobject.h" +#include "live_effects/lpeobject-reference.h" +#include "sp-lpe-item.h" + #include -#include -#include #include #include <2geom/pathvector.h> #include <2geom/bezier-curve.h> #include <2geom/hvlinesegment.h> +#include "helper/geom-curves.h" #include "svg/svg.h" #include "xml/repr.h" @@ -43,7 +47,6 @@ #include "inkscape.h" #include "style.h" #include "message-stack.h" -#include "prefs-utils.h" #include "selection.h" #define noPATH_VERBOSE @@ -57,7 +60,7 @@ static void sp_path_build(SPObject *object, SPDocument *document, Inkscape::XML: static void sp_path_set(SPObject *object, unsigned key, gchar const *value); static Inkscape::XML::Node *sp_path_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static NR::Matrix sp_path_set_transform(SPItem *item, NR::Matrix const &xform); +static Geom::Matrix sp_path_set_transform(SPItem *item, Geom::Matrix const &xform); static gchar * sp_path_description(SPItem *item); static void sp_path_convert_to_guides(SPItem *item); @@ -134,9 +137,24 @@ static gchar * sp_path_description(SPItem * item) { int count = sp_nodes_in_path(SP_PATH(item)); - if (sp_lpe_item_has_path_effect(SP_LPE_ITEM(item))) { - return g_strdup_printf(ngettext("Path (%i node, path effect)", - "Path (%i nodes, path effect)",count), count); + if (SP_IS_LPE_ITEM(item) && sp_lpe_item_has_path_effect(SP_LPE_ITEM(item))) { + + Glib::ustring s; + + PathEffectList effect_list = sp_lpe_item_get_effect_list(SP_LPE_ITEM(item)); + for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++) + { + LivePathEffectObject *lpeobj = (*it)->lpeobject; + if (!lpeobj || !lpeobj->get_lpe()) + break; + if (s.empty()) + s = lpeobj->get_lpe()->getName(); + else + s = s + ", " + lpeobj->get_lpe()->getName(); + } + + return g_strdup_printf(ngettext("Path (%i node, path effect: %s)", + "Path (%i nodes, path effect: %s)",count), count, s.c_str()); } else { return g_strdup_printf(ngettext("Path (%i node)", "Path (%i nodes)",count), count); @@ -159,9 +177,7 @@ sp_path_convert_to_guides(SPItem *item) for(Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit) { for(Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_default(); ++cit) { // only add curves for straight line segments - if( dynamic_cast(&*cit) || - dynamic_cast(&*cit) || - dynamic_cast(&*cit) ) + if( is_straight_curve(*cit) ) { pts.push_back(std::make_pair(cit->initialPoint() * i2d, cit->finalPoint() * i2d)); } @@ -259,7 +275,6 @@ sp_path_set(SPObject *object, unsigned int key, gchar const *value) object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); break; case SP_ATTR_D: - if (!sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(path))) { if (value) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *curve = new SPCurve(pv); @@ -271,7 +286,6 @@ sp_path_set(SPObject *object, unsigned int key, gchar const *value) sp_shape_set_curve((SPShape *) path, NULL, TRUE); } object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - } break; case SP_PROP_MARKER: case SP_PROP_MARKER_START: @@ -351,26 +365,26 @@ sp_path_update(SPObject *object, SPCtx *ctx, guint flags) /** * Writes the given transform into the repr for the given item. */ -static NR::Matrix -sp_path_set_transform(SPItem *item, NR::Matrix const &xform) +static Geom::Matrix +sp_path_set_transform(SPItem *item, Geom::Matrix const &xform) { SPShape *shape = (SPShape *) item; SPPath *path = (SPPath *) item; if (!shape->curve) { // 0 nodes, nothing to transform - return NR::identity(); + return Geom::identity(); } - // Transform the original-d path or the (ordinary) path - if (path->original_curve) { - path->original_curve->transform(to_2geom(xform)); - sp_lpe_item_update_patheffect(path, true, true); + // Transform the original-d path if this is a valid LPE item, other else the (ordinary) path + if (path->original_curve && SP_IS_LPE_ITEM(item) && + sp_lpe_item_has_path_effect(SP_LPE_ITEM(item))) { + path->original_curve->transform(xform); } else { - shape->curve->transform(to_2geom(xform)); + shape->curve->transform(xform); } // Adjust stroke - sp_item_adjust_stroke(item, NR::expansion(xform)); + sp_item_adjust_stroke(item, xform.descrim()); // Adjust pattern fill sp_item_adjust_pattern(item, xform); @@ -384,24 +398,26 @@ sp_path_set_transform(SPItem *item, NR::Matrix const &xform) item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); // nothing remains - we've written all of the transform, so return identity - return NR::identity(); + return Geom::identity(); } + static void sp_path_update_patheffect(SPLPEItem *lpeitem, bool write) { - SPShape *shape = (SPShape *) lpeitem; - SPPath *path = (SPPath *) lpeitem; - if (path->original_curve) { + SPShape * const shape = (SPShape *) lpeitem; + SPPath * const path = (SPPath *) lpeitem; + Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape); + + if (path->original_curve && sp_lpe_item_has_path_effect_recursive(lpeitem)) { SPCurve *curve = path->original_curve->copy(); + /* if a path does not have an lpeitem applied, then reset the curve 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, curve, TRUE); - sp_lpe_item_perform_path_effect(SP_LPE_ITEM(shape), curve); - SP_OBJECT(shape)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - curve->unref(); - if (write) { + bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM(shape), curve); + if (success && write) { // could also do SP_OBJECT(shape)->updateRepr(); but only the d attribute needs updating. - 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); @@ -409,9 +425,19 @@ sp_path_update_patheffect(SPLPEItem *lpeitem, bool write) } else { repr->setAttribute("d", NULL); } + } else { + // LPE was unsuccesfull. Read the old 'd'-attribute. + if (gchar const * value = repr->attribute("d")) { + Geom::PathVector pv = sp_svg_read_pathv(value); + SPCurve *oldcurve = new SPCurve(pv); + if (oldcurve) { + sp_shape_set_curve(shape, oldcurve, TRUE); + oldcurve->unref(); + } + } } - } else { - + SP_OBJECT(shape)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + curve->unref(); } } @@ -460,7 +486,8 @@ sp_path_get_original_curve (SPPath *path) SPCurve* sp_path_get_curve_for_edit (SPPath *path) { - if (path->original_curve) { + if (path->original_curve && SP_IS_LPE_ITEM(path) && + sp_lpe_item_has_path_effect(SP_LPE_ITEM(path))) { return sp_path_get_original_curve(path); } else { return sp_shape_get_curve( (SPShape *) path ); @@ -474,73 +501,14 @@ sp_path_get_curve_for_edit (SPPath *path) const SPCurve* sp_path_get_curve_reference (SPPath *path) { - if (path->original_curve) { + if (path->original_curve && SP_IS_LPE_ITEM(path) && + sp_lpe_item_has_path_effect(SP_LPE_ITEM(path))) { return path->original_curve; } else { return path->curve; } } -/* Create a single dot represented by a circle */ -void freehand_create_single_dot(SPEventContext *ec, NR::Point const &pt, char const *tool, guint event_state) { - g_return_if_fail(!strcmp(tool, "tools.freehand.pen") || !strcmp(tool, "tools.freehand.pencil")); - - SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(ec); - Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc()); - Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); - repr->setAttribute("sodipodi:type", "arc"); - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); - Inkscape::GC::release(repr); - - /* apply the tool's current style */ - sp_desktop_apply_style_tool(desktop, repr, tool, false); - - /* find out stroke width (TODO: is there an easier way??) */ - double stroke_width = 3.0; - gchar const *style_str = NULL; - style_str = repr->attribute("style"); - if (style_str) { - SPStyle *style = sp_style_new(SP_ACTIVE_DOCUMENT); - sp_style_merge_from_style_string(style, style_str); - stroke_width = style->stroke_width.computed; - style->stroke_width.computed = 0; - sp_style_unref(style); - } - /* unset stroke and set fill color to former stroke color */ - gchar * str; - str = g_strdup_printf("fill:#%06x;stroke:none;", sp_desktop_get_color_tool(desktop, tool, false) >> 8); - repr->setAttribute("style", str); - g_free(str); - - /* put the circle where the mouse click occurred and set the diameter to the - current stroke width, multiplied by the amount specified in the preferences */ - NR::Matrix const i2d (from_2geom(sp_item_i2d_affine (item))); - NR::Point pp = pt * i2d; - double rad = 0.5 * prefs_get_double_attribute(tool, "dot-size", 3.0); - if (event_state & GDK_MOD1_MASK) { - /* TODO: We vary the dot size between 0.5*rad and 1.5*rad, where rad is the dot size - as specified in prefs. Very simple, but it might be sufficient in practice. If not, - we need to devise something more sophisticated. */ - double s = g_random_double_range(-0.5, 0.5); - rad *= (1 + s); - } - if (event_state & GDK_SHIFT_MASK) { - // double the point size - rad *= 2; - } - - sp_repr_set_svg_double (repr, "sodipodi:cx", pp[NR::X]); - sp_repr_set_svg_double (repr, "sodipodi:cy", pp[NR::Y]); - sp_repr_set_svg_double (repr, "sodipodi:rx", rad * stroke_width); - sp_repr_set_svg_double (repr, "sodipodi:ry", rad * stroke_width); - item->updateRepr(); - - sp_desktop_selection(desktop)->set(item); - - desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating single dot")); - sp_document_done(sp_desktop_document(desktop), SP_VERB_NONE, _("Create single dot")); -} - /* Local Variables: mode:c++