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.12 by root, Mon Jun 4 15:28:49 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{
23}
24#endif
25
26rxvt_img *
27rxvt_img::new_from_root (rxvt_screen *s)
28{
29 Display *dpy = s->display->dpy;
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]);
34
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))
43 return 0;
44
45 rxvt_img *img = new rxvt_img (
46 s,
47 XRenderFindVisualFormat (dpy, DefaultVisual (dpy, s->display->screen)),
48 0,
49 0,
50 root_pm_w,
51 root_pm_h
52 );
53
54 img->pm = root_pixmap;
55 img->ref = new pixref (root_pm_w, root_pm_h);
56 img->ref->ours = false;
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;
18} 164}
19 165
20rxvt_img * 166rxvt_img *
21rxvt_img::new_from_file (rxvt_screen *s, const char *filename) 167rxvt_img::new_from_file (rxvt_screen *s, const char *filename)
22{ 168{
24 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err); 170 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err);
25 171
26 if (!pb) 172 if (!pb)
27 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message); 173 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message);
28 174
29 rxvt_img *img = new rxvt_img ( 175 rxvt_img *img = new_from_pixbuf (s, pb);
30 s,
31 XRenderFindStandardFormat (s->display->dpy, gdk_pixbuf_get_has_alpha (pb) ? PictStandardARGB32 : PictStandardRGB24),
32 gdk_pixbuf_get_width (pb),
33 gdk_pixbuf_get_height (pb)
34 );
35 176
36 img->render (pb, 0, 0, img->w, img->h, 0, 0); 177 g_object_unref (pb);
37 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 ();
44 XFreePixmap (s->display->dpy, pm); 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;
45} 216}
46 217
47void 218void
48rxvt_img::unshare () 219rxvt_img::unshare ()
49{ 220{
50 if (!shared) 221 if (ref->cnt == 1 && ref->ours)
51 return; 222 return;
52 223
53 rxvt_img *img = clone (); 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);
228 XFreeGC (s->display->dpy, gc);
54 229
55 ::swap (pm , img->pm); 230 destroy ();
56 ::swap (shared, img->shared);
57 231
58 delete img; 232 pm = pm2;
233 ref = new pixref (ref->w, ref->h);
59} 234}
60 235
61void 236void
62rxvt_img::fill (const rxvt_color &c) 237rxvt_img::fill (const rxvt_color &c)
63{ 238{
87 262
88 for (int i = 0; i < width; i++) 263 for (int i = 0; i < width; i++)
89 params[i+2] = XDoubleToFixed (kernel[i] / sum); 264 params[i+2] = XDoubleToFixed (kernel[i] / sum);
90} 265}
91 266
92void 267rxvt_img *
93rxvt_img::blur (int rh, int rv) 268rxvt_img::blur (int rh, int rv)
94{ 269{
95 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV)) 270 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
96 return; 271 return clone ();
97 272
98 Display *dpy = s->display->dpy; 273 Display *dpy = s->display->dpy;
99 int size = max (rh, rv) * 2 + 1; 274 int size = max (rh, rv) * 2 + 1;
100 double *kernel = (double *)malloc (size * sizeof (double)); 275 double *kernel = (double *)malloc (size * sizeof (double));
101 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 ();
102 281
103 XRenderPictureAttributes pa; 282 XRenderPictureAttributes pa;
104
105 pa.repeat = RepeatPad; 283 pa.repeat = RepeatPad;
106 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 284 Picture dst = XRenderCreatePicture (dpy, img->pm, format, CPRepeat, &pa);
285
107 Pixmap tmp = XCreatePixmap (dpy, pm, w, h, format->depth); 286 Pixmap tmp_pm = XCreatePixmap (dpy, pm, w, h, format->depth);
108 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa); 287 Picture tmp = XRenderCreatePicture (dpy, tmp_pm , format, CPRepeat, &pa);
109 XFreePixmap (dpy, tmp); 288 XFreePixmap (dpy, tmp_pm);
110 289
111 if (kernel && params) 290 if (kernel && params)
112 { 291 {
113 size = rh * 2 + 1; 292 size = rh * 2 + 1;
114 get_gaussian_kernel (rh, size, kernel, params); 293 get_gaussian_kernel (rh, size, kernel, params);
116 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 295 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
117 XRenderComposite (dpy, 296 XRenderComposite (dpy,
118 PictOpSrc, 297 PictOpSrc,
119 src, 298 src,
120 None, 299 None,
121 dst, 300 tmp,
122 0, 0, 301 0, 0,
123 0, 0, 302 0, 0,
124 0, 0, 303 0, 0,
125 w, h); 304 w, h);
126 305
127 ::swap (src, dst);
128
129 size = rv * 2 + 1; 306 size = rv * 2 + 1;
130 get_gaussian_kernel (rv, size, kernel, params); 307 get_gaussian_kernel (rv, size, kernel, params);
131 ::swap (params[0], params[1]); 308 ::swap (params[0], params[1]);
132 309
133 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 310 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
134 XRenderComposite (dpy, 311 XRenderComposite (dpy,
135 PictOpSrc, 312 PictOpSrc,
136 src, 313 tmp,
137 None, 314 None,
138 dst, 315 dst,
139 0, 0, 316 0, 0,
140 0, 0, 317 0, 0,
141 0, 0, 318 0, 0,
144 321
145 free (kernel); 322 free (kernel);
146 free (params); 323 free (params);
147 XRenderFreePicture (dpy, src); 324 XRenderFreePicture (dpy, src);
148 XRenderFreePicture (dpy, dst); 325 XRenderFreePicture (dpy, dst);
326 XRenderFreePicture (dpy, tmp);
327
328 return img;
149} 329}
150 330
151static Picture 331static Picture
152create_xrender_mask (Display *dpy, Drawable drawable, Bool argb) 332create_xrender_mask (Display *dpy, Drawable drawable, Bool argb)
153{ 333{
162 342
163 return mask; 343 return mask;
164} 344}
165 345
166void 346void
167rxvt_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)
168{ 348{
169 Display *dpy = s->display->dpy; 349 Display *dpy = s->display->dpy;
170 Picture src = create_xrender_mask (dpy, pm, True); 350 Picture src = create_xrender_mask (dpy, pm, True);
171 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 351 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
172 352
173 XRenderColor mask_c; 353 XRenderColor mask_c;
174 mask_c.red = float_to_component (r); 354 mask_c.red = r;
175 mask_c.green = float_to_component (g); 355 mask_c.green = g;
176 mask_c.blue = float_to_component (b); 356 mask_c.blue = b;
177 mask_c.alpha = float_to_component (a); 357 mask_c.alpha = a;
178 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 358 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
179 359
180 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);
181} 364}
182 365
183void 366void
184rxvt_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)
185{ 368{
186 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL)) 369 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL))
187 return; 370 return;
188 371
189 Display *dpy = s->display->dpy; 372 Display *dpy = s->display->dpy;
190 Picture src = create_xrender_mask (dpy, pm, True); 373 Picture src = create_xrender_mask (dpy, pm, True);
191 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 374 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
192 375
193 XRenderColor mask_c; 376 XRenderColor mask_c;
194 mask_c.red = float_to_component (r); 377 mask_c.red = r;
195 mask_c.green = float_to_component (g); 378 mask_c.green = g;
196 mask_c.blue = float_to_component (b); 379 mask_c.blue = b;
197 mask_c.alpha = float_to_component (a); 380 mask_c.alpha = a;
198 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 381 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
199 382
200 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);
201}
202 384
203void 385 XRenderFreePicture (dpy, src);
204rxvt_img::render (GdkPixbuf *pixbuf, int src_x, int src_y, int width, int height, int dst_x, int dst_y) 386 XRenderFreePicture (dpy, dst);
205{
206 //TODO
207} 387}
208 388
209rxvt_img * 389rxvt_img *
210rxvt_img::clone () 390rxvt_img::clone ()
211{ 391{
212 GC gc = XCreateGC (s->display->dpy, pm, 0, 0); 392 return new rxvt_img (*this);
213 Pixmap pm2 = XCreatePixmap (s->display->dpy, pm, w, h, format->depth);
214 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, w, h, 0, 0);
215 XFreeGC (s->display->dpy, gc);
216 return new rxvt_img (s, format, w, h, pm2);
217} 393}
218 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
219rxvt_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 *
220rxvt_img::transform (int new_width, int new_height, int repeat, double matrix[9]) 470rxvt_img::transform (int new_width, int new_height, double matrix[9])
221{ 471{
222 rxvt_img *img = new rxvt_img (s, format, new_width, new_height); 472 rxvt_img *img = new rxvt_img (s, format, 0, 0, new_width, new_height, repeat);
473 img->alloc ();
223 474
224 Display *dpy = s->display->dpy; 475 Display *dpy = s->display->dpy;
225 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); 476 Picture src = src_picture ();
226 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); 477 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
227 478
228 XTransform xfrm; 479 XTransform xfrm;
229 480
230 for (int i = 0; i < 3; ++i) 481 for (int i = 0; i < 3; ++i)
231 for (int j = 0; j < 3; ++j) 482 for (int j = 0; j < 3; ++j)
232 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]); 483 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
233 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);
234 XRenderSetPictureTransform (dpy, src, &xfrm); 491 XRenderSetPictureTransform (dpy, src, &xfrm);
235 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height); 492 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height);
236 493
237 XRenderFreePicture (dpy, src); 494 XRenderFreePicture (dpy, src);
238 XRenderFreePicture (dpy, dst); 495 XRenderFreePicture (dpy, dst);
241} 498}
242 499
243rxvt_img * 500rxvt_img *
244rxvt_img::scale (int new_width, int new_height) 501rxvt_img::scale (int new_width, int new_height)
245{ 502{
503 if (w == new_width && h == new_height)
504 return clone ();
505
246 double matrix[9] = { 506 double matrix[9] = {
247 new_width / (double)w, 0, 0, 507 w / (double)new_width, 0, 0,
248 0, new_height / (double)h, 0, 508 0, h / (double)new_height, 0,
249 0, 0, 1 509 0, 0, 1
250 }; 510 };
251 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
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
252 return transform (new_width, new_height, RepeatNormal, matrix); 535 return transform (new_width, new_height, matrix);
253} 536}
254 537
255rxvt_img * 538rxvt_img *
256rxvt_img::convert_to (XRenderPictFormat *new_format) 539rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg)
257{ 540{
541 if (new_format == format)
542 return clone ();
543
258 rxvt_img *img = new rxvt_img (s, new_format, w, h); 544 rxvt_img *img = new rxvt_img (s, new_format, x, y, w, h, repeat);
545 img->alloc ();
259 546
260 Display *dpy = s->display->dpy; 547 Display *dpy = s->display->dpy;
261 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); 548 Picture src = src_picture ();
262 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0); 549 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0);
550 int op = PictOpSrc;
263 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
264 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);
265 565
266 XRenderFreePicture (dpy, src);
267 XRenderFreePicture (dpy, dst); 566 XRenderFreePicture (dpy, src);
567 XRenderFreePicture (dpy, dst);
268 568
569 return img;
570}
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
269 return img; 595 return img2;
270} 596}
271 597
272#endif 598#endif
273 599

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines