1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** \file
3  * LPE <lattice2> implementation
4 
5  */
6 /*
7  * Authors:
8  *   Johan Engelen <j.b.c.engelen@utwente.nl>
9  *   Steren Giannini
10  *   No� Falzon
11  *   Victor Navez
12  *   ~suv
13  *   Jabiertxo Arraiza
14  *
15  * Copyright (C) 2007-2008 Authors
16  *
17  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
18  */
19 
20 #include <gtkmm.h>
21 #include "live_effects/lpe-lattice2.h"
22 #include "display/curve.h"
23 #include "helper/geom.h"
24 #include <2geom/sbasis-2d.h>
25 #include <2geom/bezier-to-sbasis.h>
26 
27 // TODO due to internal breakage in glibmm headers, this must be last:
28 #include <glibmm/i18n.h>
29 
30 using namespace Geom;
31 
32 namespace Inkscape {
33 namespace LivePathEffect {
34 
LPELattice2(LivePathEffectObject * lpeobject)35 LPELattice2::LPELattice2(LivePathEffectObject *lpeobject) :
36     Effect(lpeobject),
37     horizontal_mirror(_("Mirror movements in horizontal"), _("Mirror movements in horizontal"), "horizontal_mirror", &wr, this, false),
38     vertical_mirror(_("Mirror movements in vertical"), _("Mirror movements in vertical"), "vertical_mirror", &wr, this, false),
39     perimetral(_("Use only perimeter"), _("Use only perimeter"), "perimetral", &wr, this, false),
40     live_update(_("Update while moving knots (maybe slow)"), _("Update while moving knots (maybe slow)"), "live_update", &wr, this, true),
41     grid_point_0(_("Control 0:"), _("Control 0 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint0", &wr, this),
42     grid_point_1(_("Control 1:"), _("Control 1 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint1", &wr, this),
43     grid_point_2(_("Control 2:"), _("Control 2 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint2", &wr, this),
44     grid_point_3(_("Control 3:"), _("Control 3 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint3", &wr, this),
45     grid_point_4(_("Control 4:"), _("Control 4 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint4", &wr, this),
46     grid_point_5(_("Control 5:"), _("Control 5 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint5", &wr, this),
47     grid_point_6(_("Control 6:"), _("Control 6 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint6", &wr, this),
48     grid_point_7(_("Control 7:"), _("Control 7 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint7", &wr, this),
49     grid_point_8x9(_("Control 8x9:"), _("Control 8x9 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint8x9", &wr, this),
50     grid_point_10x11(_("Control 10x11:"), _("Control 10x11 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint10x11", &wr, this),
51     grid_point_12(_("Control 12:"), _("Control 12 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint12", &wr, this),
52     grid_point_13(_("Control 13:"), _("Control 13 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint13", &wr, this),
53     grid_point_14(_("Control 14:"), _("Control 14 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint14", &wr, this),
54     grid_point_15(_("Control 15:"), _("Control 15 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint15", &wr, this),
55     grid_point_16(_("Control 16:"), _("Control 16 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint16", &wr, this),
56     grid_point_17(_("Control 17:"), _("Control 17 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint17", &wr, this),
57     grid_point_18(_("Control 18:"), _("Control 18 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint18", &wr, this),
58     grid_point_19(_("Control 19:"), _("Control 19 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint19", &wr, this),
59     grid_point_20x21(_("Control 20x21:"), _("Control 20x21 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint20x21", &wr, this),
60     grid_point_22x23(_("Control 22x23:"), _("Control 22x23 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint22x23", &wr, this),
61     grid_point_24x26(_("Control 24x26:"), _("Control 24x26 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint24x26", &wr, this),
62     grid_point_25x27(_("Control 25x27:"), _("Control 25x27 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint25x27", &wr, this),
63     grid_point_28x30(_("Control 28x30:"), _("Control 28x30 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint28x30", &wr, this),
64     grid_point_29x31(_("Control 29x31:"), _("Control 29x31 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint29x31", &wr, this),
65     grid_point_32x33x34x35(_("Control 32x33x34x35:"), _("Control 32x33x34x35 - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"), "gridpoint32x33x34x35", &wr, this),
66     expanded(false)
67 {
68     // register all your parameters here, so Inkscape knows which parameters this effect has:
69     registerParameter(&horizontal_mirror);
70     registerParameter(&vertical_mirror);
71     registerParameter(&perimetral);
72     registerParameter(&live_update);
73     registerParameter(&grid_point_0);
74     registerParameter(&grid_point_1);
75     registerParameter(&grid_point_2);
76     registerParameter(&grid_point_3);
77     registerParameter(&grid_point_4);
78     registerParameter(&grid_point_5);
79     registerParameter(&grid_point_6);
80     registerParameter(&grid_point_7);
81     registerParameter(&grid_point_8x9);
82     registerParameter(&grid_point_10x11);
83     registerParameter(&grid_point_12);
84     registerParameter(&grid_point_13);
85     registerParameter(&grid_point_14);
86     registerParameter(&grid_point_15);
87     registerParameter(&grid_point_16);
88     registerParameter(&grid_point_17);
89     registerParameter(&grid_point_18);
90     registerParameter(&grid_point_19);
91     registerParameter(&grid_point_20x21);
92     registerParameter(&grid_point_22x23);
93     registerParameter(&grid_point_24x26);
94     registerParameter(&grid_point_25x27);
95     registerParameter(&grid_point_28x30);
96     registerParameter(&grid_point_29x31);
97     registerParameter(&grid_point_32x33x34x35);
98     apply_to_clippath_and_mask = true;
99 }
100 
101 LPELattice2::~LPELattice2()
102 = default;
103 
104 Geom::Piecewise<Geom::D2<Geom::SBasis> >
doEffect_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis>> const & pwd2_in)105 LPELattice2::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
106 {
107     PathVector pathv = path_from_piecewise(pwd2_in,0.001);
108     //this is because strange problems with sb2 and LineSegment
109     PathVector cubic = pathv_to_cubicbezier(pathv);
110     if (cubic.empty()) {
111         return pwd2_in;
112     }
113     Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in_linear_and_cubic = paths_to_pw(cubic);
114     D2<SBasis2d> sb2;
115 
116     //Initialisation of the sb2
117     for(unsigned dim = 0; dim < 2; dim++) {
118         sb2[dim].us = 3;
119         sb2[dim].vs = 3;
120         const int depth = sb2[dim].us*sb2[dim].vs;
121         sb2[dim].resize(depth, Linear2d(0));
122     }
123 
124     //Grouping the point params in a convenient vector
125 
126     std::vector<Geom::Point > handles(36);
127 
128     handles[0] = grid_point_0;
129     handles[1] = grid_point_1;
130     handles[2] = grid_point_2;
131     handles[3] = grid_point_3;
132     handles[4] = grid_point_4;
133     handles[5] = grid_point_5;
134     handles[6] = grid_point_6;
135     handles[7] = grid_point_7;
136     handles[8] = grid_point_8x9;
137     handles[9] = grid_point_8x9;
138     handles[10] = grid_point_10x11;
139     handles[11] = grid_point_10x11;
140     handles[12] = grid_point_12;
141     handles[13] = grid_point_13;
142     handles[14] = grid_point_14;
143     handles[15] = grid_point_15;
144     handles[16] = grid_point_16;
145     handles[17] = grid_point_17;
146     handles[18] = grid_point_18;
147     handles[19] = grid_point_19;
148     handles[20] = grid_point_20x21;
149     handles[21] = grid_point_20x21;
150     handles[22] = grid_point_22x23;
151     handles[23] = grid_point_22x23;
152     handles[24] = grid_point_24x26;
153     handles[25] = grid_point_25x27;
154     handles[26] = grid_point_24x26;
155     handles[27] = grid_point_25x27;
156     handles[28] = grid_point_28x30;
157     handles[29] = grid_point_29x31;
158     handles[30] = grid_point_28x30;
159     handles[31] = grid_point_29x31;
160     handles[32] = grid_point_32x33x34x35;
161     handles[33] = grid_point_32x33x34x35;
162     handles[34] = grid_point_32x33x34x35;
163     handles[35] = grid_point_32x33x34x35;
164 
165     Geom::Point origin = Geom::Point(boundingbox_X.min(),boundingbox_Y.min());
166 
167     double width = boundingbox_X.extent();
168     double height = boundingbox_Y.extent();
169 
170     //numbering is based on 4 rectangles.16
171     for(unsigned dim = 0; dim < 2; dim++) {
172         Geom::Point dir(0,0);
173         dir[dim] = 1;
174         for(unsigned vi = 0; vi < sb2[dim].vs; vi++) {
175             for(unsigned ui = 0; ui < sb2[dim].us; ui++) {
176                 for(unsigned iv = 0; iv < 2; iv++) {
177                     for(unsigned iu = 0; iu < 2; iu++) {
178                         unsigned corner = iu + 2*iv;
179                         unsigned i = ui + vi*sb2[dim].us;
180 
181                         //This is the offset from the Upperleft point
182                         Geom::Point base(   (ui + iu*(4-2*ui))*width/4.,
183                                             (vi + iv*(4-2*vi))*height/4.);
184 
185                         //Special action for corners
186                         if(vi == 0 && ui == 0) {
187                             base = Geom::Point(0,0);
188                         }
189 
190                         // i = Upperleft corner of the considerated rectangle
191                         // corner = actual corner of the rectangle
192                         // origin = Upperleft point
193                         double dl = dot((handles[corner+4*i] - (base + origin)), dir)/dot(dir,dir);
194                         sb2[dim][i][corner] = dl/( dim ? height : width )*pow(4.0,ui+vi);
195                     }
196                 }
197             }
198         }
199     }
200 
201     Piecewise<D2<SBasis> >  output;
202     output.push_cut(0.);
203     for(unsigned i = 0; i < pwd2_in_linear_and_cubic.size(); i++) {
204         D2<SBasis> B = pwd2_in_linear_and_cubic[i];
205         B[Geom::X] -= origin[Geom::X];
206         B[Geom::X]*= 1/width;
207         B[Geom::Y] -= origin[Geom::Y];
208         B[Geom::Y]*= 1/height;
209         //Here comes the magic
210         D2<SBasis> tB = compose_each(sb2,B);
211         tB[Geom::X] = tB[Geom::X] * width + origin[Geom::X];
212         tB[Geom::Y] = tB[Geom::Y] * height + origin[Geom::Y];
213 
214         output.push(tB,i+1);
215     }
216     return output;
217 }
218 
219 
220 Gtk::Widget *
newWidget()221 LPELattice2::newWidget()
222 {
223     // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
224     Gtk::Box *vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
225 
226     vbox->set_border_width(5);
227     vbox->set_homogeneous(false);
228     vbox->set_spacing(6);
229     Gtk::Box * hbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL,0));
230     Gtk::Box *vbox_expander = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
231     vbox_expander->set_border_width(0);
232     vbox_expander->set_spacing(2);
233     Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset grid"))));
234     reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPELattice2::resetGrid));
235     reset_button->set_size_request(140,30);
236     vbox->pack_start(*hbox, true,true,2);
237     hbox->pack_start(*reset_button, false, false,2);
238     std::vector<Parameter *>::iterator it = param_vector.begin();
239     while (it != param_vector.end()) {
240         if ((*it)->widget_is_visible) {
241             Parameter * param = *it;
242             Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
243             if(param->param_key == "grid") {
244                 widg = nullptr;
245             }
246             Glib::ustring * tip = param->param_getTooltip();
247             if (widg) {
248                 if (param->param_key == "horizontal_mirror" ||
249                     param->param_key == "vertical_mirror" ||
250                     param->param_key == "live_update" ||
251                     param->param_key == "perimetral")
252                 {
253                     vbox->pack_start(*widg, true, true, 2);
254                 } else {
255                     vbox_expander->pack_start(*widg, true, true, 2);
256                 }
257                 if (tip) {
258                     widg->set_tooltip_text(*tip);
259                 } else {
260                     widg->set_tooltip_text("");
261                     widg->set_has_tooltip(false);
262                 }
263             }
264         }
265 
266         ++it;
267     }
268 
269     expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show Points"))));
270     expander->add(*vbox_expander);
271     expander->set_expanded(expanded);
272     vbox->pack_start(*expander, true, true, 2);
273     expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPELattice2::onExpanderChanged) );
274     if(Gtk::Widget* widg = defaultParamSet()) {
275         vbox->pack_start(*widg, true, true, 2);
276     }
277     return dynamic_cast<Gtk::Widget *>(vbox);
278 }
279 
280 void
onExpanderChanged()281 LPELattice2::onExpanderChanged()
282 {
283     expanded = expander->get_expanded();
284     if(expanded) {
285         expander->set_label (Glib::ustring(_("Hide Points")));
286     } else {
287         expander->set_label (Glib::ustring(_("Show Points")));
288     }
289 }
290 void
vertical(PointParam & param_one,PointParam & param_two,Geom::Line vert)291 LPELattice2::vertical(PointParam &param_one, PointParam &param_two, Geom::Line vert)
292 {
293     Geom::Point A = param_one;
294     Geom::Point B = param_two;
295     double Y = (A[Geom::Y] + B[Geom::Y])/2;
296     A[Geom::Y] = Y;
297     B[Geom::Y] = Y;
298     Geom::Point nearest = vert.pointAt(vert.nearestTime(A));
299     double distance_one = Geom::distance(A,nearest);
300     double distance_two = Geom::distance(B,nearest);
301     double distance_middle = (distance_one + distance_two)/2;
302     if(A[Geom::X] > B[Geom::X]) {
303         distance_middle *= -1;
304     }
305     A[Geom::X] = nearest[Geom::X] - distance_middle;
306     B[Geom::X] = nearest[Geom::X] + distance_middle;
307     param_one.param_setValue(A, live_update);
308     param_two.param_setValue(B, live_update);
309 }
310 
311 void
horizontal(PointParam & param_one,PointParam & param_two,Geom::Line horiz)312 LPELattice2::horizontal(PointParam &param_one, PointParam &param_two, Geom::Line horiz)
313 {
314     Geom::Point A = param_one;
315     Geom::Point B = param_two;
316     double X = (A[Geom::X] + B[Geom::X])/2;
317     A[Geom::X] = X;
318     B[Geom::X] = X;
319     Geom::Point nearest = horiz.pointAt(horiz.nearestTime(A));
320     double distance_one = Geom::distance(A,nearest);
321     double distance_two = Geom::distance(B,nearest);
322     double distance_middle = (distance_one + distance_two)/2;
323     if(A[Geom::Y] > B[Geom::Y]) {
324         distance_middle *= -1;
325     }
326     A[Geom::Y] = nearest[Geom::Y] - distance_middle;
327     B[Geom::Y] = nearest[Geom::Y] + distance_middle;
328     param_one.param_setValue(A, live_update);
329     param_two.param_setValue(B, live_update);
330 }
331 
332 
333 void
doBeforeEffect(SPLPEItem const * lpeitem)334 LPELattice2::doBeforeEffect (SPLPEItem const* lpeitem)
335 {
336     original_bbox(lpeitem, false, true);
337     setDefaults();
338     if (is_applied) {
339         resetGrid();
340     }
341     Geom::Line vert(grid_point_8x9.param_get_default(),grid_point_10x11.param_get_default());
342     Geom::Line horiz(grid_point_24x26.param_get_default(),grid_point_25x27.param_get_default());
343     if(vertical_mirror) {
344         vertical(grid_point_0, grid_point_1,vert);
345         vertical(grid_point_2, grid_point_3,vert);
346         vertical(grid_point_4, grid_point_5,vert);
347         vertical(grid_point_6, grid_point_7,vert);
348         vertical(grid_point_12, grid_point_13,vert);
349         vertical(grid_point_14, grid_point_15,vert);
350         vertical(grid_point_16, grid_point_17,vert);
351         vertical(grid_point_18, grid_point_19,vert);
352         vertical(grid_point_24x26, grid_point_25x27,vert);
353         vertical(grid_point_28x30, grid_point_29x31,vert);
354     }
355     if(horizontal_mirror) {
356         horizontal(grid_point_0, grid_point_2,horiz);
357         horizontal(grid_point_1, grid_point_3,horiz);
358         horizontal(grid_point_4, grid_point_6,horiz);
359         horizontal(grid_point_5, grid_point_7,horiz);
360         horizontal(grid_point_8x9, grid_point_10x11,horiz);
361         horizontal(grid_point_12, grid_point_14,horiz);
362         horizontal(grid_point_13, grid_point_15,horiz);
363         horizontal(grid_point_16, grid_point_18,horiz);
364         horizontal(grid_point_17, grid_point_19,horiz);
365         horizontal(grid_point_20x21, grid_point_22x23,horiz);
366     }
367     if (perimetral) {
368         grid_point_16.param_hide_knot(true);
369         grid_point_20x21.param_hide_knot(true);
370         grid_point_17.param_hide_knot(true);
371         grid_point_28x30.param_hide_knot(true);
372         grid_point_32x33x34x35.param_hide_knot(true);
373         grid_point_29x31.param_hide_knot(true);
374         grid_point_18.param_hide_knot(true);
375         grid_point_22x23.param_hide_knot(true);
376         grid_point_19.param_hide_knot(true);
377         grid_point_16.param_set_default();
378         grid_point_20x21.param_set_default();
379         grid_point_17.param_set_default();
380         grid_point_28x30.param_set_default();
381         grid_point_32x33x34x35.param_set_default();
382         grid_point_29x31.param_set_default();
383         grid_point_18.param_set_default();
384         grid_point_22x23.param_set_default();
385         grid_point_19.param_set_default();
386     } else {
387         grid_point_16.param_hide_knot(false);
388         grid_point_20x21.param_hide_knot(false);
389         grid_point_17.param_hide_knot(false);
390         grid_point_28x30.param_hide_knot(false);
391         grid_point_32x33x34x35.param_hide_knot(false);
392         grid_point_29x31.param_hide_knot(false);
393         grid_point_18.param_hide_knot(false);
394         grid_point_22x23.param_hide_knot(false);
395         grid_point_19.param_hide_knot(false);
396     }
397 }
398 
399 void
setDefaults()400 LPELattice2::setDefaults()
401 {
402     Geom::Point gp0((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
403                     (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
404 
405     Geom::Point gp1((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
406                     (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
407 
408     Geom::Point gp2((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
409                     (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
410 
411     Geom::Point gp3((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
412                     (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
413 
414     Geom::Point gp4((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
415                     (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
416 
417     Geom::Point gp5((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
418                     (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
419 
420     Geom::Point gp6((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
421                     (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
422 
423     Geom::Point gp7((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
424                     (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
425 
426     Geom::Point gp8x9((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
427                       (boundingbox_Y.max()-boundingbox_Y.min())/4*0+boundingbox_Y.min());
428 
429     Geom::Point gp10x11((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
430                         (boundingbox_Y.max()-boundingbox_Y.min())/4*4+boundingbox_Y.min());
431 
432     Geom::Point gp12((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
433                      (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
434 
435     Geom::Point gp13((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
436                      (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
437 
438     Geom::Point gp14((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
439                      (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
440 
441     Geom::Point gp15((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
442                      (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
443 
444     Geom::Point gp16((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
445                      (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
446 
447     Geom::Point gp17((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
448                      (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
449 
450     Geom::Point gp18((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
451                      (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
452 
453     Geom::Point gp19((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
454                      (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
455 
456     Geom::Point gp20x21((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
457                         (boundingbox_Y.max()-boundingbox_Y.min())/4*1+boundingbox_Y.min());
458 
459     Geom::Point gp22x23((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
460                         (boundingbox_Y.max()-boundingbox_Y.min())/4*3+boundingbox_Y.min());
461 
462     Geom::Point gp24x26((boundingbox_X.max()-boundingbox_X.min())/4*0+boundingbox_X.min(),
463                         (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
464 
465     Geom::Point gp25x27((boundingbox_X.max()-boundingbox_X.min())/4*4+boundingbox_X.min(),
466                         (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
467 
468     Geom::Point gp28x30((boundingbox_X.max()-boundingbox_X.min())/4*1+boundingbox_X.min(),
469                         (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
470 
471     Geom::Point gp29x31((boundingbox_X.max()-boundingbox_X.min())/4*3+boundingbox_X.min(),
472                         (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
473 
474     Geom::Point gp32x33x34x35((boundingbox_X.max()-boundingbox_X.min())/4*2+boundingbox_X.min(),
475                               (boundingbox_Y.max()-boundingbox_Y.min())/4*2+boundingbox_Y.min());
476 
477     grid_point_0.param_update_default(gp0);
478     grid_point_1.param_update_default(gp1);
479     grid_point_2.param_update_default(gp2);
480     grid_point_3.param_update_default(gp3);
481     grid_point_4.param_update_default(gp4);
482     grid_point_5.param_update_default(gp5);
483     grid_point_6.param_update_default(gp6);
484     grid_point_7.param_update_default(gp7);
485     grid_point_8x9.param_update_default(gp8x9);
486     grid_point_10x11.param_update_default(gp10x11);
487     grid_point_12.param_update_default(gp12);
488     grid_point_13.param_update_default(gp13);
489     grid_point_14.param_update_default(gp14);
490     grid_point_15.param_update_default(gp15);
491     grid_point_16.param_update_default(gp16);
492     grid_point_17.param_update_default(gp17);
493     grid_point_18.param_update_default(gp18);
494     grid_point_19.param_update_default(gp19);
495     grid_point_20x21.param_update_default(gp20x21);
496     grid_point_22x23.param_update_default(gp22x23);
497     grid_point_24x26.param_update_default(gp24x26);
498     grid_point_25x27.param_update_default(gp25x27);
499     grid_point_28x30.param_update_default(gp28x30);
500     grid_point_29x31.param_update_default(gp29x31);
501     grid_point_32x33x34x35.param_update_default(gp32x33x34x35);
502     grid_point_0.param_set_liveupdate(live_update);
503     grid_point_1.param_set_liveupdate(live_update);
504     grid_point_2.param_set_liveupdate(live_update);
505     grid_point_3.param_set_liveupdate(live_update);
506     grid_point_4.param_set_liveupdate(live_update);
507     grid_point_5.param_set_liveupdate(live_update);
508     grid_point_6.param_set_liveupdate(live_update);
509     grid_point_7.param_set_liveupdate(live_update);
510     grid_point_8x9.param_set_liveupdate(live_update);
511     grid_point_10x11.param_set_liveupdate(live_update);
512     grid_point_12.param_set_liveupdate(live_update);
513     grid_point_13.param_set_liveupdate(live_update);
514     grid_point_14.param_set_liveupdate(live_update);
515     grid_point_15.param_set_liveupdate(live_update);
516     grid_point_16.param_set_liveupdate(live_update);
517     grid_point_17.param_set_liveupdate(live_update);
518     grid_point_18.param_set_liveupdate(live_update);
519     grid_point_19.param_set_liveupdate(live_update);
520     grid_point_20x21.param_set_liveupdate(live_update);
521     grid_point_22x23.param_set_liveupdate(live_update);
522     grid_point_24x26.param_set_liveupdate(live_update);
523     grid_point_25x27.param_set_liveupdate(live_update);
524     grid_point_28x30.param_set_liveupdate(live_update);
525     grid_point_29x31.param_set_liveupdate(live_update);
526     grid_point_32x33x34x35.param_set_liveupdate(live_update);
527 }
528 
529 void
resetGrid()530 LPELattice2::resetGrid()
531 {
532     grid_point_0.param_set_default();
533     grid_point_1.param_set_default();
534     grid_point_2.param_set_default();
535     grid_point_3.param_set_default();
536     grid_point_4.param_set_default();
537     grid_point_5.param_set_default();
538     grid_point_6.param_set_default();
539     grid_point_7.param_set_default();
540     grid_point_8x9.param_set_default();
541     grid_point_10x11.param_set_default();
542     grid_point_12.param_set_default();
543     grid_point_13.param_set_default();
544     grid_point_14.param_set_default();
545     grid_point_15.param_set_default();
546     grid_point_16.param_set_default();
547     grid_point_17.param_set_default();
548     grid_point_18.param_set_default();
549     grid_point_19.param_set_default();
550     grid_point_20x21.param_set_default();
551     grid_point_22x23.param_set_default();
552     grid_point_24x26.param_set_default();
553     grid_point_25x27.param_set_default();
554     grid_point_28x30.param_set_default();
555     grid_point_29x31.param_set_default();
556     grid_point_32x33x34x35.param_set_default();
557 }
558 
559 void
resetDefaults(SPItem const * item)560 LPELattice2::resetDefaults(SPItem const* item)
561 {
562     Effect::resetDefaults(item);
563     original_bbox(SP_LPE_ITEM(item), false, true);
564     setDefaults();
565     resetGrid();
566 }
567 
568 void
calculateCurve(Geom::Point a,Geom::Point b,SPCurve * c,bool horizontal,bool move)569 LPELattice2::calculateCurve(Geom::Point a,Geom::Point b, SPCurve* c, bool horizontal, bool move)
570 {
571     using Geom::X;
572     using Geom::Y;
573     if(move) c->moveto(a);
574     Geom::Point cubic1 = a + (1./3)* (b - a);
575     Geom::Point cubic2 = b + (1./3)* (a - b);
576     if(horizontal) c->curveto(Geom::Point(cubic1[X],a[Y]),Geom::Point(cubic2[X],b[Y]),b);
577     else c->curveto(Geom::Point(a[X],cubic1[Y]),Geom::Point(b[X],cubic2[Y]),b);
578 }
579 
580 void
addCanvasIndicators(SPLPEItem const *,std::vector<Geom::PathVector> & hp_vec)581 LPELattice2::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
582 {
583     hp_vec.clear();
584 
585     SPCurve *c = new SPCurve();
586     if (perimetral) {
587         calculateCurve(grid_point_0,grid_point_4, c,true, true);
588         calculateCurve(grid_point_4,grid_point_8x9, c,true, false);
589         calculateCurve(grid_point_8x9,grid_point_5, c,true, false);
590         calculateCurve(grid_point_5,grid_point_1, c,true, false);
591 
592         calculateCurve(grid_point_1,grid_point_13, c, false, true);
593         calculateCurve(grid_point_13,grid_point_25x27, c,false, false);
594         calculateCurve(grid_point_25x27,grid_point_15, c,false, false);
595         calculateCurve(grid_point_15,grid_point_3, c, false, false);
596 
597         calculateCurve(grid_point_2,grid_point_6, c,true, true);
598         calculateCurve(grid_point_6,grid_point_10x11, c,true, false);
599         calculateCurve(grid_point_10x11,grid_point_7, c,true, false);
600         calculateCurve(grid_point_7,grid_point_3, c,true, false);
601 
602         calculateCurve(grid_point_0,grid_point_12, c,false, true);
603         calculateCurve(grid_point_12,grid_point_24x26, c,false, false);
604         calculateCurve(grid_point_24x26,grid_point_14, c,false, false);
605         calculateCurve(grid_point_14,grid_point_2, c,false, false);
606 
607     } else {
608         calculateCurve(grid_point_0,grid_point_4, c,true, true);
609         calculateCurve(grid_point_4,grid_point_8x9, c,true, false);
610         calculateCurve(grid_point_8x9,grid_point_5, c,true, false);
611         calculateCurve(grid_point_5,grid_point_1, c,true, false);
612 
613         calculateCurve(grid_point_12,grid_point_16, c,true, true);
614         calculateCurve(grid_point_16,grid_point_20x21, c,true, false);
615         calculateCurve(grid_point_20x21,grid_point_17, c,true, false);
616         calculateCurve(grid_point_17,grid_point_13, c,true, false);
617 
618         calculateCurve(grid_point_24x26,grid_point_28x30, c,true, true);
619         calculateCurve(grid_point_28x30,grid_point_32x33x34x35, c,true, false);
620         calculateCurve(grid_point_32x33x34x35,grid_point_29x31, c,true, false);
621         calculateCurve(grid_point_29x31,grid_point_25x27, c,true, false);
622 
623         calculateCurve(grid_point_14,grid_point_18, c,true, true);
624         calculateCurve(grid_point_18,grid_point_22x23, c,true, false);
625         calculateCurve(grid_point_22x23,grid_point_19, c,true, false);
626         calculateCurve(grid_point_19,grid_point_15, c,true, false);
627 
628         calculateCurve(grid_point_2,grid_point_6, c,true, true);
629         calculateCurve(grid_point_6,grid_point_10x11, c,true, false);
630         calculateCurve(grid_point_10x11,grid_point_7, c,true, false);
631         calculateCurve(grid_point_7,grid_point_3, c,true, false);
632 
633         calculateCurve(grid_point_0,grid_point_12, c,false, true);
634         calculateCurve(grid_point_12,grid_point_24x26, c,false, false);
635         calculateCurve(grid_point_24x26,grid_point_14, c,false, false);
636         calculateCurve(grid_point_14,grid_point_2, c,false, false);
637 
638         calculateCurve(grid_point_4,grid_point_16, c,false, true);
639         calculateCurve(grid_point_16,grid_point_28x30, c,false, false);
640         calculateCurve(grid_point_28x30,grid_point_18, c,false, false);
641         calculateCurve(grid_point_18,grid_point_6, c,false, false);
642 
643         calculateCurve(grid_point_8x9,grid_point_20x21, c,false, true);
644         calculateCurve(grid_point_20x21,grid_point_32x33x34x35, c,false, false);
645         calculateCurve(grid_point_32x33x34x35,grid_point_22x23, c,false, false);
646         calculateCurve(grid_point_22x23,grid_point_10x11, c,false, false);
647 
648         calculateCurve(grid_point_5,grid_point_17, c, false, true);
649         calculateCurve(grid_point_17,grid_point_29x31, c,false, false);
650         calculateCurve(grid_point_29x31,grid_point_19, c,false, false);
651         calculateCurve(grid_point_19,grid_point_7, c,false, false);
652 
653         calculateCurve(grid_point_1,grid_point_13, c, false, true);
654         calculateCurve(grid_point_13,grid_point_25x27, c,false, false);
655         calculateCurve(grid_point_25x27,grid_point_15, c,false, false);
656         calculateCurve(grid_point_15,grid_point_3, c, false, false);
657     }
658     hp_vec.push_back(c->get_pathvector());
659 }
660 
661 
662 /* ######################## */
663 
664 } //namespace LivePathEffect
665 } /* namespace Inkscape */
666 
667 
668 
669 
670 /*
671   Local Variables:
672   mode:c++
673   c-file-style:"stroustrup"
674   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
675   indent-tabs-mode:nil
676   fill-column:99
677   End:
678 */
679 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
680