@@ -220,7 +220,7 @@ def _get_info(self, fontname, font_class, sym, fontsize, dpi):
220
220
if bunch is not None :
221
221
return bunch
222
222
223
- font , num , slanted = self ._get_glyph (
223
+ font , num , slanted , substituted_glyph = self ._get_glyph (
224
224
fontname , font_class , sym , fontsize )
225
225
226
226
font .set_size (fontsize , dpi )
@@ -239,7 +239,8 @@ def _get_info(self, fontname, font_class, sym, fontsize, dpi):
239
239
ymax = ymax + offset ,
240
240
# iceberg is the equivalent of TeX's "height"
241
241
iceberg = glyph .horiBearingY / 64.0 + offset ,
242
- slanted = slanted
242
+ slanted = slanted ,
243
+ substituted_glyph = substituted_glyph
243
244
)
244
245
245
246
result = self .glyphd [key ] = types .SimpleNamespace (
@@ -323,7 +324,7 @@ def _get_glyph(self, fontname, font_class, sym, fontsize):
323
324
if font is not None :
324
325
num = ord (sym )
325
326
if font is not None and font .get_char_index (num ) != 0 :
326
- return font , num , slanted
327
+ return font , num , slanted , False
327
328
else :
328
329
return self ._stix_fallback ._get_glyph (
329
330
fontname , font_class , sym , fontsize )
@@ -448,6 +449,8 @@ def _get_glyph(self, fontname, font_class, sym, fontsize):
448
449
found_symbol = False
449
450
_log .warning ("No TeX to Unicode mapping for {!a}." .format (sym ))
450
451
452
+ substituted_glyph = False
453
+
451
454
fontname , uniindex = self ._map_virtual_font (
452
455
fontname , font_class , uniindex )
453
456
@@ -499,8 +502,9 @@ def _get_glyph(self, fontname, font_class, sym, fontsize):
499
502
font = self ._get_font ('rm' )
500
503
uniindex = 0xA4 # currency char, for lack of anything better
501
504
slanted = False
505
+ substituted_glyph = True
502
506
503
- return font , uniindex , slanted
507
+ return font , uniindex , slanted , substituted_glyph
504
508
505
509
def get_sized_alternatives_for_symbol (self , fontname , sym ):
506
510
if self ._fallback_font :
@@ -935,6 +939,9 @@ def _update_metrics(self):
935
939
def is_slanted (self ):
936
940
return self ._metrics .slanted
937
941
942
+ def is_substituted (self ):
943
+ return self ._metrics .substituted_glyph
944
+
938
945
def get_kerning (self , next ):
939
946
"""
940
947
Return the amount of kerning between this and the given character.
@@ -2011,7 +2018,7 @@ def unknown_symbol(self, s, loc, toks):
2011
2018
raise ParseFatalException (s , loc , f"Unknown symbol: { toks ['name' ]} " )
2012
2019
2013
2020
_accent_map = {
2014
- r'hat' : r'\circumflexaccent ' ,
2021
+ r'hat' : r'\combiningcircumflexaccent ' ,
2015
2022
r'breve' : r'\combiningbreve' ,
2016
2023
r'bar' : r'\combiningoverline' ,
2017
2024
r'grave' : r'\combininggraveaccent' ,
@@ -2027,10 +2034,13 @@ def unknown_symbol(self, s, loc, toks):
2027
2034
r"'" : r'\combiningacuteaccent' ,
2028
2035
r'~' : r'\combiningtilde' ,
2029
2036
r'.' : r'\combiningdotabove' ,
2030
- r'^' : r'\circumflexaccent' ,
2031
- r'overrightarrow' : r'\rightarrow' ,
2032
- r'overleftarrow' : r'\leftarrow' ,
2033
- r'mathring' : r'\circ' ,
2037
+ r'^' : r'\combiningcircumflexaccent' ,
2038
+ r'overrightarrow' : r'\combiningrightarrowabove' ,
2039
+ r'overleftarrow' : r'\combiningleftarrowabove' ,
2040
+ r'mathring' : r'\combiningringabove' ,
2041
+ r'=' : r'\combiningmacron' ,
2042
+ r'H' : r'\combiningdoubleacuteaccent' ,
2043
+ r'check' : r'\combiningcaron' ,
2034
2044
}
2035
2045
2036
2046
_wide_accents = set (r"widehat widetilde widebar" .split ())
@@ -2050,10 +2060,27 @@ def accent(self, s, loc, toks):
2050
2060
accent_box = AutoWidthChar (
2051
2061
'\\ ' + accent , sym .width , state , char_class = Accent )
2052
2062
else :
2063
+ # Check if accent and character can be combined
2064
+ a = get_unicode_index (self ._accent_map [accent ])
2065
+ if isinstance (sym , Char ):
2066
+ c = sym .c
2067
+ else :
2068
+ c = sym .children [0 ].c
2069
+ if c == chr (305 ): # Dotless i, but normal i combines
2070
+ c = 'i'
2071
+ comb = unicodedata .normalize ('NFC' , c + chr (a ))
2072
+ if len (comb ) == 1 : # Check that they did combine
2073
+ newsym = Char (comb , state )
2074
+ # Check that glyph exists
2075
+ if not newsym .is_substituted ():
2076
+ return newsym
2077
+ if c == 'i' : # Turn i into dotless i
2078
+ sym = Char (chr (305 ), state )
2079
+ if sym .is_substituted ():
2080
+ # Dotless i does not exist
2081
+ sym = Char ('i' , state )
2082
+ # Cannot be combined
2053
2083
accent_box = Accent (self ._accent_map [accent ], state )
2054
- if accent == 'mathring' :
2055
- accent_box .shrink ()
2056
- accent_box .shrink ()
2057
2084
centered = HCentered ([Hbox (sym .width / 4.0 ), accent_box ])
2058
2085
centered .hpack (sym .width , 'exactly' )
2059
2086
return Vlist ([
@@ -2137,9 +2164,6 @@ def is_slanted(self, nucleus):
2137
2164
return nucleus .is_slanted ()
2138
2165
return False
2139
2166
2140
- def is_between_brackets (self , s , loc ):
2141
- return False
2142
-
2143
2167
def subsuper (self , s , loc , toks ):
2144
2168
nucleus = toks .get ("nucleus" , Hbox (0 ))
2145
2169
subsuper = toks .get ("subsuper" , [])
0 commit comments