Merge branch 'master' of github.com:hwhw/kindlepdfviewer into djvu-highlight

Conflicts:
	unireader.lua
pull/2/merge
Qingping Hou 12 years ago
commit 46f171df3b

@ -0,0 +1,112 @@
require "keys"
Keydef = {
keycode = nil,
modifier = nil,
descr = nil
}
function Keydef:_new(obj)
-- obj definition
obj = obj or {}
setmetatable(obj, self)
self.__index = self
self.__tostring=Keydef.tostring
return obj
end
function Keydef:new(keycode,modifier,descr)
obj = Keydef:_new()
obj.keycode = keycode
obj.modifier = modifier
obj.descr = descr
return obj
end
function Keydef:display()
return ((self.modifier and self.modifier.."+") or "")..(self.descr or "")
end
function Keydef:tostring()
return ((self.modifier and self.modifier.."+") or "").."["..(self.keycode or "").."]"..(self.descr or "")
end
Command = {
keydef = nil,
keygroup = nil,
func = nil,
help = nil,
order = nil
}
function Command:_new(obj)
-- obj definition
obj = obj or {}
setmetatable(obj, self)
self.__index = self
self.__tostring=Command.tostring
return obj
end
function Command:new(keydef, func, help, keygroup, order)
obj = Command:_new()
obj.keydef = keydef
obj.func = func
obj.help = help
obj.keygroup = keygroup
obj.order = order
--print("creating command: ["..tostring(keydef).."] keygroup:["..(keygroup or "").."] help:"..help)
return obj
end
function Command:tostring()
return tostring(self.keydef)..": "..(self.help or "<no help defined>")
end
Commands = {
map = {},
size = 0
}
function Commands:add(keycode,modifier,keydescr,help,func)
local keydef = Keydef:new(keycode,modifier,keydescr)
self:_addImpl(keydef,help,func)
end
function Commands:addGroup(keygroup,keys,help,func)
for _k,keydef in pairs(keys) do
self:_addImpl(keydef,help,func,keygroup)
end
end
function Commands:_addImpl(keydef,help,func,keygroup)
if keydef.modifier==MOD_ANY then
self:addGroup(keygroup or keydef.descr,{Keydef:new(keydef.keycode,nil), Keydef:new(keydef.keycode,MOD_SHIFT), Keydef:new(keydef.keycode,MOD_ALT)},help,func)
elseif keydef.modifier==MOD_SHIFT_OR_ALT then
self:addGroup(keygroup or (MOD_SHIFT.."|"..MOD_ALT.."+"..(keydef.descr or "")),{Keydef:new(keydef.keycode,MOD_SHIFT), Keydef:new(keydef.keycode,MOD_ALT)},help,func)
else
local command = self.map[keydef]
if command == nil then
self.size = self.size + 1
command = Command:new(keydef,func,help,keygroup,self.size)
self.map[keydef] = command
else
command.func = func
command.help = help
command.keygroup = keygroup
end
end
end
function Commands:get(keycode,modifier)
return self.map[Keydef:new(keycode, modifier)]
end
function Commands:getByKeydef(keydef)
return self.map[keydef]
end
function Commands:new(obj)
-- payload
local mt = {}
setmetatable(self.map,mt)
mt.__index=function (table, key)
return rawget(table,(key.modifier or "").."@#@"..(key.keycode or ""))
end
mt.__newindex=function (table, key, value)
return rawset(table,(key.modifier or "").."@#@"..(key.keycode or ""),value)
end
-- obj definition
obj = obj or {}
setmetatable(obj, self)
self.__index = self
return obj
end

@ -8,7 +8,7 @@ require "selectmenu"
FileChooser = {
-- Class vars:
-- spacing between lines
spacing = 40,
@ -45,7 +45,7 @@ function getAbsolutePath(aPath)
return abs_path
end
function FileChooser:readdir()
function FileChooser:readDir()
self.dirs = {}
self.files = {}
for f in lfs.dir(self.path) do
@ -67,9 +67,9 @@ end
function FileChooser:setPath(newPath)
local curr_path = self.path
self.path = getAbsolutePath(newPath)
local readdir_ok, exc = pcall(self.readdir,self)
local readdir_ok, exc = pcall(self.readDir,self)
if(not readdir_ok) then
print("readdir error: "..tostring(exc))
print("readDir error: "..tostring(exc))
self.exception_message = exc
return self:setPath(curr_path)
else
@ -135,10 +135,10 @@ function FileChooser:choose(ypos, height)
end
end
renderUtf8Text(fb.bb, 5, ypos + self.spacing * perpage + 42, fface, ffhash,
"Page "..self.page.." of "..(math.floor(self.items / perpage)+1), true)
"Page "..self.page.." of "..(math.floor(self.items / perpage)+1), true)
local msg = self.exception_message and self.exception_message:match("[^%:]+:%d+: (.*)") or "Path: "..self.path
self.exception_message = nil
renderUtf8Text(fb.bb, 5, ypos + self.spacing * (perpage+1) + 27, fface, ffhash, msg, true)
renderUtf8Text(fb.bb, 5, ypos + self.spacing * (perpage+1) + 27, fface, ffhash, msg, true)
markerdirty = true
end
if markerdirty then
@ -181,14 +181,14 @@ function FileChooser:choose(ypos, height)
pagedirty = true
elseif ev.code == KEY_S then -- invoke search input
keywords = InputBox:input(height-100, 100, "Search:")
if keywords then
if keywords then
-- call FileSearcher
--[[
This might looks a little bit dirty for using callback.
But I cannot come up with a better solution for renewing
the height arguemtn according to screen rotation mode.
The callback might also be useful for calling system
The callback might also be useful for calling system
settings menu in the future.
--]]
return nil, function()

@ -21,7 +21,7 @@ FileSearcher = {
oldcurrent = 1,
}
function FileSearcher:readdir()
function FileSearcher:readDir()
self.dirs = {self.path}
self.files = {}
while #self.dirs ~= 0 do
@ -46,7 +46,7 @@ end
function FileSearcher:setPath(newPath)
self.path = newPath
self:readdir()
self:readDir()
self.items = #self.files
--@TODO check none found 19.02 2012
if self.items == 0 then
@ -116,9 +116,9 @@ function FileSearcher:choose(ypos, height, keywords)
end
end
-- if given keywords, set new result according to keywords.
-- if given keywords, set new result according to keywords.
-- Otherwise, display the previous search result.
if keywords then
if keywords then
self:setSearchResult(keywords)
end
@ -139,17 +139,17 @@ function FileSearcher:choose(ypos, height, keywords)
local c
if self.items == 0 then -- nothing found
y = ypos + self.title_H + self.spacing * 2
renderUtf8Text(fb.bb, 20, y, cface, cfhash,
"Sorry, no match found.", true)
renderUtf8Text(fb.bb, 20, y + self.spacing, cface, cfhash,
renderUtf8Text(fb.bb, 20, y, cface, cfhash,
"Sorry, no match found.", true)
renderUtf8Text(fb.bb, 20, y + self.spacing, cface, cfhash,
"Please try a different keyword.", true)
markerdirty = false
else -- found something, draw it
for c = 1, perpage do
local i = (self.page - 1) * perpage + c
local i = (self.page - 1) * perpage + c
if i <= self.items then
y = ypos + self.title_H + (self.spacing * c)
renderUtf8Text(fb.bb, 50, y, cface, cfhash,
renderUtf8Text(fb.bb, 50, y, cface, cfhash,
self.result[i].name, true)
end
end
@ -236,7 +236,7 @@ function FileSearcher:choose(ypos, height, keywords)
file_entry = self.result[perpage*(self.page-1)+self.current]
file_full_path = file_entry.dir .. "/" .. file_entry.name
-- rotation mode might be changed while reading, so
-- rotation mode might be changed while reading, so
-- record height_percent here
local height_percent = height/fb.bb:getHeight()
openFile(file_full_path)

@ -8,7 +8,7 @@ Font = {
ffont = "sans",
-- built in fonts
fonts = {"sans", "cjk", "mono",
fonts = {"sans", "cjk", "mono",
"Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique",
"Helvetica", "Helvetica-Oblique", "Helvetica-BoldOblique",
"Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic",},
@ -42,6 +42,5 @@ end
function Font:update()
self.faces = {}
clearglyphcache()
clearGlyphCache()
end

@ -0,0 +1,96 @@
require "rendertext"
require "keys"
require "graphics"
require "font"
require "inputbox"
require "selectmenu"
require "commands"
HelpPage = {
-- Other Class vars:
-- spacing between lines
spacing = 25,
-- state buffer
commands = nil,
items = 0,
page = 1
}
-- Other Class vars:
-- font for displaying keys
HelpPage.fsize = 20
HelpPage.face, HelpPage.fhash = Font:getFaceAndHash(HelpPage.fsize, "mono")
-- font for displaying help messages
HelpPage.hfsize = 20
HelpPage.hface, HelpPage.hfhash = Font:getFaceAndHash(HelpPage.hfsize, "sans")
-- font for paging display
HelpPage.ffsize = 15
HelpPage.fface, HelpPage.ffhash = Font:getFaceAndHash(HelpPage.ffsize, "sans")
function HelpPage:show(ypos, height,commands)
self.commands = {}
self.items = 0
local keys = {}
for k,v in pairs(commands.map) do
local key = v.keygroup or v.keydef:display()
--print("order: "..v.order.." command: "..tostring(v.keydef).." - keygroup:"..(v.keygroup or "nil").." -keys[key]:"..(keys[key] or "nil"))
if keys[key] == nil then
keys[key] = 1
table.insert(self.commands,{shortcut=key,help=v.help,order=v.order})
self.items = self.items + 1
end
end
table.sort(self.commands,function(w1,w2) return w1.order<w2.order end)
local perpage = math.floor( (height - 1 * (self.ffsize + 5)) / self.spacing )
local pagedirty = true
while true do
if pagedirty then
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0)
local c
local max_x = 0
for c = 1, perpage do
local i = (self.page - 1) * perpage + c
if i <= self.items then
local pen_x = renderUtf8Text(fb.bb, 5, ypos + self.spacing*c, self.face, self.fhash, self.commands[i].shortcut, true)
max_x = math.max(max_x, pen_x)
end
end
for c = 1, perpage do
local i = (self.page - 1) * perpage + c
if i <= self.items then
renderUtf8Text(fb.bb, max_x + 20, ypos + self.spacing*c, self.hface, self.hfhash, self.commands[i].help, true)
end
end
renderUtf8Text(fb.bb, 5, height - math.floor(self.ffsize * 0.4), self.fface, self.ffhash,
"Page "..self.page.." of "..math.ceil(self.items / perpage).." - click Back to close this page", true)
markerdirty = true
end
if pagedirty then
fb:refresh(0, 0, ypos, fb.bb:getWidth(), height)
pagedirty = false
end
local ev = input.waitForEvent()
--print("key code:"..ev.code)
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then
if ev.code == KEY_PGFWD then
if self.page < (self.items / perpage) then
self.page = self.page + 1
pagedirty = true
end
elseif ev.code == KEY_PGBCK then
if self.page > 1 then
self.page = self.page - 1
pagedirty = true
end
elseif ev.code == KEY_BACK or ev.code == KEY_HOME then
return nil
end
end
end
end

@ -94,8 +94,18 @@ EV_KEY = 1
EVENT_VALUE_KEY_PRESS = 1
EVENT_VALUE_KEY_REPEAT = 2
EVENT_VALUE_KEY_RELEASE = 0
function set_k3_keycodes()
-- modifiers
MOD_SHIFT = "Shift"
MOD_ALT = "Alt"
MOD_SHIFT_OR_ALT = "ShiftAlt"
MOD_ANY = "Any"
function getKeyModifier()
return Keys.altmode and MOD_ALT or Keys.shiftmode and MOD_SHIFT
end
function setK3Keycodes()
KEY_AA = 190
KEY_SYM = 126
KEY_HOME = 102
@ -110,7 +120,7 @@ function set_k3_keycodes()
KEY_FW_PRESS = 194
end
function set_emu_keycodes()
function setEmuKeycodes()
KEY_PGFWD = 117
KEY_PGBCK = 112
KEY_HOME = 110 -- home

@ -23,6 +23,8 @@ require "djvureader"
require "filechooser"
require "settings"
require "screen"
require "keys"
require "commands"
-- option parsing:
longopts = {
@ -45,10 +47,10 @@ function openFile(filename)
local ok, err = reader:open(filename)
if ok then
reader:loadSettings(filename)
page_num = reader.settings:readsetting("last_page") or 1
page_num = reader.settings:readSetting("last_page") or 1
reader:goto(tonumber(page_num))
reader_settings:savesetting("lastfile", filename)
return reader:inputloop()
return reader:inputLoop()
else
-- TODO: error handling
end
@ -90,11 +92,11 @@ if optarg["d"] == "k3" then
input.open("/dev/input/event0")
input.open("/dev/input/event1")
input.open("/dev/input/event2")
set_k3_keycodes()
setK3Keycodes()
elseif optarg["d"] == "emu" then
input.open("")
-- SDL key codes
set_emu_keycodes()
setEmuKeycodes()
else
input.open("/dev/input/event0")
input.open("/dev/input/event1")
@ -105,7 +107,7 @@ else
if f then
print("Auto-detected Kindle 3")
input.open("/dev/input/event2")
set_k3_keycodes()
setK3Keycodes()
end
end
@ -121,7 +123,7 @@ origin_rotation_mode = Screen.cur_rotation_mode
-- set up reader's setting: font
reader_settings = DocSettings:open(".reader")
r_cfont = reader_settings:readsetting("cfont")
r_cfont = reader_settings:readSetting("cfont")
if r_cfont ~=nil then
Font.cfont = r_cfont
end
@ -133,7 +135,7 @@ PDFReader:init()
DJVUReader:init()
-- display directory or open file
local patharg = reader_settings:readsetting("lastfile")
local patharg = reader_settings:readSetting("lastfile")
if ARGV[optind] and lfs.attributes(ARGV[optind], "mode") == "directory" then
local running = true
FileChooser:setPath(ARGV[optind])

@ -2,7 +2,7 @@ glyphcache_max_memsize = 256*1024 -- 256kB glyphcache
glyphcache_current_memsize = 0
glyphcache = {}
glyphcache_max_age = 4096
function glyphcacheclaim(size)
function glyphCacheClaim(size)
if(size > glyphcache_max_memsize) then
error("too much memory claimed")
return false
@ -20,12 +20,12 @@ function glyphcacheclaim(size)
glyphcache_current_memsize = glyphcache_current_memsize + size
return true
end
function getglyph(face, facehash, charcode)
local hash = glyphcachehash(facehash, charcode)
function getGlyph(face, facehash, charcode)
local hash = glyphCacheHash(facehash, charcode)
if glyphcache[hash] == nil then
local glyph = face:renderGlyph(charcode)
local size = glyph.bb:getWidth() * glyph.bb:getHeight() / 2 + 32
glyphcacheclaim(size);
glyphCacheClaim(size);
glyphcache[hash] = {
age = glyphcache_max_age,
size = size,
@ -36,10 +36,10 @@ function getglyph(face, facehash, charcode)
end
return glyphcache[hash].g
end
function glyphcachehash(face, charcode)
function glyphCacheHash(face, charcode)
return face..'_'..charcode;
end
function clearglyphcache()
function clearGlyphCache()
glyphcache = {}
end
@ -55,7 +55,7 @@ function renderUtf8Text(buffer, x, y, face, facehash, text, kerning)
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
if pen_x < buffer:getWidth() then
local charcode = util.utf8charcode(uchar)
local glyph = getglyph(face, facehash, charcode)
local glyph = getGlyph(face, facehash, charcode)
if kerning and prevcharcode then
local kern = face:getKerning(prevcharcode, charcode)
pen_x = pen_x + kern
@ -67,5 +67,5 @@ function renderUtf8Text(buffer, x, y, face, facehash, text, kerning)
prevcharcode = charcode
end
end
return pen_x
end

@ -9,7 +9,7 @@ function DocSettings:open(docfile)
return setmetatable(new, { __index = DocSettings})
end
function DocSettings:readsetting(key)
function DocSettings:readSetting(key)
return self.data[key]
end

@ -1,6 +1,8 @@
require "keys"
require "settings"
require "selectmenu"
require "commands"
require "helppage"
UniReader = {
-- "constants":
@ -57,9 +59,11 @@ UniReader = {
doc = nil,
-- the document's setting store:
settings = nil,
-- list of available commands:
commands = nil,
-- we will use this one often, so keep it "static":
nulldc = DrawContext.new(),
nulldc = DrawContext.new(),
-- tile cache configuration:
cache_max_memsize = 1024*1024*5, -- 5MB tile cache
@ -85,7 +89,7 @@ function UniReader:new(o)
return o
end
--[[
--[[
For a new specific reader,
you must always overwrite following two methods:
@ -110,20 +114,20 @@ function UniReader:loadSettings(filename)
if self.doc ~= nil then
self.settings = DocSettings:open(filename)
local gamma = self.settings:readsetting("gamma")
local gamma = self.settings:readSetting("gamma")
if gamma then
self.globalgamma = gamma
end
local jumpstack = self.settings:readsetting("jumpstack")
local jumpstack = self.settings:readSetting("jumpstack")
self.jump_stack = jumpstack or {}
local bbox = self.settings:readsetting("bbox")
local bbox = self.settings:readSetting("bbox")
print("# bbox loaded "..dump(bbox))
self.bbox = bbox
self.globalzoom = self.settings:readsetting("globalzoom") or 1.0
self.globalzoommode = self.settings:readsetting("globalzoommode") or -1
self.globalzoom = self.settings:readSetting("globalzoom") or 1.0
self.globalzoommode = self.settings:readSetting("globalzoommode") or -1
return true
end
@ -131,24 +135,26 @@ function UniReader:loadSettings(filename)
end
function UniReader:initGlobalSettings(settings)
local pan_overlap_vertical = settings:readsetting("pan_overlap_vertical")
local pan_overlap_vertical = settings:readSetting("pan_overlap_vertical")
if pan_overlap_vertical then
self.pan_overlap_vertical = pan_overlap_vertical
end
-- initialize commands
self:addAllCommands()
local cache_max_memsize = settings:readsetting("cache_max_memsize")
local cache_max_memsize = settings:readSetting("cache_max_memsize")
if cache_max_memsize then
self.cache_max_memsize = cache_max_memsize
end
local cache_max_ttl = settings:readsetting("cache_max_ttl")
local cache_max_ttl = settings:readSetting("cache_max_ttl")
if cache_max_ttl then
self.cache_max_ttl = cache_max_ttl
end
end
-- guarantee that we have enough memory in cache
function UniReader:cacheclaim(size)
function UniReader:cacheClaim(size)
if(size > self.cache_max_memsize) then
-- we're not allowed to claim this much at all
error("too much memory claimed")
@ -171,7 +177,7 @@ function UniReader:cacheclaim(size)
return true
end
function UniReader:draworcache(no, preCache)
function UniReader:drawOrCache(no, preCache)
-- our general caching strategy is as follows:
-- #1 goal: we must render the needed area.
-- #2 goal: we render as much of the requested page as we can
@ -187,8 +193,8 @@ function UniReader:draworcache(no, preCache)
local dc = self:setzoom(page, preCache)
-- offset_x_in_page & offset_y_in_page is the offset within zoomed page
-- they are always positive.
-- you can see self.offset_x_& self.offset_y as the offset within
-- they are always positive.
-- you can see self.offset_x_& self.offset_y as the offset within
-- draw space, which includes the page. So it can be negative and positive.
local offset_x_in_page = -self.offset_x
local offset_y_in_page = -self.offset_y
@ -222,7 +228,7 @@ function UniReader:draworcache(no, preCache)
-- okay, we do not have it in cache yet.
-- so render now.
-- start off with the requested area
local tile = { x = offset_x_in_page, y = offset_y_in_page,
local tile = { x = offset_x_in_page, y = offset_y_in_page,
w = width, h = height }
-- can we cache the full page?
local max_cache = self.cache_max_memsize
@ -260,7 +266,7 @@ function UniReader:draworcache(no, preCache)
end
return nil
end
self:cacheclaim(tile.w * tile.h / 2);
self:cacheClaim(tile.w * tile.h / 2);
self.cache[pagehash] = {
x = tile.x,
y = tile.y,
@ -283,7 +289,7 @@ function UniReader:draworcache(no, preCache)
end
-- blank the cache
function UniReader:clearcache()
function UniReader:clearCache()
self.cache = {}
self.cache_current_memsize = 0
end
@ -310,14 +316,14 @@ function UniReader:setzoom(page, preCache)
print("# ORIGINAL page::getUsedBBox "..x0.."*"..y0.." "..x1.."*"..y1);
local bbox = self.bbox[self.pageno] -- exact
local odd_even = self:odd_even(self.pageno)
local oddEven = self:oddEven(self.pageno)
if bbox ~= nil then
print("## bbox from "..self.pageno)
else
bbox = self.bbox[odd_even] -- odd/even
bbox = self.bbox[oddEven] -- odd/even
end
if bbox ~= nil then -- last used up to this page
print("## bbox from "..odd_even)
print("## bbox from "..oddEven)
else
for i = 0,self.pageno do
bbox = self.bbox[ self.pageno - i ]
@ -432,7 +438,7 @@ function UniReader:setzoom(page, preCache)
self.min_offset_y = 0
end
print("# Reader:setzoom globalzoom:"..self.globalzoom.." globalrotate:"..self.globalrotate.." offset:"..self.offset_x.."*"..self.offset_y.." pagesize:"..self.fullwidth.."*"..self.fullheight.." min_offset:"..self.min_offset_x.."*"..self.min_offset_y)
print("# Reader:setZoom globalzoom:"..self.globalzoom.." globalrotate:"..self.globalrotate.." offset:"..self.offset_x.."*"..self.offset_y.." pagesize:"..self.fullwidth.."*"..self.fullheight.." min_offset:"..self.min_offset_x.."*"..self.min_offset_y)
-- set gamma here, we don't have any other good place for this right now:
if self.globalgamma ~= self.GAMMA_NO_GAMMA then
@ -444,7 +450,7 @@ end
-- render and blit a page
function UniReader:show(no)
local pagehash, offset_x, offset_y = self:draworcache(no)
local pagehash, offset_x, offset_y = self:drawOrCache(no)
if not pagehash then
return
end
@ -456,15 +462,15 @@ function UniReader:show(no)
-- we can't fill the whole output width, center the content
dest_x = (width - (bb:getWidth() - offset_x)) / 2
end
if bb:getHeight() - offset_y < height and
if bb:getHeight() - offset_y < height and
self.globalzoommode ~= self.ZOOM_FIT_TO_CONTENT_WIDTH_PAN then
-- we can't fill the whole output height and not in
-- we can't fill the whole output height and not in
-- ZOOM_FIT_TO_CONTENT_WIDTH_PAN mode, center the content
dest_y = (height - (bb:getHeight() - offset_y)) / 2
elseif self.globalzoommode == self.ZOOM_FIT_TO_CONTENT_WIDTH_PAN and
self.offset_y > 0 then
-- if we are in ZOOM_FIT_TO_CONTENT_WIDTH_PAN mode and turning to
-- the top of the page, we might leave an empty space between the
-- the top of the page, we might leave an empty space between the
-- page top and screen top.
dest_y = self.offset_y
end
@ -498,9 +504,9 @@ end
--[[
@ pageno is the page you want to add to jump_stack
--]]
function UniReader:add_jump(pageno, notes)
function UniReader:addJump(pageno, notes)
local jump_item = nil
local notes_to_add = notes
local notes_to_add = notes
if not notes_to_add then
-- no notes given, auto generate from TOC entry
notes_to_add = self:getTOCTitleByPage(self.pageno)
@ -541,7 +547,7 @@ function UniReader:add_jump(pageno, notes)
end
end
function UniReader:del_jump(pageno)
function UniReader:delJump(pageno)
for _t,_v in ipairs(self.jump_stack) do
if _v.page == pageno then
table.remove(self.jump_stack, _t)
@ -557,7 +563,7 @@ function UniReader:goto(no)
-- for jump_stack, distinguish jump from normal page turn
if self.pageno and math.abs(self.pageno - no) > 1 then
self:add_jump(self.pageno)
self:addJump(self.pageno)
end
self.pageno = no
@ -568,7 +574,7 @@ function UniReader:goto(no)
if no < self.doc:getPages() then
if #self.bbox == 0 or not self.bbox.enabled then
-- pre-cache next page, but if we will modify bbox don't!
self:draworcache(no+1, true)
self:drawOrCache(no+1, true)
end
end
end
@ -604,7 +610,7 @@ function UniReader:prevView()
if self.globalzoommode == self.ZOOM_FIT_TO_CONTENT_WIDTH_PAN then
if self.offset_y >= self.content_top then
-- hit content top, turn to previous page
-- set self.content_top with magic num to signal self:setzoom
-- set self.content_top with magic num to signal self:setZoom
self.content_top = -2012
pageno = pageno - 1
else
@ -625,14 +631,14 @@ function UniReader:prevView()
end
-- adjust global gamma setting
function UniReader:modify_gamma(factor)
print("modify_gamma, gamma="..self.globalgamma.." factor="..factor)
function UniReader:modifyGamma(factor)
print("modifyGamma, gamma="..self.globalgamma.." factor="..factor)
self.globalgamma = self.globalgamma * factor;
self:goto(self.pageno)
end
-- adjust zoom state and trigger re-rendering
function UniReader:setglobalzoommode(newzoommode)
function UniReader:setGlobalZoomMode(newzoommode)
if self.globalzoommode ~= newzoommode then
self.globalzoommode = newzoommode
self:goto(self.pageno)
@ -640,7 +646,7 @@ function UniReader:setglobalzoommode(newzoommode)
end
-- adjust zoom state and trigger re-rendering
function UniReader:setglobalzoom(zoom)
function UniReader:setGlobalZoom(zoom)
if self.globalzoom ~= zoom then
self.globalzoommode = self.ZOOM_BY_VALUE
self.globalzoom = zoom
@ -648,7 +654,7 @@ function UniReader:setglobalzoom(zoom)
end
end
function UniReader:setrotate(rotate)
function UniReader:setRotate(rotate)
self.globalrotate = rotate
self:goto(self.pageno)
end
@ -657,7 +663,7 @@ end
function UniReader:screenRotate(orien)
Screen:screenRotate(orien)
width, height = fb:getSize()
self:clearcache()
self:clearCache()
self:goto(self.pageno)
end
@ -679,7 +685,7 @@ function UniReader:getTOCTitleByPage(pageno)
if #self.toc == 0 then
return ""
end
local pre_entry = self.toc[1]
for _k,_v in ipairs(self.toc) do
if _v.page > pageno then
@ -719,11 +725,11 @@ end
function UniReader:showJumpStack()
local menu_items = {}
for _k,_v in ipairs(self.jump_stack) do
table.insert(menu_items,
table.insert(menu_items,
_v.datetime.." -> Page ".._v.page.." ".._v.notes)
end
jump_menu = SelectMenu:new{
menu_title = "Jump Keeper (current page: "..self.pageno..")",
menu_title = "Jump Keeper (current page: "..self.pageno..")",
item_array = menu_items,
no_item_msg = "No jump history.",
}
@ -762,7 +768,7 @@ function UniReader:showMenu()
" "..cur_section, true)
ypos = ypos + 15
blitbuffer.progressBar(fb.bb, 10, ypos, width-20, 15,
blitbuffer.progressBar(fb.bb, 10, ypos, width-20, 15,
5, 4, load_percent, 8)
fb:refresh(1)
while 1 do
@ -776,8 +782,8 @@ function UniReader:showMenu()
end
end
function UniReader:odd_even(number)
print("## odd_even "..number)
function UniReader:oddEven(number)
print("## oddEven "..number)
if number % 2 == 1 then
return "odd"
else
@ -786,254 +792,342 @@ function UniReader:odd_even(number)
end
-- wait for input and handle it
function UniReader:inputloop()
function UniReader:inputLoop()
local keep_running = true
while 1 do
local ev = input.waitForEvent()
ev.code = adjustKeyEvents(ev)
if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then
local secs, usecs = util.gettime()
if ev.code == KEY_PGFWD or ev.code == KEY_LPGFWD then
if Keys.shiftmode then
self:setglobalzoom(self.globalzoom+self.globalzoom_orig*0.2)
elseif Keys.altmode then
self:setglobalzoom(self.globalzoom+self.globalzoom_orig*0.1)
else
-- turn page forward
local pageno = self:nextView()
self:goto(pageno)
end
elseif ev.code == KEY_PGBCK or ev.code == KEY_LPGBCK then
if Keys.shiftmode then
self:setglobalzoom(self.globalzoom-self.globalzoom_orig*0.2)
elseif Keys.altmode then
self:setglobalzoom(self.globalzoom-self.globalzoom_orig*0.1)
else
-- turn page back
local pageno = self:prevView()
self:goto(pageno)
end
elseif ev.code == KEY_BACK then
if Keys.altmode then
-- altmode, exit reader
break
else
-- not altmode, back to last jump
if #self.jump_stack ~= 0 then
self:goto(self.jump_stack[1].page)
end
end
elseif ev.code == KEY_VPLUS then
self:modify_gamma( 1.25 )
elseif ev.code == KEY_VMINUS then
self:modify_gamma( 0.8 )
elseif ev.code == KEY_1 then
self:goto(1)
elseif ev.code >= KEY_2 and ev.code <= KEY_9 then
self:goto(math.floor(self.doc:getPages()/90*(ev.code-KEY_1)*10))
elseif ev.code == KEY_0 then
self:goto(self.doc:getPages())
elseif ev.code == KEY_A then
if Keys.shiftmode then
self:setglobalzoommode(self.ZOOM_FIT_TO_CONTENT)
else
self:setglobalzoommode(self.ZOOM_FIT_TO_PAGE)
end
elseif ev.code == KEY_S then
if Keys.shiftmode then
self:setglobalzoommode(self.ZOOM_FIT_TO_CONTENT_WIDTH)
else
self:setglobalzoommode(self.ZOOM_FIT_TO_PAGE_WIDTH)
end
elseif ev.code == KEY_D then
if Keys.shiftmode then
self:setglobalzoommode(self.ZOOM_FIT_TO_CONTENT_HEIGHT)
else
self:setglobalzoommode(self.ZOOM_FIT_TO_PAGE_HEIGHT)
end
elseif ev.code == KEY_F then
if Keys.shiftmode then
self:setglobalzoommode(self.ZOOM_FIT_TO_CONTENT_HALF_WIDTH)
else
self:setglobalzoommode(self.ZOOM_FIT_TO_CONTENT_HALF_WIDTH_MARGIN)
end
elseif ev.code == KEY_G then
local page = InputBox:input(height-100, 100, "Page:")
-- convert string to number
if not pcall(function () page = page + 0 end) then
page = self.pageno
else
if page < 1 or page > self.doc:getPages() then
page = self.pageno
end
keydef = Keydef:new(ev.code, getKeyModifier())
print("key pressed: "..tostring(keydef))
command = self.commands:getByKeydef(keydef)
if command ~= nil then
print("command to execute: "..tostring(command))
ret_code = command.func(self,keydef)
if ret_code == "break" then
break;
end
self:goto(page)
elseif ev.code == KEY_T then
self:showTOC()
elseif ev.code == KEY_B then
if Keys.shiftmode then
self:add_jump(self.pageno)
else
self:showJumpStack()
end
elseif ev.code == KEY_J then
if Keys.shiftmode then
self:screenRotate("clockwise")
else
self:setrotate( self.globalrotate + 10 )
end
elseif ev.code == KEY_K then
if Keys.shiftmode then
self:screenRotate("anticlockwise")
else
self:setrotate( self.globalrotate - 10 )
end
elseif ev.code == KEY_N then
self:startHighLightMode()
elseif ev.code == KEY_HOME then
if Keys.shiftmode or Keys.altmode then
-- signal quit
keep_running = false
end
break
elseif ev.code == KEY_Z and not (Keys.shiftmode or Keys.altmode) then
local bbox = {}
bbox["x0"] = - self.offset_x / self.globalzoom
bbox["y0"] = - self.offset_y / self.globalzoom
bbox["x1"] = bbox["x0"] + width / self.globalzoom
bbox["y1"] = bbox["y0"] + height / self.globalzoom
bbox.pan_x = self.pan_x
bbox.pan_y = self.pan_y
self.bbox[self.pageno] = bbox
self.bbox[self:odd_even(self.pageno)] = bbox
self.bbox.enabled = true
print("# bbox " .. self.pageno .. dump(self.bbox))
self.globalzoommode = self.ZOOM_FIT_TO_CONTENT -- use bbox
elseif ev.code == KEY_Z and Keys.shiftmode then
self.bbox[self.pageno] = nil;
print("# bbox remove "..self.pageno .. dump(self.bbox));
elseif ev.code == KEY_Z and Keys.altmode then
self.bbox.enabled = not self.bbox.enabled;
print("# bbox override: ", self.bbox.enabled);
elseif ev.code == KEY_MENU then
self:showMenu()
self:goto(self.pageno)
else
print("command not found: "..tostring(command))
end
-- switch to ZOOM_BY_VALUE to enable panning on fiveway move
if ev.code == KEY_FW_LEFT
or ev.code == KEY_FW_RIGHT
or ev.code == KEY_FW_UP
or ev.code == KEY_FW_DOWN
then
self.globalzoommode = self.ZOOM_BY_VALUE
end
local nsecs, nusecs = util.gettime()
local dur = (nsecs - secs) * 1000000 + nusecs - usecs
print("E: T="..ev.type.." V="..ev.value.." C="..ev.code.." DUR="..dur)
end
end
-- do clean up stuff
self:clearCache()
self.toc = nil
if self.doc ~= nil then
self.doc:close()
end
if self.settings ~= nil then
self.settings:savesetting("last_page", self.pageno)
self.settings:savesetting("gamma", self.globalgamma)
self.settings:savesetting("jumpstack", self.jump_stack)
self.settings:savesetting("bbox", self.bbox)
self.settings:savesetting("globalzoom", self.globalzoom)
self.settings:savesetting("globalzoommode", self.globalzoommode)
self.settings:close()
end
if self.globalzoommode == self.ZOOM_BY_VALUE then
return keep_running
end
-- command definitions
function UniReader:addAllCommands()
self.commands = Commands:new()
self.commands:add(KEY_PGFWD,nil,">",
"next page",
function(unireader)
unireader:goto(unireader:nextView())
end)
self.commands:add(KEY_PGBCK,nil,"<",
"previous page",
function(unireader)
unireader:goto(unireader:prevView())
end)
self.commands:add(KEY_PGFWD,MOD_ALT,">",
"zoom in 10%",
function(unireader)
unireader:setGlobalZoom(unireader.globalzoom+unireader.globalzoom_orig*0.1)
end)
self.commands:add(KEY_PGBCK,MOD_ALT,"<",
"zoom out 10%",
function(unireader)
unireader:setGlobalZoom(unireader.globalzoom-unireader.globalzoom_orig*0.1)
end)
self.commands:add(KEY_PGFWD,MOD_SHIFT,">",
"zoom in 20%",
function(unireader)
unireader:setGlobalZoom(unireader.globalzoom+unireader.globalzoom_orig*0.2)
end)
self.commands:add(KEY_PGBCK,MOD_SHIFT,"<",
"zoom out 20%",
function(unireader)
unireader:setGlobalZoom(unireader.globalzoom-unireader.globalzoom_orig*0.2)
end)
self.commands:add(KEY_BACK,nil,"back",
"back to last jump",
function(unireader)
if #unireader.jump_stack ~= 0 then
unireader:goto(unireader.jump_stack[1].page)
end
end)
self.commands:add(KEY_BACK,MOD_ALT,"back",
"close document",
function(unireader)
return "break"
end)
self.commands:add(KEY_VPLUS,nil,"vol+",
"increase gamma 25%",
function(unireader)
unireader:modifyGamma( 1.25 )
end)
self.commands:add(KEY_VMINUS,nil,"vol-",
"decrease gamma 25%",
function(unireader)
unireader:modifyGamma( 0.80 )
end)
--numeric key group
local numeric_keydefs = {}
for i=1,10 do numeric_keydefs[i]=Keydef:new(KEY_1+i-1,nil,tostring(i%10)) end
self.commands:addGroup("[1..0]",numeric_keydefs,
"jump to <key>*10% of document",
function(unireader,keydef)
print('jump to page: '..math.max(math.floor(unireader.doc:getPages()*(keydef.keycode-KEY_1)/9),1)..'/'..unireader.doc:getPages())
unireader:goto(math.max(math.floor(unireader.doc:getPages()*(keydef.keycode-KEY_1)/9),1))
end)
-- end numeric keys
self.commands:add(KEY_A,nil,"A",
"zoom to fit page",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_PAGE)
end)
self.commands:add(KEY_A,MOD_SHIFT,"A",
"zoom to fit content",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_CONTENT)
end)
self.commands:add(KEY_S,nil,"S",
"zoom to fit page width",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_PAGE_WIDTH)
end)
self.commands:add(KEY_S,MOD_SHIFT,"S",
"zoom to fit content width",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_CONTENT_WIDTH)
end)
self.commands:add(KEY_D,nil,"D",
"zoom to fit page height",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_PAGE_HEIGHT)
end)
self.commands:add(KEY_D,MOD_SHIFT,"D",
"zoom to fit content height",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_CONTENT_HEIGHT)
end)
self.commands:add(KEY_F,nil,"F",
"zoom to fit margin 2-column mode",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_CONTENT_HALF_WIDTH_MARGIN)
end)
self.commands:add(KEY_F,MOD_SHIFT,"F",
"zoom to fit content 2-column mode",
function(unireader)
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_CONTENT_HALF_WIDTH)
end)
self.commands:add(KEY_G,nil,"G",
"goto page",
function(unireader)
local page = InputBox:input(height-100, 100, "Page:")
-- convert string to number
if not pcall(function () page = page + 0 end) then
page = unireader.pageno
else
if page < 1 or page > unireader.doc:getPages() then
page = unireader.pageno
end
end
unireader:goto(page)
end)
self.commands:add(KEY_H,nil,"H",
"show help page",
function(unireader)
HelpPage:show(0,height,unireader.commands)
unireader:goto(unireader.pageno)
end)
self.commands:add(KEY_T,nil,"T",
"show table of content",
function(unireader)
unireader:showTOC()
end)
self.commands:add(KEY_B,nil,"B",
"show jump stack",
function(unireader)
unireader:showJumpStack()
end)
self.commands:add(KEY_B,MOD_SHIFT,"B",
"add jump",
function(unireader)
unireader:addJump(unireader.pageno)
end)
self.commands:add(KEY_J,nil,"J",
"rotate 10° clockwise",
function(unireader)
unireader:setRotate( unireader.globalrotate + 10 )
end)
self.commands:add(KEY_J,MOD_SHIFT,"J",
"rotate screen 90° clockwise",
function(unireader)
unireader:screenRotate("clockwise")
end)
self.commands:add(KEY_K,nil,"K",
"rotate 10° counterclockwise",
function(unireader)
unireader:setRotate( unireader.globalrotate - 10 )
end)
self.commands:add(KEY_K,MOD_SHIFT,"K",
"rotate screen 90° counterclockwise",
function(unireader)
unireader:screenRotate("anticlockwise")
end)
self.commands:add(KEY_HOME,MOD_SHIFT_OR_ALT,"Home",
"exit application",
function(unireader)
keep_running = false
return "break"
end)
self.commands:add(KEY_Z,nil,"Z",
"set crop mode",
function(unireader)
local bbox = {}
bbox["x0"] = - unireader.offset_x / unireader.globalzoom
bbox["y0"] = - unireader.offset_y / unireader.globalzoom
bbox["x1"] = bbox["x0"] + width / unireader.globalzoom
bbox["y1"] = bbox["y0"] + height / unireader.globalzoom
bbox.pan_x = unireader.pan_x
bbox.pan_y = unireader.pan_y
unireader.bbox[unireader.pageno] = bbox
unireader.bbox[unireader:oddEven(unireader.pageno)] = bbox
unireader.bbox.enabled = true
print("# bbox " .. unireader.pageno .. dump(unireader.bbox))
unireader.globalzoommode = unireader.ZOOM_FIT_TO_CONTENT -- use bbox
end)
self.commands:add(KEY_Z,MOD_SHIFT,"Z",
"reset crop",
function(unireader)
unireader.bbox[unireader.pageno] = nil;
print("# bbox remove "..unireader.pageno .. dump(unireader.bbox));
end)
self.commands:add(KEY_Z,MOD_ALT,"Z",
"toggle crop mode",
function(unireader)
unireader.bbox.enabled = not unireader.bbox.enabled;
print("# bbox override: ", unireader.bbox.enabled);
end)
self.commands:add(KEY_MENU,nil,"Menu",
"open menu",
function(unireader)
unireader:showMenu()
unireader:goto(unireader.pageno)
end)
-- panning
local panning_keys = {Keydef:new(KEY_FW_LEFT,MOD_ANY),Keydef:new(KEY_FW_RIGHT,MOD_ANY),Keydef:new(KEY_FW_UP,MOD_ANY),Keydef:new(KEY_FW_DOWN,MOD_ANY),Keydef:new(KEY_FW_PRESS,MOD_ANY)}
self.commands:addGroup("[joypad]",panning_keys,
"pan the active view; use Shift or Alt for smaller steps",
function(unireader,keydef)
if keydef.keycode ~= KEY_FW_PRESS then
unireader.globalzoommode = unireader.ZOOM_BY_VALUE
end
if unireader.globalzoommode == unireader.ZOOM_BY_VALUE then
local x
local y
if Keys.shiftmode then -- shift always moves in small steps
x = self.shift_x / 2
y = self.shift_y / 2
elseif Keys.altmode then
x = self.shift_x / 5
y = self.shift_y / 5
elseif self.pan_by_page then
if keydef.modifier==MOD_SHIFT then -- shift always moves in small steps
x = unireader.shift_x / 2
y = unireader.shift_y / 2
elseif keydef.modifier==MOD_ALT then
x = unireader.shift_x / 5
y = unireader.shift_y / 5
elseif unireader.pan_by_page then
x = width;
y = height - self.pan_overlap_vertical; -- overlap for lines which didn't fit
y = height - unireader.pan_overlap_vertical; -- overlap for lines which didn't fit
else
x = self.shift_x
y = self.shift_y
x = unireader.shift_x
y = unireader.shift_y
end
print("offset "..self.offset_x.."*"..self.offset_x.." shift "..x.."*"..y.." globalzoom="..self.globalzoom)
local old_offset_x = self.offset_x
local old_offset_y = self.offset_y
if ev.code == KEY_FW_LEFT then
print("# KEY_FW_LEFT "..self.offset_x.." + "..x.." > 0");
self.offset_x = self.offset_x + x
if self.pan_by_page then
if self.offset_x > 0 and self.pageno > 1 then
self.offset_x = self.pan_x
self.offset_y = self.min_offset_y -- bottom
self:goto(self.pageno - 1)
print("offset "..unireader.offset_x.."*"..unireader.offset_x.." shift "..x.."*"..y.." globalzoom="..unireader.globalzoom)
local old_offset_x = unireader.offset_x
local old_offset_y = unireader.offset_y
if keydef.keycode == KEY_FW_LEFT then
print("# KEY_FW_LEFT "..unireader.offset_x.." + "..x.." > 0");
unireader.offset_x = unireader.offset_x + x
if unireader.pan_by_page then
if unireader.offset_x > 0 and unireader.pageno > 1 then
unireader.offset_x = unireader.pan_x
unireader.offset_y = unireader.min_offset_y -- bottom
unireader:goto(unireader.pageno - 1)
else
self.offset_y = self.min_offset_y
unireader.offset_y = unireader.min_offset_y
end
elseif self.offset_x > 0 then
self.offset_x = 0
elseif unireader.offset_x > 0 then
unireader.offset_x = 0
end
elseif ev.code == KEY_FW_RIGHT then
print("# KEY_FW_RIGHT "..self.offset_x.." - "..x.." < "..self.min_offset_x.." - "..self.pan_margin);
self.offset_x = self.offset_x - x
if self.pan_by_page then
if self.offset_x < self.min_offset_x - self.pan_margin and self.pageno < self.doc:getPages() then
self.offset_x = self.pan_x
self.offset_y = self.pan_y
self:goto(self.pageno + 1)
elseif keydef.keycode == KEY_FW_RIGHT then
print("# KEY_FW_RIGHT "..unireader.offset_x.." - "..x.." < "..unireader.min_offset_x.." - "..unireader.pan_margin);
unireader.offset_x = unireader.offset_x - x
if unireader.pan_by_page then
if unireader.offset_x < unireader.min_offset_x - unireader.pan_margin and unireader.pageno < unireader.doc:getPages() then
unireader.offset_x = unireader.pan_x
unireader.offset_y = unireader.pan_y
unireader:goto(unireader.pageno + 1)
else
self.offset_y = self.pan_y
unireader.offset_y = unireader.pan_y
end
elseif self.offset_x < self.min_offset_x then
self.offset_x = self.min_offset_x
elseif unireader.offset_x < unireader.min_offset_x then
unireader.offset_x = unireader.min_offset_x
end
elseif ev.code == KEY_FW_UP then
self.offset_y = self.offset_y + y
if self.offset_y > 0 then
self.offset_y = 0
elseif keydef.keycode == KEY_FW_UP then
unireader.offset_y = unireader.offset_y + y
if unireader.offset_y > 0 then
unireader.offset_y = 0
end
elseif ev.code == KEY_FW_DOWN then
self.offset_y = self.offset_y - y
if self.offset_y < self.min_offset_y then
self.offset_y = self.min_offset_y
elseif keydef.keycode == KEY_FW_DOWN then
unireader.offset_y = unireader.offset_y - y
if unireader.offset_y < unireader.min_offset_y then
unireader.offset_y = unireader.min_offset_y
end
elseif ev.code == KEY_FW_PRESS then
if Keys.shiftmode then
if self.pan_by_page then
self.offset_x = self.pan_x
self.offset_y = self.pan_y
elseif keydef.keycode == KEY_FW_PRESS then
if keydef.modifier==MOD_SHIFT then
if unireader.pan_by_page then
unireader.offset_x = unireader.pan_x
unireader.offset_y = unireader.pan_y
else
self.offset_x = 0
self.offset_y = 0
unireader.offset_x = 0
unireader.offset_y = 0
end
else
self.pan_by_page = not self.pan_by_page
if self.pan_by_page then
self.pan_x = self.offset_x
self.pan_y = self.offset_y
unireader.pan_by_page = not unireader.pan_by_page
if unireader.pan_by_page then
unireader.pan_x = unireader.offset_x
unireader.pan_y = unireader.offset_y
end
end
end
if old_offset_x ~= self.offset_x
or old_offset_y ~= self.offset_y then
self:goto(self.pageno)
if old_offset_x ~= unireader.offset_x
or old_offset_y ~= unireader.offset_y then
unireader:goto(unireader.pageno)
end
end
local nsecs, nusecs = util.gettime()
local dur = (nsecs - secs) * 1000000 + nusecs - usecs
print("E: T="..ev.type.." V="..ev.value.." C="..ev.code.." DUR="..dur)
end
end
-- do clean up stuff
self:clearcache()
self.toc = nil
if self.doc ~= nil then
self.doc:close()
end
if self.settings ~= nil then
self.settings:savesetting("last_page", self.pageno)
self.settings:savesetting("gamma", self.globalgamma)
self.settings:savesetting("jumpstack", self.jump_stack)
self.settings:savesetting("highlight", self.highlight)
self.settings:savesetting("bbox", self.bbox)
self.settings:savesetting("globalzoom", self.globalzoom)
self.settings:savesetting("globalzoommode", self.globalzoommode)
self.settings:close()
end
return keep_running
end)
-- end panning
--print defined commands
--for k,v in pairs(self.commands.map) do print(v) end
end

Loading…
Cancel
Save