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.95 by root, Fri Jun 15 18:36:26 2012 UTC vs.
Revision 1.98 by root, Sun Jun 17 21:58:18 2012 UTC

1/*----------------------------------------------------------------------*
2 * File: rxvtimg.C
3 *----------------------------------------------------------------------*
4 *
5 * All portions of code are copyright by their respective author/s.
6 * Copyright (c) 2012 Marc Lehmann <schmorp@schmorp.de>
7 * Copyright (c) 2012 Emanuele Giaquinta <e.giaquinta@glauco.it>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *---------------------------------------------------------------------*/
23
1#include <string.h> 24#include <string.h>
2#include <math.h> 25#include <math.h>
3#include "../config.h" 26#include "../config.h"
4#include "rxvt.h" 27#include "rxvt.h"
5 28
7 30
8typedef rxvt_img::nv nv; 31typedef rxvt_img::nv nv;
9 32
10namespace 33namespace
11{ 34{
12
13 struct mat3x3 35 struct mat3x3
14 { 36 {
15 nv v[3][3]; 37 nv v[3][3];
16 38
17 mat3x3 () 39 mat3x3 ()
28 v[0][0] = v11; v[0][1] = v12; v[0][2] = v13; 50 v[0][0] = v11; v[0][1] = v12; v[0][2] = v13;
29 v[1][0] = v21; v[1][1] = v22; v[1][2] = v23; 51 v[1][0] = v21; v[1][1] = v22; v[1][2] = v23;
30 v[2][0] = v31; v[2][1] = v32; v[2][2] = v33; 52 v[2][0] = v31; v[2][1] = v32; v[2][2] = v33;
31 } 53 }
32 54
33 mat3x3 invert (); 55 mat3x3 inverse ();
34 56
35 nv *operator [](int i) { return &v[i][0]; } 57 nv *operator [](int i) { return &v[i][0]; }
36 const nv *operator [](int i) const { return &v[i][0]; } 58 const nv *operator [](int i) const { return &v[i][0]; }
37 59
38 operator const nv * () const { return &v[0][0]; } 60 operator const nv * () const { return &v[0][0]; }
53 static mat3x3 scale (nv s, nv t); 75 static mat3x3 scale (nv s, nv t);
54 static mat3x3 rotate (nv phi); 76 static mat3x3 rotate (nv phi);
55 }; 77 };
56 78
57 mat3x3 79 mat3x3
58 mat3x3::invert () 80 mat3x3::inverse ()
59 { 81 {
60 mat3x3 &m = *this; 82 mat3x3 &m = *this;
61 mat3x3 inv; 83 mat3x3 inv;
62 84
63 nv s0 = m[2][2] * m[1][1] - m[2][1] * m[1][2]; 85 nv s0 = m[2][2] * m[1][1] - m[2][1] * m[1][2];
127 s, c, 0, 149 s, c, 0,
128 0, 0, 1 150 0, 0, 1
129 ); 151 );
130 } 152 }
131 153
132} 154 struct composer
133
134#if 0
135struct pict
136{
137 Display *dpy;
138 Picture pic;
139
140 operator Picture () const
141 { 155 {
142 return pic; 156 rxvt_img *srcimg, *dstimg;
143 } 157 Picture src, dst, msk;
158 Display *dpy;
144 159
145 pict () 160 ecb_noinline
146 : pic (0) 161 composer (rxvt_img *srcimg, rxvt_img *dstimg = 0)
162 : srcimg (srcimg), dstimg (dstimg), msk (0)
147 { 163 {
164 if (!this->dstimg)
165 this->dstimg = srcimg->new_empty ();
166 else if (!this->dstimg->pm) // somewhat unsatisfying
167 this->dstimg->alloc ();
168
169 dpy = srcimg->s->dpy;
170 src = srcimg->picture ();
171 dst = this->dstimg->picture ();
148 } 172 }
149 173
150 pict (rxvt_img *img, XRenderPictFormat *format = 0) 174 ecb_noinline
151 : dpy (img->s->display->dpy) 175 void mask (bool rgb = true, int x = 1, int y = 1)
152 { 176 {
177 Pixmap pixmap = XCreatePixmap (dpy, srcimg->pm, x, y, rgb ? 32 : 8);
178
179 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, rgb ? PictStandardARGB32 : PictStandardA8);
153 XRenderPictureAttributes pa; 180 XRenderPictureAttributes pa;
154 pa.repeat = img->repeat; 181 pa.repeat = RepeatNormal;
155 pic = XRenderCreatePicture (dpy, img->pm, format ? format : img->format, CPRepeat, &pa); 182 pa.component_alpha = rgb;
183 msk = XRenderCreatePicture (dpy, pixmap, format, CPRepeat | CPComponentAlpha, &pa);
184
185 XFreePixmap (dpy, pixmap);
186
187 ecb_assume (msk);
188 }
189
190 // CreateSolidFill creates a very very very weird picture
191 void mask (const rgba &c)
192 {
193 XRenderColor rc = {
194 c.r * c.a / 65535,
195 c.g * c.a / 65535,
196 c.b * c.a / 65535,
197 c.a
198 };
199 msk = XRenderCreateSolidFill (dpy, &rc);
200 ecb_assume (msk);
201 }
202
203 void fill (const rgba &c)
204 {
205 XRenderColor rc = {
206 c.r * c.a / 65535,
207 c.g * c.a / 65535,
208 c.b * c.a / 65535,
209 c.a
210 };
211
212 XRenderFillRectangle (dpy, PictOpSrc, msk, &rc, 0, 0, 1, 1);
213 }
214
215 operator rxvt_img *()
216 {
217 return dstimg;
218 }
219
220 ecb_noinline
221 ~composer ()
222 {
223 XRenderFreePicture (dpy, src);
224 XRenderFreePicture (dpy, dst);
225 if (msk) XRenderFreePicture (dpy, msk);
226 }
156 } 227 };
157 228}
158 ~pict ()
159 {
160 if (pic)
161 XRenderFreePicture (dpy, pic);
162 }
163};
164#endif
165 229
166static XRenderPictFormat * 230static XRenderPictFormat *
167find_alpha_format_for (Display *dpy, XRenderPictFormat *format) 231find_alpha_format_for (Display *dpy, XRenderPictFormat *format)
168{ 232{
169 if (format->direct.alphaMask) 233 if (format->direct.alphaMask)
196} 260}
197 261
198rxvt_img * 262rxvt_img *
199rxvt_img::new_from_root (rxvt_screen *s) 263rxvt_img::new_from_root (rxvt_screen *s)
200{ 264{
201 Display *dpy = s->display->dpy; 265 Display *dpy = s->dpy;
202 unsigned int root_pm_w, root_pm_h; 266 unsigned int root_pm_w, root_pm_h;
203 Pixmap root_pixmap = s->display->get_pixmap_property (s->display->xa[XA_XROOTPMAP_ID]); 267 Pixmap root_pixmap = s->display->get_pixmap_property (s->display->xa [XA_XROOTPMAP_ID]);
204 if (root_pixmap == None) 268 if (root_pixmap == None)
205 root_pixmap = s->display->get_pixmap_property (s->display->xa[XA_ESETROOT_PMAP_ID]); 269 root_pixmap = s->display->get_pixmap_property (s->display->xa [XA_ESETROOT_PMAP_ID]);
206 270
207 if (root_pixmap == None) 271 if (root_pixmap == None)
208 return 0; 272 return 0;
209 273
210 Window wdummy; 274 Window wdummy;
233# if HAVE_PIXBUF 297# if HAVE_PIXBUF
234 298
235rxvt_img * 299rxvt_img *
236rxvt_img::new_from_pixbuf (rxvt_screen *s, GdkPixbuf *pb) 300rxvt_img::new_from_pixbuf (rxvt_screen *s, GdkPixbuf *pb)
237{ 301{
238 Display *dpy = s->display->dpy; 302 Display *dpy = s->dpy;
239 303
240 int width = gdk_pixbuf_get_width (pb); 304 int width = gdk_pixbuf_get_width (pb);
241 int height = gdk_pixbuf_get_height (pb); 305 int height = gdk_pixbuf_get_height (pb);
242 306
243 if (width > 32767 || height > 32767) // well, we *could* upload in chunks 307 if (width > 32767 || height > 32767) // well, we *could* upload in chunks
293 uint8_t r = *src++; 357 uint8_t r = *src++;
294 uint8_t g = *src++; 358 uint8_t g = *src++;
295 uint8_t b = *src++; 359 uint8_t b = *src++;
296 360
297 uint32_t v = (255 << 24) | (r << 16) | (g << 8) | b; 361 uint32_t v = (255 << 24) | (r << 16) | (g << 8) | b;
298 362
299 if (ecb_big_endian () ? !byte_order_mismatch : byte_order_mismatch) 363 if (ecb_big_endian () ? !byte_order_mismatch : byte_order_mismatch)
300 v = ecb_bswap32 (v); 364 v = ecb_bswap32 (v);
301 365
302 *dst++ = v; 366 *dst++ = v;
303 } 367 }
356{ 420{
357 if (--ref->cnt) 421 if (--ref->cnt)
358 return; 422 return;
359 423
360 if (pm && ref->ours) 424 if (pm && ref->ours)
361 XFreePixmap (s->display->dpy, pm); 425 XFreePixmap (s->dpy, pm);
362 426
363 delete ref; 427 delete ref;
364} 428}
365 429
366rxvt_img::~rxvt_img () 430rxvt_img::~rxvt_img ()
369} 433}
370 434
371void 435void
372rxvt_img::alloc () 436rxvt_img::alloc ()
373{ 437{
374 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth); 438 pm = XCreatePixmap (s->dpy, s->display->root, w, h, format->depth);
375 ref = new pixref (w, h); 439 ref = new pixref (w, h);
440}
441
442rxvt_img *
443rxvt_img::new_empty ()
444{
445 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat);
446 img->alloc ();
447
448 return img;
376} 449}
377 450
378Picture 451Picture
379rxvt_img::picture () 452rxvt_img::picture ()
380{ 453{
381 Display *dpy = s->display->dpy; 454 Display *dpy = s->dpy;
382 455
383 XRenderPictureAttributes pa; 456 XRenderPictureAttributes pa;
384 pa.repeat = repeat; 457 pa.repeat = repeat;
385 Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 458 Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
386 459
391rxvt_img::unshare () 464rxvt_img::unshare ()
392{ 465{
393 if (ref->cnt == 1 && ref->ours) 466 if (ref->cnt == 1 && ref->ours)
394 return; 467 return;
395 468
396 Pixmap pm2 = XCreatePixmap (s->display->dpy, s->display->root, ref->w, ref->h, format->depth); 469 Pixmap pm2 = XCreatePixmap (s->dpy, s->display->root, ref->w, ref->h, format->depth);
397 GC gc = XCreateGC (s->display->dpy, pm, 0, 0); 470 GC gc = XCreateGC (s->dpy, pm, 0, 0);
398 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0); 471 XCopyArea (s->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0);
399 XFreeGC (s->display->dpy, gc); 472 XFreeGC (s->dpy, gc);
400 473
401 destroy (); 474 destroy ();
402 475
403 pm = pm2; 476 pm = pm2;
404 ref = new pixref (ref->w, ref->h); 477 ref = new pixref (ref->w, ref->h);
407void 480void
408rxvt_img::fill (const rgba &c) 481rxvt_img::fill (const rgba &c)
409{ 482{
410 XRenderColor rc = { c.r, c.g, c.b, c.a }; 483 XRenderColor rc = { c.r, c.g, c.b, c.a };
411 484
412 Display *dpy = s->display->dpy; 485 Display *dpy = s->dpy;
413 Picture src = picture (); 486 Picture src = picture ();
414 XRenderFillRectangle (dpy, PictOpSrc, src, &rc, 0, 0, w, h); 487 XRenderFillRectangle (dpy, PictOpSrc, src, &rc, 0, 0, w, h);
415 XRenderFreePicture (dpy, src); 488 XRenderFreePicture (dpy, src);
416} 489}
417 490
419rxvt_img::add_alpha () 492rxvt_img::add_alpha ()
420{ 493{
421 if (format->direct.alphaMask) 494 if (format->direct.alphaMask)
422 return; 495 return;
423 496
424 Display *dpy = s->display->dpy;
425
426 rxvt_img *img = new rxvt_img (s, find_alpha_format_for (dpy, format), x, y, w, h, repeat); 497 composer cc (this, new rxvt_img (s, find_alpha_format_for (s->dpy, format), x, y, w, h, repeat));
427 img->alloc ();
428
429 Picture src = picture ();
430 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
431 498
432 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 499 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
433 500
434 XRenderFreePicture (dpy, src); 501 rxvt_img *img = cc;
435 XRenderFreePicture (dpy, dst);
436 502
437 ::swap (img->ref, ref); 503 ::swap (img->ref, ref);
438 ::swap (img->pm , pm ); 504 ::swap (img->pm , pm );
439 505
440 delete img; 506 delete img;
465rxvt_img::blur (int rh, int rv) 531rxvt_img::blur (int rh, int rv)
466{ 532{
467 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV)) 533 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
468 return clone (); 534 return clone ();
469 535
470 Display *dpy = s->display->dpy; 536 Display *dpy = s->dpy;
471 int size = max (rh, rv) * 2 + 1; 537 int size = max (rh, rv) * 2 + 1;
472 nv *kernel = (nv *)malloc (size * sizeof (nv)); 538 nv *kernel = (nv *)malloc (size * sizeof (nv));
473 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 539 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed));
474 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat); 540 rxvt_img *img = new_empty ();
475 img->alloc ();
476 541
477 XRenderPictureAttributes pa; 542 XRenderPictureAttributes pa;
478 pa.repeat = RepeatPad; 543 pa.repeat = RepeatPad;
479 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 544 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
480 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0); 545 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0);
523 XRenderFreePicture (dpy, tmp); 588 XRenderFreePicture (dpy, tmp);
524 589
525 return img; 590 return img;
526} 591}
527 592
528static Picture 593ecb_noinline static void
529create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha)
530{
531 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8);
532
533 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8);
534 XRenderPictureAttributes pa;
535 pa.repeat = RepeatNormal;
536 pa.component_alpha = component_alpha;
537 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat | CPComponentAlpha, &pa);
538
539 XFreePixmap (dpy, pixmap);
540
541 return mask;
542}
543
544static void
545extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc) 594extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc)
546{ 595{
547 int32_t x = clamp (c, cl0, cl1); 596 int32_t x = clamp (c, cl0, cl1);
548 c -= x; 597 c -= x;
549 xc = x; 598 xc = x;
550} 599}
551 600
552static bool 601ecb_noinline static bool
553extract (int32_t cl0, int32_t cl1, int32_t &r, int32_t &g, int32_t &b, int32_t &a, unsigned short &xr, unsigned short &xg, unsigned short &xb, unsigned short &xa) 602extract (int32_t cl0, int32_t cl1, int32_t &r, int32_t &g, int32_t &b, int32_t &a, unsigned short &xr, unsigned short &xg, unsigned short &xb, unsigned short &xa)
554{ 603{
555 extract (cl0, cl1, r, xr); 604 extract (cl0, cl1, r, xr);
556 extract (cl0, cl1, g, xg); 605 extract (cl0, cl1, g, xg);
557 extract (cl0, cl1, b, xb); 606 extract (cl0, cl1, b, xb);
563void 612void
564rxvt_img::brightness (int32_t r, int32_t g, int32_t b, int32_t a) 613rxvt_img::brightness (int32_t r, int32_t g, int32_t b, int32_t a)
565{ 614{
566 unshare (); 615 unshare ();
567 616
568 Display *dpy = s->display->dpy; 617 Display *dpy = s->dpy;
569 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 618 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
570 619
571 // loop should not be needed for brightness, as only -1..1 makes sense 620 // loop should not be needed for brightness, as only -1..1 makes sense
572 //while (r | g | b | a) 621 //while (r | g | b | a)
573 { 622 {
597rxvt_img::contrast (int32_t r, int32_t g, int32_t b, int32_t a) 646rxvt_img::contrast (int32_t r, int32_t g, int32_t b, int32_t a)
598{ 647{
599 if (r < 0 || g < 0 || b < 0 || a < 0) 648 if (r < 0 || g < 0 || b < 0 || a < 0)
600 rxvt_fatal ("rxvt_img::contrast does not support negative values.\n"); 649 rxvt_fatal ("rxvt_img::contrast does not support negative values.\n");
601 650
602 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat);
603 img->alloc ();
604 img->fill (rgba (0, 0, 0, 0));
605
606 // premultiply (yeah, these are not exact, sue me or fix it) 651 // premultiply (yeah, these are not exact, sue me or fix it)
607 r = (r * (a >> 8)) >> 8; 652 r = (r * (a >> 8)) >> 8;
608 g = (g * (a >> 8)) >> 8; 653 g = (g * (a >> 8)) >> 8;
609 b = (b * (a >> 8)) >> 8; 654 b = (b * (a >> 8)) >> 8;
610 655
611 Display *dpy = s->display->dpy; 656 composer cc (this);
657 rxvt_img *img = cc;
658 img->fill (rgba (0, 0, 0, 0));
612 659
613 Picture src = picture (); 660 cc.mask (true);
614 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0);
615 Picture mul = create_xrender_mask (dpy, pm, True, True);
616 661
617 //TODO: this operator does not yet implement some useful contrast 662 //TODO: this operator does not yet implement some useful contrast
618 while (r | g | b | a) 663 while (r | g | b | a)
619 { 664 {
620 unsigned short xr, xg, xb, xa; 665 unsigned short xr, xg, xb, xa;
621 XRenderColor mask_c; 666 XRenderColor mask_c;
622 667
623 if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha)) 668 if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha))
624 { 669 {
625 XRenderFillRectangle (dpy, PictOpSrc, mul, &mask_c, 0, 0, 1, 1); 670 XRenderFillRectangle (cc.dpy, PictOpSrc, cc.msk, &mask_c, 0, 0, 1, 1);
626 XRenderComposite (dpy, PictOpAdd, src, mul, dst, 0, 0, 0, 0, 0, 0, w, h); 671 XRenderComposite (cc.dpy, PictOpAdd, cc.src, cc.msk, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
627 } 672 }
628 } 673 }
629
630 XRenderFreePicture (dpy, mul);
631 XRenderFreePicture (dpy, dst);
632 XRenderFreePicture (dpy, src);
633 674
634 ::swap (img->ref, ref); 675 ::swap (img->ref, ref);
635 ::swap (img->pm , pm ); 676 ::swap (img->pm , pm );
636 677
637 delete img; 678 delete img;
640void 681void
641rxvt_img::draw (rxvt_img *img, int op, nv mask) 682rxvt_img::draw (rxvt_img *img, int op, nv mask)
642{ 683{
643 unshare (); 684 unshare ();
644 685
645 Display *dpy = s->display->dpy; 686 composer cc (img, this);
646 Picture src = img->picture ();
647 Picture dst = picture ();
648 Picture mask_p = 0;
649 687
650 if (mask != 1.) 688 if (mask != 1.)
651 { 689 cc.mask (rgba (0, 0, 0, float_to_component (mask)));
652 mask_p = create_xrender_mask (dpy, img->pm, False, False);
653 XRenderColor mask_c = { 0, 0, 0, float_to_component (mask) };
654 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
655 }
656 690
657 XRenderComposite (dpy, op, src, mask_p, dst, x - img->x, y - img->y, 0, 0, 0, 0, w, h); 691 XRenderComposite (cc.dpy, op, cc.src, cc.msk, cc.dst, x - img->x, y - img->y, 0, 0, 0, 0, w, h);
658
659 XRenderFreePicture (dpy, src);
660 XRenderFreePicture (dpy, dst);
661
662 if (mask_p)
663 XRenderFreePicture (dpy, mask_p);
664} 692}
665 693
666rxvt_img * 694rxvt_img *
667rxvt_img::clone () 695rxvt_img::clone ()
668{ 696{
673rxvt_img::reify () 701rxvt_img::reify ()
674{ 702{
675 if (x == 0 && y == 0 && w == ref->w && h == ref->h) 703 if (x == 0 && y == 0 && w == ref->w && h == ref->h)
676 return clone (); 704 return clone ();
677 705
678 Display *dpy = s->display->dpy; 706 Display *dpy = s->dpy;
679 707
680 // add an alpha channel if... 708 // add an alpha channel if...
681 bool alpha = !format->direct.alphaMask // pixmap has none yet 709 bool alpha = !format->direct.alphaMask // pixmap has none yet
682 && (x || y) // we need one because of non-zero offset 710 && (x || y) // we need one because of non-zero offset
683 && repeat == RepeatNone; // and we have no good pixels to fill with 711 && repeat == RepeatNone; // and we have no good pixels to fill with
684 712
685 rxvt_img *img = new rxvt_img (s, alpha ? find_alpha_format_for (dpy, format) : format, 0, 0, w, h, repeat); 713 composer cc (this, new rxvt_img (s, alpha ? find_alpha_format_for (s->dpy, format) : format,
686 img->alloc (); 714 0, 0, w, h, repeat));
687 715
688 Picture src = picture ();
689 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
690
691 if (alpha) 716 if (alpha)
692 { 717 {
693 XRenderColor rc = { 0, 0, 0, 0 }; 718 XRenderColor rc = { 0, 0, 0, 0 };
694 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles 719 XRenderFillRectangle (cc.dpy, PictOpSrc, cc.dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles
695 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, x, y, ref->w, ref->h); 720 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, 0, 0, 0, 0, x, y, ref->w, ref->h);
696 } 721 }
697 else 722 else
698 XRenderComposite (dpy, PictOpSrc, src, None, dst, -x, -y, 0, 0, 0, 0, w, h); 723 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, -x, -y, 0, 0, 0, 0, w, h);
699 724
700 XRenderFreePicture (dpy, src);
701 XRenderFreePicture (dpy, dst);
702
703 return img; 725 return cc;
704} 726}
705 727
706rxvt_img * 728rxvt_img *
707rxvt_img::sub_rect (int x, int y, int width, int height) 729rxvt_img::sub_rect (int x, int y, int width, int height)
708{ 730{
734rxvt_img::transform (const nv *matrix) 756rxvt_img::transform (const nv *matrix)
735{ 757{
736 mat3x3 m (matrix); 758 mat3x3 m (matrix);
737 759
738 // calculate new pixel bounding box coordinates 760 // calculate new pixel bounding box coordinates
739 nv r[2], rmin[2], rmax[2]; 761 nv rmin[2], rmax[2];
740 762
741 for (int i = 0; i < 2; ++i) 763 for (int i = 0; i < 2; ++i)
742 { 764 {
743 nv v; 765 nv v;
744 766
745 v = m.apply1 (i, 0+x, 0+y); rmin [i] = rmax [i] = v; r [i] = v; 767 v = m.apply1 (i, 0+x, 0+y); rmin [i] = rmax [i] = v;
746 v = m.apply1 (i, w+x, 0+y); min_it (rmin [i], v); max_it (rmax [i], v); 768 v = m.apply1 (i, w+x, 0+y); min_it (rmin [i], v); max_it (rmax [i], v);
747 v = m.apply1 (i, 0+x, h+y); min_it (rmin [i], v); max_it (rmax [i], v); 769 v = m.apply1 (i, 0+x, h+y); min_it (rmin [i], v); max_it (rmax [i], v);
748 v = m.apply1 (i, w+x, h+y); min_it (rmin [i], v); max_it (rmax [i], v); 770 v = m.apply1 (i, w+x, h+y); min_it (rmin [i], v); max_it (rmax [i], v);
749 } 771 }
750 772
756 int ny = floor (rmin [1]); 778 int ny = floor (rmin [1]);
757 779
758 int new_width = ceil (rmax [0] - rmin [0]); 780 int new_width = ceil (rmax [0] - rmin [0]);
759 int new_height = ceil (rmax [1] - rmin [1]); 781 int new_height = ceil (rmax [1] - rmin [1]);
760 782
761 m = mat3x3::translate (-x, -y) * m * mat3x3::translate (x, y); 783 mat3x3 inv = (mat3x3::translate (-x, -y) * m * mat3x3::translate (x, y)).inverse ();
762 784
763 mat3x3 inv = m.invert (); 785 composer cc (this, new rxvt_img (s, format, nx, ny, new_width, new_height, repeat));
764
765 rxvt_img *img = new rxvt_img (s, format, nx, ny, new_width, new_height, repeat);
766 img->alloc ();
767
768 Display *dpy = s->display->dpy;
769 Picture src = picture ();
770 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
771 786
772 XTransform xfrm; 787 XTransform xfrm;
773 788
774 for (int i = 0; i < 3; ++i) 789 for (int i = 0; i < 3; ++i)
775 for (int j = 0; j < 3; ++j) 790 for (int j = 0; j < 3; ++j)
776 xfrm.matrix [i][j] = XDoubleToFixed (inv [i][j]); 791 xfrm.matrix [i][j] = XDoubleToFixed (inv [i][j]);
777 792
778 XRenderSetPictureFilter (dpy, src, "good", 0, 0); 793 XRenderSetPictureFilter (cc.dpy, cc.src, "good", 0, 0);
779 XRenderSetPictureTransform (dpy, src, &xfrm); 794 XRenderSetPictureTransform (cc.dpy, cc.src, &xfrm);
780 XRenderComposite (dpy, PictOpSrc, src, None, dst, sx, sy, 0, 0, 0, 0, new_width, new_height); 795 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, sx, sy, 0, 0, 0, 0, new_width, new_height);
781 796
782 XRenderFreePicture (dpy, src);
783 XRenderFreePicture (dpy, dst);
784
785 return img; 797 return cc;
786} 798}
787 799
788rxvt_img * 800rxvt_img *
789rxvt_img::scale (int new_width, int new_height) 801rxvt_img::scale (int new_width, int new_height)
790{ 802{
823rxvt_img::convert_format (XRenderPictFormat *new_format, const rgba &bg) 835rxvt_img::convert_format (XRenderPictFormat *new_format, const rgba &bg)
824{ 836{
825 if (new_format == format) 837 if (new_format == format)
826 return clone (); 838 return clone ();
827 839
828 rxvt_img *img = new rxvt_img (s, new_format, x, y, w, h, repeat); 840 composer cc (this, new rxvt_img (s, new_format, x, y, w, h, repeat));
829 img->alloc ();
830 841
831 Display *dpy = s->display->dpy;
832 Picture src = picture ();
833 Picture dst = XRenderCreatePicture (dpy, img->pm, new_format, 0, 0);
834 int op = PictOpSrc; 842 int op = PictOpSrc;
835 843
836 if (format->direct.alphaMask && !new_format->direct.alphaMask) 844 if (format->direct.alphaMask && !new_format->direct.alphaMask)
837 { 845 {
838 // does it have to be that complicated 846 // does it have to be that complicated
839 XRenderColor rc = { bg.r, bg.g, bg.b, bg.a }; 847 XRenderColor rc = { bg.r, bg.g, bg.b, bg.a };
840 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h); 848 XRenderFillRectangle (cc.dpy, PictOpSrc, cc.dst, &rc, 0, 0, w, h);
841 849
842 op = PictOpOver; 850 op = PictOpOver;
843 } 851 }
844 852
845 XRenderComposite (dpy, op, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 853 XRenderComposite (cc.dpy, op, cc.src, None, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
846 854
847 XRenderFreePicture (dpy, src);
848 XRenderFreePicture (dpy, dst);
849
850 return img; 855 return cc;
851} 856}
852 857
853rxvt_img * 858rxvt_img *
854rxvt_img::blend (rxvt_img *img, nv factor) 859rxvt_img::tint (const rgba &c)
855{ 860{
856 rxvt_img *img2 = clone (); 861 composer cc (this);
857 Display *dpy = s->display->dpy; 862 cc.mask (true);
858 Picture src = img->picture (); 863 cc.fill (c);
859 Picture dst = XRenderCreatePicture (dpy, img2->pm, img2->format, 0, 0);
860 Picture mask = create_xrender_mask (dpy, img->pm, False, False);
861 864
862 XRenderColor mask_c;
863
864 mask_c.alpha = float_to_component (factor);
865 mask_c.red =
866 mask_c.green =
867 mask_c.blue = 0;
868 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
869
870 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, w, h); 865 XRenderComposite (cc.dpy, PictOpSrc, cc.src, cc.msk, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
871 866
872 XRenderFreePicture (dpy, src);
873 XRenderFreePicture (dpy, dst);
874 XRenderFreePicture (dpy, mask);
875
876 return img2; 867 return cc;
868}
869
870rxvt_img *
871rxvt_img::filter (const char *name, int nparams, nv *params)
872{
873 rxvt_img *img = new_empty ();
874
875 composer cc (img);
876
877 XFixed *xparams = rxvt_temp_buf<XFixed> (nparams);
878
879 for (int i = 0; i < nparams; ++i)
880 xparams [i] = XDoubleToFixed (params [i]);
881
882 XRenderSetPictureFilter (cc.dpy, cc.src, name, xparams, nparams);
883
884 XRenderComposite (cc.dpy, PictOpSrc, cc.src, 0, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
885
886 return cc;
877} 887}
878 888
879#endif 889#endif
880 890

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines