From 414899149070e5862aa4f8088d8882a084f7f1ec Mon Sep 17 00:00:00 2001 From: Natural-Harmonia-Gropius <50797982+Natural-Harmonia-Gropius@users.noreply.github.com> Date: Mon, 15 Aug 2022 16:47:30 +0800 Subject: [PATCH] better text_width_estimate --- uosc.lua | 42 +++++++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/uosc.lua b/uosc.lua index 64c36c1..7cf417e 100644 --- a/uosc.lua +++ b/uosc.lua @@ -560,8 +560,36 @@ function get_point_to_rectangle_proximity(point, rect) return math.sqrt(dx*dx + dy*dy); end -function text_width_estimate(letters, font_size) - return letters and letters * font_size * options.font_height_to_letter_width_ratio or 0 +function text_width_estimate(text, font_size) + if not text or text == "" then return 0 end + + local text_width = 0 + local char_width = font_size + local byte_len = #text + local byte_end = 0 + + for byte_start = 1, byte_len do + if byte_start > byte_end then + local char_width = char_width + local char_byte = string.byte(text, byte_start) + + local byte_count = 1; + if char_byte < 192 then byte_count = 1 + elseif char_byte < 224 then byte_count = 2 + elseif char_byte < 240 then byte_count = 3 + elseif char_byte < 248 then byte_count = 4 + elseif char_byte < 252 then byte_count = 5 + elseif char_byte < 254 then byte_count = 6 + end + + if byte_count ~= 1 then char_width = char_width * 2 end + + text_width = text_width + char_width + byte_end = byte_start + byte_count - 1 + end + end + + return text_width * options.font_height_to_letter_width_ratio end function opacity_to_alpha(opacity) @@ -943,8 +971,8 @@ function Menu:open(items, open_item, opts) local estimated_max_width = 0 for _, item in ipairs(this.items) do local spacings_in_item = item.hint and 3 or 2 - local estimated_width = (item.title and text_width_estimate(item.title:len(), this.font_size) or 0) - + (item.hint and text_width_estimate(item.hint:len(), this.font_size_hint) or 0) + local estimated_width = text_width_estimate(item.title, this.font_size) + + text_width_estimate(item.hint, this.font_size_hint) + (this.item_content_spacing * spacings_in_item) if estimated_width > estimated_max_width then estimated_max_width = estimated_width @@ -952,8 +980,8 @@ function Menu:open(items, open_item, opts) end -- Also check menu title - local menu_title_length = this.title and this.title:len() or 0 - local estimated_menu_title_width = text_width_estimate(menu_title_length, this.font_size) + local menu_title = this.title and this.title or "" + local estimated_menu_title_width = text_width_estimate(menu_title, this.font_size) if estimated_menu_title_width > estimated_max_width then estimated_max_width = estimated_menu_title_width end @@ -2102,7 +2130,7 @@ function render_menu(this) local has_submenu = item.items ~= nil local hint_width = 0 if item.hint then - hint_width = text_width_estimate(item.hint:len(), this.font_size_hint) + hint_width = text_width_estimate(item.hint, this.font_size_hint) elseif has_submenu then hint_width = icon_size end