diff --git a/.gitignore b/.gitignore index 161484f0..b1d18a64 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ lhelper/ submodules/ subprojects/*/ /appimage* +.vscode .cache .ccls-cache .lite-debug.log diff --git a/data/core/init.lua b/data/core/init.lua index 07610a3d..f67e7cad 100644 --- a/data/core/init.lua +++ b/data/core/init.lua @@ -497,7 +497,7 @@ local style = require "core.style" -- -- the function to load the font accept a 3rd optional argument like: -- --- {antialiasing="grayscale", hinting="full", bold=true, italic=true, underline=true} +-- {antialiasing="grayscale", hinting="full", bold=true, italic=true, underline=true, smoothing=true, strikethrough=true} -- -- possible values are: -- antialiasing: grayscale, subpixel @@ -505,6 +505,8 @@ local style = require "core.style" -- bold: true, false -- italic: true, false -- underline: true, false +-- smoothing: true, false +-- strikethrough: true, false ------------------------------ Plugins ---------------------------------------- diff --git a/docs/api/renderer.lua b/docs/api/renderer.lua index 56fe4262..fe42ed65 100644 --- a/docs/api/renderer.lua +++ b/docs/api/renderer.lua @@ -24,6 +24,8 @@ renderer.color = {} -- @field public bold boolean -- @field public italic boolean -- @field public underline boolean +-- @field public smoothing boolean +-- @field public strikethrough boolean renderer.fontoptions = {} --- diff --git a/src/api/renderer.c b/src/api/renderer.c index c23e38ea..f46fb559 100644 --- a/src/api/renderer.c +++ b/src/api/renderer.c @@ -58,6 +58,13 @@ static int font_get_options( lua_getfield(L, 3, "underline"); if (lua_toboolean(L, -1)) style_local |= FONT_STYLE_UNDERLINE; + lua_getfield(L, 3, "smoothing"); + if (lua_toboolean(L, -1)) + style_local |= FONT_STYLE_SMOOTH; + lua_getfield(L, 3, "strikethrough"); + if (lua_toboolean(L, -1)) + style_local |= FONT_STYLE_STRIKETHROUGH; + lua_pop(L, 5); if (style_local != 0) diff --git a/src/renderer.c b/src/renderer.c index 81888234..89bcdd50 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -50,6 +50,7 @@ typedef struct RenFont { ERenFontAntialiasing antialiasing; ERenFontHinting hinting; unsigned char style; + unsigned short underline_thickness; char path[1]; } RenFont; @@ -100,6 +101,8 @@ static int font_set_render_options(RenFont* font) { static int font_set_style(FT_Outline* outline, int x_translation, unsigned char style) { FT_Outline_Translate(outline, x_translation, 0 ); + if (style & FONT_STYLE_SMOOTH) + FT_Outline_Embolden(outline, 1 << 5); if (style & FONT_STYLE_BOLD) FT_Outline_EmboldenXY(outline, 1 << 5, 0); if (style & FONT_STYLE_ITALIC) { @@ -220,6 +223,10 @@ RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antial font->hinting = hinting; font->style = style; + if(FT_IS_SCALABLE(face)) + font->underline_thickness = (unsigned short)((face->underline_thickness / (float)face->units_per_EM) * font->size); + if(!font->underline_thickness) font->underline_thickness = ceil((double) font->height / 14.0); + if (FT_Load_Char(face, ' ', font_set_load_options(font))) goto failure; font->space_advance = face->glyph->advance.x / 64.0f; @@ -314,6 +321,11 @@ float ren_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor uint8_t* destination_pixels = surface->pixels; int clip_end_x = clip.x + clip.width, clip_end_y = clip.y + clip.height; + RenFont* last; + float last_pen_x = x; + bool underline = fonts[0]->style & FONT_STYLE_UNDERLINE; + bool strikethrough = fonts[0]->style & FONT_STYLE_STRIKETHROUGH; + while (text < end) { unsigned int codepoint, r, g, b; text = utf8_to_codepoint(text, &codepoint); @@ -369,10 +381,22 @@ float ren_draw_text(RenFont **fonts, const char *text, float x, int y, RenColor } } } - pen_x += metric->xadvance ? metric->xadvance : font->space_advance; + + float adv = metric->xadvance ? metric->xadvance : font->space_advance; + + if(!last) last = font; + else if(font != last || text == end) { + float local_pen_x = text == end ? pen_x + adv : pen_x; + if (underline) + ren_draw_rect((RenRect){last_pen_x, y / surface_scale + last->height - 1, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + if (strikethrough) + ren_draw_rect((RenRect){last_pen_x, y / surface_scale + last->height / 2, (local_pen_x - last_pen_x) / surface_scale, last->underline_thickness * surface_scale}, color); + last = font; + last_pen_x = pen_x; + } + + pen_x += adv; } - if (fonts[0]->style & FONT_STYLE_UNDERLINE) - ren_draw_rect((RenRect){ x, y / surface_scale + ren_font_group_get_height(fonts) - 1, (pen_x - x) / surface_scale, 1 }, color); return pen_x / surface_scale; } @@ -464,4 +488,3 @@ void ren_get_size(int *x, int *y) { *x = surface->w / scale; *y = surface->h / scale; } - diff --git a/src/renderer.h b/src/renderer.h index 57de549d..3e631ce4 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -15,7 +15,7 @@ typedef struct RenFont RenFont; typedef enum { FONT_HINTING_NONE, FONT_HINTING_SLIGHT, FONT_HINTING_FULL } ERenFontHinting; typedef enum { FONT_ANTIALIASING_NONE, FONT_ANTIALIASING_GRAYSCALE, FONT_ANTIALIASING_SUBPIXEL } ERenFontAntialiasing; -typedef enum { FONT_STYLE_BOLD = 1, FONT_STYLE_ITALIC = 2, FONT_STYLE_UNDERLINE = 4 } ERenFontStyle; +typedef enum { FONT_STYLE_BOLD = 1, FONT_STYLE_ITALIC = 2, FONT_STYLE_UNDERLINE = 4, FONT_STYLE_SMOOTH = 8, FONT_STYLE_STRIKETHROUGH = 16 } ERenFontStyle; typedef struct { uint8_t b, g, r, a; } RenColor; typedef struct { int x, y, width, height; } RenRect;