Pixelperfect HTML font rendering

Published by Manfred Karrer on Friday, 20 of April , 2012 at 00:22

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.

Comments Off on Pixelperfect HTML font rendering

Category: Flash,Haxe,HTML

Dependency Injection with code generation

Published by Manfred Karrer on Friday, 30 of March , 2012 at 20:56

Why another Dependency Injection framework?

One thing nearly all DI frameworks have in common, is the use of reflection to obtain the extra information needed to inject the objects.
The downside of this approach is that reflection in general (and particularly in Flash) is pretty slow. This will probably not matter much for smaller application, but for large apps you can save several seconds of start-up time if you are not using reflection.

Unfortunately there is no solution out there beside a project from Joa Ebert, who is using a different approach. I wrote about this in another blog entry.

Another solution would be to use code generation.
With code generation you can inspect your code base at compile-time and write the information needed to a class.

I have added such a project to the nucleo library at github.

So how does it look like and how is it used?
Here are a few code snippets from the mojito example at github:

First we need the generated class for the constructor parameter keys. This will be created by an ant task, more about this later.

[code lang="actionscript3"]public class ConstructorParameters extends AConstructorParameters {
protected override function config():void {
constructorParameterKeys[BarProvider] = [IWaitress];
constructorParameterKeys[Bar] = [IWaitress];
constructorParameterKeys[Client] = ["theFewSpanishWords", IBar];
constructorParameterKeys[Waitress] = ["isInTheMood"];
}
}[/code]

You need to create the Config class which contains the mappings of the objects used for injection.
It passes an instance of the ConstructorParameters class to the AConfig super class.

[code lang="actionscript3"]public class MojitoConfig extends AConfig {

public function MojitoConfig() {
super(new ConstructorParameters());
}

override protected function setup():void {
mapInterface(IClient).toClass(Client).asSingleton();
mapParameterName("theFewSpanishWords").toInstance("¡Muchas gracias guapa!");
mapInterface(IBar).toProvider(BarProvider).asSingleton();
mapInterface(IWaitress).toClass(Waitress).asSingleton();
mapParameterName("isInTheMood").toInstance(true);
}
}[/code]

Then the setup can be done. After that you can access some root object and use this.

[code lang="actionscript3"]// first we need our Config. This is the place where our injection
// mappings are defined.
var config:MojitoConfig = new MojitoConfig();

// createInjector is a package level function used for convenience
// to get the injector
injector = createInjector(config);

// we take the root object out of the injector. The other objects will
// be injected just in time when they are needed.
var touristInBarcelona:IClient = injector.getObject(IClient);[/code]

Beside this, there are no traces left from the framework.

The Classes which gets created by the DI container are straight classes with constructor parameters totally unaware of the framework.
They don’t need any “Inject” Metadata tag. They does not know anything from the DI framework and how they get created. This is not their responsibility.

I think this is violated by the use of the Metadata at other DI frameworks. There the class has the information inside itself that a DI container is used for creating an instance of this class. I think this should be only the responsibility of the outer world using this class like a factory or the DI container.

But back to the project.

How does it work internally?

Basically the injection works pretty simple as a chained instantiation of all the dependent objects, starting with the first object requested from the injector:

[code lang="actionscript3"]var touristInBarcelona:IClient = injector.getObject(IClient);[/code]

This will create an instance of the class which is mapped to the key IClient. In our case it is the Client class.

[code lang="actionscript3"]mapInterface(IClient).toClass(Client).asSingleton();[/code]

For creating the Client class it looks up in the ConstructorParameters Class and get the information to create the 2 arguments needed there:
The instance mapped to “theFewSpanishWords” and an object of the class mapped with the key IBar.

[code lang="actionscript3"]constructorParameterKeys[Client] = ["theFewSpanishWords", IBar];[/code]

For creating an object of the Bar class it will need other objects as well, so the chain goes on like this until all objects needed are resolved.

The binding key can be an Instance, a Class or a String (named annotation).

For the named annotation I use a simple convention:
The parameter name must be the same as the annotation name in the Config class, like the “theFewSpanishWords” in the example. I think there is no reason not to use this simple and sensible convention and it makes life much easier and there is no need to add a Metadata for packing in this information.

I only support constructor injection as I prefer this style and it lets the class stay free of any Metadata.
Property or method injection could also be added but then you need to mark them with Metadata. As they would be invoked directly after the class is created i don’t see any reason why not to add these injected data to the constructor.

Now have a look to the code generation:

I used the as3-commons-jasblocks project which is using ANTLR. With this Java project you can read in your sources and it creates an object tree with all the elements of your code (abstract syntax tree). From this you can comfortably grab the constructor parameters and write (again with jasblocks) them into a class file.

I packed this into an ant task, as ant is pretty easy to use, good integrated into the IDEs and well known.
In the ant task you need to setup 2 parameters:

  • The source directories (as comma seperated list)
  • The target directory for the generated Class.

To automatically trigger the code generation for the ConstructorParameters Class before the compilation, you can use the built-in support for ant tasks of the IDE.

In FlashBuilder and IntelliJ there are easy ways to achieve this. So if the setup guarantees to always run the ant task before the compilation, the ConstructorParameters Class will be always up to date.

Here a quick description how to do this in FlashBuilder:

  • Right-click in the project and open the project properties.
  • Under Builder add a new Ant Builder before the Flex (compile) builder.
  • Under Main point to the build file: eg. ${workspace_loc}/${project_name}/build/build.xml
  • Under JRE: select separate JRE

flashbuilder

That’s it.

In IntelliJ you need to set an “Execute On” event (“Before Compilation”) to the ant task target. Then it will be executed just before the compilation.

intellij

If you don’t like to use the code generation you can also write this class by yourself of course, you just have to maintain it and it violates the DRY principle.

A few words about code generation in general:

For some people code generation has a kind of bad smell and they don’t like to rely on it.

I think it is a very powerful tool to get around the limitations of the language and to outsource boiler plate code.
And if you use Flex you are using it anyway even if you are not aware of it. Flex use a lot of code generation behind the scenes (add the -keep compiler flag to see it) for creating ActionScript code out of MXML, css files, RPC or Data Binding.

I think for the coding experience and productivity it is not only the potential of the language which counts, but also the features of the tools (IDE) you are working with.
What would you (as a developer writing code) benefit much from a type system if you would write your code in a primitive text editor without any code completion or error highlighting (the old Flash IDE was like this, I cannot imagine anymore how to work that way).

With these tools you can get also over the shortcomings of a language.

So I think when you hit the limitations of the language or runtime, it is valid to go in this direction and add features to help you to write clean and fast code.

There are also some limitations and the project is at the moment just a kind of “proof of concept”. It is not bulletproof yet and not tested in a production environment!

So use it at your own risk. I added comments and TODOs in the Java source code about known issues.

One limitation is about external library (swc) files.

With the as3-commons-jasblocks project you can only inspect the code base you have as source code, but not the code compiled into libraries.

There are some solutions (like flagstone) to access this as well, but I have not added this yet.

With the providers (see docs and example code) you always can get around any problems with classes out of your control like 3rd party libraries.

Beside this I think DI should only be used in a limited scope of a project (module).

Comments Off on Dependency Injection with code generation

Category: Actionscript,Flash,Flex