Modify it to adjust Tizen IVI enviroment
[platform/upstream/kmscon.git] / src / text.c
1 /*
2  * kmscon - Text Renderer
3  *
4  * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com>
5  *
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:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
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.
24  */
25
26 /**
27  * SECTION:text
28  * @short_description: Text Renderer
29  * @include: text.h
30  *
31  * TODO
32  */
33
34 #include <errno.h>
35 #include <pthread.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "shl_dlist.h"
39 #include "shl_log.h"
40 #include "shl_misc.h"
41 #include "shl_register.h"
42 #include "text.h"
43 #include "uterm_video.h"
44
45 #define LOG_SUBSYSTEM "text"
46
47 static struct shl_register text_reg = SHL_REGISTER_INIT(text_reg);
48
49 static inline void kmscon_text_destroy(void *data)
50 {
51         const struct kmscon_text_ops *ops = data;
52
53         kmscon_module_unref(ops->owner);
54 }
55
56 /**
57  * kmscon_text_register:
58  * @ops: Text operations and name for new backend
59  *
60  * This register a new text backend with operations set to @ops. The name
61  * @ops->name must be valid.
62  *
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
66  * and fallback.
67  *
68  * Returns: 0 on success, negative error code on failure
69  */
70 SHL_EXPORT
71 int kmscon_text_register(const struct kmscon_text_ops *ops)
72 {
73         int ret;
74
75         if (!ops)
76                 return -EINVAL;
77
78         log_debug("register text backend %s", ops->name);
79
80         ret = shl_register_add_cb(&text_reg, ops->name, (void*)ops,
81                                   kmscon_text_destroy);
82         if (ret) {
83                 log_error("cannot register text backend %s: %d", ops->name,
84                           ret);
85                 return ret;
86         }
87
88         kmscon_module_ref(ops->owner);
89         return 0;
90 }
91
92 /**
93  * kmscon_text_unregister:
94  * @name: Name of backend
95  *
96  * This unregisters the text-backend that is registered with name @name. If
97  * @name is not found, nothing is done.
98  */
99 SHL_EXPORT
100 void kmscon_text_unregister(const char *name)
101 {
102         log_debug("unregister backend %s", name);
103         shl_register_remove(&text_reg, name);
104 }
105
106 static int new_text(struct kmscon_text *text, const char *backend)
107 {
108         struct shl_register_record *record;
109         const char *name = backend ? backend : "<default>";
110         int ret;
111
112         memset(text, 0, sizeof(*text));
113         text->ref = 1;
114
115         if (backend)
116                 record = shl_register_find(&text_reg, backend);
117         else
118                 record = shl_register_first(&text_reg);
119
120         if (!record) {
121                 log_error("requested backend '%s' not found", name);
122                 return -ENOENT;
123         }
124
125         text->record = record;
126         text->ops = record->data;
127
128         if (text->ops->init)
129                 ret = text->ops->init(text);
130         else
131                 ret = 0;
132
133         if (ret) {
134                 log_warning("backend %s cannot create renderer", name);
135                 shl_register_record_unref(record);
136                 return ret;
137         }
138
139         return 0;
140 }
141
142 /**
143  * kmscon_text_new:
144  * @out: A pointer to the new text-renderer is stored here
145  * @backend: Backend to use or NULL for default backend
146  *
147  * Returns: 0 on success, error code on failure
148  */
149 int kmscon_text_new(struct kmscon_text **out, const char *backend)
150 {
151         struct kmscon_text *text;
152         int ret;
153
154         if (!out)
155                 return -EINVAL;
156
157         text = malloc(sizeof(*text));
158         if (!text) {
159                 log_error("cannot allocate memory for new text-renderer");
160                 return -ENOMEM;
161         }
162
163         ret = new_text(text, backend);
164         if (ret) {
165                 if (backend)
166                         ret = new_text(text, NULL);
167                 if (ret)
168                         goto err_free;
169         }
170
171         log_debug("using: be: %s", text->ops->name);
172         *out = text;
173         return 0;
174
175 err_free:
176         free(text);
177         return ret;
178 }
179
180 /**
181  * kmscon_text_ref:
182  * @text: Valid text-renderer object
183  *
184  * This increases the reference count of @text by one.
185  */
186 void kmscon_text_ref(struct kmscon_text *text)
187 {
188         if (!text || !text->ref)
189                 return;
190
191         ++text->ref;
192 }
193
194 /**
195  * kmscon_text_unref:
196  * @text: Valid text-renderer object
197  *
198  * This decreases the reference count of @text by one. If it drops to zero, the
199  * object is freed.
200  */
201 void kmscon_text_unref(struct kmscon_text *text)
202 {
203         if (!text || !text->ref || --text->ref)
204                 return;
205
206         log_debug("freeing text renderer");
207         kmscon_text_unset(text);
208
209         if (text->ops->destroy)
210                 text->ops->destroy(text);
211         shl_register_record_unref(text->record);
212         free(text);
213 }
214
215 /**
216  * kmscon_text_set:
217  * @txt: Valid text-renderer object
218  * @font: font object
219  * @bold_font: bold font object or NULL
220  * @disp: display object
221  *
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.
231  *
232  * Returns: 0 on success, negative error code on failure.
233  */
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)
238 {
239         int ret;
240
241         if (!txt || !font || !disp)
242                 return -EINVAL;
243
244         if (!bold_font)
245                 bold_font = font;
246
247         kmscon_text_unset(txt);
248
249         txt->font = font;
250         txt->bold_font = bold_font;
251         txt->disp = disp;
252
253         if (txt->ops->set) {
254                 ret = txt->ops->set(txt);
255                 if (ret) {
256                         txt->font = NULL;
257                         txt->bold_font = NULL;
258                         txt->disp = NULL;
259                         return ret;
260                 }
261         }
262
263         kmscon_font_ref(txt->font);
264         kmscon_font_ref(txt->bold_font);
265         uterm_display_ref(txt->disp);
266
267         return 0;
268 }
269
270 /**
271  * kmscon_text_unset():
272  * @txt: text renderer
273  *
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.
278  */
279 void kmscon_text_unset(struct kmscon_text *txt)
280 {
281         if (!txt || !txt->disp || !txt->font)
282                 return;
283
284         if (txt->ops->unset)
285                 txt->ops->unset(txt);
286
287         kmscon_font_unref(txt->font);
288         kmscon_font_unref(txt->bold_font);
289         uterm_display_unref(txt->disp);
290         txt->font = NULL;
291         txt->bold_font = NULL;
292         txt->disp = NULL;
293         txt->cols = 0;
294         txt->rows = 0;
295         txt->rendering = false;
296 }
297
298 /**
299  * kmscon_text_get_cols:
300  * @txt: valid text renderer
301  *
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.
306  *
307  * Returns: Number of columns or 0 if @txt is invalid
308  */
309 unsigned int kmscon_text_get_cols(struct kmscon_text *txt)
310 {
311         if (!txt)
312                 return 0;
313
314         return txt->cols;
315 }
316
317 /**
318  * kmscon_text_get_rows:
319  * @txt: valid text renderer
320  *
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.
325  *
326  * Returns: Number of rows or 0 if @txt is invalid
327  */
328 unsigned int kmscon_text_get_rows(struct kmscon_text *txt)
329 {
330         if (!txt)
331                 return 0;
332
333         return txt->rows;
334 }
335
336 /**
337  * kmscon_text_prepare:
338  * @txt: valid text renderer
339  *
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.
346  *
347  * Returns: 0 on success, negative error code on failure.
348  */
349 int kmscon_text_prepare(struct kmscon_text *txt)
350 {
351         int ret = 0;
352
353         if (!txt || !txt->font || !txt->disp)
354                 return -EINVAL;
355
356         txt->rendering = true;
357         if (txt->ops->prepare)
358                 ret = txt->ops->prepare(txt);
359         if (ret)
360                 txt->rendering = false;
361
362         return ret;
363 }
364
365 /**
366  * kmscon_text_draw:
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
375  *
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().
380  *
381  * Returns: 0 on success or negative error code if this glyph couldn't be drawn.
382  */
383 int kmscon_text_draw(struct kmscon_text *txt,
384                      uint32_t id, const uint32_t *ch, size_t len,
385                      unsigned int width,
386                      unsigned int posx, unsigned int posy,
387                      const struct tsm_screen_attr *attr)
388 {
389         if (!txt || !txt->rendering)
390                 return -EINVAL;
391         if (posx >= txt->cols || posy >= txt->rows || !attr)
392                 return -EINVAL;
393
394         return txt->ops->draw(txt, id, ch, len, width, posx, posy, attr);
395 }
396
397 /**
398  * kmscon_text_render:
399  * @txt: valid text renderer
400  *
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().
403  *
404  * Returns: 0 on success, negative error on failure.
405  */
406 int kmscon_text_render(struct kmscon_text *txt)
407 {
408         int ret = 0;
409
410         if (!txt || !txt->rendering)
411                 return -EINVAL;
412
413         if (txt->ops->render)
414                 ret = txt->ops->render(txt);
415         txt->rendering = false;
416
417         return ret;
418 }
419
420 /**
421  * kmscon_text_abort:
422  * @txt: valid text renderer
423  *
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.
429  */
430 void kmscon_text_abort(struct kmscon_text *txt)
431 {
432         if (!txt || !txt->rendering)
433                 return;
434
435         if (txt->ops->abort)
436                 txt->ops->abort(txt);
437         txt->rendering = false;
438 }
439
440 int kmscon_text_draw_cb(struct tsm_screen *con,
441                         uint32_t id, const uint32_t *ch, size_t len,
442                         unsigned int width,
443                         unsigned int posx, unsigned int posy,
444                         const struct tsm_screen_attr *attr,
445                         tsm_age_t age, void *data)
446 {
447         return kmscon_text_draw(data, id, ch, len, width, posx, posy, attr);
448 }