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 */
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 */
switch (ctx.format) {
case SFDO_ICON_FILE_FORMAT_PNG:
- img_png_load(ctx.path, &icon_buffer);
+ img_png_load(ctx.path, &icon_buffer, size, scale);
break;
case SFDO_ICON_FILE_FORMAT_SVG:
#if HAVE_RSVG
#endif
break;
case SFDO_ICON_FILE_FORMAT_XPM:
- img_xpm_load(ctx.path, &icon_buffer);
+ img_xpm_load(ctx.path, &icon_buffer, size, scale);
break;
}
#undef PNG_BYTES_TO_CHECK
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) {
wlr_buffer_drop(&(*buffer)->base);
cairo_surface_destroy(image);
return;
}
- cairo_surface_flush(image);
- if (cairo_image_surface_get_format(image) == CAIRO_FORMAT_ARGB32) {
- /* 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);
+ *buffer = buffer_convert_cairo_surface_for_icon(image, size, scale);
}
return NULL;
}
-/* This function does all the work. */
-static struct lab_data_buffer *
-pixbuf_create_from_xpm(struct file_handle *handle)
+static cairo_surface_t *
+xpm_load_to_surface(struct file_handle *handle)
{
const char *buffer = file_buffer(op_header, handle);
if (!buffer) {
char *name_buf = xzalloc(n_col * (cpp + 1));
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;
char pixel_str[32]; /* cpp < 32 */
}
}
+ 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++) {
- uint32_t *pixtmp = data + w * ycnt;
+ uint32_t *pixtmp = data + stride * ycnt;
int wbytes = w * cpp;
buffer = file_buffer(op_body, handle);
if (!buffer || (strlen(buffer) < (size_t)wbytes)) {
/* Advertised width doesn't match pixels */
wlr_log(WLR_DEBUG, "Dimensions do not match data");
+ cairo_surface_destroy(surface);
+ surface = NULL;
goto out;
}
*pixtmp++ = color->argb;
}
}
-
- g_hash_table_destroy(color_hash);
- free(colors);
- free(name_buf);
-
- return buffer_create_from_data(data, w, h, 4 * w);
+ /* let cairo know pixel data has been modified */
+ cairo_surface_mark_dirty(surface);
out:
g_hash_table_destroy(color_hash);
free(colors);
free(name_buf);
- free(data);
-
- return NULL;
+ return surface;
}
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) {
wlr_buffer_drop(&(*buffer)->base);
return;
}
- *buffer = pixbuf_create_from_xpm(&h);
- if (!(*buffer)) {
+ cairo_surface_t *surface = xpm_load_to_surface(&h);
+ if (surface) {
+ *buffer = buffer_convert_cairo_surface_for_icon(surface, size,
+ scale);
+ } else {
wlr_log(WLR_ERROR, "error loading '%s'", filename);
}
zdrop(buffer);
+ int size = theme->title_height - 2 * theme->padding_height;
+ float scale = 1; /* TODO: account for output scale */
+
/* PNG */
get_button_filename(filename, sizeof(filename), b->name,
active ? "-active.png" : "-inactive.png");
- img_png_load(filename, buffer);
+ img_png_load(filename, buffer, size, scale);
#if HAVE_RSVG
/* SVG */
if (!*buffer) {
- int size = theme->title_height - 2 * theme->padding_height;
get_button_filename(filename, sizeof(filename), b->name,
active ? "-active.svg" : "-inactive.svg");
- /* TODO: account for output scale */
- img_svg_load(filename, buffer, size, 1);
+ img_svg_load(filename, buffer, size, scale);
}
#endif