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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines