From f2c1dd77ffc0ea6026964523df71438f2ff500e4 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 18 Sep 2012 13:42:22 +0200 Subject: [PATCH] text: pass symbol-data directly into text layer Instead of converting symbols into UCS4 string in each backend, we now pass the whole data from the console layer into the renderers. This makes all renderers indepedent of any recently introduced symbol-tables and they can be implemented inside of TSM without exporting them. However, we still need to pass the IDs to the text layer. The text layer must not use them for anything but identification. Moreover, it must never assume that they are valid tsm_symbol_t values. We do this so the backends can still have fast hashtable lookups rather than allocating big keys containing the UCS4 string+length and using these for lookups. Signed-off-by: David Herrmann --- src/console.c | 10 ++++++++-- src/console.h | 4 +++- src/text.c | 18 +++++++++++------- src/text.h | 20 ++++++++++++-------- src/text_bblit.c | 8 ++++---- src/text_bbulk.c | 8 ++++---- src/text_font.c | 11 +++++++---- src/text_font_8x16.c | 12 +++--------- src/text_font_freetype2.c | 30 +++++++++++++----------------- src/text_font_pango.c | 33 ++++++++++++++++++++------------- src/text_font_unifont.c | 14 ++++---------- src/text_gltex.c | 16 ++++++++-------- 12 files changed, 97 insertions(+), 87 deletions(-) diff --git a/src/console.c b/src/console.c index 58e3588..5501775 100644 --- a/src/console.c +++ b/src/console.c @@ -1255,6 +1255,8 @@ void kmscon_console_draw(struct kmscon_console *con, bool cursor_done = false; int ret, warned = 0; uint64_t time_prep = 0, time_draw = 0, time_rend = 0; + const uint32_t *ch; + size_t len; if (!con || !draw_cb) return; @@ -1318,7 +1320,11 @@ void kmscon_console_draw(struct kmscon_console *con, if (con->flags & KMSCON_CONSOLE_INVERSE) attr.inverse = !attr.inverse; - ret = draw_cb(con, cell->ch, j, i, &attr, data); + 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); if (ret && warned++ < 3) { log_debug("cannot draw glyph at %ux%u via text-renderer", j, i); @@ -1332,7 +1338,7 @@ void kmscon_console_draw(struct kmscon_console *con, if (!(con->flags & KMSCON_CONSOLE_HIDE_CURSOR)) { if (!(con->flags & KMSCON_CONSOLE_INVERSE)) attr.inverse = !attr.inverse; - draw_cb(con, 0, cur_x, i, &attr, data); + draw_cb(con, 0, NULL, 0, cur_x, i, &attr, data); } } } diff --git a/src/console.h b/src/console.h index 2bc590c..b49c590 100644 --- a/src/console.h +++ b/src/console.h @@ -68,7 +68,9 @@ struct kmscon_console_attr { typedef int (*kmscon_console_prepare_cb) (struct kmscon_console *con, void *data); typedef int (*kmscon_console_draw_cb) (struct kmscon_console *con, - tsm_symbol_t ch, + uint32_t id, + const uint32_t *ch, + size_t len, unsigned int posx, unsigned int posy, const struct kmscon_console_attr *attr, diff --git a/src/text.c b/src/text.c index fa1c301..f39d255 100644 --- a/src/text.c +++ b/src/text.c @@ -431,7 +431,9 @@ int kmscon_text_prepare(struct kmscon_text *txt) /** * kmscon_text_draw: * @txt: valid text renderer - * @ch: symbol you want to draw + * @id: a unique ID that identifies @ch globally + * @ch: ucs4 symbol you want to draw + * @len: length of @ch or 0 for empty cell * @posx: X-position of the glyph * @posy: Y-position of the glyph * @attr: glyph attributes @@ -443,16 +445,17 @@ int kmscon_text_prepare(struct kmscon_text *txt) * * Returns: 0 on success or negative error code if this glyph couldn't be drawn. */ -int kmscon_text_draw(struct kmscon_text *txt, tsm_symbol_t ch, - unsigned int posx, unsigned int posy, - const struct kmscon_console_attr *attr) +int kmscon_text_draw(struct kmscon_text *txt, + uint32_t id, const uint32_t *ch, size_t len, + unsigned int posx, unsigned int posy, + const struct kmscon_console_attr *attr) { if (!txt || !txt->rendering) return -EINVAL; if (posx >= txt->cols || posy >= txt->rows || !attr) return -EINVAL; - return txt->ops->draw(txt, ch, posx, posy, attr); + return txt->ops->draw(txt, id, ch, len, posx, posy, attr); } /** @@ -503,11 +506,12 @@ int kmscon_text_prepare_cb(struct kmscon_console *con, void *data) return kmscon_text_prepare(data); } -int kmscon_text_draw_cb(struct kmscon_console *con, tsm_symbol_t ch, +int kmscon_text_draw_cb(struct kmscon_console *con, + uint32_t id, const uint32_t *ch, size_t len, unsigned int posx, unsigned int posy, const struct kmscon_console_attr *attr, void *data) { - return kmscon_text_draw(data, ch, posx, posy, attr); + return kmscon_text_draw(data, id, ch, len, posx, posy, attr); } int kmscon_text_render_cb(struct kmscon_console *con, void *data) diff --git a/src/text.h b/src/text.h index bb6f61d..6a3ca74 100644 --- a/src/text.h +++ b/src/text.h @@ -41,7 +41,6 @@ #include #include #include "console.h" -#include "tsm_unicode.h" #include "uterm.h" /* fonts */ @@ -87,7 +86,8 @@ struct kmscon_font_ops { int (*init) (struct kmscon_font *out, const struct kmscon_font_attr *attr); void (*destroy) (struct kmscon_font *font); - int (*render) (struct kmscon_font *font, tsm_symbol_t sym, + int (*render) (struct kmscon_font *font, + uint32_t id, const uint32_t *ch, size_t len, const struct kmscon_glyph **out); int (*render_empty) (struct kmscon_font *font, const struct kmscon_glyph **out); @@ -104,7 +104,8 @@ int kmscon_font_find(struct kmscon_font **out, void kmscon_font_ref(struct kmscon_font *font); void kmscon_font_unref(struct kmscon_font *font); -int kmscon_font_render(struct kmscon_font *font, tsm_symbol_t sym, +int kmscon_font_render(struct kmscon_font *font, + uint32_t id, const uint32_t *ch, size_t len, const struct kmscon_glyph **out); int kmscon_font_render_empty(struct kmscon_font *font, const struct kmscon_glyph **out); @@ -135,7 +136,8 @@ struct kmscon_text_ops { int (*set) (struct kmscon_text *txt); void (*unset) (struct kmscon_text *txt); int (*prepare) (struct kmscon_text *txt); - int (*draw) (struct kmscon_text *txt, tsm_symbol_t ch, + int (*draw) (struct kmscon_text *txt, + uint32_t id, const uint32_t *ch, size_t len, unsigned int posx, unsigned int posy, const struct kmscon_console_attr *attr); int (*render) (struct kmscon_text *txt); @@ -157,14 +159,16 @@ unsigned int kmscon_text_get_cols(struct kmscon_text *txt); 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, tsm_symbol_t ch, - unsigned int posx, unsigned int posy, - const struct kmscon_console_attr *attr); +int kmscon_text_draw(struct kmscon_text *txt, + uint32_t id, const uint32_t *ch, size_t len, + unsigned int posx, unsigned int posy, + const struct kmscon_console_attr *attr); int kmscon_text_render(struct kmscon_text *txt); void kmscon_text_abort(struct kmscon_text *txt); int kmscon_text_prepare_cb(struct kmscon_console *con, void *data); -int kmscon_text_draw_cb(struct kmscon_console *con, tsm_symbol_t ch, +int kmscon_text_draw_cb(struct kmscon_console *con, + uint32_t id, const uint32_t *ch, size_t len, unsigned int posx, unsigned int posy, const struct kmscon_console_attr *attr, void *data); int kmscon_text_render_cb(struct kmscon_console *con, void *data); diff --git a/src/text_bblit.c b/src/text_bblit.c index 1a7a446..af5ee5b 100644 --- a/src/text_bblit.c +++ b/src/text_bblit.c @@ -38,7 +38,6 @@ #include #include "log.h" #include "text.h" -#include "tsm_unicode.h" #include "uterm.h" #define LOG_SUBSYSTEM "text_bblit" @@ -58,17 +57,18 @@ static int bblit_set(struct kmscon_text *txt) return 0; } -static int bblit_draw(struct kmscon_text *txt, tsm_symbol_t ch, +static int bblit_draw(struct kmscon_text *txt, + uint32_t id, const uint32_t *ch, size_t len, unsigned int posx, unsigned int posy, const struct kmscon_console_attr *attr) { const struct kmscon_glyph *glyph; int ret; - if (ch == 0 || ch == ' ') { + if (!len) { ret = kmscon_font_render_empty(txt->font, &glyph); } else { - ret = kmscon_font_render(txt->font, ch, &glyph); + ret = kmscon_font_render(txt->font, id, ch, len, &glyph); } if (ret) { diff --git a/src/text_bbulk.c b/src/text_bbulk.c index abb3d81..b6a42b5 100644 --- a/src/text_bbulk.c +++ b/src/text_bbulk.c @@ -38,7 +38,6 @@ #include #include "log.h" #include "text.h" -#include "tsm_unicode.h" #include "uterm.h" #define LOG_SUBSYSTEM "text_bbulk" @@ -110,7 +109,8 @@ static void bbulk_unset(struct kmscon_text *txt) bb->reqs = NULL; } -static int bbulk_draw(struct kmscon_text *txt, tsm_symbol_t ch, +static int bbulk_draw(struct kmscon_text *txt, + uint32_t id, const uint32_t *ch, size_t len, unsigned int posx, unsigned int posy, const struct kmscon_console_attr *attr) { @@ -119,10 +119,10 @@ static int bbulk_draw(struct kmscon_text *txt, tsm_symbol_t ch, int ret; struct uterm_video_blend_req *req; - if (ch == 0 || ch == ' ') { + if (!len) { ret = kmscon_font_render_empty(txt->font, &glyph); } else { - ret = kmscon_font_render(txt->font, ch, &glyph); + ret = kmscon_font_render(txt->font, id, ch, len, &glyph); } if (ret) { diff --git a/src/text_font.c b/src/text_font.c index bff6ee3..72c2295 100644 --- a/src/text_font.c +++ b/src/text_font.c @@ -449,7 +449,9 @@ void kmscon_font_unref(struct kmscon_font *font) /** * kmscon_font_render: * @font: Valid font object - * @sym: Symbol to find a glyph for + * @id: Unique ID that identifies @ch globally + * @ch: Symbol to find a glyph for + * @len: Length of @ch * @out: Output buffer for glyph * * Renders the glyph for symbol @sym and places a pointer to the glyph in @out. @@ -460,13 +462,14 @@ void kmscon_font_unref(struct kmscon_font *font) * * Returns: 0 on success, negative error code on failure */ -int kmscon_font_render(struct kmscon_font *font, tsm_symbol_t sym, +int kmscon_font_render(struct kmscon_font *font, + uint32_t id, const uint32_t *ch, size_t len, const struct kmscon_glyph **out) { - if (!font || !out) + if (!font || !out || !ch || !len) return -EINVAL; - return font->ops->render(font, sym, out); + return font->ops->render(font, id, ch, len, out); } /** diff --git a/src/text_font_8x16.c b/src/text_font_8x16.c index 78eac77..b419cfc 100644 --- a/src/text_font_8x16.c +++ b/src/text_font_8x16.c @@ -49,7 +49,6 @@ #include #include "log.h" #include "text.h" -#include "tsm_unicode.h" #include "uterm.h" #define LOG_SUBSYSTEM "text_font_8x16" @@ -82,18 +81,13 @@ static void kmscon_font_8x16_destroy(struct kmscon_font *font) } static int kmscon_font_8x16_render(struct kmscon_font *font, - tsm_symbol_t sym, + uint32_t id, const uint32_t *ch, size_t len, const struct kmscon_glyph **out) { - const uint32_t *val; - size_t len; - - val = tsm_symbol_get(NULL, &sym, &len); - if (len > 1 || *val >= 256) + if (len > 1 || *ch >= 256) return -ERANGE; - *out = &kmscon_font_8x16_glyphs[*val]; - + *out = &kmscon_font_8x16_glyphs[*ch]; return 0; } diff --git a/src/text_font_freetype2.c b/src/text_font_freetype2.c index b22aaf0..8ab749a 100644 --- a/src/text_font_freetype2.c +++ b/src/text_font_freetype2.c @@ -48,7 +48,6 @@ #include "shl_dlist.h" #include "shl_hashtable.h" #include "text.h" -#include "tsm_unicode.h" #include "uterm.h" #define LOG_SUBSYSTEM "text_font_freetype2" @@ -139,7 +138,7 @@ static void manager__unref() } static int get_glyph(struct face *face, struct kmscon_glyph **out, - tsm_symbol_t ch) + uint32_t id, const uint32_t *ch, size_t len) { struct kmscon_glyph *glyph; struct glyph *data; @@ -147,15 +146,13 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, FT_UInt idx; FT_Bitmap *bmap; FT_GlyphSlot slot; - size_t len; - const uint32_t *val; bool res; unsigned int i, j, wmax, hmax, idx1, idx2; int ret, hoff1, hoff2, woff1, woff2; pthread_mutex_lock(&face->glyph_lock); res = shl_hashtable_find(face->glyphs, (void**)&glyph, - (void*)(long)ch); + (void*)(long)id); pthread_mutex_unlock(&face->glyph_lock); if (res) { *out = glyph; @@ -181,13 +178,12 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, * TODO: Fix this by drawing all related characters into a single glyph * and saving it or simply refer to the pango backend which already does * that. */ - val = tsm_symbol_get(NULL, &ch, &len); - if (len > 1 || !*val) { + if (!*ch) { ret = -ERANGE; goto out_glyph; } - idx = FT_Get_Char_Index(face->face, *val); + idx = FT_Get_Char_Index(face->face, *ch); err = FT_Load_Glyph(face->face, idx, FT_LOAD_DEFAULT); if (err) { ret = -ERANGE; @@ -269,7 +265,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, } pthread_mutex_lock(&face->glyph_lock); - ret = shl_hashtable_insert(face->glyphs, (void*)(long)ch, glyph); + ret = shl_hashtable_insert(face->glyphs, (void*)(long)id, glyph); pthread_mutex_unlock(&face->glyph_lock); if (ret) { log_error("cannot add glyph to hashtable"); @@ -537,6 +533,7 @@ static int generate_specials(struct face *face) size_t s; struct kmscon_glyph *g; int ret; + static const uint32_t question_mark = '?'; face->empty.data = NULL; face->empty.buf.width = face->real_attr.width; @@ -550,7 +547,7 @@ static int generate_specials(struct face *face) memset(face->empty.buf.data, 0, s); - ret = get_glyph(face, &g, tsm_symbol_make('?')); + ret = get_glyph(face, &g, question_mark, &question_mark, 1); if (ret) { memcpy(&face->inval, &face->empty, sizeof(face->inval)); } else { @@ -565,8 +562,8 @@ static int kmscon_font_freetype2_init(struct kmscon_font *out, { struct face *face = NULL; int ret; - tsm_symbol_t ch; - unsigned int i, width; + unsigned int width; + uint32_t i; struct kmscon_glyph *glyph; struct glyph *data; @@ -593,8 +590,7 @@ static int kmscon_font_freetype2_init(struct kmscon_font *out, if (face->shrink) { width = 0; for (i = 0x20; i < 0x7f; ++i) { - ch = tsm_symbol_make(i); - ret = get_glyph(face, &glyph, ch); + ret = get_glyph(face, &glyph, i, &i, 1); if (ret) continue; data = glyph->data; @@ -636,8 +632,8 @@ static void kmscon_font_freetype2_destroy(struct kmscon_font *font) manager_put_face(face); } -static int kmscon_font_freetype2_render(struct kmscon_font *font, - tsm_symbol_t sym, +static int kmscon_font_freetype2_render(struct kmscon_font *font, uint32_t id, + const uint32_t *ch, size_t len, const struct kmscon_glyph **out) { struct kmscon_glyph *glyph; @@ -645,7 +641,7 @@ static int kmscon_font_freetype2_render(struct kmscon_font *font, struct face *face; int ret; - ret = get_glyph(font->data, &glyph, sym); + ret = get_glyph(font->data, &glyph, id, ch, len); if (ret) return ret; diff --git a/src/text_font_pango.c b/src/text_font_pango.c index 9cd0849..65c086d 100644 --- a/src/text_font_pango.c +++ b/src/text_font_pango.c @@ -110,21 +110,21 @@ static void manager__unref() } static int get_glyph(struct face *face, struct kmscon_glyph **out, - tsm_symbol_t ch) + uint32_t id, const uint32_t *ch, size_t len) { struct kmscon_glyph *glyph; PangoLayout *layout; PangoRectangle rec; PangoLayoutLine *line; FT_Bitmap bitmap; - size_t len, cnt; - const char *val; + size_t ulen, cnt; + char *val; bool res; int ret; pthread_mutex_lock(&face->glyph_lock); res = shl_hashtable_find(face->glyphs, (void**)&glyph, - (void*)(long)ch); + (void*)(long)id); pthread_mutex_unlock(&face->glyph_lock); if (res) { *out = glyph; @@ -149,9 +149,13 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, /* no line spacing */ pango_layout_set_spacing(layout, 0); - val = tsm_symbol_get_u8(NULL, ch, &len); - pango_layout_set_text(layout, val, len); - tsm_symbol_free_u8(val); + val = tsm_ucs4_to_utf8_alloc(ch, len, &ulen); + if (!val) { + ret = -ERANGE; + goto out_glyph; + } + pango_layout_set_text(layout, val, ulen); + free(val); cnt = pango_layout_get_line_count(layout); if (cnt == 0) { @@ -190,7 +194,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, pango_ft2_render_layout_line(&bitmap, line, -rec.x, -rec.y); pthread_mutex_lock(&face->glyph_lock); - ret = shl_hashtable_insert(face->glyphs, (void*)(long)ch, glyph); + ret = shl_hashtable_insert(face->glyphs, (void*)(long)id, glyph); pthread_mutex_unlock(&face->glyph_lock); if (ret) { log_error("cannot add glyph to hashtable"); @@ -386,14 +390,14 @@ static void kmscon_font_pango_destroy(struct kmscon_font *font) manager_put_face(face); } -static int kmscon_font_pango_render(struct kmscon_font *font, - tsm_symbol_t sym, +static int kmscon_font_pango_render(struct kmscon_font *font, uint32_t id, + const uint32_t *ch, size_t len, const struct kmscon_glyph **out) { struct kmscon_glyph *glyph; int ret; - ret = get_glyph(font->data, &glyph, sym); + ret = get_glyph(font->data, &glyph, id, ch, len); if (ret) return ret; @@ -404,13 +408,16 @@ static int kmscon_font_pango_render(struct kmscon_font *font, static int kmscon_font_pango_render_empty(struct kmscon_font *font, const struct kmscon_glyph **out) { - return kmscon_font_pango_render(font, ' ', out); + static const uint32_t empty_char = ' '; + return kmscon_font_pango_render(font, empty_char, &empty_char, 1, out); } static int kmscon_font_pango_render_inval(struct kmscon_font *font, const struct kmscon_glyph **out) { - return kmscon_font_pango_render(font, '?', out); + static const uint32_t question_mark = '?'; + return kmscon_font_pango_render(font, question_mark, &question_mark, 1, + out); } static const struct kmscon_font_ops kmscon_font_pango_ops = { diff --git a/src/text_font_unifont.c b/src/text_font_unifont.c index 93ecb00..d2b863b 100644 --- a/src/text_font_unifont.c +++ b/src/text_font_unifont.c @@ -44,7 +44,6 @@ #include #include "log.h" #include "text.h" -#include "tsm_unicode.h" #include "uterm.h" #define LOG_SUBSYSTEM "text_font_unifont" @@ -77,19 +76,14 @@ static void kmscon_font_unifont_destroy(struct kmscon_font *font) log_debug("unloading static unifont font"); } -static int kmscon_font_unifont_render(struct kmscon_font *font, - tsm_symbol_t sym, +static int kmscon_font_unifont_render(struct kmscon_font *font, uint32_t id, + const uint32_t *ch, size_t len, const struct kmscon_glyph **out) { - const uint32_t *val; - size_t len; - - val = tsm_symbol_get(NULL, &sym, &len); - if (len > 1 || *val >= kmscon_text_font_unifont_data_hex_len) + if (len > 1 || *ch >= kmscon_text_font_unifont_data_hex_len) return -ERANGE; - *out = &kmscon_text_font_unifont_data_hex_glyphs[*val]; - + *out = &kmscon_text_font_unifont_data_hex_glyphs[*ch]; return 0; } diff --git a/src/text_gltex.c b/src/text_gltex.c index e71d923..ce028ba 100644 --- a/src/text_gltex.c +++ b/src/text_gltex.c @@ -50,7 +50,6 @@ #include "shl_hashtable.h" #include "static_gl.h" #include "text.h" -#include "tsm_unicode.h" #include "uterm.h" #define LOG_SUBSYSTEM "text_gltex" @@ -367,7 +366,7 @@ err_free: } static int find_glyph(struct kmscon_text *txt, struct glyph **out, - tsm_symbol_t ch) + uint32_t id, const uint32_t *ch, size_t len) { struct gltex *gt = txt->data; struct atlas *atlas; @@ -378,7 +377,7 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out, uint8_t *packed_data, *dst, *src; res = shl_hashtable_find(gt->glyphs, (void**)&glyph, - (void*)(unsigned long)ch); + (void*)(unsigned long)id); if (res) { *out = glyph; return 0; @@ -393,10 +392,10 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out, return -ENOMEM; memset(glyph, 0, sizeof(*glyph)); - if (ch == 0 || ch == ' ') { + if (!len) { ret = kmscon_font_render_empty(txt->font, &glyph->glyph); } else { - ret = kmscon_font_render(txt->font, ch, &glyph->glyph); + ret = kmscon_font_render(txt->font, id, ch, len, &glyph->glyph); } if (ret) { @@ -480,7 +479,7 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out, glyph->atlas = atlas; glyph->texoff = atlas->fill; - ret = shl_hashtable_insert(gt->glyphs, (void*)(long)ch, glyph); + ret = shl_hashtable_insert(gt->glyphs, (void*)(long)id, glyph); if (ret) goto err_free; @@ -521,7 +520,8 @@ static int gltex_prepare(struct kmscon_text *txt) return 0; } -static int gltex_draw(struct kmscon_text *txt, tsm_symbol_t ch, +static int gltex_draw(struct kmscon_text *txt, + uint32_t id, const uint32_t *ch, size_t len, unsigned int posx, unsigned int posy, const struct kmscon_console_attr *attr) { @@ -530,7 +530,7 @@ static int gltex_draw(struct kmscon_text *txt, tsm_symbol_t ch, struct glyph *glyph; int ret, i, idx; - ret = find_glyph(txt, &glyph, ch); + ret = find_glyph(txt, &glyph, id, ch, len); if (ret) return ret; atlas = glyph->atlas;