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

Skip to content

Commit f4b57da

Browse files
committed
Fix #1810: Fix vertical text alignment in the Cairo and OS-X backends.
The renderer backends' draw_text method is now passed the location of the text baseline, not the bottom of the text bounding box.
1 parent 091776d commit f4b57da

File tree

224 files changed

+2821
-2046
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

224 files changed

+2821
-2046
lines changed

doc/users/whats_new.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ so that search results are printed prettily:
131131
'ytick.major.size': 4,
132132
'ytick.minor.size': 2})
133133

134+
Better vertical text alignment
135+
------------------------------
136+
137+
The vertical alignment of text is now consistent across backends. You
138+
may see small differences in text placement, particularly with rotated
139+
text.
140+
141+
If you are using a custom backend, note that the `draw_text` renderer
142+
method is now passed the location of the baseline, not the location of
143+
the bottom of the text bounding box.
144+
134145
.. _whats-new-1-2-2:
135146

136147
new in matplotlib 1.2.2

lib/matplotlib/backend_bases.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
475475
the x location of the text in display coords
476476
477477
*y*
478-
the y location of the text in display coords
478+
the y location of the text baseline in display coords
479479
480480
*s*
481481
the text string
@@ -497,7 +497,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
497497
498498
if 0: bbox_artist(self, renderer)
499499
500-
to if 1, and then the actual bounding box will be blotted along with
500+
to if 1, and then the actual bounding box will be plotted along with
501501
your text.
502502
"""
503503

lib/matplotlib/backends/backend_agg.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,10 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
154154
ox, oy, width, height, descent, font_image, used_characters = \
155155
self.mathtext_parser.parse(s, self.dpi, prop)
156156

157-
x = np.round(x + ox)
158-
y = np.round(y - oy)
157+
xd = descent * np.sin(angle / (180.0 * np.pi))
158+
yd = descent * np.cos(angle / (180.0 * np.pi))
159+
x = np.round(x + ox - xd)
160+
y = np.round(y - oy + yd)
159161
self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
160162

161163
def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
@@ -177,10 +179,14 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
177179
# space) in the following call to draw_text_image).
178180
font.set_text(s, 0, flags=flags)
179181
font.draw_glyphs_to_bitmap(antialiased=rcParams['text.antialiased'])
182+
d = font.get_descent() / 64.0
183+
# The descent needs to be adjusted for the angle
184+
xd = d * np.sin(angle / (180.0 * np.pi))
185+
yd = d * np.cos(angle / (180.0 * np.pi))
180186

181187
#print x, y, int(x), int(y), s
182188
self._renderer.draw_text_image(
183-
font.get_image(), np.round(x), np.round(y) + 1, angle, gc)
189+
font.get_image(), np.round(x - xd), np.round(y + yd) + 1, angle, gc)
184190

185191
def get_text_width_height_descent(self, s, prop, ismath):
186192
"""

lib/matplotlib/backends/backend_pdf.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,15 +1622,15 @@ def draw_gouraud_triangles(self, gc, points, colors, trans):
16221622
self.check_gc(gc)
16231623
self.file.output(name, Op.shading)
16241624

1625-
def _setup_textpos(self, x, y, descent, angle, oldx=0, oldy=0, olddescent=0, oldangle=0):
1625+
def _setup_textpos(self, x, y, angle, oldx=0, oldy=0, oldangle=0):
16261626
if angle == oldangle == 0:
1627-
self.file.output(x - oldx, (y + descent) - (oldy + olddescent), Op.textpos)
1627+
self.file.output(x - oldx, y - oldy, Op.textpos)
16281628
else:
16291629
angle = angle / 180.0 * pi
16301630
self.file.output( cos(angle), sin(angle),
16311631
-sin(angle), cos(angle),
16321632
x, y, Op.textmatrix)
1633-
self.file.output(0, descent, Op.textpos)
1633+
self.file.output(0, 0, Op.textpos)
16341634

16351635
def draw_mathtext(self, gc, x, y, s, prop, angle):
16361636
# TODO: fix positioning and encoding
@@ -1660,7 +1660,7 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
16601660
fonttype = global_fonttype
16611661

16621662
if fonttype == 42 or num <= 255:
1663-
self._setup_textpos(ox, oy, 0, 0, oldx, oldy)
1663+
self._setup_textpos(ox, oy, 0, oldx, oldy)
16641664
oldx, oldy = ox, oy
16651665
if (fontname, fontsize) != prev_font:
16661666
self.file.output(self.file.fontName(fontname), fontsize,
@@ -1762,7 +1762,7 @@ def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
17621762
self.file.output(elt[1], elt[2], Op.selectfont)
17631763
elif elt[0] == 'text':
17641764
curx, cury = mytrans.transform((elt[1], elt[2]))
1765-
self._setup_textpos(curx, cury, 0, angle, oldx, oldy)
1765+
self._setup_textpos(curx, cury, angle, oldx, oldy)
17661766
oldx, oldy = curx, cury
17671767
if len(elt[3]) == 1:
17681768
self.file.output(elt[3][0], Op.show)
@@ -1811,13 +1811,11 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
18111811
if rcParams['pdf.use14corefonts']:
18121812
font = self._get_font_afm(prop)
18131813
l, b, w, h = font.get_str_bbox(s)
1814-
descent = -b * fontsize / 1000
18151814
fonttype = 1
18161815
else:
18171816
font = self._get_font_ttf(prop)
18181817
self.track_characters(font, s)
18191818
font.set_text(s, 0.0, flags=LOAD_NO_HINTING)
1820-
descent = font.get_descent() / 64.0
18211819

18221820
fonttype = rcParams['pdf.fonttype']
18231821

@@ -1857,7 +1855,7 @@ def draw_text_simple():
18571855
self.file.fontName(prop),
18581856
fontsize,
18591857
Op.selectfont)
1860-
self._setup_textpos(x, y, descent, angle)
1858+
self._setup_textpos(x, y, angle)
18611859
self.file.output(self.encode_string(s, fonttype), Op.show, Op.end_text)
18621860

