Getting good vector shapes out of Flash embeds

mxmlc's use of transcoders is more complicated than you might think

A recent project I’ve been working on utilizes a couple faces from M+, a beautiful FOSS font set. There are several ways to embed fonts in Flash, and I prefer using the [Embed] meta-tag, which plays nice with the majority of the IDEs out there. However, a straight-up font embed tag wasn’t working well at all for me. The text that appeared onscreen was broken and misshapen in places.

It turns out that mxmlc, the Flash compiler, employs several “font managers” for taking embedded font files and “transcoding” them into Flash fonts. The primary manager relies on a Java library called Batik to convert the letterforms of the font file into Flash-friendly curves. I’m not sure why this was the case, but Batik was flummoxed by some of the faces in M+, specifically with the capital ‘O’ letterform.

I mean, you could trace a big O by hand if you wanted to. It’s cake. I can’t imagine why M+’s ‘O’ is so difficult to process, but if it can happen with this font, it could happen to any font.

I only managed to get good shaped text with one font manager- the one that also handles transcoding OpenType fonts and such, which uses the new Compact Font Format (CFF) system in Flash 10. (To learn more about this subject, here’s a post about the new CFF embedding system.)

It might seem subtle, but when you compare the text side by side, I think you’ll agree that all this CFF stuff I had to do was worth it. Below is the same SWF, one with M+ text imported with Batik, the other with CFF.

batik_test_font_bad.swf

batik_test_font_good.swf

In the same project, I’m using SVGs whenever I can to represent artwork. Again, this is because I want to support as many other developers’ workflows as I can. It doesn’t make sense to stick art in a FLA if you’re going to open the source to a project.

Anyway, embedding SVG files with an [Embed] tag is pretty straightforward– the only parameter you need to give is the file path to your SVG document. Unfortunately, Flash’s SVG transcoder apparently doesn’t handle things like the cap style on strokes. Again, it’s just my personal preference, but that’s kind of a deal breaker for me. A quick Google search pointed me to as3svgrendererlib, whose title is self-explanatory if you put spaces in the right spots. In a nutshell, it’s a runtime SVG interpreter, which is excellent; I can not only avoid the faulty SVG transcoder in the compiler, but I could potentially script the interpreter do handle SVGs however I want. But the [Embed] syntax still made sense for throwing the SVGs into my SWF as plain text. Doing that doesn’t take much – just remember to set its mimeType to “application/octet-stream”, and it’ll become a ByteArrayAsset:

[Embed(source="./vector_shape.svg", mimeType="application/octet-stream")]
const VectorShape:Class;
var VectorShapeSVG:XML = XML((new VectorShape).toString());

Like before, here are the bad and good SWFs side-by-side:

batik_test_svg_bad.swf

batik_test_svg_good.swf

batik_test_svg_better.swf (after editing the SVG parser to not use pixel hinting)

At this point I developed suspicion. Here are two situations where vector data is being transcoded, and where the results are suboptimal. Batik is not just a Java library for font management; it’s a full-blown SVG toolkit. Might it be used by mxmlc to transcode SVGs as well as simple font files?

There’s one easy way to find out. Batik resides within the “lib” directory in the Flex SDK. It’s easy to drop it to temporarily into another directory. I did this and recompiled all four SWFs you see here, and the two SWFs whose transcoders produced bad vector graphics both failed, verbosely. Both of them relied on Batik.

So! While something may be wrong with Batik, it is much more likely that the Batik toolkit is not being properly used in the Flex SDK. It may be possible to manually replace the Batik toolkit in the SDK with a newer version, but I would not recommend it, as I’ve demonstrated that there are easy ways to circumvent the problem. Embed your fonts as CFF, parse your SVG files at runtime and you’ll be in vector heaven.

update: I think I should point out that the default cap style for SVG is flat, while the default cap style for Flash is round. If you explicitly state in your SVG file what the cap style is for your lines, the built-in SVG system is probably fine. However, apps that export to SVG can’t be expected to handle every discrepancy between Flash’s default graphics configuration and the SVG spec’s, so you’ll be adding cap style properties to your SVG markup by hand. Personally, I’d go with the as3 SVG lib.


You can leave a response, or trackback from your own site.

Leave a Reply