Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 023414f

Browse files
committed
Support arbitrary rotation of usetex text.
svn path=/trunk/matplotlib/; revision=4618
1 parent 1796fe6 commit 023414f

4 files changed

Lines changed: 66 additions & 67 deletions

File tree

lib/matplotlib/backends/backend_agg.py

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
REQUIREMENTs
2828
2929
python2.3+
30-
numpy 1.0 +
31-
30+
numpy 1.0 +
31+
3232
agg2 (see below)
3333
freetype 2
3434
libpng
@@ -126,7 +126,7 @@ def __init__(self, width, height, dpi):
126126
self.restore_region = self._renderer.restore_region
127127
self.mathtext_parser = MathTextParser('Agg')
128128
self._fontd = {}
129-
129+
130130
self.bbox = lbwh_to_bbox(0,0, self.width, self.height)
131131
if __debug__: verbose.report('RendererAgg.__init__ done',
132132
'debug-annoying')
@@ -175,7 +175,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
175175
'debug-annoying')
176176
ox, oy, width, height, descent, font_image, used_characters = \
177177
self.mathtext_parser.parse(s, self.dpi.get(), prop)
178-
178+
179179
x = int(x) + ox
180180
y = int(y) - oy
181181
self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
@@ -209,7 +209,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath):
209209
self._renderer.draw_text_image(font.get_image(), int(x), int(y) + 1, angle, gc)
210210

211211

