@ -58,6 +58,11 @@ local CreDocument = Document:new{
default_css = " ./data/cr3.css " ,
provider = " crengine " ,
provider_name = " Cool Reader Engine " ,
hide_nonlinear_flows = false ,
flows = { } ,
page_in_flow = { } ,
last_linear_page = nil ,
}
-- NuPogodi, 20.05.12: inspect the zipfile content
@ -283,10 +288,188 @@ function CreDocument:updateColorRendering()
end
end
function CreDocument : setHideNonlinearFlows ( hide_nonlinear_flows )
if hide_nonlinear_flows ~= self.hide_nonlinear_flows then
self.hide_nonlinear_flows = hide_nonlinear_flows
self._document : setIntProperty ( " crengine.doc.nonlinear.pagebreak.force " , self.hide_nonlinear_flows and 1 or 0 )
end
end
function CreDocument : getPageCount ( )
return self._document : getPages ( )
end
-- Whether the document has any non-linear flow to care about
function CreDocument : hasNonLinearFlows ( )
return self._document : hasNonLinearFlows ( )
end
-- Whether non-linear flows (if any) will be hidden
function CreDocument : hasHiddenFlows ( )
return self.flows [ 1 ] ~= nil
end
-- Get the next/prev page number, skipping non-linear flows,
-- i.e. the next/prev page that is either in the current
-- flow or in the linear flow (flow 0)
-- If "page" is 0, these give the initial and final linear pages
function CreDocument : getNextPage ( page )
if self : hasHiddenFlows ( ) then
if page < 0 or page >= self : getPageCount ( ) then
return 0
elseif page == 0 then
return self : getFirstPageInFlow ( 0 )
end
local flow = self : getPageFlow ( page )
local start_page = page + 1
local end_page = self : getLastLinearPage ( )
local test_page = start_page
-- max to ensure at least one iteration
-- (in case the current flow goes after all linear pages)
while test_page <= math.max ( end_page , start_page ) do
local test_page_flow = self : getPageFlow ( test_page )
if test_page_flow == flow or test_page_flow == 0 then
-- same flow as current, or linear flow, this is a "good" page
return test_page
elseif test_page_flow > 0 then
-- some other non-linear flow, skip all pages in this flow
test_page = test_page + self : getTotalPagesInFlow ( test_page_flow )
else
-- went beyond the last page
break
end
end
return 0
else
return Document.getNextPage ( self , page )
end
end
function CreDocument : getPrevPage ( page )
if self : hasHiddenFlows ( ) then
if page < 0 or page > self : getPageCount ( ) then
return 0
elseif page == 0 then
return self : getLastLinearPage ( )
end
local flow = self : getPageFlow ( page )
local start_page = page - 1
local end_page = self : getFirstPageInFlow ( 0 )
local test_page = start_page
-- min to ensure at least one iteration
-- (in case the current flow goes before all linear pages)
while test_page >= math.min ( end_page , start_page ) do
local test_page_flow = self : getPageFlow ( test_page )
if test_page_flow == flow or test_page_flow == 0 then
-- same flow as current, or linear flow, this is a "good" page
return test_page
elseif test_page_flow > 0 then
-- some other non-linear flow, skip all pages in this flow
test_page = self : getFirstPageInFlow ( test_page_flow ) - 1
else
-- went beyond the first page
break
end
end
return 0
else
return Document.getPrevPage ( self , page )
end
end
function CreDocument : getPageFlow ( page )
-- Only report non-linear pages if "hide_nonlinear_flows" is enabled, and in 1-page mode,
-- otherwise all pages are linear (flow 0)
if self.hide_nonlinear_flows and self._view_mode == self.PAGE_VIEW_MODE and self : getVisiblePageCount ( ) == 1 then
return self._document : getPageFlow ( page )
else
return 0
end
end
function CreDocument : getLastLinearPage ( )
return self.last_linear_page
end
function CreDocument : getFirstPageInFlow ( flow )
return self.flows [ flow ] [ 1 ]
end
function CreDocument : getTotalPagesInFlow ( flow )
return self.flows [ flow ] [ 2 ]
end
function CreDocument : getPageNumberInFlow ( page )
if self : hasHiddenFlows ( ) then
return self.page_in_flow [ page ]
else
return page
end
end
function CreDocument : cacheFlows ( )
-- Build the cache tables "flows" and "page_in_flow", if there are
-- any non-linear flows in the source document. Also set the value
-- of "last_linear_page", to possibly speed up counting in documents
-- with many non-linear pages at the end.
-- flows[i] contains {ini, num}, where ini is the first page in flow i,
-- and num is the total number of pages in the flow.
-- page_in_flow[i] contains the number of page i with its flow.
--
-- So, flows[0][1] is the first page in the linear flow,
-- and page_in_flow[flows[0][1]] must be 1, because it is the first
self.flows = { }
self.page_in_flow = { }
if self : hasNonLinearFlows ( ) and self.hide_nonlinear_flows then
for i = 1 , self : getPageCount ( ) do
local flow = self : getPageFlow ( i )
if self.flows [ flow ] ~= nil then
self.flows [ flow ] [ 2 ] = self.flows [ flow ] [ 2 ] + 1
else
self.flows [ flow ] = { i , 1 }
end
self.page_in_flow [ i ] = self.flows [ flow ] [ 2 ]
if flow == 0 then
self.last_linear_page = i
end
end
else
self.last_linear_page = self : getPageCount ( )
self.flows [ 0 ] = { 1 , self.last_linear_page }
end
end
function CreDocument : getTotalPagesLeft ( page )
if self : hasHiddenFlows ( ) then
local pages_left
local last_linear = self : getLastLinearPage ( )
if page > last_linear then
-- If beyond the last linear page, count only the pages in the current flow
local flow = self : getPageFlow ( page )
pages_left = self : getTotalPagesInFlow ( flow ) - self : getPageNumberInFlow ( page )
else
-- Otherwise, count all pages until the last linear,
-- except the flows that start (and end) between
-- the current page and the last linear
pages_left = last_linear - page
for flow , tab in ipairs ( self.flows ) do
-- tab[1] is the initial page of the flow
-- tab[2] is the total number of pages in the flow
if tab [ 1 ] > last_linear then
break
end
-- strict >, to make sure we include pages in the current flow
if tab [ 1 ] > page then
pages_left = pages_left - tab [ 2 ]
end
end
end
return pages_left
else
return Document.getTotalPagesLeft ( self , page )
end
end
function CreDocument : getCoverPageImage ( )
-- no need to render document in order to get cover image
if not self : loadDocument ( ) then
@ -578,7 +761,7 @@ function CreDocument:gotoPos(pos)
end
function CreDocument : gotoPage ( page )
logger.dbg ( " CreDocument: goto page " , page )
logger.dbg ( " CreDocument: goto page " , page , " flow " , self : getPageFlow ( page ) )
self._document : gotoPage ( page )
end
@ -766,6 +949,9 @@ function CreDocument:setViewMode(new_mode)
self._view_mode = self.PAGE_VIEW_MODE
end
self._document : setViewMode ( self._view_mode )
if self.hide_nonlinear_flows then
self : cacheFlows ( )
end
end
end
@ -1272,6 +1458,7 @@ function CreDocument:setupCallCache()
elseif name : sub ( 1 , 6 ) == " enable " then add_reset = true
elseif name == " zoomFont " then add_reset = true -- not used by koreader
elseif name == " resetCallCache " then add_reset = true
elseif name == " cacheFlows " then add_reset = true
-- These may have crengine do native highlight or unhighlight
-- (we could keep the original buffer and use a scratch buffer while
@ -1313,6 +1500,11 @@ function CreDocument:setupCallCache()
elseif name == " getCacheFilePath " then no_wrap = true
elseif name == " getStatistics " then no_wrap = true
elseif name == " getNormalizedXPointer " then no_wrap = true
elseif name == " getNextPage " then no_wrap = true
elseif name == " getPrevPage " then no_wrap = true
elseif name == " getPageFlow " then no_wrap = true
elseif name == " getPageNumberInFlow " then no_wrap = true
elseif name == " getTotalPagesLeft " then no_wrap = true
-- Some get* have different results by page/pos
elseif name == " getLinkFromPosition " then cache_by_tag = true