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.35 by root, Thu Jun 7 08:36:53 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)
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(RepeatNormal),
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;
18} 59}
19 60
20rxvt_img * 61rxvt_img *
21rxvt_img::new_from_file (rxvt_screen *s, const char *filename) 62rxvt_img::new_from_file (rxvt_screen *s, const char *filename)
22{ 63{
23 GError *err; 64 GError *err = 0;
24 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err); 65 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err);
25 66
26 if (!pb) 67 if (!pb)
27 return 0; 68 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message);
28 69
29 rxvt_img *img = new rxvt_img ( 70 rxvt_img *img = new rxvt_img (
30 s, 71 s,
31 XRenderFindStandardFormat (s->display->dpy, gdk_pixbuf_get_has_alpha (pb) ? PictStandardARGB32 : PictStandardRGB24), 72 XRenderFindStandardFormat (s->display->dpy, gdk_pixbuf_get_has_alpha (pb) ? PictStandardARGB32 : PictStandardRGB24),
73 0,
74 0,
32 gdk_pixbuf_get_width (pb), 75 gdk_pixbuf_get_width (pb),
33 gdk_pixbuf_get_height (pb) 76 gdk_pixbuf_get_height (pb)
34 ); 77 );
35 78 img->alloc ();
36 img->render (pb, 0, 0, img->w, img->h, 0, 0); 79 img->render_pixbuf (pb, 0, 0, img->w, img->h, 0, 0);
37 80
81 g_object_unref (pb);
82
83 return img;
84}
85
86void
87rxvt_img::destroy ()
88{
89 if (--ref->cnt)
38 return img; 90 return;
91
92 if (pm && ref->ours)
93 XFreePixmap (s->display->dpy, pm);
94
95 delete ref;
39} 96}
40 97
41rxvt_img::~rxvt_img () 98rxvt_img::~rxvt_img ()
42{ 99{
43 if (!shared) 100 destroy ();
101}
102
103void
104rxvt_img::alloc ()
105{
106 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth);
107 ref = new pixref (w, h);
108}
109
110Picture
111rxvt_img::src_picture ()
112{
113 Display *dpy = s->display->dpy;
114
115 XRenderPictureAttributes pa;
116 pa.repeat = repeat;
117 Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
118
119 XRectangle clip = { -x, -y, min (w, ref->w), min (h, ref->h) };
120 XRenderSetPictureClipRectangles (dpy, pic, 0, 0, &clip, 1);
121
122 return pic;
123}
124
125void
126rxvt_img::unshare ()
127{
128 if (ref->cnt == 1 && ref->ours)
129 return;
130
131 //TODO: maybe should reify instead
132 Pixmap pm2 = XCreatePixmap (s->display->dpy, s->display->root, ref->w, ref->h, format->depth);
133 GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
134 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0);
44 XFreePixmap (s->display->dpy, pm); 135 XFreeGC (s->display->dpy, gc);
136
137 destroy ();
138
139 pm = pm2;
140 ref = new pixref (ref->w, ref->h);
45} 141}
46 142
47void 143void
48rxvt_img::fill (const rxvt_color &c) 144rxvt_img::fill (const rxvt_color &c)
49{ 145{
73 169
74 for (int i = 0; i < width; i++) 170 for (int i = 0; i < width; i++)
75 params[i+2] = XDoubleToFixed (kernel[i] / sum); 171 params[i+2] = XDoubleToFixed (kernel[i] / sum);
76} 172}
77 173
78void 174rxvt_img *
79rxvt_img::blur (int rh, int rv) 175rxvt_img::blur (int rh, int rv)
80{ 176{
81 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV)) 177 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
82 return; 178 return clone ();
83 179
84 Display *dpy = s->display->dpy; 180 Display *dpy = s->display->dpy;
85 int size = max (rh, rv) * 2 + 1; 181 int size = max (rh, rv) * 2 + 1;
86 double *kernel = (double *)malloc (size * sizeof (double)); 182 double *kernel = (double *)malloc (size * sizeof (double));
87 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 183 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
184 rxvt_img *img = new rxvt_img (s, format, x, y, w, h);
185 img->alloc ();
186
187 Picture src = src_picture ();
88 188
89 XRenderPictureAttributes pa; 189 XRenderPictureAttributes pa;
90
91 pa.repeat = RepeatPad; 190 pa.repeat = RepeatPad;
92 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 191 Picture dst = XRenderCreatePicture (dpy, img->pm, format, CPRepeat, &pa);
192
93 Pixmap tmp = XCreatePixmap (dpy, pm, w, h, format->depth); 193 Pixmap tmp_pm = XCreatePixmap (dpy, pm, w, h, format->depth);
94 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa); 194 Picture tmp = XRenderCreatePicture (dpy, tmp_pm , format, CPRepeat, &pa);
95 XFreePixmap (dpy, tmp); 195 XFreePixmap (dpy, tmp_pm);
96 196
97 if (kernel && params) 197 if (kernel && params)
98 { 198 {
99 size = rh * 2 + 1; 199 size = rh * 2 + 1;
100 get_gaussian_kernel (rh, size, kernel, params); 200 get_gaussian_kernel (rh, size, kernel, params);
102 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 202 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
103 XRenderComposite (dpy, 203 XRenderComposite (dpy,
104 PictOpSrc, 204 PictOpSrc,
105 src, 205 src,
106 None, 206 None,
107 dst, 207 tmp,
108 0, 0, 208 0, 0,
109 0, 0, 209 0, 0,
110 0, 0, 210 0, 0,
111 w, h); 211 w, h);
112 212
113 ::swap (src, dst);
114
115 size = rv * 2 + 1; 213 size = rv * 2 + 1;
116 get_gaussian_kernel (rv, size, kernel, params); 214 get_gaussian_kernel (rv, size, kernel, params);
117 ::swap (params[0], params[1]); 215 ::swap (params[0], params[1]);
118 216
119 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 217 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
120 XRenderComposite (dpy, 218 XRenderComposite (dpy,
121 PictOpSrc, 219 PictOpSrc,
122 src, 220 tmp,
123 None, 221 None,
124 dst, 222 dst,
125 0, 0, 223 0, 0,
126 0, 0, 224 0, 0,
127 0, 0, 225 0, 0,
130 228
131 free (kernel); 229 free (kernel);
132 free (params); 230 free (params);
133 XRenderFreePicture (dpy, src); 231 XRenderFreePicture (dpy, src);
134 XRenderFreePicture (dpy, dst); 232 XRenderFreePicture (dpy, dst);
233 XRenderFreePicture (dpy, tmp);
234
235 return img;
135} 236}
136 237
137static Picture 238static Picture
138create_xrender_mask (Display *dpy, Drawable drawable, Bool argb) 239create_xrender_mask (Display *dpy, Drawable drawable, Bool argb)
139{ 240{
148 249
149 return mask; 250 return mask;
150} 251}
151 252
152void 253void
153rxvt_img::brightness (double r, double g, double b, double a) 254rxvt_img::brightness (unsigned short r, unsigned short g, unsigned short b, unsigned short a)
154{ 255{
155 Display *dpy = s->display->dpy; 256 Display *dpy = s->display->dpy;
156 Picture src = create_xrender_mask (dpy, pm, True); 257 Picture src = create_xrender_mask (dpy, pm, True);
157 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 258 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
158 259
159 XRenderColor mask_c; 260 XRenderColor mask_c;
160 mask_c.red = float_to_component (r); 261 mask_c.red = r;
161 mask_c.green = float_to_component (g); 262 mask_c.green = g;
162 mask_c.blue = float_to_component (b); 263 mask_c.blue = b;
163 mask_c.alpha = float_to_component (a); 264 mask_c.alpha = a;
164 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 265 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
165 266
166 XRenderComposite (dpy, PictOpAdd, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 267 XRenderComposite (dpy, PictOpAdd, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
268
269 XRenderFreePicture (dpy, src);
270 XRenderFreePicture (dpy, dst);
167} 271}
168 272
169void 273void
170rxvt_img::contrast (double r, double g, double b, double a) 274rxvt_img::contrast (unsigned short r, unsigned short g, unsigned short b, unsigned short a)
171{ 275{
172 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL)) 276 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL))
173 return; 277 return;
174 278
175 Display *dpy = s->display->dpy; 279 Display *dpy = s->display->dpy;
176 Picture src = create_xrender_mask (dpy, pm, True); 280 Picture src = create_xrender_mask (dpy, pm, True);
177 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 281 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
178 282
179 XRenderColor mask_c; 283 XRenderColor mask_c;
180 mask_c.red = float_to_component (r); 284 mask_c.red = r;
181 mask_c.green = float_to_component (g); 285 mask_c.green = g;
182 mask_c.blue = float_to_component (b); 286 mask_c.blue = b;
183 mask_c.alpha = float_to_component (a); 287 mask_c.alpha = a;
184 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 288 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
185 289
186 XRenderComposite (dpy, PictOpMultiply, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 290 XRenderComposite (dpy, PictOpMultiply, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
187}
188 291
189void 292 XRenderFreePicture (dpy, src);
293 XRenderFreePicture (dpy, dst);
294}
295
296bool
190rxvt_img::render (GdkPixbuf *pixbuf, int src_x, int src_y, int width, int height, int dst_x, int dst_y) 297rxvt_img::render_pixbuf (GdkPixbuf *pixbuf, int src_x, int src_y, int width, int height, int dst_x, int dst_y)
191{ 298{
192 //TODO 299 Display *dpy = s->display->dpy;
193}
194 300
195rxvt_img * 301 if (s->visual->c_class != TrueColor)
196rxvt_img::copy () 302 return false;
197{ 303
304 uint32_t red_mask, green_mask, blue_mask, alpha_mask;
305
306 red_mask = (uint32_t)format->direct.redMask << format->direct.red;
307 green_mask = (uint32_t)format->direct.greenMask << format->direct.green;
308 blue_mask = (uint32_t)format->direct.blueMask << format->direct.blue;
309 alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha;
310
311 int width_r = ecb_popcount32 (red_mask);
312 int width_g = ecb_popcount32 (green_mask);
313 int width_b = ecb_popcount32 (blue_mask);
314 int width_a = ecb_popcount32 (alpha_mask);
315
316 if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8)
317 return false;
318
319 int sh_r = ecb_ctz32 (red_mask);
320 int sh_g = ecb_ctz32 (green_mask);
321 int sh_b = ecb_ctz32 (blue_mask);
322 int sh_a = ecb_ctz32 (alpha_mask);
323
324 if (width > 32767 || height > 32767)
325 return false;
326
327 XImage *ximage = XCreateImage (dpy, s->visual, format->depth, ZPixmap, 0, 0,
328 width, height, 32, 0);
329 if (!ximage)
330 return false;
331
332 if (height > INT_MAX / ximage->bytes_per_line
333 || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line)))
334 {
335 XDestroyImage (ximage);
336 return false;
337 }
338
198 GC gc = XCreateGC (s->display->dpy, pm, 0, 0); 339 GC gc = XCreateGC (dpy, pm, 0, 0);
199 Pixmap pm2 = XCreatePixmap (s->display->dpy, pm, w, h, format->depth); 340
200 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, w, h, 0, 0); 341 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
342
343 int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
344 int channels = gdk_pixbuf_get_n_channels (pixbuf);
345 unsigned char *row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels;
346 char *line = ximage->data;
347
348 for (int y = 0; y < height; y++)
349 {
350 for (int x = 0; x < width; x++)
351 {
352 unsigned char *pixel = row + x * channels;
353 uint32_t value;
354 unsigned char r, g, b, a;
355
356 if (channels == 4)
357 {
358 a = pixel[3];
359 r = pixel[0] * a / 0xff;
360 g = pixel[1] * a / 0xff;
361 b = pixel[2] * a / 0xff;
362 }
363 else
364 {
365 a = 0xff;
366 r = pixel[0];
367 g = pixel[1];
368 b = pixel[2];
369 }
370
371 value = ((r >> (8 - width_r)) << sh_r)
372 | ((g >> (8 - width_g)) << sh_g)
373 | ((b >> (8 - width_b)) << sh_b)
374 | ((a >> (8 - width_a)) << sh_a);
375
376 if (ximage->bits_per_pixel == 32)
377 ((uint32_t *)line)[x] = value;
378 else
379 XPutPixel (ximage, x, y, value);
380 }
381
382 row += rowstride;
383 line += ximage->bytes_per_line;
384 }
385
386 XPutImage (dpy, pm, gc, ximage, 0, 0, dst_x, dst_y, width, height);
387 XDestroyImage (ximage);
201 XFreeGC (s->display->dpy, gc); 388 XFreeGC (dpy, gc);
202 return new rxvt_img (s, format, w, h, pm2);
203}
204 389
390 return true;
391}
392
205rxvt_img * 393rxvt_img *
394rxvt_img::clone ()
395{
396 return new rxvt_img (*this);
397}
398
399rxvt_img *
400rxvt_img::reify ()
401{
402 if (x == 0 && y == 0 && w == ref->w && h == ref->h)
403 return clone ();
404
405 rxvt_img *img = new rxvt_img (s, format, 0, 0, w, h);
406 img->alloc ();
407
408 Display *dpy = s->display->dpy;
409
410 Picture src = src_picture ();
411 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
412
413 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h);
414
415 XRenderFreePicture (dpy, src);
416 XRenderFreePicture (dpy, dst);
417
418 return img;
419}
420
421rxvt_img *
422rxvt_img::sub_rect (int x, int y, int width, int height)
423{
424 rxvt_img *img = clone ();
425
426 //TODO: width > w, must reify
427
428 img->x += x;
429 img->y += y;
430 img->w = width;
431 img->h = height;
432
433 return img;
434}
435
436rxvt_img *
206rxvt_img::transform (int new_width, int new_height, double matrix[16]) 437rxvt_img::transform (int new_width, int new_height, double matrix[9])
207{ 438{
208 //TODO 439 rxvt_img *img = new rxvt_img (s, format, 0, 0, new_width, new_height);
440 img->alloc ();
441
442 Display *dpy = s->display->dpy;
443 Picture src = src_picture ();
444 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
445
446 XTransform xfrm;
447
448 for (int i = 0; i < 3; ++i)
449 for (int j = 0; j < 3; ++j)
450 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
451
452 xfrm.matrix [0][2] += XDoubleToFixed (x);//TODO
453 xfrm.matrix [0][3] += XDoubleToFixed (y);
454
455 XRenderSetPictureFilter (dpy, src, "good", 0, 0);
456 XRenderSetPictureTransform (dpy, src, &xfrm);
457 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height);
458
459 XRenderFreePicture (dpy, src);
460 XRenderFreePicture (dpy, dst);
461
462 return img;
209} 463}
210 464
211rxvt_img * 465rxvt_img *
212rxvt_img::scale (int new_width, int new_height) 466rxvt_img::scale (int new_width, int new_height)
213{ 467{
214 // use transform 468 double matrix[9] = {
215 //TODO 469 w / (double)new_width, 0, 0,
216} 470 0, h / (double)new_height, 0,
471 0, 0, 1
472 };
217 473
474 return transform (new_width, new_height, matrix);
475}
476
218rxvt_img * 477rxvt_img *
478rxvt_img::rotate (int new_width, int new_height, int x, int y, double phi)
479{
480 double s = sin (phi);
481 double c = cos (phi);
482
483 double matrix[9] = {
484 c, -s, -c * x + s * y + x,
485 s, c, -s * x - c * y + y,
486 0, 0, 1
487 };
488
489 return transform (new_width, new_height, matrix);
490}
491
492rxvt_img *
219rxvt_img::convert_to (XRenderPictFormat *new_format) 493rxvt_img::convert_to (XRenderPictFormat *new_format, const rxvt_color &bg)
220{ 494{
495 if (new_format == format)
496 return clone ();
497
221 rxvt_img *img = new rxvt_img (s,new_format,w, h); 498 rxvt_img *img = new rxvt_img (s, new_format, 0, 0, w, h);
499 img->alloc ();
222 500
223 Display *dpy = s->display->dpy; 501 Display *dpy = s->display->dpy;
224 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); 502 Picture src = src_picture ();
225 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0); 503 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0);
504 int op = PictOpSrc;
226 505
506 if (format->direct.alphaMask && !new_format->direct.alphaMask)
507 {
508 // does it have to be that complicated
509 rgba c;
510 bg.get (c);
511
512 XRenderColor rc = { c.r, c.g, c.b, 0xffff };
513 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);
514
515 op = PictOpOver;
516 }
517
227 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 518 XRenderComposite (dpy, op, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
228 519
229 XRenderFreePicture (dpy, src);
230 XRenderFreePicture (dpy, dst); 520 XRenderFreePicture (dpy, src);
521 XRenderFreePicture (dpy, dst);
231 522
523 return img;
524}
525
526rxvt_img *
527rxvt_img::blend (rxvt_img *img, double factor)
528{
529 rxvt_img *img2 = clone ();
530 Display *dpy = s->display->dpy;
531 Picture src = src_picture ();
532 Picture dst = XRenderCreatePicture (dpy, img2->pm, img2->format, 0, 0);
533 Picture mask = create_xrender_mask (dpy, img->pm, False);
534
535 XRenderColor mask_c;
536
537 mask_c.alpha = float_to_component (factor);
538 mask_c.red =
539 mask_c.green =
540 mask_c.blue = 0;
541 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
542
543 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, w, h);
544
545 XRenderFreePicture (dpy, src);
546 XRenderFreePicture (dpy, dst);
547 XRenderFreePicture (dpy, mask);
548
232 return img; 549 return img2;
233} 550}
234 551
235#endif 552#endif
236 553

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines