summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--docs/index.html4
-rw-r--r--docs/manual-mutool-trace.html102
-rw-r--r--source/fitz/trace-device.c2
-rw-r--r--source/tools/mutool.c2
-rw-r--r--source/tools/mutrace.c170
6 files changed, 279 insertions, 3 deletions
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 <a href="https://itunes.apple.com/us/app/mupd
The command line tools are all gathered into one umbrella command: mutool.
<p>
-For rendering and converting documents there are two commands available:
+For rendering and converting documents there are three commands available:
<dl>
<dt><a href="manual-mutool-draw.html">mutool draw</a>
@@ -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.
<dt><a href="manual-mutool-convert.html">mutool convert</a>
<dd>This tool is used for converting documents into other formats, and is easier to use.
+<dt><a href="manual-mutool-trace.html">mutool trace</a>
+<dd>This is a debugging tool used for printing a trace of the graphics device calls on a page.
</dl>
<p>
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 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>mutool trace</title>
+<link rel="stylesheet" href="style.css" type="text/css">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+
+<body>
+
+<header>
+<h1>mutool trace</h1>
+</header>
+
+<nav>
+<a href="http://mupdf.com/index.html">ABOUT</a>
+<a href="http://mupdf.com/news.html">NEWS</a>
+<a href="index.html">DOCUMENTATION</a>
+<a href="http://mupdf.com/downloads/">DOWNLOAD</a>
+<a href="http://git.ghostscript.com/?p=mupdf.git;a=summary">SOURCE</a>
+<a href="https://bugs.ghostscript.com/">BUGS</a>
+</nav>
+
+<article>
+
+<p>
+The 'mutool trace' command prints a trace of device calls needed to render a page.
+
+<pre>
+mutool trace [options] input [pages]
+</pre>
+
+<p>
+The command line options are:
+
+<dl>
+<dt><i>input</i>
+ <dd>Input file name.
+ The input can be any of the document formats supported by MuPDF: PDF, XPS, CBZ, unprotected EPUB, FB2, etc.
+<dt>[pages]
+ <dd>Comma separated list of page ranges. The first page is "1", and the last page is "N". The default is "1-N".
+<dt>-p <i>password</i>
+ <dd>Password to use for password protected PDF documents.
+</dl>
+
+<dl>
+<dt>-W <i>width</i>
+ <dd>Page width in points for EPUB layout.
+<dt>-H <i>height</i>
+ <dd>Page height in points for EPUB layout.
+<dt>-S <i>font-size</i>
+ <dd>Font size in points for EPUB layout.
+<dt>-U <i>stylesheet.css</i>
+ <dd>File name of user style sheet for EPUB layout.
+<dt>-X
+ <dd>Disable document styles for EPUB layout.
+</dl>
+
+<dl>
+<dt>-d
+ <dd>Use display list. Run the page to a display list first, then trace running the display list.
+</dl>
+
+<p>
+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.
+
+<p>
+An example trace:
+
+<pre>
+&lt;document filename="hello.pdf"&gt;
+&lt;page number="1" mediabox="0 0 595 842"&gt;
+&lt;fill_path winding="nonzero" colorspace="DeviceRGB" color="1 0 0" matrix="1 0 0 -1 0 842"&gt;
+&lt;moveto x="50" y="50"/&gt;
+&lt;lineto x="100" y="200"/&gt;
+&lt;lineto x="200" y="50"/&gt;
+&lt;/fill_path&gt;
+&lt;fill_text colorspace="DeviceRGB" color="0" matrix="1 0 0 -1 0 842"&gt;
+&lt;span font="Times-Roman" wmode="0" trm="100 0 0 100"&gt;
+&lt;g unicode="H" glyph="H" x="50" y="500" /&gt;
+&lt;g unicode="e" glyph="e" x="122.2" y="500" /&gt;
+&lt;g unicode="l" glyph="l" x="166.6" y="500" /&gt;
+&lt;g unicode="l" glyph="l" x="194.4" y="500" /&gt;
+&lt;g unicode="o" glyph="o" x="222.2" y="500" /&gt;
+&lt;g unicode="!" glyph="exclam" x="272.2" y="500" /&gt;
+&lt;/span&gt;
+&lt;/fill_text&gt;
+&lt;/page&gt;
+&lt;/document&gt;
+
+</pre>
+
+</article>
+
+<footer>
+<a href="http://artifex.com"><img src="artifex-logo.png" align="right"></a>
+Copyright &copy; 2006-2017 Artifex Software Inc.
+</footer>
+
+</body>
+</html>
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, "<tile");
+ fz_write_printf(ctx, out, "<tile id=\"%d\"", id);
fz_write_printf(ctx, out, " area=\"%g %g %g %g\"", area->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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+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("<page number=\"%d\" mediabox=\"%g %g %g %g\">\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("</page>\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("<document filename=\"%s\">\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("</document>\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;
+}