Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
effect.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
4 * Abhishek Sharma
5 *
6 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
7 */
8
9#ifdef HAVE_CONFIG_H
10# include "config.h" // only include where actually required!
11#endif
12
13//#define LPE_ENABLE_TEST_EFFECTS //uncomment for toy effects
14
15// include effects:
16#include <cstdio>
17#include <cstring>
18#include <gtkmm/expander.h>
19#include <pangomm/layout.h>
20
21#include "display/curve.h"
22#include "inkscape.h"
23#include "live_effects/effect.h"
82#include "message-stack.h"
83#include "object/sp-defs.h"
84#include "object/sp-root.h"
85#include "object/sp-shape.h"
86#include "path-chemistry.h"
87#include "ui/icon-loader.h"
88#include "ui/pack.h"
89#include "ui/tools/node-tool.h"
90#include "ui/tools/pen-tool.h"
91#include "xml/sp-css-attr.h"
92#include "helper/geom.h"
93
94namespace Inkscape {
95namespace LivePathEffect {
96
98 // {constant defined in effect-enum.h, N_("name of your effect"), "name of your effect in SVG"}
99 // please sync order with effect-enum.h
100/* 0.46 */
101 {
102 BEND_PATH,
103 NC_("path effect", "Bend") ,//label
104 "bend_path" ,//key
105 "bend-path" ,//icon
106 N_("Bend an object along the curvature of another path") ,//description
107 LPECategory::Distort ,//category
108 true ,//on_path
109 true ,//on_shape
110 true ,//on_group
111 false ,//on_image
112 false ,//on_text
113 false ,//experimental
114 },
115 {
116 GEARS,
117 NC_("path effect", "Gears") ,//label
118 "gears" ,//key
119 "gears" ,//icon
120 N_("Create interlocking, configurable gears based on the nodes of a path") ,//description
121 LPECategory::Convert ,//category
122 true ,//on_path
123 true ,//on_shape
124 true ,//on_group
125 false ,//on_image
126 false ,//on_text
127 false ,//experimental
128 },
129 {
131 NC_("path effect", "Pattern Along Path") ,//label
132 "skeletal" ,//key
133 "skeletal" ,//icon
134 N_("Place one or more copies of another path along the path") ,//description
135 LPECategory::Distort ,//category
136 true ,//on_path
137 true ,//on_shape
138 true ,//on_group
139 false ,//on_image
140 false ,//on_text
141 false ,//experimental
142 }, // for historic reasons, this effect is called skeletal(strokes) in Inkscape:SVG
143 {
145 NC_("path effect", "Stitch Sub-Paths") ,//label
146 "curvestitching" ,//key
147 "curvestitching" ,//icon
148 N_("Draw perpendicular lines between subpaths of a path, like rungs of a ladder") ,//description
149 LPECategory::Generate ,//category
150 true ,//on_path
151 false ,//on_shape
152 true ,//on_group
153 false ,//on_image
154 false ,//on_text
155 false ,//experimental
156 },
157/* 0.47 */
158 {
159 VONKOCH,
160 NC_("path effect", "VonKoch") ,//label
161 "vonkoch" ,//key
162 "vonkoch" ,//icon
163 N_("Create VonKoch fractal") ,//description
164 LPECategory::Generate ,//category
165 true ,//on_path
166 true ,//on_shape
167 true ,//on_group
168 false ,//on_image
169 false ,//on_text
170 false ,//experimental
171 },
172 {
173 KNOT,
174 NC_("path effect", "Knot") ,//label
175 "knot" ,//key
176 "knot" ,//icon
177 N_("Create gaps in self-intersections, as in Celtic knots") ,//description
178 LPECategory::EditTools ,//category
179 true ,//on_path
180 true ,//on_shape
181 true ,//on_group
182 false ,//on_image
183 false ,//on_text
184 false ,//experimental
185 },
186 {
188 NC_("path effect", "Construct grid") ,//label
189 "construct_grid" ,//key
190 "construct-grid" ,//icon
191 N_("Create a (perspective) grid from a 3-node path") ,//description
192 LPECategory::Convert ,//category
193 true ,//on_path
194 true ,//on_shape
195 true ,//on_group
196 false ,//on_image
197 false ,//on_text
198 false ,//experimental
199 },
200 {
201 SPIRO,
202 NC_("path effect", "Spiro spline") ,//label
203 "spiro" ,//key
204 "spiro" ,//icon
205 N_("Make the path curl like wire, using Spiro B-Splines. This effect is usually used directly on the canvas with the Spiro mode of the drawing tools.") ,//description
206 LPECategory::Convert ,//category
207 true ,//on_path
208 false ,//on_shape
209 false ,//on_group
210 false ,//on_image
211 false ,//on_text
212 false ,//experimental
213 },
214 {
215 ENVELOPE,
216 NC_("path effect", "Envelope Deformation") ,//label
217 "envelope" ,//key
218 "envelope" ,//icon
219 N_("Adjust the shape of an object by transforming paths on its four sides") ,//description
220 LPECategory::Distort ,//category
221 true ,//on_path
222 true ,//on_shape
223 true ,//on_group
224 false ,//on_image
225 false ,//on_text
226 false ,//experimental
227 },
228 {
230 NC_("path effect", "Interpolate Sub-Paths") ,//label
231 "interpolate" ,//key
232 "interpolate" ,//icon
233 N_("Create a smooth transition between the two subpaths of a path, blending their shapes together in steps.") ,//description
234 LPECategory::Generate ,//category
235 true ,//on_path
236 false ,//on_shape
237 false ,//on_group
238 false ,//on_image
239 false ,//on_text
240 false ,//experimental
241 },
242 {
244 NC_("path effect", "Hatches (rough)") ,//label
245 "rough_hatches" ,//key
246 "rough-hatches" ,//icon
247 N_("Fill the object with adjustable hatching") ,//description
248 LPECategory::Generate ,//category
249 true ,//on_path
250 true ,//on_shape
251 true ,//on_group
252 false ,//on_image
253 false ,//on_text
254 false ,//experimental
255 },
256 {
257 SKETCH,
258 NC_("path effect", "Sketch") ,//label
259 "sketch" ,//key
260 "sketch" ,//icon
261 N_("Draw multiple short strokes along the path, as in a pencil sketch") ,//description
262 LPECategory::Generate ,//category
263 true ,//on_path
264 true ,//on_shape
265 true ,//on_group
266 false ,//on_image
267 false ,//on_text
268 false ,//experimental
269 },
270 {
271 RULER,
272 NC_("path effect", "Ruler") ,//label
273 "ruler" ,//key
274 "ruler" ,//icon
275 N_("Add ruler marks to the object in adjustable intervals, using the object's stroke style.") ,//description
276 LPECategory::Convert ,//category
277 true ,//on_path
278 true ,//on_shape
279 true ,//on_group
280 false ,//on_image
281 false ,//on_text
282 false ,//experimental
283 },
284/* 0.91 */
285 {
287 NC_("path effect", "Power stroke") ,//label
288 "powerstroke" ,//key
289 "powerstroke" ,//icon
290 N_("Create calligraphic strokes and control their variable width and curvature. This effect can also be used directly on the canvas with a pressure sensitive stylus and the Pencil tool.") ,//description
291 LPECategory::EditTools ,//category
292 true ,//on_path
293 true ,//on_shape
294 false ,//on_group
295 false ,//on_image
296 false ,//on_text
297 false ,//experimental
298 },
299 {
301 NC_("path effect", "Clone original") ,//label
302 "clone_original" ,//key
303 "clone-original" ,//icon
304 N_("Let an object take on the shape, fill, stroke and/or other attributes of another object.") ,//description
305 LPECategory::Generate ,//category
306 true ,//on_path
307 true ,//on_shape
308 true ,//on_group
309 false ,//on_image
310 false ,//on_text
311 false ,//experimental
312 },
313/* 0.92 */
314 {
315 SIMPLIFY,
316 NC_("path effect", "Simplify") ,//label
317 "simplify" ,//key
318 "simplify" ,//icon
319 N_("Smoothen and simplify a object. This effect is also available in the Pencil tool's tool controls.") ,//description
320 LPECategory::EditTools ,//category
321 true ,//on_path
322 true ,//on_shape
323 true ,//on_group
324 false ,//on_image
325 false ,//on_text
326 false ,//experimental
327 },
328 {
329 LATTICE2,
330 NC_("path effect", "Lattice Deformation") ,//label
331 "lattice2" ,//key
332 "lattice2" ,//icon
333 N_("Warp an object's shape based on a 5x5 grid") ,//description
334 LPECategory::Distort ,//category
335 true ,//on_path
336 true ,//on_shape
337 true ,//on_group
338 false ,//on_image
339 false ,//on_text
340 false ,//experimental
341 },
342 {
344 NC_("path effect", "Perspective/Envelope") ,//label
345 "perspective-envelope" ,//key wrong key with "-" retain because historic
346 "perspective-envelope" ,//icon
347 N_("Transform the object to fit into a shape with four corners, either by stretching it or creating the illusion of a 3D-perspective") ,//description
348 LPECategory::Distort ,//category
349 true ,//on_path
350 true ,//on_shape
351 true ,//on_group
352 false ,//on_image
353 false ,//on_text
354 false ,//experimental
355 },
356 {
358 NC_("path effect", "Interpolate points") ,//label
359 "interpolate_points" ,//key
360 "interpolate-points" ,//icon
361 N_("Change the type of all nodes on the path. Useful for smoothing the shape or making it sharp.") ,//description
362 LPECategory::Convert ,//category
363 true ,//on_path
364 true ,//on_shape
365 true ,//on_group
366 false ,//on_image
367 false ,//on_text
368 false ,//experimental
369 },
370 {
372 NC_("path effect", "Transform by 2 points") ,//label
373 "transform_2pts" ,//key
374 "transform-2pts" ,//icon
375 N_("Scale, stretch and rotate an object by two handles") ,//description
376 LPECategory::Distort ,//category
377 true ,//on_path
378 true ,//on_shape
379 true ,//on_group
380 false ,//on_image
381 false ,//on_text
382 false ,//experimental
383 },
384 {
386 NC_("path effect", "Show handles") ,//label
387 "show_handles" ,//key
388 "show-handles" ,//icon
389 N_("Draw the handles and nodes of objects (replaces the original styling with a black stroke)") ,//description
390 LPECategory::Convert ,//category
391 true ,//on_path
392 true ,//on_shape
393 true ,//on_group
394 false ,//on_image
395 false ,//on_text
396 false ,//experimental
397 },
398 {
399 ROUGHEN,
400 NC_("path effect", "Roughen") ,//label
401 "roughen" ,//key
402 "roughen" ,//icon
403 N_("Roughen an object by adding and randomly shifting new nodes") ,//description
404 LPECategory::Distort ,//category
405 true ,//on_path
406 true ,//on_shape
407 true ,//on_group
408 false ,//on_image
409 false ,//on_text
410 false ,//experimental
411 },
412 {
413 BSPLINE,
414 NC_("path effect", "BSpline") ,//label
415 "bspline" ,//key
416 "bspline" ,//icon
417 N_("Create a BSpline that molds into the path's corners. This effect is usually used directly on the canvas with the BSpline mode of the drawing tools.") ,//description
418 LPECategory::Convert ,//category
419 true ,//on_path
420 false ,//on_shape
421 false ,//on_group
422 false ,//on_image
423 false ,//on_text
424 false ,//experimental
425 },
426 {
427 JOIN_TYPE,
428 NC_("path effect", "Join type") ,//label
429 "join_type" ,//key
430 "join-type" ,//icon
431 N_("Select among various join types for a object's corner nodes (mitre, rounded, extrapolated arc, ...)") ,//description
432 LPECategory::Convert ,//category
433 true ,//on_path
434 true ,//on_shape
435 true ,//on_group
436 false ,//on_image
437 false ,//on_text
438 false ,//experimental
439 },
440 {
442 NC_("path effect", "Taper stroke") ,//label
443 "taper_stroke" ,//key
444 "taper-stroke" ,//icon
445 N_("Let the path's ends narrow down to a tip") ,//description
446 LPECategory::EditTools ,//category
447 true ,//on_path
448 true ,//on_shape
449 false ,//on_group
450 false ,//on_image
451 false ,//on_text
452 false ,//experimental
453 },
454 {
456 NC_("path effect", "Mirror symmetry") ,//label
457 "mirror_symmetry" ,//key
458 "mirror-symmetry" ,//icon
459 N_("Mirror an object along a movable axis, or around the page center. The mirrored copy can be styled independently.") ,//description
460 LPECategory::Generate ,//category
461 true ,//on_path
462 true ,//on_shape
463 true ,//on_group
464 false ,//on_image
465 false ,//on_text
466 false ,//experimental
467 },
468 {
470 NC_("path effect", "Rotate copies") ,//label
471 "copy_rotate" ,//key
472 "copy-rotate" ,//icon
473 N_("Create multiple rotated copies of an object, as in a kaleidoscope. The copies can be styled independently.") ,//description
474 LPECategory::Generate ,//category
475 true ,//on_path
476 true ,//on_shape
477 true ,//on_group
478 false ,//on_image
479 false ,//on_text
480 false ,//experimental
481 },
482/* Ponyscape -> Inkscape 0.92*/
483 {
485 NC_("path effect", "Attach path") ,//label
486 "attach_path" ,//key
487 "attach-path" ,//icon
488 N_("Glue the current path's ends to a specific position on one or two other paths") ,//description
489 LPECategory::Convert ,//category
490 true ,//on_path
491 true ,//on_shape
492 true ,//on_group
493 false ,//on_image
494 false ,//on_text
495 false ,//experimental
496 },
497
498 {
500 NC_("path effect", "Fill between many") ,//label
501 "fill_between_many" ,//key
502 "fill-between-many" ,//icon
503 N_("Turn the path into a fill between multiple other open paths (e.g. between paths with PowerStroke applied to them)") ,//description
504 LPECategory::Generate ,//category
505 true ,//on_path
506 true ,//on_shape
507 true ,//on_group
508 false ,//on_image
509 false ,//on_text
510 false ,//experimental
511 },
512 {
514 NC_("path effect", "Ellipse by 5 points") ,//label
515 "ellipse_5pts" ,//key
516 "ellipse-5pts" ,//icon
517 N_("Create an ellipse from 5 nodes on its circumference") ,//description
518 LPECategory::Convert ,//category
519 true ,//on_path
520 true ,//on_shape
521 false ,//on_group
522 false ,//on_image
523 false ,//on_text
524 false ,//experimental
525 },
526 {
528 NC_("path effect", "Bounding Box") ,//label
529 "bounding_box" ,//key
530 "bounding-box" ,//icon
531 N_("Turn the path into a bounding box that entirely encompasses another path") ,//description
532 LPECategory::Convert ,//category
533 true ,//on_path
534 true ,//on_shape
535 true ,//on_group
536 false ,//on_image
537 false ,//on_text
538 false ,//experimental
539 },
540/* 1.0 */
541 {
543 NC_("path effect", "Measure Segments") ,//label
544 "measure_segments" ,//key
545 "measure-segments" ,//icon
546 N_("Add dimensioning for distances between nodes, optionally with projection and many other configuration options") ,//description
547 LPECategory::Convert ,//category
548 true ,//on_path
549 true ,//on_shape
550 false ,//on_group
551 false ,//on_image
552 false ,//on_text
553 false ,//experimental
554 },
555 {
557 NC_("path effect", "Corners") ,//label
558 "fillet_chamfer" ,//key
559 "fillet-chamfer" ,//icon
560 N_("Fillet/Chamfer: Adjust the shape of a path's corners, rounding them to a specified radius, or cutting them off") ,//description
561 LPECategory::EditTools ,//category
562 true ,//on_path
563 true ,//on_shape
564 false ,//on_group
565 false ,//on_image
566 false ,//on_text
567 false ,//experimental
568 },
569 {
570 POWERCLIP,
571 NC_("path effect", "Power clip") ,//label
572 "powerclip" ,//key
573 "powerclip" ,//icon
574 N_("Invert, hide or flatten a clip (apply like a Boolean operation)") ,//description
575 LPECategory::Generate ,//category
576 true ,//on_path
577 true ,//on_shape
578 true ,//on_group
579 false ,//on_image
580 false ,//on_text
581 false ,//experimental
582 },
583 {
584 POWERMASK,
585 NC_("path effect", "Power mask") ,//label
586 "powermask" ,//key
587 "powermask" ,//icon
588 N_("Invert or hide a mask, or use its negative") ,//description
589 LPECategory::Generate ,//category
590 true ,//on_path
591 true ,//on_shape
592 true ,//on_group
593 false ,//on_image
594 false ,//on_text
595 false ,//experimental
596 },
597 {
599 NC_("path effect", "Ellipse from points") ,//label
600 "pts2ellipse" ,//key
601 "pts2ellipse" ,//icon
602 N_("Draw a circle, ellipse, arc or slice based on the nodes of a path") ,//description
603 LPECategory::Convert ,//category
604 true ,//on_path
605 true ,//on_shape
606 true ,//on_group
607 false ,//on_image
608 false ,//on_text
609 false ,//experimental
610 },
611 {
612 OFFSET,
613 NC_("path effect", "Offset") ,//label
614 "offset" ,//key
615 "offset" ,//icon
616 N_("Offset the path, optionally keeping cusp corners cusp") ,//description
617 LPECategory::EditTools ,//category
618 true ,//on_path
619 true ,//on_shape
620 true ,//on_group
621 false ,//on_image
622 false ,//on_text
623 false ,//experimental
624 },
625 {
627 NC_("path effect", "Dashed Stroke") ,//label
628 "dashed_stroke" ,//key
629 "dashed-stroke" ,//icon
630 N_("Add a dashed stroke whose dashes end exactly on a node, optionally with the same number of dashes per path segment") ,//description
631 LPECategory::Convert ,//category
632 true ,//on_path
633 true ,//on_shape
634 true ,//on_group
635 false ,//on_image
636 false ,//on_text
637 false ,//experimental
638 },
639 /* 1.1 */
640 {
641 BOOL_OP,
642 NC_("path effect", "Boolean operation") ,//label
643 "bool_op" ,//key
644 "bool-op" ,//icon
645 N_("Cut, union, subtract, intersect and divide a path non-destructively with another path") ,//description
646 LPECategory::Generate ,//category
647 true ,//on_path
648 true ,//on_shape
649 true ,//on_group
650 false ,//on_image
651 false ,//on_text
652 false ,//experimental
653 },
654 {
655 SLICE,
656 NC_("path effect", "Slice") ,//label
657 "slice" ,//key
658 "slice" ,//icon
659 N_("Slices the item into parts. It can also be applied multiple times.") ,//description
660 LPECategory::Generate ,//category
661 true ,//on_path
662 true ,//on_shape
663 true ,//on_group
664 false ,//on_image
665 false ,//on_text
666 false ,//experimental
667 },
668 /* 1.2 */
669 {
670 TILING,
671 NC_("path effect", "Tiling") ,//label
672 "tiling" ,//key
673 "tiling" ,//icon
674 N_("Create multiple copies of an object following a grid layout. Customize size, rotation, distances, style and tiling symmetry.") ,//description
675 LPECategory::Generate ,//category
676 true ,//on_path
677 true ,//on_shape
678 true ,//on_group
679 false ,//on_image
680 false ,//on_text
681 false ,//experimental
682 },
683 // VISIBLE experimental LPEs
684 {
686 NC_("path effect", "Angle bisector") ,//label
687 "angle_bisector" ,//key
688 "experimental" ,//icon
689 N_("Draw a line that halves the angle between the first three nodes of the path") ,//description
690 LPECategory::Experimental ,//category
691 true ,//on_path
692 true ,//on_shape
693 true ,//on_group
694 false ,//on_image
695 false ,//on_text
696 true ,//experimental
697 },
698 {
700 NC_("path effect", "Circle") ,//label
701 "circle_with_radius" ,//key
702 "experimental" ,//icon
703 N_("Draw a circle by center and radius, where the first node of the path is the center, and the last determines its radius") ,//description
704 LPECategory::Experimental ,//category
705 true ,//on_path
706 true ,//on_shape
707 true ,//on_group
708 false ,//on_image
709 false ,//on_text
710 true ,//experimental
711 },
712 {
714 NC_("path effect", "Circle by 3 points") ,//label
715 "circle_3pts" ,//key
716 "experimental" ,//icon
717 N_("Draw a circle whose circumference passes through the first three nodes of the path") ,//description
718 LPECategory::Experimental ,//category
719 true ,//on_path
720 true ,//on_shape
721 true ,//on_group
722 false ,//on_image
723 false ,//on_text
724 true ,//experimental
725 },
726 {
727 EXTRUDE,
728 NC_("path effect", "Extrude") ,//label
729 "extrude" ,//key
730 "experimental" ,//icon
731 N_("Extrude the path, creating a face for each path segment") ,//description
732 LPECategory::Experimental ,//category
733 true ,//on_path
734 true ,//on_shape
735 true ,//on_group
736 false ,//on_image
737 false ,//on_text
738 true ,//experimental
739 },
740 {
742 NC_("path effect", "Line Segment") ,//label
743 "line_segment" ,//key
744 "experimental" ,//icon
745 N_("Draw a straight line that connects the first and last node of a path") ,//description
746 LPECategory::Experimental ,//category
747 true ,//on_path
748 true ,//on_shape
749 true ,//on_group
750 false ,//on_image
751 false ,//on_text
752 true ,//experimental
753 },
754 {
755 PARALLEL,
756 NC_("path effect", "Parallel") ,//label
757 "parallel" ,//key
758 "experimental" ,//icon
759 N_("Create a draggable line that will always be parallel to a two-node path") ,//description
760 LPECategory::Experimental ,//category
761 true ,//on_path
762 true ,//on_shape
763 true ,//on_group
764 false ,//on_image
765 false ,//on_text
766 true ,//experimental
767 },
768 {
770 NC_("path effect", "Perpendicular bisector") ,//label
771 "perp_bisector" ,//key
772 "experimental" ,//icon
773 N_("Draw a perpendicular line in the middle of the (imaginary) line that connects the start and end nodes") ,//description
774 LPECategory::Experimental ,//category
775 true ,//on_path
776 true ,//on_shape
777 true ,//on_group
778 false ,//on_image
779 false ,//on_text
780 true ,//experimental
781 },
782 {
784 NC_("path effect", "Tangent to curve") ,//label
785 "tangent_to_curve" ,//key
786 "experimental" ,//icon
787 N_("Draw a tangent with variable length and additional angle that can be moved along the path") ,//description
788 LPECategory::Experimental ,//category
789 true ,//on_path
790 true ,//on_shape
791 true ,//on_group
792 false ,//on_image
793 false ,//on_text
794 true ,//experimental
795 },
796 {
797 //moved to esperimental on 1.3
799 NC_("path effect", "Fill between strokes") ,//label
800 "fill_between_strokes" ,//key
801 "experimental" ,//icon
802 N_("Turn the path into a fill between two other open paths (e.g. between two paths with PowerStroke applied to them)") ,//description
803 LPECategory::Experimental ,//category
804 true ,//on_path
805 true ,//on_shape
806 true ,//on_group
807 false ,//on_image
808 false ,//on_text
809 true ,//experimental
810 },
811#ifdef LPE_ENABLE_TEST_EFFECTS
812 {
814 NC_("path effect", "doEffect stack test") ,//label
815 "doeffectstacktest" ,//key
816 "experimental" ,//icon
817 N_("Test LPE") ,//description
818 LPECategory::Experimental ,//category
819 true ,//on_path
820 true ,//on_shape
821 true ,//on_group
822 false ,//on_image
823 false ,//on_text
824 true ,//experimental
825 },
826 {
828 NC_("path effect", "Dynamic stroke") ,//label
829 "dynastroke" ,//key
830 "experimental" ,//icon
831 N_("Create calligraphic strokes with variably shaped ends, making use of a parameter for the brush angle") ,//description
832 LPECategory::Experimental ,//category
833 true ,//on_path
834 true ,//on_shape
835 true ,//on_group
836 false ,//on_image
837 false ,//on_text
838 true ,//experimental
839 },
840 {
841 LATTICE,
842 NC_("path effect", "Lattice Deformation Legacy") ,//label
843 "lattice" ,//key
844 "experimental" ,//icon
845 N_("Deform an object using a 4x4 grid") ,//description
846 LPECategory::Experimental ,//category
847 true ,//on_path
848 true ,//on_shape
849 true ,//on_group
850 false ,//on_image
851 false ,//on_text
852 true ,//experimental
853 },
854 {
856 NC_("path effect", "Path length") ,//label
857 "path_length" ,//key
858 "experimental" ,//icon
859 N_("Display the total length of a (curved) path") ,//description
860 LPECategory::Experimental ,//category
861 true ,//on_path
862 true ,//on_shape
863 true ,//on_group
864 false ,//on_image
865 false ,//on_text
866 true ,//experimental
867 },
868 {
870 NC_("path effect", "Recursive skeleton") ,//label
871 "recursive_skeleton" ,//key
872 "experimental" ,//icon
873 N_("Draw a path recursively") ,//description
874 LPECategory::Experimental ,//category
875 true ,//on_path
876 true ,//on_shape
877 true ,//on_group
878 false ,//on_image
879 false ,//on_text
880 true ,//experimental
881 },
882 {
884 NC_("path effect", "Text label") ,//label
885 "text_label" ,//key
886 "experimental" ,//icon
887 N_("Add a label for the object") ,//description
888 LPECategory::Experimental ,//category
889 true ,//on_path
890 true ,//on_shape
891 true ,//on_group
892 false ,//on_image
893 false ,//on_text
894 true ,//experimental
895 },
896 {
898 NC_("path effect", "Embroidery stitch") ,//label
899 "embrodery_stitch" ,//key
900 "embrodery-stitch" ,//icon
901 N_("Embroidery stitch") ,//description
902 LPECategory::Experimental ,//category
903 true ,//on_path
904 true ,//on_shape
905 true ,//on_group
906 false ,//on_image
907 false ,//on_text
908 false ,//experimental
909 },
910#endif
911
912};
913
915
916int
918 switch (type) {
919 case INVALID_LPE: return -1; // in case we want to distinguish between invalid LPE and valid ones that expect zero clicks
920 case ANGLE_BISECTOR: return 3;
921 case CIRCLE_3PTS: return 3;
922 case CIRCLE_WITH_RADIUS: return 2;
923 case LINE_SEGMENT: return 2;
924 case PERP_BISECTOR: return 2;
925 default: return 0;
926 }
927}
928
929Effect*
931{
932 Effect* neweffect = nullptr;
933 switch (lpenr) {
934 case EMBRODERY_STITCH:
935 neweffect = static_cast<Effect*> ( new LPEEmbroderyStitch(lpeobj) );
936 break;
937 case BOOL_OP:
938 neweffect = static_cast<Effect*> ( new LPEBool(lpeobj) );
939 break;
941 neweffect = static_cast<Effect*> ( new LPEPatternAlongPath(lpeobj) );
942 break;
943 case BEND_PATH:
944 neweffect = static_cast<Effect*> ( new LPEBendPath(lpeobj) );
945 break;
946 case SKETCH:
947 neweffect = static_cast<Effect*> ( new LPESketch(lpeobj) );
948 break;
949 case ROUGH_HATCHES:
950 neweffect = static_cast<Effect*> ( new LPERoughHatches(lpeobj) );
951 break;
952 case VONKOCH:
953 neweffect = static_cast<Effect*> ( new LPEVonKoch(lpeobj) );
954 break;
955 case KNOT:
956 neweffect = static_cast<Effect*> ( new LPEKnot(lpeobj) );
957 break;
958 case GEARS:
959 neweffect = static_cast<Effect*> ( new LPEGears(lpeobj) );
960 break;
961 case CURVE_STITCH:
962 neweffect = static_cast<Effect*> ( new LPECurveStitch(lpeobj) );
963 break;
964 case LATTICE:
965 neweffect = static_cast<Effect*> ( new LPELattice(lpeobj) );
966 break;
967 case ENVELOPE:
968 neweffect = static_cast<Effect*> ( new LPEEnvelope(lpeobj) );
969 break;
971 neweffect = static_cast<Effect*> ( new LPECircleWithRadius(lpeobj) );
972 break;
973 case SPIRO:
974 neweffect = static_cast<Effect*> ( new LPESpiro(lpeobj) );
975 break;
976 case CONSTRUCT_GRID:
977 neweffect = static_cast<Effect*> ( new LPEConstructGrid(lpeobj) );
978 break;
979 case PERP_BISECTOR:
980 neweffect = static_cast<Effect*> ( new LPEPerpBisector(lpeobj) );
981 break;
982 case TANGENT_TO_CURVE:
983 neweffect = static_cast<Effect*> ( new LPETangentToCurve(lpeobj) );
984 break;
985 case MIRROR_SYMMETRY:
986 neweffect = static_cast<Effect*> ( new LPEMirrorSymmetry(lpeobj) );
987 break;
988 case CIRCLE_3PTS:
989 neweffect = static_cast<Effect*> ( new LPECircle3Pts(lpeobj) );
990 break;
991 case ANGLE_BISECTOR:
992 neweffect = static_cast<Effect*> ( new LPEAngleBisector(lpeobj) );
993 break;
994 case PARALLEL:
995 neweffect = static_cast<Effect*> ( new LPEParallel(lpeobj) );
996 break;
997 case COPY_ROTATE:
998 neweffect = static_cast<Effect*> ( new LPECopyRotate(lpeobj) );
999 break;
1000 case OFFSET:
1001 neweffect = static_cast<Effect*> ( new LPEOffset(lpeobj) );
1002 break;
1003 case RULER:
1004 neweffect = static_cast<Effect*> ( new LPERuler(lpeobj) );
1005 break;
1006 case INTERPOLATE:
1007 neweffect = static_cast<Effect*> ( new LPEInterpolate(lpeobj) );
1008 break;
1009 case INTERPOLATE_POINTS:
1010 neweffect = static_cast<Effect*> ( new LPEInterpolatePoints(lpeobj) );
1011 break;
1012 case TEXT_LABEL:
1013 neweffect = static_cast<Effect*> ( new LPETextLabel(lpeobj) );
1014 break;
1015 case PATH_LENGTH:
1016 neweffect = static_cast<Effect*> ( new LPEPathLength(lpeobj) );
1017 break;
1018 case LINE_SEGMENT:
1019 neweffect = static_cast<Effect*> ( new LPELineSegment(lpeobj) );
1020 break;
1021 case DOEFFECTSTACK_TEST:
1022 neweffect = static_cast<Effect*> ( new LPEdoEffectStackTest(lpeobj) );
1023 break;
1024 case BSPLINE:
1025 neweffect = static_cast<Effect*> ( new LPEBSpline(lpeobj) );
1026 break;
1027 case DYNASTROKE:
1028 neweffect = static_cast<Effect*> ( new LPEDynastroke(lpeobj) );
1029 break;
1030 case RECURSIVE_SKELETON:
1031 neweffect = static_cast<Effect*> ( new LPERecursiveSkeleton(lpeobj) );
1032 break;
1033 case EXTRUDE:
1034 neweffect = static_cast<Effect*> ( new LPEExtrude(lpeobj) );
1035 break;
1036 case POWERSTROKE:
1037 neweffect = static_cast<Effect*> ( new LPEPowerStroke(lpeobj) );
1038 break;
1039 case CLONE_ORIGINAL:
1040 neweffect = static_cast<Effect*> ( new LPECloneOriginal(lpeobj) );
1041 break;
1042 case ATTACH_PATH:
1043 neweffect = static_cast<Effect*> ( new LPEAttachPath(lpeobj) );
1044 break;
1046 neweffect = static_cast<Effect*> ( new LPEFillBetweenStrokes(lpeobj) );
1047 break;
1048 case FILL_BETWEEN_MANY:
1049 neweffect = static_cast<Effect*> ( new LPEFillBetweenMany(lpeobj) );
1050 break;
1051 case ELLIPSE_5PTS:
1052 neweffect = static_cast<Effect*> ( new LPEEllipse5Pts(lpeobj) );
1053 break;
1054 case BOUNDING_BOX:
1055 neweffect = static_cast<Effect*> ( new LPEBoundingBox(lpeobj) );
1056 break;
1057 case JOIN_TYPE:
1058 neweffect = static_cast<Effect*> ( new LPEJoinType(lpeobj) );
1059 break;
1060 case TAPER_STROKE:
1061 neweffect = static_cast<Effect*> ( new LPETaperStroke(lpeobj) );
1062 break;
1063 case SIMPLIFY:
1064 neweffect = static_cast<Effect*> ( new LPESimplify(lpeobj) );
1065 break;
1066 case LATTICE2:
1067 neweffect = static_cast<Effect*> ( new LPELattice2(lpeobj) );
1068 break;
1070 neweffect = static_cast<Effect*> ( new LPEPerspectiveEnvelope(lpeobj) );
1071 break;
1072 case FILLET_CHAMFER:
1073 neweffect = static_cast<Effect*> ( new LPEFilletChamfer(lpeobj) );
1074 break;
1075 case POWERCLIP:
1076 neweffect = static_cast<Effect*> ( new LPEPowerClip(lpeobj) );
1077 break;
1078 case POWERMASK:
1079 neweffect = static_cast<Effect*> ( new LPEPowerMask(lpeobj) );
1080 break;
1081 case ROUGHEN:
1082 neweffect = static_cast<Effect*> ( new LPERoughen(lpeobj) );
1083 break;
1084 case SHOW_HANDLES:
1085 neweffect = static_cast<Effect*> ( new LPEShowHandles(lpeobj) );
1086 break;
1087 case TRANSFORM_2PTS:
1088 neweffect = static_cast<Effect*> ( new LPETransform2Pts(lpeobj) );
1089 break;
1090 case MEASURE_SEGMENTS:
1091 neweffect = static_cast<Effect*> ( new LPEMeasureSegments(lpeobj) );
1092 break;
1093 case PTS2ELLIPSE:
1094 neweffect = static_cast<Effect*> ( new LPEPts2Ellipse(lpeobj) );
1095 break;
1096 case DASHED_STROKE:
1097 neweffect = static_cast<Effect *>(new LPEDashedStroke(lpeobj));
1098 break;
1099 case SLICE:
1100 neweffect = static_cast<Effect *>(new LPESlice(lpeobj));
1101 break;
1102 case TILING:
1103 neweffect = static_cast<Effect*> ( new LPETiling(lpeobj) );
1104 break;
1105 default:
1106 g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
1107 neweffect = nullptr;
1108 break;
1109 }
1110
1111 if (neweffect) {
1112 neweffect->readallParameters(lpeobj->getRepr());
1113 }
1114
1115 return neweffect;
1116}
1117
1119{
1120 // Path effect definition
1121 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
1122 Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect");
1123 repr->setAttribute("effect", name);
1124
1125 doc->getDefs()->getRepr()->addChild(repr, nullptr); // adds to <defs> and assigns the 'id' attribute
1126 const gchar * repr_id = repr->attribute("id");
1128
1129 gchar *href = g_strdup_printf("#%s", repr_id);
1130 cast<SPLPEItem>(item)->addPathEffect(href, true);
1131 g_free(href);
1132}
1133
1134void
1136{
1137 createAndApply(LPETypeConverter.get_key(type).c_str(), doc, item);
1138}
1139
1141 : apply_to_clippath_and_mask(false),
1142 _provides_knotholder_entities(false),
1143 oncanvasedit_it(0),
1144 is_visible(_("Is visible?"), _("If unchecked, the effect remains applied to the object but is temporarily disabled on canvas"), "is_visible", &wr, this, true),
1145 lpeversion(_("Version"), _("LPE version"), "lpeversion", &wr, this, "0", true),
1146 show_orig_path(false),
1147 keep_paths(false),
1148 is_load(true),
1149 on_remove_all(false),
1150 lpeobj(lpeobject),
1151 concatenate_before_pwd2(false),
1152 sp_lpe_item(nullptr),
1153 current_zoom(0),
1154 refresh_widgets(false),
1155 current_shape(nullptr),
1156 provides_own_flash_paths(true), // is automatically set to false if providesOwnFlashPaths() is not overridden
1157 defaultsopen(false),
1158 is_ready(false),
1159 is_applied(false)
1160{
1165}
1166
1168{
1169 _before_commit_connection.disconnect();
1170}
1171
1172Glib::ustring
1174{
1176 return Glib::ustring( _(LPETypeConverter.get_label(lpeobj->effecttype).c_str()) );
1177 else
1178 return Glib::ustring( _("No effect") );
1179}
1180
1183 return lpeobj->effecttype;
1184}
1185
1186std::vector<SPLPEItem *>
1188 std::vector<SPLPEItem *> result;
1189 auto hreflist = getLPEObj()->hrefList;
1190 if (!getLPEObj()->deleted) {
1191 for (auto item : hreflist) {
1192 if (auto lpeitem = cast<SPLPEItem>(item)) {
1193 result.push_back(lpeitem);
1194 }
1195 }
1196 }
1197 return result;
1198}
1199
1203void
1204Effect::doOnApply (SPLPEItem const*/*lpeitem*/)
1205{
1206}
1207
1208void
1210{
1211 current_zoom = cZ;
1212}
1213
1217void Effect::transform_multiply(Geom::Affine const &postmul, bool /*set*/) {}
1218
1228{
1229 assert("pre: effect is referenced by lpeitem" &&
1230 std::any_of(lpeobj->hrefList.begin(), lpeobj->hrefList.end(),
1231 [lpeitem](SPObject *obj) { return lpeitem == cast<SPLPEItem>(obj); }));
1232
1233 // FIXME Is there a way to eliminate the raw Effect::sp_lpe_item pointer?
1234 sp_lpe_item = lpeitem;
1235
1236 transform_multiply(postmul, false);
1237}
1238
1239void
1240Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP)
1241{
1242 selectedNodesPoints = sNP;
1243}
1244
1249{
1250 if (auto lpeobj = getLPEObj()) {
1251 return lpeobj->isOnClipboard();
1252 }
1253 assert(lpeobj != nullptr);
1254 return false;
1255}
1256
1257bool
1259{
1260 if (selectedNodesPoints.size() > 0) {
1261 using Geom::X;
1262 using Geom::Y;
1263 for (auto p : selectedNodesPoints) {
1264 Geom::Affine transformCoordinate = sp_lpe_item->i2dt_affine();
1265 Geom::Point p2(nodePoint[X],nodePoint[Y]);
1266 p2 *= transformCoordinate;
1267 if (Geom::are_near(p, p2, 0.01)) {
1268 return true;
1269 }
1270 }
1271 }
1272 return false;
1273}
1274
1275// this is done in each action committed to undo and allow do things when all operations pending are done in this undo
1276// stack
1278{
1279 SPDocument *document = getSPDoc();
1280 if (!document || getLPEObj()->hrefList.empty() || _lpe_action == LPE_NONE) {
1282 return;
1283 }
1284 if (!sp_lpe_item || !sp_lpe_item->document) {
1285 sp_lpe_item = cast<SPLPEItem>(*getLPEObj()->hrefList.begin());
1286 if (!sp_lpe_item) {
1288 return;
1289 }
1290 }
1292 if (sp_lpe_item->getCurrentLPE() == this) {
1295 }
1297 return;
1298 }
1299 LPEAction lpe_action = _lpe_action;
1301 Inkscape::LivePathEffect::SatelliteArrayParam *lpesatellites = nullptr;
1303 std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
1304 for (auto &p : param_vector) {
1305
1306 lpesatellites = dynamic_cast<SatelliteArrayParam *>(p);
1307 lpesatellite = dynamic_cast<OriginalSatelliteParam *>(p);
1308 if (lpesatellites || lpesatellite) {
1309 break;
1310 }
1311 }
1312 if (!lpesatellites && !lpesatellite) {
1313 return;
1314 }
1315
1316 if (sp_lpe_item) {
1318 }
1319 std::vector<std::shared_ptr<SatelliteReference> > satelltelist;
1320 if (lpesatellites) {
1321 lpesatellites->read_from_SVG();
1322 satelltelist = lpesatellites->data();
1323 } else {
1324 lpesatellite->read_from_SVG();
1325 satelltelist.push_back(lpesatellite->lperef);
1326 }
1327 for (auto &iter : satelltelist) {
1328 SPObject *elemref;
1329 if (iter && iter->isAttached() && (elemref = iter->getObject())) {
1330 if (auto *item = cast<SPItem>(elemref)) {
1331 Inkscape::XML::Node *elemnode = elemref->getRepr();
1332 SPCSSAttr *css;
1333 Glib::ustring css_str;
1334 switch (lpe_action) {
1335 case LPE_TO_OBJECTS:
1336 if (item->isHidden()) {
1337 // We set updating because item signal fire a deletion that reset whole parameter satellites
1338 if (lpesatellites) {
1339 lpesatellites->setUpdating(true);
1340 item->deleteObject(true);
1341 lpesatellites->setUpdating(false);
1342 } else {
1343 lpesatellite->setUpdating(true);
1344 item->deleteObject(true);
1345 lpesatellite->setUpdating(false);
1346 }
1347 } else {
1348 elemnode->removeAttribute("sodipodi:insensitive");
1349 auto defs = cast<SPDefs>(elemref->parent);
1350 if (!defs && sp_lpe_item) {
1351 item->moveTo(sp_lpe_item, false);
1352 }
1353 }
1354 break;
1355
1356 case LPE_ERASE:
1357 // We set updating because item signal fire a deletion that reset whole parameter satellites
1358 if (lpesatellites) {
1359 lpesatellites->setUpdating(true);
1360 item->deleteObject(true);
1361 lpesatellites->setUpdating(false);
1362 } else {
1363 lpesatellite->setUpdating(true);
1364 item->deleteObject(true);
1365 lpesatellite->setUpdating(false);
1366 }
1367 break;
1368
1369 case LPE_VISIBILITY:
1372 if (!isVisible() /* && std::strcmp(elemref->getId(),sp_lpe_item->getId()) != 0*/) {
1373 css->setAttribute("display", "none");
1374 } else {
1375 css->removeAttribute("display");
1376 }
1377 sp_repr_css_write_string(css, css_str);
1378 elemnode->setAttributeOrRemoveIfEmpty("style", css_str);
1379 if (sp_lpe_item) {
1383 }
1385 break;
1386 default:
1387 break;
1388 }
1389 }
1390 }
1391 }
1392 if (lpe_action == LPE_ERASE || lpe_action == LPE_TO_OBJECTS) {
1393 Inkscape::LivePathEffect::SatelliteArrayParam *lpesatellites = nullptr;
1395 std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
1396 for (auto &p : param_vector) {
1397
1398 lpesatellites = dynamic_cast<SatelliteArrayParam *>(p);
1399 lpesatellite = dynamic_cast<OriginalSatelliteParam *>(p);
1400 if (lpesatellites) {
1401 lpesatellites->clear();
1402 lpesatellites->write_to_SVG();
1403 }
1404 if (lpesatellite) {
1405 lpesatellite->unlink();
1406 lpesatellite->write_to_SVG();
1407 }
1408 }
1409 }
1410 if (sp_lpe_item) {
1412 }
1413}
1414
1415// we delay till current operation is done to aboid deleted items crashes
1417 _lpe_action = lpe_action;
1418}
1419
1424bool Effect::doOnOpen(SPLPEItem const * /*lpeitem*/)
1425{
1426 // Do nothing for simple effects
1428 return false;
1429}
1430
1431void
1433 std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
1434 for (auto &p : param_vector) {
1435 p->update_satellites();
1436 }
1437}
1438
1439
1443void
1445{
1446 //Do nothing for simple effects
1447}
1458{
1459 //Do nothing for simple effects
1461}
1462
1463void Effect::doOnException(SPLPEItem const * /*lpeitem*/)
1464{
1465 has_exception = true;
1467}
1468
1469
1470void Effect::doOnRemove (SPLPEItem const* /*lpeitem*/)
1471{
1472}
1474{
1475}
1476
1478{
1479 _adjust_path = true;
1480}
1481
1482//secret impl methods (shhhh!)
1484{
1485 doAfterEffect(lpeitem, curve);
1486 is_load = false;
1487 is_applied = false;
1488 _adjust_path = false;
1489}
1490
1492{
1493 SPDocument *document = getSPDoc();
1494 if (!document) {
1495 return;
1496 }
1497 if (!sp_lpe_item || !sp_lpe_item->document) {
1498 sp_lpe_item = cast<SPLPEItem>(*getLPEObj()->hrefList.begin());
1499 if (!sp_lpe_item || !sp_lpe_item->document) {
1500 sp_lpe_item = nullptr;
1501 }
1502 }
1504 getLPEObj()->deleted = true;
1505}
1506
1511{
1512 std::vector<SPLPEItem *> lpeitems = getCurrrentLPEItems();
1513 if (lpeitems.size() == 1 && !isReady()) {
1514 is_load = true;
1515 doOnOpen(lpeitems[0]);
1516 setReady(true);
1517 }
1518}
1519
1520void
1521Effect::makeUndoDone(Glib::ustring message) {
1522 std::vector<SPLPEItem *> lpeitems = getCurrrentLPEItems();
1523 if (lpeitems.size() == 1) {
1524 refresh_widgets = true;
1525 sp_lpe_item = lpeitems[0];
1526 writeParamsToSVG(); // if the value change the LPEs become updated
1527 DocumentUndo::done(getSPDoc(), message.c_str(), INKSCAPE_ICON(LPETypeConverter.get_icon(effectType()).c_str()));
1528 }
1529 setReady();
1530}
1531
1533{
1534 sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
1535 is_applied = true;
1536 // we can override "lpeversion" value in each LPE using doOnApply
1537 // this allow to handle legacy LPE and some times update to newest definitions
1538 // In BBB Martin, Mc and Jabiertxof make decision
1539 // to only update this value per each LPE when changes.
1540 // and use the Inkscape release version that has this new LPE change
1541 // LPE without lpeversion are created in an inkscape lower than 1.0
1542 lpeversion.param_setValue("1", true);
1543 doOnApply(lpeitem);
1544 setReady();
1545 // this allow keep items stored as LPE items (paths instead ellipses...)
1546 sp_lpe_item->updateRepr(SP_OBJECT_CHILD_MODIFIED_FLAG);
1547 has_exception = false;
1548}
1549
1551{
1552 sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
1554 LPEItemShapesNumbers lpenumbers;
1555 // By the moment we not handle LPEItem groups. see here how to add to
1556 // https://pastebin.com/e5AesES9
1557 lpenumbers.nchildshapes = 0;
1560 if (!is_load && lpenumbers != _lpenumbers) {
1562 }
1563 //std::cout << _lpenumbers << std::endl;
1564 _lpenumbers = lpenumbers;
1565 }
1566 doBeforeEffect(lpeitem);
1567 if (is_load) {
1569 }
1571}
1572
1573void
1575 std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
1576 for (auto &p : param_vector) {
1577 p->write_to_SVG();
1578 }
1579}
1580void
1582 std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
1583 for (auto &p : param_vector) {
1584 p->read_from_SVG();
1585 }
1586}
1587
1588std::vector<SPObject *> Effect::effect_get_satellites(bool force)
1589{
1590 std::vector<SPObject *> satellites;
1591 if (!force && !satellitestoclipboard) {
1592 return satellites;
1593 }
1594 std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
1595 for (auto &p : param_vector) {
1596 std::vector<SPObject *> tmp = p->param_get_satellites();
1597 satellites.insert(satellites.begin(), tmp.begin(), tmp.end());
1598 }
1599 return satellites;
1600}
1601
1607void
1608Effect::acceptParamPath (SPPath const*/*param_path*/) {
1609 setReady();
1610}
1611
1612/*
1613 * Here be the doEffect function chain:
1614 */
1615void
1617{
1618 Geom::PathVector orig_pathv = curve->get_pathvector();
1619
1620 Geom::PathVector result_pathv = doEffect_path(orig_pathv);
1621
1622 curve->set_pathvector(result_pathv);
1623}
1624
1627{
1628 Geom::PathVector path_out;
1629
1630 if ( !concatenate_before_pwd2 ) {
1631 // default behavior
1632 for (const auto & i : path_in) {
1633 Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = i.toPwSb();
1635 Geom::PathVector path = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
1636 // add the output path vector to the already accumulated vector:
1637 for (const auto & j : path) {
1638 path_out.push_back(j);
1639 }
1640 }
1641 } else {
1642 // concatenate the path into possibly discontinuous pwd2
1644 for (const auto & i : path_in) {
1645 pwd2_in.concat( i.toPwSb() );
1646 }
1648 path_out = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
1649 }
1650
1651 return path_out;
1652}
1653
1656{
1657 g_warning("Effect has no doEffect implementation");
1658 return pwd2_in;
1659}
1660
1661void
1663{
1664 std::vector<Parameter *>::iterator it = param_vector.begin();
1666 while (it != param_vector.end()) {
1667 Parameter * param = *it;
1668 const gchar * key = param->param_key.c_str();
1669 const gchar * value = repr->attribute(key);
1670 if (value) {
1671 bool accepted = param->param_readSVGValue(value);
1672 if (!accepted) {
1673 g_warning("Effect::readallParameters - '%s' not accepted for %s", value, key);
1674 }
1675 } else {
1676 Glib::ustring pref_path = (Glib::ustring)"/live_effects/" +
1677 (Glib::ustring)LPETypeConverter.get_key(effectType()).c_str() +
1678 (Glib::ustring)"/" +
1679 (Glib::ustring)key;
1680 bool valid = prefs->getEntry(pref_path).isSet();
1681 if(valid){
1682 param->param_update_default(prefs->getString(pref_path).c_str());
1683 } else {
1684 param->param_set_default();
1685 }
1686 }
1687 ++it;
1688 }
1689}
1690
1691/* This function does not and SHOULD NOT write to XML */
1692void
1693Effect::setParameter(const gchar * key, const gchar * new_value)
1694{
1695 Parameter * param = getParameter(key);
1696 if (param) {
1697 if (new_value) {
1698 bool accepted = param->param_readSVGValue(new_value);
1699 if (!accepted) {
1700 g_warning("Effect::setParameter - '%s' not accepted for %s", new_value, key);
1701 }
1702 } else {
1703 // set default value
1704 param->param_set_default();
1705 }
1706 }
1707}
1708
1709void
1711{
1712 param_vector.push_back(param);
1713}
1714
1715
1719void
1721 using namespace Inkscape::LivePathEffect;
1722
1723 // add handles provided by the effect itself
1724 addKnotHolderEntities(knotholder, item);
1725
1726 // add handles provided by the effect's parameters (if any)
1727 for (auto & p : param_vector) {
1728 p->addKnotHolderEntities(knotholder, item);
1729 }
1730 if (is_load) {
1731 auto lpeitem = cast<SPLPEItem>(item);
1732 if (lpeitem) {
1733 sp_lpe_item_update_patheffect(lpeitem, false, false);
1734 }
1735 }
1736}
1737
1744std::vector<Geom::PathVector>
1746{
1747 std::vector<Geom::PathVector> hp_vec;
1748
1749 // add indicators provided by the effect itself
1750 addCanvasIndicators(lpeitem, hp_vec);
1751
1752 // add indicators provided by the effect's parameters
1753 for (auto & p : param_vector) {
1754 p->addCanvasIndicators(lpeitem, hp_vec);
1755 }
1756 Geom::Affine scale = lpeitem->i2doc_affine();
1757 for (auto &path : hp_vec) {
1758 path *= scale;
1759 }
1760 return hp_vec;
1761}
1762
1767void
1768Effect::addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector<Geom::PathVector> &/*hp_vec*/)
1769{
1770}
1771
1775void
1777 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
1778 if (desktop) {
1779 auto const nt = dynamic_cast<Inkscape::UI::Tools::NodeTool *>(desktop->getTool());
1780 if (nt) {
1782 }
1783 }
1784}
1785
1789Gtk::Widget *
1791{
1792 // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
1793 auto const vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
1794 vbox->set_margin(5);
1795
1796 std::vector<Parameter *>::iterator it = param_vector.begin();
1797 while (it != param_vector.end()) {
1798 if ((*it)->widget_is_visible) {
1799 Parameter * param = *it;
1800 Gtk::Widget * widg = param->param_newWidget();
1801
1802 if (widg) {
1803 if (param->widget_is_enabled) {
1804 widg->set_sensitive(true);
1805 } else {
1806 widg->set_sensitive(false);
1807 }
1808
1809 UI::pack_start(*vbox, *widg, true, true, 2);
1810
1811 if (auto const tip = param->param_getTooltip()) {
1812 widg->set_tooltip_markup(*tip);
1813 } else {
1814 widg->set_tooltip_text("");
1815 widg->set_has_tooltip(false);
1816 }
1817 }
1818 }
1819
1820 ++it;
1821 }
1822 return vbox;
1823}
1824
1828void
1830{
1831 Glib::ustring effectname = _(Inkscape::LivePathEffect::LPETypeConverter.get_label(effectType()).c_str());
1832 Glib::ustring effectkey = (Glib::ustring)Inkscape::LivePathEffect::LPETypeConverter.get_key(effectType());
1833 std::vector<Parameter *>::iterator it = param_vector.begin();
1834 bool has_params = false;
1835 while (it != param_vector.end()) {
1836 if ((*it)->widget_is_visible) {
1837 has_params = true;
1838 Parameter * param = *it;
1839 const gchar * key = param->param_key.c_str();
1840 if (g_strcmp0(key, "lpeversion") == 0) {
1841 ++it;
1842 continue;
1843 }
1844 Glib::ustring value = param->param_getSVGValue();
1845 Glib::ustring defvalue = param->param_getDefaultSVGValue();
1846 Glib::ustring pref_path = "/live_effects/";
1847 pref_path += effectkey;
1848 pref_path +="/";
1849 pref_path += key;
1850 setDefaultParam(pref_path, param);
1851 }
1852 ++it;
1853 }
1854}
1855
1859bool
1861{
1862 Glib::ustring effectname = _(Inkscape::LivePathEffect::LPETypeConverter.get_label(effectType()).c_str());
1863 Glib::ustring effectkey = (Glib::ustring)Inkscape::LivePathEffect::LPETypeConverter.get_key(effectType());
1864 std::vector<Parameter *>::iterator it = param_vector.begin();
1866 while (it != param_vector.end()) {
1867 Parameter * param = *it;
1868 const gchar * key = param->param_key.c_str();
1869 if (g_strcmp0(key, "lpeversion") == 0) {
1870 ++it;
1871 continue;
1872 }
1873 Glib::ustring pref_path = "/live_effects/";
1874 pref_path += effectkey;
1875 pref_path +="/";
1876 pref_path += key;
1877 if (prefs->getEntry(pref_path).isSet()) {
1878 return true;
1879 }
1880 ++it;
1881 }
1882 return false;
1883}
1884
1888void
1890{
1891 Glib::ustring effectname = _(Inkscape::LivePathEffect::LPETypeConverter.get_label(effectType()).c_str());
1892 Glib::ustring effectkey = (Glib::ustring)Inkscape::LivePathEffect::LPETypeConverter.get_key(effectType());
1893 std::vector<Parameter *>::iterator it = param_vector.begin();
1894 bool has_params = false;
1895 while (it != param_vector.end()) {
1896 if ((*it)->widget_is_visible) {
1897 has_params = true;
1898 Parameter * param = *it;
1899 const gchar * key = param->param_key.c_str();
1900 if (g_strcmp0(key, "lpeversion") == 0) {
1901 ++it;
1902 continue;
1903 }
1904 Glib::ustring value = param->param_getSVGValue();
1905 Glib::ustring defvalue = param->param_getDefaultSVGValue();
1906 Glib::ustring pref_path = "/live_effects/";
1907 pref_path += effectkey;
1908 pref_path +="/";
1909 pref_path += key;
1910 unsetDefaultParam(pref_path, param);
1911 }
1912 ++it;
1913 }
1914}
1915
1916void Effect::setDefaultParam(Glib::ustring pref_path, Parameter *param)
1917{
1918 Glib::ustring value = param->param_getSVGValue();
1919 Glib::ustring defvalue = param->param_getDefaultSVGValue();
1921 prefs->setString(pref_path, value);
1922}
1923
1924void Effect::unsetDefaultParam(Glib::ustring pref_path,Parameter *param)
1925{
1926 Glib::ustring value = param->param_getSVGValue();
1927 Glib::ustring defvalue = param->param_getDefaultSVGValue();
1929 if (prefs->getEntry(pref_path).isSet()) {
1930 prefs->remove(pref_path);
1931 }
1932}
1933
1935{
1936 return lpeobj->getRepr();
1937}
1938
1940{
1941 if (lpeobj->document == nullptr) {
1942 g_message("Effect::getSPDoc() returns NULL");
1943 }
1944 return lpeobj->document;
1945}
1946
1947Parameter *
1949{
1950 Glib::ustring stringkey(key);
1951
1952 if (param_vector.empty()) return nullptr;
1953 std::vector<Parameter *>::iterator it = param_vector.begin();
1954 while (it != param_vector.end()) {
1955 Parameter * param = *it;
1956 if ( param->param_key == key) {
1957 return param;
1958 }
1959
1960 ++it;
1961 }
1962
1963 return nullptr;
1964}
1965
1966Parameter *
1968{
1969 if (param_vector.size() == 0) // no parameters
1970 return nullptr;
1971
1973 if (oncanvasedit_it >= static_cast<int>(param_vector.size())) {
1974 oncanvasedit_it = 0;
1975 }
1976 int old_it = oncanvasedit_it;
1977
1978 do {
1980 if(param && param->oncanvas_editable) {
1981 return param;
1982 } else {
1984 if (oncanvasedit_it == static_cast<int>(param_vector.size())) { // loop round the map
1985 oncanvasedit_it = 0;
1986 }
1987 }
1988 } while (oncanvasedit_it != old_it); // iterate until complete loop through map has been made
1989
1990 return nullptr;
1991}
1992
1993void
1995{
1996 if (!desktop) return;
1997
1999 if (param) {
2001 gchar *message = g_strdup_printf(_("Editing parameter <b>%s</b>."), param->param_label.c_str());
2003 g_free(message);
2004 } else {
2006 _("None of the applied path effect's parameters can be edited on-canvas.") );
2007 }
2008}
2009
2010/* This function should reset the defaults and is used for example to initialize an effect right after it has been applied to a path
2011* The nice thing about this is that this function can use knowledge of the original path and set things accordingly for example to the size or origin of the original path!
2012*/
2013void
2015{
2016 std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
2017 for (auto &p : param_vector) {
2018 p->param_set_default();
2019 p->write_to_SVG();
2020 }
2021}
2022
2023bool
2025{
2026 // does the effect actively provide any knotholder entities of its own?
2028 return true;
2029 }
2030
2031 // otherwise: are there any parameters that have knotholderentities?
2032 for (auto p : param_vector) {
2033 if (p->providesKnotHolderEntities()) {
2034 return true;
2035 }
2036 }
2037
2038 return false;
2039}
2040
2041} /* namespace LivePathEffect */
2042} /* namespace Inkscape */
2043
2044/*
2045 Local Variables:
2046 mode:c++
2047 c-file-style:"stroustrup"
2048 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
2049 indent-tabs-mode:nil
2050 fill-column:99
2051 End:
2052*/
2053// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
double scale
Definition aa.cpp:228
3x3 matrix representing an affine transformation.
Definition affine.h:70
Adaptor that creates 2D functions from 1D ones.
Definition d2.h:55
Sequence of subpaths.
Definition pathvector.h:122
size_type size() const
Get the number of paths in the vector.
Definition pathvector.h:147
void push_back(Path const &path)
Append a path at the end.
Definition pathvector.h:172
Function defined as discrete pieces.
Definition piecewise.h:71
void concat(const Piecewise< T > &other)
Definition piecewise.h:235
Two-dimensional point that doubles as a vector.
Definition point.h:66
RAII-style mechanism for creating a temporary undo-insensitive context.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
std::vector< StorageType > const & data() const
Definition array.h:48
void doBeforeEffect_impl(SPLPEItem const *lpeitem)
Definition effect.cpp:1550
virtual void doOnVisibilityToggled(SPLPEItem const *lpeitem)
Definition effect.cpp:1473
std::vector< Parameter * > param_vector
Definition effect.h:179
void registerParameter(Parameter *param)
Definition effect.cpp:1710
virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector< Geom::PathVector > &hp_vec)
Add possible canvas indicators (i.e., helperpaths other than the original path) to hp_vec This functi...
Definition effect.cpp:1768
virtual void resetDefaults(SPItem const *item)
Sets all parameters to their default values and writes them to SVG.
Definition effect.cpp:2014
virtual Gtk::Widget * newWidget()
This creates a managed widget.
Definition effect.cpp:1790
void setReady(bool ready=true)
Definition effect.h:122
static void createAndApply(const char *name, SPDocument *doc, SPItem *item)
Definition effect.cpp:1118
virtual void doOnRemove(SPLPEItem const *)
Definition effect.cpp:1470
void setParameter(const gchar *key, const gchar *new_value)
Definition effect.cpp:1693
bool hasDefaultParameters()
Get LPE has defaults.
Definition effect.cpp:1860
void transform_multiply_impl(Geom::Affine const &postmul, SPLPEItem *)
Definition effect.cpp:1227
void editNextParamOncanvas(SPItem *item, SPDesktop *desktop)
Definition effect.cpp:1994
std::vector< Geom::PathVector > getCanvasIndicators(SPLPEItem const *lpeitem)
Return a vector of PathVectors which contain all canvas indicators for this effect.
Definition effect.cpp:1745
virtual void doOnApply(SPLPEItem const *lpeitem)
Is performed a single time when the effect is freshly applied to a path.
Definition effect.cpp:1204
static Effect * New(EffectType lpenr, LivePathEffectObject *lpeobj)
Definition effect.cpp:930
Parameter * getParameter(const char *key)
Definition effect.cpp:1948
LivePathEffectObject * lpeobj
Definition effect.h:220
void setDefaultParam(Glib::ustring pref_path, Parameter *param)
Definition effect.cpp:1916
Effect(const Effect &)=delete
virtual void processObjects(LPEAction lpe_action)
Definition effect.cpp:1416
std::vector< SPObject * > effect_get_satellites(bool force=true)
Definition effect.cpp:1588
sigc::connection _before_commit_connection
Definition effect.h:232
Inkscape::XML::Node * getRepr()
Definition effect.cpp:1934
void addHandles(KnotHolder *knotholder, SPItem *item)
Add all registered LPE knotholder handles to the knotholder.
Definition effect.cpp:1720
bool isOnClipboard()
The lpe is on clipboard.
Definition effect.cpp:1248
Parameter * getNextOncanvasEditableParam()
Definition effect.cpp:1967
void doAfterEffect_impl(SPLPEItem const *lpeitem, SPCurve *curve)
Definition effect.cpp:1483
void unsetDefaultParam(Glib::ustring pref_path, Parameter *param)
Definition effect.cpp:1924
bool isNodePointSelected(Geom::Point const &nodePoint) const
Definition effect.cpp:1258
std::vector< SPLPEItem * > getCurrrentLPEItems() const
Definition effect.cpp:1187
virtual void doOnException(SPLPEItem const *lpeitem)
Definition effect.cpp:1463
void setDefaultParameters()
Set this LPE defaults.
Definition effect.cpp:1829
Geom::PathVector pathvector_before_effect
Definition effect.h:174
Glib::ustring getName() const
Definition effect.cpp:1173
void doOnOpen_impl()
Is performed on document open allow things like fix legacy LPE in a undo insensitive way.
Definition effect.cpp:1510
void setSelectedNodePoints(std::vector< Geom::Point > sNP)
Definition effect.cpp:1240
EffectType effectType() const
Definition effect.cpp:1182
void makeUndoDone(Glib::ustring message)
Definition effect.cpp:1521
virtual void doBeforeEffect(SPLPEItem const *lpeitem)
Is performed each time before the effect is updated.
Definition effect.cpp:1444
LPEItemShapesNumbers _lpenumbers
Definition effect.h:233
void update_helperpath()
Call to a method on nodetool to update the helper path from the effect.
Definition effect.cpp:1776
Geom::PathVector pathvector_after_effect
Definition effect.h:175
virtual void doEffect(SPCurve *curve)
Definition effect.cpp:1616
void doOnRemove_impl(SPLPEItem const *lpeitem)
Definition effect.cpp:1491
virtual void transform_multiply(Geom::Affine const &postmul, bool set)
Overridden function to apply transforms for example to powerstroke, jointtype or tapperstroke.
Definition effect.cpp:1217
virtual void doAfterEffect(SPLPEItem const *lpeitem, SPCurve *curve)
Is performed at the end of the LPE only one time per "lpeitem" in paths/shapes is called in middle of...
Definition effect.cpp:1457
std::vector< Geom::Point > selectedNodesPoints
Definition effect.h:217
void readallParameters(Inkscape::XML::Node const *repr)
Definition effect.cpp:1662
void doOnApply_impl(SPLPEItem const *lpeitem)
Definition effect.cpp:1532
void resetDefaultParameters()
Reset this LPE defaults.
Definition effect.cpp:1889
LivePathEffectObject * getLPEObj()
Definition effect.h:151
virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in)
Definition effect.cpp:1626
virtual bool doOnOpen(SPLPEItem const *lpeitem)
Is performed on load document or revert If the item is fixed legacy return true.
Definition effect.cpp:1424
virtual void acceptParamPath(SPPath const *param_path)
If the effect expects a path parameter (specified by a number of mouse clicks) before it is applied,...
Definition effect.cpp:1608
virtual Geom::Piecewise< Geom::D2< Geom::SBasis > > doEffect_pwd2(Geom::Piecewise< Geom::D2< Geom::SBasis > > const &pwd2_in)
Definition effect.cpp:1655
virtual void addKnotHolderEntities(KnotHolder *, SPItem *)
Definition effect.h:203
Simplified management of enumerations of LPE items with UI labels.
void param_setValue(Glib::ustring newvalue, bool write=false)
Definition hidden.cpp:71
Glib::ustring const * param_getTooltip() const
Definition parameter.h:81
virtual void param_editOncanvas(SPItem *, SPDesktop *)
Definition parameter.h:88
virtual bool param_readSVGValue(char const *strvalue)=0
virtual void param_update_default(char const *default_value)=0
void setUpdating(bool updating)
Definition parameter.h:73
virtual Gtk::Widget * param_newWidget()=0
virtual Glib::ustring param_getDefaultSVGValue() const =0
virtual Glib::ustring param_getSVGValue() const =0
std::shared_ptr< SatelliteReference > lperef
Definition satellite.h:58
MessageId flash(MessageType type, char const *message)
Temporarily pushes a message onto the stack.
bool isSet() const
Check whether the received entry is set.
Preference storage class.
Definition preferences.h:66
Glib::ustring getString(Glib::ustring const &pref_path, Glib::ustring const &def="")
Retrieve an UTF-8 string.
static Preferences * get()
Access the singleton Preferences object.
Entry const getEntry(Glib::ustring const &pref_path)
Retrieve a preference entry without specifying its type.
void setString(Glib::ustring const &pref_path, Glib::ustring const &value)
Set an UTF-8 string value.
void remove(Glib::ustring const &pref_path)
Remove a node from prefs.
Interface for refcounted XML nodes.
Definition node.h:80
virtual void addChild(Node *child, Node *after)=0
Insert another node as a child of this node.
void setAttributeOrRemoveIfEmpty(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:167
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
void removeAttribute(Inkscape::Util::const_char_ptr key)
Remove an attribute of this node.
Definition node.h:280
bool isOnClipboard() const
Definition lpeobject.h:43
Inkscape::LivePathEffect::EffectType effecttype
Definition lpeobject.h:39
Wrapper around a Geom::PathVector object.
Definition curve.h:28
To do: update description of desktop.
Definition desktop.h:149
Inkscape::MessageStack * messageStack() const
Definition desktop.h:160
Inkscape::UI::Tools::ToolBase * getTool() const
Definition desktop.h:187
Typed SVG document implementation.
Definition document.h:101
sigc::connection connectBeforeCommit(BeforeCommitSignal::slot_type slot)
SPDefs * getDefs()
Return the main defs object for the document.
Definition document.cpp:246
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Definition document.h:211
Base class for visual SVG elements.
Definition sp-item.h:109
Geom::Affine i2dt_affine() const
Returns the transformation from item to desktop coords.
Definition sp-item.cpp:1837
bool isHidden() const
Definition sp-item.cpp:242
void moveTo(SPItem *target, bool intoafter)
Move this SPItem into or after another SPItem in the doc.
Definition sp-item.cpp:485
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
Definition sp-item.cpp:1832
Inkscape::LivePathEffect::Effect * getCurrentLPE()
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
SPDocument * document
Definition sp-object.h:188
SPObject * parent
Definition sp-object.h:189
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
void deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
std::list< SPObject * > hrefList
Definition sp-object.h:197
SVG <path> implementation.
Definition sp-path.h:29
std::shared_ptr< Css const > css
Css & result
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
size_t count_pathvector_curves(Geom::PathVector const &pathv)
Definition geom.cpp:747
Specific geometry functions for Inkscape, not provided my lib2geom.
Icon Loader.
SPItem * item
LPE "Circle through 3 points" implementation.
LPE effect that draws a circle based on two points and a radius.
Implementation of the construct grid LPE, see lpe-constructgrid.cpp.
LPE <copy_rotate> implementation, see lpe-copy_rotate.cpp.
Implementation of the curve stitch effect, see lpe-curvestitch.cpp.
LPE <dynastroke> implementation, see lpe-dynastroke.cpp.
LPE "Ellipse through 5 points" implementation.
LPE effect for extruding paths (making them "3D").
LPE interpolate implementation, see lpe-interpolate.cpp.
LPE interpolate_points implementation, see lpe-interpolate_points.cpp.
LPE knot effect implementation, see lpe-knot.cpp.
LPE <lattice2> implementation, see lpe-lattice2.cpp.
LPE <lattice> implementation, see lpe-lattice.cpp.
LPE <line_segment> implementation.
LPE <mirror_symmetry> implementation: mirrors a path with respect to a given line.
LPE <offset> implementation, see lpe-offset.cpp.
LPE <parallel> implementation.
LPE <path_length> implementation.
LPE <perp_bisector> implementation, see lpe-perp_bisector.cpp.
LPE <perspective-envelope> implementation , see lpe-perspective-envelope.cpp.
PowerStroke LPE effect, see lpe-powerstroke.cpp.
LPE "Points to Ellipse" implementation.
see lpe-recursiveskeleton.cpp.
Fills an area with rough hatches.
Roughen LPE effect, see lpe-roughen.cpp.
LPE <ruler> implementation, see lpe-ruler.cpp.
LPE sketch effect implementation, see lpe-sketch.cpp.
LPE <mirror_symmetry> implementation: mirrors a path with respect to a given line.
LPE <tangent_to_curve> implementation, see lpe-tangent_to_curve.cpp.
Taper Stroke path effect (meant as a replacement for using Power Strokes for tapering)
LPE <text_label> implementation.
LPE <tiling> implementation.
LPE "Transform through 2 points" implementation.
Raw stack of active status messages.
PathVector path_from_piecewise(Piecewise< D2< SBasis > > const &B, double tol, bool only_cubicbeziers=false)
Make a path from a d2 sbasis.
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
static R & release(R &r)
Decrements the reference count of a anchored object.
Live Path Effects code.
const EnumEffectData< EffectType > LPETypeData[]
Definition effect.cpp:97
const EnumEffectDataConverter< EffectType > LPETypeConverter
defined in effect.cpp
void sp_update_helperpath(SPDesktop *desktop)
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
Definition pack.cpp:141
Helper class to stream background task notifications as a series of messages.
@ NORMAL_MESSAGE
Definition message.h:26
@ WARNING_MESSAGE
Definition message.h:28
New node tool with support for multiple path editing.
static cairo_user_data_key_t key
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
PenTool: a context for pen tool events.
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
Definition repr-css.cpp:67
void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str)
Write a style attribute string from a list of properties stored in an SPCSAttr object.
Definition repr-css.cpp:243
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
Definition repr-css.cpp:76
void sp_repr_css_attr_add_from_string(SPCSSAttr *css, gchar const *p)
Use libcroco to parse a string for CSS properties and then merge them into an existing SPCSSAttr.
Definition repr-css.cpp:341
SPCSSAttr - interface for CSS Attributes.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable)
SPRoot: SVG <svg> implementation.
Interface for XML documents.
Definition document.h:43
virtual Node * createElement(char const *name)=0
Definition curve.h:24
SPDesktop * desktop
Glib::ustring name
Definition toolbars.cpp:55