From e633fe0b4081f249e9708f95da972138c86838ca Mon Sep 17 00:00:00 2001 From: Manuel Stoeckl Date: Thu, 23 Nov 2023 08:40:41 -0500 Subject: common: move load_image to swaybar swaynag, swaymsg, and sway do not use this function and are unlikely to in the future. --- common/background-image.c | 136 --------------------------------------------- common/meson.build | 2 - include/background-image.h | 7 --- include/swaybar/image.h | 7 +++ swaybar/image.c | 136 +++++++++++++++++++++++++++++++++++++++++++++ swaybar/meson.build | 1 + swaybar/tray/item.c | 2 +- 7 files changed, 145 insertions(+), 146 deletions(-) delete mode 100644 common/background-image.c delete mode 100644 include/background-image.h create mode 100644 include/swaybar/image.h create mode 100644 swaybar/image.c diff --git a/common/background-image.c b/common/background-image.c deleted file mode 100644 index 2df10dd2..00000000 --- a/common/background-image.c +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include "background-image.h" -#include "config.h" -#include "log.h" - -#if HAVE_GDK_PIXBUF -#include -#endif - -#if HAVE_GDK_PIXBUF -static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( - const GdkPixbuf *gdkbuf) { - int chan = gdk_pixbuf_get_n_channels(gdkbuf); - if (chan < 3) { - return NULL; - } - - const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); - if (!gdkpix) { - return NULL; - } - gint w = gdk_pixbuf_get_width(gdkbuf); - gint h = gdk_pixbuf_get_height(gdkbuf); - int stride = gdk_pixbuf_get_rowstride(gdkbuf); - - cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; - cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); - cairo_surface_flush (cs); - if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { - return NULL; - } - - int cstride = cairo_image_surface_get_stride(cs); - unsigned char * cpix = cairo_image_surface_get_data(cs); - - if (chan == 3) { - int i; - for (i = h; i; --i) { - const guint8 *gp = gdkpix; - unsigned char *cp = cpix; - const guint8* end = gp + 3*w; - while (gp < end) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - cp[0] = gp[2]; - cp[1] = gp[1]; - cp[2] = gp[0]; -#else - cp[1] = gp[0]; - cp[2] = gp[1]; - cp[3] = gp[2]; -#endif - gp += 3; - cp += 4; - } - gdkpix += stride; - cpix += cstride; - } - } else { - /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 - * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) - * = z/256 + (z/256)/255 = (z + z/255)/256 - * # recurse once - * = (z + (z + z/255)/256)/256 - * = (z + z/256 + z/256/255) / 256 - * # only use 16bit uint operations, loose some precision, - * # result is floored. - * -> (z + z>>8)>>8 - * # add 0x80/255 = 0.5 to convert floor to round - * => (z+0x80 + (z+0x80)>>8 ) >> 8 - * ------ - * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] - */ -#define PREMUL_ALPHA(x,a,b,z) \ - G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ - G_STMT_END - int i; - for (i = h; i; --i) { - const guint8 *gp = gdkpix; - unsigned char *cp = cpix; - const guint8* end = gp + 4*w; - guint z1, z2, z3; - while (gp < end) { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); - PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); - PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); - cp[3] = gp[3]; -#else - PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); - PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); - PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); - cp[0] = gp[3]; -#endif - gp += 4; - cp += 4; - } - gdkpix += stride; - cpix += cstride; - } -#undef PREMUL_ALPHA - } - cairo_surface_mark_dirty(cs); - return cs; -} -#endif // HAVE_GDK_PIXBUF - -cairo_surface_t *load_image(const char *path) { - cairo_surface_t *image; -#if HAVE_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); - if (!pixbuf) { - sway_log(SWAY_ERROR, "Failed to load background image (%s).", - err->message); - return NULL; - } - image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - image = cairo_image_surface_create_from_png(path); -#endif // HAVE_GDK_PIXBUF - if (!image) { - sway_log(SWAY_ERROR, "Failed to read background image."); - return NULL; - } - if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { - sway_log(SWAY_ERROR, "Failed to read background image: %s." -#if !HAVE_GDK_PIXBUF - "\nSway was compiled without gdk_pixbuf support, so only" - "\nPNG images can be loaded. This is the likely cause." -#endif // !HAVE_GDK_PIXBUF - , cairo_status_to_string(cairo_surface_status(image))); - return NULL; - } - return image; -} diff --git a/common/meson.build b/common/meson.build index 3756075a..c0ce1f68 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,7 +1,6 @@ lib_sway_common = static_library( 'sway-common', files( - 'background-image.c', 'cairo.c', 'gesture.c', 'ipc-client.c', @@ -14,7 +13,6 @@ lib_sway_common = static_library( ), dependencies: [ cairo, - gdk_pixbuf, pango, pangocairo, wayland_client.partial_dependency(compile_args: true) diff --git a/include/background-image.h b/include/background-image.h deleted file mode 100644 index 67c27c84..00000000 --- a/include/background-image.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _SWAY_BACKGROUND_IMAGE_H -#define _SWAY_BACKGROUND_IMAGE_H -#include - -cairo_surface_t *load_image(const char *path); - -#endif diff --git a/include/swaybar/image.h b/include/swaybar/image.h new file mode 100644 index 00000000..53a210dd --- /dev/null +++ b/include/swaybar/image.h @@ -0,0 +1,7 @@ +#ifndef _SWAYBAR_IMAGE_H +#define _SWAYBAR_IMAGE_H +#include + +cairo_surface_t *load_image(const char *path); + +#endif diff --git a/swaybar/image.c b/swaybar/image.c new file mode 100644 index 00000000..ed24b9f9 --- /dev/null +++ b/swaybar/image.c @@ -0,0 +1,136 @@ +#include +#include "config.h" +#include "log.h" +#include "swaybar/image.h" + +#if HAVE_GDK_PIXBUF +#include +#endif + +#if HAVE_GDK_PIXBUF +static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( + const GdkPixbuf *gdkbuf) { + int chan = gdk_pixbuf_get_n_channels(gdkbuf); + if (chan < 3) { + return NULL; + } + + const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); + if (!gdkpix) { + return NULL; + } + gint w = gdk_pixbuf_get_width(gdkbuf); + gint h = gdk_pixbuf_get_height(gdkbuf); + int stride = gdk_pixbuf_get_rowstride(gdkbuf); + + cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; + cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); + cairo_surface_flush (cs); + if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { + return NULL; + } + + int cstride = cairo_image_surface_get_stride(cs); + unsigned char * cpix = cairo_image_surface_get_data(cs); + + if (chan == 3) { + int i; + for (i = h; i; --i) { + const guint8 *gp = gdkpix; + unsigned char *cp = cpix; + const guint8* end = gp + 3*w; + while (gp < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + cp[0] = gp[2]; + cp[1] = gp[1]; + cp[2] = gp[0]; +#else + cp[1] = gp[0]; + cp[2] = gp[1]; + cp[3] = gp[2]; +#endif + gp += 3; + cp += 4; + } + gdkpix += stride; + cpix += cstride; + } + } else { + /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 + * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) + * = z/256 + (z/256)/255 = (z + z/255)/256 + * # recurse once + * = (z + (z + z/255)/256)/256 + * = (z + z/256 + z/256/255) / 256 + * # only use 16bit uint operations, loose some precision, + * # result is floored. + * -> (z + z>>8)>>8 + * # add 0x80/255 = 0.5 to convert floor to round + * => (z+0x80 + (z+0x80)>>8 ) >> 8 + * ------ + * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] + */ +#define PREMUL_ALPHA(x,a,b,z) \ + G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ + G_STMT_END + int i; + for (i = h; i; --i) { + const guint8 *gp = gdkpix; + unsigned char *cp = cpix; + const guint8* end = gp + 4*w; + guint z1, z2, z3; + while (gp < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); + PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); + PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); + cp[3] = gp[3]; +#else + PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); + PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); + PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); + cp[0] = gp[3]; +#endif + gp += 4; + cp += 4; + } + gdkpix += stride; + cpix += cstride; + } +#undef PREMUL_ALPHA + } + cairo_surface_mark_dirty(cs); + return cs; +} +#endif // HAVE_GDK_PIXBUF + +cairo_surface_t *load_image(const char *path) { + cairo_surface_t *image; +#if HAVE_GDK_PIXBUF + GError *err = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); + if (!pixbuf) { + sway_log(SWAY_ERROR, "Failed to load background image (%s).", + err->message); + return NULL; + } + image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); + g_object_unref(pixbuf); +#else + image = cairo_image_surface_create_from_png(path); +#endif // HAVE_GDK_PIXBUF + if (!image) { + sway_log(SWAY_ERROR, "Failed to read background image."); + return NULL; + } + if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { + sway_log(SWAY_ERROR, "Failed to read background image: %s." +#if !HAVE_GDK_PIXBUF + "\nSway was compiled without gdk_pixbuf support, so only" + "\nPNG images can be loaded. This is the likely cause." +#endif // !HAVE_GDK_PIXBUF + , cairo_status_to_string(cairo_surface_status(image))); + return NULL; + } + return image; +} diff --git a/swaybar/meson.build b/swaybar/meson.build index e5f1811e..34bbdeea 100644 --- a/swaybar/meson.build +++ b/swaybar/meson.build @@ -26,6 +26,7 @@ executable( 'bar.c', 'config.c', 'i3bar.c', + 'image.c', 'input.c', 'ipc.c', 'main.c', diff --git a/swaybar/tray/item.c b/swaybar/tray/item.c index c7938a35..d5fe50b1 100644 --- a/swaybar/tray/item.c +++ b/swaybar/tray/item.c @@ -7,12 +7,12 @@ #include #include "swaybar/bar.h" #include "swaybar/config.h" +#include "swaybar/image.h" #include "swaybar/input.h" #include "swaybar/tray/host.h" #include "swaybar/tray/icon.h" #include "swaybar/tray/item.h" #include "swaybar/tray/tray.h" -#include "background-image.h" #include "cairo_util.h" #include "list.h" #include "log.h" -- cgit v1.2.3-54-g00ecf