Friday, 31 October 2008

SVG font rasterising with Batik and Inkscape

Recently, I stumbled upon a problem when trying to rasterise an SVG document. The following simple SVG document shall be used to illustrate the point:

<svg xmlns="http://www.w3.org/2000/svg" version="1.0"
     width="35" height="14">
  <g>
    <text x="3" y="10"
          style="font-size: 8px;
                 font-family: PF Ronda Seven"
          text-rendering="optimizeLegibility">
      <tspan>illegible</tspan>
    </text>
  </g>
</svg>

The document contains text set in a very small size. When rasterised, the font should still look crisp and legible, without any anti-aliasing. I therefore chose an 8 pixel bitmap font (which was made for exactly such purposes) and provided the attribute text-rendering="optimizeLegibility" to give potential rasteriser applications a hint as to how to deal with fonts.

Let's compare the output of two open source rasterisers: Batik (version 1.7, bitmap on the left) and Inkscape (version 0.46, bitmap on the right), at original scale and scaled up to 800%:

Batik 1.7 Inkscape 0.46

Batik 1.7 Inkscape 0.46

Batik behaves as expected and makes proper use of the bitmap font, which consists only of white and black pixels. Inkscape however applies anti-aliasing even though we explicitly asked not to do so by specifying the appropriate text-rendering attribute. This is a known problem and will hopefully be addressed in a future release.

Now imagine the above SVG is created programmatically (e.g. an XSL transformation) and the x/y coordinates of the text element turn out to be floating point numbers rather than integers. For instance, let's change the the x coordinate to 3.3:

...
    <text x="3.3" y="10"
...

Batik 1.7 Inkscape 0.46

Batik 1.7 Inkscape 0.46

No problem for Batik, the output stays the same. Inkscape sticks to its anti-aliasing and produces blurry output that is practically illegible.

Now let's complicate the situation even more. Imagine the coordinates are floating point numbers with a decimal part of exactly 0.5:

...
    <text x="3.5" y="10"
...

Batik 1.7 Inkscape 0.46

Batik 1.7 Inkscape 0.46

Now even Batik, which previously produced perfect results, has problems. It seems like every character of the string is positioned independently. Because of alleged rounding problems (there are probably ties), the characters are not glued next to each other with the same amount of space in between. The result looks awkward and is practically illegible, not to speak of the output of Inkscape which is basically a gray smear.

It took me a while to figure out how to remedy the situation. The simple workaround I found consists in making sure that the coordinates never have a decimal part of exactly 0.5. This can be achieved e.g. by putting the text element into a group element which is translated by a tiny little bit (here by 0.01 in the x direction):

...
  <g transform="translate(0.01, 0)">
    <text x="3.5" y="10"
          style="font-size: 8px;
                 font-family: PF Ronda Seven"
          text-rendering="optimizeLegibility">
      <tspan>illegible</tspan>
    </text>
  </g>
...

Batik 1.7 Inkscape 0.46

Batik 1.7 Inkscape 0.46

Batik produces perfect output, supposedly because there are no ties when it comes to rounding to the next integer anymore. Inkscape again applies anti-aliasing.

Punkt CH, Punkt

Im Gegensatz zu den Herausgebern von "Regio Aktuell", welche es nach unzähligen Anfragen geschafft hatten, mich von der Verteilerliste zu streichen (oder ist es der Aufkleber, der die Verträger abschreckt?), bewiesen die Heinis der Gratiszeitung ".ch" Borniertheit bis zum Abwinken. Nachem ich den albernen metallenen Schuhständer vor unserem Hauseingang hatte verbannen lassen, weil beim geringsten Luftzug die Zeitungen davonflogen und als Pappmaché auf dem Boden endeten, wurden ungefragt die Briefkästen zugemüllt. Vielerorts sah man deswegen mit Anti-".ch"-Aufklebern verzierte Briefkästen. Doch auch dadurch liessen sich die Verträger nicht abhalten, das Papier wurde einfach auf der Türschwelle deponiert.

Anfang Oktober dann die frohe Botschaft: Die Hauszustellungen von ".ch" werden eingestellt, die Gratiszeitung wurde neu lanciert und erhielt ein neues Konzept. Besser geworden ist das Blatt deswegen nicht, der Heizwert ist gleich geblieben. Und die Redaktion sollte sich schämen, aus einer Fliege eine Biene zu machen.

Soviel für heute aus der Abteilung Bünzli.