Code

LPE: add Paste LPE verb + menu item. add scale ratios to curve stitch and path-along...
authorjohanengelen <johanengelen@users.sourceforge.net>
Tue, 4 Sep 2007 18:53:01 +0000 (18:53 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Tue, 4 Sep 2007 18:53:01 +0000 (18:53 +0000)
13 files changed:
src/live_effects/effect.cpp
src/live_effects/lpe-curvestitch.cpp
src/live_effects/lpe-curvestitch.h
src/live_effects/lpe-skeletalstrokes.cpp
src/live_effects/lpe-skeletalstrokes.h
src/live_effects/parameter/bool.cpp
src/live_effects/parameter/bool.h
src/menus-skeleton.h
src/selection-chemistry.cpp
src/selection-chemistry.h
src/ui/dialog/livepatheffect-editor.cpp
src/verbs.cpp
src/verbs.h

index 30a90d83406f6f3207ba3884fc6d86d41c346ef7..29f9cb7ef99a6cc9d6341cbd1f793793af2c8bd1 100644 (file)
@@ -25,6 +25,8 @@
 #include <2geom/sbasis-to-bezier.h>\r
 #include <gtkmm.h>\r
 \r
+#include <exception>\r
+\r
 // include effects:\r
 #include "live_effects/lpe-skeletalstrokes.h"\r
 #include "live_effects/lpe-slant.h"\r
@@ -114,7 +116,7 @@ Effect::doEffect (SPCurve * curve)
 {\r
     NArtBpath *new_bpath = doEffect(SP_CURVE_BPATH(curve));\r
 \r
-    if (new_bpath) {        // FIXME, add function to SPCurve to change bpath? or a copy function?\r
+    if (new_bpath && new_bpath != SP_CURVE_BPATH(curve)) {        // FIXME, add function to SPCurve to change bpath? or a copy function?\r
         if (curve->_bpath) {\r
             g_free(curve->_bpath); //delete old bpath\r
         }\r
@@ -125,13 +127,30 @@ Effect::doEffect (SPCurve * curve)
 NArtBpath *\r
 Effect::doEffect (NArtBpath * path_in)\r
 {\r
-    std::vector<Geom::Path> orig_pathv = BPath_to_2GeomPath(path_in);\r
+    try {\r
+        std::vector<Geom::Path> orig_pathv = BPath_to_2GeomPath(path_in);\r
 \r
-    std::vector<Geom::Path> result_pathv = doEffect(orig_pathv);\r
+        std::vector<Geom::Path> result_pathv = doEffect(orig_pathv);\r
 \r
-    NArtBpath *new_bpath = BPath_from_2GeomPath(result_pathv);\r
+        NArtBpath *new_bpath = BPath_from_2GeomPath(result_pathv);\r
 \r
-    return new_bpath;\r
+        return new_bpath;\r
+    }\r
+    catch (std::exception e) {\r
+        g_warning("An exception occurred during execution of an LPE - %s", e.what());\r
+        // return here\r
+        NArtBpath *path_out;\r
+\r
+        unsigned ret = 0;\r
+        while ( path_in[ret].code != NR_END ) {\r
+            ++ret;\r
+        }\r
+        unsigned len = ++ret;\r
+\r
+        path_out = g_new(NArtBpath, len);\r
+        memcpy(path_out, path_in, len * sizeof(NArtBpath));\r
+        return path_out;\r
+    }\r
 }\r
 \r
 std::vector<Geom::Path>\r
index a0a473fe7fdcbdcc6fecabf24685d34a5235d789..8eb35087e547e6c438361a1294a68a2227a5b307 100644 (file)
@@ -41,12 +41,14 @@ LPECurveStitch::LPECurveStitch(LivePathEffectObject *lpeobject) :
     nrofpaths(_("Nr of paths"), _("The number of paths that will be generated."), "count", &wr, this, 5),\r
     startpoint_variation(_("Startpoint variation"), _("..."), "startpoint_variation", &wr, this, 0),\r
     endpoint_variation(_("Endpoint variation"), _("..."), "endpoint_variation", &wr, this, 0),\r
+    prop_scale(_("Scale ratio"), _("Ratio between scaling in the x and y direction of the original path"), "prop_scale", &wr, this, 1),\r
     scale_y(_("Scale stroke y"), _("Scale the height of the stroke path with its length"), "scale_stroke_y", &wr, this, false)\r
 {\r
     registerParameter( dynamic_cast<Parameter *>(&nrofpaths) );\r
     registerParameter( dynamic_cast<Parameter *>(&startpoint_variation) );\r
     registerParameter( dynamic_cast<Parameter *>(&endpoint_variation) );\r
     registerParameter( dynamic_cast<Parameter *>(&strokepath) );\r
+    registerParameter( dynamic_cast<Parameter *>(&prop_scale) );\r
     registerParameter( dynamic_cast<Parameter *>(&scale_y) );\r
 \r
     nrofpaths.param_make_integer();\r
@@ -95,7 +97,7 @@ LPECurveStitch::doEffect (std::vector<Geom::Path> & path_in)
     \r
             Matrix transform;\r
             transform.setXAxis( (end-start) / scaling );\r
-            gdouble scaling_y = scale_y.get_value() ? L2(end-start)/scaling : 1.0;\r
+            gdouble scaling_y = scale_y.get_value() ? (L2(end-start)/scaling)*prop_scale : 1.0;\r
             transform.setYAxis( rot90(unit_vector(end-start)) * scaling_y);\r
             transform.setTranslation( start );\r
             Piecewise<D2<SBasis> > pwd2_out = (strokepath-stroke_origin) * transform;\r
index 2b3e4553e893edec9bcafa13c69f3c1da697956b..66bbbc8f0ec4740fa9d601293085e0b8b37bbbea 100644 (file)
@@ -35,6 +35,7 @@ private:
     ScalarParam nrofpaths;\r
     RandomParam startpoint_variation;\r
     RandomParam endpoint_variation;\r
+    ScalarParam prop_scale;\r
     BoolParam scale_y;\r
 \r
     LPECurveStitch(const LPECurveStitch&);\r
index 162dfe8a460f2b61b42aa7b9424b2151f0f938b7..459b01861971b406a67b607aaebf5a80c6bb6737 100644 (file)
@@ -58,11 +58,15 @@ static const Util::EnumDataConverter<SkelCopyType> SkelCopyTypeConverter(SkelCop
 \r
 LPESkeletalStrokes::LPESkeletalStrokes(LivePathEffectObject *lpeobject) :\r
     Effect(lpeobject),\r
-    pattern(_("Pattern"), _("Path to put along path"), "pattern", &wr, this, "M0,0 L1,1"),\r
-    copytype(_("Copytype"), _("How to shape the pattern path along the path"), "copytype", SkelCopyTypeConverter, &wr, this, SSCT_SINGLE_STRETCHED)\r
+    pattern(_("Pattern"), _("Path to put along path"), "pattern", &wr, this, "M0,0 L1,0"),\r
+    copytype(_("Copytype"), _("How to shape the pattern path along the path"), "copytype", SkelCopyTypeConverter, &wr, this, SSCT_SINGLE_STRETCHED),\r
+    prop_scale(_("Scale ratio"), _("Ratio between scaling in the x and y direction of the original path"), "prop_scale", &wr, this, 1),\r
+    scale_y(_("Scale pattern y"), _("Scale the height of the pattern path with its length"), "scale_stroke_y", &wr, this, false)\r
 {\r
     registerParameter( dynamic_cast<Parameter *>(&pattern) );\r
     registerParameter( dynamic_cast<Parameter *>(&copytype) );\r
+    registerParameter( dynamic_cast<Parameter *>(&prop_scale) );\r
+    registerParameter( dynamic_cast<Parameter *>(&scale_y) );\r
 }\r
 \r
 LPESkeletalStrokes::~LPESkeletalStrokes()\r
@@ -76,8 +80,7 @@ LPESkeletalStrokes::doEffect (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in
 {\r
     using namespace Geom;\r
 \r
-/* LOTS OF CODE COPIED FROM 2geom/src/toys/path-along-path.cpp\r
- * All credits should go to jfb and mgsloan of lib2geom development! */\r
+/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */\r
 \r
     SkelCopyType type = copytype.get_value();\r
 \r
@@ -94,7 +97,6 @@ LPESkeletalStrokes::doEffect (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in
     Interval pattBndsY = bounds_exact(y);\r
     y -= (pattBndsY.max()+pattBndsY.min())/2;\r
 \r
-\r
     int nbCopies = int(uskeleton.cuts.back()/pattBnds.extent());\r
     double scaling = 1;\r
 \r
@@ -121,8 +123,12 @@ LPESkeletalStrokes::doEffect (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in
 \r
     double pattWidth = pattBnds.extent() * scaling;\r
 \r
-    if (scaling != 1)\r
+    if (scaling != 1.0) {\r
         x*=scaling;\r
+    }\r
+    if ( scale_y.get_value() && (scaling*prop_scale != 1.0) ) {\r
+        y*=(scaling*prop_scale);\r
+    }\r
 \r
     double offs = 0;\r
     Piecewise<D2<SBasis> > output;\r
index b92ea8ecf4063e45ab9c81c0893d8ee770f5b652..f92b64454959f12eadebc1bf2e8767c69d84b0ff 100644 (file)
@@ -12,6 +12,7 @@
 #include "live_effects/effect.h"\r
 #include "live_effects/parameter/path.h"\r
 #include "live_effects/parameter/enum.h"\r
+#include "live_effects/parameter/bool.h"\r
 \r
 namespace Inkscape {\r
 namespace LivePathEffect {\r
@@ -34,6 +35,8 @@ public:
 private:\r
     PathParam  pattern;\r
     EnumParam<SkelCopyType> copytype;\r
+    ScalarParam  prop_scale;\r
+    BoolParam scale_y;\r
 \r
     void on_pattern_pasted();\r
 \r
index af3449dff7f00f3e4618123c603e985d324c0de1..f0d4099555bf312933aa2a437bedc21ecbf4c327 100644 (file)
@@ -26,7 +26,7 @@ namespace LivePathEffect {
 BoolParam::BoolParam( const Glib::ustring& label, const Glib::ustring& tip,\r
                       const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,\r
                       Effect* effect, bool default_value )\r
-    : Parameter(label, tip, key, wr, effect), defvalue(default_value)\r
+    : Parameter(label, tip, key, wr, effect), defvalue(default_value), value(default_value)\r
 {\r
     checkwdg = NULL;\r
 }\r
index 24c10fb3b3f24b272f8fc9893ef1cc4bdc770996..0a29a94397093d2a151a2365268349742c1a63e4 100644 (file)
@@ -29,15 +29,15 @@ public:
                Inkscape::UI::Widget::Registry* wr,\r
                Effect* effect,\r
                bool default_value = false);\r
-    ~BoolParam();\r
+    virtual ~BoolParam();\r
 \r
-    Gtk::Widget * param_getWidget();\r
+    virtual Gtk::Widget * param_getWidget();\r
 \r
-    bool param_readSVGValue(const gchar * strvalue);\r
-    gchar * param_writeSVGValue() const;\r
+    virtual bool param_readSVGValue(const gchar * strvalue);\r
+    virtual gchar * param_writeSVGValue() const;\r
 \r
     void param_setValue(bool newvalue);\r
-    void param_set_default();\r
+    virtual void param_set_default();\r
 \r
     bool get_value() { return value; };\r
 \r
index 1453b37c74f1b82287ea1439d8a0f35aa612696f..8015308b6fc7deac0ac610814f1c6879d5c0aea3 100644 (file)
@@ -66,6 +66,7 @@ static char const menus_skeleton[] =
 "       <verb verb-id=\"EditPaste\" />\n"
 "       <verb verb-id=\"EditPasteInPlace\" />\n"
 "       <verb verb-id=\"EditPasteStyle\" />\n"
+"       <verb verb-id=\"EditPasteLivePathEffect\" />\n"
 "       <submenu name=\"" N_("Paste Si_ze") "\">\n"
 "           <verb verb-id=\"EditPasteSize\" />\n"
 "           <verb verb-id=\"EditPasteWidth\" />\n"
index 1e1f135f9d08b88c35bed8ae8ba6c314eda0f0a0..99f66130f318fe90beda22f1377bffd39b53be9e 100644 (file)
@@ -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 <b>object(s)</b> 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<SPItem*>(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;
index b21cbc2a182ccfa2a12ebdd88b76335d33ed86bb..a132161ef7ff0e7e463eefafac4ed3ddc66a738c 100644 (file)
@@ -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);
index ee010eeca4a12597eefc8f09e6f6cbf0d6114180..b801e53c8758738c89578bdae5f4ecb02aad1040 100644 (file)
@@ -230,6 +230,8 @@ LivePathEffectEditor::setDesktop(SPDesktop *desktop)
 # BUTTON CLICK HANDLERS    (callbacks)\r
 ########################################################################*/\r
 \r
+// TODO:  factor out the effect applying code which can be called from anywhere. (selection-chemistry.cpp also needs it)\r
+\r
 void\r
 LivePathEffectEditor::onApply()\r
 {\r
index 89237cf7f39866df34d989b0cf2f139a880a10c3..c325b6a073d99176763c06af4d7eeb81e36fa3cb 100644 (file)
@@ -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<SPDesktop*>(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"),
index a9100de7179312882fa249f166fe433aba093f1d..838a7581ca069d887dc8269882259af50d1f7153 100644 (file)
@@ -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,