ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvtimg.C
(Generate patch)

Comparing rxvt-unicode/src/rxvtimg.C (file contents):
Revision 1.18 by sf-exg, Tue Jun 5 12:30:37 2012 UTC vs.
Revision 1.73 by sf-exg, Sat Jun 9 17:28:03 2012 UTC

2#include "../config.h" 2#include "../config.h"
3#include "rxvt.h" 3#include "rxvt.h"
4 4
5#if HAVE_IMG 5#if HAVE_IMG
6 6
7#define float_to_component(d) ((d) * 65535.99)
8
9rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int width, int height) 7rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int x, int y, int width, int height, int repeat)
10: s(screen), w(width), h(height), format(format), shared(false)
11{
12 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth);
13}
14
15rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int width, int height, Pixmap pixmap)
16: s(screen), pm(pixmap), w(width), h(height), format(format), shared(false) 8: s(screen), x(x), y(y), w(width), h(height), format(format), repeat(repeat),
9 pm(0), ref(0)
17{ 10{
11}
12
13rxvt_img::rxvt_img (const rxvt_img &img)
14: s(img.s), x(img.x), y(img.y), w(img.w), h(img.h), format(img.format), repeat(img.repeat), pm(img.pm), ref(img.ref)
15{
16 ++ref->cnt;
17}
18
19rxvt_img *
20rxvt_img::new_from_root (rxvt_screen *s)
21{
22 Display *dpy = s->display->dpy;
23 unsigned int root_pm_w, root_pm_h;
24 Pixmap root_pixmap = s->display->get_pixmap_property (s->display->xa[XA_XROOTPMAP_ID]);
25 if (root_pixmap == None)
26 root_pixmap = s->display->get_pixmap_property (s->display->xa[XA_ESETROOT_PMAP_ID]);
27
28 if (root_pixmap == None)
29 return 0;
30
31 Window wdummy;
32 int idummy;
33 unsigned int udummy;
34
35 if (!XGetGeometry (dpy, root_pixmap, &wdummy, &idummy, &idummy, &root_pm_w, &root_pm_h, &udummy, &udummy))
36 return 0;
37
38 rxvt_img *img = new rxvt_img (
39 s,
40 XRenderFindVisualFormat (dpy, DefaultVisual (dpy, s->display->screen)),
41 0,
42 0,
43 root_pm_w,
44 root_pm_h
45 );
46
47 img->pm = root_pixmap;
48 img->ref = new pixref (root_pm_w, root_pm_h);
49 img->ref->ours = false;
50
51 return img;
52}
53
54# if HAVE_PIXBUF
55rxvt_img *
56rxvt_img::new_from_pixbuf (rxvt_screen *s, GdkPixbuf *pb)
57{
58 Display *dpy = s->display->dpy;
59
60 int width = gdk_pixbuf_get_width (pb);
61 int height = gdk_pixbuf_get_height (pb);
62
63 if (width > 32767 || height > 32767) // well, we *could* upload in chunks
64 rxvt_fatal ("rxvt_img::new_from_pixbuf: image too big (maximum size 32768x32768).\n");
65
66 // since we require rgb24/argb32 formats from xrender we assume
67 // that both 24 and 32 bpp MUST be supported by any screen that supports xrender
68 int depth = gdk_pixbuf_get_has_alpha (pb) ? 32 : 24;
69
70 int byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
71
72 XImage xi;
73
74 xi.width = width;
75 xi.height = height;
76 xi.xoffset = 0;
77 xi.format = ZPixmap;
78 xi.byte_order = ImageByteOrder (dpy);
79 xi.bitmap_unit = 0; //XY only, unused
80 xi.bitmap_bit_order = 0; //XY only, unused
81 xi.bitmap_pad = BitmapPad (dpy);
82 xi.depth = depth;
83 xi.bytes_per_line = 0;
84 xi.bits_per_pixel = 32; //Z only
85 xi.red_mask = 0x00000000; //Z only, unused
86 xi.green_mask = 0x00000000; //Z only, unused
87 xi.blue_mask = 0x00000000; //Z only, unused
88 xi.obdata = 0; // probably unused
89
90 bool byte_order_mismatch = byte_order != xi.byte_order;
91
92 if (!XInitImage (&xi))
93 rxvt_fatal ("unable to initialise ximage, please report.\n");
94
95 if (height > INT_MAX / xi.bytes_per_line)
96 rxvt_fatal ("rxvt_img::new_from_pixbuf: image too big for Xlib.\n");
97
98 xi.data = (char *)rxvt_malloc (height * xi.bytes_per_line);
99
100 int rowstride = gdk_pixbuf_get_rowstride (pb);
101
102 assert (3 + (depth == 32) == gdk_pixbuf_get_n_channels (pb));
103 unsigned char *row = gdk_pixbuf_get_pixels (pb);
104 char *line = xi.data;
105
106 for (int y = 0; y < height; y++)
107 {
108 unsigned char *src = row;
109 uint32_t *dst = (uint32_t *)line;
110
111 if (depth == 24)
112 for (int x = 0; x < width; x++)
113 {
114 uint8_t r = *src++;
115 uint8_t g = *src++;
116 uint8_t b = *src++;
117
118 uint32_t v = (r << 16) | (g << 8) | b;
119
120 if (ecb_big_endian () ? !byte_order_mismatch : byte_order_mismatch)
121 v = ecb_bswap32 (v);
122
123 *dst++ = v;
124 }
125 else
126 for (int x = 0; x < width; x++)
127 {
128 uint32_t v = *(uint32_t *)src; src += 4;
129
130 if (ecb_big_endian ())
131 v = ecb_bswap32 (v);
132
133 v = ecb_rotl32 (v, 8); // abgr to bgra
134
135 if (!byte_order_mismatch)
136 v = ecb_bswap32 (v);
137
138 *dst++ = v;
139 }
140
141 row += rowstride;
142 line += xi.bytes_per_line;
143 }
144
145 rxvt_img *img = new rxvt_img (s, XRenderFindStandardFormat (dpy, depth == 24 ? PictStandardRGB24 : PictStandardARGB32), 0, 0, width, height);
146 img->alloc ();
147
148 GC gc = XCreateGC (dpy, img->pm, 0, 0);
149 XPutImage (dpy, img->pm, gc, &xi, 0, 0, 0, 0, width, height);
150 XFreeGC (dpy, gc);
151
152 free (xi.data);
153
154 return img;
18} 155}
19 156
20rxvt_img * 157rxvt_img *
21rxvt_img::new_from_file (rxvt_screen *s, const char *filename) 158rxvt_img::new_from_file (rxvt_screen *s, const char *filename)
22{ 159{
24 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err); 161 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err);
25 162
26 if (!pb) 163 if (!pb)
27 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message); 164 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message);
28 165
29 rxvt_img *img = new rxvt_img ( 166 rxvt_img *img = new_from_pixbuf (s, pb);
30 s,
31 XRenderFindStandardFormat (s->display->dpy, gdk_pixbuf_get_has_alpha (pb) ? PictStandardARGB32 : PictStandardRGB24),
32 gdk_pixbuf_get_width (pb),
33 gdk_pixbuf_get_height (pb)
34 );
35 167
36 img->render_pixbuf (pb, 0, 0, img->w, img->h, 0, 0); 168 g_object_unref (pb);
37 169
170 return img;
171}
172# endif
173
174void
175rxvt_img::destroy ()
176{
177 if (--ref->cnt)
38 return img; 178 return;
179
180 if (pm && ref->ours)
181 XFreePixmap (s->display->dpy, pm);
182
183 delete ref;
39} 184}
40 185
41rxvt_img::~rxvt_img () 186rxvt_img::~rxvt_img ()
42{ 187{
43 if (!shared) 188 destroy ();
44 XFreePixmap (s->display->dpy, pm); 189}
190
191void
192rxvt_img::alloc ()
193{
194 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth);
195 ref = new pixref (w, h);
196}
197
198Picture
199rxvt_img::src_picture ()
200{
201 Display *dpy = s->display->dpy;
202
203 XRenderPictureAttributes pa;
204 pa.repeat = repeat;
205 Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
206
207 return pic;
45} 208}
46 209
47void 210void
48rxvt_img::unshare () 211rxvt_img::unshare ()
49{ 212{
50 if (!shared) 213 if (ref->cnt == 1 && ref->ours)
51 return; 214 return;
52 215
53 rxvt_img *img = clone (); 216 Pixmap pm2 = XCreatePixmap (s->display->dpy, s->display->root, ref->w, ref->h, format->depth);
217 GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
218 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0);
219 XFreeGC (s->display->dpy, gc);
54 220
55 ::swap (pm , img->pm); 221 destroy ();
56 ::swap (shared, img->shared);
57 222
58 delete img; 223 pm = pm2;
224 ref = new pixref (ref->w, ref->h);
59} 225}
60 226
61void 227void
62rxvt_img::fill (const rxvt_color &c) 228rxvt_img::fill (const rxvt_color &c)
63{ 229{
87 253
88 for (int i = 0; i < width; i++) 254 for (int i = 0; i < width; i++)
89 params[i+2] = XDoubleToFixed (kernel[i] / sum); 255 params[i+2] = XDoubleToFixed (kernel[i] / sum);
90} 256}
91 257
92void 258rxvt_img *
93rxvt_img::blur (int rh, int rv) 259rxvt_img::blur (int rh, int rv)
94{ 260{
95 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV)) 261 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
96 return; 262 return clone ();
97 263
98 Display *dpy = s->display->dpy; 264 Display *dpy = s->display->dpy;
99 int size = max (rh, rv) * 2 + 1; 265 int size = max (rh, rv) * 2 + 1;
100 double *kernel = (double *)malloc (size * sizeof (double)); 266 double *kernel = (double *)malloc (size * sizeof (double));
101 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 267 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
268 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat);
269 img->alloc ();
102 270
103 XRenderPictureAttributes pa; 271 XRenderPictureAttributes pa;
104
105 pa.repeat = RepeatPad; 272 pa.repeat = RepeatPad;
106 Picture src = XRenderCreatePicture (dpy, pm , format, CPRepeat, &pa); 273 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
274 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0);
275
107 Pixmap tmp = XCreatePixmap (dpy, pm, w, h, format->depth); 276 Pixmap tmp_pm = XCreatePixmap (dpy, pm, w, h, format->depth);
108 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa); 277 Picture tmp = XRenderCreatePicture (dpy, tmp_pm , format, CPRepeat, &pa);
109 XFreePixmap (dpy, tmp); 278 XFreePixmap (dpy, tmp_pm);
110 279
111 if (kernel && params) 280 if (kernel && params)
112 { 281 {
113 size = rh * 2 + 1; 282 size = rh * 2 + 1;
114 get_gaussian_kernel (rh, size, kernel, params); 283 get_gaussian_kernel (rh, size, kernel, params);
115 284
116 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 285 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
117 XRenderComposite (dpy, 286 XRenderComposite (dpy,
118 PictOpSrc, 287 PictOpSrc,
119 src, 288 src,
289 None,
290 tmp,
291 0, 0,
292 0, 0,
293 0, 0,
294 w, h);
295
296 size = rv * 2 + 1;
297 get_gaussian_kernel (rv, size, kernel, params);
298 ::swap (params[0], params[1]);
299
300 XRenderSetPictureFilter (dpy, tmp, FilterConvolution, params, size+2);
301 XRenderComposite (dpy,
302 PictOpSrc,
303 tmp,
120 None, 304 None,
121 dst, 305 dst,
122 0, 0, 306 0, 0,
123 0, 0, 307 0, 0,
124 0, 0, 308 0, 0,
125 w, h); 309 w, h);
126
127 ::swap (src, dst);
128
129 size = rv * 2 + 1;
130 get_gaussian_kernel (rv, size, kernel, params);
131 ::swap (params[0], params[1]);
132
133 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
134 XRenderComposite (dpy,
135 PictOpSrc,
136 src,
137 None,
138 dst,
139 0, 0,
140 0, 0,
141 0, 0,
142 w, h);
143 } 310 }
144 311
145 free (kernel); 312 free (kernel);
146 free (params); 313 free (params);
147 XRenderFreePicture (dpy, src); 314 XRenderFreePicture (dpy, src);
148 XRenderFreePicture (dpy, dst); 315 XRenderFreePicture (dpy, dst);
149} 316 XRenderFreePicture (dpy, tmp);
150 317
151static Picture
152create_xrender_mask (Display *dpy, Drawable drawable, Bool argb)
153{
154 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
155
156 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
157 XRenderPictureAttributes pa;
158 pa.repeat = True;
159 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
160
161 XFreePixmap (dpy, pixmap);
162
163 return mask; 318 return img;
319}
320
321static void
322extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc)
323{
324 int32_t x = clamp (c, cl0, cl1);
325 c -= x;
326 xc = x;
327}
328
329static bool
330extract (int32_t cl0, int32_t cl1, int32_t &r, int32_t &g, int32_t &b, int32_t &a, unsigned short &xr, unsigned short &xg, unsigned short &xb, unsigned short &xa)
331{
332 extract (cl0, cl1, r, xr);
333 extract (cl0, cl1, g, xg);
334 extract (cl0, cl1, b, xb);
335 extract (cl0, cl1, a, xa);
336
337 return xr | xg | xb | xa;
164} 338}
165 339
166void 340void
167rxvt_img::brightness (double r, double g, double b, double a) 341rxvt_img::brightness (int32_t r, int32_t g, int32_t b, int32_t a)
168{ 342{
343 unshare ();
344
169 Display *dpy = s->display->dpy; 345 Display *dpy = s->display->dpy;
170 Picture src = create_xrender_mask (dpy, pm, True);
171 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 346 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
172 347
348 // loop should not be needed for brightness, as only -1..1 makes sense
349 //while (r | g | b | a)
350 {
351 unsigned short xr, xg, xb, xa;
352 XRenderColor mask_c;
353
354 if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha))
355 XRenderFillRectangle (dpy, PictOpAdd, dst, &mask_c, 0, 0, w, h);
356
357 if (extract (-65535, 0, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha))
358 {
359 XRenderColor mask_w = { 65535, 65535, 65535, 65535 };
360 XRenderFillRectangle (dpy, PictOpDifference, dst, &mask_w, 0, 0, w, h);
361 mask_c.red = -mask_c.red; //TODO: verify that doing clamp, assign, and negation does the right thing
362 mask_c.green = -mask_c.green;
363 mask_c.blue = -mask_c.blue;
364 mask_c.alpha = -mask_c.alpha;
365 XRenderFillRectangle (dpy, PictOpAdd, dst, &mask_c, 0, 0, w, h);
366 XRenderFillRectangle (dpy, PictOpDifference, dst, &mask_w, 0, 0, w, h);
367 }
368 }
369
370
371 XRenderFreePicture (dpy, dst);
372}
373
374void
375rxvt_img::contrast (int32_t r, int32_t g, int32_t b, int32_t a)
376{
377 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL))
378 {
379 rxvt_warn ("rxvt_img::contrast operation not supported on this display, RENDER extension too old.\n");
380 return;
381 }
382
383 unshare ();
384
385 Display *dpy = s->display->dpy;
386 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
387
173 XRenderColor mask_c; 388 XRenderColor mask_c;
174 mask_c.red = float_to_component (r); 389 mask_c.red = r;
175 mask_c.green = float_to_component (g); 390 mask_c.green = g;
176 mask_c.blue = float_to_component (b); 391 mask_c.blue = b;
177 mask_c.alpha = float_to_component (a); 392 mask_c.alpha = a;
178 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 393 XRenderFillRectangle (dpy, PictOpMultiply, dst, &mask_c, 0, 0, w, h);
179 394
180 XRenderComposite (dpy, PictOpAdd, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 395 XRenderFreePicture (dpy, dst);
181}
182
183void
184rxvt_img::contrast (double r, double g, double b, double a)
185{
186 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL))
187 return;
188
189 Display *dpy = s->display->dpy;
190 Picture src = create_xrender_mask (dpy, pm, True);
191 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
192
193 XRenderColor mask_c;
194 mask_c.red = float_to_component (r);
195 mask_c.green = float_to_component (g);
196 mask_c.blue = float_to_component (b);
197 mask_c.alpha = float_to_component (a);
198 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
199
200 XRenderComposite (dpy, PictOpMultiply, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
201}
202
203bool
204rxvt_img::render_pixbuf (GdkPixbuf *pixbuf, int src_x, int src_y, int width, int height, int dst_x, int dst_y)
205{
206 Display *dpy = s->display->dpy;
207
208 if (s->visual->c_class != TrueColor)
209 return false;
210
211 uint32_t red_mask, green_mask, blue_mask, alpha_mask;
212
213 red_mask = (uint32_t)format->direct.redMask << format->direct.red;
214 green_mask = (uint32_t)format->direct.greenMask << format->direct.green;
215 blue_mask = (uint32_t)format->direct.blueMask << format->direct.blue;
216 alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha;
217
218 int width_r = ecb_popcount32 (red_mask);
219 int width_g = ecb_popcount32 (green_mask);
220 int width_b = ecb_popcount32 (blue_mask);
221 int width_a = ecb_popcount32 (alpha_mask);
222
223 if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8)
224 return false;
225
226 int sh_r = ecb_ctz32 (red_mask);
227 int sh_g = ecb_ctz32 (green_mask);
228 int sh_b = ecb_ctz32 (blue_mask);
229 int sh_a = ecb_ctz32 (alpha_mask);
230
231 if (width > 32767 || height > 32767)
232 return false;
233
234 XImage *ximage = XCreateImage (dpy, s->visual, format->depth, ZPixmap, 0, 0,
235 width, height, 32, 0);
236 if (!ximage)
237 return false;
238
239 if (height > INT_MAX / ximage->bytes_per_line
240 || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line)))
241 {
242 XDestroyImage (ximage);
243 return false;
244 }
245
246 GC gc = XCreateGC (dpy, pm, 0, 0);
247
248 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
249
250 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
251 int channels = gdk_pixbuf_get_n_channels (pixbuf);
252 unsigned char *row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels;
253 char *line = ximage->data;
254
255 rgba c (0, 0, 0);
256
257 if (channels == 4 && alpha_mask == 0)
258 {
259 //pix_colors[Color_bg].get (c);
260 //TODO
261 c.r = 0xffff; c.g = 0xc0c0; c.b = 0xcbcb;//D
262 c.r >>= 8;
263 c.g >>= 8;
264 c.b >>= 8;
265 }
266
267 for (int y = 0; y < height; y++)
268 {
269 for (int x = 0; x < width; x++)
270 {
271 unsigned char *pixel = row + x * channels;
272 uint32_t value;
273 unsigned char r, g, b, a;
274
275 if (channels == 4)
276 {
277 a = pixel[3];
278 r = (pixel[0] * a + c.r * (0xff - a)) / 0xff;
279 g = (pixel[1] * a + c.g * (0xff - a)) / 0xff;
280 b = (pixel[2] * a + c.b * (0xff - a)) / 0xff;
281 }
282 else
283 {
284 a = 0xff;
285 r = pixel[0];
286 g = pixel[1];
287 b = pixel[2];
288 }
289
290 value = ((r >> (8 - width_r)) << sh_r)
291 | ((g >> (8 - width_g)) << sh_g)
292 | ((b >> (8 - width_b)) << sh_b)
293 | ((a >> (8 - width_a)) << sh_a);
294
295 if (ximage->bits_per_pixel == 32)
296 ((uint32_t *)line)[x] = value;
297 else
298 XPutPixel (ximage, x, y, value);
299 }
300
301 row += rowstride;
302 line += ximage->bytes_per_line;
303 }
304
305 XPutImage (dpy, pm, gc, ximage, 0, 0, dst_x, dst_y, width, height);
306 XDestroyImage (ximage);
307 XFreeGC (dpy, gc);
308
309 return true;
310} 396}
311 397
312rxvt_img * 398rxvt_img *
313rxvt_img::clone () 399rxvt_img::clone ()
314{ 400{
315 GC gc = XCreateGC (s->display->dpy, pm, 0, 0); 401 return new rxvt_img (*this);
316 Pixmap pm2 = XCreatePixmap (s->display->dpy, pm, w, h, format->depth);
317 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, w, h, 0, 0);
318 XFreeGC (s->display->dpy, gc);
319 return new rxvt_img (s, format, w, h, pm2);
320} 402}
321 403
322rxvt_img * 404static XRenderPictFormat *
323rxvt_img::transform (int new_width, int new_height, int repeat, double matrix[9]) 405find_alpha_format_for (Display *dpy, XRenderPictFormat *format)
324{ 406{
325 rxvt_img *img = new rxvt_img (s, format, new_width, new_height); 407 if (format->direct.alphaMask)
408 return format; // already has alpha
326 409
410 // try to find a suitable alpha format, one bit alpha is enough for our purposes
411 if (format->type == PictTypeDirect)
412 for (int n = 0; XRenderPictFormat *f = XRenderFindFormat (dpy, 0, 0, n); ++n)
413 if (f->direct.alphaMask
414 && f->type == PictTypeDirect
415 && ecb_popcount32 (f->direct.redMask ) >= ecb_popcount32 (format->direct.redMask )
416 && ecb_popcount32 (f->direct.greenMask) >= ecb_popcount32 (format->direct.greenMask)
417 && ecb_popcount32 (f->direct.blueMask ) >= ecb_popcount32 (format->direct.blueMask ))
418 return f;
419
420 // should be a very good fallback
421 return XRenderFindStandardFormat (dpy, PictStandardARGB32);
422}
423
424rxvt_img *
425rxvt_img::reify ()
426{
427 if (x == 0 && y == 0 && w == ref->w && h == ref->h)
428 return clone ();
429
327 Display *dpy = s->display->dpy; 430 Display *dpy = s->display->dpy;
328 XRenderPictureAttributes pa; 431
329 pa.repeat = repeat; 432 // add an alpha channel if...
330 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 433 bool alpha = !format->direct.alphaMask // pixmap has none yet
434 && (x || y) // we need one because of non-zero offset
435 && repeat == RepeatNone; // and we have no good pixels to fill with
436
437 rxvt_img *img = new rxvt_img (s, alpha ? find_alpha_format_for (dpy, format) : format, 0, 0, w, h, repeat);
438 img->alloc ();
439
440 Picture src = src_picture ();
331 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); 441 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
442
443 if (alpha)
444 {
445 XRenderColor rc = { 0, 0, 0, 0 };
446 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles
447 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, -x, -y, ref->w, ref->h);
448 }
449 else
450 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h);
451
452 XRenderFreePicture (dpy, src);
453 XRenderFreePicture (dpy, dst);
454
455 return img;
456}
457
458rxvt_img *
459rxvt_img::sub_rect (int x, int y, int width, int height)
460{
461 rxvt_img *img = clone ();
462
463 img->x += x;
464 img->y += y;
465
466 if (w != width || h != height)
467 {
468 img->w = width;
469 img->h = height;
470
471 rxvt_img *img2 = img->reify ();
472 delete img;
473 img = img2;
474 }
475
476 return img;
477}
478
479rxvt_img *
480rxvt_img::transform (int new_width, int new_height, double matrix[9])
481{
482 rxvt_img *img = new rxvt_img (s, format, 0, 0, new_width, new_height, repeat);
483 img->alloc ();
484
485 Display *dpy = s->display->dpy;
486 Picture src = src_picture ();
487 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
332 488
333 XTransform xfrm; 489 XTransform xfrm;
334 490
335 for (int i = 0; i < 3; ++i) 491 for (int i = 0; i < 3; ++i)
336 for (int j = 0; j < 3; ++j) 492 for (int j = 0; j < 3; ++j)
337 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]); 493 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
338 494
495 xfrm.matrix [0][2] -= XDoubleToFixed (x);//TODO
496 xfrm.matrix [1][2] -= XDoubleToFixed (y);
497
339 XRenderSetPictureFilter (dpy, src, "good", 0, 0); 498 XRenderSetPictureFilter (dpy, src, "good", 0, 0);
340 XRenderSetPictureTransform (dpy, src, &xfrm); 499 XRenderSetPictureTransform (dpy, src, &xfrm);
341 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height); 500 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height);
342 501
343 XRenderFreePicture (dpy, src); 502 XRenderFreePicture (dpy, src);
347} 506}
348 507
349rxvt_img * 508rxvt_img *
350rxvt_img::scale (int new_width, int new_height) 509rxvt_img::scale (int new_width, int new_height)
351{ 510{
511 if (w == new_width && h == new_height)
512 return clone ();
513
352 double matrix[9] = { 514 double matrix[9] = {
353 w / (double)new_width, 0, 0, 515 w / (double)new_width, 0, 0,
354 0, h / (double)new_height, 0, 516 0, h / (double)new_height, 0,
355 0, 0, 1 517 0, 0, 1
356 }; 518 };
357 519
520 int old_repeat_mode = repeat;
521 repeat = RepeatPad; // not right, but xrender can't proeprly scale it seems
522
358 return transform (new_width, new_height, RepeatNormal, matrix); 523 rxvt_img *img = transform (new_width, new_height, matrix);
359}
360 524
525 repeat = old_repeat_mode;
526 img->repeat = repeat;
527
528 return img;
529}
530
361rxvt_img * 531rxvt_img *
362rxvt_img::rotate (int new_width, int new_height, int repeat, int x, int y, double phi) 532rxvt_img::rotate (int new_width, int new_height, int x, int y, double phi)
363{ 533{
364 double s = sin (phi); 534 double s = sin (phi);
365 double c = cos (phi); 535 double c = cos (phi);
366 536
367 double matrix[9] = { 537 double matrix[9] = {
368 c, -s, -c * x + s * y + x, 538 c, -s, -c * x + s * y + x,
369 s, c, -s * x - c * y + y, 539 s, c, -s * x - c * y + y,
370 0, 0, 1 540 0, 0, 1
371 }; 541 };
372 542
373 return transform (new_width, new_height, repeat, matrix); 543 return transform (new_width, new_height, matrix);
374} 544}
375 545
376rxvt_img * 546rxvt_img *
377rxvt_img::convert_to (XRenderPictFormat *new_format) 547rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg)
378{ 548{
549 if (new_format == format)
550 return clone ();
551
379 rxvt_img *img = new rxvt_img (s, new_format, w, h); 552 rxvt_img *img = new rxvt_img (s, new_format, x, y, w, h, repeat);
553 img->alloc ();
380 554
381 Display *dpy = s->display->dpy; 555 Display *dpy = s->display->dpy;
382 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); 556 Picture src = src_picture ();
383 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0); 557 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0);
558 int op = PictOpSrc;
384 559
560 if (format->direct.alphaMask && !new_format->direct.alphaMask)
561 {
562 // does it have to be that complicated
563 rgba c;
564 bg.get (c);
565
566 XRenderColor rc = { c.r, c.g, c.b, 0xffff };
567 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);
568
569 op = PictOpOver;
570 }
571
385 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 572 XRenderComposite (dpy, op, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
386 573
387 XRenderFreePicture (dpy, src); 574 XRenderFreePicture (dpy, src);
388 XRenderFreePicture (dpy, dst); 575 XRenderFreePicture (dpy, dst);
389 576
390 return img; 577 return img;
391} 578}
392 579
580rxvt_img *
581rxvt_img::blend (rxvt_img *img, double factor)
582{
583 rxvt_img *img2 = clone ();
584 Display *dpy = s->display->dpy;
585 Picture src = img->src_picture ();
586 Picture dst = XRenderCreatePicture (dpy, img2->pm, img2->format, 0, 0);
587
588 Pixmap pixmap = XCreatePixmap (dpy, img->pm, 1, 1, 8);
589 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, PictStandardA8);
590 XRenderPictureAttributes pa;
591 pa.repeat = True;
592 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
593 XFreePixmap (dpy, pixmap);
594
595 XRenderColor mask_c;
596
597 mask_c.alpha = float_to_component (factor);
598 mask_c.red =
599 mask_c.green =
600 mask_c.blue = 0;
601 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
602
603 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, w, h);
604
605 XRenderFreePicture (dpy, src);
606 XRenderFreePicture (dpy, dst);
607 XRenderFreePicture (dpy, mask);
608
609 return img2;
610}
611
393#endif 612#endif
394 613

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines