dvi-decode
for LuaTeX
A Javascript module that enables rendering of dvi
files directly to the web-browser.
dvi-decode
reads a device-independent (dvi
) file and outputs a JSON object containing the glyph ID's used from each font in the document, along with position and size information for each glyph placement on each page of the document. Thus, any LaTeX
file can be rendered to a web-browser by drawing the document glyphs to a canvas using a font rendering module such as OpenType.js
.
dvi-decode
can run either in browser or with node.js, providing all necessary input files are made available (see Configuration below).
Try my DVI Viewer app to see dvi-decode
in action: https://matjp.github.io/dvi-viewer/
dvi
file
Generating the dvi-decode
works only with dvi
files generated by LuaTeX
, and with luaotfload
package version >= 3.15.
Use the dvilualatex
command to create the dvi
file for your LaTeX source.
Use the unicode-math
package if math mode is used.
The output data structure
dvi-decode
returns the Promise
of a JSON object conforming to the schema file dvi-doc.json
.
Configuration
dvi-decode
needs access to the OpenType/TrueType font files specified in the LaTeX
source.
The file font.map
lists the OpenType/TrueType font names together with their paths. The full path of this file should be passed as an argument to dvi-decode
.
dvi-decode
Running Install the dvi-decode
package:
npm i @matjp/dvi-decode
Import the dviDecode
function:
import { dviDecode } from '@matjp/dvi-decode';
Call dviDecode
and handle the returned document Promise
e.g
dviDecode(dviData, 96, 1000, fontMap, true).then(doc => {
console.log(JSON.stringify(JSON.parse(doc), undefined, 2));
});
dviDecode
Arguments to the function function dviDecode(
dviData: Uint8Array,
displayDPI: number,
magnification: number,
fontMap: Map<string,string>,
debugMode?: boolean,
logFunc?: (msg: string) => void): Promise<string>
dviData
: The binary data contained in the dvi
file to be processed, as a Uint8Array
.
displayDPI
: Pixels per inch of the target display device.
magnification
: Percentage magnification required multiplied by 10. e.g. 100% = 1000.
fontMap
: A Map
of font file names to paths for all fonts required.
debugMode
: Optionally print debug information. Default false
.
logFunc
: An optional log function to print messages with. Defaults to console.log
.
Including images
LaTeX image specials
are passed through by dvilualatex
.
dvi-decode
will extract these image references and calculate their pixel coordinates.
To render the images in the browser convert the source EPS files to SVG files and draw these files to the canvas in place of the EPS files.
Example code
See the file test/test.js
for an example of setting up the arguments and calling dviDecode
.
The returned document object can be rendered to the browser using the CanvasRenderingContext2D
interface.
The example code below from the DVI Viewer
app will render a single page from document doc
to the rendering context ctx
using the OpenType.js
library:
props.doc.pages[pageIndex].rules.forEach(
rule => ctx.fillRect(props.marginPixels + rule.x, props.marginPixels + rule.y, rule.w, rule.h)
);
props.doc.pages[pageIndex].pageFonts.forEach(
async pageFont => {
const docFont = props.doc.fonts.find(f => f.fontNum === pageFont.fontNum);
if (docFont) {
const otfFont = await opentype.load(docFont.fontPath + docFont.fontName);
if (otfFont) {
pageFont.glyphs.forEach(glyph => {
let otfGlyph = otfFont.glyphs.get(glyph.glyphIndex);
if (otfGlyph)
glyph.glyphSizes.forEach(glyphSize =>
glyphSize.glyphPlacements.forEach(glyphPlacement =>
otfGlyph.draw(ctx, props.marginPixels + glyphPlacement.x, props.marginPixels + glyphPlacement.y, glyphSize.sz, { features: {hinting: true} })
)
);
});
}
}
});
props.doc.pages[pageIndex].images.forEach(
async image => {
let img = new Image();
img.src = image.fileName.replace('.eps','.svg');
try {
await img.decode();
ctx.drawImage(img, props.marginPixels + image.x, props.marginPixels + image.y, image.w, image.h);
} catch(err) {
console.log(err);
}
}
);
DVI Viewer App
For a full example of decoding and rendering a dvi
file see the source to my React
app DVI Viewer.
dvi-decode
source code
A note about the dvi-decode
is a JWEB
literate program derived from Donald Knuth's DVIType
WEB
program. If you have an interest in understading how dvi-decode
works, it is recommended that you read the JWEB
source file dvi-decode.md
rather than the generated Javascript
source file.