mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #407 from houqp/new_ui_code
some of my fixes & merge lates changes from master branch
This commit is contained in:
6
Makefile
6
Makefile
@@ -109,7 +109,9 @@ POPENNSLIB := $(POPENNSDIR)/libpopen_noshell.a
|
||||
|
||||
all: kpdfview
|
||||
|
||||
VERSION?=$(shell git describe HEAD)
|
||||
kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o $(POPENNSLIB) util.o ft.o lfs.o mupdfimg.o $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) djvu.o $(DJVULIBS) cre.o $(CRENGINELIBS)
|
||||
echo $(VERSION) > git-rev
|
||||
$(CC) \
|
||||
$(CFLAGS) \
|
||||
kpdfview.o \
|
||||
@@ -250,7 +252,6 @@ INSTALL_DIR=kindlepdfviewer
|
||||
|
||||
LUA_FILES=reader.lua
|
||||
|
||||
VERSION?=$(shell git describe HEAD)
|
||||
customupdate: all
|
||||
# ensure that build binary is for ARM
|
||||
file kpdfview | grep ARM || exit 1
|
||||
@@ -258,12 +259,11 @@ customupdate: all
|
||||
rm -f kindlepdfviewer-$(VERSION).zip
|
||||
rm -rf $(INSTALL_DIR)
|
||||
mkdir -p $(INSTALL_DIR)/{history,screenshots}
|
||||
echo $(VERSION) > $(INSTALL_DIR)/git-rev
|
||||
cp -p README.md COPYING kpdfview kpdf.sh $(LUA_FILES) $(INSTALL_DIR)
|
||||
mkdir $(INSTALL_DIR)/data
|
||||
cp -rpL data/*.css $(INSTALL_DIR)/data
|
||||
cp -rpL fonts $(INSTALL_DIR)
|
||||
cp -r resources $(INSTALL_DIR)
|
||||
cp -r git-rev resources $(INSTALL_DIR)
|
||||
cp -rpL frontend $(INSTALL_DIR)
|
||||
mkdir $(INSTALL_DIR)/fonts/host
|
||||
zip -9 -r kindlepdfviewer-$(VERSION).zip $(INSTALL_DIR) launchpad/ kite/
|
||||
|
||||
@@ -26,7 +26,7 @@ Follow these steps:
|
||||
* install popen_noshell sources into subfolder "popen-noshell"
|
||||
|
||||
* automatically fetch thirdparty sources with Makefile:
|
||||
* make sure you have wget, unzip, git and svn installed
|
||||
* make sure you have patch, wget, unzip, git and svn installed
|
||||
* run `make fetchthirdparty`.
|
||||
|
||||
* adapt Makefile to your needs
|
||||
|
||||
2
cre.cpp
2
cre.cpp
@@ -575,7 +575,7 @@ int luaopen_cre(lua_State *L) {
|
||||
/* initialize font manager for CREngine */
|
||||
InitFontManager(lString8());
|
||||
|
||||
#ifdef DEBUG_CRENGINE
|
||||
#if DEBUG_CRENGINE
|
||||
CRLog::setStdoutLogger();
|
||||
CRLog::setLogLevel(CRLog::LL_DEBUG);
|
||||
#endif
|
||||
|
||||
108
djvu.c
108
djvu.c
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <libdjvu/miniexp.h>
|
||||
#include <libdjvu/ddjvuapi.h>
|
||||
|
||||
@@ -85,11 +86,10 @@ static int openDocument(lua_State *L) {
|
||||
ddjvu_cache_set_size(doc->context, (unsigned long)cache_size);
|
||||
|
||||
doc->doc_ref = ddjvu_document_create_by_filename_utf8(doc->context, filename, TRUE);
|
||||
if (! doc->doc_ref)
|
||||
return luaL_error(L, "cannot open DjVu file <%s>", filename);
|
||||
while (! ddjvu_document_decoding_done(doc->doc_ref))
|
||||
handle(L, doc->context, True);
|
||||
if (! doc->doc_ref) {
|
||||
return luaL_error(L, "cannot open DjVu file <%s>", filename);
|
||||
}
|
||||
|
||||
doc->pixelformat = ddjvu_format_create(DDJVU_FORMAT_GREY8, 0, NULL);
|
||||
if (! doc->pixelformat) {
|
||||
@@ -135,17 +135,28 @@ static int walkTableOfContent(lua_State *L, miniexp_t r, int *count, int depth)
|
||||
|
||||
int length = miniexp_length(r);
|
||||
int counter = 0;
|
||||
char page_number[6];
|
||||
const char* page_name;
|
||||
int page_number;
|
||||
|
||||
while(counter < length-1) {
|
||||
lua_pushnumber(L, *count);
|
||||
lua_newtable(L);
|
||||
|
||||
lua_pushstring(L, "page");
|
||||
strcpy(page_number,miniexp_to_str(miniexp_car(miniexp_cdr(miniexp_nth(counter, lista)))));
|
||||
/* page numbers appear as #11, set # to 0 so strtol works */
|
||||
page_number[0]= '0';
|
||||
lua_pushnumber(L, strtol(page_number, NULL, 10));
|
||||
page_name = miniexp_to_str(miniexp_car(miniexp_cdr(miniexp_nth(counter, lista))));
|
||||
if(page_name != NULL && page_name[0] == '#') {
|
||||
errno = 0;
|
||||
page_number = strtol(page_name + 1, NULL, 10);
|
||||
if(!errno) {
|
||||
lua_pushnumber(L, page_number);
|
||||
} else {
|
||||
/* we can not parse this as a number, TODO: parse page names */
|
||||
lua_pushnumber(L, -1);
|
||||
}
|
||||
} else {
|
||||
/* something we did not expect here */
|
||||
lua_pushnumber(L, -1);
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "depth");
|
||||
@@ -199,11 +210,10 @@ static int openPage(lua_State *L) {
|
||||
|
||||
/* djvulibre counts page starts from 0 */
|
||||
page->page_ref = ddjvu_page_create_by_pageno(doc->doc_ref, pageno - 1);
|
||||
if (! page->page_ref)
|
||||
return luaL_error(L, "cannot open page #%d", pageno);
|
||||
while (! ddjvu_page_decoding_done(page->page_ref))
|
||||
handle(L, doc->context, TRUE);
|
||||
if (! page->page_ref) {
|
||||
return luaL_error(L, "cannot open page #%d", pageno);
|
||||
}
|
||||
|
||||
page->doc = doc;
|
||||
page->num = pageno;
|
||||
@@ -231,13 +241,10 @@ static int getPageSize(lua_State *L) {
|
||||
|
||||
/* unsupported so fake it */
|
||||
static int getUsedBBox(lua_State *L) {
|
||||
DjvuPage *page = (DjvuPage*) luaL_checkudata(L, 1, "djvupage");
|
||||
|
||||
lua_pushnumber(L, (double)0.01);
|
||||
lua_pushnumber(L, (double)0.01);
|
||||
lua_pushnumber(L, (double)-0.01);
|
||||
lua_pushnumber(L, (double)-0.01);
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
@@ -259,6 +266,63 @@ static int getOriginalPageSize(lua_State *L) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int getPageInfo(lua_State *L) {
|
||||
DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument");
|
||||
int pageno = luaL_checkint(L, 2);
|
||||
ddjvu_page_t *djvu_page;
|
||||
int page_width, page_height, page_dpi;
|
||||
double page_gamma;
|
||||
ddjvu_page_type_t page_type;
|
||||
char *page_type_str;
|
||||
|
||||
djvu_page = ddjvu_page_create_by_pageno(doc->doc_ref, pageno - 1);
|
||||
if (! djvu_page)
|
||||
return luaL_error(L, "cannot create djvu_page #%d", pageno);
|
||||
|
||||
while (! ddjvu_page_decoding_done(djvu_page))
|
||||
handle(L, doc->context, TRUE);
|
||||
|
||||
page_width = ddjvu_page_get_width(djvu_page);
|
||||
lua_pushnumber(L, page_width);
|
||||
|
||||
page_height = ddjvu_page_get_height(djvu_page);
|
||||
lua_pushnumber(L, page_height);
|
||||
|
||||
page_dpi = ddjvu_page_get_resolution(djvu_page);
|
||||
lua_pushnumber(L, page_dpi);
|
||||
|
||||
page_gamma = ddjvu_page_get_gamma(djvu_page);
|
||||
lua_pushnumber(L, page_gamma);
|
||||
|
||||
page_type = ddjvu_page_get_type(djvu_page);
|
||||
switch (page_type) {
|
||||
case DDJVU_PAGETYPE_UNKNOWN:
|
||||
page_type_str = "UNKNOWN";
|
||||
break;
|
||||
|
||||
case DDJVU_PAGETYPE_BITONAL:
|
||||
page_type_str = "BITONAL";
|
||||
break;
|
||||
|
||||
case DDJVU_PAGETYPE_PHOTO:
|
||||
page_type_str = "PHOTO";
|
||||
break;
|
||||
|
||||
case DDJVU_PAGETYPE_COMPOUND:
|
||||
page_type_str = "COMPOUND";
|
||||
break;
|
||||
|
||||
default:
|
||||
page_type_str = "INVALID";
|
||||
break;
|
||||
}
|
||||
lua_pushstring(L, page_type_str);
|
||||
|
||||
ddjvu_page_release(djvu_page);
|
||||
|
||||
return 5;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a table like following:
|
||||
* {
|
||||
@@ -424,13 +488,11 @@ static int drawPage(lua_State *L) {
|
||||
unsigned char adjusted_low[16], adjusted_high[16];
|
||||
int i, adjust_pixels = 0;
|
||||
ddjvu_rect_t pagerect, renderrect;
|
||||
uint8_t *imagebuffer = malloc((bb->w)*(bb->h)+1);
|
||||
int bbsize = (bb->w)*(bb->h)+1;
|
||||
uint8_t *imagebuffer = malloc(bbsize);
|
||||
|
||||
/*printf("@page %d, @@zoom:%f, offset: (%d, %d)\n", page->num, dc->zoom, dc->offset_x, dc->offset_y);*/
|
||||
|
||||
/* fill pixel map with white color */
|
||||
memset(imagebuffer, 0xFF, (bb->w)*(bb->h)+1);
|
||||
|
||||
/* render full page into rectangle specified by pagerect */
|
||||
pagerect.x = 0;
|
||||
pagerect.y = 0;
|
||||
@@ -461,13 +523,8 @@ static int drawPage(lua_State *L) {
|
||||
* So we don't set rotation here.
|
||||
*/
|
||||
|
||||
ddjvu_page_render(page->page_ref,
|
||||
djvu_render_mode,
|
||||
&pagerect,
|
||||
&renderrect,
|
||||
page->doc->pixelformat,
|
||||
bb->w,
|
||||
imagebuffer);
|
||||
if (!ddjvu_page_render(page->page_ref, djvu_render_mode, &pagerect, &renderrect, page->doc->pixelformat, bb->w, imagebuffer))
|
||||
memset(imagebuffer, 0xFF, bbsize);
|
||||
|
||||
uint8_t *bbptr = bb->data;
|
||||
uint8_t *pmptr = imagebuffer;
|
||||
@@ -535,6 +592,7 @@ static const struct luaL_Reg djvudocument_meth[] = {
|
||||
{"getToc", getTableOfContent},
|
||||
{"getPageText", getPageText},
|
||||
{"getOriginalPageSize", getOriginalPageSize},
|
||||
{"getPageInfo", getPageInfo},
|
||||
{"close", closeDocument},
|
||||
{"getCacheSize", getCacheSize},
|
||||
{"cleanCache", cleanCache},
|
||||
|
||||
@@ -9,6 +9,11 @@ DjvuDocument = Document:new{
|
||||
}
|
||||
|
||||
function DjvuDocument:init()
|
||||
if not validDjvuFile(self.file) then
|
||||
self.error_message = "Not a valid DjVu file"
|
||||
return
|
||||
end
|
||||
|
||||
local ok
|
||||
ok, self._document = pcall(djvu.openDocument, self.file, self.djvulibre_cache_size)
|
||||
if not ok then
|
||||
@@ -20,6 +25,16 @@ function DjvuDocument:init()
|
||||
self:_readMetadata()
|
||||
end
|
||||
|
||||
-- check DjVu magic string to validate
|
||||
function validDjvuFile(filename)
|
||||
f = io.open(filename, "r")
|
||||
if not f then return false end
|
||||
local magic = f:read(8)
|
||||
f:close()
|
||||
if not magic or magic ~= "AT&TFORM" then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
function DjvuDocument:getUsedBBox(pageno)
|
||||
-- djvu does not support usedbbox, so fake it.
|
||||
local used = {}
|
||||
|
||||
@@ -128,7 +128,7 @@ function Document:getToc()
|
||||
return self._document:getToc()
|
||||
end
|
||||
|
||||
function Document:renderPage(pageno, rect, zoom, rotation)
|
||||
function Document:renderPage(pageno, rect, zoom, rotation, render_mode)
|
||||
local hash = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation
|
||||
local page_size = self:getPageDimensions(pageno, zoom, rotation)
|
||||
-- this will be the size we actually render
|
||||
@@ -172,7 +172,7 @@ function Document:renderPage(pageno, rect, zoom, rotation)
|
||||
|
||||
-- render
|
||||
local page = self._document:openPage(pageno)
|
||||
page:draw(dc, tile.bb, size.x, size.y)
|
||||
page:draw(dc, tile.bb, size.x, size.y, render_mode)
|
||||
page:close()
|
||||
Cache:insert(hash, tile)
|
||||
|
||||
@@ -185,7 +185,7 @@ function Document:hintPage(pageno, zoom, rotation)
|
||||
self:renderPage(pageno, nil, zoom, rotation)
|
||||
end
|
||||
|
||||
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation)
|
||||
function Document:drawPage(target, x, y, rect, pageno, zoom, rotation, render_mode)
|
||||
local hash_full_page = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation
|
||||
local hash_excerpt = "renderpg|"..self.file.."|"..pageno.."|"..zoom.."|"..rotation.."|"..tostring(rect)
|
||||
local tile = Cache:check(hash_full_page)
|
||||
@@ -193,7 +193,7 @@ function Document:drawPage(target, x, y, rect, pageno, zoom, rotation)
|
||||
tile = Cache:check(hash_excerpt)
|
||||
if not tile then
|
||||
DEBUG("rendering")
|
||||
tile = self:renderPage(pageno, rect, zoom, rotation)
|
||||
tile = self:renderPage(pageno, rect, zoom, rotation, render_mode)
|
||||
end
|
||||
end
|
||||
DEBUG("now painting", tile)
|
||||
|
||||
@@ -9,8 +9,9 @@ ReaderView = WidgetContainer:new{
|
||||
offset = {},
|
||||
bbox = nil,
|
||||
},
|
||||
|
||||
outer_page_color = 7,
|
||||
-- DjVu page rendering mode (used in djvu.c:drawPage())
|
||||
render_mode = 0, -- default to COLOR
|
||||
|
||||
visible_area = Geom:new{x = 0, y = 0},
|
||||
page_area = Geom:new{},
|
||||
@@ -41,7 +42,8 @@ function ReaderView:paintTo(bb, x, y)
|
||||
self.visible_area,
|
||||
self.state.page,
|
||||
self.state.zoom,
|
||||
self.state.rotation)
|
||||
self.state.rotation,
|
||||
self.render_mode)
|
||||
else
|
||||
self.ui.document:drawCurrentView(
|
||||
bb,
|
||||
@@ -88,6 +90,10 @@ function ReaderView:onSetDimensions(dimensions)
|
||||
self:recalculate()
|
||||
end
|
||||
|
||||
function ReaderView:onReadSettings(config)
|
||||
self.render_mode = config:readSetting("render_mode") or 0
|
||||
end
|
||||
|
||||
function ReaderView:onPageUpdate(new_page_no)
|
||||
self.state.page = new_page_no
|
||||
self:recalculate()
|
||||
@@ -108,3 +114,6 @@ function ReaderView:onRotationUpdate(rotation)
|
||||
self:recalculate()
|
||||
end
|
||||
|
||||
function ReaderView:onCloseDocument()
|
||||
self.ui.doc_settings:saveSetting("render_mode", self.render_mode)
|
||||
end
|
||||
|
||||
@@ -47,10 +47,11 @@ function getSubTextByWidth(text, face, width, kerning)
|
||||
end
|
||||
|
||||
function sizeUtf8Text(x, width, face, text, kerning)
|
||||
if text == nil then
|
||||
if not text then
|
||||
DEBUG("sizeUtf8Text called without text");
|
||||
return
|
||||
end
|
||||
|
||||
-- may still need more adaptive pen placement when kerning,
|
||||
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
||||
local pen_x = 0
|
||||
@@ -61,48 +62,46 @@ function sizeUtf8Text(x, width, face, text, kerning)
|
||||
if pen_x < (width - x) then
|
||||
local charcode = util.utf8charcode(uchar)
|
||||
local glyph = getGlyph(face, charcode)
|
||||
if kerning and prevcharcode then
|
||||
local kern = face.ftface:getKerning(prevcharcode, charcode)
|
||||
pen_x = pen_x + kern
|
||||
--DEBUG("prev:"..string.char(prevcharcode).." curr:"..string.char(charcode).." kern:"..kern)
|
||||
else
|
||||
--DEBUG("curr:"..string.char(charcode))
|
||||
if kerning and (prevcharcode ~= 0) then
|
||||
pen_x = pen_x + face.ftface:getKerning(prevcharcode, charcode)
|
||||
end
|
||||
pen_x = pen_x + glyph.ax
|
||||
pen_y_top = math.max(pen_y_top, glyph.t)
|
||||
pen_y_bottom = math.max(pen_y_bottom, glyph.bb:getHeight() - glyph.t)
|
||||
--DEBUG("ax:"..glyph.ax.." t:"..glyph.t.." r:"..glyph.r.." h:"..glyph.bb:getHeight().." w:"..glyph.bb:getWidth().." yt:"..pen_y_top.." yb:"..pen_y_bottom)
|
||||
prevcharcode = charcode
|
||||
end
|
||||
end
|
||||
end -- if pen_x < (width - x)
|
||||
end -- for uchar
|
||||
return { x = pen_x, y_top = pen_y_top, y_bottom = pen_y_bottom}
|
||||
end
|
||||
|
||||
function renderUtf8Text(buffer, x, y, face, text, kerning)
|
||||
if text == nil then
|
||||
if not text then
|
||||
DEBUG("renderUtf8Text called without text");
|
||||
return 0
|
||||
end
|
||||
|
||||
-- may still need more adaptive pen placement when kerning,
|
||||
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
||||
local pen_x = 0
|
||||
local prevcharcode = 0
|
||||
local buffer_width = buffer:getWidth()
|
||||
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
|
||||
if pen_x < buffer:getWidth() then
|
||||
if pen_x < buffer_width then
|
||||
local charcode = util.utf8charcode(uchar)
|
||||
local glyph = getGlyph(face, charcode)
|
||||
if kerning and prevcharcode then
|
||||
local kern = face.ftface:getKerning(prevcharcode, charcode)
|
||||
pen_x = pen_x + kern
|
||||
--DEBUG("prev:"..string.char(prevcharcode).." curr:"..string.char(charcode).." pen_x:"..pen_x.." kern:"..kern)
|
||||
buffer:addblitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
|
||||
else
|
||||
--DEBUG(" curr:"..string.char(charcode))
|
||||
buffer:blitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
|
||||
if kerning and (prevcharcode ~= 0) then
|
||||
pen_x = pen_x + face.ftface:getKerning(prevcharcode, charcode)
|
||||
end
|
||||
buffer:addblitFrom(
|
||||
glyph.bb,
|
||||
x + pen_x + glyph.l, y - glyph.t,
|
||||
0, 0,
|
||||
glyph.bb:getWidth(), glyph.bb:getHeight())
|
||||
pen_x = pen_x + glyph.ax
|
||||
prevcharcode = charcode
|
||||
end
|
||||
end
|
||||
end -- if pen_x < buffer_width
|
||||
end -- for uchar
|
||||
|
||||
return pen_x
|
||||
end
|
||||
|
||||
@@ -204,6 +204,7 @@ function TextWidget:paintTo(bb, x, y)
|
||||
--self:_render()
|
||||
--end
|
||||
--bb:blitFrom(self._bb, x, y, 0, 0, self._length, self._bb:getHeight())
|
||||
--@TODO Don't use kerning for monospaced fonts. (houqp)
|
||||
renderUtf8Text(bb, x, y+self._height*0.7, self.face, self.text, true)
|
||||
end
|
||||
|
||||
@@ -281,6 +282,8 @@ function TextBoxWidget:_render()
|
||||
for _,l in ipairs(v_list) do
|
||||
pen_x = 0
|
||||
for _,w in ipairs(l) do
|
||||
--@TODO Don't use kerning for monospaced fonts. (houqp)
|
||||
-- refert to cb25029dddc42693cc7aaefbe47e9bd3b7e1a750 in master tree
|
||||
renderUtf8Text(self._bb, pen_x, y*0.8, self.face, w.word, true)
|
||||
pen_x = pen_x + w.width + space_w
|
||||
end
|
||||
|
||||
@@ -121,6 +121,8 @@ local last_file = G_reader_settings:readSetting("lastfile")
|
||||
Screen:updateRotationMode()
|
||||
Screen.native_rotation_mode = Screen.cur_rotation_mode
|
||||
|
||||
--@TODO we can read version here, refer to commit in master tree: (houqp)
|
||||
--87712cf0e43fed624f8a9f610be42b1fe174b9fe
|
||||
|
||||
|
||||
if ARGV[optind] then
|
||||
|
||||
Reference in New Issue
Block a user