From 99d45d75841c0dc28d0aa22a5326c6a98a16e170 Mon Sep 17 00:00:00 2001 From: Benoit Pierre Date: Sun, 14 Jul 2024 22:00:32 +0200 Subject: [PATCH] djvu: honor render mode when reflowing --- .../apps/reader/modules/readerhinting.lua | 3 +- frontend/apps/reader/modules/readerview.lua | 13 ++-- frontend/document/djvudocument.lua | 13 ++-- frontend/document/document.lua | 20 +++---- frontend/document/koptinterface.lua | 59 +++++++++---------- frontend/document/pdfdocument.lua | 13 ++-- spec/unit/benchmark.lua | 4 +- spec/unit/cache_spec.lua | 6 +- 8 files changed, 67 insertions(+), 64 deletions(-) diff --git a/frontend/apps/reader/modules/readerhinting.lua b/frontend/apps/reader/modules/readerhinting.lua index e1a24288d..4dee4f112 100644 --- a/frontend/apps/reader/modules/readerhinting.lua +++ b/frontend/apps/reader/modules/readerhinting.lua @@ -18,8 +18,7 @@ function ReaderHinting:onHintPage() self.view.state.page + i, self.zoom:getZoom(self.view.state.page + i), self.view.state.rotation, - self.view.state.gamma, - self.view.render_mode) + self.view.state.gamma) end end return true diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua index e14e42cbc..7cea1aa98 100644 --- a/frontend/apps/reader/modules/readerview.lua +++ b/frontend/apps/reader/modules/readerview.lua @@ -382,8 +382,7 @@ function ReaderView:drawScrollPages(bb, x, y) state.page, state.zoom, state.rotation, - state.gamma, - self.render_mode) + state.gamma) pos.y = pos.y + state.visible_area.h -- draw page gap if not the last part if page ~= #self.page_states then @@ -457,8 +456,7 @@ function ReaderView:drawSinglePage(bb, x, y) self.state.page, self.state.zoom, self.state.rotation, - self.state.gamma, - self.render_mode) + self.state.gamma) UIManager:nextTick(self.emitHintPageEvent) end @@ -870,6 +868,7 @@ function ReaderView:onReadSettings(config) if self.ui.paging then self.document:setTileCacheValidity(config:readSetting("tile_cache_validity_ts")) self.render_mode = config:readSetting("render_mode") or G_defaults:readSetting("DRENDER_MODE") + self.document.render_mode = self.render_mode if config:has("gamma") then -- old doc contrast setting config:saveSetting("kopt_contrast", config:readSetting("gamma")) config:delSetting("gamma") @@ -1060,7 +1059,11 @@ function ReaderView:getRenderModeMenuTable() return { text = text, checked_func = function() return view.render_mode == mode end, - callback = function() view.render_mode = mode end, + callback = function() + view.render_mode = mode + view.document.render_mode = mode + view:recalculate() + end, } end return { diff --git a/frontend/document/djvudocument.lua b/frontend/document/djvudocument.lua index fc58352d8..ffb08143f 100644 --- a/frontend/document/djvudocument.lua +++ b/frontend/document/djvudocument.lua @@ -41,6 +41,7 @@ function DjvuDocument:init() self.is_open = true self.info.has_pages = true self.info.configurable = true + self.render_mode = 0 self:_readMetadata() end @@ -131,16 +132,16 @@ function DjvuDocument:findAllText(pattern, case_insensitive, nb_context_words, m return self.koptinterface:findAllText(self, pattern, case_insensitive, nb_context_words, max_hits) end -function DjvuDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mode, hinting) - return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, render_mode, hinting) +function DjvuDocument:renderPage(pageno, rect, zoom, rotation, gamma, hinting) + return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, hinting) end -function DjvuDocument:hintPage(pageno, zoom, rotation, gamma, render_mode) - return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode) +function DjvuDocument:hintPage(pageno, zoom, rotation, gamma) + return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma) end -function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) - return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) +function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma) + return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma) end function DjvuDocument:register(registry) diff --git a/frontend/document/document.lua b/frontend/document/document.lua index 70649c5b9..929df9914 100644 --- a/frontend/document/document.lua +++ b/frontend/document/document.lua @@ -399,15 +399,15 @@ function Document:resetTileCacheValidity() self.tile_cache_validity_ts = os.time() end -function Document:getFullPageHash(pageno, zoom, rotation, gamma, render_mode) +function Document:getFullPageHash(pageno, zoom, rotation, gamma) return "renderpg|"..self.file.."|"..self.mod_time.."|"..pageno.."|" - ..zoom.."|"..rotation.."|"..gamma.."|"..render_mode..(self.render_color and "|color" or "|bw") + ..zoom.."|"..rotation.."|"..gamma.."|"..self.render_mode..(self.render_color and "|color" or "|bw") ..(self.reflowable_font_size and "|"..self.reflowable_font_size or "") end -function Document:renderPage(pageno, rect, zoom, rotation, gamma, render_mode, hinting) +function Document:renderPage(pageno, rect, zoom, rotation, gamma, hinting) local hash_excerpt - local hash = self:getFullPageHash(pageno, zoom, rotation, gamma, render_mode) + local hash = self:getFullPageHash(pageno, zoom, rotation, gamma) local tile = DocCache:check(hash, TileCacheItem) if not tile then hash_excerpt = hash.."|"..tostring(rect) @@ -480,7 +480,7 @@ function Document:renderPage(pageno, rect, zoom, rotation, gamma, render_mode, h -- render local page = self._document:openPage(pageno) - page:draw(dc, tile.bb, size.x, size.y, render_mode) + page:draw(dc, tile.bb, size.x, size.y, self.render_mode) page:close() DocCache:insert(hash, tile) @@ -492,9 +492,9 @@ end -- a hint for the cache engine to paint a full page to the cache --- @todo this should trigger a background operation -function Document:hintPage(pageno, zoom, rotation, gamma, render_mode) +function Document:hintPage(pageno, zoom, rotation, gamma) logger.dbg("hinting page", pageno) - self:renderPage(pageno, nil, zoom, rotation, gamma, render_mode, true) + self:renderPage(pageno, nil, zoom, rotation, gamma, true) end --[[ @@ -505,8 +505,8 @@ Draw page content to blitbuffer. @target: target blitbuffer @rect: visible_area inside document page --]] -function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) - local tile = self:renderPage(pageno, rect, zoom, rotation, gamma, render_mode) +function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma) + local tile = self:renderPage(pageno, rect, zoom, rotation, gamma) -- Enable SW dithering if requested (only available in koptoptions) if self.sw_dithering then target:ditherblitFrom(tile.bb, @@ -539,7 +539,7 @@ function Document:getPagePart(pageno, rect, rotation) w = math.floor(rect.w * zoom), h = math.floor(rect.h * zoom), } - local tile = self:renderPage(pageno, scaled_rect, zoom, rotation, 1, 0) + local tile = self:renderPage(pageno, scaled_rect, zoom, rotation, 1.0) local target = Blitbuffer.new(scaled_rect.w, scaled_rect.h, self.render_color and self.color_bb_type or nil) target:blitFrom(tile.bb, 0, 0, scaled_rect.x, scaled_rect.y, scaled_rect.w, scaled_rect.h) return target diff --git a/frontend/document/koptinterface.lua b/frontend/document/koptinterface.lua index ad774721a..42e99dc38 100644 --- a/frontend/document/koptinterface.lua +++ b/frontend/document/koptinterface.lua @@ -170,6 +170,7 @@ function KoptInterface:getContextHash(doc, pageno, bbox, hash_list) table.insert(hash_list, doc.file) table.insert(hash_list, doc.mod_time) table.insert(hash_list, doc.render_color and 'color' or 'bw') + table.insert(hash_list, doc.render_mode) table.insert(hash_list, pageno) doc.configurable:hash(hash_list) table.insert(hash_list, bbox.x0) @@ -211,7 +212,7 @@ function KoptInterface:getAutoBBox(doc, pageno) if not cached then local page = doc._document:openPage(pageno) local kc = self:createContext(doc, pageno, bbox) - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) local x0, y0, x1, y1 = kc:getAutoBBox() local w, h = native_size.w, native_size.h if (x1 - x0)/w > 0.1 or (y1 - y0)/h > 0.1 then @@ -242,7 +243,7 @@ function KoptInterface:getSemiAutoBBox(doc, pageno) local page = doc._document:openPage(pageno) local kc = self:createContext(doc, pageno, bbox) local auto_bbox = {} - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) auto_bbox.x0, auto_bbox.y0, auto_bbox.x1, auto_bbox.y1 = kc:getAutoBBox() auto_bbox.x0 = auto_bbox.x0 + bbox.x0 auto_bbox.y0 = auto_bbox.y0 + bbox.y0 @@ -282,7 +283,7 @@ function KoptInterface:getCachedContext(doc, pageno) logger.dbg("reflowing page", pageno, "in foreground") -- reflow page --local secs, usecs = FFIUtil.gettime() - page:reflow(kc, doc.render_mode or G_defaults:readSetting("DRENDER_MODE")) -- Fall backs to a default set to DDJVU_RENDER_COLOR + page:reflow(kc, doc.render_mode) page:close() --local nsecs, nusecs = FFIUtil.gettime() --local dur = nsecs - secs + (nusecs - usecs) / 1000000 @@ -333,19 +334,19 @@ function KoptInterface:getCoverPageImage(doc) local native_size = Document.getNativePageDimensions(doc, 1) local canvas_size = CanvasContext:getSize() local zoom = math.min(canvas_size.w / native_size.w, canvas_size.h / native_size.h) - local tile = Document.renderPage(doc, 1, nil, zoom, 0, 1, 0) + local tile = Document.renderPage(doc, 1, nil, zoom, 0, 1.0) if tile then return tile.bb:copy() end end -function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, gamma, render_mode, hinting) +function KoptInterface:renderPage(doc, pageno, rect, zoom, rotation, gamma, hinting) if doc.configurable.text_wrap == 1 then - return self:renderReflowedPage(doc, pageno, rect, zoom, rotation, render_mode, hinting) + return self:renderReflowedPage(doc, pageno, rect, zoom, rotation, hinting) elseif doc.configurable.page_opt == 1 or doc.configurable.auto_straighten > 0 then - return self:renderOptimizedPage(doc, pageno, rect, zoom, rotation, render_mode, hinting) + return self:renderOptimizedPage(doc, pageno, rect, zoom, rotation, hinting) else - return Document.renderPage(doc, pageno, rect, zoom, rotation, gamma, render_mode, hinting) + return Document.renderPage(doc, pageno, rect, zoom, rotation, gamma, hinting) end end @@ -354,8 +355,7 @@ Render reflowed page into tile cache. Inherited from common document interface. --]] -function KoptInterface:renderReflowedPage(doc, pageno, rect, zoom, rotation, render_mode) - doc.render_mode = render_mode +function KoptInterface:renderReflowedPage(doc, pageno, rect, zoom, rotation) local bbox = doc:getPageBBox(pageno) local hash_list = { "renderpg" } self:getContextHash(doc, pageno, bbox, hash_list) @@ -389,8 +389,7 @@ Render optimized page into tile cache. Inherited from common document interface. --]] -function KoptInterface:renderOptimizedPage(doc, pageno, rect, zoom, rotation, render_mode, hinting) - doc.render_mode = render_mode +function KoptInterface:renderOptimizedPage(doc, pageno, rect, zoom, rotation, hinting) local bbox = doc:getPageBBox(pageno) local hash_list = { "renderoptpg" } self:getContextHash(doc, pageno, bbox, hash_list) @@ -411,7 +410,7 @@ function KoptInterface:renderOptimizedPage(doc, pageno, rect, zoom, rotation, re local kc = self:createContext(doc, pageno, full_page_bbox) local page = doc._document:openPage(pageno) kc:setZoom(zoom) - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) page:close() logger.dbg("optimizing page", pageno) kc:optimizePage() @@ -442,16 +441,16 @@ function KoptInterface:renderOptimizedPage(doc, pageno, rect, zoom, rotation, re end end -function KoptInterface:hintPage(doc, pageno, zoom, rotation, gamma, render_mode) +function KoptInterface:hintPage(doc, pageno, zoom, rotation, gamma) --- @note: Crappy safeguard around memory issues like in #7627: if we're eating too much RAM, drop half the cache... DocCache:memoryPressureCheck() if doc.configurable.text_wrap == 1 then - self:hintReflowedPage(doc, pageno, zoom, rotation, gamma, render_mode, true) + self:hintReflowedPage(doc, pageno, zoom, rotation, gamma, true) elseif doc.configurable.page_opt == 1 or doc.configurable.auto_straighten > 0 then - self:renderOptimizedPage(doc, pageno, nil, zoom, rotation, gamma, render_mode, true) + self:renderOptimizedPage(doc, pageno, nil, zoom, rotation, gamma, true) else - Document.hintPage(doc, pageno, zoom, rotation, gamma, render_mode) + Document.hintPage(doc, pageno, zoom, rotation, gamma) end end @@ -464,7 +463,7 @@ off by calling self:waitForContext(kctx) Inherited from common document interface. --]] -function KoptInterface:hintReflowedPage(doc, pageno, zoom, rotation, gamma, render_mode, hinting) +function KoptInterface:hintReflowedPage(doc, pageno, zoom, rotation, gamma, hinting) local bbox = doc:getPageBBox(pageno) local hash_list = { "kctx" } self:getContextHash(doc, pageno, bbox, hash_list) @@ -481,7 +480,7 @@ function KoptInterface:hintReflowedPage(doc, pageno, zoom, rotation, gamma, rend -- reflow will return immediately and running in background thread kc:setPreCache() self.bg_thread = true - page:reflow(kc, render_mode) + page:reflow(kc, doc.render_mode) page:close() DocCache:insert(hash, ContextCacheItem:new{ size = self.last_context_size or self.default_context_size, @@ -493,13 +492,13 @@ function KoptInterface:hintReflowedPage(doc, pageno, zoom, rotation, gamma, rend end end -function KoptInterface:drawPage(doc, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) +function KoptInterface:drawPage(doc, target, x, y, rect, pageno, zoom, rotation, gamma) if doc.configurable.text_wrap == 1 then - self:drawContextPage(doc, target, x, y, rect, pageno, zoom, rotation, render_mode) + self:drawContextPage(doc, target, x, y, rect, pageno, zoom, rotation) elseif doc.configurable.page_opt == 1 or doc.configurable.auto_straighten > 0 then - self:drawContextPage(doc, target, x, y, rect, pageno, zoom, rotation, render_mode) + self:drawContextPage(doc, target, x, y, rect, pageno, zoom, rotation) else - Document.drawPage(doc, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) + Document.drawPage(doc, target, x, y, rect, pageno, zoom, rotation, gamma) end end @@ -508,8 +507,8 @@ Draw cached tile pixels into target blitbuffer. Inherited from common document interface. --]] -function KoptInterface:drawContextPage(doc, target, x, y, rect, pageno, zoom, rotation, render_mode) - local tile = self:renderPage(doc, pageno, rect, zoom, rotation, 0, render_mode) +function KoptInterface:drawContextPage(doc, target, x, y, rect, pageno, zoom, rotation) + local tile = self:renderPage(doc, pageno, rect, zoom, rotation, 1.0) target:blitFrom(tile.bb, x, y, rect.x - tile.excerpt.x, @@ -650,7 +649,7 @@ function KoptInterface:getPanelFromPage(doc, pageno, ges) local kc = self:createContext(doc, pageno, bbox) kc:setZoom(1.0) local page = doc._document:openPage(pageno) - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) local panel = kc:getPanelFromPage(ges) page:close() kc:free() @@ -675,7 +674,7 @@ function KoptInterface:getNativeTextBoxesFromScratch(doc, pageno) local kc = self:createContext(doc, pageno, bbox) kc:setZoom(1.0) local page = doc._document:openPage(pageno) - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) local boxes, nr_word = kc:getNativeWordBoxes("src", 0, 0, page_size.w, page_size.h) if boxes then DocCache:insert(hash, CacheItem:new{ scratchnativepgboxes = boxes, size = 192 * nr_word }) -- estimation @@ -709,7 +708,7 @@ function KoptInterface:getPageBlock(doc, pageno, x, y) -- leptonica needs a source image of at least 300dpi kc:setZoom(CanvasContext:getWidth() / page_size.w * 300 / CanvasContext:getDPI()) local page = doc._document:openPage(pageno) - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) kc:findPageBlocks() DocCache:insert(hash, CacheItem:new{ kctx = kc, size = 3072 }) -- estimation page:close() @@ -786,7 +785,7 @@ function KoptInterface:getNativeOCRWord(doc, pageno, rect) local kc = self:createContext(doc, pageno, bbox) kc:setZoom(30/rect.h) local page = doc._document:openPage(pageno) - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) --kc:exportSrcPNGFile({rect}, nil, "ocr-word.png") local word_w, word_h = kc:getPageDim() local _, word = pcall( @@ -836,7 +835,7 @@ function KoptInterface:getClipPageContext(doc, pos0, pos1, pboxes, drawer) } local kc = self:createContext(doc, pos0.page, bbox) local page = doc._document:openPage(pos0.page) - page:getPagePix(kc) + page:getPagePix(kc, doc.render_mode) page:close() return kc, rect end diff --git a/frontend/document/pdfdocument.lua b/frontend/document/pdfdocument.lua index 72bc73230..82b1875bb 100644 --- a/frontend/document/pdfdocument.lua +++ b/frontend/document/pdfdocument.lua @@ -36,6 +36,7 @@ function PdfDocument:init() self.is_open = true self.info.has_pages = true self.info.configurable = true + self.render_mode = 0 if self._document:needsPassword() then self.is_locked = true else @@ -339,16 +340,16 @@ function PdfDocument:findAllText(pattern, case_insensitive, nb_context_words, ma return self.koptinterface:findAllText(self, pattern, case_insensitive, nb_context_words, max_hits) end -function PdfDocument:renderPage(pageno, rect, zoom, rotation, gamma, render_mode, hinting) - return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, render_mode, hinting) +function PdfDocument:renderPage(pageno, rect, zoom, rotation, gamma, hinting) + return self.koptinterface:renderPage(self, pageno, rect, zoom, rotation, gamma, hinting) end -function PdfDocument:hintPage(pageno, zoom, rotation, gamma, render_mode) - return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma, render_mode) +function PdfDocument:hintPage(pageno, zoom, rotation, gamma) + return self.koptinterface:hintPage(self, pageno, zoom, rotation, gamma) end -function PdfDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) - return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) +function PdfDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma) + return self.koptinterface:drawPage(self, target, x, y, rect, pageno, zoom, rotation, gamma) end function PdfDocument:register(registry) diff --git a/spec/unit/benchmark.lua b/spec/unit/benchmark.lua index d2f31c62a..ec900ecf9 100644 --- a/spec/unit/benchmark.lua +++ b/spec/unit/benchmark.lua @@ -18,7 +18,7 @@ describe("PDF rendering benchmark", function() local doc = DocumentRegistry:openDocument(sample_pdf) for pageno = 1, math.min(10, doc.info.number_of_pages) do local secs, usecs = util.gettime() - assert.truthy(doc:renderPage(pageno, nil, 1, 0, 1.0, 0)) + assert.truthy(doc:renderPage(pageno, nil, 1, 0, 1.0)) local nsecs, nusecs = util.gettime() local dur = nsecs - secs + (nusecs - usecs) / 1000000 logDuration("pdf_rendering.log", pageno, dur) @@ -32,7 +32,7 @@ describe("PDF reflowing benchmark", function() doc.configurable.text_wrap = 1 for pageno = 1, math.min(10, doc.info.number_of_pages) do local secs, usecs = util.gettime() - assert.truthy(doc:renderPage(pageno, nil, 1, 0, 1.0, 0)) + assert.truthy(doc:renderPage(pageno, nil, 1, 0, 1.0)) local nsecs, nusecs = util.gettime() local dur = nsecs - secs + (nusecs - usecs) / 1000000 logDuration("pdf_reflowing.log", pageno, dur) diff --git a/spec/unit/cache_spec.lua b/spec/unit/cache_spec.lua index 5d34d1612..2a7ca50b0 100644 --- a/spec/unit/cache_spec.lua +++ b/spec/unit/cache_spec.lua @@ -20,7 +20,7 @@ describe("Cache module", function() it("should serialize blitbuffer", function() for pageno = 1, math.min(max_page, doc.info.number_of_pages) do - doc:renderPage(pageno, nil, 1, 0, 1.0, 0) + doc:renderPage(pageno, nil, 1, 0, 1.0) DocCache:serialize() end DocCache:clear() @@ -36,7 +36,7 @@ describe("Cache module", function() it("should serialize koptcontext", function() doc.configurable.text_wrap = 1 for pageno = 1, math.min(max_page, doc.info.number_of_pages) do - doc:renderPage(pageno, nil, 1, 0, 1.0, 0) + doc:renderPage(pageno, nil, 1, 0, 1.0) doc:getPageDimensions(pageno) DocCache:serialize() end @@ -46,7 +46,7 @@ describe("Cache module", function() it("should deserialize koptcontext", function() for pageno = 1, math.min(max_page, doc.info.number_of_pages) do - doc:renderPage(pageno, nil, 1, 0, 1.0, 0) + doc:renderPage(pageno, nil, 1, 0, 1.0) end DocCache:clear() end)