summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/example.c100
-rw-r--r--docs/man/mudraw.189
-rw-r--r--docs/man/mupdf.192
-rw-r--r--docs/man/mutool.177
-rw-r--r--docs/multi-threaded.c266
-rw-r--r--docs/naming.txt30
-rw-r--r--docs/overview.txt268
-rw-r--r--docs/refcount.txt17
-rw-r--r--docs/thirdparty.txt38
9 files changed, 977 insertions, 0 deletions
diff --git a/docs/example.c b/docs/example.c
new file mode 100644
index 00000000..1a21c200
--- /dev/null
+++ b/docs/example.c
@@ -0,0 +1,100 @@
+// Rendering a page of a PDF document to a PNG image in less than 100 lines.
+
+// Compile a debug build of mupdf, then compile and run this example:
+//
+// gcc -g -o build/debug/example -Iinclude doc/example.c build/debug/lib*.a -lm
+//
+// build/debug/example /path/to/document.pdf 1 200 25
+
+// Include the MuPDF header file.
+#include <mupdf/fitz.h>
+
+void
+render(char *filename, int pagenumber, int zoom, int rotation)
+{
+ // Create a context to hold the exception stack and various caches.
+
+ fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
+
+ // Open the PDF, XPS or CBZ document.
+
+ fz_document *doc = fz_open_document(ctx, filename);
+
+ // Retrieve the number of pages (not used in this example).
+
+ int pagecount = fz_count_pages(doc);
+
+ // Load the page we want. Page numbering starts from zero.
+
+ fz_page *page = fz_load_page(doc, pagenumber - 1);
+
+ // Calculate a transform to use when rendering. This transform
+ // contains the scale and rotation. Convert zoom percentage to a
+ // scaling factor. Without scaling the resolution is 72 dpi.
+
+ fz_matrix transform;
+ fz_rotate(&transform, rotation);
+ fz_pre_scale(&transform, zoom / 100.0f, zoom / 100.0f);
+
+ // Take the page bounds and transform them by the same matrix that
+ // we will use to render the page.
+
+ fz_rect bounds;
+ fz_bound_page(doc, page, &bounds);
+ fz_transform_rect(&bounds, &transform);
+
+ // Create a blank pixmap to hold the result of rendering. The
+ // pixmap bounds used here are the same as the transformed page
+ // bounds, so it will contain the entire page. The page coordinate
+ // space has the origin at the top left corner and the x axis
+ // extends to the right and the y axis extends down.
+
+ fz_irect bbox;
+ fz_round_rect(&bbox, &bounds);
+ fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
+ fz_clear_pixmap_with_value(ctx, pix, 0xff);
+
+ // A page consists of a series of objects (text, line art, images,
+ // gradients). These objects are passed to a device when the
+ // interpreter runs the page. There are several devices, used for
+ // different purposes:
+ //
+ // draw device -- renders objects to a target pixmap.
+ //
+ // text device -- extracts the text in reading order with styling
+ // information. This text can be used to provide text search.
+ //
+ // list device -- records the graphic objects in a list that can
+ // be played back through another device. This is useful if you
+ // need to run the same page through multiple devices, without
+ // the overhead of parsing the page each time.
+
+ // Create a draw device with the pixmap as its target.
+ // Run the page with the transform.
+
+ fz_device *dev = fz_new_draw_device(ctx, pix);
+ fz_run_page(doc, page, dev, &transform, NULL);
+ fz_free_device(dev);
+
+ // Save the pixmap to a file.
+
+ fz_write_png(ctx, pix, "out.png", 0);
+
+ // Clean up.
+
+ fz_drop_pixmap(ctx, pix);
+ fz_free_page(doc, page);
+ fz_close_document(doc);
+ fz_free_context(ctx);
+}
+
+int main(int argc, char **argv)
+{
+ char *filename = argv[1];
+ int pagenumber = argc > 2 ? atoi(argv[2]) : 1;
+ int zoom = argc > 3 ? atoi(argv[3]) : 100;
+ int rotation = argc > 4 ? atoi(argv[4]) : 0;
+
+ render(filename, pagenumber, zoom, rotation);
+ return 0;
+}
diff --git a/docs/man/mudraw.1 b/docs/man/mudraw.1
new file mode 100644
index 00000000..eec79f7b
--- /dev/null
+++ b/docs/man/mudraw.1
@@ -0,0 +1,89 @@
+.TH MUDRAW 1 "March 28, 2012"
+.\" Please adjust this date whenever revising the manpage.
+.SH NAME
+mudraw \- render PDF/XPS/CBZ documents
+.SH SYNOPSIS
+.B mudraw
+.RI [ options ]
+.RI input.{pdf,xps,cbz}
+.RI [ pages]
+.SH DESCRIPTION
+.B mudraw
+will render a document of a supported document format to image files.
+The supported document formats are: pdf, xps and cbz.
+The supported image formats are: pgm, ppm, pam and png.
+Select the pages to be rendered by specifying a comma
+separated list of ranges and individual page numbers (for example: 1,5,10-15).
+In no pages are specified all the pages will be rendered.
+.SH OPTIONS
+.TP
+.B \-o output
+The image format is deduced from the output file name.
+Embed %d in the name to indicate the page number (for example: "page%d.png").
+.TP
+.B \-p password
+Use the specified password if the file is encrypted.
+.TP
+.B \-r resolution
+Render the page at the specified resolution.
+The default resolution is 72 dpi.
+.TP
+.B \-w width
+Render the page at the specified width (or, if the -r flag is used,
+render with a maximum width).
+.TP
+.B \-h height
+Render the page at the specified height (or, if the -r flag is used,
+render with a maximum height).
+.TP
+.B \-f
+'Fit' exactly; ignore the aspect ratio when matching specified width/heights.
+.TP
+.B \-R angle
+Rotate clockwise by given number of degrees.
+.TP
+.B \-a
+Save the alpha channel.
+The default behavior is to render each page with a white background.
+With this option, the page background is transparent.
+Only supported for pam and png output formats.
+.TP
+.B \-g
+Render in grayscale.
+The default is to render a full color RGB image.
+If the output format is pgm or ppm this option is ignored.
+.TP
+.B \-m
+Show timing information.
+Take the time it takes for each page to render and print
+a summary at the end.
+.TP
+.B \-5
+Print an MD5 checksum of the rendered image data for each page.
+.TP
+.B \-t
+Print the text contents of each page in UTF-8 encoding.
+Give the option twice to print detailed information
+about the location of each character in XML format.
+.TP
+.B \-x
+Print the display list used to render each page.
+.TP
+.B \-A
+Disable the use of accelerated functions.
+.TP
+.B \-G gamma
+Gamma correct the output image.
+Some typical values are 0.7 or 1.4 to thin or darken text rendering.
+.TP
+.B \-I
+Invert the output image colors.
+.TP
+.B pages
+Comma separated list of ranges to render.
+.SH SEE ALSO
+.BR mupdf (1),
+.BR mupdfclean (1).
+.BR mupdfshow (1).
+.SH AUTHOR
+MuPDF is Copyright 2006-2013 Artifex Software, Inc.
diff --git a/docs/man/mupdf.1 b/docs/man/mupdf.1
new file mode 100644
index 00000000..a4a268a5
--- /dev/null
+++ b/docs/man/mupdf.1
@@ -0,0 +1,92 @@
+.TH MUPDF 1 "June 12, 2012"
+.\" Please adjust this date whenever revising the manpage.
+.SH NAME
+mupdf \- MuPDF is a lightweight PDF viewer written in portable C
+.SH SYNOPSIS
+.B mupdf
+.RI [ options ] " PDFfile"
+.SH DESCRIPTION
+This manual page briefly describes the
+.B mupdf
+command.
+.PP
+.SH OPTIONS
+A description of each of the supported options is included below.
+.TP
+.B \-p password
+Uses the given password to open an encrypted PDF file.
+The password is tried both as user and owner password.
+.TP
+.B \-r resolution
+Changes the initial zoom level, specified as the resolution in dpi.
+The default value is 72.
+.SH MOUSE AND KEY BINDINGS
+In addition to the key bindings described below, the mouse can also be
+used. Clicking the left mouse button follows links within the PDF while
+dragging with the left mouse button pans the page. Dragging with the right
+mouse button selects an area and copies the enclosed text to the clipboard
+buffer. Using the scroll-wheel while pressing Control zooms in/out, if
+Shift is pressed on the other hand then the page is panned.
+.TP
+.B L, R
+Rotate page left (clockwise) or right (counter-clockwise).
+.TP
+.B h, j, k, l
+Scroll page left, down, up, or right.
+.TP
+.B \+, \-
+Zoom in or out.
+.TP
+.B W, H
+Zoom so page exactly fits width or height of window.
+.TP
+.B w
+Shrinkwrap window to fit the page.
+.TP
+.B r
+Reload file.
+.TP
+.B . pgdn right space
+Go to the next page
+.TP
+.B , pgup left b backspace
+Go to the previous page
+.TP
+.B <, >
+Skip back/forth 10 pages at a time.
+.TP
+.B m
+Mark page for snap back.
+.TP
+.B t
+Pop back to the latest mark.
+.TP
+.B [0-9]m
+Save the current page number in the numbered register.
+.TP
+.B [0-9]t
+Go to the page saved in the numbered register.
+.TP
+.B 123g
+Go to page 123.
+.TP
+.B /
+Search for text.
+.TP
+.B n, N
+Find the next/previous search result.
+.TP
+.B c
+Toggle between color and grayscale rendering.
+.TP
+.B i
+Toggle between normal and inverted color rendering.
+.P
+Sending a \fBSIGHUP\fR signal to the mupdf process will also cause the viewed
+file to be reloaded automatically, for use in e.g. build scripts.
+.SH SEE ALSO
+.BR mupdfclean (1),
+.BR mupdfdraw (1),
+.BR mupdfshow (1).
+.SH AUTHOR
+MuPDF is Copyright 2006-2013 Artifex Software, Inc.
diff --git a/docs/man/mutool.1 b/docs/man/mutool.1
new file mode 100644
index 00000000..d1c7079b
--- /dev/null
+++ b/docs/man/mutool.1
@@ -0,0 +1,77 @@
+.TH "MUTOOL" "1" "Oct 02, 2012"
+.\" Please adjust this date whenever revising the manpage.
+.\" no hyphenation
+.nh
+.\" adjust left
+.ad l
+.SH NAME
+mutool \- all purpose tool for dealing with PDF files
+.SH SYNOPSIS
+mutool <sub-command> [options]
+.SH DESCRIPTION
+mutool is a tool based on MuPDF for dealing with PDF files in various manners.
+There are several sub commands available, as described below.
+.SH CLEAN
+mutool clean [options] input.pdf [output.pdf] [pages]
+.PP
+The clean command pretty prints and rewrites the syntax of a PDF file.
+It can be used to repair broken files, expand compressed streams, filter
+out a range of pages, etc.
+.PP
+If no output file is specified, it will write the cleaned PDF to "out.pdf"
+in the current directory.
+.TP
+.B \-p password
+Use the specified password if the file is encrypted.
+.TP
+.B \-g
+Garbage collect objects that have no references from other objects.
+Give the option twice to renumber all objects and compact the cross reference table.
+Give it three times to merge and reuse duplicate objects.
+.TP
+.B \-d
+Decompress streams. This will make the output file larger, but provides
+easy access for reading and editing the contents with a text editor.
+.TP
+.B pages
+Comma separated list of page ranges to include.
+.SH EXTRACT
+TODO
+.SH INFO
+TODO
+.SH POSTER
+TODO
+.SH SHOW
+mutool show [options] file.pdf [object numbers ...]
+.PP
+The show command will print the specified objects and streams to stdout.
+Streams are decoded and non-printable characters are represented
+with a period by default.
+.TP
+.B \-b
+Print streams as binary data and omit the object header.
+.TP
+.B \-e
+Print streams in their original encoded (or compressed) form.
+.TP
+.B \-p password
+Use the specified password if the file is encrypted.
+.PP
+Specify objects by number, or use one of the following special names:
+.TP
+.B 'xref' or 'x'
+Print the cross reference table.
+.TP
+.B 'trailer' or 't'
+Print the trailer dictionary.
+.TP
+.B 'pages' or 'p'
+List the object numbers for every page.
+.TP
+.B 'grep' or 'g'
+Print all the objects in the file in a compact one-line format suitable for piping to grep.
+.SH SEE ALSO
+.BR mupdf (1),
+.BR mudraw (1).
+.SH AUTHOR
+MuPDF is Copyright 2006-2013 Artifex Software, Inc.
diff --git a/docs/multi-threaded.c b/docs/multi-threaded.c
new file mode 100644
index 00000000..3141e3c4
--- /dev/null
+++ b/docs/multi-threaded.c
@@ -0,0 +1,266 @@
+// Multi-threaded rendering of all pages in a document to PNG images.
+
+// First look at doc/example.c and make sure you understand it.
+// Then read the multi-threading section in doc/overview.txt,
+// before coming back here to see an example of multi-threading.
+
+// This example will create one main thread for reading pages from the
+// document, and one thread per page for rendering. After rendering
+// the main thread will wait for each rendering thread to complete before
+// writing that thread's rendered image to a PNG image. There is
+// nothing in MuPDF requiring a rendering thread to only render a
+// single page, this is just a design decision taken for this example.
+
+// Compile a debug build of mupdf, then compile and run this example:
+//
+// gcc -g -o build/debug/example-mt -Iinclude doc/multi-threading.c \
+// build/debug/lib*.a -lpthread -lm
+//
+// build/debug/example-mt /path/to/document.pdf
+//
+// Caution! As all pages are rendered simultaneously, please choose a
+// file with just a few pages to avoid stressing your machine too
+// much. Also you may run in to a limitation on the number of threads
+// depending on your environment.
+
+// Include the MuPDF header file, and pthread's header file.
+#include <mupdf/fitz.h>
+#include <pthread.h>
+
+// A convenience function for dying abruptly on pthread errors.
+
+void
+fail(char *msg)
+{
+ fprintf(stderr, "%s", msg);
+ abort();
+}
+
+// The data structure passed between the requesting main thread and
+// each rendering thread.
+
+struct data {
+ // A pointer to the original context in the main thread sent
+ // from main to rendering thread. It will be used to create
+ // each rendering thread's context clone.
+ fz_context *ctx;
+
+ // Page number sent from main to rendering thread for printing
+ int pagenumber;
+
+ // The display list as obtained by the main thread and sent
+ // from main to rendering thread. This contains the drawing
+ // commands (text, images, etc.) for the page that should be
+ // rendered.
+ fz_display_list *list;
+
+ // The area of the page to render as obtained by the main
+ // thread and sent from main to rendering thread.
+ fz_rect bbox;
+
+ // This is the result, a pixmap containing the rendered page.
+ // It is passed first from main thread to the rendering
+ // thread, then its samples are changed by the rendering
+ // thread, and then back from the rendering thread to the main
+ // thread.
+ fz_pixmap *pix;
+};
+
+// This is the function run by each rendering function. It takes
+// pointer to an instance of the data structure described above and
+// renders the display list into the pixmap before exiting.
+
+void *
+renderer(void *data)
+{
+ int pagenumber = ((struct data *) data)->pagenumber;
+ fz_context *ctx = ((struct data *) data)->ctx;
+ fz_display_list *list = ((struct data *) data)->list;
+ fz_rect bbox = ((struct data *) data)->bbox;
+ fz_pixmap *pix = ((struct data *) data)->pix;
+
+ fprintf(stderr, "thread at page %d loading!\n", pagenumber);
+
+ // The context pointer is pointing to the main thread's
+ // context, so here we create a new context based on it for
+ // use in this thread.
+
+ ctx = fz_clone_context(ctx);
+
+ // Next we run the display list through the draw device which
+ // will render the request area of the page to the pixmap.
+
+ fprintf(stderr, "thread at page %d rendering!\n", pagenumber);
+ fz_device *dev = fz_new_draw_device(ctx, pix);
+ fz_run_display_list(list, dev, &fz_identity, &bbox, NULL);
+ fz_free_device(dev);
+
+ // This threads context is freed.
+
+ fz_free_context(ctx);
+
+ fprintf(stderr, "thread at page %d done!\n", pagenumber);
+
+ return data;
+}
+
+// These are the two locking functions required by MuPDF when
+// operating in a multi-threaded environment. They each take a user
+// argument that can be used to transfer some state, in this case a
+// pointer to the array of mutexes.
+
+void lock_mutex(void *user, int lock)
+{
+ pthread_mutex_t *mutex = (pthread_mutex_t *) user;
+
+ if (pthread_mutex_lock(&mutex[lock]) != 0)
+ fail("pthread_mutex_lock()");
+}
+
+void unlock_mutex(void *user, int lock)
+{
+ pthread_mutex_t *mutex = (pthread_mutex_t *) user;
+
+ if (pthread_mutex_unlock(&mutex[lock]) != 0)
+ fail("pthread_mutex_unlock()");
+}
+
+int main(int argc, char **argv)
+{
+ char *filename = argv[1];
+ pthread_t *thread = NULL;
+ fz_locks_context locks;
+ pthread_mutex_t mutex[FZ_LOCK_MAX];
+ int i;
+
+ // Initialize FZ_LOCK_MAX number of non-recursive mutexes.
+
+ for (i = 0; i < FZ_LOCK_MAX; i++)
+ {
+ if (pthread_mutex_init(&mutex[i], NULL) != 0)
+ fail("pthread_mutex_init()");
+ }
+
+ // Initialize the locking structure with function pointers to
+ // the locking functions and to the user data. In this case
+ // the user data is a pointer to the array of mutexes so the
+ // locking functions can find the relevant lock to change when
+ // they are called. This way we avoid global variables.
+
+ locks.user = mutex;
+ locks.lock = lock_mutex;
+ locks.unlock = unlock_mutex;
+
+ // This is the main threads context function, so supply the
+ // locking structure. This context will be used to parse all
+ // the pages from the document.
+
+ fz_context *ctx = fz_new_context(NULL, &locks, FZ_STORE_UNLIMITED);
+
+ // Open the PDF, XPS or CBZ document.
+
+ fz_document *doc = fz_open_document(ctx, filename);
+
+ // Retrieve the number of pages, which translates to the
+ // number of threads used for rendering pages.
+
+ int threads = fz_count_pages(doc);
+ fprintf(stderr, "spawning %d threads, one per page...\n", threads);
+
+ thread = malloc(threads * sizeof (pthread_t));
+
+ for (i = 0; i < threads; i++)
+ {
+ // Load the relevant page for each thread.
+
+ fz_page *page = fz_load_page(doc, i);
+
+ // Compute the bounding box for each page.
+
+ fz_rect bbox;
+ fz_irect rbox;
+ fz_bound_page(doc, page, &bbox);
+
+ // Create a display list that will hold the drawing
+ // commands for the page.
+
+ fz_display_list *list = fz_new_display_list(ctx);
+
+ // Run the loaded page through a display list device
+ // to populate the page's display list.
+
+ fz_device *dev = fz_new_list_device(ctx, list);
+ fz_run_page(doc, page, dev, &fz_identity, NULL);
+ fz_free_device(dev);
+
+ // The page is no longer needed, all drawing commands
+ // are now in the display list.
+
+ fz_free_page(doc, page);
+
+ // Create a white pixmap using the correct dimensions.
+
+ fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_round_rect(&rbox, &bbox));
+ fz_clear_pixmap_with_value(ctx, pix, 0xff);
+
+ // Populate the data structure to be sent to the
+ // rendering thread for this page.
+
+ struct data *data = malloc(sizeof (struct data));
+
+ data->pagenumber = i + 1;
+ data->ctx = ctx;
+ data->list = list;
+ data->bbox = bbox;
+ data->pix = pix;
+
+ // Create the thread and pass it the data structure.
+
+ if (pthread_create(&thread[i], NULL, renderer, data) != 0)
+ fail("pthread_create()");
+ }
+
+ // Now each thread is rendering pages, so wait for each thread
+ // to complete its rendering.
+
+ fprintf(stderr, "joining %d threads...\n", threads);
+ for (i = threads - 1; i >= 0; i--)
+ {
+ char filename[42];
+ struct data *data;
+
+ if (pthread_join(thread[i], (void **) &data) != 0)
+ fail("pthread_join");
+
+ sprintf(filename, "out%04d.png", i);
+ fprintf(stderr, "\tSaving %s...\n", filename);
+
+ // Write the rendered image to a PNG file
+
+ fz_write_png(ctx, data->pix, filename, 0);
+
+ // Free the thread's pixmap and display list since
+ // they were allocated by the main thread above.
+
+ fz_drop_pixmap(ctx, data->pix);
+ fz_free_display_list(ctx, data->list);
+
+ // Free the data structured passed back and forth
+ // between the main thread and rendering thread.
+
+ free(data);
+ }
+
+ fprintf(stderr, "finally!\n");
+ fflush(NULL);
+
+ free(thread);
+
+ // Finally the document is closed and the main thread's
+ // context is freed.
+
+ fz_close_document(doc);
+ fz_free_context(ctx);
+
+ return 0;
+}
diff --git a/docs/naming.txt b/docs/naming.txt
new file mode 100644
index 00000000..6c641c33
--- /dev/null
+++ b/docs/naming.txt
@@ -0,0 +1,30 @@
+Functions should be named according to one of the following schemes:
+
+ verb_noun
+ verb_noun_with_noun
+
+ noun_attribute
+ get_noun_attribute -- when the 'noun_attribute' name conflicts with a type
+ set_noun_attribute
+
+Prefixes are mandatory for exported functions, macros, enums, globals and types.
+
+ fz for common code
+ pdf, xps, etc., for interpreter specific code
+
+Prefixes are optional (but encouraged) for private functions and types.
+
+Avoid using 'get' as this is a meaningless and redundant filler word.
+
+These words are reserved for reference counting schemes:
+
+ new, find, load, open, keep -- return objects that you are responsible for freeing.
+
+ drop, free, close -- relinquish ownership of the object passed in.
+
+When searching for an object or value, the name used depends on whether
+returning the value is passing ownership:
+
+ lookup -- return a value or borrowed pointer
+
+ find -- return an object that the caller is responsible for freeing
diff --git a/docs/overview.txt b/docs/overview.txt
new file mode 100644
index 00000000..2d4e25d7
--- /dev/null
+++ b/docs/overview.txt
@@ -0,0 +1,268 @@
+Contents
+========
+
+* Basic MuPDF usage example
+* Common function arguments
+* Error Handling
+* Multi-threading
+
+Basic MuPDF usage example
+=========================
+
+For an example of how to use MuPDF in the most basic way, see
+doc/example.c. To limit the complexity and give an easier introduction
+this code has no error handling at all, but any serious piece of code
+using MuPDF should use the error handling strategies described below.
+
+Common function arguments
+=========================
+
+Many functions in MuPDFs interface take a context argument.
+
+A context contains global state used by MuPDF inside functions when
+parsing or rendering pages of the document. It contains for example:
+
+ an exception stack (see error handling below),
+
+ a memory allocator (allowing for custom allocators)
+
+ a resource store (for caching of images, fonts, etc.)
+
+ a set of locks and (un-)locking functions (for multi-threading)
+
+Other functions in MuPDF's interface take arguments such as document,
+stream and device which contain state for each type of object. Those
+arguments each have a reference to a context and therefore act as
+proxies for a context.
+
+Without the set of locks and accompanying functions the context and
+its proxies may only be used in a single-threaded application.
+
+Error handling
+==============
+
+MuPDF uses a set of exception handling macros to simplify error return
+and cleanup. Conceptually, they work a lot like C++'s try/catch
+system, but do not require any special compiler support.
+
+The basic formulation is as follows:
+
+ fz_try(ctx)
+ {
+ // Try to perform a task. Never 'return', 'goto' or
+ // 'longjmp' out of here. 'break' may be used to
+ // safely exit (just) the try block scope.
+ }
+ fz_always(ctx)
+ {
+ // Any code here is always executed, regardless of
+ // whether an exception was thrown within the try or
+ // not. Never 'return', 'goto' or longjmp out from
+ // here. 'break' may be used to safely exit (just) the
+ // always block scope.
+ }
+ fz_catch(ctx)
+ {
+ // This code is called (after any always block) only
+ // if something within the fz_try block (including any
+ // functions it called) threw an exception. The code
+ // here is expected to handle the exception (maybe
+ // record/report the error, cleanup any stray state
+ // etc) and can then either exit the block, or pass on
+ // the exception to a higher level (enclosing) fz_try
+ // block (using fz_throw, or fz_rethrow).
+ }
+
+The fz_always block is optional, and can safely be omitted.
+
+The macro based nature of this system has 3 main limitations:
+
+1) Never return from within try (or 'goto' or longjmp out of it).
+ This upsets the internal housekeeping of the macros and will
+ cause problems later on. The code will detect such things
+ happening, but by then it is too late to give a helpful error
+ report as to where the original infraction occurred.
+
+2) The fz_try(ctx) { ... } fz_always(ctx) { ... } fz_catch(ctx) { ... }
+ is not one atomic C statement. That is to say, if you do:
+
+ if (condition)
+ fz_try(ctx) { ... }
+ fz_catch(ctx) { ... }
+
+ then you will not get what you want. Use the following instead:
+
+ if (condition) {
+ fz_try(ctx) { ... }
+ fz_catch(ctx) { ... }
+ }
+
+3) The macros are implemented using setjmp and longjmp, and so
+ the standard C restrictions on the use of those functions
+ apply to fz_try/fz_catch too. In particular, any "truly local"
+ variable that is set between the start of fz_try and something
+ in fz_try throwing an exception may become undefined as part
+ of the process of throwing that exception.
+
+ As a way of mitigating this problem, we provide an fz_var()
+ macro that tells the compiler to ensure that that variable is
+ not unset by the act of throwing the exception.
+
+A model piece of code using these macros then might be:
+
+ house build_house(plans *p)
+ {
+ material m = NULL;
+ walls w = NULL;
+ roof r = NULL;
+ house h = NULL;
+ tiles t = make_tiles();
+
+ fz_var(w);
+ fz_var(r);
+ fz_var(h);
+
+ fz_try(ctx)
+ {
+ fz_try(ctx)
+ {
+ m = make_bricks();
+ }
+ fz_catch(ctx)
+ {
+ // No bricks available, make do with straw?
+ m = make_straw();
+ }
+ w = make_walls(m, p);
+ r = make_roof(m, t);
+ // Note, NOT: return combine(w,r);
+ h = combine(w, r);
+ }
+ fz_always(ctx)
+ {
+ drop_walls(w);
+ drop_roof(r);
+ drop_material(m);
+ drop_tiles(t);
+ }
+ fz_catch(ctx)
+ {
+ fz_throw(ctx, "build_house failed");
+ }
+ return h;
+ }
+
+Things to note about this:
+
+a) If make_tiles throws an exception, this will immediately be
+ handled by some higher level exception handler. If it
+ succeeds, t will be set before fz_try starts, so there is no
+ need to fz_var(t);
+
+b) We try first off to make some bricks as our building material.
+ If this fails, we fall back to straw. If this fails, we'll end
+ up in the fz_catch, and the process will fail neatly.
+
+c) We assume in this code that combine takes new reference to
+ both the walls and the roof it uses, and therefore that w and
+ r need to be cleaned up in all cases.
+
+d) We assume the standard C convention that it is safe to destroy
+ NULL things.
+
+Multi-threading
+===============
+
+First off, study the basic usage example in doc/example.c and make
+sure you understand how it works as the data structures manipulated
+there will be refered to in this section too.
+
+MuPDF can usefully be built into a multi-threaded application without
+the library needing to know anything threading at all. If the library
+opens a document in one thread, and then sits there as a 'server'
+requesting pages and rendering them for other threads that need them,
+then the library is only ever being called from this one thread.
+
+Other threads can still be used to handle UI requests etc, but as far
+as MuPDF is concerned it is only being used in a single threaded way.
+In this instance, there are no threading issues with MuPDF at all,
+and it can safely be used without any locking, as described in the
+previous sections.
+
+This section will attempt to explain how to use MuPDF in the more
+complex case; where we genuinely want to call the MuPDF library
+concurrently from multiple threads within a single application.
+
+MuPDF can be invoked with a user supplied set of locking functions.
+It uses these to take mutexes around operations that would conflict
+if performed concurrently in multiple threads. By leaving the
+exact implementation of locks to the caller MuPDF remains threading
+library agnostic.
+
+The following simple rules should be followed to ensure that
+multi-threaded operations run smoothly:
+
+1) "No simultaneous calls to MuPDF in different threads are
+ allowed to use the same context."
+
+ Most of the time it is simplest to just use a different
+ context for every thread; just create a new context at the
+ same time as you create the thread.
+
+2) "The document is bound to the context with which it is created."
+
+ All subsequent accesses to the document implicitly use the same
+ context; this means that only 1 thread can ever be accessing
+ the document at once. This does not mean that the document can
+ only ever be used from one thread, though in many cases this
+ is the simplest structure overall.
+
+3) "Any device is bound to the context with which it is created."
+
+ All subsequent uses of a device implicitly use the context with
+ which it was created; this means that if a device is used with
+ a document, it should be created with the same context as that
+ document was. This does not mean that the device can only ever
+ be used from one thread, though in many cases this is the
+ simplest structure overall.
+
+So, how does a multi-threaded example differ from a non-multithreaded
+one?
+
+Firstly, when we create the first context, we call fz_new_context
+as before, but the second argument should be a pointer to a set
+of locking functions.
+
+The calling code should provide FZ_LOCK_MAX mutexes, which will be
+locked/unlocked by MuPDF calling the lock/unlock function pointers
+in the supplied structure with the user pointer from the structure
+and the lock number, i (0 <= i < FZ_LOCK_MAX). These mutexes can
+safely be recursive or non-recursive as MuPDF only calls in a non-
+recursive style.
+
+To make subsequent contexts, the user should NOT call fz_new_context
+again (as this will fail to share important resources such as the
+store and glyphcache), but should rather call fz_clone_context.
+Each of these cloned contexts can be freed by fz_free_context as
+usual.
+
+To open a document, call fz_open_document as usual, passing a context
+and a filename; this context is bound to the document. All future
+calls to access the document will use this context internally.
+
+Only one thread at a time can therefore perform operations such as
+fetching a page, or rendering that page to a display list. Once a
+display list has been obtained however, it can be rendered from any
+other thread (or even from several threads simultaneously, giving
+banded rendering).
+
+This means that an implementer has 2 basic choices when constructing
+an application to use MuPDF in multi-threaded mode. Either he can
+construct it so that a single nominated thread opens the document
+and then acts as a 'server' creating display lists for other threads
+to render, or he can add his own mutex around calls to mupdf that
+use the document. The former is likely to be far more efficient in
+the long run.
+
+For an example of how to do multi-threading see doc/multi-threaded.c
+which has a main thread and one rendering thread per page.
diff --git a/docs/refcount.txt b/docs/refcount.txt
new file mode 100644
index 00000000..e575142a
--- /dev/null
+++ b/docs/refcount.txt
@@ -0,0 +1,17 @@
+Reference counting uses special words in functions to make it easy to remember
+and follow the rules.
+
+Words that take ownership: new, find, load, open, keep.
+
+Words that release ownership: drop, free, close.
+
+If an object is returned by a function with one of the special words that take
+ownership, you are responsible for freeing it by calling "drop" or "free", or
+"close" before you return. You may pass ownership of an owned object by return
+it only if you name the function using one of the special words.
+
+Any objects returned by functions that do not have any of these special words,
+are borrowed and have a limited life time. Do not hold on to them past the
+duration of the current function, or stow them away inside structs. If you need
+to keep the object for longer than that, you have to either "keep" it or make
+your own copy.
diff --git a/docs/thirdparty.txt b/docs/thirdparty.txt
new file mode 100644
index 00000000..2233b634
--- /dev/null
+++ b/docs/thirdparty.txt
@@ -0,0 +1,38 @@
+ Third Party Libraries Used by MuPDF
+ ===================================
+
+
+Library Version Function License URL
+
+
+
+freetype 2.4.11 Font scaling Freetype http://www.freetype.org/
+ and rendering License
+
+
+
+jpeg 9.0 JPEG decoding "Free", with
+ acknowledgement http://www.ijg.org/
+
+
+
+openjpeg 2.0.0 JPEG 2000 BSD-style http://www.openjpeg.org/
+ (with patches) decoding
+
+
+zlib 1.2.7 (De)Flate zlib License http://www.zlib.net/
+ compression
+
+
+
+(Optional)
+v8 3.9 JavaScript BSD http://code.google.com/p/v8/
+ interpreter
+
+
+
+
+
+NOTE: jbig2dec is included in "thirdparty" but is copyright Artifex Software Inc.
+
+