20#include <glibmm/i18n.h>
22#include <gtkmm/button.h>
51namespace LivePathEffect {
55 lpesatellites(_(
"lpesatellites"), _(
"Items satellites"),
"lpesatellites", &wr, this, false),
56 allow_transforms(_(
"Allow Transforms"), _(
"Allow transforms"),
"allow_transforms", &wr, this, true),
57 start_point(_(
"Slice line start"), _(
"Start point of slice line"),
"start_point", &wr, this, _(
"Adjust start point of slice line")),
58 end_point(_(
"Slice line end"), _(
"End point of slice line"),
"end_point", &wr, this, _(
"Adjust end point of slice line")),
59 center_point(_(
"Slice line mid"), _(
"Center point of slice line"),
"center_point", &wr, this, _(
"Adjust center point of slice line"))
85 if (version <
"1.2") {
87 if (lpeitems.size() >= 1) {
104 auto const vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 2);
107 auto const hbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 0);
109 auto const center_vert_button = Gtk::make_managed<Gtk::Button>(Glib::ustring(_(
"Vertical")));
111 center_vert_button->set_size_request(110, 20);
113 auto const center_horiz_button = Gtk::make_managed<Gtk::Button>(Glib::ustring(_(
"Horizontal")));
115 center_horiz_button->set_size_request(110, 20);
117 auto const reset_button = Gtk::make_managed<Gtk::Button>(Glib::ustring(_(
"Reset styles")));
119 reset_button->set_size_request(110, 20);
126 std::vector<Parameter *>::iterator it =
param_vector.begin();
128 if ((*it)->widget_is_visible) {
136 widg->set_tooltip_markup(*tip);
138 widg->set_tooltip_text(
"");
139 widg->set_has_tooltip(
false);
167 auto group = cast<SPGroup>(
item);
169 std::vector<SPObject *> childs = group->childList(
true);
170 for (
auto &
child : childs) {
177 auto shape = cast<SPShape>(
item);
180 if (
c && !
c->is_empty()) {
184 if (shape->hasPathEffectRecursive()) {
185 SPCurve const *
c = shape->curveBeforeLPE();
186 if (
c && !
c->is_empty()) {
202 if (
c && !
c->is_empty()) {
203 curve->set_pathvector(
c->get_pathvector());
214 auto group = cast<SPGroup>(
item);
216 std::vector<SPObject *> childs = group->childList(
true);
217 for (
auto &
child : childs) {
223 auto shape = cast<SPShape>(
item);
225 SPCurve const *
c = shape->curveBeforeLPE();
226 if (
c && !
c->is_empty()) {
227 shape->bbox_vis_cache_is_valid =
false;
228 shape->bbox_geom_cache_is_valid =
false;
229 shape->setCurveInsync(
c);
231 shape->setAttribute(
"d", str);
241 if (!
is_load && version <
"1.2") {
252 bool is_applied_on =
false;
254 is_applied_on =
true;
260 if (lpereference && lpereference->isAttached() && lpereference.get()->getObject() !=
nullptr) {
275 if (iter && iter->isAttached() && (elemref = iter->getObject())) {
276 if (
auto *splpeitem = cast<SPLPEItem>(elemref)) {
277 splpeitem->setHidden(
true);
289 std::vector<std::pair<Geom::Line, size_t> > slicer =
getSplitLines();
290 if (!slicer.size()) {
296 bool creation = write;
308 if (iter && iter->isAttached() && (elemref = iter->getObject())) {
309 auto splpeitem = cast<SPLPEItem>(elemref);
310 if (splpeitem || lpeitem->
isHidden()) {
311 if (!maindata || lpeitem->
isHidden()) {
312 splpeitem->setHidden(
true);
328 if (is_applied_on && prevslice) {
331 if (link && link->isAttached()) {
332 auto spgrp = cast<SPGroup>(link->getObject());
333 auto spit = cast<SPShape>(link->getObject());
334 Glib::ustring transform =
"";
335 Glib::ustring patheffects =
"";
338 if (spgrp->getAttribute(
"transform")) {
339 transform = spgrp->getAttribute(
"transform");
341 if (spgrp->getAttribute(
"inkscape:path-effect")) {
342 patheffects = spgrp->getAttribute(
"inkscape:path-effect");
344 spgrp->setAttribute(
"transform",
nullptr);
345 spgrp->setAttribute(
"inkscape:path-effect",
nullptr);
346 _gbbox = spgrp->geometricBounds();
350 if (link2 && link2->isAttached()) {
351 auto spgrp2 = cast<SPGroup>(link2->getObject());
352 auto spit2 = cast<SPShape>(link2->getObject());
354 Geom::OptRect _bbox = spit->curveForEdit()->get_pathvector().boundsFast();
355 Geom::OptRect _bbox2 = spit2->curveForEdit()->get_pathvector().boundsFast();
356 if (_bbox && _bbox2) {
357 (*_bbox).expandBy(1);
358 if ((*_bbox).contains(*_bbox2)) {
359 spit2->setAttribute(
"transform", spit->getAttribute(
"transform"));
360 spit2->setAttribute(
"inkscape:path-effect", spit->getAttribute(
"inkscape:path-effect"));
361 spit2->setAttribute(
"style", spit->getAttribute(
"style"));
364 }
else if (spgrp && spgrp2) {
366 if (_gbbox && _gbbox2) {
367 (*_gbbox).expandBy(1);
368 if ((*_gbbox).contains(*_gbbox2)) {
369 spgrp2->setAttribute(
"transform", transform);
370 spgrp2->setAttribute(
"inkscape:path-effect", patheffects);
378 spgrp->setAttribute(
"transform", transform);
379 spgrp->setAttribute(
"inkscape:path-effect", patheffects);
388 if (itemrf && itemrf->isAttached()) {
389 auto splpeitem = cast<SPLPEItem>(itemrf->getObject());
391 splpeitem->setHidden(
true);
402 bool splited =
false;
403 size_t nsplits = slicer.size();
417 bool prevreset =
reset;
421 Glib::ustring elemref_id = Glib::ustring(
"slice-");
426 auto lpeitem = cast<SPLPEItem>(
item);
430 if (!lpeitem->hasPathEffectOfType(
SLICE) && clean_id.find(
"slice-") != Glib::ustring::npos) {
431 clean_id = clean_id.replace(0,6,
"");
432 elemref_id += clean_id;
434 elemref_id += clean_id;
451 auto other = cast<SPItem>(elemref);
454 other->setHidden(
false);
459 splititem(other,
nullptr, slicer[splitindex],
false);
461 other->setHidden(
true);
464 if (nsplits > splitindex) {
465 auto splpeother = cast<SPLPEItem>(other);
466 auto splpeitem = cast<SPLPEItem>(
item);
470 split(other,
nullptr, slicer, splitindex, creation);
479std::vector<std::pair<Geom::Line, size_t> >
481 std::vector<std::pair<Geom::Line, size_t> > splitlines;
483 if (lpeitems.size() >= 1) {
494 std::pair<Geom::Line, size_t> slice = std::make_pair(line_separation,
index);
495 splitlines.push_back(slice);
507 auto group = cast<SPGroup>(elemref);
513 std::vector<SPItem*>
const item_list = group->item_list();
515 for (
auto sub_item : item_list) {
518 previous = resultnode;
539 auto originalitem = cast<SPItem>(
orig);
540 if ( is<SPGroup>(
orig) && is<SPGroup>(dest) && cast<SPGroup>(
orig)->getItemCount() == cast<SPGroup>(dest)->getItemCount() ) {
548 std::vector< SPObject * > childs =
orig->childList(
true);
550 for (
auto &
child : childs) {
558 auto shape = cast<SPShape>(
orig);
559 auto path = cast<SPPath>(dest);
562 if (
c && !
c->is_empty()) {
564 if (path->hasPathEffectRecursive()) {
587 if (val && strcmp(val,
"nonzero") == 0) {
589 }
else if (val && strcmp(val,
"evenodd") == 0) {
599 bool splited =
false;
607 auto group = cast<SPGroup>(
item);
613 std::vector<SPObject *> childs = group->childList(
true);
614 for (
auto &
child : childs) {
615 auto dest_child = cast<SPItem>(
child);
617 splited =
splititem(dest_child,
nullptr, slicer, toggle, is_original, t,
false) ? true : splited;
624 auto shape = cast<SPShape>(
item);
625 auto path = cast<SPPath>(
item);
637 for (
auto & path_it : original_pathv) {
639 if (path_it.empty()) {
643 double time_start = 0.0;
645 bool end_open =
false;
646 if (path_it.closed()) {
647 const Geom::Curve &closingline = path_it.back_closed();
653 if (end_open && path_it.closed()) {
658 double dir = line_separation.
angle();
663 s = Geom::Point::polar(dir,size_divider) + center;
664 e = Geom::Point::polar(dir + Geom::rad_from_deg(180),size_divider) + center;
667 std::vector<double> crossed;
673 crossed.push_back(
c.ta);
675 double angle = Geom::deg_from_rad(ray.
angle());
676 bool toggleside = !(angle > 0 && angle < 180);
677 std::sort(crossed.begin(), crossed.end());
678 for (
double time_end : crossed) {
679 if (time_start != time_end && time_end - time_start >
Geom::EPSILON) {
696 time_start = time_end;
705 if (cs.size()!=0 && (position == 1)) {
712 if (cs.size() > 1 && tmp_pathvector.
size() > 0 && tmp_pathvector[0].
size() > 0 ) {
713 tmp_pathvector[0] = tmp_pathvector[0].
reversed();
715 portion.setInitial(tmp_pathvector[0].finalPoint());
716 tmp_pathvector[0].append(
portion);
717 tmp_pathvector[0] = tmp_pathvector[0].
reversed();
726 if (cs.size() > 0 &&
original.closed()) {
727 for (
auto &path : tmp_pathvector) {
728 if (!path.closed()) {
733 if (cs.size() == 0 && position == 1) {
742 tmp_pathvector.
clear();
744 if (
curve && is_original) {
745 curve->set_pathvector(path_out);
747 if (shape->curve()) {
748 shape->bbox_vis_cache_is_valid =
false;
749 shape->bbox_geom_cache_is_valid =
false;
750 shape->setCurveInsync(
SPCurve(path_out));
752 if (!is_original && shape->hasPathEffectRecursive()) {
755 shape->setAttribute(
"inkscape:original-d", str);
757 shape->setAttribute(
"d", str);
761 shape->setAttribute(
"d", str);
782 using namespace Geom;
848 for (
auto iter :
orig->style->properties()) {
850 auto key = iter->id();
852 const gchar *attr =
orig->getAttribute(iter->name().c_str());
865 if (lpeitems.size() == 1) {
869 nextslice->
reset =
true;
882 if (itemrf && itemrf->isAttached()) {
883 auto splpeitem = cast<SPLPEItem>(itemrf->getObject());
885 splpeitem->setHidden(
true);
905 using namespace Geom;
936 using namespace Geom;
945 hp_vec.push_back(helper);
TODO: insert short description here.
TODO: insert short description here.
3x3 affine transformation matrix.
3x3 matrix representing an affine transformation.
Affine inverse() const
Compute the inverse matrix.
friend Bezier portion(const Bezier &a, Coord from, Coord to)
Abstract continuous curve on a plane defined on [0,1].
virtual Point initialPoint() const =0
Retrieve the start of the curve.
virtual Point finalPoint() const =0
Retrieve the end of the curve.
constexpr bool isSingular() const
constexpr C middle() const
Infinite line on a plane.
Ray ray(Coord t)
Create a ray starting at the specified time value.
Point initialPoint() const
Coord angle() const
Angle the line makes with the X axis, in mathematical convention.
Axis-aligned rectangle that can be empty.
size_type size() const
Get the number of paths in the vector.
void push_back(Path const &path)
Append a path at the end.
void clear()
Remove all paths from the vector.
iterator insert(iterator pos, Path const &p)
PathVector reversed(bool reverse_paths=true) const
Get a new vector with reversed direction of paths.
Sequence of contiguous curves, aka spline.
void close(bool closed=true)
Set whether the path is closed.
void appendNew(Args &&... args)
Append a new curve to the path.
void start(Point const &p)
Two-dimensional point that doubles as a vector.
Straight ray from a specific point to infinity.
Axis aligned, non-empty rectangle.
std::vector< StorageType > const & data() const
void param_setValue(bool newvalue)
std::vector< Parameter * > param_vector
void registerParameter(Parameter *param)
bool apply_to_clippath_and_mask
virtual void processObjects(LPEAction lpe_action)
SPShape * getCurrentShape() const
std::vector< SPLPEItem * > getCurrrentLPEItems() const
void makeUndoDone(Glib::ustring message)
bool satellitestoclipboard
void original_bbox(SPLPEItem const *lpeitem, bool absolute=false, bool clip_mask=false, Geom::Affine base_transform=Geom::identity())
Geom::Interval boundingbox_Y
Geom::Interval boundingbox_X
void param_setValue(Glib::ustring newvalue, bool write=false)
Glib::ustring param_getSVGValue() const override
void doAfterEffect(SPLPEItem const *lpeitem, SPCurve *curve) override
Is performed at the end of the LPE only one time per "lpeitem" in paths/shapes is called in middle of...
void cloneStyle(SPObject *orig, SPObject *dest)
void doOnApply(SPLPEItem const *lpeitem) override
Is performed a single time when the effect is freshly applied to a path.
void doOnVisibilityToggled(SPLPEItem const *) override
Geom::Point previous_center
bool split(SPItem *item, SPCurve *curve, std::vector< std::pair< Geom::Line, size_t > > slicer, size_t splitindex, bool &creation)
bool allow_transforms_prev
Geom::PathVector doEffect_path(Geom::PathVector const &path_in) override
void originalDtoD(SPShape const *shape, SPCurve *curve)
Gtk::Widget * newWidget() override
This creates a managed widget.
void cloneD(SPObject *orig, SPObject *dest, bool is_original)
LPESlice(LivePathEffectObject *lpeobject)
void doBeforeEffect(SPLPEItem const *lpeitem) override
Is performed each time before the effect is updated.
void doOnRemove(SPLPEItem const *) override
BoolParam allow_transforms
bool splititem(SPItem *item, SPCurve *curve, std::pair< Geom::Line, size_t > slicer, bool toggle, bool is_original=false, Geom::Affine tpass=Geom::identity(), bool top=true)
bool doOnOpen(SPLPEItem const *lpeitem) override
Is performed on load document or revert If the item is fixed legacy return true.
Inkscape::XML::Node * createPathBase(SPObject *elemref)
SatelliteArrayParam lpesatellites
std::vector< std::pair< Geom::Line, size_t > > getSplitLines()
void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector< Geom::PathVector > &hp_vec) override
Add possible canvas indicators (i.e., helperpaths other than the original path) to hp_vec This functi...
Glib::ustring const * param_getTooltip() const
virtual void param_widget_is_visible(bool is_visible)
void setUpdating(bool updating)
void connect_selection_changed()
virtual Gtk::Widget * param_newWidget()=0
void param_update_default(Geom::Point default_point)
void param_setValue(Geom::Point newpoint, bool write=false)
void link(SPObject *to, size_t pos=Glib::ustring::npos)
Interface for refcounted XML nodes.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
Wrapper around a Geom::PathVector object.
Typed SVG document implementation.
SPObject * getObjectById(std::string const &id) const
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Base class for visual SVG elements.
std::size_t getLPEIndex(Inkscape::LivePathEffect::Effect *lpe) const
bool hasPathEffectOfType(int const type, bool is_ready=true) const
Inkscape::LivePathEffect::Effect * getPrevLPE(Inkscape::LivePathEffect::Effect *lpe)
Inkscape::LivePathEffect::Effect * getNextLPE(Inkscape::LivePathEffect::Effect *lpe)
SPObject is an abstract base class of all of the document nodes at the SVG document level.
void setAttributeOrRemoveIfEmpty(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
void setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
char const * getId() const
Returns the objects current ID string.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
SPObject * appendChildRepr(Inkscape::XML::Node *repr)
Append repr as child of this object.
SPObject * nthChild(unsigned index)
void addChild(Inkscape::XML::Node *child, Inkscape::XML::Node *prev=nullptr)
Base class for shapes, including <path> element.
SPCurve const * curveBeforeLPE() const
Return a borrowed pointer of the curve before LPE (if any exists) or NULL if there is no curve.
std::shared_ptr< Css const > css
constexpr Coord infinity()
Get a value representing infinity.
constexpr Coord EPSILON
Default "acceptably small" value.
Geom::PathVector pathv_to_linear_and_cubic_beziers(Geom::PathVector const &pathv)
Specific geometry functions for Inkscape, not provided my lib2geom.
Macro for icon names used in Inkscape.
LPE <mirror_symmetry> implementation: mirrors a path with respect to a given line.
Various utility functions.
int sgn(const T &x)
Sign function - indicates the sign of a numeric type.
Angle distance(Angle const &a, Angle const &b)
std::vector< Crossing > Crossings
Affine identity()
Create an identity matrix.
Crossings crossings(Curve const &a, Curve const &b)
Bezier portion(const Bezier &a, double from, double to)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Point middle_point(LineSegment const &_segment)
static R & release(R &r)
Decrements the reference count of a anchored object.
bool sp_has_path_data(SPItem *item, bool originald)
static FillRule GetFillTyp(SPItem *item)
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.
Glib::ustring format_classic(T const &... args)
Helper class to stream background task notifications as a series of messages.
static cairo_user_data_key_t key
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
void flatten(Geom::PathVector &pathv, FillRule fill_rule)
Inkscape::SVG::PathString - builder for SVG path strings.
SPCSSAttr * sp_repr_css_attr(Node const *repr, gchar const *attr)
Creates a new SPCSSAttr with one attribute (i.e.
char const * sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const *defval)
Returns a character string of the value of a given style property or a default value if the attribute...
TODO: insert short description here.
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)
Base class for live path effect items.
Interface for XML documents.
virtual Node * createElement(char const *name)=0
SPStyle - a style object for SPItem objects.
std::string sp_svg_transform_write(Geom::Affine const &transform)
static void sp_svg_write_path(Inkscape::SVG::PathString &str, Geom::Path const &p, bool normalize=false)