Question

Suppose I have a Font class that looks like this:

const unsigned int MAX_CHAR = 256; //better than dynamic I think?

struct BMchar
{
    int x_ofs, y_ofs;
    _uint32 x, y;
    _uint32 width, height;
    _uint32 x_advance;
};

struct BMkerninfo
{
    _ushort first, second;
    _ushort kerning;
};

class BM_FONT_CALL BMfont
{
public:

    BMfont();
    ~BMfont(); //what will I free?

    BMfont_Status Load(const char* fontName);

public:

    float scale;
    _uint32 tabSize;
    _uint32 backTexture;
    _uint32 frontTexture;
    _uint32 textureSheet;
    bool enableMasking;
    bool hasBackground;

    _uint32 base;
    _uint32 lineHeight;
    _uint32 pages;
    _uint32 scaleW, scaleH;
    _uint32 kerninfo_count;

    BMkerninfo  *kerninfo; //unused
    BMchar chars[MAX_CHAR];
    float texCoordBuff[MAX_CHAR * 8];
};

And I have a class Label:

class SWC_DLL SWC_Label
{
public:

    SWC_Label ();

public:

    void ShowText (const Point& basePoint, int baseW, int baseH);

public:

    std::string text;
    Point   textCoord;
    BMfont  font;
    T_Alignment textAlignment;

};

Then for all of this I worry about, as you see, the BMfont class uses lot of resources. I will inherit the class SWC_Label to a class SWC_Button (Yes a button, with a label/text on it).

Now, I want this SWC_Button to have a feature of having a different font. What is the better and memory-efficient way to do things like this, should I make a limitations like: make a defined number of available font only (making static fonts in class label)?

Note: I am making a UI using OpenGL

Was it helpful?

Solution

There are two design patterns that could be of help: Factory and FlyWeight.

Typically, your SWC_Label class does not need to own a BMFont, it only needs to manipulate one; my advice would be to use a Factory of fonts, that will internally keep a handle on the fonts it knows about.

Simple example:

class FontFactory {
public:
    typedef std::shared_ptr<BMFont> SharedFontPtr;

    SharedFontPtr getFont(std::string const& name) const;

private:
    std::map<std::string, SharedFontPtr> _fonts;
}; // class FontFactory

And then, the SWC_Label class holds a std::shared_ptr<BMFont> (relatively lightweight handle) rather than a full font class.

There are many variations on the topic:

  • lazy load of yet unknown fonts (from the Factory)
  • keeping a std::weak_ptr reference in the Factory, to reduce memory footprint as much as possible
  • not keeping a reference at all (potentially wasteful though), as you may end up with several copies in memory

To optimize memory consumptions of objects with a big common shared part but a small endemic part you might want to read on FlyWeight, the case we have here being a degenerate case where there is no endemic part and thus you do not have to split the object in common/endemic parcels.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top