text: add render-support for multi-cell glyphs
Multi-cell glyphs are glyphs that span across multiple horizontal cells. The font renderers already support this. This patch fixes the console renderers to take advantage of this. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
1 parent
0de1de25fd
commit
1657bb9a3a
8 files changed
+48
-18
No files matched your search
+5
-2
@@ -447,6 +447,7 @@ int kmscon_text_prepare(struct kmscon_text *txt)
|
||||
* @id: a unique ID that identifies @ch globally
|
||||
* @ch: ucs4 symbol you want to draw
|
||||
* @len: length of @ch or 0 for empty cell
|
||||
* @width: cell-width of character
|
||||
* @posx: X-position of the glyph
|
||||
* @posy: Y-position of the glyph
|
||||
* @attr: glyph attributes
|
||||
@@ -460,6 +461,7 @@ int kmscon_text_prepare(struct kmscon_text *txt)
|
||||
*/
|
||||
int kmscon_text_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr)
|
||||
{
|
||||
@@ -468,7 +470,7 @@ int kmscon_text_draw(struct kmscon_text *txt,
|
||||
if (posx >= txt->cols || posy >= txt->rows || !attr)
|
||||
return -EINVAL;
|
||||
|
||||
return txt->ops->draw(txt, id, ch, len, posx, posy, attr);
|
||||
return txt->ops->draw(txt, id, ch, len, width, posx, posy, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -521,10 +523,11 @@ int kmscon_text_prepare_cb(struct tsm_screen *con, void *data)
|
||||
|
||||
int kmscon_text_draw_cb(struct tsm_screen *con,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr, void *data)
|
||||
{
|
||||
return kmscon_text_draw(data, id, ch, len, posx, posy, attr);
|
||||
return kmscon_text_draw(data, id, ch, len, width, posx, posy, attr);
|
||||
}
|
||||
|
||||
int kmscon_text_render_cb(struct tsm_screen *con, void *data)
|
||||
|
||||
@@ -140,6 +140,7 @@ struct kmscon_text_ops {
|
||||
int (*prepare) (struct kmscon_text *txt);
|
||||
int (*draw) (struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr);
|
||||
int (*render) (struct kmscon_text *txt);
|
||||
@@ -164,6 +165,7 @@ unsigned int kmscon_text_get_rows(struct kmscon_text *txt);
|
||||
int kmscon_text_prepare(struct kmscon_text *txt);
|
||||
int kmscon_text_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr);
|
||||
int kmscon_text_render(struct kmscon_text *txt);
|
||||
@@ -172,6 +174,7 @@ void kmscon_text_abort(struct kmscon_text *txt);
|
||||
int kmscon_text_prepare_cb(struct tsm_screen *con, void *data);
|
||||
int kmscon_text_draw_cb(struct tsm_screen *con,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr, void *data);
|
||||
int kmscon_text_render_cb(struct tsm_screen *con, void *data);
|
||||
|
||||
@@ -63,6 +63,7 @@ static int bblit_set(struct kmscon_text *txt)
|
||||
|
||||
static int bblit_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr)
|
||||
{
|
||||
@@ -70,6 +71,9 @@ static int bblit_draw(struct kmscon_text *txt,
|
||||
int ret;
|
||||
struct kmscon_font *font;
|
||||
|
||||
if (!width)
|
||||
return 0;
|
||||
|
||||
if (attr->bold)
|
||||
font = txt->bold_font;
|
||||
else
|
||||
|
||||
@@ -112,6 +112,7 @@ static void bbulk_unset(struct kmscon_text *txt)
|
||||
|
||||
static int bbulk_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr)
|
||||
{
|
||||
@@ -121,6 +122,11 @@ static int bbulk_draw(struct kmscon_text *txt,
|
||||
struct uterm_video_blend_req *req;
|
||||
struct kmscon_font *font;
|
||||
|
||||
if (!width) {
|
||||
bb->reqs[posy * txt->cols + posx].buf = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (attr->bold)
|
||||
font = txt->bold_font;
|
||||
else
|
||||
|
||||
+19
-13
@@ -277,7 +277,7 @@ static unsigned int next_pow2(unsigned int num)
|
||||
}
|
||||
|
||||
/* returns an atlas with at least 1 free glyph position; NULL on error */
|
||||
static struct atlas *get_atlas(struct kmscon_text *txt)
|
||||
static struct atlas *get_atlas(struct kmscon_text *txt, unsigned int num)
|
||||
{
|
||||
struct gltex *gt = txt->data;
|
||||
struct atlas *atlas;
|
||||
@@ -289,7 +289,7 @@ static struct atlas *get_atlas(struct kmscon_text *txt)
|
||||
if (!shl_dlist_empty(>->atlases)) {
|
||||
atlas = shl_dlist_entry(gt->atlases.next, struct atlas,
|
||||
list);
|
||||
if (atlas->fill < atlas->count)
|
||||
if (atlas->fill + num <= atlas->count)
|
||||
return atlas;
|
||||
}
|
||||
|
||||
@@ -408,10 +408,6 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
atlas = get_atlas(txt);
|
||||
if (!atlas)
|
||||
return -EFAULT;
|
||||
|
||||
glyph = malloc(sizeof(*glyph));
|
||||
if (!glyph)
|
||||
return -ENOMEM;
|
||||
@@ -428,6 +424,12 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
atlas = get_atlas(txt, glyph->glyph->width);
|
||||
if (!atlas) {
|
||||
ret = -EFAULT;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* Funnily, not all OpenGLESv2 implementations support specifying the
|
||||
* stride of a texture. Therefore, we then need to create a
|
||||
* temporary image with a stride equal to the image width for loading
|
||||
@@ -507,7 +509,7 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out,
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
++atlas->fill;
|
||||
atlas->fill += glyph->glyph->width;
|
||||
|
||||
*out = glyph;
|
||||
return 0;
|
||||
@@ -542,6 +544,7 @@ static int gltex_prepare(struct kmscon_text *txt)
|
||||
|
||||
static int gltex_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr)
|
||||
{
|
||||
@@ -550,6 +553,9 @@ static int gltex_draw(struct kmscon_text *txt,
|
||||
struct glyph *glyph;
|
||||
int ret, i, idx;
|
||||
|
||||
if (!width)
|
||||
return 0;
|
||||
|
||||
ret = find_glyph(txt, &glyph, id, ch, len, attr->bold);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -567,7 +573,7 @@ static int gltex_draw(struct kmscon_text *txt,
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 3] =
|
||||
gt->advance_y * posy + gt->advance_y - 1;
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 4] =
|
||||
gt->advance_x * posx + gt->advance_x - 1;
|
||||
gt->advance_x * posx + width * gt->advance_x - 1;
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 5] =
|
||||
gt->advance_y * posy + gt->advance_y - 1;
|
||||
|
||||
@@ -576,11 +582,11 @@ static int gltex_draw(struct kmscon_text *txt,
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 7] =
|
||||
gt->advance_y * posy - 1;
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 8] =
|
||||
gt->advance_x * posx + gt->advance_x - 1;
|
||||
gt->advance_x * posx + width * gt->advance_x - 1;
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 9] =
|
||||
gt->advance_y * posy + gt->advance_y - 1;
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 10] =
|
||||
gt->advance_x * posx + gt->advance_x - 1;
|
||||
gt->advance_x * posx + width * gt->advance_x - 1;
|
||||
atlas->cache_pos[atlas->cache_num * 2 * 6 + 11] =
|
||||
gt->advance_y * posy - 1;
|
||||
|
||||
@@ -588,14 +594,14 @@ static int gltex_draw(struct kmscon_text *txt,
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 1] = 0.0;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 2] = glyph->texoff;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 3] = 1.0;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 4] = glyph->texoff + 1;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 4] = glyph->texoff + width;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 5] = 1.0;
|
||||
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 6] = glyph->texoff;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 7] = 0.0;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 8] = glyph->texoff + 1;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 8] = glyph->texoff + width;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 9] = 1.0;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 10] = glyph->texoff + 1;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 10] = glyph->texoff + width;
|
||||
atlas->cache_texpos[atlas->cache_num * 2 * 6 + 11] = 0.0;
|
||||
|
||||
for (i = 0; i < 6; ++i) {
|
||||
|
||||
+6
-3
@@ -45,6 +45,7 @@
|
||||
|
||||
struct cell {
|
||||
tsm_symbol_t ch;
|
||||
unsigned int width;
|
||||
struct tsm_screen_attr attr;
|
||||
};
|
||||
|
||||
@@ -108,6 +109,7 @@ struct tsm_screen {
|
||||
static void cell_init(struct tsm_screen *con, struct cell *cell)
|
||||
{
|
||||
cell->ch = 0;
|
||||
cell->width = 1;
|
||||
memcpy(&cell->attr, &con->def_attr, sizeof(cell->attr));
|
||||
}
|
||||
|
||||
@@ -1843,8 +1845,8 @@ void tsm_screen_draw(struct tsm_screen *con,
|
||||
ch = tsm_symbol_get(NULL, &cell->ch, &len);
|
||||
if (cell->ch == ' ' || cell->ch == 0)
|
||||
len = 0;
|
||||
ret = draw_cb(con, cell->ch, ch, len, j, i, &attr,
|
||||
data);
|
||||
ret = draw_cb(con, cell->ch, ch, len, cell->width,
|
||||
j, i, &attr, data);
|
||||
if (ret && warned++ < 3) {
|
||||
llog_debug(con,
|
||||
"cannot draw glyph at %ux%u via text-renderer",
|
||||
@@ -1860,7 +1862,8 @@ void tsm_screen_draw(struct tsm_screen *con,
|
||||
if (!(con->flags & TSM_SCREEN_HIDE_CURSOR)) {
|
||||
if (!(con->flags & TSM_SCREEN_INVERSE))
|
||||
attr.inverse = !attr.inverse;
|
||||
draw_cb(con, 0, NULL, 0, cur_x, i, &attr, data);
|
||||
draw_cb(con, 0, NULL, 0, 1,
|
||||
cur_x, i, &attr, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ typedef int (*tsm_screen_draw_cb) (struct tsm_screen *con,
|
||||
uint32_t id,
|
||||
const uint32_t *ch,
|
||||
size_t len,
|
||||
unsigned int width,
|
||||
unsigned int posx,
|
||||
unsigned int posy,
|
||||
const struct tsm_screen_attr *attr,
|
||||
|
||||
@@ -88,6 +88,7 @@ struct wlt_terminal {
|
||||
|
||||
static int draw_cell(struct tsm_screen *scr,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
unsigned int chwidth,
|
||||
unsigned int posx, unsigned int posy,
|
||||
const struct tsm_screen_attr *attr, void *data)
|
||||
{
|
||||
@@ -100,6 +101,9 @@ static int draw_cell(struct tsm_screen *scr,
|
||||
unsigned int fr, fg, fb, br, bg, bb;
|
||||
uint32_t val;
|
||||
|
||||
if (!chwidth)
|
||||
return 0;
|
||||
|
||||
if (!len)
|
||||
ret = kmscon_font_render_empty(term->font_normal, &glyph);
|
||||
else
|
||||
|
||||
Reference in new issue
Block a user