Merge pull request #407 from houqp/new_ui_code

some of my fixes & merge lates changes from master branch
This commit is contained in:
Dobrica Pavlinušić
2012-10-11 08:56:45 -07:00
10 changed files with 143 additions and 57 deletions

View File

@@ -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/

View File

@@ -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

View File

@@ -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
View File

@@ -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},

View File

@@ -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 = {}

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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