Merge pull request #2375 from koreader/houqp-master

readerpaging(fix): handle edge cases where paging pan will crash the reader
pull/2380/head
Huang Xin 8 years ago committed by GitHub
commit b16a33a232

@ -5,11 +5,6 @@ source "${CI_DIR}/common.sh"
set +e
travis_retry make coverage
pushd koreader-*/koreader
luajit $(which luacov-coveralls) -v
popd
if [ ${TRAVIS_PULL_REQUEST} = false ] && [ ${TRAVIS_BRANCH} = 'master' ]; then
travis_retry luarocks --local install ldoc
# get deploy key for doc repo
@ -36,7 +31,12 @@ if [ ${TRAVIS_PULL_REQUEST} = false ] && [ ${TRAVIS_BRANCH} = 'master' ]; then
git -c user.name="KOReader build bot" -c user.email="non-reply@koreader.rocks" \
commit -a --amend -m 'Automated documentation build from travis-ci.'
git push -f --quiet origin gh-pages > /dev/null
echo -e "\n${ANSI_GREEN}Document update pushed."
echo -e "\n${ANSI_GREEN}Documentation update pushed."
else
echo -e "\n${ANSI_GREEN}Not on official master branch, skip document update."
echo -e "\n${ANSI_GREEN}Not on official master branch, skip documentation update."
fi
travis_retry make coverage
pushd koreader-*/koreader
luajit $(which luacov-coveralls)
popd

