[systemd-devel] [RFC 05/12] gfx: add sd-gfx library with unifont section

Shawn Landden shawn at churchofgit.com
Mon Dec 2 07:26:20 PST 2013


On Wed, Nov 27, 2013 at 10:48 AM, David Herrmann <dh.herrmann at gmail.com> wrote:
> If we want to interact with a user in the initrd, during
> emergency-situations, in single-user mode, or in any other rather limited
> situation, we currently rely on the kernel to do input and graphics access
> for us. More precisely, we rely on the VT layer to do keyboard parsing and
> font rendering. Or in other words: The *kernel* provides our UI!
>
> This is bad for the same reasons we don't put any other UI into the
> kernel. However, there are a few reasons to keep a minimal UI in the
> kernel:
>  1) show panic-screen with kernel oops message
>  2) show log-screen during early boot
>  3) allow kernel-debugging via kdb
> While people using kdb are encouraged to keep VTs, for 1) and 2) there is
> a replacement via fblog/drmlog.
>
> So we run out of reasons to keep a UI in the kernel. However, to allow
> moving the UI handling to userspace, we need a bunch of helpers:
>  - keyboard handling: convert keycodes into keysyms and modifiers/..
>  - modesetting: program the gfx pipeline and provide a rendering
>                 infrastructure
>  - fonts: to render text, we need some basic fonts
>  - hotplugging: device detection and assignment during runtime
> (Note that all these are implemented (often quite rudimentary) in the
> kernel to allow a basic UI.)
>
> This patch introduces sd-gfx, a systemd-internal library dealing with all
> these things. Note that it is designed to be exported some day, but for
> now we keep it internal.
> While the library itself will be kept small and almost self-contained, it
> is designed to be extensible and can be used in rather complex graphics
> applications. For systemd, we plan to add a basic emergency-console, an
> initrd password-query, kernel-log-screen and a fallback login-screen.
> These allow booting without CONFIG_VT and provide a basic system for
> seats without VTs (either CONFIT_VT=n or seats != seat0).
>
> As a first step, we add the required header+build-chain and add the
> font-handling. To avoid heavy font-pipelines in systemd, we only provide
> a statically-sized fallback-font based on GNU-Unifont. It contains glyphs
> for the *whole* Base-Multilingual-Plane of Unicode and thus allows
> internationalized text.
>
> The "make-unifont.py" script is used by the "make update-unifont" custom
> target to regenerate the unifont files. As this can take quite some time,
> we check the result into git so only maintainers need to run this.
>
> The binary file contains all glyphs in a compressed 1-bit-per-pixel format
> for all 8x16 and 16x16 glyphs. It is linked directly into libsystemd-gfx
> via the *.bin makefile target. Binary size is 2.1MB, but thanks to paging,
> the kernel only loads required pages into memory. A ASCII-only screen thus
> only needs 40k VIRT mem.
Do we have quad-glyphs (16x32) for the ASCII part of this for hi-res screens?

(also, if we use NFD we could reuse these for some of unicode[1], but
that is less important)

