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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines