0

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

olevegard
  • 5,294
  • 1
  • 25
  • 29
mr5
  • 3,438
  • 3
  • 40
  • 57

1 Answers1

1

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.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • what does `std::map _fonts` handles? Sorry for being confused in your example code because I don't use them. Can you explain those `two params` do? – mr5 Jun 18 '13 at 13:06
  • @mr5: It is a "name of the font" -> "content of the font" map; you have to keep the correspondence somewhere. This way you ask for the font by name and you get a `SharedFontPtr` in exchange. – Matthieu M. Jun 18 '13 at 13:10
  • How do I manipulate `_fonts` i.e retrieving and putting? Can you provide more working sample code? because I still don't know how to access members on `std::map` – mr5 Jun 18 '13 at 13:18
  • does `std::shared_ptr` allocates resources already if I create label? – mr5 Jun 18 '13 at 13:23
  • @mr5: `std::shared_ptr` does not allocate resources. For `std::map`, you will need to use `insert` and `find`, the interface is described [here](http://en.cppreference.com/w/cpp/container/map). – Matthieu M. Jun 18 '13 at 13:40
  • It gets me undefined references when include `` using MinGW v4.6.2 – mr5 Jun 18 '13 at 15:15
  • @mr5: unfortunately I know not MinGW; undefined reference either mean that the MinGW library is incorrect OR that you are not linking against the appropriate library but I cannot know which. – Matthieu M. Jun 18 '13 at 16:59
  • Many many thanks!! I didn't know that there are "patterns" like this existing. I think, your answer is the absolute solution for this kind of problem. – mr5 Jun 19 '13 at 11:36
  • ahhm, can `std::shared_ptr` be substituted using `std::move` in the case that there will be no problem using it that way? is it safe? – mr5 Jun 19 '13 at 12:01
  • @mr5: no, you cannot substitute the `shared_ptr` here, however you can move it if you do not wish to copy it. – Matthieu M. Jun 19 '13 at 15:04