|
From: <md...@us...> - 2007-07-30 16:41:56
|
Revision: 3631
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3631&view=rev
Author: mdboom
Date: 2007-07-30 09:41:53 -0700 (Mon, 30 Jul 2007)
Log Message:
-----------
Major refactor to separate out backend-specific stuff from
fontset-specific stuff. What used to be the Fonts class heirarchy is
now both a Fonts heirarchy and MathtextBackend heirarchy. This should
be further improved in the future when the backends themselves are
refactored to be more consistent.
Now uses the multi-sized delimiters in the BaKoMa fonts. This
prevents the square root symbol from getting overly wide as it gets
tall. (As auto-sized parens, brackets and braces etc.)
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/_mathtext_data.py
trunk/matplotlib/lib/matplotlib/mathtext.py
Modified: trunk/matplotlib/lib/matplotlib/_mathtext_data.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-30 07:03:47 UTC (rev 3630)
+++ trunk/matplotlib/lib/matplotlib/_mathtext_data.py 2007-07-30 16:41:53 UTC (rev 3631)
@@ -14,8 +14,9 @@
print charcode, glyphind
"""
-latex_to_bakoma = {
+from sets import Set
+latex_to_bakoma = {
r'\oint' : ('cmex10', 45),
r'\bigodot' : ('cmex10', 50),
r'\bigoplus' : ('cmex10', 55),
@@ -29,13 +30,7 @@
r'\bigwedge' : ('cmex10', 4),
r'\bigvee' : ('cmex10', 37),
r'\coprod' : ('cmex10', 42),
- r'\Leftbracket' : ('cmex10', 29),
- r'\Rightbracket' : ('cmex10', 61),
- r'\Leftbrace' : ('cmex10', 43),
- r'\Rightbrace' : ('cmex10', 16),
r'\sqrt' : ('cmex10', 48),
- r'\Sqrt' : ('cmex10', 21),
- r'\SQRT' : ('cmex10', 53),
r'\leftbrace' : ('cmex10', 92),
r'{' : ('cmex10', 92),
r'\{' : ('cmex10', 92),
@@ -44,16 +39,6 @@
r'\}' : ('cmex10', 130),
r'\leftangle' : ('cmex10', 97),
r'\rightangle' : ('cmex10', 64),
- r'\Leftparen' : ('cmex10', 112),
- r'\Rightparen' : ('cmex10', 81),
- r'\LEFTparen' : ('cmex10', 119),
- r'\RIGHTparen' : ('cmex10', 87),
- r'\LEFTbracket' : ('cmex10', 125),
- r'\RIGHTbracket' : ('cmex10', 93),
- r'\LEFTbrace' : ('cmex10', 70),
- r'\RIGHTbrace' : ('cmex10', 107),
- r'\LEFTangle' : ('cmex10', 76),
- r'\RIGHTangle' : ('cmex10', 113),
r'\omega' : ('cmmi10', 29),
r'\varepsilon' : ('cmmi10', 20),
@@ -144,15 +129,15 @@
# these are mathml names, I think. I'm just using them for the
# tex methods noted
- r'\circumflexaccent' : ('cmr10', 124), # for \hat
- r'\combiningbreve' : ('cmr10', 81), # for \breve
- r'\combiningoverline' : ('cmr10', 131), # for \bar
- r'\combininggraveaccent' : ('cmr10', 114), # for \grave
- r'\combiningacuteaccent' : ('cmr10', 63), # for \accute
- r'\combiningdiaeresis' : ('cmr10', 91), # for \ddot
- r'\combiningtilde' : ('cmr10', 75), # for \tilde
+ r'\circumflexaccent' : ('cmr10', 124), # for \hat
+ r'\combiningbreve' : ('cmr10', 81), # for \breve
+ r'\combiningoverline' : ('cmr10', 131), # for \bar
+ r'\combininggraveaccent' : ('cmr10', 114), # for \grave
+ r'\combiningacuteaccent' : ('cmr10', 63), # for \accute
+ r'\combiningdiaeresis' : ('cmr10', 91), # for \ddot
+ r'\combiningtilde' : ('cmr10', 75), # for \tilde
r'\combiningrightarrowabove' : ('cmmi10', 110), # for \vec
- r'\combiningdotabove' : ('cmr10', 26), # for \dot
+ r'\combiningdotabove' : ('cmr10', 26), # for \dot
r'\leftarrow' : ('cmsy10', 10),
r'\uparrow' : ('cmsy10', 25),
@@ -199,8 +184,6 @@
r'\rceil' : ('cmsy10', 81),
r'\lbrace' : ('cmsy10', 92),
r'\rbrace' : ('cmsy10', 105),
- r'\langle' : ('cmsy10', 3),
- r'\rangle' : ('cmsy10', 88),
r'\mid' : ('cmsy10', 47),
r'\vert' : ('cmsy10', 47),
r'\Vert' : ('cmsy10', 44),
@@ -258,417 +241,6 @@
r'\spadesuit' : ('cmsy10', 7),
}
-# the kerning dictionary in design space units
-cmkern = {
- 'cmr10' :
- {
- ('A', 't') : -0.027779,
- ('A', 'C') : -0.027779,
- ('A', 'O') : -0.027779,
- ('A', 'G') : -0.027779,
- ('A', 'U') : -0.027779,
- ('A', 'Q') : -0.027779,
- ('A', 'T') : -0.083334,
- ('A', 'Y') : -0.083334,
- ('A', 'V') : -0.111112,
- ('A', 'W') : -0.111112,
- ('D', 'X') : -0.027779,
- ('D', 'W') : -0.027779,
- ('D', 'A') : -0.027779,
- ('D', 'V') : -0.027779,
- ('D', 'Y') : -0.027779,
- ('F', 'o') : -0.083334,
- ('F', 'e') : -0.083334,
- ('F', 'u') : -0.083334,
- ('F', 'r') : -0.083334,
- ('F', 'a') : -0.083334,
- ('F', 'A') : -0.111112,
- ('F', 'O') : -0.027779,
- ('F', 'C') : -0.027779,
- ('F', 'G') : -0.027779,
- ('F', 'Q') : -0.027779,
- ('I', 'I') : 0.027779,
- ('K', 'O') : -0.027779,
- ('K', 'C') : -0.027779,
- ('K', 'G') : -0.027779,
- ('K', 'Q') : -0.027779,
- ('L', 'T') : -0.083334,
- ('L', 'Y') : -0.083334,
- ('L', 'V') : -0.111112,
- ('L', 'W') : -0.111112,
- ('O', 'X') : -0.027779,
- ('O', 'W') : -0.027779,
- ('O', 'A') : -0.027779,
- ('O', 'V') : -0.027779,
- ('O', 'Y') : -0.027779,
- ('P', 'A') : -0.083334,
- ('P', 'o') : -0.027779,
- ('P', 'e') : -0.027779,
- ('P', 'a') : -0.027779,
- ('R', 't') : -0.027779,
- ('R', 'C') : -0.027779,
- ('R', 'O') : -0.027779,
- ('R', 'G') : -0.027779,
- ('R', 'U') : -0.027779,
- ('R', 'Q') : -0.027779,
- ('R', 'T') : -0.083334,
- ('R', 'Y') : -0.083334,
- ('R', 'V') : -0.111112,
- ('R', 'W') : -0.111112,
- ('T', 'y') : -0.027779,
- ('T', 'e') : -0.083334,
- ('T', 'o') : -0.083334,
- ('T', 'r') : -0.083334,
- ('T', 'a') : -0.083334,
- ('T', 'A') : -0.083334,
- ('T', 'u') : -0.083334,
- ('V', 'o') : -0.083334,
- ('V', 'e') : -0.083334,
- ('V', 'u') : -0.083334,
- ('V', 'r') : -0.083334,
- ('V', 'a') : -0.083334,
- ('V', 'A') : -0.111112,
- ('V', 'O') : -0.027779,
- ('V', 'C') : -0.027779,
- ('V', 'G') : -0.027779,
- ('V', 'Q') : -0.027779,
- ('W', 'o') : -0.083334,
- ('W', 'e') : -0.083334,
- ('W', 'u') : -0.083334,
- ('W', 'r') : -0.083334,
- ('W', 'a') : -0.083334,
- ('W', 'A') : -0.111112,
- ('W', 'O') : -0.027779,
- ('W', 'C') : -0.027779,
- ('W', 'G') : -0.027779,
- ('W', 'Q') : -0.027779,
- ('X', 'O') : -0.027779,
- ('X', 'C') : -0.027779,
- ('X', 'G') : -0.027779,
- ('X', 'Q') : -0.027779,
- ('Y', 'e') : -0.083334,
- ('Y', 'o') : -0.083334,
- ('Y', 'r') : -0.083334,
- ('Y', 'a') : -0.083334,
- ('Y', 'A') : -0.083334,
- ('Y', 'u') : -0.083334,
- ('a', 'v') : -0.027779,
- ('a', 'j') : 0.055555,
- ('a', 'y') : -0.027779,
- ('a', 'w') : -0.027779,
- ('b', 'e') : 0.027779,
- ('b', 'o') : 0.027779,
- ('b', 'x') : -0.027779,
- ('b', 'd') : 0.027779,
- ('b', 'c') : 0.027779,
- ('b', 'q') : 0.027779,
- ('b', 'v') : -0.027779,
- ('b', 'j') : 0.055555,
- ('b', 'y') : -0.027779,
- ('b', 'w') : -0.027779,
- ('c', 'h') : -0.027779,
- ('c', 'k') : -0.027779,
- ('g', 'j') : 0.027779,
- ('h', 't') : -0.027779,
- ('h', 'u') : -0.027779,
- ('h', 'b') : -0.027779,
- ('h', 'y') : -0.027779,
- ('h', 'v') : -0.027779,
- ('h', 'w') : -0.027779,
- ('k', 'a') : -0.055555,
- ('k', 'e') : -0.027779,
- ('k', 'a') : -0.027779,
- ('k', 'o') : -0.027779,
- ('k', 'c') : -0.027779,
- ('m', 't') : -0.027779,
- ('m', 'u') : -0.027779,
- ('m', 'b') : -0.027779,
- ('m', 'y') : -0.027779,
- ('m', 'v') : -0.027779,
- ('m', 'w') : -0.027779,
- ('n', 't') : -0.027779,
- ('n', 'u') : -0.027779,
- ('n', 'b') : -0.027779,
- ('n', 'y') : -0.027779,
- ('n', 'v') : -0.027779,
- ('n', 'w') : -0.027779,
- ('o', 'e') : 0.027779,
- ('o', 'o') : 0.027779,
- ('o', 'x') : -0.027779,
- ('o', 'd') : 0.027779,
- ('o', 'c') : 0.027779,
- ('o', 'q') : 0.027779,
- ('o', 'v') : -0.027779,
- ('o', 'j') : 0.055555,
- ('o', 'y') : -0.027779,
- ('o', 'w') : -0.027779,
- ('p', 'e') : 0.027779,
- ('p', 'o') : 0.027779,
- ('p', 'x') : -0.027779,
- ('p', 'd') : 0.027779,
- ('p', 'c') : 0.027779,
- ('p', 'q') : 0.027779,
- ('p', 'v') : -0.027779,
- ('p', 'j') : 0.055555,
- ('p', 'y') : -0.027779,
- ('p', 'w') : -0.027779,
- ('t', 'y') : -0.027779,
- ('t', 'w') : -0.027779,
- ('u', 'w') : -0.027779,
- ('v', 'a') : -0.055555,
- ('v', 'e') : -0.027779,
- ('v', 'a') : -0.027779,
- ('v', 'o') : -0.027779,
- ('v', 'c') : -0.027779,
- ('w', 'e') : -0.027779,
- ('w', 'a') : -0.027779,
- ('w', 'o') : -0.027779,
- ('w', 'c') : -0.027779,
- ('y', 'o') : -0.027779,
- ('y', 'e') : -0.027779,
- ('y', 'a') : -0.027779,
- },
- 'cmex10' : {},
- 'cmtt10' : {},
- 'cmsy10' : {},
- 'cmmi10' :
- {
- ('9', 'A') : -0.055555,
- ('9', 'M') : -0.055555,
- ('9', 'N') : -0.055555,
- ('9', 'Y') : 0.055555,
- ('9', 'Z') : -0.055555,
- ('d', 'Y') : 0.055555,
- ('d', 'Z') : -0.055555,
- ('d', 'j') : -0.111112,
- ('d', 'f') : -0.166667,
- },
- }
-ams_type1 = {
- r'\Leftbracket' : ( 'cmex10', '02'),
- r'\Rightbracket' : ( 'cmex10', '03'),
- r'\Leftbrace' : ( 'cmex10', '08'),
- r'\leftbrace' : ( 'cmex10', '08'),
- '{' : ( 'cmex10', '08'),
- r'\Rightbrace' : ( 'cmex10', '09'),
- r'\rightbrace' : ( 'cmex10', '09'),
- '}' : ( 'cmex10', '09'),
- r'\Leftparen' : ( 'cmex10', '10'),
- r'\Rightparen' : ( 'cmex10', '11'),
- r'\LEFTparen' : ( 'cmex10', '20'),
- r'\RIGHTparen' : ( 'cmex10', '21'),
- r'\LEFTbracket' : ( 'cmex10', '22'),
- r'\RIGHTbracket' : ( 'cmex10', '23'),
- '6' : ( 'cmex10', '26'),
- '(' : ( 'cmex10', '28'),
- r'\LEFTbrace' : ( 'cmex10', '28'),
- r'\leftparen' : ( 'cmex10', '28'),
- ')' : ( 'cmex10', '29'),
- r'\RIGHTbrace' : ( 'cmex10', '29'),
- r'\rightparen' : ( 'cmex10', '29'),
- r'\LEFTangle' : ( 'cmex10', '2A'),
- '+' : ( 'cmex10', '2B'),
- '0' : ( 'cmex10', '30'),
- '1' : ( 'cmex10', '31'),
- '2' : ( 'cmex10', '32'),
- '3' : ( 'cmex10', '33'),
- '4' : ( 'cmex10', '34'),
- '5' : ( 'cmex10', '35'),
- '7' : ( 'cmex10', '37'),
- '8' : ( 'cmex10', '38'),
- '9' : ( 'cmex10', '39'),
- ':' : ( 'cmex10', '3A'),
- ';' : ( 'cmex10', '3B'),
- '=' : ( 'cmex10', '3D'),
- r'\leftangle' : ( 'cmex10', '44'),
- r'\rightangle' : ( 'cmex10', '45'),
- r'\oint' : ( 'cmex10', '49'),
- r'\bigodot' : ( 'cmex10', '4B'),
- r'\bigoplus' : ( 'cmex10', '4D'),
- r'\bigotimes' : ( 'cmex10', '4F'),
- r'\sum' : ( 'cmex10', '58'),
- r'\prod' : ( 'cmex10', '59'),
- r'\int' : ( 'cmex10', '5A'),
- '[' : ( 'cmex10', '5B'),
- r'\bigcup' : ( 'cmex10', '5B'),
- r'\leftbracket' : ( 'cmex10', '5B'),
- r'\bigcap' : ( 'cmex10', '5C'),
- r'\biguplus' : ( 'cmex10', '5D'),
- r'\rightbracket' : ( 'cmex10', '5D'),
- ']' : ( 'cmex10', '5D'),
- r'\bigwedge' : ( 'cmex10', '5E'),
- r'\bigvee' : ( 'cmex10', '5F'),
- r'\coprod' : ( 'cmex10', '61'),
- r'\Sqrt' : ( 'cmex10', '70'),
- r'\sqrt' : ( 'cmex10', '70'),
- r'\SQRT' : ( 'cmex10', '72'),
- r'\Sigma' : ( 'cmmi10', '06'),
- r'\Upsilon' : ( 'cmmi10', '07'),
- r'\Phi' : ( 'cmmi10', '08'),
- r'\Psi' : ( 'cmmi10', '09'),
- r'\alpha' : ( 'cmmi10', '0B'),
- r'\beta' : ( 'cmmi10', '0C'),
- r'\gamma' : ( 'cmmi10', '0D'),
- r'\delta' : ( 'cmmi10', '0E'),
- r'\epsilon' : ( 'cmmi10', '0F'),
- r'\zeta' : ( 'cmmi10', '10'),
- r'\eta' : ( 'cmmi10', '11'),
- r'\theta' : ( 'cmmi10', '12'),
- r'\iota' : ( 'cmmi10', '13'),
- r'\lambda' : ( 'cmmi10', '15'),
- r'\mu' : ( 'cmmi10', '16'),
- r'\nu' : ( 'cmmi10', '17'),
- r'\xi' : ( 'cmmi10', '18'),
- r'\pi' : ( 'cmmi10', '19'),
- r'\kappa' : ( 'cmmi10', '19'),
- r'\rho' : ( 'cmmi10', '1A'),
- r'\sigma' : ( 'cmmi10', '1B'),
- r'\tau' : ( 'cmmi10', '1C'),
- r'\upsilon' : ( 'cmmi10', '1D'),
- r'\phi' : ( 'cmmi10', '1E'),
- r'\chi' : ( 'cmmi10', '1F'),
- r'\psi' : ( 'cmmi10', '20'),
- r'\omega' : ( 'cmmi10', '21'),
- r'\varepsilon' : ( 'cmmi10', '22'),
- r'\vartheta' : ( 'cmmi10', '23'),
- r'\varrho' : ( 'cmmi10', '25'),
- r'\varsigma' : ( 'cmmi10', '26'),
- r'\varphi' : ( 'cmmi10', '27'),
- r'\leftharpoonup' : ( 'cmmi10', '28'),
- r'\leftharpoondown' : ( 'cmmi10', '29'),
- r'\rightharpoonup' : ( 'cmmi10', '2A'),
- r'\rightharpoondown' : ( 'cmmi10', '2B'),
- r'\triangleright' : ( 'cmmi10', '2E'),
- r'\triangleleft' : ( 'cmmi10', '2F'),
- '.' : ( 'cmmi10', '3A'),
- ',' : ( 'cmmi10', '3B'),
- '<' : ( 'cmmi10', '3C'),
- '/' : ( 'cmmi10', '3D'),
- '>' : ( 'cmmi10', '3E'),
- r'\flat' : ( 'cmmi10', '5B'),
- r'\natural' : ( 'cmmi10', '5C'),
- r'\sharp' : ( 'cmmi10', '5D'),
- r'\smile' : ( 'cmmi10', '5E'),
- r'\frown' : ( 'cmmi10', '5F'),
- r'\ell' : ( 'cmmi10', '60'),
- r'\imath' : ( 'cmmi10', '7B'),
- r'\jmath' : ( 'cmmi10', '7C'),
- r'\wp' : ( 'cmmi10', '7D'),
- r'\Gamma' : ( 'cmr10', '00'),
- r'\Delta' : ( 'cmr10', '01'),
- r'\Theta' : ( 'cmr10', '02'),
- r'\Lambda' : ( 'cmr10', '03'),
- r'\Xi' : ( 'cmr10', '04'),
- r'\Pi' : ( 'cmr10', '05'),
- r'\Omega' : ( 'cmr10', '0A'),
- '-' : ( 'cmsy10', '00'),
- r'\cdot' : ( 'cmsy10', '01'),
- r'\times' : ( 'cmsy10', '02'),
- '*' : ( 'cmsy10', '03'),
- r'\ast' : ( 'cmsy10', '03'),
- r'\div' : ( 'cmsy10', '04'),
- r'\diamond' : ( 'cmsy10', '05'),
- r'\pm' : ( 'cmsy10', '06'),
- r'\mp' : ( 'cmsy10', '07'),
- r'\oplus' : ( 'cmsy10', '08'),
- r'\ominus' : ( 'cmsy10', '09'),
- r'\otimes' : ( 'cmsy10', '0A'),
- r'\oslash' : ( 'cmsy10', '0B'),
- r'\odot' : ( 'cmsy10', '0C'),
- r'\bigcirc' : ( 'cmsy10', '0D'),
- r'\circ' : ( 'cmsy10', '0E'),
- r'\bullet' : ( 'cmsy10', '0F'),
- r'\simeq' : ( 'cmsy10', '10'),
- r'\asymp' : ( 'cmsy10', '11'),
- r'\subseteq' : ( 'cmsy10', '12'),
- r'\supseteq' : ( 'cmsy10', '13'),
- r'\leq' : ( 'cmsy10', '14'),
- r'\geq' : ( 'cmsy10', '15'),
- r'\preceq' : ( 'cmsy10', '16'),
- r'\succeq' : ( 'cmsy10', '17'),
- r'\sim' : ( 'cmsy10', '18'),
- r'\approx' : ( 'cmsy10', '19'),
- r'\subset' : ( 'cmsy10', '1A'),
- r'\supset' : ( 'cmsy10', '1B'),
- r'\ll' : ( 'cmsy10', '1C'),
- r'\gg' : ( 'cmsy10', '1D'),
- r'\prec' : ( 'cmsy10', '1E'),
- r'\succ' : ( 'cmsy10', '1F'),
- r'\rightarrow' : ( 'cmsy10', '20'),
- r'\leftarrow' : ( 'cmsy10', '21'),
- r'\uparrow' : ( 'cmsy10', '22'),
- r'\downarrow' : ( 'cmsy10', '23'),
- r'\leftrightarrow' : ( 'cmsy10', '24'),
- r'\nearrow' : ( 'cmsy10', '25'),
- r'\searrow' : ( 'cmsy10', '26'),
- r'\Leftarrow' : ( 'cmsy10', '28'),
- r'\Rightarrow' : ( 'cmsy10', '29'),
- r'\Uparrow' : ( 'cmsy10', '2A'),
- r'\Downarrow' : ( 'cmsy10', '2B'),
- r'\Leftrightarrow' : ( 'cmsy10', '2C'),
- r'\nwarrow' : ( 'cmsy10', '2D'),
- r'\swarrow' : ( 'cmsy10', '2E'),
- r'\propto' : ( 'cmsy10', '2F'),
- r'\prime' : ( 'cmsy10', '30'),
- r'\infty' : ( 'cmsy10', '31'),
- r'\in' : ( 'cmsy10', '32'),
- r'\ni' : ( 'cmsy10', '33'),
- r'\bigtriangleup' : ( 'cmsy10', '34'),
- r'\bigtriangledown' : ( 'cmsy10', '35'),
- r'\slash' : ( 'cmsy10', '36'),
- r'\forall' : ( 'cmsy10', '38'),
- r'\exists' : ( 'cmsy10', '39'),
- r'\neg' : ( 'cmsy10', '3A'),
- r'\emptyset' : ( 'cmsy10', '3B'),
- r'\Re' : ( 'cmsy10', '3C'),
- r'\Im' : ( 'cmsy10', '3D'),
- r'\top' : ( 'cmsy10', '3E'),
- r'\bot' : ( 'cmsy10', '3F'),
- r'\aleph' : ( 'cmsy10', '40'),
- r'\cup' : ( 'cmsy10', '5B'),
- r'\cap' : ( 'cmsy10', '5C'),
- r'\uplus' : ( 'cmsy10', '5D'),
- r'\wedge' : ( 'cmsy10', '5E'),
- r'\vee' : ( 'cmsy10', '5F'),
- r'\vdash' : ( 'cmsy10', '60'),
- r'\dashv' : ( 'cmsy10', '61'),
- r'\lfloor' : ( 'cmsy10', '62'),
- r'\rfloor' : ( 'cmsy10', '63'),
- r'\lceil' : ( 'cmsy10', '64'),
- r'\rceil' : ( 'cmsy10', '65'),
- r'\lbrace' : ( 'cmsy10', '66'),
- r'\rbrace' : ( 'cmsy10', '67'),
- r'\langle' : ( 'cmsy10', '68'),
- r'\rangle' : ( 'cmsy10', '69'),
- r'\mid' : ( 'cmsy10', '6A'),
- r'\vert' : ( 'cmsy10', '6A'),
- r'\Vert' : ( 'cmsy10', '6B'),
- r'\updownarrow' : ( 'cmsy10', '6C'),
- r'\Updownarrow' : ( 'cmsy10', '6D'),
- r'\backslash' : ( 'cmsy10', '6E'),
- r'\wr' : ( 'cmsy10', '6F'),
- r'\nabla' : ( 'cmsy10', '72'),
- r'\sqcup' : ( 'cmsy10', '74'),
- r'\sqcap' : ( 'cmsy10', '75'),
- r'\sqsubseteq' : ( 'cmsy10', '76'),
- r'\sqsupseteq' : ( 'cmsy10', '77'),
- r'\S' : ( 'cmsy10', '78'),
- r'\dag' : ( 'cmsy10', '79'),
- r'\ddag' : ( 'cmsy10', '7A'),
- r'\P' : ( 'cmsy10', '7B'),
- r'\clubsuit' : ( 'cmsy10', '7C'),
- r'\diamondsuit' : ( 'cmsy10', '7D'),
- r'\heartsuit' : ( 'cmsy10', '7E'),
- r'\spadesuit' : ( 'cmsy10', '7F'),
-}
-
-"""
-no mlname for \RIGHTangle
-no type1 key \equiv # could not find in ASM
-no type1 key \kappa # could not find kappa
-no type1 key \RIGHTangle # could not find
-"""
-
latex_to_standard = {
r'\cong' : ('psyr', 64),
r'\Delta' : ('psyr', 68),
@@ -757,17 +329,60 @@
r'\langle' : ('psyr', 225),
r'\Sigma' : ('psyr', 229),
r'\sum' : ('psyr', 229),
- # these are mathml names, I think. I'm just using them for the
- # tex methods noted
- r'\circumflexaccent' : ('pncri8a', 124), # for \hat
- r'\combiningbreve' : ('pncri8a', 81), # for \breve
- r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
- r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
- r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
- r'\combiningtilde' : ('pncri8a', 75), # for \tilde
+ r'\forall' : ('psyr', 34),
+ r'\exists' : ('psyr', 36),
+ r'\lceil' : ('psyr', 233),
+ r'\lbrace' : ('psyr', 123),
+ r'\Psi' : ('psyr', 89),
+ r'\bot' : ('psyr', 0136),
+ r'\Omega' : ('psyr', 0127),
+ r'\leftbracket' : ('psyr', 0133),
+ r'\rightbracket' : ('psyr', 0135),
+ r'\leftbrace' : ('psyr', 123),
+ r'\leftparen' : ('psyr', 050),
+ r'\prime' : ('psyr', 0242),
+ r'\sharp' : ('psyr', 043),
+ r'\slash' : ('psyr', 057),
+ r'\Lamda' : ('psyr', 0114),
+ r'\neg' : ('psyr', 0330),
+ r'\Upsilon' : ('psyr', 0241),
+ r'\rightbrace' : ('psyr', 0175),
+ r'\rfloor' : ('psyr', 0373),
+ r'\lambda' : ('psyr', 0154),
+ r'\to' : ('psyr', 0256),
+ r'\Xi' : ('psyr', 0130),
+ r'\emptyset' : ('psyr', 0306),
+ r'\lfloor' : ('psyr', 0353),
+ r'\rightparen' : ('psyr', 051),
+ r'\rceil' : ('psyr', 0371),
+ r'\ni' : ('psyr', 047),
+ r'\epsilon' : ('psyr', 0145),
+ r'\Theta' : ('psyr', 0121),
+ r'\langle' : ('psyr', 0341),
+ r'\leftangle' : ('psyr', 0341),
+ r'\rangle' : ('psyr', 0361),
+ r'\rightangle' : ('psyr', 0361),
+ r'\rbrace' : ('psyr', 0175),
+ r'\circ' : ('psyr', 0260),
+ r'\diamond' : ('psyr', 0340),
+ r'\mu' : ('psyr', 0155),
+ r'\mid' : ('psyr', 0352),
+ r'\imath' : ('pncri8a', 105),
+ r'\%' : ('pncr8a', 37),
+ r'\$' : ('pncr8a', 36),
+ r'\{' : ('pncr8a', 123),
+ r'\}' : ('pncr8a', 125),
+ r'\backslash' : ('pncr8a', 92),
+ r'\ast' : ('pncr8a', 42),
+
+ r'\circumflexaccent' : ('pncri8a', 124), # for \hat
+ r'\combiningbreve' : ('pncri8a', 81), # for \breve
+ r'\combininggraveaccent' : ('pncri8a', 114), # for \grave
+ r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute
+ r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot
+ r'\combiningtilde' : ('pncri8a', 75), # for \tilde
r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec
- r'\combiningdotabove' : ('pncri8a', 26), # for \dot
- r'\imath' : ('pncri8a', 105)
+ r'\combiningdotabove' : ('pncri8a', 26), # for \dot
}
# Automatically generated.
@@ -2214,7 +1829,7 @@
'updownarrows': 8645,
'heartsuit': 9825,
'trianglelefteq': 8884,
-'ddagger': 8225,
+'ddag': 8225,
'sqsubseteq': 8849,
'mapsfrom': 8612,
'boxbar': 9707,
@@ -2516,7 +2131,7 @@
'succcurlyeq': 8829,
'gamma': 947,
'scrR': 8475,
-'dagger': 8224,
+'dag': 8224,
'thickspace': 8197,
'frakZ': 8488,
'lessdot': 8918,
@@ -2589,7 +2204,39 @@
'divideontimes': 8903,
'lbrack': 91,
'textquotedblright': 8221,
-'Colon': 8759}
+'Colon': 8759,
+'%': 37,
+'$': 36,
+'{': 123,
+'}': 125,
+'imath': 0xfd,
+'circumflexaccent' : 770,
+'combiningbreve' : 774,
+'combiningoverline' : 772,
+'combininggraveaccent' : 768,
+'combiningacuteaccent' : 764,
+'combiningdiaeresis' : 776,
+'combiningtilde' : 771,
+'combiningrightarrowabove' : 8407,
+'combiningdotabove' : 775,
+'to': 8594,
+'succeq': 8829,
+'emptyset': 8709,
+'leftparen': 40,
+'rightparen': 41,
+'bigoplus': 10753,
+'leftangle': 10216,
+'rightangle': 10217,
+'leftbrace': 124,
+'rightbrace': 125,
+'jmath': 567,
+'bigodot': 10752,
+'preceq': 8828,
+'biguplus': 10756,
+'epsilon': 949,
+'vartheta': 977,
+'bigotimes': 10754
+}
uni2tex = dict([(v,k) for k,v in tex2uni.items()])
@@ -2692,7 +2339,7 @@
'updownarrows': 'uni21C5',
'heartsuit': 'uni2661',
'trianglelefteq': 'uni22B4',
-'ddagger': 'daggerdbl',
+'ddag': 'daggerdbl',
'sqsubseteq': 'uni2291',
'mapsfrom': 'uni21A4',
'boxbar': 'uni25EB',
@@ -2994,7 +2641,7 @@
'succcurlyeq': 'uni227D',
'gamma': 'uni03B3',
'scrR': 'uni211B',
-'dagger': 'dagger',
+'dag': 'dagger',
'thickspace': 'uni2005',
'frakZ': 'uni2128',
'lessdot': 'uni22D6',
@@ -3070,4 +2717,3 @@
'Colon': 'uni2237'}
type12tex = dict([(v,k) for k,v in tex2type1.items()])
-
Modified: trunk/matplotlib/lib/matplotlib/mathtext.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 07:03:47 UTC (rev 3630)
+++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-07-30 16:41:53 UTC (rev 3631)
@@ -131,7 +131,9 @@
from __future__ import division
import os, sys
from cStringIO import StringIO
+from math import floor, ceil
from sets import Set
+from unicodedata import category
from warnings import warn
from matplotlib import verbose
@@ -146,7 +148,7 @@
is_string_like
from matplotlib.ft2font import FT2Font, KERNING_UNFITTED
from matplotlib.font_manager import fontManager, FontProperties
-from matplotlib._mathtext_data import latex_to_bakoma, cmkern, \
+from matplotlib._mathtext_data import latex_to_bakoma, \
latex_to_standard, tex2uni, type12uni, tex2type1, uni2type1
from matplotlib import get_data_path, rcParams
@@ -164,14 +166,6 @@
##############################################################################
# FONTS
-def font_open(filename):
- ext = filename.rsplit('.',1)[1]
- if ext == 'afm':
- return AFM(str(filename))
- else:
- return FT2Font(str(filename))
-
-
def get_unicode_index(symbol):
"""get_unicode_index(symbol) -> integer
@@ -187,10 +181,6 @@
try:# Is symbol a TeX symbol (i.e. \alpha)
return tex2uni[symbol.strip("\\")]
except KeyError:
- pass
- try:# Is symbol a Type1 name (i.e. degree)? If not raise error
- return type12uni[symbol]
- except KeyError:
message = """'%(symbol)s' is not a valid Unicode character or
TeX/Type1 symbol"""%locals()
raise ValueError, message
@@ -219,574 +209,473 @@
# The user did not suply a valid symbol, show usage
raise ValueError, get_type1_name.__doc__
+class MathtextBackend(object):
+ def __init__(self):
+ fonts_object = None
-class Fonts:
- """
- An abstract base class for fonts that want to render mathtext
+ def set_canvas_size(self, w, h):
+ 'Dimension the drawing canvas; may be a noop'
+ self.width = w
+ self.height = h
- The class must be able to take symbol keys and font file names and
- return the character metrics as well as do the drawing
- """
-
- def get_kern(self, facename, symleft, symright, fontsize, dpi):
- """
- Get the kerning distance for font between symleft and symright.
+ def render_glyph(self, ox, oy, info):
+ raise NotImplementedError()
- facename is one of tt, it, rm, cal or None
+ def render_filled_rect(self, x1, y1, x2, y2):
+ raise NotImplementedError()
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- """
- return 0
-
- def get_metrics(self, facename, sym, fontsize, dpi):
- """
- facename is one of tt, it, rm, cal or None
-
- sym is a single symbol(alphanum, punct) or a special symbol
- like \sigma.
-
- fontsize is in points
-
- Return object has attributes - see
- http://www.freetype.org/freetype2/docs/tutorial/step2.html for
- a pictoral representation of these attributes
-
- advance
- height
- width
- xmin, xmax, ymin, ymax - the ink rectangle of the glyph
- """
- raise NotImplementedError('Derived must override')
-
+ def get_results(self):
+ """Return a backend specific tuple of things to return to the
+ backend after all processing is done."""
+ raise NotImplementedError()
+
+class MathtextBackendAgg(MathtextBackend):
def set_canvas_size(self, w, h):
- 'Dimension the drawing canvas; may be a noop'
- self.width, self.height = w, h
+ MathtextBackend.set_canvas_size(self, w, h)
+ for font in self.fonts_object.get_fonts():
+ font.set_bitmap_size(int(w), int(h))
- def render(self, ox, oy, facename, sym, fontsize, dpi):
- pass
+ def render_glyph(self, ox, oy, info):
+ info.font.draw_glyph_to_bitmap(
+ int(ox), int(oy - info.metrics.ymax), info.glyph)
def render_rect_filled(self, x1, y1, x2, y2):
- pass
+ font = self.fonts_object.get_fonts()[0]
+ font.draw_rect_filled(
+ floor(max(0, x1 - 1)),
+ floor(y1),
+ ceil(max(x2 - 1, x1)),
+ ceil(max(y2 - 1, y1)))
+
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.fonts_object.get_fonts(),
+ self.fonts_object.get_used_characters())
- def get_used_characters(self):
- return {}
+class MathtextBackendPs(MathtextBackend):
+ def __init__(self):
+ self.pswriter = StringIO()
-
-class DummyFonts(Fonts):
- 'dummy class for debugging parser'
- def get_metrics(self, font, sym, fontsize, dpi):
-
- metrics = Bunch(
- advance = 0,
- height = 0,
- width = 0,
- xmin = 0,
- xmax = 0,
- ymin = 0,
- ymax = 0,
- )
- return metrics
-
-
-class UnicodeFonts(Fonts):
- """An abstract base class for handling Unicode fonts.
-
-Specific terminology:
- * fontface: an FT2Font object, corresponding to a facename
- * facename: a string that defines the (type)face's name - 'rm', 'it' etc.
- * filename: a string that is used for generating a fontface object
- * symbol*: a single Unicode character or a TeX command,
- or to be precise, a TeX symbol command like \alpha (but not \frac) or
- even a Type1/PS name
- * filenamesd: a dict that maps the face's name to the filename:
- filenamesd = { 'cal' : 'fontnamecal.ext',
- 'rm' : 'fontnamerm.ext',
- 'tt' : 'fontnamett.ext',
- 'it' : 'fontnameit.ext',
- None : 'fontnamesmth.ext'}
- filenamesd should be declared as a class atribute
- * glyphdict: a dict used for caching of glyph specific data
- * fonts: a dict of facename -> fontface pairs
- * charmaps: a dict of facename -> charmap pairs. Charmap maps character
- codes to glyph indices
- * glyphmaps: a dict of facename -> glyphmap pairs. A glyphmap is an
- inverted charmap
- * output: a string in ['Agg','SVG','PS'], coresponding to the backends
- * index: Fontfile specific index of a glyph.
-
-"""
-
- # The path to the dir with the fontfiles
- def __init__(self, output='Agg'):
- self.facenames = self.filenamesd.keys()
- # Set the filenames to full path
- for facename in self.filenamesd:
- self.filenamesd[facename] = self.filenamesd[facename]
- if output:
- self.output = output
- # self.glyphdict[key] = facename, metrics, glyph, offset
- self.glyphdict = {}
-
- self.fonts = dict(
- [ (facename, font_open(self.filenamesd[facename])) for
- facename in self.facenames])
- # a dict of charcode -> glyphindex pairs
- self.charmaps = dict(
- [ (facename, self.fonts[facename].get_charmap())
- for facename in self.facenames])
- # a dict of glyphindex -> charcode pairs
- self.glyphmaps = {}
- for facename in self.facenames:
- charmap = self.charmaps[facename]
- self.glyphmaps[facename] = dict([(glyphind, charcode)
- for charcode, glyphind in charmap.items()])
- for fontface in self.fonts.values():
- fontface.clear()
- if self.output == 'SVG':
- # a list of "glyphs" we need to render this thing in SVG
- self.svg_glyphs=[]
-
- def set_canvas_size(self, w, h, pswriter=None):
- 'Dimension the drawing canvas; may be a noop'
- # self.width = int(w)
- # self.height = int(h)
- # I don't know why this was different than the PS version
- self.width = w
- self.height = h
- if pswriter:
- self.pswriter = pswriter
- else:
- for fontface in self.fonts.values():
- fontface.set_bitmap_size(int(w), int(h))
-
- def render(self, ox, oy, facename, symbol, fontsize, dpi):
- filename = self.filenamesd[facename]
- uniindex, metrics, glyph, offset = self._get_info(facename,
- symbol, fontsize, dpi)
- if self.output == 'SVG':
- oy += offset - 512/2048.*10.
- # TO-DO - make a method for it
- # This gets the name of the font.
- familyname = self.fonts[facename].get_sfnt()[(1,0,0,1)]
- thetext = unichr(uniindex)
- thetext.encode('utf-8')
- self.svg_glyphs.append((familyname, fontsize, thetext, ox, oy,
- metrics))
- elif self.output == 'PS':
- # This should be changed to check for math mode or smth.
- #if filename == 'cmex10.ttf':
- # oy += offset - 512/2048.*10.
-
- # Get the PS name of a glyph (his unicode integer code)
- # from the font object
- symbolname = self._get_glyph_name(uniindex, facename)
- psfontname = self.fonts[facename].postscript_name
- ps = """/%(psfontname)s findfont
+ def render_glyph(self, ox, oy, info):
+ oy = self.height - oy + info.offset
+ postscript_name = info.postscript_name
+ fontsize = info.fontsize
+ symbol_name = info.symbol_name
+
+ ps = """/%(postscript_name)s findfont
%(fontsize)s scalefont
setfont
%(ox)f %(oy)f moveto
-/%(symbolname)s glyphshow
+/%(symbol_name)s glyphshow
""" % locals()
- self.pswriter.write(ps)
- else: # Agg
- fontface = self.fonts[facename]
- fontface.draw_glyph_to_bitmap(
- int(ox), int(self.height - oy - metrics.ymax), glyph)
+ self.pswriter.write(ps)
- def get_metrics(self, facename, symbol, fontsize, dpi):
- uniindex, metrics, glyph, offset = \
- self._get_info(facename, symbol, fontsize, dpi)
- return metrics
+ def render_rect_filled(self, x1, y1, x2, y2):
+ ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
+ self.pswriter.write(ps)
- # Methods that must be overridden for fonts that are not unicode aware
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.pswriter,
+ self.fonts_object.get_used_characters())
+
+class MathtextBackendPdf(MathtextBackend):
+ def __init__(self):
+ self.pswriter = []
+
+ def render_glyph(self, ox, oy, info):
+ filename = info.font.fname
+ oy = self.height - oy + info.offset
- def _get_unicode_index(self, symbol):
- return get_unicode_index(symbol)
+ self.pswriter.append(('glyph', ox, oy, filename, info.fontsize, info.num))
- def _get_glyph_name(self, uniindex, facename):
- """get_glyph_name(self, uniindex, facename) -> string
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
-Returns the name of the glyph directly from the font object.
+ def get_results(self):
+ return (self.width,
+ self.height,
+ self.pswriter,
+ self.fonts_object.get_used_characters())
-"""
- font = self.fonts[facename]
- glyphindex = self.glyphmaps[facename][uniindex]
- return font.get_glyph_name(glyphindex)
-
- def _get_info(self, facename, symbol, fontsize, dpi):
- 'load the facename, metrics and glyph'
- #print hex(index), symbol, filename, facename
- key = facename, symbol, fontsize, dpi
- tup = self.glyphdict.get(key)
- if tup is not None:
- return tup
- filename = self.filenamesd[facename]
- fontface = self.fonts[facename]
- fontface.set_size(fontsize, dpi)
- head = fontface.get_sfnt_table('head')
- uniindex = self._get_unicode_index(symbol)
- glyphindex = self.glyphmaps[facename][uniindex]
- glyph = fontface.load_char(uniindex)
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- # This is black magic to me (Edin)
- if filename == 'cmex10.ttf':
- if self.output == 'PS':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
- )
- self.glyphdict[key] = uniindex, metrics, glyph, offset
- return self.glyphdict[key]
-
-
-class MyUnicodeFonts(UnicodeFonts):
- _initialized = False
+class MathtextBackendSvg(MathtextBackend):
def __init__(self):
- if not MyUnicodeFonts._initialized:
- prop = FontProperties()
- prop.set_family('serif')
- self.rmfile = fontManager.findfont(prop)
+ self.svg_glyphs = []
+ self.svg_rects = []
+
+ def render_glyph(self, ox, oy, info):
+ oy = self.height - oy + info.offset
+ thetext = unichr(info.num)
+ self.svg_glyphs.append(
+ (info.font, info.fontsize, thetext, ox, oy, info.metrics))
- prop.set_family('fantasy')
- self.calfile = fontManager.findfont(prop)
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.svg_rects.append(
+ (x1, self.height - y1, x2 - x1, y2 - y1))
- prop.set_family('monospace')
- self.ttfile = fontManager.findfont(prop)
+ def get_results(self):
+ svg_elements = Bunch(svg_glyphs = self.svg_glyphs,
+ svg_rects = self.svg_rects)
+ return (self.width,
+ self.height,
+ svg_elements,
+ self.fonts_object.get_used_characters())
+
+class Fonts(object):
+ """
+ An abstract base class for fonts that want to render mathtext
- prop.set_family('serif')
- prop.set_style('italic')
- self.itfile = fontManager.findfont(prop)
- self.filenamesd = { 'rm' : self.rmfile,
- 'it' : self.itfile,
- 'cal' : self.calfile,
- 'tt' : self.ttfile,
- }
- MyUnicodeFonts._initialized = True
+ The class must be able to take symbol keys and font file names and
+ return the character metrics. It also delegates to a backend class
+ to do the actual drawing.
+ """
+ def __init__(self, default_font_prop, mathtext_backend):
+ """default_font_prop: A FontProperties object to use for the
+ default non-math font, or the base font for Unicode font
+ rendering.
+ mathtext_backend: A subclass of MathTextBackend used to
+ delegate the actual rendering."""
+ self.default_font_prop = default_font_prop
+ self.mathtext_backend = mathtext_backend
+ # Make these classes doubly-linked
+ self.mathtext_backend.fonts_object = self
+ self.used_characters = {}
+
+ def get_kern(self, font1, sym1, fontsize1,
+ font2, sym2, fontsize2, dpi):
+ """
+ Get the kerning distance for font between sym1 and sym2.
-# TO-DO: pretty much everything
-class BakomaUnicodeFonts(UnicodeFonts):
- """A class that simulates Unicode support in the BaKoMa fonts"""
+ fontX: one of the TeX font names, tt, it, rm, cal, sf, bf or
+ default (non-math)
+ symX: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+ fontsizeX: the fontsize in points
+ dpi: the current dots-per-inch
+
+ sym is a single symbol(alphanum, punct) or a special symbol
+ like \sigma.
- filenamesd = { 'cal' : 'cmsy10.ttf',
- 'rm' : 'cmr10.ttf',
- 'tt' : 'cmtt10.ttf',
- 'it' : 'cmmi10.ttf',
- 'bf' : 'cmb10.ttf',
- 'sf' : 'cmss10.ttf',
- None : 'cmmi10.ttf',
- }
+ """
+ return 0.
- # We override the UnicodeFonts methods, that depend on Unicode support
- def _get_unicode_index(self, symbol):
- uniindex = get_unicode_index(symbol)
+ def get_metrics(self, font, sym, fontsize, dpi):
+ """
+ font: one of the TeX font names, tt, it, rm, cal, sf, bf or
+ default (non-math)
+ sym: a symbol in raw TeX form. e.g. '1', 'x' or '\sigma'
+ fontsize: font size in points
+ dpi: current dots-per-inch
- # Should be deleted
- def _get_glyph_name(self, uniindex, facename):
- """get_glyph_name(self, uniindex, facename) -> string
+ advance
+ height
+ width
+ xmin, xmax, ymin, ymax - the ink rectangle of the glyph
+ iceberg - the distance from the baseline to the top of the glyph.
+ horiBearingY in Truetype parlance, height in TeX parlance
+ """
+ info = self._get_info(font, sym, fontsize, dpi)
+ return info.metrics
-Returns the name of the glyph directly from the font object.
-Because BaKoma fonts don't support Unicode, 'uniindex' is misleading
+ def set_canvas_size(self, w, h):
+ 'Dimension the drawing canvas; may be a noop'
+ self.width, self.height = ceil(w), ceil(h)
+ self.mathtext_backend.set_canvas_size(self.width, self.height)
-"""
- font = self.fonts[facename]
- glyphindex = self.glyphmaps[facename][uniindex]
- return font.get_glyph_name(glyphindex)
+ def render_glyph(self, ox, oy, facename, sym, fontsize, dpi):
+ info = self._get_info(facename, sym, fontsize, dpi)
+ realpath, stat_key = get_realpath_and_stat(info.font.fname)
+ used_characters = self.used_characters.setdefault(
+ stat_key, (realpath, Set()))
+ used_characters[1].update(unichr(info.num))
+ self.mathtext_backend.render_glyph(ox, oy, info)
- def _get_info(self, facename, symbol, fontsize, dpi):
- 'load the facename, metrics and glyph'
- #print hex(index), symbol, filename, facename
- key = facename, symbol, fontsize, dpi
- tup = self.glyphdict.get(key)
- if tup is not None:
- return tup
- filename = self.filenamesd[facename]
- fontface = self.fonts[facename]
- fontface.set_size(fontsize, dpi)
- head = fontface.get_sfnt_table('head')
- uniindex = self._get_unicode_index(symbol)
- glyphindex = self.glyphmaps[facename][uniindex]
- glyph = fontface.load_char(uniindex)
- xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- # This is black magic to me (Edin)
- if filename == 'cmex10.ttf':
- if self.output == 'PS':
- offset = -(head['yMin']+512)/head['unitsPerEm']*10.
- else:
- offset = glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
- else:
- offset = 0.
- metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
- )
- self.glyphdict[key] = uniindex, metrics, glyph, offset
- return self.glyphdict[key]
+ def render_rect_filled(self, x1, y1, x2, y2):
+ self.mathtext_backend.render_rect_filled(x1, y1, x2, y2)
+ def get_xheight(self, font, fontsize, dpi):
+ raise NotImplementedError()
-# TO-DO: Implement all methods
-class CMUUnicodeFonts(UnicodeFonts):
- """A class representing Computer Modern Unicode Fonts, made by
-Andrey V. Panov
-panov /at/ canopus. iacp. dvo. ru
-They are distributed under the X11 License.
+ def get_underline_thickness(self, font, fontsize, dpi):
+ raise NotImplementedError()
+
+ def get_used_characters(self):
+ return self.used_characters
-"""
+ def get_results(self):
+ return self.mathtext_backend.get_results()
-
-# Old classes
-
-class BakomaFonts(Fonts):
+ def get_sized_alternatives_for_symbol(self, fontname, sym):
+ """Override if your font provides multiple sizes of the same
+ symbol."""
+ return [(fontname, sym)]
+
+class TruetypeFonts(Fonts):
"""
+ A generic base class for all font setups that use Truetype fonts
+ (through ft2font)
+ """
+ """
Use the Bakoma true type fonts for rendering
"""
# allocate a new set of fonts
basepath = os.path.join( get_data_path(), 'fonts', 'ttf' )
- fontmap = { 'cal' : 'Cmsy10',
- 'rm' : 'Cmr10',
- 'tt' : 'Cmtt10',
- 'it' : 'Cmmi10',
- 'bf' : 'Cmb10',
- 'sf' : 'Cmss10',
- None : 'Cmmi10',
- 'ex' : 'Cmex10'
- }
-
class CachedFont:
def __init__(self, font):
self.font = font
self.charmap = font.get_charmap()
self.glyphmap = dict(
[(glyphind, ccode) for ccode, glyphind in self.charmap.items()])
-
- def __init__(self):
- self.glyphd = {}
- self.fonts = {}
- self.used_characters = {}
+ def __repr__(self):
+ return repr(self.font)
+
+ def __init__(self, default_font_prop, mathtext_backend):
+ Fonts.__init__(self, default_font_prop, mathtext_backend)
+ self.glyphd = {}
+ self.fonts = {}
+
+ filename = fontManager.findfont(default_font_prop)
+ default_font = self.CachedFont(FT2Font(str(filename)))
+
+ self.fonts['default'] = default_font
+
def _get_font(self, font):
"""Looks up a CachedFont with its charmap and inverse charmap.
- font may be a TeX font name (cal, rm, it etc.), a Computer Modern
- font name (cmtt10, cmr10, etc.) or an FT2Font object."""
- if isinstance(font, str):
- if font not in self.fontmap.values():
- basename = self.fontmap[font]
- else:
- basename = font
+ font may be a TeX font name (cal, rm, it etc.), or postscript name."""
+ if font in self.fontmap:
+ basename = self.fontmap[font]
else:
- basename = font.postscript_name
+ basename = font
cached_font = self.fonts.get(basename)
if cached_font is None:
- if isinstance(font, str):
- font = FT2Font(os.path.join(self.basepath, basename.lower() + ".ttf"))
- basename = font.postscript_name
+ font = FT2Font(os.path.join(self.basepath, basename + ".ttf"))
cached_font = self.CachedFont(font)
self.fonts[basename] = cached_font
- return basename, cached_font
+ self.fonts[font.postscript_name] = cached_font
+ self.fonts[font.postscript_name.lower()] = cached_font
+ return cached_font
- def get_font(self, font):
- return self._get_font(font)[1].font
-
def get_fonts(self):
- return [x.font for x in self.fonts.values()]
-
- def get_metrics(self, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- return metrics
+ return list(set([x.font for x in self.fonts.values()]))
- def _get_offset(self, basename, cached_font, glyph, fontsize, dpi):
- if basename.lower() == 'cmex10':
- return glyph.height/64.0/2 + 256.0/64.0*dpi/72.0
+ def _get_offset(self, cached_font, glyph, fontsize, dpi):
return 0.
-
- def _get_info (self, font, sym, fontsize, dpi):
+
+ def _get_info (self, fontname, sym, fontsize, dpi, mark_as_used=True):
'load the cmfont, metrics and glyph with caching'
- if hasattr(font, 'postscript_name'):
- fontname = font.postscript_name
- else:
- fontname = font
-
key = fontname, sym, fontsize, dpi
- tup = self.glyphd.get(key)
+ bunch = self.glyphd.get(key)
+ if bunch is not None:
+ return bunch
- if tup is not None: return tup
-
- if font in self.fontmap and latex_to_bakoma.has_key(sym):
- basename, num = latex_to_bakoma[sym]
- basename, cached_font = self._get_font(basename.capitalize())
- symbol_name = cached_font.font.get_glyph_name(num)
- num = cached_font.glyphmap[num]
- elif len(sym) == 1:
- basename, cached_font = self._get_font(font)
- num = ord(sym)
- symbol_name = cached_font.font.get_glyph_name(cached_font.charmap[num])
- else:
- num = 0
- raise ValueError('unrecognized symbol "%s"' % sym)
+ cached_font, num, symbol_name, fontsize = \
+ self._get_glyph(fontname, sym, fontsize)
font = cached_font.font
font.set_size(fontsize, dpi)
glyph = font.load_char(num)
- realpath, stat_key = get_realpath_and_stat(font.fname)
- used_characters = self.used_characters.setdefault(
- stat_key, (realpath, Set()))
- used_characters[1].update(unichr(num))
-
xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
- offset = self._get_offset(basename, cached_font, glyph, fontsize, dpi)
+ offset = self._get_offset(cached_font, glyph, fontsize, dpi)
metrics = Bunch(
- advance = glyph.linearHoriAdvance/65536.0,
- height = glyph.height/64.0,
- width = glyph.width/64.0,
- xmin = xmin,
- xmax = xmax,
- ymin = ymin+offset,
- ymax = ymax+offset,
+ advance = glyph.linearHoriAdvance/65536.0,
+ height = glyph.height/64.0 + offset,
+ width = glyph.width/64.0,
+ xmin = xmin,
+ xmax = xmax,
+ ymin = ymin+offset,
+ ymax = ymax+offset,
# iceberg is the equivalent of TeX's "height"
iceberg = glyph.horiBearingY/64.0 + offset
)
- self.glyphd[key] = basename, font, metrics, symbol_name, num, glyph, offset
+ self.glyphd[key] = Bunch(
+ font = font,
+ fontsize = fontsize,
+ postscript_name = font.postscript_name,
+ metrics = metrics,
+ symbol_name = symbol_name,
+ num = num,
+ glyph = glyph,
+ offset = offset
+ )
return self.glyphd[key]
- def set_canvas_size(self, w, h):
- 'Dimension the drawing canvas; may be a noop'
- self.width = int(w)
- self.height = int(h)
- for cached_font in self.fonts.values():
- cached_font.font.set_bitmap_size(int(w), int(h))
-
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
-
- font.draw_glyph_to_bitmap(
- int(ox), int(oy - metrics.ymax), glyph)
-
- def render_rect_filled(self, x1, y1, x2, y2):
- assert len(self.fonts)
- font = self.fonts.values()[0]
- font.font.draw_rect_filled(
- max(0, x1 - 1),
- y1,
- max(x2 - 1, x1),
- max(y2 - 1, y1))
-
- def get_used_characters(self):
- return self.used_characters
-
def get_xheight(self, font, fontsize, dpi):
- basename, cached_font = self._get_font(font)
+ cached_font = self._get_font(font)
cached_font.font.set_size(fontsize, dpi)
pclt = cached_font.font.get_sfnt_table('pclt')
+ if pclt is None:
+ # Some fonts don't store the xHeight, so we do a poor man's xHeight
+ metrics = self.get_metrics(font, 'x', fontsize, dpi)
+ return metrics.iceberg
xHeight = pclt['xHeight'] / 64.0
return xHeight
def get_underline_thickness(self, font, fontsize, dpi):
- basename, cached_font = self._get_font(font)
+ cached_font = self._get_font(font)
cached_font.font.set_size(fontsize, dpi)
return max(1.0, cached_font.font.underline_thickness / 64.0)
- def get_kern(self, fontleft, symleft, fontsizeleft,
- fontright, symright, fontsizeright, dpi):
- if fontsizeleft == fontsizeright:
- basename, font1, metrics, symbol_name, num1, glyph1, offset = \
- self._get_info(fontleft, symleft, fontsizeleft, dpi)
- basename, font2, metrics, symbol_name, num2, glyph2, offset = \
- self._get_info(fontright, symright, fontsizeright, dpi)
- if font1 == font2:
- basename, font = self._get_font(font1)
- return font.font.get_kerning(num1, num2, KERNING_UNFITTED) / 64.0
+ def get_kern(self, font1, sym1, fontsize1,
+ font2, sym2, fontsize2, dpi):
+ if font1 == font2 and fontsize1 == fontsize2:
+ info1 = self._get_info(font1, sym1, fontsize1, dpi)
+ info2 = self._get_info(font2, sym2, fontsize2, dpi)
+ font = info1.font
+ return font.get_kerning(info1.num, info2.num, KERNING_UNFITTED) / 64.0
return 0.0
-class BakomaPSFonts(BakomaFonts):
+class BakomaFonts(TruetypeFonts):
"""
- Use the Bakoma postscript fonts for rendering to backend_ps
+ Use the Bakoma true type fonts for rendering
"""
-
- def set_canvas_size(self, w, h, pswriter):
- 'Dimension the drawing canvas; may be a noop'
- self.width = w
- self.height = h
- self.pswriter = pswriter
-
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- oy = self.height - oy + offset
-
- ps = """/%(basename)s findfont
-%(fontsize)s scalefont
-setfont
-%(ox)f %(oy)f moveto
-/%(symbol_name)s glyphshow
-""" % locals()
- self.pswriter.write(ps)
-
- def render_rect_filled(self, x1, y1, x2, y2):
- ps = "%f %f %f %f rectfill" % (x1, self.height - y2, x2 - x1, y2 - y1)
- self.pswriter.write(ps)
+ fontmap = { 'cal' : 'cmsy10',
+ 'rm' : 'cmr10',
+ 'tt' : 'cmtt10',
+ 'it' : 'cmmi10',
+ 'bf' : 'cmb10',
+ 'sf' : 'cmss10',
+ 'ex' : 'cmex10'
+ }
-class BakomaPDFFonts(BakomaPSFonts):
- """Hack of BakomaPSFonts for PDF support."""
+ def _get_offset(self, cached_font, glyph, fontsize, dpi):
+ if cached_font.font.postscript_name == 'cmex10':
+ return glyph.height/64.0/2 + 256.0/64.0 * dpi/72.0
+ return 0.
- def render(self, ox, oy, font, sym, fontsize, dpi):
- basename, font, metrics, symbol_name, num, glyph, offset = \
- self._get_info(font, sym, fontsize, dpi)
- filename = font.fname
- oy = self.height - oy + offset
+ def _get_glyph(self, fontname, sym, fontsize):
+ if fontname in self.fontmap and latex_to_bakoma.has_key(sym):
+ basename, num = latex_to_bakoma[sym]
+ cached_font = self._get_font(basename)
+ symbol_name = cached_font.font.get_glyph_name(num)
+ num = cached_font.glyphmap[num]
+ elif len(sym) == 1:
+ cached_font = self._get_font(fontname)
+ num = ord(sym)
+ symbol_name = cached_font.font.get_glyph_name(
+ cached_font.charmap[num])
+ else:
+ raise ValueError('unrecognized symbol "%s"' % sym)
- self.pswriter.append(('glyph', ox, oy, filename, fontsize, num))
+ return cached_font, num, symbol_name, fontsize
- def render_rect_filled(self, x1, y1, x2, y2):
- self.pswriter.append(('rect', x1, self.height - y2, x2 - x1, y2 - y1))
+ # The Bakoma fonts contain many pre-sized alternatives for the
+ # delimiters. The AutoSizedChar class will use these alternatives
+ # and select the best (closest sized) glyph.
+ _size_alternatives = {
+ '(' : [('rm', '('), ('ex', '\xa1'), ('ex', '\xb3'),
+ ('ex', '\xb5'), ('ex', '\xc3')],
+ ')' : [('rm', ')'), ('ex', '\xa2'), ('ex', '\xb4'),
+ ('ex', '\xb6'), ('ex', '\x21')],
+ '{' : [('cal', '{'), ('ex', '\xa9'), ('ex', '\x6e'),
+ ('ex', '\xbd'), ('ex', '\x28')],
+ '}' : [('cal', '}'), ('ex', '\xaa'), ('ex', '\x6f'),
+ ('ex', '\xbe'), ('ex', '\x29')],
+ # The fourth size of '[' is mysteriously missing from the BaKoMa font,
+ # so I've ommitted it for both
+ '[' : [('rm', '['), ('ex', '\xa3'), ('ex', '\x68'),
+ ('ex', '\x22')],
+ ']' : [('rm', ']'), ('ex', '\xa4'), ('ex', '\x69'),
+ ('ex', '\x23')],
+ r'\lfloor' : [('cal', '\x62'), ('ex', '\xa5'), ('ex', '\x6a'),
+ ('ex', '\xb9'), ('ex', '\x24')],
+ r'\rfloor' : [('cal', '\x63'), ('ex', '\xa6'), ('ex', '\x6b'),
+ ('ex', '\xba'), ('ex', '\x25')],
+ r'\lceil' : [('cal', '\x64'), ('ex', '\xa7'), ('ex', '\x6c'),
+ ('ex', '\xbb'), ('ex', '\x26')],
+ r'\rceil' : [('cal', '\x65'), ('ex', '\xa8'), ('ex', '\x6d'),
+ ('ex', '\xbc'), ('ex', '\x27')],
+ r'\langle' : [('cal', '\x68'), ('ex', '\xad'), ('ex', '\x44'),
+ ('ex', '\xbf'), ('ex', '\x2a')],
+ r'\rangle' : [('cal', '\x69'), ('ex', '\xae'), ('ex', '\x45'),
+ ...
[truncated message content] |