Skip to content

Commit 2f9b563

Browse files
committed
fix - Some glyph are not visually centered when patching monospaced variation
See issue #1997 for detail. Some glyph in font `Noto`, has some double width glyph with the bounding box width around single width. This commit fixes that by re-centering glyph that could be visually centered while creating monospaced variation. Some debug code is preserved, and would be deleted once the PR is ready to be merged.
1 parent 1514941 commit 2f9b563

1 file changed

Lines changed: 48 additions & 1 deletion

File tree

font-patcher

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1784,7 +1784,12 @@ class font_patcher:
17841784
# If width is not zero, correct the bearings such that they are within the width:
17851785
self.remove_glyph_neg_bearings(glyph)
17861786

1787+
# TODO: Debug code, will/should be removed after this PR is checked.
1788+
# if glyph.unicode == 0x25C6:
1789+
# self.debug_glyph_metrics(glyph, "before set_glyph_width_mono")
17871790
self.set_glyph_width_mono(glyph)
1791+
# if glyph.unicode == 0x25C6:
1792+
# self.debug_glyph_metrics(glyph, "after set_glyph_width_mono")
17881793

17891794

17901795
def remove_glyph_neg_bearings(self, glyph):
@@ -1802,13 +1807,39 @@ class font_patcher:
18021807
""" Sets passed glyph.width to self.font_dim.width.
18031808
18041809
self.font_dim.width is set with self.get_sourcefont_dimensions().
1810+
1811+
If negative right side bearing appears, see if the glyph is
1812+
ought to be centered when changing to monospaced.
18051813
"""
18061814
try:
18071815
# Fontforge handles the width change like this:
18081816
# - Keep existing left_side_bearing
18091817
# - Set width
18101818
# - Calculate and set new right_side_bearing
1811-
glyph.width = self.font_dim['width']
1819+
expected_mono_width = self.font_dim['width']
1820+
glyph.width = expected_mono_width
1821+
1822+
# Visually center some double width glyph that having a bbox width approx. equal to single width.
1823+
if glyph.right_side_bearing < 0:
1824+
# TODO: Should be set as a parameter, since regular/thin/bold have different bbox width.
1825+
glyph_centering_threshold = 20
1826+
xmin, ymin, xmax, ymax = glyph.boundingBox()
1827+
glyph_width = xmax - xmin
1828+
1829+
# Do not handle those character that cannot be squished into mono width.
1830+
if glyph_width > expected_mono_width + glyph_centering_threshold:
1831+
return
1832+
1833+
# Calculate the value for centering visually.
1834+
glyph_center = (xmin + xmax) / 2.0
1835+
target_center = expected_mono_width / 2.0
1836+
x_shift = target_center - glyph_center
1837+
1838+
if x_shift != 0:
1839+
glyph.transform(psMat.translate(x_shift, 0))
1840+
1841+
# Restores the width.
1842+
glyph.width = expected_mono_width
18121843
except:
18131844
pass
18141845

@@ -1906,6 +1937,22 @@ class font_patcher:
19061937
ymin = self.font_dim["ymin"]
19071938
return get_braille_font(self.sourceFont.em, width, ymax, ymin, self.args.braille, 0.6)
19081939

1940+
def debug_glyph_metrics(self, glyph, label):
1941+
# TODO: Debug code, will/should be removed after this PR is checked.
1942+
try:
1943+
xmin, ymin, xmax, ymax = glyph.boundingBox()
1944+
print(
1945+
f"[DEBUG] {label} "
1946+
f"name={glyph.glyphname} unicode=U+{glyph.unicode:04X} "
1947+
f"width={glyph.width} "
1948+
f"lsb={glyph.left_side_bearing} "
1949+
f"rsb={glyph.right_side_bearing} "
1950+
f"bbox=({xmin},{ymin},{xmax},{ymax}) "
1951+
f"bbox_w={xmax - xmin}"
1952+
)
1953+
except Exception as e:
1954+
print(f"[DEBUG] {label} failed: {e}")
1955+
19091956
def half_gap(gap, top):
19101957
""" Divides integer value into two new integers """
19111958
# Line gap add extra space on the bottom of the line which

0 commit comments

Comments
 (0)