diff options
Diffstat (limited to 'source/tools')
-rw-r--r-- | source/tools/mudraw.c | 371 |
1 files changed, 266 insertions, 105 deletions
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c index 52788aea..55c984c4 100644 --- a/source/tools/mudraw.c +++ b/source/tools/mudraw.c @@ -369,11 +369,29 @@ static int num_workers = 0; static worker_t *workers; static struct { + int active; + int started; + fz_context *ctx; + THREAD thread; + SEMAPHORE start; + SEMAPHORE stop; + int pagenum; + char *filename; + fz_display_list *list; + fz_page *page; +} bgprint; + +static struct { int count, total; int min, max; int minpage, maxpage; char *minfilename; char *maxfilename; + int render_count, render_total; + int render_min, render_max; + int render_minpage, render_maxpage; + char *render_minfilename; + char *render_maxfilename; } timing; static void usage(void) @@ -419,6 +437,7 @@ static void usage(void) "\t-D\tdisable use of display list\n" "\t-i\tignore errors\n" "\t-L\tlow memory mode (avoid caching, clear objects after each page)\n" + "\t-P\tparallel interpretation/rendering\n" "\n" "\tpages\tcomma separated list of page numbers and ranges\n" ); @@ -555,91 +574,14 @@ static void drawband(fz_context *ctx, int savealpha, fz_page *page, fz_display_l } } -static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) +static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, int pagenum, fz_cookie *cookie, int start, char *filename, int bg) { - fz_page *page; - fz_display_list *list = NULL; - fz_device *dev = NULL; - int start; - fz_cookie cookie = { 0 }; fz_rect mediabox; - int first_page = !output_append; - - fz_var(list); - fz_var(dev); - - if (showtime) - start = gettime(); - - page = fz_load_page(ctx, doc, pagenum - 1); + fz_device *dev = NULL; - if (showmd5 || showtime || showfeatures) - fprintf(stderr, "page %s %d", filename, pagenum); fz_bound_page(ctx, page, &mediabox); - if (output_file_per_page) - { - char text_buffer[512]; - - fz_drop_output(ctx, out); - fz_snprintf(text_buffer, sizeof(text_buffer), output, pagenum); - out = fz_new_output_with_path(ctx, text_buffer, output_append); - output_append = 1; - } - - /* Output any file level (as opposed to page level) headers. */ - if (first_page) - file_level_headers(ctx); - - if (uselist) - { - fz_try(ctx) - { - list = fz_new_display_list(ctx); - dev = fz_new_list_device(ctx, list); - if (lowmemory) - fz_enable_device_hints(ctx, dev, FZ_NO_CACHE); - fz_run_page(ctx, page, dev, &fz_identity, &cookie); - } - fz_always(ctx) - { - fz_drop_device(ctx, dev); - dev = NULL; - } - fz_catch(ctx) - { - fz_drop_display_list(ctx, list); - fz_drop_page(ctx, page); - fz_rethrow(ctx); - } - } - - if (showfeatures) - { - int iscolor; - dev = fz_new_test_device(ctx, &iscolor, 0.02f); - if (lowmemory) - fz_enable_device_hints(ctx, dev, FZ_NO_CACHE); - fz_try(ctx) - { - if (list) - fz_run_display_list(ctx, list, dev, &fz_identity, &fz_infinite_rect, NULL); - else - fz_run_page(ctx, page, dev, &fz_identity, &cookie); - } - fz_always(ctx) - { - fz_drop_device(ctx, dev); - dev = NULL; - } - fz_catch(ctx) - { - fz_rethrow(ctx); - } - fprintf(stderr, " %s", iscolor ? "color" : "grayscale"); - } - if (output_format == OUT_TRACE) { fz_try(ctx) @@ -650,9 +592,9 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) if (lowmemory) fz_enable_device_hints(ctx, dev, FZ_NO_CACHE); if (list) - fz_run_display_list(ctx, list, dev, &fz_identity, &fz_infinite_rect, &cookie); + fz_run_display_list(ctx, list, dev, &fz_identity, &fz_infinite_rect, cookie); else - fz_run_page(ctx, page, dev, &fz_identity, &cookie); + fz_run_page(ctx, page, dev, &fz_identity, cookie); fz_printf(ctx, out, "</page>\n"); } fz_always(ctx) @@ -683,9 +625,9 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) if (output_format == OUT_HTML) fz_disable_device_hints(ctx, dev, FZ_IGNORE_IMAGE); if (list) - fz_run_display_list(ctx, list, dev, &fz_identity, &fz_infinite_rect, &cookie); + fz_run_display_list(ctx, list, dev, &fz_identity, &fz_infinite_rect, cookie); else - fz_run_page(ctx, page, dev, &fz_identity, &cookie); + fz_run_page(ctx, page, dev, &fz_identity, cookie); fz_drop_device(ctx, dev); dev = NULL; if (output_format == OUT_STEXT) @@ -728,9 +670,9 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) pdf_obj *page_obj; if (list) - fz_run_display_list(ctx, list, dev, &fz_identity, NULL, &cookie); + fz_run_display_list(ctx, list, dev, &fz_identity, NULL, cookie); else - fz_run_page(ctx, page, dev, &fz_identity, &cookie); + fz_run_page(ctx, page, dev, &fz_identity, cookie); page_obj = pdf_add_page(ctx, pdfout, &mediabox, rotation, resources, contents); pdf_insert_page(ctx, pdfout, -1, page_obj); @@ -779,9 +721,9 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) if (lowmemory) fz_enable_device_hints(ctx, dev, FZ_NO_CACHE); if (list) - fz_run_display_list(ctx, list, dev, &ctm, &tbounds, &cookie); + fz_run_display_list(ctx, list, dev, &ctm, &tbounds, cookie); else - fz_run_page(ctx, page, dev, &ctm, &cookie); + fz_run_page(ctx, page, dev, &ctm, cookie); fz_drop_device(ctx, dev); dev = NULL; } @@ -798,7 +740,6 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) fz_rethrow(ctx); } } - else { float zoom; @@ -811,7 +752,9 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) fz_ps_output_context *psoc = NULL; fz_mono_pcl_output_context *pmcoc = NULL; fz_color_pcl_output_context *pccoc = NULL; + fz_device *dev = NULL; + fz_var(dev); fz_var(pix); fz_var(poc); fz_var(psoc); @@ -953,10 +896,10 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) DEBUG_THREADS(("Waiting for worker %d to complete band %d\n", w->num, band)); SEMAPHORE_WAIT(w->stop); pix = w->pix; - cookie.errors += w->cookie.errors; + cookie->errors += w->cookie.errors; } else - drawband(ctx, savealpha, page, list, &ctm, &tbounds, &cookie, band, pix); + drawband(ctx, savealpha, page, list, &ctm, &tbounds, cookie, band, pix); if (output) { @@ -1072,22 +1015,44 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) int end = gettime(); int diff = end - start; - if (diff < timing.min) + if (bg) { - timing.min = diff; - timing.minpage = pagenum; - timing.minfilename = filename; + if (diff < timing.render_min) + { + timing.render_min = diff; + timing.render_minpage = pagenum; + timing.render_minfilename = filename; + } + if (diff > timing.render_max) + { + timing.render_max = diff; + timing.render_maxpage = pagenum; + timing.render_maxfilename = filename; + } + timing.render_total += diff; + timing.render_count ++; + + fprintf(stderr, " %dms (rendering)", diff); } - if (diff > timing.max) + else { - timing.max = diff; - timing.maxpage = pagenum; - timing.maxfilename = filename; - } - timing.total += diff; - timing.count ++; + if (diff < timing.min) + { + timing.min = diff; + timing.minpage = pagenum; + timing.minfilename = filename; + } + if (diff > timing.max) + { + timing.max = diff; + timing.maxpage = pagenum; + timing.maxfilename = filename; + } + timing.total += diff; + timing.count ++; - fprintf(stderr, " %dms", diff); + fprintf(stderr, " %dms", diff); + } } if (showmd5 || showtime || showfeatures) @@ -1105,10 +1070,143 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) fz_flush_warnings(ctx); - if (cookie.errors) + if (cookie->errors) errored = 1; } +static void bgprint_flush(void) +{ + if (!bgprint.active || !bgprint.started) + return; + + SEMAPHORE_WAIT(bgprint.stop); + bgprint.started = 0; +} + +static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) +{ + fz_page *page; + fz_display_list *list = NULL; + fz_device *dev = NULL; + int start; + fz_cookie cookie = { 0 }; + int first_page = !output_append; + int diff; + + fz_var(list); + fz_var(dev); + + start = (showtime ? gettime() : 0); + + page = fz_load_page(ctx, doc, pagenum - 1); + + /* Output any file level (as opposed to page level) headers. */ + if (first_page) + file_level_headers(ctx); + + if (uselist) + { + fz_try(ctx) + { + list = fz_new_display_list(ctx); + dev = fz_new_list_device(ctx, list); + if (lowmemory) + fz_enable_device_hints(ctx, dev, FZ_NO_CACHE); + fz_run_page(ctx, page, dev, &fz_identity, &cookie); + } + fz_always(ctx) + { + fz_drop_device(ctx, dev); + dev = NULL; + } + fz_catch(ctx) + { + fz_drop_display_list(ctx, list); + fz_drop_page(ctx, page); + fz_rethrow(ctx); + } + + if (bgprint.active && showtime) + { + int end = gettime(); + diff = end - start; + + if (diff < timing.min) + { + timing.min = diff; + timing.minpage = pagenum; + timing.minfilename = filename; + } + if (diff > timing.max) + { + timing.max = diff; + timing.maxpage = pagenum; + timing.maxfilename = filename; + } + timing.total += diff; + timing.count ++; + } + } + + if (showfeatures) + { + int iscolor; + dev = fz_new_test_device(ctx, &iscolor, 0.02f); + if (lowmemory) + fz_enable_device_hints(ctx, dev, FZ_NO_CACHE); + fz_try(ctx) + { + if (list) + fz_run_display_list(ctx, list, dev, &fz_identity, &fz_infinite_rect, NULL); + else + fz_run_page(ctx, page, dev, &fz_identity, &cookie); + } + fz_always(ctx) + { + fz_drop_device(ctx, dev); + dev = NULL; + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + fprintf(stderr, " %s", iscolor ? "color" : "grayscale"); + } + + if (output_file_per_page) + { + char text_buffer[512]; + + bgprint_flush(); + fz_drop_output(ctx, out); + fz_snprintf(text_buffer, sizeof(text_buffer), output, pagenum); + out = fz_new_output_with_path(ctx, text_buffer, output_append); + output_append = 1; + } + + if (bgprint.active) + { + bgprint_flush(); + if (bgprint.active && (showmd5 || showtime || showfeatures)) + { + fprintf(stderr, "page %s %d", filename, pagenum); + if (showtime) + fprintf(stderr, " %dms (interpretation)", diff); + } + + bgprint.started = 1; + bgprint.page = page; + bgprint.list = list; + bgprint.filename = filename; + bgprint.pagenum = pagenum; + SEMAPHORE_TRIGGER(bgprint.start); + } + else + { + dodrawpage(ctx, page, list, pagenum, &cookie, start, filename, 0); + } +} + static void drawrange(fz_context *ctx, fz_document *doc, char *range) { int page, spage, epage, pagecount; @@ -1241,6 +1339,29 @@ static THREAD_RETURN_TYPE worker_thread(void *arg) while (me->band >= 0); THREAD_RETURN(); } + +static THREAD_RETURN_TYPE bgprint_worker(void *arg) +{ + fz_cookie cookie = { 0 }; + (void)arg; + + do + { + DEBUG_THREADS(("BGPrint waiting\n")); + SEMAPHORE_WAIT(bgprint.start); + DEBUG_THREADS(("BGPrint woken for pagenum %d\n", bgprint.pagenum)); + if (bgprint.pagenum >= 0) + { + int start = gettime(); + memset(&cookie, 0, sizeof(cookie)); + dodrawpage(bgprint.ctx, bgprint.page, bgprint.list, bgprint.pagenum, &cookie, start, bgprint.filename, 1); + } + DEBUG_THREADS(("BGPrint completed band %d\n", bgprint.pagenum)); + SEMAPHORE_TRIGGER(bgprint.stop); + } + while (bgprint.pagenum >= 0); + THREAD_RETURN(); +} #endif #ifdef MUDRAW_STANDALONE @@ -1257,7 +1378,7 @@ int mudraw_main(int argc, char **argv) fz_var(doc); - while ((c = fz_getopt(argc, argv, "p:o:F:R:r:w:h:fB:c:G:I:s:A:DiW:H:S:T:U:Lv")) != -1) + while ((c = fz_getopt(argc, argv, "p:o:F:R:r:w:h:fB:c:G:I:s:A:DiW:H:S:T:U:LvP")) != -1) { switch (c) { @@ -1313,6 +1434,7 @@ int mudraw_main(int argc, char **argv) break; #endif case 'L': lowmemory = 1; break; + case 'P': bgprint.active = 1; break; case 'v': fprintf(stderr, "mudraw version %s\n", FZ_VERSION); return 1; } @@ -1335,6 +1457,15 @@ int mudraw_main(int argc, char **argv) } } + if (bgprint.active) + { + if (uselist == 0) + { + fprintf(stderr, "cannot bgprint without using display list\n"); + exit(1); + } + } + ctx = fz_new_context((showmemory == 0 ? NULL : &alloc_ctx), LOCKS_INIT(), (lowmemory ? 1 : FZ_STORE_DEFAULT)); if (!ctx) { @@ -1345,6 +1476,14 @@ int mudraw_main(int argc, char **argv) fz_set_text_aa_level(ctx, alphabits_text); fz_set_graphics_aa_level(ctx, alphabits_graphics); + if (bgprint.active) + { + bgprint.ctx = fz_clone_context(ctx); + SEMAPHORE_INIT(bgprint.start); + SEMAPHORE_INIT(bgprint.stop); + THREAD_INIT(bgprint.thread, bgprint_worker, NULL); + } + if (num_workers > 0) { workers = fz_calloc(ctx, num_workers, sizeof(*workers)); @@ -1494,6 +1633,14 @@ int mudraw_main(int argc, char **argv) timing.maxpage = 0; timing.minfilename = ""; timing.maxfilename = ""; + timing.render_count = 0; + timing.render_total = 0; + timing.render_min = 1 << 30; + timing.render_max = 0; + timing.render_minpage = 0; + timing.render_maxpage = 0; + timing.render_minfilename = ""; + timing.render_maxfilename = ""; fz_try(ctx) { @@ -1528,6 +1675,7 @@ int mudraw_main(int argc, char **argv) drawrange(ctx, doc, argv[fz_optind++]); } + bgprint_flush(); fz_drop_document(ctx, doc); doc = NULL; } @@ -1536,6 +1684,7 @@ int mudraw_main(int argc, char **argv) if (!ignore_errors) fz_rethrow(ctx); + bgprint_flush(); fz_drop_document(ctx, doc); doc = NULL; fz_warn(ctx, "ignoring error in '%s'", filename); @@ -1544,6 +1693,7 @@ int mudraw_main(int argc, char **argv) } fz_catch(ctx) { + bgprint_flush(); fz_drop_document(ctx, doc); fprintf(stderr, "error: cannot draw '%s'\n", filename); errored = 1; @@ -1596,12 +1746,23 @@ int mudraw_main(int argc, char **argv) SEMAPHORE_WAIT(workers[i].stop); SEMAPHORE_FIN(workers[i].start); SEMAPHORE_FIN(workers[i].stop); - fz_drop_context(workers[i].ctx); THREAD_FIN(workers[i].thread); + fz_drop_context(workers[i].ctx); } fz_free(ctx, workers); } + if (bgprint.active) + { + bgprint.pagenum = -1; + SEMAPHORE_TRIGGER(bgprint.start); + SEMAPHORE_WAIT(bgprint.stop); + SEMAPHORE_FIN(bgprint.start); + SEMAPHORE_FIN(bgprint.stop); + THREAD_FIN(bgprint.thread); + fz_drop_context(bgprint.ctx); + } + fz_drop_context(ctx); LOCKS_FIN(); |