summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/2geom/src/py2geom/cairo-helpers.cpp
blob: c3414393911a2f8da99a0d7724cce1fa01aa864f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <boost/python.hpp>
#include <cairo.h>
#include <toys/path-cairo.h>
#include <2geom/sbasis-to-bezier.h>
#include <2geom/utils.h>
#include <sstream>
#include <pycairo/pycairo.h>
#include "cairo-helpers.h"

using namespace Geom;


void
cairo_move_to (cairo_t *cr, Geom::Point p1) {
    cairo_move_to(cr, p1[0], p1[1]);
}

void
cairo_line_to (cairo_t *cr, Geom::Point p1) {
    cairo_line_to(cr, p1[0], p1[1]);
}

void
cairo_curve_to (cairo_t *cr, Geom::Point p1, 
        Geom::Point p2, Geom::Point p3) {
    cairo_curve_to(cr, p1[0], p1[1],
               p2[0], p2[1],
               p3[0], p3[1]);
}

void cairo_rectangle(cairo_t *cr, Rect const& r) {
    cairo_rectangle(cr, r.left(), r.top(), r.width(), r.height());
}

void cairo_convex_hull(cairo_t *cr, ConvexHull const& ch) {
    if(ch.empty()) return;
    cairo_move_to(cr, ch.back());
    for(unsigned i = 0; i < ch.size(); i++) {
        cairo_line_to(cr, ch[i]);
    }
}

void cairo_curve(cairo_t *cr, Curve const& c) {
    if(LineSegment const* line_segment = dynamic_cast<LineSegment const*>(&c)) {
        cairo_line_to(cr, (*line_segment)[1][0], (*line_segment)[1][1]);
    }
    else if(QuadraticBezier const *quadratic_bezier = dynamic_cast<QuadraticBezier const*>(&c)) {
        std::vector<Point> points = quadratic_bezier->controlPoints();
        Point b1 = points[0] + (2./3) * (points[1] - points[0]);
        Point b2 = b1 + (1./3) * (points[2] - points[0]);
        cairo_curve_to(cr, b1[0], b1[1], 
                       b2[0], b2[1], 
                       points[2][0], points[2][1]);
    }
    else if(CubicBezier const *cubic_bezier = dynamic_cast<CubicBezier const*>(&c)) {
        std::vector<Point> points = cubic_bezier->controlPoints();
        cairo_curve_to(cr, points[1][0], points[1][1], points[2][0], points[2][1], points[3][0], points[3][1]);
    }
//    else if(EllipticalArc const *svg_elliptical_arc = dynamic_cast<EllipticalArc *>(c)) {
//        //TODO: get at the innards and spit them out to cairo
//    }
    else {
        //this case handles sbasis as well as all other curve types
        Path sbasis_path = cubicbezierpath_from_sbasis(c.toSBasis(), 0.1);

        //recurse to convert the new path resulting from the sbasis to svgd
        for(Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
            cairo_curve(cr, *iter);
        }
    }
}

void cairo_path(cairo_t *cr, Path const &p) {
    cairo_move_to(cr, p.initialPoint()[0], p.initialPoint()[1]);
    if(p.size() == 0) { // naked moveto
        cairo_move_to(cr, p.finalPoint()+Point(8,0));
        cairo_line_to(cr, p.finalPoint()+Point(-8,0));
        cairo_move_to(cr, p.finalPoint()+Point(0,8));
        cairo_line_to(cr, p.finalPoint()+Point(0,-8));
        return;
    }

    for(Path::const_iterator iter(p.begin()), end(p.end()); iter != end; ++iter) {
        cairo_curve(cr, *iter);
    }
    if(p.closed())
        cairo_close_path(cr);
}

void cairo_path_stitches(cairo_t *cr, Path const &p) {
    Path::const_iterator iter;
    for ( iter = p.begin() ; iter != p.end() ; ++iter ) {
        Curve const &c=*iter;
        if (dynamic_cast<Path::StitchSegment const *>(&c)) {
            cairo_move_to(cr, c.initialPoint()[X], c.initialPoint()[Y]);
            cairo_line_to(cr, c.finalPoint()[X], c.finalPoint()[Y]);
            
            //std::stringstream s;
            //s << L1(c.finalPoint() - c.initialPoint());
            //std::string ss = s.str();
            //draw_text(cr, c.initialPoint()+Point(5,5), ss.c_str(), false, "Serif 6");

            //std::cout << c.finalPoint() - c.initialPoint() << std::endl;
        }
    }
}

void cairo_path(cairo_t *cr, PathVector const &p) {
    PathVector::const_iterator it;
    for(it = p.begin(); it != p.end(); ++it) {
        cairo_path(cr, *it);
    }
}

void cairo_path_stitches(cairo_t *cr, PathVector const &p) {
    PathVector::const_iterator it;
    for ( it = p.begin() ; it != p.end() ; ++it ) {
        cairo_path_stitches(cr, *it);
    }
}


void cairo_d2_sb(cairo_t *cr, D2<SBasis> const &B) {
    cairo_path(cr, path_from_sbasis(B, 0.1));
}

void cairo_d2_pw_sb(cairo_t *cr, D2<Piecewise<SBasis> > const &p) {
    cairo_pw_d2_sb(cr, sectionize(p));
}

void cairo_pw_d2_sb(cairo_t *cr, Piecewise<D2<SBasis> > const &p) {
    for(unsigned i = 0; i < p.size(); i++)
        cairo_d2_sb(cr, p[i]);
}

#if PY_MAJOR_VERSION < 3
static Pycairo_CAPI_t *Pycairo_CAPI = 0;
#endif

cairo_t* cairo_t_from_object(boost::python::object cr) {
#if PY_MAJOR_VERSION < 3
  if(!Pycairo_CAPI)
    Pycairo_IMPORT;
#else
  import_cairo();
#endif
  PycairoContext* pcc = (PycairoContext*)cr.ptr();
  assert(PyObject_TypeCheck(pcc, &PycairoContext_Type));
  return PycairoContext_GET(pcc);
}



/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(substatement-open . 0))
  indent-tabs-mode:nil
  c-brace-offset:0
  fill-column:99
  End:
  vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
*/