text: bbulk: implement bold-char renderer
[platform/upstream/kmscon.git] / src / text_bbulk.c
1 /*
2  * kmscon - Bit-Blitting Bulk Text Renderer Backend
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_bbulk.c
28  * @short_description: Bit-Blitting Bulk Text Renderer Backend
29  * @include: text.h
30  *
31  * Similar to the bblit renderer but assembles an array of blit-requests and
32  * pushes all of them at once to the video device.
33  */
34
35 #include <errno.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "log.h"
40 #include "text.h"
41 #include "uterm.h"
42
43 #define LOG_SUBSYSTEM "text_bbulk"
44
45 struct bbulk {
46         struct uterm_video_blend_req *reqs;
47 };
48
49 #define FONT_WIDTH(txt) ((txt)->font->attr.width)
50 #define FONT_HEIGHT(txt) ((txt)->font->attr.height)
51
52 #define SCREEN_WIDTH(txt) uterm_screen_width((txt)->screen)
53 #define SCREEN_HEIGHT(txt) uterm_screen_height((txt)->screen)
54
55 static int bbulk_init(struct kmscon_text *txt)
56 {
57         struct bbulk *bb;
58
59         bb = malloc(sizeof(*bb));
60         if (!bb)
61                 return -ENOMEM;
62
63         txt->data = bb;
64         return 0;
65 }
66
67 static void bbulk_destroy(struct kmscon_text *txt)
68 {
69         struct bbulk *bb = txt->data;
70
71         free(bb);
72 }
73
74 static int bbulk_set(struct kmscon_text *txt)
75 {
76         struct bbulk *bb = txt->data;
77         unsigned int sw, sh, i, j;
78         struct uterm_video_blend_req *req;
79
80         memset(bb, 0, sizeof(*bb));
81
82         sw = SCREEN_WIDTH(txt);
83         sh = SCREEN_HEIGHT(txt);
84
85         txt->cols = sw / FONT_WIDTH(txt);
86         txt->rows = sh / FONT_HEIGHT(txt);
87
88         bb->reqs = malloc(sizeof(*bb->reqs) * txt->cols * txt->rows);
89         if (!bb->reqs)
90                 return -ENOMEM;
91         memset(bb->reqs, 0, sizeof(*bb->reqs) * txt->cols * txt->rows);
92
93         for (i = 0; i < txt->rows; ++i) {
94                 for (j = 0; j < txt->cols; ++j) {
95                         req = &bb->reqs[i * txt->cols + j];
96                         req->x = j * FONT_WIDTH(txt);
97                         req->y = i * FONT_HEIGHT(txt);
98                 }
99         }
100
101         return 0;
102 }
103
104 static void bbulk_unset(struct kmscon_text *txt)
105 {
106         struct bbulk *bb = txt->data;
107
108         free(bb->reqs);
109         bb->reqs = NULL;
110 }
111
112 static int bbulk_draw(struct kmscon_text *txt,
113                       uint32_t id, const uint32_t *ch, size_t len,
114                       unsigned int posx, unsigned int posy,
115                       const struct tsm_screen_attr *attr)
116 {
117         struct bbulk *bb = txt->data;
118         const struct kmscon_glyph *glyph;
119         int ret;
120         struct uterm_video_blend_req *req;
121         struct kmscon_font *font;
122
123         if (attr->bold)
124                 font = txt->bold_font;
125         else
126                 font = txt->font;
127
128         if (!len) {
129                 ret = kmscon_font_render_empty(font, &glyph);
130         } else {
131                 ret = kmscon_font_render(font, id, ch, len, &glyph);
132         }
133
134         if (ret) {
135                 ret = kmscon_font_render_inval(font, &glyph);
136                 if (ret)
137                         return ret;
138         }
139
140         req = &bb->reqs[posy * txt->cols + posx];
141         req->buf = &glyph->buf;
142         if (attr->inverse) {
143                 req->fr = attr->br;
144                 req->fg = attr->bg;
145                 req->fb = attr->bb;
146                 req->br = attr->fr;
147                 req->bg = attr->fg;
148                 req->bb = attr->fb;
149         } else {
150                 req->fr = attr->fr;
151                 req->fg = attr->fg;
152                 req->fb = attr->fb;
153                 req->br = attr->br;
154                 req->bg = attr->bg;
155                 req->bb = attr->bb;
156         }
157
158         return 0;
159 }
160
161 static int bbulk_render(struct kmscon_text *txt)
162 {
163         struct bbulk *bb = txt->data;
164
165         return uterm_screen_blendv(txt->screen, bb->reqs,
166                                    txt->cols * txt->rows);
167 }
168
169 static const struct kmscon_text_ops kmscon_text_bbulk_ops = {
170         .name = "bbulk",
171         .init = bbulk_init,
172         .destroy = bbulk_destroy,
173         .set = bbulk_set,
174         .unset = bbulk_unset,
175         .prepare = NULL,
176         .draw = bbulk_draw,
177         .render = bbulk_render,
178         .abort = NULL,
179 };
180
181 int kmscon_text_bbulk_load(void)
182 {
183         int ret;
184
185         ret = kmscon_text_register(&kmscon_text_bbulk_ops);
186         if (ret) {
187                 log_error("cannot register bbulk renderer");
188                 return ret;
189         }
190
191         return 0;
192 }
193
194 void kmscon_text_bbulk_unload(void)
195 {
196         kmscon_text_unregister(kmscon_text_bbulk_ops.name);
197 }