Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c56e56e

Browse files
committed
improve integral and slanted nuclei placement
clean up, remove unnecesary do_kern=False fix overunder make cm clearer at small sizes
1 parent 4d7d377 commit c56e56e

File tree

2 files changed

+74
-61
lines changed

2 files changed

+74
-61
lines changed

lib/matplotlib/mathtext.py

Lines changed: 71 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,49 +1187,49 @@ def get_underline_thickness(self, font, fontsize, dpi):
11871187
# get any smaller
11881188
NUM_SIZE_LEVELS = 6
11891189
# Percentage of x-height of additional horiz. space after sub/superscripts
1190-
SCRIPT_SPACE = {'cm': 0.025,
1191-
'stix': 0.20,
1192-
'stixsans': 0.10,
1193-
'arevsans': 0.10}
1190+
SCRIPT_SPACE = {'cm': 0.075,
1191+
'stix': 0.10,
1192+
'stixsans': 0.05,
1193+
'arevsans': 0.05}
11941194
## Percentage of x-height that sub/superscripts drop below the baseline
1195-
SUBDROP = {'cm': 0.3,
1195+
SUBDROP = {'cm': 0.2,
11961196
'stix': 0.4,
11971197
'stixsans': 0.4,
1198-
'arevsans': 0.3}
1198+
'arevsans': 0.4}
11991199
# Percentage of x-height that superscripts are raised from the baseline
12001200
SUP1 = {'cm': 0.45,
12011201
'stix': 0.8,
12021202
'stixsans': 0.8,
12031203
'arevsans': 0.7}
12041204
# Percentage of x-height that subscripts drop below the baseline
1205-
SUB1 = {'cm': 0.4,
1206-
'stix': 0.6,
1207-
'stixsans': 0.6,
1208-
'arevsans': 0.6}
1205+
SUB1 = {'cm': 0.2,
1206+
'stix': 0.3,
1207+
'stixsans': 0.3,
1208+
'arevsans': 0.3}
12091209
# Percentage of x-height that subscripts drop below the baseline when a
12101210
# superscript is present
12111211
SUB2 = {'cm': 0.3,
12121212
'stix': 0.6,
12131213
'stixsans': 0.5,
1214-
'arevsans': 0.8}
1214+
'arevsans': 0.5}
12151215
# Percentage of x-height that sub/supercripts are offset relative to the
1216-
# nucleus end
1217-
DELTA = {'cm': 0.10,
1218-
'stix': 0.10,
1219-
'stixsans': 0.25,
1220-
'arevsans': 0.12}
1221-
# Additional percentage of last character height that supercripts are offset
1222-
# relative to the subscript for slanted nuclei
1223-
DELTASLANTED = {'cm': 0.05,
1216+
# nucleus edge for non-slanted nuclei
1217+
DELTA = {'cm': 0.075,
12241218
'stix': 0.05,
1225-
'stixsans': 0.05,
1226-
'arevsans': 0.12}
1227-
# Percentage of x-height that supercripts are offset relative to the subscript
1228-
# for integrals
1229-
DELTAINTEGRAL = {'cm': 0.5,
1230-
'stix': 0.5,
1231-
'stixsans': 0.4,
1232-
'arevsans': 0.5}
1219+
'stixsans': 0.025,
1220+
'arevsans': 0.025}
1221+
# Additional percentage of last character height above 2/3 of the x-height that
1222+
# supercripts are offset relative to the subscript for slanted nuclei
1223+
DELTASLANTED = {'cm': 0.3,
1224+
'stix': 0.3,
1225+
'stixsans': 0.6,
1226+
'arevsans': 0.2}
1227+
# Percentage of x-height that supercripts and subscripts are offset for
1228+
# integrals
1229+
DELTAINTEGRAL = {'cm': 0.3,
1230+
'stix': 0.3,
1231+
'stixsans': 0.3,
1232+
'arevsans': 0.3}
12331233

12341234
class MathTextWarning(Warning):
12351235
pass
@@ -2718,35 +2718,12 @@ def subsuper(self, s, loc, toks):
27182718
"Subscript/superscript sequence is too long. "
27192719
"Use braces { } to remove ambiguity.")
27202720

2721-
last_char = nucleus
2722-
if isinstance(nucleus,Hlist):
2723-
# remove kerns
2724-
new_children = []
2725-
for child in nucleus.children:
2726-
if not isinstance(child, Kern):
2727-
new_children.append(child)
2728-
nucleus = Hlist(new_children, do_kern=False)
2729-
if len(new_children):
2730-
last_char = new_children[-1]
2731-
else:
2732-
nucleus = Hlist([nucleus],do_kern=False)
2733-
27342721
state = self.get_state()
27352722
rule_thickness = state.font_output.get_underline_thickness(
27362723
state.font, state.fontsize, state.dpi)
27372724
xHeight = state.font_output.get_xheight(
27382725
state.font, state.fontsize, state.dpi)
27392726

2740-
fs = rcParams['mathtext.fontset']
2741-
# If a custom fontset is used, check if it is Arev Sans, otherwise use
2742-
# CM parameters.
2743-
if fs == 'custom':
2744-
if (rcParams['mathtext.rm'] == 'sans' and
2745-
rcParams['font.sans-serif'][0].lower() == 'Arev Sans'.lower()):
2746-
fs = 'arevsans'
2747-
else:
2748-
fs = 'cm'
2749-
27502727
if napostrophes:
27512728
if super is None:
27522729
super = Hlist([])
@@ -2782,6 +2759,38 @@ def subsuper(self, s, loc, toks):
27822759
result = Hlist([vlist])
27832760
return [result]
27842761

2762+
# We remove kerning for consistency (otherwise it will compute kerning
2763+
# based on non-shrinked characters and may put them very close together
2764+
# when superscripted)
2765+
# We change the width of the last character to match the advance to
2766+
# consider some fonts with weird metrics: e.g. stix's f has a width of
2767+
# 7.75 and a kerning of -4.0 for an advance of 3.72, and we want to put
2768+
# the superscript at the advance
2769+
last_char = nucleus
2770+
if isinstance(nucleus,Hlist):
2771+
new_children = nucleus.children
2772+
if len(new_children):
2773+
# remove last kern
2774+
if isinstance(new_children[-1],Kern):
2775+
new_children = new_children[:-1]
2776+
last_char = new_children[-1]
2777+
last_char.width = last_char._metrics.advance
2778+
# create new Hlist without kerning
2779+
nucleus = Hlist(new_children, do_kern=False)
2780+
else:
2781+
last_char.width = last_char._metrics.advance
2782+
nucleus = Hlist([nucleus])
2783+
2784+
fs = rcParams['mathtext.fontset']
2785+
# If a custom fontset is used, check if it is Arev Sans, otherwise use
2786+
# CM parameters.
2787+
if fs == 'custom':
2788+
if (rcParams['mathtext.rm'] == 'sans' and
2789+
rcParams['font.sans-serif'][0].lower() == 'Arev Sans'.lower()):
2790+
fs = 'arevsans'
2791+
else:
2792+
fs = 'cm'
2793+
27852794
# Handle regular sub/superscripts
27862795
lc_height = last_char.height
27872796
lc_baseline = 0
@@ -2792,20 +2801,22 @@ def subsuper(self, s, loc, toks):
27922801
superkern = DELTA[fs] * xHeight
27932802
subkern = DELTA[fs] * xHeight
27942803
if self.is_slanted(last_char):
2795-
superkern += DELTASLANTED[fs] * xHeight
2804+
superkern += DELTA[fs] * xHeight
2805+
superkern += DELTASLANTED[fs] * (lc_height - xHeight * 2. / 3.)
27962806
if self.is_dropsub(last_char):
2797-
subkern = -DELTAINTEGRAL[fs] * lc_height
2807+
subkern = (3 * DELTA[fs] - DELTAINTEGRAL[fs]) * lc_height
2808+
superkern = (3 * DELTA[fs] + DELTAINTEGRAL[fs]) * lc_height
27982809
else:
2799-
subkern = 0.25 * DELTA[fs] * lc_height
2810+
subkern = 0
28002811

28012812
if super is None:
28022813
# node757
28032814
x = Hlist([Kern(subkern), sub])
28042815
x.shrink()
2805-
shift_down = max(lc_baseline + SUBDROP[fs] * xHeight,
2806-
SUB1[fs] * xHeight)
2807-
if not self.is_dropsub(last_char):
2808-
shift_down /= 2
2816+
if self.is_dropsub(last_char):
2817+
shift_down = lc_baseline + SUBDROP[fs] * xHeight
2818+
else:
2819+
shift_down = SUB1[fs] * xHeight
28092820
x.shift_amount = shift_down
28102821
else:
28112822
x = Hlist([Kern(superkern), super])
@@ -2833,8 +2844,9 @@ def subsuper(self, s, loc, toks):
28332844
y])
28342845
x.shift_amount = shift_down
28352846

2836-
x.width += SCRIPT_SPACE[fs] * xHeight
2837-
result = Hlist([nucleus, x], do_kern=False)
2847+
if not self.is_dropsub(last_char):
2848+
x.width += SCRIPT_SPACE[fs] * xHeight
2849+
result = Hlist([nucleus, x])
28382850
return [result]
28392851

28402852
def _genfrac(self, ldelim, rdelim, rule, style, num, den):

lib/matplotlib/tests/test_mathtext.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,10 @@
9898
r'$M \, M \thinspace M \/ M \> M \: M \; M \ M \enspace M \quad M \qquad M \! M$',
9999
r'$\Cup$ $\Cap$ $\leftharpoonup$ $\barwedge$ $\rightharpoonup$',
100100
r'$\dotplus$ $\doteq$ $\doteqdot$ $\ddots$',
101-
r'$x_kx^py^{p-2} d_i^jb_jc_kd x^j_i E^0 E^0_u$', # github issue #4873
102-
r'${x}_{k}{x}^{p}{y}^{p-2} {d}_{i}^{j}{b}_{j}{c}_{k}{d} {x}^{j}_{i}{E}^{0}{E}^0_u$',
101+
r'$xyz^kx_kx^py^{p-2} d_i^jb_jc_kd x^j_i E^0 E^0_u$', # github issue #4873
102+
r'${xyz}^k{x}_{k}{x}^{p}{y}^{p-2} {d}_{i}^{j}{b}_{j}{c}_{k}{d} {x}^{j}_{i}{E}^{0}{E}^0_u$',
103103
r'${\int}_x^x x\oint_x^x x\int_{X}^{X}x\int_x x \int^x x \int_{x} x\int^{x}{\int}_{x} x{\int}^{x}_{x}x$',
104+
r'$f^\prime f^2 f^a F^2',
104105

105106
]
106107

0 commit comments

Comments
 (0)