Lua: Custom fonts support
[lsnes.git] / src / lua / gui-text-cf.cpp
blob56755aa49251b2d4a3dd48e53f08ab276a088d8a
1 #include "lua/internal.hpp"
2 #include "fonts/wrapper.hpp"
3 #include "library/framebuffer.hpp"
4 #include "library/customfont.hpp"
5 #include "library/utf8.hpp"
8 namespace
10 struct lua_customfont
12 public:
13 lua_customfont(lua_State* LS, const std::string& filename);
14 ~lua_customfont() throw();
15 int draw(lua_State* LS);
16 const custom_font& get_font() { return font; }
17 private:
18 custom_font font;
22 DECLARE_LUACLASS(lua_customfont, "CUSTOMFONT");
24 namespace
26 std::vector<uint32_t> decode_utf8(const std::string& t)
28 std::vector<uint32_t> x;
29 size_t ts = t.length();
30 uint16_t s = utf8_initial_state;
31 for(size_t i = 0; i <= ts; i++) {
32 int ch = (i < ts) ? (int)(unsigned char)t[i] : -1;
33 int32_t cp = utf8_parse_byte(ch, s);
34 if(cp >= 0)
35 x.push_back(cp);
37 return x;
40 struct render_object_text_cf : public render_object
42 render_object_text_cf(int32_t _x, int32_t _y, const std::string& _text, premultiplied_color _fg,
43 premultiplied_color _bg, lua_obj_pin<lua_customfont>* _font) throw()
44 : x(_x), y(_y), text(_text), fg(_fg), bg(_bg), font(_font) {}
45 ~render_object_text_cf() throw() {}
46 template<bool X> void op(struct framebuffer<X>& scr) throw()
48 fg.set_palette(scr);
49 bg.set_palette(scr);
50 const custom_font& fdata = font->object()->get_font();
51 std::vector<uint32_t> _text = decode_utf8(text);
52 int32_t orig_x = x;
53 int32_t drawx = x;
54 int32_t drawy = y;
55 for(size_t i = 0; i < _text.size();) {
56 uint32_t cp = _text[i];
57 ligature_key k = fdata.best_ligature_match(_text, i);
58 const font_glyph_data& glyph = fdata.lookup_glyph(k);
59 if(k.length())
60 i += k.length();
61 else
62 i++;
63 if(cp == 9) {
64 drawx = (drawx + 64) >> 6 << 6;
65 } else if(cp == 10) {
66 drawx = orig_x;
67 drawy += fdata.get_rowadvance();
68 } else {
69 glyph.render(scr, drawx, drawy, fg, bg);
70 drawx += glyph.width;
75 void operator()(struct framebuffer<true>& scr) throw() { op(scr); }
76 void operator()(struct framebuffer<false>& scr) throw() { op(scr); }
77 private:
78 int32_t x;
79 int32_t y;
80 premultiplied_color fg;
81 premultiplied_color bg;
82 std::string text;
83 lua_obj_pin<lua_customfont>* font;
86 lua_customfont::lua_customfont(lua_State* LS, const std::string& filename)
87 : font(filename)
89 static bool done = false;
90 if(!done) {
91 objclass<lua_customfont>().bind(LS, "__call", &lua_customfont::draw);
92 done = true;
96 lua_customfont::~lua_customfont() throw() {}
98 int lua_customfont::draw(lua_State* LS)
100 std::string fname = "CUSTOMFONT::__call";
101 if(!lua_render_ctx)
102 return 0;
103 int64_t fgc = 0xFFFFFFU;
104 int64_t bgc = -1;
105 int32_t _x = get_numeric_argument<int32_t>(LS, 2, fname.c_str());
106 int32_t _y = get_numeric_argument<int32_t>(LS, 3, fname.c_str());
107 get_numeric_argument<int64_t>(LS, 5, fgc, fname.c_str());
108 get_numeric_argument<int64_t>(LS, 6, bgc, fname.c_str());
109 std::string text = get_string_argument(LS, 4, fname.c_str());
110 auto f = lua_class<lua_customfont>::pin(LS, 1, fname.c_str());
111 premultiplied_color fg(fgc);
112 premultiplied_color bg(bgc);
113 lua_render_ctx->queue->create_add<render_object_text_cf>(_x, _y, text, fg, bg, f);
114 return 0;
117 function_ptr_luafun gui_text_cf("gui.loadfont", [](lua_State* LS, const std::string& fname) -> int {
118 std::string filename = get_string_argument(LS, 1, fname.c_str());
119 try {
120 lua_customfont* b = lua_class<lua_customfont>::create(LS, LS, filename);
121 return 1;
122 } catch(std::exception& e) {
123 lua_pushstring(LS, e.what());
124 lua_error(LS);
125 return 0;