summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-04-25 15:43:26 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-04-26 15:12:58 +0200
commita7c3d73078f9e0cfc12d7eee86d0e2de197768ab (patch)
tree3c3edc73cf4a49f4e1e8d31e7bc0cd388137314f
parentccba5ca5548a394670f4e71d1df5be0efc66db69 (diff)
downloadmupdf-a7c3d73078f9e0cfc12d7eee86d0e2de197768ab.tar.xz
Add 'mutool run' documentation.
-rw-r--r--.gitignore2
-rw-r--r--docs/mutool/examples/create-thumbnail.js19
-rw-r--r--docs/mutool/examples/draw-device.js45
-rw-r--r--docs/mutool/examples/draw-document.js9
-rw-r--r--docs/mutool/examples/pdf-create-lowlevel.js63
-rw-r--r--docs/mutool/examples/pdf-create.js35
-rw-r--r--docs/mutool/examples/pdf-merge.js66
-rw-r--r--docs/mutool/examples/trace-device.js102
-rw-r--r--docs/mutool/run.html635
9 files changed, 975 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 5eb056de..67d0403c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,7 +21,7 @@ cscope.*
*.pdf
*.xps
*.epub
-*.html
+*.fb2
*.xhtml
*.css
*.svg
diff --git a/docs/mutool/examples/create-thumbnail.js b/docs/mutool/examples/create-thumbnail.js
new file mode 100644
index 00000000..cf7a5886
--- /dev/null
+++ b/docs/mutool/examples/create-thumbnail.js
@@ -0,0 +1,19 @@
+// Create a PDF containing thumbnails of pages rendered from another PDF.
+
+var pdf = new PDFDocument()
+
+var subdoc = new Document("pdfref17.pdf")
+
+var resources = { XObject: {} }
+
+var contents = new Buffer()
+for (var i=0; i < 5; ++i) {
+ var pixmap = subdoc.loadPage(1140+i).toPixmap([0.2,0,0,0.2,0,0], DeviceRGB)
+ resources.XObject["Im" + i] = pdf.addImage(new Image(pixmap))
+ contents.writeLine("q 100 0 0 150 " + (50+100*i) + " 50 cm /Im" + i + " Do Q")
+}
+
+var page = pdf.addPage([0,0,100+i*100,250], 0, resources, contents)
+pdf.insertPage(-1, page)
+
+pdf.save("out.pdf")
diff --git a/docs/mutool/examples/draw-device.js b/docs/mutool/examples/draw-device.js
new file mode 100644
index 00000000..4912e956
--- /dev/null
+++ b/docs/mutool/examples/draw-device.js
@@ -0,0 +1,45 @@
+// Use device interface to draw some graphics and save as a PNG.
+
+var font = new Font("Times-Roman");
+var image = new Image("example.png");
+var path, text;
+
+var pixmap = new Pixmap(DeviceRGB, [0,0,500,600]);
+pixmap.clear(255);
+var device = new DrawDevice(pixmap);
+var transform = [2,0,0,2,0,0]
+{
+ text = new Text();
+ {
+ text.showString(font, [16,0,0,-16,100,30], "Hello, world!");
+ text.showString(font, [0,16,16,0,15,100], "Hello, world!");
+ }
+ device.fillText(text, transform, DeviceGray, [0], 1);
+
+ path = new Path();
+ {
+ path.moveTo(10, 10);
+ path.lineTo(90, 10);
+ path.lineTo(90, 90);
+ path.lineTo(10, 90);
+ path.closePath();
+ }
+ device.fillPath(path, false, transform, DeviceRGB, [1,0,0], 1);
+ device.strokePath(path, {dashes:[5,10], lineWidth:3, lineCap:'Round'}, transform, DeviceRGB, [0,0,0], 1);
+
+ path = new Path();
+ {
+ path.moveTo(100,100);
+ path.curveTo(150,100, 200,150, 200,200);
+ path.curveTo(200,300, 0,300, 100,100);
+ path.closePath();
+ }
+ device.clipPath(path, true, transform);
+ {
+ device.fillImage(image, Concat(transform, [300,0,0,300,0,0]), 1);
+ }
+ device.popClip();
+}
+//device.flush();
+
+pixmap.saveAsPNG("out.png");
diff --git a/docs/mutool/examples/draw-document.js b/docs/mutool/examples/draw-document.js
new file mode 100644
index 00000000..1e285ede
--- /dev/null
+++ b/docs/mutool/examples/draw-document.js
@@ -0,0 +1,9 @@
+// Draw all pages in a document and save them as PNG files.
+
+var doc = new Document(argv[1]);
+var n = doc.countPages();
+for (var i = 0; i < n; ++i) {
+ var page = doc.loadPage(i);
+ var pixmap = page.toPixmap(Identity, DeviceRGB);
+ pixmap.saveAsPNG("out" + (i+1) + ".png");
+}
diff --git a/docs/mutool/examples/pdf-create-lowlevel.js b/docs/mutool/examples/pdf-create-lowlevel.js
new file mode 100644
index 00000000..b55e22cf
--- /dev/null
+++ b/docs/mutool/examples/pdf-create-lowlevel.js
@@ -0,0 +1,63 @@
+// Create a PDF from scratch.
+
+// This example creates a new PDF file from scratch, using only the low level APIs.
+// This assumes a basic working knowledge of the PDF file format.
+
+// Create a new empty document with no pages.
+var pdf = new PDFDocument()
+
+// Create and add a font resource.
+var font = pdf.addObject({
+ Type: "Font",
+ Subtype: "Type1",
+ Encoding: "WinAnsiEncoding",
+ BaseFont: "Times-Roman",
+})
+
+// Create and add an image resource:
+// Allocate a slot for a new object and get a reference to it.
+var image = pdf.createObject()
+// Write a dictionary object into the slot.
+image.writeObject({
+ Type: "XObject",
+ Subtype: "Image",
+ Width: 4,
+ Height: 2,
+ BitsPerComponent: 8,
+ ColorSpace: "DeviceGray",
+ // The compression filter to be used:
+ Filter: "ASCIIHexDecode",
+})
+// Write raw stream data into the slot; hex encoded
+// to match the Filter entry in the dictionary.
+image.writeRawStream("004488CCEEBB7733&gt;")
+
+// Create resource dictionary.
+var resources = pdf.addObject({
+ Font: { Tm: font },
+ XObject: { Im0: image },
+})
+
+// Create content stream.
+var buffer = new Buffer()
+buffer.writeLine("10 10 280 330 re s")
+buffer.writeLine("q 200 0 0 200 50 100 cm /Im0 Do Q")
+buffer.writeLine("BT /Tm 16 Tf 50 50 TD (Hello, world!) Tj ET")
+var contents = pdf.addStream(buffer)
+
+// Create page object.
+var page = pdf.addObject({
+ Type: "Page",
+ MediaBox: [0,0,300,350],
+ Contents: contents,
+ Resources: resources,
+})
+
+// Insert page object into page tree.
+var pagetree = pdf.getTrailer().Root.Pages
+pagetree.Count = 1
+pagetree.Kids = [ page ]
+page.Parent = pagetree
+
+// Save the document.
+pdf.save("out.pdf")
diff --git a/docs/mutool/examples/pdf-create.js b/docs/mutool/examples/pdf-create.js
new file mode 100644
index 00000000..38c193a3
--- /dev/null
+++ b/docs/mutool/examples/pdf-create.js
@@ -0,0 +1,35 @@
+// Create a PDF from scratch using helper functions.
+
+// This example creates a new PDF file from scratch, using helper
+// functions to create resources and page objects.
+// This assumes a basic working knowledge of the PDF file format.
+
+// Create a new empty document with no pages.
+var pdf = new PDFDocument()
+
+// Load built-in font and create WinAnsi encoded simple font resource.
+var font = pdf.addSimpleFont(new Font("Times-Roman"))
+
+// Load PNG file and create image resource.
+var image = pdf.addImage(new Image("example.png"))
+
+// Create resource dictionary.
+var resources = pdf.addObject({
+ Font: { Tm: font },
+ XObject: { Im0: image },
+})
+
+// Create content stream data.
+var contents =
+ "10 10 280 330 re s\n" +
+ "q 200 0 0 200 50 100 cm /Im0 Do Q\n" +
+ "BT /Tm 16 Tf 50 50 TD (Hello, world!) Tj ET\n"
+
+// Create a new page object.
+var page = pdf.addPage([0,0,300,350], 0, resources, contents)
+
+// Insert page object at the end of the document.
+pdf.insertPage(-1, page)
+
+// Save the document to file.
+pdf.save("out.pdf")
diff --git a/docs/mutool/examples/pdf-merge.js b/docs/mutool/examples/pdf-merge.js
new file mode 100644
index 00000000..a468738a
--- /dev/null
+++ b/docs/mutool/examples/pdf-merge.js
@@ -0,0 +1,66 @@
+// A re-implementation of "mutool merge" in JavaScript.
+
+function graftObject(dstDoc, srcDoc, srcObj, map) {
+ var srcNum, dstRef, dstObj
+ if (!map)
+ map = []
+ if (srcObj.isIndirect()) {
+ srcNum = srcObj.toIndirect()
+ if (map[srcNum])
+ return map[srcNum]
+ map[srcNum] = dstRef = dstDoc.createObject()
+ dstRef.writeObject(graftObject(dstDoc, srcDoc, srcObj.resolve(), map))
+ if (srcObj.isStream())
+ dstRef.writeRawStream(srcObj.readRawStream())
+ return dstRef
+ }
+ if (srcObj.isArray()) {
+ dstObj = dstDoc.newArray()
+ srcObj.forEach(function (key, val) {
+ dstObj[key] = graftObject(dstDoc, srcDoc, val, map)
+ })
+ return dstObj
+ }
+ if (srcObj.isDictionary()) {
+ dstObj = dstDoc.newDictionary()
+ srcObj.forEach(function (key, val) {
+ dstObj[key] = graftObject(dstDoc, srcDoc, val, map)
+ })
+ return dstObj
+ }
+ return srcObj /* primitive objects are not bound to a document */
+}
+
+function copyPage(dstDoc, srcDoc, pageNumber, map) {
+ var srcPage, dstPage
+ srcPage = srcDoc.findPage(pageNumber)
+ dstPage = dstDoc.newDictionary()
+ if (srcPage.MediaBox) dstPage.MediaBox = graftObject(dstDoc, srcDoc, srcPage.MediaBox, map)
+ if (srcPage.Rotate) dstPage.Rotate = graftObject(dstDoc, srcDoc, srcPage.Rotate, map)
+ if (srcPage.Resources) dstPage.Resources = graftObject(dstDoc, srcDoc, srcPage.Resources, map)
+ if (srcPage.Contents) dstPage.Contents = graftObject(dstDoc, srcDoc, srcPage.Contents, map)
+ dstDoc.insertPage(-1, dstDoc.addObject(dstPage))
+}
+
+function copyAllPages(dstDoc, srcDoc) {
+ var k, n = srcDoc.countPages()
+ var srcMap = []
+ for (k = 0; k < n; ++k)
+ copyPage(dstDoc, srcDoc, k, srcMap)
+}
+
+function pdfmerge() {
+ var srcDoc, dstDoc, i
+
+ dstDoc = new PDFDocument()
+ for (i = 2; i < argv.length; ++i) {
+ srcDoc = new PDFDocument(argv[i])
+ copyAllPages(dstDoc, srcDoc)
+ }
+ dstDoc.save(argv[1])
+}
+
+if (argv.length < 3)
+ print("usage: mutool run pdf-merge.js output.pdf input1.pdf input2.pdf ...")
+else
+ pdfmerge()
diff --git a/docs/mutool/examples/trace-device.js b/docs/mutool/examples/trace-device.js
new file mode 100644
index 00000000..9d7d4373
--- /dev/null
+++ b/docs/mutool/examples/trace-device.js
@@ -0,0 +1,102 @@
+var Q = JSON.stringify
+
+var pathPrinter = {
+ moveTo: function (x,y) { print("moveTo", x, y) },
+ lineTo: function (x,y) { print("lineTo", x, y) },
+ curveTo: function (x1,y1,x2,y2,x3,y3) { print("curveTo", x1, y1, x2, y2, x3 ,y3) },
+ closePath: function () { print("closePath") },
+}
+
+var textPrinter = {
+ showGlyph: function (f,m,g,u,v,b) { print("glyph",f,m,g,u,v,b) },
+}
+
+var traceDevice = {
+ fillPath: function (path, evenOdd, ctm, colorSpace, color, alpha) {
+ print("fillPath", evenOdd, ctm, colorSpace, color, alpha)
+ path.walk(pathPrinter)
+ },
+ clipPath: function (path, evenOdd, ctm) {
+ print("clipPath", evenOdd, ctm)
+ path.walk(pathPrinter)
+ },
+ strokePath: function (path, stroke, ctm, colorSpace, color, alpha) {
+ print("strokePath", Q(stroke), ctm, colorSpace, color, alpha)
+ path.walk(pathPrinter)
+ },
+ clipStrokePath: function (path, stroke, ctm) {
+ print("clipStrokePath", Q(stroke), ctm)
+ path.walk(pathPrinter)
+ },
+
+ fillText: function (text, ctm, colorSpace, color, alpha) {
+ print("fillText", ctm, colorSpace, color, alpha)
+ text.walk(textPrinter)
+ },
+ clipText: function (text, ctm) {
+ print("clipText", ctm)
+ text.walk(textPrinter)
+ },
+ strokeText: function (text, stroke, ctm, colorSpace, color, alpha) {
+ print("strokeText", Q(stroke), ctm, colorSpace, color, alpha)
+ text.walk(textPrinter)
+ },
+ clipStrokeText: function (text, stroke, ctm) {
+ print("clipStrokeText", Q(stroke), ctm)
+ text.walk(textPrinter)
+ },
+ ignoreText: function (text, ctm) {
+ print("ignoreText", ctm)
+ text.walk(textPrinter)
+ },
+
+ fillShade: function (shade, ctm, alpha) {
+ print("fillShade", shade, ctm, alpha)
+ },
+ fillImage: function (image, ctm, alpha) {
+ print("fillImage", image, ctm, alpha)
+ },
+ fillImageMask: function (image, ctm, colorSpace, color, alpha) {
+ print("fillImageMask", image, ctm, colorSpace, color, alpha)
+ },
+ clipImageMask: function (image, ctm) {
+ print("clipImageMask", image, ctm)
+ },
+
+ beginMask: function (area, luminosity, colorspace, color) {
+ print("beginMask", area, luminosity, colorspace, color)
+ },
+ endMask: function () {
+ print("endMask")
+ },
+
+ popClip: function () {
+ print("popClip")
+ },
+
+ beginGroup: function (area, isolated, knockout, blendmode, alpha) {
+ print("beginGroup", area, isolated, knockout, blendmode, alpha)
+ },
+ endGroup: function () {
+ print("endGroup")
+ },
+ beginTile: function (area, view, xstep, ystep, ctm, id) {
+ print("beginTile", area, view, xstep, ystep, ctm, id)
+ return 0
+ },
+ endTile: function () {
+ print("endTile")
+ },
+
+ close: function () {
+ print("close")
+ },
+}
+
+if (argv.length != 3)
+ print("usage: mutool run trace-device.js document.pdf pageNumber")
+else {
+ var doc = new Document(argv[1]);
+ var page = doc.loadPage(parseInt(argv[2])-1);
+ page.run(traceDevice, Identity);
+}
diff --git a/docs/mutool/run.html b/docs/mutool/run.html
new file mode 100644
index 00000000..07f852de
--- /dev/null
+++ b/docs/mutool/run.html
@@ -0,0 +1,635 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>mutool run: reference</title>
+<style>
+body{margin:2em;max-width:50em;line-height:1.4em}
+dl,pre{margin-left:2em;}
+</style>
+</head>
+<body>
+
+<h1>
+MuPDF from JavaScript
+</h1>
+
+<p>
+The 'mutool run' command executes a JavaScript program, which has access to most of the features of the MuPDF library.
+The command supports ECMAScript 5 syntax in strict mode.
+All of the MuPDF constructors and functions live in the global object, and the command line arguments are accessible
+from the global 'argv' object.
+
+<pre>
+mutool run script.js [ arguments ... ]
+</pre>
+
+<p>
+If invoked without any arguments, it will drop you into an interactive REPL (read-eval-print-loop).
+On the interactive prompt, if you prefix a line with an equal ('=') character it will automatically print the result
+of the line.
+
+<h2>
+Example scripts
+</h2>
+
+<p>
+Create and edit PDF documents:
+
+<ul>
+<li><a href="examples/pdf-create-lowlevel.js">pdf-create-lowlevel.js</a>: Create PDF document from scratch using only low level functions.
+<li><a href="examples/pdf-create.js">pdf-create.js</a>: Create PDF document from scratch, using helper functions.
+<li><a href="examples/pdf-merge.js">pdf-merge.js</a>: Merge pages from multiple PDF documents into one PDF file.
+</ul>
+
+<p>
+Graphics and the device interface:
+
+<ul>
+<li><a href="examples/draw-document.js">draw-document.js</a>: Draw all pages in a document to PNG files.
+<li><a href="examples/draw-device.js">draw-device.js</a>: Use device API to draw graphics and save as a PNG file.
+<li><a href="examples/trace-device.js">trace-device.js</a>: Implement a device in JavaScript.
+</ul>
+
+<p>
+Advanced examples:
+
+<ul>
+<li><a href="create-thumbnail.js">create-thumbnail.js</a>: Create a PDF from rendered page thumbnails.
+</ul>
+
+<h2>
+JavaScript Shell
+</h2>
+
+<p>
+Several global functions that are common for command line shells are available:
+
+<dl>
+<dt>gc(report)
+<dd>Run the garbage collector to free up memory. Optionally report statistics on the garbage collection.
+<dt>load(fileName)
+<dd>Load and execute script in 'fileName'.
+<dt>print(...)
+<dd>Print arguments to stdout, separated by spaces and followed by a newline.
+<dt>quit()
+<dd>Exit the shell.
+<dt>read(fileName)
+<dd>Read the contents of a file and return them as a UTF-8 decoded string.
+<dt>readline()
+<dd>Read one line of input from stdin and return it as a string.
+<dt>require(module)
+<dd>Load a JavaScript module.
+<dt>write(...)
+<dd>Print arguments to stdout, separated by spaces.
+</dl>
+
+<h2>
+Buffer
+</h2>
+
+<p>
+The Buffer objects are used for working with binary data.
+They can be used much like arrays, but are much more efficient since they
+only store bytes.
+
+<dl>
+<dt>new Buffer()
+<dd>Create a new empty buffer.
+<dt>readFile(fileName)
+<dd>Create a new buffer with the contents of a file.
+<dt>Buffer#length
+<dd>The number of bytes in the buffer.
+<dt>Buffer#[n]
+<dd>Read/write the byte at index 'n'. Will throw exceptions on out of bounds accesses.
+<dt>Buffer#writeByte(b)
+<dd>Append a single byte to the end of the buffer.
+<dt>Buffer#writeRune(c)
+<dd>Encode a unicode character as UTF-8 and append to the end of the buffer.
+<dt>Buffer#writeLine(...)
+<dd>Append arguments to the end of the buffer, separated by spaces, ending with a newline.
+<dt>Buffer#write(...)
+<dd>Append arguments to the end of the buffer, separated by spaces.
+<dt>Buffer#save(fileName)
+<dd>Write the contents of the buffer to a file.
+</dl>
+
+<h2>
+Matrices and Rectangles
+</h2>
+
+<p>
+Matrices are simply 6-element arrays representing a 3-by-3 transformation matrix as
+
+<pre>
+/ a b 0 \
+| c d 0 |
+\ e f 1 /
+</pre>
+
+<p>
+This matrix is represented in JavaScript as <code>[a,b,c,d,e,f]</code>.
+
+<dl>
+<dt>Identity
+<dd>The identity matrix, short hand for <code>[1,0,0,1,0,0]</code>.
+<dt>Scale(sx, sy)
+<dd>Return a scaling matrix, short hand for <code>[sx,0,0,sy,0,0]</code>.
+<dt>Translate(tx, ty)
+<dd>Return a translation matrix, short hand for <code>[1,0,0,1,tx,ty]</code>.
+<dt>Concat(a, b)
+<dd>Concatenate matrixes a and b. Bear in mind that matrix multiplication is not commutative.
+</dl>
+
+<p>
+Rectangles are 4-element arrays, specifying the minimum and maximum corners (typically
+upper left and lower right, in a coordinate space with the origin at the top left with
+descending y): <code>[ulx,uly,lrx,lry]</code>.
+
+<p>
+If the minimum x coordinate is bigger than the maximum x coordinate, MuPDF treats the rectangle
+as infinite in size.
+
+<h2>
+Document and Page
+</h2>
+
+<p>
+MuPDF can open many document types (PDF, XPS, CBZ, EPUB, FB2 and a handful of image formats).
+
+<dl>
+<dt>new Document(fileName)
+<dd>Open the named document.
+<dt>Document#needsPassword()
+<dd>Returns true if a password is required to open this password protected PDF.
+<dt>Document#authenticatePassword(password)
+<dd>Returns true if the password matches.
+<dt>Document#getMetaData(key)
+<dd>Return various meta data information. The common keys are: "format", "encryption", "info:Author", and "info:Title".
+<dt>Document#toPDF()
+<dd>Returns a PDFDocument (see below) or null if the document is not a PDF.
+<dt>Document#layout(pageWidth, pageHeight, fontSize)
+<dd>Layout a reflowable document (EPUB, FB2, or XHTML) to fit the specified page and font size.
+<dt>Document#countPages()
+<dd>Count the number of pages in the document. This may change if you call the layout function with different parameters.
+<dt>Document#loadPage(number)
+<dd>Returns a Page object for the given page number. Page number zero (0) is the first page in the document.
+</dl>
+
+<dl>
+<dt>Page#bound()
+<dd>Returns a rectangle containing the page dimensions.
+<dt>Page#run(device, transform)
+<dd>Calls device functions for all the contents on the page, using the specified transform matrix.
+The device can be one of the built-in devices or a JavaScript object with methods for the device calls.
+<dt>Page#toPixmap(transform, colorspace)
+<dd>Render the page into a Pixmap, using the transform and colorspace.
+<dt>Page#toDisplayList()
+<dd>Record the contents on the page into a DisplayList.
+<dt>Page#search(needle)
+<dd>Search for 'needle' text on the page, and return an array with rectangles of all matches found.
+</dl>
+
+<h2>
+ColorSpace
+</h2>
+
+<dl>
+<dt>DeviceGray
+<dd>The default grayscale colorspace.
+<dt>DeviceRGB
+<dd>The default RGB colorspace.
+<dt>DeviceBGR
+<dd>The default RGB colorspace, but with components in reverse order.
+<dt>DeviceCMYK
+<dd>The default CMYK colorspace.
+<dt>ColorSpace#getNumberOfComponents()
+<dd>A grayscale colorspace has one component, RGB has 3, CMYK has 4, and DeviceN may have any number of components.
+</dl>
+
+<h2>
+Pixmap
+</h2>
+
+<p>
+A Pixmap object contains a color raster image (short for pixel map).
+The components in a pixel in the pixmap are all byte values, with the transparency as the last component.
+A pixmap also has a location (x, y) in addition to its size; so that they can easily be used to represent
+tiles of a page.
+
+<dl>
+<dt>new Pixmap(colorspace, bounds)
+<dd>Create a new pixmap. The pixel data is <b>not</b> initialized; and will contain garbage.
+<dt>Pixmap#clear(value)
+<dd>Clear the pixels to the specifed value. Pass 255 for white, or undefined for transparent.
+<dt>Pixmap#bound()
+<dd>Return the pixmap bounds.
+<dt>Pixmap#getWidth()
+<dt>Pixmap#getHeight()
+<dt>Pixmap#getNumberOfComponents()
+<dt>Pixmap#getStride()
+<dd>Number of bytes per row.
+<dt>Pixmap#getColorSpace()
+<dt>Pixmap#getXResolution()
+<dt>Pixmap#getYResolution()
+<dd>Image resolution in dots per inch.
+<dt>Pixmap#getSample(x, y, k)
+<dd>Get the value of component k at position x, y (relative to the image origin: 0, 0 is the top left pixel).
+<dt>Pixmap#saveAsPNG(fileName, saveAlpha)
+<dd>Save the pixmap as a PNG. Only works for Gray and RGB images.
+</dl>
+
+<h2>
+DrawDevice
+</h2>
+
+<p>
+The DrawDevice can be used to render to a Pixmap; either by running a Page with it or by calling its methods directly.
+
+<dl>
+<dt>new DrawDevice(pixmap)
+<dd>Create a device for drawing into a pixmap. The pixmap bounds used should match the transformed page bounds,
+or you can adjust them to only draw a part of the page.
+</dl>
+
+<h2>
+DisplayList and DisplayListDevice
+</h2>
+
+<p>
+A display list records all the device calls for playback later.
+If you want to run a page through several devices, or run it multiple times for any other reason,
+recording the page to a display list and replaying the display list may be a performance gain
+since then you can avoid reinterpreting the page each time. Be aware though, that a display list
+will keep all the graphics required in memory, so will increase the amount of memory required.
+
+<dl>
+<dt>new DisplayList()
+<dd>Create an empty display list.
+<dt>DisplayList#run(device, transform)
+<dd>Play back the recorded device calls onto the device.
+<dt>DisplayList#toPixmap(transform, colorspace, solid)
+<dd>Render display list to a pixmap. If solid is true, it will render to a white background, otherwise transparent.
+</dl>
+
+<dl>
+<dt>new DisplayListDevice(displayList)
+<dd>Create a device for recording onto a display list.
+</dl>
+
+<h2>
+Device
+</h2>
+
+<p>
+All built-in devices have the methods listed below. Any function that accepts a device will also
+accept a JavaScript object with the same methods. Any missing methods are simply ignored, so you
+only need to create methods for the device calls you care about.
+
+<p>
+Many of the methods take graphics objects as arguments: Path, Text, Image and Shade.
+
+<p>
+The stroking state is a dictionary with keys for:
+<dl>
+<dt>startCap, dashCap, endCap:
+<dd>"Butt", "Round", "Square", or "Triangle".
+<dt>lineCap:
+<dd>Set startCap, dashCap, and endCap all at once.
+<dt>lineJoin:
+<dd>"Miter", "Round", "Bevel", or "MiterXPS".
+<dt>lineWidth:
+<dd>Thickness of the line.
+<dt>miterLimit:
+<dd>Maximum ratio of the miter length to line width, before beveling the join instead.
+<dt>dashPhase:
+<dd>Starting offset for dash pattern.
+<dt>dashes:
+<dd>Array of on/off dash lengths.
+</dl>
+
+<p>
+Colors are specified as arrays with the appropriate number of components for the color space.
+
+<p>
+The methods that clip graphics must be balanced with a corresponding popClip.
+
+<dl>
+<dt>Device#fillPath(path, evenOdd, transform, colorspace, color, alpha)
+<dt>Device#strokePath(path, stroke, transform)
+<dt>Device#clipPath(path, evenOdd, transform, colorspace, color, alpha)
+<dt>Device#clipStrokePath(path, stroke, transform)
+<dd>Fill/stroke/clip a path.
+</dl>
+
+<dl>
+<dt>Device#fillText(text, transform, colorspace, color, alpha)
+<dt>Device#strokeText(text, stroke, transform, colorspace, color, alpha)
+<dt>Device#clipText(text, transform)
+<dt>Device#clipStrokeText(text, stroke, transform)
+<dd>Fill/stroke/clip a text object.
+<dt>Device#ignoreText(text, transform)
+<dd>Invisible text that can be searched but should not be visible, such as for overlaying a scanned OCR image.
+</dl>
+
+<dl>
+<dt>Device#fillShade(shade, transform, alpha)
+<dd>Fill a shade (a.k.a. gradient). TODO: this details of gradient fills are not exposed to JavaScript yet.
+<dt>Device#fillImage(shade, transform, alpha)
+<dd>Draw an image. An image always fills a unit rectangle [0,0,1,1], so must be transformed to be placed and drawn at the appropriate size.
+<dt>Device#fillImageMask(shade, transform, colorspace, color, alpha)
+<dd>An image mask is an image without color. Fill with the color where the image is opaque.
+<dt>Device#clipImageMask(shade, transform)
+<dd>Clip graphics using the image to mask the areas to be drawn.
+</dl>
+
+<dl>
+<dt>Device#beginMask(area, luminosity, backdropColorspace, backdropColor)
+<dt>Device#endMask()
+<dd>Create a soft mask. Any drawing commands between beginMask and endMask are grouped and used as a clip mask.
+If luminosity is true, the mask is derived from the luminosity (grayscale value) of the graphics drawn;
+otherwise the color is ignored completely and the mask is derived from the alpha of the group.
+</dl>
+
+<dl>
+<dt>Device#popClip()
+<dd>Pop the clip mask installed by the last clipping operation.
+</dl>
+
+<dl>
+<dt>Device#beginGroup(area, isolated, knockout, blendmode, alpha)
+<dt>Device#endGroup()
+<dd>Push/pop a transparency blending group. Blendmode is one of the standard PDF blend modes: "Normal", "Multiply", "Screen", etc. See the PDF reference for details on isolated and knockout.
+</dl>
+
+<dl>
+<dt>Device#beginTile(areaRect, viewRect, xStep, yStep, transform)
+<dt>Device#endTile()
+<dd>Draw a tiling pattern. Any drawing commands between beginTile and endTile are grouped and then repeated across the whole page.
+Apply a clip mask to restrict the pattern to the desired shape.
+</dl>
+
+<h2>
+Path
+</h2>
+
+<p>
+A Path object represents vector graphics as drawn by a pen. A path can be either stroked or filled, or used as a clip mask.
+
+<dl>
+<dt>new Path()
+<dd>Create a new empty path.
+<dt>Path#moveTo(x, y)
+<dd>Lift and move the pen to the coordinate.
+<dt>Path#lineTo(x, y)
+<dd>Draw a line to the coordinate.
+<dt>Path#curveTo(x1, y1, x2, y2, x3, y3)
+<dd>Draw a cubic bezier curve to (x3,y3) using (x1,y1) and (x2,y2) as control points.
+<dt>Path#closePath()
+<dd>Close the path by drawing a line to the last moveTo.
+<dt>Path#rect(x1, y1, x2, y2)
+<dd>Shorthand for moveTo, lineTo, lineTo, lineTo, closePath to draw a rectangle.
+<dt>Path#walk(pathWalker)
+<dd>Call moveTo, lineTo, curveTo and closePath methods on the pathWalker to replay the path.
+</dl>
+
+<h2>
+Text
+</h2>
+
+<p>
+A Text object contains text.
+
+<dl>
+<dt>new Text()
+<dd>Create a new empty text object.
+<dt>Text#showGlyph(font, transform, glyph, unicode, wmode)
+<dd>Add a glyph to the text object. Transform is the text matrix, specifying font size and glyph location. For example: <code>[size,0,0,-size,x,y]</code>.
+Glyph and unicode may be -1 for n-to-m cluster mappings.
+For example, the "fi" ligature would be added in two steps: first the glyph for the 'fi' ligature and the unicode value for 'f';
+then glyph -1 and the unicode value for 'i'.
+WMode is 0 for horizontal writing, and 1 for vertical writing.
+<dt>Text#showString(font, transform, string)
+<dd>Add a simple string to the text object. Will do font substitution if the font does not have all the unicode characters required.
+<dt>Text#walk(textWalker)
+<dd>Call showGlyph on textWalker for each glyph in the text object.
+</dl>
+
+<h2>
+Font
+</h2>
+
+<p>
+Font objects can be created from TrueType, OpenType, Type1 or CFF fonts.
+In PDF there are also special Type3 fonts.
+
+<dl>
+<dt>new Font(fontName or fileName)
+<dd>Create a new font, either using a built-in font name or a filename.
+The built-in fonts are: Times-Roman, Times-Italic, Times-Bold, Times-BoldItalic,
+Helvetica, Helvetica-Oblique, Helvetica-Bold, Helvetica-BoldOblique,
+Courier, Courier-Oblique, Courier-Bold, Courier-BoldOblique,
+Symbol, and ZapfDingbats.
+<dt>Font#getName()
+<dd>Get the font name.
+<dt>Font#encodeCharacter(unicode)
+<dd>Get the glyph index for a unicode character. Glyph zero (.notdef) is returned if the font does not have a glyph for the character.
+<dt>Font#advanceGlyph(glyph, wmode)
+<dd>Return advance width for a glyph in either horizontal or vertical writing mode.
+</dl>
+
+<h2>
+Image
+</h2>
+
+<p>
+Image objects are similar to Pixmaps, but can contain compressed data.
+
+<dl>
+<dt>new Image(pixmap or fileName)
+<dd>Create a new image from a pixmap data, or load an image from a file.
+<dt>Image#getWidth()
+<dt>Image#getHeight()
+<dd>Image size in pixels.
+<dt>Image#getXResolution()
+<dt>Image#getYResolution()
+<dd>Image resolution in dots per inch.
+<dt>Image#getColorSpace()
+<dt>Image#toPixmap(scaledWidth, scaledHeight)
+<dd>Create a pixmap from the image. The scaledWidth and scaledHeight arguments are optional,
+but may be used to decode a down-scaled pixmap.
+</dl>
+
+<h2>
+PDFDocument and PDFObject
+</h2>
+
+<p>
+With MuPDF it is also possible to create, edit and manipulate PDF documents
+using low level access to the objects and streams contained in a PDF file.
+
+<dl>
+<dt>new PDFDocument()
+<dd>Create a new empty PDF document.
+<dt>new PDFDocument(fileName)
+<dd>Load a PDF document from file.
+<dt>Document#toPDF()
+<dd>Get access to the raw PDFDocument from a Document; returns null if the document is not a PDF.
+<dt>PDFDocument#toDocument()
+<dd>Cast the PDF document to a Document.
+<dt>PDFDocument#save(fileName)
+<dd>Write the PDF document to file.
+</dl>
+
+<h3>
+PDF Object Access
+</h3>
+
+<p>
+A PDF document contains objects, similar to those in JavaScript: arrays, dictionaries, strings, booleans, and numbers.
+At the root of the PDF document is the trailer object; which contains pointers to the meta data dictionary and the
+catalog object which contains the pages and other information.
+
+<p>
+Pointers in PDF are also called indirect references,
+and are of the form "32 0 R" (where 32 is the object number, 0 is the generation, and R is magic syntax).
+All functions in MuPDF dereference indirect references automatically.
+
+<p>
+PDF has two types of strings: /Names and (Strings). All dictionary keys are names.
+
+<p>
+Some dictionaries in PDF also have attached binary data. These are called streams, and may be compressed.
+
+<dl>
+<dt>PDFDocument#getTrailer()
+<dd>The trailer dictionary. This contains indirect references to the Root and Info dictionaries.
+<dt>PDFDocument#countObjects()
+<dd>Return the number of objects in the PDF. Object number 0 is reserved, and may not be used for anything.
+<dt>PDFDocument#createObject()
+<dd>Allocate a new numbered object in the PDF, and return an indirect reference to it.
+The object itself is uninitialized.
+</dl>
+
+<p>
+PDFObjects are always bound to the document that created them.
+Do NOT mix and match objects from one document with another document!
+
+<dl>
+<dt>PDFDocument#addObject(obj)
+<dd>Add 'obj' to the PDF as a numbered object, and return an indirect reference to it.
+<dt>PDFDocument#addStream(buffer)
+<dd>Create a stream object with the contents of 'buffer', add it to the PDF, and return an indirect reference to it.
+<dt>PDFDocument#newNull()
+<dt>PDFDocument#newBoolean(boolean)
+<dt>PDFDocument#newInteger(number)
+<dt>PDFDocument#newReal(number)
+<dt>PDFDocument#newString(string)
+<dt>PDFDocument#newName(string)
+<dt>PDFDocument#newIndirect(objectNumber, generation)
+<dt>PDFDocument#newArray()
+<dt>PDFDocument#newDictionary()
+</dl>
+
+<p>
+All functions that take PDF objects, do automatic translation between JavaScript objects
+and PDF objects using a few basic rules. Null, booleans, and numbers are translated directly.
+JavaScript strings are translated to PDF names, unless they are surrounded by parentheses:
+"Foo" becomes the PDF name /Foo and "(Foo)" becomes the PDF string (Foo).
+
+<p>
+Arrays and dictionaries are recursively translated to PDF arrays and dictionaries.
+Be aware of cycles though! The translation does NOT cope with cyclic references!
+
+<p>
+The translation goes both ways: PDF dictionaries and arrays can be accessed similarly
+to JavaScript objects and arrays by getting and setting their properties.
+
+<dl>
+<dt>PDFObject#get(key or index)
+<dt>PDFObject#put(key or index, value)
+<dt>PDFObject#delete(key or index)
+<dd>Access dictionaries and arrays. Dictionaries and arrays can also be accessed using normal property syntax: obj.Foo = 42; delete obj.Foo; x = obj[5].
+<dt>PDFObject#resolve()
+<dd>If the object is an indirect reference, return the object it points to; otherwise return the object itself.
+<dt>PDFObject#isArray()
+<dt>PDFObject#isDictionary()
+<dt>PDFObject#forEach(function(key,value){...})
+<dd>Iterate over all the entries in a dictionary or array and call fun for each key-value pair.
+</dl>
+
+<p>
+The only way to access a stream is via an indirect object, since all streams
+are numbered objects.
+
+<dl>
+<dt>PDFObject#isIndirect()
+<dd>Is the object an indirect reference.
+<dt>PDFObject#toIndirect()
+<dd>Return the object number the indirect reference points to.
+<dt>PDFObject#isStream()
+<dd>True if the object is an indirect reference pointing to a stream.
+<dt>PDFObject#readStream()
+<dd>Read the contents of the stream object into a Buffer.
+<dt>PDFObject#readRawStream()
+<dd>Read the raw, uncompressed, contents of the stream object into a Buffer.
+<dt>PDFObject#writeObject(obj)
+<dd>Update the object the indirect reference points to.
+<dt>PDFObject#writeStream(buffer)
+<dd>Update the contents of the stream the indirect reference points to.
+This will update the Length, Filter and DecodeParms automatically.
+<dt>PDFObject#writeRawStream(buffer)
+<dd>Update the raw, uncompressed, contents of the stream the indirect reference points to.
+This will update the Length automatically, but leave the Filter and DecodeParms untouched.
+</dl>
+
+<h3>
+PDF Page Access
+</h3>
+
+<p>
+All page objects are structured into a page tree, which defines the order the pages appear in.
+
+<dl>
+<dt>PDFDocument#countPages()
+<dd>Number of pages in the document.
+<dt>PDFDocument#findPage(number)
+<dd>Return the page object for a page number. The first page is number zero.
+<dt>PDFDocument#deletePage(number)
+<dd>Delete the numbered page.
+<dt>PDFDocument#insertPage(at, page)
+<dd>Insert the page object in the page tree at the location. If 'at' is -1, at the end of the document.
+</dl>
+
+<p>
+Pages consist of a content stream, and a resource dictionary containing all of the fonts and images used.
+
+<dl>
+<dt>PDFDocument#addPage(mediabox, rotate, resources, contents)
+<dd>Create a new page object. Note: this function does NOT add it to the page tree.
+<dt>PDFDocument#addSimpleFont(font)
+<dd>Create a PDF object from the Font object as a WinAnsiEncoding encoded simple font.
+<dt>PDFDocument#addFont(font)
+<dd>Create a PDF object from the Font object as an Identity-H encoded CID font.
+<dt>PDFDocument#addImage(image)
+<dd>Create a PDF object from the Image object.
+</dl>
+
+<h2>
+TODO
+</h2>
+
+<p>
+There are several areas in MuPDF that still need bindings to access from JavaScript:
+
+<ul>
+<li>Shadings
+<li>PDFDocument#graftObject()
+<li>PDFDocument#save() -- write options
+<li>PDFWriteDevice
+<li>DocumentWriter
+</ul>
+
+<p>
+Copyright &copy; 2016 Artifex Software
+
+</body>