mirror of
https://github.com/koreader/koreader
synced 2024-10-31 21:20:20 +00:00
3066c86e38
This is a major overhaul of the hardware abstraction layer. A few notes: General platform distinction happens in frontend/device.lua which will delegate everything else to frontend/device/<platform_name>/device.lua which should extend frontend/device/generic/device.lua Screen handling is implemented in frontend/device/screen.lua which includes the *functionality* to support device specifics. Actually setting up the device specific functionality, however, is done in the device specific setup code in the relevant device.lua file. The same goes for input handling.
184 lines
4.3 KiB
Lua
184 lines
4.3 KiB
Lua
local Blitbuffer = require("ffi/blitbuffer")
|
|
local einkfb = require("ffi/framebuffer")
|
|
local Geom = require("ui/geometry")
|
|
local util = require("ffi/util")
|
|
local DEBUG = require("dbg")
|
|
|
|
--[[
|
|
Codes for rotation modes:
|
|
|
|
1 for no rotation,
|
|
2 for landscape with bottom on the right side of screen, etc.
|
|
|
|
2
|
|
+--------------+
|
|
| +----------+ |
|
|
| | | |
|
|
| | Freedom! | |
|
|
| | | |
|
|
| | | |
|
|
3 | | | | 1
|
|
| | | |
|
|
| | | |
|
|
| +----------+ |
|
|
| |
|
|
| |
|
|
+--------------+
|
|
0
|
|
--]]
|
|
|
|
|
|
local Screen = {
|
|
cur_rotation_mode = 0,
|
|
native_rotation_mode = nil,
|
|
blitbuffer_rotation_mode = 0,
|
|
|
|
bb = nil,
|
|
saved_bb = nil,
|
|
|
|
screen_size = Geom:new(),
|
|
viewport = nil,
|
|
|
|
fb = einkfb.open("/dev/fb0"),
|
|
-- will be set upon loading by Device class:
|
|
device = nil,
|
|
}
|
|
|
|
function Screen:new(o)
|
|
local o = o or {}
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
if o.init then o:init() end
|
|
return o
|
|
end
|
|
|
|
function Screen:init()
|
|
self.bb = self.fb.bb
|
|
self.blitbuffer_rotation_mode = self.bb:getRotation()
|
|
-- asking the framebuffer for orientation is error prone,
|
|
-- so we do this simple heuristic (for now)
|
|
self.screen_size.w = self.bb:getWidth()
|
|
self.screen_size.h = self.bb:getHeight()
|
|
if self.screen_size.w > self.screen_size.h then
|
|
self.native_rotation_mode = 1
|
|
self.screen_size.w, self.screen_size.h = self.screen_size.h, self.screen_size.w
|
|
else
|
|
self.native_rotation_mode = 0
|
|
end
|
|
self.cur_rotation_mode = self.native_rotation_mode
|
|
end
|
|
|
|
--[[
|
|
set a rectangle that represents the area of the screen we are working on
|
|
--]]
|
|
function Screen:setViewport(viewport)
|
|
self.viewport = self.screen_size:intersect(viewport)
|
|
self.bb = self.fb.bb:viewport(
|
|
self.viewport.x, self.viewport.y,
|
|
self.viewport.w, self.viewport.h)
|
|
end
|
|
|
|
function Screen:refresh(refresh_type, waveform_mode, x, y, w, h)
|
|
if self.viewport and x and y then
|
|
-- adapt to viewport
|
|
x = x + self.viewport.x
|
|
y = y + self.viewport.y
|
|
end
|
|
self.fb:refresh(refresh_type, waveform_mode, x, y, w, h)
|
|
end
|
|
|
|
function Screen:getSize()
|
|
return Geom:new{w = self.bb:getWidth(), h = self.bb:getHeight()}
|
|
end
|
|
|
|
function Screen:getWidth()
|
|
return self.bb:getWidth()
|
|
end
|
|
|
|
function Screen:getScreenWidth()
|
|
return self.screen_size.w
|
|
end
|
|
|
|
function Screen:getScreenHeight()
|
|
return self.screen_size.h
|
|
end
|
|
|
|
function Screen:getHeight()
|
|
return self.bb:getHeight()
|
|
end
|
|
|
|
function Screen:getDPI()
|
|
if self.dpi == nil then
|
|
self.dpi = G_reader_settings:readSetting("screen_dpi")
|
|
end
|
|
if self.dpi == nil then
|
|
self.dpi = self.device.display_dpi
|
|
end
|
|
if self.dpi == nil then
|
|
self.dpi = 160
|
|
end
|
|
return self.dpi
|
|
end
|
|
|
|
function Screen:setDPI(dpi)
|
|
G_reader_settings:saveSetting("screen_dpi", dpi)
|
|
end
|
|
|
|
function Screen:scaleByDPI(px)
|
|
-- scaled positive px should also be positive
|
|
return math.ceil(px * self:getDPI()/167)
|
|
end
|
|
|
|
function Screen:getRotationMode()
|
|
return self.cur_rotation_mode
|
|
end
|
|
|
|
function Screen:getScreenMode()
|
|
if self:getWidth() > self:getHeight() then
|
|
return "landscape"
|
|
else
|
|
return "portrait"
|
|
end
|
|
end
|
|
|
|
function Screen:setRotationMode(mode)
|
|
self.fb.bb:rotateAbsolute(-90 * (mode - self.native_rotation_mode - self.blitbuffer_rotation_mode))
|
|
self.cur_rotation_mode = mode
|
|
end
|
|
|
|
function Screen:setScreenMode(mode)
|
|
if mode == "portrait" then
|
|
if self.cur_rotation_mode ~= 0 then
|
|
self:setRotationMode(0)
|
|
end
|
|
elseif mode == "landscape" then
|
|
if self.cur_rotation_mode == 0 or self.cur_rotation_mode == 2 then
|
|
self:setRotationMode(DLANDSCAPE_CLOCKWISE_ROTATION and 1 or 3)
|
|
elseif self.cur_rotation_mode == 1 or self.cur_rotation_mode == 3 then
|
|
self:setRotationMode((self.cur_rotation_mode + 2) % 4)
|
|
end
|
|
end
|
|
end
|
|
|
|
function Screen:saveCurrentBB()
|
|
if self.saved_bb then self.saved_bb:free() end
|
|
self.saved_bb = self.bb:copy()
|
|
end
|
|
|
|
function Screen:restoreFromSavedBB()
|
|
if self.saved_bb then
|
|
self.bb:blitFullFrom(self.saved_bb)
|
|
-- free data
|
|
self.saved_bb:free()
|
|
self.saved_bb = nil
|
|
end
|
|
end
|
|
|
|
function Screen:close()
|
|
DEBUG("close screen framebuffer")
|
|
self.fb:close()
|
|
end
|
|
|
|
|
|
return Screen
|