@@ -528,7 +528,7 @@ class TruetypeFonts(Fonts):
528
528
A generic base class for all font setups that use Truetype fonts
529
529
(through ft2font)
530
530
"""
531
- basepath = os .path .join ( get_data_path (), 'fonts' , 'ttf' )
531
+ basepath = os .path .join ( get_data_path (), 'fonts' )
532
532
533
533
class CachedFont :
534
534
def __init__ (self , font ):
@@ -665,7 +665,7 @@ def __init__(self, *args, **kwargs):
665
665
TruetypeFonts .__init__ (self , * args , ** kwargs )
666
666
if not len (self .fontmap ):
667
667
for key , val in self ._fontmap .iteritems ():
668
- fullpath = os .path .join (self .basepath , val + ".ttf" )
668
+ fullpath = os .path .join (self .basepath , 'ttf' , val + ".ttf" )
669
669
self .fontmap [key ] = fullpath
670
670
self .fontmap [val ] = fullpath
671
671
@@ -750,7 +750,8 @@ class UnicodeFonts(TruetypeFonts):
750
750
"""
751
751
752
752
fontmap = {}
753
-
753
+ use_cmex = True
754
+
754
755
def __init__ (self , * args , ** kwargs ):
755
756
# This must come first so the backend's owner is set correctly
756
757
if rcParams ['mathtext.fallback_to_cm' ]:
@@ -772,18 +773,20 @@ def __init__(self, *args, **kwargs):
772
773
def _get_glyph (self , fontname , sym , fontsize ):
773
774
found_symbol = False
774
775
775
- uniindex = latex_to_cmex .get (sym )
776
- if uniindex is not None :
777
- fontname = 'ex'
778
- found_symbol = True
779
- else :
776
+ if self .use_cmex :
777
+ uniindex = latex_to_cmex .get (sym )
778
+ if uniindex is not None :
779
+ fontname = 'ex'
780
+ found_symbol = True
781
+
782
+ if not found_symbol :
780
783
try :
781
784
uniindex = get_unicode_index (sym )
782
785
found_symbol = True
783
786
except ValueError :
784
787
uniindex = ord ('?' )
785
788
warn ("No TeX to unicode mapping for '%s'" %
786
- sym .encode ('ascii' , 'replace ' ),
789
+ sym .encode ('ascii' , 'backslashreplace ' ),
787
790
MathTextWarning )
788
791
789
792
# Only characters in the "Letter" class should be italicized in 'it'
@@ -804,7 +807,7 @@ def _get_glyph(self, fontname, sym, fontsize):
804
807
except KeyError :
805
808
warn ("Font '%s' does not have a glyph for '%s'" %
806
809
(cached_font .font .postscript_name ,
807
- sym .encode ('ascii' , 'replace ' )),
810
+ sym .encode ('ascii' , 'backslashreplace ' )),
808
811
MathTextWarning )
809
812
found_symbol = False
810
813
@@ -815,6 +818,7 @@ def _get_glyph(self, fontname, sym, fontsize):
815
818
return self .cm_fallback ._get_glyph (fontname , sym , fontsize )
816
819
else :
817
820
warn ("Substituting with a dummy symbol." , MathTextWarning )
821
+ fontname = 'rm'
818
822
new_fontname = fontname
819
823
cached_font = self ._get_font (fontname )
820
824
uniindex = 0xA4 # currency character, for lack of anything better
@@ -829,6 +833,71 @@ def get_sized_alternatives_for_symbol(self, fontname, sym):
829
833
return self .cm_fallback .get_sized_alternatives_for_symbol (
830
834
fontname , sym )
831
835
return [(fontname , sym )]
836
+
837
+ class StixFonts (UnicodeFonts ):
838
+ _fontmap = { 'rm' : ('STIXGeneral' , 'otf' ),
839
+ 'tt' : ('VeraMono' , 'ttf' ),
840
+ 'it' : ('STIXGeneralItalic' , 'otf' ),
841
+ 'bf' : ('STIXGeneralBol' , 'otf' ),
842
+ 'sf' : ('Vera' , 'ttf' ),
843
+ 'nonunirm' : ('STIXNonUni' , 'otf' ),
844
+ 'nonuniit' : ('STIXNonUniIta' , 'otf' ),
845
+ 'nonunibf' : ('STIXNonUniBol' , 'otf' ),
846
+
847
+ 0 : ('STIXGeneral' , 'otf' ),
848
+ 1 : ('STIXSiz1Sym' , 'otf' ),
849
+ 2 : ('STIXSiz2Sym' , 'otf' ),
850
+ 3 : ('STIXSiz3Sym' , 'otf' ),
851
+ 4 : ('STIXSiz4Sym' , 'otf' ),
852
+ 5 : ('STIXSiz5Sym' , 'otf' )
853
+ }
854
+ fontmap = {}
855
+ use_cmex = False
856
+ cm_fallback = False
857
+
858
+ def __init__ (self , * args , ** kwargs ):
859
+ TruetypeFonts .__init__ (self , * args , ** kwargs )
860
+ if not len (self .fontmap ):
861
+ for key , (name , ext ) in self ._fontmap .iteritems ():
862
+ fullpath = os .path .join (self .basepath , ext , name + "." + ext )
863
+ self .fontmap [key ] = fullpath
864
+ self .fontmap [name ] = fullpath
865
+
866
+ def _get_glyph (self , fontname , sym , fontsize ):
867
+ # Handle calligraphic letters
868
+ if fontname == 'cal' :
869
+ if len (sym ) != 1 or ord (sym ) < ord ('A' ) or ord (sym ) > ord ('Z' ):
870
+ raise ValueError (r"Sym '%s' is not available in \mathcal font" % sym )
871
+ fontname = 'nonuniit'
872
+ sym = unichr (ord (sym ) + 0xe22d - ord ('A' ))
873
+
874
+ # Handle private use area glyphs
875
+ if (fontname in ('it' , 'rm' , 'bf' ) and
876
+ len (sym ) == 1 and ord (sym ) >= 0xe000 and ord (sym ) <= 0xf8ff ):
877
+ fontname = 'nonuni' + fontname
878
+
879
+ return UnicodeFonts ._get_glyph (self , fontname , sym , fontsize )
880
+
881
+ _size_alternatives = {}
882
+ def get_sized_alternatives_for_symbol (self , fontname , sym ):
883
+ alternatives = self ._size_alternatives .get (sym )
884
+ if alternatives :
885
+ return alternatives
886
+
887
+ alternatives = []
888
+ try :
889
+ uniindex = get_unicode_index (sym )
890
+ except ValueError :
891
+ return [(fontname , sym )]
892
+
893
+ for i in range (6 ):
894
+ cached_font = self ._get_font (i )
895
+ glyphindex = cached_font .charmap .get (uniindex )
896
+ if glyphindex is not None :
897
+ alternatives .append ((i , unichr (uniindex )))
898
+
899
+ self ._size_alternatives [sym ] = alternatives
900
+ return alternatives
832
901
833
902
class StandardPsFonts (Fonts ):
834
903
"""
@@ -1091,7 +1160,7 @@ def __init__(self, c, state):
1091
1160
Node .__init__ (self )
1092
1161
self .c = c
1093
1162
self .font_output = state .font_output
1094
- assert isinstance (state .font , str )
1163
+ assert isinstance (state .font , ( str , unicode , int ) )
1095
1164
self .font = state .font
1096
1165
self .fontsize = state .fontsize
1097
1166
self .dpi = state .dpi
@@ -1876,7 +1945,7 @@ def __init__(self):
1876
1945
) | Error (r"Expected \hspace{n}" ))
1877
1946
).setParseAction (self .customspace ).setName ('customspace' )
1878
1947
1879
- symbol = (Regex (r "([a-zA-Z0-9 +\-*/<>=:,.;!'@()])|(\\[%${}\[\]])" )
1948
+ symbol = (Regex (ur "([a-zA-Z0-9 +\-*/<>=:,.;!'@()\u0080-\uffff ])|(\\[%${}\[\]])" )
1880
1949
| Combine (
1881
1950
bslash
1882
1951
+ oneOf (tex2uni .keys ())
@@ -2508,10 +2577,15 @@ def parse(self, s, dpi = 72, prop = None):
2508
2577
font_output = StandardPsFonts (prop )
2509
2578
else :
2510
2579
backend = self ._backend_mapping [self ._output ]()
2511
- if rcParams ['mathtext.use_cm' ]:
2580
+ fontset = rcParams ['mathtext.fontset' ]
2581
+ if fontset == 'cm' :
2512
2582
font_output = BakomaFonts (prop , backend )
2513
- else :
2583
+ elif fontset == 'stix' :
2584
+ font_output = StixFonts (prop , backend )
2585
+ elif fontset == 'custom' :
2514
2586
font_output = UnicodeFonts (prop , backend )
2587
+ else :
2588
+ raise ValueError ("mathtext.fontset must be either 'cm', 'stix', or 'custom'" )
2515
2589
2516
2590
fontsize = prop .get_size_in_points ()
2517
2591
0 commit comments