mirror of https://github.com/koreader/koreader
Merge remote branch 'hwhw/master'
* hwhw/master: (183 commits) show infomessage on document open use InfoMessage for empty TOC, jump history and highlights copy resources dir on customupdate add resource: info icon display document open error message added infomessage dialog implementation bugfix, removed old test constant Added widget abstraction framework added interface to get blitbuffers from JPEG/PNG files fix typo added reading of pan_margin settings fix full screen refresh command, close #99 add: sleep and usleep in util module fix: add back KEY_FW{LEFT,RIGHT} commands to NumInputBox reverted removal of last-doc shortcut, introduced framework restart kill our own child process. not quite finished. added line spacing setting for crereader remove page:getPageText debug dump to improve performance on device remove page:getPageText debug dump to improve performance on device display crash.log on error ... Conflicts: ft.c helppage.lua inputbox.lua rendertext.lua rendertext_example.lua unireader.luapull/2/merge
commit
02dd9b023f
@ -0,0 +1,486 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
|
||||
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(0xFFFFFF);
|
||||
//doc->text_view->setTextColor(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 correct
|
||||
* 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 setFontSize(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
int size = luaL_checkint(L, 2);
|
||||
|
||||
doc->text_view->setFontSize(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setDefaultInterlineSpace(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
int space = luaL_checkint(L, 2);
|
||||
|
||||
doc->text_view->setDefaultInterlineSpace(space);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setStyleSheet(lua_State *L) {
|
||||
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
|
||||
const char* style_sheet_data = luaL_checkstring(L, 2);
|
||||
|
||||
doc->text_view->setStyleSheet(lString8(style_sheet_data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
/* Set DrawBuf to 4bpp */
|
||||
LVGrayDrawBuf drawBuf(w, h, 4);
|
||||
|
||||
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++) {
|
||||
/* When DrawBuf is set to 4bpp mode, CREngine still put every
|
||||
* four bits in one byte, but left the last 4 bits zero*/
|
||||
bbptr[x] = ~(pmptr[x*2] | (pmptr[x*2+1] >> 4));
|
||||
}
|
||||
if(bb->w & 1) {
|
||||
bbptr[x] = 255 - (pmptr[x*2] & 0xF0);
|
||||
}
|
||||
bbptr += bb->pitch;
|
||||
pmptr += w;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int registerFont(lua_State *L) {
|
||||
const char *fontfile = luaL_checkstring(L, 1);
|
||||
if ( !fontMan->RegisterFont(lString8(fontfile)) ) {
|
||||
return luaL_error(L, "cannot register font <%s>", fontfile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg cre_func[] = {
|
||||
{"openDocument", openDocument},
|
||||
{"getFontFaces", getFontFaces},
|
||||
{"getGammaIndex", getGammaIndex},
|
||||
{"setGammaIndex", setGammaIndex},
|
||||
{"registerFont", registerFont},
|
||||
{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},
|
||||
{"setFontSize", setFontSize},
|
||||
{"setDefaultInterlineSpace", setDefaultInterlineSpace},
|
||||
{"setStyleSheet", setStyleSheet},
|
||||
/* --- 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 font manager for CREngine */
|
||||
InitFontManager(lString8());
|
||||
|
||||
#ifdef DEBUG_CRENGINE
|
||||
CRLog::setStdoutLogger();
|
||||
CRLog::setLogLevel(CRLog::LL_DEBUG);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
@ -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
|
@ -0,0 +1,375 @@
|
||||
require "font"
|
||||
require "unireader"
|
||||
require "inputbox"
|
||||
require "selectmenu"
|
||||
|
||||
CREReader = UniReader:new{
|
||||
pos = nil,
|
||||
percent = 0,
|
||||
|
||||
gamma_index = 15,
|
||||
font_face = nil,
|
||||
|
||||
line_space_percent = 100,
|
||||
}
|
||||
|
||||
function CREReader:init()
|
||||
self:addAllCommands()
|
||||
self:adjustCreReaderCommands()
|
||||
-- we need to initialize the CRE font list
|
||||
local fonts = Font:getFontList()
|
||||
for _k, _v in ipairs(fonts) do
|
||||
local ok, err = pcall(cre.registerFont, Font.fontdir..'/'.._v)
|
||||
if not ok then
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
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,
|
||||
G_width, G_height)
|
||||
if not ok then
|
||||
return false, self.doc -- will contain error message
|
||||
end
|
||||
|
||||
self.doc:setDefaultInterlineSpace(self.line_space_percent)
|
||||
|
||||
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)
|
||||
|
||||
local line_space_percent = self.settings:readSetting("line_space_percent")
|
||||
self.line_space_percent = line_space_percent or self.line_space_percent
|
||||
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)
|
||||
self.settings:savesetting("line_space_percent", self.line_space_percent)
|
||||
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
|
||||
|
||||
-- there is no zoom mode in CREReader
|
||||
function CREReader:setGlobalZoomMode()
|
||||
return
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
-- goto related methods
|
||||
----------------------------------------------------
|
||||
function CREReader:goto(pos, pos_type)
|
||||
local prev_xpointer = self.doc:getXPointer()
|
||||
local width, height = G_width, G_height
|
||||
|
||||
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() - height)
|
||||
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)
|
||||
|
||||
print("## self.show_overlap "..self.show_overlap)
|
||||
if self.show_overlap < 0 then
|
||||
fb.bb:dimRect(0,0, width, -self.show_overlap)
|
||||
elseif self.show_overlap > 0 then
|
||||
fb.bb:dimRect(0,height - self.show_overlap, width, self.show_overlap)
|
||||
end
|
||||
self.show_overlap = 0
|
||||
|
||||
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
|
||||
print("------", self.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()
|
||||
self.show_overlap = -self.pan_overlap_vertical
|
||||
return self.pos + G_height - self.pan_overlap_vertical
|
||||
end
|
||||
|
||||
function CREReader:prevView()
|
||||
self.show_overlap = self.pan_overlap_vertical
|
||||
return self.pos - G_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 = G_height - 50
|
||||
local load_percent = self.percent/100
|
||||
|
||||
fb.bb:paintRect(0, ypos, G_width, 50, 0)
|
||||
|
||||
ypos = ypos + 15
|
||||
local face = Font:getFace("rifont", 22)
|
||||
local cur_section = self:getTocTitleOfCurrentPage()
|
||||
if cur_section ~= "" then
|
||||
cur_section = "Section: "..cur_section
|
||||
end
|
||||
renderUtf8Text(fb.bb, 10, ypos+6, face,
|
||||
"Position: "..load_percent.."%".." "..cur_section, true)
|
||||
|
||||
ypos = ypos + 15
|
||||
blitbuffer.progressBar(fb.bb, 10, ypos, G_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, MOD_SHIFT, "J")
|
||||
self.commands:del(KEY_K, MOD_SHIFT, "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")
|
||||
self.commands:del(KEY_N, nil, "N") -- highlight
|
||||
self.commands:del(KEY_N, MOD_SHIFT, "N") -- show highlights
|
||||
|
||||
-- overwrite commands
|
||||
self.commands:add(KEY_PGFWD, MOD_SHIFT, ">",
|
||||
"increase font size",
|
||||
function(cr)
|
||||
cr.doc:zoomFont(1)
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_PGBCK, MOD_SHIFT, "<",
|
||||
"decrease font size",
|
||||
function(cr)
|
||||
cr.doc:zoomFont(-1)
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_PGFWD, MOD_ALT, ">",
|
||||
"increase line spacing",
|
||||
function(cr)
|
||||
self.line_space_percent = self.line_space_percent + 10
|
||||
if self.line_space_percent > 200 then
|
||||
self.line_space_percent = 200
|
||||
end
|
||||
print("line spacing set to", self.line_space_percent)
|
||||
cr.doc:setDefaultInterlineSpace(self.line_space_percent)
|
||||
cr:redrawCurrentPage()
|
||||
end
|
||||
)
|
||||
self.commands:add(KEY_PGBCK, MOD_ALT, "<",
|
||||
"decrease line spacing",
|
||||
function(cr)
|
||||
self.line_space_percent = self.line_space_percent - 10
|
||||
if self.line_space_percent < 100 then
|
||||
self.line_space_percent = 100
|
||||
end
|
||||
print("line spacing set to", self.line_space_percent)
|
||||
cr.doc:setDefaultInterlineSpace(self.line_space_percent)
|
||||
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, G_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
|
@ -0,0 +1,43 @@
|
||||
require "widget"
|
||||
require "font"
|
||||
|
||||
InfoMessage = {
|
||||
face = Font:getFace("infofont", 25)
|
||||
}
|
||||
|
||||
function InfoMessage:show(text)
|
||||
local dialog = CenterContainer:new({
|
||||
dimen = { w = G_width, h = G_height },
|
||||
FrameContainer:new({
|
||||
margin = 2,
|
||||
background = 0,
|
||||
HorizontalGroup:new({
|
||||
align = "center",
|
||||
ImageWidget:new({
|
||||
file = "resources/info-i.png"
|
||||
}),
|
||||
Widget:new({
|
||||
dimen = { w = 10, h = 0 }
|
||||
}),
|
||||
TextWidget:new({
|
||||
text = text,
|
||||
face = Font:getFace("cfont", 30)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
dialog:paintTo(fb.bb, 0, 0)
|
||||
dialog:free()
|
||||
end
|
||||
|
||||
function showInfoMsgWithDelay(text, msec, refresh_mode)
|
||||
if not refresh_mode then refresh_mode = 0 end
|
||||
Screen:saveCurrentBB()
|
||||
|
||||
InfoMessage:show(text)
|
||||
fb:refresh(refresh_mode)
|
||||
util.usleep(msec*1000)
|
||||
|
||||
Screen:restoreFromSavedBB()
|
||||
fb:refresh(refresh_mode)
|
||||
end
|
@ -0,0 +1,25 @@
|
||||
Image = {}
|
||||
|
||||
function Image._getFileData(filename)
|
||||
local f = io.open(filename)
|
||||
local data = f:read("*a")
|
||||
f:close()
|
||||
return data
|
||||
end
|
||||
|
||||
function Image.fromPNG(filename)
|
||||
local img = mupdfimg.new()
|
||||
img:loadPNGData(Image._getFileData(filename))
|
||||
local bb = img:toBlitBuffer()
|
||||
img:free()
|
||||
return bb
|
||||
end
|
||||
|
||||
function Image.fromJPEG(filename)
|
||||
local img = mupdfimg.new()
|
||||
img:loadJPEGData(Image._getFileData(filename)(fimgdatailename))
|
||||
local bb = img:toBlitBuffer()
|
||||
img:free()
|
||||
return bb
|
||||
end
|
||||
|
@ -0,0 +1,57 @@
|
||||
|
||||
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 ${MUPDF_3RDPARTY_DIR}/freetype-2.4.8/include)
|
||||
#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(-DLINUX=1 -D_LINUX=1 -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 not build patched ANTIWORD library, because we haven't supported dictionary lookup yet.")
|
||||
#message("Will build patched ANTIWORD library")
|
||||
ADD_DEFINITIONS(-DENABLE_ANTIWORD=0)
|
||||
#ADD_DEFINITIONS(-DCR3_ANTIWORD_PATCH=1)
|
||||
#ADD_SUBDIRECTORY(${CR_3RDPARTY_DIR}/antiword)
|
||||
|
||||
message("Will build crengine library")
|
||||
SET(GUI kpv)
|
||||
#ADD_DEFINITIONS(-DJCONFIG_INCLUDED=1)
|
||||
ADD_SUBDIRECTORY(crengine/crengine)
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
Subproject commit ba469d33473670ca303e2ef7f9762452a86e18b1
|
@ -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
|
@ -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
|
@ -1,3 +1,7 @@
|
||||
[Actions]
|
||||
P P = !/mnt/us/launchpad/kpdf.sh
|
||||
# start kindlepdfviewer with filebrowser in /mnt/us/documents
|
||||
P D = !/mnt/us/launchpad/kpdf.sh /mnt/us/documents
|
||||
# start kindlepdfviewer with last document
|
||||
P P = !/mnt/us/launchpad/kpdf.sh
|
||||
# restart amazon framework - when it got irritated
|
||||
P R = !/etc/init.d/framework restart
|
||||
|
@ -0,0 +1,171 @@
|
||||
diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c
|
||||
index 5e54e0b..38bd1d8 100644
|
||||
--- a/pdf/pdf_font.c
|
||||
+++ b/pdf/pdf_font.c
|
||||
@@ -182,8 +182,13 @@ pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname)
|
||||
if (!data)
|
||||
fz_throw(ctx, "cannot find builtin font: '%s'", fontname);
|
||||
|
||||
+#ifndef NOBUILTINFONT
|
||||
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0, 1);
|
||||
/* RJW: "cannot load freetype font from memory" */
|
||||
+#else
|
||||
+ fontdesc->font = fz_new_font_from_file(ctx, data, 0, 1);
|
||||
+ free(data);
|
||||
+#endif
|
||||
|
||||
if (!strcmp(fontname, "Symbol") || !strcmp(fontname, "ZapfDingbats"))
|
||||
fontdesc->flags |= PDF_FD_SYMBOLIC;
|
||||
@@ -199,8 +204,13 @@ pdf_load_substitute_font(fz_context *ctx, pdf_font_desc *fontdesc, int mono, int
|
||||
if (!data)
|
||||
fz_throw(ctx, "cannot find substitute font");
|
||||
|
||||
+#ifndef NOBUILTINFONT
|
||||
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0, 1);
|
||||
/* RJW: "cannot load freetype font from memory" */
|
||||
+#else
|
||||
+ fontdesc->font = fz_new_font_from_file(ctx, data, 0, 1);
|
||||
+ free(data);
|
||||
+#endif
|
||||
|
||||
fontdesc->font->ft_substitute = 1;
|
||||
fontdesc->font->ft_bold = bold && !ft_is_bold(fontdesc->font->ft_face);
|
||||
@@ -218,7 +228,12 @@ pdf_load_substitute_cjk_font(fz_context *ctx, pdf_font_desc *fontdesc, int ros,
|
||||
fz_throw(ctx, "cannot find builtin CJK font");
|
||||
|
||||
/* a glyph bbox cache is too big for droid sans fallback (51k glyphs!) */
|
||||
+#ifndef NOBUILTINFONT
|
||||
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0, 0);
|
||||
+#else
|
||||
+ fontdesc->font = fz_new_font_from_file(ctx, data, 0, 0);
|
||||
+ free(data);
|
||||
+#endif
|
||||
/* RJW: "cannot load builtin CJK font" */
|
||||
|
||||
fontdesc->font->ft_substitute = 1;
|
||||
diff --git a/pdf/pdf_fontfile.c b/pdf/pdf_fontfile.c
|
||||
index 543ce76..a076033 100644
|
||||
--- a/pdf/pdf_fontfile.c
|
||||
+++ b/pdf/pdf_fontfile.c
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "fitz.h"
|
||||
#include "mupdf.h"
|
||||
|
||||
+#ifndef NOBUILTINFONT
|
||||
+
|
||||
#ifdef NOCJK
|
||||
#define NOCJKFONT
|
||||
#endif
|
||||
@@ -129,3 +131,112 @@ pdf_find_substitute_cjk_font(int ros, int serif, unsigned int *len)
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
+
|
||||
+#else // NOBUILTINFONT
|
||||
+
|
||||
+unsigned char *
|
||||
+get_font_file(char *name)
|
||||
+{
|
||||
+ char *fontdir;
|
||||
+ char *filename;
|
||||
+ int len;
|
||||
+ fontdir = getenv("FONTDIR");
|
||||
+ if(fontdir == NULL) {
|
||||
+ fontdir = "./fonts";
|
||||
+ }
|
||||
+ len = strlen(fontdir) + strlen(name) + 2;
|
||||
+ filename = malloc(len);
|
||||
+ if(filename == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ snprintf(filename, len, "%s/%s", fontdir, name);
|
||||
+ return filename;
|
||||
+}
|
||||
+
|
||||
+unsigned char *
|
||||
+pdf_find_builtin_font(char *name, unsigned int *len)
|
||||
+{
|
||||
+ *len = 0;
|
||||
+ if (!strcmp("Courier", name)) {
|
||||
+ return get_font_file("NimbusMonL-Regu.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Courier-Bold", name)) {
|
||||
+ return get_font_file("NimbusMonL-Bold.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Courier-Oblique", name)) {
|
||||
+ return get_font_file("NimbusMonL-ReguObli.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Courier-BoldOblique", name)) {
|
||||
+ return get_font_file("NimbusMonL-BoldObli.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Helvetica", name)) {
|
||||
+ return get_font_file("NimbusSanL-Regu.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Helvetica-Bold", name)) {
|
||||
+ return get_font_file("NimbusSanL-Bold.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Helvetica-Oblique", name)) {
|
||||
+ return get_font_file("NimbusSanL-ReguItal.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Helvetica-BoldOblique", name)) {
|
||||
+ return get_font_file("NimbusSanL-BoldItal.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Times-Roman", name)) {
|
||||
+ return get_font_file("NimbusRomNo9L-Regu.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Times-Bold", name)) {
|
||||
+ return get_font_file("NimbusRomNo9L-Medi.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Times-Italic", name)) {
|
||||
+ return get_font_file("NimbusRomNo9L-ReguItal.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Times-BoldItalic", name)) {
|
||||
+ return get_font_file("NimbusRomNo9L-MediItal.cff");
|
||||
+ }
|
||||
+ if (!strcmp("Symbol", name)) {
|
||||
+ return get_font_file("StandardSymL.cff");
|
||||
+ }
|
||||
+ if (!strcmp("ZapfDingbats", name)) {
|
||||
+ return get_font_file("Dingbats.cff");
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+unsigned char *
|
||||
+pdf_find_substitute_font(int mono, int serif, int bold, int italic, unsigned int *len)
|
||||
+{
|
||||
+ if (mono) {
|
||||
+ if (bold) {
|
||||
+ if (italic) return pdf_find_builtin_font("Courier-BoldOblique", len);
|
||||
+ else return pdf_find_builtin_font("Courier-Bold", len);
|
||||
+ } else {
|
||||
+ if (italic) return pdf_find_builtin_font("Courier-Oblique", len);
|
||||
+ else return pdf_find_builtin_font("Courier", len);
|
||||
+ }
|
||||
+ } else if (serif) {
|
||||
+ if (bold) {
|
||||
+ if (italic) return pdf_find_builtin_font("Times-BoldItalic", len);
|
||||
+ else return pdf_find_builtin_font("Times-Bold", len);
|
||||
+ } else {
|
||||
+ if (italic) return pdf_find_builtin_font("Times-Italic", len);
|
||||
+ else return pdf_find_builtin_font("Times-Roman", len);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (bold) {
|
||||
+ if (italic) return pdf_find_builtin_font("Helvetica-BoldOblique", len);
|
||||
+ else return pdf_find_builtin_font("Helvetica-Bold", len);
|
||||
+ } else {
|
||||
+ if (italic) return pdf_find_builtin_font("Helvetica-Oblique", len);
|
||||
+ else return pdf_find_builtin_font("Helvetica", len);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+unsigned char *
|
||||
+pdf_find_substitute_cjk_font(int ros, int serif, unsigned int *len)
|
||||
+{
|
||||
+ *len = 0;
|
||||
+ return get_font_file("droid/DroidSansFallback.ttf");
|
||||
+}
|
||||
+
|
||||
+#endif // NOBUILTINFONT
|
@ -0,0 +1,154 @@
|
||||
/*
|
||||
KindlePDFViewer: MuPDF abstraction for Lua, only image part
|
||||
Copyright (C) 2012 Hans-Werner Hilse <hilse@web.de>
|
||||
|
||||
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/>.
|
||||
*/
|
||||
#include <fitz/fitz.h>
|
||||
|
||||
#include "blitbuffer.h"
|
||||
#include "mupdfimg.h"
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
typedef struct Image {
|
||||
fz_pixmap *pixmap;
|
||||
fz_context *context;
|
||||
} Image;
|
||||
|
||||
static int newImage(lua_State *L) {
|
||||
int cache_size = luaL_optint(L, 1, 8 << 20); // 8 MB limit default
|
||||
|
||||
Image *img = (Image*) lua_newuserdata(L, sizeof(Image));
|
||||
|
||||
img->pixmap = NULL;
|
||||
|
||||
luaL_getmetatable(L, "image");
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
img->context = fz_new_context(NULL, NULL, cache_size);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int loadPNGData(lua_State *L) {
|
||||
Image *img = (Image*) luaL_checkudata(L, 1, "image");
|
||||
size_t length;
|
||||
unsigned char *data = luaL_checklstring(L, 2, &length);
|
||||
fz_try(img->context) {
|
||||
img->pixmap = fz_load_png(img->context, data, length);
|
||||
}
|
||||
fz_catch(img->context) {
|
||||
return luaL_error(L, "cannot load PNG data");
|
||||
}
|
||||
}
|
||||
|
||||
static int loadJPEGData(lua_State *L) {
|
||||
Image *img = (Image*) luaL_checkudata(L, 1, "image");
|
||||
size_t length;
|
||||
unsigned char *data = luaL_checklstring(L, 2, &length);
|
||||
fz_try(img->context) {
|
||||
img->pixmap = fz_load_jpeg(img->context, data, length);
|
||||
}
|
||||
fz_catch(img->context) {
|
||||
return luaL_error(L, "cannot open JPEG data");
|
||||
}
|
||||
}
|
||||
|
||||
static int toBlitBuffer(lua_State *L) {
|
||||
Image *img = (Image*) luaL_checkudata(L, 1, "image");
|
||||
BlitBuffer *bb;
|
||||
int ret;
|
||||
int w, h;
|
||||
|
||||
fz_pixmap *pix;
|
||||
|
||||
if(img->pixmap == NULL) {
|
||||
return luaL_error(L, "no pixmap loaded that we could convert");
|
||||
}
|
||||
|
||||
if(img->pixmap->n == 2) {
|
||||
pix = img->pixmap;
|
||||
} else {
|
||||
fz_try(img->context) {
|
||||
pix = fz_new_pixmap(img->context, fz_device_gray, img->pixmap->w, img->pixmap->h);
|
||||
}
|
||||
fz_catch(img->context) {
|
||||
return luaL_error(L, "can't claim new grayscale fz_pixmap");
|
||||
}
|
||||
fz_convert_pixmap(img->context, img->pixmap, pix);
|
||||
}
|
||||
|
||||
ret = newBlitBufferNative(L, img->pixmap->w, img->pixmap->h, &bb);
|
||||
if(ret != 1) {
|
||||
// TODO (?): fail more gracefully, clean up mem?
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t *bbptr = (uint8_t*)bb->data;
|
||||
uint16_t *pmptr = (uint16_t*)pix->samples;
|
||||
int x, y;
|
||||
|
||||
for(y = 0; y < bb->h; y++) {
|
||||
for(x = 0; x < (bb->w / 2); x++) {
|
||||
bbptr[x] = (((pmptr[x*2 + 1] & 0xF0) >> 4) | (pmptr[x*2] & 0xF0)) ^ 0xFF;
|
||||
}
|
||||
if(bb->w & 1) {
|
||||
bbptr[x] = (pmptr[x*2] & 0xF0) ^ 0xF0;
|
||||
}
|
||||
bbptr += bb->pitch;
|
||||
pmptr += bb->w;
|
||||
}
|
||||
|
||||
if(pix != img->pixmap) {
|
||||
fz_drop_pixmap(img->context, pix);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int freeImage(lua_State *L) {
|
||||
Image *img = (Image*) luaL_checkudata(L, 1, "image");
|
||||
if(img->pixmap) {
|
||||
fz_drop_pixmap(img->context, img->pixmap);
|
||||
}
|
||||
fz_free_context(img->context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg mupdfimg_func[] = {
|
||||
{"new", newImage},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const struct luaL_Reg image_meth[] = {
|
||||
{"loadPNGData", loadPNGData},
|
||||
{"loadJPEGData", loadJPEGData},
|
||||
{"toBlitBuffer", toBlitBuffer},
|
||||
{"free", freeImage},
|
||||
{"__gc", freeImage},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
int luaopen_mupdfimg(lua_State *L) {
|
||||
luaL_newmetatable(L, "image");
|
||||
lua_pushstring(L, "__index");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, -3);
|
||||
luaL_register(L, NULL, image_meth);
|
||||
lua_pop(L, 1);
|
||||
luaL_register(L, "mupdfimg", mupdfimg_func);
|
||||
return 1;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
KindlePDFViewer: MuPDF abstraction for Lua, only image part
|
||||
Copyright (C) 2012 Hans-Werner Hilse <hilse@web.de>
|
||||
|
||||
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 _MUPDFIMG_H
|
||||
#define _MUPDFIMG_H
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
int luaopen_mupdfimg(lua_State *L);
|
||||
#endif
|
@ -1,36 +0,0 @@
|
||||
#!./kpdfview
|
||||
require "rendertext"
|
||||
require "graphics"
|
||||
|
||||
fb = einkfb.open("/dev/fb0")
|
||||
width, height = fb:getSize()
|
||||
|
||||
print("open")
|
||||
size = 50
|
||||
--face = freetype.newBuiltinFace("sans", 64)
|
||||
face = freetype.newFace("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", size)
|
||||
print("got face")
|
||||
|
||||
if face:hasKerning() then
|
||||
print("has kerning")
|
||||
end
|
||||
|
||||
width, height = fb:getSize()
|
||||
fb.bb:paintRect(5,5,width-5,height-5,4);
|
||||
|
||||
faceHeight, faceAscender = face:getHeightAndAscender();
|
||||
print("face height:"..tostring(faceHeight).." - ascender:"..faceAscender)
|
||||
faceHeight = math.ceil(faceHeight)
|
||||
faceAscender = math.ceil(faceAscender)
|
||||
print("face height:"..tostring(faceHeight).." - ascender:"..faceAscender)
|
||||
|
||||
posY = 5 + faceAscender
|
||||
renderUtf8Text(fb.bb, 5, posY, face, "h", "AV T.T: gxyt!", true)
|
||||
posY = posY + faceHeight
|
||||
renderUtf8Text(fb.bb, 5, posY, face, "h2", "AV T.T: gxyt!", false)
|
||||
|
||||
fb:refresh()
|
||||
|
||||
while true do
|
||||
local ev = input.waitForEvent()
|
||||
end
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,87 @@
|
||||
/*
|
||||
KindlePDFViewer: power slider key event watcher
|
||||
Copyright (C) 2012 Qingping Hou <dave2008713@gamil.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/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define OUTPUT_SIZE 21
|
||||
#define EVENT_PIPE "/tmp/event_slider"
|
||||
#define CODE_IN_SAVER 10000
|
||||
#define CODE_OUT_SAVER 10001
|
||||
|
||||
int
|
||||
main ( int argc, char *argv[] )
|
||||
{
|
||||
int fd, ret;
|
||||
FILE *fp;
|
||||
char std_out[OUTPUT_SIZE] = "";
|
||||
struct input_event ev;
|
||||
__u16 key_code = 10000;
|
||||
|
||||
/* create the npipe if not exists */
|
||||
/*if(access(argv[1], F_OK)){*/
|
||||
/*printf("npipe %s not found, try to create it...\n", argv[1]);*/
|
||||
/*if(mkfifo(argv[1], 0777)) {*/
|
||||
/*printf("Create npipe %s failed!\n", argv[1]);*/
|
||||
/*}*/
|
||||
/*}*/
|
||||
|
||||
/* open npipe for writing */
|
||||
fd = open(argv[1], O_RDWR | O_NONBLOCK);
|
||||
if(fd < 0) {
|
||||
printf("Open %s falied: %s\n", argv[1], strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* initialize event struct */
|
||||
ev.type = EV_KEY;
|
||||
ev.code = key_code;
|
||||
ev.value = 1;
|
||||
|
||||
while(1) {
|
||||
/* listen power slider events */
|
||||
memset(std_out, 0, OUTPUT_SIZE);
|
||||
fp = popen("lipc-wait-event -s 0 com.lab126.powerd goingToScreenSaver,outOfScreenSaver", "r");
|
||||
ret = fread(std_out, OUTPUT_SIZE, 1, fp);
|
||||
pclose(fp);
|
||||
|
||||
/* fill event struct */
|
||||
gettimeofday(&ev.time, NULL);
|
||||
if(std_out[0] == 'g') {
|
||||
ev.code = CODE_IN_SAVER;
|
||||
} else if(std_out[0] == 'o') {
|
||||
ev.code = CODE_OUT_SAVER;
|
||||
} else {
|
||||
printf("Unrecognized event.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* generate event */
|
||||
ret = write(fd, &ev, sizeof(struct input_event));
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,263 @@
|
||||
require "rendertext"
|
||||
require "graphics"
|
||||
require "image"
|
||||
|
||||
--[[
|
||||
This is a (useless) generic Widget interface
|
||||
|
||||
widgets can be queried about their size and can be paint.
|
||||
that's it for now. Probably we need something more elaborate
|
||||
later.
|
||||
]]
|
||||
Widget = {
|
||||
dimen = { w = 0, h = 0},
|
||||
}
|
||||
|
||||
function Widget:new(o)
|
||||
o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
function Widget:getSize()
|
||||
return self.dimen
|
||||
end
|
||||
|
||||
function Widget:paintTo(bb, x, y)
|
||||
end
|
||||
|
||||
function Widget:free()
|
||||
end
|
||||
|
||||
--[[
|
||||
WidgetContainer is a container for another Widget
|
||||
]]
|
||||
WidgetContainer = Widget:new()
|
||||
|
||||
function WidgetContainer:free()
|
||||
for _, widget in ipairs(self) do
|
||||
widget:free()
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
CenterContainer centers its content (1 widget) within its own dimensions
|
||||
]]
|
||||
CenterContainer = WidgetContainer:new()
|
||||
|
||||
function CenterContainer:paintTo(bb, x, y)
|
||||
local contentSize = self[1]:getSize()
|
||||
if contentSize.w > self.dimen.w or contentSize.h > self.dimen.h then
|
||||
-- throw error?
|
||||
return
|
||||
end
|
||||
self[1]:paintTo(bb,
|
||||
x + (self.dimen.w - contentSize.w)/2,
|
||||
y + (self.dimen.h - contentSize.h)/2)
|
||||
end
|
||||
|
||||
--[[
|
||||
A FrameContainer is some graphics content (1 widget) that is surrounded by a frame
|
||||
]]
|
||||
FrameContainer = WidgetContainer:new({
|
||||
background = nil,
|
||||
color = 15,
|
||||
margin = 0,
|
||||
bordersize = 2,
|
||||
padding = 5,
|
||||
})
|
||||
|
||||
function FrameContainer:getSize()
|
||||
local content_size = self[1]:getSize()
|
||||
return {
|
||||
w = content_size.w + ( self.margin + self.bordersize + self.padding ) * 2,
|
||||
h = content_size.h + ( self.margin + self.bordersize + self.padding ) * 2
|
||||
}
|
||||
end
|
||||
|
||||
function FrameContainer:paintTo(bb, x, y)
|
||||
local my_size = self:getSize()
|
||||
|
||||
if self.background then
|
||||
bb:paintRect(x, y, my_size.w, my_size.h, self.background)
|
||||
end
|
||||
if self.bordersize > 0 then
|
||||
bb:paintBorder(x + self.margin, y + self.margin,
|
||||
my_size.w - self.margin * 2, my_size.h - self.margin * 2,
|
||||
self.bordersize, self.color)
|
||||
end
|
||||
self[1]:paintTo(bb,
|
||||
x + self.margin + self.bordersize + self.padding,
|
||||
y + self.margin + self.bordersize + self.padding)
|
||||
end
|
||||
|
||||
--[[
|
||||
A TextWidget puts a string on a single line
|
||||
]]
|
||||
TextWidget = Widget:new({
|
||||
text = nil,
|
||||
face = nil,
|
||||
color = 15,
|
||||
_bb = nil,
|
||||
_length = 0,
|
||||
_maxlength = 1200,
|
||||
})
|
||||
|
||||
function TextWidget:_render()
|
||||
local h = self.face.size * 1.5
|
||||
self._bb = Blitbuffer.new(self._maxlength, h)
|
||||
self._length = renderUtf8Text(self._bb, 0, h*.7, self.face, self.text, self.color)
|
||||
end
|
||||
|
||||
function TextWidget:getSize()
|
||||
if not self._bb then
|
||||
self:_render()
|
||||
end
|
||||
return { w = self._length, h = self._bb:getHeight() }
|
||||
end
|
||||
|
||||
function TextWidget:paintTo(bb, x, y)
|
||||
if not self._bb then
|
||||
self:_render()
|
||||
end
|
||||
bb:blitFrom(self._bb, x, y, 0, 0, self._length, self._bb:getHeight())
|
||||
end
|
||||
|
||||
function TextWidget:free()
|
||||
if self._bb then
|
||||
self._bb:free()
|
||||
self._bb = nil
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
ImageWidget shows an image from a file
|
||||
]]
|
||||
ImageWidget = Widget:new({
|
||||
file = nil,
|
||||
_bb = nil
|
||||
})
|
||||
|
||||
function ImageWidget:_render()
|
||||
local itype = string.lower(string.match(self.file, ".+%.([^.]+)") or "")
|
||||
if itype == "jpeg" or itype == "jpg" then
|
||||
self._bb = Image.fromJPEG(self.file)
|
||||
elseif itype == "png" then
|
||||
self._bb = Image.fromPNG(self.file)
|
||||
end
|
||||
end
|
||||
|
||||
function ImageWidget:getSize()
|
||||
if not self._bb then
|
||||
self:_render()
|
||||
end
|
||||
return { w = self._bb:getWidth(), h = self._bb:getHeight() }
|
||||
end
|
||||
|
||||
function ImageWidget:paintTo(bb, x, y)
|
||||
local size = self:getSize()
|
||||
bb:blitFrom(self._bb, x, y, 0, 0, size.w, size.h)
|
||||
end
|
||||
|
||||
function ImageWidget:free()
|
||||
if self._bb then
|
||||
self._bb:free()
|
||||
self._bb = nil
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
A Layout widget that puts objects besides each others
|
||||
]]
|
||||
HorizontalGroup = WidgetContainer:new({
|
||||
align = "center",
|
||||
_size = nil,
|
||||
})
|
||||
|
||||
function HorizontalGroup:getSize()
|
||||
if not self._size then
|
||||
self._size = { w = 0, h = 0 }
|
||||
self._offsets = { }
|
||||
for i, widget in ipairs(self) do
|
||||
local w_size = widget:getSize()
|
||||
self._offsets[i] = {
|
||||
x = self._size.w,
|
||||
y = w_size.h
|
||||
}
|
||||
self._size.w = self._size.w + w_size.w
|
||||
if w_size.h > self._size.h then
|
||||
self._size.h = w_size.h
|
||||
end
|
||||
end
|
||||
end
|
||||
return self._size
|
||||
end
|
||||
|
||||
function HorizontalGroup:paintTo(bb, x, y)
|
||||
local size = self:getSize()
|
||||
|
||||
for i, widget in ipairs(self) do
|
||||
if self.align == "center" then
|
||||
widget:paintTo(bb, x + self._offsets[i].x, y + (size.h - self._offsets[i].y) / 2)
|
||||
elseif self.align == "top" then
|
||||
widget:paintTo(bb, x + self._offsets[i].x, y)
|
||||
elseif self.align == "bottom" then
|
||||
widget:paintTo(bb, x + self._offsets[i].x, y + size.h - self._offsets[i].y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function HorizontalGroup:free()
|
||||
self._size = nil
|
||||
self._offsets = {}
|
||||
WidgetContainer.free(self)
|
||||
end
|
||||
|
||||
--[[
|
||||
A Layout widget that puts objects under each other
|
||||
]]
|
||||
VerticalGroup = WidgetContainer:new({
|
||||
align = "center",
|
||||
_size = nil,
|
||||
_offsets = {}
|
||||
})
|
||||
|
||||
function VerticalGroup:getSize()
|
||||
if not self._size then
|
||||
self._size = { w = 0, h = 0 }
|
||||
self._offsets = { }
|
||||
for i, widget in ipairs(self) do
|
||||
local w_size = widget:getSize()
|
||||
self._offsets[i] = {
|
||||
x = w_size.w,
|
||||
y = self._size.h,
|
||||
}
|
||||
self._size.h = self._size.h + w_size.h
|
||||
if w_size.w > self._size.w then
|
||||
self._size.w = w_size.w
|
||||
end
|
||||
end
|
||||
end
|
||||
return self._size
|
||||
end
|
||||
|
||||
function VerticalGroup:paintTo(bb, x, y)
|
||||
local size = self:getSize()
|
||||
|
||||
for i, widget in ipairs(self) do
|
||||
if self.align == "center" then
|
||||
widget:paintTo(bb, x + (size.w - self._offsets[i].x) / 2, y + self._offsets[i].y)
|
||||
elseif self.align == "left" then
|
||||
widget:paintTo(bb, x, y + self._offsets[i].y)
|
||||
elseif self.align == "right" then
|
||||
widget:paintTo(bb, x + size.w - self._offsets[i].x, y + self._offsets[i].y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VerticalGroup:free()
|
||||
self._size = nil
|
||||
self._offsets = {}
|
||||
WidgetContainer.free(self)
|
||||
end
|
Loading…
Reference in New Issue