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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines