From b66925c26188075d843f7661f8d0a21eeb37ec22 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Thu, 13 Jul 2017 15:28:09 +0200 Subject: Add 'mutool trace' command. --- Makefile | 2 +- docs/index.html | 4 +- docs/manual-mutool-trace.html | 102 +++++++++++++++++++++++++ source/fitz/trace-device.c | 2 +- source/tools/mutool.c | 2 + source/tools/mutrace.c | 170 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 docs/manual-mutool-trace.html create mode 100644 source/tools/mutrace.c diff --git a/Makefile b/Makefile index e6236a57..6b9b3ced 100644 --- a/Makefile +++ b/Makefile @@ -351,7 +351,7 @@ INSTALL_LIBS := $(MUPDF_LIB) $(THIRD_LIB) # --- Tools and Apps --- MUTOOL_EXE := $(OUT)/mutool -MUTOOL_SRC := source/tools/mutool.c source/tools/muconvert.c source/tools/mudraw.c source/tools/murun.c +MUTOOL_SRC := source/tools/mutool.c source/tools/muconvert.c source/tools/mudraw.c source/tools/murun.c source/tools/mutrace.c MUTOOL_SRC += $(sort $(wildcard source/tools/pdf*.c)) MUTOOL_OBJ := $(MUTOOL_SRC:%.c=$(OUT)/%.o) $(MUTOOL_OBJ) : $(FITZ_HDR) $(PDF_HDR) diff --git a/docs/index.html b/docs/index.html index 314578f3..f91906d4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -61,7 +61,7 @@ The iOS viewer is available on the mutool draw @@ -69,6 +69,8 @@ For rendering and converting documents there are two commands available: It is primarily used for rendering a document to image files.
mutool convert
This tool is used for converting documents into other formats, and is easier to use. +
mutool trace +
This is a debugging tool used for printing a trace of the graphics device calls on a page.

diff --git a/docs/manual-mutool-trace.html b/docs/manual-mutool-trace.html new file mode 100644 index 00000000..05e324c1 --- /dev/null +++ b/docs/manual-mutool-trace.html @@ -0,0 +1,102 @@ + + + +mutool trace + + + + + + +

+

mutool trace

+
+ + + +
+ +

+The 'mutool trace' command prints a trace of device calls needed to render a page. + +

+mutool trace [options] input [pages]
+
+ +

+The command line options are: + +

+
input +
Input file name. + The input can be any of the document formats supported by MuPDF: PDF, XPS, CBZ, unprotected EPUB, FB2, etc. +
[pages] +
Comma separated list of page ranges. The first page is "1", and the last page is "N". The default is "1-N". +
-p password +
Password to use for password protected PDF documents. +
+ +
+
-W width +
Page width in points for EPUB layout. +
-H height +
Page height in points for EPUB layout. +
-S font-size +
Font size in points for EPUB layout. +
-U stylesheet.css +
File name of user style sheet for EPUB layout. +
-X +
Disable document styles for EPUB layout. +
+ +
+
-d +
Use display list. Run the page to a display list first, then trace running the display list. +
+ +

+The trace takes the form of an XML document, with the root element being the document, +its children each page, and one page child element for each device call on that page. + +

+An example trace: + +

