2
0
mirror of https://github.com/koreader/koreader synced 2024-10-31 21:20:20 +00:00
koreader/frontend/device/screen.lua
Hans-Werner Hilse 3066c86e38 Refactoring hardware abstraction
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.
2014-11-02 21:19:04 +01:00

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