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