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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines