Skip to content

The svg font problem and its solution

Frank Ralf edited this page Jan 28, 2016 · 3 revisions

It is not widely known that if you have an SVG that contains text, the SVG will render differently in different SVG viewers/canvases/browsers. This is due to the facts that

  1. you can't send a copy of the font with the SVG; and
  2. you can't rely on other renderers to have available exactly the same font when the SVG is to be rendered.
This usually leads to slight positioning problems with text fragments that are mostly ignored. Text position is crucial in structural formulas, though, and makes the difference between a good looker and a nice try, so this has to be solved to satisfaction.

An attempt at a solution can be made by using so called SVG fonts1, an SVG feature through which you should be able to send a copy of font with the SVG, effectively attacking point 1 of the problem. Copying a font should have no repercussions. Hmm. Should? Am I 100 per cent positive that, e.g., the Arial Bold from my Linux machine can be embedded in an SVG without any further legal ado? In Wikipedia we can read2 the core fonts are from Microsoft and they still have a handle when you try to distribute the fonts other than with their original exe! What's more, it wouldn't solve the problem because the oh-so net-friendly Mozilla browser doesn't support SVG fonts and simply substitutes one font of his own liking3.

It is possible to work around both restrictions by

  1. using free/open source fonts; and
  2. instead of giving text, providing the glyph outlines as paths in the SVG (equivalent in Inkscape to select text and perform "Object to Path").
Although this prevents the text from being searchable this is no loss with structural formulas. If you embed larger texts in the SVG those ones suffer less from the positioning problem discussed here and, thus, should be implemented as normal text. As a bonus, we no longer need a font size in point but can deal with geometric objects in a unified way with a general metric.

So, how is this implemented in JCP? First, we make sure we use a font that doesn't force us to blow up our (usually small) SVGs with legalese. This condition is fit by the GNU freefont-ttf package. Wait, you say, wouldn't we need to enclose a copy of the GPL? Relax, the package's README explicitly states: As a special exception, if you create a document which uses this font, and embed this font or unaltered portions of this font into the document, this font does not by itself cause the resulting document to be covered by the GNU General Public License. Wow. A big thanks to some thinking lawyer, and, of course, to URW who made the fonts available in the first place!

The implementation includes a script to generate the needed values (bbox, advance, outline) for each character glyph as ready Java source. This is necessary only once, or to extend the character range covered. At the SVG side, the USE directive is employed to make the paths reusable. This makes two passes necessary, the first to write the USE directives, the second for the texts themselves, and the third for the bonds which should stop at the (slightly enlarged) bbox.