2 * kmscon - Fixed unifont font
4 * Copyright (c) 2012 Ted Kotz <ted@kotz.us>
5 * Copyright (c) 2012-2013 David Herrmann <dh.herrmann@googlemail.com>
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * SECTION:font_unifont.c
29 * @short_description: Fixed unifont font
32 * This is a fixed font renderer backend that supports just one font which is
33 * statically compiled into the file. This bitmap font has 8x16 and 16x16
34 * glyphs. This can statically compile in any font defined as a unifont style
35 * hex format. This font is from the GNU unifont project available at:
36 * http://unifoundry.com/unifont.html
38 * This file is heavily based on font_8x16.c
46 #include "shl_hashtable.h"
48 #include "uterm_video.h"
50 #define LOG_SUBSYSTEM "font_unifont"
53 * Glyph data is linked to the binary externally as binary data. The data layout
54 * is a size-byte followed by 32 data bytes. The data bytes are padded with 0 if
55 * the size is smaller than 32.
56 * Sizes bigger than 32 are not used.
62 } __attribute__((__packed__));
64 extern const struct unifont_data _binary_src_font_unifont_data_bin_start[];
65 extern const struct unifont_data _binary_src_font_unifont_data_bin_end[];
69 * The linked binary glyph data cannot be directly passed to the caller as it
70 * has the wrong format. Hence, use a glyph-cache with all used glyphs and add
71 * new ones as soon as they are used.
74 static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
75 static struct shl_hashtable *cache;
76 static unsigned long cache_refnum;
78 static void cache_ref(void)
80 pthread_mutex_lock(&cache_mutex);
82 pthread_mutex_unlock(&cache_mutex);
85 static void cache_unref(void)
87 pthread_mutex_lock(&cache_mutex);
88 if (!--cache_refnum) {
89 shl_hashtable_free(cache);
92 pthread_mutex_unlock(&cache_mutex);
95 static void free_glyph(void *data)
97 struct kmscon_glyph *g = data;
103 static void unfold(uint8_t *dst, uint8_t val)
108 static int find_glyph(uint32_t id, const struct kmscon_glyph **out)
110 struct kmscon_glyph *g;
113 const struct unifont_data *start, *end, *d;
116 pthread_mutex_lock(&cache_mutex);
119 ret = shl_hashtable_new(&cache, shl_direct_hash,
120 shl_direct_equal, NULL, free_glyph);
122 log_error("cannot create unifont hashtable: %d", ret);
126 res = shl_hashtable_find(cache, (void**)out,
139 start = _binary_src_font_unifont_data_bin_start;
140 end = _binary_src_font_unifont_data_bin_end;
160 g = malloc(sizeof(*g));
165 memset(g, 0, sizeof(*g));
167 g->buf.width = w * 8;
169 g->buf.stride = w * 8;
170 g->buf.format = UTERM_FORMAT_GREY;
172 g->buf.data = malloc(g->buf.stride * g->buf.height);
178 for (i = 0; i < d->len; ++i) {
179 unfold(&g->buf.data[i * 8 + 0], d->data[i] & 0x80);
180 unfold(&g->buf.data[i * 8 + 1], d->data[i] & 0x40);
181 unfold(&g->buf.data[i * 8 + 2], d->data[i] & 0x20);
182 unfold(&g->buf.data[i * 8 + 3], d->data[i] & 0x10);
183 unfold(&g->buf.data[i * 8 + 4], d->data[i] & 0x08);
184 unfold(&g->buf.data[i * 8 + 5], d->data[i] & 0x04);
185 unfold(&g->buf.data[i * 8 + 6], d->data[i] & 0x02);
186 unfold(&g->buf.data[i * 8 + 7], d->data[i] & 0x01);
189 ret = shl_hashtable_insert(cache, (void*)(long)id, g);
191 log_error("cannot insert glyph into glyph-cache: %d", ret);
204 pthread_mutex_unlock(&cache_mutex);
208 static int kmscon_font_unifont_init(struct kmscon_font *out,
209 const struct kmscon_font_attr *attr)
211 static const char name[] = "static-unifont";
212 const struct unifont_data *start, *end;
214 log_debug("loading static unifont font");
216 start = _binary_src_font_unifont_data_bin_start;
217 end = _binary_src_font_unifont_data_bin_end;
219 log_error("unifont glyph information not found in binary");
224 memset(&out->attr, 0, sizeof(out->attr));
225 memcpy(out->attr.name, name, sizeof(name));
226 out->attr.bold = false;
227 out->attr.italic = false;
229 out->attr.height = 16;
230 kmscon_font_attr_normalize(&out->attr);
237 static void kmscon_font_unifont_destroy(struct kmscon_font *font)
239 log_debug("unloading static unifont font");
243 static int kmscon_font_unifont_render(struct kmscon_font *font, uint32_t id,
244 const uint32_t *ch, size_t len,
245 const struct kmscon_glyph **out)
250 return find_glyph(id, out);
253 static int kmscon_font_unifont_render_inval(struct kmscon_font *font,
254 const struct kmscon_glyph **out)
256 return find_glyph(0xfffd, out);
259 static int kmscon_font_unifont_render_empty(struct kmscon_font *font,
260 const struct kmscon_glyph **out)
262 return find_glyph(' ', out);
265 struct kmscon_font_ops kmscon_font_unifont_ops = {
268 .init = kmscon_font_unifont_init,
269 .destroy = kmscon_font_unifont_destroy,
270 .render = kmscon_font_unifont_render,
271 .render_empty = kmscon_font_unifont_render_empty,
272 .render_inval = kmscon_font_unifont_render_inval,