Merge lp:~inkscape.dev/inkscape/rotatecopies_improvements into lp:~inkscape.dev/inkscape/trunk
- rotatecopies_improvements
- Merge into trunk
Proposed by
Jabiertxof
Status: | Merged |
---|---|
Merged at revision: | 15436 |
Proposed branch: | lp:~inkscape.dev/inkscape/rotatecopies_improvements |
Merge into: | lp:~inkscape.dev/inkscape/trunk |
Diff against target: |
1185 lines (+508/-120) 16 files modified
src/2geom/intersection-graph.cpp (+3/-3) src/helper/geom.cpp (+7/-0) src/helper/geom.h (+1/-1) src/live_effects/effect.cpp (+84/-8) src/live_effects/effect.h (+15/-5) src/live_effects/lpe-copy_rotate.cpp (+296/-10) src/live_effects/lpe-copy_rotate.h (+14/-0) src/live_effects/lpe-measure-line.cpp (+7/-59) src/live_effects/lpe-measure-line.h (+0/-8) src/live_effects/parameter/bool.cpp (+2/-1) src/live_effects/parameter/text.cpp (+2/-1) src/sp-item-group.cpp (+31/-12) src/sp-lpe-item.cpp (+25/-10) src/sp-lpe-item.h (+3/-2) src/sp-object.cpp (+15/-0) src/sp-object.h (+3/-0) |
To merge this branch: | bzr merge lp:~inkscape.dev/inkscape/rotatecopies_improvements |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Martin Owens | Needs Fixing | ||
Review via email: mp+315306@code.launchpad.net |
Commit message
Description of the change
With this improvements you can separate each piece of a fused to add own styles, for example rotating with gradients, adding diferent styles to each pieze....
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/2geom/intersection-graph.cpp' |
2 | --- src/2geom/intersection-graph.cpp 2016-02-08 07:32:51 +0000 |
3 | +++ src/2geom/intersection-graph.cpp 2017-01-24 07:18:19 +0000 |
4 | @@ -410,10 +410,10 @@ |
5 | assert(!result.back().empty()); |
6 | } |
7 | |
8 | - /*if (n_processed != size() * 2) { |
9 | + if (n_processed != size() * 2) { |
10 | std::cerr << "Processed " << n_processed << " intersections, expected " << (size() * 2) << std::endl; |
11 | - }*/ |
12 | - assert(n_processed == size() * 2); |
13 | + } |
14 | + //assert(n_processed == size() * 2); |
15 | |
16 | return result; |
17 | } |
18 | |
19 | === modified file 'src/helper/geom.cpp' |
20 | --- src/helper/geom.cpp 2016-08-03 13:29:38 +0000 |
21 | +++ src/helper/geom.cpp 2017-01-24 07:18:19 +0000 |
22 | @@ -843,6 +843,13 @@ |
23 | recursive_bezier4(x1234, y1234, x234, y234, x34, y34, x4, y4, m_points, level + 1); |
24 | } |
25 | |
26 | +void |
27 | +swap(Geom::Point &A, Geom::Point &B){ |
28 | + Geom::Point tmp = A; |
29 | + A = B; |
30 | + B = tmp; |
31 | +} |
32 | + |
33 | /* |
34 | Local Variables: |
35 | mode:c++ |
36 | |
37 | === modified file 'src/helper/geom.h' |
38 | --- src/helper/geom.h 2015-05-08 15:40:38 +0000 |
39 | +++ src/helper/geom.h 2017-01-24 07:18:19 +0000 |
40 | @@ -32,7 +32,7 @@ |
41 | const double x3, const double y3, const double x4, const double y4, |
42 | std::vector<Geom::Point> &pointlist, |
43 | int level); |
44 | - |
45 | +void swap(Geom::Point &A, Geom::Point &B); |
46 | #endif // INKSCAPE_HELPER_GEOM_H |
47 | |
48 | /* |
49 | |
50 | === modified file 'src/live_effects/effect.cpp' |
51 | --- src/live_effects/effect.cpp 2016-12-19 20:54:42 +0000 |
52 | +++ src/live_effects/effect.cpp 2017-01-24 07:18:19 +0000 |
53 | @@ -70,6 +70,8 @@ |
54 | #include "ui/tools/node-tool.h" |
55 | #include "ui/tools-switch.h" |
56 | #include "knotholder.h" |
57 | +#include "path-chemistry.h" |
58 | +#include "xml/sp-css-attr.h" |
59 | #include "live_effects/lpeobject.h" |
60 | #include "display/curve.h" |
61 | |
62 | @@ -356,6 +358,7 @@ |
63 | sp_lpe_item(NULL), |
64 | current_zoom(1), |
65 | upd_params(true), |
66 | + sp_shape(NULL), |
67 | sp_curve(NULL), |
68 | provides_own_flash_paths(true), // is automatically set to false if providesOwnFlashPaths() is not overridden |
69 | is_ready(false) // is automatically set to false if providesOwnFlashPaths() is not overridden |
70 | @@ -392,17 +395,17 @@ |
71 | } |
72 | |
73 | void |
74 | +Effect::setCurrentZoom(double cZ) |
75 | +{ |
76 | + current_zoom = cZ; |
77 | +} |
78 | + |
79 | +void |
80 | Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP) |
81 | { |
82 | selectedNodesPoints = sNP; |
83 | } |
84 | |
85 | -void |
86 | -Effect::setCurrentZoom(double cZ) |
87 | -{ |
88 | - current_zoom = cZ; |
89 | -} |
90 | - |
91 | bool |
92 | Effect::isNodePointSelected(Geom::Point const &nodePoint) const |
93 | { |
94 | @@ -423,6 +426,74 @@ |
95 | return false; |
96 | } |
97 | |
98 | +void |
99 | +Effect::processObjects(LpeAction lpe_action) |
100 | +{ |
101 | + SPDocument * document = SP_ACTIVE_DOCUMENT; |
102 | + for (std::vector<const char *>::iterator el_it = items.begin(); |
103 | + el_it != items.end(); ++el_it) { |
104 | + const char * id = *el_it; |
105 | + if (!id || strlen(id) == 0) { |
106 | + return; |
107 | + } |
108 | + SPObject *elemref = NULL; |
109 | + if (elemref = document->getObjectById(id)) { |
110 | + Inkscape::XML::Node * elemnode = elemref->getRepr(); |
111 | + std::vector<SPItem*> item_list; |
112 | + item_list.push_back(SP_ITEM(elemref)); |
113 | + std::vector<Inkscape::XML::Node*> item_to_select; |
114 | + std::vector<SPItem*> item_selected; |
115 | + SPCSSAttr *css; |
116 | + Glib::ustring css_str; |
117 | + switch (lpe_action){ |
118 | + case LPE_TO_OBJECTS: |
119 | + if (SP_ITEM(elemref)->isHidden()) { |
120 | + elemref->deleteObject(); |
121 | + } else { |
122 | + if (elemnode->attribute("inkscape:path-effect")) { |
123 | + sp_item_list_to_curves(item_list, item_selected, item_to_select); |
124 | + } |
125 | + elemnode->setAttribute("sodipodi:insensitive", NULL); |
126 | + } |
127 | + break; |
128 | + |
129 | + case LPE_ERASE: |
130 | + elemref->deleteObject(); |
131 | + break; |
132 | + |
133 | + case LPE_VISIBILITY: |
134 | + css = sp_repr_css_attr_new(); |
135 | + sp_repr_css_attr_add_from_string(css, elemref->getRepr()->attribute("style")); |
136 | + if (!this->isVisible()/* && std::strcmp(elemref->getId(),sp_lpe_item->getId()) != 0*/) { |
137 | + css->setAttribute("display", "none"); |
138 | + } else { |
139 | + css->setAttribute("display", NULL); |
140 | + } |
141 | + sp_repr_css_write_string(css,css_str); |
142 | + elemnode->setAttribute("style", css_str.c_str()); |
143 | + break; |
144 | + |
145 | + default: |
146 | + break; |
147 | + } |
148 | + } |
149 | + } |
150 | + if (lpe_action == LPE_ERASE || lpe_action == LPE_TO_OBJECTS) { |
151 | + items.clear(); |
152 | + } |
153 | +} |
154 | + |
155 | +void Effect::setCurrentShape(SPShape * shape){ |
156 | + if(shape){ |
157 | + sp_shape = shape; |
158 | + if (!(sp_curve = sp_shape->getCurve())) { |
159 | + // oops |
160 | + return; |
161 | + } |
162 | + pathvector_before_effect = sp_curve->get_pathvector(); |
163 | + } |
164 | +} |
165 | + |
166 | /** |
167 | * Is performed each time before the effect is updated. |
168 | */ |
169 | @@ -446,8 +517,12 @@ |
170 | void Effect::doOnApply_impl(SPLPEItem const* lpeitem) |
171 | { |
172 | sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); |
173 | - /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); |
174 | - pathvector_before_effect = sp_curve->get_pathvector();*/ |
175 | + sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); |
176 | + pathvector_before_effect = sp_curve->get_pathvector(); |
177 | + SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); |
178 | + if(shape){ |
179 | + setCurrentShape(shape); |
180 | + } |
181 | doOnApply(lpeitem); |
182 | } |
183 | |
184 | @@ -457,6 +532,7 @@ |
185 | //printf("(SPLPEITEM*) %p\n", sp_lpe_item); |
186 | SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); |
187 | if(shape){ |
188 | + setCurrentShape(shape); |
189 | sp_curve = shape->getCurve(); |
190 | pathvector_before_effect = sp_curve->get_pathvector(); |
191 | } |
192 | |
193 | === modified file 'src/live_effects/effect.h' |
194 | --- src/live_effects/effect.h 2016-12-19 20:54:42 +0000 |
195 | +++ src/live_effects/effect.h 2017-01-24 07:18:19 +0000 |
196 | @@ -19,7 +19,7 @@ |
197 | class SPDocument; |
198 | class SPDesktop; |
199 | class SPItem; |
200 | -class LivePathEffectObject; |
201 | +class LivePathEffectObject; |
202 | class SPLPEItem; |
203 | class KnotHolder; |
204 | class KnotHolderEntity; |
205 | @@ -44,6 +44,12 @@ |
206 | DEFAULT |
207 | }; |
208 | |
209 | +enum LpeAction { |
210 | + LPE_ERASE = 0, |
211 | + LPE_TO_OBJECTS, |
212 | + LPE_VISIBILITY |
213 | +}; |
214 | + |
215 | class Effect { |
216 | public: |
217 | static Effect* New(EffectType lpenr, LivePathEffectObject *lpeobj); |
218 | @@ -73,6 +79,9 @@ |
219 | static int acceptsNumClicks(EffectType type); |
220 | int acceptsNumClicks() const { return acceptsNumClicks(effectType()); } |
221 | void doAcceptPathPreparations(SPLPEItem *lpeitem); |
222 | + SPShape * getCurrentShape(){ return sp_shape; }; |
223 | + void setCurrentShape(SPShape * shape); |
224 | + void processObjects(LpeAction lpe_action); |
225 | |
226 | /* |
227 | * isReady() indicates whether all preparations which are necessary to apply the LPE are done, |
228 | @@ -125,7 +134,9 @@ |
229 | bool apply_to_clippath_and_mask; |
230 | bool erase_extra_objects; // set this to false allow retain extra generated objects, see measure line LPE |
231 | bool upd_params; |
232 | - |
233 | + BoolParam is_visible; |
234 | + SPCurve * sp_curve; |
235 | + Geom::PathVector pathvector_before_effect; |
236 | protected: |
237 | Effect(LivePathEffectObject *lpeobject); |
238 | |
239 | @@ -150,7 +161,6 @@ |
240 | bool _provides_knotholder_entities; |
241 | |
242 | int oncanvasedit_it; |
243 | - BoolParam is_visible; |
244 | |
245 | bool show_orig_path; // set this to true in derived effects to automatically have the original |
246 | // path displayed as helperpath |
247 | @@ -164,10 +174,10 @@ |
248 | bool concatenate_before_pwd2; |
249 | |
250 | SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them. |
251 | + SPShape * sp_shape; // these get stored in doBeforeEffect_impl before doEffect chain, or in performPathEffects on groups, and derived classes may do as they please with them. |
252 | + std::vector<const char *> items; |
253 | double current_zoom; |
254 | std::vector<Geom::Point> selectedNodesPoints; |
255 | - SPCurve * sp_curve; |
256 | - Geom::PathVector pathvector_before_effect; |
257 | private: |
258 | bool provides_own_flash_paths; // if true, the standard flash path is suppressed |
259 | |
260 | |
261 | === modified file 'src/live_effects/lpe-copy_rotate.cpp' |
262 | --- src/live_effects/lpe-copy_rotate.cpp 2017-01-01 03:08:02 +0000 |
263 | +++ src/live_effects/lpe-copy_rotate.cpp 2017-01-24 07:18:19 +0000 |
264 | @@ -17,6 +17,13 @@ |
265 | #include <2geom/sbasis-to-bezier.h> |
266 | #include <2geom/intersection-graph.h> |
267 | #include "live_effects/lpe-copy_rotate.h" |
268 | +#include "display/curve.h" |
269 | +#include "svg/path-string.h" |
270 | +#include "svg/svg.h" |
271 | +#include "style.h" |
272 | +#include "helper/geom.h" |
273 | +#include "xml/sp-css-attr.h" |
274 | +#include "path-chemistry.h" |
275 | // TODO due to internal breakage in glibmm headers, this must be last: |
276 | #include <glibmm/i18n.h> |
277 | |
278 | @@ -45,9 +52,11 @@ |
279 | starting_angle(_("Starting angle"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0), |
280 | rotation_angle(_("Rotation angle"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 60.0), |
281 | num_copies(_("Number of copies"), _("Number of copies of the original path"), "num_copies", &wr, this, 6), |
282 | + split_gap(_("Gap on split"), _("Gap on split"), "split_gap", &wr, this, -0.001), |
283 | copies_to_360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copies_to_360", &wr, this, true), |
284 | fuse_paths(_("Kaleidoskope"), _("Kaleidoskope by helper line, use fill-rule: evenodd for best result"), "fuse_paths", &wr, this, false), |
285 | join_paths(_("Join paths"), _("Join paths, use fill-rule: evenodd for best result"), "join_paths", &wr, this, false), |
286 | + split_items(_("Split elements"), _("Split elements, this allow gradients and other paints."), "split_items", &wr, this, false), |
287 | dist_angle_handle(100.0) |
288 | { |
289 | show_orig_path = true; |
290 | @@ -56,15 +65,21 @@ |
291 | registerParameter(&copies_to_360); |
292 | registerParameter(&fuse_paths); |
293 | registerParameter(&join_paths); |
294 | + registerParameter(&split_items); |
295 | registerParameter(&starting_angle); |
296 | registerParameter(&starting_point); |
297 | registerParameter(&rotation_angle); |
298 | registerParameter(&num_copies); |
299 | + registerParameter(&split_gap); |
300 | registerParameter(&origin); |
301 | - |
302 | + split_gap.param_set_range(-999999.0, 999999.0); |
303 | + split_gap.param_set_increments(0.1, 0.1); |
304 | + split_gap.param_set_digits(5); |
305 | + num_copies.param_set_range(0, 999999); |
306 | num_copies.param_make_integer(true); |
307 | - num_copies.param_set_range(0, 1000); |
308 | apply_to_clippath_and_mask = true; |
309 | + previous_num_copies = num_copies; |
310 | + reset = false; |
311 | } |
312 | |
313 | LPECopyRotate::~LPECopyRotate() |
314 | @@ -72,6 +87,207 @@ |
315 | |
316 | } |
317 | |
318 | +void |
319 | +LPECopyRotate::doAfterEffect (SPLPEItem const* lpeitem) |
320 | +{ |
321 | + if (split_items) { |
322 | + SPDocument * document = SP_ACTIVE_DOCUMENT; |
323 | + items.clear(); |
324 | + container = dynamic_cast<SPObject *>(sp_lpe_item->parent); |
325 | + SPDocument * doc = SP_ACTIVE_DOCUMENT; |
326 | + Inkscape::XML::Node *root = sp_lpe_item->document->getReprRoot(); |
327 | + Inkscape::XML::Node *root_origin = doc->getReprRoot(); |
328 | + if (root_origin != root) { |
329 | + return; |
330 | + } |
331 | + if (previous_num_copies != num_copies) { |
332 | + gint numcopies_gap = previous_num_copies - num_copies; |
333 | + if (numcopies_gap > 0 && num_copies != 0) { |
334 | + guint counter = num_copies - 1; |
335 | + while (numcopies_gap > 0) { |
336 | + const char * id = g_strdup(Glib::ustring("rotated-").append(std::to_string(counter)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); |
337 | + if (!id || strlen(id) == 0) { |
338 | + return; |
339 | + } |
340 | + SPObject *elemref = NULL; |
341 | + if (elemref = document->getObjectById(id)) { |
342 | + SP_ITEM(elemref)->setHidden(true); |
343 | + } |
344 | + counter++; |
345 | + numcopies_gap--; |
346 | + } |
347 | + } |
348 | + previous_num_copies = num_copies; |
349 | + } |
350 | + SPObject *elemref = NULL; |
351 | + char * id = g_strdup(Glib::ustring("rotated-").append("1").append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); |
352 | + guint counter = 0; |
353 | + while(elemref = document->getObjectById(id)) { |
354 | + if (SP_ITEM(elemref)->isHidden()) { |
355 | + items.push_back(id); |
356 | + } |
357 | + id = g_strdup(Glib::ustring("rotated-").append(std::to_string(counter)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); |
358 | + counter++; |
359 | + } |
360 | + g_free(id); |
361 | + double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max())); |
362 | + Geom::Rect bbox(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max())); |
363 | + double size_divider = Geom::distance(origin,bbox) + (diagonal * 2); |
364 | + Geom::Point line_start = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))) * size_divider; |
365 | + Geom::Point line_end = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(rotation_angle + starting_angle))) * size_divider; |
366 | + Geom::Affine m = Geom::Translate(-origin) * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))); |
367 | + if (fuse_paths) { |
368 | + size_t rest = 0; |
369 | + for (size_t i = 1; i < num_copies; ++i) { |
370 | + Geom::Affine r = Geom::identity(); |
371 | + Geom::Point dir = unit_vector((Geom::Point)origin - Geom::middle_point(line_start,line_end)); |
372 | + if( rest%2 == 0) { |
373 | + r *= Geom::Rotate(Geom::Angle(dir)).inverse(); |
374 | + r *= Geom::Scale(1, -1); |
375 | + r *= Geom::Rotate(Geom::Angle(dir)); |
376 | + } |
377 | + Geom::Rotate rot(-(Geom::rad_from_deg(rotation_angle * i))); |
378 | + Geom::Affine t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin); |
379 | + if( rest%2 == 0) { |
380 | + t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)).inverse() * Geom::Translate(origin); |
381 | + } |
382 | + t *= sp_lpe_item->transform; |
383 | + toItem(t, i-1, reset); |
384 | + rest ++; |
385 | + } |
386 | + } else { |
387 | + for (size_t i = 1; i < num_copies; ++i) { |
388 | + Geom::Rotate rot(-(Geom::rad_from_deg(rotation_angle * i))); |
389 | + Geom::Affine t = m * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin); |
390 | + t *= sp_lpe_item->transform; |
391 | + toItem(t, i - 1, reset); |
392 | + } |
393 | + } |
394 | + reset = false; |
395 | + } else { |
396 | + processObjects(LPE_ERASE); |
397 | + items.clear(); |
398 | + } |
399 | + |
400 | + std::cout << previous_num_copies << "previous_num_copies\n"; |
401 | + std::cout << num_copies << "num_copies\n"; |
402 | +} |
403 | + |
404 | +void |
405 | +LPECopyRotate::cloneD(SPObject *origin, SPObject *dest, bool root, bool reset) |
406 | +{ |
407 | + SPDocument * document = SP_ACTIVE_DOCUMENT; |
408 | + Inkscape::XML::Document *xml_doc = document->getReprDoc(); |
409 | + if ( SP_IS_GROUP(origin) && SP_IS_GROUP(dest) && SP_GROUP(origin)->getItemCount() == SP_GROUP(dest)->getItemCount() ) { |
410 | + std::vector< SPObject * > childs = origin->childList(true); |
411 | + size_t index = 0; |
412 | + for (std::vector<SPObject * >::iterator obj_it = childs.begin(); |
413 | + obj_it != childs.end(); ++obj_it) { |
414 | + SPObject *dest_child = dest->nthChild(index); |
415 | + cloneD(*obj_it, dest_child, false, reset); |
416 | + index++; |
417 | + } |
418 | + } |
419 | + SPShape * shape = SP_SHAPE(origin); |
420 | + SPPath * path = SP_PATH(dest); |
421 | + if (!path && !SP_IS_GROUP(dest)) { |
422 | + Inkscape::XML::Node *dest_node = sp_selected_item_to_curved_repr(SP_ITEM(dest), 0); |
423 | + dest->updateRepr(xml_doc, dest_node, SP_OBJECT_WRITE_ALL); |
424 | + path = SP_PATH(dest); |
425 | + } |
426 | + if (path && shape) { |
427 | + SPCurve *c = NULL; |
428 | + if (root) { |
429 | + c = new SPCurve(); |
430 | + c->set_pathvector(pathvector_before_effect); |
431 | + } else { |
432 | + c = shape->getCurve(); |
433 | + } |
434 | + if (c) { |
435 | + path->setCurve(c, TRUE); |
436 | + c->unref(); |
437 | + } else { |
438 | + dest->getRepr()->setAttribute("d", NULL); |
439 | + } |
440 | + if (reset) { |
441 | + dest->getRepr()->setAttribute("style", shape->getRepr()->attribute("style")); |
442 | + } |
443 | + } |
444 | +} |
445 | + |
446 | +void |
447 | +LPECopyRotate::toItem(Geom::Affine transform, size_t i, bool reset) |
448 | +{ |
449 | + SPDocument * document = SP_ACTIVE_DOCUMENT; |
450 | + Inkscape::XML::Document *xml_doc = document->getReprDoc(); |
451 | + const char * elemref_id = g_strdup(Glib::ustring("rotated-").append(std::to_string(i)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); |
452 | + items.push_back(elemref_id); |
453 | + SPObject *elemref= NULL; |
454 | + Inkscape::XML::Node *phantom = NULL; |
455 | + if (elemref = document->getObjectById(elemref_id)) { |
456 | + phantom = elemref->getRepr(); |
457 | + } else { |
458 | + phantom = sp_lpe_item->getRepr()->duplicate(xml_doc); |
459 | + std::vector<const char *> attrs; |
460 | + attrs.push_back("inkscape:path-effect"); |
461 | + attrs.push_back("inkscape:original-d"); |
462 | + attrs.push_back("sodipodi:type"); |
463 | + attrs.push_back("sodipodi:rx"); |
464 | + attrs.push_back("sodipodi:ry"); |
465 | + attrs.push_back("sodipodi:cx"); |
466 | + attrs.push_back("sodipodi:cy"); |
467 | + attrs.push_back("sodipodi:end"); |
468 | + attrs.push_back("sodipodi:start"); |
469 | + attrs.push_back("inkscape:flatsided"); |
470 | + attrs.push_back("inkscape:randomized"); |
471 | + attrs.push_back("inkscape:rounded"); |
472 | + attrs.push_back("sodipodi:arg1"); |
473 | + attrs.push_back("sodipodi:arg2"); |
474 | + attrs.push_back("sodipodi:r1"); |
475 | + attrs.push_back("sodipodi:r2"); |
476 | + attrs.push_back("sodipodi:sides"); |
477 | + attrs.push_back("inkscape:randomized"); |
478 | + attrs.push_back("sodipodi:argument"); |
479 | + attrs.push_back("sodipodi:expansion"); |
480 | + attrs.push_back("sodipodi:radius"); |
481 | + attrs.push_back("sodipodi:revolution"); |
482 | + attrs.push_back("sodipodi:t0"); |
483 | + attrs.push_back("inkscape:randomized"); |
484 | + attrs.push_back("inkscape:randomized"); |
485 | + attrs.push_back("inkscape:randomized"); |
486 | + attrs.push_back("x"); |
487 | + attrs.push_back("y"); |
488 | + attrs.push_back("rx"); |
489 | + attrs.push_back("ry"); |
490 | + attrs.push_back("width"); |
491 | + attrs.push_back("height"); |
492 | + phantom->setAttribute("id", elemref_id); |
493 | + for(const char * attr : attrs) { |
494 | + phantom->setAttribute(attr, NULL); |
495 | + } |
496 | + } |
497 | + if (!elemref) { |
498 | + elemref = container->appendChildRepr(phantom); |
499 | + Inkscape::GC::release(phantom); |
500 | + } |
501 | + cloneD(SP_OBJECT(sp_lpe_item), elemref, true, reset); |
502 | + elemref->getRepr()->setAttribute("transform" , sp_svg_transform_write(transform)); |
503 | + SP_ITEM(elemref)->setHidden(false); |
504 | + if (elemref->parent != container) { |
505 | + Inkscape::XML::Node *copy = phantom->duplicate(xml_doc); |
506 | + copy->setAttribute("id", elemref_id); |
507 | + container->appendChildRepr(copy); |
508 | + Inkscape::GC::release(copy); |
509 | + elemref->deleteObject(); |
510 | + } |
511 | +} |
512 | + |
513 | +void |
514 | +LPECopyRotate::resetStyles(){ |
515 | + reset = true; |
516 | + doAfterEffect(sp_lpe_item); |
517 | +} |
518 | + |
519 | Gtk::Widget * LPECopyRotate::newWidget() |
520 | { |
521 | // use manage here, because after deletion of Effect object, others might |
522 | @@ -81,7 +297,15 @@ |
523 | vbox->set_border_width(5); |
524 | vbox->set_homogeneous(false); |
525 | vbox->set_spacing(2); |
526 | - |
527 | + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0)); |
528 | + Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); |
529 | + vbox_expander->set_border_width(0); |
530 | + vbox_expander->set_spacing(2); |
531 | + Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset styles")))); |
532 | + reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPECopyRotate::resetStyles)); |
533 | + reset_button->set_size_request(140,30); |
534 | + vbox->pack_start(*hbox, true,true,2); |
535 | + hbox->pack_start(*reset_button, false, false,2); |
536 | std::vector<Parameter *>::iterator it = param_vector.begin(); |
537 | while (it != param_vector.end()) { |
538 | if ((*it)->widget_is_visible) { |
539 | @@ -125,11 +349,11 @@ |
540 | LPECopyRotate::transform_multiply(Geom::Affine const& postmul, bool set) |
541 | { |
542 | // cycle through all parameters. Most parameters will not need transformation, but path and point params do. |
543 | - |
544 | for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); ++it) { |
545 | Parameter * param = *it; |
546 | param->param_transform_multiply(postmul, set); |
547 | } |
548 | + sp_lpe_item_update_patheffect(sp_lpe_item, false, false); |
549 | } |
550 | |
551 | void |
552 | @@ -140,17 +364,17 @@ |
553 | if (copies_to_360) { |
554 | rotation_angle.param_set_value(360.0/(double)num_copies); |
555 | } |
556 | - if (fuse_paths && rotation_angle * num_copies > 360 && rotation_angle > 0) { |
557 | + if (fuse_paths && rotation_angle * num_copies > 360.1 && rotation_angle > 0) { |
558 | num_copies.param_set_value(floor(360/rotation_angle)); |
559 | } |
560 | if (fuse_paths && copies_to_360) { |
561 | - num_copies.param_set_increments(2,2); |
562 | + num_copies.param_set_increments(2.0,10.0); |
563 | if ((int)num_copies%2 !=0) { |
564 | num_copies.param_set_value(num_copies+1); |
565 | rotation_angle.param_set_value(360.0/(double)num_copies); |
566 | } |
567 | } else { |
568 | - num_copies.param_set_increments(1,1); |
569 | + num_copies.param_set_increments(1.0, 10.0); |
570 | } |
571 | |
572 | if (dist_angle_handle < 1.0) { |
573 | @@ -352,12 +576,57 @@ |
574 | tmp_path.clear(); |
575 | } |
576 | |
577 | +Geom::PathVector |
578 | +LPECopyRotate::doEffect_path (Geom::PathVector const & path_in) |
579 | +{ |
580 | + Geom::PathVector path_out; |
581 | + if (split_items && (fuse_paths || join_paths)) { |
582 | + if (num_copies == 0) { |
583 | + return path_out; |
584 | + } |
585 | + path_out = pathv_to_linear_and_cubic_beziers(path_in); |
586 | + double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max())); |
587 | + Geom::OptRect bbox = sp_lpe_item->geometricBounds(); |
588 | + double size_divider = Geom::distance(origin,bbox) + (diagonal * 2); |
589 | + Geom::Point line_start = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))) * size_divider; |
590 | + Geom::Point line_end = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(rotation_angle + starting_angle))) * size_divider; |
591 | + Geom::Path divider = Geom::Path(line_start); |
592 | + divider.appendNew<Geom::LineSegment>((Geom::Point)origin); |
593 | + divider.appendNew<Geom::LineSegment>(line_end); |
594 | + divider.close(); |
595 | + Geom::PathVector triangle; |
596 | + triangle.push_back(divider); |
597 | + Geom::PathIntersectionGraph *pig = new Geom::PathIntersectionGraph(triangle, path_out); |
598 | + if (pig && ! path_out.empty() && !triangle.empty()) { |
599 | + //TODO: Here can produce a crash because some knows problems in new boolops code |
600 | + path_out = pig->getIntersection(); |
601 | + } |
602 | + Geom::Affine r = Geom::identity(); |
603 | + Geom::Point dir = unit_vector(Geom::middle_point(line_start,line_end) - (Geom::Point)origin); |
604 | + Geom::Point gap = dir * split_gap; |
605 | + r *= Geom::Translate(gap); |
606 | + path_out *= r; |
607 | + } else { |
608 | + // default behavior |
609 | + for (unsigned int i=0; i < path_in.size(); i++) { |
610 | + Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = path_in[i].toPwSb(); |
611 | + Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in); |
612 | + Geom::PathVector path = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE); |
613 | + // add the output path vector to the already accumulated vector: |
614 | + for (unsigned int j=0; j < path.size(); j++) { |
615 | + path_out.push_back(path[j]); |
616 | + } |
617 | + } |
618 | + } |
619 | + return pathv_to_linear_and_cubic_beziers(path_out); |
620 | +} |
621 | + |
622 | Geom::Piecewise<Geom::D2<Geom::SBasis> > |
623 | LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) |
624 | { |
625 | using namespace Geom; |
626 | |
627 | - if (num_copies == 1 && !fuse_paths) { |
628 | + if ((num_copies == 1 && !fuse_paths) || split_items) { |
629 | return pwd2_in; |
630 | } |
631 | |
632 | @@ -373,10 +642,10 @@ |
633 | divider.appendNew<Geom::LineSegment>(line_end); |
634 | Piecewise<D2<SBasis> > output; |
635 | Affine pre = Translate(-origin) * Rotate(-rad_from_deg(starting_angle)); |
636 | + PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001)); |
637 | if (fuse_paths) { |
638 | Geom::PathVector path_out; |
639 | Geom::PathVector tmp_path; |
640 | - PathVector const original_pathv = path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001); |
641 | for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { |
642 | if (path_it->empty()) { |
643 | continue; |
644 | @@ -403,7 +672,7 @@ |
645 | output = paths_to_pw(path_out); |
646 | } |
647 | } else { |
648 | - Geom::PathVector output_pv = path_from_piecewise(output , 0.01); |
649 | + Geom::PathVector output_pv; |
650 | for (int i = 0; i < num_copies; ++i) { |
651 | Rotate rot(-rad_from_deg(rotation_angle * i)); |
652 | Affine t = pre * rot * Translate(origin); |
653 | @@ -449,6 +718,23 @@ |
654 | original_bbox(SP_LPE_ITEM(item)); |
655 | } |
656 | |
657 | +void |
658 | +LPECopyRotate::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) |
659 | +{ |
660 | + processObjects(LPE_VISIBILITY); |
661 | +} |
662 | + |
663 | +void |
664 | +LPECopyRotate::doOnRemove (SPLPEItem const* /*lpeitem*/) |
665 | +{ |
666 | + //unset "erase_extra_objects" hook on sp-lpe-item.cpp |
667 | + if (!erase_extra_objects) { |
668 | + processObjects(LPE_TO_OBJECTS); |
669 | + return; |
670 | + } |
671 | + processObjects(LPE_ERASE); |
672 | +} |
673 | + |
674 | } //namespace LivePathEffect |
675 | } /* namespace Inkscape */ |
676 | |
677 | |
678 | === modified file 'src/live_effects/lpe-copy_rotate.h' |
679 | --- src/live_effects/lpe-copy_rotate.h 2017-01-01 03:08:02 +0000 |
680 | +++ src/live_effects/lpe-copy_rotate.h 2017-01-24 07:18:19 +0000 |
681 | @@ -15,6 +15,8 @@ |
682 | */ |
683 | |
684 | #include "live_effects/effect.h" |
685 | +#include "live_effects/parameter/parameter.h" |
686 | +#include "live_effects/parameter/text.h" |
687 | #include "live_effects/parameter/point.h" |
688 | #include "live_effects/lpegroupbbox.h" |
689 | |
690 | @@ -26,13 +28,20 @@ |
691 | LPECopyRotate(LivePathEffectObject *lpeobject); |
692 | virtual ~LPECopyRotate(); |
693 | virtual void doOnApply (SPLPEItem const* lpeitem); |
694 | + virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in); |
695 | virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in); |
696 | virtual void doBeforeEffect (SPLPEItem const* lpeitem); |
697 | + virtual void doAfterEffect (SPLPEItem const* lpeitem); |
698 | virtual void setFusion(Geom::PathVector &path_in, Geom::Path divider, double sizeDivider); |
699 | virtual void split(Geom::PathVector &path_in, Geom::Path const ÷r); |
700 | virtual void resetDefaults(SPItem const* item); |
701 | virtual void transform_multiply(Geom::Affine const& postmul, bool set); |
702 | + virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); |
703 | + virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); |
704 | virtual Gtk::Widget * newWidget(); |
705 | + void toItem(Geom::Affine transform, size_t i, bool reset); |
706 | + void cloneD(SPObject *origin, SPObject *dest, bool root, bool reset); |
707 | + void resetStyles(); |
708 | protected: |
709 | virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); |
710 | |
711 | @@ -42,9 +51,11 @@ |
712 | ScalarParam starting_angle; |
713 | ScalarParam rotation_angle; |
714 | ScalarParam num_copies; |
715 | + ScalarParam split_gap; |
716 | BoolParam copies_to_360; |
717 | BoolParam fuse_paths; |
718 | BoolParam join_paths; |
719 | + BoolParam split_items; |
720 | Geom::Point A; |
721 | Geom::Point B; |
722 | Geom::Point dir; |
723 | @@ -52,6 +63,9 @@ |
724 | Geom::Point rot_pos; |
725 | Geom::Point previous_start_point; |
726 | double dist_angle_handle; |
727 | + double previous_num_copies; |
728 | + bool reset; |
729 | + SPObject * container; |
730 | LPECopyRotate(const LPECopyRotate&); |
731 | LPECopyRotate& operator=(const LPECopyRotate&); |
732 | }; |
733 | |
734 | === modified file 'src/live_effects/lpe-measure-line.cpp' |
735 | --- src/live_effects/lpe-measure-line.cpp 2016-12-30 16:11:45 +0000 |
736 | +++ src/live_effects/lpe-measure-line.cpp 2017-01-24 07:18:19 +0000 |
737 | @@ -21,7 +21,9 @@ |
738 | #include "svg/svg-color.h" |
739 | #include "svg/svg.h" |
740 | #include "display/curve.h" |
741 | +#include "helper/geom.h" |
742 | #include "2geom/affine.h" |
743 | +#include "path-chemistry.h" |
744 | #include "style.h" |
745 | #include "sp-root.h" |
746 | #include "sp-defs.h" |
747 | @@ -165,12 +167,6 @@ |
748 | |
749 | LPEMeasureLine::~LPEMeasureLine() {} |
750 | |
751 | -void swap(Geom::Point &A, Geom::Point &B){ |
752 | - Geom::Point tmp = A; |
753 | - A = B; |
754 | - B = tmp; |
755 | -} |
756 | - |
757 | void |
758 | LPEMeasureLine::createArrowMarker(const char * mode) |
759 | { |
760 | @@ -229,7 +225,7 @@ |
761 | elemref = SP_OBJECT(document->getDefs()->appendChildRepr(arrow)); |
762 | Inkscape::GC::release(arrow); |
763 | } |
764 | - elements.push_back(mode); |
765 | + items.push_back(mode); |
766 | } |
767 | |
768 | void |
769 | @@ -369,7 +365,7 @@ |
770 | copy->setAttribute("id", id); |
771 | elemref = elemref_copy; |
772 | } |
773 | - elements.push_back(id); |
774 | + items.push_back(id); |
775 | Geom::OptRect bounds = SP_ITEM(elemref)->bounds(SPItem::GEOMETRIC_BBOX); |
776 | if (bounds) { |
777 | anotation_width = bounds->width() * 1.4; |
778 | @@ -483,7 +479,7 @@ |
779 | elemref->deleteObject(); |
780 | copy->setAttribute("id", id); |
781 | } |
782 | - elements.push_back(id); |
783 | + items.push_back(id); |
784 | } |
785 | |
786 | void |
787 | @@ -535,7 +531,7 @@ |
788 | sp_lpe_item->getCurrentLPE() != this){ |
789 | return; |
790 | } |
791 | - elements.clear(); |
792 | + items.clear(); |
793 | start_stored = start; |
794 | end_stored = end; |
795 | Geom::Point hstart = start; |
796 | @@ -680,60 +676,12 @@ |
797 | //unset "erase_extra_objects" hook on sp-lpe-item.cpp |
798 | if (!erase_extra_objects) { |
799 | processObjects(LPE_TO_OBJECTS); |
800 | - elements.clear(); |
801 | + items.clear(); |
802 | return; |
803 | } |
804 | processObjects(LPE_ERASE); |
805 | } |
806 | |
807 | -void |
808 | -LPEMeasureLine::processObjects(LpeAction lpe_action) |
809 | -{ |
810 | - SPDocument * document = SP_ACTIVE_DOCUMENT; |
811 | - for (std::vector<const char *>::iterator el_it = elements.begin(); |
812 | - el_it != elements.end(); ++el_it) { |
813 | - const char * id = *el_it; |
814 | - if (!id || strlen(id) == 0) { |
815 | - return; |
816 | - } |
817 | - SPObject *elemref = NULL; |
818 | - if (elemref = document->getObjectById(id)) { |
819 | - SPCSSAttr *css; |
820 | - Glib::ustring css_str; |
821 | - switch (lpe_action){ |
822 | - case LPE_TO_OBJECTS: |
823 | - elemref->getRepr()->setAttribute("inkscape:path-effect", NULL); |
824 | - elemref->getRepr()->setAttribute("sodipodi:insensitive", NULL); |
825 | - break; |
826 | - |
827 | - case LPE_ERASE: |
828 | - if (std::strcmp(elemref->getId(),id_origin.param_getSVGValue()) != 0) { |
829 | - elemref->deleteObject(); |
830 | - } |
831 | - break; |
832 | - |
833 | - case LPE_VISIBILITY: |
834 | - css = sp_repr_css_attr_new(); |
835 | - sp_repr_css_attr_add_from_string(css, elemref->getRepr()->attribute("style")); |
836 | - if (!this->isVisible() && std::strcmp(elemref->getId(),id_origin.param_getSVGValue()) != 0) { |
837 | - css->setAttribute("display", "none"); |
838 | - } else { |
839 | - css->setAttribute("display", NULL); |
840 | - } |
841 | - sp_repr_css_write_string(css,css_str); |
842 | - elemref->getRepr()->setAttribute("style", css_str.c_str()); |
843 | - break; |
844 | - |
845 | - default: |
846 | - break; |
847 | - } |
848 | - } |
849 | - } |
850 | - if (lpe_action == LPE_ERASE) { |
851 | - elements.clear(); |
852 | - } |
853 | -} |
854 | - |
855 | Gtk::Widget *LPEMeasureLine::newWidget() |
856 | { |
857 | // use manage here, because after deletion of Effect object, others might |
858 | |
859 | === modified file 'src/live_effects/lpe-measure-line.h' |
860 | --- src/live_effects/lpe-measure-line.h 2016-12-26 23:00:38 +0000 |
861 | +++ src/live_effects/lpe-measure-line.h 2017-01-24 07:18:19 +0000 |
862 | @@ -35,12 +35,6 @@ |
863 | OM_END |
864 | }; |
865 | |
866 | -enum LpeAction { |
867 | - LPE_ERASE = 0, |
868 | - LPE_TO_OBJECTS, |
869 | - LPE_VISIBILITY |
870 | -}; |
871 | - |
872 | class LPEMeasureLine : public Effect { |
873 | public: |
874 | LPEMeasureLine(LivePathEffectObject *lpeobject); |
875 | @@ -51,7 +45,6 @@ |
876 | virtual void doEffect (SPCurve * curve){}; //stop the chain |
877 | virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); |
878 | virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in); |
879 | - void processObjects(LpeAction lpe_action); |
880 | void createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows = false); |
881 | void createTextLabel(Geom::Point pos, double length, Geom::Coord angle, bool remove, bool valid); |
882 | void onExpanderChanged(); |
883 | @@ -92,7 +85,6 @@ |
884 | double arrow_gap; |
885 | Geom::Point start_stored; |
886 | Geom::Point end_stored; |
887 | - std::vector<const char *> elements; |
888 | /* Geom::Affine affine_over;*/ |
889 | LPEMeasureLine(const LPEMeasureLine &); |
890 | LPEMeasureLine &operator=(const LPEMeasureLine &); |
891 | |
892 | === modified file 'src/live_effects/parameter/bool.cpp' |
893 | --- src/live_effects/parameter/bool.cpp 2016-07-24 23:43:33 +0000 |
894 | +++ src/live_effects/parameter/bool.cpp 2017-01-24 07:18:19 +0000 |
895 | @@ -72,7 +72,7 @@ |
896 | checkwdg->setActive(value); |
897 | checkwdg->setProgrammatically = false; |
898 | checkwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change bool parameter")); |
899 | - |
900 | + param_effect->upd_params = false; |
901 | return dynamic_cast<Gtk::Widget *> (checkwdg); |
902 | } else { |
903 | return NULL; |
904 | @@ -82,6 +82,7 @@ |
905 | void |
906 | BoolParam::param_setValue(bool newvalue) |
907 | { |
908 | + param_effect->upd_params = true; |
909 | value = newvalue; |
910 | } |
911 | |
912 | |
913 | === modified file 'src/live_effects/parameter/text.cpp' |
914 | --- src/live_effects/parameter/text.cpp 2016-12-06 20:41:55 +0000 |
915 | +++ src/live_effects/parameter/text.cpp 2017-01-24 07:18:19 +0000 |
916 | @@ -125,13 +125,14 @@ |
917 | rsu->setProgrammatically = false; |
918 | |
919 | rsu->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change text parameter")); |
920 | - |
921 | + param_effect->upd_params = false; |
922 | return dynamic_cast<Gtk::Widget *> (rsu); |
923 | } |
924 | |
925 | void |
926 | TextParam::param_setValue(const Glib::ustring newvalue) |
927 | { |
928 | + param_effect->upd_params = true; |
929 | value = newvalue; |
930 | if (!_hide_canvas_text) { |
931 | sp_canvastext_set_text (canvas_text, newvalue.c_str()); |
932 | |
933 | === modified file 'src/sp-item-group.cpp' |
934 | --- src/sp-item-group.cpp 2016-12-15 11:26:38 +0000 |
935 | +++ src/sp-item-group.cpp 2017-01-24 07:18:19 +0000 |
936 | @@ -925,6 +925,15 @@ |
937 | } |
938 | |
939 | sp_group_perform_patheffect(this, this, write); |
940 | + |
941 | + for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it) |
942 | + { |
943 | + LivePathEffectObject *lpeobj = (*it)->lpeobject; |
944 | + |
945 | + if (lpeobj && lpeobj->get_lpe()) { |
946 | + lpeobj->get_lpe()->doAfterEffect(this); |
947 | + } |
948 | + } |
949 | } |
950 | } |
951 | |
952 | @@ -950,25 +959,35 @@ |
953 | } else { |
954 | c = subShape->getCurve(); |
955 | } |
956 | - |
957 | + bool success = false; |
958 | // only run LPEs when the shape has a curve defined |
959 | if (c) { |
960 | c->transform(i2anc_affine(subitem, topgroup)); |
961 | - topgroup->performPathEffect(c); |
962 | + success = topgroup->performPathEffect(c, subShape); |
963 | c->transform(i2anc_affine(subitem, topgroup).inverse()); |
964 | - subShape->setCurve(c, TRUE); |
965 | - |
966 | - if (write) { |
967 | - Inkscape::XML::Node *repr = subitem->getRepr(); |
968 | - gchar *str = sp_svg_write_path(c->get_pathvector()); |
969 | - repr->setAttribute("d", str); |
970 | + Inkscape::XML::Node *repr = subitem->getRepr(); |
971 | + if (c && success) { |
972 | + subShape->setCurve(c, TRUE); |
973 | + if (write) { |
974 | + gchar *str = sp_svg_write_path(c->get_pathvector()); |
975 | + repr->setAttribute("d", str); |
976 | #ifdef GROUP_VERBOSE |
977 | - g_message("sp_group_perform_patheffect writes 'd' attribute"); |
978 | + g_message("sp_group_perform_patheffect writes 'd' attribute"); |
979 | #endif |
980 | - g_free(str); |
981 | + g_free(str); |
982 | + } |
983 | + c->unref(); |
984 | + } else { |
985 | + // LPE was unsuccesfull or doeffect stack return null. Read the old 'd'-attribute. |
986 | + if (gchar const * value = repr->attribute("d")) { |
987 | + Geom::PathVector pv = sp_svg_read_pathv(value); |
988 | + SPCurve *oldcurve = new (std::nothrow) SPCurve(pv); |
989 | + if (oldcurve) { |
990 | + subShape->setCurve(oldcurve, TRUE); |
991 | + oldcurve->unref(); |
992 | + } |
993 | + } |
994 | } |
995 | - |
996 | - c->unref(); |
997 | } |
998 | } |
999 | } |
1000 | |
1001 | === modified file 'src/sp-lpe-item.cpp' |
1002 | --- src/sp-lpe-item.cpp 2016-12-07 22:17:49 +0000 |
1003 | +++ src/sp-lpe-item.cpp 2017-01-24 07:18:19 +0000 |
1004 | @@ -24,6 +24,8 @@ |
1005 | #include "live_effects/lpeobject.h" |
1006 | #include "live_effects/lpeobject-reference.h" |
1007 | #include "live_effects/lpe-measure-line.h" |
1008 | +#include "live_effects/lpe-mirror_symmetry.h" |
1009 | +#include "live_effects/lpe-copy_rotate.h" |
1010 | |
1011 | #include "sp-path.h" |
1012 | #include "sp-item-group.h" |
1013 | @@ -126,7 +128,10 @@ |
1014 | if (!value) { |
1015 | LivePathEffectObject *lpeobj = (*it)->lpeobject; |
1016 | Inkscape::LivePathEffect::Effect * lpe = lpeobj->get_lpe(); |
1017 | - if (dynamic_cast<Inkscape::LivePathEffect::LPEMeasureLine *>(lpe)){ |
1018 | + if (dynamic_cast<Inkscape::LivePathEffect::LPEMirrorSymmetry *>(lpe) || |
1019 | + dynamic_cast<Inkscape::LivePathEffect::LPEMeasureLine *>(lpe) || |
1020 | + dynamic_cast<Inkscape::LivePathEffect::LPECopyRotate *>(lpe) ) |
1021 | + { |
1022 | lpe->doOnRemove(this); |
1023 | } |
1024 | } |
1025 | @@ -209,7 +214,7 @@ |
1026 | /** |
1027 | * returns true when LPE was successful. |
1028 | */ |
1029 | -bool SPLPEItem::performPathEffect(SPCurve *curve, bool is_clip_or_mask) { |
1030 | +bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip_or_mask) { |
1031 | |
1032 | if (!curve) { |
1033 | return false; |
1034 | @@ -241,12 +246,15 @@ |
1035 | } |
1036 | if (!is_clip_or_mask || (is_clip_or_mask && lpe->apply_to_clippath_and_mask)) { |
1037 | // Groups have their doBeforeEffect called elsewhere |
1038 | + if (current) { |
1039 | + lpe->setCurrentShape(current); |
1040 | + } |
1041 | if (!SP_IS_GROUP(this)) { |
1042 | lpe->doBeforeEffect_impl(this); |
1043 | } |
1044 | |
1045 | try { |
1046 | - lpe->doEffect(curve); |
1047 | + lpe->doEffect(curve); |
1048 | } |
1049 | catch (std::exception & e) { |
1050 | g_warning("Exception during LPE %s execution. \n %s", lpe->getName().c_str(), e.what()); |
1051 | @@ -257,6 +265,8 @@ |
1052 | return false; |
1053 | } |
1054 | if (!SP_IS_GROUP(this)) { |
1055 | + lpe->pathvector_before_effect = curve->get_pathvector(); |
1056 | + lpe->sp_curve->set_pathvector(lpe->pathvector_before_effect); |
1057 | lpe->doAfterEffect(this); |
1058 | } |
1059 | } |
1060 | @@ -604,7 +614,7 @@ |
1061 | return true; |
1062 | } |
1063 | |
1064 | -bool SPLPEItem::hasPathEffectOfType(int const type) const |
1065 | +bool SPLPEItem::hasPathEffectOfType(int const type, bool is_ready) const |
1066 | { |
1067 | if (path_effect_list->empty()) { |
1068 | return false; |
1069 | @@ -616,7 +626,9 @@ |
1070 | if (lpeobj) { |
1071 | Inkscape::LivePathEffect::Effect const* lpe = lpeobj->get_lpe(); |
1072 | if (lpe && (lpe->effectType() == type)) { |
1073 | - return true; |
1074 | + if (is_ready || lpe->isReady()) { |
1075 | + return true; |
1076 | + } |
1077 | } |
1078 | } |
1079 | } |
1080 | @@ -695,10 +707,10 @@ |
1081 | try { |
1082 | if(SP_IS_GROUP(this)){ |
1083 | c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this))); |
1084 | - success = this->performPathEffect(c, true); |
1085 | + success = this->performPathEffect(c, SP_SHAPE(clip_mask), true); |
1086 | c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse()); |
1087 | } else { |
1088 | - success = this->performPathEffect(c, true); |
1089 | + success = this->performPathEffect(c, SP_SHAPE(clip_mask), true); |
1090 | } |
1091 | } catch (std::exception & e) { |
1092 | g_warning("Exception during LPE execution. \n %s", e.what()); |
1093 | @@ -709,12 +721,13 @@ |
1094 | success = false; |
1095 | } |
1096 | Inkscape::XML::Node *repr = clip_mask->getRepr(); |
1097 | - if (success) { |
1098 | + // This c check allow to not apply LPE if curve is NULL after performPathEffect used in clone.obgets LPE |
1099 | + if (success && c) { |
1100 | gchar *str = sp_svg_write_path(c->get_pathvector()); |
1101 | repr->setAttribute("d", str); |
1102 | g_free(str); |
1103 | } else { |
1104 | - // LPE was unsuccesfull. Read the old 'd'-attribute. |
1105 | + // LPE was unsuccesfull or doeffect stack return null.. Read the old 'd'-attribute. |
1106 | if (gchar const * value = repr->attribute("d")) { |
1107 | Geom::PathVector pv = sp_svg_read_pathv(value); |
1108 | SPCurve *oldcurve = new (std::nothrow) SPCurve(pv); |
1109 | @@ -724,7 +737,9 @@ |
1110 | } |
1111 | } |
1112 | } |
1113 | - c->unref(); |
1114 | + if (c) { |
1115 | + c->unref(); |
1116 | + } |
1117 | } |
1118 | } |
1119 | } |
1120 | |
1121 | === modified file 'src/sp-lpe-item.h' |
1122 | --- src/sp-lpe-item.h 2016-03-19 11:17:59 +0000 |
1123 | +++ src/sp-lpe-item.h 2017-01-24 07:18:19 +0000 |
1124 | @@ -23,6 +23,7 @@ |
1125 | |
1126 | class LivePathEffectObject; |
1127 | class SPCurve; |
1128 | +class SPShape; |
1129 | class SPDesktop; |
1130 | |
1131 | namespace Inkscape{ |
1132 | @@ -69,11 +70,11 @@ |
1133 | |
1134 | virtual void update_patheffect(bool write); |
1135 | |
1136 | - bool performPathEffect(SPCurve *curve, bool is_clip_or_mask = false); |
1137 | + bool performPathEffect(SPCurve *curve, SPShape *current = NULL, bool is_clip_or_mask = false); |
1138 | |
1139 | bool pathEffectsEnabled() const; |
1140 | bool hasPathEffect() const; |
1141 | - bool hasPathEffectOfType(int const type) const; |
1142 | + bool hasPathEffectOfType(int const type, bool is_ready = true) const; |
1143 | bool hasPathEffectRecursive() const; |
1144 | Inkscape::LivePathEffect::Effect* getPathEffectOfType(int type); |
1145 | Inkscape::LivePathEffect::Effect const* getPathEffectOfType(int type) const; |
1146 | |
1147 | === modified file 'src/sp-object.cpp' |
1148 | --- src/sp-object.cpp 2017-01-07 15:32:48 +0000 |
1149 | +++ src/sp-object.cpp 2017-01-24 07:18:19 +0000 |
1150 | @@ -775,6 +775,21 @@ |
1151 | repr->appendChild(child); |
1152 | } |
1153 | |
1154 | +SPObject* SPObject::nthChild(unsigned index) { |
1155 | + g_assert(this->repr); |
1156 | + if (hasChildren()) { |
1157 | + std::vector<SPObject*> l; |
1158 | + unsigned counter = 0; |
1159 | + for (auto& child: children) { |
1160 | + if (counter == index) { |
1161 | + return &child; |
1162 | + } |
1163 | + counter++; |
1164 | + } |
1165 | + } |
1166 | + return NULL; |
1167 | +} |
1168 | + |
1169 | void SPObject::addChild(Inkscape::XML::Node *child, Inkscape::XML::Node * prev) |
1170 | { |
1171 | g_assert(this->repr); |
1172 | |
1173 | === modified file 'src/sp-object.h' |
1174 | --- src/sp-object.h 2016-11-05 16:51:16 +0000 |
1175 | +++ src/sp-object.h 2017-01-24 07:18:19 +0000 |
1176 | @@ -318,6 +318,9 @@ |
1177 | SPObject *lastChild() { return children.empty() ? nullptr : &children.back(); } |
1178 | SPObject const *lastChild() const { return children.empty() ? nullptr : &children.back(); } |
1179 | |
1180 | + SPObject *nthChild(unsigned index); |
1181 | + SPObject const *nthChild(unsigned index) const; |
1182 | + |
1183 | enum Action { ActionGeneral, ActionBBox, ActionUpdate, ActionShow }; |
1184 | |
1185 | /** |
There is a todo in src/2geom/ intersection- graph.cpp: 9 which should be dealt with
File src/document- undo.cpp shouldn't change in this merge.
I don't like the list of phantom attribute creators, it seems like it could be a loop instead.
Another ToDo in lpe-copy-rotate
Everything else looks good.