diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-27 15:25:25 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-03-28 14:25:19 -0400 |
commit | 632bb948b7ffbb08a6e965dabf88347afd0a1fa8 (patch) | |
tree | cbd9d4e4e3a7c605d2b0a5e3e66ce35554a74c4b /common | |
parent | Add client protocols and swaybg skeleton (diff) | |
download | sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.tar.gz sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.tar.zst sway-632bb948b7ffbb08a6e965dabf88347afd0a1fa8.zip |
Add solid-color rendering to swaybg
Diffstat (limited to 'common')
-rw-r--r-- | common/cairo.c | 127 | ||||
-rw-r--r-- | common/meson.build | 21 |
2 files changed, 143 insertions, 5 deletions
diff --git a/common/cairo.c b/common/cairo.c new file mode 100644 index 00000000..c6bd0da9 --- /dev/null +++ b/common/cairo.c | |||
@@ -0,0 +1,127 @@ | |||
1 | #include <stdint.h> | ||
2 | #include <cairo/cairo.h> | ||
3 | #include "cairo.h" | ||
4 | #ifdef WITH_GDK_PIXBUF | ||
5 | #include <gdk-pixbuf/gdk-pixbuf.h> | ||
6 | #endif | ||
7 | |||
8 | void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { | ||
9 | cairo_set_source_rgba(cairo, | ||
10 | (color >> (3*8) & 0xFF) / 255.0, | ||
11 | (color >> (2*8) & 0xFF) / 255.0, | ||
12 | (color >> (1*8) & 0xFF) / 255.0, | ||
13 | (color >> (0*8) & 0xFF) / 255.0); | ||
14 | } | ||
15 | |||
16 | cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, | ||
17 | int width, int height) { | ||
18 | int image_width = cairo_image_surface_get_width(image); | ||
19 | int image_height = cairo_image_surface_get_height(image); | ||
20 | |||
21 | cairo_surface_t *new = | ||
22 | cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); | ||
23 | cairo_t *cairo = cairo_create(new); | ||
24 | cairo_scale(cairo, (double)width / image_width, | ||
25 | (double)height / image_height); | ||
26 | cairo_set_source_surface(cairo, image, 0, 0); | ||
27 | |||
28 | cairo_paint(cairo); | ||
29 | cairo_destroy(cairo); | ||
30 | return new; | ||
31 | } | ||
32 | |||
33 | #ifdef WITH_GDK_PIXBUF | ||
34 | cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { | ||
35 | int chan = gdk_pixbuf_get_n_channels(gdkbuf); | ||
36 | if (chan < 3) { | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); | ||
41 | if (!gdkpix) { | ||
42 | return NULL; | ||
43 | } | ||
44 | gint w = gdk_pixbuf_get_width(gdkbuf); | ||
45 | gint h = gdk_pixbuf_get_height(gdkbuf); | ||
46 | int stride = gdk_pixbuf_get_rowstride(gdkbuf); | ||
47 | |||
48 | cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; | ||
49 | cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); | ||
50 | cairo_surface_flush (cs); | ||
51 | if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { | ||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | int cstride = cairo_image_surface_get_stride(cs); | ||
56 | unsigned char * cpix = cairo_image_surface_get_data(cs); | ||
57 | |||
58 | if (chan == 3) { | ||
59 | int i; | ||
60 | for (i = h; i; --i) { | ||
61 | const guint8 *gp = gdkpix; | ||
62 | unsigned char *cp = cpix; | ||
63 | const guint8* end = gp + 3*w; | ||
64 | while (gp < end) { | ||
65 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
66 | cp[0] = gp[2]; | ||
67 | cp[1] = gp[1]; | ||
68 | cp[2] = gp[0]; | ||
69 | #else | ||
70 | cp[1] = gp[0]; | ||
71 | cp[2] = gp[1]; | ||
72 | cp[3] = gp[2]; | ||
73 | #endif | ||
74 | gp += 3; | ||
75 | cp += 4; | ||
76 | } | ||
77 | gdkpix += stride; | ||
78 | cpix += cstride; | ||
79 | } | ||
80 | } else { | ||
81 | /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 | ||
82 | * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) | ||
83 | * = z/256 + (z/256)/255 = (z + z/255)/256 | ||
84 | * # recurse once | ||
85 | * = (z + (z + z/255)/256)/256 | ||
86 | * = (z + z/256 + z/256/255) / 256 | ||
87 | * # only use 16bit uint operations, loose some precision, | ||
88 | * # result is floored. | ||
89 | * -> (z + z>>8)>>8 | ||
90 | * # add 0x80/255 = 0.5 to convert floor to round | ||
91 | * => (z+0x80 + (z+0x80)>>8 ) >> 8 | ||
92 | * ------ | ||
93 | * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] | ||
94 | */ | ||
95 | #define PREMUL_ALPHA(x,a,b,z) \ | ||
96 | G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ | ||
97 | G_STMT_END | ||
98 | int i; | ||
99 | for (i = h; i; --i) { | ||
100 | const guint8 *gp = gdkpix; | ||
101 | unsigned char *cp = cpix; | ||
102 | const guint8* end = gp + 4*w; | ||
103 | guint z1, z2, z3; | ||
104 | while (gp < end) { | ||
105 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||
106 | PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); | ||
107 | PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); | ||
108 | PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); | ||
109 | cp[3] = gp[3]; | ||
110 | #else | ||
111 | PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); | ||
112 | PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); | ||
113 | PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); | ||
114 | cp[0] = gp[3]; | ||
115 | #endif | ||
116 | gp += 4; | ||
117 | cp += 4; | ||
118 | } | ||
119 | gdkpix += stride; | ||
120 | cpix += cstride; | ||
121 | } | ||
122 | #undef PREMUL_ALPHA | ||
123 | } | ||
124 | cairo_surface_mark_dirty(cs); | ||
125 | return cs; | ||
126 | } | ||
127 | #endif //WITH_GDK_PIXBUF | ||
diff --git a/common/meson.build b/common/meson.build index abe0cdcf..01736ca6 100644 --- a/common/meson.build +++ b/common/meson.build | |||
@@ -1,12 +1,23 @@ | |||
1 | lib_sway_common = static_library('sway-common', | 1 | deps = [ |
2 | cairo, | ||
3 | wlroots | ||
4 | ] | ||
5 | |||
6 | if gdk_pixbuf.found() | ||
7 | deps += [gdk_pixbuf] | ||
8 | endif | ||
9 | |||
10 | lib_sway_common = static_library( | ||
11 | 'sway-common', | ||
2 | files( | 12 | files( |
13 | 'cairo.c', | ||
14 | 'ipc-client.c', | ||
3 | 'log.c', | 15 | 'log.c', |
4 | 'list.c', | 16 | 'list.c', |
5 | 'util.c', | ||
6 | 'stringop.c', | ||
7 | 'readline.c', | 17 | 'readline.c', |
8 | 'ipc-client.c' | 18 | 'stringop.c', |
19 | 'util.c' | ||
9 | ), | 20 | ), |
10 | dependencies: [ wlroots ], | 21 | dependencies: deps, |
11 | include_directories: sway_inc | 22 | include_directories: sway_inc |
12 | ) | 23 | ) |