|
From: <md...@us...> - 2007-09-04 19:00:22
|
Revision: 3776
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3776&view=rev
Author: mdboom
Date: 2007-09-04 12:00:18 -0700 (Tue, 04 Sep 2007)
Log Message:
-----------
Add support for arbitrary angles of rotation on mathtext in Agg
backend. Uses agg to rotate the raster of the text.
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
trunk/matplotlib/lib/matplotlib/mathtext.py
trunk/matplotlib/src/_backend_agg.cpp
trunk/matplotlib/src/ft2font.cpp
trunk/matplotlib/src/ft2font.h
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-09-04 18:19:16 UTC (rev 3775)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-09-04 19:00:18 UTC (rev 3776)
@@ -174,17 +174,10 @@
'debug-annoying')
ox, oy, width, height, descent, font_image, used_characters = \
self.mathtext_parser.parse(s, self.dpi.get(), prop)
-
- if angle == 90:
- width, height = height, width
- ox, oy = oy, ox
- x = int(x) - width + ox
- y = int(y) - height + oy
- font_image.rotate()
- else:
- x = int(x) + ox
- y = int(y) - height + oy
- self._renderer.draw_text_image(font_image, x, y + 1, gc)
+
+ x = int(x) + ox
+ y = int(y) - oy
+ self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
if 0:
self._renderer.draw_rectangle(gc, None,
int(x),
@@ -205,12 +198,14 @@
if len(s) == 1 and ord(s) > 127:
font.load_char(ord(s), flags=LOAD_DEFAULT)
else:
- font.set_text(s, angle, flags=LOAD_DEFAULT)
+ font.set_text(s, 0, flags=LOAD_DEFAULT)
font.draw_glyphs_to_bitmap()
#print x, y, int(x), int(y)
- self._renderer.draw_text_image(font.get_image(), int(x), int(y) + 1, gc)
+ # We pass '0' for angle here, since is has already been rotated
+ # (in vector space) in the above call to font.set_text.
+ self._renderer.draw_text_image(font.get_image(), int(x), int(y) + 1, angle, gc)
def get_text_width_height_descent(self, s, prop, ismath, rgb=(0,0,0)):
@@ -229,7 +224,7 @@
Z = texmanager.get_rgba(s, size, self.dpi.get(), rgb)
m,n,tmp = Z.shape
# TODO: descent of TeX text (I am imitating backend_ps here -JKS)
- return n, m, m
+ return n, m, 0
if ismath:
ox, oy, width, height, descent, fonts, used_characters = \
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-09-04 18:19:16 UTC (rev 3775)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2007-09-04 19:00:18 UTC (rev 3776)
@@ -275,10 +275,9 @@
l,b,r,t = texmanager.get_ps_bbox(s, fontsize)
w = (r-l)
h = (t-b)
- #print s, w, h
# TODO: We need a way to get a good baseline from
# text.usetex
- return w, h, h
+ return w, h, 0
if ismath:
width, height, descent, pswriter, used_characters = \
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-09-04 18:19:16 UTC (rev 3775)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-09-04 19:00:18 UTC (rev 3776)
@@ -541,7 +541,7 @@
self.font = font
self.charmap = font.get_charmap()
self.glyphmap = dict(
- [(glyphind, ccode) for ccode, glyphind in self.charmap.items()])
+ [(glyphind, ccode) for ccode, glyphind in self.charmap.iteritems()])
def __repr__(self):
return repr(self.font)
@@ -671,7 +671,7 @@
def __init__(self, *args, **kwargs):
TruetypeFonts.__init__(self, *args, **kwargs)
if not len(self.fontmap):
- for key, val in self._fontmap.items():
+ for key, val in self._fontmap.iteritems():
fullpath = os.path.join(self.basepath, val + ".ttf")
self.fontmap[key] = fullpath
self.fontmap[val] = fullpath
Modified: trunk/matplotlib/src/_backend_agg.cpp
===================================================================
--- trunk/matplotlib/src/_backend_agg.cpp 2007-09-04 18:19:16 UTC (rev 3775)
+++ trunk/matplotlib/src/_backend_agg.cpp 2007-09-04 19:00:18 UTC (rev 3776)
@@ -16,6 +16,9 @@
#include "agg_scanline_storage_aa.h"
#include "agg_scanline_storage_bin.h"
#include "agg_renderer_primitives.h"
+#include "agg_span_image_filter_gray.h"
+#include "agg_span_interpolator_linear.h"
+#include "agg_span_allocator.h"
#include "util/agg_color_conv_rgb8.h"
#include "ft2font.h"
@@ -2103,13 +2106,74 @@
}
+/**
+ * This is a custom span generator that converts spans in the
+ * 8-bit inverted greyscale font buffer to rgba that agg can use.
+ */
+template<
+ class ColorT,
+ class ChildGenerator>
+class font_to_rgba :
+ public agg::span_generator<ColorT,
+ agg::span_allocator<ColorT> >
+{
+public:
+ typedef ChildGenerator child_type;
+ typedef ColorT color_type;
+ typedef agg::span_allocator<color_type> allocator_type;
+ typedef agg::span_generator<
+ ColorT,
+ agg::span_allocator<ColorT> > base_type;
+private:
+ child_type* _gen;
+ allocator_type _alloc;
+ color_type _color;
+
+public:
+ font_to_rgba(child_type* gen, color_type color) :
+ base_type(_alloc),
+ _gen(gen),
+ _color(color) {
+ }
+ color_type* generate(int x, int y, unsigned len)
+ {
+ color_type* dst = base_type::allocator().span();
+
+ typename child_type::color_type* src = _gen->generate(x, y, len);
+
+ do {
+ *dst = _color;
+ dst->a = src->v;
+ ++src;
+ ++dst;
+ } while (--len);
+
+ return base_type::allocator().span();
+ }
+
+ void prepare(unsigned max_span_len)
+ {
+ _alloc.allocate(max_span_len);
+ _gen->prepare(max_span_len);
+ }
+
+};
+
Py::Object
RendererAgg::draw_text_image(const Py::Tuple& args) {
_VERBOSE("RendererAgg::draw_text");
+
+ typedef agg::span_interpolator_linear<> interpolator_type;
+ typedef agg::span_image_filter_gray<agg::gray8, interpolator_type>
+ image_span_gen_type;
+ typedef font_to_rgba<pixfmt::color_type, image_span_gen_type>
+ span_gen_type;
+ typedef agg::renderer_scanline_aa<renderer_base, span_gen_type>
+ renderer_type;
- args.verify_length(4);
+ args.verify_length(5);
FT2Image *image = static_cast<FT2Image*>(args[0].ptr());
if (!image->get_buffer())
@@ -2125,70 +2189,48 @@
return Py::Object();
}
- GCAgg gc = GCAgg(args[3], dpi);
+ double angle = Py::Float( args[3] );
+
+ GCAgg gc = GCAgg(args[4], dpi);
- set_clipbox_rasterizer( gc.cliprect);
-
-
- pixfmt::color_type p;
- p.r = int(255*gc.color.r);
- p.b = int(255*gc.color.b);
- p.g = int(255*gc.color.g);
- p.a = int(255*gc.color.a);
-
- //y = y-font->image.height;
- unsigned thisx, thisy;
-
- double l = 0;
- double b = 0;
- double r = width;
- double t = height;
- if (gc.cliprect!=NULL) {
- l = gc.cliprect[0] ;
- b = gc.cliprect[1] ;
- double w = gc.cliprect[2];
- double h = gc.cliprect[3];
- r = l+w;
- t = b+h;
- }
-
+ set_clipbox_rasterizer(gc.cliprect);
+
const unsigned char* const buffer = image->get_buffer();
+ agg::rendering_buffer srcbuf
+ ((agg::int8u*)buffer, image->get_width(),
+ image->get_height(), image->get_width());
+ agg::pixfmt_gray8 pixf_img(srcbuf);
- for (size_t i=0; i< image->get_width(); i++) {
- for (size_t j=0; j< image->get_height(); j++) {
- thisx = i+x+image->offsetx;
- thisy = j+y+image->offsety;
- if (thisx<l || thisx>=r) continue;
- if (thisy<height-t || thisy>=height-b) continue;
- pixFmt->blend_pixel
- (thisx, thisy, p, buffer[i + j*image->get_width()]);
- }
- }
+ agg::trans_affine mtx;
+ mtx *= agg::trans_affine_translation(0, -(int)image->get_height());
+ mtx *= agg::trans_affine_rotation(-angle * agg::pi / 180.0);
+ mtx *= agg::trans_affine_translation(x, y);
+
+ agg::path_storage rect;
+ rect.move_to(0, 0);
+ rect.line_to(image->get_width(), 0);
+ rect.line_to(image->get_width(), image->get_height());
+ rect.line_to(0, image->get_height());
+ rect.line_to(0, 0);
+ agg::conv_transform<agg::path_storage> rect2(rect, mtx);
+
+ agg::trans_affine inv_mtx(mtx);
+ inv_mtx.invert();
+
+ agg::image_filter_lut filter;
+ filter.calculate(agg::image_filter_spline36());
+ interpolator_type interpolator(inv_mtx);
+ agg::span_allocator<agg::gray8> gray_span_allocator;
+ image_span_gen_type image_span_generator(gray_span_allocator,
+ srcbuf, 0, interpolator, filter);
+ span_gen_type output_span_generator(&image_span_generator, gc.color);
+ renderer_type ri(*rendererBase, output_span_generator);
+ agg::rasterizer_scanline_aa<> rasterizer;
+ agg::scanline_p8 scanline;
+ rasterizer.add_path(rect2);
+ agg::render_scanlines(rasterizer, scanline, ri);
- /* bbox the text for debug purposes
-
- agg::path_storage path;
-
- path.move_to(x, y);
- path.line_to(x, y+font->image.height);
- path.line_to(x+font->image.width, y+font->image.height);
- path.line_to(x+font->image.width, y);
- path.close_polygon();
-
- agg::rgba edgecolor(1,0,0,1);
-
- //now fill the edge
- agg::conv_stroke<agg::path_storage> stroke(path);
- stroke.width(1.0);
- rendererAA->color(edgecolor);
- //self->theRasterizer->gamma(agg::gamma_power(gamma));
- theRasterizer->add_path(stroke);
- agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
-
- */
-
return Py::Object();
-
}
Modified: trunk/matplotlib/src/ft2font.cpp
===================================================================
--- trunk/matplotlib/src/ft2font.cpp 2007-09-04 18:19:16 UTC (rev 3775)
+++ trunk/matplotlib/src/ft2font.cpp 2007-09-04 19:00:18 UTC (rev 3776)
@@ -43,8 +43,6 @@
FT_Library _ft2Library;
FT2Image::FT2Image() :
- offsetx(0), offsety(0),
- _bRotated(false),
_isDirty(true),
_buffer(NULL),
_width(0), _height(0),
@@ -54,8 +52,6 @@
}
FT2Image::FT2Image(unsigned long width, unsigned long height) :
- offsetx(0), offsety(0),
- _bRotated(false),
_isDirty(true),
_buffer(NULL),
_width(0), _height(0),
@@ -85,7 +81,6 @@
for (size_t n=0; n<numBytes; n++)
_buffer[n] = 0;
- _bRotated = false;
_isDirty = true;
}
@@ -113,10 +108,7 @@
_width = 0;
_height = 0;
- offsetx = 0;
- offsety = 0;
_isDirty = true;
- _bRotated = false;
delete [] _buffer;
_buffer = NULL;
if (_rgbCopy) {
@@ -142,58 +134,6 @@
return Py::Object();
}
-void FT2Image::rotate() {
- // If we have already rotated, just return.
- if (_bRotated)
- return;
-
- unsigned long width = _width;
- unsigned long height = _height;
-
- unsigned long newWidth = _height;
- unsigned long newHeight = _width;
-
- unsigned long numBytes = _width * _height;
-
- unsigned char * buffer = new unsigned char [numBytes];
-
- unsigned long i, j, k, offset, nhMinusOne;
-
- nhMinusOne = newHeight - 1;
-
- unsigned char * read_it = _buffer;
-
- for (i=0; i<height; i++) {
- offset = i*width;
- for (j=0; j<width; j++) {
- k = nhMinusOne - j;
- buffer[i + k*newWidth] = *(read_it++);
- }
- }
-
- delete [] _buffer;
- _buffer = buffer;
- _width = newWidth;
- _height = newHeight;
- _bRotated = true;
- _isDirty = true;
-}
-char FT2Image::rotate__doc__[] =
-"rotate()\n"
-"\n"
-"Rotates the image 90 degrees.\n"
-;
-Py::Object
-FT2Image::py_rotate(const Py::Tuple & args) {
- _VERBOSE("FT2Image::rotate");
-
- args.verify_length(0);
-
- rotate();
-
- return Py::Object();
-}
-
void
FT2Image::draw_bitmap( FT_Bitmap* bitmap,
FT_Int x,
@@ -404,17 +344,11 @@
unsigned char *src_end = src + (_width * _height);
unsigned char *dst = _rgbaCopy->_buffer;
- // This pre-multiplies the alpha, which apparently shouldn't
- // be necessary for wxGTK, but it sure as heck seems to be.
- unsigned int c;
- unsigned int tmp;
while (src != src_end) {
- c = *src++;
- tmp = ((255 - c) * c) >> 8;
- *dst++ = tmp;
- *dst++ = tmp;
- *dst++ = tmp;
- *dst++ = c;
+ *dst++ = 0;
+ *dst++ = 0;
+ *dst++ = 0;
+ *dst++ = *src++;
}
}
@@ -1266,12 +1200,6 @@
image->resize(width, height);
}
- image->offsetx = (int)(string_bbox.xMin / 64.0);
- if (angle==0)
- image->offsety = -image->get_height();
- else
- image->offsety = (int)(-string_bbox.yMax/64.0);
-
for ( size_t n = 0; n < glyphs.size(); n++ )
{
FT_BBox bbox;
@@ -1840,8 +1768,6 @@
FT2Image::clear__doc__);
add_varargs_method("resize", &FT2Image::py_resize,
FT2Image::resize__doc__);
- add_varargs_method("rotate", &FT2Image::py_rotate,
- FT2Image::rotate__doc__);
add_varargs_method("write_bitmap", &FT2Image::py_write_bitmap,
FT2Image::write_bitmap__doc__);
add_varargs_method("draw_rect", &FT2Image::py_draw_rect,
Modified: trunk/matplotlib/src/ft2font.h
===================================================================
--- trunk/matplotlib/src/ft2font.h 2007-09-04 18:19:16 UTC (rev 3775)
+++ trunk/matplotlib/src/ft2font.h 2007-09-04 19:00:18 UTC (rev 3776)
@@ -30,7 +30,6 @@
void resize(unsigned long width, unsigned long height);
void clear();
- void rotate();
void draw_bitmap(FT_Bitmap* bitmap, FT_Int x, FT_Int y);
void write_bitmap(const char* filename) const;
void draw_rect(unsigned long x0, unsigned long y0,
@@ -46,8 +45,6 @@
Py::Object py_clear(const Py::Tuple & args);
static char resize__doc__ [];
Py::Object py_resize(const Py::Tuple & args);
- static char rotate__doc__ [];
- Py::Object py_rotate(const Py::Tuple & args);
static char write_bitmap__doc__ [];
Py::Object py_write_bitmap(const Py::Tuple & args);
static char draw_rect__doc__ [];
@@ -64,11 +61,7 @@
Py::Object py_get_width(const Py::Tuple & args);
Py::Object py_get_height(const Py::Tuple & args);
- unsigned long offsetx;
- unsigned long offsety;
-
private:
- bool _bRotated;
bool _isDirty;
unsigned char *_buffer;
unsigned long _width;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|