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.20 by root, Tue Jun 5 14:07:47 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 Display *dpy = s->display->dpy;
207 373
208 if (s->visual->c_class != TrueColor) 374rxvt_img *
375rxvt_img::clone ()
376{
377 return new rxvt_img (*this);
378}
379
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 ))
209 return false; 394 return f;
210 395
211 uint32_t red_mask, green_mask, blue_mask, alpha_mask; 396 // should be a very good fallback
397 return XRenderFindStandardFormat (dpy, PictStandardARGB32);
398}
212 399
213 red_mask = (uint32_t)format->direct.redMask << format->direct.red; 400rxvt_img *
214 green_mask = (uint32_t)format->direct.greenMask << format->direct.green; 401rxvt_img::reify ()
215 blue_mask = (uint32_t)format->direct.blueMask << format->direct.blue; 402{
216 alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha; 403 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; 404 return clone ();
225 405
226 int sh_r = ecb_ctz32 (red_mask); 406 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 407
231 if (width > 32767 || height > 32767) 408 bool alpha = !format->direct.alphaMask
232 return false; 409 && (x || y)
410 && repeat == RepeatNone;
233 411
234 XImage *ximage = XCreateImage (dpy, s->visual, format->depth, ZPixmap, 0, 0, 412 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); 413 img->alloc ();
236 if (!ximage)
237 return false;
238 414
239 if (height > INT_MAX / ximage->bytes_per_line 415 Picture src = src_picture ();
240 || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line))) 416 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
417
418 if (alpha)
241 { 419 {
242 XDestroyImage (ximage); 420 XRenderColor rc = { 0, 0, 0, 0 };
243 return false; 421 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles
422 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, -x, -y, ref->w, ref->h);
244 } 423 }
424 else
425 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h);
245 426
246 GC gc = XCreateGC (dpy, pm, 0, 0); 427 XRenderFreePicture (dpy, src);
428 XRenderFreePicture (dpy, dst);
247 429
248 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 430 return img;
431}
249 432
250 int rowstride = gdk_pixbuf_get_rowstride (pixbuf); 433rxvt_img *
251 int channels = gdk_pixbuf_get_n_channels (pixbuf); 434rxvt_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; 435{
253 char *line = ximage->data; 436 rxvt_img *img = clone ();
254 437
255 rgba c (0, 0, 0); 438 img->x += x;
439 img->y += y;
256 440
257 if (channels == 4 && alpha_mask == 0) 441 if (w != width || h != height)
258 { 442 {
259 //pix_colors[Color_bg].get (c); 443 img->w = width;
260 //TODO 444 img->h = height;
261 c.r = 0xffff; c.g = 0xc0c0; c.b = 0xcbcb;//D 445
262 c.r >>= 8; 446 rxvt_img *img2 = img->reify ();
263 c.g >>= 8; 447 delete img;
264 c.b >>= 8; 448 img = img2;
265 } 449 }
266 450
267 for (int y = 0; y < height; y++)
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}
311
312rxvt_img *
313rxvt_img::clone ()
314{
315 rxvt_img *img = new rxvt_img (s, format, w, h);
316
317 GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
318 XCopyArea (s->display->dpy, pm, img->pm, gc, 0, 0, w, h, 0, 0);
319 XFreeGC (s->display->dpy, gc);
320
321 return img; 451 return img;
322} 452}
323 453
324rxvt_img * 454rxvt_img *
325rxvt_img::sub_rect (int x, int y, int width, int height, int repeat) 455rxvt_img::transform (int new_width, int new_height, double matrix[9])
326{ 456{
327 rxvt_img *img = new rxvt_img (s, format, width, height); 457 rxvt_img *img = new rxvt_img (s, format, 0, 0, new_width, new_height, repeat);
458 img->alloc ();
328 459
329 Display *dpy = s->display->dpy; 460 Display *dpy = s->display->dpy;
330 XRenderPictureAttributes pa; 461 Picture src = src_picture ();
331 pa.repeat = repeat;
332 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
333 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); 462 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
334
335 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, width, height);
336
337 XRenderFreePicture (dpy, src);
338 XRenderFreePicture (dpy, dst);
339
340 return img;
341}
342
343rxvt_img *
344rxvt_img::transform (int new_width, int new_height, double matrix[9], int repeat)
345{
346 rxvt_img *img = new rxvt_img (s, format, new_width, new_height);
347
348 Display *dpy = s->display->dpy;
349 XRenderPictureAttributes pa;
350 pa.repeat = repeat;
351 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
352 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
353 463
354 XTransform xfrm; 464 XTransform xfrm;
355 465
356 for (int i = 0; i < 3; ++i) 466 for (int i = 0; i < 3; ++i)
357 for (int j = 0; j < 3; ++j) 467 for (int j = 0; j < 3; ++j)
358 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]); 468 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
359 469
470#if 0
471 xfrm.matrix [0][2] -= XDoubleToFixed (x);//TODO
472 xfrm.matrix [1][2] -= XDoubleToFixed (y);
473#endif
474
360 XRenderSetPictureFilter (dpy, src, "good", 0, 0); 475 XRenderSetPictureFilter (dpy, src, "good", 0, 0);
361 XRenderSetPictureTransform (dpy, src, &xfrm); 476 XRenderSetPictureTransform (dpy, src, &xfrm);
362 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);
363 478
364 XRenderFreePicture (dpy, src); 479 XRenderFreePicture (dpy, src);
368} 483}
369 484
370rxvt_img * 485rxvt_img *
371rxvt_img::scale (int new_width, int new_height) 486rxvt_img::scale (int new_width, int new_height)
372{ 487{
488 if (w == new_width && h == new_height)
489 return clone ();
490
373 double matrix[9] = { 491 double matrix[9] = {
374 w / (double)new_width, 0, 0, 492 w / (double)new_width, 0, 0,
375 0, h / (double)new_height, 0, 493 0, h / (double)new_height, 0,
376 0, 0, 1 494 0, 0, 1
377 }; 495 };
378 496
497 int old_repeat_mode = repeat;
498 repeat = RepeatPad; // not right, but xrender can't proeprly scale it seems
499
379 return transform (new_width, new_height, matrix); 500 rxvt_img *img = transform (new_width, new_height, matrix);
380}
381 501
502 repeat = old_repeat_mode;
503 img->repeat = repeat;
504
505 return img;
506}
507
382rxvt_img * 508rxvt_img *
383rxvt_img::rotate (int new_width, int new_height, int x, int y, double phi, int repeat) 509rxvt_img::rotate (int new_width, int new_height, int x, int y, double phi)
384{ 510{
385 double s = sin (phi); 511 double s = sin (phi);
386 double c = cos (phi); 512 double c = cos (phi);
387 513
388 double matrix[9] = { 514 double matrix[9] = {
389 c, -s, -c * x + s * y + x, 515 c, -s, -c * x + s * y + x,
390 s, c, -s * x - c * y + y, 516 s, c, -s * x - c * y + y,
391 0, 0, 1 517 0, 0, 1
392 }; 518 };
393 519
394 return transform (new_width, new_height, matrix, repeat); 520 return transform (new_width, new_height, matrix);
395} 521}
396 522
397rxvt_img * 523rxvt_img *
398rxvt_img::convert_to (XRenderPictFormat *new_format) 524rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg)
399{ 525{
526 if (new_format == format)
527 return clone ();
528
400 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 ();
401 531
402 Display *dpy = s->display->dpy; 532 Display *dpy = s->display->dpy;
403 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); 533 Picture src = src_picture ();
404 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;
405 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
406 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);
407 550
408 XRenderFreePicture (dpy, src);
409 XRenderFreePicture (dpy, dst); 551 XRenderFreePicture (dpy, src);
552 XRenderFreePicture (dpy, dst);
410 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
411 return img; 580 return img2;
412} 581}
413 582
414#endif 583#endif
415 584

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines