From ff238e62ba44bd749cc671d6b409f7203c46f15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 3 Sep 2021 20:44:22 +0200 Subject: [PATCH] fcft: adapt to API changes in fcft-3.x --- .builds/alpine-x64.yml | 5 +++ .gitlab-ci.yml | 20 +++++++++++ .woodpecker.yml | 1 + CHANGELOG.md | 2 +- PKGBUILD | 2 +- PKGBUILD.wayland-only | 2 +- char32.c | 78 ++++++++++++++++++++++++++++++++++++++++++ char32.h | 7 ++++ main.c | 5 +-- meson.build | 3 +- particles/string.c | 27 +++++++-------- 11 files changed, 131 insertions(+), 21 deletions(-) create mode 100644 char32.c create mode 100644 char32.h diff --git a/.builds/alpine-x64.yml b/.builds/alpine-x64.yml index a5d4e9c..687af0e 100644 --- a/.builds/alpine-x64.yml +++ b/.builds/alpine-x64.yml @@ -37,6 +37,11 @@ tasks: pip install codespell cd yambar ~/.local/bin/codespell README.md CHANGELOG.md *.c *.h doc/*.scd + - fcft: | + cd yambar/subprojects + git clone https://codeberg.org/dnkl/fcft.git + cd fcft && git checkout 3.0-dev && cd .. + cd ../.. - setup: | mkdir -p bld/debug bld/release bld/x11-only bld/wayland-only bld/plugs-are-shared meson --buildtype=debug -Db_coverage=true yambar bld/debug diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 06df201..e5762c1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,6 +27,10 @@ versions: debug: stage: build script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd fcft && git checkout 3.0-dev && cd .. + - cd .. - apk add gcovr - mkdir -p bld/debug - cd bld/debug @@ -55,6 +59,10 @@ debug: release: stage: build script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd fcft && git checkout 3.0-dev && cd .. + - cd .. - mkdir -p bld/release - cd bld/release - meson --buildtype=minsize ../../ @@ -64,6 +72,10 @@ release: x11_only: stage: build script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd fcft && git checkout 3.0-dev && cd .. + - cd .. - mkdir -p bld/debug - cd bld/debug - meson --buildtype=debug -Dbackend-x11=enabled -Dbackend-wayland=disabled ../../ @@ -73,6 +85,10 @@ x11_only: wayland_only: stage: build script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd fcft && git checkout 3.0-dev && cd .. + - cd .. - mkdir -p bld/debug - cd bld/debug - meson --buildtype=debug -Dbackend-x11=disabled -Dbackend-wayland=enabled ../../ @@ -82,6 +98,10 @@ wayland_only: plugins_as_shared_modules: stage: build script: + - cd subprojects + - git clone https://codeberg.org/dnkl/fcft.git + - cd fcft && git checkout 3.0-dev && cd .. + - cd .. - mkdir -p bld/debug - cd bld/debug - meson --buildtype=debug -Dcore-plugins-as-shared-libraries=true ../../ diff --git a/.woodpecker.yml b/.woodpecker.yml index 4ea84f1..7c0a7ba 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -22,6 +22,7 @@ pipeline: - mkdir -p subprojects && cd subprojects - git clone https://codeberg.org/dnkl/tllist.git - git clone https://codeberg.org/dnkl/fcft.git + - cd fcft && git checkout 3.0-dev && cd .. - cd .. x64: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a11471..5d47017 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ ### Changed +* fcft >= 3.0 is now required. * Made `libmpdclient` an optional dependency * battery: unknown battery states are now mapped to ‘unknown’, instead of ‘discharging’. @@ -85,7 +86,6 @@ * network: `ssid`, `signal`, `rx-bitrate` and `rx-bitrate` tags. * network: `poll-interval` option (for the new `signal` and `*-bitrate` tags). -* tags: percentage formatter, for range tags: `{tag_name:%}`. * tags: percentage tag formatter, for range tags: `{tag_name:%}`. * tags: kb/mb/gb, and kib/mib/gib tag formatters. * clock: add a config option to show UTC time. diff --git a/PKGBUILD b/PKGBUILD index e4b343b..42bf855 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -15,7 +15,7 @@ depends=( 'libudev.so' 'json-c' 'libmpdclient' - 'fcft>=2.4.0') + 'fcft>=3.0.0' 'fcft<4.0.0') optdepends=('xcb-util-errors: better X error messages') source=() diff --git a/PKGBUILD.wayland-only b/PKGBUILD.wayland-only index d0963e4..a3bbd5d 100644 --- a/PKGBUILD.wayland-only +++ b/PKGBUILD.wayland-only @@ -16,7 +16,7 @@ depends=( 'libudev.so' 'json-c' 'libmpdclient' - 'fcft>=2.4.0') + 'fcft>=3.0.0' 'fcft<4.0.0') source=() pkgver() { diff --git a/char32.c b/char32.c new file mode 100644 index 0000000..4673779 --- /dev/null +++ b/char32.c @@ -0,0 +1,78 @@ +#include "char32.h" + +#include +#include +#include + +#include + +#define LOG_MODULE "char32" +#define LOG_ENABLE_DBG 0 +#include "log.h" + +/* + * For now, assume we can map directly to the corresponding wchar_t + * functions. This is true if: + * + * - both data types have the same size + * - both use the same encoding (though we require that encoding to be UTF-32) + */ + +_Static_assert( + sizeof(wchar_t) == sizeof(char32_t), "wchar_t vs. char32_t size mismatch"); + +#if !defined(__STDC_UTF_32__) || !__STDC_UTF_32__ + #error "char32_t does not use UTF-32" +#endif +#if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__) + #error "wchar_t does not use UTF-32" +#endif + +size_t +c32len(const char32_t *s) +{ + return wcslen((const wchar_t *)s); +} + +char32_t * +ambstoc32(const char *src) +{ + if (src == NULL) + return NULL; + + const size_t src_len = strlen(src); + + char32_t *ret = malloc((src_len + 1) * sizeof(ret[0])); + if (ret == NULL) + return NULL; + + mbstate_t ps = {0}; + char32_t *out = ret; + const char *in = src; + const char *const end = src + src_len + 1; + + size_t chars = 0; + size_t rc; + + while ((rc = mbrtoc32(out, in, end - in, &ps)) != 0) { + switch (rc) { + case (size_t)-1: + case (size_t)-2: + case (size_t)-3: + goto err; + } + + in += rc; + out++; + chars++; + } + + *out = U'\0'; + + ret = realloc(ret, (chars + 1) * sizeof(ret[0])); + return ret; + +err: + free(ret); + return NULL; +} diff --git a/char32.h b/char32.h new file mode 100644 index 0000000..b01a7d3 --- /dev/null +++ b/char32.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include + +size_t c32len(const char32_t *s); +char32_t *ambstoc32(const char *src); diff --git a/main.c b/main.c index 49d3985..7aab81a 100644 --- a/main.c +++ b/main.c @@ -296,8 +296,9 @@ main(int argc, char *const *argv) "fcft log level enum offset"); _Static_assert((int)LOG_COLORIZE_ALWAYS == (int)FCFT_LOG_COLORIZE_ALWAYS, "fcft colorize enum mismatch"); - fcft_log_init( - (enum fcft_log_colorize)log_colorize, log_syslog, (enum fcft_log_class)log_level); + fcft_init((enum fcft_log_colorize)log_colorize, log_syslog, + (enum fcft_log_class)log_level); + atexit(&fcft_fini); const struct sigaction sa = {.sa_handler = &signal_handler}; sigaction(SIGINT, &sa, NULL); diff --git a/meson.build b/meson.build index 66f200c..7b4aa3b 100644 --- a/meson.build +++ b/meson.build @@ -71,7 +71,7 @@ backend_wayland = wayland_client.found() and wayland_cursor.found() # "My" dependencies, fallback to subproject tllist = dependency('tllist', version: '>=1.0.1', fallback: 'tllist') -fcft = dependency('fcft', version: ['>=2.4.0', '<3.0.0'], fallback: 'fcft') +fcft = dependency('fcft', version: ['>=3.0.0', '<4.0.0'], fallback: 'fcft') add_project_arguments( ['-D_GNU_SOURCE'] + @@ -111,6 +111,7 @@ version = custom_target( yambar = executable( 'yambar', + 'char32.c', 'char32.h', 'color.h', 'config-verify.c', 'config-verify.h', 'config.c', 'config.h', diff --git a/particles/string.c b/particles/string.c index f6083f6..c5ade9f 100644 --- a/particles/string.c +++ b/particles/string.c @@ -5,6 +5,7 @@ #define LOG_MODULE "string" #define LOG_ENABLE_DBG 0 #include "../log.h" +#include "../char32.h" #include "../config.h" #include "../config-verify.h" #include "../particle.h" @@ -87,7 +88,7 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int * its descent. This way, the part of the font *above* the * baseline is centered. * - * "EEEE" will typically be dead center, with the middle of each character being in the bar's center. + * "EEEE" will typically be dead center, with the middle of each character being in the bar's center. * "eee" will be slightly below the center. * "jjj" will be even further below the center. * @@ -149,7 +150,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) struct eprivate *e = calloc(1, sizeof(*e)); struct fcft_font *font = particle->font; - wchar_t *wtext = NULL; + char32_t *wtext = NULL; char *text = tags_expand_template(p->text, tags); e->glyphs = e->allocated_glyphs = NULL; @@ -173,17 +174,13 @@ instantiate(const struct particle *particle, const struct tag_set *tags) } } - /* Not in cache - we need to rasterize it. First, convert to wchar */ - size_t chars = mbstowcs(NULL, text, 0); - if (chars == (size_t)-1) - goto done; - - wtext = malloc((chars + 1) * sizeof(wtext[0])); - mbstowcs(wtext, text, chars + 1); + /* Not in cache - we need to rasterize it. First, convert to char32_t */ + wtext = ambstoc32(text); + size_t chars = c32len(wtext); /* Truncate, if necessary */ if (p->max_len > 0) { - const size_t len = wcslen(wtext); + const size_t len = c32len(wtext); if (len > p->max_len) { size_t end = p->max_len; @@ -193,11 +190,11 @@ instantiate(const struct particle *particle, const struct tag_set *tags) } if (p->max_len > 1) { - wtext[end] = L'…'; - wtext[end + 1] = L'\0'; + wtext[end] = U'…'; + wtext[end + 1] = U'\0'; chars = end + 1; } else { - wtext[end] = L'\0'; + wtext[end] = U'\0'; chars = 0; } } @@ -206,7 +203,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) e->kern_x = calloc(chars, sizeof(e->kern_x[0])); if (fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING) { - struct fcft_text_run *run = fcft_text_run_rasterize( + struct fcft_text_run *run = fcft_rasterize_text_run_utf32( font, chars, wtext, FCFT_SUBPIXEL_NONE); if (run != NULL) { @@ -250,7 +247,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags) /* Convert text to glyph masks/images. */ for (size_t i = 0; i < chars; i++) { - const struct fcft_glyph *glyph = fcft_glyph_rasterize( + const struct fcft_glyph *glyph = fcft_rasterize_char_utf32( font, wtext[i], FCFT_SUBPIXEL_NONE); if (glyph == NULL)