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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines