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.6 by sf-exg, Sun Jun 3 18:49:55 2012 UTC vs.
Revision 1.74 by root, Sat Jun 9 19:20:04 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)
11{
12 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth);
13}
14
15rxvt_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) 8: s(screen), x(x), y(y), w(width), h(height), format(format), repeat(repeat),
9 pm(0), ref(0)
17{ 10{
18} 11}
19 12
20rxvt_img * 13rxvt_img::rxvt_img (const rxvt_img &img)
21rxvt_img::new_from_file (rxvt_screen *s, const char *filename) 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)
22{ 15{
23 GError *err; 16 ++ref->cnt;
24 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err); 17}
25 18
26 if (!pb) 19rxvt_img *
20rxvt_img::new_from_root (rxvt_screen *s)
21{
22 Display *dpy = s->display->dpy;
23 unsigned int root_pm_w, root_pm_h;
24 Pixmap root_pixmap = s->display->get_pixmap_property (s->display->xa[XA_XROOTPMAP_ID]);
25 if (root_pixmap == None)
26 root_pixmap = s->display->get_pixmap_property (s->display->xa[XA_ESETROOT_PMAP_ID]);
27
28 if (root_pixmap == None)
29 return 0;
30
31 Window wdummy;
32 int idummy;
33 unsigned int udummy;
34
35 if (!XGetGeometry (dpy, root_pixmap, &wdummy, &idummy, &idummy, &root_pm_w, &root_pm_h, &udummy, &udummy))
27 return 0; 36 return 0;
28 37
29 rxvt_img *img = new rxvt_img ( 38 rxvt_img *img = new rxvt_img (
30 s, 39 s,
31 XRenderFindStandardFormat (s->display->dpy, gdk_pixbuf_get_has_alpha (pb) ? PictStandardARGB32 : PictStandardRGB24), 40 XRenderFindVisualFormat (dpy, DefaultVisual (dpy, s->display->screen)),
32 gdk_pixbuf_get_width (pb), 41 0,
33 gdk_pixbuf_get_height (pb) 42 0,
43 root_pm_w,
44 root_pm_h
34 ); 45 );
35 46
36 img->render (pb, 0, 0, img->w, img->h, 0, 0); 47 img->pm = root_pixmap;
48 img->ref = new pixref (root_pm_w, root_pm_h);
49 img->ref->ours = false;
37 50
51 return img;
52}
53
54# if HAVE_PIXBUF
55rxvt_img *
56rxvt_img::new_from_pixbuf (rxvt_screen *s, GdkPixbuf *pb)
57{
58 Display *dpy = s->display->dpy;
59
60 int width = gdk_pixbuf_get_width (pb);
61 int height = gdk_pixbuf_get_height (pb);
62
63 if (width > 32767 || height > 32767) // well, we *could* upload in chunks
64 rxvt_fatal ("rxvt_img::new_from_pixbuf: image too big (maximum size 32768x32768).\n");
65
66 // since we require rgb24/argb32 formats from xrender we assume
67 // that both 24 and 32 bpp MUST be supported by any screen that supports xrender
68 int depth = gdk_pixbuf_get_has_alpha (pb) ? 32 : 24;
69
70 int byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
71
72 XImage xi;
73
74 xi.width = width;
75 xi.height = height;
76 xi.xoffset = 0;
77 xi.format = ZPixmap;
78 xi.byte_order = ImageByteOrder (dpy);
79 xi.bitmap_unit = 0; //XY only, unused
80 xi.bitmap_bit_order = 0; //XY only, unused
81 xi.bitmap_pad = BitmapPad (dpy);
82 xi.depth = depth;
83 xi.bytes_per_line = 0;
84 xi.bits_per_pixel = 32; //Z only
85 xi.red_mask = 0x00000000; //Z only, unused
86 xi.green_mask = 0x00000000; //Z only, unused
87 xi.blue_mask = 0x00000000; //Z only, unused
88 xi.obdata = 0; // probably unused
89
90 bool byte_order_mismatch = byte_order != xi.byte_order;
91
92 if (!XInitImage (&xi))
93 rxvt_fatal ("unable to initialise ximage, please report.\n");
94
95 if (height > INT_MAX / xi.bytes_per_line)
96 rxvt_fatal ("rxvt_img::new_from_pixbuf: image too big for Xlib.\n");
97
98 xi.data = (char *)rxvt_malloc (height * xi.bytes_per_line);
99
100 int rowstride = gdk_pixbuf_get_rowstride (pb);
101
102 assert (3 + (depth == 32) == gdk_pixbuf_get_n_channels (pb));
103 unsigned char *row = gdk_pixbuf_get_pixels (pb);
104 char *line = xi.data;
105
106 for (int y = 0; y < height; y++)
107 {
108 unsigned char *src = row;
109 uint32_t *dst = (uint32_t *)line;
110
111 if (depth == 24)
112 for (int x = 0; x < width; x++)
113 {
114 uint8_t r = *src++;
115 uint8_t g = *src++;
116 uint8_t b = *src++;
117
118 uint32_t v = (r << 16) | (g << 8) | b;
119
120 if (ecb_big_endian () ? !byte_order_mismatch : byte_order_mismatch)
121 v = ecb_bswap32 (v);
122
123 *dst++ = v;
124 }
125 else
126 for (int x = 0; x < width; x++)
127 {
128 uint32_t v = *(uint32_t *)src; src += 4;
129
130 if (ecb_big_endian ())
131 v = ecb_bswap32 (v);
132
133 v = ecb_rotl32 (v, 8); // abgr to bgra
134
135 if (!byte_order_mismatch)
136 v = ecb_bswap32 (v);
137
138 *dst++ = v;
139 }
140
141 row += rowstride;
142 line += xi.bytes_per_line;
143 }
144
145 rxvt_img *img = new rxvt_img (s, XRenderFindStandardFormat (dpy, depth == 24 ? PictStandardRGB24 : PictStandardARGB32), 0, 0, width, height);
146 img->alloc ();
147
148 GC gc = XCreateGC (dpy, img->pm, 0, 0);
149 XPutImage (dpy, img->pm, gc, &xi, 0, 0, 0, 0, width, height);
150 XFreeGC (dpy, gc);
151
152 free (xi.data);
153
154 return img;
155}
156
157rxvt_img *
158rxvt_img::new_from_file (rxvt_screen *s, const char *filename)
159{
160 GError *err = 0;
161 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err);
162
163 if (!pb)
164 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message);
165
166 rxvt_img *img = new_from_pixbuf (s, pb);
167
168 g_object_unref (pb);
169
170 return img;
171}
172# endif
173
174void
175rxvt_img::destroy ()
176{
177 if (--ref->cnt)
38 return img; 178 return;
179
180 if (pm && ref->ours)
181 XFreePixmap (s->display->dpy, pm);
182
183 delete ref;
39} 184}
40 185
41rxvt_img::~rxvt_img () 186rxvt_img::~rxvt_img ()
42{ 187{
43 if (!shared) 188 destroy ();
189}
190
191void
192rxvt_img::alloc ()
193{
194 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth);
195 ref = new pixref (w, h);
196}
197
198Picture
199rxvt_img::src_picture ()
200{
201 Display *dpy = s->display->dpy;
202
203 XRenderPictureAttributes pa;
204 pa.repeat = repeat;
205 Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
206
207 return pic;
208}
209
210void
211rxvt_img::unshare ()
212{
213 if (ref->cnt == 1 && ref->ours)
214 return;
215
216 Pixmap pm2 = XCreatePixmap (s->display->dpy, s->display->root, ref->w, ref->h, format->depth);
217 GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
218 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0);
44 XFreePixmap (s->display->dpy, pm); 219 XFreeGC (s->display->dpy, gc);
220
221 destroy ();
222
223 pm = pm2;
224 ref = new pixref (ref->w, ref->h);
45} 225}
46 226
47void 227void
48rxvt_img::fill (const rxvt_color &c) 228rxvt_img::fill (const rxvt_color &c)
49{ 229{
73 253
74 for (int i = 0; i < width; i++) 254 for (int i = 0; i < width; i++)
75 params[i+2] = XDoubleToFixed (kernel[i] / sum); 255 params[i+2] = XDoubleToFixed (kernel[i] / sum);
76} 256}
77 257
78void 258rxvt_img *
79rxvt_img::blur (int rh, int rv) 259rxvt_img::blur (int rh, int rv)
80{ 260{
81 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV)) 261 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
82 return; 262 return clone ();
83 263
84 Display *dpy = s->display->dpy; 264 Display *dpy = s->display->dpy;
85 int size = max (rh, rv) * 2 + 1; 265 int size = max (rh, rv) * 2 + 1;
86 double *kernel = (double *)malloc (size * sizeof (double)); 266 double *kernel = (double *)malloc (size * sizeof (double));
87 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 267 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
268 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat);
269 img->alloc ();
88 270
89 XRenderPictureAttributes pa; 271 XRenderPictureAttributes pa;
90
91 pa.repeat = RepeatPad; 272 pa.repeat = RepeatPad;
92 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 273 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
274 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0);
275
93 Pixmap tmp = XCreatePixmap (dpy, pm, w, h, format->depth); 276 Pixmap tmp_pm = XCreatePixmap (dpy, pm, w, h, format->depth);
94 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa); 277 Picture tmp = XRenderCreatePicture (dpy, tmp_pm , format, CPRepeat, &pa);
95 XFreePixmap (dpy, tmp); 278 XFreePixmap (dpy, tmp_pm);
96 279
97 if (kernel && params) 280 if (kernel && params)
98 { 281 {
99 size = rh * 2 + 1; 282 size = rh * 2 + 1;
100 get_gaussian_kernel (rh, size, kernel, params); 283 get_gaussian_kernel (rh, size, kernel, params);
101 284
102 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 285 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
103 XRenderComposite (dpy, 286 XRenderComposite (dpy,
104 PictOpSrc, 287 PictOpSrc,
105 src, 288 src,
289 None,
290 tmp,
291 0, 0,
292 0, 0,
293 0, 0,
294 w, h);
295
296 size = rv * 2 + 1;
297 get_gaussian_kernel (rv, size, kernel, params);
298 ::swap (params[0], params[1]);
299
300 XRenderSetPictureFilter (dpy, tmp, FilterConvolution, params, size+2);
301 XRenderComposite (dpy,
302 PictOpSrc,
303 tmp,
106 None, 304 None,
107 dst, 305 dst,
108 0, 0, 306 0, 0,
109 0, 0, 307 0, 0,
110 0, 0, 308 0, 0,
111 w, h); 309 w, h);
112
113 ::swap (src, dst);
114
115 size = rv * 2 + 1;
116 get_gaussian_kernel (rv, size, kernel, params);
117 ::swap (params[0], params[1]);
118
119 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
120 XRenderComposite (dpy,
121 PictOpSrc,
122 src,
123 None,
124 dst,
125 0, 0,
126 0, 0,
127 0, 0,
128 w, h);
129 } 310 }
130 311
131 free (kernel); 312 free (kernel);
132 free (params); 313 free (params);
133 XRenderFreePicture (dpy, src); 314 XRenderFreePicture (dpy, src);
134 XRenderFreePicture (dpy, dst); 315 XRenderFreePicture (dpy, dst);
316 XRenderFreePicture (dpy, tmp);
317
318 return img;
135} 319}
136 320
137static Picture 321static Picture
138create_xrender_mask (Display *dpy, Drawable drawable, Bool argb) 322create_xrender_mask (Display *dpy, Drawable drawable, Bool argb)
139{ 323{
140 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8); 324 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
141 325
142 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8); 326 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
327 XRenderPictureAttributes pa;
328 pa.repeat = RepeatNormal;
329 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
330
331 XFreePixmap (dpy, pixmap);
332
333 return mask;
334}
335
336static void
337extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc)
338{
339 int32_t x = clamp (c, cl0, cl1);
340 c -= x;
341 xc = x;
342}
343
344static bool
345extract (int32_t cl0, int32_t cl1, int32_t &r, int32_t &g, int32_t &b, int32_t &a, unsigned short &xr, unsigned short &xg, unsigned short &xb, unsigned short &xa)
346{
347 extract (cl0, cl1, r, xr);
348 extract (cl0, cl1, g, xg);
349 extract (cl0, cl1, b, xb);
350 extract (cl0, cl1, a, xa);
351
352 return xr | xg | xb | xa;
353}
354
355void
356rxvt_img::brightness (int32_t r, int32_t g, int32_t b, int32_t a)
357{
358 unshare ();
359
360 Display *dpy = s->display->dpy;
361 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
362
363 // loop should not be needed for brightness, as only -1..1 makes sense
364 //while (r | g | b | a)
365 {
366 unsigned short xr, xg, xb, xa;
367 XRenderColor mask_c;
368
369 if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha))
370 XRenderFillRectangle (dpy, PictOpAdd, dst, &mask_c, 0, 0, w, h);
371
372 if (extract (-65535, 0, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha))
373 {
374 XRenderColor mask_w = { 65535, 65535, 65535, 65535 };
375 XRenderFillRectangle (dpy, PictOpDifference, dst, &mask_w, 0, 0, w, h);
376 mask_c.red = -mask_c.red; //TODO: verify that doing clamp, assign, and negation does the right thing
377 mask_c.green = -mask_c.green;
378 mask_c.blue = -mask_c.blue;
379 mask_c.alpha = -mask_c.alpha;
380 XRenderFillRectangle (dpy, PictOpAdd, dst, &mask_c, 0, 0, w, h);
381 XRenderFillRectangle (dpy, PictOpDifference, dst, &mask_w, 0, 0, w, h);
382 }
383 }
384
385 XRenderFreePicture (dpy, dst);
386}
387
388void
389rxvt_img::contrast (int32_t r, int32_t g, int32_t b, int32_t a)
390{
391 if (r < 0 || g < 0 || b < 0 || a < 0)
392 rxvt_fatal ("rxvt_img::contrast does not support negative values.\n");
393
394 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat);
395 img->alloc ();
396
397 {
398 rxvt_color empty;
399 empty.set (s, rgba (0, 0, 0, 0));
400 img->fill (empty);
401 }
402
403 // premultiply (yeah, these are not exact, sue me or fix it)
404 r = (r * (a >> 8)) >> 8;
405 g = (g * (a >> 8)) >> 8;
406 b = (b * (a >> 8)) >> 8;
407
408 Display *dpy = s->display->dpy;
409
410 Picture src = src_picture ();
411 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0);
412 Picture mul = create_xrender_mask (dpy, pm, True);
413
414 XRenderPictureAttributes pa;
415 pa.component_alpha = 1;
416 XRenderChangePicture (dpy, mul, CPComponentAlpha, &pa);
417
418 //TODO: this operator does not yet implement some useful contrast
419 while (r | g | b | a)
420 {
421 unsigned short xr, xg, xb, xa;
422 XRenderColor mask_c;
423
424 if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha))
425 {
426 XRenderFillRectangle (dpy, PictOpSrc, mul, &mask_c, 0, 0, 1, 1);
427 XRenderComposite (dpy, PictOpAdd, src, mul, dst, 0, 0, 0, 0, 0, 0, w, h);
428 }
429 }
430
431 XRenderFreePicture (dpy, mul);
432 XRenderFreePicture (dpy, dst);
433 XRenderFreePicture (dpy, src);
434
435 ::swap (img->ref, ref);
436 ::swap (img->pm , pm );
437
438 delete img;
439}
440
441rxvt_img *
442rxvt_img::clone ()
443{
444 return new rxvt_img (*this);
445}
446
447static XRenderPictFormat *
448find_alpha_format_for (Display *dpy, XRenderPictFormat *format)
449{
450 if (format->direct.alphaMask)
451 return format; // already has alpha
452
453 // try to find a suitable alpha format, one bit alpha is enough for our purposes
454 if (format->type == PictTypeDirect)
455 for (int n = 0; XRenderPictFormat *f = XRenderFindFormat (dpy, 0, 0, n); ++n)
456 if (f->direct.alphaMask
457 && f->type == PictTypeDirect
458 && ecb_popcount32 (f->direct.redMask ) >= ecb_popcount32 (format->direct.redMask )
459 && ecb_popcount32 (f->direct.greenMask) >= ecb_popcount32 (format->direct.greenMask)
460 && ecb_popcount32 (f->direct.blueMask ) >= ecb_popcount32 (format->direct.blueMask ))
461 return f;
462
463 // should be a very good fallback
464 return XRenderFindStandardFormat (dpy, PictStandardARGB32);
465}
466
467rxvt_img *
468rxvt_img::reify ()
469{
470 if (x == 0 && y == 0 && w == ref->w && h == ref->h)
471 return clone ();
472
473 Display *dpy = s->display->dpy;
474
475 // add an alpha channel if...
476 bool alpha = !format->direct.alphaMask // pixmap has none yet
477 && (x || y) // we need one because of non-zero offset
478 && repeat == RepeatNone; // and we have no good pixels to fill with
479
480 rxvt_img *img = new rxvt_img (s, alpha ? find_alpha_format_for (dpy, format) : format, 0, 0, w, h, repeat);
481 img->alloc ();
482
483 Picture src = src_picture ();
484 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
485
486 if (alpha)
487 {
488 XRenderColor rc = { 0, 0, 0, 0 };
489 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles
490 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, -x, -y, ref->w, ref->h);
491 }
492 else
493 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h);
494
495 XRenderFreePicture (dpy, src);
496 XRenderFreePicture (dpy, dst);
497
498 return img;
499}
500
501rxvt_img *
502rxvt_img::sub_rect (int x, int y, int width, int height)
503{
504 rxvt_img *img = clone ();
505
506 img->x += x;
507 img->y += y;
508
509 if (w != width || h != height)
510 {
511 img->w = width;
512 img->h = height;
513
514 rxvt_img *img2 = img->reify ();
515 delete img;
516 img = img2;
517 }
518
519 return img;
520}
521
522rxvt_img *
523rxvt_img::transform (int new_width, int new_height, double matrix[9])
524{
525 rxvt_img *img = new rxvt_img (s, format, 0, 0, new_width, new_height, repeat);
526 img->alloc ();
527
528 Display *dpy = s->display->dpy;
529 Picture src = src_picture ();
530 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
531
532 XTransform xfrm;
533
534 for (int i = 0; i < 3; ++i)
535 for (int j = 0; j < 3; ++j)
536 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
537
538 xfrm.matrix [0][2] -= XDoubleToFixed (x);//TODO
539 xfrm.matrix [1][2] -= XDoubleToFixed (y);
540
541 XRenderSetPictureFilter (dpy, src, "good", 0, 0);
542 XRenderSetPictureTransform (dpy, src, &xfrm);
543 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height);
544
545 XRenderFreePicture (dpy, src);
546 XRenderFreePicture (dpy, dst);
547
548 return img;
549}
550
551rxvt_img *
552rxvt_img::scale (int new_width, int new_height)
553{
554 if (w == new_width && h == new_height)
555 return clone ();
556
557 double matrix[9] = {
558 w / (double)new_width, 0, 0,
559 0, h / (double)new_height, 0,
560 0, 0, 1
561 };
562
563 int old_repeat_mode = repeat;
564 repeat = RepeatPad; // not right, but xrender can't proeprly scale it seems
565
566 rxvt_img *img = transform (new_width, new_height, matrix);
567
568 repeat = old_repeat_mode;
569 img->repeat = repeat;
570
571 return img;
572}
573
574rxvt_img *
575rxvt_img::rotate (int new_width, int new_height, int x, int y, double phi)
576{
577 double s = sin (phi);
578 double c = cos (phi);
579
580 double matrix[9] = {
581 c, -s, -c * x + s * y + x,
582 s, c, -s * x - c * y + y,
583 0, 0, 1
584 };
585
586 return transform (new_width, new_height, matrix);
587}
588
589rxvt_img *
590rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg)
591{
592 if (new_format == format)
593 return clone ();
594
595 rxvt_img *img = new rxvt_img (s, new_format, x, y, w, h, repeat);
596 img->alloc ();
597
598 Display *dpy = s->display->dpy;
599 Picture src = src_picture ();
600 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0);
601 int op = PictOpSrc;
602
603 if (format->direct.alphaMask && !new_format->direct.alphaMask)
604 {
605 // does it have to be that complicated
606 rgba c;
607 bg.get (c);
608
609 XRenderColor rc = { c.r, c.g, c.b, 0xffff };
610 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);
611
612 op = PictOpOver;
613 }
614
615 XRenderComposite (dpy, op, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
616
617 XRenderFreePicture (dpy, src);
618 XRenderFreePicture (dpy, dst);
619
620 return img;
621}
622
623rxvt_img *
624rxvt_img::blend (rxvt_img *img, double factor)
625{
626 rxvt_img *img2 = clone ();
627 Display *dpy = s->display->dpy;
628 Picture src = img->src_picture ();
629 Picture dst = XRenderCreatePicture (dpy, img2->pm, img2->format, 0, 0);
630
631 Pixmap pixmap = XCreatePixmap (dpy, img->pm, 1, 1, 8);
632 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, PictStandardA8);
143 XRenderPictureAttributes pa; 633 XRenderPictureAttributes pa;
144 pa.repeat = True; 634 pa.repeat = True;
145 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa); 635 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
146
147 XFreePixmap (dpy, pixmap); 636 XFreePixmap (dpy, pixmap);
148 637
149 return mask;
150}
151
152void
153rxvt_img::brightness (double r, double g, double b, double a)
154{
155 Display *dpy = s->display->dpy;
156 Picture src = create_xrender_mask (dpy, pm, True);
157 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
158
159 XRenderColor mask_c; 638 XRenderColor mask_c;
160 mask_c.red = float_to_component (r); 639
161 mask_c.green = float_to_component (g);
162 mask_c.blue = float_to_component (b);
163 mask_c.alpha = float_to_component (a); 640 mask_c.alpha = float_to_component (factor);
641 mask_c.red =
642 mask_c.green =
643 mask_c.blue = 0;
164 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 644 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
165 645
166 XRenderComposite (dpy, PictOpAdd, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 646 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, w, h);
167}
168 647
169void 648 XRenderFreePicture (dpy, src);
170rxvt_img::contrast (double r, double g, double b, double a) 649 XRenderFreePicture (dpy, dst);
171{ 650 XRenderFreePicture (dpy, mask);
172 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL))
173 return;
174 651
175 Display *dpy = s->display->dpy; 652 return img2;
176 Picture src = create_xrender_mask (dpy, pm, True);
177 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
178
179 XRenderColor mask_c;
180 mask_c.red = float_to_component (r);
181 mask_c.green = float_to_component (g);
182 mask_c.blue = float_to_component (b);
183 mask_c.alpha = float_to_component (a);
184 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
185
186 XRenderComposite (dpy, PictOpMultiply, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
187} 653}
188
189void
190rxvt_img::render (GdkPixbuf *pixbuf, int src_x, int src_y, int width, int height, int dst_x, int dst_y)
191{
192 //TODO
193}
194
195rxvt_img *
196rxvt_img::copy ()
197{
198 GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
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}
204
205rxvt_img *
206rxvt_img::transform (int new_width, int new_height, double matrix[16])
207{
208 //TODO
209}
210
211rxvt_img *
212rxvt_img::scale (int new_width, int new_height)
213{
214 // use transform
215 //TODO
216}
217
218 654
219#endif 655#endif
220 656

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines