pydvi2svg & SVGfrags

Last update: 13.03.2007

Contents

News

13.03.2007

  • Beta version of SVGfrags!
  • pl: Na razie usuwam polską dokumentację, bo się trochę zdezaktualizowała, a naprawdę są ciekawsze rzeczy od jej pisania.

7.03.2007

  • Better, and I hope more obvious, command line parsing. Now output file name or output directory can be set. For example:

    dvi2svg.py file.dvi                   # output: file.svg
    dvi2svg.py file.dvi test.svg          # output: test.svg
    dvi2svg.py file.dvi dir/              # output: dir/file.svg
    dvi2svg.py file.dvi dir/test.svg      # output: dir/test.svg
    
  • New option --always-number — affects on output file name: append page number to output name even if one page is converted.

  • Option --paper-size=bbox accepts four numbers, for left, right, top and bottom margin, i.e. --paper-size=bbox:left,right,top,bottom

6.03.2007

  • Switch --paper-size accept new keyword bbox (see description of this option for details) — paper size is set to bounding box of page.

    Sample: famous Einstein equation

  • new option --verbose

4.03.2007

  • added support for mftrace utility — automatically conversion of METAFONT fonts is available

3.03.2007

  • generate a bit smaller SVG files
  • new options --no-fontforge and --no-fnt2meta that disables use of FontForge/fnt2meta
  • option --paper-size accepts value "query" — all known names & sizes are printed

2.03.2007

  • Improved .PFA/.PFB searching
  • Another bug fixed

1.03.2007

Some bugs were fixed, thanks for help to R (Chandra) Chandrasekhar.

16.10.2006

If pydvi2svg can't find SVG but Type1 fonts (PFA or PFB) are available in your TeX installation then automatically use FontForge (or fnt2meta) to converts such font.

fnt2meta.c is a small utility that reads font file and prints glyph outlines (need FreeType2). Compilation:

gcc -O2 -lfreetype fnt2meta.c -o fnt2meta

or:

gcc -O2 `freetype-config --libs` `freetype-config --cflags` -o fnt2meta fnt2meta.c

15.10.2006

New methods to determine encoding (see --enc-methods switch)

pydvi2svg

Introduction

This is another DVI to SVG converter (and is written in Python).

When I was started to write this program I just want to export mathematical expressions. But since DVI is just a set of commands that puts characters and move magic current point around a page, pydvi2svg is able to convert any kind of document.

There is partial support for color.sty specials.

Why another converter? Because programs I've checked — if they worked of course — embeded SVG font in the file. This is not supported by most SVG viewer/editor programs, including Inkscape that I use often. Because of that pydvi2svg embeds glifs as a paths and simply links to them. It works perfectly. Tested with gqview, rsvg, Inkscape, Firefox 1.5-2.0 and Opera 9.

Samples

  1. Article borrowed from English Wikipedia about DVI file format. Font face used: Computer Modern.

  1. Article borrowed from polish Wikipedia about Antykwa Półtawskiego — the original polish font face. Of course if you open SVG you will see this font "in action".

Wikipedia articles are licensed under GNU GFDL license.

