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

Skip to content

Commit eca98e9

Browse files
committed
Improve vertical alignment of large delimiters and n-ary operators.
svn path=/trunk/matplotlib/; revision=3638
1 parent 4ade259 commit eca98e9

2 files changed

Lines changed: 58 additions & 38 deletions

File tree

lib/matplotlib/_mathtext_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2235,7 +2235,7 @@
22352235
'biguplus': 10756,
22362236
'epsilon': 949,
22372237
'vartheta': 977,
2238-
'bigotimes': 10754
2238+
'bigotimes': 10754
22392239
}
22402240

22412241
uni2tex = dict([(v,k) for k,v in tex2uni.items()])

lib/matplotlib/mathtext.py

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@ def get_unicode_index(symbol):
174174
or a Type1 symbol name (i.e. 'phi').
175175
176176
"""
177+
# From UTF #25: U+2212 − minus sign is the preferred
178+
# representation of the unary and binary minus sign rather than
179+
# the ASCII-derived U+002D - hyphen-minus, because minus sign is
180+
# unambiguous and because it is rendered with a more desirable
181+
# length, usually longer than a hyphen.
182+
if symbol == '-':
183+
return 0x2212
177184
try:# This will succeed if symbol is a single unicode char
178185
return ord(symbol)
179186
except TypeError:
@@ -484,7 +491,7 @@ def _get_info (self, fontname, sym, fontsize, dpi, mark_as_used=True):
484491
offset = self._get_offset(cached_font, glyph, fontsize, dpi)
485492
metrics = Bunch(
486493
advance = glyph.linearHoriAdvance/65536.0,
487-
height = glyph.height/64.0 + offset,
494+
height = glyph.height/64.0,
488495
width = glyph.width/64.0,
489496
xmin = xmin,
490497
xmax = xmax,
@@ -545,7 +552,7 @@ class BakomaFonts(TruetypeFonts):
545552
}
546553

547554
def _get_offset(self, cached_font, glyph, fontsize, dpi):
548-
if cached_font.font.postscript_name == 'cmex10':
555+
if cached_font.font.postscript_name == 'Cmex10':
549556
return glyph.height/64.0/2 + 256.0/64.0 * dpi/72.0
550557
return 0.
551558

@@ -577,8 +584,8 @@ def _get_glyph(self, fontname, sym, fontsize):
577584
('ex', '\xbd'), ('ex', '\x28')],
578585
'}' : [('cal', '}'), ('ex', '\xaa'), ('ex', '\x6f'),
579586
('ex', '\xbe'), ('ex', '\x29')],
580-
# The fourth size of '[' is mysteriously missing from the BaKoMa font,
581-
# so I've ommitted it for both
587+
# The fourth size of '[' is mysteriously missing from the BaKoMa
588+
# font, so I've ommitted it for both '[' and ']'
582589
'[' : [('rm', '['), ('ex', '\xa3'), ('ex', '\x68'),
583590
('ex', '\x22')],
584591
']' : [('rm', ']'), ('ex', '\xa4'), ('ex', '\x69'),
@@ -839,7 +846,7 @@ def get_underline_thickness(self, font, fontsize, dpi):
839846
INV_SHRINK_FACTOR = 1.0 / SHRINK_FACTOR
840847
# The number of different sizes of chars to use, beyond which they will not
841848
# get any smaller
842-
NUM_SIZE_LEVELS = 3
849+
NUM_SIZE_LEVELS = 4
843850
# Percentage of x-height of additional horiz. space after sub/superscripts
844851
SCRIPT_SPACE = 0.3
845852
# Percentage of x-height that sub/superscripts drop below the baseline
@@ -1650,7 +1657,7 @@ class Parser(object):
16501657
_punctuation_symbols = Set(r', ; . ! \ldotp \cdotp'.split())
16511658

16521659
_overunder_symbols = Set(r'''
1653-
\sum \int \prod \coprod \oint \bigcap \bigcup \bigsqcup \bigvee
1660+
\sum \prod \int \coprod \oint \bigcap \bigcup \bigsqcup \bigvee
16541661
\bigwedge \bigodot \bigotimes \bigoplus \biguplus
16551662
'''.split()
16561663
)
@@ -1758,9 +1765,11 @@ def __init__(self):
17581765
)
17591766
+ Optional(
17601767
Suppress(Literal("["))
1761-
+ OneOrMore(
1762-
symbol
1763-
^ font
1768+
+ Group(
1769+
OneOrMore(
1770+
symbol
1771+
^ font
1772+
)
17641773
)
17651774
+ Suppress(Literal("]")),
17661775
default = None
@@ -1881,12 +1890,13 @@ def non_math(self, s, loc, toks):
18811890
#~ print "non_math", toks
18821891
symbols = [Char(c, self.get_state()) for c in toks[0]]
18831892
hlist = Hlist(symbols)
1884-
self.push_state()
18851893
# We're going into math now, so set font to 'it'
1894+
self.push_state()
18861895
self.get_state().font = 'it'
18871896
return [hlist]
18881897

18891898
def _make_space(self, percentage):
1899+
# All spaces are relative to em width
18901900
state = self.get_state()
18911901
metrics = state.font_output.get_metrics(
18921902
state.font, 'm', state.fontsize, state.dpi)
@@ -1910,12 +1920,12 @@ def symbol(self, s, loc, toks):
19101920
# print "symbol", toks
19111921
c = toks[0]
19121922
if c in self._spaced_symbols:
1913-
return [Hlist([self._make_space(0.3),
1914-
Char(c, self.get_state()),
1915-
self._make_space(0.3)])]
1923+
return [Hlist( [self._make_space(0.2),
1924+
Char(c, self.get_state()),
1925+
self._make_space(0.2)] )]
19161926
elif c in self._punctuation_symbols:
1917-
return [Hlist([Char(c, self.get_state()),
1918-
self._make_space(0.3)])]
1927+
return [Hlist( [Char(c, self.get_state()),
1928+
self._make_space(0.2)] )]
19191929
try:
19201930
return [Char(toks[0], self.get_state())]
19211931
except ValueError:
@@ -1944,6 +1954,8 @@ def accent(self, s, loc, toks):
19441954
state = self.get_state()
19451955
thickness = state.font_output.get_underline_thickness(
19461956
state.font, state.fontsize, state.dpi)
1957+
if len(toks[0]) != 2:
1958+
raise ParseFatalException("Error parsing accent")
19471959
accent, sym = toks[0]
19481960
accent = Accent(self._accent_map[accent], self.get_state())
19491961
centered = HCentered([accent])
@@ -2030,7 +2042,7 @@ def subsuperscript(self, s, loc, toks):
20302042
super = next1
20312043
sub = next2
20322044
else:
2033-
raise ParseFatalException("Subscript/superscript string is too long.")
2045+
raise ParseFatalException("Subscript/superscript sequence is too long.")
20342046

20352047
state = self.get_state()
20362048
rule_thickness = state.font_output.get_underline_thickness(
@@ -2052,17 +2064,17 @@ def subsuperscript(self, s, loc, toks):
20522064
if super is not None:
20532065
hlist = HCentered([super])
20542066
hlist.hpack(width, 'exactly')
2055-
vlist.extend([hlist, Vbox(0., rule_thickness * 2.0)])
2067+
vlist.extend([hlist, Kern(rule_thickness * 2.0)])
20562068
hlist = HCentered([nucleus])
20572069
hlist.hpack(width, 'exactly')
20582070
vlist.append(hlist)
20592071
if sub is not None:
20602072
hlist = HCentered([sub])
20612073
hlist.hpack(width, 'exactly')
2062-
vlist.extend([Vbox(0., rule_thickness), hlist])
2074+
vlist.extend([Kern(rule_thickness * 2.0), hlist])
20632075
shift = hlist.height + hlist.depth + rule_thickness * 2.0
20642076
vlist = Vlist(vlist)
2065-
vlist.shift_amount = shift
2077+
vlist.shift_amount = shift + nucleus.depth * 0.5
20662078
result = Hlist([vlist])
20672079
return [result]
20682080

@@ -2120,11 +2132,11 @@ def frac(self, s, loc, toks):
21202132
width = max(num.width, den.width) + thickness * 10.
21212133
cnum.hpack(width, 'exactly')
21222134
cden.hpack(width, 'exactly')
2123-
vlist = Vlist([cnum,
2124-
Vbox(0, thickness * 2.0),
2125-
Hrule(state),
2126-
Vbox(0, thickness * 4.0),
2127-
cden
2135+
vlist = Vlist([cnum, # numerator
2136+
Vbox(0, thickness * 2.0), # space
2137+
Hrule(state), # rule
2138+
Vbox(0, thickness * 4.0), # space
2139+
cden # denominator
21282140
])
21292141

21302142
# Shift so the fraction line sits in the middle of the
@@ -2149,35 +2161,42 @@ def sqrt(self, s, loc, toks):
21492161
if root is None:
21502162
root = Box()
21512163
else:
2164+
if not isinstance(root, ParseResults):
2165+
raise ParseFatalException(
2166+
"Can not parse root of radical. Only simple symbols are allowed.")
2167+
root = Hlist(root.asList())
21522168
root.shrink()
21532169
root.shrink()
21542170

2155-
# Add a little extra to the height so the body
2156-
# doesn't seem cramped
2171+
# Determine the height of the body, and add a little extra to
2172+
# the height so it doesn't seem cramped
21572173
height = body.height - body.shift_amount + thickness * 5.0
21582174
depth = body.depth + body.shift_amount
21592175
check = AutoSizedDelim(r'\sqrt', height, depth, state, always=True)
2160-
21612176
height = check.height - check.shift_amount
21622177
depth = check.depth + check.shift_amount
2178+
2179+
# Put a little extra space to the left and right of the body
2180+
padded_body = Hlist([Hbox(thickness * 2.0),
2181+
body,
2182+
Hbox(thickness * 2.0)])
21632183
rightside = Vlist([Hrule(state),
21642184
Fill(),
2165-
# Pack a little extra to the left and right
2166-
# of the body
2167-
Hlist([Hbox(thickness * 2.0),
2168-
body,
2169-
Hbox(thickness * 2.0)])])
2185+
padded_body])
21702186
# Stretch the glue between the hrule and the body
21712187
rightside.vpack(height + 1.0, depth, 'exactly')
21722188

2189+
# Add the root and shift it upward so it is above the tick.
2190+
# The value of 0.6 is a hard-coded hack ;)
21732191
root_vlist = Vlist([Hlist([root])])
21742192
root_vlist.shift_amount = -height * 0.6
21752193

2176-
hlist = Hlist([root_vlist,
2177-
Kern(-check.width * 0.5),
2178-
check,
2179-
Kern(-thickness * 0.3),
2180-
rightside])
2194+
hlist = Hlist([root_vlist, # Root
2195+
# Negative kerning to put root over tick
2196+
Kern(-check.width * 0.5),
2197+
check, # Check
2198+
Kern(-thickness * 0.3), # Push check into rule slightly
2199+
rightside]) # Body
21812200
return [hlist]
21822201

21832202
def auto_sized_delimiter(self, s, loc, toks):
@@ -2187,6 +2206,7 @@ def auto_sized_delimiter(self, s, loc, toks):
21872206
height = max([x.height for x in middle])
21882207
depth = max([x.depth for x in middle])
21892208
parts = []
2209+
# \left. and \right. aren't supposed to produce any symbols
21902210
if front != '.':
21912211
parts.append(AutoSizedDelim(front, height, depth, state))
21922212
parts.extend(middle.asList())

0 commit comments

Comments
 (0)