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.18 by sf-exg, Tue Jun 5 12:30:37 2012 UTC vs.
Revision 1.57 by root, Thu Jun 7 20:32:58 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);
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 Display *dpy = s->display->dpy;
207 385
208 if (s->visual->c_class != TrueColor) 386rxvt_img *
387rxvt_img::clone ()
388{
389 return new rxvt_img (*this);
390}
391
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 ))
209 return false; 406 return f;
210 407
211 uint32_t red_mask, green_mask, blue_mask, alpha_mask; 408 // should be a very good fallback
409 return XRenderFindStandardFormat (dpy, PictStandardARGB32);
410}
212 411
213 red_mask = (uint32_t)format->direct.redMask << format->direct.red; 412rxvt_img *
214 green_mask = (uint32_t)format->direct.greenMask << format->direct.green; 413rxvt_img::reify ()
215 blue_mask = (uint32_t)format->direct.blueMask << format->direct.blue; 414{
216 alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha; 415 if (x == 0 && y == 0 && w == ref->w && h == ref->h)
217
218 int width_r = ecb_popcount32 (red_mask);
219 int width_g = ecb_popcount32 (green_mask);
220 int width_b = ecb_popcount32 (blue_mask);
221 int width_a = ecb_popcount32 (alpha_mask);
222
223 if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8)
224 return false; 416 return clone ();
225 417
226 int sh_r = ecb_ctz32 (red_mask); 418 Display *dpy = s->display->dpy;
227 int sh_g = ecb_ctz32 (green_mask);
228 int sh_b = ecb_ctz32 (blue_mask);
229 int sh_a = ecb_ctz32 (alpha_mask);
230 419
231 if (width > 32767 || height > 32767) 420 bool alpha = !format->direct.alphaMask
232 return false; 421 && (x || y)
422 && repeat == RepeatNone;
233 423
234 XImage *ximage = XCreateImage (dpy, s->visual, format->depth, ZPixmap, 0, 0, 424 rxvt_img *img = new rxvt_img (s, alpha ? find_alpha_format_for (dpy, format) : format, 0, 0, w, h, repeat);
235 width, height, 32, 0); 425 img->alloc ();
236 if (!ximage)
237 return false;
238 426
239 if (height > INT_MAX / ximage->bytes_per_line 427 Picture src = src_picture ();
240 || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line))) 428 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
429
430 if (alpha)
241 { 431 {
242 XDestroyImage (ximage); 432 XRenderColor rc = { 0, 0, 0, 0 };
243 return false; 433 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles
434 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, -x, -y, ref->w, ref->h);
244 } 435 }
436 else
437 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h);
245 438
246 GC gc = XCreateGC (dpy, pm, 0, 0); 439 XRenderFreePicture (dpy, src);
440 XRenderFreePicture (dpy, dst);
247 441
248 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 442 return img;
443}
249 444
250 int rowstride = gdk_pixbuf_get_rowstride (pixbuf); 445rxvt_img *
251 int channels = gdk_pixbuf_get_n_channels (pixbuf); 446rxvt_img::sub_rect (int x, int y, int width, int height)
252 unsigned char *row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels; 447{
253 char *line = ximage->data; 448 rxvt_img *img = clone ();
254 449
255 rgba c (0, 0, 0); 450 img->x += x;
451 img->y += y;
256 452
257 if (channels == 4 && alpha_mask == 0) 453 if (w != width || h != height)
258 { 454 {
259 //pix_colors[Color_bg].get (c); 455 img->w = width;
260 //TODO 456 img->h = height;
261 c.r = 0xffff; c.g = 0xc0c0; c.b = 0xcbcb;//D 457
262 c.r >>= 8; 458 rxvt_img *img2 = img->reify ();
263 c.g >>= 8; 459 delete img;
264 c.b >>= 8; 460 img = img2;
265 } 461 }
266 462
267 for (int y = 0; y < height; y++) 463 return img;
268 {
269 for (int x = 0; x < width; x++)
270 {
271 unsigned char *pixel = row + x * channels;
272 uint32_t value;
273 unsigned char r, g, b, a;
274
275 if (channels == 4)
276 {
277 a = pixel[3];
278 r = (pixel[0] * a + c.r * (0xff - a)) / 0xff;
279 g = (pixel[1] * a + c.g * (0xff - a)) / 0xff;
280 b = (pixel[2] * a + c.b * (0xff - a)) / 0xff;
281 }
282 else
283 {
284 a = 0xff;
285 r = pixel[0];
286 g = pixel[1];
287 b = pixel[2];
288 }
289
290 value = ((r >> (8 - width_r)) << sh_r)
291 | ((g >> (8 - width_g)) << sh_g)
292 | ((b >> (8 - width_b)) << sh_b)
293 | ((a >> (8 - width_a)) << sh_a);
294
295 if (ximage->bits_per_pixel == 32)
296 ((uint32_t *)line)[x] = value;
297 else
298 XPutPixel (ximage, x, y, value);
299 }
300
301 row += rowstride;
302 line += ximage->bytes_per_line;
303 }
304
305 XPutImage (dpy, pm, gc, ximage, 0, 0, dst_x, dst_y, width, height);
306 XDestroyImage (ximage);
307 XFreeGC (dpy, gc);
308
309 return true;
310} 464}
311 465
312rxvt_img * 466rxvt_img *
313rxvt_img::clone ()
314{
315 GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
316 Pixmap pm2 = XCreatePixmap (s->display->dpy, pm, w, h, format->depth);
317 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, w, h, 0, 0);
318 XFreeGC (s->display->dpy, gc);
319 return new rxvt_img (s, format, w, h, pm2);
320}
321
322rxvt_img *
323rxvt_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])
324{ 468{
325 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 ();
326 471
327 Display *dpy = s->display->dpy; 472 Display *dpy = s->display->dpy;
328 XRenderPictureAttributes pa; 473 Picture src = src_picture ();
329 pa.repeat = repeat;
330 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
331 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); 474 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
332 475
333 XTransform xfrm; 476 XTransform xfrm;
334 477
335 for (int i = 0; i < 3; ++i) 478 for (int i = 0; i < 3; ++i)
336 for (int j = 0; j < 3; ++j) 479 for (int j = 0; j < 3; ++j)
337 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]); 480 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
338 481
482#if 0
483 xfrm.matrix [0][2] -= XDoubleToFixed (x);//TODO
484 xfrm.matrix [1][2] -= XDoubleToFixed (y);
485#endif
486
339 XRenderSetPictureFilter (dpy, src, "good", 0, 0); 487 XRenderSetPictureFilter (dpy, src, "good", 0, 0);
340 XRenderSetPictureTransform (dpy, src, &xfrm); 488 XRenderSetPictureTransform (dpy, src, &xfrm);
341 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);
342 490
343 XRenderFreePicture (dpy, src); 491 XRenderFreePicture (dpy, src);
347} 495}
348 496
349rxvt_img * 497rxvt_img *
350rxvt_img::scale (int new_width, int new_height) 498rxvt_img::scale (int new_width, int new_height)
351{ 499{
500 if (w == new_width && h == new_height)
501 return clone ();
502
352 double matrix[9] = { 503 double matrix[9] = {
353 w / (double)new_width, 0, 0, 504 w / (double)new_width, 0, 0,
354 0, h / (double)new_height, 0, 505 0, h / (double)new_height, 0,
355 0, 0, 1 506 0, 0, 1
356 }; 507 };
357 508
509 int old_repeat_mode = repeat;
510 repeat = RepeatPad; // not right, but xrender can't proeprly scale it seems
511
358 return transform (new_width, new_height, RepeatNormal, matrix); 512 rxvt_img *img = transform (new_width, new_height, matrix);
359}
360 513
514 repeat = old_repeat_mode;
515 img->repeat = repeat;
516
517 return img;
518}
519
361rxvt_img * 520rxvt_img *
362rxvt_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)
363{ 522{
364 double s = sin (phi); 523 double s = sin (phi);
365 double c = cos (phi); 524 double c = cos (phi);
366 525
367 double matrix[9] = { 526 double matrix[9] = {
368 c, -s, -c * x + s * y + x, 527 c, -s, -c * x + s * y + x,
369 s, c, -s * x - c * y + y, 528 s, c, -s * x - c * y + y,
370 0, 0, 1 529 0, 0, 1
371 }; 530 };
372 531
373 return transform (new_width, new_height, repeat, matrix); 532 return transform (new_width, new_height, matrix);
374} 533}
375 534
376rxvt_img * 535rxvt_img *
377rxvt_img::convert_to (XRenderPictFormat *new_format) 536rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg)
378{ 537{
538 if (new_format == format)
539 return clone ();
540
379 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 ();
380 543
381 Display *dpy = s->display->dpy; 544 Display *dpy = s->display->dpy;
382 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); 545 Picture src = src_picture ();
383 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;
384 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
385 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);
386 562
387 XRenderFreePicture (dpy, src);
388 XRenderFreePicture (dpy, dst); 563 XRenderFreePicture (dpy, src);
564 XRenderFreePicture (dpy, dst);
389 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
390 return img; 592 return img2;
391} 593}
392 594
393#endif 595#endif
394 596

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines