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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines