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). * 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, 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. * 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 _text: The text to render (UTF-8).
* parameter _fg: Foreground color. * parameter _fg: Foreground color.
* parameter _bg: Background 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. * 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, 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 #endif

View file

@ -136,7 +136,7 @@ skip_line:
return font_glyph_offsets.count(cp) ? font_glyph_offsets[cp] : 0; 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; uint32_t dwidth;
switch(tag & TAG_WIDTH_MASK) { switch(tag & TAG_WIDTH_MASK) {
@ -153,9 +153,9 @@ skip_line:
dwidth = 0x40 - (x & 0x3F); dwidth = 0x40 - (x & 0x3F);
break; break;
} }
x += dwidth; x += dwidth * (hdbl ? 2 : 1);
if(tag & TAG_LINECHANGE) { if(tag & TAG_LINECHANGE) {
y += 16; y += 16 * (vdbl ? 2 : 1);
x = orig_x; x = orig_x;
} }
return dwidth; 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, 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(); init_font();
next_x = x; next_x = x;
next_y = y; next_y = y;
uint32_t offset = find_font_glyph_offset(codepoint); uint32_t offset = find_font_glyph_offset(codepoint);
uint32_t tag = font_glyph_data[offset]; 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); bool visible = is_visible(tag);
return std::pair<uint32_t, const uint32_t*>(dwidth, visible ? &font_glyph_data[offset + 1] : NULL); 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, 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; int32_t orig_x = x;
uint32_t unicode_code = 0; 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 } else
continue; continue;
int32_t next_x, next_y; 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 dx = 0;
uint32_t dw = p.first; uint32_t dw = p.first * (hdbl ? 2 : 1);
uint32_t dy = 0; 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 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); uint32_t cy = static_cast<uint32_t>(static_cast<int32_t>(scr.originy) + y);
while(cx > scr.width && dw > 0) { 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) if(!dw || !dh)
continue; //Outside screen. 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) { if(p.second == NULL) {
//Blank glyph. //Blank glyph.
for(uint32_t j = 0; j < dh; j++) { 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++) for(uint32_t i = 0; i < dw; i++)
bg.apply(base[i]); bg.apply(base[i]);
} }
} else if(p.first == 16) {
//Wide glyph.
for(uint32_t j = 0; j < dh; j++) {
uint32_t dataword = p.second[(dy + j) >> 1];
uint32_t* base = scr.rowptr(cy + j) + cx;
uint32_t rbit = (~((dy + j) << 4) & 0x1F) - dx;
for(uint32_t i = 0; i < dw; i++)
if((dataword >> (rbit - i)) & 1)
fg.apply(base[i]);
else
bg.apply(base[i]);
}
} else { } else {
//narrow glyph.
for(uint32_t j = 0; j < dh; j++) { for(uint32_t j = 0; j < dh; j++) {
uint32_t dataword = p.second[(dy + j) >> 2]; uint32_t dataword = p.second[(dy + j) >> rshift];
uint32_t* base = scr.rowptr(cy + j) + cx; uint32_t* base = scr.rowptr(cy + j) + cx;
uint32_t rbit = (~((dy + j) << 3) & 0x1F) - dx; uint32_t rbit = (~((dy + j) >> yshift << rishift) & 31) - (dx >> xshift);
for(uint32_t i = 0; i < dw; i++) if(hdbl) {
if((dataword >> (rbit - i)) & 1) for(uint32_t i = 0; i < dw; i++)
fg.apply(base[i]); if((dataword >> (rbit - ((i + b) >> 1))) & 1)
else fg.apply(base[i]);
bg.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]);
}
} }
} }
x = next_x; x = next_x;

View file

@ -6,12 +6,12 @@ namespace
struct render_object_text : public render_object struct render_object_text : public render_object
{ {
render_object_text(int32_t _x, int32_t _y, const std::string& _text, premultiplied_color _fg, render_object_text(int32_t _x, int32_t _y, const std::string& _text, premultiplied_color _fg,
premultiplied_color _bg) throw() premultiplied_color _bg, bool _hdbl = false, bool _vdbl = false) throw()
: x(_x), y(_y), text(_text), fg(_fg), bg(_bg) {} : x(_x), y(_y), text(_text), fg(_fg), bg(_bg), hdbl(_hdbl), vdbl(_vdbl) {}
~render_object_text() throw() {} ~render_object_text() throw() {}
void operator()(struct screen& scr) 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: private:
int32_t x; int32_t x;
@ -19,9 +19,12 @@ namespace
premultiplied_color fg; premultiplied_color fg;
premultiplied_color bg; premultiplied_color bg;
std::string text; 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) if(!lua_render_ctx)
return 0; return 0;
int64_t fgc = 0xFFFFFFU; int64_t fgc = 0xFFFFFFU;
@ -33,7 +36,23 @@ namespace
std::string text = get_string_argument(LS, 3, fname.c_str()); std::string text = get_string_argument(LS, 3, fname.c_str());
premultiplied_color fg(fgc); premultiplied_color fg(fgc);
premultiplied_color bg(bgc); 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; 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);
}); });
} }