From 802147e255bf44b6266b4bb8787b6dafe440abc0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 1 Apr 2021 22:18:13 +0530 Subject: [PATCH] More robust ellipsis width calculation --- kitty/freetype_render_ui_text.c | 56 ++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/kitty/freetype_render_ui_text.c b/kitty/freetype_render_ui_text.c index b90254b8f..938ed6104 100644 --- a/kitty/freetype_render_ui_text.c +++ b/kitty/freetype_render_ui_text.c @@ -267,6 +267,40 @@ detect_edges(ProcessedBitmap *ans) { #undef check } +static Face* +find_fallback_font_for(RenderCtx *ctx, char_type codep, char_type next_codep) { + if (glyph_id_for_codepoint(&main_face, codep) > 0) return &main_face; + for (size_t i = 0; i < main_face.count; i++) { + if (glyph_id_for_codepoint(main_face.fallbacks + i, codep) > 0) return main_face.fallbacks + i; + } + FontConfigFace q; + bool prefer_color = false; + char_type string[3] = {codep, next_codep, 0}; + if (wcswidth_string(string) >= 2 && is_emoji_presentation_base(codep)) prefer_color = true; + if (!fallback_font(codep, main_face_family.name, main_face_family.bold, main_face_family.italic, prefer_color, &q)) return NULL; + ensure_space_for(&main_face, fallbacks, Face, main_face.count + 1, capacity, 8, true); + Face *ans = main_face.fallbacks + main_face.count; + bool ok = load_font(&q, ans); + free(q.path); + if (!ok) return NULL; + main_face.count++; + return ans; +} + + +static unsigned +calculate_ellipsis_width(RenderCtx *ctx) { + Face *face = find_fallback_font_for(ctx, ELLIPSIS, 0); + if (!face) return 0; + set_pixel_size(ctx, face, main_face.pixel_size, false); + int glyph_index = FT_Get_Char_Index(face->freetype, ELLIPSIS); + if (!glyph_index) return 0; + int error = FT_Load_Glyph(face->freetype, glyph_index, get_load_flags(face->hinting, face->hintstyle, FT_LOAD_DEFAULT)); + if (error) return 0; + return (unsigned)ceilf((float)face->freetype->glyph->metrics.horiAdvance / 64.f); +} + + static bool render_run(RenderCtx *ctx, RenderState *rs) { hb_buffer_guess_segment_properties(hb_buffer); @@ -295,7 +329,7 @@ render_run(RenderCtx *ctx, RenderState *rs) { pos += delta; } if (limit < len) { - unsigned ellipsis_width = width_for_char(&main_face, 'm'); + unsigned ellipsis_width = calculate_ellipsis_width(ctx); while (pos + ellipsis_width >= rs->output_width && limit) { limit--; pos -= (float)positions[limit].x_offset / 64.0f + (float)positions[limit].x_advance / 64.0f; @@ -377,26 +411,6 @@ render_run(RenderCtx *ctx, RenderState *rs) { return true; } -static Face* -find_fallback_font_for(RenderCtx *ctx, char_type codep, char_type next_codep) { - if (glyph_id_for_codepoint(&main_face, codep) > 0) return &main_face; - for (size_t i = 0; i < main_face.count; i++) { - if (glyph_id_for_codepoint(main_face.fallbacks + i, codep) > 0) return main_face.fallbacks + i; - } - FontConfigFace q; - bool prefer_color = false; - char_type string[3] = {codep, next_codep, 0}; - if (wcswidth_string(string) >= 2 && is_emoji_presentation_base(codep)) prefer_color = true; - if (!fallback_font(codep, main_face_family.name, main_face_family.bold, main_face_family.italic, prefer_color, &q)) return NULL; - ensure_space_for(&main_face, fallbacks, Face, main_face.count + 1, capacity, 8, true); - Face *ans = main_face.fallbacks + main_face.count; - bool ok = load_font(&q, ans); - free(q.path); - if (!ok) return NULL; - main_face.count++; - return ans; -} - static bool process_codepoint(RenderCtx *ctx, RenderState *rs, char_type codep, char_type next_codep) { bool add_to_current_buffer = false;