2
0
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:
Qingping Hou 2014-01-01 20:46:59 -08:00
commit fc6b45e03a
8 changed files with 166 additions and 9 deletions

View File

@ -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 = {}

View File

@ -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
--]]

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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