Merge lp:~liampwhite/inkscape/inkscape into lp:inkscape/experimental

Proposed by Liam P. White on 2014-07-07
Status: Merged
Merged at revision: 13545
Proposed branch: lp:~liampwhite/inkscape/inkscape
Merge into: lp:inkscape/experimental
Diff against target: 12144 lines (+10546/-196)
97 files modified
po/POTFILES.in (+15/-0)
src/Makefile_insert (+3/-0)
src/attributes.cpp (+2/-0)
src/attributes.h (+2/-0)
src/display/cairo-utils.cpp (+1/-3)
src/display/cairo-utils.h (+3/-0)
src/display/drawing-item.cpp (+3/-2)
src/display/sp-canvas.cpp (+1/-1)
src/interface.cpp (+11/-0)
src/interface.h (+1/-0)
src/knotholder.cpp (+25/-11)
src/live_effects/CMakeLists.txt (+13/-0)
src/live_effects/Makefile_insert (+16/-0)
src/live_effects/effect-enum.h (+7/-0)
src/live_effects/effect.cpp (+71/-6)
src/live_effects/effect.h (+11/-0)
src/live_effects/lpe-attach-path.cpp (+198/-0)
src/live_effects/lpe-attach-path.h (+52/-0)
src/live_effects/lpe-bounding-box.cpp (+67/-0)
src/live_effects/lpe-bounding-box.h (+37/-0)
src/live_effects/lpe-ellipse_5pts.cpp (+214/-0)
src/live_effects/lpe-ellipse_5pts.h (+50/-0)
src/live_effects/lpe-fill-between-many.cpp (+78/-0)
src/live_effects/lpe-fill-between-many.h (+36/-0)
src/live_effects/lpe-fill-between-strokes.cpp (+116/-0)
src/live_effects/lpe-fill-between-strokes.h (+38/-0)
src/live_effects/lpe-jointype.cpp (+184/-0)
src/live_effects/lpe-jointype.h (+45/-0)
src/live_effects/lpe-knot.cpp (+4/-0)
src/live_effects/lpe-knot.h (+2/-1)
src/live_effects/lpe-powerstroke-interpolators.h (+40/-0)
src/live_effects/lpe-powerstroke.cpp (+89/-11)
src/live_effects/lpe-powerstroke.h (+2/-0)
src/live_effects/lpe-tangent_to_curve.cpp (+8/-11)
src/live_effects/lpe-tangent_to_curve.h (+0/-1)
src/live_effects/lpe-taperstroke.cpp (+630/-0)
src/live_effects/lpe-taperstroke.h (+72/-0)
src/live_effects/parameter/Makefile_insert (+4/-0)
src/live_effects/parameter/filletchamferpointarray.cpp (+3/-0)
src/live_effects/parameter/originalpatharray.cpp (+497/-0)
src/live_effects/parameter/originalpatharray.h (+123/-0)
src/live_effects/parameter/powerstrokepointarray.cpp (+36/-7)
src/live_effects/parameter/powerstrokepointarray.h (+21/-2)
src/live_effects/parameter/transformedpoint.cpp (+182/-0)
src/live_effects/parameter/transformedpoint.h (+87/-0)
src/live_effects/pathoutlineprovider.cpp (+795/-0)
src/live_effects/pathoutlineprovider.h (+55/-0)
src/menus-skeleton.h (+3/-0)
src/path-chemistry.cpp (+8/-0)
src/selection-chemistry.cpp (+159/-48)
src/selection-chemistry.h (+1/-0)
src/snap.cpp (+1/-1)
src/sp-item-group.cpp (+12/-0)
src/sp-item-group.h (+8/-0)
src/sp-item.cpp (+40/-0)
src/sp-item.h (+15/-0)
src/sp-lpe-item.cpp (+8/-2)
src/sp-object.h (+1/-0)
src/sp-tag-use-reference.cpp (+156/-0)
src/sp-tag-use-reference.h (+78/-0)
src/sp-tag-use.cpp (+206/-0)
src/sp-tag-use.h (+55/-0)
src/sp-tag.cpp (+154/-0)
src/sp-tag.h (+57/-0)
src/ui/dialog/Makefile_insert (+6/-0)
src/ui/dialog/calligraphic-profile-rename.h (+1/-1)
src/ui/dialog/color-item.cpp (+2/-0)
src/ui/dialog/dialog-manager.cpp (+6/-0)
src/ui/dialog/filedialog.h (+1/-0)
src/ui/dialog/lpe-powerstroke-properties.cpp (+211/-0)
src/ui/dialog/lpe-powerstroke-properties.h (+99/-0)
src/ui/dialog/objects.cpp (+2144/-0)
src/ui/dialog/objects.h (+263/-0)
src/ui/dialog/swatches.cpp (+32/-75)
src/ui/dialog/swatches.h (+0/-2)
src/ui/dialog/tags.cpp (+1165/-0)
src/ui/dialog/tags.h (+181/-0)
src/ui/tool/multi-path-manipulator.cpp (+3/-3)
src/ui/tool/multi-path-manipulator.h (+1/-1)
src/ui/tools/node-tool.cpp (+2/-1)
src/ui/tools/pen-tool.cpp (+3/-1)
src/ui/widget/Makefile_insert (+11/-2)
src/ui/widget/addtoicon.cpp (+157/-0)
src/ui/widget/addtoicon.h (+98/-0)
src/ui/widget/clipmaskicon.cpp (+184/-0)
src/ui/widget/clipmaskicon.h (+102/-0)
src/ui/widget/filter-effect-chooser.cpp (+2/-0)
src/ui/widget/filter-effect-chooser.h (+3/-1)
src/ui/widget/highlight-picker.cpp (+214/-0)
src/ui/widget/highlight-picker.h (+90/-0)
src/ui/widget/insertordericon.cpp (+173/-0)
src/ui/widget/insertordericon.h (+100/-0)
src/ui/widget/layertypeicon.cpp (+174/-0)
src/ui/widget/layertypeicon.h (+108/-0)
src/verbs.cpp (+92/-1)
src/verbs.h (+5/-0)
src/widgets/desktop-widget.cpp (+1/-1)
To merge this branch: bzr merge lp:~liampwhite/inkscape/inkscape
Reviewer Review Type Date Requested Status
Martin Owens 2014-07-07 Approve on 2014-09-14
Johan Engelen 2014-07-07 Pending
Review via email: mp+225765@code.launchpad.net

Description of the change

Proposing to merge to watch progression of diff.

To post a comment you must log in.
lp:~liampwhite/inkscape/inkscape updated on 2014-09-07
13179. By Liam P. White <inkscapebrony at-sign gmail dot com> on 2014-07-09

Update to experimental r13428

13180. By Liam P. White <inkscapebrony at-sign gmail dot com> on 2014-07-17

Update to experimental r13429

13181. By Liam P. White <inkscapebrony at-sign gmail dot com> on 2014-07-23

Duplicate LPE entries

13182. By Liam P. White <inkscapebrony at-sign gmail dot com> on 2014-07-23

Update to experimental r13436

13183. By Liam P. White <inkscapebrony at-sign gmail dot com> on 2014-07-23

This file does not need executable permissions

13184. By Liam P. White <inkscapebrony at-sign gmail dot com> on 2014-07-23

Refactoring of linejoin code

13185. By Liam P. White on 2014-07-30

Update to experimental r13452

13186. By Liam P. White on 2014-07-30

Fix make check

13187. By Liam P. White on 2014-07-31

I'm an idiot

13188. By Liam P. White on 2014-08-06

Update to experimental r13460

13189. By Liam P. White on 2014-08-08

Update to experimental r13464

13190. By Liam P. White on 2014-08-08

Messed up German translation (??)

13191. By Liam P. White on 2014-08-08

Ponyscape feature: finish pen drawing on context switch

13192. By Liam P. White on 2014-08-08

Update to experimental r13465

13193. By Liam P. White on 2014-08-12

Update to experimental r13479

13194. By Liam P. White on 2014-08-14

Clone Original -> Fill Between Many

13195. By Liam P. White on 2014-08-17

Update to experimental r13483

13196. By Liam P. White on 2014-08-31

Update to experimental r13531

13197. By Liam P. White on 2014-09-02

Fix gtk3 build

13198. By Liam P. White on 2014-09-07

Update to experimental r13543

Martin Owens (doctormo) wrote :

