mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #517 from houqp/new_ui_code
merge latest changes from master branch
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,6 +4,9 @@ lua-*
|
||||
.reader.kpdfview.lua
|
||||
mupdf-thirdparty.zip
|
||||
djvulibre*
|
||||
crash.log
|
||||
.vimrc
|
||||
git-rev
|
||||
kpdfview
|
||||
slider_watcher
|
||||
*.o
|
||||
|
||||
65
Makefile
65
Makefile
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
277
blitbuffer.c
277
blitbuffer.c
@@ -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
98
cre.cpp
@@ -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
74
djvu.c
@@ -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
105
extr.c
Normal 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;
|
||||
}
|
||||
@@ -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
7015
k2pdfopt.c
Normal file
File diff suppressed because it is too large
Load Diff
41
k2pdfopt.h
Normal file
41
k2pdfopt.h
Normal 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
|
||||
|
||||
1
kpdf.sh
1
kpdf.sh
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
14
kpvcrlib/lvdocview-getCurrentPageLinks.patch
Normal file
14
kpvcrlib/lvdocview-getCurrentPageLinks.patch
Normal 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
64
pdf.c
@@ -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
280
pic.c
Normal 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
27
pic.h
Normal 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
84
pic_jpeg.c
Normal 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
30
pic_jpeg.h
Normal 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
11
picviewer.lua
Normal 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
|
||||
32
reader.lua
32
reader.lua
@@ -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
BIN
resources/jpeg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
resources/jpg.png
Normal file
BIN
resources/jpg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
118
utils/pdfattach
Executable file
118
utils/pdfattach
Executable 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
|
||||
Reference in New Issue
Block a user