mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Merge pull request #117 from traycold/master
updated version of mupdf and some refactoring on help page
This commit is contained in:
14
Makefile
14
Makefile
@@ -113,7 +113,7 @@ slider_watcher: slider_watcher.c
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
ft.o: %.o: %.c
|
||||
$(CC) -c $(KPDFREADER_CFLAGS) -I$(FREETYPEDIR)/include $< -o $@
|
||||
$(CC) -c $(KPDFREADER_CFLAGS) -I$(FREETYPEDIR)/include -I$(MUPDFDIR)/fitz $< -o $@
|
||||
|
||||
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 $@
|
||||
@@ -130,7 +130,7 @@ lfs.o: $(LFSDIR)/src/lfs.c
|
||||
fetchthirdparty:
|
||||
-rm -Rf lua lua-5.1.4
|
||||
-rm -Rf mupdf/thirdparty
|
||||
test -d mupdf && (cd mupdf; git checkout .)
|
||||
test -d mupdf && (cd mupdf; git checkout .) || echo warn: mupdf folder not found
|
||||
git submodule init
|
||||
git submodule update
|
||||
ln -sf kpvcrlib/crengine/cr3gui/data data
|
||||
@@ -155,10 +155,10 @@ cleanthirdparty:
|
||||
make -C $(LUADIR) clean
|
||||
make -C $(MUPDFDIR) clean
|
||||
#make -C $(CRENGINEDIR)/thirdparty/antiword clean
|
||||
make -C $(CRENGINEDIR)/thirdparty/chmlib clean
|
||||
make -C $(CRENGINEDIR)/thirdparty/libpng clean
|
||||
make -C $(CRENGINEDIR)/crengine clean
|
||||
make -C $(KPVCRLIGDIR) clean
|
||||
test -d $(CRENGINEDIR)/thirdparty/chmlib && make -C $(CRENGINEDIR)/thirdparty/chmlib clean || echo warn: chmlib folder not found
|
||||
test -d $(CRENGINEDIR)/thirdparty/libpng && (make -C $(CRENGINEDIR)/thirdparty/libpng clean) || echo warn: chmlib folder not found
|
||||
test -d $(CRENGINEDIR)/crengine && (make -C $(CRENGINEDIR)/crengine clean) || echo warn: chmlib folder not found
|
||||
test -d $(KPVCRLIGDIR) && (make -C $(KPVCRLIGDIR) clean) || echo warn: chmlib folder not found
|
||||
-rm -rf $(DJVUDIR)/build
|
||||
-rm -f $(MUPDFDIR)/fontdump.host
|
||||
-rm -f $(MUPDFDIR)/cmapdump.host
|
||||
@@ -175,7 +175,7 @@ $(MUPDFDIR)/cmapdump.host:
|
||||
|
||||
$(MUPDFLIBS) $(THIRDPARTYLIBS): $(MUPDFDIR)/cmapdump.host $(MUPDFDIR)/fontdump.host
|
||||
# build only thirdparty libs, libfitz and pdf utils, which will care for libmupdf.a being built
|
||||
CFLAGS="$(CFLAGS) -DNOBUILTINFONT" make -C mupdf CC="$(CC)" CMAPDUMP=cmapdump.host FONTDUMP=fontdump.host MUPDF= XPS_APPS= verbose=1
|
||||
CFLAGS="$(CFLAGS) -DNOBUILTINFONT" make -C mupdf CC="$(CC)" CMAPDUMP=cmapdump.host FONTDUMP=fontdump.host MUPDF= MU_APPS= BUSY_APP= XPS_APPS= verbose=1
|
||||
|
||||
$(DJVULIBS):
|
||||
-mkdir $(DJVUDIR)/build
|
||||
|
||||
32
blitbuffer.c
32
blitbuffer.c
@@ -75,7 +75,7 @@ static int blitFullToBuffer(lua_State *L) {
|
||||
if(src->w != dst->w || src->h != dst->h) {
|
||||
return luaL_error(L, "blitbuffer size must be framebuffer size!");
|
||||
}
|
||||
|
||||
|
||||
memcpy(dst->data, src->data, src->pitch * src->h);
|
||||
|
||||
return 0;
|
||||
@@ -146,8 +146,8 @@ static int blitToBuffer(lua_State *L) {
|
||||
|
||||
if(xdest & 1) {
|
||||
/* this will render the leftmost column */
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
xdest / 2);
|
||||
srcptr = (uint8_t*)(src->data +
|
||||
yoffs * src->pitch +
|
||||
@@ -172,8 +172,8 @@ static int blitToBuffer(lua_State *L) {
|
||||
w--;
|
||||
}
|
||||
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
xdest / 2);
|
||||
srcptr = (uint8_t*)(src->data +
|
||||
yoffs * src->pitch +
|
||||
@@ -243,8 +243,8 @@ static int addblitToBuffer(lua_State *L) {
|
||||
|
||||
if(xdest & 1) {
|
||||
/* this will render the leftmost column */
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
xdest / 2);
|
||||
srcptr = (uint8_t*)(src->data +
|
||||
yoffs * src->pitch +
|
||||
@@ -269,8 +269,8 @@ static int addblitToBuffer(lua_State *L) {
|
||||
w--;
|
||||
}
|
||||
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
ydest * dst->pitch +
|
||||
xdest / 2);
|
||||
srcptr = (uint8_t*)(src->data +
|
||||
yoffs * src->pitch +
|
||||
@@ -332,8 +332,8 @@ static int paintRect(lua_State *L) {
|
||||
/* This will render the leftmost column
|
||||
* in the case when x is odd. After this,
|
||||
* x will become even. */
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
y * dst->pitch +
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
y * dst->pitch +
|
||||
x / 2);
|
||||
for(cy = 0; cy < h; cy++) {
|
||||
*dstptr &= 0xF0;
|
||||
@@ -343,19 +343,19 @@ static int paintRect(lua_State *L) {
|
||||
x++;
|
||||
w--;
|
||||
}
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
y * dst->pitch +
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
y * dst->pitch +
|
||||
x / 2);
|
||||
for(cy = 0; cy < h; cy++) {
|
||||
memset(dstptr, c | (c << 4), w / 2);
|
||||
dstptr += dst->pitch;
|
||||
}
|
||||
if(w & 1) {
|
||||
/* This will render the rightmost column
|
||||
/* This will render the rightmost column
|
||||
* in the case when (w & 1) && !(x & 1) or
|
||||
* !(w & 1) && (x & 1). */
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
y * dst->pitch +
|
||||
dstptr = (uint8_t*)(dst->data +
|
||||
y * dst->pitch +
|
||||
(x + w) / 2);
|
||||
for(cy = 0; cy < h; cy++) {
|
||||
*dstptr &= 0x0F;
|
||||
|
||||
@@ -24,7 +24,7 @@ function Keydef:new(keycode,modifier,descr)
|
||||
end
|
||||
|
||||
function Keydef:display()
|
||||
return ((self.modifier and self.modifier.."+") or "")..(self.descr or "")
|
||||
return (self.modifier or "")..(self.descr or "")
|
||||
end
|
||||
|
||||
function Keydef:tostring()
|
||||
@@ -121,7 +121,7 @@ function Commands:_addImpl(keydef,help,func,keygroup)
|
||||
if keydef.modifier==MOD_ANY then
|
||||
self:addGroup(keygroup or keydef.descr,{Keydef:new(keydef.keycode,nil), Keydef:new(keydef.keycode,MOD_SHIFT), Keydef:new(keydef.keycode,MOD_ALT)},help,func)
|
||||
elseif keydef.modifier==MOD_SHIFT_OR_ALT then
|
||||
self:addGroup(keygroup or (MOD_SHIFT.."|"..MOD_ALT.."+"..(keydef.descr or "")),{Keydef:new(keydef.keycode,MOD_SHIFT), Keydef:new(keydef.keycode,MOD_ALT)},help,func)
|
||||
self:addGroup(keygroup or (MOD_SHIFT..MOD_ALT..(keydef.descr or "")),{Keydef:new(keydef.keycode,MOD_SHIFT), Keydef:new(keydef.keycode,MOD_ALT)},help,func)
|
||||
else
|
||||
local command = self.map[keydef]
|
||||
if command == nil then
|
||||
|
||||
1
font.lua
1
font.lua
@@ -57,6 +57,7 @@ function Font:getFace(font, size)
|
||||
return nil
|
||||
end
|
||||
self.faces[font..size] = face
|
||||
--print("getFace, found: "..realname.." size:"..size)
|
||||
end
|
||||
return { size = size, ftface = face, hash = font..size }
|
||||
end
|
||||
|
||||
27
ft.c
27
ft.c
@@ -23,8 +23,7 @@
|
||||
#include "blitbuffer.h"
|
||||
|
||||
/* for font access: */
|
||||
#include <fitz/fitz.h>
|
||||
#include <pdf/mupdf.h>
|
||||
#include <pdf/mupdf-internal.h>
|
||||
|
||||
#include "ft.h"
|
||||
|
||||
@@ -97,8 +96,12 @@ static int renderGlyph(lua_State *L) {
|
||||
lua_setfield(L, -2, "l");
|
||||
lua_pushinteger(L, (*face)->glyph->bitmap_top);
|
||||
lua_setfield(L, -2, "t");
|
||||
lua_pushinteger(L, (*face)->glyph->metrics.horiAdvance >> 6);
|
||||
lua_setfield(L, -2, "r");
|
||||
lua_pushinteger(L, (*face)->glyph->advance.x >> 6);
|
||||
lua_setfield(L, -2, "ax");
|
||||
lua_pushinteger(L, (*face)->glyph->advance.y >> 6);
|
||||
lua_setfield(L, -2, "ay");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -126,6 +129,25 @@ static int getKerning(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getHeightAndAscender(lua_State *L) {
|
||||
FT_Face *face = (FT_Face*) luaL_checkudata(L, 1, "ft_face");
|
||||
|
||||
double pixels_height,pixels_ascender;
|
||||
double em_size, y_scale;
|
||||
|
||||
/* compute floating point scale factors */
|
||||
em_size = 1.0 * (*face)->units_per_EM;
|
||||
y_scale = (*face)->size->metrics.y_ppem / em_size;
|
||||
|
||||
/* convert design distances to floating point pixels */
|
||||
pixels_height = (*face)->height * y_scale;
|
||||
pixels_ascender = (*face)->ascender * y_scale;
|
||||
|
||||
lua_pushnumber(L, pixels_height);
|
||||
lua_pushnumber(L, pixels_ascender);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int doneFace(lua_State *L) {
|
||||
FT_Face *face = (FT_Face*) luaL_checkudata(L, 1, "ft_face");
|
||||
if(*face != NULL) {
|
||||
@@ -142,6 +164,7 @@ static const struct luaL_Reg ft_face_meth[] = {
|
||||
{"renderGlyph", renderGlyph},
|
||||
{"hasKerning", hasKerning},
|
||||
{"getKerning", getKerning},
|
||||
{"getHeightAndAscender", getHeightAndAscender},
|
||||
{"done", doneFace},
|
||||
{"__gc", doneFace},
|
||||
{NULL, NULL}
|
||||
|
||||
53
helppage.lua
53
helppage.lua
@@ -47,34 +47,63 @@ function HelpPage:show(ypos, height, commands)
|
||||
end
|
||||
end
|
||||
table.sort(self.commands,function(w1,w2) return w1.order<w2.order end)
|
||||
local perpage = math.floor( (height - 1 * (self.ffsize + 5)) / self.spacing )
|
||||
local pagedirty = true
|
||||
|
||||
local face_height, face_ascender = self.face.ftface:getHeightAndAscender()
|
||||
--local hface_height, hface_ascender = self.hface.ftface:getHeightAndAscender()
|
||||
local fface_height, fface_ascender = self.fface.ftface:getHeightAndAscender()
|
||||
--print(face_height.."-"..face_ascender)
|
||||
--print(fface_height.."-"..fface_ascender)
|
||||
face_height = math.ceil(face_height)
|
||||
face_ascender = math.ceil(face_ascender)
|
||||
fface_height = math.ceil(fface_height)
|
||||
fface_ascender = math.ceil(fface_ascender)
|
||||
local spacing = face_height + 5
|
||||
|
||||
local perpage = math.floor( (height - ypos - 1 * (fface_height + 5)) / spacing )
|
||||
local is_pagedirty = true
|
||||
|
||||
while true do
|
||||
if pagedirty then
|
||||
if is_pagedirty then
|
||||
fb.bb:paintRect(0, ypos, fb.bb:getWidth(), height, 0)
|
||||
local c
|
||||
local max_x = 0
|
||||
for c = 1, perpage do
|
||||
local x = 5
|
||||
local i = (self.page - 1) * perpage + c
|
||||
if i <= self.items then
|
||||
local pen_x = renderUtf8Text(fb.bb, 5, ypos + self.spacing*c, self.face, self.commands[i].shortcut, true)
|
||||
max_x = math.max(max_x, pen_x)
|
||||
local key = self.commands[i].shortcut
|
||||
for _k,aMod in pairs(MOD_TABLE) do
|
||||
local modStart, modEnd = key:find(aMod.v)
|
||||
print("key:"..key.." v:"..aMod.v.." d:"..aMod.d.." modstart:"..(modStart or "nil"))
|
||||
if(modStart ~= nil) then
|
||||
key = key:sub(1,modStart-1)..key:sub(modEnd+1)
|
||||
local box = sizeUtf8Text( x, fb.bb:getWidth(), self.face, aMod.d, true)
|
||||
fb.bb:paintRect(x, ypos + spacing*c - box.y_top, box.x, box.y_top + box.y_bottom, 4)
|
||||
local pen_x = renderUtf8Text(fb.bb, x, ypos + spacing*c, self.face, aMod.d.." + ", true)
|
||||
x = x + pen_x
|
||||
max_x = math.max(max_x, pen_x)
|
||||
end
|
||||
end
|
||||
print("key:"..key)
|
||||
local box = sizeUtf8Text( x, fb.bb:getWidth(), self.face, key , true)
|
||||
fb.bb:paintRect(x, ypos + spacing*c - box.y_top, box.x, box.y_top + box.y_bottom, 4)
|
||||
local pen_x = renderUtf8Text(fb.bb, x, ypos + spacing*c, self.face, key, true)
|
||||
x = x + pen_x
|
||||
max_x = math.max(max_x, x)
|
||||
end
|
||||
end
|
||||
for c = 1, perpage do
|
||||
local i = (self.page - 1) * perpage + c
|
||||
if i <= self.items then
|
||||
renderUtf8Text(fb.bb, max_x + 20, ypos + self.spacing*c, self.hface, self.commands[i].help, true)
|
||||
renderUtf8Text(fb.bb, max_x + 20, ypos + spacing*c, self.hface, self.commands[i].help, true)
|
||||
end
|
||||
end
|
||||
renderUtf8Text(fb.bb, 5, height - math.floor(self.ffsize * 0.4), self.fface,
|
||||
renderUtf8Text(fb.bb, 5, height - fface_height + fface_ascender - 5, self.fface,
|
||||
"Page "..self.page.." of "..math.ceil(self.items / perpage).." - click Back to close this page", true)
|
||||
markerdirty = true
|
||||
end
|
||||
if pagedirty then
|
||||
if is_pagedirty then
|
||||
fb:refresh(0, 0, ypos, fb.bb:getWidth(), height)
|
||||
pagedirty = false
|
||||
is_pagedirty = false
|
||||
end
|
||||
|
||||
local ev = input.saveWaitForEvent()
|
||||
@@ -84,12 +113,12 @@ function HelpPage:show(ypos, height, commands)
|
||||
if ev.code == KEY_PGFWD then
|
||||
if self.page < (self.items / perpage) then
|
||||
self.page = self.page + 1
|
||||
pagedirty = true
|
||||
is_pagedirty = true
|
||||
end
|
||||
elseif ev.code == KEY_PGBCK then
|
||||
if self.page > 1 then
|
||||
self.page = self.page - 1
|
||||
pagedirty = true
|
||||
is_pagedirty = true
|
||||
end
|
||||
elseif ev.code == KEY_BACK or ev.code == KEY_HOME then
|
||||
return nil
|
||||
|
||||
@@ -92,6 +92,13 @@ function InputBox:delChar()
|
||||
self.input_string:sub(cur_index+1, -1)
|
||||
self:refreshText()
|
||||
self.input_cur_x = self.input_cur_x - self.fwidth
|
||||
|
||||
--fill last character with blank rectangle
|
||||
fb.bb:paintRect(self.input_cur_x, self.input_start_y-19,
|
||||
self.fwidth, self.fheight, self.input_bg)
|
||||
fb:refresh(1, self.input_cur_x, self.input_start_y-19, self.fwidth, self.fheight)
|
||||
self.input_string = self.input_string:sub(0,-2)
|
||||
|
||||
-- draw new cursor
|
||||
self.cursor:moveHorizontal(-self.fwidth)
|
||||
self.cursor:draw()
|
||||
|
||||
11
keys.lua
11
keys.lua
@@ -99,10 +99,13 @@ EVENT_VALUE_KEY_REPEAT = 2
|
||||
EVENT_VALUE_KEY_RELEASE = 0
|
||||
|
||||
-- modifiers
|
||||
MOD_SHIFT = "Shift"
|
||||
MOD_ALT = "Alt"
|
||||
MOD_SHIFT_OR_ALT = "ShiftAlt"
|
||||
MOD_ANY = "Any"
|
||||
MOD_SHIFT = "_Shift_"
|
||||
MOD_ALT = "_Alt_"
|
||||
MOD_SHIFT_OR_ALT = "_ShiftAlt_"
|
||||
MOD_ANY = "_Any_"
|
||||
MOD_SHIFT_DISPLAY = "Shift"
|
||||
MOD_ALT_DISPLAY = "Alt"
|
||||
MOD_TABLE = {MOD_SHIFT={v=MOD_SHIFT,d=MOD_SHIFT_DISPLAY},MOD_ALT={v=MOD_ALT,d=MOD_ALT_DISPLAY}}
|
||||
|
||||
function getKeyModifier()
|
||||
return Keys.altmode and MOD_ALT or Keys.shiftmode and MOD_SHIFT
|
||||
|
||||
2
mupdf
2
mupdf
Submodule mupdf updated: e7bb1c4937...bdb6b688a2
44
mupdf.patch
44
mupdf.patch
@@ -5,7 +5,7 @@ index 5e54e0b..38bd1d8 100644
|
||||
@@ -182,8 +182,13 @@ pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname)
|
||||
if (!data)
|
||||
fz_throw(ctx, "cannot find builtin font: '%s'", fontname);
|
||||
|
||||
|
||||
+#ifndef NOBUILTINFONT
|
||||
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0, 1);
|
||||
/* RJW: "cannot load freetype font from memory" */
|
||||
@@ -13,13 +13,13 @@ index 5e54e0b..38bd1d8 100644
|
||||
+ fontdesc->font = fz_new_font_from_file(ctx, data, 0, 1);
|
||||
+ free(data);
|
||||
+#endif
|
||||
|
||||
|
||||
if (!strcmp(fontname, "Symbol") || !strcmp(fontname, "ZapfDingbats"))
|
||||
fontdesc->flags |= PDF_FD_SYMBOLIC;
|
||||
@@ -199,8 +204,13 @@ pdf_load_substitute_font(fz_context *ctx, pdf_font_desc *fontdesc, int mono, int
|
||||
if (!data)
|
||||
fz_throw(ctx, "cannot find substitute font");
|
||||
|
||||
|
||||
+#ifndef NOBUILTINFONT
|
||||
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0, 1);
|
||||
/* RJW: "cannot load freetype font from memory" */
|
||||
@@ -27,12 +27,12 @@ index 5e54e0b..38bd1d8 100644
|
||||
+ fontdesc->font = fz_new_font_from_file(ctx, data, 0, 1);
|
||||
+ free(data);
|
||||
+#endif
|
||||
|
||||
|
||||
fontdesc->font->ft_substitute = 1;
|
||||
fontdesc->font->ft_bold = bold && !ft_is_bold(fontdesc->font->ft_face);
|
||||
@@ -218,7 +228,12 @@ pdf_load_substitute_cjk_font(fz_context *ctx, pdf_font_desc *fontdesc, int ros,
|
||||
fz_throw(ctx, "cannot find builtin CJK font");
|
||||
|
||||
|
||||
/* a glyph bbox cache is too big for droid sans fallback (51k glyphs!) */
|
||||
+#ifndef NOBUILTINFONT
|
||||
fontdesc->font = fz_new_font_from_memory(ctx, data, len, 0, 0);
|
||||
@@ -41,7 +41,7 @@ index 5e54e0b..38bd1d8 100644
|
||||
+ free(data);
|
||||
+#endif
|
||||
/* RJW: "cannot load builtin CJK font" */
|
||||
|
||||
|
||||
fontdesc->font->ft_substitute = 1;
|
||||
diff --git a/pdf/pdf_fontfile.c b/pdf/pdf_fontfile.c
|
||||
index 543ce76..a076033 100644
|
||||
@@ -50,7 +50,7 @@ index 543ce76..a076033 100644
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "fitz.h"
|
||||
#include "mupdf.h"
|
||||
|
||||
|
||||
+#ifndef NOBUILTINFONT
|
||||
+
|
||||
#ifdef NOCJK
|
||||
@@ -83,7 +83,7 @@ index 543ce76..a076033 100644
|
||||
+}
|
||||
+
|
||||
+unsigned char *
|
||||
+pdf_find_builtin_font(char *name, unsigned int *len)
|
||||
+pdf_lookup_builtin_font(char *name, unsigned int *len)
|
||||
+{
|
||||
+ *len = 0;
|
||||
+ if (!strcmp("Courier", name)) {
|
||||
@@ -132,37 +132,37 @@ index 543ce76..a076033 100644
|
||||
+}
|
||||
+
|
||||
+unsigned char *
|
||||
+pdf_find_substitute_font(int mono, int serif, int bold, int italic, unsigned int *len)
|
||||
+pdf_lookup_substitute_font(int mono, int serif, int bold, int italic, unsigned int *len)
|
||||
+{
|
||||
+ if (mono) {
|
||||
+ if (bold) {
|
||||
+ if (italic) return pdf_find_builtin_font("Courier-BoldOblique", len);
|
||||
+ else return pdf_find_builtin_font("Courier-Bold", len);
|
||||
+ if (italic) return pdf_lookup_builtin_font("Courier-BoldOblique", len);
|
||||
+ else return pdf_lookup_builtin_font("Courier-Bold", len);
|
||||
+ } else {
|
||||
+ if (italic) return pdf_find_builtin_font("Courier-Oblique", len);
|
||||
+ else return pdf_find_builtin_font("Courier", len);
|
||||
+ if (italic) return pdf_lookup_builtin_font("Courier-Oblique", len);
|
||||
+ else return pdf_lookup_builtin_font("Courier", len);
|
||||
+ }
|
||||
+ } else if (serif) {
|
||||
+ if (bold) {
|
||||
+ if (italic) return pdf_find_builtin_font("Times-BoldItalic", len);
|
||||
+ else return pdf_find_builtin_font("Times-Bold", len);
|
||||
+ if (italic) return pdf_lookup_builtin_font("Times-BoldItalic", len);
|
||||
+ else return pdf_lookup_builtin_font("Times-Bold", len);
|
||||
+ } else {
|
||||
+ if (italic) return pdf_find_builtin_font("Times-Italic", len);
|
||||
+ else return pdf_find_builtin_font("Times-Roman", len);
|
||||
+ if (italic) return pdf_lookup_builtin_font("Times-Italic", len);
|
||||
+ else return pdf_lookup_builtin_font("Times-Roman", len);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (bold) {
|
||||
+ if (italic) return pdf_find_builtin_font("Helvetica-BoldOblique", len);
|
||||
+ else return pdf_find_builtin_font("Helvetica-Bold", len);
|
||||
+ if (italic) return pdf_lookup_builtin_font("Helvetica-BoldOblique", len);
|
||||
+ else return pdf_lookup_builtin_font("Helvetica-Bold", len);
|
||||
+ } else {
|
||||
+ if (italic) return pdf_find_builtin_font("Helvetica-Oblique", len);
|
||||
+ else return pdf_find_builtin_font("Helvetica", len);
|
||||
+ if (italic) return pdf_lookup_builtin_font("Helvetica-Oblique", len);
|
||||
+ else return pdf_lookup_builtin_font("Helvetica", len);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+unsigned char *
|
||||
+pdf_find_substitute_cjk_font(int ros, int serif, unsigned int *len)
|
||||
+pdf_lookup_substitute_cjk_font(int ros, int serif, unsigned int *len)
|
||||
+{
|
||||
+ *len = 0;
|
||||
+ return get_font_file("droid/DroidSansFallback.ttf");
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <fitz/fitz.h>
|
||||
#include <fitz/fitz-internal.h>
|
||||
|
||||
#include "blitbuffer.h"
|
||||
#include "mupdfimg.h"
|
||||
|
||||
209
pdf.c
209
pdf.c
@@ -15,7 +15,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <fitz/fitz.h>
|
||||
#include <fitz/fitz-internal.h>
|
||||
|
||||
#include "blitbuffer.h"
|
||||
#include "drawcontext.h"
|
||||
@@ -311,8 +311,105 @@ static int openPage(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void load_lua_text_page(lua_State *L, fz_text_page *page)
|
||||
{
|
||||
fz_text_block *block;
|
||||
fz_text_line *aline;
|
||||
fz_text_span *span;
|
||||
|
||||
fz_rect bbox, linebbox;
|
||||
int i;
|
||||
int word, line;
|
||||
int len, c;
|
||||
int start;
|
||||
char chars[4]; // max length of UTF-8 encoded rune
|
||||
luaL_Buffer textbuf;
|
||||
|
||||
/* table that contains all the lines */
|
||||
lua_newtable(L);
|
||||
for (block = page->blocks; block < page->blocks + page->len; block++)
|
||||
{
|
||||
for (aline = block->lines; aline < block->lines + block->len; aline++)
|
||||
{
|
||||
for (span = aline->spans; span < aline->spans + aline->len; span++)
|
||||
{
|
||||
linebbox = span->text[0].bbox; // start with sensible default
|
||||
for(i = 0; i < span->len; ) {
|
||||
/* will hold information about a word: */
|
||||
lua_newtable(L);
|
||||
|
||||
luaL_buffinit(L, &textbuf);
|
||||
bbox = span->text[i].bbox; // start with sensible default
|
||||
for(; i < span->len; i++) {
|
||||
/* check for space characters */
|
||||
if(span->text[i].c == ' ' ||
|
||||
span->text[i].c == '\t' ||
|
||||
span->text[i].c == '\n' ||
|
||||
span->text[i].c == '\v' ||
|
||||
span->text[i].c == '\f' ||
|
||||
span->text[i].c == '\r' ||
|
||||
span->text[i].c == 0xA0 ||
|
||||
span->text[i].c == 0x1680 ||
|
||||
span->text[i].c == 0x180E ||
|
||||
(span->text[i].c >= 0x2000 && span->text[i].c <= 0x200A) ||
|
||||
span->text[i].c == 0x202F ||
|
||||
span->text[i].c == 0x205F ||
|
||||
span->text[i].c == 0x3000) {
|
||||
// ignore and end word
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
len = fz_runetochar(chars, &span->text[i].c);
|
||||
for(c = 0; c < len; c++) {
|
||||
luaL_addchar(&textbuf, chars[c]);
|
||||
}
|
||||
bbox = fz_union_rect(bbox, span->text[i].bbox);
|
||||
linebbox = fz_union_rect(linebbox, span->text[i].bbox);
|
||||
}
|
||||
lua_pushstring(L, "word");
|
||||
luaL_pushresult(&textbuf);
|
||||
lua_settable(L, -3);
|
||||
|
||||
/* bbox for a word: */
|
||||
lua_pushstring(L, "x0");
|
||||
lua_pushinteger(L, bbox.x0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y0");
|
||||
lua_pushinteger(L, bbox.y0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "x1");
|
||||
lua_pushinteger(L, bbox.x1);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y1");
|
||||
lua_pushinteger(L, bbox.y1);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_rawseti(L, -2, word++);
|
||||
}
|
||||
|
||||
/* bbox for a whole line (or in fact, a "span") */
|
||||
lua_pushstring(L, "x0");
|
||||
lua_pushinteger(L, linebbox.x0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y0");
|
||||
lua_pushinteger(L, linebbox.y0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "x1");
|
||||
lua_pushinteger(L, linebbox.x1);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y1");
|
||||
lua_pushinteger(L, linebbox.y1);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_rawseti(L, -2, line++);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get the text of the given page
|
||||
*
|
||||
*
|
||||
* will return text in a Lua table that is modeled after
|
||||
* djvu.c creates this table.
|
||||
*
|
||||
@@ -327,105 +424,20 @@ static int openPage(lua_State *L) {
|
||||
* will return an empty table if we have no text
|
||||
*/
|
||||
static int getPageText(lua_State *L) {
|
||||
fz_text_span *page_text;
|
||||
fz_text_span *ptr;
|
||||
fz_text_page *text_page;
|
||||
fz_device *tdev;
|
||||
fz_bbox bbox, linebbox;
|
||||
int i;
|
||||
int word, line;
|
||||
int len, c;
|
||||
int start;
|
||||
char chars[4]; // max length of UTF-8 encoded rune
|
||||
luaL_Buffer textbuf;
|
||||
|
||||
PdfPage *page = (PdfPage*) luaL_checkudata(L, 1, "pdfpage");
|
||||
|
||||
page_text = fz_new_text_span(page->doc->context);
|
||||
tdev = fz_new_text_device(page->doc->context, page_text);
|
||||
text_page = fz_new_text_page(page->doc->context, fz_bound_page(page->doc->xref, page->page));
|
||||
tdev = fz_new_text_device(page->doc->context, NULL, text_page);
|
||||
fz_run_page(page->doc->xref, page->page, tdev, fz_identity, NULL);
|
||||
fz_free_device(tdev);
|
||||
tdev = NULL;
|
||||
|
||||
/* table that contains all the lines */
|
||||
lua_newtable(L);
|
||||
line = 1;
|
||||
for(ptr = page_text; ptr != NULL; ptr = ptr->next) {
|
||||
if(ptr->text == NULL) continue;
|
||||
load_lua_text_page(L, text_page);
|
||||
|
||||
/* table for the words */
|
||||
lua_newtable(L);
|
||||
word = 1;
|
||||
linebbox = ptr->text[0].bbox; // start with sensible default
|
||||
for(i = 0; i < ptr->len; ) {
|
||||
/* will hold information about a word: */
|
||||
lua_newtable(L);
|
||||
|
||||
luaL_buffinit(L, &textbuf);
|
||||
bbox = ptr->text[i].bbox; // start with sensible default
|
||||
for(; i < ptr->len; i++) {
|
||||
/* check for space characters */
|
||||
if(ptr->text[i].c == ' ' ||
|
||||
ptr->text[i].c == '\t' ||
|
||||
ptr->text[i].c == '\n' ||
|
||||
ptr->text[i].c == '\v' ||
|
||||
ptr->text[i].c == '\f' ||
|
||||
ptr->text[i].c == '\r' ||
|
||||
ptr->text[i].c == 0xA0 ||
|
||||
ptr->text[i].c == 0x1680 ||
|
||||
ptr->text[i].c == 0x180E ||
|
||||
(ptr->text[i].c >= 0x2000 && ptr->text[i].c <= 0x200A) ||
|
||||
ptr->text[i].c == 0x202F ||
|
||||
ptr->text[i].c == 0x205F ||
|
||||
ptr->text[i].c == 0x3000) {
|
||||
// ignore and end word
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
len = runetochar(chars, &ptr->text[i].c);
|
||||
for(c = 0; c < len; c++) {
|
||||
luaL_addchar(&textbuf, chars[c]);
|
||||
}
|
||||
bbox = fz_union_bbox(bbox, ptr->text[i].bbox);
|
||||
linebbox = fz_union_bbox(linebbox, ptr->text[i].bbox);
|
||||
}
|
||||
lua_pushstring(L, "word");
|
||||
luaL_pushresult(&textbuf);
|
||||
lua_settable(L, -3);
|
||||
|
||||
/* bbox for a word: */
|
||||
lua_pushstring(L, "x0");
|
||||
lua_pushinteger(L, bbox.x0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y0");
|
||||
lua_pushinteger(L, bbox.y0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "x1");
|
||||
lua_pushinteger(L, bbox.x1);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y1");
|
||||
lua_pushinteger(L, bbox.y1);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_rawseti(L, -2, word++);
|
||||
}
|
||||
|
||||
/* bbox for a whole line (or in fact, a "span") */
|
||||
lua_pushstring(L, "x0");
|
||||
lua_pushinteger(L, linebbox.x0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y0");
|
||||
lua_pushinteger(L, linebbox.y0);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "x1");
|
||||
lua_pushinteger(L, linebbox.x1);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "y1");
|
||||
lua_pushinteger(L, linebbox.y1);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_rawseti(L, -2, line++);
|
||||
}
|
||||
|
||||
fz_free_text_span(page->doc->context, page_text);
|
||||
fz_free_text_page(page->doc->context, text_page);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -490,16 +502,15 @@ static int drawPage(lua_State *L) {
|
||||
fz_device *dev;
|
||||
fz_matrix ctm;
|
||||
fz_bbox bbox;
|
||||
fz_bbox rect;
|
||||
|
||||
PdfPage *page = (PdfPage*) luaL_checkudata(L, 1, "pdfpage");
|
||||
DrawContext *dc = (DrawContext*) luaL_checkudata(L, 2, "drawcontext");
|
||||
BlitBuffer *bb = (BlitBuffer*) luaL_checkudata(L, 3, "blitbuffer");
|
||||
rect.x0 = luaL_checkint(L, 4);
|
||||
rect.y0 = luaL_checkint(L, 5);
|
||||
rect.x1 = rect.x0 + bb->w;
|
||||
rect.y1 = rect.y0 + bb->h;
|
||||
pix = fz_new_pixmap_with_rect(page->doc->context, fz_device_gray, rect);
|
||||
bbox.x0 = luaL_checkint(L, 4);
|
||||
bbox.y0 = luaL_checkint(L, 5);
|
||||
bbox.x1 = bbox.x0 + bb->w;
|
||||
bbox.y1 = bbox.y0 + bb->h;
|
||||
pix = fz_new_pixmap_with_bbox(page->doc->context, fz_device_gray, bbox);
|
||||
fz_clear_pixmap_with_value(page->doc->context, pix, 0xff);
|
||||
|
||||
ctm = fz_scale(dc->zoom, dc->zoom);
|
||||
|
||||
@@ -44,10 +44,43 @@ function clearGlyphCache()
|
||||
glyphcache = {}
|
||||
end
|
||||
|
||||
function sizeUtf8Text(x, width, face, text, kerning)
|
||||
if text == nil then
|
||||
print("# sizeUtf8Text called without text");
|
||||
return
|
||||
end
|
||||
-- may still need more adaptive pen placement when kerning,
|
||||
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
||||
local pen_x = 0
|
||||
local pen_y_top = 0
|
||||
local pen_y_bottom = 0
|
||||
local prevcharcode = 0
|
||||
--print("----------------- text:"..text)
|
||||
for uchar in string.gfind(text, "([%z\1-\127\194-\244][\128-\191]*)") do
|
||||
if pen_x < (width - x) then
|
||||
local charcode = util.utf8charcode(uchar)
|
||||
local glyph = getGlyph(face, charcode)
|
||||
if kerning and prevcharcode then
|
||||
local kern = face.ftface:getKerning(prevcharcode, charcode)
|
||||
pen_x = pen_x + kern
|
||||
--print("prev:"..string.char(prevcharcode).." curr:"..string.char(charcode).." kern:"..kern)
|
||||
else
|
||||
--print("curr:"..string.char(charcode))
|
||||
end
|
||||
pen_x = pen_x + glyph.ax
|
||||
pen_y_top = math.max(pen_y_top, glyph.t)
|
||||
pen_y_bottom = math.max(pen_y_bottom, glyph.bb:getHeight() - glyph.t)
|
||||
--print("ax:"..glyph.ax.." t:"..glyph.t.." r:"..glyph.r.." h:"..glyph.bb:getHeight().." w:"..glyph.bb:getWidth().." yt:"..pen_y_top.." yb:"..pen_y_bottom)
|
||||
prevcharcode = charcode
|
||||
end
|
||||
end
|
||||
return { x = pen_x, y_top = pen_y_top, y_bottom = pen_y_bottom}
|
||||
end
|
||||
|
||||
function renderUtf8Text(buffer, x, y, face, text, kerning)
|
||||
if text == nil then
|
||||
print("# renderUtf8Text called without text");
|
||||
return
|
||||
return 0
|
||||
end
|
||||
-- may still need more adaptive pen placement when kerning,
|
||||
-- see: http://freetype.org/freetype2/docs/glyphs/glyphs-4.html
|
||||
@@ -60,8 +93,10 @@ function renderUtf8Text(buffer, x, y, face, text, kerning)
|
||||
if kerning and prevcharcode then
|
||||
local kern = face.ftface:getKerning(prevcharcode, charcode)
|
||||
pen_x = pen_x + kern
|
||||
--print("prev:"..string.char(prevcharcode).." curr:"..string.char(charcode).." pen_x:"..pen_x.." kern:"..kern)
|
||||
buffer:addblitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
|
||||
else
|
||||
--print(" curr:"..string.char(charcode))
|
||||
buffer:blitFrom(glyph.bb, x + pen_x + glyph.l, y - glyph.t, 0, 0, glyph.bb:getWidth(), glyph.bb:getHeight())
|
||||
end
|
||||
pen_x = pen_x + glyph.ax
|
||||
|
||||
@@ -1712,35 +1712,20 @@ end
|
||||
-- command definitions
|
||||
function UniReader:addAllCommands()
|
||||
self.commands = Commands:new()
|
||||
self.commands:add({KEY_PGFWD,KEY_LPGFWD},nil,">",
|
||||
"next page",
|
||||
function(unireader)
|
||||
unireader:goto(unireader:nextView())
|
||||
self.commands:addGroup("< >",{Keydef:new(KEY_PGBCK,nil),Keydef:new(KEY_PGFWD,nil)},
|
||||
"previous/next page",
|
||||
function(unireader,keydef)
|
||||
unireader:goto(keydef.keycode==KEY_PGBCK and unireader:prevView() or unireader:nextView())
|
||||
end)
|
||||
self.commands:add({KEY_PGBCK,KEY_LPGBCK},nil,"<",
|
||||
"previous page",
|
||||
function(unireader)
|
||||
unireader:goto(unireader:prevView())
|
||||
self.commands:addGroup(MOD_ALT.."< >",{Keydef:new(KEY_PGBCK,MOD_ALT),Keydef:new(KEY_PGFWD,MOD_ALT)},
|
||||
"zoom out/in 10%",
|
||||
function(unireader,keydef)
|
||||
unireader:setGlobalZoom(unireader.globalzoom + (keydef.keycode==KEY_PGBCK and -1 or 1)*unireader.globalzoom_orig*0.1)
|
||||
end)
|
||||
self.commands:add(KEY_PGFWD,MOD_ALT,">",
|
||||
"zoom in 10%",
|
||||
function(unireader)
|
||||
unireader:setGlobalZoom(unireader.globalzoom+unireader.globalzoom_orig*0.1)
|
||||
end)
|
||||
self.commands:add(KEY_PGBCK,MOD_ALT,"<",
|
||||
"zoom out 10%",
|
||||
function(unireader)
|
||||
unireader:setGlobalZoom(unireader.globalzoom-unireader.globalzoom_orig*0.1)
|
||||
end)
|
||||
self.commands:add(KEY_PGFWD,MOD_SHIFT,">",
|
||||
"zoom in 20%",
|
||||
function(unireader)
|
||||
unireader:setGlobalZoom(unireader.globalzoom+unireader.globalzoom_orig*0.2)
|
||||
end)
|
||||
self.commands:add(KEY_PGBCK,MOD_SHIFT,"<",
|
||||
"zoom out 20%",
|
||||
function(unireader)
|
||||
unireader:setGlobalZoom(unireader.globalzoom-unireader.globalzoom_orig*0.2)
|
||||
self.commands:addGroup(MOD_SHIFT.."< >",{Keydef:new(KEY_PGBCK,MOD_SHIFT),Keydef:new(KEY_PGFWD,MOD_SHIFT)},
|
||||
"zoom out/in 20%",
|
||||
function(unireader,keydef)
|
||||
unireader:setGlobalZoom(unireader.globalzoom + (keydef.keycode==KEY_PGBCK and -1 or 1)*unireader.globalzoom_orig*0.2)
|
||||
end)
|
||||
self.commands:add(KEY_BACK,nil,"Back",
|
||||
"back to last jump",
|
||||
@@ -1749,26 +1734,27 @@ function UniReader:addAllCommands()
|
||||
unireader:goto(unireader.jump_stack[1].page)
|
||||
end
|
||||
end)
|
||||
self.commands:add(KEY_BACK,MOD_ALT,"back",
|
||||
self.commands:add(KEY_BACK,MOD_ALT,"Back",
|
||||
"close document",
|
||||
function(unireader)
|
||||
return "break"
|
||||
end)
|
||||
self.commands:add(KEY_VPLUS,nil,"vol+",
|
||||
"increase gamma 25%",
|
||||
self.commands:add(KEY_HOME,nil,"Home",
|
||||
"exit application",
|
||||
function(unireader)
|
||||
unireader:modifyGamma( 1.25 )
|
||||
keep_running = false
|
||||
return "break"
|
||||
end)
|
||||
self.commands:add(KEY_VMINUS,nil,"vol-",
|
||||
"decrease gamma 25%",
|
||||
function(unireader)
|
||||
unireader:modifyGamma( 0.80 )
|
||||
self.commands:addGroup("vol-/+",{Keydef:new(KEY_VPLUS,nil),Keydef:new(KEY_VMINUS,nil)},
|
||||
"decrease/increase gamma 25%",
|
||||
function(unireader,keydef)
|
||||
unireader:modifyGamma(keydef.keycode==KEY_VPLUS and 1.25 or 0.8)
|
||||
end)
|
||||
--numeric key group
|
||||
local numeric_keydefs = {}
|
||||
for i=1,10 do numeric_keydefs[i]=Keydef:new(KEY_1+i-1,nil,tostring(i%10)) end
|
||||
self.commands:addGroup("[1..0]",numeric_keydefs,
|
||||
"jump to <key>*10% of document",
|
||||
self.commands:addGroup("[1, 2 .. 9, 0]",numeric_keydefs,
|
||||
"jump to 10%, 20% .. 90%, 100% of document",
|
||||
function(unireader,keydef)
|
||||
print('jump to page: '..math.max(math.floor(unireader.doc:getPages()*(keydef.keycode-KEY_1)/9),1)..'/'..unireader.doc:getPages())
|
||||
unireader:goto(math.max(math.floor(unireader.doc:getPages()*(keydef.keycode-KEY_1)/9),1))
|
||||
@@ -1815,7 +1801,7 @@ function UniReader:addAllCommands()
|
||||
unireader:setGlobalZoomMode(unireader.ZOOM_FIT_TO_CONTENT_HALF_WIDTH)
|
||||
end)
|
||||
self.commands:add(KEY_G,nil,"G",
|
||||
"goto page",
|
||||
"open 'go to page' input box",
|
||||
function(unireader)
|
||||
local page = NumInputBox:input(G_height-100, 100, "Page:")
|
||||
-- convert string to number
|
||||
@@ -1890,12 +1876,6 @@ function UniReader:addAllCommands()
|
||||
fb:refresh(0)
|
||||
unireader.rcount = 1
|
||||
end)
|
||||
self.commands:add(KEY_HOME,nil,"Home",
|
||||
"exit application",
|
||||
function(unireader)
|
||||
keep_running = false
|
||||
return "break"
|
||||
end)
|
||||
self.commands:add(KEY_Z,nil,"Z",
|
||||
"set crop mode",
|
||||
function(unireader)
|
||||
@@ -1925,7 +1905,7 @@ function UniReader:addAllCommands()
|
||||
print("# bbox override: ", unireader.bbox.enabled);
|
||||
end)
|
||||
self.commands:add(KEY_MENU,nil,"Menu",
|
||||
"open menu",
|
||||
"toggle info box",
|
||||
function(unireader)
|
||||
unireader:showMenu()
|
||||
unireader:redrawCurrentPage()
|
||||
|
||||
Reference in New Issue
Block a user