@ -104,6 +104,7 @@ function FileManagerMenu:setUpdateItemTable()
callback = function()
local open_last = G_reader_settings:readSetting("open_last") or false
G_reader_settings:saveSetting("open_last", not open_last)
G_reader_settings:flush()
end
})
if Device.isKobo() then
@ -121,6 +122,7 @@ function FileManagerMenu:setUpdateItemTable()
G_reader_settings:delSetting(
"use_lastfile_as_screensaver")
end
G_reader_settings:flush()
end
},
{
@ -130,6 +132,7 @@ function FileManagerMenu:setUpdateItemTable()
local function save_folder_path()
G_reader_settings:saveSetting(
"screensaver_folder", ss_folder_path_input:getInputText())
G_reader_settings:flush()
UIManager:close(ss_folder_path_input)
end
local curr_path = G_reader_settings:readSetting("screensaver_folder")

@ -10,6 +10,20 @@ local Math = require("optmath")
local DEBUG = require("dbg")
local _ = require("gettext")
local function copyPageState(page_state)
return {
page = page_state.page,
zoom = page_state.zoom,
rotation = page_state.rotation,
gamma = page_state.gamma,
offset = page_state.offset:copy(),
visible_area = page_state.visible_area:copy(),
page_area = page_state.page_area:copy(),
}
end
local ReaderPaging = InputContainer:new{
current_page = 0,
number_of_pages = 0,
@ -555,9 +569,12 @@ function ReaderPaging:getPrevPageState(blank_area, offset)
end
function ReaderPaging:updateTopPageState(state, blank_area, offset)
local visible_area = Geom:new{x = 0, y = 0}
visible_area.w, visible_area.h = blank_area.w, blank_area.h
visible_area.x, visible_area.y = state.visible_area.x, state.visible_area.y
local visible_area = Geom:new{
x = state.visible_area.x,
y = state.visible_area.y,
w = blank_area.w,
h = blank_area.h,
}
if state.page == self.number_of_pages then
visible_area:offsetWithin(state.page_area, offset.x, offset.y)
else
@ -566,14 +583,15 @@ function ReaderPaging:updateTopPageState(state, blank_area, offset)
-- shrink blank area by the height of visible area
blank_area.h = blank_area.h - visible_area.h
state.visible_area = visible_area
return state
end
function ReaderPaging:updateBottomPageState(state, blank_area, offset)
local visible_area = Geom:new{x = 0, y = 0}
visible_area.w, visible_area.h = blank_area.w, blank_area.h
visible_area.x = state.page_area.x
visible_area.y = state.visible_area.y + state.visible_area.h - visible_area.h
local visible_area = Geom:new{
x = state.page_area.x,
y = state.visible_area.y + state.visible_area.h - blank_area.h,
w = blank_area.w,
h = blank_area.h,
}
if state.page == 1 then
visible_area:offsetWithin(state.page_area, offset.x, offset.y)
else
@ -582,7 +600,6 @@ function ReaderPaging:updateBottomPageState(state, blank_area, offset)
-- shrink blank area by the height of visible area
blank_area.h = blank_area.h - visible_area.h
state.visible_area = visible_area
return state
end
function ReaderPaging:genPageStatesFromTop(top_page_state, blank_area, offset)
@ -592,16 +609,18 @@ function ReaderPaging:genPageStatesFromTop(top_page_state, blank_area, offset)
-- which will trigger the drawing of next page leaving part of current
-- page undrawn. This should also be true for generating from bottom.
if offset.y < 0 then offset.y = 0 end
local state = self:updateTopPageState(top_page_state, blank_area, offset)
self:updateTopPageState(top_page_state, blank_area, offset)
local page_states = {}
if state.visible_area.h > 0 then
table.insert(page_states, state)
if top_page_state.visible_area.h > 0 then
-- offset does not scroll pass top_page_state
table.insert(page_states, top_page_state)
end
local current_page = state.page
local state
local current_page = top_page_state.page
while blank_area.h > 0 do
blank_area.h = blank_area.h - self.view.page_gap.height
if blank_area.h > 0 then
if self.current_page == self.number_of_pages then break end
if current_page == self.number_of_pages then break end
self:_gotoPage(current_page + 1, "scrolling")
current_page = current_page + 1
state = self:getNextPageState(blank_area, Geom:new{})
@ -614,16 +633,19 @@ end
function ReaderPaging:genPageStatesFromBottom(bottom_page_state, blank_area, offset)
-- scroll up offset should always be less than 0
if offset.y > 0 then offset.y = 0 end
local state = self:updateBottomPageState(bottom_page_state, blank_area, offset)
-- find out number of pages need to be removed from current view
self:updateBottomPageState(bottom_page_state, blank_area, offset)
local page_states = {}
if state.visible_area.h > 0 then
table.insert(page_states, state)
if bottom_page_state.visible_area.h > 0 then
table.insert(page_states, bottom_page_state)
end
local current_page = state.page
-- fill up current view from bottom to top
local state
local current_page = bottom_page_state.page
while blank_area.h > 0 do
blank_area.h = blank_area.h - self.view.page_gap.height
if blank_area.h > 0 then
if self.current_page == 1 then break end
if current_page == 1 then break end
self:_gotoPage(current_page - 1, "scrolling")
current_page = current_page - 1
state = self:getPrevPageState(blank_area, Geom:new{})
@ -634,29 +656,34 @@ function ReaderPaging:genPageStatesFromBottom(bottom_page_state, blank_area, off
end
function ReaderPaging:onScrollPanRel(diff)
if diff == 0 then return true end
DEBUG("pan relative height:", diff)
local offset = Geom:new{x = 0, y = diff}
local blank_area = Geom:new{}
blank_area:setSizeTo(self.view.dimen)
local new_page_states
if diff > 0 then
local first_page_state = table.remove(self.view.page_states, 1)
local offset = Geom:new{
x = 0,
y = diff,
}
self.view.page_states = self:genPageStatesFromTop(first_page_state, blank_area, offset)
end
if diff < 0 then
local last_page_state = table.remove(self.view.page_states)
local offset = Geom:new{
x = 0,
y = diff
}
self.view.page_states = self:genPageStatesFromBottom(last_page_state, blank_area, offset)
-- pan to scroll down
local first_page_state = copyPageState(self.view.page_states[1])
new_page_states = self:genPageStatesFromTop(
first_page_state, blank_area, offset)
elseif diff < 0 then
local last_page_state = copyPageState(
self.view.page_states[#self.view.page_states])
new_page_states = self:genPageStatesFromBottom(
last_page_state, blank_area, offset)
end
if #new_page_states == 0 then
-- if we are already at the top of first page or bottom of the last
-- page, new_page_states will be empty, in this case, nothing to update
return true
end
self.view.page_states = new_page_states
-- update current pageno to the very last part in current view
self:_gotoPage(self.view.page_states[#self.view.page_states].page, "scrolling")
self:_gotoPage(self.view.page_states[#self.view.page_states].page,
"scrolling")
UIManager:setDirty(self.view.dialog, "fast")
return true
end
function ReaderPaging:calculateOverlap()
@ -664,8 +691,10 @@ function ReaderPaging:calculateOverlap()
return self.overlap + footer_height
end
function ReaderPaging:onScrollPageRel(diff)
if diff > 0 then
function ReaderPaging:onScrollPageRel(page_diff)
if page_diff == 0 then return true end
if page_diff > 0 then
-- page down, last page should be moved to top
local last_page_state = table.remove(self.view.page_states)
local last_visible_area = last_page_state.visible_area
if last_page_state.page == self.number_of_pages and
@ -683,7 +712,8 @@ function ReaderPaging:onScrollPageRel(diff)
y = last_visible_area.h - overlap
}
self.view.page_states = self:genPageStatesFromTop(last_page_state, blank_area, offset)
elseif diff < 0 then
elseif page_diff < 0 then
-- page up, first page should be moved to bottom
local blank_area = Geom:new{}
blank_area:setSizeTo(self.view.dimen)
local overlap = self:calculateOverlap()
@ -692,9 +722,8 @@ function ReaderPaging:onScrollPageRel(diff)
x = 0,
y = -first_page_state.visible_area.h + overlap
}
self.view.page_states = self:genPageStatesFromBottom(first_page_state, blank_area, offset)
else
return true
self.view.page_states = self:genPageStatesFromBottom(
first_page_state, blank_area, offset)
end
-- update current pageno to the very last part in current view
self:_gotoPage(self.view.page_states[#self.view.page_states].page, "scrolling")
@ -842,15 +871,16 @@ function ReaderPaging:onGotoPercentage(percentage)
end
function ReaderPaging:updateReadOrder()
local width, height = Screen:getWidth(), Screen:getHeight()
if self.inverse_reading_order then
self.ges_events.TapForward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()*(1-DTAP_ZONE_FORWARD.x-DTAP_ZONE_FORWARD.w),
y = Screen:getHeight()*DTAP_ZONE_FORWARD.y,
w = Screen:getWidth()*DTAP_ZONE_FORWARD.w,
h = Screen:getHeight()*DTAP_ZONE_FORWARD.h,
x = width * (1-DTAP_ZONE_FORWARD.x - DTAP_ZONE_FORWARD.w),
y = height * DTAP_ZONE_FORWARD.y,
w = width * DTAP_ZONE_FORWARD.w,
h = height * DTAP_ZONE_FORWARD.h,
}
}
}
@ -858,22 +888,22 @@ function ReaderPaging:updateReadOrder()
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()*(1-DTAP_ZONE_BACKWARD.x-DTAP_ZONE_BACKWARD.w),
y = Screen:getHeight()*DTAP_ZONE_BACKWARD.y,
w = Screen:getWidth()*DTAP_ZONE_BACKWARD.w,
h = Screen:getHeight()*DTAP_ZONE_BACKWARD.h,
x = width * (1-DTAP_ZONE_BACKWARD.x - DTAP_ZONE_BACKWARD.w),
y = height * DTAP_ZONE_BACKWARD.y,
w = width * DTAP_ZONE_BACKWARD.w,
h = height * DTAP_ZONE_BACKWARD.h,
}
}
}
else
self.ges_events.TapForward = {
self.ges_events.TapForward = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()*DTAP_ZONE_FORWARD.x,
y = Screen:getHeight()*DTAP_ZONE_FORWARD.y,
w = Screen:getWidth()*DTAP_ZONE_FORWARD.w,
h = Screen:getHeight()*DTAP_ZONE_FORWARD.h,
x = width * DTAP_ZONE_FORWARD.x,
y = height * DTAP_ZONE_FORWARD.y,
w = width * DTAP_ZONE_FORWARD.w,
h = height * DTAP_ZONE_FORWARD.h,
}
}
}
@ -881,10 +911,10 @@ function ReaderPaging:updateReadOrder()
GestureRange:new{
ges = "tap",
range = Geom:new{
x = Screen:getWidth()*DTAP_ZONE_BACKWARD.x,
y = Screen:getHeight()*DTAP_ZONE_BACKWARD.y,
w = Screen:getWidth()*DTAP_ZONE_BACKWARD.w,
h = Screen:getHeight()*DTAP_ZONE_BACKWARD.h,
x = width * DTAP_ZONE_BACKWARD.x,
y = height * DTAP_ZONE_BACKWARD.y,
w = width * DTAP_ZONE_BACKWARD.w,
h = height * DTAP_ZONE_BACKWARD.h,
}
}
}

