2
0
mirror of https://github.com/koreader/koreader synced 2024-11-18 03:25:46 +00:00
koreader/frontend/ui/widget/textwidget.lua

108 lines
3.6 KiB
Lua
Raw Normal View History

2017-08-15 12:18:15 +00:00
--[[--
A TextWidget puts a string on a single line.
Example:
UIManager:show(TextWidget:new{
text = "Make it so.",
face = Font:getFace("cfont"),
bold = true,
fgcolor = Blitbuffer.COLOR_GREY,
})
--]]
local Blitbuffer = require("ffi/blitbuffer")
local Geom = require("ui/geometry")
local Math = require("optmath")
2017-08-15 12:18:15 +00:00
local RenderText = require("ui/rendertext")
local Size = require("ui/size")
2013-10-18 20:38:07 +00:00
local Widget = require("ui/widget/widget")
local Screen = require("device").screen
2013-10-18 20:38:07 +00:00
local TextWidget = Widget:new{
2014-03-13 13:52:43 +00:00
text = nil,
face = nil,
bold = nil,
fgcolor = Blitbuffer.COLOR_BLACK,
padding = Size.padding.small, -- should padding be function of face.size ?
max_width = nil,
2014-03-13 13:52:43 +00:00
_bb = nil,
_length = 0,
_height = 0,
_baseline_h = 0,
2014-03-13 13:52:43 +00:00
_maxlength = 1200,
2013-10-18 20:38:07 +00:00
}
--function TextWidget:_render()
2014-03-13 13:52:43 +00:00
--local h = self.face.size * 1.3
--self._bb = Blitbuffer.new(self._maxlength, h)
--self._bb:fill(Blitbuffer.COLOR_WHITE)
2014-03-13 13:52:43 +00:00
--self._length = RenderText:renderUtf8Text(self._bb, 0, h*0.8, self.face, self.text, true, self.bold)
2013-10-18 20:38:07 +00:00
--end
function TextWidget:updateSize()
local tsize = RenderText:sizeUtf8Text(0, self.max_width and self.max_width or Screen:getWidth(), self.face, self.text, true, self.bold)
if not tsize then
self._length = 0
else
-- As text length includes last glyph pen "advance" (for positionning
-- next char), it's best to use math.floor() instead of math.ceil()
-- to get rid of a fraction of it in case this text is to be
-- horizontally centered
self._length = math.floor(tsize.x)
end
-- Used to be:
-- self._height = math.ceil(self.face.size * 1.5)
-- self._baseline_h = self._height*0.7
-- 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()
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
-- a bit lower than before with the hardcoded 0.7
-- require("logger").warn("1.5*face.size:", self.face.size * 1.5, "face_height:", face_height, "self._height:", self._height)
-- require("logger").warn("self._height ratio:", 1.0*self._baseline_h/self._height)
end
2013-10-18 20:38:07 +00:00
function TextWidget:getSize()
2014-03-13 13:52:43 +00:00
--if not self._bb then
--self:_render()
--end
--return { w = self._length, h = self._bb:getHeight() }
self:updateSize()
2014-03-13 13:52:43 +00:00
return Geom:new{
w = self._length,
h = self._height,
}
2013-10-18 20:38:07 +00:00
end
function TextWidget:setText(text)
self.text = text
self:updateSize()
end
2013-10-18 20:38:07 +00:00
function TextWidget:paintTo(bb, x, y)
2014-03-13 13:52:43 +00:00
--if not self._bb then
--self:_render()
--end
--bb:blitFrom(self._bb, x, y, 0, 0, self._length, self._bb:getHeight())
--@TODO Don't use kerning for monospaced fonts. (houqp)
if self.max_width and RenderText:sizeUtf8Text(0, Screen:getWidth(), self.face, self.text, true, self.bold).x > self.max_width then
self.text = RenderText:truncateTextByWidth(self.text, self.face, self.max_width, true)
end
RenderText:renderUtf8Text(bb, x, y+self._baseline_h, self.face, self.text, true, self.bold,
self.fgcolor, self.max_width and self.max_width or self.width)
2013-10-18 20:38:07 +00:00
end
function TextWidget:free()
2014-03-13 13:52:43 +00:00
if self._bb then
self._bb:free()
self._bb = nil
end
2013-10-18 20:38:07 +00:00
end
return TextWidget