|
From: <md...@us...> - 2009-12-03 20:21:32
|
Revision: 8005
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8005&view=rev
Author: mdboom
Date: 2009-12-03 20:21:21 +0000 (Thu, 03 Dec 2009)
Log Message:
-----------
Backport a number of mathtext fixes from mathtex project. Add unit tests.
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/__init__.py
trunk/matplotlib/lib/matplotlib/mathtext.py
trunk/matplotlib/lib/matplotlib/testing/decorators.py
Added Paths:
-----------
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.pdf
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.png
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.svg
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stix.pdf
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stix.png
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stix.svg
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stixsans.pdf
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stixsans.png
trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_stixsans.svg
Modified: trunk/matplotlib/lib/matplotlib/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/__init__.py 2009-12-03 19:24:30 UTC (rev 8004)
+++ trunk/matplotlib/lib/matplotlib/__init__.py 2009-12-03 20:21:21 UTC (rev 8005)
@@ -912,6 +912,7 @@
'matplotlib.tests.test_spines',
'matplotlib.tests.test_image',
'matplotlib.tests.test_simplification',
+ 'matplotlib.tests.test_mathtext'
]
def test(verbosity=0):
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2009-12-03 19:24:30 UTC (rev 8004)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2009-12-03 20:21:21 UTC (rev 8005)
@@ -999,6 +999,11 @@
if glyphindex is not None:
alternatives.append((i, unichr(uniindex)))
+ # The largest size of the radical symbol in STIX has incorrect
+ # metrics that cause it to be disconnected from the stem.
+ if sym == r'\__sqrt__':
+ alternatives = alternatives[:-1]
+
self._size_alternatives[sym] = alternatives
return alternatives
@@ -1186,7 +1191,7 @@
GROW_FACTOR = 1.0 / SHRINK_FACTOR
# The number of different sizes of chars to use, beyond which they will not
# get any smaller
-NUM_SIZE_LEVELS = 4
+NUM_SIZE_LEVELS = 6
# Percentage of x-height of additional horiz. space after sub/superscripts
SCRIPT_SPACE = 0.2
# Percentage of x-height that sub/superscripts drop below the baseline
@@ -1648,9 +1653,10 @@
"""
Convenience class to create a horizontal rule.
"""
- def __init__(self, state):
- thickness = state.font_output.get_underline_thickness(
- state.font, state.fontsize, state.dpi)
+ def __init__(self, state, thickness=None):
+ if thickness is None:
+ thickness = state.font_output.get_underline_thickness(
+ state.font, state.fontsize, state.dpi)
height = depth = thickness * 0.5
Rule.__init__(self, inf, height, depth, state)
@@ -2202,6 +2208,41 @@
| Error(r"Expected \frac{num}{den}"))
).setParseAction(self.frac).setName("frac")
+ stackrel = Group(
+ Suppress(Literal(r"\stackrel"))
+ + ((group + group)
+ | Error(r"Expected \stackrel{num}{den}"))
+ ).setParseAction(self.stackrel).setName("stackrel")
+
+
+ binom = Group(
+ Suppress(Literal(r"\binom"))
+ + ((group + group)
+ | Error(r"Expected \binom{num}{den}"))
+ ).setParseAction(self.binom).setName("binom")
+
+ ambiDelim = oneOf(list(self._ambiDelim))
+ leftDelim = oneOf(list(self._leftDelim))
+ rightDelim = oneOf(list(self._rightDelim))
+ rightDelimSafe = oneOf(list(self._rightDelim - set(['}'])))
+ genfrac = Group(
+ Suppress(Literal(r"\genfrac"))
+ + ((Suppress(Literal('{')) +
+ oneOf(list(self._ambiDelim | self._leftDelim | set(['']))) +
+ Suppress(Literal('}')) +
+ Suppress(Literal('{')) +
+ oneOf(list(self._ambiDelim |
+ (self._rightDelim - set(['}'])) |
+ set(['', r'\}']))) +
+ Suppress(Literal('}')) +
+ Suppress(Literal('{')) +
+ Regex("[0-9]*(\.?[0-9]*)?") +
+ Suppress(Literal('}')) +
+ group + group + group)
+ | Error(r"Expected \genfrac{ldelim}{rdelim}{rulesize}{style}{num}{den}"))
+ ).setParseAction(self.genfrac).setName("genfrac")
+
+
sqrt = Group(
Suppress(Literal(r"\sqrt"))
+ Optional(
@@ -2218,6 +2259,9 @@
^ accent
^ group
^ frac
+ ^ stackrel
+ ^ binom
+ ^ genfrac
^ sqrt
)
@@ -2239,9 +2283,6 @@
| placeable
)
- ambiDelim = oneOf(list(self._ambiDelim))
- leftDelim = oneOf(list(self._leftDelim))
- rightDelim = oneOf(list(self._rightDelim))
autoDelim <<(Suppress(Literal(r"\left"))
+ ((leftDelim | ambiDelim) | Error("Expected a delimiter"))
+ Group(
@@ -2626,9 +2667,9 @@
hlist = HCentered([sub])
hlist.hpack(width, 'exactly')
vlist.extend([Kern(rule_thickness * 3.0), hlist])
- shift = hlist.height + hlist.depth + rule_thickness * 2.0
+ shift = hlist.height
vlist = Vlist(vlist)
- vlist.shift_amount = shift + nucleus.depth * 0.5
+ vlist.shift_amount = shift + nucleus.depth
result = Hlist([vlist])
return [result]
@@ -2677,40 +2718,78 @@
result = Hlist([nucleus, x])
return [result]
- def frac(self, s, loc, toks):
- assert(len(toks)==1)
- assert(len(toks[0])==2)
+ def _genfrac(self, ldelim, rdelim, rule, style, num, den):
state = self.get_state()
thickness = state.font_output.get_underline_thickness(
state.font, state.fontsize, state.dpi)
- num, den = toks[0]
+ rule = float(rule)
num.shrink()
den.shrink()
cnum = HCentered([num])
cden = HCentered([den])
- width = max(num.width, den.width) + thickness * 10.
+ width = max(num.width, den.width)
cnum.hpack(width, 'exactly')
cden.hpack(width, 'exactly')
vlist = Vlist([cnum, # numerator
Vbox(0, thickness * 2.0), # space
- Hrule(state), # rule
- Vbox(0, thickness * 4.0), # space
+ Hrule(state, rule), # rule
+ Vbox(0, thickness * 2.0), # space
cden # denominator
])
# Shift so the fraction line sits in the middle of the
# equals sign
metrics = state.font_output.get_metrics(
- state.font, rcParams['mathtext.default'], '=', state.fontsize, state.dpi)
+ state.font, rcParams['mathtext.default'],
+ '=', state.fontsize, state.dpi)
shift = (cden.height -
((metrics.ymax + metrics.ymin) / 2 -
thickness * 3.0))
vlist.shift_amount = shift
- hlist = Hlist([vlist, Hbox(thickness * 2.)])
- return [hlist]
+ result = [Hlist([vlist, Hbox(thickness * 2.)])]
+ if ldelim or rdelim:
+ if ldelim == '':
+ ldelim = '.'
+ if rdelim == '':
+ rdelim = '.'
+ elif rdelim == r'\}':
+ rdelim = '}'
+ return self._auto_sized_delimiter(ldelim, result, rdelim)
+ return result
+ def genfrac(self, s, loc, toks):
+ assert(len(toks)==1)
+ assert(len(toks[0])==6)
+
+ return self._genfrac(*tuple(toks[0]))
+
+ def frac(self, s, loc, toks):
+ assert(len(toks)==1)
+ assert(len(toks[0])==2)
+ state = self.get_state()
+
+ thickness = state.font_output.get_underline_thickness(
+ state.font, state.fontsize, state.dpi)
+ num, den = toks[0]
+
+ return self._genfrac('', '', thickness, '', num, den)
+
+ def stackrel(self, s, loc, toks):
+ assert(len(toks)==1)
+ assert(len(toks[0])==2)
+ num, den = toks[0]
+
+ return self._genfrac('', '', 0.0, '', num, den)
+
+ def binom(self, s, loc, toks):
+ assert(len(toks)==1)
+ assert(len(toks[0])==2)
+ num, den = toks[0]
+
+ return self._genfrac('(', ')', 0.0, '', num, den)
+
def sqrt(self, s, loc, toks):
#~ print "sqrt", toks
root, body = toks[0]
@@ -2756,9 +2835,7 @@
rightside]) # Body
return [hlist]
- def auto_sized_delimiter(self, s, loc, toks):
- #~ print "auto_sized_delimiter", toks
- front, middle, back = toks
+ def _auto_sized_delimiter(self, front, middle, back):
state = self.get_state()
height = max([x.height for x in middle])
depth = max([x.depth for x in middle])
@@ -2766,12 +2843,19 @@
# \left. and \right. aren't supposed to produce any symbols
if front != '.':
parts.append(AutoHeightChar(front, height, depth, state))
- parts.extend(middle.asList())
+ parts.extend(middle)
if back != '.':
parts.append(AutoHeightChar(back, height, depth, state))
hlist = Hlist(parts)
return hlist
+
+ def auto_sized_delimiter(self, s, loc, toks):
+ #~ print "auto_sized_delimiter", toks
+ front, middle, back = toks
+
+ return self._auto_sized_delimiter(front, middle.asList(), back)
+
###
##############################################################################
Modified: trunk/matplotlib/lib/matplotlib/testing/decorators.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/testing/decorators.py 2009-12-03 19:24:30 UTC (rev 8004)
+++ trunk/matplotlib/lib/matplotlib/testing/decorators.py 2009-12-03 20:21:21 UTC (rev 8005)
@@ -88,7 +88,7 @@
orig_expected_fnames = [os.path.join(baseline_dir,fname) + '.' + extension for fname in baseline_images]
expected_fnames = [os.path.join(result_dir,'expected-'+fname) + '.' + extension for fname in baseline_images]
for src,dst in zip( orig_expected_fnames, expected_fnames ):
- if not os.path.exists(dst):
+ if os.path.exists(src) and not os.path.exists(dst):
shutil.copyfile(src,dst)
actual_fnames = [os.path.join(result_dir, fname) + '.' + extension for fname in baseline_images]
have_baseline_images = [os.path.exists(expected) for expected in expected_fnames]
Added: trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.pdf
===================================================================
--- trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.pdf (rev 0)
+++ trunk/matplotlib/lib/matplotlib/tests/baseline_images/test_mathtext/mathtext.pdf 2009-12-03 20:21:21 UTC (rev 8005)
@@ -0,0 +1,2076 @@
+%PDF-1.4
+%\xAC\xDC \xAB\xBA
+1 0 obj
+<< /Type /Catalog /Pages 2 0 R >>
+endobj
+8 0 obj
+<< /XObject 7 0 R /Pattern 5 0 R
+/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /ExtGState 4 0 R
+/Shading 6 0 R /Font 3 0 R >>
+endobj
+10 0 obj
+<< /Contents 9 0 R /Type /Page /Resources 8 0 R /Parent 2 0 R
+/MediaBox [ 0 0 360 2268 ] >>
+endobj
+9 0 obj
+<< /Filter /FlateDecode /Length 11 0 R >>
+stream
+x\x9C\xED\{\xAF\xB7q\xFF\xFF~\x8A\xD34E\xAFa\x9C5\xDF\xB7\x8A \xB1\x93\xFC\xA4UZ\xB9(Ȗ\xE4J\x96d=\xC0N\x81|\xBB\xE9#\x9AčS\xA4\xAD\xEC\xB4M?Xg\x96C\xEE\x90K\xEE\xD9s\xAF\x8A&\x818\x92\xF6p\x87\xDC\xE1<~\xF3 \xE5\xE1\xFE\x85:|\xF3 \xEF\xC0o\\x88\x838<<h\x87>\x98\xFFT\xCA\xF8+\xFB\xFCr\xF1\xF9M\xF8\xDB;\xF0\xDFO.$\xFCy9\x8F\xD3\xEA\xF0\xF6Ë\xAF܀1rr^o7n_\xBC\xF2\xBA<Hu\xB8q\xF7\xE2\xF2\xD6K\x87\xF7/\xC2d\x8C\xD2:e\xE1\xBDy\x84\xCA#^\x9EGH1 o}\x90ˈB\xE3\xADy\x84\x9F\x94\xF5F\xCDs\xF4i(;yu\xFE=S\x96\x93py\xEE)\xFD\x8E\xBF~w\xFE\xF5(\xA6>;\xB2\xD9\xE4\xCFhr\xAF\x84\x96\xC3\xE5\xED\xC6\xC5\xA4\x91m\xE9o\xDAO\xD1\xFA\xF4Za\xF0\xEB\x95?\xBB\xF1\x8D\x9Bo\xDCyt\xE7\xE9\xAD\xC7;\xDC{\xFC\xEC\xC3W\xF8v\x87\x88\x8F\x93\xB6\xD68|w'\x91o7\xDB$\xA3+ۤ\xFB\xDB\xF4AbU\x98\xA4r\xD2/<\xBE\xFCp\xFCy\xBE\xCE9#\x90\xB1z\xB4\xB2\xEF=\xBA\xA7\x94\x83\x85\x81\xD4兩\xA9\xAC\xCA\xE4U}\x99x\xEF\xB4\xF1n\x9EK9x.\xCE|>\xCD\xCF\xF5\xA41v\xD9ݳ\xE9\xFAt\x92\xDFt1V"l\xF3\x88\xEFfF\xAF\x98\xA4̢db\xF2Y\xFE@\xA7\x93̤*\xE6,\xFF\xDB\xFF\xC6EfR\xAF&5\x9At\xD4\xCE\x96\x87\xF4\xA9Aɖ\x97\x8E \xF7j\xD6\xE4\x86>\xA6賊\xB3X+?\xD9e\xC6 \xFE\xEF\xE9\x9D\xC3\xDD\xC3Z^DL\x90I\xB3z\x82\xEC\xA6`\xA2\xE3\xB6\xE0\xC3{\x85U\x8C\xA6\x92\xE4\xD2~\xBE K\xD3\xC7I\xAD-[\xD6iگ\xBDhڗL㍶\xCC"_c\x89\xAF\x92\xF8\xFBҿMz\xBDYD\xAD\xFBW\xB8"\xC3V\xF8'\xF4\xA6V\xE0۸j\x96ؓɌgC6\xA9\x9A\xABT\xA1\xFF\xAF?\xA0\xC4f\x85W\x97\xDF\xFC!}\xBDU!\x8A\xF1\xA7\xED\xE7\xFEk\xD5\xCA\xD3\xDBv
+A-ҷ\x83\xE5_\xE6Tv0Z\xC6 \xF6y\xA9-f\xFC:i\x8B\x9A|e\xA1\xAF\xCE
+F;\xD0甼\xCA&n\xD1\xFE\xE8\xCA*\xA3a\xFEa\xF2ɤ\xEE2\x8A\xAF\xBC\xEE\xEBv\xAA\xF47\xB4\xEF\xAFVW\xD6\x93v&#\x95V>\xAE^\xEC4\xE9h+\x99\x9F#\xBC\xAB\xDCU\xFE\xC1N\xCA{\xAFM\xBB
+\xE7\xB1a\xBDAF\x80ũ\xF66\xBF\xBF\xFA\xB2<\x85\x9Ad-\xB5\x9F<C\xCAf"\xC3;g\xCC\xDF\xF9#\xE2r\xB1\xE8U\xB3I\xAD\xD9\xF9V_/\x9F\x92wv\xB1\xC0[\x95J\xBFM\x9B\xAD\xACwg\xF0\xFCQ\xF5*\xD0\xC2ۅ\x95o\xF8\xF1\x90z1\xA3
+\xF8\xAC |