/* _backend_agg.h - A rewrite of _backend_agg using PyCXX to handle
ref counting, etc..
*/
#ifndef __BACKEND_AGG_H
#define __BACKEND_AGG_H
#include <utility>
#include "CXX/Extensions.hxx"
#include "agg_arrowhead.h"
#include "agg_basics.h"
#include "agg_bezier_arc.h"
#include "agg_color_rgba.h"
#include "agg_conv_concat.h"
#include "agg_conv_contour.h"
#include "agg_conv_curve.h"
#include "agg_conv_dash.h"
#include "agg_conv_marker.h"
#include "agg_conv_marker_adaptor.h"
#include "agg_math_stroke.h"
#include "agg_conv_stroke.h"
#include "agg_ellipse.h"
#include "agg_embedded_raster_fonts.h"
#include "agg_path_storage.h"
#include "agg_pixfmt_rgb.h"
#include "agg_pixfmt_rgba.h"
#include "agg_pixfmt_gray.h"
#include "agg_alpha_mask_u8.h"
#include "agg_pixfmt_amask_adaptor.h"
#include "agg_rasterizer_outline.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_renderer_outline_aa.h"
#include "agg_renderer_raster_text.h"
#include "agg_renderer_scanline.h"
#include "agg_rendering_buffer.h"
#include "agg_scanline_bin.h"
#include "agg_scanline_u.h"
#include "agg_scanline_p.h"
#include "agg_vcgen_markers_term.h"
#include "agg_py_path_iterator.h"
#include "path_converters.h"
// These are copied directly from path.py, and must be kept in sync
#define STOP 0
#define MOVETO 1
#define LINETO 2
#define CURVE3 3
#define CURVE4 4
#define CLOSEPOLY 5
const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 1 };
typedef agg::pixfmt_rgba32 pixfmt;
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_aa;
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_bin;
typedef agg::rasterizer_scanline_aa<> rasterizer;
typedef agg::scanline_p8 scanline_p8;
typedef agg::scanline_bin scanline_bin;
typedef agg::amask_no_clip_gray8 alpha_mask_type;
typedef agg::renderer_base<agg::pixfmt_gray8> renderer_base_alpha_mask_type;
typedef agg::renderer_scanline_aa_solid<renderer_base_alpha_mask_type> renderer_alpha_mask_type;
// a helper class to pass agg::buffer objects around. agg::buffer is
// a class in the swig wrapper
class BufferRegion : public Py::PythonExtension<BufferRegion> {
public:
BufferRegion(const agg::rect_i &r, bool freemem=true) :
rect(r), freemem(freemem) {
width = r.x2 - r.x1;
height = r.y2 - r.y1;
stride = width * 4;
data = new agg::int8u[stride * height];
}
agg::int8u* data;
agg::rect_i rect;
int width;
int height;
int stride;
bool freemem;
// set the x and y corners of the rectangle
Py::Object set_x(const Py::Tuple &args);
Py::Object set_y(const Py::Tuple &args);
Py::Object get_extents(const Py::Tuple &args);
Py::Object to_string(const Py::Tuple &args);
Py::Object to_string_argb(const Py::Tuple &args);
static void init_type(void);
virtual ~BufferRegion() {
if (freemem) {
delete [] data;
data = NULL;
}
};
};
class GCAgg {
public:
GCAgg(const Py::Object& gc, double dpi);
GCAgg(double dpi);
double dpi;
bool isaa;
agg::line_cap_e cap;
agg::line_join_e join;
double linewidth;
double alpha;
agg::rgba color;
Py::Object cliprect;
Py::Object clippath;
agg::trans_affine clippath_trans;
//dashes
typedef std::vector<std::pair<double, double> > dash_t;
double dashOffset;
dash_t dashes;
e_quantize_mode quantize_mode;
Py::Object hatchpath;
protected:
agg::rgba get_color(const Py::Object& gc);
double points_to_pixels( const Py::Object& points);
void _set_linecap(const Py::Object& gc) ;
void _set_joinstyle(const Py::Object& gc) ;
void _set_dashes(const Py::Object& gc) ;
void _set_clip_rectangle( const Py::Object& gc);
void _set_clip_path( const Py::Object& gc);
void _set_antialiased( const Py::Object& gc);
void _set_snap( const Py::Object& gc);
void _set_hatch_path( const Py::Object& gc);
};
//struct AMRenderer {
//
//}
// the renderer
class RendererAgg: public Py::PythonExtension<RendererAgg> {
typedef std::pair<bool, agg::rgba> facepair_t;
public:
RendererAgg(unsigned int width, unsigned int height, double dpi, int debug);
static void init_type(void);
unsigned int get_width() { return width;}
unsigned int get_height() { return height;}
// the drawing methods
//Py::Object _draw_markers_nocache(const Py::Tuple & args);
//Py::Object _draw_markers_cache(const Py::Tuple & args);
Py::Object draw_markers(const Py::Tuple & args);
Py::Object draw_text_image(const Py::Tuple & args);
Py::Object draw_image(const Py::Tuple & args);
Py::Object draw_path(const Py::Tuple & args);
Py::Object draw_path_collection(const Py::Tuple & args);
Py::Object draw_quad_mesh(const Py::Tuple& args);
Py::Object draw_gouraud_triangle(const Py::Tuple& args);
Py::Object draw_gouraud_triangles(const Py::Tuple& args);
Py::Object write_rgba(const Py::Tuple & args);
Py::Object tostring_rgb(const Py::Tuple & args);
Py::Object tostring_argb(const Py::Tuple & args);
Py::Object tostring_bgra(const Py::Tuple & args);
Py::Object tostring_rgba_minimized(const Py::Tuple & args);
Py::Object buffer_rgba(const Py::Tuple & args);
Py::Object clear(const Py::Tuple & args);
Py::Object copy_from_bbox(const Py::Tuple & args);
Py::Object restore_region(const Py::Tuple & args);
Py::Object restore_region2(const Py::Tuple & args);
virtual ~RendererAgg();
static const size_t PIXELS_PER_INCH;
unsigned int width, height;
double dpi;
size_t NUMBYTES; //the number of bytes in buffer
agg::int8u *pixBuffer;
agg::rendering_buffer renderingBuffer;
agg::int8u *alphaBuffer;
agg::rendering_buffer alphaMaskRenderingBuffer;
alpha_mask_type alphaMask;
agg::pixfmt_gray8 pixfmtAlphaMask;
renderer_base_alpha_mask_type rendererBaseAlphaMask;
renderer_alpha_mask_type rendererAlphaMask;
agg::scanline_p8 scanlineAlphaMask;
scanline_p8 slineP8;
scanline_bin slineBin;
pixfmt pixFmt;
renderer_base rendererBase;
renderer_aa rendererAA;
renderer_bin rendererBin;
rasterizer theRasterizer;
Py::Object lastclippath;
agg::trans_affine lastclippath_transform;
static const size_t HATCH_SIZE = 72;
agg::int8u hatchBuffer[HATCH_SIZE * HATCH_SIZE * 4];
agg::rendering_buffer hatchRenderingBuffer;
const int debug;
protected:
double points_to_pixels( const Py::Object& points);
double points_to_pixels_snapto( const Py::Object& points);
agg::rgba rgb_to_color(const Py::SeqBase<Py::Object>& rgb, double alpha);
facepair_t _get_rgba_face(const Py::Object& rgbFace, double alpha);
template<class R>
void set_clipbox(const Py::Object& cliprect, R& rasterizer);
bool render_clippath(const Py::Object& clippath, const agg::trans_affine& clippath_trans);
template<class PathIteratorType>
void _draw_path(PathIteratorType& path, bool has_clippath,
const facepair_t& face, const GCAgg& gc);
template<class PathGenerator, int check_snap, int has_curves>
Py::Object
_draw_path_collection_generic
(agg::trans_affine master_transform,
const Py::Object& cliprect,
const Py::Object& clippath,
const agg::trans_affine& clippath_trans,
const PathGenerator& path_generator,
const Py::SeqBase<Py::Object>& transforms_obj,
const Py::Object& offsets_obj,
const agg::trans_affine& offset_trans,
const Py::Object& facecolors_obj,
const Py::Object& edgecolors_obj,
const Py::SeqBase<Py::Float>& linewidths,
const Py::SeqBase<Py::Object>& linestyles_obj,
const Py::SeqBase<Py::Int>& antialiaseds);
void
_draw_gouraud_triangle(
const GCAgg& gc,
const double* points, const double* colors, agg::trans_affine trans);
private:
void create_alpha_buffers();
};
// the extension module
class _backend_agg_module : public Py::ExtensionModule<_backend_agg_module>
{
public:
_backend_agg_module()
: Py::ExtensionModule<_backend_agg_module>( "_backend_agg" )
{
RendererAgg::init_type();
BufferRegion::init_type();
add_keyword_method("RendererAgg", &_backend_agg_module::new_renderer,
"RendererAgg(width, height, dpi)");
initialize( "The agg rendering backend" );
}
virtual ~_backend_agg_module() {}
private:
Py::Object new_renderer (const Py::Tuple &args, const Py::Dict &kws);
};
#endif