Merge pull request #517 from houqp/new_ui_code

merge latest changes from master branch
This commit is contained in:
Dobrica Pavlinušić
2012-11-01 02:10:43 -07:00
23 changed files with 8188 additions and 322 deletions

3
.gitignore vendored
View File

@@ -4,6 +4,9 @@ lua-*
.reader.kpdfview.lua
mupdf-thirdparty.zip
djvulibre*
crash.log
.vimrc
git-rev
kpdfview
slider_watcher
*.o

View File

@@ -9,6 +9,7 @@ KPVCRLIBDIR=kpvcrlib
CRENGINEDIR=$(KPVCRLIBDIR)/crengine
FREETYPEDIR=$(MUPDFDIR)/thirdparty/freetype-2.4.10
JPEGDIR=$(MUPDFDIR)/thirdparty/jpeg-9
LFSDIR=luafilesystem
POPENNSDIR=popen-noshell
@@ -18,6 +19,7 @@ TTF_FONTS_DIR=$(MUPDFDIR)/fonts
# set this to your ARM cross compiler:
SHELL:=/bin/bash
CHOST?=arm-none-linux-gnueabi
CC:=$(CHOST)-gcc
CXX:=$(CHOST)-g++
@@ -88,7 +90,8 @@ KPDFREADER_CFLAGS=$(CFLAGS) -I$(LUADIR)/src -I$(MUPDFDIR)/
# for now, all dependencies except for the libc are compiled into the final binary:
MUPDFLIBS := $(MUPDFLIBDIR)/libfitz.a
DJVULIBS := $(DJVUDIR)/build/libdjvu/.libs/libdjvulibre.a
DJVULIBS := $(DJVUDIR)/build/libdjvu/.libs/libdjvulibre.so
DJVULIBDIR := $(DJVUDIR)/build/libdjvu/.libs/
CRENGINELIBS := $(CRENGINEDIR)/crengine/libcrengine.a \
$(CRENGINEDIR)/thirdparty/chmlib/libchmlib.a \
$(CRENGINEDIR)/thirdparty/libpng/libpng.a \
@@ -107,16 +110,17 @@ LUALIB := $(LUADIR)/src/libluajit.a
POPENNSLIB := $(POPENNSDIR)/libpopen_noshell.a
all: kpdfview
all: kpdfview extr
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)
kpdfview: kpdfview.o einkfb.o pdf.o k2pdfopt.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) pic.o pic_jpeg.o
echo $(VERSION) > git-rev
$(CC) \
$(CFLAGS) \
kpdfview.o \
einkfb.o \
pdf.o \
k2pdfopt.o \
blitbuffer.o \
drawcontext.o \
input.o \
@@ -129,16 +133,23 @@ kpdfview: kpdfview.o einkfb.o pdf.o blitbuffer.o drawcontext.o input.o $(POPENNS
$(THIRDPARTYLIBS) \
$(LUALIB) \
djvu.o \
$(DJVULIBS) \
pic.o \
pic_jpeg.o \
cre.o \
$(CRENGINELIBS) \
$(STATICLIBSTDCPP) \
$(LDFLAGS) \
-o $@ \
-lm -ldl -lpthread \
-lm -ldl -lpthread -ldjvulibre -ljpeg -L$(MUPDFLIBDIR) -L$(DJVULIBDIR)\
$(EMU_LDFLAGS) \
$(DYNAMICLIBSTDCPP)
extr: extr.o $(MUPDFLIBS) $(THIRDPARTYLIBS)
$(CC) $(CFLAGS) extr.o $(MUPDFLIBS) $(THIRDPARTYLIBS) -lm -o extr
extr.o: %.o: %.c
$(CC) -c -I$(MUPDFDIR)/pdf -I$(MUPDFDIR)/fitz $< -o $@
slider_watcher.o: %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
@@ -151,9 +162,18 @@ ft.o: %.o: %.c $(THIRDPARTYLIBS)
kpdfview.o pdf.o blitbuffer.o util.o drawcontext.o einkfb.o input.o mupdfimg.o: %.o: %.c
$(CC) -c $(KPDFREADER_CFLAGS) $(EMU_CFLAGS) -I$(LFSDIR)/src $< -o $@
k2pdfopt.o: %.o: %.c
$(CC) -c -I$(MUPDFDIR)/ -I$(DJVUDIR)/ $(CFLAGS) $< -o $@
djvu.o: %.o: %.c
$(CC) -c $(KPDFREADER_CFLAGS) -I$(DJVUDIR)/ $< -o $@
pic.o: %.o: %.c
$(CC) -c $(KPDFREADER_CFLAGS) $< -o $@
pic_jpeg.o: %.o: %.c
$(CC) -c $(KPDFREADER_CFLAGS) -I$(JPEGDIR)/ -I$(MUPDFDIR)/scripts/ $< -o $@
cre.o: %.o: %.cpp
$(CC) -c $(CFLAGS) -I$(CRENGINEDIR)/crengine/include/ -I$(LUADIR)/src $< -o $@
@@ -175,7 +195,8 @@ fetchthirdparty:
# CREngine patch: change child nodes' type face
# @TODO replace this dirty hack 24.04 2012 (houqp)
cd kpvcrlib/crengine/crengine/src && \
patch -N -p0 < ../../../lvrend_node_type_face.patch || true
patch -N -p0 < ../../../lvrend_node_type_face.patch && \
patch -N -p3 < ../../../lvdocview-getCurrentPageLinks.patch || true
unzip mupdf-thirdparty.zip -d mupdf
# check mupdf's thirdparty libs' version, if not matched, remove the old one
# run make fetchthirdparty again to get the latest thirdparty libs.
@@ -192,10 +213,15 @@ fetchthirdparty:
cd popen-noshell && test -f Makefile || patch -N -p0 < popen_noshell-buildfix.patch
clean:
rm -f *.o kpdfview slider_watcher
rm -f *.o kpdfview slider_watcher extr
cleanthirdparty:
$(MAKE) -C $(LUADIR) CC="$(HOSTCC)" CFLAGS="$(BASE_CFLAGS)" distclean
ifdef EMULATE_READER
rm -rf libs-emu ; mkdir libs-emu
else
rm -rf libs ; mkdir libs
endif
$(MAKE) -C $(LUADIR) CC="$(HOSTCC)" CFLAGS="$(BASE_CFLAGS)" clean
$(MAKE) -C $(MUPDFDIR) build="release" clean
$(MAKE) -C $(CRENGINEDIR)/thirdparty/antiword clean
test -d $(CRENGINEDIR)/thirdparty/chmlib && $(MAKE) -C $(CRENGINEDIR)/thirdparty/chmlib clean || echo warn: chmlib folder not found
@@ -224,11 +250,15 @@ $(MUPDFLIBS) $(THIRDPARTYLIBS): $(MUPDFDIR)/cmapdump.host $(MUPDFDIR)/fontdump.h
$(DJVULIBS):
mkdir -p $(DJVUDIR)/build
ifdef EMULATE_READER
cd $(DJVUDIR)/build && CC="$(HOSTCC)" CXX="$(HOSTCXX)" CFLAGS="$(HOSTCFLAGS)" CXXFLAGS="$(HOSTCFLAGS)" LDFLAGS="$(LDFLAGS)" ../configure --disable-desktopfiles --disable-shared --enable-static --disable-xmltools --disable-largefile
else
cd $(DJVUDIR)/build && CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ../configure --disable-desktopfiles --disable-shared --enable-static --host=$(CHOST) --disable-xmltools --disable-largefile
endif
cd $(DJVUDIR)/build && CC="$(HOSTCC)" CXX="$(HOSTCXX)" CFLAGS="$(HOSTCFLAGS)" CXXFLAGS="$(HOSTCFLAGS)" LDFLAGS="$(LDFLAGS)" ../configure --disable-desktopfiles --disable-static --enable-shared --disable-xmltools --disable-largefile
$(MAKE) -C $(DJVUDIR)/build
test -d libs-emu || mkdir libs-emu
cp -a $(DJVULIBDIR)/libdjvulibre.so* libs-emu
else
cd $(DJVUDIR)/build && CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" LDFLAGS="$(LDFLAGS)" ../configure --disable-desktopfiles --disable-static --enable-shared --host=$(CHOST) --disable-xmltools --disable-largefile
$(MAKE) -C $(DJVUDIR)/build
cp $(DJVULIBDIR)/libdjvulibre.so.21 libs
endif
$(CRENGINELIBS):
cd $(KPVCRLIBDIR) && rm -rf CMakeCache.txt CMakeFiles && \
@@ -253,14 +283,17 @@ INSTALL_DIR=kindlepdfviewer
LUA_FILES=reader.lua
customupdate: all
# ensure that build binary is for ARM
# ensure that the binaries were built for ARM
file kpdfview | grep ARM || exit 1
$(STRIP) --strip-unneeded kpdfview
file extr | grep ARM || exit 1
$(STRIP) --strip-unneeded kpdfview extr
rm -f kindlepdfviewer-$(VERSION).zip
rm -rf $(INSTALL_DIR)
mkdir -p $(INSTALL_DIR)/{history,screenshots}
cp -p README.md COPYING kpdfview kpdf.sh $(LUA_FILES) $(INSTALL_DIR)
mkdir -p $(INSTALL_DIR)/{history,screenshots,libs}
cp -p README.md COPYING kpdfview extr kpdf.sh $(LUA_FILES) $(INSTALL_DIR)
mkdir $(INSTALL_DIR)/data
cp libs/* $(INSTALL_DIR)/libs
$(STRIP) --strip-unneeded $(INSTALL_DIR)/libs/*
cp -rpL data/*.css $(INSTALL_DIR)/data
cp -rpL fonts $(INSTALL_DIR)
cp -r git-rev resources $(INSTALL_DIR)

View File

@@ -61,7 +61,8 @@ for this. It allows to develop on a standard PC and saves precious development
time. It might also compose the most unfriendly desktop PDF reader, depending
on your view.
If you are using Ubuntu, simply install `libsdl-dev1.2` package.
If you are using Fedora Core Linux, do `yum install SDL SDL-devel`.
If you are using Ubuntu, install `libsdl-dev1.2` package.
To build in "emulation mode", you need to run make like this:
make clean cleanthirdparty

View File

@@ -20,14 +20,19 @@
#include <string.h>
#include "blitbuffer.h"
inline int setPixel(lua_State *L, BlitBuffer *bb, int x, int y, int c) {
uint8_t *dstptr = (uint8_t*)(bb->data) + (y * bb->pitch) + (x / 2);
#ifndef NO_CHECK_BOUNDS
if(x < 0 || x >= bb->w || y < 0 || y >= bb->h) {
return luaL_error(L, "out of bounds in blitbuffer.setPixel()");
/* debugging statements, switch as needed */
#ifdef DEBUG
#define ASSERT_BLITBUFFER_BOUNDARIES(bb,bb_ptr) \
if((bb_ptr < bb->data) || (bb_ptr >= (bb->data + bb->pitch * bb->h))) { \
fprintf(stderr, "violated blitbuffer constraints in file %s, line %d!\r\n", __FILE__, __LINE__); exit(1); \
}
#endif
#else // DEBUG
#define ASSERT_BLITBUFFER_BOUNDARIES(bb,bb_ptr) {}
#endif // DEBUG
inline int setPixel(BlitBuffer *bb, int x, int y, int c) {
uint8_t *dstptr = (uint8_t*)(bb->data) + (y * bb->pitch) + (x / 2);
ASSERT_BLITBUFFER_BOUNDARIES(bb, dstptr);
if(x % 2 == 0) {
*dstptr &= 0x0F;
@@ -100,6 +105,63 @@ static int blitFullToBuffer(lua_State *L) {
return 0;
}
/**
* check/adapt boundaries for blitting operations
*
* @return 0 if no blitting is needed, 1 otherwise
*/
int fitBlitBufferBoundaries(BlitBuffer* src, BlitBuffer* dst, int* xdest, int* ydest, int* xoffs, int* yoffs, int* w, int* h) {
// check bounds
if(*ydest < 0) {
// negative ydest, try to compensate
if(*ydest + *h > 0) {
// shrink h by negative dest offset
*h += *ydest;
// extend source offset
*yoffs += -(*ydest);
*ydest = 0;
} else {
// effectively no height
return 0;
}
} else if(*ydest >= dst->h) {
// we're told to paint to off-bound target coords
return 0;
}
if(*ydest + *h > dst->h) {
// clamp height if too large for target size
*h = dst->h - *ydest;
}
if(*yoffs >= src->h) {
// recalculated source offset is out of bounds
return 0;
} else if(*yoffs + *h > src->h) {
// clamp height if too large for source size
*h = src->h - *yoffs;
}
// same stuff for x coords:
if(*xdest < 0) {
if(*xdest + *w > 0) {
*w += *xdest;
*xoffs += -(*xdest);
*xdest = 0;
} else {
return 0;
}
} else if(*xdest >= dst->w) {
return 0;
}
if(*xdest + *w > dst->w) {
*w = dst->w - *xdest;
}
if(*xoffs >= src->w) {
return 0;
} else if(*xoffs + *w > src->w) {
*w = src->w - *xoffs;
}
return 1; // continue processing
}
static int blitToBuffer(lua_State *L) {
BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer");
BlitBuffer *src = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
@@ -111,58 +173,12 @@ static int blitToBuffer(lua_State *L) {
int h = luaL_checkint(L, 8);
int x, y;
// check bounds
if(ydest < 0) {
// negative ydest, try to compensate
if(ydest + h > 0) {
// shrink h by negative dest offset
h += ydest;
// extend source offset
yoffs += -ydest;
ydest = 0;
} else {
// effectively no height
return 0;
}
} else if(ydest >= dst->h) {
// we're told to paint to off-bound target coords
return 0;
}
if(ydest + h > dst->h) {
// clamp height if too large for target size
h = dst->h - ydest;
}
if(yoffs >= src->h) {
// recalculated source offset is out of bounds
return 0;
} else if(yoffs + h > src->h) {
// clamp height if too large for source size
h = src->h - yoffs;
}
// same stuff for x coords:
if(xdest < 0) {
if(xdest + w > 0) {
w += xdest;
xoffs += -xdest;
xdest = 0;
} else {
return 0;
}
} else if(xdest >= dst->w) {
return 0;
}
if(xdest + w > dst->w) {
w = dst->w - xdest;
}
if(xoffs >= src->w) {
return 0;
} else if(xoffs + w > src->w) {
w = src->w - xoffs;
}
uint8_t *dstptr;
uint8_t *srcptr;
if(!fitBlitBufferBoundaries(src, dst, &xdest, &ydest, &xoffs, &yoffs, &w, &h))
return 0;
if(xdest & 1) {
/* this will render the leftmost column */
dstptr = (uint8_t*)(dst->data +
@@ -173,6 +189,8 @@ static int blitToBuffer(lua_State *L) {
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
*dstptr &= 0xF0;
*dstptr |= *srcptr & 0x0F;
dstptr += dst->pitch;
@@ -180,6 +198,8 @@ static int blitToBuffer(lua_State *L) {
}
} else {
for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
*dstptr &= 0xF0;
*dstptr |= *srcptr >> 4;
dstptr += dst->pitch;
@@ -200,6 +220,8 @@ static int blitToBuffer(lua_State *L) {
if(xoffs & 1) {
for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
for(x = 0; x < (w / 2); x++) {
dstptr[x] = (srcptr[x] << 4) | (srcptr[x+1] >> 4);
}
@@ -212,6 +234,8 @@ static int blitToBuffer(lua_State *L) {
}
} else {
for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
memcpy(dstptr, srcptr, w / 2);
if(w & 1) {
dstptr[w/2] &= 0x0F;
@@ -235,31 +259,12 @@ static int addblitToBuffer(lua_State *L) {
int h = luaL_checkint(L, 8);
int x, y;
// check bounds
if(yoffs >= src->h) {
return 0;
} else if(yoffs + h > src->h) {
h = src->h - yoffs;
}
if(ydest >= dst->h) {
return 0;
} else if(ydest + h > dst->h) {
h = dst->h - ydest;
}
if(xoffs >= src->w) {
return 0;
} else if(xoffs + w > src->w) {
w = src->w - xoffs;
}
if(xdest >= dst->w) {
return 0;
} else if(xdest + w > dst->w) {
w = dst->w - xdest;
}
uint8_t *dstptr;
uint8_t *srcptr;
if(!fitBlitBufferBoundaries(src, dst, &xdest, &ydest, &xoffs, &yoffs, &w, &h))
return 0;
if(xdest & 1) {
/* this will render the leftmost column */
dstptr = (uint8_t*)(dst->data +
@@ -270,6 +275,8 @@ static int addblitToBuffer(lua_State *L) {
xoffs / 2 );
if(xoffs & 1) {
for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint8_t v = (*dstptr & 0x0F) + (*srcptr & 0x0F);
*dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F);
dstptr += dst->pitch;
@@ -277,6 +284,8 @@ static int addblitToBuffer(lua_State *L) {
}
} else {
for(y = 0; y < h; y++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint8_t v = (*dstptr & 0x0F) + (*srcptr >> 4);
*dstptr = (*dstptr & 0xF0) | (v < 0x0F ? v : 0x0F);
dstptr += dst->pitch;
@@ -298,11 +307,15 @@ static int addblitToBuffer(lua_State *L) {
if(xoffs & 1) {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4);
uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x+1] >> 4);
dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
}
if(w & 1) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + ((srcptr[x] & 0x0F) << 4);
dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
}
@@ -312,11 +325,15 @@ static int addblitToBuffer(lua_State *L) {
} else {
for(y = 0; y < h; y++) {
for(x = 0; x < (w / 2); x++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0);
uint8_t v2 = (dstptr[x] & 0x0F) + (srcptr[x] & 0x0F);
dstptr[x] = (v1 < 0xF0 ? v1 : 0xF0) | (v2 < 0x0F ? v2 : 0x0F);
}
if(w & 1) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
ASSERT_BLITBUFFER_BOUNDARIES(src, srcptr);
uint16_t v1 = (dstptr[x] & 0xF0) + (srcptr[x] & 0xF0);
dstptr[x] = (dstptr[x] & 0x0F) | (v1 < 0xF0 ? v1 : 0xF0);
}
@@ -337,9 +354,25 @@ static int paintRect(lua_State *L) {
uint8_t *dstptr;
int cy;
if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) {
return 0;
if(x < 0) {
if (x+w > 0) {
w += x;
x = 0;
} else {
return 0;
}
}
if(y < 0) {
if (y+h > 0) {
h += y;
y = 0;
} else {
return 0;
}
}
if(x + w > dst->w) {
w = dst->w - x;
}
@@ -347,6 +380,10 @@ static int paintRect(lua_State *L) {
h = dst->h - y;
}
if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) {
return 0;
}
if(x & 1) {
/* This will render the leftmost column
* in the case when x is odd. After this,
@@ -355,6 +392,7 @@ static int paintRect(lua_State *L) {
y * dst->pitch +
x / 2);
for(cy = 0; cy < h; cy++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
*dstptr &= 0xF0;
*dstptr |= c;
dstptr += dst->pitch;
@@ -366,6 +404,7 @@ static int paintRect(lua_State *L) {
y * dst->pitch +
x / 2);
for(cy = 0; cy < h; cy++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
memset(dstptr, c | (c << 4), w / 2);
dstptr += dst->pitch;
}
@@ -377,6 +416,7 @@ static int paintRect(lua_State *L) {
y * dst->pitch +
(x + w) / 2);
for(cy = 0; cy < h; cy++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
*dstptr &= 0x0F;
*dstptr |= (c << 4);
dstptr += dst->pitch;
@@ -435,6 +475,7 @@ static int invertRect(lua_State *L) {
y * dst->pitch +
x / 2);
for(cy = 0; cy < h; cy++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
*dstptr ^= 0x0F;
dstptr += dst->pitch;
}
@@ -446,6 +487,7 @@ static int invertRect(lua_State *L) {
x / 2);
for(cy = 0; cy < h; cy++) {
for(cx = 0; cx < w/2; cx++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, (dstptr+cx));
*(dstptr+cx) ^= 0xFF;
}
dstptr += dst->pitch;
@@ -458,6 +500,7 @@ static int invertRect(lua_State *L) {
y * dst->pitch +
(x + w) / 2);
for(cy = 0; cy < h; cy++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
*dstptr ^= 0xF0;
dstptr += dst->pitch;
}
@@ -474,6 +517,27 @@ static int dimRect(lua_State *L) {
uint8_t *dstptr;
int cy, cx;
if (x < 0) {
if ( x + w > 0 ) {
w = w + x;
x = 0;
} else {
//printf("## invertRect x out of bound\n");
return 0;
}
}
if (y < 0) {
if ( y + h > 0 ) {
h = h + y;
y = 0;
} else {
//printf("## invertRect y out of bound\n");
return 0;
}
}
if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) {
return 0;
}
@@ -492,6 +556,7 @@ static int dimRect(lua_State *L) {
y * dst->pitch +
x / 2);
for(cy = 0; cy < h; cy++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
int px = *dstptr & 0x0F;
*dstptr &= 0xF0 | px >> 1;
dstptr += dst->pitch;
@@ -504,6 +569,7 @@ static int dimRect(lua_State *L) {
x / 2);
for(cy = 0; cy < h; cy++) {
for(cx = 0; cx < w/2; cx++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, (dstptr+cx));
*(dstptr+cx) =
( *(dstptr+cx) >> 1 ) & 0xF0 |
( *(dstptr+cx) & 0x0F ) >> 1;
@@ -518,6 +584,7 @@ static int dimRect(lua_State *L) {
y * dst->pitch +
(x + w) / 2);
for(cy = 0; cy < h; cy++) {
ASSERT_BLITBUFFER_BOUNDARIES(dst, dstptr);
int px = *dstptr & 0xF0;
*dstptr &= 0x0F | ( px >> 1 & 0xF0 );
dstptr += dst->pitch;
@@ -560,10 +627,10 @@ static int paintCircle(lua_State *L) {
/* draw two axles */
for(tmp_y = r; tmp_y > r2; tmp_y--) {
setPixel(L, dst, center_x+0, center_y+tmp_y, c);
setPixel(L, dst, center_x-0, center_y-tmp_y, c);
setPixel(L, dst, center_x+tmp_y, center_y+0, c);
setPixel(L, dst, center_x-tmp_y, center_y-0, c);
setPixel(dst, center_x+0, center_y+tmp_y, c);
setPixel(dst, center_x-0, center_y-tmp_y, c);
setPixel(dst, center_x+tmp_y, center_y+0, c);
setPixel(dst, center_x-tmp_y, center_y-0, c);
}
while(x < y) {
@@ -591,21 +658,21 @@ static int paintCircle(lua_State *L) {
}
for(tmp_y = y; tmp_y > y2; tmp_y--) {
setPixel(L, dst, center_x+x, center_y+tmp_y, c);
setPixel(L, dst, center_x+tmp_y, center_y+x, c);
setPixel(dst, center_x+x, center_y+tmp_y, c);
setPixel(dst, center_x+tmp_y, center_y+x, c);
setPixel(L, dst, center_x+tmp_y, center_y-x, c);
setPixel(L, dst, center_x+x, center_y-tmp_y, c);
setPixel(dst, center_x+tmp_y, center_y-x, c);
setPixel(dst, center_x+x, center_y-tmp_y, c);
setPixel(L, dst, center_x-x, center_y-tmp_y, c);
setPixel(L, dst, center_x-tmp_y, center_y-x, c);
setPixel(dst, center_x-x, center_y-tmp_y, c);
setPixel(dst, center_x-tmp_y, center_y-x, c);
setPixel(L, dst, center_x-tmp_y, center_y+x, c);
setPixel(L, dst, center_x-x, center_y+tmp_y, c);
setPixel(dst, center_x-tmp_y, center_y+x, c);
setPixel(dst, center_x-x, center_y+tmp_y, c);
}
}
if(r == w) {
setPixel(L, dst, center_x, center_y, c);
setPixel(dst, center_x, center_y, c);
}
return 0;
}
@@ -645,10 +712,10 @@ static int paintRoundedCorner(lua_State *L) {
/* draw two axles */
/*for(tmp_y = r; tmp_y > r2; tmp_y--) {*/
/*setPixel(L, dst, (w-r)+off_x+0, (h-r)+off_y+tmp_y-1, c);*/
/*setPixel(L, dst, (w-r)+off_x-0, (r)+off_y-tmp_y, c);*/
/*setPixel(L, dst, (w-r)+off_x+tmp_y, (h-r)+off_y+0, c);*/
/*setPixel(L, dst, (r)+off_x-tmp_y, (h-r)+off_y-0-1, c);*/
/*setPixel(dst, (w-r)+off_x+0, (h-r)+off_y+tmp_y-1, c);*/
/*setPixel(dst, (w-r)+off_x-0, (r)+off_y-tmp_y, c);*/
/*setPixel(dst, (w-r)+off_x+tmp_y, (h-r)+off_y+0, c);*/
/*setPixel(dst, (r)+off_x-tmp_y, (h-r)+off_y-0-1, c);*/
/*}*/
while(x < y) {
@@ -676,17 +743,17 @@ static int paintRoundedCorner(lua_State *L) {
}
for(tmp_y = y; tmp_y > y2; tmp_y--) {
setPixel(L, dst, (w-r)+off_x+x-1, (h-r)+off_y+tmp_y-1, c);
setPixel(L, dst, (w-r)+off_x+tmp_y-1, (h-r)+off_y+x-1, c);
setPixel(dst, (w-r)+off_x+x-1, (h-r)+off_y+tmp_y-1, c);
setPixel(dst, (w-r)+off_x+tmp_y-1, (h-r)+off_y+x-1, c);
setPixel(L, dst, (w-r)+off_x+tmp_y-1, (r)+off_y-x, c);
setPixel(L, dst, (w-r)+off_x+x-1, (r)+off_y-tmp_y, c);
setPixel(dst, (w-r)+off_x+tmp_y-1, (r)+off_y-x, c);
setPixel(dst, (w-r)+off_x+x-1, (r)+off_y-tmp_y, c);
setPixel(L, dst, (r)+off_x-x, (r)+off_y-tmp_y, c);
setPixel(L, dst, (r)+off_x-tmp_y, (r)+off_y-x, c);
setPixel(dst, (r)+off_x-x, (r)+off_y-tmp_y, c);
setPixel(dst, (r)+off_x-tmp_y, (r)+off_y-x, c);
setPixel(L, dst, (r)+off_x-tmp_y, (h-r)+off_y+x-1, c);
setPixel(L, dst, (r)+off_x-x, (h-r)+off_y+tmp_y-1, c);
setPixel(dst, (r)+off_x-tmp_y, (h-r)+off_y+x-1, c);
setPixel(dst, (r)+off_x-x, (h-r)+off_y+tmp_y-1, c);
}
}
return 0;

98
cre.cpp
View File

@@ -17,7 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEBUG_CRENGINE
#define DEBUG_CRENGINE 0
#endif
extern "C" {
#include "blitbuffer.h"
@@ -157,7 +159,7 @@ static int getCurrentPercent(lua_State *L) {
return 1;
}
static int getCurrentXPointer(lua_State *L) {
static int getXPointer(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
ldomXPointer xp = doc->text_view->getBookmark();
@@ -410,7 +412,92 @@ static int cursorRight(lua_State *L) {
return 0;
}
static int drawCurrentView(lua_State *L) {
static int getPageLinks(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
lua_newtable(L); // all links
ldomXRangeList links;
ldomXRangeList & sel = doc->text_view->getDocument()->getSelections();
doc->text_view->getCurrentPageLinks( links );
int linkCount = links.length();
if ( linkCount ) {
sel.clear();
for ( int i=0; i<linkCount; i++ ) {
lString16 txt = links[i]->getRangeText();
lString8 txt8 = UnicodeToLocal( txt );
lString16 link = links[i]->getHRef();
lString8 link8 = UnicodeToLocal( link );
ldomXRange currSel;
currSel = *links[i];
lvPoint start_pt ( currSel.getStart().toPoint() );
lvPoint end_pt ( currSel.getEnd().toPoint() );
CRLog::debug("# link %d start %d %d end %d %d '%s' %s\n", i,
start_pt.x, start_pt.y, end_pt.x, end_pt.y,
txt8.c_str(), link8.c_str()
);
lua_newtable(L); // new link
lua_pushstring(L, "start_x");
lua_pushinteger(L, start_pt.x);
lua_settable(L, -3);
lua_pushstring(L, "start_y");
lua_pushinteger(L, start_pt.y);
lua_settable(L, -3);
lua_pushstring(L, "end_x");
lua_pushinteger(L, end_pt.x);
lua_settable(L, -3);
lua_pushstring(L, "end_y");
lua_pushinteger(L, end_pt.y);
lua_settable(L, -3);
const char * link_to = link8.c_str();
if ( link_to[0] == '#' ) {
lua_pushstring(L, "section");
lua_pushstring(L, link_to);
lua_settable(L, -3);
sel.add( new ldomXRange(*links[i]) ); // highlight
} else {
lua_pushstring(L, "uri");
lua_pushstring(L, link_to);
lua_settable(L, -3);
}
lua_rawseti(L, -2, i + 1);
}
doc->text_view->updateSelections();
}
return 1;
}
static int gotoLink(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
const char *pos = luaL_checkstring(L, 2);
doc->text_view->goLink(lString16(pos), true);
return 0;
}
static int clearSelection(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
doc->text_view->clearSelection();
return 0;
}
static int drawCurrentPage(lua_State *L) {
CreDocument *doc = (CreDocument*) luaL_checkudata(L, 1, "credocument");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 2, "blitbuffer");
@@ -536,7 +623,7 @@ static const struct luaL_Reg credocument_meth[] = {
{"getPosFromXPointer", getPosFromXPointer},
{"getCurrentPos", getCurrentPos},
{"getCurrentPercent", getCurrentPercent},
{"getCurrentXPointer", getCurrentXPointer},
{"getXPointer", getXPointer},
{"getFullHeight", getFullHeight},
{"getFontSize", getFontSize},
{"getFontFace", getFontFace},
@@ -555,8 +642,11 @@ static const struct luaL_Reg credocument_meth[] = {
{"toggleFontBolder", toggleFontBolder},
//{"cursorLeft", cursorLeft},
//{"cursorRight", cursorRight},
{"drawCurrentView", drawCurrentView},
{"drawCurrentPage", drawCurrentPage},
{"findText", findText},
{"getPageLinks", getPageLinks},
{"gotoLink", gotoLink},
{"clearSelection", clearSelection},
{"close", closeDocument},
{"__gc", closeDocument},
{NULL, NULL}

74
djvu.c
View File

@@ -470,16 +470,68 @@ static int closePage(lua_State *L) {
return 0;
}
/* draw part of the page to bb.
*
* @page: DjvuPage user data
* @dc: DrawContext user data
* @bb: BlitBuffer user data
* @x: x offset within zoomed page
* @y: y offset within zoomed page
*
* width and height for the visible_area is obtained from bb.
*/
static int reflowPage(lua_State *L) {
DjvuPage *page = (DjvuPage*) luaL_checkudata(L, 1, "djvupage");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
ddjvu_render_mode_t mode = (int) luaL_checkint(L, 3);
int width = luaL_checkint(L, 4); // framebuffer size
int height = luaL_checkint(L, 5);
double font_size = luaL_checknumber(L, 6);
double page_margin = luaL_checknumber(L, 7);
double line_spacing = luaL_checknumber(L, 8);
double word_spacing = luaL_checknumber(L, 9);
int text_wrap = luaL_checkint(L, 10);
int straighten = luaL_checkint(L, 11);
int justification = luaL_checkint(L, 12);
int columns = luaL_checkint(L, 13);
double contrast = luaL_checknumber(L, 14);
int rotation = luaL_checknumber(L, 15);
k2pdfopt_set_params(width, height, font_size, page_margin, line_spacing, word_spacing, \
text_wrap, straighten, justification, columns, contrast, rotation);
k2pdfopt_djvu_reflow(page->page_ref, page->doc->context, mode, page->doc->pixelformat);
k2pdfopt_rfbmp_size(&width, &height);
k2pdfopt_rfbmp_zoom(&dc->zoom);
lua_pushnumber(L, (double)width);
lua_pushnumber(L, (double)height);
lua_pushnumber(L, (double)dc->zoom);
return 3;
}
static int drawReflowedPage(lua_State *L) {
uint8_t *pmptr = NULL;
DjvuPage *page = (DjvuPage*) luaL_checkudata(L, 1, "djvupage");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 3, "blitbuffer");
uint8_t *bbptr = bb->data;
k2pdfopt_rfbmp_ptr(&pmptr);
int x_offset = 0;
int y_offset = 0;
bbptr += bb->pitch * y_offset;
int x, y;
for(y = y_offset; y < bb->h; y++) {
for(x = x_offset/2; x < (bb->w/2); x++) {
int p = x*2 - x_offset;
bbptr[x] = (((pmptr[p + 1] & 0xF0) >> 4) | (pmptr[p] & 0xF0)) ^ 0xFF;
}
bbptr += bb->pitch;
pmptr += bb->w;
if (bb->w & 1) {
bbptr[x] = 255 - (pmptr[x*2] & 0xF0);
}
}
return 0;
}
static int drawPage(lua_State *L) {
DjvuPage *page = (DjvuPage*) luaL_checkudata(L, 1, "djvupage");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
@@ -605,6 +657,8 @@ static const struct luaL_Reg djvupage_meth[] = {
{"getUsedBBox", getUsedBBox},
{"close", closePage},
{"__gc", closePage},
{"reflow", reflowPage},
{"rfdraw", drawReflowedPage},
{"draw", drawPage},
{NULL, NULL}
};

105
extr.c Normal file
View File

@@ -0,0 +1,105 @@
/*
extr: Extract attachments from PDF file
Usage: extr /dir/file.pdf pageno
Returns 0 if one or more attachments saved, otherwise returns non-zero.
Prints the number of saved attachments on stdout.
Attachments are saved in /dir directory with the appropriate filenames.
Copyright (C) 2012 Tigran Aivazian <tigran@bibles.org.uk>
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 "mupdf-internal.h"
#include <libgen.h>
static pdf_document *doc;
void dump_stream(int i, FILE *fout)
{
fz_stream *stm = pdf_open_stream(doc, i, 0);
static unsigned char buf[8192];
while (1) {
int n = fz_read(stm, buf, sizeof buf);
if (n == 0) break;
fwrite(buf, 1, n, fout);
}
fz_close(stm);
}
/* returns the number of attachments saved */
int save_attachments(int pageno, char *targetdir)
{
pdf_page *page = pdf_load_page(doc, pageno-1);
pdf_annot *annot;
int saved_count = 0;
for (annot = page->annots; annot ; annot = annot->next) {
pdf_obj *fs_obj = pdf_dict_gets(annot->obj, "FS");
if (fs_obj) {
pdf_obj *ef_obj;
char *name = basename(strdup(pdf_to_str_buf(pdf_dict_gets(fs_obj, "F"))));
ef_obj = pdf_dict_gets(fs_obj, "EF");
if (ef_obj) {
pdf_obj *f_obj = pdf_dict_gets(ef_obj, "F");
if (f_obj && pdf_is_indirect(f_obj)) {
static char pathname[PATH_MAX];
sprintf(pathname, "%s/%s", targetdir, name);
FILE *fout = fopen(pathname, "w");
if (!fout) {
fprintf(stderr, "extr: cannot write to file %s\n", pathname);
exit(1);
}
dump_stream(pdf_to_num(f_obj), fout);
fclose(fout);
saved_count++;
}
}
}
}
return saved_count;
}
int main(int argc, char *argv[])
{
int saved = 0;
if (argc != 3) {
printf("Usage: extr file.pdf pageno\n");
exit(1);
}
char *filename = strdup(argv[1]);
char *dir = dirname(strdup(filename));
int pageno = atoi(argv[2]);
fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
if (!ctx) {
fprintf(stderr, "extr: cannot create context\n");
exit(1);
}
fz_var(doc);
fz_try(ctx) {
doc = pdf_open_document(ctx, filename);
saved = save_attachments(pageno, dir);
}
fz_catch(ctx)
{
}
printf("%d\n", saved);
return 0;
}

View File

@@ -1,166 +0,0 @@
-- Copyright (c) 2009 Aleksey Cheusov <vle@gmx.net>
--
-- Permission is hereby granted, free of charge, to any person obtaining
-- a copy of this software and associated documentation files (the
-- "Software"), to deal in the Software without restriction, including
-- without limitation the rights to use, copy, modify, merge, publish,
-- distribute, sublicense, and/or sell copies of the Software, and to
-- permit persons to whom the Software is furnished to do so, subject to
-- the following conditions:
--
-- The above copyright notice and this permission notice shall be
-- included in all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
local type, pairs, ipairs, io, os = type, pairs, ipairs, io, os
module ("alt_getopt")
local function convert_short2long (opts)
local i = 1
local len = #opts
local ret = {}
for short_opt, accept_arg in opts:gmatch("(%w)(:?)") do
ret[short_opt]=#accept_arg
end
return ret
end
local function exit_with_error (msg, exit_status)
io.stderr:write (msg)
os.exit (exit_status)
end
local function err_unknown_opt (opt)
exit_with_error ("Unknown option `-" ..
(#opt > 1 and "-" or "") .. opt .. "'\n", 1)
end
local function canonize (options, opt)
if not options [opt] then
err_unknown_opt (opt)
end
while type (options [opt]) == "string" do
opt = options [opt]
if not options [opt] then
err_unknown_opt (opt)
end
end
return opt
end
function get_ordered_opts (arg, sh_opts, long_opts)
local i = 1
local count = 1
local opts = {}
local optarg = {}
local options = convert_short2long (sh_opts)
for k,v in pairs (long_opts) do
options [k] = v
end
while i <= #arg do
local a = arg [i]
if a == "--" then
i = i + 1
break
elseif a == "-" then
break
elseif a:sub (1, 2) == "--" then
local pos = a:find ("=", 1, true)
if pos then
local opt = a:sub (3, pos-1)
opt = canonize (options, opt)
if options [opt] == 0 then
exit_with_error ("Bad usage of option `" .. a .. "'\n", 1)
end
optarg [count] = a:sub (pos+1)
opts [count] = opt
else
local opt = a:sub (3)
opt = canonize (options, opt)
if options [opt] == 0 then
opts [count] = opt
else
if i == #arg then
exit_with_error ("Missed value for option `" .. a .. "'\n", 1)
end
optarg [count] = arg [i+1]
opts [count] = opt
i = i + 1
end
end
count = count + 1
elseif a:sub (1, 1) == "-" then
local j
for j=2,a:len () do
local opt = canonize (options, a:sub (j, j))
if options [opt] == 0 then
opts [count] = opt
count = count + 1
elseif a:len () == j then
if i == #arg then
exit_with_error ("Missed value for option `-" .. opt .. "'\n", 1)
end
optarg [count] = arg [i+1]
opts [count] = opt
i = i + 1
count = count + 1
break
else
optarg [count] = a:sub (j+1)
opts [count] = opt
count = count + 1
break
end
end
else
break
end
i = i + 1
end
return opts,i,optarg
end
function get_opts (arg, sh_opts, long_opts)
local ret = {}
local opts,optind,optarg = get_ordered_opts (arg, sh_opts, long_opts)
for i,v in ipairs (opts) do
if optarg [i] then
ret [v] = optarg [i]
else
ret [v] = 1
end
end
return ret,optind
end

7015
k2pdfopt.c Normal file

File diff suppressed because it is too large Load Diff

41
k2pdfopt.h Normal file
View File

@@ -0,0 +1,41 @@
/*
** k2pdfopt.h K2pdfopt optimizes PDF/DJVU files for mobile e-readers
** (e.g. the Kindle) and smartphones. It works well on
** multi-column PDF/DJVU files. K2pdfopt is freeware.
**
** Copyright (C) 2012 http://willus.com
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero 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 Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
*/
#ifndef _K2PDFOPT_H
#define _K2PDFOPT_H
#include <fitz/fitz-internal.h>
#include <libdjvu/ddjvuapi.h>
void k2pdfopt_set_params(int bb_width, int bb_height, \
double font_size, double page_margin, \
double line_space, double word_space, \
int wrapping, int straighten, int justification, \
int columns, double contrast, int rotation);
void k2pdfopt_mupdf_reflow(fz_document *doc, fz_page *page, fz_context *ctx);
void k2pdfopt_djvu_reflow(ddjvu_page_t *page, ddjvu_context_t *ctx, ddjvu_render_mode_t mode, ddjvu_format_t *fmt);
void k2pdfopt_rfbmp_size(int *width, int *height);
void k2pdfopt_rfbmp_ptr(unsigned char** bmp_ptr_ptr);
void k2pdfopt_rfbmp_zoom(double *zoom);
#endif

View File

@@ -21,6 +21,7 @@ fi
# stop cvm
killall -stop cvm
export LD_LIBRARY_PATH=`pwd`/libs
# finally call reader
./reader.lua "$1" 2> /mnt/us/kindlepdfviewer/crash.log || cat /mnt/us/kindlepdfviewer/crash.log

View File

@@ -28,6 +28,7 @@
#include "pdf.h"
#include "mupdfimg.h"
#include "djvu.h"
#include "pic.h"
#include "cre.h"
#include "einkfb.h"
#include "input.h"
@@ -96,6 +97,7 @@ int main(int argc, char **argv) {
luaopen_einkfb(L);
luaopen_pdf(L);
luaopen_djvu(L);
luaopen_pic(L);
luaopen_cre(L);
luaopen_input(L);
luaopen_util(L);

View File

@@ -0,0 +1,14 @@
diff --git a/crengine/src/lvdocview.cpp b/crengine/src/lvdocview.cpp
index e7a355a..e1178de 100755
--- a/crengine/src/lvdocview.cpp
+++ b/crengine/src/lvdocview.cpp
@@ -4539,7 +4539,8 @@ void LVDocView::getCurrentPageLinks(ldomXRangeList & list) {
if (_list[i]->getStart().getNode() == elem)
return true; // don't add, duplicate found!
}
- _list.add(new ldomXRange(elem->getChildNode(0)));
+ ldomNode * node = elem->getChildNode(0);
+ if ( node ) _list.add(new ldomXRange(node));
}
return true;
}

64
pdf.c
View File

@@ -58,6 +58,7 @@ static size_t msize_min;
static size_t msize_iniz;
static int is_realloc=0;
#if 0
char* readable_fs(double size/*in bytes*/, char *buf) {
int i = 0;
const char* units[] = {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
@@ -68,6 +69,7 @@ char* readable_fs(double size/*in bytes*/, char *buf) {
sprintf(buf, "%.*f %s", i, size, units[i]);
return buf;
}
#endif
static void resetMsize(){
msize_iniz = msize;
@@ -509,6 +511,66 @@ static int closePage(lua_State *L) {
return 0;
}
static int reflowPage(lua_State *L) {
PdfPage *page = (PdfPage*) luaL_checkudata(L, 1, "pdfpage");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
int width = luaL_checkint(L, 4); // framebuffer size
int height = luaL_checkint(L, 5);
double font_size = luaL_checknumber(L, 6);
double page_margin = luaL_checknumber(L, 7);
double line_spacing = luaL_checknumber(L, 8);
double word_spacing = luaL_checknumber(L, 9);
int text_wrap = luaL_checkint(L, 10);
int straighten = luaL_checkint(L, 11);
int justification = luaL_checkint(L, 12);
int columns = luaL_checkint(L, 13);
double contrast = luaL_checknumber(L, 14);
int rotation = luaL_checknumber(L, 15);
k2pdfopt_set_params(width, height, font_size, page_margin, line_spacing, word_spacing, \
text_wrap, straighten, justification, columns, contrast, rotation);
k2pdfopt_mupdf_reflow(page->doc->xref, page->page, page->doc->context);
k2pdfopt_rfbmp_size(&width, &height);
k2pdfopt_rfbmp_zoom(&dc->zoom);
lua_pushnumber(L, (double)width);
lua_pushnumber(L, (double)height);
lua_pushnumber(L, (double)dc->zoom);
return 3;
}
static int drawReflowedPage(lua_State *L) {
uint8_t *pmptr = NULL;
PdfPage *page = (PdfPage*) luaL_checkudata(L, 1, "pdfpage");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 3, "blitbuffer");
uint8_t *bbptr = bb->data;
k2pdfopt_rfbmp_ptr(&pmptr);
int x_offset = 0;
int y_offset = 0;
bbptr += bb->pitch * y_offset;
int x, y;
for(y = y_offset; y < bb->h; y++) {
for(x = x_offset/2; x < (bb->w/2); x++) {
int p = x*2 - x_offset;
bbptr[x] = (((pmptr[p + 1] & 0xF0) >> 4) | (pmptr[p] & 0xF0)) ^ 0xFF;
}
bbptr += bb->pitch;
pmptr += bb->w;
if (bb->w & 1) {
bbptr[x] = 255 - (pmptr[x*2] & 0xF0);
}
}
return 0;
}
static int drawPage(lua_State *L) {
fz_pixmap *pix;
fz_device *dev;
@@ -655,6 +717,8 @@ static const struct luaL_Reg pdfpage_meth[] = {
{"getPageLinks", getPageLinks},
{"close", closePage},
{"__gc", closePage},
{"reflow", reflowPage},
{"rfdraw", drawReflowedPage},
{"draw", drawPage},
{NULL, NULL}
};

280
pic.c Normal file
View File

@@ -0,0 +1,280 @@
/*
KindlePDFViewer: Picture viewer abstraction for Lua
Copyright (C) 2012 Tigran Aivazian <tigran@bibles.org.uk>
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 <string.h>
#include <stdio.h>
#include <math.h>
#include "blitbuffer.h"
#include "drawcontext.h"
#include "pic.h"
#include "pic_jpeg.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
typedef struct PicDocument {
int width;
int height;
int components;
uint8_t *image;
} PicDocument;
typedef struct PicPage {
int width;
int height;
uint8_t *image;
PicDocument *doc;
} PicPage;
/* Uses luminance match for approximating the human perception of colour,
* as per http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
* L = 0.299*Red + 0.587*Green + 0.114*Blue */
static uint8_t *rgbToGrayscale(uint8_t *image, int width, int height)
{
int x, y;
uint8_t *buf = malloc(width*height+1);
if (!buf) return NULL;
for (x=0; x<width; x++)
for (y=0; y<height; y++) {
int pos = 3*(x+y*width);
buf[x+y*width] = (uint8_t)(0.299*((double)image[pos]) + 0.587*((double)image[pos+1]) + 0.114*((double)image[pos+2]));
}
return buf;
}
static int openDocument(lua_State *L) {
int width, height, components;
const char *filename = luaL_checkstring(L, 1);
PicDocument *doc = (PicDocument*) lua_newuserdata(L, sizeof(PicDocument));
luaL_getmetatable(L, "picdocument");
lua_setmetatable(L, -2);
uint8_t *raw_image = jpegLoadFile(filename, &width, &height, &components);
if (!raw_image)
return luaL_error(L, "Cannot open jpeg file");
doc->image = NULL;
if (components == 1)
doc->image = raw_image;
else if (components == 3) {
uint8_t *gray_image = rgbToGrayscale(raw_image, width, height);
free(raw_image);
if (!gray_image)
return luaL_error(L, "Cannot convert to grayscale");
else
doc->image = gray_image;
} else {
free(raw_image);
return luaL_error(L, "Unsupported image format");
}
doc->width = width;
doc->height = height;
doc->components = components;
return 1;
}
static int openPage(lua_State *L) {
PicDocument *doc = (PicDocument*) luaL_checkudata(L, 1, "picdocument");
PicPage *page = (PicPage*) lua_newuserdata(L, sizeof(PicPage));
luaL_getmetatable(L, "picpage");
lua_setmetatable(L, -2);
page->width = doc->width;
page->height = doc->height;
page->image = doc->image;
page->doc = doc;
return 1;
}
static int getNumberOfPages(lua_State *L) {
lua_pushinteger(L, 1);
return 1;
}
static int getOriginalPageSize(lua_State *L) {
PicDocument *doc = (PicDocument*) luaL_checkudata(L, 1, "picdocument");
lua_pushnumber(L, doc->width);
lua_pushnumber(L, doc->height);
lua_pushnumber(L, doc->components);
return 3;
}
/* re-entrant */
static int closeDocument(lua_State *L) {
PicDocument *doc = (PicDocument*) luaL_checkudata(L, 1, "picdocument");
if (doc->image != NULL) {
free(doc->image);
doc->image = NULL;
}
return 0;
}
/* uses very simple nearest neighbour scaling */
static void scaleImage(uint8_t *result, uint8_t *image, int width, int height, int new_width, int new_height)
{
int x, y;
for (x=0; x<new_width; x++)
for (y=0; y<new_height; y++)
result[x+y*new_width] = image[(x*width/new_width) + (y*height/new_height)*width];
}
static int drawPage(lua_State *L) {
PicPage *page = (PicPage*) luaL_checkudata(L, 1, "picpage");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 3, "blitbuffer");
int x_offset = MAX(0, dc->offset_x);
int y_offset = MAX(0, dc->offset_y);
int x, y;
int img_width = page->width;
int img_height = page->height;
int img_new_width = bb->w;
int img_new_height = bb->h;
unsigned char adjusted_low[16], adjusted_high[16];
int i, adjust_pixels = 0;
/* prepare the tables for adjusting the intensity of pixels */
if (dc->gamma != -1.0) {
for (i=0; i<16; i++) {
adjusted_low[i] = MIN(15, (unsigned char)floorf(dc->gamma * (float)i));
adjusted_high[i] = adjusted_low[i] << 4;
}
adjust_pixels = 1;
}
uint8_t *scaled_image = malloc(img_new_width*img_new_height+1);
if (!scaled_image)
return 0;
scaleImage(scaled_image, page->image, img_width, img_height, img_new_width, img_new_height);
uint8_t *bbptr = bb->data;
uint8_t *pmptr = scaled_image;
bbptr += bb->pitch * y_offset;
for(y = y_offset; y < img_new_height; y++) {
for(x = x_offset/2; x < (img_new_width / 2); x++) {
int p = x*2 - x_offset;
unsigned char low = 15 - (pmptr[p + 1] >> 4);
unsigned char high = 15 - (pmptr[p] >> 4);
if (adjust_pixels)
bbptr[x] = adjusted_high[high] | adjusted_low[low];
else
bbptr[x] = (high << 4) | low;
}
if (img_new_width & 1)
bbptr[x] = 255 - (pmptr[x*2] & 0xF0);
bbptr += bb->pitch;
pmptr += img_new_width;
}
free(scaled_image);
return 0;
}
static int getCacheSize(lua_State *L) {
lua_pushnumber(L, 0);
return 1;
}
static int cleanCache(lua_State *L) {
return 0;
}
static int getPageSize(lua_State *L) {
PicPage *page = (PicPage*) luaL_checkudata(L, 1, "picpage");
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
lua_pushnumber(L, dc->zoom * page->width);
lua_pushnumber(L, dc->zoom * page->height);
return 2;
}
static int closePage(lua_State *L) {
return 0;
}
/* unsupported so fake it */
static int getUsedBBox(lua_State *L) {
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;
}
static int getTableOfContent(lua_State *L) {
lua_newtable(L);
return 1;
}
static const struct luaL_Reg pic_func[] = {
{"openDocument", openDocument},
{NULL, NULL}
};
static const struct luaL_Reg picdocument_meth[] = {
{"openPage", openPage},
{"getPages", getNumberOfPages},
{"getToc", getTableOfContent},
{"getOriginalPageSize", getOriginalPageSize},
{"getCacheSize", getCacheSize},
{"close", closeDocument},
{"cleanCache", cleanCache},
{"__gc", closeDocument},
{NULL, NULL}
};
static const struct luaL_Reg picpage_meth[] = {
{"getSize", getPageSize},
{"getUsedBBox", getUsedBBox},
{"close", closePage},
{"__gc", closePage},
{"draw", drawPage},
{NULL, NULL}
};
int luaopen_pic(lua_State *L) {
luaL_newmetatable(L, "picdocument");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);
lua_settable(L, -3);
luaL_register(L, NULL, picdocument_meth);
lua_pop(L, 1);
luaL_newmetatable(L, "picpage");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);
lua_settable(L, -3);
luaL_register(L, NULL, picpage_meth);
lua_pop(L, 1);
luaL_register(L, "pic", pic_func);
return 1;
}

27
pic.h Normal file
View File

@@ -0,0 +1,27 @@
/*
KindlePDFViewer: JPEG Picture viewer abstraction for Lua
Copyright (C) 2012 Tigran Aivazian <tigran@bibles.org.uk>
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 _PIC_H
#define _PIC_H
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
int luaopen_pic(lua_State *L);
#endif

84
pic_jpeg.c Normal file
View File

@@ -0,0 +1,84 @@
/*
KindlePDFViewer: JPEG support for Picture Viewer module
Copyright (C) 2012 Tigran Aivazian <tigran@bibles.org.uk>
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 <stdint.h>
#include <string.h>
#include <setjmp.h>
#include <stdio.h>
#include "jpeglib.h"
struct my_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
typedef struct my_error_mgr *my_error_ptr;
METHODDEF(void) my_error_exit(j_common_ptr cinfo)
{
my_error_ptr myerr = (my_error_ptr) cinfo->err;
(*cinfo->err->output_message) (cinfo);
longjmp(myerr->setjmp_buffer, 1);
}
uint8_t *jpegLoadFile(const char *fname, int *width, int *height, int *components)
{
struct jpeg_decompress_struct cinfo;
struct my_error_mgr jerr;
FILE *infile;
JSAMPARRAY buffer;
int row_stride;
long cont;
JSAMPLE *image_buffer;
if ((infile = fopen(fname, "r")) == NULL) return NULL;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return NULL;
}
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
(void) jpeg_read_header(&cinfo, TRUE);
(void) jpeg_start_decompress(&cinfo);
row_stride = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) & cinfo, JPOOL_IMAGE, row_stride, 1);
image_buffer = (JSAMPLE *) malloc(cinfo.image_width*cinfo.image_height*cinfo.output_components);
if (image_buffer == NULL) return NULL;
*width = cinfo.image_width;
*height = cinfo.image_height;
//cont = cinfo.output_height - 1;
cont = 0;
while (cinfo.output_scanline < cinfo.output_height) {
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
memcpy(image_buffer + cinfo.image_width * cinfo.output_components * cont, buffer[0], row_stride);
cont++;
}
(void) jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
*components = cinfo.output_components;
return (uint8_t *)image_buffer;
}

30
pic_jpeg.h Normal file
View File

@@ -0,0 +1,30 @@
/*
KindlePDFViewer: Interface to JPEG module for picture viewer
Copyright (C) 2012 Tigran Aivazian <tigran@bibles.org.uk>
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 _PIC_JPEG_H
#define _PIC_JPEG_H
/* each new image format must provide fmtLoadFile() function which
* performs the following:
* 1. Opens the file 'filename'
* 2. Reads the image data from it into a buffer allocated with malloc()
* 3. Fills in the image *width, *height and *components (number of bytes per pixel)
* 4. Closes the file
* 5. Returns the pointer to the image data
*/
extern uint8_t *jpegLoadFile(const char *fname, int *width, int *height, int *components);
#endif

11
picviewer.lua Normal file
View File

@@ -0,0 +1,11 @@
require "unireader"
PICViewer = UniReader:new{}
function PICViewer:open(filename)
ok, self.doc = pcall(pic.openDocument, filename)
if not ok then
return ok, self.doc
end
return ok
end

View File

@@ -6,7 +6,6 @@ require "ui/readerui"
require "ui/filechooser"
require "ui/infomessage"
require "document/document"
require "alt_getopt"
function showReader(file, pass)
local document = DocumentRegistry:openDocument(file)
@@ -74,11 +73,8 @@ function showusage()
print("usage: ./reader.lua [OPTION] ... path")
print("Read all the books on your E-Ink reader")
print("")
print("-p, --password=PASSWORD set password for reading PDF document")
print("-G, --gamma=GAMMA set gamma correction")
print(" (floating point notation, e.g. \"1.5\")")
print("-d, --debug start in debug mode")
print("-h, --help show this usage help")
print("-d start in debug mode")
print("-h show this usage help")
print("")
print("If you give the name of a directory instead of a file path, a file")
print("chooser will show up and let you select a file")
@@ -90,21 +86,17 @@ function showusage()
return
end
optarg, optind = alt_getopt.get_opts(ARGV, "p:G:hg:dg:", longopts)
if optarg["h"] then
if ARGV[1] == "-h" then
return showusage()
end
if not optarg["d"] then
local argidx = 1
if ARGV[1] == "-d" then
argidx = argidx + 1
else
DEBUG = function() end
end
if optarg["G"] ~= nil then
globalgamma = optarg["G"]
end
if Device.isKindle4() then
-- remove menu item shortcut for K4
Menu.is_enable_shortcut = false
@@ -125,11 +117,11 @@ Screen.native_rotation_mode = Screen.cur_rotation_mode
--87712cf0e43fed624f8a9f610be42b1fe174b9fe
if ARGV[optind] then
if lfs.attributes(ARGV[optind], "mode") == "directory" then
showFileManager(ARGV[optind])
elseif lfs.attributes(ARGV[optind], "mode") == "file" then
showReader(ARGV[optind], optarg["p"])
if ARGV[argidx] then
if lfs.attributes(ARGV[argidx], "mode") == "directory" then
showFileManager(ARGV[argidx])
elseif lfs.attributes(ARGV[argidx], "mode") == "file" then
showReader(ARGV[argidx], optarg["p"])
end
UIManager:run()
elseif last_file and lfs.attributes(last_file, "mode") == "file" then

BIN
resources/jpeg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
resources/jpg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

118
utils/pdfattach Executable file
View File

@@ -0,0 +1,118 @@
#!/bin/bash
#
# pdfattach --- embed specified file(s) in a specified PDF file
# Requires pdfLaTeX and attachfile.sty package to run
# Returns 0 on success or >0 on error
#
# Written by Tigran Aivazian <tigran@bibles.org.uk>
#
progname=$(basename $0)
function escape_tex_specialchars()
{
local txt=$1
local res=$(echo "$txt" | sed -e "s%_%\\\_%g" -e "s%&%\\\&%g")
echo "$res"
}
function usage()
{
echo "Usage: $progname -o file.pdf file1.djvu [file2.mp3] ..."
exit 1
}
if (! getopts ":o:" opt); then
echo "$progname: Missing options." >&2
usage
fi
if ! type pdflatex > /dev/null 2>&1 ; then
echo "$progname: pdfLaTeX program is required." >&2
exit 1
fi
if ! kpsewhich attachfile.sty > /dev/null 2>&1 ; then
echo "$progname: attachfile.sty package is required." >&2
exit 1
fi
declare outfile=""
declare -a infiles=()
declare -a infiles_texclean=()
declare -a infilesize=()
declare -i infcount=0 outfcount=0 totalsize=0
while getopts ":o:" opt; do
case $opt in
o)
outfile=$(readlink -f "$OPTARG")
((outfcount++))
;;
\?)
echo "$progname: Invalid option: -$OPTARG" >&2
usage
;;
:)
echo "$progname: Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
shift $((OPTIND-1))
numargs=$#
for ((i=1 ; i <= $numargs ; i++))
do
fullname=$(readlink -f "$1")
if [ ! -r "$fullname" ] ; then
echo "$progname: cannot access the file \"$fullname\"" >&2
usage
fi
infiles[$infcount]="$fullname"
infiles_texclean[$infcount]=$(escape_tex_specialchars $(basename "${infiles[$infcount]}"))
infilesize[$infcount]=$(stat --print="%s" "$fullname")
((totalsize=totalsize+${infilesize[$infcount]}))
((infcount++))
shift
done
if ((infcount == 0)) ; then
echo "$progname: No input file(s) specified." >&2
usage
fi
if ((outfcount != 1)) ; then
echo "$progname: One (and only one) output file must be specified." >&2
usage
fi
workdir=$(mktemp --tmpdir -d pdfattach.XXXXXX)
cd $workdir
> tmp.tex
# emit TeX preamble
echo -E "\documentclass{book}" >> tmp.tex
echo -E "\usepackage[margin={1mm},papersize={9cm,12cm}]{geometry}" >> tmp.tex
echo -E "\usepackage{hyperref,attachfile}" >> tmp.tex
echo -E "\begin{document}" >> tmp.tex
echo -E "\tolerance=10000\pagestyle{empty}\fontsize{7}{13}\selectfont" >> tmp.tex
# emit the list of all files
for ((i = 0 ; i < ${#infiles[*]} ; i++));
do
echo -E "\noindent \hyperlink{L$i}{$((i+1))/${infcount}} \texttt{${infiles_texclean[$i]}} (${infilesize[$i]} bytes)" >> tmp.tex
echo >> tmp.tex
done
echo -E "\noindent Total size $totalsize bytes\newpage" >> tmp.tex
# now emit all the attachments, one per page
for ((i = 0 ; i < ${#infiles[*]} ; i++));
do
echo -E "\noindent\hypertarget{L$i}$((i+1))/${infcount}\\\\\texttt{${infiles_texclean[$i]}} (\textattachfile[color={0 0 0}]{${infiles[$i]}}{${infilesize[$i]} bytes})\newpage" >> tmp.tex
done
echo -E "\end{document}" >> tmp.tex
pdflatex -halt-on-error tmp.tex > /dev/null && mv tmp.pdf "$outfile"
cd - > /dev/null
rm -rf $workdir