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