Add <functional> to files that use std::function
[lsnes.git] / src / library / memorywatch-fb.cpp
blobfa4b47d7f711b79f222b60da8611ed3f50b430d8
1 #include "framebuffer-font2.hpp"
2 #include "memorywatch-fb.hpp"
3 #include "utf8.hpp"
4 #include "minmax.hpp"
5 #include <functional>
7 namespace memorywatch
9 namespace
11 struct fb_object : public framebuffer::object
13 struct params
15 int64_t x;
16 int64_t y;
17 bool cliprange_x;
18 bool cliprange_y;
19 bool alt_origin_x;
20 bool alt_origin_y;
21 framebuffer::font2* font;
22 framebuffer::color fg;
23 framebuffer::color bg;
24 framebuffer::color halo;
26 fb_object(const params& _p, const std::string& _msg);
27 ~fb_object() throw();
28 void operator()(struct framebuffer::fb<false>& scr) throw();
29 void operator()(struct framebuffer::fb<true>& scr) throw();
30 void clone(framebuffer::queue& q) const throw(std::bad_alloc);
31 private:
32 template<bool ext> void draw(struct framebuffer::fb<ext>& scr) throw();
33 params p;
34 std::u32string msg;
37 fb_object::fb_object(const fb_object::params& _p, const std::string& _msg)
38 : p(_p)
40 msg = utf8::to32(_msg);
43 fb_object::~fb_object() throw() {}
44 void fb_object::operator()(struct framebuffer::fb<false>& scr) throw() { draw(scr); }
45 void fb_object::operator()(struct framebuffer::fb<true>& scr) throw() { draw(scr); }
47 void fb_object::clone(framebuffer::queue& q) const throw(std::bad_alloc) { q.clone_helper(this); }
49 template<bool ext> void fb_object::draw(struct framebuffer::fb<ext>& scr) throw()
51 p.x += scr.get_origin_x();
52 p.y += scr.get_origin_y();
53 if(p.alt_origin_x)
54 p.x += scr.get_last_blit_width();
55 if(p.alt_origin_y)
56 p.y += scr.get_last_blit_height();
57 p.fg.set_palette(scr);
58 p.bg.set_palette(scr);
59 p.halo.set_palette(scr);
61 bool has_halo = p.halo;
62 //Layout the text.
63 int64_t orig_x = p.x;
64 int64_t drawx = p.x;
65 int64_t drawy = p.y;
66 int64_t max_drawx = p.x;
67 for(size_t i = 0; i < msg.size();) {
68 uint32_t cp = msg[i];
69 std::u32string k = p.font->best_ligature_match(msg, i);
70 const framebuffer::font2::glyph& glyph = p.font->lookup_glyph(k);
71 if(k.length())
72 i += k.length();
73 else
74 i++;
75 if(cp == 9) {
76 drawx = (drawx + 64) >> 6 << 6;
77 } else if(cp == 10) {
78 drawx = orig_x;
79 drawy += p.font->get_rowadvance();
80 } else {
81 drawx += glyph.width;
82 max_drawx = max(max_drawx, drawx);
85 uint64_t width = max_drawx - p.x;
86 uint64_t height = drawy - p.y;
87 if(has_halo) {
88 width += 2;
89 height += 2;
91 drawx = p.x;
92 drawy = p.y;
93 orig_x = p.x;
94 if(p.cliprange_x) {
95 if(drawx < 0)
96 drawx = 0;
97 else if(drawx + width > scr.get_width())
98 drawx = scr.get_width() - width;
100 if(p.cliprange_y) {
101 if(drawy < 0)
102 drawy = 0;
103 else if(drawy + height > scr.get_height())
104 drawy = scr.get_height() - height;
106 if(has_halo) {
107 orig_x++;
108 drawx++;
109 drawy++;
111 for(size_t i = 0; i < msg.size();) {
112 uint32_t cp = msg[i];
113 std::u32string k = p.font->best_ligature_match(msg, i);
114 const framebuffer::font2::glyph& glyph = p.font->lookup_glyph(k);
115 if(k.length())
116 i += k.length();
117 else
118 i++;
119 if(cp == 9) {
120 drawx = (drawx + 64) >> 6 << 6;
121 } else if(cp == 10) {
122 drawx = orig_x;
123 drawy += p.font->get_rowadvance();
124 } else {
125 glyph.render(scr, drawx, drawy, p.fg, p.bg, p.halo);
126 drawx += glyph.width;
132 output_fb::output_fb()
134 font = NULL;
137 output_fb::~output_fb()
139 if(dtor_cb)
140 dtor_cb(*this);
143 void output_fb::set_rqueue(framebuffer::queue& rqueue)
145 queue = &rqueue;
148 void output_fb::set_dtor_cb(std::function<void(output_fb&)> cb)
150 dtor_cb = cb;
153 void output_fb::show(const std::string& iname, const std::string& val)
155 fb_object::params p;
156 try {
157 if(cond_enable) {
158 enabled->reset();
159 auto e = enabled->evaluate();
160 if(!e.type->toboolean(e._value))
161 return;
163 pos_x->reset();
164 pos_y->reset();
165 auto x = pos_x->evaluate();
166 auto y = pos_y->evaluate();
167 p.x = x.type->tosigned(x._value);
168 p.y = y.type->tosigned(y._value);
169 p.alt_origin_x = alt_origin_x;
170 p.alt_origin_y = alt_origin_y;
171 p.cliprange_x = cliprange_x;
172 p.cliprange_y = cliprange_y;
173 p.font = font;
174 p.fg = fg;
175 p.bg = bg;
176 p.halo = halo;
177 queue->create_add<fb_object>(p, val);
178 } catch(...) {
182 void output_fb::reset()
184 enabled->reset();
185 pos_x->reset();
186 pos_y->reset();