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).
reviewable/pr11385/r1
poire-z 3 months ago
parent 487e5f667a
commit 43d36b2ea9

@ -7,6 +7,7 @@ local InputDialog = require("ui/widget/inputdialog")
local Menu = require("ui/widget/menu")
local Notification = require("ui/widget/notification")
local SpinWidget = require("ui/widget/spinwidget")
local TextBoxWidget = require("ui/widget/textboxwidget")
local UIManager = require("ui/uimanager")
local Utf8Proc = require("ffi/utf8proc")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
@ -525,14 +526,17 @@ function ReaderSearch:showFindAllResults(not_cached)
if item.matched_word_suffix then
word = word .. item.matched_word_suffix
end
-- Make this word bolder, using Poor Text Formatting provided by TextBoxWidget
-- (we know this text ends up in a TextBoxWidget).
local text = TextBoxWidget.PTF_BOLD_START .. word .. TextBoxWidget.PTF_BOLD_END
-- append context before and after the word
local text = "" .. word .. ""
if item.prev_text then
text = item.prev_text .. text
end
if item.next_text then
text = text .. item.next_text
end
text = TextBoxWidget.PTF_HEADER .. text -- enable handling of our bold tags
item.text = text
item.mandatory = self.ui.bookmark:getBookmarkPageString(item.start)
end

@ -12,6 +12,7 @@ local FFIUtil = require("ffi/util")
local Geom = require("ui/geometry")
local KOPTContext = require("ffi/koptcontext")
local Persist = require("persist")
local TextBoxWidget = require("ui/widget/textboxwidget")
local TileCacheItem = require("document/tilecacheitem")
local Utf8Proc = require("ffi/utf8proc")
local logger = require("logger")
@ -1510,15 +1511,18 @@ function KoptInterface:findAllText(doc, pattern, case_insensitive, nb_context_wo
i_next, j_next = i, j
end
end
text = "" .. table.concat(text, " ") .. ""
-- Make this word bolder, using Poor Text Formatting provided by TextBoxWidget
-- (we know this text ends up in a TextBoxWidget).
text = TextBoxWidget.PTF_BOLD_START .. table.concat(text, " ") .. TextBoxWidget.PTF_BOLD_END
local prev_text = get_prev_text(text_boxes, i_prev, j_prev, nb_context_words)
if prev_text then
text = prev_text .. text
text = prev_text .. " " .. text
end
local next_text = get_next_text(text_boxes, i_next, j_next, nb_context_words)
if next_text then
text = text .. next_text
text = text .. " " .. next_text
end
text = TextBoxWidget.PTF_HEADER .. text -- enable handling of our bold tags
res_item.text = text
table.insert(res, res_item)
if #res == max_hits then

@ -289,17 +289,25 @@ end
-- @int glyph index
-- @bool[opt=false] bold whether the glyph should be artificially boldened
-- @treturn glyph
function RenderText:getGlyphByIndex(face, glyphindex, bold)
function RenderText:getGlyphByIndex(face, glyphindex, bold, bolder)
if face.is_real_bold then
bold = false -- don't embolden glyphs already bold
end
local hash = "xglyph|"..face.hash.."|"..glyphindex.."|"..(bold and 1 or 0)
local hash = "xglyph|"..face.hash.."|"..glyphindex.."|"..(bold and 1 or 0)..(bolder and "x" or "")
local glyph = GlyphCache:check(hash)
if glyph then
-- cache hit
return glyph
end
local rendered_glyph = face.ftsize:renderGlyphByIndex(glyphindex, bold and face.embolden_half_strength)
local embolden_strength
if bold or bolder then
embolden_strength = face.embolden_half_strength
if bolder then
-- Even if not bold, get it bolder than the strength we'd use for bold
embolden_strength = embolden_strength * 1.5
end
end
local rendered_glyph = face.ftsize:renderGlyphByIndex(glyphindex, embolden_strength)
if not rendered_glyph then
logger.warn("error rendering glyph (glyphindex=", glyphindex, ") for face", face)
return

@ -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

Loading…
Cancel
Save