Fix monospace font calculations on macOS
* src/macfont.m (macfont_monospace_width_multiplier): New function to compute the width for monospace fonts (bug#24582). (macfont_glyph_extents): Fix monospace glyph computation. (macfont_shape): Ditto.
This commit is contained in:
parent
88567ca8ec
commit
fdba95d2f8
1 changed files with 77 additions and 11 deletions
|
@ -1120,7 +1120,10 @@ sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
|
|||
glyph width. The `width_int' member is an integer that is
|
||||
closest to the width. The `width_frac' member is the fractional
|
||||
adjustment representing a value in [-.5, .5], multiplied by
|
||||
WIDTH_FRAC_SCALE. For synthetic monospace fonts, they represent
|
||||
WIDTH_FRAC_SCALE. For monospace fonts, non-zero `width_frac'
|
||||
means `width_int' is further adjusted to a multiple of the
|
||||
(rounded) font width, and `width_frac' represents adjustment per
|
||||
unit character. For synthetic monospace fonts, they represent
|
||||
the advance delta for centering instead of the glyph width. */
|
||||
signed width_frac : WIDTH_FRAC_BITS, width_int : 16 - WIDTH_FRAC_BITS;
|
||||
};
|
||||
|
@ -1148,6 +1151,27 @@ sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
|
|||
#define LCD_FONT_SMOOTHING_LEFT_MARGIN (0.396f)
|
||||
#define LCD_FONT_SMOOTHING_RIGHT_MARGIN (0.396f)
|
||||
|
||||
/* If FONT is monospace and WIDTH can be regarded as a multiple of its
|
||||
width where the multiplier is greater than 1, then return the
|
||||
multiplier. Otherwise return 0. */
|
||||
static int
|
||||
macfont_monospace_width_multiplier (struct font *font, CGFloat width)
|
||||
{
|
||||
struct macfont_info *macfont_info = (struct macfont_info *) font;
|
||||
int multiplier = 0;
|
||||
|
||||
if (macfont_info->spacing == MACFONT_SPACING_MONO
|
||||
&& font->space_width != 0)
|
||||
{
|
||||
multiplier = lround (width / font->space_width);
|
||||
if (multiplier == 1
|
||||
|| lround (width / multiplier) != font->space_width)
|
||||
multiplier = 0;
|
||||
}
|
||||
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
static int
|
||||
macfont_glyph_extents (struct font *font, CGGlyph glyph,
|
||||
struct font_metrics *metrics, CGFloat *advance_delta,
|
||||
|
@ -1192,13 +1216,38 @@ sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
|
|||
else
|
||||
fwidth = mac_font_get_advance_width_for_glyph (macfont, glyph);
|
||||
|
||||
/* For synthetic mono fonts, cache->width_{int,frac} holds the
|
||||
advance delta value. */
|
||||
if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
|
||||
fwidth = (font->pixel_size - fwidth) / 2;
|
||||
cache->width_int = lround (fwidth);
|
||||
cache->width_frac = lround ((fwidth - cache->width_int)
|
||||
* WIDTH_FRAC_SCALE);
|
||||
if (macfont_info->spacing == MACFONT_SPACING_MONO)
|
||||
{
|
||||
/* Some monospace fonts for programming languages contain
|
||||
wider ligature glyphs consisting of multiple characters.
|
||||
For such glyphs, simply rounding the combined fractional
|
||||
width to an integer can result in a value that is not a
|
||||
multiple of the (rounded) font width. */
|
||||
int multiplier = macfont_monospace_width_multiplier (font, fwidth);
|
||||
|
||||
if (multiplier)
|
||||
{
|
||||
cache->width_int = font->space_width * multiplier;
|
||||
cache->width_frac = lround ((fwidth / multiplier
|
||||
- font->space_width)
|
||||
* WIDTH_FRAC_SCALE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cache->width_int = lround (fwidth);
|
||||
cache->width_frac = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For synthetic mono fonts, cache->width_{int,frac} holds
|
||||
the advance delta value. */
|
||||
if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
|
||||
fwidth = (font->pixel_size - fwidth) / 2;
|
||||
cache->width_int = lround (fwidth);
|
||||
cache->width_frac = lround ((fwidth - cache->width_int)
|
||||
* WIDTH_FRAC_SCALE);
|
||||
}
|
||||
METRICS_SET_STATUS (cache, METRICS_WIDTH_VALID);
|
||||
}
|
||||
if (macfont_info->spacing == MACFONT_SPACING_SYNTHETIC_MONO)
|
||||
|
@ -1235,6 +1284,10 @@ sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
|
|||
/ (CGFloat) (WIDTH_FRAC_SCALE * 2));
|
||||
break;
|
||||
case MACFONT_SPACING_MONO:
|
||||
if (cache->width_frac)
|
||||
bounds.origin.x += - ((cache->width_frac
|
||||
/ (CGFloat) (WIDTH_FRAC_SCALE * 2))
|
||||
* (cache->width_int / font->space_width));
|
||||
break;
|
||||
case MACFONT_SPACING_SYNTHETIC_MONO:
|
||||
bounds.origin.x += (cache->width_int
|
||||
|
@ -1271,7 +1324,16 @@ sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
|
|||
/ (CGFloat) (WIDTH_FRAC_SCALE * 2)));
|
||||
break;
|
||||
case MACFONT_SPACING_MONO:
|
||||
*advance_delta = 0;
|
||||
if (cache->width_frac)
|
||||
*advance_delta = 0;
|
||||
else
|
||||
{
|
||||
CGFloat delta = - ((cache->width_frac
|
||||
/ (CGFloat) (WIDTH_FRAC_SCALE * 2))
|
||||
* (cache->width_int / font->space_width));
|
||||
|
||||
*advance_delta = (force_integral_p ? round (delta) : delta);
|
||||
}
|
||||
break;
|
||||
case MACFONT_SPACING_SYNTHETIC_MONO:
|
||||
*advance_delta = (force_integral_p ? cache->width_int
|
||||
|
@ -3015,7 +3077,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no
|
|||
struct mac_glyph_layout *gl = glyph_layouts + i;
|
||||
EMACS_INT from, to;
|
||||
struct font_metrics metrics;
|
||||
int xoff, yoff, wadjust;
|
||||
int xoff, yoff, wadjust, multiplier;
|
||||
|
||||
if (NILP (lglyph))
|
||||
{
|
||||
|
@ -3068,7 +3130,11 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no
|
|||
|
||||
xoff = lround (gl->advance_delta);
|
||||
yoff = lround (- gl->baseline_delta);
|
||||
wadjust = lround (gl->advance);
|
||||
multiplier = macfont_monospace_width_multiplier (font, gl->advance);
|
||||
if (multiplier)
|
||||
wadjust = font->space_width * multiplier;
|
||||
else
|
||||
wadjust = lround (gl->advance);
|
||||
if (xoff != 0 || yoff != 0 || wadjust != metrics.width)
|
||||
{
|
||||
Lisp_Object vec = make_uninit_vector (3);
|
||||
|
|
Loading…
Add table
Reference in a new issue