summaryrefslogtreecommitdiff
path: root/src/libsystemd-terminal/unifont-def.h
blob: 2b0b859eb095d5d62631ac18dbf03243fa4cca42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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/systemd/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_;