diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-07-18 17:34:03 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-07-18 17:45:33 +0200 |
commit | 86db5dfb6d334e583ea4161191754522ce850eed (patch) | |
tree | 5abc777472cb907b954f63e8523e95dfa494e974 /src/libsystemd-terminal/unifont-def.h | |
parent | 545149a2fc3523bbcbf3703fae3ae1ca5312f8c8 (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.h | 137 |
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_; |