From: Ferdinand Bachmann Date: Tue, 29 Oct 2024 20:59:57 +0000 (+0100) Subject: label-freetype: implement bold font handling X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=42430bcdf895bb9c5f9d0d123282b78500e8c23b;p=thirdparty%2Fplymouth.git label-freetype: implement bold font handling Bold monospace fonts are prominently used in the console output printed by systemd. Without them, the output looks incorrect compared to pango. This still is far from a complete implementation of rich text, but brings label-freetype much closer to what label-pango does for the default theme. This commit introduces a glyph_face variable in load_glyphs() that holds the correct face for the current glyph (label->face or label->bold_face). This face is then passed on to load_glyph() and finish_measuring_line() to ensure correct font measurements. --- diff --git a/src/plugins/controls/label-freetype/plugin.c b/src/plugins/controls/label-freetype/plugin.c index 8064519a..2594c800 100644 --- a/src/plugins/controls/label-freetype/plugin.c +++ b/src/plugins/controls/label-freetype/plugin.c @@ -42,7 +42,9 @@ /* This is used if fontconfig (fc-match) is not available, like in the initrd. */ #define FONT_FALLBACK "/usr/share/fonts/Plymouth.ttf" +#define BOLD_FONT_FALLBACK "/usr/share/fonts/Plymouth-bold.ttf" #define MONOSPACE_FONT_FALLBACK "/usr/share/fonts/Plymouth-monospace.ttf" +#define MONOSPACE_BOLD_FONT_FALLBACK "/usr/share/fonts/Plymouth-monospace-bold.ttf" /* This is a little sketchy... It relies on implementation details of the compiler * but it makes dealing with the fixed point math freetype uses much more pleasant, @@ -85,6 +87,7 @@ struct _ply_label_plugin_control FT_Library library; FT_Face face; + FT_Face bold_face; char *font; char *text; @@ -141,6 +144,26 @@ find_default_font_path (void) return fc_match_out; } +static const char * +find_default_bold_font_path (void) +{ + FILE *fp; + static char fc_match_out[PATH_MAX]; + + fp = popen ("/usr/bin/fc-match -f %{file} :weight=bold", "r"); + if (!fp) + return BOLD_FONT_FALLBACK; + + fgets (fc_match_out, sizeof(fc_match_out), fp); + + pclose (fp); + + if (strcmp (fc_match_out, "") == 0) + return BOLD_FONT_FALLBACK; + + return fc_match_out; +} + static const char * find_default_monospace_font_path (void) { @@ -161,6 +184,26 @@ find_default_monospace_font_path (void) return fc_match_out; } +static const char * +find_default_monospace_bold_font_path (void) +{ + FILE *fp; + static char fc_match_out[PATH_MAX]; + + fp = popen ("/usr/bin/fc-match -f %{file} monospace:weight=bold", "r"); + if (!fp) + return MONOSPACE_BOLD_FONT_FALLBACK; + + fgets (fc_match_out, sizeof(fc_match_out), fp); + + pclose (fp); + + if (strcmp (fc_match_out, "") == 0) + return MONOSPACE_BOLD_FONT_FALLBACK; + + return fc_match_out; +} + static ply_label_plugin_control_t * create_control (void) { @@ -213,6 +256,7 @@ destroy_control (ply_label_plugin_control_t *label) free (label->text); free (label->font); FT_Done_Face (label->face); + FT_Done_Face (label->bold_face); FT_Done_FreeType (label->library); free (label); @@ -235,14 +279,15 @@ get_height_of_control (ply_label_plugin_control_t *label) static FT_GlyphSlot load_glyph (ply_label_plugin_control_t *label, ply_load_glyph_action_t action, - const char *input_text) + const char *input_text, + FT_Face face) { FT_Error error; size_t character_size; wchar_t character; FT_Int32 load_flags = FT_LOAD_TARGET_LIGHT; - if (label->face == NULL) + if (face == NULL) return NULL; character_size = mbrtowc (&character, input_text, PLY_UTF8_CHARACTER_SIZE_MAX, NULL); @@ -255,12 +300,12 @@ load_glyph (ply_label_plugin_control_t *label, if (action == PLY_LOAD_GLYPH_ACTION_RENDER) load_flags |= FT_LOAD_RENDER; - error = FT_Load_Char (label->face, (FT_ULong) character, load_flags); + error = FT_Load_Char (face, (FT_ULong) character, load_flags); if (error) return NULL; - return label->face->glyph; + return face->glyph; } static void @@ -424,16 +469,17 @@ static void finish_measuring_line (ply_label_plugin_control_t *label, ply_freetype_unit_t *glyph_x, ply_freetype_unit_t *glyph_y, - ply_rectangle_t *dimensions) + ply_rectangle_t *dimensions, + FT_Face face) { ply_freetype_unit_t line_height; ply_rectangle_t *entry; - if (label->face == NULL) + if (face == NULL) return; - line_height.as_integer = label->face->size->metrics.ascender + -label->face->size->metrics.descender; + line_height.as_integer = face->size->metrics.ascender + -face->size->metrics.descender; dimensions->x = label->area.x * label->scale_factor; @@ -485,6 +531,7 @@ load_glyphs (ply_label_plugin_control_t *label, ply_pixel_buffer_t *pixel_buffer) { FT_GlyphSlot glyph = NULL; + FT_Face glyph_face = label->face; ply_rich_text_iterator_t rich_text_iterator; ply_utf8_string_iterator_t utf8_string_iterator; uint32_t *target = NULL; @@ -570,6 +617,12 @@ load_glyphs (ply_label_plugin_control_t *label, current_character = rich_text_character->bytes; + if (label->bold_face != NULL && rich_text_character->style.bold_enabled) { + glyph_face = label->bold_face; + } else { + glyph_face = label->face; + } + if (action == PLY_LOAD_GLYPH_ACTION_RENDER) { look_up_rgb_color_from_terminal_color (label, rich_text_character->style.foreground_color, @@ -587,26 +640,27 @@ load_glyphs (ply_label_plugin_control_t *label, break; } - glyph = load_glyph (label, action, current_character); + + glyph = load_glyph (label, action, current_character, glyph_face); if (glyph == NULL) continue; if (is_first_character) { /* Move pen to the first character's base line */ - glyph_y.as_integer += label->face->size->metrics.ascender; + glyph_y.as_integer += glyph_face->size->metrics.ascender; } if (*current_character == '\n') { if (action == PLY_LOAD_GLYPH_ACTION_MEASURE) - finish_measuring_line (label, &glyph_x, &glyph_y, line_dimensions); + finish_measuring_line (label, &glyph_x, &glyph_y, line_dimensions, glyph_face); else line_dimensions = dimensions_of_lines[line_number++]; glyph_x.as_pixels_unit.pixels = line_dimensions->x; glyph_y.as_pixels_unit.pixels = line_dimensions->y; - glyph_y.as_integer += label->face->size->metrics.ascender; + glyph_y.as_integer += glyph_face->size->metrics.ascender; continue; } @@ -635,7 +689,7 @@ load_glyphs (ply_label_plugin_control_t *label, if (!is_first_character) { FT_Vector kerning_space; - error = FT_Get_Kerning (label->face, previous_glyph_index, glyph->glyph_index, FT_KERNING_DEFAULT, &kerning_space); + error = FT_Get_Kerning (glyph_face, previous_glyph_index, glyph->glyph_index, FT_KERNING_DEFAULT, &kerning_space); if (error == 0) glyph_x.as_integer += kerning_space.x; @@ -650,7 +704,7 @@ load_glyphs (ply_label_plugin_control_t *label, if (!is_first_character) { char *text = NULL; - finish_measuring_line (label, &glyph_x, &glyph_y, line_dimensions); + finish_measuring_line (label, &glyph_x, &glyph_y, line_dimensions, glyph_face); if (ply_is_tracing ()) { if (label->rich_text != NULL) @@ -783,29 +837,51 @@ set_font_for_control (ply_label_plugin_control_t *label, if (strstr (font, "Mono") || strstr (font, "mono")) { if (!label->is_monospaced) { FT_Done_Face (label->face); + FT_Done_Face (label->bold_face); + label->face = NULL; + label->bold_face = NULL; font_path = find_default_monospace_font_path (); if (font_path != NULL) error = FT_New_Face (label->library, font_path, 0, &label->face); + font_path = find_default_monospace_bold_font_path (); + + /* Ignore errors when loading bold face to allow + * fallback to regular face */ + if (font_path != NULL) + FT_New_Face (label->library, font_path, 0, &label->bold_face); + label->is_monospaced = true; } } else { if (label->is_monospaced || label->face == NULL) { FT_Done_Face (label->face); + FT_Done_Face (label->bold_face); + label->face = NULL; + label->bold_face = NULL; font_path = find_default_font_path (); if (font_path != NULL) error = FT_New_Face (label->library, font_path, 0, &label->face); + font_path = find_default_bold_font_path (); + + /* Ignore errors when loading bold face to allow + * fallback to regular face */ + if (font_path != NULL) + FT_New_Face (label->library, font_path, 0, &label->bold_face); + label->is_monospaced = false; } } if (error != 0) { FT_Done_Face (label->face); + FT_Done_Face (label->bold_face); label->face = NULL; + label->bold_face = NULL; ply_trace ("Could not load font, error %d", error); return; @@ -834,6 +910,13 @@ set_font_for_control (ply_label_plugin_control_t *label, else FT_Set_Char_Size (label->face, size.as_integer, 0, dpi * label->scale_factor, 0); + if (label->bold_face != NULL) { + if (size_in_pixels) + FT_Set_Pixel_Sizes (label->bold_face, 0, size.as_pixels_unit.pixels * label->scale_factor); + else + FT_Set_Char_Size (label->bold_face, size.as_integer, 0, dpi * label->scale_factor, 0); + } + /* Ignore errors, to keep the current size. */ trigger_redraw (label, true); }