Compile-time FXG

FXG was introduced with Flex 4 and offers a great way to skin and style your application without relying on bitmaps like PNGs.

“FXG is a declarative XML syntax for defining vector graphics in applications built with Flex.”

When you declare FXG within your MXML it is computed at runtime but there is also a way to use compile time FXG. There is up to 10x improvement in memory consumption and start-up time when converting complex MXML Graphics (with lots of Paths) into FXG.

Deepa explains it like this:

“This is an optimization scheme which takes advantage of the fact that a lot of FXG content is simply static assets that do not need to be updatd or re-rendered at runtime. In cases like that, you could imagine that instead of creating ActionScript objects to represent those graphic elements, the Flex compiler could instead create SWF graphic primitive tags to draw the static FXG asset”

So there is some benefit in using compile time FXG and in many cases you can just copy and paste the FXG to an .fxg file with some minor syntactical changes. The downside of compile time FXG is that you have to specify fix dimensions. This means you cannot use percentage values for the width and height.

Let’s look at an example which uses FXG to define the background of a Group.
Comparison:

Runtime FXG

Compile-time FXG

You see that you can instantiate the Background.fxg like any other class.
The differences between compile and runtime are fairly simple:

  • Add a Graphic tag
  • Replace spark namespace with default namespace
  • Change numeric values 0x to #
  • Define fix width and height

Another difference is that you have to apply a scale-9-grid for the background in case of rounded corners and filters. This would like like this:

These are still simple examples and it can get way more complex and you will run into limitations. Compile time FXG was developed by Peter Farland from the Flex side and he gave some inside about the limitations of compile time FXG in combination with scale-9-grid:

  • An item with a scaling grid cannot have child <Group> elements (because ata lower level a scaling grid cannot be applied to a DefineSprite that has a child DefineSprite(s)… this also means that you can’t use a scaling grid with children that are ultimately DefineSprite based including <RichText>,or a custom Library Definition, and I think if alpha masks, luminosity masks, or pixel-bender based blend modes (such as colordodge, colorburn,exclusion, softlight, hue, saturation, color, luminosity) are applied).
  • A scaling grid must be a valid rectangle – i.e. the resulting rect must have a non-zero width and height and the left extent must be to the left of the right extend, and the top extent must be above the bottom extent.
  • The scaling grid¹s center rectangle must be wholly within the bounds ofthe item(s) being scaled.
  • Rotated items cannot be scaled with a scaling grid (I think? though notethat restriction doesn’t apply to rotated gradient fills applied to shapesbeing scaled, for instance).
  • There are several bugs when applying a scaling grid to a collection of child shapes – adding a transparent Rect underneath that spans the bounds of all of the child shapes can help.
  • When manually calculating the dimensions of a scaling grid you need to consider the total bounds of the item(s) being scaled. This must take into account the stroke width, miter and joint types. Watch out for fractionalpixels of strokes that apply once an item is scaled.

Conclusion
Try to use compile-time FXG when possible. The performance of your application will improve and you have a better separation of design and code which is one step further for the designer/developer workflow.
For further reference check the FXG 2.0 Specification

.

5 comments to Compile-time FXG

  • Thuan Bui

    Hello Sönke Rohde,

    I have a question that I hope that you would answere.

    When your AIR Mobile StageWebView UIComponent is implemented in a view and when that view is called it is impossible to use back button on the device or ex. navigator.pushview(MyPreviousView1) to navigate back to the calling view afterwards. The html-page is still on the screen.

    Do you know how to make it work?

    Thanks in advance.

    Best regards
    Thuan

  • Thuan Bui

    found out that stageWebView.dispose() has to be called before using navigator.pushview to navigate back to the previous view..

    thanks for your excellent StageWebView component…

  • Really nice tech note. While I my passion still remains with Degrafa, this is a VERY nice trick for performance improvements.

  • If I am not mistaken, the scale-9 slicing in Background2.fxg does not currently work in Flash Player, due to the filter. (No joke!) If you remove the filter, it works fine. This makes me very sad.