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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines