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

Skip to content

Commit 6e4e3a2

Browse files
committed
Merge pull request #4873 from zblz/subsuper-finetune
mathtext: Finetuning sup/super block to match TeX reference
2 parents 3bc5e80 + f1fe6e5 commit 6e4e3a2

File tree

380 files changed

+30241
-26172
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

380 files changed

+30241
-26172
lines changed

lib/matplotlib/mathtext.py

Lines changed: 119 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,15 +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 = 0.2
1191-
# Percentage of x-height that sub/superscripts drop below the baseline
1192-
SUBDROP = 0.3
1193-
# Percentage of x-height that superscripts drop below the baseline
1194-
SUP1 = 0.5
1190+
SCRIPT_SPACE = {'cm': 0.075,
1191+
'stix': 0.10,
1192+
'stixsans': 0.05,
1193+
'arevsans': 0.05}
1194+
## Percentage of x-height that sub/superscripts drop below the baseline
1195+
SUBDROP = {'cm': 0.2,
1196+
'stix': 0.4,
1197+
'stixsans': 0.4,
1198+
'arevsans': 0.4}
1199+
# Percentage of x-height that superscripts are raised from the baseline
1200+
SUP1 = {'cm': 0.45,
1201+
'stix': 0.8,
1202+
'stixsans': 0.8,
1203+
'arevsans': 0.7}
11951204
# Percentage of x-height that subscripts drop below the baseline
1196-
SUB1 = 0.0
1197-
# Percentage of x-height that superscripts are offset relative to the subscript
1198-
DELTA = 0.18
1205+
SUB1 = {'cm': 0.2,
1206+
'stix': 0.3,
1207+
'stixsans': 0.3,
1208+
'arevsans': 0.3}
1209+
# Percentage of x-height that subscripts drop below the baseline when a
1210+
# superscript is present
1211+
SUB2 = {'cm': 0.3,
1212+
'stix': 0.6,
1213+
'stixsans': 0.5,
1214+
'arevsans': 0.5}
1215+
# Percentage of x-height that sub/supercripts are offset relative to the
1216+
# nucleus edge for non-slanted nuclei
1217+
DELTA = {'cm': 0.075,
1218+
'stix': 0.05,
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}
11991233

12001234
class MathTextWarning(Warning):
12011235
pass
@@ -2628,9 +2662,21 @@ def is_slanted(self, nucleus):
26282662
return nucleus.is_slanted()
26292663
return False
26302664

2665+
def _get_fontset_name(self):
2666+
fs = rcParams['mathtext.fontset']
2667+
# If a custom fontset is used, check if it is Arev Sans, otherwise use
2668+
# CM parameters.
2669+
if fs == 'custom':
2670+
if (rcParams['mathtext.rm'] == 'sans' and
2671+
rcParams['font.sans-serif'][0].lower() == 'Arev Sans'.lower()):
2672+
fs = 'arevsans'
2673+
else:
2674+
fs = 'cm'
2675+
2676+
return fs
2677+
26312678
def subsuper(self, s, loc, toks):
26322679
assert(len(toks)==1)
2633-
# print 'subsuper', toks
26342680

26352681
nucleus = None
26362682
sub = None
@@ -2726,48 +2772,87 @@ def subsuper(self, s, loc, toks):
27262772
result = Hlist([vlist])
27272773
return [result]
27282774

2729-
# Handle regular sub/superscripts
2730-
shift_up = nucleus.height - SUBDROP * xHeight
2731-
if self.is_dropsub(nucleus):
2732-
shift_down = nucleus.depth + SUBDROP * xHeight
2775+
# We remove kerning on the last character for consistency (otherwise it
2776+
# will compute kerning based on non-shrinked characters and may put them
2777+
# too close together when superscripted)
2778+
# We change the width of the last character to match the advance to
2779+
# consider some fonts with weird metrics: e.g. stix's f has a width of
2780+
# 7.75 and a kerning of -4.0 for an advance of 3.72, and we want to put
2781+
# the superscript at the advance
2782+
last_char = nucleus
2783+
if isinstance(nucleus, Hlist):
2784+
new_children = nucleus.children
2785+
if len(new_children):
2786+
# remove last kern
2787+
if isinstance(new_children[-1],Kern):
2788+
new_children = new_children[:-1]
2789+
last_char = new_children[-1]
2790+
last_char.width = last_char._metrics.advance
2791+
# create new Hlist without kerning
2792+
nucleus = Hlist(new_children, do_kern=False)
27332793
else:
2734-
shift_down = SUBDROP * xHeight
2794+
if isinstance(nucleus, Char):
2795+
last_char.width = last_char._metrics.advance
2796+
nucleus = Hlist([nucleus])
2797+
2798+
# Handle regular sub/superscripts
2799+
2800+
fs = self._get_fontset_name()
2801+
2802+
lc_height = last_char.height
2803+
lc_baseline = 0
2804+
if self.is_dropsub(last_char):
2805+
lc_baseline = last_char.depth
2806+
2807+
# Compute kerning for sub and super
2808+
superkern = DELTA[fs] * xHeight
2809+
subkern = DELTA[fs] * xHeight
2810+
if self.is_slanted(last_char):
2811+
superkern += DELTA[fs] * xHeight
2812+
superkern += DELTASLANTED[fs] * (lc_height - xHeight * 2. / 3.)
2813+
if self.is_dropsub(last_char):
2814+
subkern = (3 * DELTA[fs] - DELTAINTEGRAL[fs]) * lc_height
2815+
superkern = (3 * DELTA[fs] + DELTAINTEGRAL[fs]) * lc_height
2816+
else:
2817+
subkern = 0
2818+
27352819
if super is None:
27362820
# node757
2737-
sub.shrink()
2738-
x = Hlist([sub])
2739-
# x.width += SCRIPT_SPACE * xHeight
2740-
shift_down = max(shift_down, SUB1)
2741-
clr = x.height - (abs(xHeight * 4.0) / 5.0)
2742-
shift_down = max(shift_down, clr)
2821+
x = Hlist([Kern(subkern), sub])
2822+
x.shrink()
2823+
if self.is_dropsub(last_char):
2824+
shift_down = lc_baseline + SUBDROP[fs] * xHeight
2825+
else:
2826+
shift_down = SUB1[fs] * xHeight
27432827
x.shift_amount = shift_down
27442828
else:
2745-
super.shrink()
2746-
x = Hlist([super])
2747-
# x.width += SCRIPT_SPACE * xHeight
2748-
clr = SUP1 * xHeight
2749-
shift_up = max(shift_up, clr)
2750-
clr = x.depth + (abs(xHeight) / 4.0)
2751-
shift_up = max(shift_up, clr)
2829+
x = Hlist([Kern(superkern), super])
2830+
x.shrink()
2831+
if self.is_dropsub(last_char):
2832+
shift_up = lc_height - SUBDROP[fs] * xHeight
2833+
else:
2834+
shift_up = SUP1[fs] * xHeight
27522835
if sub is None:
27532836
x.shift_amount = -shift_up
27542837
else: # Both sub and superscript
2755-
sub.shrink()
2756-
y = Hlist([sub])
2757-
# y.width += SCRIPT_SPACE * xHeight
2758-
shift_down = max(shift_down, SUB1 * xHeight)
2838+
y = Hlist([Kern(subkern),sub])
2839+
y.shrink()
2840+
if self.is_dropsub(last_char):
2841+
shift_down = lc_baseline + SUBDROP[fs] * xHeight
2842+
else:
2843+
shift_down = SUB2[fs] * xHeight
2844+
# If sub and superscript collide, move super up
27592845
clr = (2.0 * rule_thickness -
27602846
((shift_up - x.depth) - (y.height - shift_down)))
27612847
if clr > 0.:
27622848
shift_up += clr
2763-
shift_down += clr
2764-
if self.is_slanted(nucleus):
2765-
x.shift_amount = DELTA * (shift_up + shift_down)
27662849
x = Vlist([x,
27672850
Kern((shift_up - x.depth) - (y.height - shift_down)),
27682851
y])
27692852
x.shift_amount = shift_down
27702853

2854+
if not self.is_dropsub(last_char):
2855+
x.width += SCRIPT_SPACE[fs] * xHeight
27712856
result = Hlist([nucleus, x])
27722857
return [result]
27732858

Binary file not shown.
Loading

0 commit comments

Comments
 (0)