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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines