From: <md...@us...> - 2007-08-28 15:31:56
|
Revision: 3743 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3743&view=rev Author: mdboom Date: 2007-08-28 05:27:56 -0700 (Tue, 28 Aug 2007) Log Message: ----------- Fix bug where some the images of some math expressions were truncated at the edges when using Agg backend. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py trunk/matplotlib/lib/matplotlib/mathtext.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-08-27 19:34:23 UTC (rev 3742) +++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py 2007-08-28 12:27:56 UTC (rev 3743) @@ -173,17 +173,21 @@ """ if __debug__: verbose.report('RendererAgg.draw_mathtext', 'debug-annoying') - width, height, fonts, used_characters = self.mathtext_parser.parse( - s, self.dpi.get(), prop) + ox, oy, width, height, fonts, 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 + else: + x = int(x) + ox + y = int(y) - height + oy for font in fonts: if angle == 90: font.horiz_image_to_vert_image() # <-- Rotate - self._renderer.draw_text( font, int(x)-width, int(y)-height, gc) - else: - self._renderer.draw_text( font, int(x), int(y)-height, gc) + self._renderer.draw_text( font, x, y, gc) if 0: self._renderer.draw_rectangle(gc, None, int(x), @@ -230,8 +234,8 @@ return n,m if ismath: - width, height, fonts, used_characters = self.mathtext_parser.parse( - s, self.dpi.get(), prop) + ox, oy, width, height, fonts, used_characters = \ + self.mathtext_parser.parse(s, self.dpi.get(), prop) return width, height font = self._get_agg_font(prop) font.set_text(s, 0.0, flags=LOAD_DEFAULT) # the width and height of unrotated string Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-27 19:34:23 UTC (rev 3742) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-08-28 12:27:56 UTC (rev 3743) @@ -215,7 +215,7 @@ class MathtextBackend(object): def __init__(self): - fonts_object = None + self.fonts_object = None def set_canvas_size(self, w, h): 'Dimension the drawing canvas; may be a noop' @@ -228,7 +228,7 @@ def render_filled_rect(self, x1, y1, x2, y2): raise NotImplementedError() - def get_results(self): + def get_results(self, box): """Return a backend specific tuple of things to return to the backend after all processing is done.""" raise NotImplementedError() @@ -236,7 +236,54 @@ def get_hinting_type(self): return LOAD_NO_HINTING -class MathtextBackendAgg(MathtextBackend): +class MathtextBackendBbox(MathtextBackend): + """A backend whose only purpose is to get a precise bounding box. + Only required for the Agg backend.""" + + def __init__(self, real_backend): + MathtextBackend.__init__(self) + self.bbox = [0, 0, 0, 0] + self.real_backend = real_backend + + def _update_bbox(self, x1, y1, x2, y2): + self.bbox = [min(self.bbox[0], x1), + min(self.bbox[1], y1), + max(self.bbox[2], x2), + max(self.bbox[3], y2)] + + def render_glyph(self, ox, oy, info): + self._update_bbox(ox + info.metrics.xmin, + oy + info.metrics.ymin, + ox + info.metrics.xmax, + oy + info.metrics.ymax) + + def render_rect_filled(self, x1, y1, x2, y2): + self._update_bbox(x1, y1, x2, y2) + + def get_results(self, box): + ship(0, 0, box) + bbox = self.bbox + bbox = [bbox[0] - 2, bbox[1] - 2, bbox[2] + 2, bbox[3] + 2] + self._switch_to_real_backend() + self.fonts_object.set_canvas_size(bbox[2] - bbox[0], bbox[3] - bbox[1]) + ship(-bbox[0], -bbox[1], box) + return self.fonts_object.get_results(box) + + def get_hinting_type(self): + return self.real_backend.get_hinting_type() + + def _switch_to_real_backend(self): + self.fonts_object.mathtext_backend = self.real_backend + self.real_backend.fonts_object = self.fonts_object + self.real_backend.ox = self.bbox[0] + self.real_backend.oy = self.bbox[1] + +class MathtextBackendAggRender(MathtextBackend): + def __init__(self): + self.ox = 0 + self.oy = 0 + MathtextBackend.__init__(self) + def set_canvas_size(self, w, h): MathtextBackend.set_canvas_size(self, w, h) for font in self.fonts_object.get_fonts(): @@ -248,10 +295,12 @@ def render_rect_filled(self, x1, y1, x2, y2): font = self.fonts_object.get_fonts()[0] - font.draw_rect_filled(x1, y1, x2, y2 - 1) + font.draw_rect_filled(x1, y1, x2, max(y2 - 1, y1)) - def get_results(self): - return (self.width, + def get_results(self, box): + return (self.ox, + self.oy, + self.width, self.height, self.fonts_object.get_fonts(), self.fonts_object.get_used_characters()) @@ -259,6 +308,9 @@ def get_hinting_type(self): return LOAD_DEFAULT +def MathtextBackendAgg(): + return MathtextBackendBbox(MathtextBackendAggRender()) + class MathtextBackendPs(MathtextBackend): def __init__(self): self.pswriter = StringIO() @@ -281,7 +333,8 @@ ps = "%f %f %f %f rectfill\n" % (x1, self.height - y2, x2 - x1, y2 - y1) self.pswriter.write(ps) - def get_results(self): + def get_results(self, box): + ship(0, 0, box) return (self.width, self.height, self.pswriter, @@ -302,7 +355,8 @@ def render_rect_filled(self, x1, y1, x2, y2): self.rects.append((x1, self.height - y2, x2 - x1, y2 - y1)) - def get_results(self): + def get_results(self, box): + ship(0, 0, box) return (self.width, self.height, self.glyphs, @@ -324,7 +378,8 @@ self.svg_rects.append( (x1, self.height - y1 + 1, x2 - x1, y2 - y1)) - def get_results(self): + def get_results(self, box): + ship(0, 0, box) svg_elements = Bunch(svg_glyphs = self.svg_glyphs, svg_rects = self.svg_rects) return (self.width, @@ -347,7 +402,8 @@ self.rects.append( (x1, y1 - self.height, x2 - x1, y2 - y1)) - def get_results(self): + def get_results(self, box): + ship(0, 0, box) return (self.width, self.height, self.glyphs, @@ -434,8 +490,8 @@ def get_used_characters(self): return self.used_characters - def get_results(self): - return self.mathtext_backend.get_results() + def get_results(self, box): + return self.mathtext_backend.get_results(box) def get_sized_alternatives_for_symbol(self, fontname, sym): """Override if your font provides multiple sizes of the same @@ -2384,17 +2440,16 @@ font_output = UnicodeFonts(prop, backend) fontsize = prop.get_size_in_points() + # This is a class variable so we don't rebuild the parser # with each request. if self._parser is None: self.__class__._parser = Parser() + box = self._parser.parse(s, font_output, fontsize, dpi) w, h = box.width, box.height + box.depth - w += 4 - h += 4 font_output.set_canvas_size(w, h) - ship(2, 2, box) - result = font_output.get_results() + result = font_output.get_results(box) self._cache[cacheKey] = result # Free up the transient data structures self._parser.clear() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |