Skip to content

Commit c10b4bb

Browse files
committed
Merging mathtext changes into trunk.
svn path=/trunk/matplotlib/; revision=3617
1 parent 43dbe48 commit c10b4bb

File tree

17 files changed

+2863
-1446
lines changed

17 files changed

+2863
-1446
lines changed

examples/mathtext_demo.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,25 @@
11
#!/usr/bin/env python
22
"""
3-
4-
In order to use mathtext, you must build matplotlib.ft2font. This is
5-
built by default in the windows installer.
6-
7-
For other platforms, edit setup.py and set
8-
9-
BUILD_FT2FONT = True
10-
3+
Use matplotlib's internal LaTex parser and layout engine. For true
4+
latex rendering, see the text.usetex option
115
"""
12-
from pylab import *
13-
subplot(111, axisbg='y')
14-
plot([1,2,3], 'r')
15-
x = arange(0.0, 3.0, 0.1)
6+
import numpy as npy
7+
from pylab import figure, show
8+
fig = figure()
9+
fig.subplots_adjust(bottom=0.2)
1610

17-
grid(True)
18-
xlabel(r'$\Delta_i^j$', fontsize=20)
19-
ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
20-
tex = r'$\cal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\rm{sin}(2 \pi f x_i)$'
21-
text(1, 1.6, tex, fontsize=20)
11+
ax = fig.add_subplot(111, axisbg='y')
12+
ax.plot([1,2,3], 'r')
13+
x = npy.arange(0.0, 3.0, 0.1)
2214

23-
#title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
24-
savefig('mathtext_demo')
15+
ax.grid(True)
16+
ax.set_xlabel(r'$\Delta_i^j$', fontsize=20)
17+
ax.set_ylabel(r'$\Delta_{i+1}^j$', fontsize=20)
18+
tex = r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i\sin(2 \pi f x_i)$'
2519

20+
ax.text(1, 1.6, tex, fontsize=20, va='bottom')
2621

22+
#title(r'$\Delta_i^j \hspace{0.4} \rm{versus} \hspace{0.4} \Delta_{i+1}^j$', fontsize=20)
23+
fig.savefig('mathtext_demo')
2724

2825
show()

examples/mathtext_examples.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env python
2+
3+
import os, sys
4+
5+
stests = [
6+
r'Kerning: AVA $AVA$',
7+
r'$x y$',
8+
r'$x+y\ x=y\ x<y\ x:y\ x,y\ x@y$',
9+
r'$100\%y\ x*y\ x/y x\$y$',
10+
r'$x\leftarrow y\ x\forall y$',
11+
r'$x \sf x \bf x {\cal X} \rm x$',
12+
r'$\{ \rm braces \}$',
13+
r'$\left[\left\lfloor\frac{5}{\frac{\left(3\right)}{4}} y\right)\right]$',
14+
r'$\left(x\right)$',
15+
r'$\sin(x)$',
16+
r'$x_2$',
17+
r'$x^2$',
18+
r'$x^2_y$',
19+
r'$x_y^2$',
20+
r'$\prod_{i=\alpha_{i+1}}^\infty$',
21+
r'$x = \frac{x+\frac{5}{2}}{\frac{y+3}{8}}$',
22+
r'$dz/dt \/ = \/ \gamma x^2 \/ + \/ {\rm sin}(2\pi y+\phi)$',
23+
r'Foo: $\alpha_{i+1}^j \/ = \/ {\rm sin}(2\pi f_j t_i) e^{-5 t_i/\tau}$',
24+
r'$\mathcal{R}\prod_{i=\alpha_{i+1}}^\infty a_i \sin(2 \pi f x_i)$',
25+
# r'$\bigodot \bigoplus {\sf R} a_i{\rm sin}(2 \pi f x_i)$',
26+
r'Variable $i$ is good',
27+
r'$\Delta_i^j$',
28+
r'$\Delta^j_{i+1}$',
29+
r'$\ddot{o}\acute{e}\grave{e}\hat{O}\breve{\imath}\tilde{n}\vec{q}$',
30+
r'$_i$',
31+
r"$\arccos((x^i))$",
32+
r"$\gamma = \frac{x=\frac{6}{8}}{y} \delta$",
33+
r'$\"o\ddot o \'e\`e\~n\.x\^y$',
34+
35+
]
36+
37+
from pylab import *
38+
39+
if '--latex' in sys.argv:
40+
fd = open("mathtext_examples.ltx", "w")
41+
fd.write("\\documentclass{article}\n")
42+
fd.write("\\begin{document}\n")
43+
fd.write("\\begin{enumerate}\n")
44+
45+
for i, s in enumerate(stests):
46+
fd.write("\\item %s\n" % s)
47+
48+
fd.write("\\end{enumerate}\n")
49+
fd.write("\\end{document}\n")
50+
fd.close()
51+
52+
os.system("pdflatex mathtext_examples.ltx")
53+
else:
54+
for i, s in enumerate(stests):
55+
print "%02d: %s" % (i, s)
56+
plot([1,2,3], 'r')
57+
x = arange(0.0, 3.0, 0.1)
58+
59+
grid(True)
60+
text(1, 1.6, s, fontsize=20)
61+
62+
savefig('mathtext_example%02d' % i)
63+
figure()
64+

lib/matplotlib/_mathtext_data.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
r'\SQRT' : ('cmex10', 53),
3939
r'\leftbrace' : ('cmex10', 92),
4040
r'{' : ('cmex10', 92),
41+
r'\{' : ('cmex10', 92),
4142
r'\rightbrace' : ('cmex10', 130),
4243
r'}' : ('cmex10', 130),
44+
r'\}' : ('cmex10', 130),
4345
r'\leftangle' : ('cmex10', 97),
4446
r'\rightangle' : ('cmex10', 64),
4547
r'\Leftparen' : ('cmex10', 112),
@@ -112,7 +114,7 @@
112114
r'\phi' : ('cmmi10', 42),
113115
r'\chi' : ('cmmi10', 17),
114116
r'\psi' : ('cmmi10', 31),
115-
117+
116118
r'(' : ('cmr10', 119),
117119
r'\leftparen' : ('cmr10', 119),
118120
r'\rightparen' : ('cmr10', 68),
@@ -135,7 +137,11 @@
135137
r'[' : ('cmr10', 62),
136138
r'\rightbracket' : ('cmr10', 72),
137139
r']' : ('cmr10', 72),
138-
140+
r'\%' : ('cmr10', 48),
141+
r'%' : ('cmr10', 48),
142+
r'\$' : ('cmr10', 99),
143+
r'@' : ('cmr10', 111),
144+
139145
# these are mathml names, I think. I'm just using them for the
140146
# tex methods noted
141147
r'\circumflexaccent' : ('cmr10', 124), # for \hat
@@ -749,7 +755,17 @@
749755
r'\langle' : ('psyr', 225),
750756
r'\Sigma' : ('psyr', 229),
751757
r'\sum' : ('psyr', 229),
752-
758+
# these are mathml names, I think. I'm just using them for the
759+
# tex methods noted
760+
r'\circumflexaccent' : ('pncri8a', 124), # for \hat
761+
r'\combiningbreve' : ('pncri8a', 81), # for \breve
762+
r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
763+
r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
764+
r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
765+
r'\combiningtilde' : ('pncri8a', 75), # for \tilde
766+
r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec
767+
r'\combiningdotabove' : ('pncri8a', 26), # for \dot
768+
r'\imath' : ('pncri8a', 105)
753769
}
754770

755771
# Automatically generated.

lib/matplotlib/afm.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,14 @@ def get_angle(self):
394394
"Return the fontangle as float"
395395
return self._header['ItalicAngle']
396396

397-
397+
def get_xheight(self):
398+
"Return the xheight as float"
399+
return self._header['XHeight']
400+
401+
def get_underline_thickness(self):
402+
"Return the underline thickness as float"
403+
return self._header['UnderlineThickness']
404+
398405

399406
if __name__=='__main__':
400407
#pathname = '/usr/local/lib/R/afm/'

lib/matplotlib/backends/backend_agg.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,9 @@ def draw_mathtext(self, gc, x, y, s, prop, angle):
173173
"""
174174
if __debug__: verbose.report('RendererAgg.draw_mathtext',
175175
'debug-annoying')
176-
size = prop.get_size_in_points()
177-
width, height, fonts = math_parse_s_ft2font(
178-
s, self.dpi.get(), size, angle)
179-
176+
width, height, fonts, used_characters = math_parse_s_ft2font(
177+
s, self.dpi.get(), prop, angle)
178+
180179
if angle == 90:
181180
width, height = height, width
182181
for font in fonts:
@@ -225,7 +224,6 @@ def get_text_width_height(self, s, prop, ismath, rgb=(0,0,0)):
225224
# texmanager more efficient. It is not meant to be used
226225
# outside the backend
227226
"""
228-
229227
if ismath=='TeX':
230228
# todo: handle props
231229
size = prop.get_size_in_points()
@@ -235,8 +233,8 @@ def get_text_width_height(self, s, prop, ismath, rgb=(0,0,0)):
235233
return n,m
236234

237235
if ismath:
238-
width, height, fonts = math_parse_s_ft2font(
239-
s, self.dpi.get(), prop.get_size_in_points())
236+
width, height, fonts, used_characters = math_parse_s_ft2font(
237+
s, self.dpi.get(), prop)
240238
return width, height
241239
font = self._get_agg_font(prop)
242240
font.set_text(s, 0.0) # the width and height of unrotated string

lib/matplotlib/backends/backend_cairo.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,8 @@ def _draw_mathtext(self, gc, x, y, s, prop, angle):
314314
# "_draw_mathtext()")
315315
# return
316316

317-
size = prop.get_size_in_points()
318-
width, height, fonts = math_parse_s_ft2font(
319-
s, self.dpi.get(), size)
317+
width, height, fonts, used_characters = math_parse_s_ft2font(
318+
s, self.dpi.get(), prop)
320319

321320
if angle==90:
322321
width, height = height, width
@@ -372,8 +371,8 @@ def get_canvas_width_height(self):
372371
def get_text_width_height(self, s, prop, ismath):
373372
if _debug: print '%s.%s()' % (self.__class__.__name__, _fn_name())
374373
if ismath:
375-
width, height, fonts = math_parse_s_ft2font(
376-
s, self.dpi.get(), prop.get_size_in_points())
374+
width, height, fonts, used_characters = math_parse_s_ft2font(
375+
s, self.dpi.get(), prop)
377376
return width, height
378377

379378
ctx = self.text_ctx

lib/matplotlib/backends/backend_gdk.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath):
198198

199199

200200
def _draw_mathtext(self, gc, x, y, s, prop, angle):
201-
size = prop.get_size_in_points()
202-
width, height, fonts = math_parse_s_ft2font(
203-
s, self.dpi.get(), size)
201+
width, height, fonts, used_characters = math_parse_s_ft2font(
202+
s, self.dpi.get(), prop)
204203

205204
if angle==90:
206205
width, height = height, width
@@ -342,8 +341,8 @@ def get_canvas_width_height(self):
342341

343342
def get_text_width_height(self, s, prop, ismath):
344343
if ismath:
345-
width, height, fonts = math_parse_s_ft2font(
346-
s, self.dpi.get(), prop.get_size_in_points())
344+
width, height, fonts, used_characters = math_parse_s_ft2font(
345+
s, self.dpi.get(), prop)
347346
return width, height
348347

349348
layout, inkRect, logicalRect = self._get_pango_layout(s, prop)

lib/matplotlib/backends/backend_pdf.py

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,9 @@ def writeFonts(self):
457457
fontdictObject = self._write_afm_font(filename)
458458
else:
459459
realpath, stat_key = get_realpath_and_stat(filename)
460-
fontdictObject = self.embedTTF(
461-
*self.used_characters[stat_key])
460+
chars = self.used_characters.get(stat_key)
461+
if chars is not None and len(chars[1]):
462+
fontdictObject = self.embedTTF(realpath, chars[1])
462463
fonts[Fx] = fontdictObject
463464
#print >>sys.stderr, filename
464465
self.writeObject(self.fontObject, fonts)
@@ -1092,37 +1093,36 @@ def _setup_textpos(self, x, y, angle, oldx=0, oldy=0, oldangle=0):
10921093

10931094
def draw_mathtext(self, gc, x, y, s, prop, angle):
10941095
# TODO: fix positioning and encoding
1095-
fontsize = prop.get_size_in_points()
10961096
width, height, pswriter, used_characters = \
1097-
math_parse_s_pdf(s, 72, fontsize, 0)
1097+
math_parse_s_pdf(s, 72, prop, 0)
10981098
self.merge_used_characters(used_characters)
1099-
1099+
11001100
self.check_gc(gc, gc._rgb)
11011101
self.file.output(Op.begin_text)
11021102
prev_font = None, None
11031103
oldx, oldy = 0, 0
1104-
for ox, oy, fontname, fontsize, glyph in pswriter:
1105-
#print ox, oy, glyph
1106-
fontname = fontname.lower()
1107-
a = angle / 180.0 * pi
1108-
newx = x + cos(a)*ox - sin(a)*oy
1109-
newy = y + sin(a)*ox + cos(a)*oy
1110-
self._setup_textpos(newx, newy, angle, oldx, oldy)
1111-
oldx, oldy = newx, newy
1112-
if (fontname, fontsize) != prev_font:
1113-
self.file.output(self.file.fontName(fontname), fontsize,
1114-
Op.selectfont)
1115-
prev_font = fontname, fontsize
1116-
1117-
#if fontname.endswith('cmsy10.ttf') or \
1118-
#fontname.endswith('cmmi10.ttf') or \
1119-
#fontname.endswith('cmex10.ttf'):
1120-
# string = '\0' + chr(glyph)
1121-
1122-
string = chr(glyph)
1123-
self.file.output(string, Op.show)
1104+
for record in pswriter:
1105+
if record[0] == 'glyph':
1106+
rec_type, ox, oy, fontname, fontsize, glyph = record
1107+
a = angle / 180.0 * pi
1108+
newx = x + cos(a)*ox - sin(a)*oy
1109+
newy = y + sin(a)*ox + cos(a)*oy
1110+
self._setup_textpos(newx, newy, angle, oldx, oldy)
1111+
oldx, oldy = newx, newy
1112+
if (fontname, fontsize) != prev_font:
1113+
self.file.output(self.file.fontName(fontname), fontsize,
1114+
Op.selectfont)
1115+
prev_font = fontname, fontsize
1116+
1117+
string = chr(glyph)
1118+
self.file.output(string, Op.show)
11241119
self.file.output(Op.end_text)
11251120

1121+
for record in pswriter:
1122+
if record[0] == 'rect':
1123+
rec_type, ox, oy, width, height = record
1124+
self.file.output(Op.gsave, x + ox, y + oy, width, height, Op.rectangle, Op.fill, Op.grestore)
1125+
11261126
def _draw_tex(self, gc, x, y, s, prop, angle):
11271127
# Rename to draw_tex to enable, but note the following:
11281128
# TODO:
@@ -1208,9 +1208,7 @@ def get_text_width_height(self, s, prop, ismath):
12081208
s = s.encode('cp1252', 'replace')
12091209

12101210
if ismath:
1211-
fontsize = prop.get_size_in_points()
1212-
w, h, pswriter, used_characters = math_parse_s_pdf(
1213-
s, 72, fontsize, 0)
1211+
w, h, pswriter, used_characters = math_parse_s_pdf(s, 72, prop, 0)
12141212

12151213
elif rcParams['pdf.use14corefonts']:
12161214
font = self._get_font_afm(prop)

lib/matplotlib/backends/backend_ps.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def get_text_width_height(self, s, prop, ismath):
278278

279279
if ismath:
280280
width, height, pswriter, used_characters = math_parse_s_ps(
281-
s, 72, prop.get_size_in_points(), 0)
281+
s, 72, prop, 0)
282282
return width, height
283283

284284
if rcParams['ps.useafm']:
@@ -813,11 +813,9 @@ def draw_mathtext(self, gc,
813813
if debugPS:
814814
self._pswriter.write("% mathtext\n")
815815

816-
fontsize = prop.get_size_in_points()
817816
width, height, pswriter, used_characters = \
818-
math_parse_s_ps(s, 72, fontsize, angle)
817+
math_parse_s_ps(s, 72, prop, angle)
819818
self.merge_used_characters(used_characters)
820-
821819
self.set_color(*gc.get_rgb())
822820
thetext = pswriter.getvalue()
823821
ps = """gsave
@@ -1038,13 +1036,14 @@ def print_figure(self, outfile, dpi=72, facecolor='w', edgecolor='w',
10381036
print >>fh, l.strip()
10391037
if not rcParams['ps.useafm']:
10401038
for font_filename, chars in renderer.used_characters.values():
1041-
font = FT2Font(font_filename)
1042-
cmap = font.get_charmap()
1043-
glyph_ids = []
1044-
for c in chars:
1045-
gind = cmap.get(ord(c)) or 0
1046-
glyph_ids.append(gind)
1047-
convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids)
1039+
if len(chars):
1040+
font = FT2Font(font_filename)
1041+
cmap = font.get_charmap()
1042+
glyph_ids = []
1043+
for c in chars:
1044+
gind = cmap.get(ord(c)) or 0
1045+
glyph_ids.append(gind)
1046+
convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids)
10481047
print >>fh, "end"
10491048
print >>fh, "%%EndProlog"
10501049

0 commit comments

Comments
 (0)