2 * kmscon - Text Renderer
4 * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * @short_description: Text Renderer
38 #include "shl_dlist.h"
41 #include "shl_register.h"
43 #include "uterm_video.h"
45 #define LOG_SUBSYSTEM "text"
47 static struct shl_register text_reg = SHL_REGISTER_INIT(text_reg);
49 static inline void kmscon_text_destroy(void *data)
51 const struct kmscon_text_ops *ops = data;
53 kmscon_module_unref(ops->owner);
57 * kmscon_text_register:
58 * @ops: Text operations and name for new backend
60 * This register a new text backend with operations set to @ops. The name
61 * @ops->name must be valid.
63 * The first font that is registered automatically becomes the default and
64 * fallback. So make sure you register a safe fallback as first backend.
65 * If this is unregistered, the next in the list becomes the default
68 * Returns: 0 on success, negative error code on failure
71 int kmscon_text_register(const struct kmscon_text_ops *ops)
78 log_debug("register text backend %s", ops->name);
80 ret = shl_register_add_cb(&text_reg, ops->name, (void*)ops,
83 log_error("cannot register text backend %s: %d", ops->name,
88 kmscon_module_ref(ops->owner);
93 * kmscon_text_unregister:
94 * @name: Name of backend
96 * This unregisters the text-backend that is registered with name @name. If
97 * @name is not found, nothing is done.
100 void kmscon_text_unregister(const char *name)
102 log_debug("unregister backend %s", name);
103 shl_register_remove(&text_reg, name);
106 static int new_text(struct kmscon_text *text, const char *backend)
108 struct shl_register_record *record;
109 const char *name = backend ? backend : "<default>";
112 memset(text, 0, sizeof(*text));
116 record = shl_register_find(&text_reg, backend);
118 record = shl_register_first(&text_reg);
121 log_error("requested backend '%s' not found", name);
125 text->record = record;
126 text->ops = record->data;
129 ret = text->ops->init(text);
134 log_warning("backend %s cannot create renderer", name);
135 shl_register_record_unref(record);
144 * @out: A pointer to the new text-renderer is stored here
145 * @backend: Backend to use or NULL for default backend
147 * Returns: 0 on success, error code on failure
149 int kmscon_text_new(struct kmscon_text **out, const char *backend)
151 struct kmscon_text *text;
157 text = malloc(sizeof(*text));
159 log_error("cannot allocate memory for new text-renderer");
163 ret = new_text(text, backend);
166 ret = new_text(text, NULL);
171 log_debug("using: be: %s", text->ops->name);
182 * @text: Valid text-renderer object
184 * This increases the reference count of @text by one.
186 void kmscon_text_ref(struct kmscon_text *text)
188 if (!text || !text->ref)
196 * @text: Valid text-renderer object
198 * This decreases the reference count of @text by one. If it drops to zero, the
201 void kmscon_text_unref(struct kmscon_text *text)
203 if (!text || !text->ref || --text->ref)
206 log_debug("freeing text renderer");
207 kmscon_text_unset(text);
209 if (text->ops->destroy)
210 text->ops->destroy(text);
211 shl_register_record_unref(text->record);
217 * @txt: Valid text-renderer object
219 * @bold_font: bold font object or NULL
220 * @disp: display object
222 * This makes the text-renderer @txt use the font @font and screen @screen. You
223 * can drop your reference to both after calling this.
224 * This calls kmscon_text_unset() first to remove all previous associations.
225 * None of the arguments can be NULL!
226 * If this function fails then you must assume that no font/screen will be set
227 * and the object is invalid.
228 * If @bold_font is NULL, @font is also used for bold characters. The caller
229 * must make sure that @font and @bold_font have the same metrics. The renderers
230 * will always use the metrics of @font.
232 * Returns: 0 on success, negative error code on failure.
234 int kmscon_text_set(struct kmscon_text *txt,
235 struct kmscon_font *font,
236 struct kmscon_font *bold_font,
237 struct uterm_display *disp)
241 if (!txt || !font || !disp)
247 kmscon_text_unset(txt);
250 txt->bold_font = bold_font;
254 ret = txt->ops->set(txt);
257 txt->bold_font = NULL;
263 kmscon_font_ref(txt->font);
264 kmscon_font_ref(txt->bold_font);
265 uterm_display_ref(txt->disp);
271 * kmscon_text_unset():
272 * @txt: text renderer
274 * This redos kmscon_text_set() by dropping the internal references to the font
275 * and screen and invalidating the object. You need to call kmscon_text_set()
276 * again to make use of this text renderer.
277 * This is automatically called when the text renderer is destroyed.
279 void kmscon_text_unset(struct kmscon_text *txt)
281 if (!txt || !txt->disp || !txt->font)
285 txt->ops->unset(txt);
287 kmscon_font_unref(txt->font);
288 kmscon_font_unref(txt->bold_font);
289 uterm_display_unref(txt->disp);
291 txt->bold_font = NULL;
295 txt->rendering = false;
299 * kmscon_text_get_cols:
300 * @txt: valid text renderer
302 * After setting the arguments with kmscon_text_set(), the renderer will compute
303 * the number of columns/rows of the console that it can display on the screen.
304 * You can retrieve these values via these functions.
305 * If kmscon_text_set() hasn't been called, this will return 0.
307 * Returns: Number of columns or 0 if @txt is invalid
309 unsigned int kmscon_text_get_cols(struct kmscon_text *txt)
318 * kmscon_text_get_rows:
319 * @txt: valid text renderer
321 * After setting the arguments with kmscon_text_set(), the renderer will compute
322 * the number of columns/rows of the console that it can display on the screen.
323 * You can retrieve these values via these functions.
324 * If kmscon_text_set() hasn't been called, this will return 0.
326 * Returns: Number of rows or 0 if @txt is invalid
328 unsigned int kmscon_text_get_rows(struct kmscon_text *txt)
337 * kmscon_text_prepare:
338 * @txt: valid text renderer
340 * This starts a rendering-round. When rendering a console via a text renderer,
341 * you have to call this first, then render all your glyphs via
342 * kmscon_text_draw() and finally use kmscon_text_render(). If you modify this
343 * renderer during rendering or if you activate different OpenGL contexts in
344 * between, you need to restart rendering by calling kmscon_text_prepare() again
345 * and redoing everything from the beginning.
347 * Returns: 0 on success, negative error code on failure.
349 int kmscon_text_prepare(struct kmscon_text *txt)
353 if (!txt || !txt->font || !txt->disp)
356 txt->rendering = true;
357 if (txt->ops->prepare)
358 ret = txt->ops->prepare(txt);
360 txt->rendering = false;
367 * @txt: valid text renderer
368 * @id: a unique ID that identifies @ch globally
369 * @ch: ucs4 symbol you want to draw
370 * @len: length of @ch or 0 for empty cell
371 * @width: cell-width of character
372 * @posx: X-position of the glyph
373 * @posy: Y-position of the glyph
374 * @attr: glyph attributes
376 * This draws a single glyph at the requested position. The position is a
377 * console position, not a pixel position! You must precede this call with
378 * kmscon_text_prepare(). Use this function to feed all glyphs into the
379 * rendering pipeline and finally call kmscon_text_render().
381 * Returns: 0 on success or negative error code if this glyph couldn't be drawn.
383 int kmscon_text_draw(struct kmscon_text *txt,
384 uint32_t id, const uint32_t *ch, size_t len,
386 unsigned int posx, unsigned int posy,
387 const struct tsm_screen_attr *attr)
389 if (!txt || !txt->rendering)
391 if (posx >= txt->cols || posy >= txt->rows || !attr)
394 return txt->ops->draw(txt, id, ch, len, width, posx, posy, attr);
398 * kmscon_text_render:
399 * @txt: valid text renderer
401 * This does the final rendering round after kmscon_text_prepare() has been
402 * called and all glyphs were sent to the renderer via kmscon_text_draw().
404 * Returns: 0 on success, negative error on failure.
406 int kmscon_text_render(struct kmscon_text *txt)
410 if (!txt || !txt->rendering)
413 if (txt->ops->render)
414 ret = txt->ops->render(txt);
415 txt->rendering = false;
422 * @txt: valid text renderer
424 * If you called kmscon_text_prepare() but you want to abort rendering instead
425 * of finishing it with kmscon_text_render(), you can safely call this to reset
426 * internal state. It is optional to call this or simply restart rendering.
427 * Especially if the other renderers return an error, then they probably already
428 * aborted rendering and it is not required to call this.
430 void kmscon_text_abort(struct kmscon_text *txt)
432 if (!txt || !txt->rendering)
436 txt->ops->abort(txt);
437 txt->rendering = false;
440 int kmscon_text_prepare_cb(struct tsm_screen *con, void *data)
442 return kmscon_text_prepare(data);
445 int kmscon_text_draw_cb(struct tsm_screen *con,
446 uint32_t id, const uint32_t *ch, size_t len,
448 unsigned int posx, unsigned int posy,
449 const struct tsm_screen_attr *attr, void *data)
451 return kmscon_text_draw(data, id, ch, len, width, posx, posy, attr);
454 int kmscon_text_render_cb(struct tsm_screen *con, void *data)
456 return kmscon_text_render(data);