Seen with some fonts like FiraSans, github issue: https://github.com/franko/lite-xl/issues/46 The fix works essentially by looking to the bounds of each glyph to accurately ensure that there are no overlaps between the glyphs. The construction of the font atlas was changed to make some related improvements now that the bounds of each glyph are know. The main changes are: - no longer align glyph on the baseline but align them on their upper bounds. We ensure this way that very tall fonts do not leak in the upper part - terminate the row based on x bounds of the glyph to be more accurate - for each row keep trace of the y of the more larger along y of the glyph. The value is used to start a new row to be sure that the new now does not overlap with the previous one - sort glyphs by y size before drawing them. In this way the space utilization is better. The algorithm used is the very simple insert sort. It behaves like O(n^2) with the number of characters but should be ok since n is always small, typically below 128. - compute the optimal image width and height for the given font's atlas for optimal memory usage. As a bonus now the lite's code don't have to try and repeat to get a good image size
58 lines
1.4 KiB
C++
58 lines
1.4 KiB
C++
#ifndef FONT_RENDERER_H
|
|
#define FONT_RENDERER_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct {
|
|
unsigned short x0, y0, x1, y1;
|
|
float xoff, yoff, xadvance;
|
|
} FR_Bitmap_Glyph_Metrics;
|
|
|
|
typedef struct FR_Bitmap FR_Bitmap;
|
|
|
|
#ifdef __cplusplus
|
|
class FR_Renderer;
|
|
#else
|
|
struct FR_Renderer;
|
|
typedef struct FR_Renderer FR_Renderer;
|
|
#endif
|
|
|
|
enum {
|
|
FR_HINTING = 1 << 0,
|
|
FR_KERNING = 1 << 1,
|
|
FR_SUBPIXEL = 1 << 2,
|
|
FR_PRESCALE_X = 1 << 3,
|
|
};
|
|
|
|
typedef struct {
|
|
uint8_t r, g, b;
|
|
} FR_Color;
|
|
|
|
typedef struct {
|
|
int left, top, right, bottom;
|
|
} FR_Clip_Area;
|
|
|
|
FR_Renderer * FR_Renderer_New(unsigned int flags);
|
|
void FR_Renderer_Free(FR_Renderer *);
|
|
int FR_Load_Font(FR_Renderer *, const char *filename);
|
|
FR_Bitmap* FR_Bitmap_New(FR_Renderer *, int width, int height);
|
|
void FR_Bitmap_Free(FR_Bitmap *image);
|
|
int FR_Get_Font_Height(FR_Renderer *, float size);
|
|
FR_Bitmap * FR_Bake_Font_Bitmap(FR_Renderer *, int font_height,
|
|
int first_char, int num_chars, FR_Bitmap_Glyph_Metrics *glyph_info);
|
|
void FR_Blend_Glyph(FR_Renderer *font_renderer,
|
|
FR_Clip_Area *clip, int x, int y,
|
|
uint8_t *dst, int dst_width,
|
|
const FR_Bitmap *glyphs_bitmap,
|
|
const FR_Bitmap_Glyph_Metrics *glyph, FR_Color color);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|