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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines