Dual pages: shown as 2 columns on a single page

Rework Dual pages code so that the view is considered
a single page number, so it looks more like 2-columns
on a single page.
This solves a few issues like:
- Page number and count are consistent between top
  and bottom status bars
- SkimTo -1/+1 doing nothing every other tap
- Statistics being wrong (like "Pages read" never
  going over half of the book page count)
reviewable/pr7211/r4
poire-z 3 years ago
parent 7779e2d8e7
commit 05126b94b6

@ -10,16 +10,14 @@ local ReaderCoptListener = EventListener:new{}
function ReaderCoptListener:onReadSettings(config)
local view_mode = config:readSetting("copt_view_mode") or
G_reader_settings:readSetting("copt_view_mode")
if view_mode == 0 then
self.ui:registerPostReadyCallback(function()
self.view:onSetViewMode("page")
end)
elseif view_mode == 1 then
self.ui:registerPostReadyCallback(function()
self.view:onSetViewMode("scroll")
end)
end
G_reader_settings:readSetting("copt_view_mode") or 0 -- default to "page" mode
local view_mode_name = view_mode == 0 and "page" or "scroll"
-- Let crengine know of the view mode before rendering, as it can
-- cause a rendering change (2-pages would become 1-page in
-- scroll mode).
self.ui.document:setViewMode(view_mode_name)
-- ReaderView is the holder of the view_mode state
self.view.view_mode = view_mode_name
-- crengine top status bar can only show author and title together
self.title = G_reader_settings:readSetting("cre_header_title") or 1

@ -873,16 +873,20 @@ function ReaderHighlight:onHoldPan(_, ges)
elseif self.hold_pos.x <= screen_half_width and is_in_next_page_corner then
return true
end
local cur_page = self.ui.document:getCurrentPage()
-- To be able to browse half-page when 2 visible pages as 1 page number,
-- we must work with internal page numbers
local cur_page = self.ui.document:getCurrentPage(true)
local restore_page_mode_xpointer = self.ui.document:getXPointer() -- top of current page
self.ui.document.no_page_sync = true -- avoid CreDocument:drawCurrentViewByPage() to resync page
self.restore_page_mode_func = function()
self.ui.document.no_page_sync = nil
self.ui.rolling:onGotoXPointer(restore_page_mode_xpointer, self.selected_text_start_xpointer)
end
if is_in_next_page_corner then -- bottom right corner in LTR UI
self.ui.rolling:_gotoPage(cur_page + 1, true) -- no odd left page enforcement
self.ui.rolling:_gotoPage(cur_page + 1, true, true) -- no odd left page enforcement
self.hold_pos.x = self.hold_pos.x - screen_half_width
else -- top left corner in RTL UI
self.ui.rolling:_gotoPage(cur_page - 1, true) -- no odd left page enforcement
self.ui.rolling:_gotoPage(cur_page - 1, true, true) -- no odd left page enforcement
self.hold_pos.x = self.hold_pos.x + screen_half_width
end
UIManager:setDirty(self.dialog, "ui")

@ -558,7 +558,7 @@ function ReaderRolling:onResume()
end
function ReaderRolling:onGotoNextChapter()
local visible_page_count = self.ui.document:getVisiblePageCount()
local visible_page_count = self.ui.document:getVisiblePageNumberCount()
local pageno = self.current_page + (visible_page_count > 1 and 1 or 0)
local new_page
if self.ui.document:hasHiddenFlows() then
@ -664,7 +664,7 @@ function ReaderRolling:onGotoXPointer(xp, marker_xp)
-- In the middle margin, on the right of text
-- Same trick as below, assuming page2_x is equal to page 1 right x
screen_x = math.floor(Screen:getWidth() * 0.5)
local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage()+1)
local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage(true)+1)
marker_w = page2_x + marker_w - screen_x
screen_x = screen_x - marker_w
else
@ -678,7 +678,7 @@ function ReaderRolling:onGotoXPointer(xp, marker_xp)
-- This is a bit tricky with how the middle margin is sized
-- by crengine (see LVDocView::updateLayout() in lvdocview.cpp)
screen_x = math.floor(Screen:getWidth() * 0.5)
local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage()+1)
local page2_x = self.ui.document:getPageOffsetX(self.ui.document:getCurrentPage(true)+1)
marker_w = page2_x + marker_w - screen_x
end
end
@ -767,7 +767,7 @@ function ReaderRolling:onGotoViewRel(diff)
self.ui:handleEvent(Event:new("EndOfBook"))
end
elseif self.view.view_mode == "page" then
local page_count = self.ui.document:getVisiblePageCount()
local page_count = self.ui.document:getVisiblePageNumberCount()
local old_page = self.current_page
-- we're in paged mode, so round up
if diff > 0 then
@ -970,8 +970,9 @@ function ReaderRolling:_gotoPercent(new_percent)
end
end
function ReaderRolling:_gotoPage(new_page, free_first_page)
if self.ui.document:getVisiblePageCount() > 1 and not free_first_page then
function ReaderRolling:_gotoPage(new_page, free_first_page, internal)
if self.ui.document:getVisiblePageCount() > 1 and not free_first_page
and (internal or self.ui.document:getVisiblePageNumberCount() == 2) then
-- Ensure we always have the first of the two pages odd
if self.odd_or_even_first_page == 1 then -- odd
if band(new_page, 1) == 0 then
@ -985,7 +986,7 @@ function ReaderRolling:_gotoPage(new_page, free_first_page)
end
end
end
self.ui.document:gotoPage(new_page)
self.ui.document:gotoPage(new_page, internal)
if self.view.view_mode == "page" then
self.ui:handleEvent(Event:new("PageUpdate", self.ui.document:getCurrentPage()))
else
@ -1012,16 +1013,15 @@ end
--]]
function ReaderRolling:onSetVisiblePages(visible_pages)
-- crengine may decide to not ensure the value we request
-- (for example, in 2-pages mode, it may stop being ensured
-- when we increase the font size up to a point where a line
-- would contain less that 20 glyphs).
-- crengine may enforce visible_page=1 when:
-- - not in page mode but in scroll mode
-- - screen w/h < 6/5
-- - w < 20*em
-- We nevertheless update the setting (that will saved) with what
-- the user has requested - and not what crengine has enforced.
-- By default, crengine may decide to not ensure the value we request
-- (for example, in 2-pages mode, it may stop being ensured when we
-- increase the font size up to a point where a line would contain
-- less that 20 glyphs).
-- But we have CreDocument:setVisiblePageCount() provide only_if_sane=false
-- so these checks are not done.
-- We nevertheless update the setting (that will be saved) with what
-- the user has requested - and not what crengine has enforced, and
-- always query crengine for if it ends up ensuring it or not.
self.visible_pages = visible_pages
local prev_visible_pages = self.ui.document:getVisiblePageCount()
self.ui.document:setVisiblePageCount(visible_pages)