+<document filename="hello.pdf">
+<page number="1" mediabox="0 0 595 842">
+<fill_path winding="nonzero" colorspace="DeviceRGB" color="1 0 0" matrix="1 0 0 -1 0 842">
+<moveto x="50" y="50"/>
+<lineto x="100" y="200"/>
+<lineto x="200" y="50"/>
+</fill_path>
+<fill_text colorspace="DeviceRGB" color="0" matrix="1 0 0 -1 0 842">
+<span font="Times-Roman" wmode="0" trm="100 0 0 100">
+<g unicode="H" glyph="H" x="50" y="500" />
+<g unicode="e" glyph="e" x="122.2" y="500" />
+<g unicode="l" glyph="l" x="166.6" y="500" />
+<g unicode="l" glyph="l" x="194.4" y="500" />
+<g unicode="o" glyph="o" x="222.2" y="500" />
+<g unicode="!" glyph="exclam" x="272.2" y="500" />
+</span>
+</fill_text>
+</page>
+</document>
+
+
+ +
+ +
+ +Copyright © 2006-2017 Artifex Software Inc. +
+ + + diff --git a/source/fitz/trace-device.c b/source/fitz/trace-device.c index 13ce7256..2b7b24aa 100644 --- a/source/fitz/trace-device.c +++ b/source/fitz/trace-device.c @@ -332,7 +332,7 @@ static int fz_trace_begin_tile(fz_context *ctx, fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id) { fz_output *out = ((fz_trace_device*)dev)->out; - fz_write_printf(ctx, out, "x0, area->y0, area->x1, area->y1); fz_write_printf(ctx, out, " view=\"%g %g %g %g\"", view->x0, view->y0, view->x1, view->y1); fz_write_printf(ctx, out, " xstep=\"%g\" ystep=\"%g\"", xstep, ystep); diff --git a/source/tools/mutool.c b/source/tools/mutool.c index 688c4fbb..3e4cbf09 100644 --- a/source/tools/mutool.c +++ b/source/tools/mutool.c @@ -13,6 +13,7 @@ int muconvert_main(int argc, char *argv[]); int mudraw_main(int argc, char *argv[]); +int mutrace_main(int argc, char *argv[]); int murun_main(int argc, char *argv[]); int pdfclean_main(int argc, char *argv[]); @@ -38,6 +39,7 @@ static struct { { pdfcreate_main, "create", "create pdf document" }, #endif { mudraw_main, "draw", "convert document" }, + { mutrace_main, "trace", "trace device calls" }, #if FZ_ENABLE_PDF { pdfextract_main, "extract", "extract font and image resources" }, #endif diff --git a/source/tools/mutrace.c b/source/tools/mutrace.c new file mode 100644 index 00000000..2baef7d1 --- /dev/null +++ b/source/tools/mutrace.c @@ -0,0 +1,170 @@ +#include "mupdf/fitz.h" + +#include +#include +#include + +static void usage(void) +{ + fprintf(stderr, + "Usage: mutool trace [options] file [pages]\n" + "\t-p -\tpassword\n" + "\n" + "\t-W -\tpage width for EPUB layout\n" + "\t-H -\tpage height for EPUB layout\n" + "\t-S -\tfont size for EPUB layout\n" + "\t-U -\tfile name of user stylesheet for EPUB layout\n" + "\t-X\tdisable document styles for EPUB layout\n" + "\n" + "\t-d\tuse display list\n" + "\n" + "\tpages\tcomma separated list of page numbers and ranges\n" + ); + exit(1); +} + +static float layout_w = 450; +static float layout_h = 600; +static float layout_em = 12; +static char *layout_css = NULL; +static int layout_use_doc_css = 1; + +static int use_display_list = 0; + +static void runpage(fz_context *ctx, fz_document *doc, int number) +{ + fz_page *page = NULL; + fz_display_list *list = NULL; + fz_device *dev = NULL; + fz_rect mediabox; + + fz_var(page); + fz_var(list); + fz_var(dev); + fz_try(ctx) + { + page = fz_load_page(ctx, doc, number - 1); + fz_bound_page(ctx, page, &mediabox); + printf("\n", + number, mediabox.x0, mediabox.y0, mediabox.x1, mediabox.y1); + dev = fz_new_trace_device(ctx, fz_stdout(ctx)); + if (use_display_list) + { + list = fz_new_display_list_from_page(ctx, page); + fz_run_display_list(ctx, list, dev, &fz_identity, NULL, NULL); + } + else + { + fz_run_page(ctx, page, dev, &fz_identity, NULL); + } + printf("\n"); + } + fz_always(ctx) + { + fz_drop_display_list(ctx, list); + fz_drop_page(ctx, page); + fz_drop_device(ctx, dev); + } + fz_catch(ctx) + fz_rethrow(ctx); +} + +static void runrange(fz_context *ctx, fz_document *doc, int count, const char *range) +{ + int start, end, i; + + while ((range = fz_parse_page_range(ctx, range, &start, &end, count))) + { + if (start < end) + for (i = start; i <= end; ++i) + runpage(ctx, doc, i); + else + for (i = start; i >= end; --i) + runpage(ctx, doc, i); + } +} + +int mutrace_main(int argc, char **argv) +{ + fz_context *ctx; + fz_document *doc = NULL; + char *password = ""; + int i, c, count; + + while ((c = fz_getopt(argc, argv, "p:W:H:S:U:Xd")) != -1) + { + switch (c) + { + default: usage(); break; + case 'p': password = fz_optarg; break; + + case 'W': layout_w = fz_atof(fz_optarg); break; + case 'H': layout_h = fz_atof(fz_optarg); break; + case 'S': layout_em = fz_atof(fz_optarg); break; + case 'U': layout_css = fz_optarg; break; + case 'X': layout_use_doc_css = 0; break; + + case 'd': use_display_list = 1; break; + } + } + + if (fz_optind == argc) + usage(); + + ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); + if (!ctx) + { + fprintf(stderr, "cannot create mupdf context\n"); + return EXIT_FAILURE; + } + + fz_try(ctx) + { + fz_register_document_handlers(ctx); + if (layout_css) + { + fz_buffer *buf = fz_read_file(ctx, layout_css); + fz_set_user_css(ctx, fz_string_from_buffer(ctx, buf)); + fz_drop_buffer(ctx, buf); + } + fz_set_use_document_css(ctx, layout_use_doc_css); + } + fz_catch(ctx) + { + fprintf(stderr, "cannot initialize mupdf: %s\n", fz_caught_message(ctx)); + fz_drop_context(ctx); + return EXIT_FAILURE; + } + + fz_var(doc); + fz_try(ctx) + { + for (i = fz_optind; i < argc; ++i) + { + doc = fz_open_document(ctx, argv[i]); + if (fz_needs_password(ctx, doc)) + if (!fz_authenticate_password(ctx, doc, password)) + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot authenticate password: %s", argv[i]); + fz_layout_document(ctx, doc, layout_w, layout_h, layout_em); + printf("\n", argv[i]); + count = fz_count_pages(ctx, doc); + if (i+1 < argc && fz_is_page_range(ctx, argv[i+1])) + runrange(ctx, doc, count, argv[++i]); + else + runrange(ctx, doc, count, "1-N"); + printf("\n"); + fz_drop_document(ctx, doc); + doc = NULL; + } + } + fz_catch(ctx) + { + fprintf(stderr, "cannot run document: %s\n", fz_caught_message(ctx)); + fz_drop_document(ctx, doc); + fz_drop_context(ctx); + return EXIT_FAILURE; + } + + fz_drop_context(ctx); + return EXIT_SUCCESS; +} -- cgit v1.2.3