2016-12-25 20:13:30 +00:00
|
|
|
--[[--
|
|
|
|
ReaderView module handles all the screen painting for document browsing.
|
|
|
|
]]
|
|
|
|
|
2014-11-17 13:44:13 +00:00
|
|
|
local AlphaContainer = require("ui/widget/container/alphacontainer")
|
2017-05-22 14:21:23 +00:00
|
|
|
local Blitbuffer = require("ffi/blitbuffer")
|
|
|
|
local ConfirmBox = require("ui/widget/confirmbox")
|
2016-10-14 18:11:35 +00:00
|
|
|
local Device = require("device")
|
2013-10-18 20:38:07 +00:00
|
|
|
local Geom = require("ui/geometry")
|
|
|
|
local Event = require("ui/event")
|
2017-05-22 14:21:23 +00:00
|
|
|
local ImageWidget = require("ui/widget/imagewidget")
|
|
|
|
local OverlapGroup = require("ui/widget/overlapgroup")
|
|
|
|
local ReaderDogear = require("apps/reader/modules/readerdogear")
|
|
|
|
local ReaderFlipping = require("apps/reader/modules/readerflipping")
|
|
|
|
local ReaderFooter = require("apps/reader/modules/readerfooter")
|
|
|
|
local UIManager = require("ui/uimanager")
|
2016-04-19 06:50:36 +00:00
|
|
|
local dbg = require("dbg")
|
2016-12-29 08:10:38 +00:00
|
|
|
local logger = require("logger")
|
2014-10-15 12:31:24 +00:00
|
|
|
local _ = require("gettext")
|
2017-05-22 14:21:23 +00:00
|
|
|
local Screen = Device.screen
|
|
|
|
local T = require("ffi/util").template
|
2013-10-18 20:38:07 +00:00
|
|
|
|
2016-12-25 20:13:30 +00:00
|
|
|
local ReaderView = OverlapGroup:extend{
|
2014-03-13 13:52:43 +00:00
|
|
|
document = nil,
|
|
|
|
|
|
|
|
-- single page state
|
|
|
|
state = {
|
|
|
|
page = nil,
|
|
|
|
pos = 0,
|
|
|
|
zoom = 1.0,
|
|
|
|
rotation = 0,
|
|
|
|
gamma = 1.0,
|
|
|
|
offset = nil,
|
|
|
|
bbox = nil,
|
|
|
|
},
|
2014-10-22 13:34:11 +00:00
|
|
|
outer_page_color = Blitbuffer.gray(DOUTER_PAGE_COLOR/15),
|
2017-11-20 20:58:58 +00:00
|
|
|
-- highlight with "lighten" or "underscore" or "invert"
|
2014-03-13 13:52:43 +00:00
|
|
|
highlight = {
|
2014-10-22 13:34:11 +00:00
|
|
|
lighten_factor = 0.2,
|
2014-03-13 13:52:43 +00:00
|
|
|
temp_drawer = "invert",
|
|
|
|
temp = {},
|
|
|
|
saved_drawer = "lighten",
|
|
|
|
saved = {},
|
|
|
|
},
|
|
|
|
highlight_visible = true,
|
|
|
|
-- PDF/DjVu continuous paging
|
|
|
|
page_scroll = nil,
|
2014-10-22 13:34:11 +00:00
|
|
|
page_bgcolor = Blitbuffer.gray(DBACKGROUND_COLOR/15),
|
2014-03-13 13:52:43 +00:00
|
|
|
page_states = {},
|
|
|
|
scroll_mode = "vertical",
|
2016-11-05 15:12:19 +00:00
|
|
|
-- properties of the gap drawn between each page in scroll mode:
|
2014-03-13 13:52:43 +00:00
|
|
|
page_gap = {
|
2016-11-05 15:12:19 +00:00
|
|
|
-- width in pixels (when scrolling horizontally)
|
|
|
|
width = Screen:scaleBySize(G_reader_settings:readSetting("page_gap_width") or 8),
|
|
|
|
-- height in pixels (when scrolling vertically)
|
|
|
|
height = Screen:scaleBySize(G_reader_settings:readSetting("page_gap_height") or 8),
|
|
|
|
-- color (0 = white, 8 = gray, 15 = black)
|
|
|
|
color = Blitbuffer.gray((G_reader_settings:readSetting("page_gap_color") or 8)/15),
|
2014-03-13 13:52:43 +00:00
|
|
|
},
|
|
|
|
-- DjVu page rendering mode (used in djvu.c:drawPage())
|
|
|
|
render_mode = DRENDER_MODE, -- default to COLOR
|
|
|
|
-- Crengine view mode
|
|
|
|
view_mode = DCREREADER_VIEW_MODE, -- default to page mode
|
|
|
|
hinting = true,
|
|
|
|
|
|
|
|
-- visible area within current viewing page
|
|
|
|
visible_area = Geom:new{x = 0, y = 0},
|
|
|
|
-- dimen for current viewing page
|
|
|
|
page_area = Geom:new{},
|
|
|
|
-- dimen for area to dim
|
2014-11-13 04:37:10 +00:00
|
|
|
dim_area = nil,
|
2014-03-13 13:52:43 +00:00
|
|
|
-- has footer
|
|
|
|
footer_visible = nil,
|
|
|
|
-- has dogear
|
|
|
|
dogear_visible = false,
|
|
|
|
-- in flipping state
|
|
|
|
flipping_visible = false,
|
2014-04-02 20:59:17 +00:00
|
|
|
|
2014-03-13 13:52:43 +00:00
|
|
|
-- auto save settings after turning pages
|
2014-04-02 20:59:17 +00:00
|
|
|
auto_save_paging_count = 0,
|
2016-07-13 06:53:23 +00:00
|
|
|
autoSaveSettings = function()end
|
2012-05-18 22:50:26 +00:00
|
|
|
}
|
|
|
|
|
2013-02-24 11:49:23 +00:00
|
|
|
function ReaderView:init()
|
2016-12-25 20:13:30 +00:00
|
|
|
self.view_modules = {}
|
2014-04-30 15:19:24 +00:00
|
|
|
-- fix recalculate from close document pageno
|
|
|
|
self.state.page = nil
|
2014-11-13 04:37:10 +00:00
|
|
|
-- fix inherited dim_area for following opened documents
|
|
|
|
self:resetDimArea()
|
2015-03-12 06:35:43 +00:00
|
|
|
self:addWidgets()
|
2016-02-17 06:36:40 +00:00
|
|
|
self.emitHintPageEvent = function()
|
|
|
|
self.ui:handleEvent(Event:new("HintPage", self.hinting))
|
|
|
|
end
|
2013-02-24 11:49:23 +00:00
|
|
|
end
|
|
|
|
|
2014-11-13 04:37:10 +00:00
|
|
|
function ReaderView:resetDimArea()
|
|
|
|
self.dim_area = Geom:new{w = 0, h = 0}
|
|
|
|
end
|
|
|
|
|
2015-03-12 06:35:43 +00:00
|
|
|
function ReaderView:addWidgets()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.dogear = ReaderDogear:new{
|
|
|
|
view = self,
|
|
|
|
ui = self.ui,
|
|
|
|
}
|
|
|
|
self.footer = ReaderFooter:new{
|
|
|
|
view = self,
|
|
|
|
ui = self.ui,
|
|
|
|
}
|
|
|
|
self.flipping = ReaderFlipping:new{
|
|
|
|
view = self,
|
|
|
|
ui = self.ui,
|
|
|
|
}
|
2014-11-17 13:44:13 +00:00
|
|
|
self.arrow = AlphaContainer:new{
|
|
|
|
alpha = 0.6,
|
|
|
|
ImageWidget:new{
|
|
|
|
file = "resources/icons/appbar.control.expand.png",
|
|
|
|
}
|
|
|
|
}
|
2014-03-13 13:52:43 +00:00
|
|
|
self[1] = self.dogear
|
|
|
|
self[2] = self.footer
|
|
|
|
self[3] = self.flipping
|
2013-02-23 18:25:57 +00:00
|
|
|
end
|
|
|
|
|
2016-12-25 20:13:30 +00:00
|
|
|
--[[--
|
|
|
|
Register a view UI widget module for document browsing.
|
|
|
|
|
|
|
|
@tparam string name module name, registered widget can be accessed by readerui.view.view_modules[name].
|
|
|
|
@tparam ui.widget.widget.Widget widget paintable widget, i.e. has a paintTo method.
|
|
|
|
|
|
|
|
@usage
|
|
|
|
local ImageWidget = require("ui/widget/imagewidget")
|
|
|
|
local dummy_image = ImageWidget:new{
|
|
|
|
file = "resources/icons/appbar.control.expand.png",
|
|
|
|
}
|
|
|
|
-- the image will be painted on all book pages
|
|
|
|
readerui.view:registerViewModule('dummy_image', dummy_image)
|
|
|
|
]]
|
|
|
|
function ReaderView:registerViewModule(name, widget)
|
|
|
|
if not widget.paintTo then
|
|
|
|
print(name .. " view module does not have paintTo method!")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
widget.view = self
|
|
|
|
widget.ui = self.ui
|
|
|
|
self.view_modules[name] = widget
|
|
|
|
end
|
|
|
|
|
2015-03-12 06:35:43 +00:00
|
|
|
function ReaderView:resetLayout()
|
2016-12-25 20:13:30 +00:00
|
|
|
for _, widget in ipairs(self) do
|
2016-03-08 06:42:46 +00:00
|
|
|
widget:resetLayout()
|
2015-03-12 06:35:43 +00:00
|
|
|
end
|
2016-12-25 20:13:30 +00:00
|
|
|
for _, m in pairs(self.view_modules) do
|
|
|
|
if m.resetLayout then m:resetLayout() end
|
|
|
|
end
|
2015-03-12 06:35:43 +00:00
|
|
|
end
|
|
|
|
|
2012-05-18 22:50:26 +00:00
|
|
|
function ReaderView:paintTo(bb, x, y)
|
2016-08-12 09:47:35 +00:00
|
|
|
dbg:v("readerview painting", self.visible_area, "to", x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.page_scroll then
|
|
|
|
self:drawPageBackground(bb, x, y)
|
|
|
|
else
|
|
|
|
self:drawPageSurround(bb, x, y)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- draw page content
|
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
if self.page_scroll then
|
|
|
|
self:drawScrollPages(bb, x, y)
|
|
|
|
else
|
|
|
|
self:drawSinglePage(bb, x, y)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if self.view_mode == "page" then
|
|
|
|
self:drawPageView(bb, x, y)
|
|
|
|
elseif self.view_mode == "scroll" then
|
|
|
|
self:drawScrollView(bb, x, y)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- dim last read area
|
2014-11-17 13:44:13 +00:00
|
|
|
if self.dim_area.w ~= 0 and self.dim_area.h ~= 0 then
|
|
|
|
if self.page_overlap_style == "dim" then
|
|
|
|
bb:dimRect(
|
|
|
|
self.dim_area.x, self.dim_area.y,
|
|
|
|
self.dim_area.w, self.dim_area.h
|
|
|
|
)
|
|
|
|
elseif self.page_overlap_style == "arrow" then
|
|
|
|
self.arrow:paintTo(bb, 0, self.dim_area.h)
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
end
|
|
|
|
-- draw saved highlight
|
|
|
|
if self.highlight_visible then
|
|
|
|
self:drawSavedHighlight(bb, x, y)
|
|
|
|
end
|
|
|
|
-- draw temporary highlight
|
|
|
|
if self.highlight.temp then
|
|
|
|
self:drawTempHighlight(bb, x, y)
|
|
|
|
end
|
|
|
|
-- paint dogear
|
|
|
|
if self.dogear_visible then
|
|
|
|
self.dogear:paintTo(bb, x, y)
|
|
|
|
end
|
|
|
|
-- paint footer
|
|
|
|
if self.footer_visible then
|
|
|
|
self.footer:paintTo(bb, x, y)
|
|
|
|
end
|
|
|
|
-- paint flipping
|
|
|
|
if self.flipping_visible then
|
|
|
|
self.flipping:paintTo(bb, x, y)
|
|
|
|
end
|
2016-12-25 20:13:30 +00:00
|
|
|
for _, m in pairs(self.view_modules) do
|
|
|
|
m:paintTo(bb, x, y)
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
-- stop activity indicator
|
|
|
|
self.ui:handleEvent(Event:new("StopActivityIndicator"))
|
Enable HW dithering in a few key places (#4541)
* Enable HW dithering on supported devices (Clara HD, Forma; Oasis 2, PW4)
* FileManager and co. (where appropriate, i.e., when covers are shown)
* Book Status
* Reader, where appropriate:
* CRe: on pages whith image content (for over 7.5% of the screen area, should hopefully leave stuff like bullet points or small scene breaks alone).
* Other engines: on user-request (in the gear tab of the bottom menu), via the new "Dithering" knob (will only appear on supported devices).
* ScreenSaver
* ImageViewer
* Minimize repaints when flash_ui is enabled (by, almost everywhere, only repainting the flashing element, and not the toplevel window which hosts it).
(The first pass of this involved fixing a few Button instances whose show_parent was wrong, in particular, chevrons in the FM & TopMenu).
* Hunted down a few redundant repaints (unneeded setDirty("all") calls),
either by switching the widget to nil when only a refresh was needed, and not a repaint,
or by passing the appropritate widget to setDirty.
(Note to self: Enable *verbose* debugging to catch broken setDirty calls via its post guard).
There were also a few instances of 'em right behind a widget close.
* Don't repaint the underlying widget when initially showing TopMenu & ConfigDialog.
We unfortunately do need to do it when switching tabs, because of their variable heights.
* On Kobo, disabled the extra and completely useless full refresh before suspend/reboot/poweroff, as well as on resume. No more double refreshes!
* Fix another debug guard in Kobo sysfs_light
* Switch ImageWidget & ImageViewer mostly to "ui" updates, which will be better suited to image content pretty much everywhere, REAGL or not.
PS: (Almost :100: commits! :D)
2019-02-07 00:14:37 +00:00
|
|
|
|
|
|
|
-- Most pages should not require dithering
|
|
|
|
self.dialog.dithered = nil
|
|
|
|
-- For KOpt, let the user choose.
|
|
|
|
if self.ui.document.info.has_pages then
|
2019-02-08 17:31:40 +00:00
|
|
|
-- Also enforce dithering in PicDocument
|
|
|
|
if self.ui.document.is_pic or self.document.configurable.hw_dithering == 1 then
|
Enable HW dithering in a few key places (#4541)
* Enable HW dithering on supported devices (Clara HD, Forma; Oasis 2, PW4)
* FileManager and co. (where appropriate, i.e., when covers are shown)
* Book Status
* Reader, where appropriate:
* CRe: on pages whith image content (for over 7.5% of the screen area, should hopefully leave stuff like bullet points or small scene breaks alone).
* Other engines: on user-request (in the gear tab of the bottom menu), via the new "Dithering" knob (will only appear on supported devices).
* ScreenSaver
* ImageViewer
* Minimize repaints when flash_ui is enabled (by, almost everywhere, only repainting the flashing element, and not the toplevel window which hosts it).
(The first pass of this involved fixing a few Button instances whose show_parent was wrong, in particular, chevrons in the FM & TopMenu).
* Hunted down a few redundant repaints (unneeded setDirty("all") calls),
either by switching the widget to nil when only a refresh was needed, and not a repaint,
or by passing the appropritate widget to setDirty.
(Note to self: Enable *verbose* debugging to catch broken setDirty calls via its post guard).
There were also a few instances of 'em right behind a widget close.
* Don't repaint the underlying widget when initially showing TopMenu & ConfigDialog.
We unfortunately do need to do it when switching tabs, because of their variable heights.
* On Kobo, disabled the extra and completely useless full refresh before suspend/reboot/poweroff, as well as on resume. No more double refreshes!
* Fix another debug guard in Kobo sysfs_light
* Switch ImageWidget & ImageViewer mostly to "ui" updates, which will be better suited to image content pretty much everywhere, REAGL or not.
PS: (Almost :100: commits! :D)
2019-02-07 00:14:37 +00:00
|
|
|
self.dialog.dithered = true
|
|
|
|
end
|
|
|
|
else
|
|
|
|
-- Whereas for CRe,
|
|
|
|
-- If we're attempting to show a large enough amount of image data, request dithering (without triggering another repaint ;)).
|
|
|
|
local img_count, img_coverage = self.ui.document:getDrawnImagesStatistics()
|
|
|
|
-- With some nil guards because this may not be implemented in every engine ;).
|
|
|
|
if img_count and img_count > 0 and img_coverage and img_coverage >= 0.075 then
|
|
|
|
self.dialog.dithered = true
|
|
|
|
end
|
|
|
|
end
|
2012-05-18 22:50:26 +00:00
|
|
|
end
|
|
|
|
|
2013-04-23 22:59:52 +00:00
|
|
|
--[[
|
|
|
|
Given coordinates on the screen return position in original page
|
|
|
|
]]--
|
|
|
|
function ReaderView:screenToPageTransform(pos)
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
if self.page_scroll then
|
|
|
|
return self:getScrollPagePosition(pos)
|
|
|
|
else
|
|
|
|
return self:getSinglePagePosition(pos)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
pos.page = self.ui.document:getCurrentPage()
|
2016-02-15 09:33:48 +00:00
|
|
|
-- local last_y = self.ui.document:getCurrentPos()
|
2016-12-29 08:10:38 +00:00
|
|
|
logger.dbg("document has no pages at", pos)
|
2014-03-13 13:52:43 +00:00
|
|
|
return pos
|
|
|
|
end
|
2013-04-23 22:59:52 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
--[[
|
|
|
|
Given rectangle in original page return rectangle on the screen
|
|
|
|
]]--
|
|
|
|
function ReaderView:pageToScreenTransform(page, rect)
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
if self.page_scroll then
|
|
|
|
return self:getScrollPageRect(page, rect)
|
|
|
|
else
|
|
|
|
return self:getSinglePageRect(rect)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return rect
|
|
|
|
end
|
2013-04-23 22:59:52 +00:00
|
|
|
end
|
|
|
|
|
2014-07-02 08:38:09 +00:00
|
|
|
--[[
|
|
|
|
Get page area on screen for a given page number
|
|
|
|
--]]
|
|
|
|
function ReaderView:getScreenPageArea(page)
|
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
local area = Geom:new{x = 0, y = 0}
|
|
|
|
if self.page_scroll then
|
|
|
|
for _, state in ipairs(self.page_states) do
|
|
|
|
if page ~= state.page then
|
|
|
|
area.y = area.y + state.visible_area.h + state.offset.y
|
|
|
|
area.y = area.y + self.page_gap.height
|
|
|
|
else
|
|
|
|
area.x = state.offset.x
|
|
|
|
area.w = state.visible_area.w
|
|
|
|
area.h = state.visible_area.h
|
|
|
|
return area
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
area.x = self.state.offset.x
|
|
|
|
area.y = self.state.offset.y
|
|
|
|
area.w = self.visible_area.w
|
|
|
|
area.h = self.visible_area.h
|
|
|
|
return area
|
|
|
|
end
|
|
|
|
else
|
2014-11-25 03:02:33 +00:00
|
|
|
return self.dimen
|
2014-07-02 08:38:09 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-03-10 06:23:26 +00:00
|
|
|
function ReaderView:drawPageBackground(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
bb:paintRect(x, y, self.dimen.w, self.dimen.h, self.page_bgcolor)
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:drawPageSurround(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.dimen.h > self.visible_area.h then
|
|
|
|
bb:paintRect(x, y, self.dimen.w, self.state.offset.y, self.outer_page_color)
|
|
|
|
bb:paintRect(x, y + self.dimen.h - self.state.offset.y - 1,
|
|
|
|
self.dimen.w, self.state.offset.y + 1, self.outer_page_color)
|
|
|
|
end
|
|
|
|
if self.dimen.w > self.visible_area.w then
|
|
|
|
bb:paintRect(x, y, self.state.offset.x, self.dimen.h, self.outer_page_color)
|
|
|
|
bb:paintRect(x + self.dimen.w - self.state.offset.x - 1, y,
|
|
|
|
self.state.offset.x + 1, self.dimen.h, self.outer_page_color)
|
|
|
|
end
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:drawScrollPages(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
local pos = Geom:new{x = x , y = y}
|
|
|
|
for page, state in ipairs(self.page_states) do
|
|
|
|
self.ui.document:drawPage(
|
|
|
|
bb,
|
|
|
|
pos.x + state.offset.x,
|
|
|
|
pos.y + state.offset.y,
|
|
|
|
state.visible_area,
|
|
|
|
state.page,
|
|
|
|
state.zoom,
|
|
|
|
state.rotation,
|
|
|
|
state.gamma,
|
|
|
|
self.render_mode)
|
|
|
|
pos.y = pos.y + state.visible_area.h
|
|
|
|
-- draw page gap if not the last part
|
|
|
|
if page ~= #self.page_states then
|
|
|
|
self:drawPageGap(bb, pos.x, pos.y)
|
|
|
|
pos.y = pos.y + self.page_gap.height
|
|
|
|
end
|
|
|
|
end
|
2016-02-17 06:36:40 +00:00
|
|
|
UIManager:nextTick(self.emitHintPageEvent)
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
2013-06-15 15:13:19 +00:00
|
|
|
function ReaderView:getCurrentPageList()
|
2014-03-13 13:52:43 +00:00
|
|
|
local pages = {}
|
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
if self.page_scroll then
|
|
|
|
for _, state in ipairs(self.page_states) do
|
|
|
|
table.insert(pages, state.page)
|
|
|
|
end
|
|
|
|
else
|
|
|
|
table.insert(pages, self.state.page)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return pages
|
2013-06-15 15:13:19 +00:00
|
|
|
end
|
|
|
|
|
2013-04-23 22:59:52 +00:00
|
|
|
function ReaderView:getScrollPagePosition(pos)
|
2016-02-15 09:33:48 +00:00
|
|
|
local x_p, y_p
|
2014-03-13 13:52:43 +00:00
|
|
|
local x_s, y_s = pos.x, pos.y
|
|
|
|
for _, state in ipairs(self.page_states) do
|
|
|
|
if y_s < state.visible_area.h + state.offset.y then
|
|
|
|
y_p = (state.visible_area.y + y_s - state.offset.y) / state.zoom
|
|
|
|
x_p = (state.visible_area.x + x_s - state.offset.x) / state.zoom
|
|
|
|
return {
|
|
|
|
x = x_p,
|
|
|
|
y = y_p,
|
|
|
|
page = state.page,
|
|
|
|
zoom = state.zoom,
|
|
|
|
rotation = state.rotation,
|
|
|
|
}
|
|
|
|
else
|
|
|
|
y_s = y_s - state.visible_area.h - self.page_gap.height
|
|
|
|
end
|
|
|
|
end
|
2013-04-23 22:59:52 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:getScrollPageRect(page, rect_p)
|
2014-03-13 13:52:43 +00:00
|
|
|
local rect_s = Geom:new{}
|
|
|
|
for _, state in ipairs(self.page_states) do
|
|
|
|
local trans_p = Geom:new(rect_p):copy()
|
|
|
|
trans_p:transformByScale(state.zoom, state.zoom)
|
2014-10-21 09:24:19 +00:00
|
|
|
if page == state.page and state.visible_area:intersectWith(trans_p) then
|
2014-03-13 13:52:43 +00:00
|
|
|
rect_s.x = rect_s.x + state.offset.x + trans_p.x - state.visible_area.x
|
|
|
|
rect_s.y = rect_s.y + state.offset.y + trans_p.y - state.visible_area.y
|
|
|
|
rect_s.w = trans_p.w
|
|
|
|
rect_s.h = trans_p.h
|
|
|
|
return rect_s
|
|
|
|
end
|
|
|
|
rect_s.y = rect_s.y + state.visible_area.h + self.page_gap.height
|
|
|
|
end
|
2013-04-23 22:59:52 +00:00
|
|
|
end
|
|
|
|
|
2013-03-10 06:23:26 +00:00
|
|
|
function ReaderView:drawPageGap(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.scroll_mode == "vertical" then
|
|
|
|
bb:paintRect(x, y, self.dimen.w, self.page_gap.height, self.page_gap.color)
|
|
|
|
elseif self.scroll_mode == "horizontal" then
|
|
|
|
bb:paintRect(x, y, self.page_gap.width, self.dimen.h, self.page_gap.color)
|
|
|
|
end
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:drawSinglePage(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui.document:drawPage(
|
|
|
|
bb,
|
|
|
|
x + self.state.offset.x,
|
|
|
|
y + self.state.offset.y,
|
|
|
|
self.visible_area,
|
|
|
|
self.state.page,
|
|
|
|
self.state.zoom,
|
|
|
|
self.state.rotation,
|
|
|
|
self.state.gamma,
|
|
|
|
self.render_mode)
|
2016-02-17 06:36:40 +00:00
|
|
|
UIManager:nextTick(self.emitHintPageEvent)
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
2013-04-23 22:59:52 +00:00
|
|
|
function ReaderView:getSinglePagePosition(pos)
|
2014-03-13 13:52:43 +00:00
|
|
|
local x_s, y_s = pos.x, pos.y
|
|
|
|
return {
|
|
|
|
x = (self.visible_area.x + x_s - self.state.offset.x) / self.state.zoom,
|
|
|
|
y = (self.visible_area.y + y_s - self.state.offset.y) / self.state.zoom,
|
|
|
|
page = self.state.page,
|
|
|
|
zoom = self.state.zoom,
|
|
|
|
rotation = self.state.rotation,
|
|
|
|
}
|
2013-04-23 22:59:52 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:getSinglePageRect(rect_p)
|
2014-03-13 13:52:43 +00:00
|
|
|
local rect_s = Geom:new{}
|
|
|
|
local trans_p = Geom:new(rect_p):copy()
|
|
|
|
trans_p:transformByScale(self.state.zoom, self.state.zoom)
|
2014-10-21 09:24:19 +00:00
|
|
|
if self.visible_area:intersectWith(trans_p) then
|
2014-03-13 13:52:43 +00:00
|
|
|
rect_s.x = self.state.offset.x + trans_p.x - self.visible_area.x
|
|
|
|
rect_s.y = self.state.offset.y + trans_p.y - self.visible_area.y
|
|
|
|
rect_s.w = trans_p.w
|
|
|
|
rect_s.h = trans_p.h
|
|
|
|
return rect_s
|
|
|
|
end
|
2013-04-23 22:59:52 +00:00
|
|
|
end
|
|
|
|
|
2013-03-10 06:23:26 +00:00
|
|
|
function ReaderView:drawPageView(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui.document:drawCurrentViewByPage(
|
|
|
|
bb,
|
|
|
|
x + self.state.offset.x,
|
|
|
|
y + self.state.offset.y,
|
|
|
|
self.visible_area,
|
|
|
|
self.state.page)
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:drawScrollView(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui.document:drawCurrentViewByPos(
|
|
|
|
bb,
|
|
|
|
x + self.state.offset.x,
|
|
|
|
y + self.state.offset.y,
|
|
|
|
self.visible_area,
|
|
|
|
self.state.pos)
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
2013-06-15 15:13:19 +00:00
|
|
|
function ReaderView:drawTempHighlight(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
for page, boxes in pairs(self.highlight.temp) do
|
|
|
|
for i = 1, #boxes do
|
|
|
|
local rect = self:pageToScreenTransform(page, boxes[i])
|
|
|
|
if rect then
|
|
|
|
self:drawHighlightRect(bb, x, y, rect, self.highlight.temp_drawer)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-06-15 15:13:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:drawSavedHighlight(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
self:drawPageSavedHighlight(bb, x, y)
|
|
|
|
else
|
|
|
|
self:drawXPointerSavedHighlight(bb, x, y)
|
|
|
|
end
|
2014-01-17 19:05:17 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:drawPageSavedHighlight(bb, x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
local pages = self:getCurrentPageList()
|
|
|
|
for _, page in pairs(pages) do
|
|
|
|
local items = self.highlight.saved[page]
|
|
|
|
if not items then items = {} end
|
|
|
|
for i = 1, #items do
|
|
|
|
local item = items[i]
|
|
|
|
local pos0, pos1 = item.pos0, item.pos1
|
|
|
|
local boxes = self.ui.document:getPageBoxesFromPositions(page, pos0, pos1)
|
|
|
|
if boxes then
|
|
|
|
for _, box in pairs(boxes) do
|
|
|
|
local rect = self:pageToScreenTransform(page, box)
|
|
|
|
if rect then
|
|
|
|
self:drawHighlightRect(bb, x, y, rect, item.drawer or self.highlight.saved_drawer)
|
|
|
|
end
|
|
|
|
end -- end for each box
|
|
|
|
end -- end if boxes
|
|
|
|
end -- end for each highlight
|
|
|
|
end -- end for each page
|
2013-06-15 15:13:19 +00:00
|
|
|
end
|
|
|
|
|
2014-01-17 19:05:17 +00:00
|
|
|
function ReaderView:drawXPointerSavedHighlight(bb, x, y)
|
2018-10-08 16:57:59 +00:00
|
|
|
-- Getting screen boxes is done for each tap on screen (changing pages,
|
|
|
|
-- showing menu...). We might want to cache these boxes per page (and
|
|
|
|
-- clear that cache when page layout change or highlights are added
|
|
|
|
-- or removed).
|
2017-11-20 20:58:58 +00:00
|
|
|
local cur_page
|
|
|
|
-- In scroll mode, we'll need to check for highlights in previous or next
|
|
|
|
-- page too as some parts of them may be displayed
|
|
|
|
local neighbour_pages = self.view_mode ~= "page" and 1 or 0
|
2014-03-13 13:52:43 +00:00
|
|
|
for page, _ in pairs(self.highlight.saved) do
|
|
|
|
local items = self.highlight.saved[page]
|
|
|
|
if not items then items = {} end
|
|
|
|
for j = 1, #items do
|
2017-11-20 20:58:58 +00:00
|
|
|
if not cur_page then
|
|
|
|
cur_page = self.ui.document:getPageFromXPointer(self.ui.document:getXPointer())
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
local item = items[j]
|
|
|
|
local pos0, pos1 = item.pos0, item.pos1
|
2017-11-20 20:58:58 +00:00
|
|
|
-- document:getScreenBoxesFromPositions() is expensive, so we
|
|
|
|
-- first check this item is on current page
|
|
|
|
local page0 = self.ui.document:getPageFromXPointer(pos0)
|
|
|
|
local page1 = self.ui.document:getPageFromXPointer(pos1)
|
|
|
|
local start_page = math.min(page0, page1)
|
|
|
|
local end_page = math.max(page0, page1)
|
|
|
|
-- In scroll mode, we may be displaying cur_page and cur_page+1, so
|
|
|
|
-- we have to check the highlight start_page is <= cur_page+1.
|
|
|
|
-- Same thinking with highlight's end_page >= cur_page-1 as we may
|
|
|
|
-- be displaying a part of cur_page-1.
|
|
|
|
-- (A highlight starting on cur_page-17 and ending on cur_page+13 is
|
|
|
|
-- a highlight to consider)
|
|
|
|
if start_page <= cur_page + neighbour_pages and end_page >= cur_page - neighbour_pages then
|
2018-10-08 16:57:59 +00:00
|
|
|
local boxes = self.ui.document:getScreenBoxesFromPositions(pos0, pos1, true) -- get_segments=true
|
2017-11-20 20:58:58 +00:00
|
|
|
if boxes then
|
|
|
|
for _, box in pairs(boxes) do
|
|
|
|
local rect = self:pageToScreenTransform(page, box)
|
|
|
|
if rect then
|
|
|
|
self:drawHighlightRect(bb, x, y, rect, item.drawer or self.highlight.saved_drawer)
|
|
|
|
end
|
|
|
|
end -- end for each box
|
|
|
|
end -- end if boxes
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
end -- end for each highlight
|
|
|
|
end -- end for all saved highlight
|
2014-01-17 19:05:17 +00:00
|
|
|
end
|
|
|
|
|
2016-06-27 16:43:23 +00:00
|
|
|
function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer)
|
2014-03-13 13:52:43 +00:00
|
|
|
local x, y, w, h = rect.x, rect.y, rect.w, rect.h
|
2014-04-02 20:59:17 +00:00
|
|
|
|
2014-03-13 13:52:43 +00:00
|
|
|
if drawer == "underscore" then
|
|
|
|
self.highlight.line_width = self.highlight.line_width or 2
|
2014-10-22 13:34:11 +00:00
|
|
|
self.highlight.line_color = self.highlight.line_color or Blitbuffer.gray(0.33)
|
2014-03-13 13:52:43 +00:00
|
|
|
bb:paintRect(x, y+h-1, w,
|
|
|
|
self.highlight.line_width,
|
|
|
|
self.highlight.line_color)
|
|
|
|
elseif drawer == "lighten" then
|
2014-10-22 13:34:11 +00:00
|
|
|
bb:lightenRect(x, y, w, h, self.highlight.lighten_factor)
|
2014-03-13 13:52:43 +00:00
|
|
|
elseif drawer == "invert" then
|
|
|
|
bb:invertRect(x, y, w, h)
|
|
|
|
end
|
2013-04-23 22:59:52 +00:00
|
|
|
end
|
|
|
|
|
2013-03-10 06:23:26 +00:00
|
|
|
function ReaderView:getPageArea(page, zoom, rotation)
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.use_bbox then
|
|
|
|
return self.ui.document:getUsedBBoxDimensions(page, zoom, rotation)
|
|
|
|
else
|
|
|
|
return self.ui.document:getPageDimensions(page, zoom, rotation)
|
|
|
|
end
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
2012-12-08 06:05:10 +00:00
|
|
|
--[[
|
|
|
|
This method is supposed to be only used by ReaderPaging
|
|
|
|
--]]
|
2012-05-18 22:50:26 +00:00
|
|
|
function ReaderView:recalculate()
|
Enable HW dithering in a few key places (#4541)
* Enable HW dithering on supported devices (Clara HD, Forma; Oasis 2, PW4)
* FileManager and co. (where appropriate, i.e., when covers are shown)
* Book Status
* Reader, where appropriate:
* CRe: on pages whith image content (for over 7.5% of the screen area, should hopefully leave stuff like bullet points or small scene breaks alone).
* Other engines: on user-request (in the gear tab of the bottom menu), via the new "Dithering" knob (will only appear on supported devices).
* ScreenSaver
* ImageViewer
* Minimize repaints when flash_ui is enabled (by, almost everywhere, only repainting the flashing element, and not the toplevel window which hosts it).
(The first pass of this involved fixing a few Button instances whose show_parent was wrong, in particular, chevrons in the FM & TopMenu).
* Hunted down a few redundant repaints (unneeded setDirty("all") calls),
either by switching the widget to nil when only a refresh was needed, and not a repaint,
or by passing the appropritate widget to setDirty.
(Note to self: Enable *verbose* debugging to catch broken setDirty calls via its post guard).
There were also a few instances of 'em right behind a widget close.
* Don't repaint the underlying widget when initially showing TopMenu & ConfigDialog.
We unfortunately do need to do it when switching tabs, because of their variable heights.
* On Kobo, disabled the extra and completely useless full refresh before suspend/reboot/poweroff, as well as on resume. No more double refreshes!
* Fix another debug guard in Kobo sysfs_light
* Switch ImageWidget & ImageViewer mostly to "ui" updates, which will be better suited to image content pretty much everywhere, REAGL or not.
PS: (Almost :100: commits! :D)
2019-02-07 00:14:37 +00:00
|
|
|
-- Start by resetting the dithering flag early, so it doesn't carry over from the previous page.
|
|
|
|
self.dialog.dithered = nil
|
|
|
|
|
2014-03-13 13:52:43 +00:00
|
|
|
if self.ui.document.info.has_pages and self.state.page then
|
|
|
|
self.page_area = self:getPageArea(
|
|
|
|
self.state.page,
|
|
|
|
self.state.zoom,
|
|
|
|
self.state.rotation)
|
|
|
|
-- reset our size
|
|
|
|
self.visible_area:setSizeTo(self.dimen)
|
2014-08-06 14:06:34 +00:00
|
|
|
if self.ui.document.configurable.writing_direction == 0 then
|
|
|
|
-- starts from left top of page_area
|
|
|
|
self.visible_area.x = self.page_area.x
|
|
|
|
self.visible_area.y = self.page_area.y
|
|
|
|
else
|
|
|
|
-- start from right top of page_area
|
|
|
|
self.visible_area.x = self.page_area.x + self.page_area.w - self.visible_area.w
|
|
|
|
self.visible_area.y = self.page_area.y
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
-- and recalculate it according to page size
|
|
|
|
self.visible_area:offsetWithin(self.page_area, 0, 0)
|
|
|
|
-- clear dim area
|
|
|
|
self.dim_area.w = 0
|
|
|
|
self.dim_area.h = 0
|
|
|
|
self.ui:handleEvent(
|
|
|
|
Event:new("ViewRecalculate", self.visible_area, self.page_area))
|
|
|
|
else
|
|
|
|
self.visible_area:setSizeTo(self.dimen)
|
|
|
|
end
|
|
|
|
self.state.offset = Geom:new{x = 0, y = 0}
|
|
|
|
if self.dimen.h > self.visible_area.h then
|
|
|
|
self.state.offset.y = (self.dimen.h - self.visible_area.h) / 2
|
|
|
|
end
|
|
|
|
if self.dimen.w > self.visible_area.w then
|
|
|
|
self.state.offset.x = (self.dimen.w - self.visible_area.w) / 2
|
|
|
|
end
|
|
|
|
-- flag a repaint so self:paintTo will be called
|
Enable HW dithering in a few key places (#4541)
* Enable HW dithering on supported devices (Clara HD, Forma; Oasis 2, PW4)
* FileManager and co. (where appropriate, i.e., when covers are shown)
* Book Status
* Reader, where appropriate:
* CRe: on pages whith image content (for over 7.5% of the screen area, should hopefully leave stuff like bullet points or small scene breaks alone).
* Other engines: on user-request (in the gear tab of the bottom menu), via the new "Dithering" knob (will only appear on supported devices).
* ScreenSaver
* ImageViewer
* Minimize repaints when flash_ui is enabled (by, almost everywhere, only repainting the flashing element, and not the toplevel window which hosts it).
(The first pass of this involved fixing a few Button instances whose show_parent was wrong, in particular, chevrons in the FM & TopMenu).
* Hunted down a few redundant repaints (unneeded setDirty("all") calls),
either by switching the widget to nil when only a refresh was needed, and not a repaint,
or by passing the appropritate widget to setDirty.
(Note to self: Enable *verbose* debugging to catch broken setDirty calls via its post guard).
There were also a few instances of 'em right behind a widget close.
* Don't repaint the underlying widget when initially showing TopMenu & ConfigDialog.
We unfortunately do need to do it when switching tabs, because of their variable heights.
* On Kobo, disabled the extra and completely useless full refresh before suspend/reboot/poweroff, as well as on resume. No more double refreshes!
* Fix another debug guard in Kobo sysfs_light
* Switch ImageWidget & ImageViewer mostly to "ui" updates, which will be better suited to image content pretty much everywhere, REAGL or not.
PS: (Almost :100: commits! :D)
2019-02-07 00:14:37 +00:00
|
|
|
-- NOTE: This is also unfortunately called during panning, essentially making sure we'll never be using "fast" for pans ;).
|
2014-11-30 00:12:00 +00:00
|
|
|
UIManager:setDirty(self.dialog, "partial")
|
2012-05-18 22:50:26 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:PanningUpdate(dx, dy)
|
2016-12-29 08:10:38 +00:00
|
|
|
logger.dbg("pan by", dx, dy)
|
2014-03-13 13:52:43 +00:00
|
|
|
local old = self.visible_area:copy()
|
|
|
|
self.visible_area:offsetWithin(self.page_area, dx, dy)
|
|
|
|
if self.visible_area ~= old then
|
|
|
|
-- flag a repaint
|
2019-02-11 02:28:46 +00:00
|
|
|
UIManager:setDirty(self.dialog, "partial")
|
2016-12-29 08:10:38 +00:00
|
|
|
logger.dbg("on pan: page_area", self.page_area)
|
|
|
|
logger.dbg("on pan: visible_area", self.visible_area)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui:handleEvent(
|
|
|
|
Event:new("ViewRecalculate", self.visible_area, self.page_area))
|
|
|
|
end
|
|
|
|
return true
|
2012-05-18 22:50:26 +00:00
|
|
|
end
|
|
|
|
|
2014-01-02 03:08:06 +00:00
|
|
|
function ReaderView:PanningStart(x, y)
|
2016-12-29 08:10:38 +00:00
|
|
|
logger.dbg("panning start", x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
if not self.panning_visible_area then
|
|
|
|
self.panning_visible_area = self.visible_area:copy()
|
|
|
|
end
|
|
|
|
self.visible_area = self.panning_visible_area:copy()
|
|
|
|
self.visible_area:offsetWithin(self.page_area, x, y)
|
|
|
|
self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area))
|
2019-02-11 02:28:46 +00:00
|
|
|
UIManager:setDirty(self.dialog, "partial")
|
2014-01-02 03:08:06 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:PanningStop()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.panning_visible_area = nil
|
2014-01-02 03:08:06 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:SetZoomCenter(x, y)
|
2014-03-13 13:52:43 +00:00
|
|
|
local old = self.visible_area:copy()
|
|
|
|
self.visible_area:centerWithin(self.page_area, x, y)
|
|
|
|
if self.visible_area ~= old then
|
|
|
|
self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area))
|
2014-11-30 00:12:00 +00:00
|
|
|
UIManager:setDirty(self.dialog, "partial")
|
2014-03-13 13:52:43 +00:00
|
|
|
end
|
2014-01-02 03:08:06 +00:00
|
|
|
end
|
|
|
|
|
2016-03-27 08:26:37 +00:00
|
|
|
function ReaderView:getViewContext()
|
|
|
|
if self.page_scroll then
|
|
|
|
return self.page_states
|
|
|
|
else
|
|
|
|
return {
|
|
|
|
{
|
|
|
|
page = self.state.page,
|
|
|
|
pos = self.state.pos,
|
|
|
|
zoom = self.state.zoom,
|
|
|
|
rotation = self.state.rotation,
|
|
|
|
gamma = self.state.gamma,
|
|
|
|
offset = self.state.offset:copy(),
|
|
|
|
bbox = self.state.bbox,
|
|
|
|
},
|
|
|
|
self.visible_area:copy(),
|
|
|
|
self.page_area:copy(),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:restoreViewContext(ctx)
|
|
|
|
if self.page_scroll then
|
|
|
|
self.page_states = ctx
|
|
|
|
else
|
|
|
|
self.state = ctx[1]
|
|
|
|
self.visible_area = ctx[2]
|
|
|
|
self.page_area = ctx[3]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-12-28 03:32:42 +00:00
|
|
|
-- NOTE: This is just a shim for koptoptions, because we want to be able to pass an optional second argument to SetScreenMode...
|
|
|
|
-- This is also used as a sink for gsensor input events, because we can only send a single event per input,
|
|
|
|
-- and we need to cover both CRe & KOpt...
|
|
|
|
function ReaderView:onSwapScreenMode(new_mode, rotation)
|
|
|
|
-- Don't do anything if an explicit rotation was requested, but it hasn't actually changed,
|
|
|
|
-- because we may be sending this event *right before* a ChangeScreenMode in CRe (gyro)
|
|
|
|
if rotation ~= nil and rotation ~= true and rotation == Screen:getRotationMode() then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
-- CRe
|
|
|
|
self.ui:handleEvent(Event:new("ChangeScreenMode", new_mode, rotation or true))
|
|
|
|
-- KOpt (On CRe, since it's redundant (RR:onChangeScreenMode already sends one), this'll get discarded early)
|
|
|
|
self.ui:handleEvent(Event:new("SetScreenMode", new_mode, rotation or true))
|
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:onSetScreenMode(new_mode, rotation, noskip)
|
|
|
|
-- Don't do anything if an explicit rotation was requested, but it hasn't actually changed,
|
|
|
|
-- because we may be sending this event *right after* a ChangeScreenMode in CRe (gsensor)
|
|
|
|
-- We only want to let the onReadSettings one go through, otherwise the testsuite blows up...
|
|
|
|
if noskip == nil and rotation ~= nil and rotation ~= true and rotation == Screen:getRotationMode() then
|
|
|
|
return true
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
if new_mode == "landscape" or new_mode == "portrait" then
|
|
|
|
self.screen_mode = new_mode
|
2018-12-28 03:32:42 +00:00
|
|
|
-- NOTE: Hacky hack! If rotation is "true", that's actually an "interactive" flag for setScreenMode
|
|
|
|
-- FIXME: That's because we can't store nils in a table, which is what Event:new attempts to do ;).
|
|
|
|
-- c.f., https://stackoverflow.com/q/7183998/ & http://lua-users.org/wiki/VarargTheSecondClassCitizen
|
|
|
|
-- With a fixed Event implementation, we'd instead stick "interactive" in a third argument,
|
|
|
|
-- which we could happily pass while still keeping rotation nil ;).
|
|
|
|
if rotation ~= nil and rotation ~= true then
|
2014-03-13 13:52:43 +00:00
|
|
|
Screen:setRotationMode(rotation)
|
|
|
|
else
|
2018-12-28 03:32:42 +00:00
|
|
|
Screen:setScreenMode(new_mode, rotation)
|
2014-03-13 13:52:43 +00:00
|
|
|
end
|
2014-12-05 21:25:32 +00:00
|
|
|
UIManager:setDirty(self.dialog, "full")
|
2016-12-04 06:57:57 +00:00
|
|
|
local new_screen_size = Screen:getSize()
|
|
|
|
self.ui:handleEvent(Event:new("SetDimensions", new_screen_size))
|
|
|
|
self.ui:onScreenResize(new_screen_size)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
|
|
|
end
|
2018-12-28 03:32:42 +00:00
|
|
|
self.cur_rotation_mode = Screen:getRotationMode()
|
2014-03-13 13:52:43 +00:00
|
|
|
return true
|
2013-02-02 08:46:06 +00:00
|
|
|
end
|
|
|
|
|
2012-06-12 16:14:23 +00:00
|
|
|
function ReaderView:onSetDimensions(dimensions)
|
2014-03-13 13:52:43 +00:00
|
|
|
self:resetLayout()
|
|
|
|
self.dimen = dimensions
|
|
|
|
-- recalculate view
|
|
|
|
self:recalculate()
|
2013-02-23 18:25:57 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:onRestoreDimensions(dimensions)
|
2014-03-13 13:52:43 +00:00
|
|
|
self:resetLayout()
|
|
|
|
self.dimen = dimensions
|
|
|
|
-- recalculate view
|
|
|
|
self:recalculate()
|
2012-06-12 16:14:23 +00:00
|
|
|
end
|
|
|
|
|
2013-02-23 18:25:57 +00:00
|
|
|
function ReaderView:onSetFullScreen(full_screen)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.footer_visible = not full_screen
|
|
|
|
self.ui:handleEvent(Event:new("SetDimensions", Screen:getSize()))
|
2013-02-23 18:25:57 +00:00
|
|
|
end
|
|
|
|
|
2016-03-27 22:39:47 +00:00
|
|
|
function ReaderView:onSetScrollMode(page_scroll)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.page_scroll = page_scroll
|
|
|
|
self:recalculate()
|
|
|
|
self.ui:handleEvent(Event:new("InitScrollPageStates"))
|
2013-03-10 06:23:26 +00:00
|
|
|
end
|
|
|
|
|
2012-10-09 22:26:01 +00:00
|
|
|
function ReaderView:onReadSettings(config)
|
2014-07-17 17:22:54 +00:00
|
|
|
local screen_mode
|
2014-03-13 13:52:43 +00:00
|
|
|
self.render_mode = config:readSetting("render_mode") or 0
|
2014-07-17 17:22:54 +00:00
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
screen_mode = config:readSetting("screen_mode") or G_reader_settings:readSetting("kopt_screen_mode") or "portrait"
|
|
|
|
else
|
|
|
|
screen_mode = config:readSetting("screen_mode") or G_reader_settings:readSetting("copt_screen_mode") or "portrait"
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
if screen_mode then
|
|
|
|
Screen:setScreenMode(screen_mode)
|
2018-12-28 03:32:42 +00:00
|
|
|
self:onSetScreenMode(screen_mode, config:readSetting("rotation_mode"), true)
|
2014-03-13 13:52:43 +00:00
|
|
|
end
|
|
|
|
self.state.gamma = config:readSetting("gamma") or DGLOBALGAMMA
|
|
|
|
local full_screen = config:readSetting("kopt_full_screen") or self.document.configurable.full_screen
|
2016-07-24 00:57:29 +00:00
|
|
|
if full_screen == 0 then
|
2016-04-28 07:02:15 +00:00
|
|
|
self.footer_visible = false
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
self:resetLayout()
|
|
|
|
local page_scroll = config:readSetting("kopt_page_scroll") or self.document.configurable.page_scroll
|
|
|
|
self.page_scroll = page_scroll == 1 and true or false
|
|
|
|
self.highlight.saved = config:readSetting("highlight") or {}
|
2017-05-22 14:21:23 +00:00
|
|
|
self.page_overlap_style = config:readSetting("page_overlap_style") or G_reader_settings:readSetting("page_overlap_style") or "dim"
|
2012-10-09 22:26:01 +00:00
|
|
|
end
|
|
|
|
|
2012-05-18 22:50:26 +00:00
|
|
|
function ReaderView:onPageUpdate(new_page_no)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.state.page = new_page_no
|
|
|
|
self:recalculate()
|
|
|
|
self.highlight.temp = {}
|
2016-07-13 06:53:23 +00:00
|
|
|
UIManager:nextTick(self.autoSaveSettings)
|
2012-05-18 22:50:26 +00:00
|
|
|
end
|
|
|
|
|
2012-06-05 07:23:36 +00:00
|
|
|
function ReaderView:onPosUpdate(new_pos)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.state.pos = new_pos
|
|
|
|
self:recalculate()
|
|
|
|
self.highlight.temp = {}
|
2016-07-13 06:53:23 +00:00
|
|
|
UIManager:nextTick(self.autoSaveSettings)
|
2012-06-05 07:23:36 +00:00
|
|
|
end
|
|
|
|
|
2012-11-26 07:30:24 +00:00
|
|
|
function ReaderView:onZoomUpdate(zoom)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.state.zoom = zoom
|
|
|
|
self:recalculate()
|
|
|
|
self.highlight.temp = {}
|
2012-05-18 22:50:26 +00:00
|
|
|
end
|
|
|
|
|
2012-12-02 09:09:32 +00:00
|
|
|
function ReaderView:onBBoxUpdate(bbox)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.use_bbox = bbox and true or false
|
2012-12-02 09:09:32 +00:00
|
|
|
end
|
|
|
|
|
2012-05-18 22:50:26 +00:00
|
|
|
function ReaderView:onRotationUpdate(rotation)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.state.rotation = rotation
|
|
|
|
self:recalculate()
|
2012-05-18 22:50:26 +00:00
|
|
|
end
|
|
|
|
|
2013-02-20 06:32:51 +00:00
|
|
|
function ReaderView:onGammaUpdate(gamma)
|
2014-03-13 13:52:43 +00:00
|
|
|
self.state.gamma = gamma
|
|
|
|
if self.page_scroll then
|
|
|
|
self.ui:handleEvent(Event:new("UpdateScrollPageGamma", gamma))
|
|
|
|
end
|
2013-01-05 14:28:14 +00:00
|
|
|
end
|
|
|
|
|
2013-04-20 08:17:38 +00:00
|
|
|
function ReaderView:onFontSizeUpdate()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui:handleEvent(Event:new("ReZoom"))
|
2013-04-20 08:17:38 +00:00
|
|
|
end
|
|
|
|
|
2013-04-14 07:16:42 +00:00
|
|
|
function ReaderView:onDefectSizeUpdate()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui:handleEvent(Event:new("ReZoom"))
|
2013-04-14 07:16:42 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:onPageCrop()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui:handleEvent(Event:new("ReZoom"))
|
2013-04-14 07:16:42 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ReaderView:onMarginUpdate()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui:handleEvent(Event:new("ReZoom"))
|
2013-04-14 07:16:42 +00:00
|
|
|
end
|
|
|
|
|
2013-01-07 12:05:48 +00:00
|
|
|
function ReaderView:onSetViewMode(new_mode)
|
2017-10-02 22:31:14 +00:00
|
|
|
if new_mode ~= self.view_mode then
|
|
|
|
self.view_mode = new_mode
|
|
|
|
self.ui.document:setViewMode(new_mode)
|
|
|
|
self.ui:handleEvent(Event:new("ChangeViewMode"))
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
return true
|
2013-01-05 14:28:14 +00:00
|
|
|
end
|
|
|
|
|
2013-12-27 15:18:16 +00:00
|
|
|
function ReaderView:onSaveSettings()
|
2014-03-13 13:52:43 +00:00
|
|
|
self.ui.doc_settings:saveSetting("render_mode", self.render_mode)
|
|
|
|
self.ui.doc_settings:saveSetting("screen_mode", self.screen_mode)
|
|
|
|
self.ui.doc_settings:saveSetting("rotation_mode", self.cur_rotation_mode)
|
|
|
|
self.ui.doc_settings:saveSetting("gamma", self.state.gamma)
|
2014-04-02 20:59:17 +00:00
|
|
|
self.ui.doc_settings:saveSetting("highlight", self.highlight.saved)
|
2014-11-17 13:44:13 +00:00
|
|
|
self.ui.doc_settings:saveSetting("page_overlap_style", self.page_overlap_style)
|
2012-10-09 22:26:01 +00:00
|
|
|
end
|
2013-10-18 20:38:07 +00:00
|
|
|
|
2014-10-15 12:31:24 +00:00
|
|
|
function ReaderView:getRenderModeMenuTable()
|
|
|
|
local view = self
|
|
|
|
local function make_mode(text, mode)
|
|
|
|
return {
|
|
|
|
text = text,
|
|
|
|
checked_func = function() return view.render_mode == mode end,
|
|
|
|
callback = function() view.render_mode = mode end,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
return {
|
|
|
|
text = _("DjVu render mode"),
|
|
|
|
sub_item_table = {
|
|
|
|
make_mode(_("COLOUR (works for both colour and b&w pages)"), 0),
|
|
|
|
make_mode(_("BLACK & WHITE (for b&w pages only, much faster)"), 1),
|
|
|
|
make_mode(_("COLOUR ONLY (slightly faster than COLOUR)"), 2),
|
|
|
|
make_mode(_("MASK ONLY (for b&w pages only)"), 3),
|
|
|
|
make_mode(_("COLOUR BACKGROUND (show only background)"), 4),
|
|
|
|
make_mode(_("COLOUR FOREGROUND (show only foreground)"), 5),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2014-11-17 13:44:13 +00:00
|
|
|
local page_overlap_styles = {
|
|
|
|
arrow = _("Arrow"),
|
|
|
|
dim = _("Gray out"),
|
|
|
|
}
|
|
|
|
|
2019-02-03 10:17:27 +00:00
|
|
|
function ReaderView:genOverlapStyleMenu(overlap_enabled_func)
|
2014-11-17 13:44:13 +00:00
|
|
|
local view = self
|
|
|
|
local get_overlap_style = function(style)
|
|
|
|
return {
|
|
|
|
text = page_overlap_styles[style],
|
2019-02-03 10:17:27 +00:00
|
|
|
enabled_func = overlap_enabled_func,
|
2014-11-17 13:44:13 +00:00
|
|
|
checked_func = function()
|
|
|
|
return view.page_overlap_style == style
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
view.page_overlap_style = style
|
2017-05-22 14:21:23 +00:00
|
|
|
end,
|
|
|
|
hold_callback = function()
|
|
|
|
UIManager:show(ConfirmBox:new{
|
|
|
|
text = T(
|
|
|
|
_("Set default overlap style to %1?"),
|
|
|
|
style
|
|
|
|
),
|
|
|
|
ok_callback = function()
|
|
|
|
view.page_overlap_style = style
|
|
|
|
G_reader_settings:saveSetting("page_overlap_style", style)
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
end,
|
2014-11-17 13:44:13 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
return {
|
|
|
|
get_overlap_style("arrow"),
|
|
|
|
get_overlap_style("dim"),
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2016-02-17 06:36:40 +00:00
|
|
|
function ReaderView:onCloseDocument()
|
|
|
|
self.hinting = false
|
|
|
|
-- stop any in fly HintPage event
|
|
|
|
UIManager:unschedule(self.emitHintPageEvent)
|
|
|
|
end
|
|
|
|
|
2016-07-13 06:53:23 +00:00
|
|
|
function ReaderView:onReaderReady()
|
|
|
|
if DAUTO_SAVE_PAGING_COUNT ~= nil then
|
|
|
|
if DAUTO_SAVE_PAGING_COUNT <= 0 then
|
|
|
|
self.autoSaveSettings = function()
|
|
|
|
self.ui:saveSettings()
|
|
|
|
end
|
|
|
|
else
|
|
|
|
self.autoSaveSettings = function()
|
|
|
|
if self.auto_save_paging_count == DAUTO_SAVE_PAGING_COUNT then
|
|
|
|
self.ui:saveSettings()
|
|
|
|
self.auto_save_paging_count = 0
|
|
|
|
else
|
|
|
|
self.auto_save_paging_count = self.auto_save_paging_count + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-10-18 20:38:07 +00:00
|
|
|
return ReaderView
|