Prerequisites

  • Python interpreter, version 2.4
  • If you need additional SVG fonts, you will need TeX installation (all its' utilities, fonts, etc.) and:
    • fnt2meta — pydvi2svg utility to convert Type1 fonts; if you don't need METAFONT, just Type1 fonts this utility should be enough
    • free, multiplatform font editor Fontforge that is able to save SVG fonts (pydvi2svg uses Fontforge to convert Type1 fonts)
    • mftrace and autotrace or potrace — to convert METAFONT fonts to SVG

Installation

Following archives are needed:

  1. pydvi2svg.tar.bz2 — source files of pydvi2svg & SVGfrags
  2. fonts.tar.bz2Computer Modern fonts converted to SVG

If you have them, then:

$ tar -xjf pydvi2svg.tar.bz2
$ tar -xjf fonts.tar.bz2

After correct installation directory tree should looks as follow:

pydvi2svg
 |
 +- cache           - empty dir
 +- conv            - dvi2svg program files
 +- frags           - SVGfrags program files
 +- enc             - set of *.enc files
 +- fonts
     |
     +- cm          - set of *.svg files

Now you can create symbolic link to pydvi2svg.py (and/or svgfrags.py) in some directory listed from $PATH, for example:

sudo ln -sf <full path to script>/dvi2svg.py /usr/local/bin/

If realpath utility is present in your system, then:

sudo ln -sf `realpath pydvi2svg/dvi2svg.py` /usr/local/bin

Program options

dvi2svg.py [OPTION] file.dvi [target SVG/dir]

For example:

dvi2svg.py file.dvi                   # output: file.svg
dvi2svg.py file.dvi test.svg          # output: test.svg
dvi2svg.py file.dvi dir/              # output: dir/file.svg
dvi2svg.py file.dvi dir/test.svg      # output: dir/test.svg

You can set as many input-output pairs as you want, for example:

dvi2svg.py file1.dvi file2.dvi output2.svg file3.dvi outputdir

Options:

--pages [list]

List of document pages or page ranges to convert. List's element are separated by colons. Examples:

--pages 1,2,3,4,7       # convert pages 1, 2, 3, 4 and 7
--pages 1-4,7           # above shorter
--pages 7-              # convert all pages starting from 7th
--pages -10             # convert pages 1-10

By default all pages are converted.

--enc-method [list]

Choose methods used to determine font encoding:

  • cache (or c) — encoding is readed from file enc/font.info (or is set with option --enc)
  • TFM (or t) — encoding is readed from TFM associated with font
  • AFM (or a) — encoding is readed from AFM associated with font
  • MAP (or m) — scans all .map files and try to find encoding used by other programs (like dvipis); it is quite slow, but could bring good results if Type1 fonts are used
  • guess (or g) — scans all known encodings (stored in files enc/*) and hit best one, i.e. encoding that covers all or almost all characters defined in font; it could find more then one encoding — in this case propositions are printed and programs do not perform any action; you have to try proposed encodings by passing them with --enc switch

Default value: cache,tfm,afm

--enc [list]

Override (or set) encoding of selected fonts. Elements are separated with colons, and has format font name:encoding name. For example:

--enc cmr12:ot1,pltt12:pltt
--scale [non-negative number]

Change default scale of document

Default value: 1.0

--paper-size [value]

value:

  • page format name, like A4, B3, etc. (see Wikipedia); for example --paper-size A4, --paper-size=B5

  • string query — all known names are printed and program exits

  • string bbox — paper size is set to bounding box of page; additionaly margin around bbox can be set:

    • bbox:margin — all margin equal
    • bbox:marginx,marginy — margin left & right equal marginx, margin top & bottom equal marginy
    • bbox:margin_left,margin_right,margin_top,margin_bottom

    for example --paper-size=bbox:10, --paper-size bbox:5,20, --paper-size=bbox:10,20,30,40

Default value: A4

--always-number
Append page number to output name even if one page is converted.
--single-file
All pages are saved in single file. (By default pages are saved in separate files).
--no-fontforge
Never use Fontforge (even if it is present)
--no-fnt2meta
Never use fnt2meta (even if it is present)
--verbose
Print all messages.
--pretty-xml
"Pretty formatting" of SVG (files become larger, but are easy to read).

Solving common problems

Where can I find other fonts saved in SVG format

The easiest way is to convert your own fonts with Fontforge assistance. SVG font have to be placed in fonts directory or its subdirectory.

Fontforge is able to read most vector font formats---in a TeX installation we usually find Type1 fonts (PFB or PFA). If there is just Metafont source, you still can convert font: Fontforge use autotrace or potrace to trace glyph's vector outlines.

Before you create font (Generate font...) assure that glyph's names are not changed (option No Rename set).

If you use other utility, make sure that output SVG fits following rules:

  • <glyph> element has attributes name and d (path)
  • if element hasn't got d attribute there must be just one child element <path> contains it

SVG have to get following structure:

<font>
        <glyph name="..." d="..."/>
        <glyph name="..." d="..."/>
        ...
</font>

or

<font>
        <glyph name="...">
                <path d="..."/>
        </glyph>
        <glyph name="...">
                <path d="..."/>
        </glyph>
        ...
</font>

(Of course these rules are not fixed and I'm able to change them, but have never met SVG fonts with different structure).

I got warning missing char

Usually it means that encoding of certain font is not correct. Try to change it with command line option --enc: look in enc subdirectory or locate other .enc files in your TeX installation.

If you find correct encoding you can change pydvi2svg settings permanently. You have to update file enc/file.info; single line has format:

font_name        encoding_name        designsize

Here is a sample:

pltt12           pltt                 12.000000

pydvi2svg tries to find TFM files and read encoding name (it tries AFM files too, but it is not well tested). But if SVG font has been converted from, for example, Type1 format its' encoding may be different.

For example TFM file that describe font pltt12 claims that encoding is "TeX typewriter text", i.e. texnansi. But since this font was converted from PFB we have to a look into some .map file, and than will notice that TeX applies encoding file called pltt.enc (so, we must set encoding pltt).

Likewise CM fonts may have encoding OT1 instead of T1.

I got error Unknown TeX/AFM encoding

You have to check which *.enc describe reported encoding. Files are placed in directory enc and somewhere in your TeX installation tree. If you find adequate encoding, then update file enc/enc.info (and of course drop me a line).

SVGfrags

SVGfrags is utility build on top of pydvi2svg, that includes pieces of TeX/LaTeX expressions into existing SVG file. It works similar to well known psfrags LaTeX package, but has some additional features.

SVGfrags is distributed with pydvi2svg, see Installation section.

Replacement rules have to be defined in separate file, and must follow this simple syntax:

SVG target => TeX expression [additional options]
% the same comments style as in (La)TeX

You can see detailed syntax, or better read next sections and take a look at example.

Brief overview

SVG target could be (case A):

  • Quoted text phrase, for example "some text" — all occurrences of some text are replaced by adequate TeX expression.
  • XML id attribute — <text> node that has such id is replaced with adequate TeX expression.
  • point(x, y) — put TeX expression at arbitrary position.

Additionally SVG target could refer to rectangular area, where TeX expression is placed (case B):

  • XML id attribute refers to element <rect>, <circle> or <ellipse> (bounding box of these objects are considered).
  • rect(x, y, width, height) — arbitrary defined rectangle.

TeX expression could be:

  • Quoted string, like "$\sin x + \cos x = 1$"
  • Word this (unquoted!) — if SVG target is text or id refers to <text> node, then TeX expression gets value of SVG target. In other words TeX expression are read from SVG document.

Additional options

position

Place TeX expression relative to SVG target object.

Syntax:

position ::= px ["," py]

By default py = 1.0 and px = 0.0 (case B) or px = inherit (case A).

Arguments px and py define point inside rectangle (bounding box of TeX expression, and also in target rectangle in case B). For example px = 0.5, py = 0.5 is center point; px = 0.0, py = 1.0 — left lower corner, and so on.

px and py can be:

  • number
  • percent, i.e. number followed by char '%'

Some useful constants are also defined:

  • pxcenter = 0.5, left = 0.0, right = 1.0
  • pycenter = 0.5, top = 0.0, bottom = 1.0
case ASVG target points to reference point in document canvas

Point inside bbox of TeX expression is calculated and then expression is moved to make this point and reference equal.

In this case px can have value inherit (default), then px gets value (if possible) from SVG attribute text-anchor or from CSS style string. These values are start = 0.0, middle = 0.5 and end = 1.0 (see SVG spec for more info about text-anchor).

case BSVG target points to rectangular area

Points inside bbox of TeX expression and target rectangle are calculated and then expression is moved to make these points equal.

For example if px = 0.5, py = 0.5 then TeX expression is centered.

margins

Additional margins around bounding box of TeX expression; applied before scaling. Syntax:

  • margin: m — left, right, top and bottom margin are equal m
  • margin: mx, my — left and right are equal mx, top and bottom margin are equal my
  • margin: ml, mr, mt, mb — all margins can have different values

scale

Uniform or nonuniform scale of TeX expression.

Syntax:

scale: "fit" | (sx ["," sy])

Value fit is suitable only in case B — TeX expression is uniformly scaled to fill a target rectangle.

Scale factor sx/sy values:

  • Number;
  • Percent;
  • Word uniform — if just one scale direction is set and uniform scaling is needed, then another direction have get this value; if both sx and sy has value uniform then no scale is applied;
  • Word length followed by number — set width/height of TeX expression to exact value;
  • width(#id)/height(#id) — set width/height of TeX expression to width or height of object with given id;
  • width(this)/height(this) — set width/height of TeX expression to width or height of SVG target rectangle; valid only in case B.

Command line options

-i, --input
SVG input file
-o, --output
SVG input file
-r, --rules
name of text file that contains replacement pairs
--no-strip
By default leading & trailing spaces in strings (target string & SVG text) are stripped — this options disabled it
--keep-tex
Do not remove temporary TeX files (useful for debugging)
--keep-dvi
Do not remove temporary DVI files; if rules file are not changed, then DVI can be resued
--no-hide-text-obj
By default replaced text nodes are hide, i.e. property display gets value none — this option disables it.
--remove-text-obj
Remove replaced text nodes.
-f, --force-overwrite
By default SVGfrags do not overwrite existing files — this option turns off protection.
--traceback
In case of error whole Python traceback is printed; it is useful just for debugging.

SVGfrags accepts also following pydvi2svg options:

  • --enc
  • --enc-repl
  • --no-fontforge
  • --no-fnt2meta

Example

Substitution list:
"TeX & LaTeX" => "\TeX\ \& \LaTeX"
        scale: 4

"$\sin x + \cos x = 1$" => this
        scale: 3

"equation2" => "$f(x) = \frac{x^3 - 5}{x^2 + 4} \cdot \frac{1}{x}$"
        scale: 3

"left" => this
        scale: uniform, length 20

"center" => this
        scale: uniform, length 20

"right" => this
        scale: uniform, length 20

"top" => "top"
        position: left, top
        scale: uniform, length 20

"center2" => "center"
        position: left, center
        scale: uniform, length 20

"bottom" => "bottom"
        position: left, bottom
        scale: uniform, length 20

#title => "\LaTeX/\TeX\ \& \texttt{SVGfrags}"
        position: center, center
        margin: 1
        scale: fit

#scaletowidth => "\[P(t) = \sum_{i=0}^n p_i B_i^n (t)\]"
        scale: width(this)

#scaletoheight => "\[\frac{1}{\frac{1}{\frac{1}{x}}}\]"
        position: 0.7
        scale: uniform, height(this)

#nonuniform => "\[\frac{1}{x^2 + 1} + \frac{\sin x}{\log_2 x}\]"
        scale: width(this), height(this)

#settowidth => "$\sin x$"
        scale: width(#scaletowidth), height(#nonuniform)

% eof

Sample source image I've drawn in Inkscape
samples/svgfrags-sample.png
Result
samples/svgfrags-sample-res.png
Result (marked bounding boxes and reference points of TeX expressions
samples/svgfrags-sample-debug.png

License

Remarks, errors, patches

Please send to author any remarks, bugs, patches, questions, etc.:

Wojciech Muła, wojciech_mula@poczta.onet.pl