フォントクラス
昔に作ったライブラリのフォントクラスとあまり違わなかったり。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 を使うと遅い(少なくとも昔は遅かった)ので、文字列の幅を自前で計算しているのが特徴的(といっても前のライブラリと一緒だけど)かも?