render titlebar button icons directly from XPM character data, bypassing XPM parser (which depends on X11)

This commit is contained in:
Window Maker 2026-06-04 09:36:19 +02:00
parent c7a3e80c73
commit 0e582d0580
1 changed files with 41 additions and 24 deletions

View File

@ -727,6 +727,42 @@ wl_frame_paint(struct WFrameWindow *fwin)
return 1;
}
/* Render XPM character data into an alpha mask RImage.
* Walks the XPM rows directly — only needs the character grid,
* not the XPM color definitions (just "None" detection). */
static RImage *xpm_to_alpha_mask(char **xpm)
{
int w = 0, h = 0, ncolors = 0, cpp = 0;
if (sscanf(xpm[0], "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4)
return NULL;
if (w <= 0 || h <= 0 || ncolors < 0 || (cpp != 1 && cpp != 2))
return NULL;
char none_sym[3] = {0, 0, 0};
for (int _i = 1; _i <= ncolors; _i++) {
const char *def = xpm[_i];
if (strstr(def, "None") || strstr(def, "none")) {
none_sym[0] = def[0];
if (cpp == 2 && def[1] != ' ') none_sym[1] = def[1];
break;
}
}
RImage *img = RCreateImage(w, h, True);
if (!img) return NULL;
memset(img->data, 0, w * h * 4);
int data_start = 1 + ncolors;
for (int _r = 0; _r < h && (data_start + _r) < 512; _r++) {
const char *row = xpm[data_start + _r];
int rowlen = strlen(row);
for (int _c = 0; _c < w && _c < rowlen; _c++) {
int is_none = (none_sym[0] && row[_c] == none_sym[0]);
if (cpp == 2 && _c + 1 < rowlen && none_sym[1])
is_none = is_none && (row[_c + 1] == none_sym[1]);
if (!is_none)
img->data[(_r * w + _c) * 4 + 3] = 0xFF;
}
}
return img;
}
void
wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
@ -748,30 +784,11 @@ wl_frame_paint_button(WCoreWindow *button, WTexture *texture,
if (bw < 3 || bh < 3)
return;
/* Build button icon RImages once (avoids XPM parser dependency) */
if (!wl_state.btn_close_img) {
wl_state.btn_close_img = RCreateImage(10, 10, True);
if (wl_state.btn_close_img) {
unsigned char *d = wl_state.btn_close_img->data;
memset(d, 0, 10 * 10 * 4);
for (int _i = 0; _i < 10; _i++) {
int _j = _i, _k = 9 - _i;
d[(_j * 10 + _i) * 4 + 3] = 0xFF; /* alpha=255 on X diagonals */
d[(_k * 10 + _i) * 4 + 3] = 0xFF;
}
}
}
if (!wl_state.btn_iconify_img) {
wl_state.btn_iconify_img = RCreateImage(10, 10, True);
if (wl_state.btn_iconify_img) {
unsigned char *d = wl_state.btn_iconify_img->data;
memset(d, 0, 10 * 10 * 4);
for (int _i = 0; _i < 10; _i++) {
d[(8 * 10 + _i) * 4 + 3] = 0xFF; /* alpha=255 on two rows */
d[(9 * 10 + _i) * 4 + 3] = 0xFF;
}
}
}
/* Build button icon RImages from XPM data arrays directly */
if (!wl_state.btn_close_img)
wl_state.btn_close_img = xpm_to_alpha_mask(PRED_CLOSE_XPM);
if (!wl_state.btn_iconify_img)
wl_state.btn_iconify_img = xpm_to_alpha_mask(PRED_ICONIFY_XPM);
RImage *icon = NULL;
if (button == fwin->right_button)