diff --git a/descriptions/ab+/en_us.lua b/descriptions/ab+/en_us.lua index e2dff692..1195b2c4 100644 --- a/descriptions/ab+/en_us.lua +++ b/descriptions/ab+/en_us.lua @@ -16,7 +16,7 @@ EID.descriptions[languageCode].custom = {} -- table for custom entity descriptio EID.descriptions[languageCode].languageName = "English" -- Fonts to be used with this language pack -EID.descriptions[languageCode].fonts = {{name="default", lineHeight=11}, {name="inverted", lineHeight=11}, {name="borderless", lineHeight=11}} +EID.descriptions[languageCode].fonts = {{name="default", lineHeight=11, textboxWidth = 115}, {name="inverted", lineHeight=11, textboxWidth = 115}, {name="borderless", lineHeight=11, textboxWidth = 115}} ---------- Collectibles ---------- EID.descriptions[languageCode].collectibles={ diff --git a/descriptions/ab+/ko_kr.lua b/descriptions/ab+/ko_kr.lua index e56df226..bfa71758 100644 --- a/descriptions/ab+/ko_kr.lua +++ b/descriptions/ab+/ko_kr.lua @@ -29,7 +29,7 @@ EID.descriptions[languageCode].languageName = "Korean" korean_galmoori9, korean_galmoori11 is added for community request. ]] -EID.descriptions[languageCode].fonts = {{name="korean_hcrdotum", lineHeight=11}, {name="korean_lanapixel", lineHeight=12}, {name="korean_soyakkoma", lineHeight=13}, {name="korean_soyakkoma_borderless", lineHeight=13}, {name="korean_soyakkoma_inverted", lineHeight=13}, {name="korean_soyanon", lineHeight=12}, {name="korean_galmoori9", lineHeight=12}, {name="korean_galmoori11", lineHeight=14}} +EID.descriptions[languageCode].fonts = {{name="korean_hcrdotum", lineHeight=11, textboxWidth = 115}, {name="korean_lanapixel", lineHeight=12, textboxWidth = 115}, {name="korean_soyakkoma", lineHeight=13, textboxWidth = 115}, {name="korean_soyakkoma_borderless", lineHeight=13, textboxWidth = 115}, {name="korean_soyakkoma_inverted", lineHeight=13, textboxWidth = 115}, {name="korean_soyanon", lineHeight=12, textboxWidth = 115}, {name="korean_galmoori9", lineHeight=12, textboxWidth = 115}, {name="korean_galmoori11", lineHeight=14, textboxWidth = 115}} ---------- Collectibles ---------- EID.descriptions[languageCode].collectibles={ diff --git a/descriptions/ab+/zh_cn.lua b/descriptions/ab+/zh_cn.lua index 778ef20b..97072791 100644 --- a/descriptions/ab+/zh_cn.lua +++ b/descriptions/ab+/zh_cn.lua @@ -16,7 +16,7 @@ EID.descriptions[languageCode].custom = {} -- table for custom entity descriptio EID.descriptions[languageCode].languageName = "Chinese" -- Fonts to be used with this languagepack -EID.descriptions[languageCode].fonts = {{name = "default_cn", lineHeight = 14}} +EID.descriptions[languageCode].fonts = {{name = "default_cn", lineHeight = 14, textboxWidth = 150}} ---------- Collectibles ---------- EID.descriptions[languageCode].collectibles={ diff --git a/eid_api.lua b/eid_api.lua index 9c0ea8dd..12c05697 100644 --- a/eid_api.lua +++ b/eid_api.lua @@ -530,11 +530,7 @@ end -- Generates a string with the defined pixel-length using a custom 1px wide character -- This will only work for this specific custom font function EID:generatePlaceholderString(length) - local placeholder = "" - for i = 1, length do - placeholder = placeholder .. "¤" - end - return placeholder + return string.rep("¤", length) end -- Returns the inlineIcon object of a given Iconstring @@ -720,29 +716,103 @@ end -- Fits a given string to a specific width -- returns the string as a table of lines -function EID:fitTextToWidth(str, textboxWidth) +function EID:fitTextToWidth(str, textboxWidth, breakUtf8Chars) local formatedLines = {} local curLength = 0 - local text = "" - for word in string.gmatch(str, "([^%s]+)") do - local colorFiltered = EID:filterColorMarkup(word, EID:getTextColor()) - local filteredWord = "" - for _, filtered in ipairs(colorFiltered) do - filteredWord = filteredWord .. filtered[1] - end - local strFiltered, spriteTable = EID:filterIconMarkup(filteredWord, 0, 0) - local wordLength = EID:getStrWidth(strFiltered) + local text = {} - if curLength + wordLength <= textboxWidth or curLength < 12 then - text = text .. word .. " " - curLength = curLength + wordLength - else - table.insert(formatedLines, text) - text = word .. " " - curLength = wordLength + local cursor = 1 + local word_begin_index = 1 + + local byte = string.byte -- for speed up + local sub = string.sub + local byte_space = string.byte(' ') + + while cursor <= #str do + -- ascii word: 0x0xxxxxxx + -- utf8 word (sequence): 0x11xxxxxx 0x10xxxxxx 0x10xxxxxx ... 0x10xxxxxx + -- see https://en.wikipedia.org/wiki/UTF-8 + -- we can only break after space, or before 0x11xxxxxx + local can_break_after_cursor = false + local cur, next = byte(str,cursor), byte(str,cursor+1) + if + -- cond#1: we can break at the end of string + cursor == #str or + -- cond#2: we can break after space + cur == byte_space or + -- handle utf8 characters + (breakUtf8Chars and( + -- cond#3: we can break if the next character is 0x11xxxxxx + ((next & 0xC0) == 0xC0) or + -- cond#4: we can also break if the current is 0x10xxxxxx while the next is ascii but not space + (((cur & 0xC0) == 0x80) and (next~= byte_space and (next & 0x80) == 0x00)) + )) + then + --[[ + -------------------ascii only--------------- + word will be separated by spaces. + wordA |wordB |wordC |^%@&Q%#^&#@!! |aksldj + ↑ + cond#2 + we may break after every space. + spaces | | | | | |woops + ↑ + cond#2 + -------------------UTF8 only---------------- + word is 0x11xxxxxx followed by several 0x10xxxxxx until the next 0x11xxxxxx (not included) + 你|好|,|世|界|!|↑|↑|↑|↑ + ↑ + cond#3 + byte data of a word: + [0x11xxxxxx,0x10xxxxxx,0x10xxxxxx, (next is 0x11xxxxxx, cond#3)] + --------------------ascii->utf8------------ + utf8 word must start with 0x11xxxxxx, so cond#3 split before it. + word|世|界 + | ↑ + ↑ cond#3 + cond#3 + + world |means |世|界 + ↑ + cond#2 + -------------------utf8->ascii-------------- + 世|界|是|world + | ↑ + ↑ cond#4 + cond#3 + 世|界|是 |world + | ↑ + ↑ cond#2 + cond#3 + ]] + + -- we can break after str[cursor] + local word = sub(str, word_begin_index, cursor) + + local colorFiltered = EID:filterColorMarkup(word, EID:getTextColor()) + local filteredWord = {} + for _, filtered in ipairs(colorFiltered) do + table.insert(filteredWord, filtered[1]) + end + local strFiltered, spriteTable = EID:filterIconMarkup(table.concat(filteredWord), 0, 0) + local wordLength = EID:getStrWidth(strFiltered) + + if curLength + wordLength <= textboxWidth or curLength < 12 then + table.insert(text, word) + curLength = curLength + wordLength + else + table.insert(formatedLines, table.concat(text)) + text = { word } + curLength = wordLength + end + + -- next word starts here + word_begin_index = cursor + 1 end + cursor = cursor + 1 end - table.insert(formatedLines, text) + + table.insert(formatedLines, table.concat(text)) return formatedLines end @@ -1041,6 +1111,7 @@ function EID:fixDefinedFont() end EID.Config["FontType"] = EID.descriptions[curLang].fonts[1].name EID.lineHeight = EID.descriptions[curLang].fonts[1].lineHeight + EID.Config["TextboxWidth"] = EID.descriptions[curLang].fonts[1].textboxWidth return true end diff --git a/eid_data.lua b/eid_data.lua index 9e8e699e..2cc6dc9e 100644 --- a/eid_data.lua +++ b/eid_data.lua @@ -498,3 +498,7 @@ EID.GoldenTrinketData = { -- Lil Clot, Swallowed M80, The Twins (default text), Cricket Leg (17%, 1 in 6), Apollyon's Best Friend, Broken Glasses [176] = 1, [178] = {t={50},mult=2}, [183] = 0, [185] = 17, [186] = 1, [187] = {t={50,50}, mult=2}, } + +EID.BreakUtf8CharsLanguage = { + ['zh_cn'] = true +} diff --git a/main.lua b/main.lua index 8733aafb..2cf00409 100644 --- a/main.lua +++ b/main.lua @@ -517,7 +517,7 @@ function EID:printBulletPoints(description, renderPos) local textScale = Vector(EID.Scale, EID.Scale) description = EID:replaceShortMarkupStrings(description) for line in string.gmatch(description, "([^#]+)") do - local formatedLines = EID:fitTextToWidth(line, textboxWidth) + local formatedLines = EID:fitTextToWidth(line, textboxWidth, EID.BreakUtf8CharsLanguage[EID.Config["Language"]]) local textColor = EID:getTextColor() for i, lineToPrint in ipairs(formatedLines) do -- render bulletpoint diff --git a/mod_config_menu.lua b/mod_config_menu.lua index 26204ef4..695fdd56 100644 --- a/mod_config_menu.lua +++ b/mod_config_menu.lua @@ -1014,6 +1014,7 @@ if MCMLoaded then OnChange = function(currentNum) EID.Config["FontType"] = fontNames[currentNum] EID.lineHeight = fonts[currentNum].lineHeight + EID.Config["TextboxWidth"] = fonts[currentNum].textboxWidth EID:fixDefinedFont() local fontFile = EID.Config["FontType"] or "default" EID:loadFont(EID.modPath .. "resources/font/eid_"..fontFile..".fnt")