mirror of
https://github.com/koreader/koreader
synced 2024-10-31 21:20:20 +00:00
379cba7b68
The last argument of renderUtf8Text() accepts only boolean values of `kerning`.
264 lines
5.5 KiB
Lua
264 lines
5.5 KiB
Lua
require "rendertext"
|
|
require "graphics"
|
|
require "image"
|
|
|
|
--[[
|
|
This is a (useless) generic Widget interface
|
|
|
|
widgets can be queried about their size and can be paint.
|
|
that's it for now. Probably we need something more elaborate
|
|
later.
|
|
]]
|
|
Widget = {
|
|
dimen = { w = 0, h = 0},
|
|
}
|
|
|
|
function Widget:new(o)
|
|
o = o or {}
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
return o
|
|
end
|
|
|
|
function Widget:getSize()
|
|
return self.dimen
|
|
end
|
|
|
|
function Widget:paintTo(bb, x, y)
|
|
end
|
|
|
|
function Widget:free()
|
|
end
|
|
|
|
--[[
|
|
WidgetContainer is a container for another Widget
|
|
]]
|
|
WidgetContainer = Widget:new()
|
|
|
|
function WidgetContainer:free()
|
|
for _, widget in ipairs(self) do
|
|
widget:free()
|
|
end
|
|
end
|
|
|
|
--[[
|
|
CenterContainer centers its content (1 widget) within its own dimensions
|
|
]]
|
|
CenterContainer = WidgetContainer:new()
|
|
|
|
function CenterContainer:paintTo(bb, x, y)
|
|
local contentSize = self[1]:getSize()
|
|
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
|
-- throw error?
|
|
return
|
|
end
|
|
self[1]:paintTo(bb,
|
|
x + (self.dimen.w - contentSize.w)/2,
|
|
y + (self.dimen.h - contentSize.h)/2)
|
|
end
|
|
|
|
--[[
|
|
A FrameContainer is some graphics content (1 widget) that is surrounded by a frame
|
|
]]
|
|
FrameContainer = WidgetContainer:new({
|
|
background = nil,
|
|
color = 15,
|
|
margin = 0,
|
|
bordersize = 2,
|
|
padding = 5,
|
|
})
|
|
|
|
function FrameContainer:getSize()
|
|
local content_size = self[1]:getSize()
|
|
return {
|
|
w = content_size.w + ( self.margin + self.bordersize + self.padding ) * 2,
|
|
h = content_size.h + ( self.margin + self.bordersize + self.padding ) * 2
|
|
}
|
|
end
|
|
|
|
function FrameContainer:paintTo(bb, x, y)
|
|
local my_size = self:getSize()
|
|
|
|
if self.background then
|
|
bb:paintRect(x, y, my_size.w, my_size.h, self.background)
|
|
end
|
|
if self.bordersize > 0 then
|
|
bb:paintBorder(x + self.margin, y + self.margin,
|
|
my_size.w - self.margin * 2, my_size.h - self.margin * 2,
|
|
self.bordersize, self.color)
|
|
end
|
|
self[1]:paintTo(bb,
|
|
x + self.margin + self.bordersize + self.padding,
|
|
y + self.margin + self.bordersize + self.padding)
|
|
end
|
|
|
|
--[[
|
|
A TextWidget puts a string on a single line
|
|
]]
|
|
TextWidget = Widget:new({
|
|
text = nil,
|
|
face = nil,
|
|
color = 15,
|
|
_bb = nil,
|
|
_length = 0,
|
|
_maxlength = 1200,
|
|
})
|
|
|
|
function TextWidget:_render()
|
|
local h = self.face.size * 1.5
|
|
self._bb = Blitbuffer.new(self._maxlength, h)
|
|
self._length = renderUtf8Text(self._bb, 0, h*.7, self.face, self.text, true)
|
|
end
|
|
|
|
function TextWidget:getSize()
|
|
if not self._bb then
|
|
self:_render()
|
|
end
|
|
return { w = self._length, h = self._bb:getHeight() }
|
|
end
|
|
|
|
function TextWidget:paintTo(bb, x, y)
|
|
if not self._bb then
|
|
self:_render()
|
|
end
|
|
bb:blitFrom(self._bb, x, y, 0, 0, self._length, self._bb:getHeight())
|
|
end
|
|
|
|
function TextWidget:free()
|
|
if self._bb then
|
|
self._bb:free()
|
|
self._bb = nil
|
|
end
|
|
end
|
|
|
|
--[[
|
|
ImageWidget shows an image from a file
|
|
]]
|
|
ImageWidget = Widget:new({
|
|
file = nil,
|
|
_bb = nil
|
|
})
|
|
|
|
function ImageWidget:_render()
|
|
local itype = string.lower(string.match(self.file, ".+%.([^.]+)") or "")
|
|
if itype == "jpeg" or itype == "jpg" then
|
|
self._bb = Image.fromJPEG(self.file)
|
|
elseif itype == "png" then
|
|
self._bb = Image.fromPNG(self.file)
|
|
end
|
|
end
|
|
|
|
function ImageWidget:getSize()
|
|
if not self._bb then
|
|
self:_render()
|
|
end
|
|
return { w = self._bb:getWidth(), h = self._bb:getHeight() }
|
|
end
|
|
|
|
function ImageWidget:paintTo(bb, x, y)
|
|
local size = self:getSize()
|
|
bb:blitFrom(self._bb, x, y, 0, 0, size.w, size.h)
|
|
end
|
|
|
|
function ImageWidget:free()
|
|
if self._bb then
|
|
self._bb:free()
|
|
self._bb = nil
|
|
end
|
|
end
|
|
|
|
--[[
|
|
A Layout widget that puts objects besides each others
|
|
]]
|
|
HorizontalGroup = WidgetContainer:new({
|
|
align = "center",
|
|
_size = nil,
|
|
})
|
|
|
|
function HorizontalGroup:getSize()
|
|
if not self._size then
|
|
self._size = { w = 0, h = 0 }
|
|
self._offsets = { }
|
|
for i, widget in ipairs(self) do
|
|
local w_size = widget:getSize()
|
|
self._offsets[i] = {
|
|
x = self._size.w,
|
|
y = w_size.h
|
|
}
|
|
self._size.w = self._size.w + w_size.w
|
|
if w_size.h > self._size.h then
|
|
self._size.h = w_size.h
|
|
end
|
|
end
|
|
end
|
|
return self._size
|
|
end
|
|
|
|
function HorizontalGroup:paintTo(bb, x, y)
|
|
local size = self:getSize()
|
|
|
|
for i, widget in ipairs(self) do
|
|
if self.align == "center" then
|
|
widget:paintTo(bb, x + self._offsets[i].x, y + (size.h - self._offsets[i].y) / 2)
|
|
elseif self.align == "top" then
|
|
widget:paintTo(bb, x + self._offsets[i].x, y)
|
|
elseif self.align == "bottom" then
|
|
widget:paintTo(bb, x + self._offsets[i].x, y + size.h - self._offsets[i].y)
|
|
end
|
|
end
|
|
end
|
|
|
|
function HorizontalGroup:free()
|
|
self._size = nil
|
|
self._offsets = {}
|
|
WidgetContainer.free(self)
|
|
end
|
|
|
|
--[[
|
|
A Layout widget that puts objects under each other
|
|
]]
|
|
VerticalGroup = WidgetContainer:new({
|
|
align = "center",
|
|
_size = nil,
|
|
_offsets = {}
|
|
})
|
|
|
|
function VerticalGroup:getSize()
|
|
if not self._size then
|
|
self._size = { w = 0, h = 0 }
|
|
self._offsets = { }
|
|
for i, widget in ipairs(self) do
|
|
local w_size = widget:getSize()
|
|
self._offsets[i] = {
|
|
x = w_size.w,
|
|
y = self._size.h,
|
|
}
|
|
self._size.h = self._size.h + w_size.h
|
|
if w_size.w > self._size.w then
|
|
self._size.w = w_size.w
|
|
end
|
|
end
|
|
end
|
|
return self._size
|
|
end
|
|
|
|
function VerticalGroup:paintTo(bb, x, y)
|
|
local size = self:getSize()
|
|
|
|
for i, widget in ipairs(self) do
|
|
if self.align == "center" then
|
|
widget:paintTo(bb, x + (size.w - self._offsets[i].x) / 2, y + self._offsets[i].y)
|
|
elseif self.align == "left" then
|
|
widget:paintTo(bb, x, y + self._offsets[i].y)
|
|
elseif self.align == "right" then
|
|
widget:paintTo(bb, x + size.w - self._offsets[i].x, y + self._offsets[i].y)
|
|
end
|
|
end
|
|
end
|
|
|
|
function VerticalGroup:free()
|
|
self._size = nil
|
|
self._offsets = {}
|
|
WidgetContainer.free(self)
|
|
end
|