Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
lpe-fill-between-many.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
4 *
5 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
6 */
7
8
10
11#include "inkscape.h"
12#include "selection.h"
13
14#include "display/curve.h"
15#include "object/sp-defs.h"
16#include "object/sp-root.h"
17#include "object/sp-shape.h"
18
19// TODO due to internal breakage in glibmm headers, this must be last:
20#include <glibmm/i18n.h>
21
22namespace Inkscape {
23namespace LivePathEffect {
24
26 { FLM_ORIGINALD, N_("Without LPEs"), "originald" },
27 { FLM_BSPLINESPIRO, N_("With Spiro or BSpline"), "bsplinespiro" },
28 { FLM_D, N_("With all LPEs"), "d" }
29};
31
33 : Effect(lpeobject)
34 , linked_paths(_("Linked path:"), _("Paths from which to take the original path data"), "linkedpaths", &wr, this)
35 , method(_("LPEs:"), _("Which LPEs of the linked paths should be considered"), "method", FLMConverter, &wr, this, FLM_BSPLINESPIRO)
36 , join(_("Join subpaths"), _("Join subpaths"), "join", &wr, this, true)
37 , close(_("Close"), _("Close path"), "close", &wr, this, true)
38 , autoreverse(_("Autoreverse"), _("Autoreverse"), "autoreverse", &wr, this, true)
39{
47}
48
50
51void
53{
54 lpeversion.param_setValue("1.2", true);
55}
56
57bool
59{
60 if (!is_load || is_applied) {
61 return false;
62 }
63
67 std::vector<SPLPEItem *> lpeitems = getCurrrentLPEItems();
68 if (lpeitems.size() == 1) {
69 sp_lpe_item = lpeitems[0];
71 }
72 return false;
73}
74
75void
77{
78 legacytest = false;
79 std::vector<SPLPEItem *> lpeitems = getCurrrentLPEItems();
80 if (lpeitems.size() == 1) {
81 sp_lpe_item = lpeitems[0];
82 }
83 if (!is_load) {
86 } else {
90 }
91 Glib::ustring version = lpeversion.param_getSVGValue();
92 if (version < "1.2") {
93 legacytest = true;
94 }
95}
96
97void
99{
100 if (is_visible && sp_lpe_item->pathEffectsEnabled() && !isOnClipboard() && !postmul.isIdentity()) {
101 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
102 Inkscape::Selection *selection = nullptr;
103 if (desktop) {
104 selection = desktop->getSelection();
105 }
106 std::vector<SPLPEItem *> lpeitems = getCurrrentLPEItems();
107 if (lpeitems.size() == 1) {
108 sp_lpe_item = lpeitems[0];
109 }
110 for (auto & iter : linked_paths._vector) {
111 SPItem *item;
112 if (iter->ref.isAttached() && (( item = cast<SPItem>(iter->ref.getObject()) )) &&
113 !iter->_pathvector.empty() && iter->visibled) {
114 if (iter->_pathvector.front().closed() && linked_paths._vector.size() > 1) {
115 continue;
116 }
117 if (item->document->isSensitive() && selection && !selection->includes(item, true) && selection->includes(sp_lpe_item, true)) {
119 item->transform *= postmul.inverse();
121 item->doWriteTransform(item->transform, nullptr, false);
122 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
123 }
124 }
125 }
126 }
127}
128
129void
131{
132 if (previous_method != method) {
133 if (method == FLM_BSPLINESPIRO) {
136 } else if(method == FLM_ORIGINALD) {
139 } else {
142 }
144 }
145 Geom::PathVector res_pathv;
146 if (!autoreverse) {
147 for (auto & iter : linked_paths._vector) {
148 SPItem *item;
149 if (iter->ref.isAttached() && (( item = cast<SPItem>(iter->ref.getObject()) )) &&
150 !iter->_pathvector.empty() && iter->visibled) {
151 for (auto linked_path : iter->_pathvector) {
152 if (iter->reversed) {
153 linked_path = linked_path.reversed();
154 }
155 linked_path *= item->getRelativeTransform(sp_lpe_item);
156 if (!res_pathv.empty() && join) {
157 if (!are_near(res_pathv.front().finalPoint(), linked_path.initialPoint(), 0.1)) {
158 res_pathv.front().appendNew<Geom::LineSegment>(linked_path.initialPoint());
159 } else {
160 linked_path.setInitial(res_pathv.front().finalPoint());
161 }
162 res_pathv.front().append(linked_path);
163 } else {
164 if (close && !join) {
165 linked_path.close();
166 }
167 res_pathv.push_back(linked_path);
168 }
169 }
170 }
171 }
172 } else {
173 unsigned int counter = 0;
175 counter = 0;
176 std::vector<unsigned int> done;
177 for (auto & iter : linked_paths._vector) {
178 SPItem *item;
179 if (iter->ref.isAttached() && (( item = cast<SPItem>(iter->ref.getObject()) )) &&
180 !iter->_pathvector.empty() && iter->visibled) {
181 Geom::Path linked_path;
182 if (iter->_pathvector.front().closed() && linked_paths._vector.size() > 1) {
183 counter++;
184 continue;
185 }
186 if (counter == 0) {
187 Geom::Path initial_path = iter->_pathvector.front();
188 if (!legacytest && iter->reversed) {
189 initial_path = initial_path.reversed();
190 }
191 done.push_back(0);
192 if (close && !join) {
193 initial_path.close();
194 }
195 initial_path *= item->getRelativeTransform(sp_lpe_item);
196 res_pathv.push_back(initial_path);
197 current = res_pathv.front().finalPoint();
198 }
200 unsigned int counter2 = 0;
201 unsigned int added = 0;
202 PathAndDirectionAndVisible *nearest = nullptr;
203 for (auto & iter2 : linked_paths._vector) {
204 SPItem *item2;
205 if (iter2->ref.isAttached() && (( item2 = cast<SPItem>(iter2->ref.getObject()) )) &&
206 !iter2->_pathvector.empty() && iter2->visibled) {
207 if (item == item2 || std::find(done.begin(), done.end(), counter2) != done.end()) {
208 counter2++;
209 continue;
210 }
211 if (iter2->_pathvector.front().closed() && linked_paths._vector.size() > 1) {
212 counter2++;
213 continue;
214 }
215 Geom::Point start = iter2->_pathvector.front().initialPoint();
216 Geom::Point end = iter2->_pathvector.front().finalPoint();
217 if (!legacytest && iter2->reversed) {
218 std::swap(start,end);
219 }
220 if (!legacytest) {
221 current = res_pathv.finalPoint();
222 }
223 Geom::Coord distance_iter =
225 if (distance > distance_iter) {
226 distance = distance_iter;
227 nearest = iter2;
228 added = counter2;
229 }
230 counter2++;
231 }
232 }
233 if (nearest != nullptr) {
234 done.push_back(added);
237 if (!legacytest && nearest->reversed) {
238 linked_path = iter->_pathvector.front().reversed();
239 std::swap(start,end);
240 } else {
241 linked_path = iter->_pathvector.front();
242 }
244 linked_path = nearest->_pathvector.front();
245 } else {
246 linked_path = nearest->_pathvector.front().reversed();
247 }
248
249 if (legacytest) {
250 current = end;
251 }
252 SPItem *itemnear;
253 if (nearest->ref.isAttached() && (( itemnear = cast<SPItem>(nearest->ref.getObject()) ))) {
254 linked_path *= itemnear->getRelativeTransform(sp_lpe_item);
255 }
256 if (!res_pathv.empty() && join) {
257 if (!getSPDoc()->getRoot()->inkscape.getVersion().isInsideRangeInclusive({0, 1}, {1, 1}) &&
258 Geom::distance(res_pathv.front().finalPoint(), linked_path.initialPoint()) >
259 Geom::distance(res_pathv.front().finalPoint(), linked_path.finalPoint())) {
260 linked_path = linked_path.reversed();
261 }
262 if (!are_near(res_pathv.front().finalPoint(), linked_path.initialPoint(), 0.1)) {
263 res_pathv.front().appendNew<Geom::LineSegment>(linked_path.initialPoint());
264 } else {
265 linked_path.setInitial(res_pathv.front().finalPoint());
266 }
267 res_pathv.front().append(linked_path);
268 } else {
269 if (close && !join) {
270 linked_path.close();
271 }
272 res_pathv.push_back(linked_path);
273 }
274 }
275 counter++;
276 }
277 }
278 }
279 if (!res_pathv.empty() && close) {
280 res_pathv.front().close();
281 res_pathv.front().snapEnds(0.1);
282 }
283 if (res_pathv.empty()) {
284 res_pathv = curve->get_pathvector();
285 }
286 curve->set_pathvector(res_pathv);
287}
288
289} // namespace LivePathEffect
290} /* namespace Inkscape */
291
292/*
293 Local Variables:
294 mode:c++
295 c-file-style:"stroustrup"
296 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
297 indent-tabs-mode:nil
298 fill-column:99
299 End:
300*/
301// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
3x3 matrix representing an affine transformation.
Definition affine.h:70
bool isIdentity(Coord eps=EPSILON) const
Check whether this matrix is an identity matrix.
Definition affine.cpp:109
Affine inverse() const
Compute the inverse matrix.
Definition affine.cpp:388
void setInitial(Point const &v) override
Change the starting point of the curve.
Sequence of subpaths.
Definition pathvector.h:122
void push_back(Path const &path)
Append a path at the end.
Definition pathvector.h:172
Point finalPoint() const
Get the last point in the last path of the vector.
Definition pathvector.h:222
bool empty() const
Check whether the vector contains any paths.
Definition pathvector.h:145
Sequence of contiguous curves, aka spline.
Definition path.h:353
Point finalPoint() const
Get the last point in the path.
Definition path.h:709
void close(bool closed=true)
Set whether the path is closed.
Definition path.cpp:322
void append(Curve *curve)
Add a new curve to the end of the path.
Definition path.h:750
Point initialPoint() const
Get the first point in the path.
Definition path.h:705
Curve const & front() const
Access the first curve in the path.
Definition path.h:443
Path reversed() const
Obtain a reversed version of the current path.
Definition path.cpp:866
void snapEnds(Coord precision=EPSILON)
Reduce the closing segment to a point if it's shorter than precision.
Definition path.cpp:969
void setInitial(Point const &p)
Definition path.h:734
void appendNew(Args &&... args)
Append a new curve to the path.
Definition path.h:804
Two-dimensional point that doubles as a vector.
Definition point.h:66
void registerParameter(Parameter *param)
Definition effect.cpp:1710
bool isOnClipboard()
The lpe is on clipboard.
Definition effect.cpp:1248
std::vector< SPLPEItem * > getCurrrentLPEItems() const
Definition effect.cpp:1187
void param_setValue(Glib::ustring newvalue, bool write=false)
Definition hidden.cpp:71
Glib::ustring param_getSVGValue() const override
Definition hidden.cpp:53
void doBeforeEffect(SPLPEItem const *lpeitem) override
Is performed each time before the effect is updated.
void doOnApply(SPLPEItem const *lpeitem) override
Is performed a single time when the effect is freshly applied to a path.
bool doOnOpen(SPLPEItem const *lpeitem) override
Is performed on load document or revert If the item is fixed legacy return true.
void transform_multiply_nested(Geom::Affine const &postmul)
LPEFillBetweenMany(LivePathEffectObject *lpeobject)
void setUpdating(bool updating)
Definition parameter.h:73
void allowOnlyBsplineSpiro(bool allow_only_bspline_spiro)
Definition patharray.h:78
std::vector< PathAndDirectionAndVisible * > _vector
Definition patharray.h:79
void setFromOriginalD(bool from_original_d)
Definition patharray.h:77
The set of selected SPObjects for a given document and layer model.
Definition selection.h:80
bool includes(XML::Node *repr, bool anyAncestor=false)
Returns true if the given item is selected.
Definition selection.h:140
SPObject * getObject() const
Returns a pointer to the current referrent of the attached URI, or NULL.
bool isAttached() const
Returns true if there is currently an attached URI.
Simplified management of enumerations of svg items with UI labels.
Definition enums.h:42
Wrapper around a Geom::PathVector object.
Definition curve.h:26
To do: update description of desktop.
Definition desktop.h:149
Inkscape::Selection * getSelection() const
Definition desktop.h:188
SPRoot * getRoot()
Returns our SPRoot.
Definition document.h:202
bool isSensitive() const
Definition document.h:365
Base class for visual SVG elements.
Definition sp-item.h:109
Geom::Affine transform
Definition sp-item.h:138
Geom::Affine getRelativeTransform(SPObject const *obj) const
Definition sp-item.cpp:1812
void doWriteTransform(Geom::Affine const &transform, Geom::Affine const *adv=nullptr, bool compensate=true)
Set a new transform on an object.
Definition sp-item.cpp:1658
bool pathEffectsEnabled() const
SPDocument * document
Definition sp-object.h:188
SPObject * parent
Definition sp-object.h:189
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
static char const *const current
Definition dir-util.cpp:71
constexpr Coord infinity()
Get a value representing infinity.
Definition coord.h:88
double Coord
Floating point type used to store coordinates.
Definition coord.h:76
SPItem * item
Geom::Point start
Geom::Point end
Angle distance(Angle const &a, Angle const &b)
Definition angle.h:163
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
static const Util::EnumData< Filllpemethod > FilllpemethodData[]
static const Util::EnumDataConverter< Filllpemethod > FLMConverter(FilllpemethodData, FLM_END)
Helper class to stream background task notifications as a series of messages.
static Glib::ustring join(std::vector< Glib::ustring > const &accels, char const separator)
static gint counter
Definition box3d.cpp:39
Geom::Affine i2anc_affine(SPObject const *object, SPObject const *ancestor)
Definition sp-item.cpp:1787
SPRoot: SVG <svg> implementation.
Simplified management of enumerations of svg items with UI labels.
Definition enums.h:27
Definition curve.h:24
SPDesktop * desktop