From fac3eb9aebddbdb591b931d4c42a1a7d10f51a1c Mon Sep 17 00:00:00 2001 From: johanengelen Date: Tue, 4 Sep 2007 18:53:01 +0000 Subject: [PATCH] LPE: add Paste LPE verb + menu item. add scale ratios to curve stitch and path-along-path. remove trailing space in verbs.cpp. Fix initialization of BoolParam --- src/live_effects/effect.cpp | 29 +++++++++++--- src/live_effects/lpe-curvestitch.cpp | 4 +- src/live_effects/lpe-curvestitch.h | 1 + src/live_effects/lpe-skeletalstrokes.cpp | 18 ++++++--- src/live_effects/lpe-skeletalstrokes.h | 3 ++ src/live_effects/parameter/bool.cpp | 2 +- src/live_effects/parameter/bool.h | 10 ++--- src/menus-skeleton.h | 1 + src/selection-chemistry.cpp | 48 ++++++++++++++++++++++++ src/selection-chemistry.h | 1 + src/ui/dialog/livepatheffect-editor.cpp | 2 + src/verbs.cpp | 35 +++++++++-------- src/verbs.h | 1 + 13 files changed, 122 insertions(+), 33 deletions(-) diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 30a90d834..29f9cb7ef 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -25,6 +25,8 @@ #include <2geom/sbasis-to-bezier.h> #include +#include + // include effects: #include "live_effects/lpe-skeletalstrokes.h" #include "live_effects/lpe-slant.h" @@ -114,7 +116,7 @@ Effect::doEffect (SPCurve * curve) { NArtBpath *new_bpath = doEffect(SP_CURVE_BPATH(curve)); - if (new_bpath) { // FIXME, add function to SPCurve to change bpath? or a copy function? + if (new_bpath && new_bpath != SP_CURVE_BPATH(curve)) { // FIXME, add function to SPCurve to change bpath? or a copy function? if (curve->_bpath) { g_free(curve->_bpath); //delete old bpath } @@ -125,13 +127,30 @@ Effect::doEffect (SPCurve * curve) NArtBpath * Effect::doEffect (NArtBpath * path_in) { - std::vector orig_pathv = BPath_to_2GeomPath(path_in); + try { + std::vector orig_pathv = BPath_to_2GeomPath(path_in); - std::vector result_pathv = doEffect(orig_pathv); + std::vector result_pathv = doEffect(orig_pathv); - NArtBpath *new_bpath = BPath_from_2GeomPath(result_pathv); + NArtBpath *new_bpath = BPath_from_2GeomPath(result_pathv); - return new_bpath; + return new_bpath; + } + catch (std::exception e) { + g_warning("An exception occurred during execution of an LPE - %s", e.what()); + // return here + NArtBpath *path_out; + + unsigned ret = 0; + while ( path_in[ret].code != NR_END ) { + ++ret; + } + unsigned len = ++ret; + + path_out = g_new(NArtBpath, len); + memcpy(path_out, path_in, len * sizeof(NArtBpath)); + return path_out; + } } std::vector diff --git a/src/live_effects/lpe-curvestitch.cpp b/src/live_effects/lpe-curvestitch.cpp index a0a473fe7..8eb35087e 100644 --- a/src/live_effects/lpe-curvestitch.cpp +++ b/src/live_effects/lpe-curvestitch.cpp @@ -41,12 +41,14 @@ LPECurveStitch::LPECurveStitch(LivePathEffectObject *lpeobject) : nrofpaths(_("Nr of paths"), _("The number of paths that will be generated."), "count", &wr, this, 5), startpoint_variation(_("Startpoint variation"), _("..."), "startpoint_variation", &wr, this, 0), endpoint_variation(_("Endpoint variation"), _("..."), "endpoint_variation", &wr, this, 0), + prop_scale(_("Scale ratio"), _("Ratio between scaling in the x and y direction of the original path"), "prop_scale", &wr, this, 1), scale_y(_("Scale stroke y"), _("Scale the height of the stroke path with its length"), "scale_stroke_y", &wr, this, false) { registerParameter( dynamic_cast(&nrofpaths) ); registerParameter( dynamic_cast(&startpoint_variation) ); registerParameter( dynamic_cast(&endpoint_variation) ); registerParameter( dynamic_cast(&strokepath) ); + registerParameter( dynamic_cast(&prop_scale) ); registerParameter( dynamic_cast(&scale_y) ); nrofpaths.param_make_integer(); @@ -95,7 +97,7 @@ LPECurveStitch::doEffect (std::vector & path_in) Matrix transform; transform.setXAxis( (end-start) / scaling ); - gdouble scaling_y = scale_y.get_value() ? L2(end-start)/scaling : 1.0; + gdouble scaling_y = scale_y.get_value() ? (L2(end-start)/scaling)*prop_scale : 1.0; transform.setYAxis( rot90(unit_vector(end-start)) * scaling_y); transform.setTranslation( start ); Piecewise > pwd2_out = (strokepath-stroke_origin) * transform; diff --git a/src/live_effects/lpe-curvestitch.h b/src/live_effects/lpe-curvestitch.h index 2b3e4553e..66bbbc8f0 100644 --- a/src/live_effects/lpe-curvestitch.h +++ b/src/live_effects/lpe-curvestitch.h @@ -35,6 +35,7 @@ private: ScalarParam nrofpaths; RandomParam startpoint_variation; RandomParam endpoint_variation; + ScalarParam prop_scale; BoolParam scale_y; LPECurveStitch(const LPECurveStitch&); diff --git a/src/live_effects/lpe-skeletalstrokes.cpp b/src/live_effects/lpe-skeletalstrokes.cpp index 162dfe8a4..459b01861 100644 --- a/src/live_effects/lpe-skeletalstrokes.cpp +++ b/src/live_effects/lpe-skeletalstrokes.cpp @@ -58,11 +58,15 @@ static const Util::EnumDataConverter SkelCopyTypeConverter(SkelCop LPESkeletalStrokes::LPESkeletalStrokes(LivePathEffectObject *lpeobject) : Effect(lpeobject), - pattern(_("Pattern"), _("Path to put along path"), "pattern", &wr, this, "M0,0 L1,1"), - copytype(_("Copytype"), _("How to shape the pattern path along the path"), "copytype", SkelCopyTypeConverter, &wr, this, SSCT_SINGLE_STRETCHED) + pattern(_("Pattern"), _("Path to put along path"), "pattern", &wr, this, "M0,0 L1,0"), + copytype(_("Copytype"), _("How to shape the pattern path along the path"), "copytype", SkelCopyTypeConverter, &wr, this, SSCT_SINGLE_STRETCHED), + prop_scale(_("Scale ratio"), _("Ratio between scaling in the x and y direction of the original path"), "prop_scale", &wr, this, 1), + scale_y(_("Scale pattern y"), _("Scale the height of the pattern path with its length"), "scale_stroke_y", &wr, this, false) { registerParameter( dynamic_cast(&pattern) ); registerParameter( dynamic_cast(©type) ); + registerParameter( dynamic_cast(&prop_scale) ); + registerParameter( dynamic_cast(&scale_y) ); } LPESkeletalStrokes::~LPESkeletalStrokes() @@ -76,8 +80,7 @@ LPESkeletalStrokes::doEffect (Geom::Piecewise > & pwd2_in { using namespace Geom; -/* LOTS OF CODE COPIED FROM 2geom/src/toys/path-along-path.cpp - * All credits should go to jfb and mgsloan of lib2geom development! */ +/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */ SkelCopyType type = copytype.get_value(); @@ -94,7 +97,6 @@ LPESkeletalStrokes::doEffect (Geom::Piecewise > & pwd2_in Interval pattBndsY = bounds_exact(y); y -= (pattBndsY.max()+pattBndsY.min())/2; - int nbCopies = int(uskeleton.cuts.back()/pattBnds.extent()); double scaling = 1; @@ -121,8 +123,12 @@ LPESkeletalStrokes::doEffect (Geom::Piecewise > & pwd2_in double pattWidth = pattBnds.extent() * scaling; - if (scaling != 1) + if (scaling != 1.0) { x*=scaling; + } + if ( scale_y.get_value() && (scaling*prop_scale != 1.0) ) { + y*=(scaling*prop_scale); + } double offs = 0; Piecewise > output; diff --git a/src/live_effects/lpe-skeletalstrokes.h b/src/live_effects/lpe-skeletalstrokes.h index b92ea8ecf..f92b64454 100644 --- a/src/live_effects/lpe-skeletalstrokes.h +++ b/src/live_effects/lpe-skeletalstrokes.h @@ -12,6 +12,7 @@ #include "live_effects/effect.h" #include "live_effects/parameter/path.h" #include "live_effects/parameter/enum.h" +#include "live_effects/parameter/bool.h" namespace Inkscape { namespace LivePathEffect { @@ -34,6 +35,8 @@ public: private: PathParam pattern; EnumParam copytype; + ScalarParam prop_scale; + BoolParam scale_y; void on_pattern_pasted(); diff --git a/src/live_effects/parameter/bool.cpp b/src/live_effects/parameter/bool.cpp index af3449dff..f0d409955 100644 --- a/src/live_effects/parameter/bool.cpp +++ b/src/live_effects/parameter/bool.cpp @@ -26,7 +26,7 @@ namespace LivePathEffect { BoolParam::BoolParam( const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, Effect* effect, bool default_value ) - : Parameter(label, tip, key, wr, effect), defvalue(default_value) + : Parameter(label, tip, key, wr, effect), defvalue(default_value), value(default_value) { checkwdg = NULL; } diff --git a/src/live_effects/parameter/bool.h b/src/live_effects/parameter/bool.h index 24c10fb3b..0a29a9439 100644 --- a/src/live_effects/parameter/bool.h +++ b/src/live_effects/parameter/bool.h @@ -29,15 +29,15 @@ public: Inkscape::UI::Widget::Registry* wr, Effect* effect, bool default_value = false); - ~BoolParam(); + virtual ~BoolParam(); - Gtk::Widget * param_getWidget(); + virtual Gtk::Widget * param_getWidget(); - bool param_readSVGValue(const gchar * strvalue); - gchar * param_writeSVGValue() const; + virtual bool param_readSVGValue(const gchar * strvalue); + virtual gchar * param_writeSVGValue() const; void param_setValue(bool newvalue); - void param_set_default(); + virtual void param_set_default(); bool get_value() { return value; }; diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 1453b37c7..8015308b6 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -66,6 +66,7 @@ static char const menus_skeleton[] = " \n" " \n" " \n" +" \n" " \n" " \n" " \n" diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 1e1f135f9..99f66130f 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -1184,6 +1184,54 @@ void sp_selection_paste_style() _("Paste style")); } +void sp_selection_paste_livepatheffect() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop == NULL) return; + + Inkscape::Selection *selection = sp_desktop_selection(desktop); + + // check if something is in the clipboard + if (clipboard == NULL) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing on the clipboard.")); + return; + } + + // check if something is selected + if (selection->isEmpty()) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select object(s) to paste live path effect to.")); + return; + } + + paste_defs (&defs_clipboard, sp_desktop_document(desktop)); + + Inkscape::XML::Node *repr = (Inkscape::XML::Node *) clipboard->data; + const char * effectstr = repr->attribute("inkscape:path-effect"); + if (!effectstr) { + SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Clipboard does not contain a live path effect.")); + return; + } + + for ( GSList const *itemlist = selection->itemList(); itemlist != NULL; itemlist = g_slist_next(itemlist) ) { + SPItem *item = reinterpret_cast(itemlist->data); + if ( item && SP_IS_SHAPE(item) ) { + Inkscape::XML::Node *selrepr = (Inkscape::XML::Node *) SP_OBJECT_REPR(item); + selrepr->setAttribute("inkscape:path-effect", effectstr); + + // set inkscape:original-d for paths. the other shapes don't need this. + if ( SP_IS_PATH(item) ) { + Inkscape::XML::Node *pathrepr = SP_OBJECT_REPR(item); + if ( ! pathrepr->attribute("inkscape:original-d") ) { + pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d")); + } + } + } + } + + sp_document_done(sp_desktop_document (desktop), SP_VERB_EDIT_PASTE_LIVEPATHEFFECT, + _("Paste live path effect")); +} + void sp_selection_paste_size (bool apply_x, bool apply_y) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index b21cbc2a1..a132161ef 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -52,6 +52,7 @@ void sp_selection_cut(); void sp_selection_copy(); void sp_selection_paste(bool in_place); void sp_selection_paste_style(); +void sp_selection_paste_livepatheffect(); void sp_selection_paste_size(bool apply_x, bool apply_y); void sp_selection_paste_size_separately(bool apply_x, bool apply_y); diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index ee010eeca..b801e53c8 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -230,6 +230,8 @@ LivePathEffectEditor::setDesktop(SPDesktop *desktop) # BUTTON CLICK HANDLERS (callbacks) ########################################################################*/ +// TODO: factor out the effect applying code which can be called from anywhere. (selection-chemistry.cpp also needs it) + void LivePathEffectEditor::onApply() { diff --git a/src/verbs.cpp b/src/verbs.cpp index 89237cf7f..c325b6a07 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -114,7 +114,7 @@ namespace Inkscape { class PanelDialog : public Inkscape::UI::Dialog::Dialog { public: - PanelDialog(char const *prefs_path, int const verb_num) : + PanelDialog(char const *prefs_path, int const verb_num) : Dialog( (prefs_get_int_attribute_limited ("options.dialogtype", "value", UI::Dialog::DOCK, 0, 1) == UI::Dialog::FLOATING ? &UI::Dialog::Behavior::FloatingBehavior::create : @@ -359,7 +359,7 @@ public: gchar const *image) : Verb(code, id, name, tip, image) { } -}; //TextVerb : public Verb +}; //TextVerb : public Verb Verb::VerbTable Verb::_verbs; Verb::VerbIDTable Verb::_verb_ids; @@ -795,12 +795,12 @@ FileVerb::perform(SPAction *action, void *data, void *pdata) Inkscape::UI::View::View *current_view = sp_action_get_view(action); SPDocument *current_document = current_view->doc(); #endif - + SPDesktop *desktop = dynamic_cast(sp_action_get_view(action)); g_assert(desktop != NULL); Gtk::Window *parent = desktop->getToplevel(); g_assert(parent != NULL); - + switch ((long) data) { case SP_VERB_FILE_NEW: sp_file_new_default(); @@ -859,7 +859,7 @@ FileVerb::perform(SPAction *action, void *data, void *pdata) default: break; } - + } // end of sp_verb_action_file_perform() @@ -912,6 +912,9 @@ EditVerb::perform(SPAction *action, void *data, void *pdata) case SP_VERB_EDIT_PASTE_IN_PLACE: sp_selection_paste(true); break; + case SP_VERB_EDIT_PASTE_LIVEPATHEFFECT: + sp_selection_paste_livepatheffect(); + break; case SP_VERB_EDIT_DELETE: sp_selection_delete(); break; @@ -965,7 +968,7 @@ EditVerb::perform(SPAction *action, void *data, void *pdata) } break; - case SP_VERB_EDIT_SELECT_NEXT: + case SP_VERB_EDIT_SELECT_NEXT: if (tools_isactive(dt, TOOLS_NODES)) { SP_NODE_CONTEXT(ec)->shape_editor->select_next(); } else if (tools_isactive(dt, TOOLS_GRADIENT)) { @@ -974,7 +977,7 @@ EditVerb::perform(SPAction *action, void *data, void *pdata) sp_selection_item_next(); } break; - case SP_VERB_EDIT_SELECT_PREV: + case SP_VERB_EDIT_SELECT_PREV: if (tools_isactive(dt, TOOLS_NODES)) { SP_NODE_CONTEXT(ec)->shape_editor->select_prev(); } else if (tools_isactive(dt, TOOLS_GRADIENT)) { @@ -1142,7 +1145,7 @@ LayerVerb::perform(SPAction *action, void *data, void *pdata) SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); if (next) { dt->setCurrentLayer(next); - sp_document_done(sp_desktop_document(dt), SP_VERB_LAYER_NEXT, + sp_document_done(sp_desktop_document(dt), SP_VERB_LAYER_NEXT, _("Move to next layer")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Moved to next layer.")); } else { @@ -1154,7 +1157,7 @@ LayerVerb::perform(SPAction *action, void *data, void *pdata) SPObject *prev=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); if (prev) { dt->setCurrentLayer(prev); - sp_document_done(sp_desktop_document(dt), SP_VERB_LAYER_PREV, + sp_document_done(sp_desktop_document(dt), SP_VERB_LAYER_PREV, _("Move to previous layer")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Moved to previous layer.")); } else { @@ -1253,7 +1256,7 @@ LayerVerb::perform(SPAction *action, void *data, void *pdata) dt->setCurrentLayer(survivor); } - sp_document_done(sp_desktop_document(dt), SP_VERB_LAYER_DELETE, + sp_document_done(sp_desktop_document(dt), SP_VERB_LAYER_DELETE, _("Delete layer")); // TRANSLATORS: this means "The layer has been deleted." @@ -1333,7 +1336,7 @@ ObjectVerb::perform( SPAction *action, void *data, void *pdata ) SP_NODE_CONTEXT(ec)->shape_editor->flip(NR::X); } - // When working with the selector tool, flip the selection about its rotation center + // When working with the selector tool, flip the selection about its rotation center // (if it is visible) or about the center of the bounding box. } else { sp_selection_scale_relative(sel, center, NR::scale(-1.0, 1.0)); @@ -1541,7 +1544,7 @@ TextVerb::perform(SPAction *action, void *data, void *pdata) Inkscape::XML::Node *repr = SP_OBJECT_REPR(dt->namedview); (void)repr; } - + /** \brief Decode the verb code and take appropriate action */ void ZoomVerb::perform(SPAction *action, void *data, void *pdata) @@ -1667,7 +1670,7 @@ ZoomVerb::perform(SPAction *action, void *data, void *pdata) default: break; } - + dt->updateNow(); } // end of sp_verb_action_zoom_perform() @@ -2043,7 +2046,7 @@ FitCanvasVerb::perform(SPAction *action, void *data, void *pdata) if (!dt) return; SPDocument *doc = sp_desktop_document(dt); if (!doc) return; - + switch ((long) data) { case SP_VERB_FIT_CANVAS_TO_SELECTION: fit_canvas_to_selection(dt); @@ -2112,7 +2115,7 @@ LockAndHideVerb::perform(SPAction *action, void *data, void *pdata) if (!dt) return; SPDocument *doc = sp_desktop_document(dt); if (!doc) return; - + switch ((long) data) { case SP_VERB_UNLOCK_ALL: unlock_all(dt); @@ -2208,6 +2211,8 @@ Verb *Verb::_base_verbs[] = { N_("Scale each selected object vertically to match the height of the copied object"), NULL), new EditVerb(SP_VERB_EDIT_PASTE_IN_PLACE, "EditPasteInPlace", N_("Paste _In Place"), N_("Paste objects from clipboard to the original location"), "selection_paste_in_place"), + new EditVerb(SP_VERB_EDIT_PASTE_LIVEPATHEFFECT, "EditPasteLivePathEffect", N_("Paste Live Path _Effect"), + N_("Apply the live path effect of the copied object to selection"), NULL), new EditVerb(SP_VERB_EDIT_DELETE, "EditDelete", N_("_Delete"), N_("Delete selection"), GTK_STOCK_DELETE), new EditVerb(SP_VERB_EDIT_DUPLICATE, "EditDuplicate", N_("Duplic_ate"), diff --git a/src/verbs.h b/src/verbs.h index a9100de71..838a7581c 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -61,6 +61,7 @@ enum { SP_VERB_EDIT_PASTE_SIZE_SEPARATELY_X, SP_VERB_EDIT_PASTE_SIZE_SEPARATELY_Y, SP_VERB_EDIT_PASTE_IN_PLACE, + SP_VERB_EDIT_PASTE_LIVEPATHEFFECT, SP_VERB_EDIT_DELETE, SP_VERB_EDIT_DUPLICATE, SP_VERB_EDIT_CLONE, -- 2.30.2