212-
def get_text_width_height_descent(self, s, prop, ismath, rgb=(0,0,0)):
212+
def get_text_width_height_descent(self, s, prop, ismath):
213213
"""
214214
get the width and height in display coords of the string s
215215
with FontPropertry prop
@@ -222,8 +222,8 @@ def get_text_width_height_descent(self, s, prop, ismath, rgb=(0,0,0)):
222222
# todo: handle props
223223
size = prop.get_size_in_points()
224224
texmanager = self.get_texmanager()
225-
Z = texmanager.get_rgba(s, size, self.dpi.get(), rgb)
226-
m,n,tmp = Z.shape
225+
Z = texmanager.get_grey(s, size, self.dpi.get())
226+
m,n = Z.shape
227227
# TODO: descent of TeX text (I am imitating backend_ps here -JKS)
228228
return n, m, 0
229229

@@ -242,44 +242,18 @@ def get_text_width_height_descent(self, s, prop, ismath, rgb=(0,0,0)):
242242

243243
def draw_tex(self, gc, x, y, s, prop, angle):
244244
# todo, handle props, angle, origins
245-
rgb = gc.get_rgb()
246245
size = prop.get_size_in_points()
247246
dpi = self.dpi.get()
248247

249-
flip = angle==90
250-
w,h,d = self.get_text_width_height_descent(s, prop, 'TeX', rgb)
251-
if flip:
252-
w,h = h,w
253-
x -= w
254-
255248
texmanager = self.get_texmanager()
256-
key = s, size, dpi, rgb, angle, texmanager.get_font_config()
249+
key = s, size, dpi, angle, texmanager.get_font_config()
257250
im = self.texd.get(key)
258251
if im is None:
259-
Z = texmanager.get_rgba(s, size, dpi, rgb)
260-
if flip:
261-
r = Z[:,:,0]
262-
g = Z[:,:,1]
263-
b = Z[:,:,2]
264-
a = Z[:,:,3]
265-
m,n,tmp = Z.shape
266-
267-
def func(x):
268-
return npy.transpose(npy.fliplr(x))
269-
270-
Z = npy.zeros((n,m,4), float)
271-
Z[:,:,0] = func(r)
272-
Z[:,:,1] = func(g)
273-
Z[:,:,2] = func(b)
274-
Z[:,:,3] = func(a)
275-
im = fromarray(Z, 1)
276-
im.flipud_out()
277-
self.texd[key] = im
278-
279-
cliprect = gc.get_clip_rectangle()
280-
if cliprect is None: bbox = None
281-
else: bbox = lbwh_to_bbox(*cliprect)
282-
self.draw_image(x, self.height-y, im, bbox)
252+
Z = texmanager.get_grey(s, size, dpi)
253+
Z = npy.array(Z * 255.0, npy.uint8)
254+
255+
self._renderer.draw_text_image(Z, x, y, angle, gc)
256+
283257

284258
def get_canvas_width_height(self):
285259
'return the canvas width and height in display coords'
@@ -413,8 +387,8 @@ def print_raw(self, filename, *args, **kwargs):
413387
self.draw()
414388
self.get_renderer()._renderer.write_rgba(str(filename))
415389
print_rgba = print_raw
416-
390+
417391
def print_png(self, filename, *args, **kwargs):
418392
self.draw()
419393
self.get_renderer()._renderer.write_png(filename, self.figure.dpi.get())
420-
394+

lib/matplotlib/texmanager.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ class TexManager:
7979
dvipngVersion = get_dvipng_version()
8080

8181
# mappable cache of
82-
arrayd = {}
82+
rgba_arrayd = {}
83+
grey_arrayd = {}
8384
postscriptd = {}
8485
pscnt = 0
8586

@@ -131,7 +132,7 @@ def __init__(self):
131132
found_font = self.font_info[font.lower()]
132133
setattr(self, font_family_attr,
133134
self.font_info[font.lower()])
134-
if DEBUG:
135+
if DEBUG:
135136
print 'family: %s, font: %s, info: %s'%(font_family,
136137
font, self.font_info[font.lower()])
137138
break
@@ -323,6 +324,24 @@ def get_ps_bbox(self, tex, fontsize):
323324
return [int(val) for val in line.split()[1:]]
324325
raise RuntimeError('Could not parse %s'%psfile)
325326

327+
def get_grey(self, tex, fontsize=None, dpi=None):
328+
key = tex, self.get_font_config(), fontsize, dpi
329+
alpha = self.grey_arrayd.get(key)
330+
331+
if alpha is None:
332+
pngfile = self.make_png(tex, fontsize, dpi)
333+
X = readpng(os.path.join(self.texcache, pngfile))
334+
335+
if (self.dvipngVersion < '1.6') or rcParams['text.dvipnghack']:
336+
# hack the alpha channel as described in comment above
337+
alpha = npy.sqrt(1-X[:,:,0])
338+
else:
339+
alpha = X[:,:,-1]
340+
341+
self.grey_arrayd[key] = alpha
342+
return alpha
343+
344+
326345
def get_rgba(self, tex, fontsize=None, dpi=None, rgb=(0,0,0)):
327346
"""
328347
Return tex string as an rgba array
@@ -351,23 +370,16 @@ def get_rgba(self, tex, fontsize=None, dpi=None, rgb=(0,0,0)):
351370
if not dpi: dpi = rcParams['savefig.dpi']
352371
r,g,b = rgb
353372
key = tex, self.get_font_config(), fontsize, dpi, tuple(rgb)
354-
Z = self.arrayd.get(key)
373+
Z = self.rgba_arrayd.get(key)
355374

356375
if Z is None:
357-
pngfile = self.make_png(tex, fontsize, dpi)
358-
X = readpng(os.path.join(self.texcache, pngfile))
359-
360-
if (self.dvipngVersion < '1.6') or rcParams['text.dvipnghack']:
361-
# hack the alpha channel as described in comment above
362-
alpha = npy.sqrt(1-X[:,:,0])
363-
else:
364-
alpha = X[:,:,-1]
376+
alpha = self.get_grey(tex, fontsize, dpi)
365377

366-
Z = npy.zeros(X.shape, npy.float)
378+
Z = npy.zeros((X.shape[0], X.shape[1], 4), npy.float)
367379
Z[:,:,0] = r
368380
Z[:,:,1] = g
369381
Z[:,:,2] = b
370382
Z[:,:,3] = alpha
371-
self.arrayd[key] = Z
383+
self.rgba_arrayd[key] = Z
372384

373385
return Z

src/_backend_agg.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ void RendererAgg::DrawQuadMesh(int meshWidth, int meshHeight, void* colors_void,
10031003
for(k = firstRow; k <= lastRow; k++)
10041004
{
10051005
numCol = inPolygon(k, xs, ys, col);
1006-
1006+
10071007
if (numCol >= 2) rendererBase->copy_hline(col[0], k, col[1] - 1, color);
10081008
if (numCol == 4) rendererBase->copy_hline(col[2], k, col[3] - 1, color);
10091009
}
@@ -2137,9 +2137,25 @@ RendererAgg::draw_text_image(const Py::Tuple& args) {
21372137

21382138
args.verify_length(5);
21392139

2140-
FT2Image *image = static_cast<FT2Image*>(args[0].ptr());
2141-
if (!image->get_buffer())
2142-
return Py::Object();
2140+
const unsigned char* buffer = NULL;
2141+
int width, height;
2142+
Py::Object image_obj = args[0];
2143+
if (PyArray_Check(image_obj.ptr())) {
2144+
PyArrayObject* image_array = NULL;
2145+
image_array = (PyArrayObject*)PyArray_FromObject(image_obj.ptr(), PyArray_UBYTE, 2, 2);
2146+
if (!image_array)
2147+
throw Py::ValueError("First argument to draw_text_image must be a FT2Font.Image object or a Nx2 uint8 numpy array.");
2148+
buffer = (unsigned char *)PyArray_DATA(image_array);
2149+
width = PyArray_DIM(image_array, 1);
2150+
height = PyArray_DIM(image_array, 0);
2151+
} else {
2152+
FT2Image *image = static_cast<FT2Image*>(args[0].ptr());
2153+
if (!image->get_buffer())
2154+
throw Py::ValueError("First argument to draw_text_image must be a FT2Font.Image object or a Nx2 uint8 numpy array.");
2155+
buffer = image->get_buffer();
2156+
width = image->get_width();
2157+
height = image->get_height();
2158+
}
21432159

21442160
int x(0),y(0);
21452161
try {
@@ -2157,22 +2173,19 @@ RendererAgg::draw_text_image(const Py::Tuple& args) {
21572173

21582174
set_clipbox_rasterizer(gc.cliprect);
21592175

2160-
const unsigned char* const buffer = image->get_buffer();
2161-
agg::rendering_buffer srcbuf
2162-
((agg::int8u*)buffer, image->get_width(),
2163-
image->get_height(), image->get_width());
2176+
agg::rendering_buffer srcbuf((agg::int8u*)buffer, width, height, width);
21642177
agg::pixfmt_gray8 pixf_img(srcbuf);
21652178

21662179
agg::trans_affine mtx;
2167-
mtx *= agg::trans_affine_translation(0, -(int)image->get_height());
2180+
mtx *= agg::trans_affine_translation(0, -(int)height);
21682181
mtx *= agg::trans_affine_rotation(-angle * agg::pi / 180.0);
21692182
mtx *= agg::trans_affine_translation(x, y);
21702183

21712184
agg::path_storage rect;
21722185
rect.move_to(0, 0);
2173-
rect.line_to(image->get_width(), 0);
2174-
rect.line_to(image->get_width(), image->get_height());
2175-
rect.line_to(0, image->get_height());
2186+
rect.line_to(width, 0);
2187+
rect.line_to(width, height);
2188+
rect.line_to(0, height);
21762189
rect.line_to(0, 0);
21772190
agg::conv_transform<agg::path_storage> rect2(rect, mtx);
21782191

src/_image.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ _image_module::from_images(const Py::Tuple& args) {
850850
char _image_module_readpng__doc__[] =
851851
"readpng(fname)\n"
852852
"\n"
853-
"Load an image from png file into a numerix array of MxNx4 uint8";
853+
"Load an image from png file into a numerix array of MxNx4 float";
854854
Py::Object
855855
_image_module::readpng(const Py::Tuple& args) {
856856

0 commit comments

Comments
 (0)