loading...

TrueType Font not working in Feathers?

amir_rezai profile image Amir Mohammad Rezai ・3 min read

The Error

So I tried so many ways to use TTF in my code in feathers but every time there was an error:
ArgumetError: BitmapFontTextFormat font must be a BitmapFont instance or a String representing the name of a registered bitmap font.

So I started writing a new theme for myself as I'm going to explain it in this post.

StyleNameFunctionTheme

This was the entry point of my problems, and I needed that fontStyles set to my own fonts so I began creating my theme for feathers.

package theme {
    import feathers.themes.StyleNameFunctionTheme;
    public class MyTheme extends StyleNameFunctionTheme {
        public function MyTheme(){
            super();
        }
    }
}

I just created a simple theme inherited from main starling theme provider, at this point I compiled my code and saw that even fonts are not showing, so I assumed that I have to provide fonts and stuff now.

I added buttonStyle the same as tutorial said for font only (without atlas) but it was not working either. So I started reading the example theme files source code.
First started reading MinimalDesktopTheme but it used bitmap fonts so no use to it.

Reading theme source code

As you can see most feather-ui themes contain 3 files:
Base$NAMETheme.as
$NAMETheme.as
$NAMEThemeWithAssetManager.as
Where $NAME is the name of theme.

BaseCustomTheme.as

This file contains every constant and includes a theme need.
looking at the start of file you can see something like this:

import feathers.controls.Alert;
import feathers.controls.AutoComplete;
...

That means we have to include every single feather component we want to change in here.
Next there comes the constructor of the class which extends StyleNameFunctionTheme and embeds the truetype fonts here:

public class BaseCustomTheme extends StyleNameFunctionTheme {
    [Embed(source="path/to/font.ttf", fontFamily="CustomFont", mimeType="application/x-font", embedAsCFF="true")]
protected static const CUSTOM_FONT_NAME:Class;

    ...
}

Then there are constants definitions all in SHOUTING style:

    protected static const PRIMARY_BG_COLOR:uint = 0x000000;
    protected static const LIGHT_TEXT_COLOR:uint = 0xffffff;
    ...

But then there was something unusual in the code as I could see some function called textRendererFactory:TextBlockTextRenderer passed into FeathersControl.defaultTextRendererFactory. They were separated so I brought them all together here:

    import feathers.controls.text.TextBlockTextRenderer;
    import feathers.core.FeathersControl;


    protected static function textRendererFactory():TextBlockTextRenderer 
    {
        return new TextBlockTextRenderer();
    }

    ...

    protected function initialize():void
    {
        // initialize fonts and stuff here but Globals is our target.
        ...
        initializeGlobals();
        ...
    }

    ...

    protected function initializeGlobals():void
    {
        FeathersControl.defaultTextRendererFactory = textRendererFactory;
        ...
    } 

In one glance

I usually don't read the whole article when I have a problem I read the gist code written in the end which solved the problem. here is how I made Monaco.ttf work in my code:

package theme {

    import starling.text.TextFormat;
    import feathers.themes.StyleNameFunctionTheme;
    import feathers.controls.text.TextBlockTextRenderer;
    import feathers.core.FeathersControl;
    import feathers.controls.Button;

    public class MyTheme extends StyleNameFunctionTheme {
        [Embed(source="/theme/monaco.ttf",fontFamily="Monaco",mimeType="application/x-font",embedAsCFF="false")]
        protected static const MONACO:Class;
        public function MyTheme(){
            super();
            this.initialize();
        }

        private function initialize():void {
            this.initializeGlobals();
            this.initializeStyleProviders();
        }

        private function textBlockRenderer():TextBlockTextRenderer {
            return new TextBlockTextRenderer();
        }

        private function initializeGlobals():void {
            FeathersControl.defaultTextRendererFactory = textBlockRenderer;
        }

        private function initializeStyleProviders():void {
            this.getStyleProviderForClass( Button ).defaultStyleFunction = this.setButtonStyles;
        }

        private function setButtonStyles( button:Button ):void {
            button.padding = 20;
            button.gap = 15;
            button.fontStyles = new TextFormat( "Monaco", 20, 0xFF0000 );
        }
    }
}

It is part of theme.MyTheme so I have to import theme.MyTheme into main source and then add a new MyTheme() to initialize the theme.

Posted on by:

amir_rezai profile

Amir Mohammad Rezai

@amir_rezai

I'm a game developer, with performance issues in mind. Live in Nerverland, Iran.

Discussion

markdown guide