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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines