/* For general Scribus (>=1.3.2) copyright and licensing information please refer to the COPYING file provided with the program. Following this notice may exist a copyright and/or license notice that predates the release of Scribus 1.3.2 for which a new license (GPL+exception) is in place. */ #include "scribushelper.h" // Functions to convert from lib2geom to FPointArray and vice versa void scribus_curve(FPointArray *cr, Geom::Curve const& c) { if(Geom::LineSegment const* line_segment = dynamic_cast(&c)) { cr->addPoint(currentPoint); cr->addPoint(currentPoint); cr->addPoint((*line_segment)[1][0], (*line_segment)[1][1]); cr->addPoint((*line_segment)[1][0], (*line_segment)[1][1]); currentPoint = FPoint((*line_segment)[1][0], (*line_segment)[1][1]); } else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast(&c)) { std::vector points = quadratic_bezier->points(); Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]); Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]); cr->addPoint(currentPoint); cr->addPoint(b1[0], b1[1]); cr->addPoint(points[2][0], points[2][1]); cr->addPoint(b2[0], b2[1]); currentPoint = FPoint(points[2][0], points[2][1]); } else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast(&c)) { std::vector points = cubic_bezier->points(); cr->addPoint(currentPoint); cr->addPoint(points[1][0], points[1][1]); cr->addPoint(points[3][0], points[3][1]); cr->addPoint(points[2][0], points[2][1]); currentPoint = FPoint(points[3][0], points[3][1]); } else { //this case handles sbasis as well as all other curve types Geom::Path sbasis_path = Geom::path_from_sbasis(c.toSBasis(), 0.1); currentPoint = FPoint(sbasis_path.initialPoint()[0], sbasis_path.initialPoint()[1]); //recurse to convert the new path resulting from the sbasis to svgd for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) { scribus_curve(cr, *iter); } } } void geomPath2FPointArray(FPointArray *p, Geom::Path &pp) { currentPoint = FPoint(pp.initialPoint()[0], pp.initialPoint()[1]); for(Geom::Path::iterator iter(pp.begin()), end(pp.end()); iter != end; ++iter) { scribus_curve(p, *iter); } if (pp.closed()) p->setMarker(); } void Piecewise2FPointArray(FPointArray *p, Geom::Piecewise > &pp) { std::vector pa = path_from_piecewise( pp, 0.1); std::vector::iterator it(pa.begin()); for(; it != pa.end(); it++) { geomPath2FPointArray(p, *it); } } void D2sb2d2FPointArray(FPointArray* cr, Geom::D2 const &sb2, int num, double width) { Geom::D2 B; for(int ui = 0; ui <= num; ui++) { double u = ui / static_cast(num); B[0] = extract_u(sb2[0], u);// + Linear(u); B[1] = extract_u(sb2[1], u); for(unsigned i = 0; i < 2; i ++) { B[i] = B[i]*(width/2) + Geom::Linear(width/4); } Geom::Path pp = path_from_sbasis(B, 0.1); geomPath2FPointArray(cr, pp); cr->setMarker(); } for(int vi = 0; vi <= num; vi++) { double v = vi / static_cast(num); B[1] = extract_v(sb2[1], v);// + Linear(v); B[0] = extract_v(sb2[0], v); for(unsigned i = 0; i < 2; i ++) { B[i] = B[i]*(width/2) + Geom::Linear(width/4); } Geom::Path pp = path_from_sbasis(B, 0.1); geomPath2FPointArray(cr, pp); cr->setMarker(); } } std::vector FPointArray2geomPath(FPointArray &p, bool closed) { std::vector pa; Geom::Path ret = Geom::Path(); Geom::Point cur; FPoint np, np1, np2, np3; bool nPath = true; if (p.size() > 3) { for (uint poi=0; poi < p.size()-3; poi += 4) { if (p.point(poi).x() > 900000) { if (closed) ret.close(); pa.push_back(ret); ret.clear(); nPath = true; continue; } if (nPath) { np = p.point(poi); cur = Geom::Point(np.x(), np.y()); nPath = false; } np = p.point(poi); np1 = p.point(poi+1); np2 = p.point(poi+3); np3 = p.point(poi+2); if ((np == np1) && (np2 == np3)) { // Geom::Point pe = Geom::Point(np3.x(), np3.y()); // ret.append(Geom::LineSegment(cur, pe)); Geom::Point pc1 = Geom::Point(np1.x()+0.001, np1.y()+0.001); Geom::Point pc2 = Geom::Point(np2.x()+0.001, np2.y()+0.001); Geom::Point pe = Geom::Point(np3.x(), np3.y()); ret.append(Geom::CubicBezier(cur, pc1, pc2, pe)); cur = pe; } else { Geom::Point pc1 = Geom::Point(np1.x(), np1.y()); Geom::Point pc2 = Geom::Point(np2.x(), np2.y()); Geom::Point pe = Geom::Point(np3.x(), np3.y()); ret.append(Geom::CubicBezier(cur, pc1, pc2, pe)); cur = pe; } } } if (closed) ret.close(); pa.push_back(ret); return pa; } Geom::Piecewise > FPointArray2Piecewise(FPointArray &p, bool closed) { Geom::Piecewise > patternpwd2; std::vector originald = FPointArray2geomPath(p, closed); for (unsigned int i=0; i < originald.size(); i++) { patternpwd2.concat( originald[i].toPwSb() ); } return patternpwd2; } // Functions to convert from lib2geom to QPainterPath and vice versa void arthur_curve(QPainterPath *cr, Geom::Curve const& c) { if(Geom::LineSegment const* line_segment = dynamic_cast(&c)) { cr->lineTo(QPointF((*line_segment)[1][0], (*line_segment)[1][1])); } else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast(&c)) { std::vector points = quadratic_bezier->points(); Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]); Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]); cr->cubicTo(b1[0], b1[1], b2[0], b2[1], points[2][0], points[2][1]); } else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast(&c)) { std::vector points = cubic_bezier->points(); cr->cubicTo(points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]); } else { //this case handles sbasis as well as all other curve types Geom::Path sbasis_path = Geom::path_from_sbasis(c.toSBasis(), 0.1); cr->moveTo(sbasis_path.initialPoint()[0], sbasis_path.initialPoint()[1]); //recurse to convert the new path resulting from the sbasis to svgd for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) { arthur_curve(cr, *iter); } } } void geomPath2QPainterPath(QPainterPath *p, Geom::Path &pp) { p->moveTo(pp.initialPoint()[0], pp.initialPoint()[1]); for(Geom::Path::iterator iter(pp.begin()), end(pp.end()); iter != end; ++iter) { arthur_curve(p, *iter); } if (pp.closed()) p->closeSubpath(); } void Piecewise2QPainterPath(QPainterPath *p, Geom::Piecewise > &pp) { std::vector pa = path_from_piecewise( pp, 0.1); std::vector::iterator it(pa.begin()); for(; it != pa.end(); it++) { geomPath2QPainterPath(p, *it); } } void D2sb2d2QPainterPath(QPainterPath* cr, Geom::D2 const &sb2, int num, double width) { Geom::D2 B; for(int ui = 0; ui <= num; ui++) { double u = ui / static_cast(num); B[0] = extract_u(sb2[0], u);// + Linear(u); B[1] = extract_u(sb2[1], u); for(unsigned i = 0; i < 2; i ++) { B[i] = B[i]*(width/2) + Geom::Linear(width/4); } Geom::Path pp = path_from_sbasis(B, 0.1); geomPath2QPainterPath(cr, pp); // cr->setMarker(); } for(int vi = 0; vi <= num; vi++) { double v = vi / static_cast(num); B[1] = extract_v(sb2[1], v);// + Linear(v); B[0] = extract_v(sb2[0], v); for(unsigned i = 0; i < 2; i ++) { B[i] = B[i]*(width/2) + Geom::Linear(width/4); } Geom::Path pp = path_from_sbasis(B, 0.1); geomPath2QPainterPath(cr, pp); // cr->setMarker(); } } std::vector QPainterPath2geomPath(QPainterPath &p, bool closed) { std::vector pa; Geom::Path ret = Geom::Path(); Geom::Point cur; bool WasM = false; for (int i = 0; i < p.elementCount(); ++i) { const QPainterPath::Element &elm = p.elementAt(i); switch (elm.type) { case QPainterPath::MoveToElement: if (WasM) { if (closed) ret.close(); pa.push_back(ret); ret.clear(); } WasM = true; cur = Geom::Point(elm.x, elm.y); break; case QPainterPath::LineToElement: ret.append(Geom::LineSegment(cur, Geom::Point(elm.x, elm.y))); cur = Geom::Point(elm.x, elm.y); break; case QPainterPath::CurveToElement: { Geom::Point pc1 = Geom::Point(elm.x, elm.y); Geom::Point pc2 = Geom::Point(p.elementAt(i+1).x, p.elementAt(i+1).y); Geom::Point pe = Geom::Point(p.elementAt(i+2).x, p.elementAt(i+2).y); ret.append(Geom::CubicBezier(cur, pc1, pc2, pe)); cur = pe; } break; default: break; } } if (closed) ret.close(); pa.push_back(ret); return pa; } Geom::Piecewise > QPainterPath2Piecewise(QPainterPath &p, bool closed) { Geom::Piecewise > patternpwd2; std::vector originald = QPainterPath2geomPath(p, closed); for (unsigned int i=0; i < originald.size(); i++) { patternpwd2.concat( originald[i].toPwSb() ); } return patternpwd2; }