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

Not easy to use “usePhasedInstantiation”

Published by Manfred Karrer on Wednesday, 23 of March , 2011 at 23:47

Have you ever tried to use usePhasedInstantiation? It is not so easy, as you will see…

What is usePhasedInstantiation?
This is a property at the LayoutManager which is used to decide if the methods for the 3 Lifecycle phases (validateProperties, validateSize and validateDisplayList) are deferred with 3 (half-)frames or if they are all executed synchronously in one Frame. So if it is set to true (default state) at an EnterFrame event validateProperties() is called, on the next Render event validateSize() and on the next EnterFrame event validateDisplayList().

As I discussed in a previous blog entry, I was wondering why Flex is using a deferred asynchronous execution model. I tried to find out what happens if you change this property.

First I tracked the executed frames and checked out how it behaves with different use cases of Flex applications:
With a simply Flex application with a few random components it was like expected: 1 Frame delay for the whole cycle (3 half frames).
Then i added much more components and also some really heavy weight components like DataGrid, DateChooser or ColorPicker.
Here it took 3 frames, so it seems that there is some code in some of these Flex components which causes additional invalidation cycles (for instance if you call a invalidateProperties method inside of a creationComplete handler you will trigger a new cycle).
At last I measured with our Spreadbetting application at CMC Markets. Here it was a bit more difficult because there was more complex stuff going on. I measured the executed frames and time it takes until the application was idle in the login state and waiting for user input. We will compare the results later.

I tried to investigate to change this property to see and measure the effects on performance.
But unfortunately it didn´t had any effect. After stepping into the SDK sources, i found the reason:
It is set to true in the Containers createComponentFromDescriptor method which is called for adding the MXML children inside a Container. So it doesn´t help much if you set it to false at any place in the Application, because it will be overwritten by the adding of the first child at any Container class (Canvas, HBox,…).
I am not sure if there is a clean solution how to change this default behavior, but for my test case it was enough to simply ignore the value passed into the setter method in the LayoutManager and set the value to false by default.
But to change the LayoutManager is not so easy. It is setup in the SystemManager and to override this implementation you need to change the SystemManager which can be only defined in an own Application class.

Here are the steps how to do this:

In your MXML Application you use a custom Application class:

[code lang="actionscript3"]

MyApplication defines the custom SystemManager as factoryClass in the "Frame" metadata tag:

[code lang="actionscript3"][Frame(factoryClass="com.test.bootstrap.MySystemManager")]
public class MyApplication extends Application
[/code]

MySystemManager overrides the docFrameHandler method and set MyLayoutManager as implementation class for the ILayoutManager:

[code lang="actionscript3"]public class MySystemManager extends SystemManager {
override mx_internal function docFrameHandler(event:Event = null):void {
  Singleton.registerClass("mx.managers::ILayoutManager",
    Class(getDefinitionByName("com.test.bootstrap::MyLayoutManager")));
  super.mx_internal::docFrameHandler(event);
}
[/code]

In MyLayoutManager you can bypass the assignment of the usePhasedInstantiation property:

[code lang="actionscript3"]public function set usePhasedInstantiation(value:Boolean):void {
  // for simple testing purpose:
  // simply ignore the values coming from Container and
  // set it by default to false
  value = false;

  if (_usePhasedInstantiation != value) {
    _usePhasedInstantiation=value;
    var sm:ISystemManager=SystemManagerGlobals.topLevelSystemManagers[0];
    var stage:Stage=SystemManagerGlobals.topLevelSystemManagers[0].stage;
    if (stage) {
      if (value) {
        originalFrameRate=stage.frameRate;
        stage.frameRate=1000;
      } else {
        stage.frameRate=originalFrameRate;
      }
    }
  }
}
[/code]

Another interesting detail is that Flex is setting the framerate to 1000 while these phased instantiation is active to speed up the execution (but this could also lead to strange side effects with too fast running animations like we have in our application with a pre-loader animation).

So lets do the tests again with this new setting:
The simple setup showed that all is executed inside of one frame and the time measured showed a faster startup, but the difference was pretty small.
The setup with the more complex Flex components gave a bigger difference in time and of course all was executed in one frame again.
In our CMC application the startup was 400ms faster (2300ms vs. 2700ms).
So 15% faster startup with usePhasedInstantiation set to false in our application startup.

To be honest, I was expecting more. Maybe it is related to the fact that at our application startup (until the login screen) there are not many components created.
I also tried to compare the 2 versions after the user has logged in and under heavy load with a lot of modules and windows open. I could not see a distinct difference but that was probably because of the complexity in this setup caused by a lot of network events.
At least i could not see any problems with rendering. The application was not freezing in any state, so the reason why usePhasedInstantiation was introduced to make the startup more fluidly, does not show any effect in our application.

What is the conclusion?
It does not improve the startup performance much if this property is changed (15% in our application), but I could imagine, when using a lot of components created all at once at startup time, the difference could be stronger. Maybe there could also be problems with freezing the rendering when setting the flag to false.

Even the result is for our use-case not much improvement, it was interesting to see how it is implemented, and to show that Flex is working fine without the deferred lifecycle as well. Also the technique how to exchange the SystemManager and how the implementation for a LayoutManager is configured, was an interesting learning.

Comments (2)

Category: Actionscript,Flash,SDK