1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7
8 #include "scribushelper.h"
9
10 // Functions to convert from lib2geom to FPointArray and vice versa
scribus_curve(FPointArray * cr,Geom::Curve const & c)11 void scribus_curve(FPointArray *cr, Geom::Curve const& c)
12 {
13 if(Geom::LineSegment const* line_segment = dynamic_cast<Geom::LineSegment const*>(&c))
14 {
15 cr->addPoint(currentPoint);
16 cr->addPoint(currentPoint);
17 cr->addPoint((*line_segment)[1][0], (*line_segment)[1][1]);
18 cr->addPoint((*line_segment)[1][0], (*line_segment)[1][1]);
19 currentPoint = FPoint((*line_segment)[1][0], (*line_segment)[1][1]);
20 }
21 else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c))
22 {
23 std::vector<Geom::Point> points = quadratic_bezier->points();
24 Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]);
25 Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]);
26 cr->addPoint(currentPoint);
27 cr->addPoint(b1[0], b1[1]);
28 cr->addPoint(points[2][0], points[2][1]);
29 cr->addPoint(b2[0], b2[1]);
30 currentPoint = FPoint(points[2][0], points[2][1]);
31 }
32 else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const*>(&c))
33 {
34 std::vector<Geom::Point> points = cubic_bezier->points();
35 cr->addPoint(currentPoint);
36 cr->addPoint(points[1][0], points[1][1]);
37 cr->addPoint(points[3][0], points[3][1]);
38 cr->addPoint(points[2][0], points[2][1]);
39 currentPoint = FPoint(points[3][0], points[3][1]);
40 }
41 else
42 {
43 //this case handles sbasis as well as all other curve types
44 Geom::Path sbasis_path = Geom::path_from_sbasis(c.toSBasis(), 0.1);
45 currentPoint = FPoint(sbasis_path.initialPoint()[0], sbasis_path.initialPoint()[1]);
46 //recurse to convert the new path resulting from the sbasis to svgd
47 for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter)
48 {
49 scribus_curve(cr, *iter);
50 }
51 }
52 }
53
geomPath2FPointArray(FPointArray * p,Geom::Path & pp)54 void geomPath2FPointArray(FPointArray *p, Geom::Path &pp)
55 {
56 currentPoint = FPoint(pp.initialPoint()[0], pp.initialPoint()[1]);
57 for(Geom::Path::iterator iter(pp.begin()), end(pp.end()); iter != end; ++iter)
58 {
59 scribus_curve(p, *iter);
60 }
61 if (pp.closed())
62 p->setMarker();
63 }
64
Piecewise2FPointArray(FPointArray * p,Geom::Piecewise<Geom::D2<Geom::SBasis>> & pp)65 void Piecewise2FPointArray(FPointArray *p, Geom::Piecewise<Geom::D2<Geom::SBasis> > &pp)
66 {
67 std::vector<Geom::Path> pa = path_from_piecewise( pp, 0.1);
68 std::vector<Geom::Path>::iterator it(pa.begin());
69 for(; it != pa.end(); it++)
70 {
71 geomPath2FPointArray(p, *it);
72 }
73 }
74
D2sb2d2FPointArray(FPointArray * cr,Geom::D2<Geom::SBasis2d> const & sb2,int num,double width)75 void D2sb2d2FPointArray(FPointArray* cr, Geom::D2<Geom::SBasis2d> const &sb2, int num, double width)
76 {
77 Geom::D2<Geom::SBasis> B;
78 for(int ui = 0; ui <= num; ui++)
79 {
80 double u = ui / static_cast<double>(num);
81 B[0] = extract_u(sb2[0], u);// + Linear(u);
82 B[1] = extract_u(sb2[1], u);
83 for(unsigned i = 0; i < 2; i ++)
84 {
85 B[i] = B[i]*(width/2) + Geom::Linear(width/4);
86 }
87 Geom::Path pp = path_from_sbasis(B, 0.1);
88 geomPath2FPointArray(cr, pp);
89 cr->setMarker();
90 }
91 for(int vi = 0; vi <= num; vi++)
92 {
93 double v = vi / static_cast<double>(num);
94 B[1] = extract_v(sb2[1], v);// + Linear(v);
95 B[0] = extract_v(sb2[0], v);
96 for(unsigned i = 0; i < 2; i ++)
97 {
98 B[i] = B[i]*(width/2) + Geom::Linear(width/4);
99 }
100 Geom::Path pp = path_from_sbasis(B, 0.1);
101 geomPath2FPointArray(cr, pp);
102 cr->setMarker();
103 }
104 }
105
FPointArray2geomPath(FPointArray & p,bool closed)106 std::vector<Geom::Path> FPointArray2geomPath(FPointArray &p, bool closed)
107 {
108 std::vector<Geom::Path> pa;
109 Geom::Path ret = Geom::Path();
110 Geom::Point cur;
111 FPoint np, np1, np2, np3;
112 bool nPath = true;
113 if (p.size() > 3)
114 {
115 for (int poi=0; poi < p.size()-3; poi += 4)
116 {
117 if (p.isMarker(poi))
118 {
119 if (closed)
120 ret.close();
121 pa.push_back(ret);
122 ret.clear();
123 nPath = true;
124 continue;
125 }
126 if (nPath)
127 {
128 np = p.point(poi);
129 cur = Geom::Point(np.x(), np.y());
130 nPath = false;
131 }
132 np = p.point(poi);
133 np1 = p.point(poi+1);
134 np2 = p.point(poi+3);
135 np3 = p.point(poi+2);
136 if ((np == np1) && (np2 == np3))
137 {
138 // Geom::Point pe = Geom::Point(np3.x(), np3.y());
139 // ret.append(Geom::LineSegment(cur, pe));
140 Geom::Point pc1 = Geom::Point(np1.x()+0.001, np1.y()+0.001);
141 Geom::Point pc2 = Geom::Point(np2.x()+0.001, np2.y()+0.001);
142 Geom::Point pe = Geom::Point(np3.x(), np3.y());
143 ret.append(Geom::CubicBezier(cur, pc1, pc2, pe));
144 cur = pe;
145 }
146 else
147 {
148 Geom::Point pc1 = Geom::Point(np1.x(), np1.y());
149 Geom::Point pc2 = Geom::Point(np2.x(), np2.y());
150 Geom::Point pe = Geom::Point(np3.x(), np3.y());
151 ret.append(Geom::CubicBezier(cur, pc1, pc2, pe));
152 cur = pe;
153 }
154 }
155 }
156 if (closed)
157 ret.close();
158 pa.push_back(ret);
159 return pa;
160 }
161
FPointArray2Piecewise(FPointArray & p,bool closed)162 Geom::Piecewise<Geom::D2<Geom::SBasis> > FPointArray2Piecewise(FPointArray &p, bool closed)
163 {
164 Geom::Piecewise<Geom::D2<Geom::SBasis> > patternpwd2;
165 std::vector<Geom::Path> originald = FPointArray2geomPath(p, closed);
166 for (unsigned int i=0; i < originald.size(); i++)
167 {
168 patternpwd2.concat( originald[i].toPwSb() );
169 }
170 return patternpwd2;
171 }
172
173 // Functions to convert from lib2geom to QPainterPath and vice versa
arthur_curve(QPainterPath * cr,Geom::Curve const & c)174 void arthur_curve(QPainterPath *cr, Geom::Curve const& c)
175 {
176 if(Geom::LineSegment const* line_segment = dynamic_cast<Geom::LineSegment const*>(&c))
177 {
178 cr->lineTo(QPointF((*line_segment)[1][0], (*line_segment)[1][1]));
179 }
180 else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const*>(&c))
181 {
182 std::vector<Geom::Point> points = quadratic_bezier->points();
183 Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]);
184 Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]);
185 cr->cubicTo(b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]);
186 }
187 else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const*>(&c))
188 {
189 std::vector<Geom::Point> points = cubic_bezier->points();
190 cr->cubicTo(points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
191 }
192 else
193 {
194 //this case handles sbasis as well as all other curve types
195 Geom::Path sbasis_path = Geom::path_from_sbasis(c.toSBasis(), 0.1);
196 cr->moveTo(sbasis_path.initialPoint()[0], sbasis_path.initialPoint()[1]);
197 //recurse to convert the new path resulting from the sbasis to svgd
198 for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter)
199 {
200 arthur_curve(cr, *iter);
201 }
202 }
203 }
204
geomPath2QPainterPath(QPainterPath * p,Geom::Path & pp)205 void geomPath2QPainterPath(QPainterPath *p, Geom::Path &pp)
206 {
207 p->moveTo(pp.initialPoint()[0], pp.initialPoint()[1]);
208 for(Geom::Path::iterator iter(pp.begin()), end(pp.end()); iter != end; ++iter)
209 {
210 arthur_curve(p, *iter);
211 }
212 if (pp.closed())
213 p->closeSubpath();
214 }
215
Piecewise2QPainterPath(QPainterPath * p,Geom::Piecewise<Geom::D2<Geom::SBasis>> & pp)216 void Piecewise2QPainterPath(QPainterPath *p, Geom::Piecewise<Geom::D2<Geom::SBasis> > &pp)
217 {
218 std::vector<Geom::Path> pa = path_from_piecewise( pp, 0.1);
219 std::vector<Geom::Path>::iterator it(pa.begin());
220 for(; it != pa.end(); it++)
221 {
222 geomPath2QPainterPath(p, *it);
223 }
224 }
225
D2sb2d2QPainterPath(QPainterPath * cr,Geom::D2<Geom::SBasis2d> const & sb2,int num,double width)226 void D2sb2d2QPainterPath(QPainterPath* cr, Geom::D2<Geom::SBasis2d> const &sb2, int num, double width)
227 {
228 Geom::D2<Geom::SBasis> B;
229 for(int ui = 0; ui <= num; ui++)
230 {
231 double u = ui / static_cast<double>(num);
232 B[0] = extract_u(sb2[0], u);// + Linear(u);
233 B[1] = extract_u(sb2[1], u);
234 for(unsigned i = 0; i < 2; i ++)
235 {
236 B[i] = B[i]*(width/2) + Geom::Linear(width/4);
237 }
238 Geom::Path pp = path_from_sbasis(B, 0.1);
239 geomPath2QPainterPath(cr, pp);
240 // cr->setMarker();
241 }
242 for(int vi = 0; vi <= num; vi++)
243 {
244 double v = vi / static_cast<double>(num);
245 B[1] = extract_v(sb2[1], v);// + Linear(v);
246 B[0] = extract_v(sb2[0], v);
247 for(unsigned i = 0; i < 2; i ++)
248 {
249 B[i] = B[i]*(width/2) + Geom::Linear(width/4);
250 }
251 Geom::Path pp = path_from_sbasis(B, 0.1);
252 geomPath2QPainterPath(cr, pp);
253 // cr->setMarker();
254 }
255 }
256
QPainterPath2geomPath(QPainterPath & p,bool closed)257 std::vector<Geom::Path> QPainterPath2geomPath(QPainterPath &p, bool closed)
258 {
259 std::vector<Geom::Path> pa;
260 Geom::Path ret = Geom::Path();
261 Geom::Point cur;
262 bool WasM = false;
263 for (int i = 0; i < p.elementCount(); ++i)
264 {
265 const QPainterPath::Element &elm = p.elementAt(i);
266 switch (elm.type)
267 {
268 case QPainterPath::MoveToElement:
269 if (WasM)
270 {
271 if (closed)
272 ret.close();
273 pa.push_back(ret);
274 ret.clear();
275 }
276 WasM = true;
277 cur = Geom::Point(elm.x, elm.y);
278 break;
279 case QPainterPath::LineToElement:
280 ret.append(Geom::LineSegment(cur, Geom::Point(elm.x, elm.y)));
281 cur = Geom::Point(elm.x, elm.y);
282 break;
283 case QPainterPath::CurveToElement:
284 {
285 Geom::Point pc1 = Geom::Point(elm.x, elm.y);
286 Geom::Point pc2 = Geom::Point(p.elementAt(i+1).x, p.elementAt(i+1).y);
287 Geom::Point pe = Geom::Point(p.elementAt(i+2).x, p.elementAt(i+2).y);
288 ret.append(Geom::CubicBezier(cur, pc1, pc2, pe));
289 cur = pe;
290 }
291 break;
292 default:
293 break;
294 }
295 }
296 if (closed)
297 ret.close();
298 pa.push_back(ret);
299 return pa;
300 }
301
QPainterPath2Piecewise(QPainterPath & p,bool closed)302 Geom::Piecewise<Geom::D2<Geom::SBasis> > QPainterPath2Piecewise(QPainterPath &p, bool closed)
303 {
304 Geom::Piecewise<Geom::D2<Geom::SBasis> > patternpwd2;
305 std::vector<Geom::Path> originald = QPainterPath2geomPath(p, closed);
306 for (unsigned int i=0; i < originald.size(); i++)
307 {
308 patternpwd2.concat( originald[i].toPwSb() );
309 }
310 return patternpwd2;
311 }
312