From 913459411934d955b1a89bb46e362fa9153d04f7 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Thu, 18 Apr 2019 23:26:53 +0200 Subject: [PATCH] Allow toggling CRe's new dithering & scaling (#4922) Smooth scaling toggle is per document, in the gear tab. Dithering is in the Dev top menu ;). --- base | 2 +- frontend/apps/filemanager/filemanagermenu.lua | 37 +++++++++++++++++++ .../apps/reader/modules/readertypeset.lua | 25 +++++++++++++ frontend/document/credocument.lua | 14 +++++-- frontend/ui/data/creoptions.lua | 13 +++++++ frontend/ui/data/strings.lua | 1 + frontend/ui/uimanager.lua | 6 +++ frontend/ui/widget/imagewidget.lua | 25 ++++++++++--- frontend/util.lua | 16 ++++++++ reader.lua | 10 +++++ 10 files changed, 140 insertions(+), 9 deletions(-) diff --git a/base b/base index ccd44cf38..b6b6d7497 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit ccd44cf38a82ff3e3fb5aaebe683b6cb18296a23 +Subproject commit b6b6d74979d7f52b93b1e112afa995815c87a649 diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index 51ab85b13..478844d2b 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -289,6 +289,43 @@ function FileManagerMenu:setUpdateItemTable() end, }) end + if Device:hasEinkScreen() and Device:canHWDither() then + table.insert(self.menu_items.developer_options.sub_item_table, { + text = _("Disable HW dithering"), + checked_func = function() + return not Device.screen.hw_dithering + end, + callback = function() + G_reader_settings:flipNilOrFalse("dev_no_hw_dither") + Device.screen:toggleHWDithering() + -- Make sure SW dithering gets disabled when we enable HW dithering + if Device.screen.hw_dithering and Device.screen.sw_dithering then + Device.screen:toggleSWDithering() + end + UIManager:setDirty("all", "full") + end, + }) + end + if Device:hasEinkScreen() then + table.insert(self.menu_items.developer_options.sub_item_table, { + text = _("Disable SW dithering"), + enabled_func = function() + return Device.screen.fb_bpp == 8 + end, + checked_func = function() + return not Device.screen.sw_dithering + end, + callback = function() + G_reader_settings:flipNilOrFalse("dev_no_sw_dither") + Device.screen:toggleSWDithering() + -- Make sure HW dithering gets disabled when we enable SW dithering + if Device.screen.hw_dithering and Device.screen.sw_dithering then + Device.screen:toggleHWDithering() + end + UIManager:setDirty("all", "full") + end, + }) + end self.menu_items.cloud_storage = { text = _("Cloud storage"), callback = function() diff --git a/frontend/apps/reader/modules/readertypeset.lua b/frontend/apps/reader/modules/readertypeset.lua index c2bbd0ddb..1bd05058e 100644 --- a/frontend/apps/reader/modules/readertypeset.lua +++ b/frontend/apps/reader/modules/readertypeset.lua @@ -75,6 +75,14 @@ function ReaderTypeset:onReadSettings(config) self.txt_preformatted = config:readSetting("txt_preformatted") or G_reader_settings:readSetting("txt_preformatted") or 1 self:toggleTxtPreFormatted(self.txt_preformatted) + + -- default to disable smooth scaling for now. + self.smooth_scaling = config:readSetting("smooth_scaling") + if self.smooth_scaling == nil then + local global = G_reader_settings:readSetting("copt_smooth_scaling") + self.smooth_scaling = (global == nil or global == 0) and 0 or 1 + end + self:toggleImageScaling(self.smooth_scaling) end function ReaderTypeset:onSaveSettings() @@ -83,6 +91,7 @@ function ReaderTypeset:onSaveSettings() self.ui.doc_settings:saveSetting("floating_punctuation", self.floating_punctuation) self.ui.doc_settings:saveSetting("embedded_fonts", self.embedded_fonts) self.ui.doc_settings:saveSetting("render_dpi", self.render_dpi) + self.ui.doc_settings:saveSetting("smooth_scaling", self.smooth_scaling) end function ReaderTypeset:onToggleEmbeddedStyleSheet(toggle) @@ -95,6 +104,11 @@ function ReaderTypeset:onToggleEmbeddedFonts(toggle) return true end +function ReaderTypeset:onToggleImageScaling(toggle) + self:toggleImageScaling(toggle) + return true +end + -- June 2018: epub.css has been cleaned to be more conforming to HTML specs -- and to not include class name based styles (with conditional compatiblity -- styles for previously opened documents). It should be usable on all @@ -248,6 +262,17 @@ function ReaderTypeset:toggleEmbeddedFonts(toggle) self.ui:handleEvent(Event:new("UpdatePos")) end +function ReaderTypeset:toggleImageScaling(toggle) + if toggle and (toggle == true or toggle == 1) then + self.smooth_scaling = true + self.ui.document:setImageScaling(true) + else + self.smooth_scaling = false + self.ui.document:setImageScaling(false) + end + self.ui:handleEvent(Event:new("UpdatePos")) +end + function ReaderTypeset:toggleFloatingPunctuation(toggle) -- for some reason the toggle value read from history files may stay boolean -- and there seems no more elegant way to convert boolean values to numbers diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index acf2c864d..cb0d21841 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -5,6 +5,7 @@ local Document = require("document/document") local FontList = require("fontlist") local Geom = require("ui/geometry") local RenderImage = require("ui/renderimage") +local Screen = require("device").screen local ffi = require("ffi") local C = ffi.C local lfs = require("libs/libkoreader-lfs") @@ -21,6 +22,7 @@ local CreDocument = Document:new{ _document = false, _loaded = false, _view_mode = nil, + _smooth_scaling = false, line_space_percent = 100, default_font = "Noto Serif", @@ -368,14 +370,15 @@ function CreDocument:drawCurrentView(target, x, y, rect, pos) -- same buffer. And it could only change when some other methods -- from here are called - -- If in night mode, ask crengine to invert all images, so they + -- If in night mode, we ask crengine to invert all images, so they -- get displayed in their original colors when the whole screen -- is inverted by night mode - local invert_images = G_reader_settings:isTrue("night_mode") + -- We also honor the current smooth scaling setting, + -- as well as the global SW dithering setting. -- local start_clock = os.clock() self._drawn_images_count, self._drawn_images_surface_ratio = - self._document:drawCurrentPage(self.buffer, self.render_color, invert_images) + self._document:drawCurrentPage(self.buffer, self.render_color, Screen.night_mode, self._smooth_scaling, Screen.sw_dithering) -- print(string.format("CreDocument:drawCurrentView: Rendering took %9.3f ms", (os.clock() - start_clock) * 1000)) -- start_clock = os.clock() @@ -728,6 +731,11 @@ function CreDocument:setPageMargins(left, top, right, bottom) self._document:setIntProperty("crengine.page.margin.bottom", bottom) end +function CreDocument:setImageScaling(toggle) + logger.dbg("CreDocument: set smooth scaling", toggle) + self._smooth_scaling = toggle +end + function CreDocument:setFloatingPunctuation(enabled) -- FIXME: occasional segmentation fault when toggling floating punctuation logger.dbg("CreDocument: set floating punctuation", enabled) diff --git a/frontend/ui/data/creoptions.lua b/frontend/ui/data/creoptions.lua index 4ae484b8a..de4d0ec7d 100644 --- a/frontend/ui/data/creoptions.lua +++ b/frontend/ui/data/creoptions.lua @@ -322,6 +322,19 @@ Note that your selected font size is not affected by this setting.]]), help_text = _([[Enable or disable the use of the fonts embedded in the book. (Disabling the fonts specified in the publisher stylesheets can also be achieved via Style Tweaks in the main menu.)]]), }, + { + name = "smooth_scaling", + name_text = S.IMAGE_SCALING, + toggle = {S.FAST, S.BEST}, + values = {0, 1}, + default_value = 0, + args = {false, true}, + default_arg = nil, + event = "ToggleImageScaling", + name_text_hold_callback = optionsutil.showValues, + help_text = _([[- 'fast' uses a fast but inaccurate scaling algorithm when scaling images. +- 'best' switches to a more costly but vastly more pleasing and accurate algorithm.]]), + }, }, }, } diff --git a/frontend/ui/data/strings.lua b/frontend/ui/data/strings.lua index 635f5970e..c6564ef4e 100644 --- a/frontend/ui/data/strings.lua +++ b/frontend/ui/data/strings.lua @@ -35,6 +35,7 @@ S.PROGRESS_BAR = _("Progress Bar") S.FORCED_OCR = _("Forced OCR") S.HW_DITHERING = _("Dithering") S.INVERSE_READING_ORDER = _("Inverse Order") +S.IMAGE_SCALING = _("Image Scaling") S.ON = _("on") S.OFF = _("off") diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index e7086f0d2..018e52db8 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -928,6 +928,12 @@ function UIManager:_repaint() -- execute refreshes: for _, refresh in ipairs(self._refresh_stack) do + -- Honor dithering hints from *anywhere* in the dirty stack + refresh.dither = update_dither(refresh.dither, dithered) + -- If HW dithering is disabled, unconditionally drop the dither flag + if not Screen.hw_dithering then + refresh.dither = nil + end dbg:v("triggering refresh", refresh) -- NOTE: We overshoot by 1px to account for potential off-by-ones. -- This may not strictly be needed anymore, and is blatantly unneeded for full-screen updates, diff --git a/frontend/ui/widget/imagewidget.lua b/frontend/ui/widget/imagewidget.lua index a6b7eb416..65fa670f5 100644 --- a/frontend/ui/widget/imagewidget.lua +++ b/frontend/ui/widget/imagewidget.lua @@ -29,6 +29,7 @@ local Screen = require("device").screen local UIManager = require("ui/uimanager") local Widget = require("ui/widget/widget") local logger = require("logger") +local util = require("util") -- DPI_SCALE can't change without a restart, so let's compute it now local function get_dpi_scale() @@ -355,17 +356,31 @@ function ImageWidget:paintTo(bb, x, y) h = size.h } logger.dbg("blitFrom", x, y, self._offset_x, self._offset_y, size.w, size.h) + -- Figure out if we're trying to render one of our own icons... + local is_icon = self.file and util.stringStartsWith(self.file, "resources/") if self.alpha == true then -- Only actually try to alpha-blend if the image really has an alpha channel... local bbtype = self._bb:getType() if bbtype == Blitbuffer.TYPE_BB8A or bbtype == Blitbuffer.TYPE_BBRGB32 then -- NOTE: MuPDF feeds us premultiplied alpha (and we don't care w/ GifLib, as alpha is all or nothing). - bb:pmulalphablitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + if Screen.sw_dithering and not is_icon then + bb:ditherpmulalphablitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + else + bb:pmulalphablitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + end else - bb:blitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + if Screen.sw_dithering and not is_icon then + bb:ditherblitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + else + bb:blitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + end end else - bb:blitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + if Screen.sw_dithering and not is_icon then + bb:ditherblitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + else + bb:blitFrom(self._bb, x, y, self._offset_x, self._offset_y, size.w, size.h) + end end if self.invert then bb:invertRect(x, y, size.w, size.h) @@ -375,9 +390,9 @@ function ImageWidget:paintTo(bb, x, y) end -- If in night mode, invert all rendered images, so the original is -- displayed when the whole screen is inverted by night mode. - -- Except for our black & white icon files, that we want inverted + -- Except for our black & white icon files, that we do want inverted -- in night mode. - if not self.file and G_reader_settings:isTrue("night_mode") then + if Screen.night_mode and not is_icon then bb:invertRect(x, y, size.w, size.h) end end diff --git a/frontend/util.lua b/frontend/util.lua index 45af8f183..d97698cfe 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -782,4 +782,20 @@ function util.unpackArchive(archive, extract_to) return true end +-- Simple startsWith / endsWith string helpers +-- c.f., http://lua-users.org/wiki/StringRecipes +-- @param str string: source string +-- @param start string: string to match +-- @return boolean: true on success +function util.stringStartsWith(str, start) + return str:sub(1, #start) == start +end + +-- @param str string: source string +-- @param ending string: string to match +-- @return boolean: true on success +function util.stringEndsWith(str, ending) + return ending == "" or str:sub(-#ending) == ending +end + return util diff --git a/reader.lua b/reader.lua index ced1f1a5f..ddbf39b3f 100755 --- a/reader.lua +++ b/reader.lua @@ -173,6 +173,16 @@ end if G_reader_settings:isTrue("night_mode") then Device.screen:toggleNightMode() end +-- dithering +if Device:hasEinkScreen() then + Device.screen:setupDithering() + if Device.screen.hw_dithering and G_reader_settings:isTrue("dev_no_hw_dither") then + Device.screen:toggleHWDithering() + end + if Device.screen.sw_dithering and G_reader_settings:isTrue("dev_no_sw_dither") then + Device.screen:toggleSWDithering() + end +end if Device:needsTouchScreenProbe() then Device:touchScreenProbe()