diff --git a/src/text.c b/src/text.c index 8000dbd..d14ce2f 100644 --- a/src/text.c +++ b/src/text.c @@ -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) diff --git a/src/text.h b/src/text.h index 33fb269..214cd11 100644 --- a/src/text.h +++ b/src/text.h @@ -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); diff --git a/src/text_bblit.c b/src/text_bblit.c index a95ce83..d10be98 100644 --- a/src/text_bblit.c +++ b/src/text_bblit.c @@ -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 diff --git a/src/text_bbulk.c b/src/text_bbulk.c index 6684ab6..d733803 100644 --- a/src/text_bbulk.c +++ b/src/text_bbulk.c @@ -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 diff --git a/src/text_gltex.c b/src/text_gltex.c index 74a36f0..b1b1efe 100644 --- a/src/text_gltex.c +++ b/src/text_gltex.c @@ -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) { diff --git a/src/tsm_screen.c b/src/tsm_screen.c index e8005eb..c7d259b 100644 --- a/src/tsm_screen.c +++ b/src/tsm_screen.c @@ -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); } } } diff --git a/src/tsm_screen.h b/src/tsm_screen.h index e294630..8f0ec4c 100644 --- a/src/tsm_screen.h +++ b/src/tsm_screen.h @@ -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, diff --git a/src/wlt_terminal.c b/src/wlt_terminal.c index 0353a89..380e814 100644 --- a/src/wlt_terminal.c +++ b/src/wlt_terminal.c @@ -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