icon-loader: update PNG and XPM loaders to use new buffer helper

This commit is contained in:
John Lindgren 2024-10-06 22:38:03 -04:00
parent 2e9b5886ce
commit 36f754e662
6 changed files with 34 additions and 43 deletions

View file

@ -4,6 +4,7 @@
struct lab_data_buffer; struct lab_data_buffer;
void img_png_load(const char *filename, struct lab_data_buffer **buffer); void img_png_load(const char *filename, struct lab_data_buffer **buffer,
int size, float scale);
#endif /* LABWC_IMG_PNG_H */ #endif /* LABWC_IMG_PNG_H */

View file

@ -4,6 +4,7 @@
struct lab_data_buffer; struct lab_data_buffer;
void img_xpm_load(const char *filename, struct lab_data_buffer **buffer); void img_xpm_load(const char *filename, struct lab_data_buffer **buffer,
int size, float scale);
#endif /* LABWC_IMG_XPM_H */ #endif /* LABWC_IMG_XPM_H */

View file

@ -266,7 +266,7 @@ icon_loader_lookup(struct server *server, const char *app_id, int size,
switch (ctx.format) { switch (ctx.format) {
case SFDO_ICON_FILE_FORMAT_PNG: case SFDO_ICON_FILE_FORMAT_PNG:
img_png_load(ctx.path, &icon_buffer); img_png_load(ctx.path, &icon_buffer, size, scale);
break; break;
case SFDO_ICON_FILE_FORMAT_SVG: case SFDO_ICON_FILE_FORMAT_SVG:
#if HAVE_RSVG #if HAVE_RSVG
@ -274,7 +274,7 @@ icon_loader_lookup(struct server *server, const char *app_id, int size,
#endif #endif
break; break;
case SFDO_ICON_FILE_FORMAT_XPM: case SFDO_ICON_FILE_FORMAT_XPM:
img_xpm_load(ctx.path, &icon_buffer); img_xpm_load(ctx.path, &icon_buffer, size, scale);
break; break;
} }

View file

@ -43,7 +43,8 @@ ispng(const char *filename)
#undef PNG_BYTES_TO_CHECK #undef PNG_BYTES_TO_CHECK
void void
img_png_load(const char *filename, struct lab_data_buffer **buffer) img_png_load(const char *filename, struct lab_data_buffer **buffer, int size,
float scale)
{ {
if (*buffer) { if (*buffer) {
wlr_buffer_drop(&(*buffer)->base); wlr_buffer_drop(&(*buffer)->base);
@ -62,22 +63,6 @@ img_png_load(const char *filename, struct lab_data_buffer **buffer)
cairo_surface_destroy(image); cairo_surface_destroy(image);
return; return;
} }
cairo_surface_flush(image);
if (cairo_image_surface_get_format(image) == CAIRO_FORMAT_ARGB32) { *buffer = buffer_convert_cairo_surface_for_icon(image, size, scale);
/* we can wrap ARGB32 image surfaces directly */
*buffer = buffer_adopt_cairo_surface(image);
return;
}
/* convert to ARGB32 by painting to a new surface */
uint32_t w = cairo_image_surface_get_width(image);
uint32_t h = cairo_image_surface_get_height(image);
*buffer = buffer_create_cairo(w, h, 1);
cairo_t *cairo = (*buffer)->cairo;
cairo_set_source_surface(cairo, image, 0, 0);
cairo_paint(cairo);
cairo_surface_flush((*buffer)->surface);
/* destroy original surface */
cairo_surface_destroy(image);
} }

View file

@ -286,9 +286,8 @@ file_buffer(enum buf_op op, struct file_handle *h)
return NULL; return NULL;
} }
/* This function does all the work. */ static cairo_surface_t *
static struct lab_data_buffer * xpm_load_to_surface(struct file_handle *handle)
pixbuf_create_from_xpm(struct file_handle *handle)
{ {
const char *buffer = file_buffer(op_header, handle); const char *buffer = file_buffer(op_header, handle);
if (!buffer) { if (!buffer) {
@ -332,7 +331,7 @@ pixbuf_create_from_xpm(struct file_handle *handle)
char *name_buf = xzalloc(n_col * (cpp + 1)); char *name_buf = xzalloc(n_col * (cpp + 1));
struct xpm_color *colors = znew_n(struct xpm_color, n_col); struct xpm_color *colors = znew_n(struct xpm_color, n_col);
uint32_t *data = znew_n(uint32_t, w * h); cairo_surface_t *surface = NULL;
struct xpm_color *fallbackcolor = NULL; struct xpm_color *fallbackcolor = NULL;
char pixel_str[32]; /* cpp < 32 */ char pixel_str[32]; /* cpp < 32 */
@ -357,14 +356,20 @@ pixbuf_create_from_xpm(struct file_handle *handle)
} }
} }
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h);
uint32_t *data = (uint32_t *)cairo_image_surface_get_data(surface);
int stride = cairo_image_surface_get_stride(surface) / sizeof(uint32_t);
for (int ycnt = 0; ycnt < h; ycnt++) { for (int ycnt = 0; ycnt < h; ycnt++) {
uint32_t *pixtmp = data + w * ycnt; uint32_t *pixtmp = data + stride * ycnt;
int wbytes = w * cpp; int wbytes = w * cpp;
buffer = file_buffer(op_body, handle); buffer = file_buffer(op_body, handle);
if (!buffer || (strlen(buffer) < (size_t)wbytes)) { if (!buffer || (strlen(buffer) < (size_t)wbytes)) {
/* Advertised width doesn't match pixels */ /* Advertised width doesn't match pixels */
wlr_log(WLR_DEBUG, "Dimensions do not match data"); wlr_log(WLR_DEBUG, "Dimensions do not match data");
cairo_surface_destroy(surface);
surface = NULL;
goto out; goto out;
} }
@ -382,24 +387,19 @@ pixbuf_create_from_xpm(struct file_handle *handle)
*pixtmp++ = color->argb; *pixtmp++ = color->argb;
} }
} }
/* let cairo know pixel data has been modified */
g_hash_table_destroy(color_hash); cairo_surface_mark_dirty(surface);
free(colors);
free(name_buf);
return buffer_create_from_data(data, w, h, 4 * w);
out: out:
g_hash_table_destroy(color_hash); g_hash_table_destroy(color_hash);
free(colors); free(colors);
free(name_buf); free(name_buf);
free(data); return surface;
return NULL;
} }
void void
img_xpm_load(const char *filename, struct lab_data_buffer **buffer) img_xpm_load(const char *filename, struct lab_data_buffer **buffer, int size,
float scale)
{ {
if (*buffer) { if (*buffer) {
wlr_buffer_drop(&(*buffer)->base); wlr_buffer_drop(&(*buffer)->base);
@ -413,8 +413,11 @@ img_xpm_load(const char *filename, struct lab_data_buffer **buffer)
return; return;
} }
*buffer = pixbuf_create_from_xpm(&h); cairo_surface_t *surface = xpm_load_to_surface(&h);
if (!(*buffer)) { if (surface) {
*buffer = buffer_convert_cairo_surface_for_icon(surface, size,
scale);
} else {
wlr_log(WLR_ERROR, "error loading '%s'", filename); wlr_log(WLR_ERROR, "error loading '%s'", filename);
} }

View file

@ -246,19 +246,20 @@ load_button(struct theme *theme, struct button *b, int active)
zdrop(buffer); zdrop(buffer);
int size = theme->title_height - 2 * theme->padding_height;
float scale = 1; /* TODO: account for output scale */
/* PNG */ /* PNG */
get_button_filename(filename, sizeof(filename), b->name, get_button_filename(filename, sizeof(filename), b->name,
active ? "-active.png" : "-inactive.png"); active ? "-active.png" : "-inactive.png");
img_png_load(filename, buffer); img_png_load(filename, buffer, size, scale);
#if HAVE_RSVG #if HAVE_RSVG
/* SVG */ /* SVG */
if (!*buffer) { if (!*buffer) {
int size = theme->title_height - 2 * theme->padding_height;
get_button_filename(filename, sizeof(filename), b->name, get_button_filename(filename, sizeof(filename), b->name,
active ? "-active.svg" : "-inactive.svg"); active ? "-active.svg" : "-inactive.svg");
/* TODO: account for output scale */ img_svg_load(filename, buffer, size, scale);
img_svg_load(filename, buffer, size, 1);
} }
#endif #endif