Using custom font on many labels throws "Out Of Memory Error"

I'm using a custom font with a complex DataField.
And my layout is similar to this:

<label id="cad" x="2" y="18" color="Gfx.COLOR_BLACK" justification="Gfx.TEXT_JUSTIFY_LEFT" font="Rez.Fonts.bebas" />
<label id="avgspeed" x="197" y="18" color="Gfx.COLOR_BLACK" justification="Gfx.TEXT_JUSTIFY_RIGHT" font="Rez.Fonts.bebas" />
<label id="dist" x="2" y="63" color="Gfx.COLOR_BLACK" justification="Gfx.TEXT_JUSTIFY_LEFT" font="Rez.Fonts.bebas" />
<label id="disttg" x="197" y="63" color="Gfx.COLOR_BLACK" justification="Gfx.TEXT_JUSTIFY_RIGHT" font="Rez.Fonts.bebas" />

But if I put in my layout more label that use the custom font I have an "Out Of Memory Error".
How can I solve this problem?
  • Datafields have very little memory, so you will definitely face challenges with custom fonts, especially when using layouts as well.

    It is a known fact that layouts consume a lot of memory.

    Try using dc object to render yourself. Should give you more free memory for custom fonts.
  • I'm not sure if you are doing a DF, widget or watch-app,and I will freely admit I don't use layouts in anything, but my guess here is you keep loading the same font in the way you did your layout. So just in the code you posted, you have 4 copies of the font. (calling Travis! you know this stuff far better than me!)

    Also, with custom fonts, only include the things you need. Be it in bmfont, or by using a filter in the xml where you define the font. If you only need numbers, you don't need a-z and A-Z for example.
  • I'm assuming the same as Jim that the font will be loaded several times when using the layout system (I don't use the layout system either because it's so excessive in memory usage) and on some of the lower end watches you only have 16k for your complex datafield!

    The direct dc.draw approach allows you to keep memory usage way lower, in my second tutorial I explain how do the dc.draw approach: http://starttorun.info/tutorial-layout-by-coding-dc-draw-calls-directly/

    Peter.
    Fat Burner - Burn that FAT, baby!
    My other apps in the store

  • You're seeing the same bug that I filed a long time ago. Have a look at this thread.

    I agree with the suggestions posted above. You should always be using the character filter with your font definition (described in the Programmer's Guide here). This saves memory and doesn't require any changes to your source code. If you need to save more memory, then you might want to try font caching. If that isn't enough, then you'll probably want to consider switching over to loading fonts and drawing primitives directly.
  • To follow up, the following table compares the used memory for a layout with 4 labels using the custom font for 0, 1, 2, 3, and 4 of the labels...

    | | 0| 1| 2| 3| 4|
    |usedMemory |7344| 8080| 8816| 9552| 10280|


    If you load the font once and set it on each label in onLayout() like this, it only takes 8208 bytes.

    hidden var _mLayout;

    function onLayout(dc) {
    _mLayout = Rez.Layouts.MyLayout(dc);

    var font = Ui.loadResource(Rez.Fonts.bebas);
    for (var i = 0, j = _mLayout.size(); i < j; ++i) {
    layout.setFont(font);
    }

    DataField.setLayout(layout);
    }
    [/code]

    Since you are implementing a data field, you don't need to be concerned about font caching fonts across views. If you are implementing an app or widget with multiple views, you should try to use Ui.switchToView() where possible to avoid having multiple views in memory at the same time. If you must stack views via calls to Ui.pushView(), it may make sense to cache the font in the view and load/unload it in onShow() and onHide() even if you are not using layouts.

    Travis