@ -5,6 +5,20 @@ local optionsutil = require("ui/data/optionsutil")
local _ = require ( " gettext " )
local Screen = Device.screen
-- The values used for Font Size are not actually font sizes, but kopt zoom levels.
local FONT_SCALE_FACTORS = { 0.2 , 0.4 , 0.5 , 0.6 , 0.7 , 0.8 , 0.9 , 1.0 , 1.1 , 1.3 , 1.6 , 2.0 }
-- Font sizes used for the font size widget only
local FONT_SCALE_DISPLAY_SIZE = { 12 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 22 , 25 , 30 , 35 }
-- Get font scale numbers as a table of strings
local tableOfNumbersToTableOfStrings = function ( numbers )
local t = { }
for i , v in ipairs ( numbers ) do
table.insert ( t , string.format ( " %0.1f " , v ) )
end
return t
end
local KoptOptions = {
prefix = ' kopt ' ,
needs_redraw_on_change = true ,
@ -30,15 +44,35 @@ local KoptOptions = {
{
name = " trim_page " ,
name_text = S.PAGE_CROP ,
toggle = { S.MANUAL , S.AUTO , S.SEMIAUTO , S.NONE } ,
-- manual=0, auto=1, semi-auto=2, none=3
-- ordered from least to max cropping done or possible
toggle = { S.NONE , S.AUTO , S.SEMIAUTO , S.MANUAL } ,
alternate = false ,
values = { 0 , 1 , 2 , 3 } ,
values = { 3, 1 , 2 , 0 } ,
default_value = DKOPTREADER_CONFIG_TRIM_PAGE ,
enabled_func = Device.isTouchDevice ,
event = " PageCrop " ,
args = { " manual " , " auto " , " semi-auto " , " none " } ,
args = { " none " , " auto " , " semi-auto " , " manual " } ,
name_text_hold_callback = optionsutil.showValues ,
}
help_text = _ ( [ [ Allows cropping blank page margins in the original document .
This might be needed on scanned documents , that may have speckles or fingerprints in the margins , to be able to use zoom to fit content width .
- ' none ' does not cut the original document margins .
- ' auto ' finds content area automatically .
- ' semi-auto" finds content area automatically, inside some larger area defined manually.
- ' manual" uses the area defined manually as-is.
In ' semi-auto ' and ' manual ' modes , you may need to define areas once on an odd page number , and once on an even page number ( these areas will then be used for all odd , or even , page numbers ) . ] ] ) ,
} ,
{
name = " page_margin " ,
name_text = S.PAGE_MARGIN ,
toggle = { S.SMALL , S.MEDIUM , S.LARGE } ,
values = { 0.05 , 0.10 , 0.25 } ,
default_value = DKOPTREADER_CONFIG_PAGE_MARGIN ,
event = " MarginUpdate " ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[Set margins to be applied after page-crop and zoom modes are applied.]] ) ,
} ,
}
} ,
{
@ -47,12 +81,28 @@ local KoptOptions = {
{
name = " page_scroll " ,
name_text = S.VIEW_MODE ,
toggle = { S.VIEW_ SCROLL, S.VIEW_PAGE } ,
values = { 1, 0 } ,
toggle = { S.VIEW_ PAGE, S.VIEW_SCROLL } ,
values = { 0, 1 } ,
default_value = 1 ,
event = " SetScrollMode " ,
args = { true, fals e} ,
args = { false, tru e} ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [ [ - ' page ' mode shows only one page of the document at a time .
- ' continuous ' mode allows you to scroll the pages like you would in a web browser . ] ] ) ,
} ,
{
name = " page_gap_height " ,
name_text = S.PAGE_GAP ,
toggle = { S.NONE , S.SMALL , S.MEDIUM , S.LARGE } ,
values = { 0 , 8 , 16 , 32 } ,
default_value = 8 ,
args = { 0 , 8 , 16 , 32 } ,
event = " PageGapUpdate " ,
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " page_scroll " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[In continuous view mode, sets the thickness of the separator between document pages.]] ) ,
} ,
{
name = " full_screen " ,
@ -62,16 +112,7 @@ local KoptOptions = {
default_value = 1 ,
event = " SetFullScreen " ,
args = { true , false } ,
show = false ,
name_text_hold_callback = optionsutil.showValues ,
} ,
{
name = " page_margin " ,
name_text = S.PAGE_MARGIN ,
toggle = { S.SMALL , S.MEDIUM , S.LARGE } ,
values = { 0.05 , 0.10 , 0.25 } ,
default_value = DKOPTREADER_CONFIG_PAGE_MARGIN ,
event = " MarginUpdate " ,
show = false , -- toggling bottom status can be done via tap
name_text_hold_callback = optionsutil.showValues ,
} ,
{
@ -81,35 +122,12 @@ local KoptOptions = {
values = { 1.0 , 1.2 , 1.4 } ,
default_value = DKOPTREADER_CONFIG_LINE_SPACING ,
advanced = true ,
name_text_hold_callback = optionsutil.showValues ,
} ,
{
name = " page_gap_height " ,
name_text = S.PAGE_GAP ,
toggle = { S.NONE , S.SMALL , S.MEDIUM , S.LARGE } ,
values = { 0 , 8 , 16 , 32 } ,
default_value = 8 ,
args = { 0 , 8 , 16 , 32 } ,
event = " PageGapUpdate " ,
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " page_scroll " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
} ,
{
name = " max_columns " ,
name_text = S.COLUMNS ,
item_icons = {
" resources/icons/appbar.column.one.png " ,
" resources/icons/appbar.column.two.png " ,
" resources/icons/appbar.column.three.png " ,
} ,
values = { 1 , 2 , 3 } ,
default_value = DKOPTREADER_CONFIG_MAX_COLUMNS ,
enabled_func = function ( configurable )
-- seems to only work in reflow mode
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[In reflow mode, sets the spacing between lines.]] ) ,
} ,
{
name = " justification " ,
@ -129,6 +147,8 @@ local KoptOptions = {
end ,
labels = { S.AUTO , S.LEFT , S.CENTER , S.RIGHT , S.JUSTIFY } ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [ [ In reflow mode , sets the text alignment .
The first option ( " auto " ) tries to automatically align reflowed text as it is in the original document . ] ] ) ,
} ,
}
} ,
@ -137,13 +157,13 @@ local KoptOptions = {
options = {
{
name = " font_size " ,
item_text = { " Aa " , " Aa " , " Aa " , " Aa " , " Aa " , " Aa " , " Aa " , " Aa " } ,
item_text = tableOfNumbersToTableOfStrings ( FONT_SCALE_FACTORS ) ,
item_align_center = 1.0 ,
spacing = 15 ,
height = 60 ,
item_font_size = { 24 , 28 , 32 , 34 , 36 , 38 , 42 , 46 } ,
args = { 0.2 , 0.4 , 0.6 , 0.8 , 1.0 , 1.2 , 1.6 , 2.0 } ,
values = { 0.2 , 0.4 , 0.6 , 0.8 , 1.0 , 1.2 , 1.6 , 2.0 } ,
item_font_size = FONT_SCALE_DISPLAY_SIZE ,
args = FONT_SCALE_FACTORS ,
values = FONT_SCALE_FACTORS ,
default_value = DKOPTREADER_CONFIG_FONT_SIZE ,
event = " FontSizeUpdate " ,
enabled_func = function ( configurable , document )
@ -153,7 +173,7 @@ local KoptOptions = {
} ,
{
name = " font_fine_tune " ,
name_text = S.FONT SIZE_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 ,
values = { - 0.05 , 0.05 } ,
@ -169,37 +189,28 @@ local KoptOptions = {
local opt = {
name = " font_size " ,
name_text = _ ( " Font Size " ) ,
help_text = _ ( [[In reflow mode, sets a font scaling factor that is applied to the original document font sizes.]] ) ,
}
optionsutil.showValues ( configurable , opt , prefix )
end
}
}
end ,
} ,
{
icon = " resources/icons/appbar.grade.b.large.png " ,
options = {
{
name = " contrast " ,
name_text = S.CONTRAST ,
buttonprogress = true ,
values = { 1 / 0.8 , 1 / 1.0 , 1 / 1.5 , 1 / 2.0 , 1 / 3.0 , 1 / 4.0 , 1 / 6.0 , 1 / 9.0 } ,
default_pos = 2 ,
default_value = DKOPTREADER_CONFIG_CONTRAST ,
event = " GammaUpdate " ,
args = { 0.8 , 1.0 , 1.5 , 2.0 , 3.0 , 4.0 , 6.0 , 9.0 } ,
labels = { 0.8 , 1.0 , 1.5 , 2.0 , 3.0 , 4.0 , 6.0 , 9.0 } ,
name = " word_spacing " ,
name_text = S.WORD_GAP ,
toggle = { S.SMALL , S.AUTO , S.LARGE } ,
values = DKOPTREADER_CONFIG_WORD_SPACINGS ,
default_value = DKOPTREADER_CONFIG_DEFAULT_WORD_SPACING ,
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
}
}
help_text = _ ( [[In reflow mode, sets the spacing between words.]] ) ,
} ,
{
icon = " resources/icons/appbar.settings.large.png " ,
options = {
{
name = " text_wrap " ,
name_text = S.REFLOW ,
toggle = { S.O N, S.OFF } ,
values = { 1, 0 } ,
toggle = { S.O FF, S.ON } ,
values = { 0, 1 } ,
default_value = DKOPTREADER_CONFIG_TEXT_WRAP ,
events = {
{
@ -213,49 +224,49 @@ local KoptOptions = {
} ,
} ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [ [ Reflow mode extracts text and images from the original document , possibly discarding some formatting , and reflows it on the screen for easier reading .
Some of the other settings are only available when reflow mode is enabled . ] ] ) ,
} ,
}
} ,
{
icon = " resources/icons/appbar.grade.b.large.png " ,
options = {
{
name = " contrast " ,
name_text = S.CONTRAST ,
buttonprogress = true ,
-- See https://github.com/koreader/koreader/issues/1299#issuecomment-65183895
-- For pdf reflowing mode (kopt_contrast):
values = { 1 / 0.8 , 1 / 1.0 , 1 / 1.5 , 1 / 2.0 , 1 / 4.0 , 1 / 6.0 , 1 / 10.0 , 1 / 50.0 } ,
default_pos = 2 ,
default_value = DKOPTREADER_CONFIG_CONTRAST ,
event = " GammaUpdate " ,
-- For pdf non-reflowing mode (mupdf):
args = { 0.8 , 1.0 , 1.5 , 2.0 , 4.0 , 6.0 , 10.0 , 50.0 } ,
labels = { 0.8 , 1.0 , 1.5 , 2.0 , 4.0 , 6.0 , 10.0 , 50.0 } ,
name_text_hold_callback = optionsutil.showValues ,
} ,
{
name = " page_opt " ,
name_text = S.DEWATERMARK ,
toggle = { S.ON , S.OFF } ,
values = { 1 , 0 } ,
toggle = { S.O FF, S.ON } ,
values = { 0, 1 } ,
default_value = 0 ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [ [ Remove watermarks from the rendered document .
This can also be used to remove some gray background or to convert a grayscale or color document to black & white and get more contrast for easier reading . ] ] ) ,
} ,
{
name = " doc_language " ,
name_text = S.DOC_LANG ,
toggle = DKOPTREADER_CONFIG_DOC_LANGS_TEXT ,
values = DKOPTREADER_CONFIG_DOC_LANGS_CODE ,
default_value = DKOPTREADER_CONFIG_DOC_DEFAULT_LANG_CODE ,
event = " DocLangUpdate " ,
args = DKOPTREADER_CONFIG_DOC_LANGS_CODE ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[(Used by the OCR engine.)]] ) ,
} ,
{
name = " word_spacing " ,
name_text = S.WORD_GAP ,
toggle = { S.SMALL , S.AUTO , S.LARGE } ,
values = DKOPTREADER_CONFIG_WORD_SPACINGS ,
default_value = DKOPTREADER_CONFIG_DEFAULT_WORD_SPACING ,
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
} ,
{
name = " writing_direction " ,
name_text = S.WRITING_DIR ,
toggle = { S.LTR , S.RTL , S.TBRTL } ,
values = { 0 , 1 , 2 } ,
name = " hw_dithering " ,
name_text = S.HW_DITHERING ,
toggle = { S.OFF , S.ON } ,
values = { 0 , 1 } ,
default_value = 0 ,
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
advanced = true ,
show = Device : hasEinkScreen ( ) and Device : canHWDither ( ) ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[Enable Hardware dithering.]] ) ,
} ,
{
name = " quality " ,
@ -268,25 +279,45 @@ This can also be used to remove some gray background or to convert a grayscale o
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[In reflow mode, sets the quality of the text and image extraction processing and output.]] ) ,
} ,
}
} ,
{
name = " hw_dithering " ,
name_text = S.HW_DITHERING ,
toggle = { S.ON , S.OFF } ,
values = { 1 , 0 } ,
default_value = 0 ,
advanced = true ,
show = Device : hasEinkScreen ( ) and Device : canHWDither ( ) ,
icon = " resources/icons/appbar.settings.large.png " ,
options = {
{
name = " doc_language " ,
name_text = S.DOC_LANG ,
toggle = DKOPTREADER_CONFIG_DOC_LANGS_TEXT ,
values = DKOPTREADER_CONFIG_DOC_LANGS_CODE ,
default_value = DKOPTREADER_CONFIG_DOC_DEFAULT_LANG_CODE ,
event = " DocLangUpdate " ,
args = DKOPTREADER_CONFIG_DOC_LANGS_CODE ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[Set the language to be used by the OCR engine.]] ) ,
} ,
{
name = " forced_ocr " ,
name_text = S.FORCED_OCR ,
toggle = { S.O N, S.OFF } ,
values = { 1, 0 } ,
toggle = { S.O FF, S.ON } ,
values = { 0, 1 } ,
default_value = 0 ,
advanced = true ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[Force the use of OCR for text selection, even if the document has a text layer.]] ) ,
} ,
{
name = " writing_direction " ,
name_text = S.WRITING_DIR ,
toggle = { S.LTR , S.RTL , S.TBRTL } ,
values = { 0 , 1 , 2 } ,
default_value = 0 ,
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [[In reflow mode, sets the original text direction. This needs to be set to RTL to correctly extract and reflow RTL languages like Arabic or Hebrew.]] ) ,
} ,
{
name = " defect_size " ,
@ -295,7 +326,7 @@ This can also be used to remove some gray background or to convert a grayscale o
values = { 1.0 , 3.0 , 5.0 } ,
default_value = DKOPTREADER_CONFIG_DEFECT_SIZE ,
event = " DefectSizeUpdate " ,
show = false ,
show = false , -- might work somehow, but larger values than 1.0 might easily eat content
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
@ -307,7 +338,7 @@ This can also be used to remove some gray background or to convert a grayscale o
toggle = { S.ZERO_DEG , S.FIVE_DEG , S.TEN_DEG } ,
values = { 0 , 5 , 10 } ,
default_value = DKOPTREADER_CONFIG_AUTO_STRAIGHTEN ,
show = false ,
show = false , -- does not work (and slows rendering)
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
@ -316,14 +347,31 @@ This can also be used to remove some gray background or to convert a grayscale o
{
name = " detect_indent " ,
name_text = S.INDENTATION ,
toggle = { S.O N, S.OFF } ,
values = { 1, 0 } ,
toggle = { S.O FF, S.ON } ,
values = { 0, 1 } ,
default_value = DKOPTREADER_CONFIG_DETECT_INDENT ,
show = false ,
show = false , -- does not work
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
} ,
{
name = " max_columns " ,
name_text = S.DOCUMENT_COLUMNS ,
item_icons = {
" resources/icons/appbar.column.one.png " ,
" resources/icons/appbar.column.two.png " ,
" resources/icons/appbar.column.three.png " ,
} ,
values = { 1 , 2 , 3 } ,
default_value = DKOPTREADER_CONFIG_MAX_COLUMNS ,
enabled_func = function ( configurable )
return optionsutil.enableIfEquals ( configurable , " text_wrap " , 1 )
end ,
name_text_hold_callback = optionsutil.showValues ,
help_text = _ ( [ [ In reflow mode , sets the max number of columns to try to detect in the original document .
You might need to set it to 1 column if , in a full width document , text is incorrectly detected as multiple columns because of unlucky word spacing . ] ] ) ,
} ,
}
} ,
@ -334,7 +382,7 @@ if BD.mirroredUILayout() then
-- be mirrored - but that's not enough: we need to swap LEFT and RIGHT,
-- so they appear in a more expected and balanced order to RTL users:
-- {JUSTIFY, LEFT, CENTER, RIGHT, AUTO}
local j = KoptOptions [ 3 ] . options [ 7 ]
local j = KoptOptions [ 3 ] . options [ 5 ]
assert ( j.name == " justification " )
j.item_icons [ 2 ] , j.item_icons [ 4 ] = j.item_icons [ 4 ] , j.item_icons [ 2 ]
j.values [ 2 ] , j.values [ 4 ] = j.values [ 4 ] , j.values [ 2 ]