Decrease fonts memory use (#10618)

Instead of opening the same font multiple times for each different
size (multiple face instances), share one face instance and create
multiple size instances.
reviewable/pr10648/r1
Benoit Pierre 10 months ago committed by GitHub
parent fc89b1affa
commit 346d8eb83e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1 +1 @@
Subproject commit b4cfe83c1fb268f1a8213de3f3a3b4756f1348e8
Subproject commit 9b5cf240bf8f60e4fa8328243f06ddaacb69342b

@ -109,15 +109,15 @@ local function collectFaceInfo(path)
return
end
for i=0, n-1 do
local ok, face = pcall(FT.newFace, path, nil, i)
local ok, ftsize = pcall(FT.newFaceSize, path, nil, i)
if not ok then
return nil
end
-- If family_name is missing, it's probably too broken to be useful
if face.family_name ~= nil then
local fres = face:getInfo()
local hbface = HB.hb_ft_face_create_referenced(face)
if ftsize.face.family_name ~= nil then
local fres = ftsize:getInfo()
local hbface = HB.hb_ft_face_create_referenced(ftsize.face)
fres.names = hbface:getNames()
fres.scripts, fres.langs = hbface:getCoverage()
fres.path = path
@ -125,7 +125,7 @@ local function collectFaceInfo(path)
table.insert(res, fres)
hbface:destroy()
end
face:done()
ftsize:done()
end
return res
end

@ -195,7 +195,7 @@ local bold_strength_factor = 3/8 -- as crengine, lighter
local _completeFaceProperties = function(face_obj)
if not face_obj.embolden_half_strength then
-- Cache this value in case we use bold, to avoid recomputation
face_obj.embolden_half_strength = face_obj.ftface:getEmboldenHalfStrength(bold_strength_factor)
face_obj.embolden_half_strength = face_obj.ftsize:getEmboldenHalfStrength(bold_strength_factor)
end
end
@ -302,9 +302,9 @@ function Font:getFace(font, size, faceindex)
face_obj.orig_size = orig_size
end
else
-- Build face if not found
-- Build face size if not found
local builtin_font_location = FontList.fontdir.."/"..realname
local ok, face = pcall(Freetype.newFace, builtin_font_location, size, faceindex)
local ok, ftsize = pcall(Freetype.newFaceSize, 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.
@ -315,14 +315,14 @@ function Font:getFace(font, size, faceindex)
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, faceindex)
ok, ftsize = pcall(Freetype.newFaceSize, _v, size, faceindex)
if ok then break end
end
end
end
if not ok then
logger.err("#! Font ", font, " (", realname, ") not supported: ", face)
logger.err("#! Font ", font, " (", realname, ") not supported: ", ftsize)
return nil
end
--- Freetype font face wrapper object
@ -330,14 +330,14 @@ function Font:getFace(font, size, faceindex)
-- @field orig_font font name requested
-- @field size size of the font face (after scaled by screen size)
-- @field orig_size raw size of the font face (before scale)
-- @field ftface font face object from freetype
-- @field ftsize font size object from freetype
-- @field hash hash key for this font face
face_obj = {
orig_font = font,
realname = realname,
size = size,
orig_size = orig_size,
ftface = face,
ftsize = ftsize,
hash = hash,
is_real_bold = is_real_bold,
}
@ -433,7 +433,7 @@ function Font:getAdjustedFace(face, bold)
-- We can keep the same FT object and the same hash in this face_obj
-- (which is only used to identify cached glyphs, that we don't need
-- to distinguish as "bold" is appended when synthetized as bold)
ftface = face.ftface,
ftsize = face.ftsize,
hash = face.hash,
hb_features = face.hb_features,
is_real_bold = nil,

@ -87,15 +87,15 @@ function RenderText:getGlyph(face, charcode, bold)
-- cache hit
return glyph
end
local rendered_glyph = face.ftface:renderGlyph(charcode, bold)
if face.ftface:checkGlyph(charcode) == 0 then
local rendered_glyph = face.ftsize:renderGlyph(charcode, bold)
if not face.ftsize:hasGlyph(charcode) then
for index, font in pairs(Font.fallbacks) do
-- use original size before scaling by screen DPI
local fb_face = Font:getFace(font, face.orig_size)
if fb_face ~= nil then
-- for some characters it cannot find in Fallbacks, it will crash here
if fb_face.ftface:checkGlyph(charcode) ~= 0 then
rendered_glyph = fb_face.ftface:renderGlyph(charcode, orig_bold)
if fb_face.ftsize:hasGlyph(charcode) then
rendered_glyph = fb_face.ftsize:renderGlyph(charcode, orig_bold)
break
end
end
@ -127,7 +127,7 @@ function RenderText:getSubTextByWidth(text, face, width, kerning, bold)
if pen_x < width then
local glyph = self:getGlyph(face, charcode, bold)
if kerning and prevcharcode then
local kern = face.ftface:getKerning(prevcharcode, charcode)
local kern = face.ftsize:getKerning(prevcharcode, charcode)
pen_x = pen_x + kern
end
pen_x = pen_x + glyph.ax
@ -170,7 +170,7 @@ function RenderText:sizeUtf8Text(x, width, face, text, kerning, bold)
if not width or pen_x < (width - x) then
local glyph = self:getGlyph(face, charcode, bold)
if kerning and (prevcharcode ~= 0) then
pen_x = pen_x + (face.ftface):getKerning(prevcharcode, charcode)
pen_x = pen_x + (face.ftsize):getKerning(prevcharcode, charcode)
end
pen_x = pen_x + glyph.ax
pen_y_top = math.max(pen_y_top, glyph.t)
@ -225,7 +225,7 @@ function RenderText:renderUtf8Text(dest_bb, x, baseline, face, text, kerning, bo
if pen_x < text_width then
local glyph = self:getGlyph(face, charcode, bold)
if kerning and (prevcharcode ~= 0) then
pen_x = pen_x + face.ftface:getKerning(prevcharcode, charcode)
pen_x = pen_x + face.ftsize:getKerning(prevcharcode, charcode)
end
dest_bb:colorblitFrom(
glyph.bb,
@ -299,7 +299,7 @@ function RenderText:getGlyphByIndex(face, glyphindex, bold)
-- cache hit
return glyph
end
local rendered_glyph = face.ftface:renderGlyphByIndex(glyphindex, bold and face.embolden_half_strength)
local rendered_glyph = face.ftsize:renderGlyphByIndex(glyphindex, bold and face.embolden_half_strength)
if not rendered_glyph then
logger.warn("error rendering glyph (glyphindex=", glyphindex, ") for face", face)
return

@ -125,7 +125,7 @@ function TextBoxWidget:init()
self.line_height_px = Math.round( (1 + self.line_height) * self.face.size )
-- Get accurate initial baseline and possible height overflow (so our bb
-- is tall enough to draw glyphs with descender larger than line height)
local face_height, face_ascender = self.face.ftface:getHeightAndAscender()
local face_height, face_ascender = self.face.ftsize:getHeightAndAscender()
local line_heights_diff = math.floor(self.line_height_px - face_height)
if line_heights_diff >= 0 then
-- Glyphs will fit in our line_height_px: adjust baseline.
@ -1113,7 +1113,7 @@ function TextBoxWidget:getFontSizeToFitHeight(height_px, nb_lines, line_height_e
local line_height_px = Math.round( (1 + line_height_em) * Screen:scaleBySize(font_size) )
local face = Font:getFace(font_face, font_size)
face = Font:getAdjustedFace(face, font_bold)
local face_height = face.ftface:getHeightAndAscender()
local face_height = face.ftsize:getHeightAndAscender()
local line_heights_diff = math.floor(line_height_px - face_height)
if line_heights_diff >= 0 then
break

@ -81,7 +81,7 @@ function TextWidget:getFontSizeToFitHeight(font_name, height_px, padding)
break
end
local face = Font:getFace(font_name, font_size)
local face_height = face.ftface:getHeightAndAscender()
local face_height = face.ftsize:getHeightAndAscender()
face_height = math.ceil(face_height) + 2*padding
until face_height <= height_px
return font_size
@ -109,7 +109,7 @@ function TextWidget:updateSize()
-- But better compute baseline alignment from freetype font metrics
-- to get better vertical centering of text in box
-- (Freetype doc on this at https://www.freetype.org/freetype2/docs/tutorial/step2.html)
local face_height, face_ascender = self.face.ftface:getHeightAndAscender()
local face_height, face_ascender = self.face.ftsize:getHeightAndAscender()
self._height = math.ceil(face_height) + 2*self.padding
self._baseline_h = Math.round(face_ascender) + self.padding
-- With our UI fonts, this usually gives 0.72 to 0.74, so text is aligned

@ -7,10 +7,10 @@ describe("Font module", function()
it("should get face", function()
local f
f = Font:getFace('cfont', 18)
assert.are_not.equals(f.ftface, nil)
assert.are_not.equals(f.ftsize, nil)
f = Font:getFace('tfont', 16)
assert.are_not.equals(f.ftface, nil)
assert.are_not.equals(f.ftsize, nil)
f = Font:getFace('hfont', 12)
assert.are_not.equals(f.ftface, nil)
assert.are_not.equals(f.ftsize, nil)
end)
end)

Loading…
Cancel
Save