diff options
author | Drew DeVault <sir@cmpwn.com> | 2019-04-25 11:23:37 -0400 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2019-04-25 18:44:28 +0300 |
commit | 236ca63419528da1ebfbfe7aabd24a1c3b274437 (patch) | |
tree | 88dbafbde4595ce0ce35b26b70a716154a90acd1 /common | |
parent | Remove obsolete README translations (diff) | |
download | sway-236ca63419528da1ebfbfe7aabd24a1c3b274437.tar.gz sway-236ca63419528da1ebfbfe7aabd24a1c3b274437.tar.zst sway-236ca63419528da1ebfbfe7aabd24a1c3b274437.zip |
swaybg: split into standalone project
The new upstream is https://github.com/swaywm/swaybg
This commit also refactors our use of gdk-pixbuf a bit, since the only
remaining reverse dependency is swaybar tray support.
Diffstat (limited to 'common')
-rw-r--r-- | common/background-image.c | 100 | ||||
-rw-r--r-- | common/cairo.c | 99 |
2 files changed, 100 insertions, 99 deletions
diff --git a/common/background-image.c b/common/background-image.c index 4431b725..de42e8e9 100644 --- a/common/background-image.c +++ b/common/background-image.c | |||
@@ -2,6 +2,9 @@ | |||
2 | #include "background-image.h" | 2 | #include "background-image.h" |
3 | #include "cairo.h" | 3 | #include "cairo.h" |
4 | #include "log.h" | 4 | #include "log.h" |
5 | #if HAVE_GDK_PIXBUF | ||
6 | #include <gdk-pixbuf/gdk-pixbuf.h> | ||
7 | #endif | ||
5 | 8 | ||
6 | enum background_mode parse_background_mode(const char *mode) { | 9 | enum background_mode parse_background_mode(const char *mode) { |
7 | if (strcmp(mode, "stretch") == 0) { | 10 | if (strcmp(mode, "stretch") == 0) { |
@@ -21,6 +24,103 @@ enum background_mode parse_background_mode(const char *mode) { | |||
21 | return BACKGROUND_MODE_INVALID; | 24 | return BACKGROUND_MODE_INVALID; |
22 | } | 25 | } |
23 | 26 | ||
27 | #if HAVE_GDK_PIXBUF | ||
28 | static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( | ||
29 | const GdkPixbuf *gdkbuf) { | ||
30 | int chan = gdk_pixbuf_get_n_channels(gdkbuf); | ||
31 | if (chan < 3) { | ||
32 | return NULL; | ||
33 | } | ||
34 | |||
35 | const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); | ||
36 | if (!gdkpix) { | ||
37 | return NULL; | ||
38 | } | ||
39 | gint w = gdk_pixbuf_get_width(gdkbuf); | ||
40 | gint h = gdk_pixbuf_get_height(gdkbuf); | ||
41 | int stride = gdk_pixbuf_get_rowstride(gdkbuf); | ||
42 | |||
43 | cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; | ||
44 | cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); | ||
45 | cairo_surface_flush (cs); | ||
46 | if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | int cstride = cairo_image_surface_get_stride(cs); | ||
51 | unsigned char * cpix = cairo_image_surface_get_data(cs); | ||
52 | |||
53 | if (chan == 3) { | ||
54 | int i; | ||
55 | for (i = h; i; --i) { | ||
56 | const guint8 *gp = gdkpix; | ||
57 | unsigned char *cp = cpix; | ||
58 | const guint8* end = gp + 3*w; | ||
59 | while (gp < end) { | ||
60 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
61 | cp[0] = gp[2]; | ||
62 | cp[1] = gp[1]; | ||
63 | cp[2] = gp[0]; | ||
64 | #else | ||
65 | cp[1] = gp[0]; | ||
66 | cp[2] = gp[1]; | ||
67 | cp[3] = gp[2]; | ||
68 | #endif | ||
69 | gp += 3; | ||
70 | cp += 4; | ||
71 | } | ||
72 | gdkpix += stride; | ||
73 | cpix += cstride; | ||
74 | } | ||
75 | } else { | ||
76 | /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 | ||
77 | * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) | ||
78 | * = z/256 + (z/256)/255 = (z + z/255)/256 | ||
79 | * # recurse once | ||
80 | * = (z + (z + z/255)/256)/256 | ||
81 | * = (z + z/256 + z/256/255) / 256 | ||
82 | * # only use 16bit uint operations, loose some precision, | ||
83 | * # result is floored. | ||
84 | * -> (z + z>>8)>>8 | ||
85 | * # add 0x80/255 = 0.5 to convert floor to round | ||
86 | * => (z+0x80 + (z+0x80)>>8 ) >> 8 | ||
87 | * ------ | ||
88 | * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] | ||
89 | */ | ||
90 | #define PREMUL_ALPHA(x,a,b,z) \ | ||
91 | G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ | ||
92 | G_STMT_END | ||
93 | int i; | ||
94 | for (i = h; i; --i) { | ||
95 | const guint8 *gp = gdkpix; | ||
96 | unsigned char *cp = cpix; | ||
97 | const guint8* end = gp + 4*w; | ||
98 | guint z1, z2, z3; | ||
99 | while (gp < end) { | ||
100 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
101 | PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); | ||
102 | PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); | ||
103 | PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); | ||
104 | cp[3] = gp[3]; | ||
105 | #else | ||
106 | PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); | ||
107 | PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); | ||
108 | PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); | ||
109 | cp[0] = gp[3]; | ||
110 | #endif | ||
111 | gp += 4; | ||
112 | cp += 4; | ||
113 | } | ||
114 | gdkpix += stride; | ||
115 | cpix += cstride; | ||
116 | } | ||
117 | #undef PREMUL_ALPHA | ||
118 | } | ||
119 | cairo_surface_mark_dirty(cs); | ||
120 | return cs; | ||
121 | } | ||
122 | #endif // HAVE_GDK_PIXBUF | ||
123 | |||
24 | cairo_surface_t *load_background_image(const char *path) { | 124 | cairo_surface_t *load_background_image(const char *path) { |
25 | cairo_surface_t *image; | 125 | cairo_surface_t *image; |
26 | #if HAVE_GDK_PIXBUF | 126 | #if HAVE_GDK_PIXBUF |
diff --git a/common/cairo.c b/common/cairo.c index f2ad54c1..403dcf49 100644 --- a/common/cairo.c +++ b/common/cairo.c | |||
@@ -1,9 +1,6 @@ | |||
1 | #include <stdint.h> | 1 | #include <stdint.h> |
2 | #include <cairo/cairo.h> | 2 | #include <cairo/cairo.h> |
3 | #include "cairo.h" | 3 | #include "cairo.h" |
4 | #if HAVE_GDK_PIXBUF | ||
5 | #include <gdk-pixbuf/gdk-pixbuf.h> | ||
6 | #endif | ||
7 | 4 | ||
8 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | 5 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { |
9 | cairo_set_source_rgba(cairo, | 6 | cairo_set_source_rgba(cairo, |
@@ -45,99 +42,3 @@ cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, | |||
45 | cairo_destroy(cairo); | 42 | cairo_destroy(cairo); |
46 | return new; | 43 | return new; |
47 | } | 44 | } |
48 | |||
49 | #if HAVE_GDK_PIXBUF | ||
50 | cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { | ||
51 | int chan = gdk_pixbuf_get_n_channels(gdkbuf); | ||
52 | if (chan < 3) { | ||
53 | return NULL; | ||
54 | } | ||
55 | |||
56 | const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); | ||
57 | if (!gdkpix) { | ||
58 | return NULL; | ||
59 | } | ||
60 | gint w = gdk_pixbuf_get_width(gdkbuf); | ||
61 | gint h = gdk_pixbuf_get_height(gdkbuf); | ||
62 | int stride = gdk_pixbuf_get_rowstride(gdkbuf); | ||
63 | |||
64 | cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; | ||
65 | cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); | ||
66 | cairo_surface_flush (cs); | ||
67 | if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { | ||
68 | return NULL; | ||
69 | } | ||
70 | |||
71 | int cstride = cairo_image_surface_get_stride(cs); | ||
72 | unsigned char * cpix = cairo_image_surface_get_data(cs); | ||
73 | |||
74 | if (chan == 3) { | ||
75 | int i; | ||
76 | for (i = h; i; --i) { | ||
77 | const guint8 *gp = gdkpix; | ||
78 | unsigned char *cp = cpix; | ||
79 | const guint8* end = gp + 3*w; | ||
80 | while (gp < end) { | ||
81 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
82 | cp[0] = gp[2]; | ||
83 | cp[1] = gp[1]; | ||
84 | cp[2] = gp[0]; | ||
85 | #else | ||
86 | cp[1] = gp[0]; | ||
87 | cp[2] = gp[1]; | ||
88 | cp[3] = gp[2]; | ||
89 | #endif | ||
90 | gp += 3; | ||
91 | cp += 4; | ||
92 | } | ||
93 | gdkpix += stride; | ||
94 | cpix += cstride; | ||
95 | } | ||
96 | } else { | ||
97 | /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 | ||
98 | * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) | ||
99 | * = z/256 + (z/256)/255 = (z + z/255)/256 | ||
100 | * # recurse once | ||
101 | * = (z + (z + z/255)/256)/256 | ||
102 | * = (z + z/256 + z/256/255) / 256 | ||
103 | * # only use 16bit uint operations, loose some precision, | ||
104 | * # result is floored. | ||
105 | * -> (z + z>>8)>>8 | ||
106 | * # add 0x80/255 = 0.5 to convert floor to round | ||
107 | * => (z+0x80 + (z+0x80)>>8 ) >> 8 | ||
108 | * ------ | ||
109 | * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] | ||
110 | */ | ||
111 | #define PREMUL_ALPHA(x,a,b,z) \ | ||
112 | G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ | ||
113 | G_STMT_END | ||
114 | int i; | ||
115 | for (i = h; i; --i) { | ||
116 | const guint8 *gp = gdkpix; | ||
117 | unsigned char *cp = cpix; | ||
118 | const guint8* end = gp + 4*w; | ||
119 | guint z1, z2, z3; | ||
120 | while (gp < end) { | ||
121 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
122 | PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); | ||
123 | PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); | ||
124 | PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); | ||
125 | cp[3] = gp[3]; | ||
126 | #else | ||
127 | PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); | ||
128 | PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); | ||
129 | PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); | ||
130 | cp[0] = gp[3]; | ||
131 | #endif | ||
132 | gp += 4; | ||
133 | cp += 4; | ||
134 | } | ||
135 | gdkpix += stride; | ||
136 | cpix += cstride; | ||
137 | } | ||
138 | #undef PREMUL_ALPHA | ||
139 | } | ||
140 | cairo_surface_mark_dirty(cs); | ||
141 | return cs; | ||
142 | } | ||
143 | #endif // HAVE_GDK_PIXBUF | ||