summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-01-04 18:33:33 +0000
committerRobin Watts <robin.watts@artifex.com>2012-01-04 19:13:41 +0000
commit2ae2a7b68381f0fc5940e983ccdec5b4cc08d188 (patch)
treea0ff2e359868cf6d4bcc6de7fabc06d9ade9774a
parent94439d77f23763d59457b9946ba35bd354ea4841 (diff)
downloadmupdf-2ae2a7b68381f0fc5940e983ccdec5b4cc08d188.tar.xz
Bug 692739: Add ability to abort time consuming actions
A new 'cookie' parameter is added to page rendering/interpretation functions. Supply this as NULL to get existing behaviour. If you supply a non-NULL cookie, then this is taken as a pointer to a struct that can be used for simple, non-thread locked communication between caller and library. The entire struct should be memset to zero before entry, except for specific flags (thus coping with future extensions to this struct). The abort flag should be zero on entry. It will be checked periodically by the library - if the caller sets it non-zero (via another thread) then the current operation will be aborted. No guarantees are given as to how often this will be checked, or how fast it will be responded to. The progress_max field will be set to an integer (-1 for unknown) representing the number of 'things' to do. The progress field will count up from 0 to this number as time goes by. No guarantees are made as to the accuracy of this information, but it should be useful for offering some sort of progress bar etc. Note that progress_max may increase during the job. In general, callers should be careful to accept out of range or invalid data in this structure as this is deliberately accessed 'unlocked'.
-rw-r--r--android/jni/mupdf.c4
-rw-r--r--apps/pdfapp.c6
-rw-r--r--apps/pdfdraw.c14
-rw-r--r--apps/xpsdraw.c6
-rw-r--r--fitz/dev_list.c17
-rw-r--r--fitz/fitz.h15
-rw-r--r--pdf/mupdf.h4
-rw-r--r--pdf/pdf_interpret.c49
8 files changed, 89 insertions, 26 deletions
diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c
index c7f06252..48ffbe87 100644
--- a/android/jni/mupdf.c
+++ b/android/jni/mupdf.c
@@ -139,7 +139,7 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int
/* Render to list */
currentPageList = fz_new_display_list(ctx);
dev = fz_new_list_device(ctx, currentPageList);
- pdf_run_page(xref, currentPage, dev, fz_identity);
+ pdf_run_page(xref, currentPage, dev, fz_identity, NULL);
}
fz_catch(ctx)
{
@@ -240,7 +240,7 @@ Java_com_artifex_mupdf_MuPDFCore_drawPage(JNIEnv *env, jobject thiz, jobject bit
time = clock();
for (i=0; i<100;i++) {
#endif
- fz_execute_display_list(currentPageList, dev, ctm, bbox);
+ fz_execute_display_list(currentPageList, dev, ctm, bbox, NULL);
#ifdef TIME_DISPLAY_LIST
}
time = clock() - time;
diff --git a/apps/pdfapp.c b/apps/pdfapp.c
index cdb88e61..34fe09a5 100644
--- a/apps/pdfapp.c
+++ b/apps/pdfapp.c
@@ -333,7 +333,7 @@ static void pdfapp_loadpage_pdf(pdfapp_t *app)
mdev = fz_new_list_device(app->ctx, app->page_list);
fz_try(app->ctx)
{
- pdf_run_page(app->xref, page, mdev, fz_identity);
+ pdf_run_page(app->xref, page, mdev, fz_identity, NULL);
}
fz_catch(app->ctx)
{
@@ -408,7 +408,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai
/* Extract text */
app->page_text = fz_new_text_span(app->ctx);
tdev = fz_new_text_device(app->ctx, app->page_text);
- fz_execute_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox);
+ fz_execute_display_list(app->page_list, tdev, fz_identity, fz_infinite_bbox, NULL);
fz_free_device(tdev);
}
@@ -435,7 +435,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai
app->image = fz_new_pixmap_with_rect(app->ctx, colorspace, bbox);
fz_clear_pixmap_with_color(app->image, 255);
idev = fz_new_draw_device(app->ctx, app->cache, app->image);
- fz_execute_display_list(app->page_list, idev, ctm, bbox);
+ fz_execute_display_list(app->page_list, idev, ctm, bbox, NULL);
fz_free_device(idev);
}
diff --git a/apps/pdfdraw.c b/apps/pdfdraw.c
index 6b2923c1..91d09c6c 100644
--- a/apps/pdfdraw.c
+++ b/apps/pdfdraw.c
@@ -117,7 +117,7 @@ static void drawpage(pdf_xref *xref, int pagenum)
{
list = fz_new_display_list(ctx);
dev = fz_new_list_device(ctx, list);
- pdf_run_page(xref, page, dev, fz_identity);
+ pdf_run_page(xref, page, dev, fz_identity, NULL);
}
fz_catch(ctx)
{
@@ -137,9 +137,9 @@ static void drawpage(pdf_xref *xref, int pagenum)
dev = fz_new_trace_device(ctx);
printf("<page number=\"%d\">\n", pagenum);
if (list)
- fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
+ fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox, NULL);
else
- pdf_run_page(xref, page, dev, fz_identity);
+ pdf_run_page(xref, page, dev, fz_identity, NULL);
printf("</page>\n");
}
fz_catch(ctx)
@@ -164,9 +164,9 @@ static void drawpage(pdf_xref *xref, int pagenum)
text = fz_new_text_span(ctx);
dev = fz_new_text_device(ctx, text);
if (list)
- fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
+ fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox, NULL);
else
- pdf_run_page(xref, page, dev, fz_identity);
+ pdf_run_page(xref, page, dev, fz_identity, NULL);
fz_free_device(dev);
dev = NULL;
printf("[Page %d]\n", pagenum);
@@ -219,9 +219,9 @@ static void drawpage(pdf_xref *xref, int pagenum)
dev = fz_new_draw_device(ctx, glyphcache, pix);
if (list)
- fz_execute_display_list(list, dev, ctm, bbox);
+ fz_execute_display_list(list, dev, ctm, bbox, NULL);
else
- pdf_run_page(xref, page, dev, ctm);
+ pdf_run_page(xref, page, dev, ctm, NULL);
fz_free_device(dev);
dev = NULL;
diff --git a/apps/xpsdraw.c b/apps/xpsdraw.c
index ced38357..33fb9db2 100644
--- a/apps/xpsdraw.c
+++ b/apps/xpsdraw.c
@@ -110,7 +110,7 @@ static void drawpage(xps_document *doc, int pagenum)
dev = fz_new_trace_device(doc->ctx);
printf("<page number=\"%d\">\n", pagenum);
if (list)
- fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
+ fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox, NULL);
else
xps_run_page(doc, page, dev, fz_identity);
printf("</page>\n");
@@ -122,7 +122,7 @@ static void drawpage(xps_document *doc, int pagenum)
fz_text_span *text = fz_new_text_span(doc->ctx);
dev = fz_new_text_device(doc->ctx, text);
if (list)
- fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox);
+ fz_execute_display_list(list, dev, fz_identity, fz_infinite_bbox, NULL);
else
xps_run_page(doc, page, dev, fz_identity);
fz_free_device(dev);
@@ -166,7 +166,7 @@ static void drawpage(xps_document *doc, int pagenum)
dev = fz_new_draw_device(doc->ctx, glyphcache, pix);
if (list)
- fz_execute_display_list(list, dev, ctm, bbox);
+ fz_execute_display_list(list, dev, ctm, bbox, NULL);
else
xps_run_page(doc, page, dev, ctm);
fz_free_device(dev);
diff --git a/fitz/dev_list.c b/fitz/dev_list.c
index 376cdac8..c6a71ec9 100644
--- a/fitz/dev_list.c
+++ b/fitz/dev_list.c
@@ -591,7 +591,7 @@ fz_free_display_list(fz_context *ctx, fz_display_list *list)
}
void
-fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_bbox scissor)
+fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_bbox scissor, fz_cookie *cookie)
{
fz_display_node *node;
fz_matrix ctm;
@@ -600,6 +600,7 @@ fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm
int clipped = 0;
int tiled = 0;
int empty;
+ int progress = 0;
if (!fz_is_infinite_bbox(scissor))
{
@@ -609,8 +610,22 @@ fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm
scissor.x1 += 20; scissor.y1 += 20;
}
+ if (cookie)
+ {
+ cookie->progress_max = list->last - list->first;
+ cookie->progress = 0;
+ }
+
for (node = list->first; node; node = node->next)
{
+ /* Check the cookie for aborting */
+ if (cookie)
+ {
+ if (cookie->abort)
+ break;
+ cookie->progress = progress++;
+ }
+
/* cull objects to draw using a quick visibility test */
if (tiled || node->cmd == FZ_CMD_BEGIN_TILE || node->cmd == FZ_CMD_END_TILE)
diff --git a/fitz/fitz.h b/fitz/fitz.h
index d79d39f2..becd5df9 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -1150,6 +1150,19 @@ void fz_debug_text_span_xml(fz_text_span *span);
fz_device *fz_new_text_device(fz_context *ctx, fz_text_span *text);
/*
+ * Cookie support - simple communication channel between app/library.
+ */
+
+typedef struct fz_cookie_s fz_cookie;
+
+struct fz_cookie_s
+{
+ int abort;
+ int progress;
+ int progress_max; /* -1 for unknown */
+};
+
+/*
* Display list device -- record and play back device commands.
*/
@@ -1158,7 +1171,7 @@ typedef struct fz_display_list_s fz_display_list;
fz_display_list *fz_new_display_list(fz_context *ctx);
void fz_free_display_list(fz_context *ctx, fz_display_list *list);
fz_device *fz_new_list_device(fz_context *ctx, fz_display_list *list);
-void fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, fz_bbox area);
+void fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, fz_bbox area, fz_cookie *cookie);
/*
diff --git a/pdf/mupdf.h b/pdf/mupdf.h
index bc912987..cd3c1d82 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -462,8 +462,8 @@ void pdf_free_page(fz_context *ctx, pdf_page *page);
* Content stream parsing
*/
-void pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event);
-void pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm);
+void pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie);
+void pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie);
void pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm);
#endif
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c
index 7fce1d52..14574f14 100644
--- a/pdf/pdf_interpret.c
+++ b/pdf/pdf_interpret.c
@@ -97,6 +97,9 @@ struct pdf_csi_s
fz_matrix top_ctm;
pdf_gstate gstate[64];
int gtop;
+
+ /* cookie support */
+ fz_cookie *cookie;
};
static void pdf_run_buffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents);
@@ -855,7 +858,7 @@ pdf_init_gstate(pdf_gstate *gs, fz_matrix ctm)
}
static pdf_csi *
-pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event)
+pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie)
{
pdf_csi *csi;
fz_context *ctx = dev->ctx;
@@ -890,6 +893,8 @@ pdf_new_csi(pdf_xref *xref, fz_device *dev, fz_matrix ctm, char *event)
csi->top_ctm = ctm;
pdf_init_gstate(&csi->gstate[0], ctm);
csi->gtop = 0;
+
+ csi->cookie = cookie;
}
fz_catch(ctx)
{
@@ -2410,11 +2415,25 @@ pdf_run_stream(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen
pdf_clear_stack(csi);
in_array = 0;
+ if (csi->cookie)
+ {
+ csi->cookie->progress_max = -1;
+ csi->cookie->progress = 0;
+ }
+
while (1)
{
if (csi->top == nelem(csi->stack) - 1)
fz_throw(ctx, "stack overflow");
+ /* Check the cookie */
+ if (csi->cookie)
+ {
+ if (csi->cookie->abort)
+ break;
+ csi->cookie->progress++;
+ }
+
tok = pdf_lex(file, buf, buflen, &len);
/* RJW: "lexical error in content stream" */
@@ -2543,7 +2562,7 @@ pdf_run_buffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents)
}
void
-pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event)
+pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie)
{
pdf_csi *csi;
pdf_annot *annot;
@@ -2553,7 +2572,7 @@ pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matri
if (page->transparency)
fz_begin_group(dev, fz_transform_rect(ctm, page->mediabox), 1, 0, 0, 1);
- csi = pdf_new_csi(xref, dev, ctm, event);
+ csi = pdf_new_csi(xref, dev, ctm, event, cookie);
fz_try(ctx)
{
pdf_run_buffer(csi, page->resources, page->contents);
@@ -2565,8 +2584,24 @@ pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matri
}
pdf_free_csi(csi);
+ if (cookie && cookie->progress_max != -1)
+ {
+ int count = 1;
+ for (annot = page->annots; annot; annot = annot->next)
+ count++;
+ cookie->progress_max += count;
+ }
+
for (annot = page->annots; annot; annot = annot->next)
{
+ /* Check the cookie for aborting */
+ if (cookie)
+ {
+ if (cookie->abort)
+ break;
+ cookie->progress++;
+ }
+
flags = fz_to_int(fz_dict_gets(annot->obj, "F"));
/* TODO: NoZoom and NoRotate */
@@ -2577,7 +2612,7 @@ pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matri
if (flags & (1 << 5)) /* NoView */
continue;
- csi = pdf_new_csi(xref, dev, ctm, event);
+ csi = pdf_new_csi(xref, dev, ctm, event, cookie);
if (!pdf_is_hidden_ocg(fz_dict_gets(annot->obj, "OC"), csi, page->resources))
{
fz_try(ctx)
@@ -2598,15 +2633,15 @@ pdf_run_page_with_usage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matri
}
void
-pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm)
+pdf_run_page(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
{
- pdf_run_page_with_usage(xref, page, dev, ctm, "View");
+ pdf_run_page_with_usage(xref, page, dev, ctm, "View", cookie);
}
void
pdf_run_glyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm)
{
- pdf_csi *csi = pdf_new_csi(xref, dev, ctm, "View");
+ pdf_csi *csi = pdf_new_csi(xref, dev, ctm, "View", NULL);
fz_context *ctx = xref->ctx;
fz_try(ctx)