I've passed along a few clean up points over irc and I can't spot anything really bad. So I'm going ahead with a merge.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2014-08-30 15:50:55 +0000
+++ po/POTFILES.in 2014-09-07 17:02:32 +0000
@@ -153,7 +153,18 @@
153src/live_effects/lpe-skeleton.cpp153src/live_effects/lpe-skeleton.cpp
154src/live_effects/lpe-sketch.cpp154src/live_effects/lpe-sketch.cpp
155src/live_effects/lpe-vonkoch.cpp155src/live_effects/lpe-vonkoch.cpp
156src/live_effects/lpe-envelope-perspective.cpp
157src/live_effects/lpe-attach-path.cpp
158src/live_effects/lpe-bounding-box.cpp
159src/live_effects/lpe-ellipse_5pts.cpp
160src/live_effects/lpe-fill-between-many.cpp
161src/live_effects/lpe-fill-between-strokes.cpp
162src/live_effects/lpe-jointype.cpp
163src/live_effects/lpe-taperstroke.cpp
164src/live_effects/lpe-fillet-chamfer.cpp
156src/live_effects/parameter/filletchamferpointarray.cpp165src/live_effects/parameter/filletchamferpointarray.cpp
166src/live_effects/parameter/originalpatharray.cpp
167src/live_effects/parameter/transformedpoint.cpp
157src/live_effects/parameter/pointreseteable.cpp168src/live_effects/parameter/pointreseteable.cpp
158src/live_effects/parameter/togglebutton.cpp169src/live_effects/parameter/togglebutton.cpp
159src/live_effects/parameter/bool.cpp170src/live_effects/parameter/bool.cpp
@@ -260,6 +271,10 @@
260src/ui/dialog/tracedialog.cpp271src/ui/dialog/tracedialog.cpp
261src/ui/dialog/transformation.cpp272src/ui/dialog/transformation.cpp
262src/ui/dialog/xml-tree.cpp273src/ui/dialog/xml-tree.cpp
274src/ui/dialog/lpe-fillet-chamfer-properties.cpp
275src/ui/dialog/lpe-powerstroke-properties.cpp
276src/ui/dialog/objects.cpp
277src/ui/dialog/tags.cpp
263src/ui/tool/curve-drag-point.cpp278src/ui/tool/curve-drag-point.cpp
264src/ui/tool/multi-path-manipulator.cpp279src/ui/tool/multi-path-manipulator.cpp
265src/ui/tool/node.cpp280src/ui/tool/node.cpp
266281
=== modified file 'src/Makefile_insert'
--- src/Makefile_insert 2014-08-31 18:17:26 +0000
+++ src/Makefile_insert 2014-09-07 17:02:32 +0000
@@ -199,6 +199,9 @@
199 sp-style-elem.cpp sp-style-elem.h \199 sp-style-elem.cpp sp-style-elem.h \
200 sp-switch.cpp sp-switch.h \200 sp-switch.cpp sp-switch.h \
201 sp-symbol.cpp sp-symbol.h \201 sp-symbol.cpp sp-symbol.h \
202 sp-tag.cpp sp-tag.h \
203 sp-tag-use.cpp sp-tag-use.h \
204 sp-tag-use-reference.cpp sp-tag-use-reference.h \
202 sp-text.cpp sp-text.h \205 sp-text.cpp sp-text.h \
203 sp-textpath.h \206 sp-textpath.h \
204 sp-title.cpp sp-title.h \207 sp-title.cpp sp-title.h \
205208
=== modified file 'src/attributes.cpp'
--- src/attributes.cpp 2014-08-18 20:19:55 +0000
+++ src/attributes.cpp 2014-09-07 17:02:32 +0000
@@ -40,6 +40,7 @@
40 {SP_ATTR_TRANSFORM_CENTER_X, "inkscape:transform-center-x"},40 {SP_ATTR_TRANSFORM_CENTER_X, "inkscape:transform-center-x"},
41 {SP_ATTR_TRANSFORM_CENTER_Y, "inkscape:transform-center-y"},41 {SP_ATTR_TRANSFORM_CENTER_Y, "inkscape:transform-center-y"},
42 {SP_ATTR_INKSCAPE_PATH_EFFECT, "inkscape:path-effect"},42 {SP_ATTR_INKSCAPE_PATH_EFFECT, "inkscape:path-effect"},
43 {SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR, "inkscape:highlight-color"},
43 /* SPAnchor */44 /* SPAnchor */
44 {SP_ATTR_XLINK_HREF, "xlink:href"},45 {SP_ATTR_XLINK_HREF, "xlink:href"},
45 {SP_ATTR_XLINK_TYPE, "xlink:type"},46 {SP_ATTR_XLINK_TYPE, "xlink:type"},
@@ -50,6 +51,7 @@
50 {SP_ATTR_XLINK_ACTUATE, "xlink:actuate"},51 {SP_ATTR_XLINK_ACTUATE, "xlink:actuate"},
51 {SP_ATTR_TARGET, "target"},52 {SP_ATTR_TARGET, "target"},
52 {SP_ATTR_INKSCAPE_GROUPMODE, "inkscape:groupmode"},53 {SP_ATTR_INKSCAPE_GROUPMODE, "inkscape:groupmode"},
54 {SP_ATTR_INKSCAPE_EXPANDED, "inkscape:expanded"},
53 /* SPRoot */55 /* SPRoot */
54 {SP_ATTR_VERSION, "version"},56 {SP_ATTR_VERSION, "version"},
55 {SP_ATTR_WIDTH, "width"},57 {SP_ATTR_WIDTH, "width"},
5658
=== modified file 'src/attributes.h'
--- src/attributes.h 2014-08-04 16:19:41 +0000
+++ src/attributes.h 2014-09-07 17:02:32 +0000
@@ -40,6 +40,7 @@
40 SP_ATTR_TRANSFORM_CENTER_X,40 SP_ATTR_TRANSFORM_CENTER_X,
41 SP_ATTR_TRANSFORM_CENTER_Y,41 SP_ATTR_TRANSFORM_CENTER_Y,
42 SP_ATTR_INKSCAPE_PATH_EFFECT,42 SP_ATTR_INKSCAPE_PATH_EFFECT,
43 SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR,
43 /* SPAnchor */44 /* SPAnchor */
44 SP_ATTR_XLINK_HREF,45 SP_ATTR_XLINK_HREF,
45 SP_ATTR_XLINK_TYPE,46 SP_ATTR_XLINK_TYPE,
@@ -51,6 +52,7 @@
51 SP_ATTR_TARGET,52 SP_ATTR_TARGET,
52 /* SPGroup */53 /* SPGroup */
53 SP_ATTR_INKSCAPE_GROUPMODE,54 SP_ATTR_INKSCAPE_GROUPMODE,
55 SP_ATTR_INKSCAPE_EXPANDED,
54 /* SPRoot */56 /* SPRoot */
55 SP_ATTR_VERSION,57 SP_ATTR_VERSION,
56 SP_ATTR_WIDTH,58 SP_ATTR_WIDTH,
5759
=== modified file 'src/display/cairo-utils.cpp'
--- src/display/cairo-utils.cpp 2014-09-06 15:25:51 +0000
+++ src/display/cairo-utils.cpp 2014-09-07 17:02:32 +0000
@@ -33,8 +33,6 @@
33#include "helper/geom-curves.h"33#include "helper/geom-curves.h"
34#include "display/cairo-templates.h"34#include "display/cairo-templates.h"
3535
36static void ink_cairo_pixbuf_cleanup(guchar *, void *);
37
38/**36/**
39 * Key for cairo_surface_t to keep track of current color interpolation value37 * Key for cairo_surface_t to keep track of current color interpolation value
40 * Only the address of the structure is used, it is never initialized. See:38 * Only the address of the structure is used, it is never initialized. See:
@@ -1172,7 +1170,7 @@
1172 * to gdk_pixbuf_new_from_data when creating a GdkPixbuf backed by1170 * to gdk_pixbuf_new_from_data when creating a GdkPixbuf backed by
1173 * a Cairo surface.1171 * a Cairo surface.
1174 */1172 */
1175static void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data)1173void ink_cairo_pixbuf_cleanup(guchar * /*pixels*/, void *data)
1176{1174{
1177 cairo_surface_t *surface = static_cast<cairo_surface_t*>(data);1175 cairo_surface_t *surface = static_cast<cairo_surface_t*>(data);
1178 cairo_surface_destroy(surface);1176 cairo_surface_destroy(surface);
11791177
=== modified file 'src/display/cairo-utils.h'
--- src/display/cairo-utils.h 2014-08-30 17:23:17 +0000
+++ src/display/cairo-utils.h 2014-09-07 17:02:32 +0000
@@ -20,6 +20,9 @@
20struct SPColor;20struct SPColor;
21typedef struct _GdkPixbuf GdkPixbuf;21typedef struct _GdkPixbuf GdkPixbuf;
2222
23void ink_cairo_pixbuf_cleanup(unsigned char *, void *);
24void convert_pixbuf_argb32_to_normal(GdkPixbuf *pb);
25
23namespace Inkscape {26namespace Inkscape {
2427
25/**28/**
2629
=== modified file 'src/display/drawing-item.cpp'
--- src/display/drawing-item.cpp 2014-08-18 21:18:05 +0000
+++ src/display/drawing-item.cpp 2014-09-07 17:02:32 +0000
@@ -825,9 +825,10 @@
825{825{
826 // Sometimes there's no BBOX in state, reason unknown (bug 992817)826 // Sometimes there's no BBOX in state, reason unknown (bug 992817)
827 // I made this not an assert to remove the warning827 // I made this not an assert to remove the warning
828 // This warning clutters the console output, so commented out
828 if (!(_state & STATE_BBOX) || !(_state & STATE_PICK)) {829 if (!(_state & STATE_BBOX) || !(_state & STATE_PICK)) {
829 g_warning("Invalid state when picking: STATE_BBOX = %d, STATE_PICK = %d",830 /*g_warning("Invalid state when picking: STATE_BBOX = %d, STATE_PICK = %d",
830 _state & STATE_BBOX, _state & STATE_PICK);831 _state & STATE_BBOX, _state & STATE_PICK);*/
831 return NULL;832 return NULL;
832 }833 }
833 // ignore invisible and insensitive items unless sticky834 // ignore invisible and insensitive items unless sticky
834835
=== modified file 'src/display/sp-canvas.cpp'
--- src/display/sp-canvas.cpp 2014-08-26 11:14:18 +0000
+++ src/display/sp-canvas.cpp 2014-09-07 17:02:32 +0000
@@ -1146,7 +1146,7 @@
1146sp_canvas_init(SPCanvas *canvas)1146sp_canvas_init(SPCanvas *canvas)
1147{1147{
1148 gtk_widget_set_has_window (GTK_WIDGET (canvas), TRUE);1148 gtk_widget_set_has_window (GTK_WIDGET (canvas), TRUE);
1149 //gtk_widget_set_double_buffered (GTK_WIDGET (canvas), TRUE);1149 gtk_widget_set_double_buffered (GTK_WIDGET (canvas), FALSE);
1150 gtk_widget_set_can_focus (GTK_WIDGET (canvas), TRUE);1150 gtk_widget_set_can_focus (GTK_WIDGET (canvas), TRUE);
11511151
1152 canvas->pick_event.type = GDK_LEAVE_NOTIFY;1152 canvas->pick_event.type = GDK_LEAVE_NOTIFY;
11531153
=== modified file 'src/interface.cpp'
--- src/interface.cpp 2014-09-02 21:14:55 +0000
+++ src/interface.cpp 2014-09-07 17:02:32 +0000
@@ -1756,6 +1756,13 @@
1756 }1756 }
1757 mi->show();1757 mi->show();
1758 append(*mi);1758 append(*mi);
1759
1760 /*SSet Clip Group */
1761 mi = Gtk::manage(new Gtk::MenuItem(_("Create Clip G_roup"),1));
1762 mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::CreateGroupClip));
1763 mi->set_sensitive(TRUE);
1764 mi->show();
1765 append(*mi);
1759 1766
1760 /* Set Clip */1767 /* Set Clip */
1761 mi = Gtk::manage(new Gtk::MenuItem(_("Set Cl_ip"), 1));1768 mi = Gtk::manage(new Gtk::MenuItem(_("Set Cl_ip"), 1));
@@ -1867,6 +1874,10 @@
1867 sp_selection_unset_mask(_desktop, false);1874 sp_selection_unset_mask(_desktop, false);
1868}1875}
18691876
1877void ContextMenu::CreateGroupClip(void)
1878{
1879 sp_selection_set_clipgroup(_desktop);
1880}
18701881
1871void ContextMenu::SetClip(void)1882void ContextMenu::SetClip(void)
1872{1883{
18731884
=== modified file 'src/interface.h'
--- src/interface.h 2014-08-31 18:17:26 +0000
+++ src/interface.h 2014-09-07 17:02:32 +0000
@@ -183,6 +183,7 @@
183 void SelectSameStrokeStyle(void);183 void SelectSameStrokeStyle(void);
184 void SelectSameObjectType(void);184 void SelectSameObjectType(void);
185 void ItemCreateLink(void);185 void ItemCreateLink(void);
186 void CreateGroupClip(void);
186 void SetMask(void);187 void SetMask(void);
187 void ReleaseMask(void);188 void ReleaseMask(void);
188 void SetClip(void);189 void SetClip(void);
189190
=== modified file 'src/knotholder.cpp'
--- src/knotholder.cpp 2014-08-04 16:10:37 +0000
+++ src/knotholder.cpp 2014-09-07 17:02:32 +0000
@@ -154,8 +154,15 @@
154 }154 }
155155
156 // for drag, this is done by ungrabbed_handler, but for click we must do it here156 // for drag, this is done by ungrabbed_handler, but for click we must do it here
157 DocumentUndo::done(saved_item->document, object_verb,157
158 _("Change handle"));158 if (saved_item) { //increasingly aggressive sanity checks
159 if (saved_item->document) {
160 if (object_verb <= SP_VERB_LAST && object_verb >= SP_VERB_INVALID) {
161 DocumentUndo::done(saved_item->document, object_verb,
162 _("Change handle"));
163 }
164 }
165 } // else { abort(); }
159}166}
160167
161void168void
@@ -203,14 +210,16 @@
203 /* do cleanup tasks (e.g., for LPE items write the parameter values210 /* do cleanup tasks (e.g., for LPE items write the parameter values
204 * that were changed by dragging the handle to SVG)211 * that were changed by dragging the handle to SVG)
205 */212 */
206 if (SP_IS_LPE_ITEM(object)) {213 if (dynamic_cast<SPLPEItem*> (object)) {
207 // This writes all parameters to SVG. Is this sufficiently efficient or should we only214 // This writes all parameters to SVG. Is this sufficiently efficient or should we only
208 // write the ones that were changed?215 // write the ones that were changed?
209216 SPLPEItem * lpeitem = SP_LPE_ITEM(object);
210 Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(object)->getCurrentLPE();217 if (lpeitem) {
211 if (lpe) {218 Inkscape::LivePathEffect::Effect *lpe = lpeitem->getCurrentLPE();
212 LivePathEffectObject *lpeobj = lpe->getLPEObj();219 if (lpe) {
213 lpeobj->updateRepr();220 LivePathEffectObject *lpeobj = lpe->getLPEObj();
221 lpeobj->updateRepr();
222 }
214 }223 }
215 }224 }
216225
@@ -232,9 +241,14 @@
232 else241 else
233 object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET;242 object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET;
234 }243 }
235244 if (object) { //increasingly aggressive sanity checks
236 DocumentUndo::done(object->document, object_verb,245 if (object->document) {
237 _("Move handle"));246 if (object_verb <= SP_VERB_LAST && object_verb >= SP_VERB_INVALID) {
247 DocumentUndo::done(object->document, object_verb,
248 _("Move handle"));
249 }
250 }
251 } //else { abort(); }
238 }252 }
239}253}
240254
241255
=== modified file 'src/live_effects/CMakeLists.txt'
--- src/live_effects/CMakeLists.txt 2014-08-12 22:30:34 +0000
+++ src/live_effects/CMakeLists.txt 2014-09-07 17:02:32 +0000
@@ -2,8 +2,10 @@
2set(live_effects_SRC2set(live_effects_SRC
3 effect.cpp3 effect.cpp
4 lpe-angle_bisector.cpp4 lpe-angle_bisector.cpp
5 lpe-attach-path.cpp
5 lpe-bendpath.cpp6 lpe-bendpath.cpp
6 lpe-boolops.cpp7 lpe-boolops.cpp
8 lpe-bounding-box.cpp
7 lpe-circle_3pts.cpp9 lpe-circle_3pts.cpp
8 lpe-circle_with_radius.cpp10 lpe-circle_with_radius.cpp
9 lpe-clone-original.cpp11 lpe-clone-original.cpp
@@ -11,9 +13,12 @@
11 lpe-copy_rotate.cpp13 lpe-copy_rotate.cpp
12 lpe-curvestitch.cpp14 lpe-curvestitch.cpp
13 lpe-dynastroke.cpp15 lpe-dynastroke.cpp
16 lpe-ellipse-5pts.cpp
14 lpe-envelope.cpp17 lpe-envelope.cpp
15 lpe-envelope-perspective.cpp18 lpe-envelope-perspective.cpp
16 lpe-extrude.cpp19 lpe-extrude.cpp
20 lpe-fill-between-many.cpp
21 lpe-fill-between-strokes.cpp
17 lpe-fillet-chamfer.cpp22 lpe-fillet-chamfer.cpp
18 lpe-gears.cpp23 lpe-gears.cpp
19 lpe-interpolate.cpp24 lpe-interpolate.cpp
@@ -55,11 +60,13 @@
55 parameter/parameter.cpp60 parameter/parameter.cpp
56 parameter/path.cpp61 parameter/path.cpp
57 parameter/originalpath.cpp62 parameter/originalpath.cpp
63 parameter/originalpatharray.cpp
58 parameter/path-reference.cpp64 parameter/path-reference.cpp
59 parameter/point.cpp65 parameter/point.cpp
60 parameter/powerstrokepointarray.cpp66 parameter/powerstrokepointarray.cpp
61 parameter/random.cpp67 parameter/random.cpp
62 parameter/text.cpp68 parameter/text.cpp
69 paramter/transformedpoint.cpp
63 parameter/togglebutton.cpp70 parameter/togglebutton.cpp
64 parameter/unit.cpp71 parameter/unit.cpp
65 parameter/vector.cpp72 parameter/vector.cpp
@@ -70,8 +77,10 @@
70 effect-enum.h77 effect-enum.h
71 effect.h78 effect.h
72 lpe-angle_bisector.h79 lpe-angle_bisector.h
80 lpe-attach-path.h
73 lpe-bendpath.h81 lpe-bendpath.h
74 lpe-boolops.h82 lpe-boolops.h
83 lpe-bounding-box.h
75 lpe-circle_3pts.h84 lpe-circle_3pts.h
76 lpe-circle_with_radius.h85 lpe-circle_with_radius.h
77 lpe-clone-original.h86 lpe-clone-original.h
@@ -79,8 +88,11 @@
79 lpe-copy_rotate.h88 lpe-copy_rotate.h
80 lpe-curvestitch.h89 lpe-curvestitch.h
81 lpe-dynastroke.h90 lpe-dynastroke.h
91 lpe-ellipse-5pts.h
82 lpe-envelope.h92 lpe-envelope.h
83 lpe-extrude.h93 lpe-extrude.h
94 lpe-fill-between-many.h
95 lpe-fill-between-strokes.h
84 lpe-fillet-chamfer.h96 lpe-fillet-chamfer.h
85 lpe-gears.h97 lpe-gears.h
86 lpe-interpolate.h98 lpe-interpolate.h
@@ -125,6 +137,7 @@
125 parameter/path-reference.h137 parameter/path-reference.h
126 parameter/path.h138 parameter/path.h
127 parameter/originalpath.h139 parameter/originalpath.h
140 parameter/originalpatharray.h
128 parameter/point.h141 parameter/point.h
129 parameter/powerstrokepointarray.h142 parameter/powerstrokepointarray.h
130 parameter/random.h143 parameter/random.h
131144
=== modified file 'src/live_effects/Makefile_insert'
--- src/live_effects/Makefile_insert 2014-08-23 16:39:36 +0000
+++ src/live_effects/Makefile_insert 2014-09-07 17:02:32 +0000
@@ -97,5 +97,21 @@
97 live_effects/lpe-path_length.h \97 live_effects/lpe-path_length.h \
98 live_effects/lpe-line_segment.cpp \98 live_effects/lpe-line_segment.cpp \
99 live_effects/lpe-line_segment.h \99 live_effects/lpe-line_segment.h \
100 live_effects/lpe-bounding-box.cpp \
101 live_effects/lpe-bounding-box.h \
102 live_effects/lpe-attach-path.cpp \
103 live_effects/lpe-attach-path.h \
104 live_effects/lpe-fill-between-strokes.cpp \
105 live_effects/lpe-fill-between-strokes.h \
106 live_effects/lpe-fill-between-many.cpp \
107 live_effects/lpe-fill-between-many.h \
108 live_effects/lpe-ellipse_5pts.cpp \
109 live_effects/lpe-ellipse_5pts.h \
110 live_effects/pathoutlineprovider.cpp \
111 live_effects/pathoutlineprovider.h \
112 live_effects/lpe-jointype.cpp \
113 live_effects/lpe-jointype.h \
114 live_effects/lpe-taperstroke.cpp \
115 live_effects/lpe-taperstroke.h \
100 live_effects/lpe-envelope-perspective.cpp \116 live_effects/lpe-envelope-perspective.cpp \
101 live_effects/lpe-envelope-perspective.h117 live_effects/lpe-envelope-perspective.h
102118
=== modified file 'src/live_effects/effect-enum.h'
--- src/live_effects/effect-enum.h 2014-08-23 16:39:36 +0000
+++ src/live_effects/effect-enum.h 2014-09-07 17:02:32 +0000
@@ -56,6 +56,13 @@
56 EXTRUDE,56 EXTRUDE,
57 POWERSTROKE,57 POWERSTROKE,
58 CLONE_ORIGINAL,58 CLONE_ORIGINAL,
59 ATTACH_PATH,
60 FILL_BETWEEN_STROKES,
61 FILL_BETWEEN_MANY,
62 ELLIPSE_5PTS,
63 BOUNDING_BOX,
64 JOIN_TYPE,
65 TAPER_STROKE,
59 ENVELOPE_PERSPECTIVE,66 ENVELOPE_PERSPECTIVE,
60 FILLET_CHAMFER,67 FILLET_CHAMFER,
61 INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan)68 INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan)
6269
=== modified file 'src/live_effects/effect.cpp'
--- src/live_effects/effect.cpp 2014-08-23 16:39:36 +0000
+++ src/live_effects/effect.cpp 2014-09-07 17:02:32 +0000
@@ -5,6 +5,8 @@
5 * Released under GNU GPL, read the file 'COPYING' for more information5 * Released under GNU GPL, read the file 'COPYING' for more information
6 */6 */
77
8//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects
9
8#ifdef HAVE_CONFIG_H10#ifdef HAVE_CONFIG_H
9# include "config.h"11# include "config.h"
10#endif12#endif
@@ -19,7 +21,6 @@
19#include "live_effects/lpe-rough-hatches.h"21#include "live_effects/lpe-rough-hatches.h"
20#include "live_effects/lpe-dynastroke.h"22#include "live_effects/lpe-dynastroke.h"
21#include "live_effects/lpe-test-doEffect-stack.h"23#include "live_effects/lpe-test-doEffect-stack.h"
22#include "live_effects/lpe-bspline.h"
23#include "live_effects/lpe-gears.h"24#include "live_effects/lpe-gears.h"
24#include "live_effects/lpe-curvestitch.h"25#include "live_effects/lpe-curvestitch.h"
25#include "live_effects/lpe-circle_with_radius.h"26#include "live_effects/lpe-circle_with_radius.h"
@@ -51,6 +52,14 @@
51#include "live_effects/lpe-extrude.h"52#include "live_effects/lpe-extrude.h"
52#include "live_effects/lpe-powerstroke.h"53#include "live_effects/lpe-powerstroke.h"
53#include "live_effects/lpe-clone-original.h"54#include "live_effects/lpe-clone-original.h"
55#include "live_effects/lpe-bspline.h"
56#include "live_effects/lpe-attach-path.h"
57#include "live_effects/lpe-fill-between-strokes.h"
58#include "live_effects/lpe-fill-between-many.h"
59#include "live_effects/lpe-ellipse_5pts.h"
60#include "live_effects/lpe-bounding-box.h"
61#include "live_effects/lpe-jointype.h"
62#include "live_effects/lpe-taperstroke.h"
54#include "live_effects/lpe-envelope-perspective.h"63#include "live_effects/lpe-envelope-perspective.h"
55#include "live_effects/lpe-fillet-chamfer.h"64#include "live_effects/lpe-fillet-chamfer.h"
5665
@@ -132,10 +141,18 @@
132 {SHOW_HANDLES, N_("Show handles"), "show_handles"},141 {SHOW_HANDLES, N_("Show handles"), "show_handles"},
133 {ROUGHEN, N_("Roughen"), "roughen"},142 {ROUGHEN, N_("Roughen"), "roughen"},
134 {BSPLINE, N_("BSpline"), "bspline"},143 {BSPLINE, N_("BSpline"), "bspline"},
135 {SIMPLIFY, N_("Simplify"), "simplify"},144 {JOIN_TYPE, N_("Join type"), "join_type"},
136 {LATTICE2, N_("Lattice Deformation 2"), "lattice2"},145 {TAPER_STROKE, N_("Taper stroke"), "taper_stroke"},
137 // TRANSLATORS: "Envelope Perspective" should be equivalent to "perspective transformation"146/* Ponyscape */
138 {ENVELOPE_PERSPECTIVE, N_("Envelope Perspective"), "envelope-perspective"},147 {ATTACH_PATH, N_("Attach path"), "attach_path"},
148 {FILL_BETWEEN_STROKES, N_("Fill between strokes"), "fill_between_strokes"},
149 {FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"},
150 {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"},
151 {BOUNDING_BOX, N_("Bounding Box"), "bounding_box"},
152/* 0.91 */
153 {SIMPLIFY, N_("Simplify"), "simplify"},
154 {LATTICE2, N_("Lattice Deformation 2"), "lattice2"},
155 {ENVELOPE_PERSPECTIVE, N_("Envelope-Perspective"), "envelope-perspective"},
139 {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"},156 {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet-chamfer"},
140 {INTERPOLATE_POINTS, N_("Interpolate points"), "interpolate_points"},157 {INTERPOLATE_POINTS, N_("Interpolate points"), "interpolate_points"},
141};158};
@@ -267,6 +284,27 @@
267 case CLONE_ORIGINAL:284 case CLONE_ORIGINAL:
268 neweffect = static_cast<Effect*> ( new LPECloneOriginal(lpeobj) );285 neweffect = static_cast<Effect*> ( new LPECloneOriginal(lpeobj) );
269 break;286 break;
287 case ATTACH_PATH:
288 neweffect = static_cast<Effect*> ( new LPEAttachPath(lpeobj) );
289 break;
290 case FILL_BETWEEN_STROKES:
291 neweffect = static_cast<Effect*> ( new LPEFillBetweenStrokes(lpeobj) );
292 break;
293 case FILL_BETWEEN_MANY:
294 neweffect = static_cast<Effect*> ( new LPEFillBetweenMany(lpeobj) );
295 break;
296 case ELLIPSE_5PTS:
297 neweffect = static_cast<Effect*> ( new LPEEllipse5Pts(lpeobj) );
298 break;
299 case BOUNDING_BOX:
300 neweffect = static_cast<Effect*> ( new LPEBoundingBox(lpeobj) );
301 break;
302 case JOIN_TYPE:
303 neweffect = static_cast<Effect*> ( new LPEJoinType(lpeobj) );
304 break;
305 case TAPER_STROKE:
306 neweffect = static_cast<Effect*> ( new LPETaperStroke(lpeobj) );
307 break;
270 case SIMPLIFY:308 case SIMPLIFY:
271 neweffect = static_cast<Effect*> ( new LPESimplify(lpeobj) );309 neweffect = static_cast<Effect*> ( new LPESimplify(lpeobj) );
272 break;310 break;
@@ -286,7 +324,7 @@
286 neweffect = static_cast<Effect*> ( new LPEShowHandles(lpeobj) );324 neweffect = static_cast<Effect*> ( new LPEShowHandles(lpeobj) );
287 break;325 break;
288 default:326 default:
289 g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);327 g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
290 neweffect = NULL;328 neweffect = NULL;
291 break;329 break;
292 }330 }
@@ -369,6 +407,33 @@
369 //Do nothing for simple effects407 //Do nothing for simple effects
370}408}
371409
410void Effect::doAfterEffect (SPLPEItem const* lpeitem)
411{
412}
413
414void Effect::doOnRemove (SPLPEItem const* lpeitem)
415{
416}
417
418//secret impl methods (shhhh!)
419void Effect::doOnApply_impl(SPLPEItem const* lpeitem)
420{
421 sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
422 /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve();
423 pathvector_before_effect = sp_curve->get_pathvector();*/
424 doOnApply(lpeitem);
425}
426
427void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem)
428{
429 sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
430 //printf("(SPLPEITEM*) %p\n", sp_lpe_item);
431 sp_curve = SP_SHAPE(sp_lpe_item)->getCurve();
432 pathvector_before_effect = sp_curve->get_pathvector();
433
434 doBeforeEffect(lpeitem);
435}
436
372/**437/**
373 * Effects can have a parameter path set before they are applied by accepting a nonzero number of438 * Effects can have a parameter path set before they are applied by accepting a nonzero number of
374 * mouse clicks. This method activates the pen context, which waits for the specified number of439 * mouse clicks. This method activates the pen context, which waits for the specified number of
375440
=== modified file 'src/live_effects/effect.h'
--- src/live_effects/effect.h 2014-05-05 07:13:35 +0000
+++ src/live_effects/effect.h 2014-09-07 17:02:32 +0000
@@ -53,8 +53,16 @@
5353
54 EffectType effectType() const;54 EffectType effectType() const;
5555
56 //basically, to get this method called before the derived classes, a bit
57 //of indirection is needed. We first call these methods, then the below.
58 void doOnApply_impl(SPLPEItem const* lpeitem);
59 void doBeforeEffect_impl(SPLPEItem const* lpeitem);
60
56 virtual void doOnApply (SPLPEItem const* lpeitem);61 virtual void doOnApply (SPLPEItem const* lpeitem);
57 virtual void doBeforeEffect (SPLPEItem const* lpeitem);62 virtual void doBeforeEffect (SPLPEItem const* lpeitem);
63
64 virtual void doAfterEffect (SPLPEItem const* lpeitem);
65 virtual void doOnRemove (SPLPEItem const* lpeitem);
5866
59 void writeParamsToSVG();67 void writeParamsToSVG();
6068
@@ -147,6 +155,9 @@
147 // instead of normally 'splitting' the path into continuous pwd2 paths and calling doEffect_pwd2 for each.155 // instead of normally 'splitting' the path into continuous pwd2 paths and calling doEffect_pwd2 for each.
148 bool concatenate_before_pwd2;156 bool concatenate_before_pwd2;
149157
158 SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
159 SPCurve * sp_curve;
160 std::vector<Geom::Path> pathvector_before_effect;
150private:161private:
151 bool provides_own_flash_paths; // if true, the standard flash path is suppressed162 bool provides_own_flash_paths; // if true, the standard flash path is suppressed
152163
153164
=== added file 'src/live_effects/lpe-attach-path.cpp'
--- src/live_effects/lpe-attach-path.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-attach-path.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,198 @@
1/*
2 * Copyright (C) Johan Engelen 2012 <j.b.c.engelen@alumnus.utwente.nl>
3 *
4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */
6
7#include <glibmm/i18n.h>
8#include <math.h>
9
10#include "live_effects/lpe-attach-path.h"
11
12#include "display/curve.h"
13#include "sp-item.h"
14#include "2geom/path.h"
15#include "sp-shape.h"
16#include "sp-text.h"
17#include "2geom/bezier-curve.h"
18#include "2geom/path-sink.h"
19#include "parameter/parameter.h"
20#include "live_effects/parameter/point.h"
21#include "parameter/originalpath.h"
22#include "2geom/affine.h"
23
24namespace Inkscape {
25namespace LivePathEffect {
26
27LPEAttachPath::LPEAttachPath(LivePathEffectObject *lpeobject) :
28 Effect(lpeobject),
29 start_path(_("Start path:"), _("Path to attach to the start of this path"), "startpath", &wr, this),
30 start_path_position(_("Start path position:"), _("Position to attach path start to"), "startposition", &wr, this, 0.0),
31 start_path_curve_start(_("Start path curve start:"), _("Starting curve"), "startcurvestart", &wr, this, Geom::Point(20,0)/*, true*/),
32 start_path_curve_end(_("Start path curve end:"), _("Ending curve"), "startcurveend", &wr, this, Geom::Point(20,0)/*, true*/),
33 end_path(_("End path:"), _("Path to attach to the end of this path"), "endpath", &wr, this),
34 end_path_position(_("End path position:"), _("Position to attach path end to"), "endposition", &wr, this, 0.0),
35 end_path_curve_start(_("End path curve start:"), _("Starting curve"), "endcurvestart", &wr, this, Geom::Point(20,0)/*, true*/),
36 end_path_curve_end(_("End path curve end:"), _("Ending curve"), "endcurveend", &wr, this, Geom::Point(20,0)/*, true*/)
37{
38 registerParameter( dynamic_cast<Parameter *>(&start_path) );
39 registerParameter( dynamic_cast<Parameter *>(&start_path_position) );
40 registerParameter( dynamic_cast<Parameter *>(&start_path_curve_start) );
41 registerParameter( dynamic_cast<Parameter *>(&start_path_curve_end) );
42
43 registerParameter( dynamic_cast<Parameter *>(&end_path) );
44 registerParameter( dynamic_cast<Parameter *>(&end_path_position) );
45 registerParameter( dynamic_cast<Parameter *>(&end_path_curve_start) );
46 registerParameter( dynamic_cast<Parameter *>(&end_path_curve_end) );
47
48 //perceived_path = true;
49 show_orig_path = true;
50 curve_start_previous_origin = start_path_curve_end.getOrigin();
51 curve_end_previous_origin = end_path_curve_end.getOrigin();
52}
53
54LPEAttachPath::~LPEAttachPath()
55{
56
57}
58
59void LPEAttachPath::resetDefaults(SPItem const * item)
60{
61 curve_start_previous_origin = start_path_curve_end.getOrigin();
62 curve_end_previous_origin = end_path_curve_end.getOrigin();
63}
64
65void LPEAttachPath::doEffect (SPCurve * curve)
66{
67 std::vector<Geom::Path> this_pathv = curve->get_pathvector();
68 if (sp_lpe_item && !this_pathv.empty()) {
69 Geom::Path p = Geom::Path(this_pathv.front().initialPoint());
70
71 bool set_start_end = start_path_curve_end.getOrigin() != curve_start_previous_origin;
72 bool set_end_end = end_path_curve_end.getOrigin() != curve_end_previous_origin;
73
74 if (start_path.linksToPath()) {
75
76 std::vector<Geom::Path> linked_pathv = start_path.get_pathvector();
77 Geom::Affine linkedtransform = start_path.getObject()->getRelativeTransform(sp_lpe_item);
78
79 if ( !linked_pathv.empty() )
80 {
81 Geom::Path transformedpath = linked_pathv.front() * linkedtransform;
82 start_path_curve_start.setOrigin(this_pathv.front().initialPoint());
83
84 std::vector<Geom::Point> derivs = this_pathv.front().front().pointAndDerivatives(0, 3);
85
86 for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) {
87 Geom::Coord length = derivs[deriv_n].length();
88 if ( ! Geom::are_near(length, 0) ) {
89 if (set_start_end) {
90 start_path_position.param_set_value(transformedpath.nearestPoint(start_path_curve_end.getOrigin()));
91 }
92
93 if (start_path_position > transformedpath.size()) {
94 start_path_position.param_set_value(transformedpath.size());
95 } else if (start_path_position < 0) {
96 start_path_position.param_set_value(0);
97 }
98 const Geom::Curve *c = start_path_position >= transformedpath.size() ? &transformedpath.back() : &transformedpath.at_index((int)start_path_position);
99
100 std::vector<Geom::Point> derivs_2 = c->pointAndDerivatives(start_path_position >= transformedpath.size() ? 1 : (start_path_position - (int)start_path_position), 3);
101 for (unsigned deriv_n_2 = 1; deriv_n_2 < derivs_2.size(); deriv_n_2++) {
102 Geom::Coord length_2 = derivs[deriv_n_2].length();
103 if ( ! Geom::are_near(length_2, 0) ) {
104 start_path_curve_end.setOrigin(derivs_2[0]);
105 curve_start_previous_origin = start_path_curve_end.getOrigin();
106
107 double startangle = atan2(start_path_curve_start.getVector().y(), start_path_curve_start.getVector().x());
108 double endangle = atan2(start_path_curve_end.getVector().y(), start_path_curve_end.getVector().x());
109 double startderiv = atan2(derivs[deriv_n].y(), derivs[deriv_n].x());
110 double endderiv = atan2(derivs_2[deriv_n_2].y(), derivs_2[deriv_n_2].x());
111 Geom::Point pt1 = Geom::Point(start_path_curve_start.getVector().length() * cos(startangle + startderiv), start_path_curve_start.getVector().length() * sin(startangle + startderiv));
112 Geom::Point pt2 = Geom::Point(start_path_curve_end.getVector().length() * cos(endangle + endderiv), start_path_curve_end.getVector().length() * sin(endangle + endderiv));
113 p = Geom::Path(derivs_2[0]);
114 p.appendNew<Geom::CubicBezier>(-pt2 + derivs_2[0], -pt1 + this_pathv.front().initialPoint(), this_pathv.front().initialPoint());
115 break;
116
117 }
118 }
119 break;
120 }
121 }
122 }
123 }
124
125 p.append(this_pathv.front());
126
127 if (end_path.linksToPath()) {
128
129 std::vector<Geom::Path> linked_pathv = end_path.get_pathvector();
130 Geom::Affine linkedtransform = end_path.getObject()->getRelativeTransform(sp_lpe_item);
131
132 if ( !linked_pathv.empty() )
133 {
134 Geom::Path transformedpath = linked_pathv.front() * linkedtransform;
135 Geom::Curve * last_seg_reverse = this_pathv.front().back().reverse();
136
137 end_path_curve_start.setOrigin(last_seg_reverse->initialPoint());
138
139 std::vector<Geom::Point> derivs = last_seg_reverse->pointAndDerivatives(0, 3);
140 for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) {
141 Geom::Coord length = derivs[deriv_n].length();
142 if ( ! Geom::are_near(length, 0) ) {
143 if (set_end_end) {
144 end_path_position.param_set_value(transformedpath.nearestPoint(end_path_curve_end.getOrigin()));
145 }
146
147 if (end_path_position > transformedpath.size()) {
148 end_path_position.param_set_value(transformedpath.size());
149 } else if (end_path_position < 0) {
150 end_path_position.param_set_value(0);
151 }
152 const Geom::Curve *c = end_path_position >= transformedpath.size() ? &transformedpath.back() : &transformedpath.at_index((int)end_path_position);
153
154 std::vector<Geom::Point> derivs_2 = c->pointAndDerivatives(end_path_position >= transformedpath.size() ? 1 : (end_path_position - (int)end_path_position), 3);
155 for (unsigned deriv_n_2 = 1; deriv_n_2 < derivs_2.size(); deriv_n_2++) {
156 Geom::Coord length_2 = derivs[deriv_n_2].length();
157 if ( ! Geom::are_near(length_2, 0) ) {
158
159 end_path_curve_end.setOrigin(derivs_2[0]);
160 curve_end_previous_origin = end_path_curve_end.getOrigin();
161
162 double startangle = atan2(end_path_curve_start.getVector().y(), end_path_curve_start.getVector().x());
163 double endangle = atan2(end_path_curve_end.getVector().y(), end_path_curve_end.getVector().x());
164 double startderiv = atan2(derivs[deriv_n].y(), derivs[deriv_n].x());
165 double endderiv = atan2(derivs_2[deriv_n_2].y(), derivs_2[deriv_n_2].x());
166 Geom::Point pt1 = Geom::Point(end_path_curve_start.getVector().length() * cos(startangle + startderiv), end_path_curve_start.getVector().length() * sin(startangle + startderiv));
167 Geom::Point pt2 = Geom::Point(end_path_curve_end.getVector().length() * cos(endangle + endderiv), end_path_curve_end.getVector().length() * sin(endangle + endderiv));
168 p.appendNew<Geom::CubicBezier>(-pt1 + this_pathv.front().finalPoint(), -pt2 + derivs_2[0], derivs_2[0]);
169
170 break;
171
172 }
173 }
174 break;
175 }
176 }
177 delete last_seg_reverse;
178 }
179 }
180 Geom::PathVector outvector;
181 outvector.push_back(p);
182 curve->set_pathvector(outvector);
183 }
184}
185
186} // namespace LivePathEffect
187} /* namespace Inkscape */
188
189/*
190 Local Variables:
191 mode:c++
192 c-file-style:"stroustrup"
193 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
194 indent-tabs-mode:nil
195 fill-column:99
196 End:
197*/
198// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
0199
=== added file 'src/live_effects/lpe-attach-path.h'
--- src/live_effects/lpe-attach-path.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-attach-path.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,52 @@
1#ifndef INKSCAPE_LPE_ATTACH_PATH_H
2#define INKSCAPE_LPE_ATTACH_PATH_H
3
4/*
5 * Inkscape::LPEAttachPath
6 *
7 * Copyright (C) Ted Janeczko 2012 <flutterguy317@gmail.com>
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
11
12#include "live_effects/effect.h"
13#include "live_effects/parameter/parameter.h"
14#include "live_effects/parameter/point.h"
15#include "live_effects/parameter/originalpath.h"
16#include "live_effects/parameter/vector.h"
17#include "live_effects/parameter/bool.h"
18#include "live_effects/parameter/transformedpoint.h"
19
20namespace Inkscape {
21namespace LivePathEffect {
22
23class LPEAttachPath : public Effect {
24public:
25 LPEAttachPath(LivePathEffectObject *lpeobject);
26 virtual ~LPEAttachPath();
27
28 virtual void doEffect (SPCurve * curve);
29 virtual void resetDefaults(SPItem const * item);
30
31private:
32 LPEAttachPath(const LPEAttachPath&);
33 LPEAttachPath& operator=(const LPEAttachPath&);
34
35 Geom::Point curve_start_previous_origin;
36 Geom::Point curve_end_previous_origin;
37
38 OriginalPathParam start_path;
39 ScalarParam start_path_position;
40 TransformedPointParam start_path_curve_start;
41 VectorParam start_path_curve_end;
42
43 OriginalPathParam end_path;
44 ScalarParam end_path_position;
45 TransformedPointParam end_path_curve_start;
46 VectorParam end_path_curve_end;
47};
48
49}; //namespace LivePathEffect
50}; //namespace Inkscape
51
52#endif
053
=== added file 'src/live_effects/lpe-bounding-box.cpp'
--- src/live_effects/lpe-bounding-box.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-bounding-box.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,67 @@
1/*
2 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
3 *
4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */
6
7#include <glibmm/i18n.h>
8
9#include "live_effects/lpe-bounding-box.h"
10
11#include "display/curve.h"
12#include "sp-item.h"
13#include "2geom/path.h"
14#include "sp-shape.h"
15#include "sp-text.h"
16#include "2geom/bezier-curve.h"
17#include "lpe-bounding-box.h"
18
19namespace Inkscape {
20namespace LivePathEffect {
21
22LPEBoundingBox::LPEBoundingBox(LivePathEffectObject *lpeobject) :
23 Effect(lpeobject),
24 linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this),
25 visual_bounds(_("Visual Bounds"), _("Uses the visual bounding box"), "visualbounds", &wr, this)
26{
27 registerParameter( dynamic_cast<Parameter *>(&linked_path) );
28 registerParameter( dynamic_cast<Parameter *>(&visual_bounds) );
29 //perceived_path = true;
30}
31
32LPEBoundingBox::~LPEBoundingBox()
33{
34
35}
36
37void LPEBoundingBox::doEffect (SPCurve * curve)
38{
39 if (curve) {
40 if ( linked_path.linksToPath() && linked_path.getObject() ) {
41 SPItem * item = linked_path.getObject();
42 Geom::OptRect bbox = visual_bounds.get_value() ? item->visualBounds() : item->geometricBounds();
43 Geom::Path p(Geom::Point(bbox->left(), bbox->top()));
44 p.appendNew<Geom::LineSegment>(Geom::Point(bbox->right(), bbox->top()));
45 p.appendNew<Geom::LineSegment>(Geom::Point(bbox->right(), bbox->bottom()));
46 p.appendNew<Geom::LineSegment>(Geom::Point(bbox->left(), bbox->bottom()));
47 p.appendNew<Geom::LineSegment>(Geom::Point(bbox->left(), bbox->top()));
48 std::vector<Geom::Path> out;
49 out.push_back(p);
50 curve->set_pathvector(out);
51 }
52 }
53}
54
55} // namespace LivePathEffect
56} /* namespace Inkscape */
57
58/*
59 Local Variables:
60 mode:c++
61 c-file-style:"stroustrup"
62 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
63 indent-tabs-mode:nil
64 fill-column:99
65 End:
66*/
67// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
068
=== added file 'src/live_effects/lpe-bounding-box.h'
--- src/live_effects/lpe-bounding-box.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-bounding-box.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,37 @@
1#ifndef INKSCAPE_LPE_BOUNDING_BOX_H
2#define INKSCAPE_LPE_BOUNDING_BOX_H
3
4/*
5 * Inkscape::LPEFillBetweenStrokes
6 *
7 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
11
12#include "live_effects/effect.h"
13#include "live_effects/parameter/originalpath.h"
14
15namespace Inkscape {
16namespace LivePathEffect {
17
18class LPEBoundingBox : public Effect {
19public:
20 LPEBoundingBox(LivePathEffectObject *lpeobject);
21 virtual ~LPEBoundingBox();
22
23 virtual void doEffect (SPCurve * curve);
24
25private:
26 OriginalPathParam linked_path;
27 BoolParam visual_bounds;
28
29private:
30 LPEBoundingBox(const LPEBoundingBox&);
31 LPEBoundingBox& operator=(const LPEBoundingBox&);
32};
33
34}; //namespace LivePathEffect
35}; //namespace Inkscape
36
37#endif
038
=== added file 'src/live_effects/lpe-ellipse_5pts.cpp'
--- src/live_effects/lpe-ellipse_5pts.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-ellipse_5pts.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,214 @@
1/** \file
2 * LPE "Ellipse through 5 points" implementation
3 */
4
5/*
6 * Authors:
7 * Theodore Janeczko
8 *
9 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
13
14#include "live_effects/lpe-ellipse_5pts.h"
15
16// You might need to include other 2geom files. You can add them here:
17#include <glibmm/i18n.h>
18#include <2geom/path.h>
19#include <2geom/circle.h>
20#include <2geom/ellipse.h>
21#include <2geom/path-sink.h>
22#include "inkscape.h"
23#include "desktop.h"
24#include "message-stack.h"
25
26namespace Inkscape {
27namespace LivePathEffect {
28
29LPEEllipse5Pts::LPEEllipse5Pts(LivePathEffectObject *lpeobject) :
30 Effect(lpeobject)
31{
32 //perceived_path = true;
33}
34
35LPEEllipse5Pts::~LPEEllipse5Pts()
36{
37}
38
39static double _det3(double (*mat)[3])
40{
41 for (int i = 0; i < 2; i++)
42 {
43 for (int j = i + 1; j < 3; j++)
44 {
45 for (int k = i + 1; k < 3; k++)
46 {
47 mat[j][k] = (mat[j][k] * mat[i][i] - mat[j][i] * mat[i][k]);
48 if (i) mat[j][k] /= mat[i-1][i-1];
49 }
50 }
51 }
52 return mat[2][2];
53}
54static double _det5(double (*mat)[5])
55{
56 for (int i = 0; i < 4; i++)
57 {
58 for (int j = i + 1; j < 5; j++)
59 {
60 for (int k = i + 1; k < 5; k++)
61 {
62 mat[j][k] = (mat[j][k] * mat[i][i] - mat[j][i] * mat[i][k]);
63 if (i) mat[j][k] /= mat[i-1][i-1];
64 }
65 }
66 }
67 return mat[4][4];
68}
69
70std::vector<Geom::Path>
71LPEEllipse5Pts::doEffect_path (std::vector<Geom::Path> const & path_in)
72{
73 std::vector<Geom::Path> path_out = std::vector<Geom::Path>();
74
75 if (path_in[0].size() < 4) {
76
77 SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Five points required for constructing an ellipse"));
78 return path_in;
79 }
80 // we assume that the path has >= 3 nodes
81 Geom::Point A = path_in[0].initialPoint();
82 Geom::Point B = path_in[0].pointAt(1);
83 Geom::Point C = path_in[0].pointAt(2);
84 Geom::Point D = path_in[0].pointAt(3);
85 Geom::Point E = path_in[0].pointAt(4);
86
87 using namespace Geom;
88
89 double rowmajor_matrix[5][6] =
90 {
91 {A.x()*A.x(), A.x()*A.y(), A.y()*A.y(), A.x(), A.y(), 1},
92 {B.x()*B.x(), B.x()*B.y(), B.y()*B.y(), B.x(), B.y(), 1},
93 {C.x()*C.x(), C.x()*C.y(), C.y()*C.y(), C.x(), C.y(), 1},
94 {D.x()*D.x(), D.x()*D.y(), D.y()*D.y(), D.x(), D.y(), 1},
95 {E.x()*E.x(), E.x()*E.y(), E.y()*E.y(), E.x(), E.y(), 1}
96 };
97
98 double mat_a[5][5] =
99 {
100 {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
101 {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
102 {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
103 {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
104 {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
105 };
106 double mat_b[5][5] =
107 {
108 {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
109 {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
110 {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
111 {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
112 {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
113 };
114 double mat_c[5][5] =
115 {
116 {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
117 {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
118 {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
119 {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
120 {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
121 };
122 double mat_d[5][5] =
123 {
124 {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
125 {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
126 {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
127 {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]},
128 {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
129 };
130 double mat_e[5][5] =
131 {
132 {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
133 {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
134 {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
135 {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
136 {rowmajor_matrix[0][5], rowmajor_matrix[1][5], rowmajor_matrix[2][5], rowmajor_matrix[3][5], rowmajor_matrix[4][5]}
137 };
138 double mat_f[5][5] =
139 {
140 {rowmajor_matrix[0][0], rowmajor_matrix[1][0], rowmajor_matrix[2][0], rowmajor_matrix[3][0], rowmajor_matrix[4][0]},
141 {rowmajor_matrix[0][1], rowmajor_matrix[1][1], rowmajor_matrix[2][1], rowmajor_matrix[3][1], rowmajor_matrix[4][1]},
142 {rowmajor_matrix[0][2], rowmajor_matrix[1][2], rowmajor_matrix[2][2], rowmajor_matrix[3][2], rowmajor_matrix[4][2]},
143 {rowmajor_matrix[0][3], rowmajor_matrix[1][3], rowmajor_matrix[2][3], rowmajor_matrix[3][3], rowmajor_matrix[4][3]},
144 {rowmajor_matrix[0][4], rowmajor_matrix[1][4], rowmajor_matrix[2][4], rowmajor_matrix[3][4], rowmajor_matrix[4][4]}
145 };
146
147 double a1 = _det5(mat_a);
148 double b1 = -_det5(mat_b);
149 double c1 = _det5(mat_c);
150 double d1 = -_det5(mat_d);
151 double e1 = _det5(mat_e);
152 double f1 = -_det5(mat_f);
153
154 double mat_check[][3] =
155 {
156 {a1, b1/2, d1/2},
157 {b1/2, c1, e1/2},
158 {d1/2, e1/2, f1}
159 };
160
161 if (_det3(mat_check) == 0 || a1*c1 - b1*b1/4 <= 0) {
162 SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No ellipse found for specified points"));
163 return path_in;
164 }
165
166 Geom::Ellipse el(a1, b1, c1, d1, e1, f1);
167
168 double s, e;
169 double x0, y0, x1, y1, x2, y2, x3, y3;
170 double len;
171
172 // figure out if we have a slice, guarding against rounding errors
173
174 Path p(Geom::Point(cos(0), sin(0)));
175
176 double end = 2 * M_PI;
177 for (s = 0; s < end; s += M_PI_2) {
178 e = s + M_PI_2;
179 if (e > end)
180 e = end;
181 len = 4*tan((e - s)/4)/3;
182 x0 = cos(s);
183 y0 = sin(s);
184 x1 = x0 + len * cos(s + M_PI_2);
185 y1 = y0 + len * sin(s + M_PI_2);
186 x3 = cos(e);
187 y3 = sin(e);
188 x2 = x3 + len * cos(e - M_PI_2);
189 y2 = y3 + len * sin(e - M_PI_2);
190 p.appendNew<Geom::CubicBezier>(Geom::Point(x1,y1), Geom::Point(x2,y2), Geom::Point(x3,y3));
191 }
192
193 Geom::Affine aff = Geom::Scale(el.ray(Geom::X), el.ray(Geom::Y)) * Geom::Rotate(el.rot_angle()) * Geom::Translate(el.center());
194
195 path_out.push_back(p * aff);
196
197 return path_out;
198}
199
200/* ######################## */
201
202} //namespace LivePathEffect
203} /* namespace Inkscape */
204
205/*
206 Local Variables:
207 mode:c++
208 c-file-style:"stroustrup"
209 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
210 indent-tabs-mode:nil
211 fill-column:99
212 End:
213*/
214// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
0215
=== added file 'src/live_effects/lpe-ellipse_5pts.h'
--- src/live_effects/lpe-ellipse_5pts.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-ellipse_5pts.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,50 @@
1#ifndef INKSCAPE_LPE_ELLIPSE_5PTS_H
2#define INKSCAPE_LPE_ELLIPSE_5PTS_H
3
4/** \file
5 * LPE "Ellipse through 5 points" implementation
6 */
7
8/*
9 * Authors:
10 * Theodore Janeczko
11 *
12 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
13 *
14 * Released under GNU GPL, read the file 'COPYING' for more information
15 */
16
17#include "live_effects/effect.h"
18#include "live_effects/parameter/parameter.h"
19#include "live_effects/parameter/point.h"
20
21namespace Inkscape {
22namespace LivePathEffect {
23
24class LPEEllipse5Pts : public Effect {
25public:
26 LPEEllipse5Pts(LivePathEffectObject *lpeobject);
27 virtual ~LPEEllipse5Pts();
28
29 virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
30
31private:
32 LPEEllipse5Pts(const LPEEllipse5Pts&);
33 LPEEllipse5Pts& operator=(const LPEEllipse5Pts&);
34};
35
36} //namespace LivePathEffect
37} //namespace Inkscape
38
39#endif
40
41/*
42 Local Variables:
43 mode:c++
44 c-file-style:"stroustrup"
45 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
46 indent-tabs-mode:nil
47 fill-column:99
48 End:
49*/
50// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
051
=== added file 'src/live_effects/lpe-fill-between-many.cpp'
--- src/live_effects/lpe-fill-between-many.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-fill-between-many.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,78 @@
1/*
2 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
3 *
4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */
6
7#include <gtkmm/box.h>
8
9#include "live_effects/lpe-fill-between-many.h"
10
11#include "display/curve.h"
12#include "sp-item.h"
13#include "2geom/path.h"
14#include "sp-shape.h"
15#include "sp-text.h"
16#include "2geom/bezier-curve.h"
17
18#include <glibmm/i18n.h>
19
20namespace Inkscape {
21namespace LivePathEffect {
22
23LPEFillBetweenMany::LPEFillBetweenMany(LivePathEffectObject *lpeobject) :
24 Effect(lpeobject),
25 linked_paths(_("Linked path:"), _("Paths from which to take the original path data"), "linkedpaths", &wr, this)
26{
27 registerParameter( dynamic_cast<Parameter *>(&linked_paths) );
28 //perceived_path = true;
29}
30
31LPEFillBetweenMany::~LPEFillBetweenMany()
32{
33
34}
35
36void LPEFillBetweenMany::doEffect (SPCurve * curve)
37{
38 std::vector<Geom::Path> res_pathv;
39 SPItem * firstObj = NULL;
40 for (std::vector<PathAndDirection*>::iterator iter = linked_paths._vector.begin(); iter != linked_paths._vector.end(); iter++) {
41 SPObject *obj;
42 if ((*iter)->ref.isAttached() && (obj = (*iter)->ref.getObject()) && SP_IS_ITEM(obj) && !(*iter)->_pathvector.empty()) {
43 Geom::Path linked_path;
44 if ((*iter)->reversed) {
45 linked_path = (*iter)->_pathvector.front().reverse();
46 } else {
47 linked_path = (*iter)->_pathvector.front();
48 }
49
50 if (!res_pathv.empty()) {
51 linked_path = linked_path * SP_ITEM(obj)->getRelativeTransform(firstObj);
52 res_pathv.front().appendNew<Geom::LineSegment>(linked_path.initialPoint());
53 res_pathv.front().append(linked_path);
54 } else {
55 firstObj = SP_ITEM(obj);
56 res_pathv.push_back(linked_path);
57 }
58 }
59 }
60 if (!res_pathv.empty()) {
61 res_pathv.front().close();
62 }
63 curve->set_pathvector(res_pathv);
64}
65
66} // namespace LivePathEffect
67} /* namespace Inkscape */
68
69/*
70 Local Variables:
71 mode:c++
72 c-file-style:"stroustrup"
73 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
74 indent-tabs-mode:nil
75 fill-column:99
76 End:
77*/
78// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
079
=== added file 'src/live_effects/lpe-fill-between-many.h'
--- src/live_effects/lpe-fill-between-many.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-fill-between-many.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,36 @@
1#ifndef INKSCAPE_LPE_FILL_BETWEEN_MANY_H
2#define INKSCAPE_LPE_FILL_BETWEEN_MANY_H
3
4/*
5 * Inkscape::LPEFillBetweenStrokes
6 *
7 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
11
12#include "live_effects/effect.h"
13#include "live_effects/parameter/originalpatharray.h"
14
15namespace Inkscape {
16namespace LivePathEffect {
17
18class LPEFillBetweenMany : public Effect {
19public:
20 LPEFillBetweenMany(LivePathEffectObject *lpeobject);
21 virtual ~LPEFillBetweenMany();
22
23 virtual void doEffect (SPCurve * curve);
24
25private:
26 OriginalPathArrayParam linked_paths;
27
28private:
29 LPEFillBetweenMany(const LPEFillBetweenMany&);
30 LPEFillBetweenMany& operator=(const LPEFillBetweenMany&);
31};
32
33}; //namespace LivePathEffect
34}; //namespace Inkscape
35
36#endif
037
=== added file 'src/live_effects/lpe-fill-between-strokes.cpp'
--- src/live_effects/lpe-fill-between-strokes.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-fill-between-strokes.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,116 @@
1/*
2 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
3 *
4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */
6
7#include <glibmm/i18n.h>
8
9#include "live_effects/lpe-fill-between-strokes.h"
10
11#include "display/curve.h"
12#include "sp-item.h"
13#include "2geom/path.h"
14#include "sp-shape.h"
15#include "sp-text.h"
16#include "2geom/bezier-curve.h"
17
18namespace Inkscape {
19namespace LivePathEffect {
20
21LPEFillBetweenStrokes::LPEFillBetweenStrokes(LivePathEffectObject *lpeobject) :
22 Effect(lpeobject),
23 linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this),
24 second_path(_("Second path:"), _("Second path from which to take the original path data"), "secondpath", &wr, this),
25 reverse_second(_("Reverse Second"), _("Reverses the second path order"), "reversesecond", &wr, this)
26{
27 registerParameter( dynamic_cast<Parameter *>(&linked_path) );
28 registerParameter( dynamic_cast<Parameter *>(&second_path) );
29 registerParameter( dynamic_cast<Parameter *>(&reverse_second) );
30 //perceived_path = true;
31}
32
33LPEFillBetweenStrokes::~LPEFillBetweenStrokes()
34{
35
36}
37
38void LPEFillBetweenStrokes::doEffect (SPCurve * curve)
39{
40 if (curve) {
41 if ( linked_path.linksToPath() && second_path.linksToPath() && linked_path.getObject() && second_path.getObject() ) {
42 std::vector<Geom::Path> linked_pathv = linked_path.get_pathvector();
43 std::vector<Geom::Path> second_pathv = second_path.get_pathvector();
44 std::vector<Geom::Path> result_linked_pathv;
45 std::vector<Geom::Path> result_second_pathv;
46 Geom::Affine second_transform = second_path.getObject()->getRelativeTransform(linked_path.getObject());
47
48 for (std::vector<Geom::Path>::iterator iter = linked_pathv.begin(); iter != linked_pathv.end(); ++iter)
49 {
50 result_linked_pathv.push_back((*iter));
51 }
52 for (std::vector<Geom::Path>::iterator iter = second_pathv.begin(); iter != second_pathv.end(); ++iter)
53 {
54 result_second_pathv.push_back((*iter) * second_transform);
55 }
56
57 if ( !result_linked_pathv.empty() && !result_second_pathv.empty() && !result_linked_pathv.front().closed() ) {
58 if (reverse_second.get_value())
59 {
60 result_linked_pathv.front().appendNew<Geom::LineSegment>(result_second_pathv.front().finalPoint());
61 result_linked_pathv.front().append(result_second_pathv.front().reverse());
62 }
63 else
64 {
65 result_linked_pathv.front().appendNew<Geom::LineSegment>(result_second_pathv.front().initialPoint());
66 result_linked_pathv.front().append(result_second_pathv.front());
67 }
68 curve->set_pathvector(result_linked_pathv);
69 }
70 else if ( !result_linked_pathv.empty() ) {
71 curve->set_pathvector(result_linked_pathv);
72 }
73 else if ( !result_second_pathv.empty() ) {
74 curve->set_pathvector(result_second_pathv);
75 }
76 }
77 else if ( linked_path.linksToPath() && linked_path.getObject() ) {
78 std::vector<Geom::Path> linked_pathv = linked_path.get_pathvector();
79 std::vector<Geom::Path> result_pathv;
80
81 for (std::vector<Geom::Path>::iterator iter = linked_pathv.begin(); iter != linked_pathv.end(); ++iter)
82 {
83 result_pathv.push_back((*iter));
84 }
85 if ( !result_pathv.empty() ) {
86 curve->set_pathvector(result_pathv);
87 }
88 }
89 else if ( second_path.linksToPath() && second_path.getObject() ) {
90 std::vector<Geom::Path> second_pathv = second_path.get_pathvector();
91 std::vector<Geom::Path> result_pathv;
92
93 for (std::vector<Geom::Path>::iterator iter = second_pathv.begin(); iter != second_pathv.end(); ++iter)
94 {
95 result_pathv.push_back((*iter));
96 }
97 if ( !result_pathv.empty() ) {
98 curve->set_pathvector(result_pathv);
99 }
100 }
101 }
102}
103
104} // namespace LivePathEffect
105} /* namespace Inkscape */
106
107/*
108 Local Variables:
109 mode:c++
110 c-file-style:"stroustrup"
111 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
112 indent-tabs-mode:nil
113 fill-column:99
114 End:
115*/
116// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
0117
=== added file 'src/live_effects/lpe-fill-between-strokes.h'
--- src/live_effects/lpe-fill-between-strokes.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-fill-between-strokes.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,38 @@
1#ifndef INKSCAPE_LPE_FILL_BETWEEN_STROKES_H
2#define INKSCAPE_LPE_FILL_BETWEEN_STROKES_H
3
4/*
5 * Inkscape::LPEFillBetweenStrokes
6 *
7 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
11
12#include "live_effects/effect.h"
13#include "live_effects/parameter/originalpath.h"
14
15namespace Inkscape {
16namespace LivePathEffect {
17
18class LPEFillBetweenStrokes : public Effect {
19public:
20 LPEFillBetweenStrokes(LivePathEffectObject *lpeobject);
21 virtual ~LPEFillBetweenStrokes();
22
23 virtual void doEffect (SPCurve * curve);
24
25private:
26 OriginalPathParam linked_path;
27 OriginalPathParam second_path;
28 BoolParam reverse_second;
29
30private:
31 LPEFillBetweenStrokes(const LPEFillBetweenStrokes&);
32 LPEFillBetweenStrokes& operator=(const LPEFillBetweenStrokes&);
33};
34
35}; //namespace LivePathEffect
36}; //namespace Inkscape
37
38#endif
039
=== added file 'src/live_effects/lpe-jointype.cpp'
--- src/live_effects/lpe-jointype.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-jointype.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,184 @@
1/** \file
2 * LPE "Join Type" implementation
3 */
4 /* Authors:
5 *
6 * Liam P White
7 *
8 * Copyright (C) 2014 Authors
9 *
10 * Released under GNU GPL v2, read the file 'COPYING' for more information
11 */
12
13#include <math.h>
14
15#include "live_effects/parameter/enum.h"
16#include "live_effects/pathoutlineprovider.h"
17
18#include "sp-shape.h"
19#include "style.h"
20#include "xml/repr.h"
21#include "sp-paint-server.h"
22#include "svg/svg-color.h"
23#include "desktop-style.h"
24#include "svg/css-ostringstream.h"
25#include "display/curve.h"
26
27#include <2geom/path.h>
28#include <2geom/svg-elliptical-arc.h>
29
30#include "lpe-jointype.h"
31
32namespace Inkscape {
33namespace LivePathEffect {
34
35static const Util::EnumData<unsigned> JoinTypeData[] = {
36 {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
37 {LINEJOIN_ROUND, N_("Rounded"), "round"},
38 {LINEJOIN_POINTY, N_("Miter"), "miter"},
39 {LINEJOIN_REFLECTED, N_("Reflected"), "extrapolated"},
40 {LINEJOIN_EXTRAPOLATED, N_("Extrapolated arc"), "extrp_arc"}
41};
42
43static const Util::EnumData<unsigned> CapTypeData[] = {
44 {BUTT_STRAIGHT, N_("Butt"), "butt"},
45 {BUTT_ROUND, N_("Rounded"), "round"},
46 {BUTT_SQUARE, N_("Square"), "square"},
47 {BUTT_POINTY, N_("Peak"), "peak"},
48 {BUTT_LEANED, N_("Leaned"), "leaned"}
49};
50
51static const Util::EnumDataConverter<unsigned> CapTypeConverter(CapTypeData, sizeof(CapTypeData)/sizeof(*CapTypeData));
52static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinTypeData, sizeof(JoinTypeData)/sizeof(*JoinTypeData));
53
54LPEJoinType::LPEJoinType(LivePathEffectObject *lpeobject) :
55 Effect(lpeobject),
56 line_width(_("Line width"), _("Thickness of the stroke"), "line_width", &wr, this, 1.),
57 linecap_type(_("Line cap"), _("The end shape of the stroke"), "linecap_type", CapTypeConverter, &wr, this, butt_straight),
58 linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
59 start_lean(_("Start path lean"), _("Start path lean"), "start_lean", &wr, this, 0.),
60 end_lean(_("End path lean"), _("End path lean"), "end_lean", &wr, this, 0.),
61 miter_limit(_("Miter limit:"), _("Maximum length of the miter join (in units of stroke width)"), "miter_limit", &wr, this, 100.),
62 attempt_force_join(_("Force miter"), _("Overrides the miter limit and forces a join."), "attempt_force_join", &wr, this, true)
63{
64 show_orig_path = true;
65 registerParameter( dynamic_cast<Parameter *>(&linecap_type) );
66 registerParameter( dynamic_cast<Parameter *>(&line_width) );
67 registerParameter( dynamic_cast<Parameter *>(&linejoin_type) );
68 registerParameter( dynamic_cast<Parameter *>(&start_lean) );
69 registerParameter( dynamic_cast<Parameter *>(&end_lean) );
70 registerParameter( dynamic_cast<Parameter *>(&miter_limit) );
71 registerParameter( dynamic_cast<Parameter *>(&attempt_force_join) );
72 was_initialized = false;
73 start_lean.param_set_range(-1,1);
74 start_lean.param_set_increments(0.1, 0.1);
75 start_lean.param_set_digits(4);
76 end_lean.param_set_range(-1,1);
77 end_lean.param_set_increments(0.1, 0.1);
78 end_lean.param_set_digits(4);
79}
80
81LPEJoinType::~LPEJoinType()
82{
83}
84
85//from LPEPowerStroke -- sets fill if stroke color because we will
86//be converting to a fill to make the new join.
87
88void LPEJoinType::doOnApply(SPLPEItem const* lpeitem)
89{
90 if (SP_IS_SHAPE(lpeitem)) {
91 SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
92 double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
93
94 SPCSSAttr *css = sp_repr_css_attr_new ();
95 if (true) {
96 if (lpeitem->style->stroke.isPaintserver()) {
97 SPPaintServer * server = lpeitem->style->getStrokePaintServer();
98 if (server) {
99 Glib::ustring str;
100 str += "url(#";
101 str += server->getId();
102 str += ")";
103 sp_repr_css_set_property (css, "fill", str.c_str());
104 }
105 } else if (lpeitem->style->stroke.isColor()) {
106 gchar c[64];
107 sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
108 sp_repr_css_set_property (css, "fill", c);
109 } else {
110 sp_repr_css_set_property (css, "fill", "none");
111 }
112 } else {
113 sp_repr_css_unset_property (css, "fill");
114 }
115
116 sp_repr_css_set_property(css, "stroke", "none");
117
118 sp_desktop_apply_css_recursive(item, css, true);
119 sp_repr_css_attr_unref (css);
120 if (!was_initialized)
121 {
122 was_initialized = true;
123 line_width.param_set_value(width);
124 }
125 } else {
126 g_warning("LPE Join Type can only be applied to paths (not groups).");
127 }
128}
129
130//from LPEPowerStroke -- sets stroke color from existing fill color
131
132void LPEJoinType::doOnRemove(SPLPEItem const* lpeitem)
133{
134
135 if (SP_IS_SHAPE(lpeitem)) {
136 SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
137
138 SPCSSAttr *css = sp_repr_css_attr_new ();
139 if (true) {
140 if (lpeitem->style->fill.isPaintserver()) {
141 SPPaintServer * server = lpeitem->style->getFillPaintServer();
142 if (server) {
143 Glib::ustring str;
144 str += "url(#";
145 str += server->getId();
146 str += ")";
147 sp_repr_css_set_property (css, "stroke", str.c_str());
148 }
149 } else if (lpeitem->style->fill.isColor()) {
150 gchar c[64];
151 sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
152 sp_repr_css_set_property (css, "stroke", c);
153 } else {
154 sp_repr_css_set_property (css, "stroke", "none");
155 }
156 } else {
157 sp_repr_css_unset_property (css, "stroke");
158 }
159
160 Inkscape::CSSOStringStream os;
161 os << fabs(line_width);
162 sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
163
164 sp_repr_css_set_property(css, "fill", "none");
165
166 sp_desktop_apply_css_recursive(item, css, true);
167 sp_repr_css_attr_unref (css);
168 item->updateRepr();
169 }
170}
171
172//NOTE: I originally had all the outliner functions defined in here, but they were actually useful
173//enough for other LPEs so I moved them all into pathoutlineprovider.cpp. The code here is just a
174//wrapper around it.
175std::vector<Geom::Path> LPEJoinType::doEffect_path(std::vector<Geom::Path> const & path_in)
176{
177 return Outline::PathVectorOutline(path_in, line_width, static_cast<ButtTypeMod>(linecap_type.get_value()),
178 static_cast<LineJoinType>(linejoin_type.get_value()),
179 (attempt_force_join ? std::numeric_limits<double>::max() : miter_limit),
180 start_lean/2 ,end_lean/2);
181}
182
183} //namespace LivePathEffect
184} //namespace Inkscape
0185
=== added file 'src/live_effects/lpe-jointype.h'
--- src/live_effects/lpe-jointype.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-jointype.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,45 @@
1/* Authors:
2 * Liam P White
3 *
4 * Copyright (C) 2014 Authors
5 *
6 * Released under GNU GPL v2, read the file COPYING for more information
7 */
8#ifndef INKSCAPE_LPE_JOINTYPE_H
9#define INKSCAPE_LPE_JOINTYPE_H
10
11#include "live_effects/effect.h"
12#include "live_effects/parameter/parameter.h"
13#include "live_effects/parameter/point.h"
14#include "live_effects/parameter/enum.h"
15
16namespace Inkscape {
17namespace LivePathEffect {
18
19class LPEJoinType : public Effect {
20public:
21 LPEJoinType(LivePathEffectObject *lpeobject);
22 virtual ~LPEJoinType();
23
24 virtual void doOnApply(SPLPEItem const* lpeitem);
25 virtual void doOnRemove(SPLPEItem const* lpeitem);
26 virtual std::vector <Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
27
28private:
29 LPEJoinType(const LPEJoinType&);
30 LPEJoinType& operator=(const LPEJoinType&);
31
32 ScalarParam line_width;
33 EnumParam<unsigned> linecap_type;
34 EnumParam<unsigned> linejoin_type;
35 ScalarParam start_lean;
36 ScalarParam end_lean;
37 ScalarParam miter_limit;
38 BoolParam attempt_force_join;
39 bool was_initialized;
40};
41
42} //namespace LivePathEffect
43} //namespace Inkscape
44
45#endif
046
=== modified file 'src/live_effects/lpe-knot.cpp'
--- src/live_effects/lpe-knot.cpp 2014-08-31 18:17:26 +0000
+++ src/live_effects/lpe-knot.cpp 2014-09-07 17:02:32 +0000
@@ -537,6 +537,10 @@
537{537{
538 using namespace Geom;538 using namespace Geom;
539 original_bbox(lpeitem);539 original_bbox(lpeitem);
540
541 if (SP_IS_PATH(lpeitem)) {
542 supplied_path = SP_PATH(lpeitem)->getCurve()->get_pathvector();
543 }
540544
541 gpaths.clear();545 gpaths.clear();
542 gstroke_widths.clear();546 gstroke_widths.clear();
543547
=== modified file 'src/live_effects/lpe-knot.h'
--- src/live_effects/lpe-knot.h 2014-06-16 21:34:16 +0000
+++ src/live_effects/lpe-knot.h 2014-09-07 17:02:32 +0000
@@ -64,7 +64,8 @@
64 void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);64 void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
6565
66protected:66protected:
67 virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec);67 virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec);
68 std::vector<Geom::Path> supplied_path; //for knotholder business
68 69
69private:70private:
70 void updateSwitcher();71 void updateSwitcher();
7172
=== modified file 'src/live_effects/lpe-powerstroke-interpolators.h'
--- src/live_effects/lpe-powerstroke-interpolators.h 2014-08-23 17:14:02 +0000
+++ src/live_effects/lpe-powerstroke-interpolators.h 2014-09-07 17:02:32 +0000
@@ -28,6 +28,7 @@
28 INTERP_CUBICBEZIER,28 INTERP_CUBICBEZIER,
29 INTERP_CUBICBEZIER_JOHAN,29 INTERP_CUBICBEZIER_JOHAN,
30 INTERP_SPIRO,30 INTERP_SPIRO,
31 INTERP_CUBICBEZIER_SMOOTH,
31 INTERP_CENTRIPETAL_CATMULLROM32 INTERP_CENTRIPETAL_CATMULLROM
32};33};
3334
@@ -134,6 +135,43 @@
134 CubicBezierJohan& operator=(const CubicBezierJohan&);135 CubicBezierJohan& operator=(const CubicBezierJohan&);
135};136};
136137
138/// @todo invent name for this class
139class CubicBezierSmooth : public Interpolator {
140public:
141 CubicBezierSmooth(double beta = 0.2) {
142 _beta = beta;
143 };
144 virtual ~CubicBezierSmooth() {};
145
146 virtual Path interpolateToPath(std::vector<Point> const &points) const {
147 Path fit;
148 fit.start(points.at(0));
149 unsigned int num_points = points.size();
150 for (unsigned int i = 1; i < num_points; ++i) {
151 Point p0 = points.at(i-1);
152 Point p1 = points.at(i);
153 Point dx = Point(p1[X] - p0[X], 0);
154 if (i == 1) {
155 fit.appendNew<CubicBezier>(p0, p1-0.75*dx, p1);
156 } else if (i == points.size() - 1) {
157 fit.appendNew<CubicBezier>(p0+0.75*dx, p1, p1);
158 } else {
159 fit.appendNew<CubicBezier>(p0+_beta*dx, p1-_beta*dx, p1);
160 }
161 }
162 return fit;
163 };
164
165 void setBeta(double beta) {
166 _beta = beta;
167 }
168
169 double _beta;
170
171private:
172 CubicBezierSmooth(const CubicBezierSmooth&);
173 CubicBezierSmooth& operator=(const CubicBezierSmooth&);
174};
137175
138class SpiroInterpolator : public Interpolator {176class SpiroInterpolator : public Interpolator {
139public:177public:
@@ -261,6 +299,8 @@
261 return new Geom::Interpolate::CubicBezierJohan();299 return new Geom::Interpolate::CubicBezierJohan();
262 case INTERP_SPIRO:300 case INTERP_SPIRO:
263 return new Geom::Interpolate::SpiroInterpolator();301 return new Geom::Interpolate::SpiroInterpolator();
302 case INTERP_CUBICBEZIER_SMOOTH:
303 return new Geom::Interpolate::CubicBezierSmooth();
264 case INTERP_CENTRIPETAL_CATMULLROM:304 case INTERP_CENTRIPETAL_CATMULLROM:
265 return new Geom::Interpolate::CentripetalCatmullRomInterpolator();305 return new Geom::Interpolate::CentripetalCatmullRomInterpolator();
266 default:306 default:
267307
=== modified file 'src/live_effects/lpe-powerstroke.cpp'
--- src/live_effects/lpe-powerstroke.cpp 2014-08-23 16:39:36 +0000
+++ src/live_effects/lpe-powerstroke.cpp 2014-09-07 17:02:32 +0000
@@ -15,6 +15,11 @@
1515
16#include "sp-shape.h"16#include "sp-shape.h"
17#include "style.h"17#include "style.h"
18#include "xml/repr.h"
19#include "sp-paint-server.h"
20#include "svg/svg-color.h"
21#include "desktop-style.h"
22#include "svg/css-ostringstream.h"
18#include "display/curve.h"23#include "display/curve.h"
1924
20#include <2geom/path.h>25#include <2geom/path.h>
@@ -185,6 +190,7 @@
185namespace LivePathEffect {190namespace LivePathEffect {
186191
187static const Util::EnumData<unsigned> InterpolatorTypeData[] = {192static const Util::EnumData<unsigned> InterpolatorTypeData[] = {
193 {Geom::Interpolate::INTERP_CUBICBEZIER_SMOOTH, N_("CubicBezierSmooth"), "CubicBezierSmooth"},
188 {Geom::Interpolate::INTERP_LINEAR , N_("Linear"), "Linear"},194 {Geom::Interpolate::INTERP_LINEAR , N_("Linear"), "Linear"},
189 {Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"},195 {Geom::Interpolate::INTERP_CUBICBEZIER , N_("CubicBezierFit"), "CubicBezierFit"},
190 {Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"},196 {Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN , N_("CubicBezierJohan"), "CubicBezierJohan"},
@@ -223,9 +229,7 @@
223 {LINEJOIN_EXTRP_MITER, N_("Extrapolated"), "extrapolated"},229 {LINEJOIN_EXTRP_MITER, N_("Extrapolated"), "extrapolated"},
224 {LINEJOIN_MITER, N_("Miter"), "miter"},230 {LINEJOIN_MITER, N_("Miter"), "miter"},
225 {LINEJOIN_SPIRO, N_("Spiro"), "spiro"},231 {LINEJOIN_SPIRO, N_("Spiro"), "spiro"},
226#ifdef LPE_ENABLE_TEST_EFFECTS
227 {LINEJOIN_EXTRP_MITER_ARC, N_("Extrapolated arc"), "extrp_arc"}, 232 {LINEJOIN_EXTRP_MITER_ARC, N_("Extrapolated arc"), "extrp_arc"},
228#endif
229};233};
230static const Util::EnumDataConverter<unsigned> LineJoinTypeConverter(LineJoinTypeData, sizeof(LineJoinTypeData)/sizeof(*LineJoinTypeData));234static const Util::EnumDataConverter<unsigned> LineJoinTypeConverter(LineJoinTypeData, sizeof(LineJoinTypeData)/sizeof(*LineJoinTypeData));
231235
@@ -233,12 +237,12 @@
233 Effect(lpeobject),237 Effect(lpeobject),
234 offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this),238 offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this),
235 sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true),239 sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true),
236 interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN),240 interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER),
237 interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2),241 interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2),
238 start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND),242 start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT),
239 linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_ROUND),243 linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_EXTRP_MITER_ARC),
240 miter_limit(_("Miter limit:"), _("Maximum length of the miter (in units of stroke width)"), "miter_limit", &wr, this, 4.),244 miter_limit(_("Miter limit:"), _("Maximum length of the miter (in units of stroke width)"), "miter_limit", &wr, this, 4.),
241 end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND)245 end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT)
242{246{
243 show_orig_path = true;247 show_orig_path = true;
244248
@@ -267,20 +271,52 @@
267LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem)271LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem)
268{272{
269 if (SP_IS_SHAPE(lpeitem)) {273 if (SP_IS_SHAPE(lpeitem)) {
274 SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
270 std::vector<Geom::Point> points;275 std::vector<Geom::Point> points;
271 Geom::PathVector const &pathv = SP_SHAPE(lpeitem)->_curve->get_pathvector();276 Geom::PathVector const &pathv = SP_SHAPE(lpeitem)->_curve->get_pathvector();
272 double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;277 double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed / 2 : 1.;
278
279 SPCSSAttr *css = sp_repr_css_attr_new ();
280 if (true) {
281 if (lpeitem->style->stroke.isPaintserver()) {
282 SPPaintServer * server = lpeitem->style->getStrokePaintServer();
283 if (server) {
284 Glib::ustring str;
285 str += "url(#";
286 str += server->getId();
287 str += ")";
288 sp_repr_css_set_property (css, "fill", str.c_str());
289 }
290 } else if (lpeitem->style->stroke.isColor()) {
291 gchar c[64];
292 sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
293 sp_repr_css_set_property (css, "fill", c);
294 } else {
295 sp_repr_css_set_property (css, "fill", "none");
296 }
297 } else {
298 sp_repr_css_unset_property (css, "fill");
299 }
300
301 sp_repr_css_set_property(css, "stroke", "none");
302
303 sp_desktop_apply_css_recursive(item, css, true);
304 sp_repr_css_attr_unref (css);
305
306 item->updateRepr();
273 if (pathv.empty()) {307 if (pathv.empty()) {
274 points.push_back( Geom::Point(0.,width) );308 points.push_back( Geom::Point(0.2,width) );
275 points.push_back( Geom::Point(0.5,width) );309 points.push_back( Geom::Point(0.5,width) );
276 points.push_back( Geom::Point(1.,width) );310 points.push_back( Geom::Point(0.8,width) );
277 } else {311 } else {
278 Geom::Path const &path = pathv.front();312 Geom::Path const &path = pathv.front();
279 Geom::Path::size_type const size = path.size_default();313 Geom::Path::size_type const size = path.size_default();
280 points.push_back( Geom::Point(0.,width) );314 if (!path.closed()) {
315 points.push_back( Geom::Point(0.2,width) );
316 }
281 points.push_back( Geom::Point(0.5*size,width) );317 points.push_back( Geom::Point(0.5*size,width) );
282 if (!path.closed()) {318 if (!path.closed()) {
283 points.push_back( Geom::Point(size,width) );319 points.push_back( Geom::Point(size - 0.2,width) );
284 }320 }
285 }321 }
286 offset_points.param_set_and_write_new_value(points);322 offset_points.param_set_and_write_new_value(points);
@@ -289,6 +325,45 @@
289 }325 }
290}326}
291327
328void LPEPowerStroke::doOnRemove(SPLPEItem const* lpeitem)
329{
330 if (SP_IS_SHAPE(lpeitem)) {
331 SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
332 SPCSSAttr *css = sp_repr_css_attr_new ();
333 if (true) {
334 if (lpeitem->style->fill.isPaintserver()) {
335 SPPaintServer * server = lpeitem->style->getFillPaintServer();
336 if (server) {
337 Glib::ustring str;
338 str += "url(#";
339 str += server->getId();
340 str += ")";
341 sp_repr_css_set_property (css, "stroke", str.c_str());
342 }
343 } else if (lpeitem->style->fill.isColor()) {
344 gchar c[64];
345 sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
346 sp_repr_css_set_property (css, "stroke", c);
347 } else {
348 sp_repr_css_set_property (css, "stroke", "none");
349 }
350 } else {
351 sp_repr_css_unset_property (css, "stroke");
352 }
353
354 Inkscape::CSSOStringStream os;
355 os << offset_points.median_width() * 2;
356 sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
357
358 sp_repr_css_set_property(css, "fill", "none");
359
360 sp_desktop_apply_css_recursive(item, css, true);
361 sp_repr_css_attr_unref (css);
362
363 item->updateRepr();
364 }
365}
366
292void367void
293LPEPowerStroke::adjustForNewPath(std::vector<Geom::Path> const & path_in)368LPEPowerStroke::adjustForNewPath(std::vector<Geom::Path> const & path_in)
294{369{
@@ -588,6 +663,9 @@
588 if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast<Geom::Interpolate::CubicBezierJohan*>(interpolator)) {663 if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast<Geom::Interpolate::CubicBezierJohan*>(interpolator)) {
589 johan->setBeta(interpolator_beta);664 johan->setBeta(interpolator_beta);
590 }665 }
666 if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast<Geom::Interpolate::CubicBezierSmooth*>(interpolator)) {
667 smooth->setBeta(interpolator_beta);
668 }
591 Geom::Path strokepath = interpolator->interpolateToPath(ts);669 Geom::Path strokepath = interpolator->interpolateToPath(ts);
592 delete interpolator;670 delete interpolator;
593671
594672
=== modified file 'src/live_effects/lpe-powerstroke.h'
--- src/live_effects/lpe-powerstroke.h 2014-03-27 01:33:44 +0000
+++ src/live_effects/lpe-powerstroke.h 2014-09-07 17:02:32 +0000
@@ -25,9 +25,11 @@
25 LPEPowerStroke(LivePathEffectObject *lpeobject);25 LPEPowerStroke(LivePathEffectObject *lpeobject);
26 virtual ~LPEPowerStroke();26 virtual ~LPEPowerStroke();
2727
28
28 virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);29 virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
2930
30 virtual void doOnApply(SPLPEItem const* lpeitem);31 virtual void doOnApply(SPLPEItem const* lpeitem);
32 virtual void doOnRemove(SPLPEItem const* lpeitem);
3133
32 // methods called by path-manipulator upon edits34 // methods called by path-manipulator upon edits
33 void adjustForNewPath(std::vector<Geom::Path> const & path_in);35 void adjustForNewPath(std::vector<Geom::Path> const & path_in);
3436
=== modified file 'src/live_effects/lpe-tangent_to_curve.cpp'
--- src/live_effects/lpe-tangent_to_curve.cpp 2014-03-27 01:33:44 +0000
+++ src/live_effects/lpe-tangent_to_curve.cpp 2014-09-07 17:02:32 +0000
@@ -16,8 +16,6 @@
16#include <glibmm/i18n.h>16#include <glibmm/i18n.h>
1717
18#include "live_effects/lpe-tangent_to_curve.h"18#include "live_effects/lpe-tangent_to_curve.h"
19// FIXME: The following are only needed to convert the path's SPCurve* to pwd2.
20// There must be a more convenient way to achieve this.
21#include "sp-path.h"19#include "sp-path.h"
22#include "display/curve.h"20#include "display/curve.h"
2321
@@ -108,13 +106,13 @@
108 {106 {
109 KnotHolderEntity *e = new TtC::KnotHolderEntityLeftEnd(this);107 KnotHolderEntity *e = new TtC::KnotHolderEntityLeftEnd(this);
110 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,108 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
111 _("Adjust the \"left\" end of the tangent") );109 _("Adjust the <b>left</b> end of the tangent") );
112 knotholder->add(e);110 knotholder->add(e);
113 }111 }
114 {112 {
115 KnotHolderEntity *e = new TtC::KnotHolderEntityRightEnd(this);113 KnotHolderEntity *e = new TtC::KnotHolderEntityRightEnd(this);
116 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,114 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
117 _("Adjust the \"right\" end of the tangent") );115 _("Adjust the <b>right</b> end of the tangent") );
118 knotholder->add(e);116 knotholder->add(e);
119 }117 }
120};118};
@@ -130,14 +128,13 @@
130128
131 Geom::Point const s = snap_knot_position(p, state);129 Geom::Point const s = snap_knot_position(p, state);
132130
133 // FIXME: There must be a better way of converting the path's SPCurve* to pwd2.131 if ( !SP_IS_SHAPE(lpe->sp_lpe_item) ) {
134 SPCurve *curve = SP_PATH(item)->get_curve_for_edit();132 //lpe->t_attach.param_set_value(0);
135 Geom::PathVector pathv = curve->get_pathvector();133 g_warning("LPEItem is not a path! %s:%d\n", __FILE__, __LINE__);
136 Piecewise<D2<SBasis> > pwd2;134 return;
137 for (unsigned int i=0; i < pathv.size(); i++) {
138 pwd2.concat(pathv[i].toPwSb());
139 }135 }
140136 Piecewise<D2<SBasis> > pwd2 = paths_to_pw( lpe->pathvector_before_effect );
137
141 double t0 = nearest_point(s, pwd2);138 double t0 = nearest_point(s, pwd2);
142 lpe->t_attach.param_set_value(t0);139 lpe->t_attach.param_set_value(t0);
143140
144141
=== modified file 'src/live_effects/lpe-tangent_to_curve.h'
--- src/live_effects/lpe-tangent_to_curve.h 2012-04-07 14:09:58 +0000
+++ src/live_effects/lpe-tangent_to_curve.h 2014-09-07 17:02:32 +0000
@@ -34,7 +34,6 @@
34public:34public:
35 LPETangentToCurve(LivePathEffectObject *lpeobject);35 LPETangentToCurve(LivePathEffectObject *lpeobject);
36 virtual ~LPETangentToCurve();36 virtual ~LPETangentToCurve();
37
38 virtual Geom::Piecewise<Geom::D2<Geom::SBasis> >37 virtual Geom::Piecewise<Geom::D2<Geom::SBasis> >
39 doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);38 doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
4039
4140
=== added file 'src/live_effects/lpe-taperstroke.cpp'
--- src/live_effects/lpe-taperstroke.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-taperstroke.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,630 @@
1/**
2 * @file
3 * Taper Stroke path effect, provided as an alternative to Power Strokes
4 * for otherwise constant-width paths.
5 *
6 * Authors:
7 * Liam P White <inkscapebrony@gmail.com>
8 *
9 * Copyright (C) 2014 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
13
14#include "live_effects/lpe-taperstroke.h"
15
16#include <2geom/path.h>
17#include <2geom/shape.h>
18#include <2geom/path.h>
19#include <2geom/circle.h>
20#include <2geom/sbasis-to-bezier.h>
21#include "pathoutlineprovider.h"
22#include "display/curve.h"
23#include "sp-shape.h"
24#include "style.h"
25#include "xml/repr.h"
26#include "sp-paint-server.h"
27#include "svg/svg-color.h"
28#include "desktop-style.h"
29#include "svg/css-ostringstream.h"
30#include "svg/svg.h"
31
32//#include <glibmm/i18n.h>
33
34#include "knot-holder-entity.h"
35#include "knotholder.h"
36
37template<typename T>
38inline bool withinRange(T value, T low, T high) {
39 return (value > low && value < high);
40}
41
42namespace Inkscape {
43namespace LivePathEffect {
44
45namespace TpS {
46 class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity {
47 public:
48 KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
49 virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
50 virtual Geom::Point knot_get() const;
51 };
52
53 class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity {
54 public:
55 KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
56 virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
57 virtual Geom::Point knot_get() const;
58 };
59} // TpS
60
61static const Util::EnumData<unsigned> JoinType[] = {
62 {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
63 {LINEJOIN_ROUND, N_("Rounded"), "round"},
64 {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"},
65 {LINEJOIN_POINTY, N_("Miter"), "miter"},
66 {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"}
67};
68
69static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinType, sizeof (JoinType)/sizeof(*JoinType));
70
71LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) :
72 Effect(lpeobject),
73 line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 1.),
74 attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2),
75 attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2),
76 smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5),
77 join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
78 miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 100.)
79{
80 show_orig_path = true;
81 _provides_knotholder_entities = true;
82
83 attach_start.param_set_digits(3);
84 attach_end.param_set_digits(3);
85
86
87 registerParameter( dynamic_cast<Parameter *>(&line_width) );
88 registerParameter( dynamic_cast<Parameter *>(&attach_start) );
89 registerParameter( dynamic_cast<Parameter *>(&attach_end) );
90 registerParameter( dynamic_cast<Parameter *>(&smoothing) );
91 registerParameter( dynamic_cast<Parameter *>(&join_type) );
92 registerParameter( dynamic_cast<Parameter *>(&miter_limit) );
93}
94
95LPETaperStroke::~LPETaperStroke()
96{
97
98}
99
100//from LPEPowerStroke -- sets fill if stroke color because we will
101//be converting to a fill to make the new join.
102
103void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem)
104{
105 if (SP_IS_SHAPE(lpeitem)) {
106 SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
107 double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
108
109 SPCSSAttr *css = sp_repr_css_attr_new ();
110 if (true) {
111 if (lpeitem->style->stroke.isPaintserver()) {
112 SPPaintServer * server = lpeitem->style->getStrokePaintServer();
113 if (server) {
114 Glib::ustring str;
115 str += "url(#";
116 str += server->getId();
117 str += ")";
118 sp_repr_css_set_property (css, "fill", str.c_str());
119 }
120 } else if (lpeitem->style->stroke.isColor()) {
121 gchar c[64];
122 sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
123 sp_repr_css_set_property (css, "fill", c);
124 } else {
125 sp_repr_css_set_property (css, "fill", "none");
126 }
127 } else {
128 sp_repr_css_unset_property (css, "fill");
129 }
130
131 sp_repr_css_set_property(css, "stroke", "none");
132
133 sp_desktop_apply_css_recursive(item, css, true);
134 sp_repr_css_attr_unref (css);
135
136 line_width.param_set_value(width);
137 } else {
138 g_warning("LPE Join Type can only be applied to paths (not groups).");
139 }
140}
141
142//from LPEPowerStroke -- sets stroke color from existing fill color
143
144void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem)
145{
146
147 if (SP_IS_SHAPE(lpeitem)) {
148 SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
149
150 SPCSSAttr *css = sp_repr_css_attr_new ();
151 if (true) {
152 if (lpeitem->style->fill.isPaintserver()) {
153 SPPaintServer * server = lpeitem->style->getFillPaintServer();
154 if (server) {
155 Glib::ustring str;
156 str += "url(#";
157 str += server->getId();
158 str += ")";
159 sp_repr_css_set_property (css, "stroke", str.c_str());
160 }
161 } else if (lpeitem->style->fill.isColor()) {
162 gchar c[64];
163 sp_svg_write_color (c, sizeof(c), lpeitem->style->stroke.value.color.toRGBA32(SP_SCALE24_TO_FLOAT(lpeitem->style->stroke_opacity.value)));
164 sp_repr_css_set_property (css, "stroke", c);
165 } else {
166 sp_repr_css_set_property (css, "stroke", "none");
167 }
168 } else {
169 sp_repr_css_unset_property (css, "stroke");
170 }
171
172 Inkscape::CSSOStringStream os;
173 os << fabs(line_width);
174 sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
175
176 sp_repr_css_set_property(css, "fill", "none");
177
178 sp_desktop_apply_css_recursive(item, css, true);
179 sp_repr_css_attr_unref (css);
180 item->updateRepr();
181 }
182}
183
184//actual effect impl here
185
186Geom::Path return_at_first_cusp (Geom::Path const & path_in, double /*smooth_tolerance*/ = 0.05)
187{
188 return Geom::split_at_cusps(path_in)[0];
189}
190
191Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in, Geom::Path pattern, double width);
192
193//references to pointers, because magic
194void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second);
195
196Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in)
197{
198 Geom::Path first_cusp = return_at_first_cusp(path_in[0]);
199 Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse());
200
201 bool zeroStart = false;
202 bool zeroEnd = false;
203 bool metInMiddle = false;
204
205 //there is a pretty good chance that people will try to drag the knots
206 //on top of each other, so block it
207
208 unsigned size = path_in[0].size();
209 if (size == first_cusp.size()) {
210 //check to see if the knots were dragged over each other
211 //if so, reset the end offset, but still allow the start offset.
212 if ( attach_start >= (size - attach_end) ) {
213 attach_end.param_set_value( size - attach_start );
214 metInMiddle = true;
215 }
216 }
217
218 if (attach_start == size - attach_end) {
219 metInMiddle = true;
220 }
221 if (attach_end == size - attach_start) {
222 metInMiddle = true;
223 }
224
225 //don't let it be integer
226 {
227 if (double(unsigned(attach_start)) == attach_start) {
228 attach_start.param_set_value(attach_start - 0.00001);
229 }
230 if (double(unsigned(attach_end)) == attach_end) {
231 attach_end.param_set_value(attach_end - 0.00001);
232 }
233 }
234
235 unsigned allowed_start = first_cusp.size();
236 unsigned allowed_end = last_cusp.size();
237
238 //don't let the knots be farther than they are allowed to be
239 {
240 if ((unsigned)attach_start >= allowed_start) {
241 attach_start.param_set_value((double)allowed_start - 0.00001);
242 }
243 if ((unsigned)attach_end >= allowed_end) {
244 attach_end.param_set_value((double)allowed_end - 0.00001);
245 }
246 }
247
248 //don't let it be zero
249 if (attach_start < 0.0000001 || withinRange(double(attach_start), 0.00000001, 0.000001)) {
250 attach_start.param_set_value( 0.0000001 );
251 zeroStart = true;
252 }
253 if (attach_end < 0.0000001 || withinRange(double(attach_end), 0.00000001, 0.000001)) {
254 attach_end.param_set_value( 0.0000001 );
255 zeroEnd = true;
256 }
257
258 //remember, Path::operator () means get point at time t
259 start_attach_point = first_cusp(attach_start);
260 end_attach_point = last_cusp(attach_end);
261 Geom::PathVector pathv_out;
262
263 //the following function just splits it up into three pieces.
264 pathv_out = doEffect_simplePath(path_in);
265
266 //now for the actual tapering. We use the stretch_along method to get this done.
267
268 Geom::PathVector real_pathv;
269 Geom::Path real_path;
270 Geom::PathVector pat_vec;
271 Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2;
272 Geom::Path throwaway_path;
273
274 if (!zeroStart) {
275 //Construct the pattern (pat_str stands for pattern string) (and yes, this is easier, trust me)
276 std::stringstream pat_str;
277 pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1";
278
279 pat_vec = sp_svg_read_pathv(pat_str.str().c_str());
280 pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width)));
281 throwaway_path = Geom::path_from_piecewise(pwd2, LPE_CONVERSION_TOLERANCE)[0];
282
283 real_path.append(throwaway_path);
284 }
285
286 if (!metInMiddle) {
287 //append the outside outline of the path (with direction)
288 throwaway_path = Outline::PathOutsideOutline(pathv_out[1],
289 -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
290 if (!zeroStart && real_path.size() >= 1 && throwaway_path.size() >= 1) {
291 if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001) {
292 real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
293 } else {
294 real_path.setFinal(throwaway_path.initialPoint());
295 }
296 }
297 real_path.append(throwaway_path);
298 }
299
300 if (!zeroEnd) {
301 //append the ending taper
302 std::stringstream pat_str_1;
303 pat_str_1 << "M 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0";
304 pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str());
305
306 pwd2 = Geom::Piecewise<Geom::D2<Geom::SBasis> > ();
307 pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width)));
308
309 throwaway_path = Geom::path_from_piecewise(pwd2, LPE_CONVERSION_TOLERANCE)[0];
310 if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001 && real_path.size() >= 1) {
311 real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
312 } else {
313 real_path.setFinal(throwaway_path.initialPoint());
314 }
315 real_path.append(throwaway_path);
316 }
317
318 if (!metInMiddle) {
319 //append the inside outline of the path (against direction)
320 throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(),
321 -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
322
323 if (Geom::distance(real_path.finalPoint(), throwaway_path.initialPoint()) > 0.0000001 && real_path.size() >= 1) {
324 real_path.appendNew<Geom::LineSegment>(throwaway_path.initialPoint());
325 } else {
326 real_path.setFinal(throwaway_path.initialPoint());
327 }
328 real_path.append(throwaway_path);
329 }
330
331 if (Geom::distance(real_path.finalPoint(), real_path.initialPoint()) > 0.0000001) {
332 real_path.appendNew<Geom::LineSegment>(real_path.initialPoint());
333 } else {
334 real_path.setFinal(real_path.initialPoint());
335 }
336 real_path.close();
337
338 real_pathv.push_back(real_path);
339
340 return real_pathv;
341}
342
343//in all cases, this should return a PathVector with three elements.
344Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & path_in)
345{
346 unsigned size = path_in[0].size();
347
348 //do subdivision and get out
349 unsigned loc = (unsigned)attach_start;
350 Geom::Curve * curve_start = path_in[0] [loc].duplicate();
351
352 std::vector<Geom::Path> pathv_out;
353 Geom::Path path_out = Geom::Path();
354
355 Geom::Path trimmed_start = Geom::Path();
356 Geom::Path trimmed_end = Geom::Path();
357
358 for (unsigned i = 0; i < loc; i++) {
359 trimmed_start.append(path_in[0] [i]);
360 }
361
362 Geom::Curve * temp;
363 subdivideCurve(curve_start, attach_start - loc, temp, curve_start);
364 trimmed_start.append(*temp);
365 if (temp) delete temp; temp = 0;
366
367 //special case: path is one segment long
368 //special case: what if the two knots occupy the same segment?
369 if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) {
370 Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start);
371
372 //it is just a dumb segment
373 //we have to do some shifting here because the value changed when we reduced the length
374 //of the previous segment.
375
376 subdivideCurve(curve_start, t, curve_start, temp);
377 trimmed_end.append(*temp);
378 if (temp) delete temp; temp = 0;
379
380 for (unsigned j = (size - attach_end) + 1; j < size; j++) {
381 trimmed_end.append(path_in[0] [j]);
382 }
383
384 path_out.append(*curve_start);
385 pathv_out.push_back(trimmed_start);
386 pathv_out.push_back(path_out);
387 pathv_out.push_back(trimmed_end);
388 return pathv_out;
389 }
390
391 pathv_out.push_back(trimmed_start);
392
393 //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute)
394 path_out.append(*curve_start);
395
396 for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) {
397 path_out.append(path_in[0] [k]);
398 }
399
400 //deal with the last segment in a very similar fashion to the first
401 loc = size - attach_end;
402
403 Geom::Curve * curve_end = path_in[0] [loc].duplicate();
404
405 Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end);
406
407 subdivideCurve(curve_end, t, curve_end, temp);
408 trimmed_end.append(*temp);
409 if (temp) delete temp; temp = 0;
410
411 for (unsigned j = (size - attach_end) + 1; j < size; j++) {
412 trimmed_end.append(path_in[0] [j]);
413 }
414
415 path_out.append(*curve_end);
416 pathv_out.push_back(path_out);
417
418 pathv_out.push_back(trimmed_end);
419
420 if (curve_end) delete curve_end;
421 if (curve_start) delete curve_start;
422 return pathv_out;
423}
424
425
426//most of the below code is verbatim from Pattern Along Path. However, it needed a little
427//tweaking to get it to work right in this case.
428Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in, Geom::Path pattern, double prop_scale)
429{
430 using namespace Geom;
431
432 // Don't allow empty path parameter:
433 if ( pattern.empty() ) {
434 return pwd2_in;
435 }
436
437 /* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */
438 Piecewise<D2<SBasis> > output;
439 std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pre_output;
440
441 D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pattern.toPwSb());
442 Piecewise<SBasis> x0 = Piecewise<SBasis>(patternd2[0]);
443 Piecewise<SBasis> y0 = Piecewise<SBasis>(patternd2[1]);
444 OptInterval pattBndsX = bounds_exact(x0);
445 OptInterval pattBndsY = bounds_exact(y0);
446 if (pattBndsX && pattBndsY) {
447 x0 -= pattBndsX->min();
448 y0 -= pattBndsY->middle();
449
450 double xspace = 0;
451 double noffset = 0;
452 double toffset = 0;
453 //Prevent more than 90% overlap...
454 if (xspace < -pattBndsX->extent()*.9) {
455 xspace = -pattBndsX->extent()*.9;
456 }
457
458 y0+=noffset;
459
460 std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > paths_in;
461 paths_in = split_at_discontinuities(pwd2_in);
462
463 for (unsigned idx = 0; idx < paths_in.size(); idx++) {
464 Geom::Piecewise<Geom::D2<Geom::SBasis> > path_i = paths_in[idx];
465 Piecewise<SBasis> x = x0;
466 Piecewise<SBasis> y = y0;
467 Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(path_i,2,.1);
468 uskeleton = remove_short_cuts(uskeleton,.01);
469 Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
470 n = force_continuity(remove_short_cuts(n,.1));
471
472 int nbCopies = 0;
473 double scaling = 1;
474 nbCopies = 1;
475 scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent();
476
477 double pattWidth = pattBndsX->extent() * scaling;
478
479 if (scaling != 1.0) {
480 x*=scaling;
481 }
482 if ( false ) {
483 y*=(scaling*prop_scale);
484 } else {
485 if (prop_scale != 1.0) y *= prop_scale;
486 }
487 x += toffset;
488
489 double offs = 0;
490 for (int i=0; i<nbCopies; i++) {
491 if (false) {
492 Geom::Piecewise<Geom::D2<Geom::SBasis> > output_piece = compose(uskeleton,x+offs)+y*compose(n,x+offs);
493 std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > splited_output_piece = split_at_discontinuities(output_piece);
494 pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() );
495 } else {
496 output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
497 }
498 offs+=pattWidth;
499 }
500 }
501 return output;
502 } else {
503 return pwd2_in;
504 }
505}
506
507void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second)
508{
509 if (Geom::LineSegment* linear = dynamic_cast<Geom::LineSegment*>(curve_in)) {
510 //special case for line segments
511 std::pair<Geom::LineSegment, Geom::LineSegment> seg_pair = linear->subdivide(t);
512 val_first = seg_pair.first.duplicate();
513 val_second = seg_pair.second.duplicate();
514 } else {
515 //all other cases:
516 Geom::CubicBezier cubic = Geom::sbasis_to_cubicbezier(curve_in->toSBasis());
517 std::pair<Geom::CubicBezier, Geom::CubicBezier> cubic_pair = cubic.subdivide(t);
518 val_first = cubic_pair.first.duplicate();
519 val_second = cubic_pair.second.duplicate();
520 }
521}
522
523
524void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
525{
526 {
527 KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this);
528 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
529 _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE );
530 knotholder->add(e);
531 }
532 {
533 KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this);
534 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
535 _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE );
536 knotholder->add(e);
537 }
538}
539
540namespace TpS {
541void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
542{
543 using namespace Geom;
544
545 LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
546
547 Geom::Point const s = snap_knot_position(p, state);
548
549 if (!SP_IS_SHAPE(lpe->sp_lpe_item) ) {
550 g_warning("LPEItem is not a path! %s:%d\n", __FILE__, __LINE__);
551 return;
552 }
553
554 SPCurve* curve;
555 if ( !(curve = SP_SHAPE(lpe->sp_lpe_item)->getCurve()) ) {
556 //oops
557 //lpe->attach_start.param_set_value(0);
558 return;
559 }
560 //in case you are wondering, the above are simply sanity checks. we never want to actually
561 //use that object.
562
563 Geom::PathVector pathv = lpe->pathvector_before_effect;
564
565 Piecewise<D2<SBasis> > pwd2;
566 Geom::Path p_in = return_at_first_cusp(pathv[0]);
567 pwd2.concat(p_in.toPwSb());
568
569 double t0 = nearest_point(s, pwd2);
570 lpe->attach_start.param_set_value(t0);
571
572 // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
573 sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
574}
575void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state)
576{
577 using namespace Geom;
578
579 LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
580
581 Geom::Point const s = snap_knot_position(p, state);
582
583 if (!SP_IS_SHAPE(lpe->sp_lpe_item) ) {
584 g_warning("LPEItem is not a path! %s:%d\n", __FILE__, __LINE__);
585 return;
586 }
587
588 SPCurve* curve;
589 if ( !(curve = SP_SHAPE(lpe->sp_lpe_item)->getCurve()) ) {
590 //oops
591 //lpe->attach_end.param_set_value(0);
592 return;
593 }
594 Geom::PathVector pathv = lpe->pathvector_before_effect;
595 Geom::Path p_in = return_at_first_cusp(pathv[0].reverse());
596 Piecewise<D2<SBasis> > pwd2 = p_in.toPwSb();
597
598 double t0 = nearest_point(s, pwd2);
599 lpe->attach_end.param_set_value(t0);
600
601 sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
602}
603Geom::Point KnotHolderEntityAttachBegin::knot_get() const
604{
605 LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
606 return lpe->start_attach_point;
607}
608Geom::Point KnotHolderEntityAttachEnd::knot_get() const
609{
610 LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
611 return lpe->end_attach_point;
612}
613}
614
615
616/* ######################## */
617
618} //namespace LivePathEffect
619} /* namespace Inkscape */
620
621/*
622 Local Variables:
623 mode:c++
624 c-file-style:"stroustrup"
625 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
626 indent-tabs-mode:nil
627 fill-column:99
628 End:
629*/
630// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
0631
=== added file 'src/live_effects/lpe-taperstroke.h'
--- src/live_effects/lpe-taperstroke.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/lpe-taperstroke.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,72 @@
1/** @file
2 * @brief Taper Stroke path effect (meant as a replacement for using Power Strokes for tapering)
3 */
4/* Authors:
5 * Liam P White <inkscapebrony@gmail.com>
6 * Copyright (C) 2014 Authors
7 *
8 * Released under GNU GPL, read the file 'COPYING' for more information
9 */
10
11#ifndef INKSCAPE_LPE_TAPERSTROKE_H
12#define INKSCAPE_LPE_TAPERSTROKE_H
13
14#include "live_effects/parameter/enum.h"
15#include "live_effects/effect.h"
16#include "live_effects/parameter/parameter.h"
17#include "live_effects/parameter/vector.h"
18
19namespace Inkscape {
20namespace LivePathEffect {
21
22namespace TpS {
23// we need a separate namespace to avoid clashes with other LPEs
24class KnotHolderEntityAttachBegin;
25class KnotHolderEntityAttachEnd;
26}
27
28class LPETaperStroke : public Effect {
29public:
30 LPETaperStroke(LivePathEffectObject *lpeobject);
31 virtual ~LPETaperStroke();
32
33 virtual void doOnApply(SPLPEItem const* lpeitem);
34 virtual void doOnRemove(SPLPEItem const* lpeitem);
35
36 virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in);
37 Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in);
38
39 virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item);
40
41 friend class TpS::KnotHolderEntityAttachBegin;
42 friend class TpS::KnotHolderEntityAttachEnd;
43private:
44 ScalarParam line_width;
45 ScalarParam attach_start;
46 ScalarParam attach_end;
47 ScalarParam smoothing;
48 EnumParam<unsigned> join_type;
49 ScalarParam miter_limit;
50
51 Geom::Point start_attach_point;
52 Geom::Point end_attach_point;
53
54 LPETaperStroke(const LPETaperStroke&);
55 LPETaperStroke& operator=(const LPETaperStroke&);
56};
57
58} //namespace LivePathEffect
59} //namespace Inkscape
60
61#endif
62
63/*
64 Local Variables:
65 mode:c++
66 c-file-style:"stroustrup"
67 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
68 indent-tabs-mode:nil
69 fill-column:99
70 End:
71*/
72// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
073
=== modified file 'src/live_effects/parameter/Makefile_insert'
--- src/live_effects/parameter/Makefile_insert 2014-07-02 11:14:35 +0000
+++ src/live_effects/parameter/Makefile_insert 2014-09-07 17:02:32 +0000
@@ -20,12 +20,16 @@
20 live_effects/parameter/path.h \20 live_effects/parameter/path.h \
21 live_effects/parameter/originalpath.cpp \21 live_effects/parameter/originalpath.cpp \
22 live_effects/parameter/originalpath.h \22 live_effects/parameter/originalpath.h \
23 live_effects/parameter/originalpatharray.cpp \
24 live_effects/parameter/originalpatharray.h \
23 live_effects/parameter/powerstrokepointarray.cpp \25 live_effects/parameter/powerstrokepointarray.cpp \
24 live_effects/parameter/powerstrokepointarray.h \26 live_effects/parameter/powerstrokepointarray.h \
25 live_effects/parameter/filletchamferpointarray.cpp \27 live_effects/parameter/filletchamferpointarray.cpp \
26 live_effects/parameter/filletchamferpointarray.h \28 live_effects/parameter/filletchamferpointarray.h \
27 live_effects/parameter/text.cpp \29 live_effects/parameter/text.cpp \
28 live_effects/parameter/text.h \30 live_effects/parameter/text.h \
31 live_effects/parameter/transformedpoint.cpp \
32 live_effects/parameter/transformedpoint.h \
29 live_effects/parameter/togglebutton.cpp \33 live_effects/parameter/togglebutton.cpp \
30 live_effects/parameter/togglebutton.h \34 live_effects/parameter/togglebutton.h \
31 live_effects/parameter/unit.cpp \35 live_effects/parameter/unit.cpp \
3236
=== modified file 'src/live_effects/parameter/filletchamferpointarray.cpp'
--- src/live_effects/parameter/filletchamferpointarray.cpp 2014-08-24 10:37:18 +0000
+++ src/live_effects/parameter/filletchamferpointarray.cpp 2014-09-07 17:02:32 +0000
@@ -8,11 +8,14 @@
8 * Released under GNU GPL, read the file 'COPYING' for more information8 * Released under GNU GPL, read the file 'COPYING' for more information
9 */9 */
1010
11#include <glibmm.h>
12
11#include "ui/dialog/lpe-fillet-chamfer-properties.h"13#include "ui/dialog/lpe-fillet-chamfer-properties.h"
12#include "live_effects/parameter/filletchamferpointarray.h"14#include "live_effects/parameter/filletchamferpointarray.h"
13#include <2geom/piecewise.h>15#include <2geom/piecewise.h>
14#include <2geom/sbasis-to-bezier.h>16#include <2geom/sbasis-to-bezier.h>
15#include <2geom/sbasis-geometric.h>17#include <2geom/sbasis-geometric.h>
18#include <gtkmm.h>
1619
17#include "live_effects/effect.h"20#include "live_effects/effect.h"
18#include "svg/svg.h"21#include "svg/svg.h"
1922
=== added file 'src/live_effects/parameter/originalpatharray.cpp'
--- src/live_effects/parameter/originalpatharray.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/parameter/originalpatharray.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,497 @@
1/*
2 * Copyright (C) Johan Engelen 2008 <j.b.c.engelen@utwente.nl>
3 *
4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */
6
7#ifdef HAVE_CONFIG_H
8# include "config.h"
9#endif
10
11#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H
12#include <glibmm/threads.h>
13#endif
14
15#include "live_effects/parameter/originalpatharray.h"
16
17#include <gtkmm/widget.h>
18#include <gtkmm/icontheme.h>
19#include <gtkmm/imagemenuitem.h>
20#include <gtkmm/separatormenuitem.h>
21#include <gtkmm/scrolledwindow.h>
22
23#include <glibmm/i18n.h>
24
25#include "inkscape.h"
26#include "icon-size.h"
27#include "widgets/icon.h"
28#include "ui/clipboard.h"
29#include "svg/svg.h"
30#include "svg/stringstream.h"
31#include "originalpath.h"
32#include "uri.h"
33#include "display/curve.h"
34
35#include <2geom/coord.h>
36#include <2geom/point.h>
37#include "sp-shape.h"
38#include "sp-text.h"
39#include "live_effects/effect.h"
40
41#include "verbs.h"
42#include "document-undo.h"
43#include "document.h"
44
45namespace Inkscape {
46
47namespace LivePathEffect {
48
49class OriginalPathArrayParam::ModelColumns : public Gtk::TreeModel::ColumnRecord
50{
51public:
52
53 ModelColumns()
54 {
55 add(_colObject);
56 add(_colLabel);
57 add(_colReverse);
58 }
59 virtual ~ModelColumns() {}
60
61 Gtk::TreeModelColumn<PathAndDirection*> _colObject;
62 Gtk::TreeModelColumn<Glib::ustring> _colLabel;
63 Gtk::TreeModelColumn<bool> _colReverse;
64};
65
66OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label,
67 const Glib::ustring& tip,
68 const Glib::ustring& key,
69 Inkscape::UI::Widget::Registry* wr,
70 Effect* effect )
71: Parameter(label, tip, key, wr, effect),
72 _vector(),
73 _tree(),
74 _text_renderer(),
75 _toggle_renderer(),
76 _scroller()
77{
78 _model = new ModelColumns();
79 _store = Gtk::TreeStore::create(*_model);
80 _tree.set_model(_store);
81
82 _tree.set_reorderable(true);
83 _tree.enable_model_drag_dest (Gdk::ACTION_MOVE);
84
85 _text_renderer = manage(new Gtk::CellRendererText());
86 int nameColNum = _tree.append_column(_("Name"), *_text_renderer) - 1;
87 _name_column = _tree.get_column(nameColNum);
88 _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel);
89
90 _tree.set_expander_column( *_tree.get_column(nameColNum) );
91 _tree.set_search_column(_model->_colLabel);
92
93 Gtk::CellRendererToggle * _toggle_renderer = manage(new Gtk::CellRendererToggle());
94 int toggleColNum = _tree.append_column(_("Reverse"), *_toggle_renderer) - 1;
95 Gtk::TreeViewColumn* col = _tree.get_column(toggleColNum);
96 _toggle_renderer->set_activatable(true);
97 _toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled));
98 col->add_attribute(_toggle_renderer->property_active(), _model->_colReverse);
99
100 //quick little hack -- newer versions of gtk gave the item zero space allotment
101 _scroller.set_size_request(-1, 120);
102
103 _scroller.add(_tree);
104 _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
105 //_scroller.set_shadow_type(Gtk::SHADOW_IN);
106
107 oncanvas_editable = true;
108
109}
110
111OriginalPathArrayParam::~OriginalPathArrayParam()
112{
113 while (!_vector.empty()) {
114 PathAndDirection *w = _vector.back();
115 _vector.pop_back();
116 unlink(w);
117 delete w;
118 }
119 delete _model;
120}
121
122void OriginalPathArrayParam::on_reverse_toggled(const Glib::ustring& path)
123{
124 Gtk::TreeModel::iterator iter = _store->get_iter(path);
125 Gtk::TreeModel::Row row = *iter;
126 PathAndDirection *w = row[_model->_colObject];
127 row[_model->_colReverse] = !row[_model->_colReverse];
128 w->reversed = row[_model->_colReverse];
129
130 gchar * full = param_getSVGValue();
131 param_write_to_repr(full);
132 g_free(full);
133 DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
134 _("Link path parameter to path"));
135}
136
137void OriginalPathArrayParam::param_set_default()
138{
139
140}
141
142Gtk::Widget* OriginalPathArrayParam::param_newWidget()
143{
144 Gtk::VBox* vbox = Gtk::manage(new Gtk::VBox());
145 Gtk::HBox* hbox = Gtk::manage(new Gtk::HBox());
146
147 vbox->pack_start(_scroller, Gtk::PACK_EXPAND_WIDGET);
148
149
150 { // Paste path to link button
151 Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_PASTE, Inkscape::ICON_SIZE_BUTTON) );
152 Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
153 pButton->set_relief(Gtk::RELIEF_NONE);
154 pIcon->show();
155 pButton->add(*pIcon);
156 pButton->show();
157 pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_link_button_click));
158 hbox->pack_start(*pButton, Gtk::PACK_SHRINK);
159 pButton->set_tooltip_text(_("Link to path"));
160 }
161
162 { // Remove linked path
163 Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_REMOVE, Inkscape::ICON_SIZE_BUTTON) );
164 Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
165 pButton->set_relief(Gtk::RELIEF_NONE);
166 pIcon->show();
167 pButton->add(*pIcon);
168 pButton->show();
169 pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_remove_button_click));
170 hbox->pack_start(*pButton, Gtk::PACK_SHRINK);
171 pButton->set_tooltip_text(_("Remove Path"));
172 }
173
174 { // Move Down
175 Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_GO_DOWN, Inkscape::ICON_SIZE_BUTTON) );
176 Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
177 pButton->set_relief(Gtk::RELIEF_NONE);
178 pIcon->show();
179 pButton->add(*pIcon);
180 pButton->show();
181 pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_down_button_click));
182 hbox->pack_end(*pButton, Gtk::PACK_SHRINK);
183 pButton->set_tooltip_text(_("Move Down"));
184 }
185
186 { // Move Down
187 Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( GTK_STOCK_GO_UP, Inkscape::ICON_SIZE_BUTTON) );
188 Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
189 pButton->set_relief(Gtk::RELIEF_NONE);
190 pIcon->show();
191 pButton->add(*pIcon);
192 pButton->show();
193 pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_up_button_click));
194 hbox->pack_end(*pButton, Gtk::PACK_SHRINK);
195 pButton->set_tooltip_text(_("Move Up"));
196 }
197
198 vbox->pack_end(*hbox, Gtk::PACK_SHRINK);
199
200 vbox->show_all_children(true);
201
202 return vbox;
203}
204
205bool OriginalPathArrayParam::_selectIndex(const Gtk::TreeIter& iter, int* i)
206{
207 if ((*i)-- <= 0) {
208 _tree.get_selection()->select(iter);
209 return true;
210 }
211 return false;
212}
213
214void OriginalPathArrayParam::on_up_button_click()
215{
216 Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
217 if (iter) {
218 Gtk::TreeModel::Row row = *iter;
219
220 int i = -1;
221 std::vector<PathAndDirection*>::iterator piter = _vector.begin();
222 for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); piter = iter, i++, iter++) {
223 if (*iter == row[_model->_colObject]) {
224 _vector.erase(iter);
225 _vector.insert(piter, row[_model->_colObject]);
226 break;
227 }
228 }
229
230 gchar * full = param_getSVGValue();
231 param_write_to_repr(full);
232 g_free(full);
233
234 DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
235 _("Move path up"));
236
237 _store->foreach_iter(sigc::bind<int*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_selectIndex), &i));
238 }
239}
240
241void OriginalPathArrayParam::on_down_button_click()
242{
243 Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
244 if (iter) {
245 Gtk::TreeModel::Row row = *iter;
246
247 int i = 0;
248 for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); i++, iter++) {
249 if (*iter == row[_model->_colObject]) {
250 std::vector<PathAndDirection*>::iterator niter = _vector.erase(iter);
251 if (niter != _vector.end()) {
252 niter++;
253 i++;
254 }
255 _vector.insert(niter, row[_model->_colObject]);
256 break;
257 }
258 }
259
260 gchar * full = param_getSVGValue();
261 param_write_to_repr(full);
262 g_free(full);
263
264 DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
265 _("Move path down"));
266
267 _store->foreach_iter(sigc::bind<int*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_selectIndex), &i));
268 }
269}
270
271void OriginalPathArrayParam::on_remove_button_click()
272{
273 Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
274 if (iter) {
275 Gtk::TreeModel::Row row = *iter;
276 remove_link(row[_model->_colObject]);
277
278 gchar * full = param_getSVGValue();
279 param_write_to_repr(full);
280 g_free(full);
281
282 DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
283 _("Remove path"));
284 }
285
286}
287
288void
289OriginalPathArrayParam::on_link_button_click()
290{
291 Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
292 Glib::ustring pathid = cm->getShapeOrTextObjectId(SP_ACTIVE_DESKTOP);
293
294 if (pathid == "") {
295 return;
296 }
297 // add '#' at start to make it an uri.
298 pathid.insert(pathid.begin(), '#');
299
300 Inkscape::SVGOStringStream os;
301 bool foundOne = false;
302 for (std::vector<PathAndDirection*>::const_iterator iter = _vector.begin(); iter != _vector.end(); iter++) {
303 if (foundOne) {
304 os << "|";
305 } else {
306 foundOne = true;
307 }
308 os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0");
309 }
310
311 if (foundOne) {
312 os << "|";
313 }
314
315 os << pathid.c_str() << ",0";
316
317 param_write_to_repr(os.str().c_str());
318 DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
319 _("Link path parameter to path"));
320}
321
322void OriginalPathArrayParam::unlink(PathAndDirection* to)
323{
324 to->linked_modified_connection.disconnect();
325 to->linked_delete_connection.disconnect();
326 to->ref.detach();
327 to->_pathvector = Geom::PathVector();
328 if (to->href) {
329 g_free(to->href);
330 to->href = NULL;
331 }
332}
333
334void OriginalPathArrayParam::remove_link(PathAndDirection* to)
335{
336 unlink(to);
337 for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); iter++) {
338 if (*iter == to) {
339 PathAndDirection *w = *iter;
340 _vector.erase(iter);
341 delete w;
342 return;
343 }
344 }
345}
346
347void OriginalPathArrayParam::linked_delete(SPObject */*deleted*/, PathAndDirection* to)
348{
349 //remove_link(to);
350
351 gchar * full = param_getSVGValue();
352 param_write_to_repr(full);
353 g_free(full);
354}
355
356bool OriginalPathArrayParam::_updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd)
357{
358 Gtk::TreeModel::Row row = *iter;
359 if (row[_model->_colObject] == pd) {
360 SPObject *obj = pd->ref.getObject();
361 row[_model->_colLabel] = obj && obj->getId() ? ( obj->label() ? obj->label() : obj->getId() ) : pd->href;
362 return true;
363 }
364 return false;
365}
366
367void OriginalPathArrayParam::linked_changed(SPObject */*old_obj*/, SPObject *new_obj, PathAndDirection* to)
368{
369 to->linked_delete_connection.disconnect();
370 to->linked_modified_connection.disconnect();
371 to->linked_transformed_connection.disconnect();
372
373 if (new_obj && SP_IS_ITEM(new_obj)) {
374 to->linked_delete_connection = new_obj->connectDelete(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_delete), to));
375 to->linked_modified_connection = new_obj->connectModified(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_modified), to));
376 to->linked_transformed_connection = SP_ITEM(new_obj)->connectTransformed(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_transformed), to));
377
378 linked_modified(new_obj, SP_OBJECT_MODIFIED_FLAG, to);
379 } else {
380 to->_pathvector = Geom::PathVector();
381 SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG);
382 _store->foreach_iter(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to));
383 }
384}
385
386void OriginalPathArrayParam::linked_transformed(Geom::Affine const *mp, SPItem* original, PathAndDirection* to)
387{
388
389}
390
391void OriginalPathArrayParam::setPathVector(SPObject *linked_obj, guint flags, PathAndDirection* to)
392{
393 if (!to) {
394 return;
395 }
396 SPCurve *curve = NULL;
397 if (SP_IS_SHAPE(linked_obj)) {
398 curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE();
399 }
400 if (SP_IS_TEXT(linked_obj)) {
401 curve = SP_TEXT(linked_obj)->getNormalizedBpath();
402 }
403
404 if (curve == NULL) {
405 // curve invalid, set empty pathvector
406 to->_pathvector = Geom::PathVector();
407 } else {
408 to->_pathvector = curve->get_pathvector();
409 curve->unref();
410 }
411}
412
413void OriginalPathArrayParam::linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to)
414{
415 if (!to) {
416 return;
417 }
418 setPathVector(linked_obj, flags, to);
419 SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG);
420 _store->foreach_iter(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to));
421}
422
423//void PathParam::linked_transformed(Geom::Affine const *rel_transf, SPItem *moved_item)
424//{
425// linked_transformed_callback(rel_transf, moved_item);
426//}
427
428bool OriginalPathArrayParam::param_readSVGValue(const gchar* strvalue)
429{
430 if (strvalue) {
431 while (!_vector.empty()) {
432 PathAndDirection *w = _vector.back();
433 unlink(w);
434 _vector.pop_back();
435 delete w;
436 }
437 _store->clear();
438
439 gchar ** strarray = g_strsplit(strvalue, "|", 0);
440 for (gchar ** iter = strarray; *iter != NULL; iter++) {
441 if ((*iter)[0] == '#') {
442 gchar ** substrarray = g_strsplit(*iter, ",", 0);
443 PathAndDirection* w = new PathAndDirection((SPObject *)param_effect->getLPEObj());
444 w->href = g_strdup(*substrarray);
445 w->reversed = *(substrarray+1) != NULL && (*(substrarray+1))[0] == '1';
446
447 w->linked_changed_connection = w->ref.changedSignal().connect(sigc::bind<PathAndDirection *>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_changed), w));
448 w->ref.attach(URI(w->href));
449
450 _vector.push_back(w);
451
452 Gtk::TreeModel::iterator iter = _store->append();
453 Gtk::TreeModel::Row row = *iter;
454 SPObject *obj = w->ref.getObject();
455
456 row[_model->_colObject] = w;
457 row[_model->_colLabel] = obj ? ( obj->label() ? obj->label() : obj->getId() ) : w->href;
458 row[_model->_colReverse] = w->reversed;
459 g_strfreev (substrarray);
460 }
461 }
462 g_strfreev (strarray);
463 return true;
464 }
465 return false;
466}
467
468gchar * OriginalPathArrayParam::param_getSVGValue() const
469{
470 Inkscape::SVGOStringStream os;
471 bool foundOne = false;
472 for (std::vector<PathAndDirection*>::const_iterator iter = _vector.begin(); iter != _vector.end(); iter++) {
473 if (foundOne) {
474 os << "|";
475 } else {
476 foundOne = true;
477 }
478 os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0");
479 }
480 gchar * str = g_strdup(os.str().c_str());
481 return str;
482}
483
484} /* namespace LivePathEffect */
485
486} /* namespace Inkscape */
487
488/*
489 Local Variables:
490 mode:c++
491 c-file-style:"stroustrup"
492 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
493 indent-tabs-mode:nil
494 fill-column:99
495 End:
496*/
497// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
0498
=== added file 'src/live_effects/parameter/originalpatharray.h'
--- src/live_effects/parameter/originalpatharray.h 1970-01-01 00:00:00 +0000
+++ src/live_effects/parameter/originalpatharray.h 2014-09-07 17:02:32 +0000
@@ -0,0 +1,123 @@
1#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALPATHARRAY_H
2#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALPATHARRAY_H
3
4/*
5 * Inkscape::LivePathEffectParameters
6 *
7* Copyright (C) Johan Engelen 2008 <j.b.c.engelen@utwente.nl>
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
11
12#include <vector>
13
14#include <gtkmm/box.h>
15#include <gtkmm/treeview.h>
16#include <gtkmm/treestore.h>
17#include <gtkmm/scrolledwindow.h>
18
19#include "live_effects/parameter/parameter.h"
20#include "live_effects/parameter/path-reference.h"
21
22#include "svg/svg.h"
23#include "svg/stringstream.h"
24#include "path-reference.h"
25#include "sp-object.h"
26
27namespace Inkscape {
28
29namespace LivePathEffect {
30
31class PathAndDirection {
32public:
33 PathAndDirection(SPObject *owner)
34 : href(NULL),
35 ref(owner),
36 _pathvector(Geom::PathVector()),
37 reversed(false)
38 {
39
40 }
41 gchar *href;
42 URIReference ref;
43 //SPItem *obj;
44 std::vector<Geom::Path> _pathvector;
45 bool reversed;
46
47 sigc::connection linked_changed_connection;
48 sigc::connection linked_delete_connection;
49 sigc::connection linked_modified_connection;
50 sigc::connection linked_transformed_connection;
51};
52
53class OriginalPathArrayParam : public Parameter {
54public:
55 class ModelColumns;
56
57 OriginalPathArrayParam( const Glib::ustring& label,
58 const Glib::ustring& tip,
59 const Glib::ustring& key,
60 Inkscape::UI::Widget::Registry* wr,
61 Effect* effect);
62
63 virtual ~OriginalPathArrayParam();
64
65 virtual Gtk::Widget * param_newWidget();
66 virtual bool param_readSVGValue(const gchar * strvalue);
67 virtual gchar * param_getSVGValue() const;
68 virtual void param_set_default();
69
70 /** Disable the canvas indicators of parent class by overriding this method */
71 virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {};
72 /** Disable the canvas indicators of parent class by overriding this method */
73 virtual void addCanvasIndicators(SPLPEItem const* /*lpeitem*/, std::vector<Geom::PathVector> & /*hp_vec*/) {};
74
75 std::vector<PathAndDirection*> _vector;
76
77protected:
78 bool _updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd);
79 bool _selectIndex(const Gtk::TreeIter& iter, int* i);
80 void unlink(PathAndDirection* to);
81 void remove_link(PathAndDirection* to);
82 void setPathVector(SPObject *linked_obj, guint flags, PathAndDirection* to);
83
84 void linked_changed(SPObject *old_obj, SPObject *new_obj, PathAndDirection* to);
85 void linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to);
86 void linked_transformed(Geom::Affine const *mp, SPItem *original, PathAndDirection* to);
87 void linked_delete(SPObject *deleted, PathAndDirection* to);
88
89 ModelColumns *_model;
90 Glib::RefPtr<Gtk::TreeStore> _store;
91 Gtk::TreeView _tree;
92 Gtk::CellRendererText *_text_renderer;
93 Gtk::CellRendererToggle *_toggle_renderer;
94 Gtk::TreeView::Column *_name_column;
95 Gtk::ScrolledWindow _scroller;
96
97 void on_link_button_click();
98 void on_remove_button_click();
99 void on_up_button_click();
100 void on_down_button_click();
101 void on_reverse_toggled(const Glib::ustring& path);
102
103private:
104 OriginalPathArrayParam(const OriginalPathArrayParam&);
105 OriginalPathArrayParam& operator=(const OriginalPathArrayParam&);
106};
107
108} //namespace LivePathEffect
109
110} //namespace Inkscape
111
112#endif
113
114/*
115 Local Variables:
116 mode:c++
117 c-file-style:"stroustrup"
118 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
119 indent-tabs-mode:nil
120 fill-column:99
121 End:
122*/
123// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
0124
=== modified file 'src/live_effects/parameter/powerstrokepointarray.cpp'
--- src/live_effects/parameter/powerstrokepointarray.cpp 2014-07-27 01:17:50 +0000
+++ src/live_effects/parameter/powerstrokepointarray.cpp 2014-09-07 17:02:32 +0000
@@ -4,8 +4,7 @@
4 * Released under GNU GPL, read the file 'COPYING' for more information4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */5 */
66
7#include <glibmm/i18n.h>7#include "ui/dialog/lpe-powerstroke-properties.h"
8
9#include "live_effects/parameter/powerstrokepointarray.h"8#include "live_effects/parameter/powerstrokepointarray.h"
109
11#include "live_effects/effect.h"10#include "live_effects/effect.h"
@@ -21,6 +20,8 @@
21#include "desktop.h"20#include "desktop.h"
22#include "live_effects/lpeobject.h"21#include "live_effects/lpeobject.h"
2322
23#include <glibmm/i18n.h>
24
24namespace Inkscape {25namespace Inkscape {
2526
26namespace LivePathEffect {27namespace LivePathEffect {
@@ -102,6 +103,23 @@
102 }103 }
103}104}
104105
106float PowerStrokePointArrayParam::median_width()
107{
108 size_t size = _vector.size();
109 if (size > 0)
110 {
111 if (size % 2 == 0)
112 {
113 return (_vector[size / 2 - 1].y() + _vector[size / 2].y()) / 2;
114 }
115 else
116 {
117 return _vector[size / 2].y();
118 }
119 }
120 return 1;
121}
122
105void123void
106PowerStrokePointArrayParam::set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in, Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_normal_in)124PowerStrokePointArrayParam::set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in, Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_normal_in)
107{125{
@@ -117,7 +135,7 @@
117 knot_mode = mode;135 knot_mode = mode;
118 knot_color = color;136 knot_color = color;
119}137}
120138/*
121class PowerStrokePointArrayParamKnotHolderEntity : public KnotHolderEntity {139class PowerStrokePointArrayParamKnotHolderEntity : public KnotHolderEntity {
122public:140public:
123 PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index);141 PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index);
@@ -127,7 +145,7 @@
127 virtual Geom::Point knot_get() const;145 virtual Geom::Point knot_get() const;
128 virtual void knot_click(guint state);146 virtual void knot_click(guint state);
129147
130 /** Checks whether the index falls within the size of the parameter's vector */148 // Checks whether the index falls within the size of the parameter's vector
131 bool valid_index(unsigned int index) const {149 bool valid_index(unsigned int index) const {
132 return (_pparam->_vector.size() > index);150 return (_pparam->_vector.size() > index);
133 };151 };
@@ -135,7 +153,7 @@
135private:153private:
136 PowerStrokePointArrayParam *_pparam;154 PowerStrokePointArrayParam *_pparam;
137 unsigned int _index;155 unsigned int _index;
138};156};*/
139157
140PowerStrokePointArrayParamKnotHolderEntity::PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index) 158PowerStrokePointArrayParamKnotHolderEntity::PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index)
141 : _pparam(p), 159 : _pparam(p),
@@ -184,6 +202,12 @@
184 return canvas_point;202 return canvas_point;
185}203}
186204
205void PowerStrokePointArrayParamKnotHolderEntity::knot_set_offset(Geom::Point offset)
206{
207 _pparam->_vector.at(_index) = Geom::Point(offset.x(), offset.y() / 2);
208 this->parent_holder->knot_ungrabbed_handler(this->knot, 0);
209}
210
187void211void
188PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state)212PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state)
189{213{
@@ -226,10 +250,15 @@
226 // add knot to knotholder250 // add knot to knotholder
227 PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(_pparam, _index+1);251 PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(_pparam, _index+1);
228 e->create( this->desktop, this->item, parent_holder, Inkscape::CTRL_TYPE_UNKNOWN,252 e->create( this->desktop, this->item, parent_holder, Inkscape::CTRL_TYPE_UNKNOWN,
229 _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it."),253 _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it, <b>Shift+click</b> launches width dialog."),
230 _pparam->knot_shape, _pparam->knot_mode, _pparam->knot_color);254 _pparam->knot_shape, _pparam->knot_mode, _pparam->knot_color);
231 parent_holder->add(e);255 parent_holder->add(e);
232 }256 }
257 }
258 else if ((state & GDK_MOD1_MASK) || (state & GDK_SHIFT_MASK))
259 {
260 Geom::Point offset = Geom::Point(_pparam->_vector.at(_index).x(), _pparam->_vector.at(_index).y() * 2);
261 Inkscape::UI::Dialogs::PowerstrokePropertiesDialog::showDialog(this->desktop, offset, this);
233 } 262 }
234}263}
235264
@@ -238,7 +267,7 @@
238 for (unsigned int i = 0; i < _vector.size(); ++i) {267 for (unsigned int i = 0; i < _vector.size(); ++i) {
239 PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(this, i);268 PowerStrokePointArrayParamKnotHolderEntity *e = new PowerStrokePointArrayParamKnotHolderEntity(this, i);
240 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,269 e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
241 _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it."),270 _("<b>Stroke width control point</b>: drag to alter the stroke width. <b>Ctrl+click</b> adds a control point, <b>Ctrl+Alt+click</b> deletes it, <b>Shift+click</b> launches width dialog."),
242 knot_shape, knot_mode, knot_color);271 knot_shape, knot_mode, knot_color);
243 knotholder->add(e);272 knotholder->add(e);
244 }273 }
245274
=== modified file 'src/live_effects/parameter/powerstrokepointarray.h'
--- src/live_effects/parameter/powerstrokepointarray.h 2014-03-27 01:33:44 +0000
+++ src/live_effects/parameter/powerstrokepointarray.h 2014-09-07 17:02:32 +0000
@@ -20,8 +20,6 @@
2020
21namespace LivePathEffect {21namespace LivePathEffect {
2222
23class PowerStrokePointArrayParamKnotHolderEntity;
24
25class PowerStrokePointArrayParam : public ArrayParam<Geom::Point> {23class PowerStrokePointArrayParam : public ArrayParam<Geom::Point> {
26public:24public:
27 PowerStrokePointArrayParam( const Glib::ustring& label,25 PowerStrokePointArrayParam( const Glib::ustring& label,
@@ -37,6 +35,8 @@
3735
38 void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);36 void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color);
3937
38 float median_width();
39
40 virtual bool providesKnotHolderEntities() const { return true; }40 virtual bool providesKnotHolderEntities() const { return true; }
41 virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);41 virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
4242
@@ -60,6 +60,25 @@
60 Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2_normal;60 Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2_normal;
61};61};
6262
63class PowerStrokePointArrayParamKnotHolderEntity : public KnotHolderEntity {
64public:
65 PowerStrokePointArrayParamKnotHolderEntity(PowerStrokePointArrayParam *p, unsigned int index);
66 virtual ~PowerStrokePointArrayParamKnotHolderEntity() {}
67
68 virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
69 virtual Geom::Point knot_get() const;
70 virtual void knot_set_offset(Geom::Point offset);
71 virtual void knot_click(guint state);
72
73 /** Checks whether the index falls within the size of the parameter's vector */
74 bool valid_index(unsigned int index) const {
75 return (_pparam->_vector.size() > index);
76 };
77
78private:
79 PowerStrokePointArrayParam *_pparam;
80 unsigned int _index;
81};
6382
64} //namespace LivePathEffect83} //namespace LivePathEffect
6584
6685
=== added file 'src/live_effects/parameter/transformedpoint.cpp'
--- src/live_effects/parameter/transformedpoint.cpp 1970-01-01 00:00:00 +0000
+++ src/live_effects/parameter/transformedpoint.cpp 2014-09-07 17:02:32 +0000
@@ -0,0 +1,182 @@
1/*
2 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
3 *
4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */
6
7#include "ui/widget/registered-widget.h"
8#include "live_effects/parameter/transformedpoint.h"
9#include "sp-lpe-item.h"
10#include "knotholder.h"
11#include "svg/svg.h"
12#include "svg/stringstream.h"
13
14#include "live_effects/effect.h"
15#include "desktop.h"
16#include "verbs.h"
17
18#include <glibmm/i18n.h>
19
20namespace Inkscape {
21
22namespace LivePathEffect {
23
24TransformedPointParam::TransformedPointParam( const Glib::ustring& label, const Glib::ustring& tip,
25 const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
26 Effect* effect, Geom::Point default_vector,
27 bool dontTransform)
28 : Parameter(label, tip, key, wr, effect),
29 defvalue(default_vector),
30 origin(0.,0.),
31 vector(default_vector),
32 noTransform(dontTransform)
33{
34 vec_knot_shape = SP_KNOT_SHAPE_DIAMOND;
35 vec_knot_mode = SP_KNOT_MODE_XOR;
36 vec_knot_color = 0xffffb500;
37}
38
39TransformedPointParam::~TransformedPointParam()
40{
41
42}
43
44void
45TransformedPointParam::param_set_default()
46{
47 setOrigin(Geom::Point(0.,0.));
48 setVector(defvalue);
49}
50
51bool
52TransformedPointParam::param_readSVGValue(const gchar * strvalue)
53{
54 gchar ** strarray = g_strsplit(strvalue, ",", 4);
55 if (!strarray) {
56 return false;
57 }
58 double val[4];
59 unsigned int i = 0;
60 while (i < 4 && strarray[i]) {
61 if (sp_svg_number_read_d(strarray[i], &val[i]) != 0) {
62 i++;
63 } else {
64 break;
65 }
66 }
67 g_strfreev (strarray);
68 if (i == 4) {
69 setOrigin( Geom::Point(val[0], val[1]) );
70 setVector( Geom::Point(val[2], val[3]) );
71 return true;
72 }
73 return false;
74}
75
76gchar *
77TransformedPointParam::param_getSVGValue() const
78{
79 Inkscape::SVGOStringStream os;
80 os << origin << " , " << vector;
81 gchar * str = g_strdup(os.str().c_str());
82 return str;
83}
84
85Gtk::Widget *
86TransformedPointParam::param_newWidget()
87{
88 Inkscape::UI::Widget::RegisteredVector * pointwdg = Gtk::manage(
89 new Inkscape::UI::Widget::RegisteredVector( param_label,
90 param_tooltip,
91 param_key,
92 *param_wr,
93 param_effect->getRepr(),
94 param_effect->getSPDoc() ) );
95 pointwdg->setPolarCoords();
96 pointwdg->setValue( vector, origin );
97 pointwdg->clearProgrammatically();
98 pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change vector parameter"));
99
100 Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
101 static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
102 static_cast<Gtk::HBox*>(hbox)->show_all_children();
103
104 return dynamic_cast<Gtk::Widget *> (hbox);
105}
106
107void
108TransformedPointParam::set_and_write_new_values(Geom::Point const &new_origin, Geom::Point const &new_vector)
109{
110 setValues(new_origin, new_vector);
111 gchar * str = param_getSVGValue();
112 param_write_to_repr(str);
113 g_free(str);