mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #787 from chrox/background_hint
add background hinting in koptinterface
This commit is contained in:
@@ -80,6 +80,14 @@ function DjvuDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mod
|
||||
end
|
||||
end
|
||||
|
||||
function DjvuDocument:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
||||
if self.configurable.text_wrap == 1 then
|
||||
self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
||||
else
|
||||
Document.hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
||||
end
|
||||
end
|
||||
|
||||
function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
||||
if self.configurable.text_wrap == 1 then
|
||||
self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, render_mode)
|
||||
|
||||
@@ -195,10 +195,38 @@ KoptOptions = {
|
||||
},
|
||||
}
|
||||
|
||||
KoptInterface = {}
|
||||
KoptInterface = {
|
||||
bg_context = {
|
||||
contex = nil,
|
||||
pageno = nil,
|
||||
hash = nil,
|
||||
cached = false,
|
||||
},
|
||||
}
|
||||
|
||||
function KoptInterface:waitForContext(kc)
|
||||
-- if koptcontext is being processed in background thread
|
||||
-- the isPreCache will return 1.
|
||||
while kc and kc:isPreCache() == 1 do
|
||||
DEBUG("waiting for background rendering")
|
||||
util.usleep(100000)
|
||||
end
|
||||
end
|
||||
|
||||
function KoptInterface:consumeBgContext(doc)
|
||||
-- clear up background context
|
||||
self:waitForContext(self.bg_context.context)
|
||||
if self.bg_context.context and not self.bg_context.cached then
|
||||
self:makeCache(doc, self.bg_context.pageno, self.bg_context.hash)
|
||||
self.bg_context.cached = true
|
||||
end
|
||||
end
|
||||
|
||||
-- get reflow context
|
||||
function KoptInterface:getKOPTContext(doc, pageno, bbox)
|
||||
-- since libk2pdfopt only has one bitmap buffer that holds reflowed page
|
||||
-- we should consume background production before allocating new context.
|
||||
self:consumeBgContext(doc)
|
||||
local kc = KOPTContext.new()
|
||||
local screen_size = Screen:getSize()
|
||||
kc:setTrim(doc.configurable.trim_page)
|
||||
@@ -222,6 +250,7 @@ function KoptInterface:getKOPTContext(doc, pageno, bbox)
|
||||
end
|
||||
|
||||
function KoptInterface:setTrimPage(doc, pageno)
|
||||
if doc.configurable.trim_page == 0 then return end
|
||||
local page_dimens = doc:getNativePageDimensions(pageno)
|
||||
--DEBUG("original page dimens", page_dimens)
|
||||
local orig_bbox = doc:getUsedBBox(pageno)
|
||||
@@ -251,6 +280,11 @@ function KoptInterface:logReflowDuration(pageno, dur)
|
||||
end
|
||||
end
|
||||
|
||||
function KoptInterface:getReflowedDim(kc)
|
||||
self:waitForContext(kc)
|
||||
return kc:getPageDim()
|
||||
end
|
||||
|
||||
-- calculates page dimensions
|
||||
function KoptInterface:getPageDimensions(doc, pageno, zoom, rotation)
|
||||
self:setTrimPage(doc, pageno)
|
||||
@@ -277,11 +311,37 @@ function KoptInterface:getPageDimensions(doc, pageno, zoom, rotation)
|
||||
return page_size
|
||||
end
|
||||
--DEBUG("Found cached koptcontex on page", pageno, cached)
|
||||
local fullwidth, fullheight = cached.kctx:getPageDim()
|
||||
local fullwidth, fullheight = self:getReflowedDim(cached.kctx)
|
||||
local page_size = Geom:new{ w = fullwidth, h = fullheight }
|
||||
return page_size
|
||||
end
|
||||
|
||||
function KoptInterface:makeCache(doc, pageno, context_hash)
|
||||
-- draw to blitbuffer
|
||||
local kc_hash = "kctx|"..context_hash
|
||||
local tile_hash = "renderpg|"..context_hash
|
||||
local page = doc._document:openPage(pageno)
|
||||
local cached = Cache:check(kc_hash)
|
||||
if cached then
|
||||
local fullwidth, fullheight = self:getReflowedDim(cached.kctx)
|
||||
-- prepare cache item with contained blitbuffer
|
||||
local tile = CacheItem:new{
|
||||
size = fullwidth * fullheight / 2 + 64, -- estimation
|
||||
excerpt = Geom:new{ w = fullwidth, h = fullheight },
|
||||
pageno = pageno,
|
||||
bb = Blitbuffer.new(fullwidth, fullheight)
|
||||
}
|
||||
page:rfdraw(cached.kctx, tile.bb)
|
||||
page:close()
|
||||
--DEBUG("cached hash", hash)
|
||||
if not Cache:check(tile_hash) then
|
||||
Cache:insert(tile_hash, tile)
|
||||
end
|
||||
return tile
|
||||
end
|
||||
DEBUG("Error: cannot render page before reflowing.")
|
||||
end
|
||||
|
||||
function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, render_mode)
|
||||
self:setTrimPage(doc, pageno)
|
||||
doc.render_mode = render_mode
|
||||
@@ -307,30 +367,33 @@ function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, render_mode
|
||||
end
|
||||
|
||||
local cached = Cache:check(hash)
|
||||
if cached then return cached end
|
||||
|
||||
-- prepare cache item with contained blitbuffer
|
||||
local tile = CacheItem:new{
|
||||
size = size.w * size.h / 2 + 64, -- estimation
|
||||
excerpt = size,
|
||||
pageno = pageno,
|
||||
bb = Blitbuffer.new(size.w, size.h)
|
||||
}
|
||||
|
||||
-- draw to blitbuffer
|
||||
local kc_hash = "kctx|"..context_hash
|
||||
local page = doc._document:openPage(pageno)
|
||||
local cached = Cache:check(kc_hash)
|
||||
if cached then
|
||||
page:rfdraw(cached.kctx, tile.bb)
|
||||
page:close()
|
||||
--DEBUG("cached hash", hash)
|
||||
if not Cache:check(hash) then
|
||||
Cache:insert(hash, tile)
|
||||
end
|
||||
return tile
|
||||
return cached
|
||||
else
|
||||
return self:makeCache(doc, pageno, context_hash)
|
||||
end
|
||||
end
|
||||
|
||||
function KoptInterface:hintPage(doc, pageno, zoom, rotation, gamma, render_mode)
|
||||
self:setTrimPage(doc, pageno)
|
||||
local bbox = doc:getPageBBox(pageno)
|
||||
local context_hash = self:getContextHash(doc, pageno, bbox)
|
||||
local hash = "kctx|"..context_hash
|
||||
local cached = Cache:check(hash)
|
||||
if not cached then
|
||||
local kc = self:getKOPTContext(doc, pageno, bbox)
|
||||
local page = doc._document:openPage(pageno)
|
||||
kc:setPreCache()
|
||||
self.bg_context.context = kc
|
||||
self.bg_context.pageno = pageno
|
||||
self.bg_context.hash = context_hash
|
||||
self.bg_context.cached = false
|
||||
DEBUG("hinting page", pageno, "in background")
|
||||
-- will return immediately
|
||||
page:reflow(kc, 0)
|
||||
page:close()
|
||||
Cache:insert(hash, CacheItem:new{ kctx = kc })
|
||||
end
|
||||
DEBUG("Error: cannot render page before reflowing.")
|
||||
end
|
||||
|
||||
function KoptInterface:drawPage(doc, target, x, y, rect, pageno, zoom, rotation, render_mode)
|
||||
|
||||
@@ -82,6 +82,14 @@ function PdfDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mode
|
||||
end
|
||||
end
|
||||
|
||||
function PdfDocument:hintPage(pageno, zoom, rotation, gamma, render_mode)
|
||||
if self.configurable.text_wrap == 1 then
|
||||
self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
||||
else
|
||||
Document.hintPage(self, pageno, zoom, rotation, gamma, render_mode)
|
||||
end
|
||||
end
|
||||
|
||||
function PdfDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
|
||||
if self.configurable.text_wrap == 1 then
|
||||
self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, render_mode)
|
||||
|
||||
@@ -82,8 +82,11 @@ function ReaderConfig:onShowConfigMenu()
|
||||
ui = self.ui,
|
||||
configurable = self.configurable,
|
||||
config_options = self.options,
|
||||
close_callback = function()
|
||||
self.ui:handleEvent(Event:new("RestoreHinting"))
|
||||
end,
|
||||
}
|
||||
|
||||
self.ui:handleEvent(Event:new("DisableHinting"))
|
||||
UIManager:show(self.config_dialog)
|
||||
|
||||
return true
|
||||
|
||||
@@ -63,6 +63,8 @@ function ReaderCropping:onPageCrop(mode)
|
||||
-- backup original page scroll
|
||||
self.orig_page_scroll = self.view.page_scroll
|
||||
self.view.page_scroll = false
|
||||
-- backup and disable original hinting state
|
||||
self.ui:handleEvent(Event:new("DisableHinting"))
|
||||
-- backup original reflow mode as cropping use non-reflow mode
|
||||
self.orig_reflow_mode = self.document.configurable.text_wrap
|
||||
if self.orig_reflow_mode == 1 then
|
||||
@@ -110,6 +112,8 @@ function ReaderCropping:onCancelPageCrop()
|
||||
end
|
||||
|
||||
function ReaderCropping:exitPageCrop(confirmed)
|
||||
-- restore hinting state
|
||||
self.ui:handleEvent(Event:new("RestoreHinting"))
|
||||
-- restore page scroll
|
||||
self.view.page_scroll = self.orig_page_scroll
|
||||
-- restore view bgcolor
|
||||
|
||||
19
frontend/ui/reader/readerhinting.lua
Normal file
19
frontend/ui/reader/readerhinting.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
ReaderHinting = EventListener:new{
|
||||
hinting_states = {}
|
||||
}
|
||||
|
||||
function ReaderHinting:onSetHinting(hinting)
|
||||
self.view.hinting = hinting
|
||||
end
|
||||
|
||||
function ReaderHinting:onDisableHinting()
|
||||
table.insert(self.hinting_states, self.view.hinting)
|
||||
self.view.hinting = false
|
||||
return true
|
||||
end
|
||||
|
||||
function ReaderHinting:onRestoreHinting()
|
||||
self.view.hinting = table.remove(self.hinting_states)
|
||||
return true
|
||||
end
|
||||
@@ -143,6 +143,7 @@ function ReaderPaging:onToggleFlipping()
|
||||
if self.flipping_mode then
|
||||
self:updateOriginalPage(self.current_page)
|
||||
end
|
||||
self.ui:handleEvent(Event:new("SetHinting", not self.flipping_mode))
|
||||
UIManager:setDirty(self.view.dialog, "partial")
|
||||
end
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ ReaderView = OverlapGroup:new{
|
||||
render_mode = 0, -- default to COLOR
|
||||
-- Crengine view mode
|
||||
view_mode = "page", -- 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
|
||||
@@ -148,7 +149,9 @@ function ReaderView:drawScrollPages(bb, x, y)
|
||||
pos.y = pos.y + self.page_gap.height
|
||||
end
|
||||
end
|
||||
UIManager:scheduleIn(0, function() self.ui:handleEvent(Event:new("HintPage")) end)
|
||||
UIManager:scheduleIn(0, function()
|
||||
self.ui:handleEvent(Event:new("HintPage", self.hinting))
|
||||
end)
|
||||
end
|
||||
|
||||
function ReaderView:drawPageGap(bb, x, y)
|
||||
@@ -170,7 +173,9 @@ function ReaderView:drawSinglePage(bb, x, y)
|
||||
self.state.rotation,
|
||||
self.state.gamma,
|
||||
self.render_mode)
|
||||
UIManager:scheduleIn(0, function() self.ui:handleEvent(Event:new("HintPage")) end)
|
||||
UIManager:scheduleIn(0, function()
|
||||
self.ui:handleEvent(Event:new("HintPage", self.hinting))
|
||||
end)
|
||||
end
|
||||
|
||||
function ReaderView:drawPageView(bb, x, y)
|
||||
|
||||
@@ -110,6 +110,7 @@ function ReaderZooming:onPageUpdate(new_page_no)
|
||||
end
|
||||
|
||||
function ReaderZooming:onHintPage()
|
||||
if not self.view.hinting then return true end
|
||||
if self.current_page < self.ui.document.info.number_of_pages then
|
||||
self.ui.document:hintPage(
|
||||
self.view.state.page + 1,
|
||||
|
||||
@@ -15,6 +15,7 @@ require "ui/reader/readercropping"
|
||||
require "ui/reader/readerkopt"
|
||||
require "ui/reader/readercopt"
|
||||
require "ui/reader/readerscreenshot"
|
||||
require "ui/reader/readerhinting"
|
||||
|
||||
--[[
|
||||
This is an abstraction for a reader interface
|
||||
@@ -132,6 +133,14 @@ function ReaderUI:init()
|
||||
document = self.document,
|
||||
}
|
||||
table.insert(self, cropper)
|
||||
-- hinting controller
|
||||
local hinter = ReaderHinting:new{
|
||||
dialog = self.dialog,
|
||||
view = self[1],
|
||||
ui = self,
|
||||
document = self.document,
|
||||
}
|
||||
table.insert(self, hinter)
|
||||
else
|
||||
-- make sure we load document first before calling any callback
|
||||
table.insert(self.postInitCallback, function()
|
||||
|
||||
Reference in New Issue
Block a user