summaryrefslogtreecommitdiff
path: root/src/libsystemd-terminal/unifont-def.h
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-07-18 17:34:03 +0200
committerDavid Herrmann <dh.herrmann@gmail.com>2014-07-18 17:45:33 +0200
commit86db5dfb6d334e583ea4161191754522ce850eed (patch)
tree5abc777472cb907b954f63e8523e95dfa494e974 /src/libsystemd-terminal/unifont-def.h
parent545149a2fc3523bbcbf3703fae3ae1ca5312f8c8 (diff)
terminal: add unifont font-handling
The unifont layer of libsystemd-terminal provides a fallback font for situations where no system-fonts are available, or if you don't want to deal with traditional font-formats for some reasons. The unifont API mmaps a pre-compiled bitmap font that was generated out of GNU-Unifont font-data. This guarantees, that all users of the font will share the pages in memory. Furthermore, the layout of the binary file allows accessing glyph data in O(1) without pre-rendering glyphs etc. That is, the OS can skip loading pages for glyphs that we never access. Note that this is currently a test-run and we want to include the binary file in the GNU-Unifont package. However, until it was considered stable and accepted by the maintainers, we will ship it as part of systemd. So far it's only enabled with the experimental --enable-terminal, anyway.
Diffstat (limited to 'src/libsystemd-terminal/unifont-def.h')
-rw-r--r--src/libsystemd-terminal/unifont-def.h137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/libsystemd-terminal/unifont-def.h b/src/libsystemd-terminal/unifont-def.h
new file mode 100644
index 0000000000..7a0d48505a
--- /dev/null
+++ b/src/libsystemd-terminal/unifont-def.h
@@ -0,0 +1,137 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright (C) 2014 David Herrmann <dh.herrmann@gmail.com>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "sparse-endian.h"
+#include "util.h"
+
+typedef struct unifont_header unifont_header;
+typedef struct unifont_glyph_header unifont_glyph_header;
+
+/*
+ * Unifont: On-disk data
+ * Conventional font-formats have the problem that you have to pre-render each
+ * glyph before you can use it. If you just need one glyph, you have to parse
+ * the font-file until you found that glyph.
+ * GNU-Unifont is a bitmap font with very good Unicode coverage. All glyphs are
+ * (n*8)x16 bitmaps. Our on-disk data stores all those glyphs pre-compiled with
+ * fixed offsets. Therefore, the font-file can be mmap()ed and all glyphs can
+ * be accessed in O(1) (because all glyphs have the same size and thus their
+ * offsets can be easily computed). This guarantees, that the kernel only loads
+ * the pages that are really accessed. Thus, we have a far lower overhead than
+ * traditional font-formats like BDF. Furthermore, the backing file is read-only
+ * and can be shared in memory between multiple users.
+ *
+ * The binary-format starts with a fixed header:
+ *
+ * | 2bytes | 2bytes | 2bytes | 2bytes |
+ *
+ * +-----------------------------------+
+ * | SIGNATURE | 8 bytes
+ * +-----------------+-----------------+
+ * | COMPAT FLAGS | INCOMPAT FLAGS | 8 bytes
+ * +-----------------+--------+--------+
+ * | HEADER SIZE |GH-SIZE |G-STRIDE| 8 bytes
+ * +-----------------+--------+--------+
+ * | GLYPH BODY SIZE | 8 bytes
+ * +-----------------------------------+
+ *
+ * * The 8 bytes signature must be set to the ASCII string "DVDHRMUF".
+ * * The 4 bytes compatible-flags field contains flags for new features that
+ * might be added in the future and which are compatible to older parsers.
+ * * The 4 bytes incompatible-flags field contains flags for new features that
+ * might be added in the future and which are incompatible to old parses.
+ * Thus, if you encounter an unknown bit set, you must abort!
+ * * The 4 bytes header-size field contains the size of the header in bytes. It
+ * must be at least 32 (the size of this fixed header). If new features are
+ * added, it might be increased. It can also be used to add padding to the
+ * end of the header.
+ * * The 2 bytes glyph-header-size field specifies the size of each glyph
+ * header in bytes (see below).
+ * * The 2 bytes glyph-stride field specifies the stride of each line of glyph
+ * data in "bytes per line".
+ * * The 8 byte glyph-body-size field defines the size of each glyph body in
+ * bytes.
+ *
+ * After the header, the file can contain padding bytes, depending on the
+ * header-size field. Everything beyond the header+padding is treated as a big
+ * array of glyphs. Each glyph looks like this:
+ *
+ * | 1 byte |
+ *
+ * +-----------------------------------+
+ * | WIDTH | 1 byte
+ * +-----------------------------------+
+ * ~ PADDING ~
+ * +-----------------------------------+
+ * ~ ~
+ * ~ ~
+ * ~ DATA ~
+ * ~ ~
+ * ~ ~
+ * +-----------------------------------+
+ *
+ * * The first byte specifies the width of the glyph. If it is 0, the glyph
+ * must be treated as non-existant.
+ * All glyphs are "8*n" pixels wide and "16" pixels high. The width-field
+ * specifies the width multiplier "n".
+ * * After the width field padding might be added. This depends on the global
+ * glyph-header-size field. It defines the total size of each glyph-header.
+ * After the glyph-header+padding, the data-field starts.
+ * * The data-field contains a byte-array of bitmap data. The array is always
+ * as big as specified in the global glyph-body-size header field. This might
+ * include padding.
+ * The array contains all 16 lines of bitmap information for that glyph. The
+ * stride is given in the global glyph-stride header field. This can be used
+ * to add padding after each line.
+ * Each line is encoded as 1 bit per pixel bitmap. That is, each byte encodes
+ * data for 8 pixels (left most pixel is encoded in the LSB, right most pixel
+ * in the MSB). The width field defines the number of bytes valid per line.
+ * For width==1, you need 1 byte to encode the 8 pixels. The stride defines
+ * where the encoding of the next line starts.
+ * Any data beyond the 16th line is padding and must be ignored.
+ */
+
+/* path to binary file */
+#define UNIFONT_PATH "/usr/share/unifont/unifont-glyph-array.bin"
+
+/* header-size of version 1 */
+#define UNIFONT_HEADER_SIZE_MIN 32
+
+struct unifont_header {
+ /* fields available in version 1 */
+ uint8_t signature[8];
+ le32_t compatible_flags;
+ le32_t incompatible_flags;
+ le32_t header_size;
+ le16_t glyph_header_size;
+ le16_t glyph_stride;
+ le64_t glyph_body_size;
+} _packed_;
+
+struct unifont_glyph_header {
+ /* fields available in version 1 */
+ uint8_t width;
+} _packed_;