From f981b70ac0d4fa921b7cd0e9822865386ff2fafc Mon Sep 17 00:00:00 2001 From: chrox Date: Tue, 13 Nov 2012 11:54:23 +0800 Subject: [PATCH] add multi-threaded precache Because the lua reader is single threaded on which both user inputloop and background page rendering is processed. Although there is a pretty good precache system to save user's time spending on waiting for the rendering when going to the next page, user input is indeed blocked when running the precache thing. The situation is even worse in koptreader as reflowing on page would usually take several second, in this period users cannot move to the next page view even it's already in the cache. This patch will let precache run in the background in a seperate thread so that the koptreader is still responsive when precaching the next page. Now it only just works. Welcome to find out bugs in it. --- djvu.c | 13 +++++++++---- koptcontext.c | 19 +++++++++++++++++++ pdf.c | 21 +++++++++++++-------- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/djvu.c b/djvu.c index 0171d3a06..a09e036b7 100644 --- a/djvu.c +++ b/djvu.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -476,7 +477,6 @@ static int reflowPage(lua_State *L) { DjvuPage *page = (DjvuPage*) luaL_checkudata(L, 1, "djvupage"); KOPTContext *kctx = (KOPTContext*) luaL_checkudata(L, 2, "koptcontext"); ddjvu_render_mode_t mode = (int) luaL_checkint(L, 3); - WILLUSBITMAP _src, *src; ddjvu_rect_t prect; ddjvu_rect_t rrect; @@ -510,7 +510,7 @@ static int reflowPage(lua_State *L) { dpi *= kctx->shrink_factor; } while (rrect.w > kctx->read_max_width | rrect.h > kctx->read_max_height); - src = &_src; + WILLUSBITMAP *src = malloc(sizeof(WILLUSBITMAP)); bmp_init(src); src->width = rrect.w; src->height = rrect.h; @@ -528,8 +528,13 @@ static int reflowPage(lua_State *L) { status = ddjvu_page_render(page->page_ref, mode, &prect, &rrect, page->doc->pixelformat, bmp_bytewidth(src), (char *) src->data); - k2pdfopt_reflow_bmp(kctx, src); - bmp_free(src); + kctx->src = src; + if (kctx->precache) { + pthread_t rf_thread; + pthread_create(&rf_thread, NULL, k2pdfopt_reflow_bmp, (void*) kctx); + } else { + k2pdfopt_reflow_bmp(kctx); + } return 0; } diff --git a/koptcontext.c b/koptcontext.c index 408ca7f71..0a810d310 100644 --- a/koptcontext.c +++ b/koptcontext.c @@ -46,6 +46,8 @@ static int newKOPTContext(lua_State *L) { uint8_t *data = NULL; BBox bbox = {0, 0, 0, 0}; + WILLUSBITMAP *src; + int precache = 0; KOPTContext *kc = (KOPTContext*) lua_newuserdata(L, sizeof(KOPTContext)); @@ -76,6 +78,8 @@ static int newKOPTContext(lua_State *L) { kc->data = data; kc->bbox = bbox; + kc->src = src; + kc->precache = precache; luaL_getmetatable(L, "koptcontext"); lua_setmetatable(L, -2); @@ -216,6 +220,18 @@ static int kcSetWordSpacing(lua_State *L) { return 0; } +static int kcSetPreCache(lua_State *L) { + KOPTContext *kc = (KOPTContext*) luaL_checkudata(L, 1, "koptcontext"); + kc->precache = 1; + return 0; +} + +static int kcIsPreCache(lua_State *L) { + KOPTContext *kc = (KOPTContext*) luaL_checkudata(L, 1, "koptcontext"); + lua_pushinteger(L, kc->precache); + return 1; +} + static const struct luaL_Reg koptcontext_meth[] = { {"setBBox", kcSetBBox}, {"setTrim", kcSetTrim}, @@ -239,6 +255,9 @@ static const struct luaL_Reg koptcontext_meth[] = { {"setDefectSize", kcSetDefectSize}, {"setLineSpacing", kcSetLineSpacing}, {"setWordSpacing", kcSetWordSpacing}, + + {"setPreCache", kcSetPreCache}, + {"isPreCache", kcIsPreCache}, {NULL, NULL} }; diff --git a/pdf.c b/pdf.c index 111576055..b8f35a68c 100644 --- a/pdf.c +++ b/pdf.c @@ -15,6 +15,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ + +#include +#include +#include +#include #include #include "blitbuffer.h" @@ -22,10 +27,6 @@ #include "koptcontext.h" #include "k2pdfopt.h" #include "pdf.h" -#include -#include -#include - typedef struct PdfDocument { fz_document *xref; @@ -563,7 +564,6 @@ static int reflowPage(lua_State *L) { fz_rect bounds,bounds2; fz_matrix ctm; fz_bbox bbox; - WILLUSBITMAP _src, *src; pix = NULL; fz_var(pix); @@ -606,14 +606,19 @@ static int reflowPage(lua_State *L) { fz_run_page(page->doc->xref, page->page, dev, ctm, NULL); fz_free_device(dev); - src = &_src; + WILLUSBITMAP *src = malloc(sizeof(WILLUSBITMAP)); bmp_init(src); int status = bmpmupdf_pixmap_to_bmp(src, page->doc->context, pix); fz_drop_pixmap(page->doc->context, pix); - k2pdfopt_reflow_bmp(kctx, src); - bmp_free(src); + kctx->src = src; + if (kctx->precache) { + pthread_t rf_thread; + pthread_create( &rf_thread, NULL, k2pdfopt_reflow_bmp, (void*) kctx); + } else { + k2pdfopt_reflow_bmp(kctx); + } return 0; }