diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b3a6f1a..2c4aa7a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install dependencies - run: apk update && apk add meson wayland-dev musl-dev wayland-protocols gcc inih-dev cmocka-dev + run: apk update && apk add meson wayland-dev musl-dev wayland-protocols gcc inih-dev cmocka-dev freetype-dev - name: Run tests run: meson setup test && ninja -C test test @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install dependencies - run: apk update && apk add meson wayland-dev musl-dev wayland-protocols gcc inih-dev cmocka-dev clang19 clang19-extra-tools clang19-analyzer + run: apk update && apk add meson wayland-dev musl-dev wayland-protocols gcc inih-dev cmocka-dev freetype-dev clang19 clang19-extra-tools clang19-analyzer - name: Run clang-analyzer if: success() || failure() run: scan-build meson setup clang-analyzer && scan-build --status-bugs ninja -C clang-analyzer diff --git a/meson.build b/meson.build index ae47c15..2697a64 100644 --- a/meson.build +++ b/meson.build @@ -38,17 +38,17 @@ rt = cc.find_library('rt') libm = cc.find_library('m') seccomp = dependency('libseccomp', required: get_option('seccomp')) inih = dependency('inih') +freetype2 = dependency('freetype2', required: get_option('text')) sysconfdir = get_option('sysconfdir') if not fs.is_absolute(sysconfdir) sysconfdir = prefix / sysconfdir endif -global_configuration_h = configuration_data({ - 'WOB_VERSION': '"@0@"'.format(meson.project_version()), - 'WOB_ETC_CONFIG_FOLDER_PATH': '"@0@"'.format(sysconfdir), -}) -configure_file(output: 'global_configuration.h', configuration: global_configuration_h) +global_configuration_h = configuration_data() + +global_configuration_h.set_quoted('WOB_VERSION', meson.project_version()) +global_configuration_h.set_quoted('WOB_ETC_CONFIG_FOLDER_PATH', sysconfdir) wayland_scanner_code = generator( wayland_scanner, @@ -87,11 +87,23 @@ endforeach wob_sources = ['src/main.c', 'src/image.c', 'src/log.c', 'src/color.c', 'src/config.c', 'src/wob.c', 'src/shm.c', wl_proto_src, wl_proto_headers] wob_dependencies = [wayland_client, rt, inih, libm] + if seccomp.found() wob_dependencies += seccomp wob_sources += 'src/pledge_seccomp.c' + global_configuration_h.set('WOB_PLEDGE_ENABLED', 'true') else wob_sources += 'src/pledge.c' + global_configuration_h.set('WOB_PLEDGE_ENABLED', 'false') +endif + +if freetype2.found() + wob_dependencies += freetype2 + wob_sources += 'src/font_freetype.c' + global_configuration_h.set('WOB_TEXT_ENABLED', 'true') +else + wob_sources += 'src/font_stub.c' + global_configuration_h.set('WOB_TEXT_ENABLED', 'false') endif executable( @@ -146,3 +158,5 @@ if get_option('systemd-unit-files').enabled() ) install_data('etc/systemd/wob.socket', install_dir: systemd_unit_dir) endif + +configure_file(output: 'global_configuration.h', configuration: global_configuration_h) diff --git a/meson_options.txt b/meson_options.txt index 99f1ca9..4ca33ae 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,3 +2,4 @@ option('man-pages', type: 'feature', value: 'auto', description: 'Generate and i option('seccomp', type: 'feature', value: 'auto', description: 'Use seccomp on Linux') option('tests', type: 'feature', value: 'auto', description: 'Build tests') option('systemd-unit-files', type: 'feature', value: 'enabled', description: 'Install systemd unit files') +option('text', type: 'feature', value: 'auto', description: 'Build with freetype2 text rendering') diff --git a/src/color.c b/src/color.c index 9538a32..d0e28a4 100644 --- a/src/color.c +++ b/src/color.c @@ -8,6 +8,32 @@ #include "color.h" +struct wob_color +wob_color_from_argb8888(uint32_t argb) +{ + struct wob_color result = { + .a = (float) (argb >> 24 & 0xFF) / 255.0f, + .r = (float) (argb >> 16 & 0xFF) / 255.0f, + .g = (float) (argb >> 8 & 0xFF) / 255.0f, + .b = (float) (argb & 0xFF) / 255.0f, + }; + + return result; +} + +struct wob_color +wob_color_blend_premultiplied(struct wob_color foreground, struct wob_color background) +{ + struct wob_color result = { + .a = foreground.a + background.a * (1 - foreground.a), + .r = foreground.r + background.r * (1 - foreground.a), + .b = foreground.b + background.b * (1 - foreground.a), + .g = foreground.g + background.g * (1 - foreground.a), + }; + + return result; +} + uint32_t wob_color_to_argb(const struct wob_color color) { @@ -63,22 +89,36 @@ bool wob_color_from_rgba_string(const char *str, struct wob_color *color) { unsigned long length = strlen(str); - for (const char *c = str; *c != '\0'; ++c) { - if (!isxdigit(*c)) { - return false; - } - } uint8_t parts[4]; parts[3] = 0xFF; switch (length) { case 8: - parts[3] = hex_to_int(str[6]) * 16 + hex_to_int(str[7]); + int p6 = hex_to_int(str[6]); + int p7 = hex_to_int(str[7]); + + if (p6 < 0 || p7 < 0) { + return false; + } + + parts[3] = p6 * 16 + p7; // fallthrough case 6: - parts[0] = hex_to_int(str[0]) * 16 + hex_to_int(str[1]); - parts[1] = hex_to_int(str[2]) * 16 + hex_to_int(str[3]); - parts[2] = hex_to_int(str[4]) * 16 + hex_to_int(str[5]); + int p0 = hex_to_int(str[0]); + int p1 = hex_to_int(str[1]); + int p2 = hex_to_int(str[2]); + int p3 = hex_to_int(str[3]); + int p4 = hex_to_int(str[4]); + int p5 = hex_to_int(str[5]); + + if (p0 < 0 || p1 < 0 || p2 < 0 || p3 < 0 || p4 < 0 || p5 < 0) { + return false; + } + + parts[0] = p0 * 16 + p1; + parts[1] = p2 * 16 + p3; + parts[2] = p4 * 16 + p5; + break; default: return false; diff --git a/src/color.h b/src/color.h index e926d46..69136f7 100644 --- a/src/color.h +++ b/src/color.h @@ -14,6 +14,10 @@ struct wob_color { float b; }; +struct wob_color wob_color_from_argb8888(uint32_t argb); + +struct wob_color wob_color_blend_premultiplied(struct wob_color foreground, struct wob_color background); + uint32_t wob_color_to_argb(struct wob_color color); uint32_t wob_color_to_rgba(struct wob_color color); diff --git a/src/config.c b/src/config.c index 9defe24..7825f65 100644 --- a/src/config.c +++ b/src/config.c @@ -306,6 +306,18 @@ handler(void *user, const char *section, const char *name, const char *value) } return 1; } + if (strcmp(name, "font") == 0) { + config->font_path = strdup(value); + return 1; + } + if (strcmp(name, "font_size") == 0) { + if (parse_number(value, &ul) == false) { + wob_log_error("Font size must be a positive value."); + return 0; + } + config->font_size = ul; + return 1; + } wob_log_warn("Unknown config key %s", name); return 1; @@ -389,6 +401,14 @@ handler(void *user, const char *section, const char *name, const char *value) output_config->dimensions.bar_padding = ul; return 1; } + if (strcmp(name, "font_size") == 0) { + if (parse_number(value, &ul) == false) { + wob_log_error("Font size must be a positive value."); + return 0; + } + output_config->font_size = ul; + return 1; + } wob_log_warn("Unknown config key %s", name); return 1; @@ -512,6 +532,8 @@ wob_config_create() config->margin = (struct wob_margin) {.top = 0, .left = 0, .bottom = 0, .right = 0}; config->anchor = WOB_ANCHOR_CENTER; config->overflow_mode = WOB_OVERFLOW_MODE_WRAP; + config->font_path = NULL; + config->font_size = 16; config->default_style.colors.background = (struct wob_color) {.a = 1.0f, .r = 0.0f, .g = 0.0f, .b = 0.0f}; config->default_style.colors.value = (struct wob_color) {.a = 1.0f, .r = 1.0f, .g = 1.0f, .b = 1.0f}; config->default_style.colors.border = (struct wob_color) {.a = 1.0f, .r = 1.0f, .g = 1.0f, .b = 1.0f}; @@ -585,6 +607,8 @@ wob_config_debug(struct wob_config *config) wob_log_debug("config.overflow_colors.background = " WOB_COLOR_PRINTF_FORMAT, WOB_COLOR_PRINTF_RGBA(config->default_style.overflow_colors.background)); wob_log_debug("config.overflow_colors.value = " WOB_COLOR_PRINTF_FORMAT, WOB_COLOR_PRINTF_RGBA(config->default_style.overflow_colors.value)); wob_log_debug("config.overflow_colors.border = " WOB_COLOR_PRINTF_FORMAT, WOB_COLOR_PRINTF_RGBA(config->default_style.overflow_colors.border)); + wob_log_debug("config.font = %s", config->font_path != NULL ? config->font_path : ""); + wob_log_debug("config.font_size = %d", config->font_size); struct wob_style *style; wl_list_for_each (style, &config->styles, link) { @@ -615,6 +639,7 @@ wob_config_debug(struct wob_config *config) WOB_ORIENTATION_HORIZONTAL, WOB_ORIENTATION_VERTICAL ); + wob_log_debug("config.output.%s.font_size = %d", output_config->id, output_config->font_size); } } @@ -634,6 +659,10 @@ wob_config_destroy(struct wob_config *config) free(style); } + if (config->font_path != NULL) { + free(config->font_path); + } + free(config); } @@ -683,7 +712,8 @@ wob_config_match_output(struct wob_config *config, const char *match) struct wob_output_config *output_config = NULL; bool output_found = false; wl_list_for_each (output_config, &config->outputs, link) { - if (strstr(output_config->match, match) == 0) { + wob_log_debug("%s = %s?", output_config->match, match); + if (strstr(match, output_config->match) != NULL) { output_found = true; break; } diff --git a/src/config.h b/src/config.h index 3f0291b..ddb9ff8 100644 --- a/src/config.h +++ b/src/config.h @@ -53,6 +53,7 @@ struct wob_output_config { struct wob_dimensions dimensions; struct wob_margin margin; unsigned long anchor; + unsigned long font_size; }; struct wob_colors { @@ -79,6 +80,8 @@ struct wob_config { struct wl_list styles; struct wl_list outputs; bool sandbox; + char *font_path; + unsigned long font_size; }; struct wob_config *wob_config_create(); diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000..a375623 --- /dev/null +++ b/src/font.h @@ -0,0 +1,32 @@ +#ifndef FONT_H +#define FONT_H + +#include + +#include "color.h" +#include "config.h" + +struct wob_font_manager; + +struct wob_font; + +struct wob_font_text_dimensions { + int w; + int h; +}; + +struct wob_font_manager *wob_font_manager_create(); + +void wob_font_manager_destroy(struct wob_font_manager *); + +void wob_font_manager_load_font(struct wob_font_manager *, const char *fpath); + +void wob_font_manager_load_fonts_from_config(struct wob_font_manager *, struct wob_config *); + +struct wob_font *wob_font_manager_get(struct wob_font_manager *, const char *fpath); + +void wob_font_render_text(struct wob_font *font, char *text, int font_size, struct wob_color font_color, uint32_t *argb8888_buffer, size_t argb8888_buffer_size); + +struct wob_font_text_dimensions wob_font_render_text_dimensions(struct wob_font *font, char *text, int font_size); + +#endif diff --git a/src/font_freetype.c b/src/font_freetype.c new file mode 100644 index 0000000..baae3aa --- /dev/null +++ b/src/font_freetype.c @@ -0,0 +1,162 @@ +#define WOB_FILE "font_freetype.c" + +#include "font.h" +#include "log.h" + +#include +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +FT_Library library; + +struct wob_font { + char *name; + FT_Face data; + struct wl_list link; +}; + +struct wob_font_manager { + struct wl_list fonts; +}; + +void +draw_glyph(uint32_t *pixels, size_t stride, FT_Bitmap *ft_bitmap, struct wob_color font_color) +{ + for (unsigned int row = 0; row < ft_bitmap->rows; row += 1) { + for (unsigned int width = 0; width < ft_bitmap->width; width += 1) { + uint8_t alpha = ft_bitmap->buffer[row * ft_bitmap->width + width]; + + struct wob_color background = wob_color_from_argb8888(pixels[width]); + struct wob_color foreground = font_color; + + foreground.a = alpha / 255.0f; + foreground = wob_color_premultiply_alpha(foreground); + + struct wob_color result = wob_color_blend_premultiplied(foreground, background); + + pixels[width] = wob_color_to_argb(result); + } + pixels += stride; + } +} + +struct wob_font_manager * +wob_font_manager_create() +{ + struct wob_font_manager *manager = malloc(sizeof(struct wob_font_manager)); + + FT_Init_FreeType(&library); + + wl_list_init(&manager->fonts); + + return manager; +} + +void +wob_font_manager_destroy(struct wob_font_manager *manager) +{ + struct wob_font *font, *font_tmp; + wl_list_for_each_safe (font, font_tmp, &manager->fonts, link) { + free(font->name); + FT_Done_Face(font->data); + + free(font); + } + + FT_Done_FreeType(library); +} + +void +wob_font_manager_load_font(struct wob_font_manager *manager, const char *fpath) +{ + struct wob_font *font = calloc(1, sizeof(struct wob_font)); + font->name = strdup(fpath); + FT_New_Face(library, fpath, 0, &font->data); + + wl_list_insert(&manager->fonts, &font->link); +} + +void +wob_font_manager_load_fonts_from_config(struct wob_font_manager *manager, struct wob_config *config) +{ + if (config->font_path != NULL) { + wob_font_manager_load_font(manager, config->font_path); + } +} + +struct wob_font * +wob_font_manager_get(struct wob_font_manager *manager, const char *fpath) +{ + struct wob_font *font; + wl_list_for_each (font, &manager->fonts, link) { + if (strcmp(font->name, fpath) == 0) { + return font; + } + } + + return NULL; +} + +struct wob_font_text_dimensions +wob_font_render_text_dimensions(struct wob_font *font, char *text, int font_size) +{ + struct wob_font_text_dimensions dimensions = {.h = 0, .w = 0}; + + FT_Face ft_face = font->data; + FT_Set_Pixel_Sizes(ft_face, 0, font_size); + FT_UInt previous = 0; + + bool has_kerning = FT_HAS_KERNING(ft_face); + + for (char *c = text; *c != '\0'; c += 1) { + FT_UInt glyph_index = FT_Get_Char_Index(ft_face, *c); + FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_DEFAULT); + + FT_Glyph glyph; + FT_Get_Glyph(ft_face->glyph, &glyph); + + FT_BBox glyph_bbox; + FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox); + FT_Vector delta; + + dimensions.h = glyph_bbox.yMax; + dimensions.w += glyph_bbox.xMax; + + if (has_kerning && previous != 0) { + FT_Get_Kerning(ft_face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); + dimensions.w += delta.x / 64; + } + + previous = glyph_index; + } + + return dimensions; +} + +void +wob_font_render_text(struct wob_font *font, char *text, int font_size, struct wob_color font_color, uint32_t *argb8888_buffer, size_t argb8888_buffer_size) +{ + FT_Face ft_face = font->data; + FT_UInt previous = 0; + FT_Set_Pixel_Sizes(ft_face, 0, font_size); + + bool has_kerning = FT_HAS_KERNING(ft_face); + + for (const char *c = text; *c != '\0'; c += 1) { + FT_Vector delta; + FT_UInt glyph_index = FT_Get_Char_Index(ft_face, *c); + FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_DEFAULT); + FT_Render_Glyph(ft_face->glyph, FT_RENDER_MODE_NORMAL); + + draw_glyph(argb8888_buffer, argb8888_buffer_size, &ft_face->glyph->bitmap, font_color); + + argb8888_buffer += ft_face->glyph->advance.x / 64; + if (has_kerning && previous != 0) { + FT_Get_Kerning(ft_face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); + argb8888_buffer += delta.x / 64; + } + + previous = glyph_index; + } +} diff --git a/src/font_stub.c b/src/font_stub.c new file mode 100644 index 0000000..299e98f --- /dev/null +++ b/src/font_stub.c @@ -0,0 +1,57 @@ +#define WOB_FILE "font_stub.c" + +#include "font.h" +#include "log.h" + +struct wob_font {}; + +struct wob_font_manager {}; + +struct wob_font_manager * +wob_font_manager_create() +{ + return NULL; +} + +void +wob_font_manager_destroy(struct wob_font_manager *manager) +{ +} + +void +wob_font_manager_load_font(struct wob_font_manager *manager, const char *fpath) +{ + wob_log_error("STUB wob_font_manager_load_font!"); +} + +void +wob_font_manager_load_fonts_from_config(struct wob_font_manager *manager, struct wob_config *config) +{ + if (config->font_path != NULL) { + wob_font_manager_load_font(manager, config->font_path); + } +} + +struct wob_font * +wob_font_manager_get(struct wob_font_manager *manager, const char *fpath) +{ + wob_log_error("STUB wob_font_manager_get!"); + + return NULL; +} + +struct wob_font_text_dimensions +wob_font_render_text_dimensions(struct wob_font *font, char *text, int font_size) +{ + wob_log_error("STUB wob_font_render_text_dimensions!"); + + struct wob_font_text_dimensions d = {.h = 0, .w = 0}; + + return d; +} + +void +wob_font_render_text(struct wob_font *font, char *text, int font_size, struct wob_color font_color, uint32_t *argb8888_buffer, size_t argb8888_buffer_size) +{ + wob_log_error("STUB wob_font_render_text!"); +} diff --git a/src/image.c b/src/image.c index de4fb81..2c42450 100644 --- a/src/image.c +++ b/src/image.c @@ -1,6 +1,9 @@ #define WOB_FILE "image.c" +#include + #include "image.h" +#include "log.h" void fill_rectangle(uint32_t *pixels, size_t width, size_t height, size_t stride, uint32_t color) @@ -14,7 +17,7 @@ fill_rectangle(uint32_t *pixels, size_t width, size_t height, size_t stride, uin } void -wob_image_draw(uint32_t *image_data, struct wob_dimensions dimensions, struct wob_colors colors, double percentage) +wob_image_draw(uint32_t *image_data, struct wob_dimensions dimensions, struct wob_colors colors, double percentage, struct wob_font *font, unsigned long font_size) { uint32_t bar_color = wob_color_to_argb(wob_color_premultiply_alpha(colors.value)); uint32_t background_color = wob_color_to_argb(wob_color_premultiply_alpha(colors.background)); @@ -60,4 +63,60 @@ wob_image_draw(uint32_t *image_data, struct wob_dimensions dimensions, struct wo fill_rectangle(data, width, height, stride, bar_color); break; } + + if (font == NULL) { + return; + } + + size_t font_padding = font_size / 4; + + char percentage_buff[64] = {0}; + snprintf(percentage_buff, 64, "%d", (int) (percentage * 100)); + struct wob_font_text_dimensions text_dimensions = wob_font_render_text_dimensions(font, percentage_buff, font_size); + wob_log_debug("declared font height %d, rendered text width: %d x %d\n", font_size, text_dimensions.w, text_dimensions.h); + + const uint32_t width_needed_for_text = text_dimensions.w + 2 * font_padding; + struct wob_color font_color; + + // data is positing to the beginning of TOP LEFT corner of rendered block + switch (dimensions.orientation) { + case WOB_ORIENTATION_HORIZONTAL: + // get to the X position first + if (width_needed_for_text < width) { + data += width - text_dimensions.w - font_padding; + font_color = colors.background; + } + else if (width_needed_for_text < bar_width) { + data += width + font_padding; + font_color = colors.value; + } + else { + wob_log_warn("bar text is too big for the bar to be rendered, skipping!"); + return; + } + + // get to the Y position + data += stride * ((bar_height - text_dimensions.h) / 2); + break; + case WOB_ORIENTATION_VERTICAL: + // get to the Y position first + if (width_needed_for_text < height) { + data += stride * font_padding; + font_color = colors.background; + } + else if (width_needed_for_text < bar_height) { + data -= stride * (text_dimensions.h + font_padding); + font_color = colors.value; + } + else { + wob_log_warn("bar text is too big for the bar to be rendered, skipping!"); + return; + } + + // get to the X position + data += (width - text_dimensions.w) / 2; + break; + } + + wob_font_render_text(font, percentage_buff, font_size, font_color, data, stride); } diff --git a/src/image.h b/src/image.h index 7212c6c..6077ed1 100644 --- a/src/image.h +++ b/src/image.h @@ -5,7 +5,8 @@ #include #include "config.h" +#include "font.h" -void wob_image_draw(uint32_t *data, struct wob_dimensions dimensions, struct wob_colors colors, double percentage); +void wob_image_draw(uint32_t *data, struct wob_dimensions dimensions, struct wob_colors colors, double percentage, struct wob_font *font, unsigned long font_size); #endif diff --git a/src/log.h b/src/log.h index c68cc3f..b78fc96 100644 --- a/src/log.h +++ b/src/log.h @@ -2,6 +2,7 @@ #define _WOB_LOG_H #include +#include typedef enum { WOB_LOG_DEBUG = 0, diff --git a/src/main.c b/src/main.c index 585f843..3839e96 100644 --- a/src/main.c +++ b/src/main.c @@ -8,6 +8,7 @@ #include #include "config.h" +#include "font.h" #include "global_configuration.h" #include "log.h" #include "wob.h" @@ -78,7 +79,7 @@ main(int argc, char **argv) } } - wob_log_info("wob version %s started with pid %jd", WOB_VERSION, (intmax_t) getpid()); + wob_log_info("wob version %s started with pid %jd, text = %s, pledge = %s", WOB_VERSION, getpid(), WOB_TEXT_ENABLED ? "YES" : "NO", WOB_PLEDGE_ENABLED ? "YES" : "NO"); if (wob_config_path == NULL) { wob_config_path = wob_config_default_path(); @@ -99,8 +100,16 @@ main(int argc, char **argv) config->sandbox = false; } + struct wob_font_manager *font_manager = wob_font_manager_create(); + wob_font_manager_load_fonts_from_config(font_manager, config); + wob_config_debug(config); free(wob_config_path); - return wob_run(config); + int result = wob_run(config, font_manager); + + wob_config_destroy(config); + wob_font_manager_destroy(font_manager); + + return result; } diff --git a/src/pledge_seccomp.c b/src/pledge_seccomp.c index a5c3f02..7b8caba 100644 --- a/src/pledge_seccomp.c +++ b/src/pledge_seccomp.c @@ -17,6 +17,7 @@ wob_pledge(void) { // clang-format off const int scmp_sc[] = { + SCMP_SYS(brk), SCMP_SYS(clock_gettime), SCMP_SYS(close), SCMP_SYS(exit), diff --git a/src/wob.c b/src/wob.c index 5e31a5e..95773ee 100644 --- a/src/wob.c +++ b/src/wob.c @@ -19,6 +19,8 @@ #include "wlr-layer-shell-unstable-v1.h" #include "wob.h" +#include "font.h" + struct wob_buffer { struct wl_buffer *wl_buffer; struct wob_dimensions dimensions; @@ -40,6 +42,8 @@ struct wob_surface { // TODO move somewhere? double desired_percentage; struct wob_colors desired_colors; + struct wob_font *desired_font; + unsigned long desired_font_size; }; struct wob_output { @@ -167,7 +171,7 @@ layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *zwlr_surface, // redraw only if we have dimensions set, otherwise keep the transparent pixel if (surface->dimensions.height != 1 || surface->dimensions.width != 1) { - wob_image_draw(surface->wob_buffer->shm_data, surface->wob_buffer->dimensions, surface->desired_colors, surface->desired_percentage); + wob_image_draw(surface->wob_buffer->shm_data, surface->wob_buffer->dimensions, surface->desired_colors, surface->desired_percentage, surface->desired_font, surface->desired_font_size); } if (surface->wp_viewport != NULL) { @@ -197,20 +201,23 @@ layer_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output struct wob_margin margin = app->config->margin; struct wob_dimensions dimensions = app->config->dimensions; enum wob_anchor anchor = app->config->anchor; + unsigned long font_size = app->config->font_size; // try to match output config struct wob_output_config *output_config = NULL; if (selected_output->name != NULL) { output_config = wob_config_match_output(app->config, selected_output->name); } - if (output_config != NULL && selected_output->description != NULL) { + if (output_config == NULL && selected_output->description != NULL) { output_config = wob_config_match_output(app->config, selected_output->description); } if (output_config != NULL) { + wob_log_debug("selected output %s", output_config->id); margin = output_config->margin; dimensions = output_config->dimensions; anchor = output_config->anchor; + font_size = output_config->font_size; } struct wob_surface *surface = app->surface; @@ -220,6 +227,7 @@ layer_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output zwlr_layer_surface_v1_set_size(surface->wlr_layer_surface, dimensions.width, dimensions.height); surface->dimensions = dimensions; + surface->desired_font_size = font_size; wl_surface_commit(surface->wl_surface); } @@ -315,6 +323,10 @@ wob_create_surface(struct wob *app) .anchor = 0, .wp_viewport = wp_viewport, .fractional = wp_fractional, + .desired_colors = (struct wob_color) {.a = 0, .r = 0, .g = 0, .b = 0}, + .desired_percentage = 0, + .desired_font = NULL, + .desired_font_size = 0, }; wl_surface_commit(wl_surface); @@ -332,7 +344,7 @@ wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) struct wob_surface *surface = data; wob_log_debug("rendering frame"); - wob_image_draw(surface->wob_buffer->shm_data, surface->wob_buffer->dimensions, surface->desired_colors, surface->desired_percentage); + wob_image_draw(surface->wob_buffer->shm_data, surface->wob_buffer->dimensions, surface->desired_colors, surface->desired_percentage, surface->desired_font, surface->desired_font_size); wl_surface_attach(surface->wl_surface, surface->wob_buffer->wl_buffer, 0, 0); wl_surface_damage_buffer(surface->wl_surface, 0, 0, INT32_MAX, INT32_MAX); @@ -504,7 +516,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) } int -wob_run(struct wob_config *config) +wob_run(struct wob_config *config, struct wob_font_manager *font_manager) { int _exit_code; @@ -682,6 +694,9 @@ wob_run(struct wob_config *config) state->surface->desired_colors = effective_colors; state->surface->desired_percentage = (double) percentage / (double) state->config->max; + struct wob_font *font = wob_font_manager_get(font_manager, config->font_path); + state->surface->desired_font = font; + wl_display_flush(wl_display); } } @@ -696,7 +711,6 @@ wob_run(struct wob_config *config) wl_list_for_each_safe (output, output_tmp, &state->wob_outputs, link) { wob_output_destroy(output); } - wob_config_destroy(state->config); free(state); // cleanup global managers & registry diff --git a/src/wob.h b/src/wob.h index 409c1fe..e761cc9 100644 --- a/src/wob.h +++ b/src/wob.h @@ -2,9 +2,10 @@ #define BUILD_WOB_H #include "config.h" +#include "font.h" #define INPUT_BUFFER_LENGTH 255 -int wob_run(struct wob_config *config); +int wob_run(struct wob_config *config, struct wob_font_manager *font_manager); #endif