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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines