diff --git a/frontend/apps/reader/modules/readerbookmark.lua b/frontend/apps/reader/modules/readerbookmark.lua index a5af33603..d620253c0 100644 --- a/frontend/apps/reader/modules/readerbookmark.lua +++ b/frontend/apps/reader/modules/readerbookmark.lua @@ -586,4 +586,8 @@ function ReaderBookmark:getLatestBookmark() return latest_bookmark end +function ReaderBookmark:hasBookmarks() + return self.bookmarks and #self.bookmarks > 0 +end + return ReaderBookmark diff --git a/frontend/apps/reader/modules/readerrolling.lua b/frontend/apps/reader/modules/readerrolling.lua index 7228aeda0..9c95afb77 100644 --- a/frontend/apps/reader/modules/readerrolling.lua +++ b/frontend/apps/reader/modules/readerrolling.lua @@ -221,13 +221,20 @@ end function ReaderRolling:onCheckDomStyleCoherence() if self.ui.document and self.ui.document:isBuiltDomStale() then + local has_bookmarks_warn_txt = "" + if self.ui.bookmark:hasBookmarks() then + has_bookmarks_warn_txt = _("\nNote that this change in styles may render your bookmarks or highlights no more valid.\nIf some of them do not show anymore, you can just revert the change you just made to have them shown again.\n\n") + end UIManager:show(ConfirmBox:new{ - text = _("Styles have changed in such a way that fully reloading the document may be needed for a correct rendering.\nDo you want to reload the document?"), + text = T(_("Styles have changed in such a way that fully reloading the document may be needed for a correct rendering.\n%1Do you want to reload the document?"), has_bookmarks_warn_txt), ok_callback = function() -- Allow for ConfirmBox to be closed before showing -- "Opening file" InfoMessage UIManager:scheduleIn(0.5, function () - self.ui:reloadDocument() + -- And check we haven't quit reader in these 0.5s + if self.ui.document then + self.ui:reloadDocument() + end end) end, }) @@ -660,6 +667,10 @@ function ReaderRolling:onUpdatePos() end function ReaderRolling:updatePos() + if not self.ui.document then + -- document closed since we were scheduleIn'ed + return + end -- reread document height self.ui.document:_readMetadata() -- update self.current_pos if the height of document has been changed. diff --git a/frontend/apps/reader/modules/readertypeset.lua b/frontend/apps/reader/modules/readertypeset.lua index 384cf4159..26ac987a1 100644 --- a/frontend/apps/reader/modules/readertypeset.lua +++ b/frontend/apps/reader/modules/readertypeset.lua @@ -52,6 +52,24 @@ function ReaderTypeset:onReadSettings(config) end self.ui.document:setEmbeddedStyleSheet(self.embedded_css and 1 or 0) + -- Block rendering mode: stay with legacy rendering for books + -- previously opened so bookmarks and highlights stay valid. + -- For new books, use 'web' mode below in BLOCK_RENDERING_FLAGS + local block_rendering_default_mode = 3 + self.block_rendering_mode = config:readSetting("copt_block_rendering_mode") + if not self.block_rendering_mode then + if config:readSetting("last_xpointer") then + -- We have a last_xpointer: this book was previously opened + self.block_rendering_mode = 0 + else + self.block_rendering_mode = G_reader_settings:readSetting("copt_block_rendering_mode") + or block_rendering_default_mode + end + -- Let ConfigDialog know so it can update it on screen and have it saved on quit + self.ui.document.configurable.block_rendering_mode = self.block_rendering_mode + end + self:setBlockRenderingMode(self.block_rendering_mode) + -- set render DPI self.render_dpi = config:readSetting("render_dpi") or G_reader_settings:readSetting("copt_render_dpi") or 96 @@ -136,6 +154,11 @@ function ReaderTypeset:onToggleNightmodeImages(toggle) return true end +function ReaderTypeset:onSetBlockRenderingMode(mode) + self:setBlockRenderingMode(mode) + 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 @@ -191,11 +214,15 @@ function ReaderTypeset:genStyleSheetMenu() css_files[f] = "./data/"..f end end - -- Add the 2 main styles + -- Add the 3 main styles if css_files["epub.css"] then table.insert(style_table, getStyleMenuItem(_("HTML / EPUB (epub.css)"), css_files["epub.css"])) css_files["epub.css"] = nil end + if css_files["html5.css"] then + table.insert(style_table, getStyleMenuItem(_("HTML5 (html5.css)"), css_files["html5.css"])) + css_files["html5.css"] = nil + end if css_files["fb2.css"] then table.insert(style_table, getStyleMenuItem(_("FictionBook (fb2.css)"), css_files["fb2.css"], true)) css_files["fb2.css"] = nil @@ -289,6 +316,54 @@ function ReaderTypeset:toggleEmbeddedFonts(toggle) self.ui:handleEvent(Event:new("UpdatePos")) end +-- crengine enhanced block rendering feature/flags (see crengine/include/lvrend.h): +-- legacy flat book web +-- ENHANCED 0x00000001 x x x +-- ALLOW_PAGE_BREAK_WHEN_NO_CONTENT 0x00000002 x +-- +-- COLLAPSE_VERTICAL_MARGINS 0x00000010 x x x +-- ALLOW_VERTICAL_NEGATIVE_MARGINS 0x00000020 x x x +-- ALLOW_NEGATIVE_COLLAPSED_MARGINS 0x00000040 x +-- +-- ENSURE_MARGIN_AUTO_ALIGNMENT 0x00000100 x x +-- ALLOW_HORIZONTAL_NEGATIVE_MARGINS 0x00000200 x +-- ALLOW_HORIZONTAL_BLOCK_OVERFLOW 0x00000400 x +-- ALLOW_HORIZONTAL_PAGE_OVERFLOW 0x00000800 x +-- +-- USE_W3C_BOX_MODEL 0x00001000 x x x +-- ALLOW_STYLE_W_H_ABSOLUTE_UNITS 0x00002000 x +-- ENSURE_STYLE_WIDTH 0x00004000 x x +-- ENSURE_STYLE_HEIGHT 0x00008000 x +-- +-- WRAP_FLOATS 0x00010000 x x x +-- PREPARE_FLOATBOXES 0x00020000 x x x +-- FLOAT_FLOATBOXES 0x00040000 x x +-- DO_NOT_CLEAR_OWN_FLOATS 0x00100000 x x +-- ALLOW_EXACT_FLOATS_FOOTPRINTS 0x00200000 x x + +local BLOCK_RENDERING_FLAGS = { + 0x00000000, -- legacy block rendering + 0x00030031, -- flat mode (with prepared floatBoxes, so inlined, to avoid display hash mismatch) + 0x00375131, -- book mode (floating floatBoxes, limited widths support) + 0x7FFFFFFF, -- web mode, all features/flags +} + +function ReaderTypeset:setBlockRenderingMode(mode) + -- mode starts for now with 0 = legacy, so we may later be able + -- to remove it and then start with 1 = flat + -- (Ensure we don't crash if we added and removed some options) + if mode + 1 > #BLOCK_RENDERING_FLAGS then + mode = #BLOCK_RENDERING_FLAGS - 1 + end + local flags = BLOCK_RENDERING_FLAGS[mode + 1] + if not flags then + return + end + self.block_rendering_mode = mode + self.ui.document:setBlockRenderingFlags(flags) + self.ui:handleEvent(Event:new("UpdatePos")) +end + function ReaderTypeset:toggleImageScaling(toggle) if toggle and (toggle == true or toggle == 1) then self.smooth_scaling = true diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index 01030535a..905bc2424 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -732,6 +732,11 @@ function CreDocument:setPageMargins(left, top, right, bottom) self._document:setIntProperty("crengine.page.margin.bottom", bottom) end +function CreDocument:setBlockRenderingFlags(flags) + logger.dbg("CreDocument: set block rendering flags", string.format("0x%x", flags)) + self._document:setIntProperty("crengine.render.block.rendering.flags", flags) +end + function CreDocument:setImageScaling(toggle) logger.dbg("CreDocument: set smooth scaling", toggle) self._smooth_scaling = toggle diff --git a/frontend/ui/data/creoptions.lua b/frontend/ui/data/creoptions.lua index f0f74a3e9..a9cce0138 100644 --- a/frontend/ui/data/creoptions.lua +++ b/frontend/ui/data/creoptions.lua @@ -193,6 +193,22 @@ In the top menu → Settings → Status bar, you can choose whether the bottom m name_text_hold_callback = optionsutil.showValues, help_text = _([[- 'scroll' mode allows you to scroll the text like you would in a web browser (the 'Page Overlap' setting is only available in this mode). - 'page' mode splits the text into pages, at the most acceptable places (page numbers and the number of pages may change when you change fonts, margins, styles, etc.).]]), + }, + { + name = "block_rendering_mode", + name_text = S.BLOCK_RENDERING_MODE, + toggle = {S.LEGACY, S.FLAT, S.BOOK, S.WEB}, + values = {0, 1, 2, 3}, + default_value = 2, + args = {0, 1, 2, 3}, + default_arg = 2, + event = "SetBlockRenderingMode", + name_text_hold_callback = optionsutil.showValues, + help_text = _([[ +- 'legacy' uses original CR3 block rendering code. +- 'flat' ensures flat rendering with collapsing margins and accurate page breaks. +- 'book' additionally allows floats, but limits style support to avoid blank spaces and overflows. +- 'web' renders as web browsers do, allowing negative margins and possible page overflow.]]), }, { name = "render_dpi", diff --git a/frontend/ui/data/strings.lua b/frontend/ui/data/strings.lua index 1bcd29238..a93134212 100644 --- a/frontend/ui/data/strings.lua +++ b/frontend/ui/data/strings.lua @@ -34,6 +34,7 @@ S.FONT_KERNING = _("Font Kerning") S.VIEW_MODE = _("View Mode") S.EMBEDDED_STYLE = _("Embedded Style") S.EMBEDDED_FONTS = _("Embedded Fonts") +S.BLOCK_RENDERING_MODE = _("Render Mode") S.WRITING_DIR = _("Writing Direction") S.PROGRESS_BAR = _("Progress Bar") S.FORCED_OCR = _("Forced OCR") @@ -83,5 +84,9 @@ S.LEFT = _("left") S.CENTER = _("center") S.RIGHT = _("right") S.JUSTIFY = _("justify") +S.LEGACY = _("legacy") +S.FLAT = _("flat") +S.BOOK = _("book") +S.WEB = _("web") return S diff --git a/spec/unit/readerfooter_spec.lua b/spec/unit/readerfooter_spec.lua index 5e1ffb1db..523e404fc 100644 --- a/spec/unit/readerfooter_spec.lua +++ b/spec/unit/readerfooter_spec.lua @@ -296,8 +296,8 @@ describe("Readerfooter module", function() assert.are.same(365, footer.text_width) footer:onPageUpdate(100) - assert.are.same(183, footer.progress_bar.width) - assert.are.same(397, footer.text_width) + assert.are.same(191, footer.progress_bar.width) + assert.are.same(389, footer.text_width) end) it("should support chapter markers", function() diff --git a/spec/unit/readerlink_spec.lua b/spec/unit/readerlink_spec.lua index e90f73c7a..c1cbfe547 100644 --- a/spec/unit/readerlink_spec.lua +++ b/spec/unit/readerlink_spec.lua @@ -17,9 +17,9 @@ describe("ReaderLink module", function() local readerui = ReaderUI:new{ document = DocumentRegistry:openDocument(sample_epub), } - readerui.rolling:onGotoPage(5) - readerui.link:onTap(nil, {pos = {x = 340, y = 70}}) - assert.is.same(38, readerui.rolling.current_page) + readerui.rolling:onGotoPage(4) + readerui.link:onTap(nil, {pos = {x = 340, y = 110}}) + assert.is.same(36, readerui.rolling.current_page) end) it("should jump to links in pdf page mode", function() @@ -54,11 +54,11 @@ describe("ReaderLink module", function() local readerui = ReaderUI:new{ document = DocumentRegistry:openDocument(sample_epub), } - readerui.rolling:onGotoPage(5) - readerui.link:onTap(nil, {pos = {x = 340, y = 70}}) - assert.is.same(38, readerui.rolling.current_page) + readerui.rolling:onGotoPage(4) + readerui.link:onTap(nil, {pos = {x = 340, y = 110}}) + assert.is.same(36, readerui.rolling.current_page) readerui.link:onGoBackLink() - assert.is.same(5, readerui.rolling.current_page) + assert.is.same(4, readerui.rolling.current_page) end) it("should be able to go back after link jump in pdf page mode", function() diff --git a/spec/unit/readerrolling_spec.lua b/spec/unit/readerrolling_spec.lua index d6acf8310..b4e09a7fe 100644 --- a/spec/unit/readerrolling_spec.lua +++ b/spec/unit/readerrolling_spec.lua @@ -186,13 +186,13 @@ describe("Readerrolling module", function() it("should show pages for different word gap", function() readerui.document:setSpaceCondensing(100) readerui:handleEvent(Event:new("ChangeScreenMode", "portrait")) - assert.are.same(249, readerui.document:getPageCount()) + assert.are.same(248, readerui.document:getPageCount()) readerui.document:setSpaceCondensing(75) readerui:handleEvent(Event:new("ChangeScreenMode", "portrait")) - assert.are.same(242, readerui.document:getPageCount()) + assert.are.same(241, readerui.document:getPageCount()) readerui.document:setSpaceCondensing(50) readerui:handleEvent(Event:new("ChangeScreenMode", "portrait")) - assert.are.same(233, readerui.document:getPageCount()) + assert.are.same(231, readerui.document:getPageCount()) end) end) @@ -201,7 +201,7 @@ describe("Readerrolling module", function() local ReaderView = require("apps/reader/modules/readerview") local saved_handler = ReaderView.onPageUpdate ReaderView.onPageUpdate = function(_self) - assert.are.same(7, _self.ui.document:getPageCount()) + assert.are.same(6, _self.ui.document:getPageCount()) end local test_book = "spec/front/unit/data/sample.txt" require("docsettings"):open(test_book):purge() diff --git a/spec/unit/readertoc_spec.lua b/spec/unit/readertoc_spec.lua index 85eeb44de..45e2bfdc9 100644 --- a/spec/unit/readertoc_spec.lua +++ b/spec/unit/readertoc_spec.lua @@ -72,7 +72,7 @@ describe("Readertoc module", function() assert.are.same(nil, toc:getChapterPagesLeft(290, 0)) end) it("should get page done of chapter", function() - assert.truthy(toc:getChapterPagesDone(12, 0) < 5) + assert.truthy(toc:getChapterPagesDone(11, 0) < 5) assert.truthy(toc:getChapterPagesDone(95, 0) < 5) assert.truthy(toc:getChapterPagesDone(290, 0) > 10) end)