フォントクラス

昔に作ったライブラリのフォントクラスとあまり違わなかったり。id:melpon:20090324(文字列をテクスチャ化する)で使ってます。
BREW2.x は非対応でつ(多分スモールフォントあたりちょっと弄れば動くけど)。

#ifndef AEE_SIMULATOR
# include <kddifonts.h>
#else
# include <FontCreator.h>
#endif

struct font_type
{
    enum type
    {
        very_small = 0x7998,
        small = 0x7999,
        normal = AEE_FONT_NORMAL,
        bold = AEE_FONT_BOLD,
        large = AEE_FONT_LARGE,
    };
};

class font
{
public:
    struct font_guard : noncopyable
    {
        font_guard(const font& f)
            : disp_(f.display_.get()), small_(f.small_.get())
        {
            if (small_ != nullptr)
            {
                old_ = IDISPLAY_SetFont(disp_, AEE_FONT_NORMAL, small_);
            }
        }
        ~font_guard()
        {
            if (small_ != nullptr)
            {
                IDISPLAY_SetFont(disp_, AEE_FONT_NORMAL , old_);
            }
        }
    private:
        IDisplay* disp_;
        IFont* small_;
        IFont* old_;
    };

    friend struct font_guard;

    static brew_ptr<IFont> make_small_font(IShell* sh, bool very_small)
    {
#ifndef AEE_SIMULATOR
        AEECLSID id = very_small ? KDDI_FONT_FIXED12X12 : KDDI_FONT_FIXED16X16;
        return static_pointer_cast<IFont>(shell(sh).create(id));
#else
        brew_ptr<IFont> f;

        int size = very_small ? 12 : 16;

        IFontCreator* creator;
        ISHELL_CreateInstance(sh, AEECLSID_FONTCREATOR_SJIS, reinterpret_cast<void**>(&creator));
        AEEFontInfo fi;
        fi.nDescent = 2;
        fi.nAscent = size - fi.nDescent;

        IFONTCREATOR_CreateFont(creator, "MSGOTHIC", size, 0, FALSE,
            &fi, sizeof(AEEFontInfo), f.address());
        IFONTCREATOR_Release(creator);
        return f;
#endif
    }

public:
    font(IShell* sh, IDisplay* disp)
        : shell_(sh), display_(disp)
    {
        reset(font_type::normal);
    }
    font(IShell* sh, IDisplay* disp, font_type::type f)
        : shell_(sh), display_(disp)
    {
        reset(f);
    }

    void reset(font_type::type f)
    {
        if (f == font_type::small || f == font_type::very_small)
        {
            small_ = make_small_font(shell_.get(), f == font_type::very_small);
        }
        else
        {
            small_.reset();
        }

        font_ = f;
        AEEFont aefont = getAEEFont();
        font_guard guard(*this);
        hei_ = (uint8)IDISPLAY_GetFontMetrics(display_.get(), aefont, nullptr, nullptr);
        wid_ = (uint8)IDISPLAY_MeasureText(display_.get(), aefont, reinterpret_cast<const AECHAR*>("a\0\0\0"));
    }
    font_type::type get() const
    {
        return font_;
    }
    AEEFont getAEEFont() const
    {
        if (font_ == font_type::small || font_ == font_type::very_small)
        {
            return AEE_FONT_NORMAL;
        }
        else
        {
            return static_cast<AEEFont>(font_);
        }
    }
    int height() const
    {
        return hei_;
    }
    int string_width(const AECHAR* str) const
    {
        return string_width(str, -1);
    }
    int string_width(const AECHAR* str, int width) const
    {
        uint32 w = 0;
        uint32 wid = (width >= 0) ? width : (uint32)(-1);
        for ( ; *str; ++str){
            uint32 ow = w;
            AECHAR c = *str;
            w += is_single(c) ? wid_ : wid_ * 2;
            if (w > wid)
            {
                return ow;
            }
        }
        return w;
    }
    int line_break(const AECHAR* str, int width) const
    {
        const AECHAR* save = str;
        int w = 0;
        for ( ; *str; ++str){
            AECHAR c = *str;
            w += is_single(c) ? wid_ : wid_ * 2;
            if (w > width)
            {
                return str - save;
            }
        }
        return str - save;
    }

    // ダブルディスパッチ用
    void draw_string(const AECHAR* str, int x, int y, const color& c) const
    {
        font_guard guard(*this);
        IDISPLAY_SetColor(display_.get(), CLR_USER_TEXT, MAKE_RGB(c.r, c.g, c.b));
        int result = IDISPLAY_DrawText(display_.get(), getAEEFont(), str, -1, x, y, nullptr, IDF_TEXT_TRANSPARENT);
    }

private:
    static bool is_single(AECHAR c)
    {
        return c < 128 || (0xa0 <= c && c <= 0xdf);
    }

    shell                   shell_;
    brew_ptr<IDisplay>      display_;
    brew_ptr<IFont>         small_;
    font_type::type         font_;
    uint8       wid_;
    uint8       hei_;
};

IDISPLAY_MeasureTextEx を使うと遅い(少なくとも昔は遅かった)ので、文字列の幅を自前で計算しているのが特徴的(といっても前のライブラリと一緒だけど)かも?