From afda299fe4e9052894207df11522c26d9ab346a9 Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Fri, 4 Dec 2020 16:15:54 +0100 Subject: [PATCH] Implement optional font rendering options The user can now choose antialiasing grayscale and subpixel and hinting non, slight or full. --- data/core/style.lua | 16 +++++++++++++++- src/api/renderer_font.c | 36 +++++++++++++++++++++++++++++++++++- src/renderer.c | 13 +++++++++++-- src/renderer.h | 13 ++++++++++++- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/data/core/style.lua b/data/core/style.lua index 8ab2008e..e8567de5 100644 --- a/data/core/style.lua +++ b/data/core/style.lua @@ -7,9 +7,23 @@ style.scrollbar_size = common.round(4 * SCALE) style.caret_width = common.round(2 * SCALE) style.tab_width = common.round(170 * SCALE) +-- The function renderer.font.load can accept an option table as a second optional argument. +-- It shoud be like the following: +-- +-- {antialiasing= "grayscale", hinting = "full"} +-- +-- The possible values for each option are: +-- - for antialiang: grayscale, subpixel +-- - for hinting: none, slight, full +-- +-- The defaults values are antialiang subpixel and hinting slight for optimal visualization +-- on ordinary LCD monitor with RGB patterns. +-- +-- On High DPI monitor or non RGB monitor you may consider using antialiang grayscale instead. +-- The antialising grayscale with full hinting is interesting for crisp font rendering. style.font = renderer.font.load(DATADIR .. "/fonts/font.ttf", 14 * SCALE) style.big_font = renderer.font.load(DATADIR .. "/fonts/font.ttf", 34 * SCALE) -style.icon_font = renderer.font.load(DATADIR .. "/fonts/icons.ttf", 14 * SCALE) +style.icon_font = renderer.font.load(DATADIR .. "/fonts/icons.ttf", 14 * SCALE, {antialiasing="grayscale", hinting="full"}) style.code_font = renderer.font.load(DATADIR .. "/fonts/monospace.ttf", 13.5 * SCALE) style.background = { common.color "#2e2e32" } diff --git a/src/api/renderer_font.c b/src/api/renderer_font.c index 452aedeb..0dea11ae 100644 --- a/src/api/renderer_font.c +++ b/src/api/renderer_font.c @@ -6,9 +6,43 @@ static int f_load(lua_State *L) { const char *filename = luaL_checkstring(L, 1); float size = luaL_checknumber(L, 2); + unsigned int font_options = 0; + if (lua_gettop(L) > 2 && lua_istable(L, 3)) { + lua_getfield(L, 3, "antialiasing"); + if (lua_isstring(L, -1)) { + const char *antialiasing = lua_tostring(L, -1); + if (antialiasing) { + if (strcmp(antialiasing, "grayscale") == 0) { + font_options |= RenFontGrayscale; + } else if (strcmp(antialiasing, "subpixel") == 0) { + font_options |= RenFontSubpixel; + } else { + return luaL_error(L, "error in renderer.font.load, unknown antialiasing option: \"%s\"", antialiasing); + } + } + } + lua_pop(L, 1); + + lua_getfield(L, 3, "hinting"); + if (lua_isstring(L, -1)) { + const char *hinting = lua_tostring(L, -1); + if (hinting) { + if (strcmp(hinting, "slight") == 0) { + font_options |= RenFontHintingSlight; + } else if (strcmp(hinting, "none") == 0) { + font_options |= RenFontHintingNone; + } else if (strcmp(hinting, "full") == 0) { + font_options |= RenFontHintingFull; + } else { + return luaL_error(L, "error in renderer.font.load, unknown hinting option: \"%s\"", hinting); + } + } + } + lua_pop(L, 1); + } RenFont **self = lua_newuserdata(L, sizeof(*self)); luaL_setmetatable(L, API_TYPE_FONT); - *self = ren_load_font(filename, size); + *self = ren_load_font(filename, size, font_options); if (!*self) { luaL_error(L, "failed to load font"); } return 1; } diff --git a/src/renderer.c b/src/renderer.c index e0ab519b..ce9ce86a 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -141,14 +141,23 @@ static GlyphSet* get_glyphset(RenFont *font, int codepoint) { } -RenFont* ren_load_font(const char *filename, float size) { +RenFont* ren_load_font(const char *filename, float size, unsigned int renderer_flags) { RenFont *font = NULL; /* init font */ font = check_alloc(calloc(1, sizeof(RenFont))); font->size = size; - font->renderer = FR_Renderer_New(FR_HINTING | FR_SUBPIXEL | FR_PRESCALE_X); + unsigned int fr_renderer_flags = 0; + if ((renderer_flags & RenFontAntialiasingMask) == RenFontSubpixel) { + fr_renderer_flags |= FR_SUBPIXEL; + } + if ((renderer_flags & RenFontHintingMask) == RenFontHintingSlight) { + fr_renderer_flags |= (FR_HINTING | FR_PRESCALE_X); + } else if ((renderer_flags & RenFontHintingMask) == RenFontHintingFull) { + fr_renderer_flags |= FR_HINTING; + } + font->renderer = FR_Renderer_New(fr_renderer_flags); if (FR_Load_Font(font->renderer, filename)) { free(font); return NULL; diff --git a/src/renderer.h b/src/renderer.h index aa37495d..3b041846 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -7,6 +7,17 @@ typedef struct RenImage RenImage; typedef struct RenFont RenFont; +enum { + RenFontAntialiasingMask = 1, + RenFontGrayscale = 1, + RenFontSubpixel = 0, + + RenFontHintingMask = 3 << 1, + RenFontHintingSlight = 0 << 1, + RenFontHintingNone = 1 << 1, + RenFontHintingFull = 2 << 1, +}; + typedef struct { uint8_t b, g, r, a; } RenColor; typedef struct { int x, y, width, height; } RenRect; @@ -19,7 +30,7 @@ void ren_get_size(int *x, int *y); RenImage* ren_new_image(int width, int height); void ren_free_image(RenImage *image); -RenFont* ren_load_font(const char *filename, float size); +RenFont* ren_load_font(const char *filename, float size, unsigned int renderer_flags); void ren_free_font(RenFont *font); void ren_set_font_tab_width(RenFont *font, int n); int ren_get_font_tab_width(RenFont *font);