1 /* -*- mode: c++; c-basic-offset: 4 -*- */
2
3 #include <Python.h>
4 #define NO_IMPORT_ARRAY
5 #include "numpy/arrayobject.h"
6
7 #include "py_converters.h"
8
9 #include "py_adaptors.h"
10 #include "agg_conv_transform.h"
11 #include "path_converters.h"
12
13 class PathCleanupIterator
14 {
15 typedef agg::conv_transform<py::PathIterator> transformed_path_t;
16 typedef PathNanRemover<transformed_path_t> nan_removal_t;
17 typedef PathClipper<nan_removal_t> clipped_t;
18 typedef PathSnapper<clipped_t> snapped_t;
19 typedef PathSimplifier<snapped_t> simplify_t;
20 typedef Sketch<simplify_t> sketch_t;
21
22 py::PathIterator m_path_iter;
23 agg::trans_affine m_transform;
24 transformed_path_t m_transformed;
25 nan_removal_t m_nan_removed;
26 clipped_t m_clipped;
27 snapped_t m_snapped;
28 simplify_t m_simplify;
29 sketch_t m_sketch;
30
31 public:
PathCleanupIterator(PyObject * path,agg::trans_affine trans,bool remove_nans,bool do_clip,const agg::rect_base<double> & rect,e_snap_mode snap_mode,double stroke_width,bool do_simplify,double sketch_scale,double sketch_length,double sketch_randomness)32 PathCleanupIterator(PyObject *path,
33 agg::trans_affine trans,
34 bool remove_nans,
35 bool do_clip,
36 const agg::rect_base<double> &rect,
37 e_snap_mode snap_mode,
38 double stroke_width,
39 bool do_simplify,
40 double sketch_scale,
41 double sketch_length,
42 double sketch_randomness)
43 : m_transform(trans),
44 m_transformed(m_path_iter, m_transform),
45 m_nan_removed(m_transformed, remove_nans, m_path_iter.has_curves()),
46 m_clipped(m_nan_removed, do_clip && !m_path_iter.has_curves(), rect),
47 m_snapped(m_clipped, snap_mode, m_path_iter.total_vertices(), stroke_width),
48 m_simplify(m_snapped,
49 do_simplify && m_path_iter.should_simplify(),
50 m_path_iter.simplify_threshold()),
51 m_sketch(m_simplify, sketch_scale, sketch_length, sketch_randomness)
52 {
53 convert_path(path, &m_path_iter);
54
55 Py_INCREF(path);
56 m_path_iter.rewind(0);
57 }
58
vertex(double * x,double * y)59 unsigned vertex(double *x, double *y)
60 {
61 return m_simplify.vertex(x, y);
62 }
63 };
64
65 extern "C" {
get_path_iterator(PyObject * path,PyObject * trans,int remove_nans,int do_clip,double rect[4],e_snap_mode snap_mode,double stroke_width,int do_simplify,double sketch_scale,double sketch_length,double sketch_randomness)66 void *get_path_iterator(PyObject *path,
67 PyObject *trans,
68 int remove_nans,
69 int do_clip,
70 double rect[4],
71 e_snap_mode snap_mode,
72 double stroke_width,
73 int do_simplify,
74 double sketch_scale,
75 double sketch_length,
76 double sketch_randomness)
77 {
78 agg::trans_affine agg_trans;
79 if (!convert_trans_affine(trans, &agg_trans)) {
80 return NULL;
81 }
82 agg::rect_base<double> clip_rect(rect[0], rect[1], rect[2], rect[3]);
83
84 PathCleanupIterator *pipeline = new PathCleanupIterator(path,
85 agg_trans,
86 remove_nans != 0,
87 do_clip != 0,
88 clip_rect,
89 snap_mode,
90 stroke_width,
91 do_simplify != 0,
92 sketch_scale,
93 sketch_length,
94 sketch_randomness);
95
96 return (void *)pipeline;
97 }
98
get_vertex(void * pipeline,double * x,double * y)99 unsigned get_vertex(void *pipeline, double *x, double *y)
100 {
101 PathCleanupIterator *pipeline_iter = (PathCleanupIterator *)pipeline;
102
103 unsigned code = pipeline_iter->vertex(x, y);
104 return code;
105 }
106
free_path_iterator(void * pipeline)107 void free_path_iterator(void *pipeline)
108 {
109 PathCleanupIterator *pipeline_iter = (PathCleanupIterator *)pipeline;
110
111 delete pipeline_iter;
112 }
113 }
114