From ef68ccebfec0c7ab64b4c0ab88679f72d52c5595 Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 12 Mar 2013 20:26:02 +0800 Subject: [PATCH 1/2] add background hinting in koptinterface --- frontend/document/djvudocument.lua | 8 ++ frontend/document/koptinterface.lua | 111 ++++++++++++++++++++++------ frontend/document/pdfdocument.lua | 8 ++ 3 files changed, 103 insertions(+), 24 deletions(-) diff --git a/frontend/document/djvudocument.lua b/frontend/document/djvudocument.lua index 3dbb1161e..3f0f34cc1 100644 --- a/frontend/document/djvudocument.lua +++ b/frontend/document/djvudocument.lua @@ -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) diff --git a/frontend/document/koptinterface.lua b/frontend/document/koptinterface.lua index 795b6b13e..e868f441c 100644 --- a/frontend/document/koptinterface.lua +++ b/frontend/document/koptinterface.lua @@ -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) diff --git a/frontend/document/pdfdocument.lua b/frontend/document/pdfdocument.lua index ee8d38c7f..bda9c6c1c 100644 --- a/frontend/document/pdfdocument.lua +++ b/frontend/document/pdfdocument.lua @@ -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) From a6609119eca027bd1375bc54bc5a530a8ad3aa18 Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 12 Mar 2013 20:28:01 +0800 Subject: [PATCH 2/2] disable hinting temporarily in config dialog and flipping mode and cropping dialog Since hinting is of little use in these situations. --- frontend/ui/reader/readerconfig.lua | 5 ++++- frontend/ui/reader/readercropping.lua | 4 ++++ frontend/ui/reader/readerhinting.lua | 19 +++++++++++++++++++ frontend/ui/reader/readerpaging.lua | 1 + frontend/ui/reader/readerview.lua | 11 ++++++++--- frontend/ui/reader/readerzooming.lua | 1 + frontend/ui/readerui.lua | 9 +++++++++ 7 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 frontend/ui/reader/readerhinting.lua diff --git a/frontend/ui/reader/readerconfig.lua b/frontend/ui/reader/readerconfig.lua index 794d5da12..f40e60222 100644 --- a/frontend/ui/reader/readerconfig.lua +++ b/frontend/ui/reader/readerconfig.lua @@ -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 diff --git a/frontend/ui/reader/readercropping.lua b/frontend/ui/reader/readercropping.lua index 0dd9fd571..396380257 100644 --- a/frontend/ui/reader/readercropping.lua +++ b/frontend/ui/reader/readercropping.lua @@ -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 diff --git a/frontend/ui/reader/readerhinting.lua b/frontend/ui/reader/readerhinting.lua new file mode 100644 index 000000000..1fad17ba1 --- /dev/null +++ b/frontend/ui/reader/readerhinting.lua @@ -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 \ No newline at end of file diff --git a/frontend/ui/reader/readerpaging.lua b/frontend/ui/reader/readerpaging.lua index 5709a3390..22cc3efbc 100644 --- a/frontend/ui/reader/readerpaging.lua +++ b/frontend/ui/reader/readerpaging.lua @@ -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 diff --git a/frontend/ui/reader/readerview.lua b/frontend/ui/reader/readerview.lua index e5f2f913f..c868568b5 100644 --- a/frontend/ui/reader/readerview.lua +++ b/frontend/ui/reader/readerview.lua @@ -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) diff --git a/frontend/ui/reader/readerzooming.lua b/frontend/ui/reader/readerzooming.lua index 3528c5ac2..df31cf29a 100644 --- a/frontend/ui/reader/readerzooming.lua +++ b/frontend/ui/reader/readerzooming.lua @@ -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, diff --git a/frontend/ui/readerui.lua b/frontend/ui/readerui.lua index ea69f128e..3a6dd54a2 100644 --- a/frontend/ui/readerui.lua +++ b/frontend/ui/readerui.lua @@ -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()