@matjp/dvi-decode

0.4.7 • Public • Published

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/

Generating the dvi file

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.

Running dvi-decode

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));
});

Arguments to the function dviDecode

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.

A note about the dvi-decode source code

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.

Package Sidebar

Install

npm i @matjp/dvi-decode

Weekly Downloads

3

Version

0.4.7

License

GPL-3.0-or-later

Unpacked Size

261 kB

Total Files

17

Last publish

Collaborators

  • matjp