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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines