pull/11044/merge
Rowan Decker 2 months ago committed by GitHub
commit d3eb25edb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,4 +1,5 @@
local BD = require("ui/bidi")
local BlitBuffer = require("ffi/blitbuffer")
local ButtonDialog = require("ui/widget/buttondialog")
local ConfirmBox = require("ui/widget/confirmbox")
local Device = require("device")
@ -18,10 +19,22 @@ local ffiUtil = require("ffi/util")
local time = require("ui/time")
local _ = require("gettext")
local C_ = _.pgettext
local N_ = _.ngettext
local T = ffiUtil.template
local Screen = Device.screen
local ReaderHighlight = InputContainer:extend{}
local ReaderHighlight = InputContainer:extend{
highlight_colors = {
{_("Red"), "red"},
{_("Orange"), "orange"},
{_("Yellow"), "yellow"},
{_("Green"), "green"},
{_("Cyan"), "cyan"},
{_("Blue"), "blue"},
{_("Purple"), "purple"},
{_("Gray"), "gray"},
}
}
local function inside_box(pos, box)
if pos then
@ -54,6 +67,7 @@ function ReaderHighlight:init()
self._current_indicator_pos = nil
self._previous_indicator_pos = nil
self._last_indicator_move_args = {dx = 0, dy = 0, distance = 0, time = time:now()}
self._fallback_color = Screen:isColorEnabled() and "yellow" or "gray"
self:registerKeyEvents()
@ -405,7 +419,55 @@ function ReaderHighlight:addToMainMenu(menu_items)
end
table.insert(menu_items.highlight_options.sub_item_table, {
text_func = function()
return T(_("Highlight opacity: %1"), G_reader_settings:readSetting("highlight_lighten_factor", 0.2))
local saved_color = self.view.highlight.saved_color or self._fallback_color
for __, v in ipairs(self.highlight_colors) do
if v[2] == saved_color then
return T(_("Highlight color: %1"), string.lower(v[1]))
end
end
return T(_("Highlight color: %1"), saved_color)
end,
enabled_func = function()
return self.view.highlight.saved_drawer ~= "invert"
end,
callback = function(touchmenu_instance)
local default_color = G_reader_settings:readSetting("highlight_color", self._fallback_color)
local saved_color = self.view.highlight.saved_color or self._fallback_color
local radio_buttons = {}
for _, v in ipairs(self.highlight_colors) do
table.insert(radio_buttons, {
{
text = v[1],
checked = v[2] == saved_color,
bgcolor = BlitBuffer.colorFromName(v[2]) or BlitBuffer.Color8(bit.bxor(0xFF * self.view.highlight.lighten_factor, 0xFF)),
provider = v[2],
},
})
end
UIManager:show(require("ui/widget/radiobuttonwidget"):new{
title_text = _("Highlight color"),
width_factor = 0.5,
keep_shown_on_apply = false,
radio_buttons = radio_buttons,
default_provider = default_color,
callback = function(radio)
self.view.highlight.saved_color = radio.provider
UIManager:setDirty(self.dialog, "ui")
if touchmenu_instance then touchmenu_instance:updateItems() end
end,
})
end,
hold_callback = function(touchmenu_instance)
G_reader_settings:saveSetting("highlight_color", self.view.highlight.saved_color)
UIManager:show(Notification:new{
text = T(_("Default highlight color changed to '%1'."), self.view.highlight.saved_color),
})
if touchmenu_instance then touchmenu_instance:updateItems() end
end,
})
table.insert(menu_items.highlight_options.sub_item_table, {
text_func = function()
return T(_("Gray highlight opacity: %1"), G_reader_settings:readSetting("highlight_lighten_factor", 0.2))
end,
enabled_func = function()
return self.view.highlight.saved_drawer == "lighten"
@ -422,8 +484,8 @@ function ReaderHighlight:addToMainMenu(menu_items)
value_hold_step = 0.25,
default_value = 0.2,
keep_shown_on_apply = true,
title_text = _("Highlight opacity"),
info_text = _("The higher the value, the darker the highlight."),
title_text = _("Gray highlight opacity"),
info_text = _("The higher the value, the darker the gray."),
callback = function(spin)
G_reader_settings:saveSetting("highlight_lighten_factor", spin.value)
self.view.highlight.lighten_factor = spin.value
@ -475,6 +537,35 @@ function ReaderHighlight:addToMainMenu(menu_items)
})
end,
})
table.insert(menu_items.highlight_options.sub_item_table, {
text = _("Apply default style to all highlights"),
callback = function(touchmenu_instance)
UIManager:show(ConfirmBox:new{
text = _("Are you sure you want to edit all highlights."),
icon = "texture-box",
ok_callback = function()
local count = 0
for _, items in pairs(self.view.highlight.saved) do
if items then
count = count + #items
for i = 1, #items do
local item = items[i]
item.drawer = self.view.highlight.saved_drawer
item.color = self.view.highlight.saved_color
end
end
end
if count > 0 then
UIManager:setDirty(self.dialog, "ui")
UIManager:show(Notification:new{
text = T(N_("Applied default style to 1 highlight",
"Applied default style to %1 highlights", count), count),
})
end
end
})
end,
})
if self.document.info.has_pages then
menu_items.panel_zoom_options = {
text = _("Panel zoom (manga/comic)"),
@ -1012,7 +1103,7 @@ function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
self.edit_highlight_dialog = nil
end,
},
}
},
}
if self.ui.rolling then
@ -1728,7 +1819,6 @@ function ReaderHighlight:onCycleHighlightStyle()
next_style_num = 1
end
self.view.highlight.saved_drawer = highlight_style[next_style_num][2]
self.ui.doc_settings:saveSetting("highlight_drawer", self.view.highlight.saved_drawer)
UIManager:show(Notification:new{
text = T(_("Default highlight style changed to '%1'."), highlight_style[next_style_num][1]),
})
@ -1867,6 +1957,7 @@ function ReaderHighlight:saveHighlight(extend_to_sentence)
pboxes = self.selected_text.pboxes,
ext = self.selected_text.ext,
drawer = self.view.highlight.saved_drawer,
color = self.view.highlight.saved_color,
chapter = chapter_name,
}
table.insert(self.view.highlight.saved[page], hl_item)
@ -2017,10 +2108,32 @@ function ReaderHighlight:editHighlightStyle(page, i)
datetime = item.datetime,
})))
end
self:showHighlightStyleDialog(apply_drawer, item.drawer)
self:showHighlightStyleDialog(apply_drawer, item.drawer, page, i)
end
function ReaderHighlight:editHighlightColor(page, i)
local item = self.view.highlight.saved[page][i]
local apply_color = function(color)
self:writePdfAnnotation("delete", page, item)
item.color = color
if self.ui.paging then
self:writePdfAnnotation("save", page, item)
local bm_note = self.ui.bookmark:getBookmarkNote(item)
if bm_note then
self:writePdfAnnotation("content", page, item, bm_note)
end
end
UIManager:setDirty(self.dialog, "ui")
self.ui:handleEvent(Event:new("BookmarkUpdated",
self.ui.bookmark:getBookmarkForHighlight({
page = self.ui.paging and page or item.pos0,
datetime = item.datetime,
})))
end
self:showHighlightColorDialog(apply_color, item.color)
end
function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer)
function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer, page, i)
local default_drawer, keep_shown_on_apply
if item_drawer then -- called from editHighlightStyle
default_drawer = self.view.highlight.saved_drawer or
@ -2038,7 +2151,7 @@ function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer)
})
end
local RadioButtonWidget = require("ui/widget/radiobuttonwidget")
UIManager:show(RadioButtonWidget:new{
local ctor = {
title_text = _("Highlight style"),
width_factor = 0.5,
keep_shown_on_apply = keep_shown_on_apply,
@ -2047,6 +2160,52 @@ function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer)
callback = function(radio)
caller_callback(radio.provider)
end,
}
if page and i then
-- called from editHighlightStyle
ctor.extra_text = _("Highlight color")
ctor.extra_callback = function(this)
local item = self.view.highlight.saved[page][i]
if item.drawer == "invert" then
UIManager:show(InfoMessage:new{ text = _("Colors unavailable when highlight style is set to 'Invert'") })
else
-- Close the style dialog before showing the color dialog
this:onClose()
self:editHighlightColor(page, i)
end
end
end
UIManager:show(RadioButtonWidget:new(ctor))
end
function ReaderHighlight:showHighlightColorDialog(caller_callback, item_color)
local default_color, keep_shown_on_apply
if item_color then -- called from editHighlightColor
default_color = self.view.highlight.saved_color or
G_reader_settings:readSetting("highlight_color", self._fallback_color)
keep_shown_on_apply = true
end
local radio_buttons = {}
for _, v in ipairs(self.highlight_colors) do
table.insert(radio_buttons, {
{
text = v[1],
checked = item_color == v[2],
bgcolor = BlitBuffer.colorFromName(v[2]) or BlitBuffer.Color8(bit.bxor(0xFF * self.view.highlight.lighten_factor, 0xFF)),
provider = v[2],
},
})
end
local RadioButtonWidget = require("ui/widget/radiobuttonwidget")
UIManager:show(RadioButtonWidget:new{
title_text = _("Highlight color"),
width_factor = 0.5,
keep_shown_on_apply = keep_shown_on_apply,
radio_buttons = radio_buttons,
default_provider = default_color,
callback = function(radio)
caller_callback(radio.provider)
end,
})
end
@ -2175,7 +2334,8 @@ function ReaderHighlight:getSavedExtendedHighlightPage(hl_or_bm, page, index)
end
local item = {}
item.datetime = highlight.datetime
item.drawer = highlight.drawer
item.drawer = highlight.drawer or self.highlight.saved_drawer
item.color = highlight.color or self.highlight.saved_color
item.pos0 = highlight.ext[page].pos0
item.pos0.zoom = highlight.pos0.zoom
item.pos0.rotation = highlight.pos0.rotation
@ -2190,6 +2350,8 @@ end
function ReaderHighlight:onReadSettings(config)
self.view.highlight.saved_drawer = config:readSetting("highlight_drawer")
or G_reader_settings:readSetting("highlight_drawing_style") or self.view.highlight.saved_drawer
self.view.highlight.saved_color = config:readSetting("highlight_color")
or G_reader_settings:readSetting("highlight_color") or self.view.highlight.saved_color
self.view.highlight.disabled = G_reader_settings:has("default_highlight_action")
and G_reader_settings:readSetting("default_highlight_action") == "nothing"
@ -2219,6 +2381,7 @@ end
function ReaderHighlight:onSaveSettings()
self.ui.doc_settings:saveSetting("highlight_drawer", self.view.highlight.saved_drawer)
self.ui.doc_settings:saveSetting("highlight_color", self.view.highlight.saved_color)
self.ui.doc_settings:saveSetting("panel_zoom_enabled", self.panel_zoom_enabled)
end

@ -95,6 +95,7 @@ function ReaderView:init()
temp_drawer = "invert",
temp = {},
saved_drawer = "lighten",
saved_color = Screen:isColorEnabled() and "yellow" or "gray",
saved = {},
indicator = nil, -- geom: non-touch highlight position indicator: {x = 50, y=50}
}
@ -213,7 +214,8 @@ function ReaderView:paintTo(bb, x, y)
-- dim last read area
if not self.dim_area:isEmpty() and self:isOverlapAllowed() then
if self.page_overlap_style == "dim" then
bb:dimRect(
-- NOTE: "dim", as in make black text fainter, e.g., lighten the rect
bb:lightenRect(
self.dim_area.x, self.dim_area.y,
self.dim_area.w, self.dim_area.h
)
@ -561,13 +563,13 @@ function ReaderView:drawPageSavedHighlight(bb, x, y)
for _, item in ipairs(items) do
local boxes = self.document:getPageBoxesFromPositions(page, item.pos0, item.pos1)
if boxes then
local drawer = item.drawer or self.highlight.saved_drawer
local color = Blitbuffer.colorFromName(item.color)
local draw_note_mark = self.highlight.note_mark and
self.ui.bookmark:getBookmarkNote({datetime = item.datetime})
for _, box in ipairs(boxes) do
local rect = self:pageToScreenTransform(page, box)
if rect then
self:drawHighlightRect(bb, x, y, rect, drawer, draw_note_mark)
self:drawHighlightRect(bb, x, y, rect, item.drawer, color, draw_note_mark)
if draw_note_mark and self.highlight.note_mark == "sidemark" then
draw_note_mark = false -- side mark in the first line only
end
@ -609,12 +611,12 @@ function ReaderView:drawXPointerSavedHighlight(bb, x, y)
if start_pos <= cur_view_bottom and end_pos >= cur_view_top then
local boxes = self.document:getScreenBoxesFromPositions(pos0, pos1, true) -- get_segments=true
if boxes then
local drawer = item.drawer or self.highlight.saved_drawer
local color = Blitbuffer.colorFromName(item.color)
local draw_note_mark = self.highlight.note_mark and
self.ui.bookmark:getBookmarkNote({datetime = item.datetime})
for _, box in ipairs(boxes) do
if box.h ~= 0 then
self:drawHighlightRect(bb, x, y, box, drawer, draw_note_mark)
self:drawHighlightRect(bb, x, y, box, item.drawer, color, draw_note_mark)
if draw_note_mark and self.highlight.note_mark == "sidemark" then
draw_note_mark = false -- side mark in the first line only
end
@ -627,24 +629,58 @@ function ReaderView:drawXPointerSavedHighlight(bb, x, y)
end -- end for all saved highlight
end
function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer, draw_note_mark)
function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer, color, draw_note_mark)
local x, y, w, h = rect.x, rect.y, rect.w, rect.h
if drawer == "lighten" then
bb:lightenRect(x, y, w, h, self.highlight.lighten_factor)
if not color then
bb:darkenRect(x, y, w, h, self.highlight.lighten_factor)
else
if bb:getInverse() == 1 then
-- MUL doesn't really work on a black background, so, switch to OVER if we're in software nightmode...
-- NOTE: If we do *not* invert the color here, it *will* get inverted by the blitter given that the target bb is inverted.
-- While not particularly pretty, this (roughly) matches with hardware nightmode, *and* how MuPDF renders highlights...
-- But it's *really* not pretty (https://github.com/koreader/koreader/pull/11044#issuecomment-1902886069), so we'll fix it ;p.
local c = Blitbuffer.ColorRGB32(color.r, color.g, color.b, 0xFF * self.highlight.lighten_factor):invert()
bb:blendRectRGB32(x, y, w, h, c)
else
bb:multiplyRectRGB(x, y, w, h, color)
end
end
elseif drawer == "underscore" then
bb:paintRect(x, y + h - 1, w, Size.line.medium, Blitbuffer.COLOR_GRAY)
if not color then
color = Blitbuffer.COLOR_GRAY
end
if Blitbuffer.isColor8(color) then
bb:paintRect(x, y + h - 1, w, Size.line.medium, color)
else
bb:paintRectRGB32(x, y + h - 1, w, Size.line.medium, color)
end
elseif drawer == "strikeout" then
if not color then
color = Blitbuffer.COLOR_BLACK
end
local line_y = y + math.floor(h / 2) + 1
if self.ui.paging then
line_y = line_y + 2
end
bb:paintRect(x, line_y, w, Size.line.medium, Blitbuffer.COLOR_BLACK)
if Blitbuffer.isColor8(color) then
bb:paintRect(x, line_y, w, Size.line.medium, color)
else
bb:paintRectRGB32(x, line_y, w, Size.line.medium, color)
end
elseif drawer == "invert" then
bb:invertRect(x, y, w, h)
end
if draw_note_mark then
if not color then
color = Blitbuffer.COLOR_BLACK
end
if self.highlight.note_mark == "underline" then
bb:paintRect(x, y + h - 1, w, Size.line.medium, Blitbuffer.COLOR_BLACK)
if Blitbuffer.isColor8(color) then
bb:paintRect(x, y + h - 1, w, Size.line.medium, color)
else
bb:paintRectRGB32(x, y + h - 1, w, Size.line.medium, color)
end
else
local note_mark_pos_x
if self.ui.paging or
@ -655,7 +691,11 @@ function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer, draw_note_mark)
note_mark_pos_x = self.note_mark_pos_x2
end
if self.highlight.note_mark == "sideline" then
bb:paintRect(note_mark_pos_x, y, self.note_mark_line_w, h, Blitbuffer.COLOR_BLACK)
if Blitbuffer.isColor8(color) then
bb:paintRect(note_mark_pos_x, y, self.note_mark_line_w, h, color)
else
bb:paintRectRGB32(note_mark_pos_x, y, self.note_mark_line_w, h, color)
end
elseif self.highlight.note_mark == "sidemark" then
self.note_mark_sign:paintTo(bb, note_mark_pos_x, y)
end

@ -1,3 +1,4 @@
local BlitBuffer = require("ffi/blitbuffer")
local CacheItem = require("cacheitem")
local CanvasContext = require("document/canvascontext")
local DocCache = require("document/doccache")
@ -249,6 +250,7 @@ function PdfDocument:saveHighlight(pageno, item)
local quadpoints, n = _quadpointsFromPboxes(item.pboxes)
local page = self._document:openPage(pageno)
local annot_type = C.PDF_ANNOT_HIGHLIGHT
local annot_color = BlitBuffer.colorFromName(item.color)
if item.drawer == "lighten" then
annot_type = C.PDF_ANNOT_HIGHLIGHT
elseif item.drawer == "underscore" then
@ -256,7 +258,9 @@ function PdfDocument:saveHighlight(pageno, item)
elseif item.drawer == "strikeout" then
annot_type = C.PDF_ANNOT_STRIKE_OUT
end
page:addMarkupAnnotation(quadpoints, n, annot_type) -- may update/adjust quadpoints
-- NOTE: For highlights, display style may differ compared to ReaderView:drawHighlightRect...
-- (e.g., we do a MUL blend, MuPDF currently appears to do an OVER blend).
page:addMarkupAnnotation(quadpoints, n, annot_type, annot_color) -- may update/adjust quadpoints
-- Update pboxes with the possibly adjusted coordinates (this will have it updated
-- in self.view.highlight.saved[page])
item.pboxes = _quadpointsToPboxes(quadpoints, n)

@ -67,11 +67,14 @@ function CheckButton:initCheckButton(checked)
show_parent = self.show_parent or self,
}
end
local fgcolor = self.fgcolor or Blitbuffer.COLOR_BLACK
self._textwidget = TextBoxWidget:new{
text = self.text,
face = self.face,
width = (self.width or self.parent:getAddedWidgetAvailableWidth()) - self._checkmark.dimen.w,
fgcolor = self.enabled and Blitbuffer.COLOR_BLACK or Blitbuffer.COLOR_DARK_GRAY,
bold = self.bold,
fgcolor = self.enabled and fgcolor or Blitbuffer.COLOR_DARK_GRAY,
bgcolor = self.bgcolor,
}
local textbox_shift = math.max(0, self._checkmark.baseline - self._textwidget:getBaseline())
self._verticalgroup = VerticalGroup:new{

@ -160,7 +160,7 @@ function FrameContainer:paintTo(bb, x, y)
container_height - 2*self.bordersize)
end
if self.dim then
bb:dimRect(x + self.bordersize, y + self.bordersize,
bb:lightenRect(x + self.bordersize, y + self.bordersize,
container_width - 2*self.bordersize,
container_height - 2*self.bordersize)
end

@ -574,7 +574,7 @@ function ImageWidget:paintTo(bb, x, y)
--- This would require the *original* transparent icon, not the flattened one in the cache.
--- c.f., https://github.com/koreader/koreader/pull/6937#issuecomment-748372429 for a PoC
if self.dim then
bb:dimRect(x, y, size.w, size.h)
bb:lightenRect(x, y, size.w, size.h)
end
-- In night mode, invert all rendered images, so the original is
-- displayed when the whole screen is inverted by night mode.

@ -66,6 +66,10 @@ function RadioButtonTable:init()
radio = true,
provider = btn_entry.provider,
bold = btn_entry.bold,
fgcolor = btn_entry.fgcolor,
bgcolor = btn_entry.bgcolor,
width = (self.width - sizer_space) / column_cnt,
bordersize = 0,
margin = 0,

@ -835,11 +835,18 @@ function TextBoxWidget:_renderText(start_row_idx, end_row_idx)
h = h + self.line_glyph_extra_height
if self._bb then self._bb:free() end
local bbtype = nil
if self.line_num_to_image and self.line_num_to_image[start_row_idx] then
local color_fg = not Blitbuffer.isColor8(self.fgcolor)
local color_bg = not Blitbuffer.isColor8(self.bgcolor)
-- Color, whether from images or fg or bg, means we'll need an RGB32 buffer (if it makes sense, e.g., on a color screen).
if (self.line_num_to_image and self.line_num_to_image[start_row_idx]) or color_fg or color_bg then
bbtype = Screen:isColorEnabled() and Blitbuffer.TYPE_BBRGB32 or Blitbuffer.TYPE_BB8
end
self._bb = Blitbuffer.new(self.width, h, bbtype)
self._bb:fill(self.bgcolor)
if not color_bg then
self._bb:fill(self.bgcolor)
else
self._bb:paintRectRGB32(0, 0, self._bb:getWidth(), self._bb:getHeight(), self.bgcolor)
end
local y = self.line_glyph_baseline
if self.use_xtext then
@ -874,10 +881,17 @@ function TextBoxWidget:_renderText(start_row_idx, end_row_idx)
if self._alt_color_for_rtl then
color = xglyph.is_rtl and Blitbuffer.COLOR_DARK_GRAY or Blitbuffer.COLOR_BLACK
end
self._bb:colorblitFrom(glyph.bb,
xglyph.x0 + glyph.l + xglyph.x_offset,
y - glyph.t - xglyph.y_offset,
0, 0, glyph.bb:getWidth(), glyph.bb:getHeight(), color)
if not color_fg then
self._bb:colorblitFrom(glyph.bb,
xglyph.x0 + glyph.l + xglyph.x_offset,
y - glyph.t - xglyph.y_offset,
0, 0, glyph.bb:getWidth(), glyph.bb:getHeight(), color)
else
self._bb:colorblitFromRGB32(glyph.bb,
xglyph.x0 + glyph.l + xglyph.x_offset,
y - glyph.t - xglyph.y_offset,
0, 0, glyph.bb:getWidth(), glyph.bb:getHeight(), color)
end
end
end
end

@ -58,7 +58,7 @@ end
-- So sorry for the Tolinos with (Android 4.4.x).
-- Maybe https://f-droid.org/de/packages/jackpal.androidterm/ could be an alternative then.
if (Device:isAndroid() and Device.firmware_rev < 21) or not check_prerequisites() then
logger.warn("Terminal: Device doesn't meet some of the plugin's prerequisites")
logger.warn("Terminal: Device doesn't meet some of the plugin's requirements")
return { disabled = true, }
end

Loading…
Cancel
Save