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:
Kovid Goyal 2018-12-02 14:12:46 +05:30
parent 8ba8320189
commit 222beedc2a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 12 additions and 11 deletions

View File

@ -55,6 +55,9 @@ Changelog
- 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
respected (:iss:`1085`)

View File

@ -302,6 +302,7 @@ typedef struct {
FT_Pixel_Mode pixel_mode;
bool needs_free;
unsigned int factor, right_edge;
int bitmap_left, bitmap_top;
} ProcessedBitmap;
static inline void
@ -330,7 +331,7 @@ trim_borders(ProcessedBitmap *ans, size_t extra) {
}
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->rows = bitmap->rows;
if (copy_buf) {
@ -341,6 +342,7 @@ populate_processed_bitmap(FT_Bitmap *bitmap, ProcessedBitmap *ans, bool copy_buf
} else ans->buf = bitmap->buffer;
ans->start_x = 0; ans->width = bitmap->width;
ans->pixel_mode = bitmap->pixel_mode;
ans->bitmap_top = slot->bitmap_top; ans->bitmap_left = slot->bitmap_left;
}
static inline bool
@ -364,10 +366,10 @@ render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_
// We only have 2 levels
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);
} 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) {
@ -480,16 +482,14 @@ copy_color_bitmap(uint8_t *src, pixel* dest, Region *src_rect, Region *dest_rect
}
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
// 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 };
// Calculate column bounds
float bearing_x = (float)metrics->horiBearingX / 64.f;
bearing_x /= bm->factor;
int32_t xoff = (ssize_t)(x_offset + bearing_x);
int32_t xoff = (ssize_t)(x_offset + bm->bitmap_left);
uint32_t extra;
if (xoff < 0) src.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
float bearing_y = (float)metrics->horiBearingY / 64.f;
bearing_y /= bm->factor;
int32_t yoff = (ssize_t)(y_offset + bearing_y);
int32_t yoff = (ssize_t)(y_offset + bm->bitmap_top);
if ((yoff > 0 && (size_t)yoff > baseline)) {
dest.top = 0;
} 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;
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;
free_processed_bitmap(&bm);
}