Linux: Automatically increase cell height if the font being used is broken and draws the underscore outside the bounding box

See #690
This commit is contained in:
Kovid Goyal 2019-05-29 16:04:50 +05:30
parent 4e9dabfb25
commit 1ae32b5742
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 53 additions and 24 deletions

View File

@ -29,6 +29,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- When resizing and only a single window is present in the current layout,
use that window's background color to fill in the blank areas.
- Linux: Automatically increase cell height if the font being used is broken
and draws the underscore outside the bounding box (:iss:`690`)
0.14.0 [2019-05-24]
---------------------

View File

@ -280,7 +280,9 @@ cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, u
*baseline = (unsigned int)self->ascent;
// float line_height = MAX(1, floor(self->ascent + self->descent + MAX(0, self->leading) + 0.5));
// Let CoreText's layout engine calculate the line height. Slower, but hopefully more accurate.
CFStringRef ts = CFSTR("test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test test");
#define W "AQWMH_gyl "
CFStringRef ts = CFSTR(W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W);
#undef W
CFMutableAttributedStringRef test_string = CFAttributedStringCreateMutable(kCFAllocatorDefault, CFStringGetLength(ts));
CFAttributedStringReplaceString(test_string, CFRangeMake(0, 0), ts);
CFAttributedStringSetAttribute(test_string, CFRangeMake(0, CFStringGetLength(ts)), kCTFontAttributeName, self->ct_font);

View File

@ -75,8 +75,6 @@ set_freetype_error(const char* prefix, int err_code) {
static FT_Library library;
#define CALC_CELL_HEIGHT(self) font_units_to_pixels_y(self, self->height)
static inline int
font_units_to_pixels_y(Face *self, int x) {
return ceil((double)FT_MulFix(x, self->face->size->metrics.y_scale) / 64.0);
@ -87,11 +85,56 @@ font_units_to_pixels_x(Face *self, int x) {
return ceil((double)FT_MulFix(x, self->face->size->metrics.x_scale) / 64.0);
}
static inline int
get_load_flags(int hinting, int hintstyle, int base) {
int flags = base;
if (hinting) {
if (hintstyle >= 3) flags |= FT_LOAD_TARGET_NORMAL;
else if (0 < hintstyle && hintstyle < 3) flags |= FT_LOAD_TARGET_LIGHT;
} else flags |= FT_LOAD_NO_HINTING;
return flags;
}
static inline bool
load_glyph(Face *self, int glyph_index, int load_type) {
int flags = get_load_flags(self->hinting, self->hintstyle, load_type);
int error = FT_Load_Glyph(self->face, glyph_index, flags);
if (error) { set_freetype_error("Failed to load glyph, with error:", error); return false; }
return true;
}
static inline unsigned int
get_height_for_char(Face *self, char ch) {
unsigned int ans = 0;
int glyph_index = FT_Get_Char_Index(self->face, ch);
if (load_glyph(self, glyph_index, FT_LOAD_DEFAULT)) {
unsigned int baseline = font_units_to_pixels_y(self, self->ascender);
FT_GlyphSlotRec *glyph = self->face->glyph;
FT_Bitmap *bm = &glyph->bitmap;
if (glyph->bitmap_top <= 0 || (glyph->bitmap_top > 0 && (unsigned int)glyph->bitmap_top < baseline)) {
ans = baseline - glyph->bitmap_top + bm->rows;
}
}
return ans;
}
static inline unsigned int
calc_cell_height(Face *self, bool for_metrics) {
unsigned int ans = font_units_to_pixels_y(self, self->height);
unsigned int underscore_height = get_height_for_char(self, '_');
if (for_metrics && global_state.debug_font_fallback && underscore_height > ans) {
printf("Increasing cell height by %u pixels to work around buggy font that renders underscore outside the bounding box\n", underscore_height - ans);
}
return MAX(ans, underscore_height);
}
static inline bool
set_font_size(Face *self, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt xdpi, FT_UInt ydpi, unsigned int desired_height, unsigned int cell_height) {
int error = FT_Set_Char_Size(self->face, 0, char_height, xdpi, ydpi);
if (!error) {
unsigned int ch = CALC_CELL_HEIGHT(self);
unsigned int ch = calc_cell_height(self, false);
if (desired_height && ch != desired_height) {
FT_F26Dot6 h = floor((double)char_height * (double)desired_height / (double) ch);
return set_font_size(self, 0, h, xdpi, ydpi, 0, cell_height);
@ -147,17 +190,6 @@ set_size_for_face(PyObject *s, unsigned int desired_height, bool force, FONTS_DA
return set_font_size(self, w, w, xdpi, ydpi, desired_height, fg->cell_height);
}
static inline int
get_load_flags(int hinting, int hintstyle, int base) {
int flags = base;
if (hinting) {
if (hintstyle >= 3) flags |= FT_LOAD_TARGET_NORMAL;
else if (0 < hintstyle && hintstyle < 3) flags |= FT_LOAD_TARGET_LIGHT;
} else flags |= FT_LOAD_NO_HINTING;
return flags;
}
static inline bool
init_ft_face(Face *self, PyObject *path, int hinting, int hintstyle, FONTS_DATA_HANDLE fg) {
#define CPY(n) self->n = self->face->n;
@ -236,14 +268,6 @@ repr(Face *self) {
}
static inline bool
load_glyph(Face *self, int glyph_index, int load_type) {
int flags = get_load_flags(self->hinting, self->hintstyle, load_type);
int error = FT_Load_Glyph(self->face, glyph_index, flags);
if (error) { set_freetype_error("Failed to load glyph, with error:", error); return false; }
return true;
}
static inline unsigned int
calc_cell_width(Face *self) {
unsigned int ans = 0;
@ -260,7 +284,7 @@ void
cell_metrics(PyObject *s, unsigned int* cell_width, unsigned int* cell_height, unsigned int* baseline, unsigned int* underline_position, unsigned int* underline_thickness) {
Face *self = (Face*)s;
*cell_width = calc_cell_width(self);
*cell_height = CALC_CELL_HEIGHT(self);
*cell_height = calc_cell_height(self, true);
*baseline = font_units_to_pixels_y(self, self->ascender);
*underline_position = MIN(*cell_height - 1, (unsigned int)font_units_to_pixels_y(self, MAX(0, self->ascender - self->underline_position)));
*underline_thickness = MAX(1, font_units_to_pixels_y(self, self->underline_thickness));