From eb137d720e232e7f49a75a322640cdb4bf3dfd65 Mon Sep 17 00:00:00 2001 From: poire-z Date: Mon, 5 Oct 2020 20:26:33 +0200 Subject: [PATCH] Font menu: show font names with their own font --- frontend/apps/reader/modules/readerfont.lua | 24 +++++++++++++++++++-- frontend/ui/font.lua | 10 ++++++--- frontend/ui/widget/textwidget.lua | 10 +++++++-- frontend/ui/widget/touchmenu.lua | 21 +++++++++++++++++- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/frontend/apps/reader/modules/readerfont.lua b/frontend/apps/reader/modules/readerfont.lua index b35e13d04..f3f36a8e1 100644 --- a/frontend/apps/reader/modules/readerfont.lua +++ b/frontend/apps/reader/modules/readerfont.lua @@ -3,6 +3,7 @@ local CenterContainer = require("ui/widget/container/centercontainer") local ConfirmBox = require("ui/widget/confirmbox") local Device = require("device") local Event = require("ui/event") +local Font = require("ui/font") local Input = Device.input local InputContainer = require("ui/widget/container/inputcontainer") local Menu = require("ui/widget/menu") @@ -74,6 +75,14 @@ function ReaderFont:init() end return text end, + font_func = function(size) + if G_reader_settings:nilOrTrue("font_menu_use_font_face") then + local font_filename, font_faceindex = cre.getFontFaceFilenameAndFaceIndex(v) + if font_filename and font_faceindex then + return Font:getFace(font_filename, size, font_faceindex) + end + end + end, callback = function() self:setFont(v) end, @@ -84,7 +93,6 @@ function ReaderFont:init() return v == self.font_face end }) - face_list[k] = {text = v} end self.ui.menu:registerToMainMenu(self) end @@ -360,13 +368,25 @@ function ReaderFont:getFontSettingsTable() settings_table[#settings_table].separator = true end + table.insert(settings_table, { + text = _("Display font names with their own font"), + checked_func = function() + return G_reader_settings:nilOrTrue("font_menu_use_font_face") + end, + callback = function() + G_reader_settings:flipNilOrTrue("font_menu_use_font_face") + end, + help_text = _([[In the font menu, display each font name with its own font face.]]), + separator = true, + }) + table.insert(settings_table, { text = _("Use additional fallback fonts"), checked_func = function() return G_reader_settings:nilOrTrue("additional_fallback_fonts") end, callback = function() - G_reader_settings:flipNilOrTrue("additional_fallback_fonts") + G_reader_settings:flipNilOrTrue("additional_fallback_fonts") self.ui.document:setupFallbackFontFaces() self.ui:handleEvent(Event:new("UpdatePos")) end, diff --git a/frontend/ui/font.lua b/frontend/ui/font.lua index 5c3bbf26a..e950b836b 100644 --- a/frontend/ui/font.lua +++ b/frontend/ui/font.lua @@ -214,8 +214,9 @@ end --- Gets font face object. -- @string font -- @int size optional size +-- @int faceindex optional index of font face in font file -- @treturn table @{FontFaceObj} -function Font:getFace(font, size) +function Font:getFace(font, size, faceindex) -- default to content font if not font then font = self.cfont end @@ -235,6 +236,9 @@ function Font:getFace(font, size) -- Make a hash from the realname (many fonts in our fontmap use -- the same font file: have them share their glyphs cache) local hash = realname..size + if faceindex then + hash = hash .. "/" .. faceindex + end local face_obj = self.faces[hash] if face_obj then @@ -250,7 +254,7 @@ function Font:getFace(font, size) else -- Build face if not found local builtin_font_location = FontList.fontdir.."/"..realname - local ok, face = pcall(Freetype.newFace, builtin_font_location, size) + local ok, face = pcall(Freetype.newFace, builtin_font_location, size, faceindex) -- Not all fonts are bundled on all platforms because they come with the system. -- In that case, search through all font folders for the requested font. @@ -261,7 +265,7 @@ function Font:getFace(font, size) for _k, _v in ipairs(fonts) do if _v:find(escaped_realname) then logger.dbg("Found font:", realname, "in", _v) - ok, face = pcall(Freetype.newFace, _v, size) + ok, face = pcall(Freetype.newFace, _v, size, faceindex) if ok then break end end diff --git a/frontend/ui/widget/textwidget.lua b/frontend/ui/widget/textwidget.lua index 1397cfd5f..40b22b226 100644 --- a/frontend/ui/widget/textwidget.lua +++ b/frontend/ui/widget/textwidget.lua @@ -36,6 +36,12 @@ local TextWidget = Widget:new{ truncate_with_ellipsis = true, -- when truncation at max_width needed, add "…" truncate_left = false, -- truncate on the right by default + -- Force a baseline and height to use instead of those obtained from the font used + -- (mostly only useful for TouchMenu to display font names in their own font, to + -- ensure they get correctly vertically aligned in the menu) + forced_baseline = nil, + forced_height = nil, + -- for internal use _updated = nil, _face_adjusted = nil, @@ -279,7 +285,7 @@ function TextWidget:getSize() self:updateSize() return Geom:new{ w = self._length, - h = self._height, + h = self.forced_height or self._height, } end @@ -338,7 +344,7 @@ function TextWidget:paintTo(bb, x, y) text_width = self.max_width end local pen_x = 0 - local baseline = self._baseline_h + local baseline = self.forced_baseline or self._baseline_h for i, xglyph in ipairs(self._xshaping) do if pen_x >= text_width then break diff --git a/frontend/ui/widget/touchmenu.lua b/frontend/ui/widget/touchmenu.lua index fb0f969fb..fea07082c 100644 --- a/frontend/ui/widget/touchmenu.lua +++ b/frontend/ui/widget/touchmenu.lua @@ -88,6 +88,23 @@ function TouchMenuItem:init() -- FrameContainer default paddings minus the checked widget width local text_max_width = self.dimen.w - 2*Size.padding.default - checked_widget:getSize().w local text = getMenuText(self.item) + local face = self.face + local forced_baseline, forced_height + if self.item.font_func then + -- A font_func() may be provided by ReaderFont to have each font name + -- displayed in its own font: we must tell TextWidget to use the default + -- font baseline and height for items to be correctly aligned without + -- variations due to each font different metrics. + face = self.item.font_func(self.face.orig_size) + if face then + local w = TextWidget:new{ text = "", face = self.face } + forced_baseline = w:getBaseline() + forced_height = w:getSize().h + w:free() + else + face = self.face + end + end self.item_frame = FrameContainer:new{ width = self.dimen.w, bordersize = 0, @@ -102,7 +119,9 @@ function TouchMenuItem:init() text = text, max_width = text_max_width, fgcolor = item_enabled ~= false and Blitbuffer.COLOR_BLACK or Blitbuffer.COLOR_DARK_GRAY, - face = self.face, + face = face, + forced_baseline = forced_baseline, + forced_height = forced_height, }, }, }