Lua: Add gui.textH, gui.textV, gui.textHV

This commit is contained in:
Ilari Liusvaara 2011-12-25 00:26:25 +02:00
parent 7f8b57b7ad
commit 9e3b7c82d4
3 changed files with 58 additions and 36 deletions

View file

@ -368,7 +368,7 @@ void do_init_font();
* returns: Two components: First is width of character, second is pointer to font data (NULL if blank glyph).
*/
std::pair<uint32_t, const uint32_t*> find_glyph(uint32_t codepoint, int32_t x, int32_t y, int32_t orig_x,
int32_t& next_x, int32_t& next_y) throw();
int32_t& next_x, int32_t& next_y, bool hdbl = false, bool vdbl = false) throw();
/**
* Render text into screen.
@ -378,9 +378,11 @@ std::pair<uint32_t, const uint32_t*> find_glyph(uint32_t codepoint, int32_t x, i
* parameter _text: The text to render (UTF-8).
* parameter _fg: Foreground color.
* parameter _bg: Background color.
* parameter _hdbl: If true, draw text using double width.
* parameter _vdbl: If true, draw text using double height.
* throws std::bad_alloc: Not enough memory.
*/
void render_text(struct screen& scr, int32_t _x, int32_t _y, const std::string& _text, premultiplied_color _fg,
premultiplied_color _bg) throw(std::bad_alloc);
premultiplied_color _bg, bool _hdbl = false, bool _vdbl = false) throw(std::bad_alloc);
#endif

View file

@ -136,7 +136,7 @@ skip_line:
return font_glyph_offsets.count(cp) ? font_glyph_offsets[cp] : 0;
}
inline uint32_t process_tag(uint32_t tag, int32_t& x, int32_t& y, int32_t orig_x)
inline uint32_t process_tag(uint32_t tag, int32_t& x, int32_t& y, int32_t orig_x, bool hdbl, bool vdbl)
{
uint32_t dwidth;
switch(tag & TAG_WIDTH_MASK) {
@ -153,9 +153,9 @@ skip_line:
dwidth = 0x40 - (x & 0x3F);
break;
}
x += dwidth;
x += dwidth * (hdbl ? 2 : 1);
if(tag & TAG_LINECHANGE) {
y += 16;
y += 16 * (vdbl ? 2 : 1);
x = orig_x;
}
return dwidth;
@ -174,14 +174,14 @@ void do_init_font()
}
std::pair<uint32_t, const uint32_t*> find_glyph(uint32_t codepoint, int32_t x, int32_t y, int32_t orig_x,
int32_t& next_x, int32_t& next_y) throw()
int32_t& next_x, int32_t& next_y, bool hdbl, bool vdbl) throw()
{
init_font();
next_x = x;
next_y = y;
uint32_t offset = find_font_glyph_offset(codepoint);
uint32_t tag = font_glyph_data[offset];
uint32_t dwidth = process_tag(tag, next_x, next_y, orig_x);
uint32_t dwidth = process_tag(tag, next_x, next_y, orig_x, hdbl, vdbl);
bool visible = is_visible(tag);
return std::pair<uint32_t, const uint32_t*>(dwidth, visible ? &font_glyph_data[offset + 1] : NULL);
}
@ -191,7 +191,7 @@ render_object::~render_object() throw()
}
void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& text, premultiplied_color fg,
premultiplied_color bg) throw(std::bad_alloc)
premultiplied_color bg, bool hdbl, bool vdbl) throw(std::bad_alloc)
{
int32_t orig_x = x;
uint32_t unicode_code = 0;
@ -221,11 +221,11 @@ void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& te
} else
continue;
int32_t next_x, next_y;
auto p = find_glyph(unicode_code, x, y, orig_x, next_x, next_y);
auto p = find_glyph(unicode_code, x, y, orig_x, next_x, next_y, hdbl, vdbl);
uint32_t dx = 0;
uint32_t dw = p.first;
uint32_t dw = p.first * (hdbl ? 2 : 1);
uint32_t dy = 0;
uint32_t dh = 16;
uint32_t dh = 16 * (vdbl ? 2 : 1);
uint32_t cx = static_cast<uint32_t>(static_cast<int32_t>(scr.originx) + x);
uint32_t cy = static_cast<uint32_t>(static_cast<int32_t>(scr.originy) + y);
while(cx > scr.width && dw > 0) {
@ -245,6 +245,12 @@ void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& te
if(!dw || !dh)
continue; //Outside screen.
uint32_t rshift = (p.first == 16) ? (vdbl ? 2 : 1) : (vdbl ? 3 : 2);
uint32_t rishift = (p.first == 16) ? 4 : 3;
uint32_t xshift = hdbl ? 1 : 0;
uint32_t yshift = vdbl ? 1 : 0;
uint32_t b = dx & 1;
if(p.second == NULL) {
//Blank glyph.
for(uint32_t j = 0; j < dh; j++) {
@ -252,29 +258,24 @@ void render_text(struct screen& scr, int32_t x, int32_t y, const std::string& te
for(uint32_t i = 0; i < dw; i++)
bg.apply(base[i]);
}
} else if(p.first == 16) {
//Wide glyph.
} else {
for(uint32_t j = 0; j < dh; j++) {
uint32_t dataword = p.second[(dy + j) >> 1];
uint32_t dataword = p.second[(dy + j) >> rshift];
uint32_t* base = scr.rowptr(cy + j) + cx;
uint32_t rbit = (~((dy + j) << 4) & 0x1F) - dx;
uint32_t rbit = (~((dy + j) >> yshift << rishift) & 31) - (dx >> xshift);
if(hdbl) {
for(uint32_t i = 0; i < dw; i++)
if((dataword >> (rbit - ((i + b) >> 1))) & 1)
fg.apply(base[i]);
else
bg.apply(base[i]);
} else {
for(uint32_t i = 0; i < dw; i++)
if((dataword >> (rbit - i)) & 1)
fg.apply(base[i]);
else
bg.apply(base[i]);
}
} else {
//narrow glyph.
for(uint32_t j = 0; j < dh; j++) {
uint32_t dataword = p.second[(dy + j) >> 2];
uint32_t* base = scr.rowptr(cy + j) + cx;
uint32_t rbit = (~((dy + j) << 3) & 0x1F) - dx;
for(uint32_t i = 0; i < dw; i++)
if((dataword >> (rbit - i)) & 1)
fg.apply(base[i]);
else
bg.apply(base[i]);
}
}
x = next_x;

View file

@ -6,12 +6,12 @@ namespace
struct render_object_text : public render_object
{
render_object_text(int32_t _x, int32_t _y, const std::string& _text, premultiplied_color _fg,
premultiplied_color _bg) throw()
: x(_x), y(_y), text(_text), fg(_fg), bg(_bg) {}
premultiplied_color _bg, bool _hdbl = false, bool _vdbl = false) throw()
: x(_x), y(_y), text(_text), fg(_fg), bg(_bg), hdbl(_hdbl), vdbl(_vdbl) {}
~render_object_text() throw() {}
void operator()(struct screen& scr) throw()
{
render_text(scr, x, y, text, fg, bg);
render_text(scr, x, y, text, fg, bg, hdbl, vdbl);
}
private:
int32_t x;
@ -19,9 +19,12 @@ namespace
premultiplied_color fg;
premultiplied_color bg;
std::string text;
bool hdbl;
bool vdbl;
};
function_ptr_luafun gui_text("gui.text", [](lua_State* LS, const std::string& fname) -> int {
int internal_gui_text(lua_State* LS, const std::string& fname, bool hdbl, bool vdbl)
{
if(!lua_render_ctx)
return 0;
int64_t fgc = 0xFFFFFFU;
@ -33,7 +36,23 @@ namespace
std::string text = get_string_argument(LS, 3, fname.c_str());
premultiplied_color fg(fgc);
premultiplied_color bg(bgc);
lua_render_ctx->queue->add(*new render_object_text(_x, _y, text, fg, bg));
lua_render_ctx->queue->add(*new render_object_text(_x, _y, text, fg, bg, hdbl, vdbl));
return 0;
}
function_ptr_luafun gui_text("gui.text", [](lua_State* LS, const std::string& fname) -> int {
internal_gui_text(LS, fname, false, false);
});
function_ptr_luafun gui_textH("gui.textH", [](lua_State* LS, const std::string& fname) -> int {
internal_gui_text(LS, fname, true, false);
});
function_ptr_luafun gui_textV("gui.textV", [](lua_State* LS, const std::string& fname) -> int {
internal_gui_text(LS, fname, false, true);
});
function_ptr_luafun gui_textHV("gui.textHV", [](lua_State* LS, const std::string& fname) -> int {
internal_gui_text(LS, fname, true, true);
});
}