[1]http://blog.golang.org/normalization
> ---
> Hi
>
> I removed the unifont-data from this patch so this will not apply cleanly.
> However, the ML would reject the huge patch otherwise. If anyone is interested
> in the raw patch, the series is available on:
>   http://cgit.freedesktop.org/~dvdhrm/systemd/log/?h=console
>
> Thanks
> David
>
>  Makefile.am                      |    31 +
>  configure.ac                     |    10 +
>  make-unifont.py                  |   138 +
>  src/libsystemd-gfx/.gitignore    |     1 +
>  src/libsystemd-gfx/Makefile      |     1 +
>  src/libsystemd-gfx/gfx-unifont.c |   273 +
>  src/libsystemd-gfx/unifont.bin   |   Bin 0 -> 2162688 bytes
>  src/libsystemd-gfx/unifont.hex   | 63488 +++++++++++++++++++++++++++++++++++++
>  src/systemd/sd-gfx.h             |    65 +
>  9 files changed, 64007 insertions(+)
>  create mode 100755 make-unifont.py
>  create mode 100644 src/libsystemd-gfx/.gitignore
>  create mode 120000 src/libsystemd-gfx/Makefile
>  create mode 100644 src/libsystemd-gfx/gfx-unifont.c
>  create mode 100644 src/libsystemd-gfx/unifont.bin
>  create mode 100644 src/libsystemd-gfx/unifont.hex
>  create mode 100644 src/systemd/sd-gfx.h
>
> diff --git a/Makefile.am b/Makefile.am
> index ce27e82..2edb091 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -3853,6 +3853,37 @@ EXTRA_DIST += \
>  endif
>
>  # ------------------------------------------------------------------------------
> +if HAVE_GFX
> +noinst_LTLIBRARIES += \
> +       libsystemd-gfx.la
> +
> +libsystemd_gfx_la_SOURCES = \
> +       src/libsystemd-gfx/sd-gfx.h \
> +       src/libsystemd-gfx/gfx-unifont.c
> +
> +libsystemd_gfx_la_CFLAGS = \
> +       $(AM_CFLAGS)
> +
> +libsystemd_gfx_la_LIBADD = \
> +       libsystemd-shared.la \
> +       src/libsystemd-gfx/unifont.bin.lo
> +
> +src/libsystemd-gfx/unifont.bin: make-unifont.py src/libsystemd-gfx/unifont.hex
> +       $(AM_V_GEN)cat $(top_srcdir)/src/libsystemd-gfx/unifont.hex | $(PYTHON) $< >$@
> +
> +src/libsystemd-gfx/unifont.cmp: make-unifont.py src/libsystemd-gfx/unifont.bin
> +       $(AM_V_GEN)cat $(top_srcdir)/src/libsystemd-gfx/unifont.bin | $(PYTHON) $< verify >$@
> +
> +update-unifont: src/libsystemd-gfx/unifont.bin src/libsystemd-gfx/unifont.cmp
> +       @RET=`diff -u src/libsystemd-gfx/unifont.hex src/libsystemd-gfx/unifont.cmp | wc -l` ; \
> +               if test "x$$?" != "x0" -o "x$$RET" != "x0" ; then \
> +                       echo "Generated Unifont-file differs from original; generator probably broken" ; \
> +                       exit 1 ; \
> +               fi
> +       @echo "unifont.bin has been regenerated"
> +endif
> +
> +# ------------------------------------------------------------------------------
>  if ENABLE_NETWORKD
>  rootlibexec_PROGRAMS += \
>         systemd-networkd
> diff --git a/configure.ac b/configure.ac
> index 3fd05da..354673a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -291,6 +291,15 @@ fi
>  AM_CONDITIONAL(HAVE_KMOD, [test "$have_kmod" = "yes"])
>
>  # ------------------------------------------------------------------------------
> +have_gfx=no
> +AC_ARG_ENABLE(gfx, AS_HELP_STRING([--disable-gfx], [disable sd-gfx graphics and input support]))
> +if test "x$enable_gfx" != "xno"; then
> +        AC_DEFINE(HAVE_GFX, 1, [Define if sd-gfx is built])
> +        have_gfx=yes
> +fi
> +AM_CONDITIONAL(HAVE_GFX, [test "$have_gfx" = "yes"])
> +
> +# ------------------------------------------------------------------------------
>  have_blkid=no
>  AC_ARG_ENABLE(blkid, AS_HELP_STRING([--disable-blkid], [disable blkid support]))
>  if test "x$enable_blkid" != "xno"; then
> @@ -1079,6 +1088,7 @@ AC_MSG_RESULT([
>          polkit:                  ${have_polkit}
>          efi:                     ${have_efi}
>          kmod:                    ${have_kmod}
> +        sd-gfx:                  ${have_gfx}
>          blkid:                   ${have_blkid}
>          nss-myhostname:          ${have_myhostname}
>          gudev:                   ${enable_gudev}
> diff --git a/make-unifont.py b/make-unifont.py
> new file mode 100755
> index 0000000..375c8a4
> --- /dev/null
> +++ b/make-unifont.py
> @@ -0,0 +1,138 @@
> +#  -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
> +#
> +#  This file is part of systemd.
> +#
> +#  Copyright 2013 David Herrmann <dh.herrmann at 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/>.
> +
> +#
> +# Parse a unifont.hex file and produce a compressed binary-format we use in
> +# our gfx applications. Can also do the reverse to verify correctness.
> +#
> +
> +from __future__ import print_function
> +import re
> +import sys
> +import fileinput
> +import struct
> +
> +#
> +# Write "bits" array as binary output.
> +#
> +
> +def write_bin_entry(entry):
> +    l = len(entry)
> +    if l != 32 and l != 64:
> +        entry = "0" * 64
> +        l = 0
> +    elif l < 64:
> +        entry += "0" * (64 - l)
> +
> +    sys.stdout.buffer.write(struct.pack('B', int(l / 32)))
> +
> +    for i in range(0, 64, 2):
> +        c = int(entry[i:i+2], 16)
> +        sys.stdout.buffer.write(struct.pack('B', c))
> +
> +def write_bin(bits):
> +    for idx in range(len(bits)):
> +        write_bin_entry(bits[idx])
> +
> +#
> +# Parse hex file into "bits" array
> +#
> +
> +def parse_hex_line(bits, line):
> +    m = re.match(r"^([0-9A-Fa-f]+):([0-9A-Fa-f]+)$", line)
> +    if m == None:
> +        return
> +
> +    idx = int(m.group(1), 16)
> +    val = m.group(2)
> +
> +    # insert skipped lines
> +    for i in range(len(bits), idx):
> +        bits.append("")
> +
> +    bits.insert(idx, val)
> +
> +def parse_hex():
> +    bits = []
> +
> +    for line in sys.stdin:
> +        if not line:
> +            continue
> +        if line.startswith("#"):
> +            continue
> +
> +        parse_hex_line(bits, line)
> +
> +    return bits
> +
> +#
> +# Write "bits" array as text-file line-by-line to stdout.
> +#
> +
> +def write_hex_line(idx, entry):
> +    if entry:
> +        print("%04X:%s" % (idx, entry))
> +
> +def write_hex(bits):
> +    for idx, entry in enumerate(bits):
> +        if not entry:
> +            continue
> +
> +        write_hex_line(idx, entry)
> +
> +#
> +# Parse a binary file into "bits" so we can verify the correctness of a given
> +# binary file.
> +#
> +
> +def parse_bin_entry(bits, chunk):
> +    entry = ""
> +    l = struct.unpack('B', chunk[0:1])[0]
> +    for c in chunk[1:l*16+1]:
> +        entry += format(c, "02X")
> +
> +    bits.append(entry)
> +
> +def parse_bin():
> +    bits = []
> +
> +    while True:
> +        chunk = sys.stdin.buffer.read(33)
> +        if chunk:
> +            parse_bin_entry(bits, chunk)
> +        else:
> +            break
> +
> +    return bits
> +
> +#
> +# In normal mode we simply read line by line from standard-input (or first
> +# argument) and write the binary-file to standard-output.
> +#
> +# In verify-mode, we read the binary-file from standard-input and write the
> +# text-file line-by-line to standard-output.
> +#
> +
> +if __name__ == "__main__":
> +    if len(sys.argv) > 1 and sys.argv[1] == "verify":
> +        bits = parse_bin()
> +        write_hex(bits)
> +    else:
> +        bits = parse_hex()
> +        write_bin(bits)
> diff --git a/src/libsystemd-gfx/.gitignore b/src/libsystemd-gfx/.gitignore
> new file mode 100644
> index 0000000..a792d8f
> --- /dev/null
> +++ b/src/libsystemd-gfx/.gitignore
> @@ -0,0 +1 @@
> +/unifont.cmp
> diff --git a/src/libsystemd-gfx/Makefile b/src/libsystemd-gfx/Makefile
> new file mode 120000
> index 0000000..d0b0e8e
> --- /dev/null
> +++ b/src/libsystemd-gfx/Makefile
> @@ -0,0 +1 @@
> +../Makefile
> \ No newline at end of file
> diff --git a/src/libsystemd-gfx/gfx-unifont.c b/src/libsystemd-gfx/gfx-unifont.c
> new file mode 100644
> index 0000000..c2fc879
> --- /dev/null
> +++ b/src/libsystemd-gfx/gfx-unifont.c
> @@ -0,0 +1,273 @@
> +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
> +
> +/***
> +  This file is part of systemd.
> +
> +  Copyright 2013 David Herrmann <dh.herrmann at 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/>.
> +***/
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <inttypes.h>
> +#include <stdbool.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +
> +#include "def.h"
> +#include "hashmap.h"
> +#include "log.h"
> +#include "macro.h"
> +#include "sd-gfx.h"
> +#include "util.h"
> +
> +/* Glyphs are linked as binary data. The data layout is a size-byte followed by
> + * 32 data bytes. The data bytes are padded with 0 if the size is smaller than
> + * 32. The size-byte specifies the size of a single line. Each glyph always
> + * consists of 16 lines.
> + * Currently, size==1 is used for single-width glyphs and size==2 for
> + * double-width glyphs. */
> +
> +struct unifont_data {
> +        uint8_t cells;
> +        uint8_t data[32];
> +} _packed_;
> +
> +extern const struct unifont_data _binary_src_libsystemd_gfx_unifont_bin_start[];
> +extern const struct unifont_data _binary_src_libsystemd_gfx_unifont_bin_end[];
> +static const unsigned int unifont_width = 8;
> +static const unsigned int unifont_stride = 1;
> +static const unsigned int unifont_max_cells = 2;
> +static const unsigned int unifont_height = 16;
> +
> +static const struct unifont_data unifont_fallback = {
> +        .cells = 1,
> +        .data = "\x00\x00\x00\x7E\x66\x5A\x5A\x7A\x76\x76\x7E\x76\x76\x7E\x00\x00",
> +};
> +
> +static const struct unifont_data *unifont_get(uint32_t ucs4) {
> +        const struct unifont_data *begin, *end, *g;
> +
> +        begin = _binary_src_libsystemd_gfx_unifont_bin_start;
> +        end = _binary_src_libsystemd_gfx_unifont_bin_end;
> +
> +        g = &begin[ucs4];
> +        if (g >= end)
> +                return &unifont_fallback;
> +        if (g->cells == 0 || g->cells > unifont_max_cells)
> +                return &unifont_fallback;
> +
> +        return g;
> +}
> +
> +/*
> + * Fonts
> + * We provide a built-in static font. This can be used to render text in any
> + * situation without depending on huge text-pipelines like pango. The font is
> + * based on "GNU Unifont" which provides fixed-size glyphs for the whole
> + * Unicode Basic Multilingual Plane.
> + * This can be used in initrds, emergency-consoles and other situations where a
> + * full text-pipeline would be overkill.
> + *
> + * Note that we provide some enhanced features to properly support all systems.
> + * This currently includes:
> + *  - scaling: You can specify a "ppi" value to scale the static fonts. This
> + *             can only be done with integer-scaling and should only be used
> + *             as reading-aid or for high-DPI screens.
> + *  - combining: Glyph-combining (eg., for unicode combining characters) is
> + *               implemented in the renderer to correctly draw combined
> + *               characters for non-latin scripts. Character-combining is left
> + *               to the caller, we only allow drawing a set of characters as a
> + *               single glyph.
> + *  - caching: To support fast lookups we cache modified glyphs.
> + */
> +
> +typedef struct gfx_glyph gfx_glyph;
> +
> +struct gfx_glyph {
> +        sd_gfx_buffer buf;
> +};
> +
> +struct sd_gfx_font {
> +        unsigned int ppi;
> +        unsigned int width;
> +        unsigned int height;
> +        Hashmap *glyphs;
> +
> +        gfx_glyph fallback;
> +};
> +
> +static void gfx_glyph_blend(gfx_glyph *g, unsigned int ppi, const struct unifont_data *u) {
> +        unsigned int i, j;
> +        const uint8_t *src;
> +        uint8_t *dst;
> +
> +        /*
> +         * TODO: scale glyph according to @ppi
> +         */
> +
> +        src = u->data;
> +        dst = g->buf.data;
> +
> +        for (i = 0; i < unifont_height; ++i) {
> +                for (j = 0; j < u->cells; ++j)
> +                        dst[j] |= src[j];
> +
> +                src += u->cells * unifont_stride;
> +                dst += g->buf.stride;
> +        }
> +}
> +
> +static int gfx_glyph_render(gfx_glyph *g, unsigned int ppi, const struct unifont_data *u) {
> +        g->buf.width = u->cells * unifont_width;
> +        g->buf.height = unifont_height;
> +        g->buf.stride = u->cells * unifont_stride;
> +        g->buf.format = SD_GFX_BUFFER_FORMAT_A1;
> +
> +        g->buf.data = calloc(unifont_height, unifont_max_cells * unifont_stride);
> +        if (!g->buf.data)
> +                return -ENOMEM;
> +
> +        gfx_glyph_blend(g, ppi, u);
> +        return 0;
> +}
> +
> +int sd_gfx_font_new(sd_gfx_font **out, unsigned int ppi) {
> +        sd_gfx_font *font;
> +        int r;
> +
> +        ppi = CLAMP(ppi, 10U, 1000U);
> +
> +        font = calloc(1, sizeof(*font));
> +        if (!font)
> +                return log_oom();
> +
> +        font->ppi = ppi;
> +        font->width = unifont_width;
> +        font->height = unifont_height;
> +
> +        font->glyphs = hashmap_new(trivial_hash_func, trivial_compare_func);
> +        if (!font->glyphs) {
> +                free(font);
> +                return log_oom();
> +        }
> +
> +        r = gfx_glyph_render(&font->fallback, font->ppi, &unifont_fallback);
> +        if (r < 0) {
> +                hashmap_free(font->glyphs);
> +                free(font);
> +                return log_oom();
> +        }
> +
> +        *out = font;
> +        return 0;
> +}
> +
> +static void gfx_glyph_free(gfx_glyph *g) {
> +        free(g->buf.data);
> +        free(g);
> +}
> +
> +void sd_gfx_font_free(sd_gfx_font *font) {
> +        gfx_glyph *g;
> +
> +        if (!font)
> +                return;
> +
> +        while ((g = hashmap_steal_first(font->glyphs)))
> +                gfx_glyph_free(g);
> +
> +        hashmap_free(font->glyphs);
> +        free(font);
> +}
> +
> +unsigned int sd_gfx_font_get_ppi(sd_gfx_font *font) {
> +        return font->ppi;
> +}
> +
> +unsigned int sd_gfx_font_get_width(sd_gfx_font *font) {
> +        return font->width;
> +}
> +
> +unsigned int sd_gfx_font_get_height(sd_gfx_font *font) {
> +        return font->height;
> +}
> +
> +/*
> + * Render a glyph
> + * This first tries to look up the glyph in the cache. If found, it is returned,
> + * otherwise the glyph is rendered and put into the cache.
> + *
> + * This function never fails. If the glyph cannot be rendered, a fallback glyph
> + * is returned. Note that this function can render multiple glyphs into a single
> + * buffer. You simply have to pass multiple codepoints via @ucs4 / @len.
> + * However, this should only be used for combining-characters.
> + *
> + * Whenever you render a glyph, this functions needs a unique ID to identify it.
> + * You have to pass it via @id. If you render only a single codepoint, simply
> + * pass the codepoint as @id (or pass 0 in which case the first codepoint is
> + * automatically taken as id). But if you render combined codepoints, you need
> + * to allocate a unique ID for them. See libtsm for an example how to do that.
> + *
> + * The lifetime of the returned buffer is bound to @font. You don't have to free
> + * it yourself.
> + */
> +void sd_gfx_font_render(sd_gfx_font *font, uint32_t id, const uint32_t *ucs4, size_t len, sd_gfx_buffer **out) {
> +        const struct unifont_data *u;
> +        gfx_glyph *g;
> +
> +        if (!len)
> +                goto error;
> +
> +        if (!id)
> +                id = *ucs4;
> +
> +        g = hashmap_get(font->glyphs, INT_TO_PTR(id));
> +        if (g)
> +                goto out;
> +
> +        g = calloc(1, sizeof(*g));
> +        if (!g) {
> +                log_oom();
> +                goto error;
> +        }
> +
> +        u = unifont_get(*ucs4);
> +        if (gfx_glyph_render(g, font->ppi, u) < 0) {
> +                log_oom();
> +                free(g);
> +                goto error;
> +        }
> +
> +        while (--len) {
> +                u = unifont_get(*++ucs4);
> +                gfx_glyph_blend(g, font->ppi, u);
> +        }
> +
> +        if (hashmap_put(font->glyphs, INT_TO_PTR(id), g) < 0) {
> +                log_oom();
> +                free(g->buf.data);
> +                free(g);
> +                goto error;
> +        }
> +
> +        goto out;
> +
> +error:
> +        g = &font->fallback;
> +out:
> +        *out = &g->buf;
> +}
> diff --git a/src/libsystemd-gfx/unifont.bin b/src/libsystemd-gfx/unifont.bin
> new file mode 100644
> index 0000000000000000000000000000000000000000..0b32d80222dd465d0612188915ef67355dc73e4d
> GIT binary patch
> literal 2162688
> z9F*YJIJ$6q>;c^VB)T=i&<gm^zxN+SppMS|-OpAY!~fZzt8D^U-P?cj(n~*i<Be_n
>
> [... skipped for ML ...]
>
> h<$hpdYOEeTz{h7Yzz4==k?}x2v&LpIyNUqW`UBL12zCGf
>
> literal 0
> HcmV?d00001
>
> diff --git a/src/libsystemd-gfx/unifont.hex b/src/libsystemd-gfx/unifont.hex
> new file mode 100644
> index 0000000..90672a8
> --- /dev/null
> +++ b/src/libsystemd-gfx/unifont.hex
> @@ -0,0 +1,63488 @@
> +0000:AAAA00018000000180004A51EA505A51C99E0001800000018000000180005555
> +0001:AAAA00018000000180003993C252325F8A527193800000018000000180005555
>
> [... skipped for ML ...]
>
> +FFFE:FFFFFFFFE187EFBFE38FEFBFEFBFFFFFFFFFE187EFBFE38FEFBFEF87FFFFFFFF
> +FFFF:FFFFFFFFE187EFBFE38FEFBFEFBFFFFFFFFFE187EFBFE38FEFBFEFBFFFFFFFFF
> diff --git a/src/systemd/sd-gfx.h b/src/systemd/sd-gfx.h
> new file mode 100644
> index 0000000..c46fbd4
> --- /dev/null
> +++ b/src/systemd/sd-gfx.h
> @@ -0,0 +1,65 @@
> +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
> +
> +#ifndef foosdgfxhfoo
> +#define foosdgfxhfoo
> +
> +/***
> +  This file is part of systemd.
> +
> +  Copyright 2013 David Herrmann <dh.herrmann at 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/>.
> +***/
> +
> +#include <errno.h>
> +#include <inttypes.h>
> +#include <stdbool.h>
> +#include <stdlib.h>
> +#include <systemd/_sd-common.h>
> +
> +_SD_BEGIN_DECLARATIONS;
> +
> +typedef struct sd_gfx_buffer sd_gfx_buffer;
> +typedef struct sd_gfx_font sd_gfx_font;
> +
> +/* memory buffer */
> +
> +enum {
> +        SD_GFX_BUFFER_FORMAT_A1,
> +        SD_GFX_BUFFER_FORMAT_A8,
> +        SD_GFX_BUFFER_FORMAT_XRGB8888,
> +};
> +
> +struct sd_gfx_buffer {
> +        unsigned int width;
> +        unsigned int height;
> +        int stride;
> +        unsigned int format;
> +        void *data;
> +};
> +
> +/* unifont */
> +
> +int sd_gfx_font_new(sd_gfx_font **out, unsigned int ppi);
> +void sd_gfx_font_free(sd_gfx_font *font);
> +
> +unsigned int sd_gfx_font_get_ppi(sd_gfx_font *font);
> +unsigned int sd_gfx_font_get_width(sd_gfx_font *font);
> +unsigned int sd_gfx_font_get_height(sd_gfx_font *font);
> +
> +void sd_gfx_font_render(sd_gfx_font *font, uint32_t id, const uint32_t *ucs4, size_t len, sd_gfx_buffer **out);
> +
> +_SD_END_DECLARATIONS;
> +
> +#endif
> --
> 1.8.4.2
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel


More information about the systemd-devel mailing list