diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | docs/mutool/examples/create-thumbnail.js | 19 | ||||
-rw-r--r-- | docs/mutool/examples/draw-device.js | 45 | ||||
-rw-r--r-- | docs/mutool/examples/draw-document.js | 9 | ||||
-rw-r--r-- | docs/mutool/examples/pdf-create-lowlevel.js | 63 | ||||
-rw-r--r-- | docs/mutool/examples/pdf-create.js | 35 | ||||
-rw-r--r-- | docs/mutool/examples/pdf-merge.js | 66 | ||||
-rw-r--r-- | docs/mutool/examples/trace-device.js | 102 | ||||
-rw-r--r-- | docs/mutool/run.html | 635 |
9 files changed, 975 insertions, 1 deletions
@@ -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>") + +// 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 © 2016 Artifex Software + +</body> |