@@ -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+
19091956def 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