mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-18 22:44:50 +02:00
Fix freetype based rendering of non-hinted fonts at small sizes
Now use the post hinting bitmap bearing values instead of the hinting independent glyph metrics bearing values. Fixes #1173
This commit is contained in:
@@ -55,6 +55,9 @@ Changelog
|
|||||||
|
|
||||||
- macOS: Fix touch scrolling sensitivity low on retina screens (:iss:`1112`)
|
- macOS: Fix touch scrolling sensitivity low on retina screens (:iss:`1112`)
|
||||||
|
|
||||||
|
- Linux: Fix incorrect rendering of some fonts when hinting is disabled at
|
||||||
|
small sizes (:iss:`1173`)
|
||||||
|
|
||||||
- Linux: Fix match rules used as aliases in Fontconfig configuration not being
|
- Linux: Fix match rules used as aliases in Fontconfig configuration not being
|
||||||
respected (:iss:`1085`)
|
respected (:iss:`1085`)
|
||||||
|
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ typedef struct {
|
|||||||
FT_Pixel_Mode pixel_mode;
|
FT_Pixel_Mode pixel_mode;
|
||||||
bool needs_free;
|
bool needs_free;
|
||||||
unsigned int factor, right_edge;
|
unsigned int factor, right_edge;
|
||||||
|
int bitmap_left, bitmap_top;
|
||||||
} ProcessedBitmap;
|
} ProcessedBitmap;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -330,7 +331,7 @@ trim_borders(ProcessedBitmap *ans, size_t extra) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
populate_processed_bitmap(FT_Bitmap *bitmap, ProcessedBitmap *ans, bool copy_buf) {
|
populate_processed_bitmap(FT_GlyphSlotRec *slot, FT_Bitmap *bitmap, ProcessedBitmap *ans, bool copy_buf) {
|
||||||
ans->stride = bitmap->pitch < 0 ? -bitmap->pitch : bitmap->pitch;
|
ans->stride = bitmap->pitch < 0 ? -bitmap->pitch : bitmap->pitch;
|
||||||
ans->rows = bitmap->rows;
|
ans->rows = bitmap->rows;
|
||||||
if (copy_buf) {
|
if (copy_buf) {
|
||||||
@@ -341,6 +342,7 @@ populate_processed_bitmap(FT_Bitmap *bitmap, ProcessedBitmap *ans, bool copy_buf
|
|||||||
} else ans->buf = bitmap->buffer;
|
} else ans->buf = bitmap->buffer;
|
||||||
ans->start_x = 0; ans->width = bitmap->width;
|
ans->start_x = 0; ans->width = bitmap->width;
|
||||||
ans->pixel_mode = bitmap->pixel_mode;
|
ans->pixel_mode = bitmap->pixel_mode;
|
||||||
|
ans->bitmap_top = slot->bitmap_top; ans->bitmap_left = slot->bitmap_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
@@ -364,10 +366,10 @@ render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_
|
|||||||
// We only have 2 levels
|
// We only have 2 levels
|
||||||
for (unsigned int j = 0; j < bitmap.width; ++j) bitmap.buffer[i * stride + j] *= 255;
|
for (unsigned int j = 0; j < bitmap.width; ++j) bitmap.buffer[i * stride + j] *= 255;
|
||||||
}
|
}
|
||||||
populate_processed_bitmap(&bitmap, ans, true);
|
populate_processed_bitmap(self->face->glyph, &bitmap, ans, true);
|
||||||
FT_Bitmap_Done(library, &bitmap);
|
FT_Bitmap_Done(library, &bitmap);
|
||||||
} else {
|
} else {
|
||||||
populate_processed_bitmap(&self->face->glyph->bitmap, ans, false);
|
populate_processed_bitmap(self->face->glyph, &self->face->glyph->bitmap, ans, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ans->width > max_width) {
|
if (ans->width > max_width) {
|
||||||
@@ -480,16 +482,14 @@ copy_color_bitmap(uint8_t *src, pixel* dest, Region *src_rect, Region *dest_rect
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, FT_Glyph_Metrics *metrics, size_t baseline) {
|
place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, size_t baseline) {
|
||||||
// We want the glyph to be positioned inside the cell based on the bearingX
|
// We want the glyph to be positioned inside the cell based on the bearingX
|
||||||
// and bearingY values, making sure that it does not overflow the cell.
|
// and bearingY values, making sure that it does not overflow the cell.
|
||||||
|
|
||||||
Region src = { .left = bm->start_x, .bottom = bm->rows, .right = bm->width + bm->start_x }, dest = { .bottom = cell_height, .right = cell_width };
|
Region src = { .left = bm->start_x, .bottom = bm->rows, .right = bm->width + bm->start_x }, dest = { .bottom = cell_height, .right = cell_width };
|
||||||
|
|
||||||
// Calculate column bounds
|
// Calculate column bounds
|
||||||
float bearing_x = (float)metrics->horiBearingX / 64.f;
|
int32_t xoff = (ssize_t)(x_offset + bm->bitmap_left);
|
||||||
bearing_x /= bm->factor;
|
|
||||||
int32_t xoff = (ssize_t)(x_offset + bearing_x);
|
|
||||||
uint32_t extra;
|
uint32_t extra;
|
||||||
if (xoff < 0) src.left += -xoff;
|
if (xoff < 0) src.left += -xoff;
|
||||||
else dest.left = xoff;
|
else dest.left = xoff;
|
||||||
@@ -500,9 +500,7 @@ place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate row bounds
|
// Calculate row bounds
|
||||||
float bearing_y = (float)metrics->horiBearingY / 64.f;
|
int32_t yoff = (ssize_t)(y_offset + bm->bitmap_top);
|
||||||
bearing_y /= bm->factor;
|
|
||||||
int32_t yoff = (ssize_t)(y_offset + bearing_y);
|
|
||||||
if ((yoff > 0 && (size_t)yoff > baseline)) {
|
if ((yoff > 0 && (size_t)yoff > baseline)) {
|
||||||
dest.top = 0;
|
dest.top = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -538,7 +536,7 @@ render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *inf
|
|||||||
}
|
}
|
||||||
x_offset = x + (float)positions[i].x_offset / 64.0f;
|
x_offset = x + (float)positions[i].x_offset / 64.0f;
|
||||||
y = (float)positions[i].y_offset / 64.0f;
|
y = (float)positions[i].y_offset / 64.0f;
|
||||||
if ((*was_colored || self->face->glyph->metrics.width > 0) && bm.width > 0) place_bitmap_in_canvas(canvas, &bm, canvas_width, cell_height, x_offset, y, &self->face->glyph->metrics, baseline);
|
if ((*was_colored || self->face->glyph->metrics.width > 0) && bm.width > 0) place_bitmap_in_canvas(canvas, &bm, canvas_width, cell_height, x_offset, y, baseline);
|
||||||
x += (float)positions[i].x_advance / 64.0f;
|
x += (float)positions[i].x_advance / 64.0f;
|
||||||
free_processed_bitmap(&bm);
|
free_processed_bitmap(&bm);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user