1 #include "mplutils.h"
2 #include "py_converters.h"
3 #include "_backend_agg.h"
4
5 typedef struct
6 {
7 PyObject_HEAD
8 RendererAgg *x;
9 Py_ssize_t shape[3];
10 Py_ssize_t strides[3];
11 Py_ssize_t suboffsets[3];
12 } PyRendererAgg;
13
14 typedef struct
15 {
16 PyObject_HEAD
17 BufferRegion *x;
18 Py_ssize_t shape[3];
19 Py_ssize_t strides[3];
20 Py_ssize_t suboffsets[3];
21 } PyBufferRegion;
22
23
24 /**********************************************************************
25 * BufferRegion
26 * */
27
PyBufferRegion_new(PyTypeObject * type,PyObject * args,PyObject * kwds)28 static PyObject *PyBufferRegion_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
29 {
30 PyBufferRegion *self;
31 self = (PyBufferRegion *)type->tp_alloc(type, 0);
32 self->x = NULL;
33 return (PyObject *)self;
34 }
35
PyBufferRegion_dealloc(PyBufferRegion * self)36 static void PyBufferRegion_dealloc(PyBufferRegion *self)
37 {
38 delete self->x;
39 Py_TYPE(self)->tp_free((PyObject *)self);
40 }
41
PyBufferRegion_to_string(PyBufferRegion * self,PyObject * args,PyObject * kwds)42 static PyObject *PyBufferRegion_to_string(PyBufferRegion *self, PyObject *args, PyObject *kwds)
43 {
44 return PyBytes_FromStringAndSize((const char *)self->x->get_data(),
45 self->x->get_height() * self->x->get_stride());
46 }
47
48 /* TODO: This doesn't seem to be used internally. Remove? */
49
PyBufferRegion_set_x(PyBufferRegion * self,PyObject * args,PyObject * kwds)50 static PyObject *PyBufferRegion_set_x(PyBufferRegion *self, PyObject *args, PyObject *kwds)
51 {
52 int x;
53 if (!PyArg_ParseTuple(args, "i:set_x", &x)) {
54 return NULL;
55 }
56 self->x->get_rect().x1 = x;
57
58 Py_RETURN_NONE;
59 }
60
PyBufferRegion_set_y(PyBufferRegion * self,PyObject * args,PyObject * kwds)61 static PyObject *PyBufferRegion_set_y(PyBufferRegion *self, PyObject *args, PyObject *kwds)
62 {
63 int y;
64 if (!PyArg_ParseTuple(args, "i:set_y", &y)) {
65 return NULL;
66 }
67 self->x->get_rect().y1 = y;
68
69 Py_RETURN_NONE;
70 }
71
PyBufferRegion_get_extents(PyBufferRegion * self,PyObject * args,PyObject * kwds)72 static PyObject *PyBufferRegion_get_extents(PyBufferRegion *self, PyObject *args, PyObject *kwds)
73 {
74 agg::rect_i rect = self->x->get_rect();
75
76 return Py_BuildValue("IIII", rect.x1, rect.y1, rect.x2, rect.y2);
77 }
78
PyBufferRegion_to_string_argb(PyBufferRegion * self,PyObject * args,PyObject * kwds)79 static PyObject *PyBufferRegion_to_string_argb(PyBufferRegion *self, PyObject *args, PyObject *kwds)
80 {
81 PyObject *bufobj;
82 uint8_t *buf;
83
84 bufobj = PyBytes_FromStringAndSize(NULL, self->x->get_height() * self->x->get_stride());
85 buf = (uint8_t *)PyBytes_AS_STRING(bufobj);
86
87 CALL_CPP_CLEANUP("to_string_argb", (self->x->to_string_argb(buf)), Py_DECREF(bufobj));
88
89 return bufobj;
90 }
91
PyBufferRegion_get_buffer(PyBufferRegion * self,Py_buffer * buf,int flags)92 int PyBufferRegion_get_buffer(PyBufferRegion *self, Py_buffer *buf, int flags)
93 {
94 Py_INCREF(self);
95 buf->obj = (PyObject *)self;
96 buf->buf = self->x->get_data();
97 buf->len = self->x->get_width() * self->x->get_height() * 4;
98 buf->readonly = 0;
99 buf->format = (char *)"B";
100 buf->ndim = 3;
101 self->shape[0] = self->x->get_height();
102 self->shape[1] = self->x->get_width();
103 self->shape[2] = 4;
104 buf->shape = self->shape;
105 self->strides[0] = self->x->get_width() * 4;
106 self->strides[1] = 4;
107 self->strides[2] = 1;
108 buf->strides = self->strides;
109 buf->suboffsets = NULL;
110 buf->itemsize = 1;
111 buf->internal = NULL;
112
113 return 1;
114 }
115
116 static PyTypeObject PyBufferRegionType;
117
PyBufferRegion_init_type(PyObject * m,PyTypeObject * type)118 static PyTypeObject *PyBufferRegion_init_type(PyObject *m, PyTypeObject *type)
119 {
120 static PyMethodDef methods[] = {
121 { "to_string", (PyCFunction)PyBufferRegion_to_string, METH_NOARGS, NULL },
122 { "to_string_argb", (PyCFunction)PyBufferRegion_to_string_argb, METH_NOARGS, NULL },
123 { "set_x", (PyCFunction)PyBufferRegion_set_x, METH_VARARGS, NULL },
124 { "set_y", (PyCFunction)PyBufferRegion_set_y, METH_VARARGS, NULL },
125 { "get_extents", (PyCFunction)PyBufferRegion_get_extents, METH_NOARGS, NULL },
126 { NULL }
127 };
128
129 static PyBufferProcs buffer_procs;
130 memset(&buffer_procs, 0, sizeof(PyBufferProcs));
131 buffer_procs.bf_getbuffer = (getbufferproc)PyBufferRegion_get_buffer;
132
133 memset(type, 0, sizeof(PyTypeObject));
134 type->tp_name = "matplotlib.backends._backend_agg.BufferRegion";
135 type->tp_basicsize = sizeof(PyBufferRegion);
136 type->tp_dealloc = (destructor)PyBufferRegion_dealloc;
137 type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER;
138 type->tp_methods = methods;
139 type->tp_new = PyBufferRegion_new;
140 type->tp_as_buffer = &buffer_procs;
141
142 if (PyType_Ready(type) < 0) {
143 return NULL;
144 }
145
146 /* Don't need to add to module, since you can't create buffer
147 regions directly from Python */
148
149 return type;
150 }
151
152 /**********************************************************************
153 * RendererAgg
154 * */
155
PyRendererAgg_new(PyTypeObject * type,PyObject * args,PyObject * kwds)156 static PyObject *PyRendererAgg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
157 {
158 PyRendererAgg *self;
159 self = (PyRendererAgg *)type->tp_alloc(type, 0);
160 self->x = NULL;
161 return (PyObject *)self;
162 }
163
PyRendererAgg_init(PyRendererAgg * self,PyObject * args,PyObject * kwds)164 static int PyRendererAgg_init(PyRendererAgg *self, PyObject *args, PyObject *kwds)
165 {
166 unsigned int width;
167 unsigned int height;
168 double dpi;
169 int debug = 0;
170
171 if (!PyArg_ParseTuple(args, "IId|i:RendererAgg", &width, &height, &dpi, &debug)) {
172 return -1;
173 }
174
175 if (dpi <= 0.0) {
176 PyErr_SetString(PyExc_ValueError, "dpi must be positive");
177 return -1;
178 }
179
180 if (width >= 1 << 16 || height >= 1 << 16) {
181 PyErr_Format(
182 PyExc_ValueError,
183 "Image size of %dx%d pixels is too large. "
184 "It must be less than 2^16 in each direction.",
185 width, height);
186 return -1;
187 }
188
189 CALL_CPP_INIT("RendererAgg", self->x = new RendererAgg(width, height, dpi))
190
191 return 0;
192 }
193
PyRendererAgg_dealloc(PyRendererAgg * self)194 static void PyRendererAgg_dealloc(PyRendererAgg *self)
195 {
196 delete self->x;
197 Py_TYPE(self)->tp_free((PyObject *)self);
198 }
199
PyRendererAgg_draw_path(PyRendererAgg * self,PyObject * args,PyObject * kwds)200 static PyObject *PyRendererAgg_draw_path(PyRendererAgg *self, PyObject *args, PyObject *kwds)
201 {
202 GCAgg gc;
203 py::PathIterator path;
204 agg::trans_affine trans;
205 PyObject *faceobj = NULL;
206 agg::rgba face;
207
208 if (!PyArg_ParseTuple(args,
209 "O&O&O&|O:draw_path",
210 &convert_gcagg,
211 &gc,
212 &convert_path,
213 &path,
214 &convert_trans_affine,
215 &trans,
216 &faceobj)) {
217 return NULL;
218 }
219
220 if (!convert_face(faceobj, gc, &face)) {
221 return NULL;
222 }
223
224 CALL_CPP("draw_path", (self->x->draw_path(gc, path, trans, face)));
225
226 Py_RETURN_NONE;
227 }
228
PyRendererAgg_draw_text_image(PyRendererAgg * self,PyObject * args,PyObject * kwds)229 static PyObject *PyRendererAgg_draw_text_image(PyRendererAgg *self, PyObject *args, PyObject *kwds)
230 {
231 numpy::array_view<agg::int8u, 2> image;
232 double x;
233 double y;
234 double angle;
235 GCAgg gc;
236
237 if (!PyArg_ParseTuple(args,
238 "O&dddO&:draw_text_image",
239 &image.converter_contiguous,
240 &image,
241 &x,
242 &y,
243 &angle,
244 &convert_gcagg,
245 &gc)) {
246 return NULL;
247 }
248
249 CALL_CPP("draw_text_image", (self->x->draw_text_image(gc, image, x, y, angle)));
250
251 Py_RETURN_NONE;
252 }
253
PyRendererAgg_draw_markers(PyRendererAgg * self,PyObject * args,PyObject * kwds)254 PyObject *PyRendererAgg_draw_markers(PyRendererAgg *self, PyObject *args, PyObject *kwds)
255 {
256 GCAgg gc;
257 py::PathIterator marker_path;
258 agg::trans_affine marker_path_trans;
259 py::PathIterator path;
260 agg::trans_affine trans;
261 PyObject *faceobj = NULL;
262 agg::rgba face;
263
264 if (!PyArg_ParseTuple(args,
265 "O&O&O&O&O&|O:draw_markers",
266 &convert_gcagg,
267 &gc,
268 &convert_path,
269 &marker_path,
270 &convert_trans_affine,
271 &marker_path_trans,
272 &convert_path,
273 &path,
274 &convert_trans_affine,
275 &trans,
276 &faceobj)) {
277 return NULL;
278 }
279
280 if (!convert_face(faceobj, gc, &face)) {
281 return NULL;
282 }
283
284 CALL_CPP("draw_markers",
285 (self->x->draw_markers(gc, marker_path, marker_path_trans, path, trans, face)));
286
287 Py_RETURN_NONE;
288 }
289
PyRendererAgg_draw_image(PyRendererAgg * self,PyObject * args,PyObject * kwds)290 static PyObject *PyRendererAgg_draw_image(PyRendererAgg *self, PyObject *args, PyObject *kwds)
291 {
292 GCAgg gc;
293 double x;
294 double y;
295 numpy::array_view<agg::int8u, 3> image;
296
297 if (!PyArg_ParseTuple(args,
298 "O&ddO&:draw_image",
299 &convert_gcagg,
300 &gc,
301 &x,
302 &y,
303 &image.converter_contiguous,
304 &image)) {
305 return NULL;
306 }
307
308 x = mpl_round(x);
309 y = mpl_round(y);
310
311 gc.alpha = 1.0;
312 CALL_CPP("draw_image", (self->x->draw_image(gc, x, y, image)));
313
314 Py_RETURN_NONE;
315 }
316
317 static PyObject *
PyRendererAgg_draw_path_collection(PyRendererAgg * self,PyObject * args,PyObject * kwds)318 PyRendererAgg_draw_path_collection(PyRendererAgg *self, PyObject *args, PyObject *kwds)
319 {
320 GCAgg gc;
321 agg::trans_affine master_transform;
322 PyObject *pathobj;
323 numpy::array_view<const double, 3> transforms;
324 numpy::array_view<const double, 2> offsets;
325 agg::trans_affine offset_trans;
326 numpy::array_view<const double, 2> facecolors;
327 numpy::array_view<const double, 2> edgecolors;
328 numpy::array_view<const double, 1> linewidths;
329 DashesVector dashes;
330 numpy::array_view<const uint8_t, 1> antialiaseds;
331 PyObject *ignored;
332 e_offset_position offset_position;
333
334 if (!PyArg_ParseTuple(args,
335 "O&O&OO&O&O&O&O&O&O&O&OO&:draw_path_collection",
336 &convert_gcagg,
337 &gc,
338 &convert_trans_affine,
339 &master_transform,
340 &pathobj,
341 &convert_transforms,
342 &transforms,
343 &convert_points,
344 &offsets,
345 &convert_trans_affine,
346 &offset_trans,
347 &convert_colors,
348 &facecolors,
349 &convert_colors,
350 &edgecolors,
351 &linewidths.converter,
352 &linewidths,
353 &convert_dashes_vector,
354 &dashes,
355 &antialiaseds.converter,
356 &antialiaseds,
357 &ignored,
358 &convert_offset_position,
359 &offset_position)) {
360 return NULL;
361 }
362
363 try
364 {
365 py::PathGenerator path(pathobj);
366
367 CALL_CPP("draw_path_collection",
368 (self->x->draw_path_collection(gc,
369 master_transform,
370 path,
371 transforms,
372 offsets,
373 offset_trans,
374 facecolors,
375 edgecolors,
376 linewidths,
377 dashes,
378 antialiaseds,
379 offset_position)));
380 }
381 catch (const py::exception &)
382 {
383 return NULL;
384 }
385
386 Py_RETURN_NONE;
387 }
388
PyRendererAgg_draw_quad_mesh(PyRendererAgg * self,PyObject * args,PyObject * kwds)389 static PyObject *PyRendererAgg_draw_quad_mesh(PyRendererAgg *self, PyObject *args, PyObject *kwds)
390 {
391 GCAgg gc;
392 agg::trans_affine master_transform;
393 unsigned int mesh_width;
394 unsigned int mesh_height;
395 numpy::array_view<const double, 3> coordinates;
396 numpy::array_view<const double, 2> offsets;
397 agg::trans_affine offset_trans;
398 numpy::array_view<const double, 2> facecolors;
399 int antialiased;
400 numpy::array_view<const double, 2> edgecolors;
401
402 if (!PyArg_ParseTuple(args,
403 "O&O&IIO&O&O&O&iO&:draw_quad_mesh",
404 &convert_gcagg,
405 &gc,
406 &convert_trans_affine,
407 &master_transform,
408 &mesh_width,
409 &mesh_height,
410 &coordinates.converter,
411 &coordinates,
412 &convert_points,
413 &offsets,
414 &convert_trans_affine,
415 &offset_trans,
416 &convert_colors,
417 &facecolors,
418 &antialiased,
419 &convert_colors,
420 &edgecolors)) {
421 return NULL;
422 }
423
424 CALL_CPP("draw_quad_mesh",
425 (self->x->draw_quad_mesh(gc,
426 master_transform,
427 mesh_width,
428 mesh_height,
429 coordinates,
430 offsets,
431 offset_trans,
432 facecolors,
433 antialiased,
434 edgecolors)));
435
436 Py_RETURN_NONE;
437 }
438
439 static PyObject *
PyRendererAgg_draw_gouraud_triangle(PyRendererAgg * self,PyObject * args,PyObject * kwds)440 PyRendererAgg_draw_gouraud_triangle(PyRendererAgg *self, PyObject *args, PyObject *kwds)
441 {
442 GCAgg gc;
443 numpy::array_view<const double, 2> points;
444 numpy::array_view<const double, 2> colors;
445 agg::trans_affine trans;
446
447 if (!PyArg_ParseTuple(args,
448 "O&O&O&O&|O:draw_gouraud_triangle",
449 &convert_gcagg,
450 &gc,
451 &points.converter,
452 &points,
453 &colors.converter,
454 &colors,
455 &convert_trans_affine,
456 &trans)) {
457 return NULL;
458 }
459
460 if (points.dim(0) != 3 || points.dim(1) != 2) {
461 PyErr_Format(PyExc_ValueError,
462 "points must be a 3x2 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT,
463 points.dim(0), points.dim(1));
464 return NULL;
465 }
466
467 if (colors.dim(0) != 3 || colors.dim(1) != 4) {
468 PyErr_Format(PyExc_ValueError,
469 "colors must be a 3x4 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT,
470 colors.dim(0), colors.dim(1));
471 return NULL;
472 }
473
474
475 CALL_CPP("draw_gouraud_triangle", (self->x->draw_gouraud_triangle(gc, points, colors, trans)));
476
477 Py_RETURN_NONE;
478 }
479
480 static PyObject *
PyRendererAgg_draw_gouraud_triangles(PyRendererAgg * self,PyObject * args,PyObject * kwds)481 PyRendererAgg_draw_gouraud_triangles(PyRendererAgg *self, PyObject *args, PyObject *kwds)
482 {
483 GCAgg gc;
484 numpy::array_view<const double, 3> points;
485 numpy::array_view<const double, 3> colors;
486 agg::trans_affine trans;
487
488 if (!PyArg_ParseTuple(args,
489 "O&O&O&O&|O:draw_gouraud_triangles",
490 &convert_gcagg,
491 &gc,
492 &points.converter,
493 &points,
494 &colors.converter,
495 &colors,
496 &convert_trans_affine,
497 &trans)) {
498 return NULL;
499 }
500
501 if (points.size() != 0 && (points.dim(1) != 3 || points.dim(2) != 2)) {
502 PyErr_Format(PyExc_ValueError,
503 "points must be a Nx3x2 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT "x%" NPY_INTP_FMT,
504 points.dim(0), points.dim(1), points.dim(2));
505 return NULL;
506 }
507
508 if (colors.size() != 0 && (colors.dim(1) != 3 || colors.dim(2) != 4)) {
509 PyErr_Format(PyExc_ValueError,
510 "colors must be a Nx3x4 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT "x%" NPY_INTP_FMT,
511 colors.dim(0), colors.dim(1), colors.dim(2));
512 return NULL;
513 }
514
515 if (points.size() != colors.size()) {
516 PyErr_Format(PyExc_ValueError,
517 "points and colors arrays must be the same length, got %" NPY_INTP_FMT " and %" NPY_INTP_FMT,
518 points.dim(0), colors.dim(0));
519 return NULL;
520 }
521
522 CALL_CPP("draw_gouraud_triangles", self->x->draw_gouraud_triangles(gc, points, colors, trans));
523
524 Py_RETURN_NONE;
525 }
526
PyRendererAgg_tostring_rgb(PyRendererAgg * self,PyObject * args,PyObject * kwds)527 static PyObject *PyRendererAgg_tostring_rgb(PyRendererAgg *self, PyObject *args, PyObject *kwds)
528 {
529 PyObject *buffobj = NULL;
530
531 buffobj = PyBytes_FromStringAndSize(NULL, self->x->get_width() * self->x->get_height() * 3);
532 if (buffobj == NULL) {
533 return NULL;
534 }
535
536 CALL_CPP_CLEANUP("tostring_rgb",
537 (self->x->tostring_rgb((uint8_t *)PyBytes_AS_STRING(buffobj))),
538 Py_DECREF(buffobj));
539
540 return buffobj;
541 }
542
PyRendererAgg_tostring_argb(PyRendererAgg * self,PyObject * args,PyObject * kwds)543 static PyObject *PyRendererAgg_tostring_argb(PyRendererAgg *self, PyObject *args, PyObject *kwds)
544 {
545 PyObject *buffobj = NULL;
546
547 buffobj = PyBytes_FromStringAndSize(NULL, self->x->get_width() * self->x->get_height() * 4);
548 if (buffobj == NULL) {
549 return NULL;
550 }
551
552 CALL_CPP_CLEANUP("tostring_argb",
553 (self->x->tostring_argb((uint8_t *)PyBytes_AS_STRING(buffobj))),
554 Py_DECREF(buffobj));
555
556 return buffobj;
557 }
558
PyRendererAgg_tostring_bgra(PyRendererAgg * self,PyObject * args,PyObject * kwds)559 static PyObject *PyRendererAgg_tostring_bgra(PyRendererAgg *self, PyObject *args, PyObject *kwds)
560 {
561 PyObject *buffobj = NULL;
562
563 buffobj = PyBytes_FromStringAndSize(NULL, self->x->get_width() * self->x->get_height() * 4);
564 if (buffobj == NULL) {
565 return NULL;
566 }
567
568 CALL_CPP_CLEANUP("to_string_bgra",
569 (self->x->tostring_bgra((uint8_t *)PyBytes_AS_STRING(buffobj))),
570 Py_DECREF(buffobj));
571
572 return buffobj;
573 }
574
575 static PyObject *
PyRendererAgg_get_content_extents(PyRendererAgg * self,PyObject * args,PyObject * kwds)576 PyRendererAgg_get_content_extents(PyRendererAgg *self, PyObject *args, PyObject *kwds)
577 {
578 agg::rect_i extents;
579
580 CALL_CPP("get_content_extents", (extents = self->x->get_content_extents()));
581
582 return Py_BuildValue(
583 "iiii", extents.x1, extents.y1, extents.x2 - extents.x1, extents.y2 - extents.y1);
584 }
585
PyRendererAgg_buffer_rgba(PyRendererAgg * self,PyObject * args,PyObject * kwds)586 static PyObject *PyRendererAgg_buffer_rgba(PyRendererAgg *self, PyObject *args, PyObject *kwds)
587 {
588 #if PY3K
589 return PyBytes_FromStringAndSize((const char *)self->x->pixBuffer,
590 self->x->get_width() * self->x->get_height() * 4);
591 #else
592 return PyBuffer_FromReadWriteMemory(self->x->pixBuffer,
593 self->x->get_width() * self->x->get_height() * 4);
594 #endif
595 }
596
PyRendererAgg_get_buffer(PyRendererAgg * self,Py_buffer * buf,int flags)597 int PyRendererAgg_get_buffer(PyRendererAgg *self, Py_buffer *buf, int flags)
598 {
599 Py_INCREF(self);
600 buf->obj = (PyObject *)self;
601 buf->buf = self->x->pixBuffer;
602 buf->len = self->x->get_width() * self->x->get_height() * 4;
603 buf->readonly = 0;
604 buf->format = (char *)"B";
605 buf->ndim = 3;
606 self->shape[0] = self->x->get_height();
607 self->shape[1] = self->x->get_width();
608 self->shape[2] = 4;
609 buf->shape = self->shape;
610 self->strides[0] = self->x->get_width() * 4;
611 self->strides[1] = 4;
612 self->strides[2] = 1;
613 buf->strides = self->strides;
614 buf->suboffsets = NULL;
615 buf->itemsize = 1;
616 buf->internal = NULL;
617
618 return 1;
619 }
620
PyRendererAgg_clear(PyRendererAgg * self,PyObject * args,PyObject * kwds)621 static PyObject *PyRendererAgg_clear(PyRendererAgg *self, PyObject *args, PyObject *kwds)
622 {
623 CALL_CPP("clear", self->x->clear());
624
625 Py_RETURN_NONE;
626 }
627
PyRendererAgg_copy_from_bbox(PyRendererAgg * self,PyObject * args,PyObject * kwds)628 static PyObject *PyRendererAgg_copy_from_bbox(PyRendererAgg *self, PyObject *args, PyObject *kwds)
629 {
630 agg::rect_d bbox;
631 BufferRegion *reg;
632 PyObject *regobj;
633
634 if (!PyArg_ParseTuple(args, "O&:copy_from_bbox", &convert_rect, &bbox)) {
635 return 0;
636 }
637
638 CALL_CPP("copy_from_bbox", (reg = self->x->copy_from_bbox(bbox)));
639
640 regobj = PyBufferRegion_new(&PyBufferRegionType, NULL, NULL);
641 ((PyBufferRegion *)regobj)->x = reg;
642
643 return regobj;
644 }
645
PyRendererAgg_restore_region(PyRendererAgg * self,PyObject * args,PyObject * kwds)646 static PyObject *PyRendererAgg_restore_region(PyRendererAgg *self, PyObject *args, PyObject *kwds)
647 {
648 PyBufferRegion *regobj;
649 int xx1 = 0, yy1 = 0, xx2 = 0, yy2 = 0, x = 0, y = 0;
650
651 if (!PyArg_ParseTuple(args,
652 "O!|iiiiii:restore_region",
653 &PyBufferRegionType,
654 ®obj,
655 &xx1,
656 &yy1,
657 &xx2,
658 &yy2,
659 &x,
660 &y)) {
661 return 0;
662 }
663
664 if (PySequence_Size(args) == 1) {
665 CALL_CPP("restore_region", (self->x->restore_region(*(regobj->x))));
666 } else {
667 CALL_CPP("restore_region", self->x->restore_region(*(regobj->x), xx1, yy1, xx2, yy2, x, y));
668 }
669
670 Py_RETURN_NONE;
671 }
672
673 PyTypeObject PyRendererAggType;
674
PyRendererAgg_init_type(PyObject * m,PyTypeObject * type)675 static PyTypeObject *PyRendererAgg_init_type(PyObject *m, PyTypeObject *type)
676 {
677 static PyMethodDef methods[] = {
678 {"draw_path", (PyCFunction)PyRendererAgg_draw_path, METH_VARARGS, NULL},
679 {"draw_markers", (PyCFunction)PyRendererAgg_draw_markers, METH_VARARGS, NULL},
680 {"draw_text_image", (PyCFunction)PyRendererAgg_draw_text_image, METH_VARARGS, NULL},
681 {"draw_image", (PyCFunction)PyRendererAgg_draw_image, METH_VARARGS, NULL},
682 {"draw_path_collection", (PyCFunction)PyRendererAgg_draw_path_collection, METH_VARARGS, NULL},
683 {"draw_quad_mesh", (PyCFunction)PyRendererAgg_draw_quad_mesh, METH_VARARGS, NULL},
684 {"draw_gouraud_triangle", (PyCFunction)PyRendererAgg_draw_gouraud_triangle, METH_VARARGS, NULL},
685 {"draw_gouraud_triangles", (PyCFunction)PyRendererAgg_draw_gouraud_triangles, METH_VARARGS, NULL},
686
687 {"tostring_rgb", (PyCFunction)PyRendererAgg_tostring_rgb, METH_NOARGS, NULL},
688 {"tostring_argb", (PyCFunction)PyRendererAgg_tostring_argb, METH_NOARGS, NULL},
689 {"tostring_bgra", (PyCFunction)PyRendererAgg_tostring_bgra, METH_NOARGS, NULL},
690 {"get_content_extents", (PyCFunction)PyRendererAgg_get_content_extents, METH_NOARGS, NULL},
691 {"buffer_rgba", (PyCFunction)PyRendererAgg_buffer_rgba, METH_NOARGS, NULL},
692 {"clear", (PyCFunction)PyRendererAgg_clear, METH_NOARGS, NULL},
693
694 {"copy_from_bbox", (PyCFunction)PyRendererAgg_copy_from_bbox, METH_VARARGS, NULL},
695 {"restore_region", (PyCFunction)PyRendererAgg_restore_region, METH_VARARGS, NULL},
696 {NULL}
697 };
698
699 static PyBufferProcs buffer_procs;
700 memset(&buffer_procs, 0, sizeof(PyBufferProcs));
701 buffer_procs.bf_getbuffer = (getbufferproc)PyRendererAgg_get_buffer;
702
703 memset(type, 0, sizeof(PyTypeObject));
704 type->tp_name = "matplotlib.backends._backend_agg.RendererAgg";
705 type->tp_basicsize = sizeof(PyRendererAgg);
706 type->tp_dealloc = (destructor)PyRendererAgg_dealloc;
707 type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER;
708 type->tp_methods = methods;
709 type->tp_init = (initproc)PyRendererAgg_init;
710 type->tp_new = PyRendererAgg_new;
711 type->tp_as_buffer = &buffer_procs;
712
713 if (PyType_Ready(type) < 0) {
714 return NULL;
715 }
716
717 if (PyModule_AddObject(m, "RendererAgg", (PyObject *)type)) {
718 return NULL;
719 }
720
721 return type;
722 }
723
724 extern "C" {
725
726 #if PY3K
727 static struct PyModuleDef moduledef = {
728 PyModuleDef_HEAD_INIT,
729 "_backend_agg",
730 NULL,
731 0,
732 NULL,
733 NULL,
734 NULL,
735 NULL,
736 NULL
737 };
738
739 #define INITERROR return NULL
740
PyInit__backend_agg(void)741 PyMODINIT_FUNC PyInit__backend_agg(void)
742
743 #else
744 #define INITERROR return
745
746 PyMODINIT_FUNC init_backend_agg(void)
747 #endif
748
749 {
750 PyObject *m;
751
752 #if PY3K
753 m = PyModule_Create(&moduledef);
754 #else
755 m = Py_InitModule3("_backend_agg", NULL, NULL);
756 #endif
757
758 if (m == NULL) {
759 INITERROR;
760 }
761
762 import_array();
763
764 if (!PyRendererAgg_init_type(m, &PyRendererAggType)) {
765 INITERROR;
766 }
767
768 if (!PyBufferRegion_init_type(m, &PyBufferRegionType)) {
769 INITERROR;
770 }
771
772 #if PY3K
773 return m;
774 #endif
775 }
776
777 } // extern "C"
778