@ -210,6 +210,13 @@ function CreDocument:setupDefaultView()
self._document:setIntProperty("crengine.image.scaling.zoomout.inline.mode", 0)
self._document:setIntProperty("crengine.image.scaling.zoomout.inline.scale", 1)
-- If switching to two pages on view, we want it to behave like two columns
-- and each view to be a single page number (instead of the default of two).
-- This ensures that page number and count are consistent between top and
-- bottom status bars, that SkimTo -1/+1 don't do nothing every other tap,
-- and that reading statistics do not see half of the pages never read.
self._document:setIntProperty("window.pages.two.visible.as.one.page.number", 1)
-- set fallback font faces (this was formerly done in :init(), but it
-- affects crengine calcGlobalSettingsHash() and would invalidate the
-- cache from the main currently being read document when we just
@ -312,8 +319,8 @@ function CreDocument:setHideNonlinearFlows(hide_nonlinear_flows)
end
end
function CreDocument:getPageCount()
return self._document:getPages()
function CreDocument:getPageCount(internal)
return self._document:getPages(internal)
end
-- Whether the document has any non-linear flow to care about
@ -693,7 +700,14 @@ function CreDocument:drawCurrentViewByPos(target, x, y, rect, pos)
end
function CreDocument:drawCurrentViewByPage(target, x, y, rect, page)
self._document:gotoPage(page)
if not self.no_page_sync then
-- Avoid syncing page when this flag is set, when selecting text
-- across pages in 2-page mode and flipping half the screen
-- (currently only set by ReaderHighlight:onHoldPan())
-- self._document:gotoPage(page)
-- This allows this method to not be cached by cre call cache
self:gotoPage(page)
end
self:drawCurrentView(target, x, y, rect)
end
@ -750,8 +764,9 @@ function CreDocument:getScreenPositionFromXPointer(xp)
if self._view_mode == self.PAGE_VIEW_MODE then
if self:getVisiblePageCount() > 1 then
-- Correct coordinates if on the 2nd page in 2-pages mode
local next_page = self:getCurrentPage() + 1
if next_page <= self:getPageCount() then
-- getPageStartY() and getPageOffsetX() expects internal page numbers
local next_page = self:getCurrentPage(true) + 1
if next_page <= self:getPageCount(true) then
local next_top_y = self._document:getPageStartY(next_page)
if doc_y >= next_top_y then
screen_y = doc_y - next_top_y
@ -831,9 +846,9 @@ function CreDocument:gotoPos(pos)
self._document:gotoPos(pos)
end
function CreDocument:gotoPage(page)
function CreDocument:gotoPage(page, internal)
logger.dbg("CreDocument: goto page", page, "flow", self:getPageFlow(page))
self._document:gotoPage(page)
self._document:gotoPage(page, internal)
end
function CreDocument:gotoLink(link)
@ -851,8 +866,8 @@ function CreDocument:goForward(link)
self._document:goForward()
end
function CreDocument:getCurrentPage()
return self._document:getCurrentPage()
function CreDocument:getCurrentPage(internal)
return self._document:getCurrentPage(internal)
end
function CreDocument:setFontFace(new_font_face)
@ -1145,6 +1160,8 @@ function CreDocument:setTxtPreFormatted(enabled)
self._document:setIntProperty("crengine.file.txt.preformatted", enabled)
end
-- get crengine internal visible page count (to be used when doing specific
-- screen position handling)
function CreDocument:getVisiblePageCount()
return self._document:getVisiblePageCount()
end
@ -1154,6 +1171,11 @@ function CreDocument:setVisiblePageCount(new_count)
self._document:setVisiblePageCount(new_count, false)
end
-- get visible page number count (to be used when only interested in page numbers)
function CreDocument:getVisiblePageNumberCount()
return self._document:getVisiblePageNumberCount()
end
function CreDocument:setBatteryState(state)
logger.dbg("CreDocument: set battery state", state)
self._document:setBatteryState(state)
@ -1519,6 +1541,7 @@ function CreDocument:setupCallCache()
local cache_global = false
local set_tag = nil
local set_arg = nil
local set_arg2 = nil
local is_cached = false
-- Assume all set* may change rendering
@ -1541,10 +1564,14 @@ function CreDocument:setupCallCache()
elseif name == "findText" then add_buffer_trash = true
-- These may change page/pos
elseif name == "gotoPage" then set_tag = "page" ; set_arg = 2
elseif name == "gotoPage" then set_tag = "page" ; set_arg = 2 ; set_arg2 = 3
elseif name == "gotoPos" then set_tag = "pos" ; set_arg = 2
elseif name == "drawCurrentViewByPage" then set_tag = "page" ; set_arg = 6
elseif name == "drawCurrentViewByPos" then set_tag = "pos" ; set_arg = 6
-- elseif name == "drawCurrentViewByPage" then set_tag = "page" ; set_arg = 6
-- drawCurrentViewByPage() has some tweaks when browsing half-pages for
-- text selection in two-pages mode: no need to wrap it, as it uses
-- internally 2 other functions that are themselves wrapped
-- gotoXPointer() is for cre internal fixup, we always use gotoPage/Pos
-- (goBack, goForward, gotoLink are not used)
@ -1554,6 +1581,7 @@ function CreDocument:setupCallCache()
elseif name == "getCurrentPage" then no_wrap = true
elseif name == "getCurrentPos" then no_wrap = true
elseif name == "getVisiblePageCount" then no_wrap = true
elseif name == "getVisiblePageNumberCount" then no_wrap = true
elseif name == "getCoverPageImage" then no_wrap = true
elseif name == "getDocumentFileContent" then no_wrap = true
elseif name == "getHTMLFromXPointer" then no_wrap = true
@ -1611,6 +1639,12 @@ function CreDocument:setupCallCache()
self[name] = function(...)
if do_log then logger.dbg("callCache:", name, "setting tag") end
local val = select(set_arg, ...)
if set_arg2 then
local val2 = select(set_arg2, ...)
if val2 ~= nil then
val = val .. tostring(val2)
end
end
self._callCacheSetCurrentTag(set_tag .. val)
return func(...)
end

@ -33,7 +33,7 @@ local CreOptions = {
},
{
name = "visible_pages",
name_text = _("Dual Pages"),
name_text = _("Two Columns"),
toggle = {_("off"), _("on")},
values = {1, 2},
default_value = 1,
@ -55,8 +55,8 @@ local CreOptions = {
-- and Device.screen:getScreenMode() == "landscape"
end,
name_text_hold_callback = optionsutil.showValues,
help_text = _([[In landscape mode, you can choose to display one or two pages of the book on the screen.
Note that this may not be ensured under some conditions: in scroll mode, when a very big font size is used, or on devices with a very low aspect ratio.]]),
help_text = _([[Render the document on half the screen width and display two pages at once with a single page number. This makes it look like two columns.
This is disabled in scroll mode. Switching from page mode with two columns to scroll mode will cause the document to be re-rendered.]]),
},
}
},

Loading…
Cancel
Save