Merge pull request #1057 from jgmdev/PR/font-additions
renderer fonts: additions and improvements
This commit is contained in:
commit
6a8eed45c7
|
@ -14,9 +14,7 @@ for _, attr in pairs({"bold", "italic", "bold_italic"}) do
|
||||||
attributes["bold"] = true
|
attributes["bold"] = true
|
||||||
attributes["italic"] = true
|
attributes["italic"] = true
|
||||||
end
|
end
|
||||||
-- no way to copy user custom font with additional attributes :(
|
style.syntax_fonts["markdown_"..attr] = style.code_font:copy(
|
||||||
style.syntax_fonts["markdown_"..attr] = renderer.font.load(
|
|
||||||
DATADIR .. "/fonts/JetBrainsMono-Regular.ttf",
|
|
||||||
style.code_font:get_size(),
|
style.code_font:get_size(),
|
||||||
attributes
|
attributes
|
||||||
)
|
)
|
||||||
|
|
|
@ -79,14 +79,14 @@ local function set_scale(scale)
|
||||||
style.tab_width = style.tab_width * s
|
style.tab_width = style.tab_width * s
|
||||||
|
|
||||||
for _, name in ipairs {"font", "big_font", "icon_font", "icon_big_font", "code_font"} do
|
for _, name in ipairs {"font", "big_font", "icon_font", "icon_big_font", "code_font"} do
|
||||||
style[name] = renderer.font.copy(style[name], s * style[name]:get_size())
|
style[name]:set_size(s * style[name]:get_size())
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
style.code_font = renderer.font.copy(style.code_font, s * style.code_font:get_size())
|
style.code_font:set_size(s * style.code_font:get_size())
|
||||||
end
|
end
|
||||||
|
|
||||||
for name, font in pairs(style.syntax_fonts) do
|
for name, font in pairs(style.syntax_fonts) do
|
||||||
style.syntax_fonts[name] = renderer.font.copy(font, s * font:get_size())
|
style.syntax_fonts[name]:set_size(s * font:get_size())
|
||||||
end
|
end
|
||||||
|
|
||||||
-- restore scroll positions
|
-- restore scroll positions
|
||||||
|
@ -108,12 +108,10 @@ end
|
||||||
|
|
||||||
local function inc_scale()
|
local function inc_scale()
|
||||||
set_scale(current_scale + scale_steps)
|
set_scale(current_scale + scale_steps)
|
||||||
collectgarbage "step"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function dec_scale()
|
local function dec_scale()
|
||||||
set_scale(current_scale - scale_steps)
|
set_scale(current_scale - scale_steps)
|
||||||
collectgarbage "step"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ renderer.font = {}
|
||||||
---
|
---
|
||||||
---@param path string
|
---@param path string
|
||||||
---@param size number
|
---@param size number
|
||||||
---@param options renderer.fontoptions
|
---@param options? renderer.fontoptions
|
||||||
---
|
---
|
||||||
---@return renderer.font
|
---@return renderer.font
|
||||||
function renderer.font.load(path, size, options) end
|
function renderer.font.load(path, size, options) end
|
||||||
|
@ -54,9 +54,10 @@ function renderer.font.group(fonts) end
|
||||||
---Clones a font object into a new one.
|
---Clones a font object into a new one.
|
||||||
---
|
---
|
||||||
---@param size? number Optional new size for cloned font.
|
---@param size? number Optional new size for cloned font.
|
||||||
|
---@param options? renderer.fontoptions
|
||||||
---
|
---
|
||||||
---@return renderer.font
|
---@return renderer.font
|
||||||
function renderer.font:copy(size) end
|
function renderer.font:copy(size, options) end
|
||||||
|
|
||||||
---
|
---
|
||||||
---Set the amount of characters that represent a tab.
|
---Set the amount of characters that represent a tab.
|
||||||
|
@ -92,6 +93,13 @@ function renderer.font:get_size() end
|
||||||
---@param size number
|
---@param size number
|
||||||
function renderer.font:set_size(size) end
|
function renderer.font:set_size(size) end
|
||||||
|
|
||||||
|
---
|
||||||
|
---Get the current path of the font as a string if a single font or as an
|
||||||
|
---array of strings if a group font.
|
||||||
|
---
|
||||||
|
---@return string | table<integer, string>
|
||||||
|
function renderer.font:get_path() end
|
||||||
|
|
||||||
---
|
---
|
||||||
---Toggles drawing debugging rectangles on the currently rendered sections
|
---Toggles drawing debugging rectangles on the currently rendered sections
|
||||||
---of the window to help troubleshoot the renderer.
|
---of the window to help troubleshoot the renderer.
|
||||||
|
|
|
@ -3,55 +3,83 @@
|
||||||
#include "../renderer.h"
|
#include "../renderer.h"
|
||||||
#include "../rencache.h"
|
#include "../rencache.h"
|
||||||
|
|
||||||
static int f_font_load(lua_State *L) {
|
static int font_get_options(
|
||||||
const char *filename = luaL_checkstring(L, 1);
|
lua_State *L,
|
||||||
float size = luaL_checknumber(L, 2);
|
ERenFontAntialiasing *antialiasing,
|
||||||
unsigned int font_hinting = FONT_HINTING_SLIGHT, font_style = 0;
|
ERenFontHinting *hinting,
|
||||||
ERenFontAntialiasing font_antialiasing = FONT_ANTIALIASING_SUBPIXEL;
|
int *style
|
||||||
|
) {
|
||||||
if (lua_gettop(L) > 2 && lua_istable(L, 3)) {
|
if (lua_gettop(L) > 2 && lua_istable(L, 3)) {
|
||||||
lua_getfield(L, 3, "antialiasing");
|
lua_getfield(L, 3, "antialiasing");
|
||||||
if (lua_isstring(L, -1)) {
|
if (lua_isstring(L, -1)) {
|
||||||
const char *antialiasing = lua_tostring(L, -1);
|
const char *antialiasing_str = lua_tostring(L, -1);
|
||||||
if (antialiasing) {
|
if (antialiasing_str) {
|
||||||
if (strcmp(antialiasing, "none") == 0) {
|
if (strcmp(antialiasing_str, "none") == 0) {
|
||||||
font_antialiasing = FONT_ANTIALIASING_NONE;
|
*antialiasing = FONT_ANTIALIASING_NONE;
|
||||||
} else if (strcmp(antialiasing, "grayscale") == 0) {
|
} else if (strcmp(antialiasing_str, "grayscale") == 0) {
|
||||||
font_antialiasing = FONT_ANTIALIASING_GRAYSCALE;
|
*antialiasing = FONT_ANTIALIASING_GRAYSCALE;
|
||||||
} else if (strcmp(antialiasing, "subpixel") == 0) {
|
} else if (strcmp(antialiasing_str, "subpixel") == 0) {
|
||||||
font_antialiasing = FONT_ANTIALIASING_SUBPIXEL;
|
*antialiasing = FONT_ANTIALIASING_SUBPIXEL;
|
||||||
} else {
|
} else {
|
||||||
return luaL_error(L, "error in renderer.font.load, unknown antialiasing option: \"%s\"", antialiasing);
|
return luaL_error(
|
||||||
|
L,
|
||||||
|
"error in font options, unknown antialiasing option: \"%s\"",
|
||||||
|
antialiasing_str
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_getfield(L, 3, "hinting");
|
lua_getfield(L, 3, "hinting");
|
||||||
if (lua_isstring(L, -1)) {
|
if (lua_isstring(L, -1)) {
|
||||||
const char *hinting = lua_tostring(L, -1);
|
const char *hinting_str = lua_tostring(L, -1);
|
||||||
if (hinting) {
|
if (hinting_str) {
|
||||||
if (strcmp(hinting, "slight") == 0) {
|
if (strcmp(hinting_str, "slight") == 0) {
|
||||||
font_hinting = FONT_HINTING_SLIGHT;
|
*hinting = FONT_HINTING_SLIGHT;
|
||||||
} else if (strcmp(hinting, "none") == 0) {
|
} else if (strcmp(hinting_str, "none") == 0) {
|
||||||
font_hinting = FONT_HINTING_NONE;
|
*hinting = FONT_HINTING_NONE;
|
||||||
} else if (strcmp(hinting, "full") == 0) {
|
} else if (strcmp(hinting_str, "full") == 0) {
|
||||||
font_hinting = FONT_HINTING_FULL;
|
*hinting = FONT_HINTING_FULL;
|
||||||
} else {
|
} else {
|
||||||
return luaL_error(L, "error in renderer.font.load, unknown hinting option: \"%s\"", hinting);
|
return luaL_error(
|
||||||
|
L,
|
||||||
|
"error in font options, unknown hinting option: \"%s\"",
|
||||||
|
hinting
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int style_local = 0;
|
||||||
lua_getfield(L, 3, "italic");
|
lua_getfield(L, 3, "italic");
|
||||||
if (lua_toboolean(L, -1))
|
if (lua_toboolean(L, -1))
|
||||||
font_style |= FONT_STYLE_ITALIC;
|
style_local |= FONT_STYLE_ITALIC;
|
||||||
lua_getfield(L, 3, "bold");
|
lua_getfield(L, 3, "bold");
|
||||||
if (lua_toboolean(L, -1))
|
if (lua_toboolean(L, -1))
|
||||||
font_style |= FONT_STYLE_BOLD;
|
style_local |= FONT_STYLE_BOLD;
|
||||||
lua_getfield(L, 3, "underline");
|
lua_getfield(L, 3, "underline");
|
||||||
if (lua_toboolean(L, -1))
|
if (lua_toboolean(L, -1))
|
||||||
font_style |= FONT_STYLE_UNDERLINE;
|
style_local |= FONT_STYLE_UNDERLINE;
|
||||||
lua_pop(L, 5);
|
lua_pop(L, 5);
|
||||||
|
|
||||||
|
if (style_local != 0)
|
||||||
|
*style = style_local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int f_font_load(lua_State *L) {
|
||||||
|
const char *filename = luaL_checkstring(L, 1);
|
||||||
|
float size = luaL_checknumber(L, 2);
|
||||||
|
int style = 0;
|
||||||
|
ERenFontHinting hinting = FONT_HINTING_SLIGHT;
|
||||||
|
ERenFontAntialiasing antialiasing = FONT_ANTIALIASING_SUBPIXEL;
|
||||||
|
|
||||||
|
int ret_code = font_get_options(L, &antialiasing, &hinting, &style);
|
||||||
|
if (ret_code > 0)
|
||||||
|
return ret_code;
|
||||||
|
|
||||||
RenFont** font = lua_newuserdata(L, sizeof(RenFont*));
|
RenFont** font = lua_newuserdata(L, sizeof(RenFont*));
|
||||||
*font = ren_font_load(filename, size, font_antialiasing, font_hinting, font_style);
|
*font = ren_font_load(filename, size, antialiasing, hinting, style);
|
||||||
if (!*font)
|
if (!*font)
|
||||||
return luaL_error(L, "failed to load font");
|
return luaL_error(L, "failed to load font");
|
||||||
luaL_setmetatable(L, API_TYPE_FONT);
|
luaL_setmetatable(L, API_TYPE_FONT);
|
||||||
|
@ -77,13 +105,21 @@ static int f_font_copy(lua_State *L) {
|
||||||
RenFont* fonts[FONT_FALLBACK_MAX];
|
RenFont* fonts[FONT_FALLBACK_MAX];
|
||||||
bool table = font_retrieve(L, fonts, 1);
|
bool table = font_retrieve(L, fonts, 1);
|
||||||
float size = lua_gettop(L) >= 2 ? luaL_checknumber(L, 2) : ren_font_group_get_height(fonts);
|
float size = lua_gettop(L) >= 2 ? luaL_checknumber(L, 2) : ren_font_group_get_height(fonts);
|
||||||
|
int style = -1;
|
||||||
|
ERenFontHinting hinting = -1;
|
||||||
|
ERenFontAntialiasing antialiasing = -1;
|
||||||
|
|
||||||
|
int ret_code = font_get_options(L, &antialiasing, &hinting, &style);
|
||||||
|
if (ret_code > 0)
|
||||||
|
return ret_code;
|
||||||
|
|
||||||
if (table) {
|
if (table) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
luaL_setmetatable(L, API_TYPE_FONT);
|
luaL_setmetatable(L, API_TYPE_FONT);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
|
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
|
||||||
RenFont** font = lua_newuserdata(L, sizeof(RenFont*));
|
RenFont** font = lua_newuserdata(L, sizeof(RenFont*));
|
||||||
*font = ren_font_copy(fonts[i], size);
|
*font = ren_font_copy(fonts[i], size, antialiasing, hinting, style);
|
||||||
if (!*font)
|
if (!*font)
|
||||||
return luaL_error(L, "failed to copy font");
|
return luaL_error(L, "failed to copy font");
|
||||||
luaL_setmetatable(L, API_TYPE_FONT);
|
luaL_setmetatable(L, API_TYPE_FONT);
|
||||||
|
@ -99,6 +135,22 @@ static int f_font_group(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int f_font_get_path(lua_State *L) {
|
||||||
|
RenFont* fonts[FONT_FALLBACK_MAX];
|
||||||
|
bool table = font_retrieve(L, fonts, 1);
|
||||||
|
|
||||||
|
if (table) {
|
||||||
|
lua_newtable(L);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
|
||||||
|
const char* path = ren_font_get_path(fonts[i]);
|
||||||
|
lua_pushstring(L, path);
|
||||||
|
if (table)
|
||||||
|
lua_rawseti(L, -2, i+1);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int f_font_set_tab_size(lua_State *L) {
|
static int f_font_set_tab_size(lua_State *L) {
|
||||||
RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1);
|
RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1);
|
||||||
int n = luaL_checknumber(L, 2);
|
int n = luaL_checknumber(L, 2);
|
||||||
|
@ -133,6 +185,13 @@ static int f_font_get_size(lua_State *L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int f_font_set_size(lua_State *L) {
|
||||||
|
RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1);
|
||||||
|
float size = luaL_checknumber(L, 2);
|
||||||
|
ren_font_group_set_size(fonts, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static RenColor checkcolor(lua_State *L, int idx, int def) {
|
static RenColor checkcolor(lua_State *L, int idx, int def) {
|
||||||
RenColor color;
|
RenColor color;
|
||||||
if (lua_isnoneornil(L, idx)) {
|
if (lua_isnoneornil(L, idx)) {
|
||||||
|
@ -240,6 +299,8 @@ static const luaL_Reg fontLib[] = {
|
||||||
{ "get_width", f_font_get_width },
|
{ "get_width", f_font_get_width },
|
||||||
{ "get_height", f_font_get_height },
|
{ "get_height", f_font_get_height },
|
||||||
{ "get_size", f_font_get_size },
|
{ "get_size", f_font_get_size },
|
||||||
|
{ "set_size", f_font_set_size },
|
||||||
|
{ "get_path", f_font_get_path },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,19 @@ static RenFont* font_group_get_glyph(GlyphSet** set, GlyphMetric** metric, RenFo
|
||||||
return fonts[0];
|
return fonts[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void font_clear_glyph_cache(RenFont* font) {
|
||||||
|
for (int i = 0; i < SUBPIXEL_BITMAPS_CACHED; ++i) {
|
||||||
|
for (int j = 0; j < MAX_GLYPHSET; ++j) {
|
||||||
|
if (font->sets[i][j]) {
|
||||||
|
if (font->sets[i][j]->surface)
|
||||||
|
SDL_FreeSurface(font->sets[i][j]->surface);
|
||||||
|
free(font->sets[i][j]);
|
||||||
|
font->sets[i][j] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) {
|
RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) {
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
if (FT_New_Face( library, path, 0, &face))
|
if (FT_New_Face( library, path, 0, &face))
|
||||||
|
@ -217,20 +230,20 @@ RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antial
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenFont* ren_font_copy(RenFont* font, float size) {
|
RenFont* ren_font_copy(RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style) {
|
||||||
return ren_font_load(font->path, size, font->antialiasing, font->hinting, font->style);
|
antialiasing = antialiasing == -1 ? font->antialiasing : antialiasing;
|
||||||
|
hinting = hinting == -1 ? font->hinting : hinting;
|
||||||
|
style = style == -1 ? font->style : style;
|
||||||
|
|
||||||
|
return ren_font_load(font->path, size, antialiasing, hinting, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ren_font_get_path(RenFont *font) {
|
||||||
|
return font->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ren_font_free(RenFont* font) {
|
void ren_font_free(RenFont* font) {
|
||||||
for (int i = 0; i < SUBPIXEL_BITMAPS_CACHED; ++i) {
|
font_clear_glyph_cache(font);
|
||||||
for (int j = 0; j < MAX_GLYPHSET; ++j) {
|
|
||||||
if (font->sets[i][j]) {
|
|
||||||
if (font->sets[i][j]->surface)
|
|
||||||
SDL_FreeSurface(font->sets[i][j]->surface);
|
|
||||||
free(font->sets[i][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FT_Done_Face(font->face);
|
FT_Done_Face(font->face);
|
||||||
free(font);
|
free(font);
|
||||||
}
|
}
|
||||||
|
@ -253,6 +266,22 @@ int ren_font_group_get_tab_size(RenFont **fonts) {
|
||||||
float ren_font_group_get_size(RenFont **fonts) {
|
float ren_font_group_get_size(RenFont **fonts) {
|
||||||
return fonts[0]->size;
|
return fonts[0]->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ren_font_group_set_size(RenFont **fonts, float size) {
|
||||||
|
const int surface_scale = renwin_surface_scale(&window_renderer);
|
||||||
|
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
|
||||||
|
font_clear_glyph_cache(fonts[i]);
|
||||||
|
FT_Face face = fonts[i]->face;
|
||||||
|
FT_Set_Pixel_Sizes(face, 0, (int)(size*surface_scale));
|
||||||
|
fonts[i]->size = size;
|
||||||
|
fonts[i]->height = (short)((face->height / (float)face->units_per_EM) * size);
|
||||||
|
fonts[i]->baseline = (short)((face->ascender / (float)face->units_per_EM) * size);
|
||||||
|
FT_Load_Char(face, ' ', font_set_load_options(fonts[i]));
|
||||||
|
fonts[i]->space_advance = face->glyph->advance.x / 64.0f;
|
||||||
|
fonts[i]->tab_advance = fonts[i]->space_advance * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ren_font_group_get_height(RenFont **fonts) {
|
int ren_font_group_get_height(RenFont **fonts) {
|
||||||
return fonts[0]->height;
|
return fonts[0]->height;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,13 @@ typedef struct { uint8_t b, g, r, a; } RenColor;
|
||||||
typedef struct { int x, y, width, height; } RenRect;
|
typedef struct { int x, y, width, height; } RenRect;
|
||||||
|
|
||||||
RenFont* ren_font_load(const char *filename, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style);
|
RenFont* ren_font_load(const char *filename, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style);
|
||||||
RenFont* ren_font_copy(RenFont* font, float size);
|
RenFont* ren_font_copy(RenFont* font, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, int style);
|
||||||
|
const char* ren_font_get_path(RenFont *font);
|
||||||
void ren_font_free(RenFont *font);
|
void ren_font_free(RenFont *font);
|
||||||
int ren_font_group_get_tab_size(RenFont **font);
|
int ren_font_group_get_tab_size(RenFont **font);
|
||||||
int ren_font_group_get_height(RenFont **font);
|
int ren_font_group_get_height(RenFont **font);
|
||||||
float ren_font_group_get_size(RenFont **font);
|
float ren_font_group_get_size(RenFont **font);
|
||||||
|
void ren_font_group_set_size(RenFont **font, float size);
|
||||||
void ren_font_group_set_tab_size(RenFont **font, int n);
|
void ren_font_group_set_tab_size(RenFont **font, int n);
|
||||||
float ren_font_group_get_width(RenFont **font, const char *text);
|
float ren_font_group_get_width(RenFont **font, const char *text);
|
||||||
float ren_draw_text(RenFont **font, const char *text, float x, int y, RenColor color);
|
float ren_draw_text(RenFont **font, const char *text, float x, int y, RenColor color);
|
||||||
|
|
Loading…
Reference in New Issue