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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines