X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftext.c;h=d7e5f0e7e8f44d7af0030e126f324a59928c4eb6;hb=refs%2Fheads%2Ftizen_3.0.m14.2_ivi;hp=b2db07c92401b82f0f1f061515256dc110e05cf2;hpb=2652637fb9d0e0878cc0233e7c3a16b2b27beb97;p=platform%2Fupstream%2Fkmscon.git diff --git a/src/text.c b/src/text.c index b2db07c..d7e5f0e 100644 --- a/src/text.c +++ b/src/text.c @@ -35,29 +35,22 @@ #include #include #include -#include "log.h" -#include "static_misc.h" +#include "shl_dlist.h" +#include "shl_log.h" +#include "shl_misc.h" +#include "shl_register.h" #include "text.h" -#include "uterm.h" +#include "uterm_video.h" #define LOG_SUBSYSTEM "text" -struct text_backend { - struct kmscon_dlist list; - const struct kmscon_text_ops *ops; -}; +static struct shl_register text_reg = SHL_REGISTER_INIT(text_reg); -static pthread_mutex_t text_mutex = PTHREAD_MUTEX_INITIALIZER; -static struct kmscon_dlist text__list = KMSCON_DLIST_INIT(text__list); - -static void text_lock() +static inline void kmscon_text_destroy(void *data) { - pthread_mutex_lock(&text_mutex); -} + const struct kmscon_text_ops *ops = data; -static void text_unlock() -{ - pthread_mutex_unlock(&text_mutex); + kmscon_module_unref(ops->owner); } /** @@ -74,45 +67,26 @@ static void text_unlock() * * Returns: 0 on success, negative error code on failure */ +SHL_EXPORT int kmscon_text_register(const struct kmscon_text_ops *ops) { - struct kmscon_dlist *iter; - struct text_backend *be; int ret; - if (!ops || !ops->name) + if (!ops) return -EINVAL; log_debug("register text backend %s", ops->name); - text_lock(); - - kmscon_dlist_for_each(iter, &text__list) { - be = kmscon_dlist_entry(iter, struct text_backend, list); - if (!strcmp(be->ops->name, ops->name)) { - log_error("registering already available backend %s", - ops->name); - ret = -EALREADY; - goto out_unlock; - } - } - - be = malloc(sizeof(*be)); - if (!be) { - log_error("cannot allocate memory for backend"); - ret = -ENOMEM; - goto out_unlock; + ret = shl_register_add_cb(&text_reg, ops->name, (void*)ops, + kmscon_text_destroy); + if (ret) { + log_error("cannot register text backend %s: %d", ops->name, + ret); + return ret; } - memset(be, 0, sizeof(*be)); - be->ops = ops; - kmscon_dlist_link(&text__list, &be->list); - - ret = 0; - -out_unlock: - text_unlock(); - return ret; + kmscon_module_ref(ops->owner); + return 0; } /** @@ -120,39 +94,49 @@ out_unlock: * @name: Name of backend * * This unregisters the text-backend that is registered with name @name. If - * @name is not found, a warning is printed but nothing else is done. + * @name is not found, nothing is done. */ +SHL_EXPORT void kmscon_text_unregister(const char *name) { - struct kmscon_dlist *iter; - struct text_backend *be; - - if (!name) - return; - log_debug("unregister backend %s", name); + shl_register_remove(&text_reg, name); +} - text_lock(); +static int new_text(struct kmscon_text *text, const char *backend) +{ + struct shl_register_record *record; + const char *name = backend ? backend : ""; + int ret; - kmscon_dlist_for_each(iter, &text__list) { - be = kmscon_dlist_entry(iter, struct text_backend, list); - if (strcmp(name, be->ops->name)) - continue; + memset(text, 0, sizeof(*text)); + text->ref = 1; + + if (backend) + record = shl_register_find(&text_reg, backend); + else + record = shl_register_first(&text_reg); - kmscon_dlist_unlink(&be->list); - break; + if (!record) { + log_error("requested backend '%s' not found", name); + return -ENOENT; } - if (iter == &text__list) - be = NULL; + text->record = record; + text->ops = record->data; - text_unlock(); + if (text->ops->init) + ret = text->ops->init(text); + else + ret = 0; - if (!be) { - log_error("cannot unregister backend %s: not found", name); - } else { - free(be); + if (ret) { + log_warning("backend %s cannot create renderer", name); + shl_register_record_unref(record); + return ret; } + + return 0; } /** @@ -162,94 +146,34 @@ void kmscon_text_unregister(const char *name) * * Returns: 0 on success, error code on failure */ -int kmscon_text_new(struct kmscon_text **out, - const char *backend) +int kmscon_text_new(struct kmscon_text **out, const char *backend) { struct kmscon_text *text; - struct kmscon_dlist *iter; - struct text_backend *be, *def; int ret; if (!out) return -EINVAL; - text_lock(); - - if (kmscon_dlist_empty(&text__list)) { - log_error("no text backend available"); - ret = -EFAULT; - } else { - ret = 0; - def = kmscon_dlist_entry(text__list.prev, - struct text_backend, - list); - if (!backend) { - be = def; - } else { - kmscon_dlist_for_each(iter, &text__list) { - be = kmscon_dlist_entry(iter, - struct text_backend, - list); - if (!strcmp(backend, be->ops->name)) - break; - } - if (iter == &text__list) { - log_warning("requested backend %s not found", - backend); - be = def; - } - } - } - - if (ret) - goto out_unlock; - text = malloc(sizeof(*text)); if (!text) { log_error("cannot allocate memory for new text-renderer"); - ret = -ENOMEM; - goto out_unlock; + return -ENOMEM; } - memset(text, 0, sizeof(*text)); - text->ref = 1; - text->ops = be->ops; - - if (text->ops->init) - ret = text->ops->init(text); - else - ret = 0; + ret = new_text(text, backend); if (ret) { - if (be == def) { - log_error("default backend %s cannot create renderer", - text->ops->name); + if (backend) + ret = new_text(text, NULL); + if (ret) goto err_free; - } - - log_warning("backend %s cannot create renderer; trying default backend %s", - be->ops->name, def->ops->name); - - memset(text, 0, sizeof(*text)); - text->ref = 1; - text->ops = def->ops; - - ret = text->ops->init(text); - if (ret) { - log_error("default backend %s cannot create renderer", - text->ops->name); - goto err_free; - } } log_debug("using: be: %s", text->ops->name); *out = text; - ret = 0; - goto out_unlock; + return 0; err_free: free(text); -out_unlock: - text_unlock(); return ret; } @@ -282,20 +206,18 @@ void kmscon_text_unref(struct kmscon_text *text) log_debug("freeing text renderer"); kmscon_text_unset(text); - text_lock(); - if (text->ops->destroy) text->ops->destroy(text); + shl_register_record_unref(text->record); free(text); - - text_unlock(); } /** * kmscon_text_set: * @txt: Valid text-renderer object * @font: font object - * @screen: screen object + * @bold_font: bold font object or NULL + * @disp: display object * * This makes the text-renderer @txt use the font @font and screen @screen. You * can drop your reference to both after calling this. @@ -303,34 +225,44 @@ void kmscon_text_unref(struct kmscon_text *text) * None of the arguments can be NULL! * If this function fails then you must assume that no font/screen will be set * and the object is invalid. + * If @bold_font is NULL, @font is also used for bold characters. The caller + * must make sure that @font and @bold_font have the same metrics. The renderers + * will always use the metrics of @font. * * Returns: 0 on success, negative error code on failure. */ int kmscon_text_set(struct kmscon_text *txt, struct kmscon_font *font, - struct uterm_screen *screen) + struct kmscon_font *bold_font, + struct uterm_display *disp) { int ret; - if (!txt || !font || !screen) + if (!txt || !font || !disp) return -EINVAL; + if (!bold_font) + bold_font = font; + kmscon_text_unset(txt); txt->font = font; - txt->screen = screen; + txt->bold_font = bold_font; + txt->disp = disp; if (txt->ops->set) { ret = txt->ops->set(txt); if (ret) { txt->font = NULL; - txt->screen = NULL; + txt->bold_font = NULL; + txt->disp = NULL; return ret; } } kmscon_font_ref(txt->font); - uterm_screen_ref(txt->screen); + kmscon_font_ref(txt->bold_font); + uterm_display_ref(txt->disp); return 0; } @@ -346,16 +278,18 @@ int kmscon_text_set(struct kmscon_text *txt, */ void kmscon_text_unset(struct kmscon_text *txt) { - if (!txt || !txt->screen || !txt->font) + if (!txt || !txt->disp || !txt->font) return; if (txt->ops->unset) txt->ops->unset(txt); kmscon_font_unref(txt->font); - uterm_screen_unref(txt->screen); + kmscon_font_unref(txt->bold_font); + uterm_display_unref(txt->disp); txt->font = NULL; - txt->screen = NULL; + txt->bold_font = NULL; + txt->disp = NULL; txt->cols = 0; txt->rows = 0; txt->rendering = false; @@ -416,7 +350,7 @@ int kmscon_text_prepare(struct kmscon_text *txt) { int ret = 0; - if (!txt || !txt->font || !txt->screen) + if (!txt || !txt->font || !txt->disp) return -EINVAL; txt->rendering = true; @@ -431,7 +365,10 @@ 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 + * @width: cell-width of character * @posx: X-position of the glyph * @posy: Y-position of the glyph * @attr: glyph attributes @@ -443,16 +380,18 @@ 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, kmscon_symbol_t ch, - unsigned int posx, unsigned int posy, - const struct font_char_attr *attr) +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) { 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, width, posx, posy, attr); } /** @@ -497,3 +436,13 @@ void kmscon_text_abort(struct kmscon_text *txt) txt->ops->abort(txt); txt->rendering = false; } + +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, + tsm_age_t age, void *data) +{ + return kmscon_text_draw(data, id, ch, len, width, posx, posy, attr); +}