1 #include "platform/wxwidgets/textrender.hpp"
2 #include "platform/wxwidgets/platform.hpp"
3 #include "fonts/wrapper.hpp"
4 #include "library/utf8.hpp"
5 #include "library/string.hpp"
7 #include <wx/dcclient.h>
10 extern const uint32_t text_framebuffer::element::white
= 0xFFFFFF;
11 extern const uint32_t text_framebuffer::element::black
= 0x000000;
13 text_framebuffer::text_framebuffer()
19 text_framebuffer::text_framebuffer(size_t w
, size_t h
)
26 void text_framebuffer::set_size(size_t w
, size_t h
)
28 if(w
== width
&& h
== height
)
30 std::vector
<element
> newfb
;
32 for(size_t i
= 0; i
< h
&& i
< height
; i
++)
33 for(size_t j
= 0; j
< w
&& j
< width
; j
++)
34 newfb
[i
* w
+ j
] = buffer
[i
* width
+ j
];
40 std::pair
<size_t, size_t> text_framebuffer::get_cell()
42 return std::make_pair(8, 16);
45 std::pair
<size_t, size_t> text_framebuffer::get_pixels()
48 return std::make_pair(x
.first
* width
, x
.second
* height
);
51 void text_framebuffer::render(char* tbuffer
)
53 uint32_t dummy
[8] = {0};
54 size_t stride
= 24 * width
;
55 size_t cellstride
= 24;
56 for(size_t y
= 0; y
< height
; y
++) {
58 for(size_t x
= 0; x
< width
; x
++) {
60 break; //No more space in row.
61 char* cellbase
= tbuffer
+ y
* (16 * stride
) + xp
* cellstride
;
62 const element
& e
= buffer
[y
* width
+ x
];
63 const framebuffer::font::glyph
& g
= main_font
.get_glyph(e
.ch
);
64 char bgb
= (e
.bg
>> 16);
65 char bgg
= (e
.bg
>> 8);
66 char bgr
= (e
.bg
>> 0);
67 char fgb
= (e
.fg
>> 16);
68 char fgg
= (e
.fg
>> 8);
69 char fgr
= (e
.fg
>> 0);
70 const uint32_t* data
= (g
.data
? g
.data
: dummy
);
71 if(g
.wide
&& xp
< width
- 1) {
72 //Wide character, can draw full width.
73 for(size_t y2
= 0; y2
< 16; y2
++) {
74 uint32_t d
= data
[y2
>> 1];
75 d
>>= 16 - ((y2
& 1) << 4);
76 for(size_t j
= 0; j
< 16; j
++) {
78 if(((d
>> b
) & 1) != 0) {
79 cellbase
[3 * j
+ 0] = fgr
;
80 cellbase
[3 * j
+ 1] = fgg
;
81 cellbase
[3 * j
+ 2] = fgb
;
83 cellbase
[3 * j
+ 0] = bgr
;
84 cellbase
[3 * j
+ 1] = bgg
;
85 cellbase
[3 * j
+ 2] = bgb
;
92 //Wide character, can only draw half.
93 for(size_t y2
= 0; y2
< 16; y2
++) {
94 uint32_t d
= data
[y2
>> 1];
95 d
>>= 16 - ((y2
& 1) << 4);
96 for(size_t j
= 0; j
< 8; j
++) {
98 if(((d
>> b
) & 1) != 0) {
99 cellbase
[3 * j
+ 0] = fgr
;
100 cellbase
[3 * j
+ 1] = fgg
;
101 cellbase
[3 * j
+ 2] = fgb
;
103 cellbase
[3 * j
+ 0] = bgr
;
104 cellbase
[3 * j
+ 1] = bgg
;
105 cellbase
[3 * j
+ 2] = bgb
;
113 for(size_t y2
= 0; y2
< 16; y2
++) {
114 uint32_t d
= data
[y2
>> 2];
115 d
>>= 24 - ((y2
& 3) << 3);
116 for(size_t j
= 0; j
< 8; j
++) {
118 if(((d
>> b
) & 1) != 0) {
119 cellbase
[3 * j
+ 0] = fgr
;
120 cellbase
[3 * j
+ 1] = fgg
;
121 cellbase
[3 * j
+ 2] = fgb
;
123 cellbase
[3 * j
+ 0] = bgr
;
124 cellbase
[3 * j
+ 1] = bgg
;
125 cellbase
[3 * j
+ 2] = bgb
;
136 size_t text_framebuffer::text_width(const std::string
& text
)
138 auto x
= main_font
.get_metrics(text
);
142 size_t text_framebuffer::write(const std::string
& str
, size_t w
, size_t x
, size_t y
, uint32_t fg
, uint32_t bg
)
144 return write(utf8::to32(str
), w
, x
, y
, fg
, bg
);
147 size_t text_framebuffer::write(const std::u32string
& str
, size_t w
, size_t x
, size_t y
, uint32_t fg
, uint32_t bg
)
156 if(x
+ pused
< width
) {
157 element
& e
= buffer
[y
* width
+ x
+ pused
];
166 const framebuffer::font::glyph
& g
= main_font
.get_glyph(u
);
167 if(x
+ pused
< width
) {
168 element
& e
= buffer
[y
* width
+ x
+ pused
];
173 pused
+= (g
.wide
? 2 : 1);
177 if(x
+ pused
< width
) {
178 element
& e
= buffer
[y
* width
+ x
+ pused
];
188 text_framebuffer_panel::text_framebuffer_panel(wxWindow
* parent
, size_t w
, size_t h
, wxWindowID id
,
190 : wxPanel(parent
, id
), text_framebuffer(w
, h
)
193 redirect
= _redirect
;
194 auto psize
= get_pixels();
195 size_changed
= false;
197 paint_requested
= false;
198 SetMinSize(wxSize(psize
.first
, psize
.second
));
199 this->Connect(wxEVT_PAINT
, wxPaintEventHandler(text_framebuffer_panel::on_paint
), NULL
, this);
200 this->Connect(wxEVT_ERASE_BACKGROUND
, wxEraseEventHandler(text_framebuffer_panel::on_erase
), NULL
, this);
201 this->Connect(wxEVT_SET_FOCUS
, wxFocusEventHandler(text_framebuffer_panel::on_focus
), NULL
, this);
204 text_framebuffer_panel::~text_framebuffer_panel()
208 void text_framebuffer_panel::set_size(size_t _width
, size_t _height
)
211 text_framebuffer::set_size(_width
, _height
);
212 auto psize
= get_pixels();
213 buffer
.resize(psize
.first
* psize
.second
* 3);
215 SetMinSize(wxSize(psize
.first
, psize
.second
));
221 void text_framebuffer_panel::request_paint()
225 auto psize
= get_pixels();
226 SetMinSize(wxSize(psize
.first
, psize
.second
));
227 size_changed
= false;
228 paint_requested
= true;
230 } else if(!paint_requested
) {
231 paint_requested
= true;
236 void text_framebuffer_panel::on_erase(wxEraseEvent
& e
)
240 void text_framebuffer_panel::on_paint(wxPaintEvent
& e
)
244 auto size
= GetSize();
245 text_framebuffer::set_size((size
.x
+ 7) / 8, (size
.y
+ 15) / 16);
246 auto psize
= get_pixels();
247 buffer
.resize(psize
.first
* psize
.second
* 3);
250 psize
= get_pixels();
253 wxBitmap
bmp1(wxImage(psize
.first
, psize
.second
, reinterpret_cast<unsigned char*>(&buffer
[0]),
255 dc
.DrawBitmap(bmp1
, 0, 0, false);
256 paint_requested
= false;
259 void text_framebuffer_panel::on_focus(wxFocusEvent
& e
)
263 redirect
->SetFocus();