X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-path.cpp;h=e16147b120ad0ef3d304564fbd7d251aaece2ba9;hb=5d67bd380afd0885c8b4656cb3383aea24aedfcb;hp=a8e3ad6eebf74db53a4a0aacee145a22c2e186d0;hpb=7a8af702272bac1fbba95077d0ddbebfa54f01ca;p=inkscape.git diff --git a/src/sp-path.cpp b/src/sp-path.cpp index a8e3ad6ee..e16147b12 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -33,6 +33,15 @@ #include "sp-guide.h" #include "document.h" +#include "desktop.h" +#include "desktop-handles.h" +#include "desktop-style.h" +#include "event-context.h" +#include "inkscape.h" +#include "style.h" +#include "message-stack.h" +#include "prefs-utils.h" +#include "selection.h" #define noPATH_VERBOSE @@ -50,7 +59,7 @@ static gchar * sp_path_description(SPItem *item); static void sp_path_convert_to_guides(SPItem *item); static void sp_path_update(SPObject *object, SPCtx *ctx, guint flags); -static void sp_path_update_patheffect(SPShape *shape, bool write); +static void sp_path_update_patheffect(SPLPEItem *lpeitem, bool write); static SPShapeClass *parent_class; @@ -89,7 +98,7 @@ sp_path_class_init(SPPathClass * klass) GObjectClass *gobject_class = (GObjectClass *) klass; SPObjectClass *sp_object_class = (SPObjectClass *) klass; SPItemClass *item_class = (SPItemClass *) klass; - SPShapeClass *shape_class = (SPShapeClass *) klass; + SPLPEItemClass *lpe_item_class = (SPLPEItemClass *) klass; parent_class = (SPShapeClass *)g_type_class_peek_parent(klass); @@ -105,7 +114,7 @@ sp_path_class_init(SPPathClass * klass) item_class->set_transform = sp_path_set_transform; item_class->convert_to_guides = sp_path_convert_to_guides; - shape_class->update_patheffect = sp_path_update_patheffect; + lpe_item_class->update_patheffect = sp_path_update_patheffect; } @@ -113,21 +122,16 @@ gint sp_nodes_in_path(SPPath *path) { SPCurve *curve = SP_SHAPE(path)->curve; - if (!curve) return 0; - gint r = curve->end; - gint i = curve->length - 1; - if (i > r) i = r; // sometimes after switching from node editor length is wrong, e.g. f6 - draw - f2 - tab - f1, this fixes it - for (; i >= 0; i --) - if (SP_CURVE_BPATH(curve)[i].code == NR_MOVETO) - r --; - return r; + if (!curve) + return 0; + return curve->nodes_in_path(); } static gchar * sp_path_description(SPItem * item) { int count = sp_nodes_in_path(SP_PATH(item)); - if (SP_SHAPE(item)->path_effect_href) { + 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); } else { @@ -148,7 +152,7 @@ sp_path_convert_to_guides(SPItem *item) SPCurve *curve = SP_SHAPE(path)->curve; if (!curve) return; - NArtBpath *bpath = SP_CURVE_BPATH(curve); + NArtBpath const *bpath = SP_CURVE_BPATH(curve); NR::Point last_pt; NR::Point pt; @@ -165,8 +169,6 @@ sp_path_convert_to_guides(SPItem *item) } sp_guide_pt_pairs_to_guides(doc, pts); - - SP_OBJECT(path)->deleteObject(true); } /** @@ -225,7 +227,7 @@ sp_path_release(SPObject *object) path->connEndPair.release(); if (path->original_curve) { - path->original_curve = sp_curve_unref (path->original_curve); + path->original_curve = path->original_curve->unref(); } if (((SPObjectClass *) parent_class)->release) { @@ -246,10 +248,10 @@ sp_path_set(SPObject *object, unsigned int key, gchar const *value) case SP_ATTR_INKSCAPE_ORIGINAL_D: if (value) { NArtBpath *bpath = sp_svg_read_path(value); - SPCurve *curve = sp_curve_new_from_bpath(bpath); + SPCurve *curve = SPCurve::new_from_bpath(bpath); if (curve) { sp_path_set_original_curve(path, curve, TRUE, true); - sp_curve_unref(curve); + curve->unref(); } } else { sp_path_set_original_curve(path, NULL, TRUE, true); @@ -257,13 +259,13 @@ sp_path_set(SPObject *object, unsigned int key, gchar const *value) object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); break; case SP_ATTR_D: - if (!((SPShape *) path)->path_effect_href) { + if (!sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(path))) { if (value) { NArtBpath *bpath = sp_svg_read_path(value); - SPCurve *curve = sp_curve_new_from_bpath(bpath); + SPCurve *curve = SPCurve::new_from_bpath(bpath); if (curve) { sp_shape_set_curve((SPShape *) path, curve, TRUE); - sp_curve_unref(curve); + curve->unref(); } } else { sp_shape_set_curve((SPShape *) path, NULL, TRUE); @@ -306,28 +308,18 @@ sp_path_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) } if ( shape->curve != NULL ) { - NArtBpath *abp = sp_curve_first_bpath(shape->curve); - if (abp) { - gchar *str = sp_svg_write_path(abp); - repr->setAttribute("d", str); - g_free(str); - } else { - repr->setAttribute("d", ""); - } + gchar *str = sp_svg_write_path(shape->curve->get_pathvector()); + repr->setAttribute("d", str); + g_free(str); } else { repr->setAttribute("d", NULL); } SPPath *path = (SPPath *) object; if ( path->original_curve != NULL ) { - NArtBpath *abp = sp_curve_first_bpath(path->original_curve); - if (abp) { - gchar *str = sp_svg_write_path(abp); - repr->setAttribute("inkscape:original-d", str); - g_free(str); - } else { - repr->setAttribute("inkscape:original-d", ""); - } + gchar *str = sp_svg_write_path(path->original_curve->get_pathvector()); + repr->setAttribute("inkscape:original-d", str); + g_free(str); } else { repr->setAttribute("inkscape:original-d", NULL); } @@ -370,24 +362,12 @@ sp_path_set_transform(SPItem *item, NR::Matrix const &xform) return NR::identity(); } - if (path->original_curve) { /* Transform the original-d path */ - NRBPath dorigpath, sorigpath; - sorigpath.path = SP_CURVE_BPATH(path->original_curve); - nr_path_duplicate_transform(&dorigpath, &sorigpath, xform); - SPCurve *origcurve = sp_curve_new_from_bpath(dorigpath.path); - if (origcurve) { - sp_path_set_original_curve(path, origcurve, TRUE, true); - sp_curve_unref(origcurve); - } - } else { /* Transform the path */ - NRBPath dpath, spath; - spath.path = SP_CURVE_BPATH(shape->curve); - nr_path_duplicate_transform(&dpath, &spath, xform); - SPCurve *curve = sp_curve_new_from_bpath(dpath.path); - if (curve) { - sp_shape_set_curve(shape, curve, TRUE); - sp_curve_unref(curve); - } + // Transform the original-d path or the (ordinary) path + if (path->original_curve) { + path->original_curve->transform(xform); + sp_lpe_item_update_patheffect(path, true, true); + } else { + shape->curve->transform(xform); } // Adjust stroke @@ -409,27 +389,24 @@ sp_path_set_transform(SPItem *item, NR::Matrix const &xform) } static void -sp_path_update_patheffect(SPShape *shape, bool write) +sp_path_update_patheffect(SPLPEItem *lpeitem, bool write) { - SPPath *path = (SPPath *) shape; + SPShape *shape = (SPShape *) lpeitem; + SPPath *path = (SPPath *) lpeitem; if (path->original_curve) { - SPCurve *curve = sp_curve_copy (path->original_curve); - sp_shape_perform_path_effect(curve, shape); - sp_shape_set_curve(shape, curve, TRUE); - sp_curve_unref(curve); + SPCurve *curve = path->original_curve->copy(); + 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) { // 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 ) { - NArtBpath *abp = sp_curve_first_bpath(shape->curve); - if (abp) { - gchar *str = sp_svg_write_path(abp); - repr->setAttribute("d", str); - g_free(str); - } else { - repr->setAttribute("d", ""); - } + gchar *str = sp_svg_write_path(shape->curve->get_pathvector()); + repr->setAttribute("d", str); + g_free(str); } else { repr->setAttribute("d", NULL); } @@ -444,24 +421,24 @@ sp_path_update_patheffect(SPShape *shape, bool write) * Adds a original_curve to the path. If owner is specified, a reference * will be made, otherwise the curve will be copied into the path. * Any existing curve in the path will be unreferenced first. - * This routine triggers reapplication of the an effect is present - * an also triggers a request to update the display. Does not write -* result to XML when write=false. + * This routine triggers reapplication of an effect if present + * and also triggers a request to update the display. Does not write + * result to XML when write=false. */ void sp_path_set_original_curve (SPPath *path, SPCurve *curve, unsigned int owner, bool write) { if (path->original_curve) { - path->original_curve = sp_curve_unref (path->original_curve); + path->original_curve = path->original_curve->unref(); } if (curve) { if (owner) { - path->original_curve = sp_curve_ref (curve); + path->original_curve = curve->ref(); } else { - path->original_curve = sp_curve_copy (curve); + path->original_curve = curve->copy(); } } - sp_path_update_patheffect(path, write); + sp_lpe_item_update_patheffect(path, true, write); SP_OBJECT(path)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } @@ -472,7 +449,7 @@ SPCurve * sp_path_get_original_curve (SPPath *path) { if (path->original_curve) { - return sp_curve_copy (path->original_curve); + return path->original_curve->copy(); } return NULL; } @@ -505,6 +482,66 @@ sp_path_get_curve_reference (SPPath *path) } } +/* 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 (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++