Merge pull request #647 from houqp/new_ui_houqp

add usedbbox support
pull/2/merge
{Qingping,Dave} Hou 12 years ago
commit add2c62528

@ -124,6 +124,20 @@ function Document:getPageDimensions(pageno, zoom, rotation)
return native_dimen
end
function Document:getUsedBBoxDimensions(pageno, zoom, rotation)
ubbox = self:getUsedBBox(pageno)
ubbox_dimen = Geom:new{
x = ubbox.x0,
y = ubbox.y0,
w = ubbox.x1 - ubbox.x0,
h = ubbox.y1 - ubbox.y0,
}
if zoom ~= 1 then
ubbox_dimen:transformByScale(zoom)
end
return ubbox_dimen
end
function Document:getToc()
return self._document:getToc()
end
@ -185,6 +199,14 @@ function Document:hintPage(pageno, zoom, rotation)
self:renderPage(pageno, nil, zoom, rotation)
end
--[[
Draw page content to blitbuffer.
1. find tile in cache
2. if not found, call renderPage
@target: target blitbuffer
@rect: visible_area inside document page
--]]
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, render_mode)
local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation
local hash_excerpt = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..tostring(rect)
@ -196,8 +218,12 @@ function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, render_mo
tile = self:renderPage(pageno, rect, zoom, rotation, render_mode)
end
end
DEBUG("now painting", tile)
target:blitFrom(tile.bb, x, y, rect.x - tile.excerpt.x, rect.y - tile.excerpt.y, rect.w, rect.h)
DEBUG("now painting", tile, rect)
target:blitFrom(tile.bb,
x, y,
rect.x - tile.excerpt.x,
rect.y - tile.excerpt.y,
rect.w, rect.h)
end
function Document:drawCurrentView(target, x, y, rect, pos)

@ -37,12 +37,15 @@ function PdfDocument:getUsedBBox(pageno)
local hash = "pgubbox|"..self.file.."|"..pageno
local cached = Cache:check(hash)
if cached then
return cached.data
return cached.ubbox
end
local page = self._document:openPage(pageno)
local used = {}
used.x, used.y, used.w, used.h = page:getUsedBBox()
Cache:insert(hash, CacheItem:new{ used })
used.x0, used.y0, used.x1, used.y1 = page:getUsedBBox()
--@TODO give size for cacheitem? 02.12 2012 (houqp)
Cache:insert(hash, CacheItem:new{
ubbox = used,
})
page:close()
return used
end

@ -65,6 +65,15 @@ function Geom:scaleBy(zx, zy)
return self
end
--[[
this method also takes care of x and y
]]--
function Geom:transformByScale(zx, zy)
self.x = self.x * zx
self.y = self.y * (zx or zy)
self:scaleBy(zx, zy)
end
--[[
enlarges or shrinks dimensions or rectangles
@ -128,6 +137,19 @@ function Geom:intersect(rect_b)
return intersected
end
--[[
return true if self does not share any area with rect_b
]]--
function Geom:notIntersectWith(rect_b)
if (self.x >= (rect_b.x + rect_b.w))
or (self.y >= (rect_b.y + rect_b.h))
or (rect_b.x >= (self.x + self.w))
or (rect_b.y >= (self.y + self.h)) then
return true
end
return false
end
--[[
set size of dimension or rectangle to size of given dimension/rectangle
]]--
@ -236,3 +258,20 @@ function Geom:offsetWithin(rect_b, dx, dy)
self.y = rect_b.y + rect_b.h - self.h
end
end
--[[
Simple math helper function
]]--
function math.roundAwayFromZero(num)
if num > 0 then
return math.ceil(num)
else
return math.floor(num)
end
end

@ -1,6 +1,8 @@
ReaderPaging = InputContainer:new{
current_page = 0,
number_of_pages = 0
number_of_pages = 0,
visible_area = nil,
page_area = nil,
}
function ReaderPaging:init()
@ -63,6 +65,14 @@ function ReaderPaging:init()
self.number_of_pages = self.ui.document.info.number_of_pages
end
function ReaderPaging:onReadSettings(config)
self:gotoPage(config:readSetting("last_page") or 1)
end
function ReaderPaging:onCloseDocument()
self.ui.doc_settings:saveSetting("last_page", self.current_page)
end
-- wrapper for bounds checking
function ReaderPaging:gotoPage(number)
if number == self.current_page then
@ -81,14 +91,21 @@ function ReaderPaging:gotoPage(number)
return true
end
function ReaderPaging:onReadSettings(config)
self:gotoPage(config:readSetting("last_page") or 1)
function ReaderPaging:onZoomModeUpdate(new_mode)
-- we need to remember zoom mode to handle page turn event
self.zoom_mode = new_mode
end
function ReaderPaging:onPageUpdate(new_page_no)
self.current_page = new_page_no
end
function ReaderPaging:onViewRecalculate(visible_area, page_area)
-- we need to remember areas to handle page turn event
self.visible_area = visible_area
self.page_area = page_area
end
function ReaderPaging:onGotoPercent(percent)
DEBUG("goto document offset in percent:", percent)
local dest = math.floor(self.number_of_pages * percent / 100)
@ -102,12 +119,48 @@ end
function ReaderPaging:onGotoPageRel(diff)
DEBUG("goto relative page:", diff)
self:gotoPage(self.current_page + diff)
return true
end
local new_va = self.visible_area:copy()
local x_pan_off, y_pan_off = 0, 0
function ReaderPaging:onCloseDocument()
self.ui.doc_settings:saveSetting("last_page", self.current_page)
if 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
else
-- must be fit content or page zoom mode
if self.visible_area.w == self.page_area.w then
y_pan_off = self.visible_area.h * diff
else
x_pan_off = self.visible_area.w * diff
end
end
-- adjust offset to help with page turn decision
x_pan_off = math.roundAwayFromZero(x_pan_off)
y_pan_off = math.roundAwayFromZero(y_pan_off)
new_va.x = math.roundAwayFromZero(self.visible_area.x+x_pan_off)
new_va.y = math.roundAwayFromZero(self.visible_area.y+y_pan_off)
if (new_va:notIntersectWith(self.page_area)) then
self:gotoPage(self.current_page + diff)
-- if we are going back to previous page, reset
-- view to bottom of previous page
if x_pan_off < 0 then
self.view:PanningUpdate(self.page_area.w, 0)
elseif y_pan_off < 0 then
self.view:PanningUpdate(0, self.page_area.h)
end
else
-- fit new view area into page area
new_va:offsetWithin(self.page_area, 0, 0)
self.view:PanningUpdate(
new_va.x - self.visible_area.x,
new_va.y - self.visible_area.y)
-- update self.visible_area
self.visible_area = new_va
end
return true
end
function ReaderPaging:onTapForward()

@ -13,7 +13,9 @@ ReaderView = WidgetContainer:new{
-- DjVu page rendering mode (used in djvu.c:drawPage())
render_mode = 0, -- default to COLOR
-- visible area within current viewing page
visible_area = Geom:new{x = 0, y = 0},
-- dimen for current viewing page
page_area = Geom:new{},
}
@ -44,7 +46,6 @@ function ReaderView:paintTo(bb, x, y)
self.state.zoom,
self.state.rotation,
self.render_mode)
self:recalculate()
else
self.ui.document:drawCurrentView(
bb,
@ -56,12 +57,22 @@ function ReaderView:paintTo(bb, x, y)
end
function ReaderView:recalculate()
local page_size = nil
if self.ui.document.info.has_pages then
local page_size = self.ui.document:getPageDimensions(
self.state.page, self.state.zoom, self.state.rotation)
-- TODO: bbox
self.page_area = page_size
if not self.bbox then
self.page_area = self.ui.document:getPageDimensions(
self.state.page,
self.state.zoom,
self.state.rotation)
else
self.page_area = self.ui.document:getUsedBBoxDimensions(
self.state.page,
self.state.zoom,
self.state.rotation)
end
-- starts from left top of page_area
self.visible_area.x = self.page_area.x
self.visible_area.y = self.page_area.y
-- reset our size
self.visible_area:setSizeTo(self.dimen)
-- and recalculate it according to page size
@ -69,6 +80,8 @@ function ReaderView:recalculate()
else
self.visible_area:setSizeTo(self.dimen)
end
self.ui:handleEvent(
Event:new("ViewRecalculate", self.visible_area, self.page_area))
-- flag a repaint so self:paintTo will be called
UIManager:setDirty(self.dialog)
end
@ -80,8 +93,8 @@ function ReaderView:PanningUpdate(dx, dy)
if self.visible_area ~= old then
-- flag a repaint
UIManager:setDirty(self.dialog)
DEBUG(self.page_area)
DEBUG(self.visible_area)
DEBUG("on pan: page_area", self.page_area)
DEBUG("on pan: visible_area", self.visible_area)
end
return true
end
@ -111,6 +124,10 @@ function ReaderView:onZoomUpdate(zoom)
self:recalculate()
end
function ReaderView:onBBoxUpdate(bbox)
self.bbox = bbox
end
function ReaderView:onRotationUpdate(rotation)
self.state.rotation = rotation
self:recalculate()

@ -2,46 +2,72 @@ ReaderZooming = InputContainer:new{
key_events = {
ZoomIn = {
{ "Shift", Input.group.PgFwd },
doc = "zoom in", event = "Zoom", args = "in"
doc = "zoom in",
event = "Zoom", args = "in"
},
ZoomOut = {
{ "Shift", Input.group.PgBack },
doc = "zoom out", event = "Zoom", args = "out"
doc = "zoom out",
event = "Zoom", args = "out"
},
ZoomToFitPage = {
{ "A" },
doc = "zoom to fit page", event = "SetZoomMode", args = "page"
doc = "zoom to fit page",
event = "SetZoomMode", args = "page"
},
ZoomToFitContent = {
{ "Shift", "A" },
doc = "zoom to fit content", event = "SetZoomMode", args = "content"
doc = "zoom to fit content",
event = "SetZoomMode", args = "content"
},
ZoomToFitPageWidth = {
{ "S" },
doc = "zoom to fit page width", event = "SetZoomMode", args = "pagewidth"
doc = "zoom to fit page width",
event = "SetZoomMode", args = "pagewidth"
},
ZoomToFitContentWidth = {
{ "Shift", "S" },
doc = "zoom to fit content width", event = "SetZoomMode", args = "contentwidth"
doc = "zoom to fit content width",
event = "SetZoomMode", args = "contentwidth"
},
ZoomToFitPageHeight = {
{ "D" },
doc = "zoom to fit page height", event = "SetZoomMode", args = "pageheight"
doc = "zoom to fit page height",
event = "SetZoomMode", args = "pageheight"
},
ZoomToFitContentHeight = {
{ "Shift", "D" },
doc = "zoom to fit content height", event = "SetZoomMode", args = "contentheight"
doc = "zoom to fit content height",
event = "SetZoomMode", args = "contentheight"
},
},
zoom = 1.0,
zoom_mode = "free",
-- default to nil so we can trigger ZoomModeUpdate events on start up
zoom_mode = nil,
DEFAULT_ZOOM_MODE = "page",
current_page = 1,
rotation = 0
}
function ReaderZooming:onReadSettings(config)
-- @TODO config file from old code base uses globalzoom_mode
-- instead of zoom_mode, we need to handle this imcompatibility
-- 04.12 2012 (houqp)
local zoom_mode = config:readSetting("zoom_mode")
if not zoom_mode then
zoom_mode = self.DEFAULT_ZOOM_MODE
end
self:onSetZoomMode(zoom_mode)
end
function ReaderZooming:onCloseDocument()
self.ui.doc_settings:saveSetting("zoom_mode", self.zoom_mode)
end
function ReaderZooming:onSetDimensions(dimensions)
-- we were resized
self.dimen = dimensions
self:setZoom()
end
function ReaderZooming:onRotationUpdate(rotation)
@ -49,21 +75,54 @@ function ReaderZooming:onRotationUpdate(rotation)
self:setZoom()
end
function ReaderZooming:onZoom(direction)
DEBUG("zoom", direction)
if direction == "in" then
self.zoom = self.zoom * 1.333333
elseif direction == "out" then
self.zoom = self.zoom * 0.75
end
DEBUG("zoom is now at", self.zoom)
self:onSetZoomMode("free")
self.view:onZoomUpdate(self.zoom)
return true
end
function ReaderZooming:onSetZoomMode(new_mode)
if self.zoom_mode ~= new_mode then
DEBUG("setting zoom mode to", new_mode)
self.zoom_mode = new_mode
self:setZoom()
self.ui:handleEvent(Event:new("ZoomModeUpdate", new_mode))
end
return true
end
function ReaderZooming:onPageUpdate(new_page_no)
self.current_page = new_page_no
self:setZoom()
end
function ReaderZooming:setZoom()
-- nothing to do in free zoom mode
if self.zoom_mode == "free" then
return
end
if not self.dimen then
self.dimen = self.ui.dimen
end
-- check if we're in bbox mode and work on bbox if that's the case
local page_size = {}
if self.zoom_mode == "content"
or self.zoom_mode == "contentwidth"
or self.zoom_mode == "contentheight" then
-- TODO: enable this, still incomplete
page_size = self.ui.document:getUsedBBox(self.current_page)
self.view:handleEvent(Event:new("BBoxUpdate", page_size))
ubbox_dimen = self.ui.document:getUsedBBoxDimensions(self.current_page, 1)
--self.view:handleEvent(Event:new("BBoxUpdate", page_size))
self.view:onBBoxUpdate(ubbox_dimen)
page_size = ubbox_dimen
else
-- otherwise, operate on full page
self.view:onBBoxUpdate(nil)
page_size = self.ui.document:getNativePageDimensions(self.current_page)
end
-- calculate zoom value:
@ -88,29 +147,4 @@ function ReaderZooming:setZoom()
self.view:onZoomUpdate(self.zoom)
end
function ReaderZooming:onZoom(direction)
DEBUG("zoom", direction)
if direction == "in" then
self.zoom = self.zoom * 1.333333
elseif direction == "out" then
self.zoom = self.zoom * 0.75
end
DEBUG("zoom is now at", self.zoom)
self:onSetZoomMode("free")
self.view:onZoomUpdate(self.zoom)
return true
end
function ReaderZooming:onSetZoomMode(what)
if self.zoom_mode ~= what then
DEBUG("setting zoom mode to", what)
self.zoom_mode = what
self:setZoom()
end
return true
end
function ReaderZooming:onPageUpdate(new_page_no)
self.current_page = new_page_no
self:setZoom()
end

@ -69,6 +69,13 @@ function ReaderUI:init()
if self.document.info.has_pages then
-- for page specific controller
-- if needed, insert a paging container
local pager = ReaderPaging:new{
dialog = self.dialog,
view = self[1],
ui = self
}
table.insert(self, pager)
-- zooming controller
local zoomer = ReaderZooming:new{
dialog = self.dialog,
@ -83,13 +90,6 @@ function ReaderUI:init()
ui = self
}
table.insert(self, panner)
-- if needed, insert a paging container
local pager = ReaderPaging:new{
dialog = self.dialog,
view = self[1],
ui = self
}
table.insert(self, pager)
else
-- rolling controller
local roller = ReaderRolling:new{

Loading…
Cancel
Save