TextBoxWidget: allow showing bits of text in bold

Allow for embedding "tags" (invalid Unicode codepoints)
in the text string to trigger some text formatting:
for now only bolding some parts of text is possible.

Use it with fulltext search "all results" to highlight the
matched word (instead of the previously used brackets).
This commit is contained in:
poire-z
2024-01-15 16:30:14 +01:00
parent 487e5f667a
commit 43d36b2ea9
4 changed files with 71 additions and 8 deletions

View File

@@ -110,6 +110,17 @@ local TextBoxWidget = InputContainer:extend{
-- for internal use
for_measurement_only = nil, -- When the widget is a one-off used to compute text height
-- Some Poor Text Formatting (PTF, not not to be confused with Richer RTF :)) can be done
-- by embedding some chars in self.text (these codepoints are not part of Unicode, so
-- hopefully not present naturally in any provided self.text).
PTF_HEADER = "\u{FFF1}", -- should be put at start of 'text' to indicate we may find other PTF_ chars
PTF_BOLD_START = "\u{FFF2}", -- start a sequence of bold chars
PTF_BOLD_END = "\u{FFF3}", -- end a sequence of bold chars
_ptf_char_is_bold = nil,
-- This uses fake/synthetic bold, making each glyph bolder without modifying advance.
-- Some other possible formatting we could implement is different alignment (center,
-- right) of some lines in the provided text.
}
function TextBoxWidget:init()
@@ -154,6 +165,41 @@ function TextBoxWidget:init()
self.text_height = self.lines_per_page * self.line_height_px
end
-- Check for Poor Text Formatting
if not self.charlist and self.text and type(self.text) == "string"
and self.text:sub(1, #TextBoxWidget.PTF_HEADER) == TextBoxWidget.PTF_HEADER then
-- Support for very simple text styling (bold only for now)
self._ptf_char_is_bold = {}
-- Alas, we can't let any of our flag characters be fed to xtext (even with ASCII control
-- chars, it would give them a width, which would result at best in spurious added spacing).
-- So, split text into a table of chars, filter our flags out keeping track of where they
-- start and end bold, and rebuild self.text without them.
local charlist = util.splitToChars(self.text)
table.remove(charlist, 1)
local is_bold = false
local len = #charlist
local i = 1
while i <= len do
local ch = charlist[i]
if ch == TextBoxWidget.PTF_BOLD_START then
is_bold = true
table.remove(charlist, i)
len = len - 1
elseif ch == TextBoxWidget.PTF_BOLD_END then
is_bold = false
table.remove(charlist, i)
len = len - 1
else
if is_bold then
self._ptf_char_is_bold[i] = true
end
i = i + 1
end
end
self.text = table.concat(charlist, "")
charlist = nil -- luacheck: no unused
end
self:_computeTextDimensions()
self:_updateLayout()
if self.editable then
@@ -822,7 +868,8 @@ function TextBoxWidget:_renderText(start_row_idx, end_row_idx)
for _, xglyph in ipairs(line.xglyphs) do
if not xglyph.no_drawing then
local face = self.face.getFallbackFont(xglyph.font_num) -- callback (not a method)
local glyph = RenderText:getGlyphByIndex(face, xglyph.glyph, self.bold)
local bolder = self._ptf_char_is_bold and self._ptf_char_is_bold[xglyph.text_index] or false
local glyph = RenderText:getGlyphByIndex(face, xglyph.glyph, self.bold, bolder)
local color = self.fgcolor
if self._alt_color_for_rtl then
color = xglyph.is_rtl and Blitbuffer.COLOR_DARK_GRAY or Blitbuffer.COLOR_BLACK