When a presentation is exported from LibreOffice Impress as SVG, it embeds all of the fonts that are used in the document. This is done conservatively: the embedded fonts only include the glyphs that are actually used in the presentation. This is a great feature, but it introduces some complications we need to deal with.

When I started importing multiple SVG presentations into a single HTML presentation, each SVG would come with its own set of glyphs. This worked, but meant that each time I imported a new file I was adding a mostly-redundant embedded font to the document. Particularly after I added the ability to re-import exported presentations to make changes, this led to documents accumulating a lot of unnecessary bloat.

Fortunately this was not very hard to deal with, since SVG fonts are just normal DOM objects that can be manipulated like any other. After spending some time with the SVG fonts specification to figure out what distinguished a particular font definition, I wrote some functions to handle this. Each time a file is imported its font definitions are loaded into memory and removed from the SVG element. Redundant glyphs are ignored. Once the files have all been loaded we generate new embedded fonts, with no redundant data.

SVG fonts are not as powerful as “real” font formats. There’s no hinting available, and the kerning options aren’t as flexible. (In most cases the kerning isn’t an issue for us because LibreOffice manually positions the characters, but that’s not a general solution.) Therefore if a font is installed on the system, we would prefer to use that local copy instead of the embedded copy.

Previously, I had been rewriting every font reference in the document to refer to both the embedded and native fonts, using different font-family names, with the native fonts having a higher priority. While I was reading font specifications to work on deduplication, a more elegant solution ocurred to me.

Instead of inserting the embedded font directly into the document, it’s encoded as a base64 data: URL and embedded in a CSS @font-face declaration. These declarations let us specify a list of font sources, all grouped under a single font-family. For example, if we use Consolas in a presentation our declaration will first reference local(“Consolas”), the installed system font, before falling back to url(“data:[…]”) format(“svg”), our embedded font.

This is a nice solution all around. It has no unnecessary bloat, and elements in our document just need just to reference their desired font-family in the normal manner, without needing to worry about fallbacks.

Advertisements