18631861
def draw_text_woven(chunks):
@@ -1878,7 +1876,6 @@ def draw_text_woven(chunks):
18781876
# output all the 2-byte characters.
18791877
for mode in (1, 2):
18801878
newx = oldx = 0
1881-
olddescent = 0
18821879
# Output a 1-byte character chunk
18831880
if mode == 1:
18841881
self.file.output(Op.begin_text,
@@ -1888,10 +1885,9 @@ def draw_text_woven(chunks):
18881885

18891886
for chunk_type, chunk in chunks:
18901887
if mode == 1 and chunk_type == 1:
1891-
self._setup_textpos(newx, 0, descent, 0, oldx, 0, olddescent, 0)
1888+
self._setup_textpos(newx, 0, 0, oldx, 0, 0)
18921889
self.file.output(self.encode_string(chunk, fonttype), Op.show)
18931890
oldx = newx
1894-
olddescent = descent
18951891

18961892
lastgind = None
18971893
for c in chunk:

lib/matplotlib/backends/backend_pgf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
643643
text_args.append("x=%fin" % (x * f))
644644
text_args.append("y=%fin" % (y * f))
645645
text_args.append("left")
646-
text_args.append("bottom")
646+
text_args.append("base")
647647

648648
if angle != 0:
649649
text_args.append("rotate=%f" % angle)

lib/matplotlib/backends/backend_ps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
755755
#print 'text', s
756756
lines = []
757757
thisx = 0
758-
thisy = font.get_descent() / 64.0
758+
thisy = 0
759759
for c in s:
760760
ccode = ord(c)
761761
gind = cmap.get(ccode)

lib/matplotlib/backends/backend_svg.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -852,8 +852,6 @@ def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None):
852852
_glyphs = text2path.get_glyphs_with_font(
853853
font, s, glyph_map=glyph_map, return_new_glyphs_only=True)
854854
glyph_info, glyph_map_new, rects = _glyphs
855-
y -= ((font.get_descent() / 64.0) *
856-
(prop.get_size_in_points() / text2path.FONT_SCALE))
857855

858856
if glyph_map_new:
859857
writer.start(u'defs')
@@ -953,8 +951,6 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
953951
if not ismath:
954952
font = self._get_font(prop)
955953
font.set_text(s, 0.0, flags=LOAD_NO_HINTING)
956-
descent = font.get_descent() / 64.0
957-
y -= descent
958954

959955
fontsize = prop.get_size_in_points()
960956

@@ -982,10 +978,9 @@ def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None):
982978
# to the anchor point manually for now.
983979
angle_rad = angle * np.pi / 180.
984980
dir_vert = np.array([np.sin(angle_rad), np.cos(angle_rad)])
985-
y += descent # Undo inappropriate text descent handling
986981
v_offset = np.dot(dir_vert, [(x - ax), (y - ay)])
987-
ax = ax + (v_offset - descent) * dir_vert[0]
988-
ay = ay + (v_offset - descent) * dir_vert[1]
982+
ax = ax + v_offset * dir_vert[0]
983+
ay = ay + v_offset * dir_vert[1]
989984

990985
ha_mpl_to_svg = {'left': 'start', 'right': 'end',
991986
'center': 'middle'}

lib/matplotlib/mathtext.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ def render_rect_filled(self, x1, y1, x2, y2):
261261
self.pswriter.write(ps)
262262

263263
def get_results(self, box, used_characters):
264-
ship(0, -self.depth, box)
264+
ship(0, 0, box)
265265
return (self.width,
266266
self.height + self.depth,
267267
self.depth,
@@ -288,7 +288,7 @@ def render_rect_filled(self, x1, y1, x2, y2):
288288
self.rects.append((x1, self.height - y2, x2 - x1, y2 - y1))
289289

290290
def get_results(self, box, used_characters):
291-
ship(0, -self.depth, box)
291+
ship(0, 0, box)
292292
return (self.width,
293293
self.height + self.depth,
294294
self.depth,
@@ -316,7 +316,7 @@ def render_rect_filled(self, x1, y1, x2, y2):
316316
(x1, self.height - y1 + 1, x2 - x1, y2 - y1))
317317

318318
def get_results(self, box, used_characters):
319-
ship(0, -self.depth, box)
319+
ship(0, 0, box)
320320
svg_elements = Bunch(svg_glyphs = self.svg_glyphs,
321321
svg_rects = self.svg_rects)
322322
return (self.width,
@@ -346,7 +346,7 @@ def render_rect_filled(self, x1, y1, x2, y2):
346346
(x1, self.height-y2 , x2 - x1, y2 - y1))
347347

348348
def get_results(self, box, used_characters):
349-
ship(0, -self.depth, box)
349+
ship(0, 0, box)
350350
return (self.width,
351351
self.height + self.depth,
352352
self.depth,
@@ -374,7 +374,7 @@ def render_rect_filled(self, x1, y1, x2, y2):
374374
(x1, y1 - self.height, x2 - x1, y2 - y1))
375375

376376
def get_results(self, box, used_characters):
377-
ship(0, -self.depth, box)
377+
ship(0, 0, box)
378378
return (self.width,
379379
self.height + self.depth,
380380
self.depth,
Binary file not shown.
Loading

0 commit comments

Comments
 (0)