ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/rxvtimg.C
Revision: 1.14
Committed: Mon Jun 4 15:53:12 2012 UTC (11 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.13: +118 -4 lines
Log Message:
quick hack

File Contents

# User Rev Content
1 sf-exg 1.6 #include <math.h>
2 root 1.1 #include "../config.h"
3     #include "rxvt.h"
4    
5     #if HAVE_IMG
6    
7 sf-exg 1.6 #define float_to_component(d) ((d) * 65535.99)
8    
9 root 1.3 rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int width, int height)
10 root 1.4 : s(screen), w(width), h(height), format(format), shared(false)
11 root 1.1 {
12 root 1.3 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth);
13 root 1.1 }
14    
15 root 1.3 rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int width, int height, Pixmap pixmap)
16 root 1.4 : s(screen), pm(pixmap), w(width), h(height), format(format), shared(false)
17 root 1.1 {
18     }
19    
20 root 1.4 rxvt_img *
21     rxvt_img::new_from_file (rxvt_screen *s, const char *filename)
22     {
23 root 1.11 GError *err = 0;
24 root 1.4 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err);
25    
26     if (!pb)
27 root 1.11 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message);
28 root 1.4
29     rxvt_img *img = new rxvt_img (
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    
36 root 1.14 img->render_pixbuf (pb, 0, 0, img->w, img->h, 0, 0);
37 root 1.4
38     return img;
39     }
40    
41 root 1.1 rxvt_img::~rxvt_img ()
42     {
43 root 1.4 if (!shared)
44 root 1.1 XFreePixmap (s->display->dpy, pm);
45     }
46    
47     void
48 root 1.11 rxvt_img::unshare ()
49     {
50     if (!shared)
51     return;
52    
53     rxvt_img *img = clone ();
54    
55     ::swap (pm , img->pm);
56     ::swap (shared, img->shared);
57    
58     delete img;
59     }
60    
61     void
62 root 1.1 rxvt_img::fill (const rxvt_color &c)
63     {
64     XGCValues gcv;
65     gcv.foreground = c;
66     GC gc = XCreateGC (s->display->dpy, pm, GCForeground, &gcv);
67     XFillRectangle (s->display->dpy, pm, gc, 0, 0, w, h);
68 root 1.3 XFreeGC (s->display->dpy, gc);
69 root 1.1 }
70    
71 sf-exg 1.6 static void
72     get_gaussian_kernel (int radius, int width, double *kernel, XFixed *params)
73     {
74     double sigma = radius / 2.0;
75     double scale = sqrt (2.0 * M_PI) * sigma;
76     double sum = 0.0;
77    
78     for (int i = 0; i < width; i++)
79     {
80     double x = i - width / 2;
81     kernel[i] = exp (-(x * x) / (2.0 * sigma * sigma)) / scale;
82     sum += kernel[i];
83     }
84    
85     params[0] = XDoubleToFixed (width);
86     params[1] = XDoubleToFixed (1);
87    
88     for (int i = 0; i < width; i++)
89     params[i+2] = XDoubleToFixed (kernel[i] / sum);
90     }
91    
92 root 1.3 void
93     rxvt_img::blur (int rh, int rv)
94     {
95 sf-exg 1.6 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
96     return;
97    
98     Display *dpy = s->display->dpy;
99     int size = max (rh, rv) * 2 + 1;
100     double *kernel = (double *)malloc (size * sizeof (double));
101     XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
102    
103     XRenderPictureAttributes pa;
104    
105     pa.repeat = RepeatPad;
106     Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
107     Pixmap tmp = XCreatePixmap (dpy, pm, w, h, format->depth);
108     Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa);
109     XFreePixmap (dpy, tmp);
110    
111     if (kernel && params)
112     {
113     size = rh * 2 + 1;
114     get_gaussian_kernel (rh, size, kernel, params);
115    
116     XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
117     XRenderComposite (dpy,
118     PictOpSrc,
119     src,
120     None,
121     dst,
122     0, 0,
123     0, 0,
124     0, 0,
125     w, h);
126    
127     ::swap (src, dst);
128    
129     size = rv * 2 + 1;
130     get_gaussian_kernel (rv, size, kernel, params);
131     ::swap (params[0], params[1]);
132    
133     XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
134     XRenderComposite (dpy,
135     PictOpSrc,
136     src,
137     None,
138     dst,
139     0, 0,
140     0, 0,
141     0, 0,
142     w, h);
143     }
144    
145     free (kernel);
146     free (params);
147     XRenderFreePicture (dpy, src);
148     XRenderFreePicture (dpy, dst);
149     }
150    
151     static Picture
152     create_xrender_mask (Display *dpy, Drawable drawable, Bool argb)
153     {
154     Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
155    
156     XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
157     XRenderPictureAttributes pa;
158     pa.repeat = True;
159     Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa);
160    
161     XFreePixmap (dpy, pixmap);
162    
163     return mask;
164 root 1.3 }
165    
166     void
167     rxvt_img::brightness (double r, double g, double b, double a)
168     {
169 sf-exg 1.6 Display *dpy = s->display->dpy;
170     Picture src = create_xrender_mask (dpy, pm, True);
171     Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
172    
173     XRenderColor mask_c;
174     mask_c.red = float_to_component (r);
175     mask_c.green = float_to_component (g);
176     mask_c.blue = float_to_component (b);
177     mask_c.alpha = float_to_component (a);
178     XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
179    
180     XRenderComposite (dpy, PictOpAdd, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
181 root 1.3 }
182    
183     void
184     rxvt_img::contrast (double r, double g, double b, double a)
185 root 1.1 {
186 sf-exg 1.6 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL))
187     return;
188    
189     Display *dpy = s->display->dpy;
190     Picture src = create_xrender_mask (dpy, pm, True);
191     Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
192    
193     XRenderColor mask_c;
194     mask_c.red = float_to_component (r);
195     mask_c.green = float_to_component (g);
196     mask_c.blue = float_to_component (b);
197     mask_c.alpha = float_to_component (a);
198     XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
199    
200     XRenderComposite (dpy, PictOpMultiply, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
201 root 1.1 }
202    
203 root 1.14 bool
204     rxvt_img::render_pixbuf (GdkPixbuf *pixbuf, int src_x, int src_y, int width, int height, int dst_x, int dst_y)
205 root 1.3 {
206 root 1.14 bool argb = format->id == PictStandardARGB32;
207    
208     Display *dpy = s->display->dpy;
209    
210     if (s->visual->c_class != TrueColor)
211     return false;
212    
213     uint32_t red_mask, green_mask, blue_mask, alpha_mask;
214    
215     if (argb)
216     {
217     red_mask = 0xff << 16;
218     green_mask = 0xff << 8;
219     blue_mask = 0xff;
220     alpha_mask = 0xff << 24;
221     }
222     else
223     {
224     red_mask = s->visual->red_mask;
225     green_mask = s->visual->green_mask;
226     blue_mask = s->visual->blue_mask;
227     alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha;
228     }
229    
230     int width_r = ecb_popcount32 (red_mask);
231     int width_g = ecb_popcount32 (green_mask);
232     int width_b = ecb_popcount32 (blue_mask);
233     int width_a = ecb_popcount32 (alpha_mask);
234    
235     if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8)
236     return false;
237    
238     int sh_r = ecb_ctz32 (red_mask);
239     int sh_g = ecb_ctz32 (green_mask);
240     int sh_b = ecb_ctz32 (blue_mask);
241     int sh_a = ecb_ctz32 (alpha_mask);
242    
243     if (width > 32767 || height > 32767)
244     return false;
245    
246     XImage *ximage = XCreateImage (dpy, s->visual, argb ? 32 : format->depth, ZPixmap, 0, 0,
247     width, height, 32, 0);
248     if (!ximage)
249     return false;
250    
251     if (height > INT_MAX / ximage->bytes_per_line
252     || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line)))
253     {
254     XDestroyImage (ximage);
255     return false;
256     }
257    
258     GC gc = XCreateGC (dpy, pm, 0, 0);
259    
260     ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst;
261    
262     int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
263     int channels = gdk_pixbuf_get_n_channels (pixbuf);
264     unsigned char *row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels;
265     char *line = ximage->data;
266    
267     rgba c (0, 0, 0);
268    
269     if (channels == 4 && alpha_mask == 0)
270     {
271     //pix_colors[Color_bg].get (c);
272     //TODO
273     c.r >>= 8;
274     c.g >>= 8;
275     c.b >>= 8;
276     }
277    
278     for (int y = 0; y < height; y++)
279     {
280     for (int x = 0; x < width; x++)
281     {
282     unsigned char *pixel = row + x * channels;
283     uint32_t value;
284     unsigned char r, g, b, a;
285    
286     if (channels == 4)
287     {
288     a = pixel[3];
289     r = (pixel[0] * a + c.r * (0xff - a)) / 0xff;
290     g = (pixel[1] * a + c.g * (0xff - a)) / 0xff;
291     b = (pixel[2] * a + c.b * (0xff - a)) / 0xff;
292     }
293     else
294     {
295     a = 0xff;
296     r = pixel[0];
297     g = pixel[1];
298     b = pixel[2];
299     }
300    
301     value = ((r >> (8 - width_r)) << sh_r)
302     | ((g >> (8 - width_g)) << sh_g)
303     | ((b >> (8 - width_b)) << sh_b)
304     | ((a >> (8 - width_a)) << sh_a);
305    
306     if (ximage->bits_per_pixel == 32)
307     ((uint32_t *)line)[x] = value;
308     else
309     XPutPixel (ximage, x, y, value);
310     }
311    
312     row += rowstride;
313     line += ximage->bytes_per_line;
314     }
315    
316     XPutImage (dpy, pm, gc, ximage, 0, 0, dst_x, dst_y, width, height);
317     XDestroyImage (ximage);
318     XFreeGC (dpy, gc);
319    
320     return true;
321 root 1.3 }
322    
323     rxvt_img *
324 root 1.11 rxvt_img::clone ()
325 root 1.3 {
326     GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
327     Pixmap pm2 = XCreatePixmap (s->display->dpy, pm, w, h, format->depth);
328     XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, w, h, 0, 0);
329     XFreeGC (s->display->dpy, gc);
330     return new rxvt_img (s, format, w, h, pm2);
331     }
332    
333     rxvt_img *
334 root 1.11 rxvt_img::transform (int new_width, int new_height, int repeat, double matrix[9])
335 root 1.3 {
336 root 1.12 rxvt_img *img = new rxvt_img (s, format, new_width, new_height);
337    
338     Display *dpy = s->display->dpy;
339 root 1.13 XRenderPictureAttributes pa;
340     pa.repeat = repeat;
341     Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
342     Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
343 root 1.12
344     XTransform xfrm;
345    
346     for (int i = 0; i < 3; ++i)
347     for (int j = 0; j < 3; ++j)
348     xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
349    
350     XRenderSetPictureTransform (dpy, src, &xfrm);
351     XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, new_width, new_height);
352    
353     XRenderFreePicture (dpy, src);
354     XRenderFreePicture (dpy, dst);
355    
356     return img;
357 root 1.3 }
358    
359     rxvt_img *
360     rxvt_img::scale (int new_width, int new_height)
361     {
362 root 1.11 double matrix[9] = {
363     new_width / (double)w, 0, 0,
364     0, new_height / (double)h, 0,
365     0, 0, 1
366     };
367    
368     return transform (new_width, new_height, RepeatNormal, matrix);
369 root 1.3 }
370    
371 sf-exg 1.7 rxvt_img *
372     rxvt_img::convert_to (XRenderPictFormat *new_format)
373     {
374 sf-exg 1.10 rxvt_img *img = new rxvt_img (s, new_format, w, h);
375 root 1.9
376 sf-exg 1.7 Display *dpy = s->display->dpy;
377 root 1.12 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0);
378 root 1.8 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0);
379 sf-exg 1.7
380     XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, w, h);
381    
382     XRenderFreePicture (dpy, src);
383     XRenderFreePicture (dpy, dst);
384    
385     return img;
386     }
387 root 1.3
388 root 1.1 #endif
389