@@ -174,6 +174,13 @@ def get_unicode_index(symbol):
174174or 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):
839846INV_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
844851SCRIPT_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