Lua: Don't lua_error() out of context with pending dtors
[lsnes.git] / src / lua / gui-text-cf.cpp
blob01fd4bf1f9afa2d47fba29118fd8c2232cec14df
1 #include "core/instance.hpp"
2 #include "lua/internal.hpp"
3 #include "lua/bitmap.hpp"
4 #include "fonts/wrapper.hpp"
5 #include "core/framebuffer.hpp"
6 #include "core/instance.hpp"
7 #include "library/framebuffer-font2.hpp"
8 #include "library/utf8.hpp"
9 #include "library/lua-framebuffer.hpp"
10 #include "library/zip.hpp"
11 #include <algorithm>
14 namespace
16 struct lua_customfont
18 public:
19 struct empty_font_tag {};
20 lua_customfont(lua::state& L, const std::string& filename, const std::string& filename2);
21 lua_customfont(lua::state& L);
22 lua_customfont(lua::state& L, empty_font_tag tag);
23 static size_t overcommit() { return 0; }
24 static size_t overcommit(const std::string& filename, const std::string& filename2) { return 0; }
25 static size_t overcommit(empty_font_tag tag) { return 0; }
26 ~lua_customfont() throw();
27 static int create(lua::state& L, lua::parameters& P);
28 static int load(lua::state& L, lua::parameters& P);
29 int draw(lua::state& L, lua::parameters& P);
30 int edit(lua::state& L, lua::parameters& P);
31 const framebuffer::font2& get_font() { return font; }
32 std::string print()
34 return orig_filename;
36 private:
37 std::string orig_filename;
38 framebuffer::font2 font;
41 lua::_class<lua_customfont> LUA_class_customfont(lua_class_gui, "CUSTOMFONT", {
42 {"new", lua_customfont::create},
43 {"load", lua_customfont::load},
44 }, {
45 {"__call", &lua_customfont::draw},
46 {"edit", &lua_customfont::edit},
47 }, &lua_customfont::print);
49 struct render_object_text_cf : public framebuffer::object
51 render_object_text_cf(int32_t _x, int32_t _y, const std::string& _text, framebuffer::color _fg,
52 framebuffer::color _bg, framebuffer::color _hl, lua::objpin<lua_customfont> _font) throw()
53 : x(_x), y(_y), text(_text), fg(_fg), bg(_bg), hl(_hl), font(_font) {}
54 ~render_object_text_cf() throw()
57 template<bool X> void op(struct framebuffer::fb<X>& scr) throw()
59 const framebuffer::font2& fdata = font->get_font();
60 std::u32string _text = utf8::to32(text);
61 int32_t orig_x = x;
62 int32_t drawx = x;
63 int32_t drawy = y;
64 if(hl) {
65 //Adjust for halo.
66 drawx++;
67 orig_x++;
68 drawy++;
70 for(size_t i = 0; i < _text.size();) {
71 uint32_t cp = _text[i];
72 std::u32string k = fdata.best_ligature_match(_text, i);
73 const framebuffer::font2::glyph& glyph = fdata.lookup_glyph(k);
74 if(k.length())
75 i += k.length();
76 else
77 i++;
78 if(cp == 9) {
79 drawx = (drawx + 64) >> 6 << 6;
80 } else if(cp == 10) {
81 drawx = orig_x;
82 drawy += fdata.get_rowadvance();
83 } else {
84 glyph.render(scr, drawx, drawy, fg, bg, hl);
85 drawx += glyph.width;
89 bool kill_request(void* obj) throw()
91 return kill_request_ifeq(font.object(), obj);
93 void operator()(struct framebuffer::fb<true>& scr) throw() { op(scr); }
94 void operator()(struct framebuffer::fb<false>& scr) throw() { op(scr); }
95 void clone(framebuffer::queue& q) const throw(std::bad_alloc) { q.clone_helper(this); }
96 private:
97 int32_t x;
98 int32_t y;
99 std::string text;
100 framebuffer::color fg;
101 framebuffer::color bg;
102 framebuffer::color hl;
103 lua::objpin<lua_customfont> font;
106 lua_customfont::lua_customfont(lua::state& L, const std::string& filename, const std::string& filename2)
107 : orig_filename(zip::resolverel(filename, filename2)), font(orig_filename)
111 lua_customfont::lua_customfont(lua::state& L)
112 : font(main_font)
114 orig_filename = "<builtin>";
117 lua_customfont::~lua_customfont() throw()
119 CORE().fbuf->render_kill_request(this);
122 int lua_customfont::draw(lua::state& L, lua::parameters& P)
124 auto& core = CORE();
125 int32_t _x, _y;
126 framebuffer::color fg, bg, hl;
127 std::string text;
128 lua::objpin<lua_customfont> f;
130 if(!core.lua2->render_ctx)
131 return 0;
133 P(f, _x, _y, text, P.optional(fg, 0xFFFFFFU), P.optional(bg, -1), P.optional(hl, -1));
135 core.lua2->render_ctx->queue->create_add<render_object_text_cf>(_x, _y, text, fg, bg, hl, f);
136 return 0;
139 lua_customfont::lua_customfont(lua::state& L, lua_customfont::empty_font_tag tag)
141 orig_filename = "<empty>";
144 int lua_customfont::edit(lua::state& L, lua::parameters& P)
146 std::string text;
147 lua_bitmap* _glyph;
149 P(P.skipped(), text, _glyph);
151 framebuffer::font2::glyph glyph;
152 glyph.width = _glyph->width;
153 glyph.height = _glyph->height;
154 glyph.stride = (glyph.width + 31) / 32;
155 glyph.fglyph.resize(glyph.stride * glyph.height);
156 memset(&glyph.fglyph[0], 0, sizeof(uint32_t) * glyph.fglyph.size());
157 for(size_t y = 0; y < glyph.height; y++) {
158 size_t bpos = y * glyph.stride * 32;
159 for(size_t x = 0; x < glyph.width; x++) {
160 size_t e = (bpos + x) / 32;
161 size_t b = 31 - (bpos + x) % 32;
162 if(_glyph->pixels[y * _glyph->width + x])
163 glyph.fglyph[e] |= (1UL << b);
166 font.add(utf8::to32(text), glyph);
167 return 0;
170 int lua_customfont::create(lua::state& L, lua::parameters& P)
172 lua::_class<lua_customfont>::create(L, lua_customfont::empty_font_tag());
173 return 1;
176 int lua_customfont::load(lua::state& L, lua::parameters& P)
178 std::string filename, filename2;
179 if(P.is_novalue()) {
180 lua::_class<lua_customfont>::create(L);
181 return 1;
184 P(filename, P.optional(filename2, ""));
186 lua::_class<lua_customfont>::create(L, filename, filename2);
187 return 1;