@ -1,18 +1,20 @@
describe("Readerpaging module", function()
local sample_pdf = "spec/front/unit/data/sample.pdf"
local readerui, UIManager, Event
local readerui, UIManager, Event, DocumentRegistry, ReaderUI
local paging
setup(function()
require("commonrequire")
UIManager = require("ui/uimanager")
Event = require("ui/event")
DocumentRegistry = require("document/documentregistry")
ReaderUI = require("apps/reader/readerui")
end)
describe("Page mode", function()
setup(function()
readerui = require("apps/reader/readerui"):new{
document = require("document/documentregistry"):openDocument(sample_pdf),
readerui = ReaderUI:new{
document = DocumentRegistry:openDocument(sample_pdf),
}
paging = readerui.paging
end)
@ -43,8 +45,8 @@ describe("Readerpaging module", function()
purgeDir(DocSettings:getSidecarDir(sample_pdf))
os.remove(DocSettings:getHistoryPath(sample_pdf))
readerui = require("apps/reader/readerui"):new{
document = require("document/documentregistry"):openDocument(sample_pdf),
readerui = ReaderUI:new{
document = DocumentRegistry:openDocument(sample_pdf),
}
paging = readerui.paging
end)
@ -68,5 +70,25 @@ describe("Readerpaging module", function()
readerui.onEndOfBook = nil
UIManager:quit()
end)
it("should scroll withtout crash backward on the first page", function()
local sample_djvu = "spec/front/unit/data/djvu3spec.djvu"
local tmp_readerui = ReaderUI:new{
document = DocumentRegistry:openDocument(sample_djvu),
}
tmp_readerui.paging:onScrollPanRel(-100)
end)
it("should scroll withtout crash forward on the last page", function()
local sample_djvu = "spec/front/unit/data/djvu3spec.djvu"
local tmp_readerui = ReaderUI:new{
document = DocumentRegistry:openDocument(sample_djvu),
}
local paging = tmp_readerui.paging
paging:onGotoPage(tmp_readerui.document:getPageCount())
paging:onScrollPanRel(120)
paging:onScrollPanRel(-1)
paging:onScrollPanRel(120)
end)
end)
end)

@ -272,7 +272,7 @@ describe("ReadHistory module", function()
for i = 1, 500 do -- at most 500 items are stored
assert_item_is(h, i, string.format("%04d", i))
end
for i = 1, 1000 do
rm(to_file(i))
end

Loading…
Cancel
Save