Pixelperfect HTML font rendering
I Just came back from the great Haxe conference in Paris. Was a wonderful weekend with great hosts (SilexLabs) and a great community!
I am looking forward to get my hands dirty with Haxe.
Specially the macros seems to be an incredible power tool to bend the limits of a language.
But the most important feature of Haxe is the multi platform compilation.
Write your code in Haxe and compile it to:
- Flash (Bytecode as well as AS3 source code)
- JavaScript
- NekoVM
- PHP
- C++
- C#
- Java (soon)
Thanks to NME you can also compile code written against an API similar to the Flash API to:
- iOS
- Android
- webOS
- BlackBerry
- Windows
- Mac
- Linux
Of course the platform specific code (rendering, features, limitations) needs to be treated for every platform specifically. But luckily a lot of this effort is already done in some frameworks.
Sounds all great but of course the reality is a bit more complex.
The support for all platforms will have its limits with the inherent problems from these platforms and from the more and more growing variety of platforms.
And unfortunately the HTML inherent problems will not be disappearing magically when using Haxe ;-).
Peter Halacsy presented at the conference a problem which address a very basic problem of HTML. The problem with pixel exact layout of text/fonts.
There are cases where an exact layout is not necessary, but others where it is essential, for instance if you need to zoom into it, then any inaccuracy will be multiplied and would screw up the whole layout.
It seems that a proper solution to solve these problems is very hard to find and probably needs to come from the browser vendors.
But there are maybe some “hacky” solutions to get around this.
So I would like to share some ideas here.
The problem:
When the layout of some graphical element is derived from a text, it is not possible to get the exact pixel position of any text character.
A simple example would be to display a custom graphic which is dependent to the width of the text.
If in one browser the text is a few pixels wider then in another, you have a problem to display everything pixel perfect.
In Flash you would not have any problems with static text. You simply place the graphic the way that it looks perfect. There are luckily no differences in browsers with text layout (embedded fonts).
With dynamic text you get some help from TextLineMetrics and properties of the TextField. This works basically fine. Even if it is not absolutely accurate, it is for the most use cases good enough.
In HTML the font rendering is different in every browser/OS and you don’t get any help to read out the metrics. I am not a HTML/JS guy but I think there is no possibility to access the font metrics in HTML.
So for static text a solution could be to create a custom font for every different browser and embed this font into your webpage with CSS3.
Lets assume we want to use Arial but it does have a different layout in Firefox and Chrome. We could derive from Arial 2 versions, an Arial_Firefox and an Arial_Chrome font which have different font metrics, so they look exactly the same on screen.
To do this change of the font metrics by hand you need to display a character in both browsers and find out the differences to a reference font display (for instance in Flash embedded Arial). Then change the font metrics in the way that it fits exactly the position and size of the reference font. If the layout engines are treating all characters the same way, it should be fine to do this metrics tuning only with one character. Otherwise it is much more work to repeat this procedure with all characters, but it is doable as well.
Then export the Font and use it in HTML as embedded font.
This way you have 2 different fonts in 2 different browsers with different font metrics, but both should look exactly the same. Of course it is some boring work and it would be great to have a tool to do this for you.
If using free fonts there should be also no problems with license issues and once a font is deployed for all major browsers, it could be shared to the community, so the effort only needs to be done once for a certain font and browser.
We used such an approach when getting layout problems with the Chinese version of the Flex trading application of the company i am working for. The Arial Unicode has different font metrics then the standard Arial, so our layout got screwed up. By changing the font metrics we solved this problem.
I know this sounds a bit hacky, but HTML/Javascript is a hacky world. And if you have a look to other assets, like video or sound, it it quite normal (in HTML) to deploy and create different files/formats for different browsers. If the approach works fine and someone creates a tool, then the whole process would be automated and a new font for any browser could be easily added .
With this you should get pixel perfect and unified font rendering.
For dynamic text you might also want to know the pixel position of any character.
A font specific metrics table could help here.
You could create this table from the (browser specific) font metrics and from measuring the actual pixel size/position.
It could be done by taking one character with a huge font size, display it in the browser and measure the exact pixel size/position. If all behaves in a linear manner you should be able to interpolate any font size and use the factors derived from the font metrics and the pixel size to apply it to all other characters. If this does not deliver good results you need again do the procedure with all single characters, but as long as you does not need to support chinese fonts it should be doable. Again a task for a tool to do this boring work…
So once you have a table with the exact metrics for any character and font size for a specific font, you could calculate the exact position and size of any character in the text.
In reality this will probably become more complex and difficult (many kind of font format options…), but I think it should be possible to get more or less the same range of accuracy like in Flash.
Please note this is only a rough idea without testing the approaches. But I guess for the ones who are suffering from these problems in the HTML world, it could be worth to give it a try.