Clean up system font drawing

Refactor font reading to fewer places
This commit is contained in:
Ilari Liusvaara 2015-05-27 15:38:22 +03:00
parent 1dd19faaeb
commit c2a7eed9d8
6 changed files with 51 additions and 124 deletions

View file

@ -492,6 +492,16 @@ struct font
bool wide; //If set, 16 wide instead of 8.
uint32_t* data; //Glyph data. Bitpacked with element padding between rows.
size_t offset; //Glyph offset.
uint32_t get_width() const throw() { return wide ? 16 : 8; }
uint32_t get_height() const throw() { return 16; }
bool read_pixel(uint32_t x, uint32_t y) const throw()
{
if(wide) {
return ((data[y >> 1] >> (31 - (((y & 1) << 4) + x))) & 1) != 0;
} else {
return ((data[y >> 2] >> (31 - (((y & 3) << 3) + x))) & 1) != 0;
}
}
};
/**

View file

@ -53,12 +53,9 @@ namespace
{
while(rlist->scale) {
auto g = main_font.get_glyph(rlist->codepoint);
for(uint32_t j = 0; j < 16; j++) {
for(uint32_t i = 0; i < (g.wide ? 16 : 8); i++) {
uint32_t slice = g.data[j / (g.wide ? 2 : 4)];
uint32_t bit = 31 - ((j % (g.wide ? 2 : 4)) * (g.wide ? 16 : 8) + i);
uint32_t value = (slice >> bit) & 1;
if(value) {
for(uint32_t j = 0; j < g.get_height(); j++) {
for(uint32_t i = 0; i < g.get_width(); i++) {
if(g.read_pixel(i, j)) {
uint32_t basex = rlist->x + rlist->scale * i;
uint32_t basey = rlist->y + rlist->scale * j;
for(uint32_t j2 = 0; j2 < rlist->scale; j2++)

View file

@ -965,17 +965,11 @@ failed:
main_font.for_each_glyph(str, 0, false, false, [size, &fg, &bg, bmp](uint32_t ix, uint32_t iy,
const framebuffer::font::glyph& g, bool hdbl, bool vdbl) {
T* _bmp = bmp + (iy * size.first + ix);
size_t w = g.wide ? 16 : 8;
size_t w = g.get_width();
size_t skip = size.first - w;
for(size_t _y = 0; _y < 16; _y++) {
uint32_t d = g.data[_y >> (g.wide ? 1 : 2)];
if(g.wide)
d >>= 16 - ((_y & 1) << 4);
else
d >>= 24 - ((_y & 3) << 3);
for(size_t _x = 0; _x < w; _x++, _bmp++) {
uint32_t b = w - _x - 1;
*_bmp = ((d >> b) & 1) ? fg : bg;
for(size_t _y = 0; _y < g.get_height(); _y++) {
for(size_t _x = 0; _x < g.get_width(); _x++, _bmp++) {
*_bmp = g.read_pixel(_x, _y) ? fg : bg;
}
_bmp = _bmp + skip;
}

View file

@ -19,43 +19,20 @@ namespace
if(x >= w || y >= h)
return;
const framebuffer::font::glyph& g = main_font.get_glyph(ch);
unsigned maxw = min((size_t)(g.wide ? 16 : 8), (size_t)(w - x));
unsigned maxh = min((size_t)16, (size_t)(h - y));
unsigned maxw = min((size_t)g.get_width(), (size_t)(w - x));
unsigned maxh = min((size_t)g.get_height(), (size_t)(h - y));
unsigned char* cellbase = reinterpret_cast<unsigned char*>(fb) + y * istride + pstride * x;
if(g.wide) {
//Wide character.
for(size_t y2 = 0; y2 < maxh; y2++) {
uint32_t d = g.data[y2 >> 1];
d >>= 16 - ((y2 & 1) << 4);
for(size_t j = 0; j < maxw; j++) {
uint32_t b = 15 - j;
if(((d >> b) & 1) != 0) {
for(unsigned k = 0; k < pstride; k++)
cellbase[pstride * j + k] = _fg[k];
} else {
for(unsigned k = 0; k < pstride; k++)
cellbase[pstride * j + k] = _bg[k];
}
for(size_t y2 = 0; y2 < maxh; y2++) {
for(size_t j = 0; j < maxw; j++) {
if(g.read_pixel(j, y2)) {
for(unsigned k = 0; k < pstride; k++)
cellbase[pstride * j + k] = _fg[k];
} else {
for(unsigned k = 0; k < pstride; k++)
cellbase[pstride * j + k] = _bg[k];
}
cellbase += istride;
}
} else {
//Narrow character.
for(size_t y2 = 0; y2 < maxh; y2++) {
uint32_t d = g.data[y2 >> 2];
d >>= 24 - ((y2 & 3) << 3);
for(size_t j = 0; j < maxw; j++) {
uint32_t b = 7 - j;
if(((d >> b) & 1) != 0) {
for(unsigned k = 0; k < pstride; k++)
cellbase[pstride * j + k] = _fg[k];
} else {
for(unsigned k = 0; k < pstride; k++)
cellbase[pstride * j + k] = _bg[k];
}
}
cellbase += istride;
}
cellbase += istride;
}
}
}
@ -91,7 +68,7 @@ void cover_next_position(uint32_t ch, unsigned& x, unsigned& y)
y = y + 16;
} else {
const framebuffer::font::glyph& g = main_font.get_glyph(ch);
x = x + (g.wide ? 16 : 8);
x = x + g.get_width();
}
}

View file

@ -240,31 +240,25 @@ font2::font2(const std::string& file)
font2::font2(struct font& bfont)
{
auto s = bfont.get_glyphs_set();
rowadvance = 0;
for(auto i = s.begin();;i++) {
const font::glyph& j = (i != s.end()) ? bfont.get_glyph(*i) : bfont.get_bad_glyph();
glyph k;
k.width = j.wide ? 16 : 8;
k.height = 16;
k.width = j.get_width();
k.height = j.get_height();
k.stride = 1;
k.fglyph.resize(16);
for(size_t y = 0; y < 16; y++) {
k.fglyph[y] = 0;
uint32_t r = j.data[y / (j.wide ? 2 : 4)];
if(j.wide)
r >>= 16 - ((y & 1) << 4);
else
r >>= 24 - ((y & 3) << 3);
for(size_t y = 0; y < k.height; y++) {
for(size_t x = 0; x < k.width; x++) {
uint32_t b = (j.wide ? 15 : 7) - x;
if(((r >> b) & 1) != 0)
if(j.read_pixel(x, y))
k.fglyph[y] |= 1UL << (31 - x);
}
}
rowadvance = std::max((size_t)rowadvance, (size_t)j.get_height());
std::u32string key = (i != s.end()) ? std::u32string(1, *i) : std::u32string();
glyphs[key] = k;
if(i == s.end()) break;
}
rowadvance = 16;
}
std::ostream& operator<<(std::ostream& os, const std::u32string& lkey)

View file

@ -50,7 +50,6 @@ std::pair<size_t, size_t> text_framebuffer::get_pixels()
void text_framebuffer::render(char* tbuffer)
{
uint32_t dummy[8] = {0};
size_t stride = 24 * width;
size_t cellstride = 24;
for(size_t y = 0; y < height; y++) {
@ -67,68 +66,24 @@ void text_framebuffer::render(char* tbuffer)
char fgb = (e.fg >> 16);
char fgg = (e.fg >> 8);
char fgr = (e.fg >> 0);
const uint32_t* data = (g.data ? g.data : dummy);
if(g.wide && xp < width - 1) {
//Wide character, can draw full width.
for(size_t y2 = 0; y2 < 16; y2++) {
uint32_t d = data[y2 >> 1];
d >>= 16 - ((y2 & 1) << 4);
for(size_t j = 0; j < 16; j++) {
uint32_t b = 15 - j;
if(((d >> b) & 1) != 0) {
cellbase[3 * j + 0] = fgr;
cellbase[3 * j + 1] = fgg;
cellbase[3 * j + 2] = fgb;
} else {
cellbase[3 * j + 0] = bgr;
cellbase[3 * j + 1] = bgg;
cellbase[3 * j + 2] = bgb;
}
uint32_t cells = g.get_width() / 8;
uint32_t drawc = 8 * std::min(cells, (uint32_t)((xp < width - 1) ? 2 : 1));
for(size_t y2 = 0; y2 < g.get_height(); y2++) {
for(size_t j = 0; j < drawc; j++) {
if(g.read_pixel(j, y2)) {
cellbase[3 * j + 0] = fgr;
cellbase[3 * j + 1] = fgg;
cellbase[3 * j + 2] = fgb;
} else {
cellbase[3 * j + 0] = bgr;
cellbase[3 * j + 1] = bgg;
cellbase[3 * j + 2] = bgb;
}
cellbase += stride;
}
xp += 2;
} else if(g.wide) {
//Wide character, can only draw half.
for(size_t y2 = 0; y2 < 16; y2++) {
uint32_t d = data[y2 >> 1];
d >>= 16 - ((y2 & 1) << 4);
for(size_t j = 0; j < 8; j++) {
uint32_t b = 15 - j;
if(((d >> b) & 1) != 0) {
cellbase[3 * j + 0] = fgr;
cellbase[3 * j + 1] = fgg;
cellbase[3 * j + 2] = fgb;
} else {
cellbase[3 * j + 0] = bgr;
cellbase[3 * j + 1] = bgg;
cellbase[3 * j + 2] = bgb;
}
}
cellbase += stride;
}
xp += 2;
} else {
//Narrow character.
for(size_t y2 = 0; y2 < 16; y2++) {
uint32_t d = data[y2 >> 2];
d >>= 24 - ((y2 & 3) << 3);
for(size_t j = 0; j < 8; j++) {
uint32_t b = 7 - j;
if(((d >> b) & 1) != 0) {
cellbase[3 * j + 0] = fgr;
cellbase[3 * j + 1] = fgg;
cellbase[3 * j + 2] = fgb;
} else {
cellbase[3 * j + 0] = bgr;
cellbase[3 * j + 1] = bgg;
cellbase[3 * j + 2] = bgb;
}
}
cellbase += stride;
}
xp += 1;
cellbase += stride;
}
xp += cells;
}
}
}
@ -170,7 +125,7 @@ size_t text_framebuffer::write(const std::u32string& str, size_t w, size_t x, si
e.fg = fg;
e.bg = bg;
}
pused += (g.wide ? 2 : 1);
pused += g.get_width() / 8;
}
while(pused < w) {
//Pad with spaces.