0925becbb55d6dde15287b91df1d68394b2149be
1 #define INKSCAPE_LPE_SPIRO_C
3 /*
4 * Released under GNU GPL, read the file 'COPYING' for more information
5 */
7 #include "live_effects/lpe-spiro.h"
8 #include "display/curve.h"
9 #include <libnr/n-art-bpath.h>
11 #include "live_effects/bezctx.h"
12 #include "live_effects/bezctx_intf.h"
13 #include "live_effects/spiro.h"
15 typedef struct {
16 bezctx base;
17 SPCurve *curve;
18 int is_open;
19 } bezctx_ink;
21 void bezctx_ink_moveto(bezctx *bc, double x, double y, int is_open)
22 {
23 bezctx_ink *bi = (bezctx_ink *) bc;
24 sp_curve_moveto(bi->curve, x, y);
25 }
27 void bezctx_ink_lineto(bezctx *bc, double x, double y)
28 {
29 bezctx_ink *bi = (bezctx_ink *) bc;
30 sp_curve_lineto(bi->curve, x, y);
31 }
33 void bezctx_ink_quadto(bezctx *bc, double xm, double ym, double x3, double y3)
34 {
35 bezctx_ink *bi = (bezctx_ink *) bc;
37 double x0, y0;
38 double x1, y1;
39 double x2, y2;
41 NR::Point last = sp_curve_last_point(bi->curve);
42 x0 = last[NR::X];
43 y0 = last[NR::Y];
44 x1 = xm + (1./3) * (x0 - xm);
45 y1 = ym + (1./3) * (y0 - ym);
46 x2 = xm + (1./3) * (x3 - xm);
47 y2 = ym + (1./3) * (y3 - ym);
49 sp_curve_curveto(bi->curve, x1, y1, x2, y2, x3, y3);
50 }
52 void bezctx_ink_curveto(bezctx *bc, double x1, double y1, double x2, double y2,
53 double x3, double y3)
54 {
55 bezctx_ink *bi = (bezctx_ink *) bc;
56 sp_curve_curveto(bi->curve, x1, y1, x2, y2, x3, y3);
57 }
59 bezctx *
60 new_bezctx_ink(SPCurve *curve) {
61 bezctx_ink *result = g_new(bezctx_ink, 1);
62 result->base.moveto = bezctx_ink_moveto;
63 result->base.lineto = bezctx_ink_lineto;
64 result->base.quadto = bezctx_ink_quadto;
65 result->base.curveto = bezctx_ink_curveto;
66 result->base.mark_knot = NULL;
67 result->curve = curve;
68 return &result->base;
69 }
74 namespace Inkscape {
75 namespace LivePathEffect {
77 LPESpiro::LPESpiro(LivePathEffectObject *lpeobject) :
78 Effect(lpeobject)
79 {
80 }
82 LPESpiro::~LPESpiro()
83 {
84 }
86 void
87 LPESpiro::setup_nodepath(Inkscape::NodePath::Path *np)
88 {
89 }
91 void
92 LPESpiro::doEffect(SPCurve * curve)
93 {
94 SPCurve *csrc = sp_curve_copy(curve);
95 sp_curve_reset(curve);
96 bezctx *bc = new_bezctx_ink(curve);
97 int len = SP_CURVE_LENGTH(csrc);
98 spiro_cp *path = g_new (spiro_cp, len + 1);
99 NArtBpath *bpath = csrc->_bpath;
100 int ib = 0;
101 int ip = 0;
102 bool closed = false;
103 NR::Point pt(0, 0);
104 NArtBpath *first_in_subpath = NULL;
105 while(ib <= len) {
106 path [ip].x = bpath[ib].x3;
107 path [ip].y = bpath[ib].y3;
108 // std::cout << "==" << bpath[ib].code << " ip" << ip << " ib" << ib << "\n";
109 if (bpath[ib].code == NR_END || bpath[ib].code == NR_MOVETO_OPEN || bpath[ib].code == NR_MOVETO) {
110 if (ip != 0) { // run prev subpath
111 int sp_len = 0;
112 if (!closed) {
113 path[ip - 1].ty = '}';
114 sp_len = ip;
115 } else {
116 sp_len = ip - 1;
117 }
118 spiro_seg *s = NULL;
119 //for (int j = 0; j <= sp_len; j ++) printf ("%c\n", path[j].ty);
120 s = run_spiro(path, sp_len);
121 spiro_to_bpath(s, sp_len, bc);
122 free(s);
123 path[0].x = path[ip].x;
124 path[0].y = path[ip].y;
125 ip = 0;
126 }
127 if (bpath[ib].code == NR_MOVETO_OPEN) {
128 closed = false;
129 path[ip].ty = '{';
130 } else {
131 closed = true;
132 if (ib < len)
133 first_in_subpath = &(bpath[ib + 1]);
134 path[ip].ty = 'c';
135 }
136 } else {
137 // this point is not last, so makes sense to find a proper type for it
138 NArtBpath *next = NULL;
139 if (ib < len && (bpath[ib+1].code == NR_END || bpath[ib+1].code == NR_MOVETO_OPEN || bpath[ib+1].code == NR_MOVETO)) { // end of subpath
140 if (closed)
141 next = first_in_subpath;
142 } else {
143 if (ib < len)
144 next = &(bpath[ib+1]);
145 else if (closed)
146 next = first_in_subpath;
147 }
148 if (next) {
149 bool this_is_line = bpath[ib].code == NR_LINETO ||
150 (NR::L2(NR::Point(bpath[ib].x3, bpath[ib].y3) - NR::Point(bpath[ib].x2, bpath[ib].y2)) < 0.001);
151 bool next_is_line = next->code == NR_LINETO ||
152 (NR::L2(NR::Point(bpath[ib].x3, bpath[ib].y3) - NR::Point(next->x1, next->y1)) < 0.001);
153 double this_angle = NR_HUGE;
154 if (this_is_line) {
155 this_angle = atan2 (bpath[ib].x3 - pt[NR::X], bpath[ib].y3 - pt[NR::Y]);
156 } else if (bpath[ib].code == NR_CURVETO) {
157 this_angle = atan2 (bpath[ib].x3 - bpath[ib].x2, bpath[ib].y3 - bpath[ib].y2);
158 }
159 double next_angle = NR_HUGE;
160 if (next_is_line) {
161 next_angle = atan2 (next->x3 - bpath[ib].x3, next->y3 - bpath[ib].y3);
162 } else if (next->code == NR_CURVETO) {
163 next_angle = atan2 (next->x1 - bpath[ib].x3, next->y1 - bpath[ib].y3);
164 }
165 if (this_angle != NR_HUGE && next_angle != NR_HUGE && fabs(this_angle - next_angle) < 0.001) {
166 if (this_is_line && !next_is_line) {
167 path[ip].ty = ']';
168 } else if (next_is_line && !this_is_line) {
169 path[ip].ty = '[';
170 } else {
171 path[ip].ty = 'c';
172 }
173 } else {
174 path[ip].ty = 'v';
176 }
177 if (closed && next == first_in_subpath) {
178 path[0].ty = path[ip].ty;
179 }
180 }
181 }
182 pt = NR::Point(bpath[ib].x3, bpath[ib].y3);
183 ip++;
184 ib++;
185 }
186 g_free (path);
187 }
189 }; //namespace LivePathEffect
190 }; /* namespace Inkscape */
192 /*
193 Local Variables:
194 mode:c++
195 c-file-style:"stroustrup"
196 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
197 indent-tabs-mode:nil
198 fill-column:99
199 End:
200 */
201 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :