1616#include " agg_scanline_storage_aa.h"
1717#include " agg_scanline_storage_bin.h"
1818#include " agg_renderer_primitives.h"
19+ #include " agg_span_image_filter_gray.h"
20+ #include " agg_span_interpolator_linear.h"
21+ #include " agg_span_allocator.h"
1922#include " util/agg_color_conv_rgb8.h"
2023
2124#include " ft2font.h"
@@ -2103,13 +2106,74 @@ RendererAgg::draw_path(const Py::Tuple& args) {
21032106
21042107}
21052108
2109+ /* *
2110+ * This is a custom span generator that converts spans in the
2111+ * 8-bit inverted greyscale font buffer to rgba that agg can use.
2112+ */
2113+ template <
2114+ class ColorT ,
2115+ class ChildGenerator >
2116+ class font_to_rgba :
2117+ public agg::span_generator<ColorT,
2118+ agg::span_allocator<ColorT> >
2119+ {
2120+ public:
2121+ typedef ChildGenerator child_type;
2122+ typedef ColorT color_type;
2123+ typedef agg::span_allocator<color_type> allocator_type;
2124+ typedef agg::span_generator<
2125+ ColorT,
2126+ agg::span_allocator<ColorT> > base_type;
2127+
2128+ private:
2129+ child_type* _gen;
2130+ allocator_type _alloc;
2131+ color_type _color;
2132+
2133+ public:
2134+ font_to_rgba (child_type* gen, color_type color) :
2135+ base_type (_alloc),
2136+ _gen (gen),
2137+ _color (color) {
2138+ }
21062139
2140+ color_type* generate (int x, int y, unsigned len)
2141+ {
2142+ color_type* dst = base_type::allocator ().span ();
2143+
2144+ typename child_type::color_type* src = _gen->generate (x, y, len);
2145+
2146+ do {
2147+ *dst = _color;
2148+ dst->a = src->v ;
2149+ ++src;
2150+ ++dst;
2151+ } while (--len);
2152+
2153+ return base_type::allocator ().span ();
2154+ }
2155+
2156+ void prepare (unsigned max_span_len)
2157+ {
2158+ _alloc.allocate (max_span_len);
2159+ _gen->prepare (max_span_len);
2160+ }
2161+
2162+ };
21072163
21082164Py::Object
21092165RendererAgg::draw_text_image (const Py::Tuple& args) {
21102166 _VERBOSE (" RendererAgg::draw_text" );
2167+
2168+ typedef agg::span_interpolator_linear<> interpolator_type;
2169+ typedef agg::span_image_filter_gray<agg::gray8, interpolator_type>
2170+ image_span_gen_type;
2171+ typedef font_to_rgba<pixfmt::color_type, image_span_gen_type>
2172+ span_gen_type;
2173+ typedef agg::renderer_scanline_aa<renderer_base, span_gen_type>
2174+ renderer_type;
21112175
2112- args.verify_length (4 );
2176+ args.verify_length (5 );
21132177
21142178 FT2Image *image = static_cast <FT2Image*>(args[0 ].ptr ());
21152179 if (!image->get_buffer ())
@@ -2125,70 +2189,48 @@ RendererAgg::draw_text_image(const Py::Tuple& args) {
21252189 return Py::Object ();
21262190 }
21272191
2128- GCAgg gc = GCAgg (args[3 ], dpi);
2129-
2130- set_clipbox_rasterizer ( gc.cliprect );
2131-
2132-
2133- pixfmt::color_type p;
2134- p.r = int (255 *gc.color .r );
2135- p.b = int (255 *gc.color .b );
2136- p.g = int (255 *gc.color .g );
2137- p.a = int (255 *gc.color .a );
2138-
2139- // y = y-font->image.height;
2140- unsigned thisx, thisy;
2141-
2142- double l = 0 ;
2143- double b = 0 ;
2144- double r = width;
2145- double t = height;
2146- if (gc.cliprect !=NULL ) {
2147- l = gc.cliprect [0 ] ;
2148- b = gc.cliprect [1 ] ;
2149- double w = gc.cliprect [2 ];
2150- double h = gc.cliprect [3 ];
2151- r = l+w;
2152- t = b+h;
2153- }
2192+ double angle = Py::Float ( args[3 ] );
2193+
2194+ GCAgg gc = GCAgg (args[4 ], dpi);
21542195
2196+ set_clipbox_rasterizer (gc.cliprect );
2197+
21552198 const unsigned char * const buffer = image->get_buffer ();
2156-
2157- for ( size_t i= 0 ; i< image->get_width (); i++) {
2158- for ( size_t j= 0 ; j< image->get_height (); j++) {
2159- thisx = i+x+image-> offsetx ;
2160- thisy = j+y+image-> offsety ;
2161- if (thisx<l || thisx>=r) continue ;
2162- if (thisy<height-t || thisy>=height-b) continue ;
2163- pixFmt-> blend_pixel
2164- (thisx, thisy, p, buffer[i + j*image-> get_width ()] );
2165- }
2166- }
2167-
2168- /* bbox the text for debug purposes
2169-
2170- agg::path_storage path ;
2171-
2172- path.move_to(x, y );
2173- path.line_to(x, y+font->image.height);
2174- path.line_to(x+font->image.width, y+font->image.height );
2175- path.line_to(x+font->image.width, y );
2176- path.close_polygon();
2177-
2178- agg::rgba edgecolor(1,0,0,1 );
2179-
2180- //now fill the edge
2181- agg::conv_stroke<agg::path_storage> stroke(path);
2182- stroke.width(1.0 );
2183- rendererAA->color(edgecolor );
2184- //self->theRasterizer->gamma(agg::gamma_power(gamma) );
2185- theRasterizer->add_path(stroke) ;
2186- agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA) ;
2187-
2188- */
2199+ agg::rendering_buffer srcbuf
2200+ ((agg::int8u*)buffer, image->get_width (),
2201+ image->get_height (), image-> get_width ());
2202+ agg::pixfmt_gray8 pixf_img (srcbuf) ;
2203+
2204+ agg::trans_affine mtx ;
2205+ mtx *= agg::trans_affine_translation ( 0 , -( int )image-> get_height ()) ;
2206+ mtx *= agg::trans_affine_rotation (-angle * agg::pi / 180.0 );
2207+ mtx *= agg::trans_affine_translation (x, y );
2208+
2209+ agg::path_storage rect;
2210+ rect. move_to ( 0 , 0 );
2211+ rect. line_to (image-> get_width (), 0 );
2212+ rect. line_to (image-> get_width (), image-> get_height ());
2213+ rect. line_to ( 0 , image-> get_height ()) ;
2214+ rect. line_to ( 0 , 0 );
2215+ agg::conv_transform<agg::path_storage> rect2 (rect, mtx );
2216+
2217+ agg::trans_affine inv_mtx (mtx );
2218+ inv_mtx. invert ( );
2219+
2220+ agg::image_filter_lut filter;
2221+ filter. calculate ( agg::image_filter_spline36 () );
2222+ interpolator_type interpolator (inv_mtx);
2223+ agg::span_allocator<agg::gray8> gray_span_allocator;
2224+ image_span_gen_type image_span_generator (gray_span_allocator,
2225+ srcbuf, 0 , interpolator, filter );
2226+ span_gen_type output_span_generator (&image_span_generator, gc. color );
2227+ renderer_type ri (*rendererBase, output_span_generator );
2228+ agg::rasterizer_scanline_aa<> rasterizer ;
2229+ agg::scanline_p8 scanline ;
2230+ rasterizer. add_path (rect2);
2231+ agg::render_scanlines (rasterizer, scanline, ri);
21892232
21902233 return Py::Object ();
2191-
21922234}
21932235
21942236
0 commit comments