mirror of
https://github.com/koreader/koreader
synced 2024-11-10 01:10:34 +00:00
Merge pull request #427 from chrox/master
add regional zoom mode in pdf/djvu page
This commit is contained in:
commit
fc6b45e03a
@ -80,6 +80,10 @@ function DjvuDocument:getOCRText(pageno, tboxes)
|
||||
return self.koptinterface:getOCRText(self, pageno, tboxes)
|
||||
end
|
||||
|
||||
function DjvuDocument:getPageRegions(pageno)
|
||||
return self.koptinterface:getPageRegions(self, pageno)
|
||||
end
|
||||
|
||||
function DjvuDocument:getUsedBBox(pageno)
|
||||
-- djvu does not support usedbbox, so fake it.
|
||||
local used = {}
|
||||
|
@ -447,6 +447,35 @@ function KoptInterface:getNativeTextBoxesFromScratch(doc, pageno)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
get page regions in native page via optical method,
|
||||
--]]
|
||||
function KoptInterface:getPageRegions(doc, pageno)
|
||||
local bbox = doc:getPageBBox(pageno)
|
||||
local context_hash = self:getContextHash(doc, pageno, bbox)
|
||||
local hash = "pageregions|"..context_hash
|
||||
local cached = Cache:check(hash)
|
||||
if not cached then
|
||||
local page_size = Document.getNativePageDimensions(doc, pageno)
|
||||
local bbox = {
|
||||
x0 = 0, y0 = 0,
|
||||
x1 = page_size.w,
|
||||
y1 = page_size.h,
|
||||
}
|
||||
local kc = self:createContext(doc, pageno, bbox)
|
||||
kc:setZoom(1.0)
|
||||
local page = doc._document:openPage(pageno)
|
||||
page:getPagePix(kc)
|
||||
local regions = kc:getPageRegions()
|
||||
Cache:insert(hash, CacheItem:new{ pageregions = regions })
|
||||
page:close()
|
||||
kc:free()
|
||||
return regions
|
||||
else
|
||||
return cached.pageregions
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
get word from OCR providing selected word box
|
||||
--]]
|
||||
|
@ -70,6 +70,10 @@ function PdfDocument:getOCRText(pageno, tboxes)
|
||||
return self.koptinterface:getOCRText(self, pageno, tboxes)
|
||||
end
|
||||
|
||||
function PdfDocument:getPageRegions(pageno)
|
||||
return self.koptinterface:getPageRegions(self, pageno)
|
||||
end
|
||||
|
||||
function PdfDocument:getUsedBBox(pageno)
|
||||
local hash = "pgubbox|"..self.file.."|"..pageno
|
||||
local cached = Cache:check(hash)
|
||||
|
@ -274,6 +274,35 @@ function Geom:offsetWithin(rect_b, dx, dy)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
center the current rectangle at position x and y of a given rectangle
|
||||
]]--
|
||||
function Geom:centerWithin(rect_b, x, y)
|
||||
-- check size constraints and shrink us when we're too big
|
||||
if self.w > rect_b.w then
|
||||
self.w = rect_b.w
|
||||
end
|
||||
if self.h > rect_b.h then
|
||||
self.h = rect_b.h
|
||||
end
|
||||
-- place to center
|
||||
self.x = x - self.w/2
|
||||
self.y = y - self.h/2
|
||||
-- check boundary
|
||||
if self.x < rect_b.x then
|
||||
self.x = rect_b.x
|
||||
end
|
||||
if self.y < rect_b.y then
|
||||
self.y = rect_b.y
|
||||
end
|
||||
if self.x + self.w > rect_b.x + rect_b.w then
|
||||
self.x = rect_b.x + rect_b.w - self.w
|
||||
end
|
||||
if self.y + self.h > rect_b.y + rect_b.h then
|
||||
self.y = rect_b.y + rect_b.h - self.h
|
||||
end
|
||||
end
|
||||
|
||||
function Geom:shrinkInside(rect_b, dx, dy)
|
||||
self:offsetBy(dx, dy)
|
||||
return self:intersect(rect_b)
|
||||
|
@ -209,16 +209,26 @@ function ReaderPaging:enterFlippingMode()
|
||||
self.orig_reflow_mode = self.view.document.configurable.text_wrap
|
||||
self.orig_footer_mode = self.view.footer_visible
|
||||
self.orig_scroll_mode = self.view.page_scroll
|
||||
self.orig_zoom_mode = self.view.zoom_mode
|
||||
DEBUG("store zoom mode", self.orig_zoom_mode)
|
||||
self.DGESDETECT_DISABLE_DOUBLE_TAP = DGESDETECT_DISABLE_DOUBLE_TAP
|
||||
|
||||
self.view.document.configurable.text_wrap = 0
|
||||
self.view.page_scroll = false
|
||||
self.view.footer_visible = true
|
||||
Input.disable_double_tap = false
|
||||
DGESDETECT_DISABLE_DOUBLE_TAP = false
|
||||
self.ui:handleEvent(Event:new("SetZoomMode", "page"))
|
||||
end
|
||||
|
||||
function ReaderPaging:exitFlippingMode()
|
||||
self.view.document.configurable.text_wrap = self.orig_reflow_mode
|
||||
self.view.page_scroll = self.orig_scroll_mode
|
||||
self.view.footer_visible = self.orig_footer_mode
|
||||
DGESDETECT_DISABLE_DOUBLE_TAP = self.DGESDETECT_DISABLE_DOUBLE_TAP
|
||||
Input.disable_double_tap = DGESDETECT_DISABLE_DOUBLE_TAP
|
||||
DEBUG("restore zoom mode", self.orig_zoom_mode)
|
||||
self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode))
|
||||
end
|
||||
|
||||
function ReaderPaging:updateOriginalPage(page)
|
||||
@ -268,7 +278,11 @@ end
|
||||
|
||||
function ReaderPaging:onPan(arg, ges)
|
||||
if self.flipping_mode then
|
||||
self:flipping(self.flipping_page, ges)
|
||||
if self.view.zoom_mode == "page" then
|
||||
self:flipping(self.flipping_page, ges)
|
||||
else
|
||||
self.view:PanningStart(-ges.relative.x, -ges.relative.y)
|
||||
end
|
||||
elseif ges.direction == "north" or ges.direction == "south" then
|
||||
self:onPanningRel(self.last_pan_relative_y - ges.relative.y)
|
||||
self.last_pan_relative_y = ges.relative.y
|
||||
@ -278,7 +292,11 @@ end
|
||||
|
||||
function ReaderPaging:onPanRelease(arg, ges)
|
||||
if self.flipping_mode then
|
||||
self:updateFlippingPage(self.current_page)
|
||||
if self.view.zoom_mode == "page" then
|
||||
self:updateFlippingPage(self.current_page)
|
||||
else
|
||||
self.view:PanningStop()
|
||||
end
|
||||
else
|
||||
self.last_pan_relative_y = 0
|
||||
UIManager.full_refresh = true
|
||||
@ -588,7 +606,9 @@ function ReaderPaging:onGotoPageRel(diff)
|
||||
local new_va = self.visible_area:copy()
|
||||
local x_pan_off, y_pan_off = 0, 0
|
||||
|
||||
if self.zoom_mode:find("width") then
|
||||
if self.zoom_mode == "free" then
|
||||
-- do nothing in free zoom mode
|
||||
elseif self.zoom_mode:find("width") then
|
||||
y_pan_off = self.visible_area.h * diff
|
||||
elseif self.zoom_mode:find("height") then
|
||||
x_pan_off = self.visible_area.w * diff
|
||||
|
@ -439,6 +439,30 @@ function ReaderView:PanningUpdate(dx, dy)
|
||||
return true
|
||||
end
|
||||
|
||||
function ReaderView:PanningStart(x, y)
|
||||
DEBUG("panning start", x, y)
|
||||
if not self.panning_visible_area then
|
||||
self.panning_visible_area = self.visible_area:copy()
|
||||
end
|
||||
self.visible_area = self.panning_visible_area:copy()
|
||||
self.visible_area:offsetWithin(self.page_area, x, y)
|
||||
self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area))
|
||||
UIManager:setDirty(self.dialog)
|
||||
end
|
||||
|
||||
function ReaderView:PanningStop()
|
||||
self.panning_visible_area = nil
|
||||
end
|
||||
|
||||
function ReaderView:SetZoomCenter(x, y)
|
||||
local old = self.visible_area:copy()
|
||||
self.visible_area:centerWithin(self.page_area, x, y)
|
||||
if self.visible_area ~= old then
|
||||
self.ui:handleEvent(Event:new("ViewRecalculate", self.visible_area, self.page_area))
|
||||
UIManager:setDirty(self.dialog)
|
||||
end
|
||||
end
|
||||
|
||||
function ReaderView:onSetScreenMode(new_mode, rotation)
|
||||
if new_mode == "landscape" or new_mode == "portrait" then
|
||||
self.screen_mode = new_mode
|
||||
|
@ -84,6 +84,16 @@ function ReaderZooming:init()
|
||||
}
|
||||
}
|
||||
},
|
||||
ToggleFreeZoom = {
|
||||
GestureRange:new{
|
||||
ges = "double_tap",
|
||||
range = Geom:new{
|
||||
x = 0, y = 0,
|
||||
w = Screen:getWidth(),
|
||||
h = Screen:getHeight(),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
end
|
||||
self.ui.menu:registerToMainMenu(self)
|
||||
@ -126,6 +136,24 @@ function ReaderZooming:onPinch(arg, ges)
|
||||
return true
|
||||
end
|
||||
|
||||
function ReaderZooming:onToggleFreeZoom(arg, ges)
|
||||
if self.zoom_mode ~= "free" then
|
||||
self.orig_zoom = self.zoom
|
||||
self.orig_zoom_mode = self.zoom_mode
|
||||
local xpos, ypos
|
||||
self.zoom, xpos, ypos = self:getRegionalZoomCenter(self.current_page, ges.pos)
|
||||
DEBUG("zoom center", self.zoom, xpos, ypos)
|
||||
self.ui:handleEvent(Event:new("SetZoomMode", "free"))
|
||||
if xpos == nil or ypos == nil then
|
||||
xpos = ges.pos.x * self.zoom / self.orig_zoom
|
||||
ypos = ges.pos.y * self.zoom / self.orig_zoom
|
||||
end
|
||||
self.view:SetZoomCenter(xpos, ypos)
|
||||
else
|
||||
self.ui:handleEvent(Event:new("SetZoomMode", self.orig_zoom_mode or "page"))
|
||||
end
|
||||
end
|
||||
|
||||
function ReaderZooming:onSetDimensions(dimensions)
|
||||
-- we were resized
|
||||
self.dimen = dimensions
|
||||
@ -160,9 +188,9 @@ function ReaderZooming:onSetZoomMode(new_mode)
|
||||
self.view.zoom_mode = new_mode
|
||||
if self.zoom_mode ~= new_mode then
|
||||
DEBUG("setting zoom mode to", new_mode)
|
||||
self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode))
|
||||
self.zoom_mode = new_mode
|
||||
self:setZoom()
|
||||
self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode))
|
||||
end
|
||||
end
|
||||
|
||||
@ -212,15 +240,34 @@ function ReaderZooming:getZoom(pageno)
|
||||
zoom = zoom_w
|
||||
elseif self.zoom_mode == "contentheight" or self.zoom_mode == "pageheight" then
|
||||
zoom = zoom_h
|
||||
elseif self.zoom_mode == "free" then
|
||||
zoom = self.zoom
|
||||
end
|
||||
return zoom
|
||||
end
|
||||
|
||||
function ReaderZooming:setZoom()
|
||||
-- nothing to do in free zoom mode
|
||||
if self.zoom_mode == "free" then
|
||||
return
|
||||
function ReaderZooming:getRegionalZoomCenter(pageno, pos)
|
||||
local p_pos = self.view:getSinglePagePosition(pos)
|
||||
local page_size = self.ui.document:getNativePageDimensions(pageno)
|
||||
local pos_x = p_pos.x / page_size.w / p_pos.zoom
|
||||
local pos_y = p_pos.y / page_size.h / p_pos.zoom
|
||||
local regions = self.ui.document:getPageRegions(pageno)
|
||||
DEBUG("get page regions", regions)
|
||||
local margin = self.ui.document.configurable.page_margin * Screen:getDPI()
|
||||
for i = 1, #regions do
|
||||
if regions[i].x0 <= pos_x and pos_x <= regions[i].x1
|
||||
and regions[i].y0 <= pos_y and pos_y <= regions[i].y1 then
|
||||
local zoom = 1/(regions[i].x1 - regions[i].x0)
|
||||
zoom = zoom/(1 + 3*margin/zoom/page_size.w)
|
||||
local xpos = (regions[i].x0 + regions[i].x1)/2 * zoom * page_size.w
|
||||
local ypos = p_pos.y / p_pos.zoom * zoom
|
||||
return zoom, xpos, ypos
|
||||
end
|
||||
end
|
||||
return 2
|
||||
end
|
||||
|
||||
function ReaderZooming:setZoom()
|
||||
if not self.dimen then
|
||||
self.dimen = self.ui.dimen
|
||||
end
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8b9989a5f91d1e708a285c3e660009232ad14a08
|
||||
Subproject commit bf3ef2a6c9002a665b8c224632eba744e6147fe0
|
Loading…
Reference in New Issue
Block a user