diff --git a/include/button/button-xbm.h b/include/button/button-xbm.h new file mode 100644 index 00000000..ae78222e --- /dev/null +++ b/include/button/button-xbm.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LABWC_BUTTON_XBM_H +#define LABWC_BUTTON_XBM_H + +struct lab_data_buffer; + +/* button_xbm_load - Convert xbm file to buffer with cairo surface */ +void button_xbm_load(const char *filename, struct lab_data_buffer **buffer, + char *fallback_button, float *rgba); + +#endif /* LABWC_BUTTON_XBM_H */ diff --git a/include/xbm/parse.h b/include/xbm/parse.h deleted file mode 100644 index f9ad9119..00000000 --- a/include/xbm/parse.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Parse xbm token to create pixmap - * - * Copyright Johan Malm 2020 - */ - -#ifndef LABWC_PARSE_H -#define LABWC_PARSE_H - -#include "xbm/tokenize.h" -#include - -struct pixmap { - uint32_t *data; - int width; - int height; -}; - -/** - * parse_set_color - set color to be used when parsing icons - * @rgba: four floats representing red, green, blue, alpha - */ -void parse_set_color(float *rgba); - -/** - * parse_xbm_tokens - parse xbm tokens and create pixmap - * @tokens: token vector - */ -struct pixmap parse_xbm_tokens(struct token *tokens); - -/** - * parse_xbm_builtin - parse builtin xbm button and create pixmap - * @button: button byte array (xbm format) - */ -struct pixmap parse_xbm_builtin(const char *button, int size); - -#endif /* LABWC_PARSE_H */ diff --git a/include/xbm/tokenize.h b/include/xbm/tokenize.h deleted file mode 100644 index b39f881d..00000000 --- a/include/xbm/tokenize.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * XBM file tokenizer - * - * Copyright Johan Malm 2020 - */ - -#ifndef LABWC_TOKENIZE_H -#define LABWC_TOKENIZE_H - -enum token_type { - TOKEN_NONE = 0, - TOKEN_IDENT, - TOKEN_INT, - TOKEN_SPECIAL, - TOKEN_OTHER, -}; - -#define MAX_TOKEN_SIZE (256) -struct token { - char name[MAX_TOKEN_SIZE]; - int value; - size_t pos; - enum token_type type; -}; - -/** - * tokenize - tokenize xbm file - * @buffer: buffer containing xbm file - * return token vector - */ -struct token *tokenize_xbm(char *buffer); - -#endif /* LABWC_TOKENIZE_H */ diff --git a/include/xbm/xbm.h b/include/xbm/xbm.h deleted file mode 100644 index 8c36dfbc..00000000 --- a/include/xbm/xbm.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef LABWC_XBM_H -#define LABWC_XBM_H - -#include - -#include "xbm/parse.h" - -/** - * xbm_load - load theme xbm files into global theme struct - */ -void xbm_load_button(const char *filename, struct lab_data_buffer **buffer, - char *fallback_button, float *rgba); - -#endif /* LABWC_XBM_H */ diff --git a/src/button/button-xbm.c b/src/button/button-xbm.c new file mode 100644 index 00000000..eb2a39ec --- /dev/null +++ b/src/button/button-xbm.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Convert xbm file to buffer with cairo surface + * + * Copyright Johan Malm 2020-2023 + */ + +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include +#include +#include +#include +#include "button/button-xbm.h" +#include "common/dir.h" +#include "common/grab-file.h" +#include "common/mem.h" +#include "config/rcxml.h" +#include "theme.h" +#include "buffer.h" + +enum token_type { + TOKEN_NONE = 0, + TOKEN_IDENT, + TOKEN_INT, + TOKEN_SPECIAL, + TOKEN_OTHER, +}; + +#define MAX_TOKEN_SIZE (256) +struct token { + char name[MAX_TOKEN_SIZE]; + int value; + size_t pos; + enum token_type type; +}; + +struct pixmap { + uint32_t *data; + int width; + int height; +}; + +static uint32_t color; +static char *current_buffer_position; +static struct token *tokens; +static int nr_tokens, alloc_tokens; + +static void +add_token(enum token_type token_type) +{ + if (nr_tokens == alloc_tokens) { + alloc_tokens = (alloc_tokens + 16) * 2; + tokens = xrealloc(tokens, alloc_tokens * sizeof(struct token)); + } + struct token *token = tokens + nr_tokens; + memset(token, 0, sizeof(*token)); + nr_tokens++; + token->type = token_type; +} + +static void +get_identifier_token(void) +{ + struct token *token = tokens + nr_tokens - 1; + token->name[token->pos] = current_buffer_position[0]; + token->pos++; + if (token->pos == MAX_TOKEN_SIZE - 1) { + return; + } + current_buffer_position++; + switch (current_buffer_position[0]) { + case '\0': + return; + case 'a' ... 'z': + case 'A' ... 'Z': + case '0' ... '9': + case '_': + case '#': + get_identifier_token(); + break; + default: + break; + } +} + +static void +get_number_token(void) +{ + struct token *token = tokens + nr_tokens - 1; + token->name[token->pos] = current_buffer_position[0]; + token->pos++; + if (token->pos == MAX_TOKEN_SIZE - 1) { + return; + } + current_buffer_position++; + switch (current_buffer_position[0]) { + case '\0': + return; + case '0' ... '9': + case 'a' ... 'f': + case 'A' ... 'F': + case 'x': + get_number_token(); + break; + default: + break; + } +} + +static void +get_special_char_token(void) +{ + struct token *token = tokens + nr_tokens - 1; + token->name[0] = current_buffer_position[0]; + current_buffer_position++; +} + +/** + * tokenize_xbm - tokenize xbm file + * @buffer: buffer containing xbm file + * return token vector + */ +static struct token * +tokenize_xbm(char *buffer) +{ + tokens = NULL; + nr_tokens = 0; + alloc_tokens = 0; + + current_buffer_position = buffer; + + for (;;) { + switch (current_buffer_position[0]) { + case '\0': + goto out; + case 'a' ... 'z': + case 'A' ... 'Z': + case '_': + case '#': + add_token(TOKEN_IDENT); + get_identifier_token(); + continue; + case '0' ... '9': + add_token(TOKEN_INT); + get_number_token(); + struct token *token = tokens + nr_tokens - 1; + token->value = (int)strtol(token->name, NULL, 0); + continue; + case '{': + add_token(TOKEN_SPECIAL); + get_special_char_token(); + continue; + default: + break; + } + ++current_buffer_position; + } +out: + add_token(TOKEN_NONE); /* vector end marker */ + return tokens; +} + +static uint32_t +u32(float *rgba) +{ + uint32_t r[4] = { 0 }; + for (int i = 0; i < 4; i++) { + r[i] = rgba[i] * 255; + } + return ((r[3] & 0xff) << 24) | ((r[0] & 0xff) << 16) | + ((r[1] & 0xff) << 8) | (r[2] & 0xff); +} + +static void +process_bytes(struct pixmap *pixmap, struct token *tokens) +{ + pixmap->data = znew_n(uint32_t, pixmap->width * pixmap->height); + struct token *t = tokens; + for (int row = 0; row < pixmap->height; row++) { + int byte = 1; + for (int col = 0; col < pixmap->width; col++) { + if (col == byte * 8) { + ++byte; + ++t; + } + if (!t->type) { + return; + } + if (t->type != TOKEN_INT) { + return; + } + int bit = 1 << (col % 8); + if (t->value & bit) { + pixmap->data[row * pixmap->width + col] = color; + } + } + ++t; + } +} + +/** + * parse_xbm_tokens - parse xbm tokens and create pixmap + * @tokens: token vector + */ +static struct pixmap +parse_xbm_tokens(struct token *tokens) +{ + struct pixmap pixmap = { 0 }; + + for (struct token *t = tokens; t->type; t++) { + if (pixmap.width && pixmap.height) { + if (t->type != TOKEN_INT) { + continue; + } + process_bytes(&pixmap, t); + goto out; + } + if (strstr(t->name, "width")) { + pixmap.width = atoi((++t)->name); + } else if (strstr(t->name, "height")) { + pixmap.height = atoi((++t)->name); + } + } +out: + return pixmap; +} + +/* + * Openbox built-in icons are not bigger than 8x8, so have only written this + * function to cope wit that max size + */ +#define LABWC_BUILTIN_ICON_MAX_SIZE (8) + +/** + * parse_xbm_builtin - parse builtin xbm button and create pixmap + * @button: button byte array (xbm format) + */ +static struct pixmap +parse_xbm_builtin(const char *button, int size) +{ + struct pixmap pixmap = { 0 }; + + assert(size <= LABWC_BUILTIN_ICON_MAX_SIZE); + pixmap.width = size; + pixmap.height = size; + + struct token t[LABWC_BUILTIN_ICON_MAX_SIZE + 1]; + for (int i = 0; i < size; i++) { + t[i].value = button[i]; + t[i].type = TOKEN_INT; + } + t[size].type = 0; + process_bytes(&pixmap, t); + return pixmap; +} + +static char * +xbm_path(const char *button) +{ + static char buffer[4096] = { 0 }; + snprintf(buffer, sizeof(buffer), "%s/%s", theme_dir(rc.theme_name), button); + return buffer; +} + +void +button_xbm_load(const char *filename, struct lab_data_buffer **buffer, + char *fallback_button, float *rgba) +{ + struct pixmap pixmap = {0}; + if (*buffer) { + wlr_buffer_drop(&(*buffer)->base); + *buffer = NULL; + } + + color = u32(rgba); + + /* Read file into memory as it's easier to tokenzie that way */ + char *token_buffer = grab_file(xbm_path(filename)); + if (token_buffer) { + struct token *tokens = tokenize_xbm(token_buffer); + free(token_buffer); + pixmap = parse_xbm_tokens(tokens); + if (tokens) { + free(tokens); + } + } + if (!pixmap.data) { + pixmap = parse_xbm_builtin(fallback_button, 6); + } + + /* Create buffer with free_on_destroy being true */ + *buffer = buffer_create_wrap(pixmap.data, pixmap.width, pixmap.height, + pixmap.width * 4, true); +} diff --git a/src/button/meson.build b/src/button/meson.build new file mode 100644 index 00000000..cf7b3d1f --- /dev/null +++ b/src/button/meson.build @@ -0,0 +1,3 @@ +labwc_sources += files( + 'button-xbm.c', +) diff --git a/src/meson.build b/src/meson.build index dec3ed7b..292eb675 100644 --- a/src/meson.build +++ b/src/meson.build @@ -42,6 +42,6 @@ endif subdir('common') subdir('config') subdir('decorations') -subdir('xbm') +subdir('button') subdir('menu') subdir('ssd') diff --git a/src/theme.c b/src/theme.c index 3c216228..3ff96f67 100644 --- a/src/theme.c +++ b/src/theme.c @@ -25,8 +25,8 @@ #include "common/string-helpers.h" #include "config/rcxml.h" #include "button-png.h" +#include "button/button-xbm.h" #include "theme.h" -#include "xbm/xbm.h" #include "buffer.h" #include "ssd.h" @@ -106,11 +106,11 @@ load_buttons(struct theme *theme) /* If there were no png buttons, use xbm */ snprintf(filename, sizeof(filename), "%s.xbm", b->name); if (!*b->active.buffer) { - xbm_load_button(filename, b->active.buffer, + button_xbm_load(filename, b->active.buffer, b->fallback_button, b->active.rgba); } if (!*b->inactive.buffer) { - xbm_load_button(filename, b->inactive.buffer, + button_xbm_load(filename, b->inactive.buffer, b->fallback_button, b->inactive.rgba); } } diff --git a/src/xbm/meson.build b/src/xbm/meson.build deleted file mode 100644 index 8aa98734..00000000 --- a/src/xbm/meson.build +++ /dev/null @@ -1,5 +0,0 @@ -labwc_sources += files( - 'parse.c', - 'tokenize.c', - 'xbm.c', -) diff --git a/src/xbm/parse.c b/src/xbm/parse.c deleted file mode 100644 index 0af100ce..00000000 --- a/src/xbm/parse.c +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Parse xbm token to create pixmap - * - * Copyright Johan Malm 2020 - */ - -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include - -#include "common/mem.h" -#include "xbm/parse.h" - -static uint32_t color; - -static uint32_t -u32(float *rgba) -{ - uint32_t r[4] = { 0 }; - for (int i = 0; i < 4; i++) { - r[i] = rgba[i] * 255; - } - return ((r[3] & 0xff) << 24) | ((r[0] & 0xff) << 16) | - ((r[1] & 0xff) << 8) | (r[2] & 0xff); -} - -void -parse_set_color(float *rgba) -{ - color = u32(rgba); -} - -static void -process_bytes(struct pixmap *pixmap, struct token *tokens) -{ - pixmap->data = znew_n(uint32_t, pixmap->width * pixmap->height); - struct token *t = tokens; - for (int row = 0; row < pixmap->height; row++) { - int byte = 1; - for (int col = 0; col < pixmap->width; col++) { - if (col == byte * 8) { - ++byte; - ++t; - } - if (!t->type) { - return; - } - if (t->type != TOKEN_INT) { - return; - } - int bit = 1 << (col % 8); - if (t->value & bit) { - pixmap->data[row * pixmap->width + col] = color; - } - } - ++t; - } -} - -struct pixmap -parse_xbm_tokens(struct token *tokens) -{ - struct pixmap pixmap = { 0 }; - - for (struct token *t = tokens; t->type; t++) { - if (pixmap.width && pixmap.height) { - if (t->type != TOKEN_INT) { - continue; - } - process_bytes(&pixmap, t); - goto out; - } - if (strstr(t->name, "width")) { - pixmap.width = atoi((++t)->name); - } else if (strstr(t->name, "height")) { - pixmap.height = atoi((++t)->name); - } - } -out: - return pixmap; -} - -/* - * Openbox built-in icons are not bigger than 8x8, so have only written this - * function to cope wit that max size - */ -#define LABWC_BUILTIN_ICON_MAX_SIZE (8) -struct pixmap -parse_xbm_builtin(const char *button, int size) -{ - struct pixmap pixmap = { 0 }; - - assert(size <= LABWC_BUILTIN_ICON_MAX_SIZE); - pixmap.width = size; - pixmap.height = size; - - struct token t[LABWC_BUILTIN_ICON_MAX_SIZE + 1]; - for (int i = 0; i < size; i++) { - t[i].value = button[i]; - t[i].type = TOKEN_INT; - } - t[size].type = 0; - process_bytes(&pixmap, t); - return pixmap; -} diff --git a/src/xbm/tokenize.c b/src/xbm/tokenize.c deleted file mode 100644 index 4675c0f0..00000000 --- a/src/xbm/tokenize.c +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * XBM file tokenizer - * - * Copyright Johan Malm 2020 - */ - -#include -#include -#include - -#include "common/mem.h" -#include "xbm/tokenize.h" - -static char *current_buffer_position; -static struct token *tokens; -static int nr_tokens, alloc_tokens; - -static void -add_token(enum token_type token_type) -{ - if (nr_tokens == alloc_tokens) { - alloc_tokens = (alloc_tokens + 16) * 2; - tokens = xrealloc(tokens, alloc_tokens * sizeof(struct token)); - } - struct token *token = tokens + nr_tokens; - memset(token, 0, sizeof(*token)); - nr_tokens++; - token->type = token_type; -} - -static void -get_identifier_token(void) -{ - struct token *token = tokens + nr_tokens - 1; - token->name[token->pos] = current_buffer_position[0]; - token->pos++; - if (token->pos == MAX_TOKEN_SIZE - 1) { - return; - } - current_buffer_position++; - switch (current_buffer_position[0]) { - case '\0': - return; - case 'a' ... 'z': - case 'A' ... 'Z': - case '0' ... '9': - case '_': - case '#': - get_identifier_token(); - break; - default: - break; - } -} - -static void -get_number_token(void) -{ - struct token *token = tokens + nr_tokens - 1; - token->name[token->pos] = current_buffer_position[0]; - token->pos++; - if (token->pos == MAX_TOKEN_SIZE - 1) { - return; - } - current_buffer_position++; - switch (current_buffer_position[0]) { - case '\0': - return; - case '0' ... '9': - case 'a' ... 'f': - case 'A' ... 'F': - case 'x': - get_number_token(); - break; - default: - break; - } -} - -static void -get_special_char_token(void) -{ - struct token *token = tokens + nr_tokens - 1; - token->name[0] = current_buffer_position[0]; - current_buffer_position++; -} - -struct token * -tokenize_xbm(char *buffer) -{ - tokens = NULL; - nr_tokens = 0; - alloc_tokens = 0; - - current_buffer_position = buffer; - - for (;;) { - switch (current_buffer_position[0]) { - case '\0': - goto out; - case 'a' ... 'z': - case 'A' ... 'Z': - case '_': - case '#': - add_token(TOKEN_IDENT); - get_identifier_token(); - continue; - case '0' ... '9': - add_token(TOKEN_INT); - get_number_token(); - struct token *token = tokens + nr_tokens - 1; - token->value = (int)strtol(token->name, NULL, 0); - continue; - case '{': - add_token(TOKEN_SPECIAL); - get_special_char_token(); - continue; - default: - break; - } - ++current_buffer_position; - } -out: - add_token(TOKEN_NONE); /* vector end marker */ - return tokens; -} diff --git a/src/xbm/xbm.c b/src/xbm/xbm.c deleted file mode 100644 index a19d50ff..00000000 --- a/src/xbm/xbm.c +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Create wlr textures based on xbm data - * - * Copyright Johan Malm 2020-2023 - */ - -#include -#include -#include - -#include "common/dir.h" -#include "common/grab-file.h" -#include "config/rcxml.h" -#include "theme.h" -#include "xbm/parse.h" -#include "xbm/xbm.h" -#include "buffer.h" - -static char * -xbm_path(const char *button) -{ - static char buffer[4096] = { 0 }; - snprintf(buffer, sizeof(buffer), "%s/%s", - theme_dir(rc.theme_name), button); - return buffer; -} - -void -xbm_load_button(const char *filename, struct lab_data_buffer **buffer, - char *fallback_button, float *rgba) -{ - struct pixmap pixmap = {0}; - if (*buffer) { - wlr_buffer_drop(&(*buffer)->base); - *buffer = NULL; - } - - parse_set_color(rgba); - - /* Read file into memory as it's easier to tokenzie that way */ - char *token_buffer = grab_file(xbm_path(filename)); - if (token_buffer) { - struct token *tokens = tokenize_xbm(token_buffer); - free(token_buffer); - pixmap = parse_xbm_tokens(tokens); - if (tokens) { - free(tokens); - } - } - if (!pixmap.data) { - pixmap = parse_xbm_builtin(fallback_button, 6); - } - - /* Create buffer with free_on_destroy being true */ - *buffer = buffer_create_wrap(pixmap.data, pixmap.width, pixmap.height, - pixmap.width * 4, true); -}