2
0
mirror of https://github.com/koreader/koreader synced 2024-11-10 01:10:34 +00:00

"Simplify" HW/SW dithering checks

Make it a real Document property, updated at init & toggle time.

Also, simplify a bunch of redundant nested lookups in ReaderView
(self.ui.view is self, self.ui.document is self.document).
This commit is contained in:
NiLuJe 2022-02-06 18:01:45 +01:00
parent afe1dc9681
commit 35776f1f87
5 changed files with 90 additions and 47 deletions

View File

@ -33,6 +33,7 @@ function ReaderKoptListener:onReadSettings(config)
if self.document.configurable.word_spacing == -1 then if self.document.configurable.word_spacing == -1 then
self.document.configurable.word_spacing = -0.2 self.document.configurable.word_spacing = -0.2
end end
self.ui:handleEvent(Event:new("DitheringUpdate"))
end end
function ReaderKoptListener:onSaveSettings() function ReaderKoptListener:onSaveSettings()

View File

@ -164,7 +164,7 @@ function ReaderView:paintTo(bb, x, y)
end end
-- draw page content -- draw page content
if self.ui.document.info.has_pages then if self.ui.paging then
if self.page_scroll then if self.page_scroll then
self:drawScrollPages(bb, x, y) self:drawScrollPages(bb, x, y)
else else
@ -220,15 +220,14 @@ function ReaderView:paintTo(bb, x, y)
-- Most pages should not require dithering -- Most pages should not require dithering
self.dialog.dithered = nil self.dialog.dithered = nil
-- For KOpt, let the user choose. -- For KOpt, let the user choose.
if self.ui.document.info.has_pages then if self.ui.paging then
-- Also enforce HW dithering in PicDocument if self.document.hw_dithering then
if self.ui.document.is_pic or self.document.configurable.hw_dithering == 1 then
self.dialog.dithered = true self.dialog.dithered = true
end end
else else
-- Whereas for CRe, -- Whereas for CRe,
-- If we're attempting to show a large enough amount of image data, request dithering (without triggering another repaint ;)). -- If we're attempting to show a large enough amount of image data, request dithering (without triggering another repaint ;)).
local img_count, img_coverage = self.ui.document:getDrawnImagesStatistics() local img_count, img_coverage = self.document:getDrawnImagesStatistics()
-- With some nil guards because this may not be implemented in every engine ;). -- With some nil guards because this may not be implemented in every engine ;).
if img_count and img_count > 0 and img_coverage and img_coverage >= 0.075 then if img_count and img_count > 0 and img_coverage and img_coverage >= 0.075 then
self.dialog.dithered = true self.dialog.dithered = true
@ -245,15 +244,15 @@ end
Given coordinates on the screen return position in original page Given coordinates on the screen return position in original page
]]-- ]]--
function ReaderView:screenToPageTransform(pos) function ReaderView:screenToPageTransform(pos)
if self.ui.document.info.has_pages then if self.ui.paging then
if self.page_scroll then if self.page_scroll then
return self:getScrollPagePosition(pos) return self:getScrollPagePosition(pos)
else else
return self:getSinglePagePosition(pos) return self:getSinglePagePosition(pos)
end end
else else
pos.page = self.ui.document:getCurrentPage() pos.page = self.document:getCurrentPage()
-- local last_y = self.ui.document:getCurrentPos() -- local last_y = self.document:getCurrentPos()
logger.dbg("document has no pages at", pos) logger.dbg("document has no pages at", pos)
return pos return pos
end end
@ -263,7 +262,7 @@ end
Given rectangle in original page return rectangle on the screen Given rectangle in original page return rectangle on the screen
]]-- ]]--
function ReaderView:pageToScreenTransform(page, rect) function ReaderView:pageToScreenTransform(page, rect)
if self.ui.document.info.has_pages then if self.ui.paging then
if self.page_scroll then if self.page_scroll then
return self:getScrollPageRect(page, rect) return self:getScrollPageRect(page, rect)
else else
@ -278,7 +277,7 @@ end
Get page area on screen for a given page number Get page area on screen for a given page number
--]] --]]
function ReaderView:getScreenPageArea(page) function ReaderView:getScreenPageArea(page)
if self.ui.document.info.has_pages then if self.ui.paging then
local area = Geom:new{x = 0, y = 0} local area = Geom:new{x = 0, y = 0}
if self.page_scroll then if self.page_scroll then
for _, state in ipairs(self.page_states) do for _, state in ipairs(self.page_states) do
@ -313,7 +312,7 @@ function ReaderView:drawPageSurround(bb, x, y)
bb:paintRect(x, y, self.dimen.w, self.state.offset.y, self.outer_page_color) bb:paintRect(x, y, self.dimen.w, self.state.offset.y, self.outer_page_color)
local bottom_margin = y + self.visible_area.h + self.state.offset.y local bottom_margin = y + self.visible_area.h + self.state.offset.y
bb:paintRect(x, bottom_margin, self.dimen.w, self.state.offset.y + bb:paintRect(x, bottom_margin, self.dimen.w, self.state.offset.y +
self.ui.view.footer:getHeight(), self.outer_page_color) self.footer:getHeight(), self.outer_page_color)
end end
if self.dimen.w > self.visible_area.w then if self.dimen.w > self.visible_area.w then
bb:paintRect(x, y, self.state.offset.x, self.dimen.h, self.outer_page_color) bb:paintRect(x, y, self.state.offset.x, self.dimen.h, self.outer_page_color)
@ -325,7 +324,7 @@ end
function ReaderView:drawScrollPages(bb, x, y) function ReaderView:drawScrollPages(bb, x, y)
local pos = Geom:new{x = x , y = y} local pos = Geom:new{x = x , y = y}
for page, state in ipairs(self.page_states) do for page, state in ipairs(self.page_states) do
self.ui.document:drawPage( self.document:drawPage(
bb, bb,
pos.x + state.offset.x, pos.x + state.offset.x,
pos.y + state.offset.y, pos.y + state.offset.y,
@ -347,7 +346,7 @@ end
function ReaderView:getCurrentPageList() function ReaderView:getCurrentPageList()
local pages = {} local pages = {}
if self.ui.document.info.has_pages then if self.ui.paging then
if self.page_scroll then if self.page_scroll then
for _, state in ipairs(self.page_states) do for _, state in ipairs(self.page_states) do
table.insert(pages, state.page) table.insert(pages, state.page)
@ -400,7 +399,7 @@ function ReaderView:drawPageGap(bb, x, y)
end end
function ReaderView:drawSinglePage(bb, x, y) function ReaderView:drawSinglePage(bb, x, y)
self.ui.document:drawPage( self.document:drawPage(
bb, bb,
x + self.state.offset.x, x + self.state.offset.x,
y + self.state.offset.y, y + self.state.offset.y,
@ -438,7 +437,7 @@ function ReaderView:getSinglePageRect(rect_p)
end end
function ReaderView:drawPageView(bb, x, y) function ReaderView:drawPageView(bb, x, y)
self.ui.document:drawCurrentViewByPage( self.document:drawCurrentViewByPage(
bb, bb,
x + self.state.offset.x, x + self.state.offset.x,
y + self.state.offset.y, y + self.state.offset.y,
@ -447,7 +446,7 @@ function ReaderView:drawPageView(bb, x, y)
end end
function ReaderView:drawScrollView(bb, x, y) function ReaderView:drawScrollView(bb, x, y)
self.ui.document:drawCurrentViewByPos( self.document:drawCurrentViewByPos(
bb, bb,
x + self.state.offset.x, x + self.state.offset.x,
y + self.state.offset.y, y + self.state.offset.y,
@ -467,7 +466,7 @@ function ReaderView:drawTempHighlight(bb, x, y)
end end
function ReaderView:drawSavedHighlight(bb, x, y) function ReaderView:drawSavedHighlight(bb, x, y)
if self.ui.document.info.has_pages then if self.ui.paging then
self:drawPageSavedHighlight(bb, x, y) self:drawPageSavedHighlight(bb, x, y)
else else
self:drawXPointerSavedHighlight(bb, x, y) self:drawXPointerSavedHighlight(bb, x, y)
@ -482,7 +481,7 @@ function ReaderView:drawPageSavedHighlight(bb, x, y)
for i = 1, #items do for i = 1, #items do
local item = items[i] local item = items[i]
local pos0, pos1 = item.pos0, item.pos1 local pos0, pos1 = item.pos0, item.pos1
local boxes = self.ui.document:getPageBoxesFromPositions(page, pos0, pos1) local boxes = self.document:getPageBoxesFromPositions(page, pos0, pos1)
if boxes then if boxes then
for _, box in pairs(boxes) do for _, box in pairs(boxes) do
local rect = self:pageToScreenTransform(page, box) local rect = self:pageToScreenTransform(page, box)
@ -513,19 +512,19 @@ function ReaderView:drawXPointerSavedHighlight(bb, x, y)
-- Even in page mode, it's safer to use pos and ui.dimen.h -- Even in page mode, it's safer to use pos and ui.dimen.h
-- than pages' xpointers pos, even if ui.dimen.h is a bit -- than pages' xpointers pos, even if ui.dimen.h is a bit
-- larger than pages' heights -- larger than pages' heights
cur_view_top = self.ui.document:getCurrentPos() cur_view_top = self.document:getCurrentPos()
if self.view_mode == "page" and self.ui.document:getVisiblePageCount() > 1 then if self.view_mode == "page" and self.document:getVisiblePageCount() > 1 then
cur_view_bottom = cur_view_top + 2 * self.ui.dimen.h cur_view_bottom = cur_view_top + 2 * self.ui.dimen.h
else else
cur_view_bottom = cur_view_top + self.ui.dimen.h cur_view_bottom = cur_view_top + self.ui.dimen.h
end end
end end
local spos0 = self.ui.document:getPosFromXPointer(pos0) local spos0 = self.document:getPosFromXPointer(pos0)
local spos1 = self.ui.document:getPosFromXPointer(pos1) local spos1 = self.document:getPosFromXPointer(pos1)
local start_pos = math.min(spos0, spos1) local start_pos = math.min(spos0, spos1)
local end_pos = math.max(spos0, spos1) local end_pos = math.max(spos0, spos1)
if start_pos <= cur_view_bottom and end_pos >= cur_view_top then if start_pos <= cur_view_bottom and end_pos >= cur_view_top then
local boxes = self.ui.document:getScreenBoxesFromPositions(pos0, pos1, true) -- get_segments=true local boxes = self.document:getScreenBoxesFromPositions(pos0, pos1, true) -- get_segments=true
if boxes then if boxes then
for _, box in pairs(boxes) do for _, box in pairs(boxes) do
local rect = self:pageToScreenTransform(page, box) local rect = self:pageToScreenTransform(page, box)
@ -559,9 +558,9 @@ end
function ReaderView:getPageArea(page, zoom, rotation) function ReaderView:getPageArea(page, zoom, rotation)
if self.use_bbox then if self.use_bbox then
return self.ui.document:getUsedBBoxDimensions(page, zoom, rotation) return self.document:getUsedBBoxDimensions(page, zoom, rotation)
else else
return self.ui.document:getPageDimensions(page, zoom, rotation) return self.document:getPageDimensions(page, zoom, rotation)
end end
end end
@ -572,17 +571,17 @@ function ReaderView:recalculate()
-- Start by resetting the dithering flag early, so it doesn't carry over from the previous page. -- Start by resetting the dithering flag early, so it doesn't carry over from the previous page.
self.dialog.dithered = nil self.dialog.dithered = nil
if self.ui.document.info.has_pages and self.state.page then if self.ui.paging and self.state.page then
self.page_area = self:getPageArea( self.page_area = self:getPageArea(
self.state.page, self.state.page,
self.state.zoom, self.state.zoom,
self.state.rotation) self.state.rotation)
-- reset our size -- reset our size
self.visible_area:setSizeTo(self.dimen) self.visible_area:setSizeTo(self.dimen)
if self.ui.view.footer_visible and not self.ui.view.footer.settings.reclaim_height then if self.footer_visible and not self.footer.settings.reclaim_height then
self.visible_area.h = self.visible_area.h - self.ui.view.footer:getHeight() self.visible_area.h = self.visible_area.h - self.footer:getHeight()
end end
if self.ui.document.configurable.writing_direction == 0 then if self.document.configurable.writing_direction == 0 then
-- starts from left of page_area -- starts from left of page_area
self.visible_area.x = self.page_area.x self.visible_area.x = self.page_area.x
else else
@ -609,8 +608,8 @@ function ReaderView:recalculate()
end end
self.state.offset = Geom:new{x = 0, y = 0} self.state.offset = Geom:new{x = 0, y = 0}
if self.dimen.h > self.visible_area.h then if self.dimen.h > self.visible_area.h then
if self.ui.view.footer_visible and not self.ui.view.footer.settings.reclaim_height then if self.footer_visible and not self.footer.settings.reclaim_height then
self.state.offset.y = (self.dimen.h - (self.visible_area.h + self.ui.view.footer:getHeight())) / 2 self.state.offset.y = (self.dimen.h - (self.visible_area.h + self.footer:getHeight())) / 2
else else
self.state.offset.y = (self.dimen.h - self.visible_area.h) / 2 self.state.offset.y = (self.dimen.h - self.visible_area.h) / 2
end end
@ -740,9 +739,9 @@ function ReaderView:onSetFullScreen(full_screen)
end end
function ReaderView:onSetScrollMode(page_scroll) function ReaderView:onSetScrollMode(page_scroll)
if self.ui.document.info.has_pages and page_scroll if self.ui.paging and page_scroll
and self.ui.zooming.paged_modes[self.zoom_mode] and self.ui.zooming.paged_modes[self.zoom_mode]
and self.ui.document.configurable.text_wrap == 0 then and self.document.configurable.text_wrap == 0 then
UIManager:show(InfoMessage:new{ UIManager:show(InfoMessage:new{
text = _([[ text = _([[
Continuous view (scroll mode) works best with zoom to page width, zoom to content width or zoom to rows. Continuous view (scroll mode) works best with zoom to page width, zoom to content width or zoom to rows.
@ -754,7 +753,7 @@ In combination with zoom to fit page, page height, content height, content or co
self.page_scroll = page_scroll self.page_scroll = page_scroll
if not page_scroll then if not page_scroll then
self.ui.document.configurable.page_scroll = 0 self.document.configurable.page_scroll = 0
end end
self:recalculate() self:recalculate()
self.ui:handleEvent(Event:new("InitScrollPageStates")) self.ui:handleEvent(Event:new("InitScrollPageStates"))
@ -772,7 +771,7 @@ function ReaderView:onReadSettings(config)
rotation_mode = config:readSetting("rotation_mode") -- Doc's rotation_mode = config:readSetting("rotation_mode") -- Doc's
else else
-- No doc specific rotation, pickup global defaults for the doc type -- No doc specific rotation, pickup global defaults for the doc type
if self.ui.document.info.has_pages then if self.ui.paging then
rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or Screen.ORIENTATION_PORTRAIT rotation_mode = G_reader_settings:readSetting("kopt_rotation_mode") or Screen.ORIENTATION_PORTRAIT
else else
rotation_mode = G_reader_settings:readSetting("copt_rotation_mode") or Screen.ORIENTATION_PORTRAIT rotation_mode = G_reader_settings:readSetting("copt_rotation_mode") or Screen.ORIENTATION_PORTRAIT
@ -864,17 +863,17 @@ end
function ReaderView:onReaderFooterVisibilityChange() function ReaderView:onReaderFooterVisibilityChange()
-- Don't bother ReaderRolling with this nonsense, the footer's height is NOT handled via visible_area there ;) -- Don't bother ReaderRolling with this nonsense, the footer's height is NOT handled via visible_area there ;)
if self.ui.document.info.has_pages and self.state.page then if self.ui.paging and self.state.page then
-- NOTE: Simply relying on recalculate would be a wee bit too much: it'd reset the in-page offsets, -- NOTE: Simply relying on recalculate would be a wee bit too much: it'd reset the in-page offsets,
-- which would be wrong, and is also not necessary, since the footer is at the bottom of the screen ;). -- which would be wrong, and is also not necessary, since the footer is at the bottom of the screen ;).
-- So, simply mangle visible_area's height ourselves... -- So, simply mangle visible_area's height ourselves...
if not self.ui.view.footer.settings.reclaim_height then if not self.footer.settings.reclaim_height then
-- NOTE: Yes, this means that toggling reclaim_height requires a page switch (for a proper recalculate). -- NOTE: Yes, this means that toggling reclaim_height requires a page switch (for a proper recalculate).
-- Thankfully, most of the time, the quirks are barely noticeable ;). -- Thankfully, most of the time, the quirks are barely noticeable ;).
if self.ui.view.footer_visible then if self.footer_visible then
self.visible_area.h = self.visible_area.h - self.ui.view.footer:getHeight() self.visible_area.h = self.visible_area.h - self.footer:getHeight()
else else
self.visible_area.h = self.visible_area.h + self.ui.view.footer:getHeight() self.visible_area.h = self.visible_area.h + self.footer:getHeight()
end end
end end
self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area)) self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area))
@ -889,6 +888,33 @@ function ReaderView:onGammaUpdate(gamma)
Notification:notify(T(_("Font gamma set to: %1."), gamma)) Notification:notify(T(_("Font gamma set to: %1."), gamma))
end end
-- For ReaderKOptListener
function ReaderView:onDitheringUpdate()
-- Do the device cap checks again, to avoid snafus when sharing configs between devices
if Device:hasEinkScreen() then
if Device:canHWDither() then
if self.document.configurable.hw_dithering then
self.document.hw_dithering = self.document.configurable.hw_dithering == 1
end
elseif Screen.fb_bpp == 8 then
if self.document.configurable.sw_dithering then
self.document.sw_dithering = self.document.configurable.sw_dithering == 1
end
end
end
end
-- For KOptOptions
function ReaderView:onHWDitheringUpdate(toggle)
self.document.hw_dithering = toggle
Notification:notify(T(_("Hardware dithering set to: %1."), tostring(toggle)))
end
function ReaderView:onSWDitheringUpdate(toggle)
self.document.sw_dithering = toggle
Notification:notify(T(_("Software dithering set to: %1."), tostring(toggle)))
end
function ReaderView:onFontSizeUpdate(font_size) function ReaderView:onFontSizeUpdate(font_size)
self.ui:handleEvent(Event:new("ReZoom", font_size)) self.ui:handleEvent(Event:new("ReZoom", font_size))
Notification:notify(T(_("Font zoom set to: %1."), font_size)) Notification:notify(T(_("Font zoom set to: %1."), font_size))
@ -909,7 +935,7 @@ end
function ReaderView:onSetViewMode(new_mode) function ReaderView:onSetViewMode(new_mode)
if new_mode ~= self.view_mode then if new_mode ~= self.view_mode then
self.view_mode = new_mode self.view_mode = new_mode
self.ui.document:setViewMode(new_mode) self.document:setViewMode(new_mode)
self.ui:handleEvent(Event:new("ChangeViewMode")) self.ui:handleEvent(Event:new("ChangeViewMode"))
Notification:notify(T( _("View mode set to: %1"), optionsutil:getOptionText("SetViewMode", new_mode))) Notification:notify(T( _("View mode set to: %1"), optionsutil:getOptionText("SetViewMode", new_mode)))
end end
@ -1006,7 +1032,7 @@ function ReaderView:checkAutoSaveSettings()
end end
function ReaderView:isOverlapAllowed() function ReaderView:isOverlapAllowed()
if self.ui.document.info.has_pages then if self.ui.paging then
return not self.page_scroll return not self.page_scroll
and (self.ui.paging.zoom_mode ~= "page" and (self.ui.paging.zoom_mode ~= "page"
or (self.ui.paging.zoom_mode == "page" and self.ui.paging.is_reflowed)) or (self.ui.paging.zoom_mode == "page" and self.ui.paging.is_reflowed))

View File

@ -75,9 +75,14 @@ function Document:_init()
date = "" date = ""
} }
-- Should be updated by a call to Document.updateColorRendering(self) -- Should be updated by a call to Document.updateColorRendering(self) in subclasses
-- in subclasses
self.render_color = false self.render_color = false
-- Those may be updated via KOptOptions, or the DitheringUpdate event.
-- Whether HW dithering is enabled
self.hw_dithering = false
-- Whether SW dithering is enabled
self.sw_dithering = false
end end
-- override this method to open a document -- override this method to open a document
@ -496,9 +501,7 @@ Draw page content to blitbuffer.
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode) function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma, render_mode)
local tile = self:renderPage(pageno, rect, zoom, rotation, gamma, render_mode) local tile = self:renderPage(pageno, rect, zoom, rotation, gamma, render_mode)
-- Enable SW dithering if requested (only available in koptoptions) -- Enable SW dithering if requested (only available in koptoptions)
-- Much Like ReaderView, also enforce SW dithering in PicDocument if the device can't do HW dithering... if self.sw_dithering then
if (self.is_pic and CanvasContext:hasEinkScreen() and not CanvasContext:canHWDither() and CanvasContext.fb_bpp == 8)
or (self.configurable.sw_dithering and self.configurable.sw_dithering == 1) then
target:ditherblitFrom(tile.bb, target:ditherblitFrom(tile.bb,
x, y, x, y,
rect.x - tile.excerpt.x, rect.x - tile.excerpt.x,

View File

@ -26,6 +26,15 @@ function PicDocument:init()
self.info.has_pages = true self.info.has_pages = true
self.info.configurable = false self.info.configurable = false
-- Enforce dithering in PicDocument
if CanvasContext:hasEinkScreen() then
if CanvasContext:canHWDither() then
self.hw_dithering = true
elseif CanvasContext.fb_bpp == 8 then
self.sw_dithering = true
end
end
self:_readMetadata() self:_readMetadata()
end end

View File

@ -502,6 +502,8 @@ This can also be used to remove some gray background or to convert a grayscale o
values = {0, 1}, values = {0, 1},
default_value = 0, default_value = 0,
advanced = true, advanced = true,
event = "HWDitheringUpdate",
args = {false, true},
show = Device:hasEinkScreen() and Device:canHWDither(), show = Device:hasEinkScreen() and Device:canHWDither(),
name_text_hold_callback = optionsutil.showValues, name_text_hold_callback = optionsutil.showValues,
help_text = _([[Enable hardware dithering.]]), help_text = _([[Enable hardware dithering.]]),
@ -513,6 +515,8 @@ This can also be used to remove some gray background or to convert a grayscale o
values = {0, 1}, values = {0, 1},
default_value = 0, default_value = 0,
advanced = true, advanced = true,
event = "SWDitheringUpdate",
args = {false, true},
show = Device:hasEinkScreen() and not Device:canHWDither() and Device.screen.fb_bpp == 8, show = Device:hasEinkScreen() and not Device:canHWDither() and Device.screen.fb_bpp == 8,
name_text_hold_callback = optionsutil.showValues, name_text_hold_callback = optionsutil.showValues,
help_text = _([[Enable software dithering.]]), help_text = _([[Enable software dithering.]]),