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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines