1 #include <boost/python.hpp>
2 #include <cairo.h>
3 #include <toys/path-cairo.h>
4 #include <2geom/sbasis-to-bezier.h>
5 #include <2geom/utils.h>
6 #include <sstream>
7 #include <pycairo/pycairo.h>
8 #include "cairo-helpers.h"
9 
10 using namespace Geom;
11 
12 
13 void
cairo_move_to(cairo_t * cr,Geom::Point p1)14 cairo_move_to (cairo_t *cr, Geom::Point p1) {
15     cairo_move_to(cr, p1[0], p1[1]);
16 }
17 
18 void
cairo_line_to(cairo_t * cr,Geom::Point p1)19 cairo_line_to (cairo_t *cr, Geom::Point p1) {
20     cairo_line_to(cr, p1[0], p1[1]);
21 }
22 
23 void
cairo_curve_to(cairo_t * cr,Geom::Point p1,Geom::Point p2,Geom::Point p3)24 cairo_curve_to (cairo_t *cr, Geom::Point p1,
25         Geom::Point p2, Geom::Point p3) {
26     cairo_curve_to(cr, p1[0], p1[1],
27                p2[0], p2[1],
28                p3[0], p3[1]);
29 }
30 
cairo_rectangle(cairo_t * cr,Rect const & r)31 void cairo_rectangle(cairo_t *cr, Rect const& r) {
32     cairo_rectangle(cr, r.left(), r.top(), r.width(), r.height());
33 }
34 
cairo_convex_hull(cairo_t * cr,ConvexHull const & ch)35 void cairo_convex_hull(cairo_t *cr, ConvexHull const& ch) {
36     if(ch.empty()) return;
37     cairo_move_to(cr, ch.back());
38     for(unsigned i = 0; i < ch.size(); i++) {
39         cairo_line_to(cr, ch[i]);
40     }
41 }
42 
cairo_curve(cairo_t * cr,Curve const & c)43 void cairo_curve(cairo_t *cr, Curve const& c) {
44     if(LineSegment const* line_segment = dynamic_cast<LineSegment const*>(&c)) {
45         cairo_line_to(cr, (*line_segment)[1][0], (*line_segment)[1][1]);
46     }
47     else if(QuadraticBezier const *quadratic_bezier = dynamic_cast<QuadraticBezier const*>(&c)) {
48         std::vector<Point> points = quadratic_bezier->controlPoints();
49         Point b1 = points[0] + (2./3) * (points[1] - points[0]);
50         Point b2 = b1 + (1./3) * (points[2] - points[0]);
51         cairo_curve_to(cr, b1[0], b1[1],
52                        b2[0], b2[1],
53                        points[2][0], points[2][1]);
54     }
55     else if(CubicBezier const *cubic_bezier = dynamic_cast<CubicBezier const*>(&c)) {
56         std::vector<Point> points = cubic_bezier->controlPoints();
57         cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
58     }
59 //    else if(EllipticalArc const *svg_elliptical_arc = dynamic_cast<EllipticalArc *>(c)) {
60 //        //TODO: get at the innards and spit them out to cairo
61 //    }
62     else {
63         //this case handles sbasis as well as all other curve types
64         Path sbasis_path = cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);
65 
66         //recurse to convert the new path resulting from the sbasis to svgd
67         for(Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
68             cairo_curve(cr, *iter);
69         }
70     }
71 }
72 
cairo_path(cairo_t * cr,Path const & p)73 void cairo_path(cairo_t *cr, Path const &p) {
74     cairo_move_to(cr, p.initialPoint()[0], p.initialPoint()[1]);
75     if(p.size() == 0) { // naked moveto
76         cairo_move_to(cr, p.finalPoint()+Point(8,0));
77         cairo_line_to(cr, p.finalPoint()+Point(-8,0));
78         cairo_move_to(cr, p.finalPoint()+Point(0,8));
79         cairo_line_to(cr, p.finalPoint()+Point(0,-8));
80         return;
81     }
82 
83     for(Path::const_iterator iter(p.begin()), end(p.end()); iter != end; ++iter) {
84         cairo_curve(cr, *iter);
85     }
86     if(p.closed())
87         cairo_close_path(cr);
88 }
89 
cairo_path_stitches(cairo_t * cr,Path const & p)90 void cairo_path_stitches(cairo_t *cr, Path const &p) {
91     Path::const_iterator iter;
92     for ( iter = p.begin() ; iter != p.end() ; ++iter ) {
93         Curve const &c=*iter;
94         if (dynamic_cast<Path::StitchSegment const *>(&c)) {
95             cairo_move_to(cr, c.initialPoint()[X], c.initialPoint()[Y]);
96             cairo_line_to(cr, c.finalPoint()[X], c.finalPoint()[Y]);
97 
98             //std::stringstream s;
99             //s << L1(c.finalPoint() - c.initialPoint());
100             //std::string ss = s.str();
101             //draw_text(cr, c.initialPoint()+Point(5,5), ss.c_str(), false, "Serif 6");
102 
103             //std::cout << c.finalPoint() - c.initialPoint() << std::endl;
104         }
105     }
106 }
107 
cairo_path(cairo_t * cr,PathVector const & p)108 void cairo_path(cairo_t *cr, PathVector const &p) {
109     PathVector::const_iterator it;
110     for(it = p.begin(); it != p.end(); ++it) {
111         cairo_path(cr, *it);
112     }
113 }
114 
cairo_path_stitches(cairo_t * cr,PathVector const & p)115 void cairo_path_stitches(cairo_t *cr, PathVector const &p) {
116     PathVector::const_iterator it;
117     for ( it = p.begin() ; it != p.end() ; ++it ) {
118         cairo_path_stitches(cr, *it);
119     }
120 }
121 
122 
cairo_d2_sb(cairo_t * cr,D2<SBasis> const & B)123 void cairo_d2_sb(cairo_t *cr, D2<SBasis> const &B) {
124     cairo_path(cr, path_from_sbasis(B, 0.1));
125 }
126 
cairo_d2_pw_sb(cairo_t * cr,D2<Piecewise<SBasis>> const & p)127 void cairo_d2_pw_sb(cairo_t *cr, D2<Piecewise<SBasis> > const &p) {
128     cairo_pw_d2_sb(cr, sectionize(p));
129 }
130 
cairo_pw_d2_sb(cairo_t * cr,Piecewise<D2<SBasis>> const & p)131 void cairo_pw_d2_sb(cairo_t *cr, Piecewise<D2<SBasis> > const &p) {
132     for(unsigned i = 0; i < p.size(); i++)
133         cairo_d2_sb(cr, p[i]);
134 }
135 
136 #if PY_MAJOR_VERSION < 3
137 static Pycairo_CAPI_t *Pycairo_CAPI = 0;
138 #endif
139 
cairo_t_from_object(boost::python::object cr)140 cairo_t* cairo_t_from_object(boost::python::object cr) {
141 #if PY_MAJOR_VERSION < 3
142   if(!Pycairo_CAPI)
143     Pycairo_IMPORT;
144 #else
145   import_cairo();
146 #endif
147   PycairoContext* pcc = (PycairoContext*)cr.ptr();
148   assert(PyObject_TypeCheck(pcc, &PycairoContext_Type));
149   return PycairoContext_GET(pcc);
150 }
151 
152 
153 
154 /*
155   Local Variables:
156   mode:c++
157   c-file-style:"stroustrup"
158   c-file-offsets:((innamespace . 0)(substatement-open . 0))
159   indent-tabs-mode:nil
160   c-brace-offset:0
161   fill-column:99
162   End:
163   vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
164 */
165