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.21 by sf-exg, Tue Jun 5 14:59:44 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{
18} 23}
24#endif
19 25
20rxvt_img * 26rxvt_img *
21rxvt_img::new_from_root (rxvt_screen *s) 27rxvt_img::new_from_root (rxvt_screen *s)
22{ 28{
23 Display *dpy = s->display->dpy; 29 Display *dpy = s->display->dpy;
37 return 0; 43 return 0;
38 44
39 rxvt_img *img = new rxvt_img ( 45 rxvt_img *img = new rxvt_img (
40 s, 46 s,
41 XRenderFindVisualFormat (dpy, DefaultVisual (dpy, s->display->screen)), 47 XRenderFindVisualFormat (dpy, DefaultVisual (dpy, s->display->screen)),
48 0,
49 0,
42 root_pm_w, 50 root_pm_w,
43 root_pm_h, 51 root_pm_h
44 root_pixmap
45 ); 52 );
46 53
47 img->shared = true; 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);
48 147
49 return img; 148 return img;
50} 149}
51 150
52rxvt_img * 151rxvt_img *
56 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err); 155 GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err);
57 156
58 if (!pb) 157 if (!pb)
59 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message); 158 rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message);
60 159
61 rxvt_img *img = new rxvt_img ( 160 rxvt_img *img = new_from_pixbuf (s, pb);
62 s,
63 XRenderFindStandardFormat (s->display->dpy, gdk_pixbuf_get_has_alpha (pb) ? PictStandardARGB32 : PictStandardRGB24),
64 gdk_pixbuf_get_width (pb),
65 gdk_pixbuf_get_height (pb)
66 );
67 161
68 img->render_pixbuf (pb, 0, 0, img->w, img->h, 0, 0); 162 g_object_unref (pb);
69 163
164 return img;
165}
166
167void
168rxvt_img::destroy ()
169{
170 if (--ref->cnt)
70 return img; 171 return;
172
173 if (pm && ref->ours)
174 XFreePixmap (s->display->dpy, pm);
175
176 delete ref;
71} 177}
72 178
73rxvt_img::~rxvt_img () 179rxvt_img::~rxvt_img ()
74{ 180{
75 if (!shared) 181 destroy ();
76 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;
77} 201}
78 202
79void 203void
80rxvt_img::unshare () 204rxvt_img::unshare ()
81{ 205{
82 if (!shared) 206 if (ref->cnt == 1 && ref->ours)
83 return; 207 return;
84 208
85 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);
86 214
87 ::swap (pm , img->pm); 215 destroy ();
88 ::swap (shared, img->shared);
89 216
90 delete img; 217 pm = pm2;
218 ref = new pixref (ref->w, ref->h);
91} 219}
92 220
93void 221void
94rxvt_img::fill (const rxvt_color &c) 222rxvt_img::fill (const rxvt_color &c)
95{ 223{
119 247
120 for (int i = 0; i < width; i++) 248 for (int i = 0; i < width; i++)
121 params[i+2] = XDoubleToFixed (kernel[i] / sum); 249 params[i+2] = XDoubleToFixed (kernel[i] / sum);
122} 250}
123 251
124void 252rxvt_img *
125rxvt_img::blur (int rh, int rv) 253rxvt_img::blur (int rh, int rv)
126{ 254{
127 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV)) 255 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
128 return; 256 return clone ();
129 257
130 Display *dpy = s->display->dpy; 258 Display *dpy = s->display->dpy;
131 int size = max (rh, rv) * 2 + 1; 259 int size = max (rh, rv) * 2 + 1;
132 double *kernel = (double *)malloc (size * sizeof (double)); 260 double *kernel = (double *)malloc (size * sizeof (double));
133 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 ();
134 266
135 XRenderPictureAttributes pa; 267 XRenderPictureAttributes pa;
136
137 pa.repeat = RepeatPad; 268 pa.repeat = RepeatPad;
138 Picture src = XRenderCreatePicture (dpy, pm , format, CPRepeat, &pa); 269 Picture dst = XRenderCreatePicture (dpy, img->pm, format, CPRepeat, &pa);
270
139 Pixmap tmp = XCreatePixmap (dpy, pm, w, h, format->depth); 271 Pixmap tmp_pm = XCreatePixmap (dpy, pm, w, h, format->depth);
140 Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa); 272 Picture tmp = XRenderCreatePicture (dpy, tmp_pm , format, CPRepeat, &pa);
141 XFreePixmap (dpy, tmp); 273 XFreePixmap (dpy, tmp_pm);
142 274
143 if (kernel && params) 275 if (kernel && params)
144 { 276 {
145 size = rh * 2 + 1; 277 size = rh * 2 + 1;
146 get_gaussian_kernel (rh, size, kernel, params); 278 get_gaussian_kernel (rh, size, kernel, params);
148 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 280 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
149 XRenderComposite (dpy, 281 XRenderComposite (dpy,
150 PictOpSrc, 282 PictOpSrc,
151 src, 283 src,
152 None, 284 None,
153 dst, 285 tmp,
154 0, 0, 286 0, 0,
155 0, 0, 287 0, 0,
156 0, 0, 288 0, 0,
157 w, h); 289 w, h);
158 290
159 ::swap (src, dst);
160
161 size = rv * 2 + 1; 291 size = rv * 2 + 1;
162 get_gaussian_kernel (rv, size, kernel, params); 292 get_gaussian_kernel (rv, size, kernel, params);
163 ::swap (params[0], params[1]); 293 ::swap (params[0], params[1]);
164 294
165 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); 295 XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2);
166 XRenderComposite (dpy, 296 XRenderComposite (dpy,
167 PictOpSrc, 297 PictOpSrc,
168 src, 298 tmp,
169 None, 299 None,
170 dst, 300 dst,
171 0, 0, 301 0, 0,
172 0, 0, 302 0, 0,
173 0, 0, 303 0, 0,
176 306
177 free (kernel); 307 free (kernel);
178 free (params); 308 free (params);
179 XRenderFreePicture (dpy, src); 309 XRenderFreePicture (dpy, src);
180 XRenderFreePicture (dpy, dst); 310 XRenderFreePicture (dpy, dst);
311 XRenderFreePicture (dpy, tmp);
312
313 return img;
181} 314}
182 315
183static Picture 316static Picture
184create_xrender_mask (Display *dpy, Drawable drawable, Bool argb) 317create_xrender_mask (Display *dpy, Drawable drawable, Bool argb)
185{ 318{
194 327
195 return mask; 328 return mask;
196} 329}
197 330
198void 331void
199rxvt_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)
200{ 333{
201 Display *dpy = s->display->dpy; 334 Display *dpy = s->display->dpy;
202 Picture src = create_xrender_mask (dpy, pm, True); 335 Picture src = create_xrender_mask (dpy, pm, True);
203 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 336 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
204 337
205 XRenderColor mask_c; 338 XRenderColor mask_c;
206 mask_c.red = float_to_component (r); 339 mask_c.red = r;
207 mask_c.green = float_to_component (g); 340 mask_c.green = g;
208 mask_c.blue = float_to_component (b); 341 mask_c.blue = b;
209 mask_c.alpha = float_to_component (a); 342 mask_c.alpha = a;
210 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 343 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
211 344
212 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);
213} 349}
214 350
215void 351void
216rxvt_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)
217{ 353{
218 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL)) 354 if (!(s->display->flags & DISPLAY_HAS_RENDER_MUL))
219 return; 355 return;
220 356
221 Display *dpy = s->display->dpy; 357 Display *dpy = s->display->dpy;
222 Picture src = create_xrender_mask (dpy, pm, True); 358 Picture src = create_xrender_mask (dpy, pm, True);
223 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 359 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
224 360
225 XRenderColor mask_c; 361 XRenderColor mask_c;
226 mask_c.red = float_to_component (r); 362 mask_c.red = r;
227 mask_c.green = float_to_component (g); 363 mask_c.green = g;
228 mask_c.blue = float_to_component (b); 364 mask_c.blue = b;
229 mask_c.alpha = float_to_component (a); 365 mask_c.alpha = a;
230 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1); 366 XRenderFillRectangle (dpy, PictOpSrc, src, &mask_c, 0, 0, 1, 1);
231 367
232 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);
233}
234 369
235bool 370 XRenderFreePicture (dpy, src);
236rxvt_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);
237{ 372}
238 Display *dpy = s->display->dpy;
239 373
240 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 ))
241 return false; 394 return f;
242 395
243 uint32_t red_mask, green_mask, blue_mask, alpha_mask; 396 // should be a very good fallback
397 return XRenderFindStandardFormat (dpy, PictStandardARGB32);
398}
244 399
245 red_mask = (uint32_t)format->direct.redMask << format->direct.red; 400rxvt_img *
246 green_mask = (uint32_t)format->direct.greenMask << format->direct.green; 401rxvt_img::reify ()
247 blue_mask = (uint32_t)format->direct.blueMask << format->direct.blue; 402{
248 alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha; 403 if (x == 0 && y == 0 && w == ref->w && h == ref->h)
249
250 int width_r = ecb_popcount32 (red_mask);
251 int width_g = ecb_popcount32 (green_mask);
252 int width_b = ecb_popcount32 (blue_mask);
253 int width_a = ecb_popcount32 (alpha_mask);
254
255 if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8)
256 return false; 404 return clone ();
257 405
258 int sh_r = ecb_ctz32 (red_mask); 406 Display *dpy = s->display->dpy;
259 int sh_g = ecb_ctz32 (green_mask);
260 int sh_b = ecb_ctz32 (blue_mask);
261 int sh_a = ecb_ctz32 (alpha_mask);
262 407
263 if (width > 32767 || height > 32767) 408 bool alpha = !format->direct.alphaMask
264 return false; 409 && (x || y)
410 && repeat == RepeatNone;
265 411
266 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);
267 width, height, 32, 0); 413 img->alloc ();
268 if (!ximage)
269 return false;
270 414
271 if (height > INT_MAX / ximage->bytes_per_line 415 Picture src = src_picture ();
272 || !(ximage->data = (char *)malloc (height * ximage->bytes_per_line))) 416 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
417
418 if (alpha)
273 { 419 {
274 XDestroyImage (ximage); 420 XRenderColor rc = { 0, 0, 0, 0 };
275 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);
276 } 423 }
424 else
425 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, w, h);
277 426
278 GC gc = XCreateGC (dpy, pm, 0, 0); 427 XRenderFreePicture (dpy, src);
428 XRenderFreePicture (dpy, dst);
279 429
280 ximage->byte_order = ecb_big_endian () ? MSBFirst : LSBFirst; 430 return img;
431}
281 432
282 int rowstride = gdk_pixbuf_get_rowstride (pixbuf); 433rxvt_img *
283 int channels = gdk_pixbuf_get_n_channels (pixbuf); 434rxvt_img::sub_rect (int x, int y, int width, int height)
284 unsigned char *row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels; 435{
285 char *line = ximage->data; 436 rxvt_img *img = clone ();
286 437
287 rgba c (0, 0, 0); 438 img->x += x;
439 img->y += y;
288 440
289 if (channels == 4 && alpha_mask == 0) 441 if (w != width || h != height)
290 { 442 {
291 //pix_colors[Color_bg].get (c); 443 img->w = width;
292 //TODO 444 img->h = height;
293 c.r = 0xffff; c.g = 0xc0c0; c.b = 0xcbcb;//D 445
294 c.r >>= 8; 446 rxvt_img *img2 = img->reify ();
295 c.g >>= 8; 447 delete img;
296 c.b >>= 8; 448 img = img2;
297 } 449 }
298 450
299 for (int y = 0; y < height; y++)
300 {
301 for (int x = 0; x < width; x++)
302 {
303 unsigned char *pixel = row + x * channels;
304 uint32_t value;
305 unsigned char r, g, b, a;
306
307 if (channels == 4)
308 {
309 a = pixel[3];
310 r = (pixel[0] * a + c.r * (0xff - a)) / 0xff;
311 g = (pixel[1] * a + c.g * (0xff - a)) / 0xff;
312 b = (pixel[2] * a + c.b * (0xff - a)) / 0xff;
313 }
314 else
315 {
316 a = 0xff;
317 r = pixel[0];
318 g = pixel[1];
319 b = pixel[2];
320 }
321
322 value = ((r >> (8 - width_r)) << sh_r)
323 | ((g >> (8 - width_g)) << sh_g)
324 | ((b >> (8 - width_b)) << sh_b)
325 | ((a >> (8 - width_a)) << sh_a);
326
327 if (ximage->bits_per_pixel == 32)
328 ((uint32_t *)line)[x] = value;
329 else
330 XPutPixel (ximage, x, y, value);
331 }
332
333 row += rowstride;
334 line += ximage->bytes_per_line;
335 }
336
337 XPutImage (dpy, pm, gc, ximage, 0, 0, dst_x, dst_y, width, height);
338 XDestroyImage (ximage);
339 XFreeGC (dpy, gc);
340
341 return true;
342}
343
344rxvt_img *
345rxvt_img::clone ()
346{
347 rxvt_img *img = new rxvt_img (s, format, w, h);
348
349 GC gc = XCreateGC (s->display->dpy, pm, 0, 0);
350 XCopyArea (s->display->dpy, pm, img->pm, gc, 0, 0, w, h, 0, 0);
351 XFreeGC (s->display->dpy, gc);
352
353 return img; 451 return img;
354} 452}
355 453
356rxvt_img * 454rxvt_img *
357rxvt_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])
358{ 456{
359 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 ();
360 459
361 Display *dpy = s->display->dpy; 460 Display *dpy = s->display->dpy;
362 XRenderPictureAttributes pa; 461 Picture src = src_picture ();
363 pa.repeat = repeat;
364 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
365 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); 462 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
366
367 XRenderComposite (dpy, PictOpSrc, src, None, dst, x, y, 0, 0, 0, 0, width, height);
368
369 XRenderFreePicture (dpy, src);
370 XRenderFreePicture (dpy, dst);
371
372 return img;
373}
374
375rxvt_img *
376rxvt_img::transform (int new_width, int new_height, double matrix[9], int repeat)
377{
378 rxvt_img *img = new rxvt_img (s, format, new_width, new_height);
379
380 Display *dpy = s->display->dpy;
381 XRenderPictureAttributes pa;
382 pa.repeat = repeat;
383 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
384 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
385 463
386 XTransform xfrm; 464 XTransform xfrm;
387 465
388 for (int i = 0; i < 3; ++i) 466 for (int i = 0; i < 3; ++i)
389 for (int j = 0; j < 3; ++j) 467 for (int j = 0; j < 3; ++j)
390 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]); 468 xfrm.matrix [i][j] = XDoubleToFixed (matrix [i * 3 + j]);
391 469
470#if 0
471 xfrm.matrix [0][2] -= XDoubleToFixed (x);//TODO
472 xfrm.matrix [1][2] -= XDoubleToFixed (y);
473#endif
474
392 XRenderSetPictureFilter (dpy, src, "good", 0, 0); 475 XRenderSetPictureFilter (dpy, src, "good", 0, 0);
393 XRenderSetPictureTransform (dpy, src, &xfrm); 476 XRenderSetPictureTransform (dpy, src, &xfrm);
394 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);
395 478
396 XRenderFreePicture (dpy, src); 479 XRenderFreePicture (dpy, src);
400} 483}
401 484
402rxvt_img * 485rxvt_img *
403rxvt_img::scale (int new_width, int new_height) 486rxvt_img::scale (int new_width, int new_height)
404{ 487{
488 if (w == new_width && h == new_height)
489 return clone ();
490
405 double matrix[9] = { 491 double matrix[9] = {
406 w / (double)new_width, 0, 0, 492 w / (double)new_width, 0, 0,
407 0, h / (double)new_height, 0, 493 0, h / (double)new_height, 0,
408 0, 0, 1 494 0, 0, 1
409 }; 495 };
410 496
497 int old_repeat_mode = repeat;
498 repeat = RepeatPad; // not right, but xrender can't proeprly scale it seems
499
411 return transform (new_width, new_height, matrix); 500 rxvt_img *img = transform (new_width, new_height, matrix);
412}
413 501
502 repeat = old_repeat_mode;
503 img->repeat = repeat;
504
505 return img;
506}
507
414rxvt_img * 508rxvt_img *
415rxvt_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)
416{ 510{
417 double s = sin (phi); 511 double s = sin (phi);
418 double c = cos (phi); 512 double c = cos (phi);
419 513
420 double matrix[9] = { 514 double matrix[9] = {
421 c, -s, -c * x + s * y + x, 515 c, -s, -c * x + s * y + x,
422 s, c, -s * x - c * y + y, 516 s, c, -s * x - c * y + y,
423 0, 0, 1 517 0, 0, 1
424 }; 518 };
425 519
426 return transform (new_width, new_height, matrix, repeat); 520 return transform (new_width, new_height, matrix);
427} 521}
428 522
429rxvt_img * 523rxvt_img *
430rxvt_img::convert_to (XRenderPictFormat *new_format) 524rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg)
431{ 525{
526 if (new_format == format)
527 return clone ();
528
432 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 ();
433 531
434 Display *dpy = s->display->dpy; 532 Display *dpy = s->display->dpy;
435 Picture src = XRenderCreatePicture (dpy, pm, format, 0, 0); 533 Picture src = src_picture ();
436 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;
437 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
438 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);
439 550
440 XRenderFreePicture (dpy, src);
441 XRenderFreePicture (dpy, dst); 551 XRenderFreePicture (dpy, src);
552 XRenderFreePicture (dpy, dst);
442 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
443 return img; 580 return img2;
444} 581}
445 582
446#endif 583#endif
447 584

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines