mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
4
.gitignore
vendored
4
.gitignore
vendored
@@ -13,3 +13,7 @@ kindlepdfviewer-*.zip
|
||||
/.project
|
||||
/.reader.kpdfview
|
||||
|
||||
kpvcrlib/CMakeCache.txt
|
||||
kpvcrlib/CMakeFiles/
|
||||
kpvcrlib/cmake_install.cmake
|
||||
kpvcrlib/Makefile
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -7,3 +7,6 @@
|
||||
[submodule "djvulibre"]
|
||||
path = djvulibre
|
||||
url = git://djvu.git.sourceforge.net/gitroot/djvu/djvulibre.git
|
||||
[submodule "kpvcrlib/crengine"]
|
||||
path = kpvcrlib/crengine
|
||||
url = git://crengine.git.sourceforge.net/gitroot/crengine/crengine
|
||||
|
||||
49
Makefile
49
Makefile
@@ -5,10 +5,15 @@ MUPDFDIR=mupdf
|
||||
MUPDFTARGET=build/debug
|
||||
MUPDFLIBDIR=$(MUPDFDIR)/$(MUPDFTARGET)
|
||||
DJVUDIR=djvulibre
|
||||
KPVCRLIGDIR=kpvcrlib
|
||||
CRENGINEDIR=$(KPVCRLIGDIR)/crengine
|
||||
|
||||
FREETYPEDIR=$(MUPDFDIR)/thirdparty/freetype-2.4.8
|
||||
LFSDIR=luafilesystem
|
||||
|
||||
# must point to directory with *.ttf fonts for crengine
|
||||
TTF_FONTS_DIR=/usr/share/fonts/truetype/freefont/
|
||||
|
||||
# set this to your ARM cross compiler:
|
||||
|
||||
CC:=arm-unknown-linux-gnueabi-gcc
|
||||
@@ -55,17 +60,25 @@ KPDFREADER_CFLAGS=$(CFLAGS) -I$(LUADIR)/src -I$(MUPDFDIR)/
|
||||
|
||||
MUPDFLIBS := $(MUPDFLIBDIR)/libfitz.a
|
||||
DJVULIBS := $(DJVUDIR)/build/libdjvu/.libs/libdjvulibre.a
|
||||
CRENGINELIBS := $(CRENGINEDIR)/crengine/libcrengine.a \
|
||||
$(CRENGINEDIR)/thirdparty/chmlib/libchmlib.a \
|
||||
$(CRENGINEDIR)/thirdparty/libpng/libpng.a \
|
||||
$(CRENGINEDIR)/thirdparty/antiword/libantiword.a
|
||||
THIRDPARTYLIBS := $(MUPDFLIBDIR)/libfreetype.a \
|
||||
$(MUPDFLIBDIR)/libjpeg.a \
|
||||
$(MUPDFLIBDIR)/libopenjpeg.a \
|
||||
$(MUPDFLIBDIR)/libjbig2dec.a \
|
||||
$(MUPDFLIBDIR)/libz.a
|
||||
$(MUPDFLIBDIR)/libopenjpeg.a \
|
||||
$(MUPDFLIBDIR)/libjbig2dec.a \
|
||||
$(MUPDFLIBDIR)/libjpeg.a \
|
||||
$(MUPDFLIBDIR)/libz.a
|
||||
|
||||
#@TODO patch crengine to use the latest libjpeg 04.04 2012 (houqp)
|
||||
#$(MUPDFLIBDIR)/libjpeg.a
|
||||
#$(CRENGINEDIR)/thirdparty/libjpeg/libjpeg.a
|
||||
|
||||
LUALIB := $(LUADIR)/src/liblua.a
|
||||
|
||||
all:kpdfview slider_watcher
|
||||
|
||||
kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o util.o ft.o lfs.o $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS) djvu.o
|
||||
kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o util.o ft.o lfs.o $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) djvu.o $(DJVULIBS) cre.o $(CRENGINELIBS)
|
||||
$(CC) -lm -ldl -lpthread $(EMU_LDFLAGS) -lstdc++ \
|
||||
kpdfview.o \
|
||||
einkfb.o \
|
||||
@@ -81,6 +94,8 @@ kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o util.o ft
|
||||
$(LUALIB) \
|
||||
djvu.o \
|
||||
$(DJVULIBS) \
|
||||
cre.o \
|
||||
$(CRENGINELIBS) \
|
||||
-o kpdfview
|
||||
|
||||
einkfb.o input.o: %.o: %.c
|
||||
@@ -98,16 +113,24 @@ kpdfview.o pdf.o blitbuffer.o util.o drawcontext.o: %.o: %.c
|
||||
djvu.o: %.o: %.c
|
||||
$(CC) -c $(KPDFREADER_CFLAGS) -I$(DJVUDIR)/ $< -o $@
|
||||
|
||||
cre.o: %.o: %.cpp
|
||||
$(CC) -c -I$(CRENGINEDIR)/crengine/include/ -Ilua/src $< -o $@ -lstdc++
|
||||
|
||||
lfs.o: $(LFSDIR)/src/lfs.c
|
||||
$(CC) -c $(CFLAGS) -I$(LUADIR)/src -I$(LFSDIR)/src $(LFSDIR)/src/lfs.c -o $@
|
||||
|
||||
fetchthirdparty:
|
||||
-rm -Rf lua lua-5.1.4*
|
||||
-rm -Rf lua lua-5.1.4
|
||||
-rm -Rf mupdf/thirdparty
|
||||
git submodule init
|
||||
git submodule update
|
||||
ln -sf kpvcrlib/crengine/cr3gui/data data
|
||||
test -d fonts || ln -sf $(TTF_FONTS_DIR) fonts
|
||||
test -f mupdf-thirdparty.zip || wget http://www.mupdf.com/download/mupdf-thirdparty.zip
|
||||
unzip mupdf-thirdparty.zip -d mupdf
|
||||
cd mupdf/thirdparty/jpeg-*/ && \
|
||||
patch -N -p0 < ../../../kpvcrlib/jpeg_compress_struct_size.patch &&\
|
||||
patch -N -p0 < ../../../kpvcrlib/jpeg_decompress_struct_size.patch
|
||||
test -f lua-5.1.4.tar.gz || wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
|
||||
tar xvzf lua-5.1.4.tar.gz && ln -s lua-5.1.4 lua
|
||||
|
||||
@@ -117,6 +140,11 @@ clean:
|
||||
cleanthirdparty:
|
||||
make -C $(LUADIR) clean
|
||||
make -C $(MUPDFDIR) clean
|
||||
make -C $(CRENGINEDIR)/thirdparty/antiword clean
|
||||
make -C $(CRENGINEDIR)/thirdparty/chmlib clean
|
||||
make -C $(CRENGINEDIR)/thirdparty/libpng clean
|
||||
make -C $(CRENGINEDIR)/crengine clean
|
||||
make -C $(KPVCRLIGDIR) clean
|
||||
-rm -rf $(DJVUDIR)/build
|
||||
-rm -f $(MUPDFDIR)/fontdump.host
|
||||
-rm -f $(MUPDFDIR)/cmapdump.host
|
||||
@@ -144,10 +172,15 @@ else
|
||||
endif
|
||||
make -C $(DJVUDIR)/build
|
||||
|
||||
$(CRENGINELIBS):
|
||||
cd $(KPVCRLIGDIR) && rm -rf CMakeCache.txt CMakeFiles && \
|
||||
CFLAGS="$(CFLAGS)" CC="$(CC)" CXX="$(CXX)" cmake . && \
|
||||
make
|
||||
|
||||
$(LUALIB):
|
||||
make -C lua/src CC="$(CC)" CFLAGS="$(CFLAGS)" MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E" liblua.a
|
||||
|
||||
thirdparty: $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS)
|
||||
thirdparty: $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS) $(CRENGINELIBS)
|
||||
|
||||
INSTALL_DIR=kindlepdfviewer
|
||||
|
||||
@@ -162,6 +195,8 @@ customupdate: kpdfview
|
||||
file kpdfview | grep ARM || exit 1
|
||||
mkdir $(INSTALL_DIR)
|
||||
cp -p README.TXT COPYING kpdfview slider_watcher *.lua $(INSTALL_DIR)
|
||||
cp -rpL data $(INSTALL_DIR)
|
||||
cp -rp fonts $(INSTALL_DIR)
|
||||
zip -r kindlepdfviewer-$(VERSION).zip $(INSTALL_DIR) launchpad/
|
||||
rm -Rf $(INSTALL_DIR)
|
||||
@echo "copy kindlepdfviewer-$(VERSION).zip to /mnt/us/customupdates and install with shift+shift+I"
|
||||
|
||||
65
commands.lua
65
commands.lua
@@ -5,6 +5,7 @@ Keydef = {
|
||||
modifier = nil,
|
||||
descr = nil
|
||||
}
|
||||
|
||||
function Keydef:_new(obj)
|
||||
-- obj definition
|
||||
obj = obj or {}
|
||||
@@ -13,6 +14,7 @@ function Keydef:_new(obj)
|
||||
self.__tostring=Keydef.tostring
|
||||
return obj
|
||||
end
|
||||
|
||||
function Keydef:new(keycode,modifier,descr)
|
||||
obj = Keydef:_new()
|
||||
obj.keycode = keycode
|
||||
@@ -20,13 +22,16 @@ function Keydef:new(keycode,modifier,descr)
|
||||
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,
|
||||
@@ -34,6 +39,7 @@ Command = {
|
||||
help = nil,
|
||||
order = nil
|
||||
}
|
||||
|
||||
function Command:_new(obj)
|
||||
-- obj definition
|
||||
obj = obj or {}
|
||||
@@ -42,6 +48,7 @@ function Command:_new(obj)
|
||||
self.__tostring=Command.tostring
|
||||
return obj
|
||||
end
|
||||
|
||||
function Command:new(keydef, func, help, keygroup, order)
|
||||
obj = Command:_new()
|
||||
obj.keydef = keydef
|
||||
@@ -52,6 +59,7 @@ function Command:new(keydef, func, help, keygroup, 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
|
||||
@@ -61,6 +69,7 @@ Commands = {
|
||||
map = {},
|
||||
size = 0
|
||||
}
|
||||
|
||||
function Commands:add(keycode,modifier,keydescr,help,func)
|
||||
if type(keycode) == "table" then
|
||||
for i=1,#keycode,1 do
|
||||
@@ -72,11 +81,42 @@ function Commands:add(keycode,modifier,keydescr,help,func)
|
||||
self:_addImpl(keydef,help,func)
|
||||
end
|
||||
end
|
||||
|
||||
function Commands:addGroup(keygroup,keys,help,func)
|
||||
for _k,keydef in pairs(keys) do
|
||||
self:_addImpl(keydef,help,func,keygroup)
|
||||
end
|
||||
end
|
||||
|
||||
--@TODO handle MOD_ANY 06.04 2012 (houqp)
|
||||
function Commands:del(keycode, modifier, keydescr)
|
||||
local keydef = nil
|
||||
|
||||
if not keydescr then
|
||||
for k,v in pairs(self.map) do
|
||||
if v.keydef.keycode == keycode
|
||||
and v.keydef.modifier == modifier then
|
||||
keydef = k
|
||||
break
|
||||
end
|
||||
end -- EOF for
|
||||
else
|
||||
keydef = Keydef:new(keycode, modifier, keydescr)
|
||||
end -- EOF if
|
||||
|
||||
self.map[keydef] = nil
|
||||
end
|
||||
|
||||
function Commands:delGroup(keygroup)
|
||||
if keygroup then
|
||||
for k,v in pairs(self.map) do
|
||||
if v.keygroup == keygroup then
|
||||
self.map[k] = nil
|
||||
end
|
||||
end -- EOF for
|
||||
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)
|
||||
@@ -95,25 +135,32 @@ function Commands:_addImpl(keydef,help,func,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 {}
|
||||
obj.map = {}
|
||||
obj.size = 0
|
||||
setmetatable(obj, self)
|
||||
self.__index = self
|
||||
|
||||
-- payload
|
||||
local 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
|
||||
setmetatable(obj.map, mt)
|
||||
|
||||
return obj
|
||||
end
|
||||
|
||||
464
cre.cpp
Normal file
464
cre.cpp
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
KindlePDFViewer: CREngine abstraction for Lua
|
||||
Copyright (C) 2012 Hans-Werner Hilse <hilse@web.de>
|
||||
Qingping Hou <qingping.hou@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "blitbuffer.h"
|
||||
#include "drawcontext.h"
|
||||
#include "cre.h"
|
||||
}
|
||||
|
||||
#include "crengine.h"
|
||||
|
||||
//using namespace std;
|
||||
|
||||
typedef struct CreDocument {
|
||||
LVDocView *text_view;
|
||||
ldomDocument *dom_doc;
|
||||
} CreDocument;
|
||||
|
||||
|
||||
static int openDocument(lua_State *L) {
|
||||
const char *file_name = luaL_checkstring(L, 1);
|
||||
const char *style_sheet = luaL_checkstring(L, 2);
|
||||
|
||||
int width = luaL_checkint(L, 3);
|
||||
int height = luaL_checkint(L, 4);
|
||||
lString8 css;
|
||||
|
||||
CreDocument *doc = (CreDocument*) lua_newuserdata(L, sizeof(CreDocument));
|
||||
luaL_getmetatable(L, "credocument");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
doc->text_view = new LVDocView();
|
||||
doc->text_view->setBackgroundColor(0x000000);
|
||||
if (LVLoadStylesheetFile(lString16(style_sheet), css)){
|
||||
if (!css.empty()){
|
||||
doc->text_view->setStyleSheet(css);
|
||||
}
|
||||
}
|
||||
doc->text_view->setViewMode(DVM_SCROLL, -1);
|
||||
doc->text_view->Resize(width, height);
|
||||
doc->text_view->LoadDocument(file_name);
|
||||
doc->dom_doc = doc->text_view->getDocument();
|
||||
doc->text_view->Render();
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getGammaIndex(lua_State *L) {
|
||||
lua_pushinteger(L, fontMan->GetGammaIndex());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setGammaIndex(lua_State *L) {
|
||||
int index = luaL_checkint(L, 1);
|
||||
|
||||
fontMan->SetGammaIndex(index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int closeDocument(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
delete doc->text_view;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getNumberOfPages(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
lua_pushinteger(L, doc->text_view->getPageCount());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getCurrentPage(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
lua_pushinteger(L, doc->text_view->getCurPage());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getPageFromXPointer(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
const char *xpointer_str = luaL_checkstring(L, 2);
|
||||
|
||||
int page = 0;
|
||||
ldomXPointer xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
|
||||
|
||||
page = doc->text_view->getBookmarkPage(xp);
|
||||
lua_pushinteger(L, page);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getCurrentPos(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
lua_pushinteger(L, doc->text_view->GetPos());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//static int getPosFromXPointer(lua_State *L) {
|
||||
//CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
//const char *xpointer_str = luaL_checkstring(L, 2);
|
||||
|
||||
//lvRect rc;
|
||||
//int pos;
|
||||
|
||||
//ldomXPointer *xp = NULL;
|
||||
//xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
|
||||
//getCursorDocRect(*xp, rc);
|
||||
//pos =
|
||||
|
||||
//return 1;
|
||||
//}
|
||||
|
||||
static int getCurrentPercent(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
lua_pushinteger(L, doc->text_view->getPosPercent());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getXPointer(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
ldomXPointer xp = doc->text_view->getBookmark();
|
||||
lua_pushstring(L, UnicodeToLocal(xp.toString()).c_str());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getFullHeight(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
lua_pushinteger(L, doc->text_view->GetFullHeight());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function for getTableOfContent()
|
||||
*/
|
||||
static int walkTableOfContent(lua_State *L, LVTocItem *toc, int *count) {
|
||||
LVTocItem *toc_tmp = NULL;
|
||||
int i = 0,
|
||||
nr_child = toc->getChildCount();
|
||||
|
||||
for(i = 0; i < nr_child; i++) {
|
||||
toc_tmp = toc->getChild(i);
|
||||
lua_pushnumber(L, (*count)++);
|
||||
|
||||
/* set subtable, Toc entry */
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "page");
|
||||
lua_pushnumber(L, toc_tmp->getPercent());
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "xpointer");
|
||||
lua_pushstring(L, UnicodeToLocal(
|
||||
toc_tmp->getXPointer().toString()).c_str()
|
||||
);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "depth");
|
||||
lua_pushnumber(L, toc_tmp->getLevel());
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "title");
|
||||
lua_pushstring(L, UnicodeToLocal(toc_tmp->getName()).c_str());
|
||||
lua_settable(L, -3);
|
||||
|
||||
|
||||
/* set Toc entry to Toc table */
|
||||
lua_settable(L, -3);
|
||||
|
||||
if (toc_tmp->getChildCount() > 0) {
|
||||
walkTableOfContent(L, toc_tmp, count);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a table like this:
|
||||
* {
|
||||
* {
|
||||
* page=12,
|
||||
* xpointer = "/body/DocFragment[11].0",
|
||||
* depth=1,
|
||||
* title="chapter1"
|
||||
* },
|
||||
* {
|
||||
* page=54,
|
||||
* xpointer = "/body/DocFragment[13].0",
|
||||
* depth=1,
|
||||
* title="chapter2"
|
||||
* },
|
||||
* }
|
||||
*
|
||||
* Warnning: not like pdf or djvu support, page here refers to the
|
||||
* percent of height within the document, not the real page number.
|
||||
* We use page here just to keep consistent with other readers.
|
||||
*
|
||||
*/
|
||||
static int getTableOfContent(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
LVTocItem * toc = doc->text_view->getToc();
|
||||
int count = 0;
|
||||
|
||||
lua_newtable(L);
|
||||
walkTableOfContent(L, toc, &count);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a table like this:
|
||||
* {
|
||||
* "FreeMono",
|
||||
* "FreeSans",
|
||||
* "FreeSerif",
|
||||
* }
|
||||
*
|
||||
*/
|
||||
static int getFontFaces(lua_State *L) {
|
||||
int i = 0;
|
||||
lString16Collection face_list;
|
||||
|
||||
fontMan->getFaceList(face_list);
|
||||
|
||||
lua_newtable(L);
|
||||
for (i = 0; i < face_list.length(); i++)
|
||||
{
|
||||
lua_pushnumber(L, i+1);
|
||||
lua_pushstring(L, UnicodeToLocal(face_list[i]).c_str());
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setFontFace(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
const char *face = luaL_checkstring(L, 2);
|
||||
|
||||
doc->text_view->setDefaultFontFace(lString8(face));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gotoPage(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
int pageno = luaL_checkint(L, 2);
|
||||
|
||||
doc->text_view->goToPage(pageno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gotoPercent(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
int percent = luaL_checkint(L, 2);
|
||||
|
||||
doc->text_view->SetPos(percent * doc->text_view->GetFullHeight() / 10000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gotoPos(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
int pos = luaL_checkint(L, 2);
|
||||
|
||||
doc->text_view->SetPos(pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gotoXPointer(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
const char *xpointer_str = luaL_checkstring(L, 2);
|
||||
|
||||
ldomXPointer xp = doc->dom_doc->createXPointer(lString16(xpointer_str));
|
||||
|
||||
doc->text_view->goToBookmark(xp);
|
||||
/* CREngine does not call checkPos() immediately after goToBookmark,
|
||||
* so I have to manually update the pos in order to get a correctionColor
|
||||
* return from GetPos() call. */
|
||||
doc->text_view->SetPos(xp.toPoint().y);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* zoom font by given delta and return zoomed font size */
|
||||
static int zoomFont(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
int delta = luaL_checkint(L, 2);
|
||||
|
||||
doc->text_view->ZoomFont(delta);
|
||||
|
||||
lua_pushnumber(L, doc->text_view->getFontSize());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int toggleFontBolder(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
doc->text_view->doCommand(DCMD_TOGGLE_BOLD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cursorRight(lua_State *L) {
|
||||
//CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
|
||||
//LVDocView *tv = doc->text_view;
|
||||
|
||||
//ldomXPointer p = tv->getCurrentPageMiddleParagraph();
|
||||
//lString16 s = p.toString();
|
||||
//printf("~~~~~~~~~~%s\n", UnicodeToLocal(s).c_str());
|
||||
|
||||
//tv->selectRange(*(tv->selectFirstPageLink()));
|
||||
//ldomXRange *r = tv->selectNextPageLink(true);
|
||||
//lString16 s = r->getRangeText();
|
||||
//printf("------%s\n", UnicodeToLocal(s).c_str());
|
||||
|
||||
//tv->selectRange(*r);
|
||||
//tv->updateSelections();
|
||||
|
||||
//LVPageWordSelector sel(doc->text_view);
|
||||
//doc->text_view->doCommand(DCMD_SELECT_FIRST_SENTENCE);
|
||||
//sel.moveBy(DIR_RIGHT, 2);
|
||||
//sel.updateSelection();
|
||||
//printf("---------------- %s\n", UnicodeToLocal(sel.getSelectedWord()->getText()).c_str());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drawCurrentPage(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
|
||||
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 3, "blitbuffer");
|
||||
|
||||
int w = bb->w,
|
||||
h = bb->h;
|
||||
LVGrayDrawBuf drawBuf(w, h, 8);
|
||||
|
||||
doc->text_view->Resize(w, h);
|
||||
doc->text_view->Render();
|
||||
doc->text_view->Draw(drawBuf);
|
||||
|
||||
|
||||
uint8_t *bbptr = (uint8_t*)bb->data;
|
||||
uint8_t *pmptr = (uint8_t*)drawBuf.GetScanLine(0);
|
||||
int i,x;
|
||||
|
||||
for (i = 0; i < h; i++) {
|
||||
for (x = 0; x < (bb->w / 2); x++) {
|
||||
bbptr[x] = 255 - (((pmptr[x*2 + 1] & 0xF0) >> 4) |
|
||||
(pmptr[x*2] & 0xF0));
|
||||
}
|
||||
if(bb->w & 1) {
|
||||
bbptr[x] = 255 - (pmptr[x*2] & 0xF0);
|
||||
}
|
||||
bbptr += bb->pitch;
|
||||
pmptr += w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const struct luaL_Reg cre_func[] = {
|
||||
{"openDocument", openDocument},
|
||||
{"getFontFaces", getFontFaces},
|
||||
{"getGammaIndex", getGammaIndex},
|
||||
{"setGammaIndex", setGammaIndex},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct luaL_Reg credocument_meth[] = {
|
||||
/*--- get methods ---*/
|
||||
{"getPages", getNumberOfPages},
|
||||
{"getCurrentPage", getCurrentPage},
|
||||
{"getPageFromXPointer", getPageFromXPointer},
|
||||
{"getCurrentPos", getCurrentPos},
|
||||
{"getCurrentPercent", getCurrentPercent},
|
||||
{"getXPointer", getXPointer},
|
||||
{"getFullHeight", getFullHeight},
|
||||
{"getToc", getTableOfContent},
|
||||
/*--- set methods ---*/
|
||||
{"setFontFace", setFontFace},
|
||||
/* --- control methods ---*/
|
||||
{"gotoPage", gotoPage},
|
||||
{"gotoPercent", gotoPercent},
|
||||
{"gotoPos", gotoPos},
|
||||
{"gotoXPointer", gotoXPointer},
|
||||
{"zoomFont", zoomFont},
|
||||
{"toggleFontBolder", toggleFontBolder},
|
||||
//{"cursorLeft", cursorLeft},
|
||||
//{"cursorRight", cursorRight},
|
||||
{"drawCurrentPage", drawCurrentPage},
|
||||
{"close", closeDocument},
|
||||
{"__gc", closeDocument},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
int luaopen_cre(lua_State *L) {
|
||||
luaL_newmetatable(L, "credocument");
|
||||
lua_pushstring(L, "__index");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, -3);
|
||||
luaL_register(L, NULL, credocument_meth);
|
||||
lua_pop(L, 1);
|
||||
luaL_register(L, "cre", cre_func);
|
||||
|
||||
|
||||
/* initialize fonts for CREngine */
|
||||
InitFontManager(lString8("./fonts"));
|
||||
|
||||
lString8 fontDir("./fonts");
|
||||
LVContainerRef dir = LVOpenDirectory( LocalToUnicode(fontDir).c_str() );
|
||||
if ( !dir.isNull() )
|
||||
for ( int i=0; i<dir->GetObjectCount(); i++ ) {
|
||||
const LVContainerItemInfo * item = dir->GetObjectInfo(i);
|
||||
lString16 fileName = item->GetName();
|
||||
if ( !item->IsContainer() && fileName.length()>4 && lString16(fileName, fileName.length()-4, 4)==L".ttf" ) {
|
||||
lString8 fn = UnicodeToLocal(fileName);
|
||||
printf("loading font: %s\n", fn.c_str());
|
||||
if ( !fontMan->RegisterFont(fn) ) {
|
||||
printf(" failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRENGINE
|
||||
CRLog::setStdoutLogger();
|
||||
CRLog::setLogLevel(CRLog::LL_DEBUG);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
28
cre.h
Normal file
28
cre.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
KindlePDFViewer: CREngine abstraction for Lua
|
||||
Copyright (C) 2012 Hans-Werner Hilse <hilse@web.de>
|
||||
Qingping Hou <qingping.hou@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CRENGING_H
|
||||
#define _CRENGING_H
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
int luaopen_cre(lua_State *L);
|
||||
#endif
|
||||
314
crereader.lua
Normal file
314
crereader.lua
Normal file
@@ -0,0 +1,314 @@
|
||||
require "unireader"
|
||||
require "inputbox"
|
||||
require "selectmenu"
|
||||
|
||||
CREReader = UniReader:new{
|
||||
pos = nil,
|
||||
percent = 0,
|
||||
|
||||
gamma_index = 15,
|
||||
font_face = nil,
|
||||
}
|
||||
|
||||
function CREReader:init()
|
||||
self:addAllCommands()
|
||||
self:adjustCreReaderCommands()
|
||||
end
|
||||
|
||||
-- open a CREngine supported file and its settings store
|
||||
function CREReader:open(filename)
|
||||
local ok
|
||||
local file_type = string.lower(string.match(filename, ".+%.([^.]+)"))
|
||||
-- these two format use the same css file
|
||||
if file_type == "html" then
|
||||
file_type = "htm"
|
||||
end
|
||||
local style_sheet = "./data/"..file_type..".css"
|
||||
ok, self.doc = pcall(cre.openDocument, filename, style_sheet,
|
||||
width, height)
|
||||
if not ok then
|
||||
return false, self.doc -- will contain error message
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- setting related methods
|
||||
----------------------------------------------------
|
||||
function CREReader:loadSpecialSettings()
|
||||
local font_face = self.settings:readSetting("font_face")
|
||||
self.font_face = font_face or "FreeSerif"
|
||||
self.doc:setFontFace(self.font_face)
|
||||
|
||||
local gamma_index = self.settings:readSetting("gamma_index")
|
||||
self.gamma_index = gamma_index or self.gamma_index
|
||||
cre.setGammaIndex(self.gamma_index)
|
||||
end
|
||||
|
||||
function CREReader:getLastPageOrPos()
|
||||
local last_percent = self.settings:readSetting("last_percent")
|
||||
if last_percent then
|
||||
return math.floor((last_percent * self.doc:getFullHeight()) / 10000)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function CREReader:saveSpecialSettings()
|
||||
self.settings:savesetting("font_face", self.font_face)
|
||||
self.settings:savesetting("gamma_index", self.gamma_index)
|
||||
end
|
||||
|
||||
function CREReader:saveLastPageOrPos()
|
||||
self.settings:savesetting("last_percent", self.percent)
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- render related methods
|
||||
----------------------------------------------------
|
||||
-- we don't need setzoom in CREReader
|
||||
function CREReader:setzoom(page, preCache)
|
||||
return
|
||||
end
|
||||
|
||||
function CREReader:redrawCurrentPage()
|
||||
self:goto(self.pos)
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- goto related methods
|
||||
----------------------------------------------------
|
||||
function CREReader:goto(pos, pos_type)
|
||||
local prev_xpointer = self.doc:getXPointer()
|
||||
if pos_type == "xpointer" then
|
||||
self.doc:gotoXPointer(pos)
|
||||
pos = self.doc:getCurrentPos()
|
||||
else -- pos_type is PERCENT * 100
|
||||
pos = math.min(pos, self.doc:getFullHeight())
|
||||
pos = math.max(pos, 0)
|
||||
self.doc:gotoPos(pos)
|
||||
end
|
||||
|
||||
-- add to jump_stack, distinguish jump from normal page turn
|
||||
-- NOTE:
|
||||
-- even though we have called gotoPos() or gotoXPointer() previously,
|
||||
-- self.pos hasn't been updated yet here, so we can still make use of it.
|
||||
if self.pos and math.abs(self.pos - pos) > height then
|
||||
self:addJump(prev_xpointer)
|
||||
end
|
||||
|
||||
self.doc:drawCurrentPage(self.nulldc, fb.bb)
|
||||
|
||||
if self.rcount == self.rcountmax then
|
||||
print("full refresh")
|
||||
self.rcount = 1
|
||||
fb:refresh(0)
|
||||
else
|
||||
print("partial refresh")
|
||||
self.rcount = self.rcount + 1
|
||||
fb:refresh(1)
|
||||
end
|
||||
|
||||
self.pos = pos
|
||||
self.pageno = self.doc:getCurrentPage()
|
||||
self.percent = self.doc:getCurrentPercent()
|
||||
end
|
||||
|
||||
function CREReader:gotoPercent(percent)
|
||||
self:goto(percent * self.doc:getFullHeight() / 10000)
|
||||
end
|
||||
|
||||
function CREReader:gotoTocEntry(entry)
|
||||
self:goto(entry.xpointer, "xpointer")
|
||||
end
|
||||
|
||||
function CREReader:nextView()
|
||||
return self.pos + height - self.pan_overlap_vertical
|
||||
end
|
||||
|
||||
function CREReader:prevView()
|
||||
return self.pos - height + self.pan_overlap_vertical
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- jump stack related methods
|
||||
----------------------------------------------------
|
||||
function CREReader:isSamePage(p1, p2)
|
||||
return self.doc:getPageFromXPointer(p1) == self.doc:getPageFromXPointer(p2)
|
||||
end
|
||||
|
||||
function CREReader:showJumpStack()
|
||||
local menu_items = {}
|
||||
print(dump(self.jump_stack))
|
||||
for k,v in ipairs(self.jump_stack) do
|
||||
table.insert(menu_items,
|
||||
v.datetime.." -> page "..
|
||||
(self.doc:getPageFromXPointer(v.page)).." "..v.notes)
|
||||
end
|
||||
jump_menu = SelectMenu:new{
|
||||
menu_title = "Jump Keeper (current page: "..self.pageno..")",
|
||||
item_array = menu_items,
|
||||
no_item_msg = "No jump history.",
|
||||
}
|
||||
item_no = jump_menu:choose(0, fb.bb:getHeight())
|
||||
if item_no then
|
||||
local jump_item = self.jump_stack[item_no]
|
||||
self:goto(jump_item.page, "xpointer")
|
||||
else
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- TOC related methods
|
||||
----------------------------------------------------
|
||||
function CREReader:getTocTitleOfCurrentPage()
|
||||
return self:getTocTitleByPage(self.percent)
|
||||
end
|
||||
|
||||
|
||||
----------------------------------------------------
|
||||
-- menu related methods
|
||||
----------------------------------------------------
|
||||
-- used in CREReader:showMenu()
|
||||
function CREReader:_drawReadingInfo()
|
||||
local ypos = height - 50
|
||||
local load_percent = self.percent/100
|
||||
|
||||
fb.bb:paintRect(0, ypos, width, 50, 0)
|
||||
|
||||
ypos = ypos + 15
|
||||
local face, fhash = Font:getFaceAndHash(22)
|
||||
local cur_section = self:getTocTitleOfCurrentPage()
|
||||
if cur_section ~= "" then
|
||||
cur_section = "Section: "..cur_section
|
||||
end
|
||||
renderUtf8Text(fb.bb, 10, ypos+6, face, fhash,
|
||||
"Position: "..load_percent.."%".." "..cur_section, true)
|
||||
|
||||
ypos = ypos + 15
|
||||
blitbuffer.progressBar(fb.bb, 10, ypos, width-20, 15,
|
||||
5, 4, load_percent/100, 8)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function CREReader:adjustCreReaderCommands()
|
||||
-- delete commands
|
||||
self.commands:delGroup("[joypad]")
|
||||
self.commands:del(KEY_G, nil, "G")
|
||||
self.commands:del(KEY_J, nil, "J")
|
||||
self.commands:del(KEY_K, nil, "K")
|
||||
self.commands:del(KEY_Z, nil, "Z")
|
||||
self.commands:del(KEY_Z, MOD_SHIFT, "Z")
|
||||
self.commands:del(KEY_Z, MOD_ALT, "Z")
|
||||
self.commands:del(KEY_A, nil, "A")
|
||||
self.commands:del(KEY_A, MOD_SHIFT, "A")
|
||||
self.commands:del(KEY_A, MOD_ALT, "A")
|
||||
self.commands:del(KEY_S, nil, "S")
|
||||
self.commands:del(KEY_S, MOD_SHIFT, "S")
|
||||
self.commands:del(KEY_S, MOD_ALT, "S")
|
||||
self.commands:del(KEY_D, nil, "D")
|
||||
self.commands:del(KEY_D, MOD_SHIFT, "D")
|
||||
self.commands:del(KEY_D, MOD_ALT, "D")
|
||||
self.commands:del(KEY_F, MOD_SHIFT, "F")
|
||||
self.commands:del(KEY_F, MOD_ALT, "F")
|
||||
|
||||
-- overwrite commands
|
||||
self.commands:add(KEY_PGFWD, MOD_SHIFT_OR_ALT, ">",
|
||||
"increase font size",
|
||||
function(cr)
|
||||
cr.doc:zoomFont(1)
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_PGBCK, MOD_SHIFT_OR_ALT, "<",
|
||||
"decrease font size",
|
||||
function(cr)
|
||||
cr.doc:zoomFont(-1)
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
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(cr, keydef)
|
||||
print('jump to position: '..
|
||||
math.floor(cr.doc:getFullHeight()*(keydef.keycode-KEY_1)/9)..
|
||||
'/'..cr.doc:getFullHeight())
|
||||
cr:goto(math.floor(cr.doc:getFullHeight()*(keydef.keycode-KEY_1)/9))
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_F, nil, "F",
|
||||
"invoke font menu",
|
||||
function(cr)
|
||||
local face_list = cre.getFontFaces()
|
||||
|
||||
local fonts_menu = SelectMenu:new{
|
||||
menu_title = "Fonts Menu",
|
||||
item_array = face_list,
|
||||
}
|
||||
|
||||
local item_no = fonts_menu:choose(0, height)
|
||||
print(face_list[item_no])
|
||||
if item_no then
|
||||
cr.doc:setFontFace(face_list[item_no])
|
||||
self.font_face = face_list[item_no]
|
||||
end
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_F, MOD_ALT, "F",
|
||||
"Toggle font bolder attribute",
|
||||
function(cr)
|
||||
cr.doc:toggleFontBolder()
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_B, MOD_SHIFT, "B",
|
||||
"add jump",
|
||||
function(cr)
|
||||
cr:addJump(self.doc:getXPointer())
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_BACK,nil,"back",
|
||||
"back to last jump",
|
||||
function(cr)
|
||||
if #cr.jump_stack ~= 0 then
|
||||
cr:goto(cr.jump_stack[1].page, "xpointer")
|
||||
end
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_VPLUS, nil, "vol+",
|
||||
"increase gamma",
|
||||
function(cr)
|
||||
cre.setGammaIndex(self.gamma_index + 1)
|
||||
self.gamma_index = cre.getGammaIndex()
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_VMINUS, nil, "vol-",
|
||||
"decrease gamma",
|
||||
function(cr)
|
||||
cre.setGammaIndex(self.gamma_index - 1)
|
||||
self.gamma_index = cre.getGammaIndex()
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_UP, nil, "joypad up",
|
||||
"pan "..self.shift_y.." pixels upwards",
|
||||
function(cr)
|
||||
cr:goto(cr.pos - cr.shift_y)
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_FW_DOWN, nil, "joypad down",
|
||||
"pan "..self.shift_y.." pixels downwards",
|
||||
function(cr)
|
||||
cr:goto(cr.pos + cr.shift_y)
|
||||
end
|
||||
)
|
||||
end
|
||||
2
djvu.c
2
djvu.c
@@ -473,7 +473,7 @@ static const struct luaL_Reg djvu_func[] = {
|
||||
static const struct luaL_Reg djvudocument_meth[] = {
|
||||
{"openPage", openPage},
|
||||
{"getPages", getNumberOfPages},
|
||||
{"getTOC", getTableOfContent},
|
||||
{"getToc", getTableOfContent},
|
||||
{"getPageText", getPageText},
|
||||
{"close", closeDocument},
|
||||
{"getCacheSize", getCacheSize},
|
||||
|
||||
@@ -13,6 +13,27 @@ function DJVUReader:open(filename)
|
||||
return ok
|
||||
end
|
||||
|
||||
function DJVUReader:init()
|
||||
self:addAllCommands()
|
||||
self:adjustDjvuReaderCommand()
|
||||
end
|
||||
|
||||
function DJVUReader:adjustDjvuReaderCommand()
|
||||
self.commands:add(KEY_N, nil, "N",
|
||||
"start highlight mode",
|
||||
function(unireader)
|
||||
unireader:startHighLightMode()
|
||||
unireader:goto(unireader.pageno)
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_N, MOD_SHIFT, "N",
|
||||
"display all highlights",
|
||||
function(unireader)
|
||||
unireader:showHighLight()
|
||||
unireader:goto(unireader.pageno)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
-----------[ highlight support ]----------
|
||||
|
||||
@@ -54,7 +54,11 @@ function FileChooser:readDir()
|
||||
table.insert(self.dirs, f)
|
||||
else
|
||||
local file_type = string.lower(string.match(f, ".+%.([^.]+)") or "")
|
||||
if file_type == "djvu" or file_type == "pdf" or file_type == "xps" or file_type == "cbz" then
|
||||
if file_type == "djvu"
|
||||
or file_type == "pdf" or file_type == "xps" or file_type == "cbz"
|
||||
or file_type == "epub" or file_type == "txt" or file_type == "rtf"
|
||||
or file_type == "htm" or file_type == "html"
|
||||
or file_type == "fb2" or file_type == "chm" then
|
||||
table.insert(self.files, f)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,10 +30,16 @@ function FileSearcher:readDir()
|
||||
for __, d in pairs(self.dirs) do
|
||||
-- handle files in d
|
||||
for f in lfs.dir(d) do
|
||||
local file_type = string.lower(string.match(f, ".+%.([^.]+)") or "")
|
||||
if lfs.attributes(d.."/"..f, "mode") == "directory"
|
||||
and f ~= "." and f~= ".." and not string.match(f, "^%.[^.]") then
|
||||
table.insert(new_dirs, d.."/"..f)
|
||||
elseif string.match(f, ".+%.[pP][dD][fF]$") or string.match(f, ".+%.[dD][jJ][vV][uU]$") then
|
||||
elseif file_type == "djvu" or file_type == "pdf"
|
||||
or file_type == "xps" or file_type == "cbz"
|
||||
or file_type == "epub" or file_type == "txt"
|
||||
or file_type == "rtf" or file_type == "htm"
|
||||
or file_type == "html"
|
||||
or file_type == "fb2" or file_type == "chm" then
|
||||
file_entry = {dir=d, name=f,}
|
||||
table.insert(self.files, file_entry)
|
||||
--print("file:"..d.."/"..f)
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "blitbuffer.h"
|
||||
#include "drawcontext.h"
|
||||
#include "pdf.h"
|
||||
#include "djvu.h"
|
||||
#include "cre.h"
|
||||
#include "einkfb.h"
|
||||
#include "input.h"
|
||||
#include "ft.h"
|
||||
@@ -53,6 +55,7 @@ int main(int argc, char **argv) {
|
||||
luaopen_einkfb(L);
|
||||
luaopen_pdf(L);
|
||||
luaopen_djvu(L);
|
||||
luaopen_cre(L);
|
||||
luaopen_input(L);
|
||||
luaopen_util(L);
|
||||
luaopen_ft(L);
|
||||
|
||||
51
kpvcrlib/CMakeLists.txt
Normal file
51
kpvcrlib/CMakeLists.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
PROJECT(kpvcrlib)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
SET(MUPDF_DIR ../mupdf)
|
||||
SET(MUPDF_3RDPARTY_DIR ${MUPDF_DIR}/thirdparty)
|
||||
SET(CR_3RDPARTY_DIR crengine/thirdparty)
|
||||
|
||||
SET(CR3_PNG 1)
|
||||
#SET(CR3_JPEG 1)
|
||||
|
||||
SET(FREETYPE_INCLUDE_DIRS ${CR_3RDPARTY_DIR}/freetype/include)
|
||||
SET(ANTIWORD_INCLUDE_DIR ${CR_3RDPARTY_DIR}/antiword)
|
||||
SET(CHM_INCLUDE_DIRS ${CR_3RDPARTY_DIR}/chmlib)
|
||||
SET(PNG_INCLUDE_DIR ${CR_3RDPARTY_DIR}/libpng)
|
||||
SET(ZLIB_INCLUDE_DIR ${MUPDF_3RDPARTY_DIR}/zlib-1.2.5)
|
||||
#SET(ZLIB_INCLUDE_DIR ${CR_3RDPARTY_DIR}/zlib)
|
||||
SET(JPEGLIB_INCLUDE_DIR ${MUPDF_3RDPARTY_DIR}/jpeg-8d)
|
||||
#SET(JPEGLIB_INCLUDE_DIR ${CR_3RDPARTY_DIR}/libjpeg)
|
||||
SET(JCONFIG_INCLUDE_DIR ${MUPDF_DIR}/scripts)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${FREETYPE_INCLUDE_DIRS}
|
||||
${ANTIWORD_INCLUDE_DIR}
|
||||
${CHM_INCLUDE_DIRS}
|
||||
${PNG_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${JPEGLIB_INCLUDE_DIR}
|
||||
${JCONFIG_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS(-DUSE_FONTCONFIG=0 -DUSE_FREETYPE=1 -DCR3_PATCH=1 -DNDEBUG=1)
|
||||
|
||||
message("Will build patched LIBCHM library")
|
||||
ADD_DEFINITIONS(-DCHM_SUPPORT_ENABLED=1)
|
||||
ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/chmlib)
|
||||
|
||||
message("Will build patched LIBPNG library")
|
||||
ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/libpng)
|
||||
|
||||
#message("Will build patched JPEGLIB library")
|
||||
#ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/libjpeg)
|
||||
|
||||
message("Will build patched ANTIWORD library")
|
||||
ADD_DEFINITIONS(-DENABLE_ANTIWORD=1)
|
||||
ADD_DEFINITIONS(-DCR3_ANTIWORD_PATCH=1)
|
||||
ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/antiword)
|
||||
|
||||
SET(GUI kpv)
|
||||
#ADD_DEFINITIONS(-DJCONFIG_INCLUDED=1)
|
||||
ADD_SUBDIRECTORY(crengine/crengine)
|
||||
|
||||
1
kpvcrlib/crengine
Submodule
1
kpvcrlib/crengine
Submodule
Submodule kpvcrlib/crengine added at ba469d3347
15
kpvcrlib/jpeg_compress_struct_size.patch
Normal file
15
kpvcrlib/jpeg_compress_struct_size.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
--- jcapimin.c 2012-04-04 00:02:30.000000000 +0800
|
||||
+++ jcapimin-patched.c 2012-04-04 00:02:26.000000000 +0800
|
||||
@@ -36,9 +36,9 @@
|
||||
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
|
||||
if (version != JPEG_LIB_VERSION)
|
||||
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
|
||||
- if (structsize != SIZEOF(struct jpeg_compress_struct))
|
||||
- ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
|
||||
- (int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
|
||||
+ /*if (structsize != SIZEOF(struct jpeg_compress_struct))*/
|
||||
+ /*ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, */
|
||||
+ /*(int) SIZEOF(struct jpeg_compress_struct), (int) structsize);*/
|
||||
|
||||
/* For debugging purposes, we zero the whole master structure.
|
||||
* But the application has already set the err pointer, and may have set
|
||||
15
kpvcrlib/jpeg_decompress_struct_size.patch
Normal file
15
kpvcrlib/jpeg_decompress_struct_size.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
--- jdapimin.c 2012-04-04 01:09:00.000000000 +0800
|
||||
+++ jdapimin-patched.c 2012-04-04 01:42:44.000000000 +0800
|
||||
@@ -36,9 +36,9 @@
|
||||
cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
|
||||
if (version != JPEG_LIB_VERSION)
|
||||
ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
|
||||
- if (structsize != SIZEOF(struct jpeg_decompress_struct))
|
||||
- ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
|
||||
- (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
|
||||
+ /*if (structsize != SIZEOF(struct jpeg_decompress_struct))*/
|
||||
+ /*ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, */
|
||||
+ /*(int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);*/
|
||||
|
||||
/* For debugging purposes, we zero the whole master structure.
|
||||
* But the application has already set the err pointer, and may have set
|
||||
2
pdf.c
2
pdf.c
@@ -445,7 +445,7 @@ static const struct luaL_Reg pdfdocument_meth[] = {
|
||||
{"authenticatePassword", authenticatePassword},
|
||||
{"openPage", openPage},
|
||||
{"getPages", getNumberOfPages},
|
||||
{"getTOC", getTableOfContent},
|
||||
{"getToc", getTableOfContent},
|
||||
{"close", closeDocument},
|
||||
{"getCacheSize", getCacheSize},
|
||||
{"cleanCache", cleanCache},
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
require "alt_getopt"
|
||||
require "pdfreader"
|
||||
require "djvureader"
|
||||
require "crereader"
|
||||
require "filechooser"
|
||||
require "settings"
|
||||
require "screen"
|
||||
@@ -42,12 +43,14 @@ function openFile(filename)
|
||||
reader = DJVUReader
|
||||
elseif file_type == "pdf" or file_type == "xps" or file_type == "cbz" then
|
||||
reader = PDFReader
|
||||
elseif file_type == "epub" or file_type == "txt" or file_type == "rtf" or file_type == "htm" or file_type == "html" or file_type == "fb2" or file_type == "chm" then
|
||||
reader = CREReader
|
||||
end
|
||||
if reader then
|
||||
local ok, err = reader:open(filename)
|
||||
if ok then
|
||||
reader:loadSettings(filename)
|
||||
page_num = reader.settings:readSetting("last_page") or 1
|
||||
page_num = reader:getLastPageOrPos()
|
||||
reader:goto(tonumber(page_num))
|
||||
reader_settings:savesetting("lastfile", filename)
|
||||
return reader:inputLoop()
|
||||
@@ -135,6 +138,7 @@ UniReader:initGlobalSettings(reader_settings)
|
||||
-- initialize specific readers
|
||||
PDFReader:init()
|
||||
DJVUReader:init()
|
||||
CREReader:init()
|
||||
|
||||
-- display directory or open file
|
||||
local patharg = reader_settings:readSetting("lastfile")
|
||||
|
||||
304
selectmenu.lua
304
selectmenu.lua
@@ -2,6 +2,7 @@ require "rendertext"
|
||||
require "keys"
|
||||
require "graphics"
|
||||
require "font"
|
||||
require "commands"
|
||||
|
||||
SelectMenu = {
|
||||
-- font for displaying item names
|
||||
@@ -32,10 +33,14 @@ SelectMenu = {
|
||||
"Z", "X", "C", "V", "B", "N", "M", ".", "Sym", "Ent",
|
||||
},
|
||||
last_shortcut = 0,
|
||||
|
||||
-- state buffer
|
||||
page = 1,
|
||||
current = 1,
|
||||
oldcurrent = 0,
|
||||
selected_item = nil,
|
||||
|
||||
commands = nil,
|
||||
}
|
||||
|
||||
function SelectMenu:new(o)
|
||||
@@ -46,10 +51,12 @@ function SelectMenu:new(o)
|
||||
o.page = 1
|
||||
o.current = 1
|
||||
o.oldcurrent = 0
|
||||
o.selected_item = nil
|
||||
-- increase spacing for DXG so we don't have more than 30 shortcuts
|
||||
if fb.bb:getHeight() == 1200 then
|
||||
o.spacing = 37
|
||||
end
|
||||
o:addAllCommands()
|
||||
return o
|
||||
end
|
||||
|
||||
@@ -62,43 +69,164 @@ function SelectMenu:getItemIndexByShortCut(c, perpage)
|
||||
end
|
||||
end
|
||||
|
||||
--[
|
||||
function SelectMenu:addAllCommands()
|
||||
self.commands = Commands:new{}
|
||||
|
||||
self.commands:add(KEY_FW_UP, nil, "",
|
||||
"previous item",
|
||||
function(sm)
|
||||
if sm.current == 1 then
|
||||
if sm.page > 1 then
|
||||
sm.current = sm.perpage
|
||||
sm.page = sm.page - 1
|
||||
sm.pagedirty = true
|
||||
end
|
||||
else
|
||||
sm.current = sm.current - 1
|
||||
sm.markerdirty = true
|
||||
end
|
||||
end)
|
||||
|
||||
self.commands:add(KEY_FW_DOWN, nil, "",
|
||||
"next item",
|
||||
function(sm)
|
||||
if sm.current == sm.perpage then
|
||||
if sm.page < (sm.items / sm.perpage) then
|
||||
sm.current = 1
|
||||
sm.page = sm.page + 1
|
||||
sm.pagedirty = true
|
||||
end
|
||||
else
|
||||
if sm.page ~= math.floor(sm.items / sm.perpage) + 1
|
||||
or sm.current + (sm.page - 1) * sm.perpage < sm.items then
|
||||
sm.current = sm.current + 1
|
||||
sm.markerdirty = true
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
self.commands:add({KEY_PGFWD, KEY_LPGFWD}, nil, "",
|
||||
"next page",
|
||||
function(sm)
|
||||
if sm.page < (sm.items / sm.perpage) then
|
||||
if sm.current + sm.page * sm.perpage > sm.items then
|
||||
sm.current = sm.items - sm.page * sm.perpage
|
||||
end
|
||||
sm.page = sm.page + 1
|
||||
sm.pagedirty = true
|
||||
else
|
||||
sm.current = sm.items - (sm.page - 1) * sm.perpage
|
||||
sm.markerdirty = true
|
||||
end
|
||||
end)
|
||||
|
||||
self.commands:add({KEY_PGBCK, KEY_LPGBCK}, nil, "",
|
||||
"previous page",
|
||||
function(sm)
|
||||
if sm.page > 1 then
|
||||
sm.page = sm.page - 1
|
||||
sm.pagedirty = true
|
||||
else
|
||||
sm.current = 1
|
||||
sm.markerdirty = true
|
||||
end
|
||||
end)
|
||||
|
||||
self.commands:add(KEY_FW_PRESS, nil, "",
|
||||
"select menu item",
|
||||
function(sm)
|
||||
if sm.last_shortcut < 30 then
|
||||
if sm.items == 0 then
|
||||
return "break"
|
||||
else
|
||||
self.selected_item = (sm.perpage * (sm.page - 1)
|
||||
+ sm.current)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local KEY_Q_to_E = {}
|
||||
for i = KEY_Q, KEY_P do
|
||||
table.insert(KEY_Q_to_E, Keydef:new(i, nil, ""))
|
||||
end
|
||||
self.commands:addGroup("Q to E", KEY_Q_to_E,
|
||||
"Select menu item with Q to E key as shortcut",
|
||||
function(sm, keydef)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(
|
||||
sm.item_shortcuts[ keydef.keycode - KEY_Q + 1 ], sm.perpage)
|
||||
end)
|
||||
|
||||
local KEY_A_to_L = {}
|
||||
for i = KEY_A, KEY_L do
|
||||
table.insert(KEY_A_to_L, Keydef:new(i, nil, ""))
|
||||
end
|
||||
self.commands:addGroup("A to L", KEY_A_to_L,
|
||||
"Select menu item with A to L key as shortcut",
|
||||
function(sm, keydef)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(
|
||||
sm.item_shortcuts[ keydef.keycode - KEY_A + 11 ], sm.perpage)
|
||||
end)
|
||||
|
||||
local KEY_Z_to_M = {}
|
||||
for i = KEY_Z, KEY_M do
|
||||
table.insert(KEY_Z_to_M, Keydef:new(i, nil, ""))
|
||||
end
|
||||
self.commands:addGroup("Z to M", KEY_Z_to_M,
|
||||
"Select menu item with Z to M key as shortcut",
|
||||
function(sm, keydef)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(
|
||||
sm.item_shortcuts[ keydef.keycode - KEY_Z + 21 ], sm.perpage)
|
||||
end)
|
||||
|
||||
self.commands:add(KEY_DEL, nil, "",
|
||||
"Select menu item with del key as shortcut",
|
||||
function(sm)
|
||||
sm.selected_item = sm:getItemIndexByShortCut("Del", sm.perpage)
|
||||
end)
|
||||
|
||||
self.commands:add(KEY_DOT, nil, "",
|
||||
"Select menu item with dot key as shortcut",
|
||||
function(sm)
|
||||
sm.selected_item = sm:getItemIndexByShortCut(".", sm.perpage)
|
||||
end)
|
||||
|
||||
self.commands:add({KEY_SYM, KEY_SLASH}, nil, "",
|
||||
"Select menu item with sym/slash key as shortcut",
|
||||
function(sm)
|
||||
-- DXG has slash after dot
|
||||
sm.selected_item = sm:getItemIndexByShortCut("Sym", sm.perpage)
|
||||
end)
|
||||
|
||||
self.commands:add(KEY_ENTER, nil, "",
|
||||
"Select menu item with enter key as shortcut",
|
||||
function(sm)
|
||||
sm.selected_item = sm:getItemIndexByShortCut("Ent", sm.perpage)
|
||||
end)
|
||||
|
||||
self.commands:add(KEY_BACK, nil, "",
|
||||
"Exit menu",
|
||||
function(sm)
|
||||
return "break"
|
||||
end)
|
||||
end
|
||||
|
||||
function SelectMenu:clearCommands()
|
||||
self.commands = Commands:new{}
|
||||
|
||||
self.commands:add(KEY_BACK, nil, "",
|
||||
"Exit menu",
|
||||
function(sm)
|
||||
return "break"
|
||||
end)
|
||||
end
|
||||
|
||||
------------------------------------------------
|
||||
-- return the index of selected item
|
||||
--]
|
||||
------------------------------------------------
|
||||
function SelectMenu:choose(ypos, height)
|
||||
local perpage = math.floor(height / self.spacing) - 2
|
||||
local pagedirty = true
|
||||
local markerdirty = false
|
||||
|
||||
local prevItem = function ()
|
||||
if self.current == 1 then
|
||||
if self.page > 1 then
|
||||
self.current = perpage
|
||||
self.page = self.page - 1
|
||||
pagedirty = true
|
||||
end
|
||||
else
|
||||
self.current = self.current - 1
|
||||
markerdirty = true
|
||||
end
|
||||
end
|
||||
|
||||
local nextItem = function ()
|
||||
if self.current == perpage then
|
||||
if self.page < (self.items / perpage) then
|
||||
self.current = 1
|
||||
self.page = self.page + 1
|
||||
pagedirty = true
|
||||
end
|
||||
else
|
||||
if self.page ~= math.floor(self.items / perpage) + 1
|
||||
or self.current + (self.page-1)*perpage < self.items then
|
||||
self.current = self.current + 1
|
||||
markerdirty = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.perpage = math.floor(height / self.spacing) - 2
|
||||
self.pagedirty = true
|
||||
self.markerdirty = false
|
||||
self.last_shortcut = 0
|
||||
|
||||
while true do
|
||||
@@ -106,8 +234,8 @@ function SelectMenu:choose(ypos, height)
|
||||
local tface, tfhash = Font:getFaceAndHash(25, Font.tfont)
|
||||
local fface, ffhash = Font:getFaceAndHash(16, Font.ffont)
|
||||
|
||||
if pagedirty then
|
||||
markerdirty = true
|
||||
if self.pagedirty then
|
||||
self.markerdirty = true
|
||||
-- draw menu title
|
||||
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), self.title_H + 10, 0)
|
||||
fb.bb:paintRect(10, ypos + 10, fb.bb:getWidth() - 20, self.title_H, 5)
|
||||
@@ -125,11 +253,12 @@ function SelectMenu:choose(ypos, height)
|
||||
y = y + self.spacing
|
||||
renderUtf8Text(fb.bb, 30, y, cface, cfhash,
|
||||
self.no_item_msg, true)
|
||||
markerdirty = false
|
||||
self.markerdirty = false
|
||||
self:clearCommands()
|
||||
else
|
||||
local c
|
||||
for c = 1, perpage do
|
||||
local i = (self.page - 1) * perpage + c
|
||||
for c = 1, self.perpage do
|
||||
local i = (self.page - 1) * self.perpage + c
|
||||
if i <= self.items then
|
||||
y = ypos + self.title_H + (self.spacing * c)
|
||||
|
||||
@@ -153,19 +282,21 @@ function SelectMenu:choose(ypos, height)
|
||||
|
||||
renderUtf8Text(fb.bb, 50, y, cface, cfhash,
|
||||
self.item_array[i], true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end -- EOF if i <= self.items
|
||||
end -- EOF for
|
||||
end -- EOF if
|
||||
|
||||
-- draw footer
|
||||
y = ypos + self.title_H + (self.spacing * perpage) + self.foot_H + 5
|
||||
y = ypos + self.title_H + (self.spacing * self.perpage)
|
||||
+ self.foot_H + 5
|
||||
x = (fb.bb:getWidth() / 2) - 50
|
||||
renderUtf8Text(fb.bb, x, y, fface, ffhash,
|
||||
"Page "..self.page.." of "..(math.floor(self.items / perpage)+1), true)
|
||||
"Page "..self.page.." of "..
|
||||
(math.ceil(self.items / self.perpage)), true)
|
||||
end
|
||||
|
||||
if markerdirty then
|
||||
if not pagedirty then
|
||||
if self.markerdirty then
|
||||
if not self.pagedirty then
|
||||
if self.oldcurrent > 0 then
|
||||
y = ypos + self.title_H + (self.spacing * self.oldcurrent) + 8
|
||||
fb.bb:paintRect(45, y, fb.bb:getWidth() - 60, 3, 0)
|
||||
@@ -175,72 +306,41 @@ function SelectMenu:choose(ypos, height)
|
||||
-- draw new marker line
|
||||
y = ypos + self.title_H + (self.spacing * self.current) + 8
|
||||
fb.bb:paintRect(45, y, fb.bb:getWidth() - 60, 3, 15)
|
||||
if not pagedirty then
|
||||
if not self.pagedirty then
|
||||
fb:refresh(1, 45, y, fb.bb:getWidth() - 60, 3)
|
||||
end
|
||||
self.oldcurrent = self.current
|
||||
markerdirty = false
|
||||
self.markerdirty = false
|
||||
end
|
||||
|
||||
if pagedirty then
|
||||
if self.pagedirty then
|
||||
fb:refresh(0, 0, ypos, fb.bb:getWidth(), height)
|
||||
pagedirty = false
|
||||
self.pagedirty = false
|
||||
end
|
||||
|
||||
local ev = input.waitForEvent()
|
||||
ev.code = adjustKeyEvents(ev)
|
||||
if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then
|
||||
local selected = nil
|
||||
if ev.code == KEY_FW_UP then
|
||||
prevItem()
|
||||
elseif ev.code == KEY_FW_DOWN then
|
||||
nextItem()
|
||||
elseif ev.code == KEY_PGFWD or ev.code == KEY_LPGFWD then
|
||||
if self.page < (self.items / perpage) then
|
||||
if self.current + self.page*perpage > self.items then
|
||||
self.current = self.items - self.page*perpage
|
||||
end
|
||||
self.page = self.page + 1
|
||||
pagedirty = true
|
||||
else
|
||||
self.current = self.items - (self.page-1)*perpage
|
||||
markerdirty = true
|
||||
end
|
||||
elseif ev.code == KEY_PGBCK or ev.code == KEY_LPGBCK then
|
||||
if self.page > 1 then
|
||||
self.page = self.page - 1
|
||||
pagedirty = true
|
||||
else
|
||||
self.current = 1
|
||||
markerdirty = true
|
||||
end
|
||||
elseif ev.code == KEY_FW_PRESS or ev.code == KEY_ENTER and self.last_shortcut < 30 then
|
||||
if self.items == 0 then
|
||||
return nil
|
||||
else
|
||||
return (perpage*(self.page-1) + self.current)
|
||||
end
|
||||
elseif ev.code >= KEY_Q and ev.code <= KEY_P then
|
||||
selected = self:getItemIndexByShortCut(self.item_shortcuts[ ev.code - KEY_Q + 1 ], perpage)
|
||||
elseif ev.code >= KEY_A and ev.code <= KEY_L then
|
||||
selected = self:getItemIndexByShortCut(self.item_shortcuts[ ev.code - KEY_A + 11], perpage)
|
||||
elseif ev.code >= KEY_Z and ev.code <= KEY_M then
|
||||
selected = self:getItemIndexByShortCut(self.item_shortcuts[ ev.code - KEY_Z + 21], perpage)
|
||||
elseif ev.code == KEY_DEL then
|
||||
selected = self:getItemIndexByShortCut("Del", perpage)
|
||||
elseif ev.code == KEY_DOT then
|
||||
selected = self:getItemIndexByShortCut(".", perpage)
|
||||
elseif ev.code == KEY_SYM or ev.code == KEY_SLASH then -- DXG has slash after dot
|
||||
selected = self:getItemIndexByShortCut("Sym", perpage)
|
||||
elseif ev.code == KEY_ENTER then
|
||||
selected = self:getItemIndexByShortCut("Ent", perpage)
|
||||
elseif ev.code == KEY_BACK then
|
||||
return nil
|
||||
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)
|
||||
else
|
||||
print("command not found: "..tostring(command))
|
||||
end
|
||||
if selected ~= nil then
|
||||
print("# selected "..selected)
|
||||
return selected
|
||||
|
||||
if ret_code == "break" then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.selected_item ~= nil then
|
||||
print("# selected "..self.selected_item)
|
||||
return self.selected_item
|
||||
end
|
||||
end -- EOF if
|
||||
end -- EOF while
|
||||
return nil
|
||||
end
|
||||
|
||||
182
unireader.lua
182
unireader.lua
@@ -94,22 +94,23 @@ end
|
||||
-- !!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
--
|
||||
-- For a new specific reader,
|
||||
-- you must always overwrite following two methods:
|
||||
-- you must always overwrite following method:
|
||||
--
|
||||
-- * self:open()
|
||||
-- * self:init()
|
||||
--
|
||||
-- overwrite other methods if needed.
|
||||
----------------------------------------------------
|
||||
function UniReader:init()
|
||||
end
|
||||
|
||||
-- open a file and its settings store
|
||||
-- tips: you can use self:loadSettings in open() method.
|
||||
-- open a file
|
||||
function UniReader:open(filename, cache_size)
|
||||
return false
|
||||
end
|
||||
|
||||
function UniReader:init()
|
||||
-- initialize commands
|
||||
self:addAllCommands()
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- You need to overwrite following two methods if your
|
||||
-- reader supports highlight feature.
|
||||
@@ -128,7 +129,7 @@ function UniReader:toggleTextHighLight(word_list)
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- renderer memory
|
||||
-- Renderer memory
|
||||
----------------------------------------------------
|
||||
|
||||
function UniReader:getCacheSize()
|
||||
@@ -139,9 +140,46 @@ function UniReader:cleanCache()
|
||||
return
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- Setting related methods
|
||||
----------------------------------------------------
|
||||
|
||||
-- load special settings for specific reader
|
||||
function UniReader:loadSpecialSettings()
|
||||
return
|
||||
end
|
||||
|
||||
-- save special settings for specific reader
|
||||
function UniReader:saveSpecialSettings()
|
||||
end
|
||||
|
||||
|
||||
|
||||
--[ following are default methods ]--
|
||||
|
||||
function UniReader:initGlobalSettings(settings)
|
||||
local pan_overlap_vertical = settings:readSetting("pan_overlap_vertical")
|
||||
if pan_overlap_vertical then
|
||||
self.pan_overlap_vertical = pan_overlap_vertical
|
||||
end
|
||||
|
||||
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")
|
||||
if cache_max_ttl then
|
||||
self.cache_max_ttl = cache_max_ttl
|
||||
end
|
||||
|
||||
local rcountmax = settings:readSetting("partial_refresh_count")
|
||||
if rcountmax then
|
||||
self.rcountmax = rcountmax
|
||||
end
|
||||
end
|
||||
|
||||
-- This is a low-level method that can be shared with all readers.
|
||||
function UniReader:loadSettings(filename)
|
||||
if self.doc ~= nil then
|
||||
self.settings = DocSettings:open(filename,self.cache_document_size)
|
||||
@@ -164,33 +202,18 @@ function UniReader:loadSettings(filename)
|
||||
self.globalzoom = self.settings:readSetting("globalzoom") or 1.0
|
||||
self.globalzoommode = self.settings:readSetting("globalzoommode") or -1
|
||||
|
||||
self:loadSpecialSettings()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function UniReader:initGlobalSettings(settings)
|
||||
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()
|
||||
function UniReader:getLastPageOrPos()
|
||||
return self.settings:readSetting("last_page") or 1
|
||||
end
|
||||
|
||||
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")
|
||||
if cache_max_ttl then
|
||||
self.cache_max_ttl = cache_max_ttl
|
||||
end
|
||||
|
||||
local rcountmax = settings:readSetting("partial_refresh_count")
|
||||
if rcountmax then
|
||||
self.rcountmax = rcountmax
|
||||
end
|
||||
function UniReader:saveLastPageOrPos()
|
||||
self.settings:savesetting("last_page", self.pageno)
|
||||
end
|
||||
|
||||
-- guarantee that we have enough memory in cache
|
||||
@@ -542,27 +565,32 @@ function UniReader:show(no)
|
||||
self.slot_visible = slot;
|
||||
end
|
||||
|
||||
function UniReader:isSamePage(p1, p2)
|
||||
return p1 == p2
|
||||
end
|
||||
|
||||
--[[
|
||||
@ pageno is the page you want to add to jump_stack
|
||||
NOTE: for CREReader, pageno refers to xpointer
|
||||
--]]
|
||||
function UniReader:addJump(pageno, notes)
|
||||
local jump_item = nil
|
||||
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)
|
||||
-- no notes given, auto generate from Toc entry
|
||||
notes_to_add = self:getTocTitleOfCurrentPage()
|
||||
if notes_to_add ~= "" then
|
||||
notes_to_add = "in "..notes_to_add
|
||||
end
|
||||
end
|
||||
-- move pageno page to jump_stack top if already in
|
||||
for _t,_v in ipairs(self.jump_stack) do
|
||||
if _v.page == pageno then
|
||||
if self:isSamePage(_v.page, pageno) then
|
||||
jump_item = _v
|
||||
table.remove(self.jump_stack, _t)
|
||||
-- if original notes is not empty, probably defined by users,
|
||||
-- we use the original notes to overwrite auto generated notes
|
||||
-- from TOC entry
|
||||
-- from Toc entry
|
||||
if jump_item.notes ~= "" then
|
||||
notes_to_add = jump_item.notes
|
||||
end
|
||||
@@ -620,6 +648,10 @@ function UniReader:goto(no)
|
||||
end
|
||||
end
|
||||
|
||||
function UniReader:redrawCurrentPage()
|
||||
self:goto(self.pageno)
|
||||
end
|
||||
|
||||
function UniReader:nextView()
|
||||
local pageno = self.pageno
|
||||
|
||||
@@ -675,14 +707,14 @@ end
|
||||
function UniReader:modifyGamma(factor)
|
||||
print("modifyGamma, gamma="..self.globalgamma.." factor="..factor)
|
||||
self.globalgamma = self.globalgamma * factor;
|
||||
self:goto(self.pageno)
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
|
||||
-- adjust zoom state and trigger re-rendering
|
||||
function UniReader:setGlobalZoomMode(newzoommode)
|
||||
if self.globalzoommode ~= newzoommode then
|
||||
self.globalzoommode = newzoommode
|
||||
self:goto(self.pageno)
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -691,13 +723,13 @@ function UniReader:setGlobalZoom(zoom)
|
||||
if self.globalzoom ~= zoom then
|
||||
self.globalzoommode = self.ZOOM_BY_VALUE
|
||||
self.globalzoom = zoom
|
||||
self:goto(self.pageno)
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
end
|
||||
|
||||
function UniReader:setRotate(rotate)
|
||||
self.globalrotate = rotate
|
||||
self:goto(self.pageno)
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
|
||||
-- @ orien: 1 for clockwise rotate, -1 for anti-clockwise
|
||||
@@ -705,21 +737,21 @@ function UniReader:screenRotate(orien)
|
||||
Screen:screenRotate(orien)
|
||||
width, height = fb:getSize()
|
||||
self:clearCache()
|
||||
self:goto(self.pageno)
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
|
||||
function UniReader:cleanUpTOCTitle(title)
|
||||
function UniReader:cleanUpTocTitle(title)
|
||||
return title:gsub("\13", "")
|
||||
end
|
||||
|
||||
function UniReader:fillTOC()
|
||||
self.toc = self.doc:getTOC()
|
||||
function UniReader:fillToc()
|
||||
self.toc = self.doc:getToc()
|
||||
end
|
||||
|
||||
function UniReader:getTOCTitleByPage(pageno)
|
||||
function UniReader:getTocTitleByPage(pageno)
|
||||
if not self.toc then
|
||||
-- build toc when needed.
|
||||
self:fillTOC()
|
||||
self:fillToc()
|
||||
end
|
||||
|
||||
-- no table of content
|
||||
@@ -734,32 +766,41 @@ function UniReader:getTOCTitleByPage(pageno)
|
||||
end
|
||||
pre_entry = _v
|
||||
end
|
||||
return self:cleanUpTOCTitle(pre_entry.title)
|
||||
return self:cleanUpTocTitle(pre_entry.title)
|
||||
end
|
||||
|
||||
function UniReader:showTOC()
|
||||
function UniReader:getTocTitleOfCurrentPage()
|
||||
return self:getTocTitleByPage(self.pageno)
|
||||
end
|
||||
|
||||
function UniReader:gotoTocEntry(entry)
|
||||
self:goto(entry.page)
|
||||
end
|
||||
|
||||
function UniReader:showToc()
|
||||
if not self.toc then
|
||||
-- build toc when needed.
|
||||
self:fillTOC()
|
||||
-- build toc if needed.
|
||||
self:fillToc()
|
||||
end
|
||||
local menu_items = {}
|
||||
local filtered_toc = {}
|
||||
|
||||
-- build menu items
|
||||
local menu_items = {}
|
||||
for k,v in ipairs(self.toc) do
|
||||
table.insert(menu_items,
|
||||
(" "):rep(v.depth-1)..self:cleanUpTOCTitle(v.title))
|
||||
table.insert(filtered_toc,v.page)
|
||||
(" "):rep(v.depth-1)..self:cleanUpTocTitle(v.title))
|
||||
end
|
||||
|
||||
toc_menu = SelectMenu:new{
|
||||
menu_title = "Table of Contents",
|
||||
item_array = menu_items,
|
||||
no_item_msg = "This document does not have a Table of Contents.",
|
||||
}
|
||||
item_no = toc_menu:choose(0, fb.bb:getHeight())
|
||||
|
||||
if item_no then
|
||||
self:goto(filtered_toc[item_no])
|
||||
self:gotoTocEntry(self.toc[item_no])
|
||||
else
|
||||
self:goto(self.pageno)
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -779,7 +820,7 @@ function UniReader:showJumpStack()
|
||||
local jump_item = self.jump_stack[item_no]
|
||||
self:goto(jump_item.page)
|
||||
else
|
||||
self:goto(self.pageno)
|
||||
self:redrawCurrentPage()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -806,7 +847,9 @@ function UniReader:showHighLight()
|
||||
end
|
||||
end
|
||||
|
||||
function UniReader:showMenu()
|
||||
-- used in UniReader:showMenu()
|
||||
function UniReader:_drawReadingInfo()
|
||||
local ypos = height - 50
|
||||
local load_percent = (self.pageno / self.doc:getPages())
|
||||
local face, fhash = Font:getFaceAndHash(22)
|
||||
|
||||
@@ -822,7 +865,7 @@ function UniReader:showMenu()
|
||||
local ypos = height - 50
|
||||
fb.bb:paintRect(0, ypos, width, 50, 0)
|
||||
ypos = ypos + 15
|
||||
local cur_section = self:getTOCTitleByPage(self.pageno)
|
||||
local cur_section = self:getTocTitleOfCurrentPage()
|
||||
if cur_section ~= "" then
|
||||
cur_section = "Section: "..cur_section
|
||||
end
|
||||
@@ -833,6 +876,10 @@ function UniReader:showMenu()
|
||||
ypos = ypos + 15
|
||||
blitbuffer.progressBar(fb.bb, 10, ypos, width-20, 15,
|
||||
5, 4, load_percent, 8)
|
||||
end
|
||||
|
||||
function UniReader:showMenu()
|
||||
self:_drawReadingInfo()
|
||||
|
||||
fb:refresh(1)
|
||||
while 1 do
|
||||
@@ -891,13 +938,14 @@ function UniReader:inputLoop()
|
||||
self.doc:close()
|
||||
end
|
||||
if self.settings ~= nil then
|
||||
self.settings:savesetting("last_page", self.pageno)
|
||||
self:saveLastPageOrPos()
|
||||
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:savesetting("highlight", self.highlight)
|
||||
self:saveSpecialSettings()
|
||||
self.settings:close()
|
||||
end
|
||||
|
||||
@@ -1027,12 +1075,12 @@ function UniReader:addAllCommands()
|
||||
"show help page",
|
||||
function(unireader)
|
||||
HelpPage:show(0,height,unireader.commands)
|
||||
unireader:goto(unireader.pageno)
|
||||
unireader:redrawCurrentPage()
|
||||
end)
|
||||
self.commands:add(KEY_T,nil,"T",
|
||||
"show table of content",
|
||||
function(unireader)
|
||||
unireader:showTOC()
|
||||
unireader:showToc()
|
||||
end)
|
||||
self.commands:add(KEY_B,nil,"B",
|
||||
"show jump stack",
|
||||
@@ -1064,18 +1112,6 @@ function UniReader:addAllCommands()
|
||||
function(unireader)
|
||||
unireader:screenRotate("anticlockwise")
|
||||
end)
|
||||
self.commands:add(KEY_N, nil, "N",
|
||||
"start highlight mode",
|
||||
function(unireader)
|
||||
unireader:startHighLightMode()
|
||||
unireader:goto(unireader.pageno)
|
||||
end)
|
||||
self.commands:add(KEY_N, MOD_SHIFT, "N",
|
||||
"display all highlights",
|
||||
function(unireader)
|
||||
unireader:showHighLight()
|
||||
unireader:goto(unireader.pageno)
|
||||
end)
|
||||
self.commands:add(KEY_R, MOD_SHIFT, "R",
|
||||
"manual full screen refresh",
|
||||
function(unireader)
|
||||
@@ -1120,7 +1156,7 @@ function UniReader:addAllCommands()
|
||||
"open menu",
|
||||
function(unireader)
|
||||
unireader:showMenu()
|
||||
unireader:goto(unireader.pageno)
|
||||
unireader:redrawCurrentPage()
|
||||
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)}
|
||||
@@ -1208,7 +1244,7 @@ function UniReader:addAllCommands()
|
||||
end
|
||||
if old_offset_x ~= unireader.offset_x
|
||||
or old_offset_y ~= unireader.offset_y then
|
||||
unireader:goto(unireader.pageno)
|
||||
unireader:redrawCurrentPage()
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -1226,7 +1262,7 @@ function UniReader:addAllCommands()
|
||||
os.execute("sleep 1")
|
||||
os.execute("killall -stop cvm")
|
||||
fb:setOrientation(Screen.kpv_rotation_mode)
|
||||
unireader:goto(unireader.pageno)
|
||||
unireader:redrawCurrentPage()
|
||||
end)
|
||||
print("## defined commands "..dump(self.commands.map))
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user