|
From: Michael D. <md...@st...> - 2012-08-20 18:27:43
|
Thanks for this. It's been a long-standing bug that text is handled by bounding box, but it's been difficult to find a way forward without breaking backward compatibility. I've filed an issue for this here. https://github.com/matplotlib/matplotlib/issues/1121 It may be, in the long run, that we want to fix the other backends to use baselines rather than fixing Cairo to use bounding boxes. Mike On 08/20/2012 01:07 PM, Freddie Witherden wrote: > On 19/08/12 23:48, Freddie Witherden wrote: >> Hello, >> >> Using the Cairo backend with the following snippet: >> >> from matplotlib.figure import Figure >> from matplotlib.artist import setp >> from matplotlib.backends.backend_agg import FigureCanvasAgg >> from matplotlib.backends.backend_cairo import FigureCanvasCairo >> import numpy as np >> >> fig = Figure() >> ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) >> x = np.arange(0, 10, 0.2) >> >> ax1.plot(x, np.sin(x)) >> ax1.xaxis.set_ticklabels(['Apr', 'Jul', 'Oct', '\'12', 'Apr', 'Jul']) >> setp(ax1.yaxis.get_ticklabels(), visible=False) >> >> FigureCanvasCairo(fig).print_figure('test.png') >> >> >> Results in the x-axis tick labels being significantly displaced. >> Specifically, "Oct" and "'12" are positioned far closer to the axis than >> either "Apr" or "Jul". >> >> With the AGG backend all of the labels are roughly aligned to the >> baseline of the font -- give or take a pixel. >> >> I have observed this on a Gentoo and Debian system, both running 1.1.1, >> albeit with different default fonts. >> >> Although I am not completely sure it appears as if a label contains a >> glyph that extends below the baseline, e.g. 'p' or 'J', that the label >> is forced away from the axis. >> >> Can anyone suggest a workaround for this (or explain where I am going >> wrong)? > I have been looking into this issue today and it /appears/ to be because > the Cairo backend -- or more precisely -- cairo::show_text method takes > a y-coordinate relative to the baseline. This makes sense given that > the descent of a font is a well-defined concept in Cairo (and can be > extracted via the font_extents method). However, as far as I can tell, > matplotlib expects the draw_text method to provide an absolute y-coordinate. > > The result is that any text with a descender is pushed downwards > (assuming a default rotation angle). This can be visualized by > > setp(ax1.xaxis.get_ticklabels(), backgroundcolor='r') > > The solution is to have the draw_text method account for any descenders. > After a bit of juggling the relevant portion of draw_text becomes: > > ctx = gc.ctx > ctx.new_path() > #ctx.move_to (x, y) > ctx.select_font_face (prop.get_name(), > self.fontangles [prop.get_style()], > self.fontweights[prop.get_weight()]) > > size = prop.get_size_in_points() * self.dpi / 72.0 > ctx.set_font_size(size) > > y_bearing, w, h = ctx.text_extents(s.encode("utf-8"))[1:4] > ctx.move_to(x, y - (h + y_bearing)) > > ctx.save() > if angle: > ctx.rotate (-angle * np.pi / 180) > #ctx.set_font_size (size) > ctx.show_text (s.encode("utf-8")) > ctx.restore() > > where commented lines highlight modifications (specifically, the > movement of the set_font_size and move_to calls). In my limited testing > this fixes the aforementioned issues. Discrepancies between baselines > are now limited to +/- 1px (the same as with the AGG backend). > Eliminating these one pixel misalignments is rather difficult so long as > text rendering is performed relative to the bounding box as opposed to a > baseline. > > Regards, Freddie. > > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > > > _______________________________________________ > Matplotlib-users mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-users |