From e074b603e0d0ef976ddf911c4612af0ec338e8bb Mon Sep 17 00:00:00 2001 From: poire-z Date: Sun, 3 May 2020 18:06:58 +0200 Subject: [PATCH] Adds Word Expansion: use of letter spacing for justification Bump crengine: - Text: fix occasional BiDi bad word splitting - Font: fix HB fallback measurement/drawing mismatches - Font: do not add letter spacing on diacritics - Text: tunable use of letter spacing for justification - Text: dont adjust space after initial quotation mark/dash (rework) - Text: fix possible bad widths after collapsed spaces xtext.cpp: pick crengine fix with HB fallback measurement/drawing mismatches Adds "Word Expansion" to bottom Font size menu, and moved "Word Spacing" there too, to balance the panels' heights to 4 items. --- .luacheckrc | 3 + base | 2 +- defaults.lua | 7 ++ frontend/apps/reader/modules/readerfont.lua | 12 +++ frontend/document/credocument.lua | 5 ++ frontend/ui/data/creoptions.lua | 83 ++++++++++++++------- frontend/ui/data/strings.lua | 4 + spec/unit/defaults_spec.lua | 33 ++++---- 8 files changed, 108 insertions(+), 41 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 58eda1a43..9298cedb7 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -106,6 +106,9 @@ read_globals = { "DCREREADER_CONFIG_WORD_SPACING_SMALL", "DCREREADER_CONFIG_WORD_SPACING_MEDIUM", "DCREREADER_CONFIG_WORD_SPACING_LARGE", + "DCREREADER_CONFIG_WORD_EXPANSION_NONE", + "DCREREADER_CONFIG_WORD_EXPANSION_SOME", + "DCREREADER_CONFIG_WORD_EXPANSION_MORE", "DMINIBAR_CONTAINER_HEIGHT", "DGESDETECT_DISABLE_DOUBLE_TAP", "FRONTLIGHT_SENSITIVITY_DECREASE", diff --git a/base b/base index 57c848f36..87300d3b0 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit 57c848f3630e150321cfb8a975cc905070cb316e +Subproject commit 87300d3b026b15f2e6a87505efe8261bf406a1d1 diff --git a/defaults.lua b/defaults.lua index 14d60e450..4168eb94f 100644 --- a/defaults.lua +++ b/defaults.lua @@ -185,6 +185,13 @@ DCREREADER_CONFIG_WORD_SPACING_SMALL = {75, 50} DCREREADER_CONFIG_WORD_SPACING_MEDIUM = {95, 75} DCREREADER_CONFIG_WORD_SPACING_LARGE = {100, 90} +-- word expansion, to reduce excessive spacing on justified line +-- by using letter spacing on the words +-- value is the max allowed added letter spacing, as a % of the font size +DCREREADER_CONFIG_WORD_EXPANSION_NONE = 0 +DCREREADER_CONFIG_WORD_EXPANSION_SOME = 5 +DCREREADER_CONFIG_WORD_EXPANSION_MORE = 15 + -- crereader progress bar (no longer needed) -- 0 for top "full" progress bar -- 1 for bottom "mini" progress bar diff --git a/frontend/apps/reader/modules/readerfont.lua b/frontend/apps/reader/modules/readerfont.lua index af8c39cc6..9479b125d 100644 --- a/frontend/apps/reader/modules/readerfont.lua +++ b/frontend/apps/reader/modules/readerfont.lua @@ -125,6 +125,10 @@ function ReaderFont:onReadSettings(config) or G_reader_settings:readSetting("copt_word_spacing") or {95, 75} self.ui.document:setWordSpacing(self.word_spacing) + self.word_expansion = config:readSetting("word_expansion") + or G_reader_settings:readSetting("copt_word_expansion") or 0 + self.ui.document:setWordExpansion(self.word_expansion) + self.line_space_percent = config:readSetting("line_space_percent") or G_reader_settings:readSetting("copt_line_spacing") or DCREREADER_CONFIG_LINE_SPACE_PERCENT_MEDIUM @@ -239,6 +243,13 @@ function ReaderFont:onSetWordSpacing(values) return true end +function ReaderFont:onSetWordExpansion(value) + self.word_expansion = value + self.ui.document:setWordExpansion(value) + self.ui:handleEvent(Event:new("UpdatePos")) + return true +end + function ReaderFont:onSetFontGamma(gamma) self.gamma_index = gamma self.ui.document:setGammaIndex(self.gamma_index) @@ -259,6 +270,7 @@ function ReaderFont:onSaveSettings() self.ui.doc_settings:saveSetting("font_hinting", self.font_hinting) self.ui.doc_settings:saveSetting("font_kerning", self.font_kerning) self.ui.doc_settings:saveSetting("word_spacing", self.word_spacing) + self.ui.doc_settings:saveSetting("word_expansion", self.word_expansion) self.ui.doc_settings:saveSetting("line_space_percent", self.line_space_percent) self.ui.doc_settings:saveSetting("gamma_index", self.gamma_index) end diff --git a/frontend/document/credocument.lua b/frontend/document/credocument.lua index c396522ff..5d16baf11 100644 --- a/frontend/document/credocument.lua +++ b/frontend/document/credocument.lua @@ -812,6 +812,11 @@ function CreDocument:setWordSpacing(values) self._document:setIntProperty("crengine.style.space.condensing.percent", values[2]) end +function CreDocument:setWordExpansion(value) + logger.dbg("CreDocument: set word expansion", value) + self._document:setIntProperty("crengine.style.max.added.letter.spacing.percent", value or 0) +end + function CreDocument:setStyleSheet(new_css_file, appended_css_content ) logger.dbg("CreDocument: set style sheet:", new_css_file and new_css_file or "no file", diff --git a/frontend/ui/data/creoptions.lua b/frontend/ui/data/creoptions.lua index 8b9e38054..9f8f35ac6 100644 --- a/frontend/ui/data/creoptions.lua +++ b/frontend/ui/data/creoptions.lua @@ -300,7 +300,7 @@ Note that your selected font size is not affected by this setting.]]), }, { name = "font_fine_tune", - name_text = S.FONTSIZE_FINE_TUNING, + name_text = S.FONT_SIZE, toggle = Device:isTouchDevice() and {S.DECREASE, S.INCREASE} or nil, item_text = not Device:isTouchDevice() and {S.DECREASE, S.INCREASE} or nil, more_options = true, @@ -325,7 +325,63 @@ Note that your selected font size is not affected by this setting.]]), } optionsutil.showValues(configurable, opt, prefix) end, - } + }, + { + name = "word_spacing", + name_text = S.WORD_SPACING, + toggle = {S.SMALL, S.MEDIUM, S.LARGE}, + values = { + DCREREADER_CONFIG_WORD_SPACING_SMALL, + DCREREADER_CONFIG_WORD_SPACING_MEDIUM, + DCREREADER_CONFIG_WORD_SPACING_LARGE, + }, + default_value = DCREREADER_CONFIG_WORD_SPACING_MEDIUM, + args = { + DCREREADER_CONFIG_WORD_SPACING_SMALL, + DCREREADER_CONFIG_WORD_SPACING_MEDIUM, + DCREREADER_CONFIG_WORD_SPACING_LARGE, + }, + event = "SetWordSpacing", + help_text = _([[Tells the rendering engine how much to scale the width of each 'space' character in the text from its regular width, and how much it can additionally reduce them to make more words fit on a line (100% means no reduction).]]), + name_text_hold_callback = optionsutil.showValues, + name_text_true_values = true, + show_true_value_func = function(val) + return string.format("%d%%, +%d%%", val[1], val[2]) + end, + }, + { + name = "word_expansion", + name_text = S.WORD_EXPANSION, + more_options = true, + more_options_param = { + value_min = 0, + value_max = 20, + value_step = 1, + value_hold_step = 4, + name = "word_expansion", + name_text = _("Allowed word expansion (%)"), + event = "SetWordExpansion", + }, + toggle = {S.NONE, S.SOME, S.MORE}, + values = { + DCREREADER_CONFIG_WORD_EXPANSION_NONE, + DCREREADER_CONFIG_WORD_EXPANSION_SOME, + DCREREADER_CONFIG_WORD_EXPANSION_MORE, + }, + default_value = DCREREADER_CONFIG_WORD_EXPANSION_NONE, + args = { + DCREREADER_CONFIG_WORD_EXPANSION_NONE, + DCREREADER_CONFIG_WORD_EXPANSION_SOME, + DCREREADER_CONFIG_WORD_EXPANSION_MORE, + }, + event = "SetWordExpansion", + help_text = _([[On justified lines having too wide spaces, allow distributing the excessive space into words by expanding them with letter spacing. This sets the max allowed letter spacing as a % of the font size.]]), + name_text_hold_callback = optionsutil.showValues, + name_text_true_values = true, + show_true_value_func = function(val) + return string.format("%d%%", val) + end, + }, } }, { @@ -400,29 +456,6 @@ Note that your selected font size is not affected by this setting.]]), (Font Hinting may need to be adjusted for the best result with either kerning implementation.)]]), }, - { - name = "word_spacing", - name_text = S.WORD_SPACING, - toggle = {S.SMALL, S.MEDIUM, S.LARGE}, - values = { - DCREREADER_CONFIG_WORD_SPACING_SMALL, - DCREREADER_CONFIG_WORD_SPACING_MEDIUM, - DCREREADER_CONFIG_WORD_SPACING_LARGE, - }, - default_value = DCREREADER_CONFIG_WORD_SPACING_MEDIUM, - args = { - DCREREADER_CONFIG_WORD_SPACING_SMALL, - DCREREADER_CONFIG_WORD_SPACING_MEDIUM, - DCREREADER_CONFIG_WORD_SPACING_LARGE, - }, - event = "SetWordSpacing", - help_text = _([[Tells the rendering engine how much to scale the width of each 'space' character in the text from its regular width, and how much it can additionally reduce them to make more words fit on a line (100% means no reduction).]]), - name_text_hold_callback = optionsutil.showValues, - name_text_true_values = true, - show_true_value_func = function(val) - return string.format("%d%%, +%d%%", val[1], val[2]) - end, - } } }, { diff --git a/frontend/ui/data/strings.lua b/frontend/ui/data/strings.lua index 5db647faa..ceef5ae05 100644 --- a/frontend/ui/data/strings.lua +++ b/frontend/ui/data/strings.lua @@ -17,6 +17,7 @@ S.COLUMNS = _("Columns") -- @translators Text alignment. Options given as icons: left, right, center, justify. S.TEXT_ALIGN = _("Alignment") S.FONTSIZE_FINE_TUNING = _("Fine Tuning") +S.FONT_SIZE = _("Font Size") S.CONTRAST = _("Contrast") -- @translators Reflow text. S.REFLOW = _("Reflow") @@ -34,6 +35,7 @@ S.GAMMA = _("Gamma") S.FONT_HINT = _("Font Hinting") S.FONT_KERNING = _("Font Kerning") S.WORD_SPACING = _("Word Spacing") +S.WORD_EXPANSION = _("Word Expansion") S.VIEW_MODE = _("View Mode") S.EMBEDDED_STYLE = _("Embedded Style") S.EMBEDDED_FONTS = _("Embedded Fonts") @@ -57,6 +59,8 @@ S.NONE = _("none") S.SMALL = _("small") S.MEDIUM = _("medium") S.LARGE = _("large") +S.SOME = _("some") +S.MORE = _("more") S.DECREASE = _("decrease") S.INCREASE = _("increase") S.LIGHTEST = _("lightest") diff --git a/spec/unit/defaults_spec.lua b/spec/unit/defaults_spec.lua index e8efddc85..a9e5686d0 100644 --- a/spec/unit/defaults_spec.lua +++ b/spec/unit/defaults_spec.lua @@ -8,24 +8,27 @@ describe("defaults module", function() it("should load all defaults from defaults.lua", function() Defaults:init() - assert.is_same(103, #Defaults.defaults_name) + assert.is_same(106, #Defaults.defaults_name) end) it("should save changes to defaults.persistent.lua", function() local persistent_filename = DataStorage:getDataDir() .. "/defaults.persistent.lua" os.remove(persistent_filename) + -- To see indices and help updating this when new settings are added: + -- for i=1, 106 do print(i.." ".. Defaults.defaults_name[i]) end + -- not in persistent but checked in defaults Defaults.changed[20] = true - Defaults.changed[47] = true - Defaults.changed[53] = true - Defaults.changed[82] = true - Defaults.changed[98] = true --SEARCH_LIBRARY_PATH = "" + Defaults.changed[50] = true + Defaults.changed[56] = true + Defaults.changed[85] = true + Defaults.changed[101] = true --SEARCH_LIBRARY_PATH = "" Defaults:saveSettings() - assert.is_same(103, #Defaults.defaults_name) - assert.is_same("SEARCH_LIBRARY_PATH", Defaults.defaults_name[98]) - assert.is_same("DTAP_ZONE_BACKWARD", Defaults.defaults_name[82]) - assert.is_same("DCREREADER_CONFIG_WORD_SPACING_LARGE", Defaults.defaults_name[47]) + assert.is_same(106, #Defaults.defaults_name) + assert.is_same("SEARCH_LIBRARY_PATH", Defaults.defaults_name[101]) + assert.is_same("DTAP_ZONE_BACKWARD", Defaults.defaults_name[85]) + assert.is_same("DCREREADER_CONFIG_WORD_SPACING_LARGE", Defaults.defaults_name[50]) assert.is_same("DCREREADER_CONFIG_H_MARGIN_SIZES_XXX_LARGE", Defaults.defaults_name[20]) local fd = io.open(persistent_filename, "r") assert.Equals( @@ -57,15 +60,15 @@ DDOUBLE_TAP_ZONE_PREV_CHAPTER = { -- in persistent Defaults:init() - Defaults.changed[53] = true - Defaults.defaults_value[53] = { + Defaults.changed[56] = true + Defaults.defaults_value[56] = { y = 0, x = 0, h = 0.25, w = 0.75 } - Defaults.changed[82] = true - Defaults.defaults_value[82] = { + Defaults.changed[85] = true + Defaults.defaults_value[85] = { y = 10, x = 10.125, h = 20.25, @@ -119,8 +122,8 @@ DHINTCOUNT = 2 -- in persistent Defaults:init() - Defaults.changed[54] = true - Defaults.defaults_value[54] = 1 + Defaults.changed[57] = true + Defaults.defaults_value[57] = 1 Defaults:saveSettings() fd = io.open(persistent_filename) assert.Equals(