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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines