mirror of
https://github.com/koreader/koreader.git
synced 2025-12-24 12:14:05 +01:00
This should finish the work to make all globals to local variables. That allows LuaJIT to properly compile things by interning the references to the relevant parts (rather than looking up globals all the time which stops a trace).
221 lines
6.3 KiB
Lua
221 lines
6.3 KiB
Lua
local InputContainer = require("ui/widget/container/inputcontainer")
|
|
local Geom = require("ui/geometry")
|
|
local Event = require("ui/event")
|
|
local UIManager = require("ui/uimanager")
|
|
local Device = require("ui/device")
|
|
local GestureRange = require("ui/gesturerange")
|
|
|
|
--[[
|
|
BBoxWidget shows a bbox for page cropping
|
|
]]
|
|
local BBoxWidget = InputContainer:new{
|
|
page_bbox = nil,
|
|
screen_bbox = nil,
|
|
linesize = 2,
|
|
fine_factor = 10,
|
|
}
|
|
|
|
function BBoxWidget:init()
|
|
self.page_bbox = self.document:getPageBBox(self.view.state.page)
|
|
--DEBUG("used page bbox on page", self.view.state.page, self.page_bbox)
|
|
if Device:isTouchDevice() then
|
|
self.ges_events = {
|
|
TapAdjust = {
|
|
GestureRange:new{
|
|
ges = "tap",
|
|
range = self.view.dimen,
|
|
}
|
|
},
|
|
SwipeAdjust = {
|
|
GestureRange:new{
|
|
ges = "swipe",
|
|
range = self.view.dimen,
|
|
}
|
|
},
|
|
HoldAdjust = {
|
|
GestureRange:new{
|
|
ges = "hold",
|
|
range = self.view.dimen,
|
|
}
|
|
},
|
|
ConfirmAdjust = {
|
|
GestureRange:new{
|
|
ges = "double_tap",
|
|
range = self.view.dimen,
|
|
}
|
|
}
|
|
}
|
|
end
|
|
end
|
|
|
|
function BBoxWidget:getSize()
|
|
return self.view.dimen
|
|
end
|
|
|
|
function BBoxWidget:paintTo(bb, x, y)
|
|
-- As getScreenBBox uses view states, screen_bbox initialization is postponed.
|
|
self.screen_bbox = self.screen_bbox or self:getScreenBBox(self.page_bbox)
|
|
local bbox = self.screen_bbox
|
|
-- top edge
|
|
bb:invertRect(bbox.x0 + self.linesize, bbox.y0, bbox.x1 - bbox.x0, self.linesize)
|
|
-- bottom edge
|
|
bb:invertRect(bbox.x0 + self.linesize, bbox.y1, bbox.x1 - bbox.x0 - self.linesize, self.linesize)
|
|
-- left edge
|
|
bb:invertRect(bbox.x0, bbox.y0, self.linesize, bbox.y1 - bbox.y0 + self.linesize)
|
|
-- right edge
|
|
bb:invertRect(bbox.x1, bbox.y0 + self.linesize, self.linesize, bbox.y1 - bbox.y0)
|
|
end
|
|
|
|
-- transform page bbox to screen bbox
|
|
function BBoxWidget:getScreenBBox(page_bbox)
|
|
local bbox = {}
|
|
local scale = self.view.state.zoom
|
|
local screen_offset = self.view.state.offset
|
|
--DEBUG("screen offset in page_to_screen", screen_offset)
|
|
bbox.x0 = math.round(page_bbox.x0 * scale + screen_offset.x)
|
|
bbox.y0 = math.round(page_bbox.y0 * scale + screen_offset.y)
|
|
bbox.x1 = math.round(page_bbox.x1 * scale + screen_offset.x)
|
|
bbox.y1 = math.round(page_bbox.y1 * scale + screen_offset.y)
|
|
return bbox
|
|
end
|
|
|
|
-- transform screen bbox to page bbox
|
|
function BBoxWidget:getPageBBox(screen_bbox)
|
|
local bbox = {}
|
|
local scale = self.view.state.zoom
|
|
local screen_offset = self.view.state.offset
|
|
--DEBUG("screen offset in screen_to_page", screen_offset)
|
|
bbox.x0 = math.round((screen_bbox.x0 - screen_offset.x) / scale)
|
|
bbox.y0 = math.round((screen_bbox.y0 - screen_offset.y) / scale)
|
|
bbox.x1 = math.round((screen_bbox.x1 - screen_offset.x) / scale)
|
|
bbox.y1 = math.round((screen_bbox.y1 - screen_offset.y) / scale)
|
|
return bbox
|
|
end
|
|
|
|
function BBoxWidget:inPageArea(ges)
|
|
local offset = self.view.state.offset
|
|
local page_area = self.view.page_area
|
|
local page_dimen = Geom:new{ x = offset.x, y = offset.y, h = page_area.h, w = page_area.w}
|
|
return not ges.pos:notIntersectWith(page_dimen)
|
|
end
|
|
|
|
function BBoxWidget:adjustScreenBBox(ges, relative)
|
|
--DEBUG("adjusting crop bbox with pos", ges.pos)
|
|
if not self:inPageArea(ges) then return end
|
|
local bbox = self.screen_bbox
|
|
local upper_left = Geom:new{ x = bbox.x0, y = bbox.y0}
|
|
local upper_right = Geom:new{ x = bbox.x1, y = bbox.y0}
|
|
local bottom_left = Geom:new{ x = bbox.x0, y = bbox.y1}
|
|
local bottom_right = Geom:new{ x = bbox.x1, y = bbox.y1}
|
|
local upper_center = Geom:new{ x = (bbox.x0 + bbox.x1) / 2, y = bbox.y0}
|
|
local bottom_center = Geom:new{ x = (bbox.x0 + bbox.x1) / 2, y = bbox.y1}
|
|
local right_center = Geom:new{ x = bbox.x1, y = (bbox.y0 + bbox.y1) / 2}
|
|
local left_center = Geom:new{ x = bbox.x0, y = (bbox.y0 + bbox.y1) / 2}
|
|
local anchors = {
|
|
upper_left, upper_center, upper_right,
|
|
left_center, right_center,
|
|
bottom_left, bottom_center, bottom_right,
|
|
}
|
|
local _, nearest = math.tmin(anchors, function(a,b)
|
|
return a:distance(ges.pos) > b:distance(ges.pos)
|
|
end)
|
|
--DEBUG("nearest anchor", nearest)
|
|
if nearest == upper_left then
|
|
upper_left.x = ges.pos.x
|
|
upper_left.y = ges.pos.y
|
|
elseif nearest == bottom_right then
|
|
bottom_right.x = ges.pos.x
|
|
bottom_right.y = ges.pos.y
|
|
elseif nearest == upper_right then
|
|
bottom_right.x = ges.pos.x
|
|
upper_left.y = ges.pos.y
|
|
elseif nearest == bottom_left then
|
|
upper_left.x = ges.pos.x
|
|
bottom_right.y = ges.pos.y
|
|
elseif nearest == upper_center then
|
|
if relative then
|
|
local delta = 0
|
|
if ges.direction == "north" then
|
|
delta = -ges.distance / self.fine_factor
|
|
elseif ges.direction == "south" then
|
|
delta = ges.distance / self.fine_factor
|
|
end
|
|
upper_left.y = upper_left.y + delta
|
|
else
|
|
upper_left.y = ges.pos.y
|
|
end
|
|
elseif nearest == right_center then
|
|
if relative then
|
|
local delta = 0
|
|
if ges.direction == "west" then
|
|
delta = -ges.distance / self.fine_factor
|
|
elseif ges.direction == "east" then
|
|
delta = ges.distance / self.fine_factor
|
|
end
|
|
bottom_right.x = bottom_right.x + delta
|
|
else
|
|
bottom_right.x = ges.pos.x
|
|
end
|
|
elseif nearest == bottom_center then
|
|
if relative then
|
|
local delta = 0
|
|
if ges.direction == "north" then
|
|
delta = -ges.distance / self.fine_factor
|
|
elseif ges.direction == "south" then
|
|
delta = ges.distance / self.fine_factor
|
|
end
|
|
bottom_right.y = bottom_right.y + delta
|
|
else
|
|
bottom_right.y = ges.pos.y
|
|
end
|
|
elseif nearest == left_center then
|
|
if relative then
|
|
local delta = 0
|
|
if ges.direction == "west" then
|
|
delta = -ges.distance / self.fine_factor
|
|
elseif ges.direction == "east" then
|
|
delta = ges.distance / self.fine_factor
|
|
end
|
|
upper_left.x = upper_left.x + delta
|
|
else
|
|
upper_left.x = ges.pos.x
|
|
end
|
|
end
|
|
self.screen_bbox = {
|
|
x0 = math.round(upper_left.x),
|
|
y0 = math.round(upper_left.y),
|
|
x1 = math.round(bottom_right.x),
|
|
y1 = math.round(bottom_right.y)
|
|
}
|
|
|
|
UIManager.repaint_all = true
|
|
end
|
|
|
|
function BBoxWidget:getModifiedPageBBox()
|
|
return self:getPageBBox(self.screen_bbox)
|
|
end
|
|
|
|
function BBoxWidget:onTapAdjust(arg, ges)
|
|
self:adjustScreenBBox(ges)
|
|
return true
|
|
end
|
|
|
|
function BBoxWidget:onSwipeAdjust(arg, ges)
|
|
self:adjustScreenBBox(ges, true)
|
|
return true
|
|
end
|
|
|
|
function BBoxWidget:onHoldAdjust(arg, ges)
|
|
self:adjustScreenBBox(ges)
|
|
return true
|
|
end
|
|
|
|
function BBoxWidget:onConfirmAdjust(arg, ges)
|
|
if self:inPageArea(ges) then
|
|
self.ui:handleEvent(Event:new("ConfirmPageCrop"))
|
|
end
|
|
return true
|
|
end
|
|
|
|
return BBoxWidget
|