Fix multiple problems with text drawing
[lsnes.git] / src / lua / gui-text.cpp
blob74d344ec06c1efa25bdb88964f60cb7d4c95d057
1 #include "core/instance.hpp"
2 #include "lua/internal.hpp"
3 #include "lua/halo.hpp"
4 #include "fonts/wrapper.hpp"
5 #include "library/framebuffer.hpp"
6 #include "library/lua-framebuffer.hpp"
8 namespace
10 struct render_object_text : public framebuffer::object
12 render_object_text(int32_t _x, int32_t _y, const std::string& _text, framebuffer::color _fg,
13 framebuffer::color _bg, framebuffer::color _hl, bool _hdbl = false, bool _vdbl = false)
14 throw()
15 : x(_x), y(_y), text(_text), fg(_fg), bg(_bg), hl(_hl), hdbl(_hdbl), vdbl(_vdbl) {}
16 ~render_object_text() throw() {}
17 template<bool X> void op(struct framebuffer::fb<X>& scr) throw()
19 auto size = main_font.get_metrics(text, x, hdbl, vdbl);
20 auto orig_size = size;
21 //Enlarge size by 2 in each dimension, in order to accomodiate halo, if any.
22 //Round up width to multiple of 32.
23 size.first = (size.first + 33) >> 5 << 5;
24 size.second += 2;
25 //The -1 is to accomodiate halo.
26 size_t allocsize = size.first * size.second + 32;
28 if(allocsize > 32768) {
29 std::vector<uint8_t> memory;
30 memory.resize(allocsize);
31 op_with(scr, &memory[0], size, orig_size);
32 } else {
33 uint8_t memory[allocsize];
34 op_with(scr, memory, size, orig_size);
37 template<bool X> void op_with(struct framebuffer::fb<X>& scr, unsigned char* mem,
38 std::pair<size_t, size_t> size, std::pair<size_t, size_t> orig_size) throw()
40 uint32_t rx = x + (int32_t)scr.get_origin_x() - 1;
41 uint32_t ry = y + (int32_t)scr.get_origin_y() - 1;
42 mem += (32 - ((size_t)mem & 31)) & 31; //Align.
43 memset(mem, 0, size.first * size.second);
44 main_font.render(mem + size.first + 1, size.first, text, x, hdbl, vdbl);
45 halo_blit(scr, mem, size.first, size.second, orig_size.first, orig_size.second, rx, ry, bg,
46 fg, hl);
48 void operator()(struct framebuffer::fb<true>& scr) throw() { op(scr); }
49 void operator()(struct framebuffer::fb<false>& scr) throw() { op(scr); }
50 void clone(framebuffer::queue& q) const throw(std::bad_alloc) { q.clone_helper(this); }
51 private:
52 int32_t x;
53 int32_t y;
54 std::string text;
55 framebuffer::color fg;
56 framebuffer::color bg;
57 framebuffer::color hl;
58 bool hdbl;
59 bool vdbl;
62 template<bool hdbl, bool vdbl>
63 int internal_gui_text(lua::state& L, lua::parameters& P)
65 auto& core = CORE();
66 int32_t x, y;
67 std::string text;
68 framebuffer::color fg, bg, hl;
70 if(!core.lua2->render_ctx) return 0;
72 P(x, y, text, P.optional(fg, 0xFFFFFFU), P.optional(bg, -1), P.optional(hl, -1));
74 core.lua2->render_ctx->queue->create_add<render_object_text>(x, y, text, fg, bg, hl, hdbl, vdbl);
75 return 0;
78 lua::functions LUA_text_fns(lua_func_misc, "gui", {
79 {"text", internal_gui_text<false, false>},
80 {"textH", internal_gui_text<true, false>},
81 {"textV", internal_gui_text<false, true>},
82 {"textHV", internal_gui_text<true, true>},
83 });