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.107 by root, Thu May 22 18:54:33 2014 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 3 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 w = 1, int h = 1)
152 { 176 {
177 Pixmap pixmap = XCreatePixmap (dpy, srcimg->pm, w, h, 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
285 for (int y = 0; y < height; y++) 349 for (int y = 0; y < height; y++)
286 { 350 {
287 unsigned char *src = row; 351 unsigned char *src = row;
288 uint32_t *dst = (uint32_t *)line; 352 uint32_t *dst = (uint32_t *)line;
289 353
290 if (!pb_has_alpha)
291 for (int x = 0; x < width; x++) 354 for (int x = 0; x < width; x++)
292 { 355 {
293 uint8_t r = *src++; 356 uint8_t r = *src++;
294 uint8_t g = *src++; 357 uint8_t g = *src++;
295 uint8_t b = *src++; 358 uint8_t b = *src++;
359 uint8_t a = *src;
296 360
361 // this is done so it can be jump-free, but newer gcc's clone inner the loop
362 a = pb_has_alpha ? a : 255;
363 src += pb_has_alpha;
364
365 r = (r * a + 127) / 255;
366 g = (g * a + 127) / 255;
367 b = (b * a + 127) / 255;
368
297 uint32_t v = (255 << 24) | (r << 16) | (g << 8) | b; 369 uint32_t v = (a << 24) | (r << 16) | (g << 8) | b;
298 370
299 if (ecb_big_endian () ? !byte_order_mismatch : byte_order_mismatch) 371 if (ecb_big_endian () ? !byte_order_mismatch : byte_order_mismatch)
300 v = ecb_bswap32 (v); 372 v = ecb_bswap32 (v);
301 373
302 *dst++ = v; 374 *dst++ = v;
303 } 375 }
304 else
305 for (int x = 0; x < width; x++)
306 {
307 uint32_t v = *(uint32_t *)src; src += 4;
308
309 if (ecb_big_endian ())
310 v = ecb_bswap32 (v);
311
312 v = ecb_rotl32 (v, 8); // abgr to bgra
313
314 if (!byte_order_mismatch)
315 v = ecb_bswap32 (v);
316
317 *dst++ = v;
318 }
319 376
320 row += rowstride; 377 row += rowstride;
321 line += xi.bytes_per_line; 378 line += xi.bytes_per_line;
322 } 379 }
323 380
356{ 413{
357 if (--ref->cnt) 414 if (--ref->cnt)
358 return; 415 return;
359 416
360 if (pm && ref->ours) 417 if (pm && ref->ours)
361 XFreePixmap (s->display->dpy, pm); 418 XFreePixmap (s->dpy, pm);
362 419
363 delete ref; 420 delete ref;
364} 421}
365 422
366rxvt_img::~rxvt_img () 423rxvt_img::~rxvt_img ()
369} 426}
370 427
371void 428void
372rxvt_img::alloc () 429rxvt_img::alloc ()
373{ 430{
374 pm = XCreatePixmap (s->display->dpy, s->display->root, w, h, format->depth); 431 pm = XCreatePixmap (s->dpy, s->display->root, w, h, format->depth);
375 ref = new pixref (w, h); 432 ref = new pixref (w, h);
433}
434
435rxvt_img *
436rxvt_img::new_empty ()
437{
438 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat);
439 img->alloc ();
440
441 return img;
376} 442}
377 443
378Picture 444Picture
379rxvt_img::picture () 445rxvt_img::picture ()
380{ 446{
381 Display *dpy = s->display->dpy; 447 Display *dpy = s->dpy;
382 448
383 XRenderPictureAttributes pa; 449 XRenderPictureAttributes pa;
384 pa.repeat = repeat; 450 pa.repeat = repeat;
385 Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 451 Picture pic = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
386 452
391rxvt_img::unshare () 457rxvt_img::unshare ()
392{ 458{
393 if (ref->cnt == 1 && ref->ours) 459 if (ref->cnt == 1 && ref->ours)
394 return; 460 return;
395 461
396 Pixmap pm2 = XCreatePixmap (s->display->dpy, s->display->root, ref->w, ref->h, format->depth); 462 Pixmap pm2 = XCreatePixmap (s->dpy, s->display->root, ref->w, ref->h, format->depth);
397 GC gc = XCreateGC (s->display->dpy, pm, 0, 0); 463 GC gc = XCreateGC (s->dpy, pm, 0, 0);
398 XCopyArea (s->display->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0); 464 XCopyArea (s->dpy, pm, pm2, gc, 0, 0, ref->w, ref->h, 0, 0);
399 XFreeGC (s->display->dpy, gc); 465 XFreeGC (s->dpy, gc);
400 466
401 destroy (); 467 destroy ();
402 468
403 pm = pm2; 469 pm = pm2;
404 ref = new pixref (ref->w, ref->h); 470 ref = new pixref (ref->w, ref->h);
405} 471}
406 472
407void 473void
474rxvt_img::fill (const rgba &c, int x, int y, int w, int h)
475{
476 XRenderColor rc = { c.r, c.g, c.b, c.a };
477
478 Display *dpy = s->dpy;
479 Picture src = picture ();
480 XRenderFillRectangle (dpy, PictOpSrc, src, &rc, x, y, w, h);
481 XRenderFreePicture (dpy, src);
482}
483
484void
408rxvt_img::fill (const rgba &c) 485rxvt_img::fill (const rgba &c)
409{ 486{
410 XRenderColor rc = { c.r, c.g, c.b, c.a }; 487 fill (c, 0, 0, w, h);
411
412 Display *dpy = s->display->dpy;
413 Picture src = picture ();
414 XRenderFillRectangle (dpy, PictOpSrc, src, &rc, 0, 0, w, h);
415 XRenderFreePicture (dpy, src);
416} 488}
417 489
418void 490void
419rxvt_img::add_alpha () 491rxvt_img::add_alpha ()
420{ 492{
421 if (format->direct.alphaMask) 493 if (format->direct.alphaMask)
422 return; 494 return;
423 495
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); 496 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 497
432 XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 498 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
433 499
434 XRenderFreePicture (dpy, src); 500 rxvt_img *img = cc;
435 XRenderFreePicture (dpy, dst);
436 501
437 ::swap (img->ref, ref); 502 ::swap (img->ref, ref);
438 ::swap (img->pm , pm ); 503 ::swap (img->pm , pm );
439 504
440 delete img; 505 delete img;
465rxvt_img::blur (int rh, int rv) 530rxvt_img::blur (int rh, int rv)
466{ 531{
467 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV)) 532 if (!(s->display->flags & DISPLAY_HAS_RENDER_CONV))
468 return clone (); 533 return clone ();
469 534
470 Display *dpy = s->display->dpy; 535 Display *dpy = s->dpy;
471 int size = max (rh, rv) * 2 + 1; 536 int size = max (rh, rv) * 2 + 1;
472 nv *kernel = (nv *)malloc (size * sizeof (nv)); 537 nv *kernel = (nv *)malloc (size * sizeof (nv));
473 XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); 538 XFixed *params = rxvt_temp_buf<XFixed> (size + 2);
474 rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat); 539 rxvt_img *img = new_empty ();
475 img->alloc ();
476 540
477 XRenderPictureAttributes pa; 541 XRenderPictureAttributes pa;
478 pa.repeat = RepeatPad; 542 pa.repeat = RepeatPad;
479 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa); 543 Picture src = XRenderCreatePicture (dpy, pm, format, CPRepeat, &pa);
480 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0); 544 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0);
514 0, 0, 578 0, 0,
515 w, h); 579 w, h);
516 } 580 }
517 581
518 free (kernel); 582 free (kernel);
519 free (params);
520 583
521 XRenderFreePicture (dpy, src); 584 XRenderFreePicture (dpy, src);
522 XRenderFreePicture (dpy, dst); 585 XRenderFreePicture (dpy, dst);
523 XRenderFreePicture (dpy, tmp); 586 XRenderFreePicture (dpy, tmp);
524 587
525 return img; 588 return img;
526} 589}
527 590
528static Picture 591rxvt_img *
529create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha) 592rxvt_img::muladd (nv mul, nv add)
530{ 593{
531 Pixmap pixmap = XCreatePixmap (dpy, drawable, 1, 1, argb ? 32 : 8); 594 // STEP 1: double the image width, fill all odd columns with white (==1)
532 595
533 XRenderPictFormat *format = XRenderFindStandardFormat (dpy, argb ? PictStandardARGB32 : PictStandardA8); 596 composer cc (this, new rxvt_img (s, format, 0, 0, w * 2, h, repeat));
534 XRenderPictureAttributes pa;
535 pa.repeat = RepeatNormal;
536 pa.component_alpha = component_alpha;
537 Picture mask = XRenderCreatePicture (dpy, pixmap, format, CPRepeat | CPComponentAlpha, &pa);
538 597
539 XFreePixmap (dpy, pixmap); 598 // why the hell does XRenderSetPictureTransform want a writable matrix :(
599 // that keeps us from just static const'ing this matrix.
600 XTransform h_double = {
601 0x08000, 0, 0,
602 0, 0x10000, 0,
603 0, 0, 0x10000
604 };
540 605
541 return mask; 606 XRenderSetPictureFilter (cc.dpy, cc.src, "nearest", 0, 0);
542} 607 XRenderSetPictureTransform (cc.dpy, cc.src, &h_double);
608 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, 0, 0, 0, 0, 0, 0, w * 2, h);
543 609
544static void 610 cc.mask (false, 2, 1);
611
612 static const XRenderColor c0 = { 0, 0, 0, 0 };
613 XRenderFillRectangle (cc.dpy, PictOpSrc, cc.msk, &c0, 0, 0, 1, 1);
614 static const XRenderColor c1 = { 65535, 65535, 65535, 65535 };
615 XRenderFillRectangle (cc.dpy, PictOpSrc, cc.msk, &c1, 1, 0, 1, 1);
616
617 Picture white = XRenderCreateSolidFill (cc.dpy, &c1);
618
619 XRenderComposite (cc.dpy, PictOpOver, white, cc.msk, cc.dst, 0, 0, 0, 0, 0, 0, w * 2, h);
620
621 XRenderFreePicture (cc.dpy, white);
622
623 // STEP 2: convolve the image with a 3x1 filter
624 // a 2x1 filter would obviously suffice, but given the total lack of specification
625 // for xrender, I expect different xrender implementations to randomly diverge.
626 // we also halve the image, and hope for the best (again, for lack of specs).
627 composer cc2 (cc.dstimg);
628
629 XFixed kernel [] = {
630 XDoubleToFixed (3), XDoubleToFixed (1),
631 XDoubleToFixed (0), XDoubleToFixed (mul), XDoubleToFixed (add)
632 };
633
634 XTransform h_halve = {
635 0x20000, 0, 0,
636 0, 0x10000, 0,
637 0, 0, 0x10000
638 };
639
640 XRenderSetPictureFilter (cc.dpy, cc2.src, "nearest", 0, 0);
641 XRenderSetPictureTransform (cc.dpy, cc2.src, &h_halve);
642 XRenderSetPictureFilter (cc.dpy, cc2.src, FilterConvolution, kernel, ecb_array_length (kernel));
643
644 XRenderComposite (cc.dpy, PictOpSrc, cc2.src, None, cc2.dst, 0, 0, 0, 0, 0, 0, w * 2, h);
645
646 return cc2;
647}
648
649ecb_noinline static void
545extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc) 650extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc)
546{ 651{
547 int32_t x = clamp (c, cl0, cl1); 652 int32_t x = clamp (c, cl0, cl1);
548 c -= x; 653 c -= x;
549 xc = x; 654 xc = x;
550} 655}
551 656
552static bool 657ecb_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) 658extract (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{ 659{
555 extract (cl0, cl1, r, xr); 660 extract (cl0, cl1, r, xr);
556 extract (cl0, cl1, g, xg); 661 extract (cl0, cl1, g, xg);
557 extract (cl0, cl1, b, xb); 662 extract (cl0, cl1, b, xb);
563void 668void
564rxvt_img::brightness (int32_t r, int32_t g, int32_t b, int32_t a) 669rxvt_img::brightness (int32_t r, int32_t g, int32_t b, int32_t a)
565{ 670{
566 unshare (); 671 unshare ();
567 672
568 Display *dpy = s->display->dpy; 673 Display *dpy = s->dpy;
569 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); 674 Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0);
570 675
571 // loop should not be needed for brightness, as only -1..1 makes sense 676 // loop should not be needed for brightness, as only -1..1 makes sense
572 //while (r | g | b | a) 677 //while (r | g | b | a)
573 { 678 {
597rxvt_img::contrast (int32_t r, int32_t g, int32_t b, int32_t a) 702rxvt_img::contrast (int32_t r, int32_t g, int32_t b, int32_t a)
598{ 703{
599 if (r < 0 || g < 0 || b < 0 || a < 0) 704 if (r < 0 || g < 0 || b < 0 || a < 0)
600 rxvt_fatal ("rxvt_img::contrast does not support negative values.\n"); 705 rxvt_fatal ("rxvt_img::contrast does not support negative values.\n");
601 706
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) 707 // premultiply (yeah, these are not exact, sue me or fix it)
607 r = (r * (a >> 8)) >> 8; 708 r = (r * (a >> 8)) >> 8;
608 g = (g * (a >> 8)) >> 8; 709 g = (g * (a >> 8)) >> 8;
609 b = (b * (a >> 8)) >> 8; 710 b = (b * (a >> 8)) >> 8;
610 711
611 Display *dpy = s->display->dpy; 712 composer cc (this);
713 rxvt_img *img = cc;
714 img->fill (rgba (0, 0, 0, 0));
612 715
613 Picture src = picture (); 716 cc.mask (true);
614 Picture dst = XRenderCreatePicture (dpy, img->pm, format, 0, 0);
615 Picture mul = create_xrender_mask (dpy, pm, True, True);
616 717
617 //TODO: this operator does not yet implement some useful contrast 718 //TODO: this operator does not yet implement some useful contrast
618 while (r | g | b | a) 719 while (r | g | b | a)
619 { 720 {
620 unsigned short xr, xg, xb, xa; 721 unsigned short xr, xg, xb, xa;
621 XRenderColor mask_c; 722 XRenderColor mask_c;
622 723
623 if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha)) 724 if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha))
624 { 725 {
625 XRenderFillRectangle (dpy, PictOpSrc, mul, &mask_c, 0, 0, 1, 1); 726 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); 727 XRenderComposite (cc.dpy, PictOpAdd, cc.src, cc.msk, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
627 } 728 }
628 } 729 }
629
630 XRenderFreePicture (dpy, mul);
631 XRenderFreePicture (dpy, dst);
632 XRenderFreePicture (dpy, src);
633 730
634 ::swap (img->ref, ref); 731 ::swap (img->ref, ref);
635 ::swap (img->pm , pm ); 732 ::swap (img->pm , pm );
636 733
637 delete img; 734 delete img;
640void 737void
641rxvt_img::draw (rxvt_img *img, int op, nv mask) 738rxvt_img::draw (rxvt_img *img, int op, nv mask)
642{ 739{
643 unshare (); 740 unshare ();
644 741
645 Display *dpy = s->display->dpy; 742 composer cc (img, this);
646 Picture src = img->picture ();
647 Picture dst = picture ();
648 Picture mask_p = 0;
649 743
650 if (mask != 1.) 744 if (mask != 1.)
651 { 745 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 746
657 XRenderComposite (dpy, op, src, mask_p, dst, x - img->x, y - img->y, 0, 0, 0, 0, w, h); 747 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} 748}
665 749
666rxvt_img * 750rxvt_img *
667rxvt_img::clone () 751rxvt_img::clone ()
668{ 752{
672rxvt_img * 756rxvt_img *
673rxvt_img::reify () 757rxvt_img::reify ()
674{ 758{
675 if (x == 0 && y == 0 && w == ref->w && h == ref->h) 759 if (x == 0 && y == 0 && w == ref->w && h == ref->h)
676 return clone (); 760 return clone ();
677
678 Display *dpy = s->display->dpy;
679 761
680 // add an alpha channel if... 762 // add an alpha channel if...
681 bool alpha = !format->direct.alphaMask // pixmap has none yet 763 bool alpha = !format->direct.alphaMask // pixmap has none yet
682 && (x || y) // we need one because of non-zero offset 764 && (x || y) // we need one because of non-zero offset
683 && repeat == RepeatNone; // and we have no good pixels to fill with 765 && repeat == RepeatNone; // and we have no good pixels to fill with
684 766
685 rxvt_img *img = new rxvt_img (s, alpha ? find_alpha_format_for (dpy, format) : format, 0, 0, w, h, repeat); 767 composer cc (this, new rxvt_img (s, alpha ? find_alpha_format_for (s->dpy, format) : format,
686 img->alloc (); 768 0, 0, w, h, repeat));
687 769
688 Picture src = picture (); 770 if (repeat == RepeatNone)
689 Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0);
690
691 if (alpha)
692 { 771 {
693 XRenderColor rc = { 0, 0, 0, 0 }; 772 XRenderColor rc = { 0, 0, 0, 0 };
694 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h);//TODO: split into four fillrectangles 773 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); 774 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, 0, 0, 0, 0, x, y, ref->w, ref->h);
696 } 775 }
697 else 776 else
698 XRenderComposite (dpy, PictOpSrc, src, None, dst, -x, -y, 0, 0, 0, 0, w, h); 777 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, -x, -y, 0, 0, 0, 0, w, h);
699 778
700 XRenderFreePicture (dpy, src);
701 XRenderFreePicture (dpy, dst);
702
703 return img; 779 return cc;
704} 780}
705 781
706rxvt_img * 782rxvt_img *
707rxvt_img::sub_rect (int x, int y, int width, int height) 783rxvt_img::sub_rect (int x, int y, int width, int height)
708{ 784{
734rxvt_img::transform (const nv *matrix) 810rxvt_img::transform (const nv *matrix)
735{ 811{
736 mat3x3 m (matrix); 812 mat3x3 m (matrix);
737 813
738 // calculate new pixel bounding box coordinates 814 // calculate new pixel bounding box coordinates
739 nv r[2], rmin[2], rmax[2]; 815 nv rmin[2], rmax[2];
740 816
741 for (int i = 0; i < 2; ++i) 817 for (int i = 0; i < 2; ++i)
742 { 818 {
743 nv v; 819 nv v;
744 820
745 v = m.apply1 (i, 0+x, 0+y); rmin [i] = rmax [i] = v; r [i] = v; 821 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); 822 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); 823 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); 824 v = m.apply1 (i, w+x, h+y); min_it (rmin [i], v); max_it (rmax [i], v);
749 } 825 }
750 826
756 int ny = floor (rmin [1]); 832 int ny = floor (rmin [1]);
757 833
758 int new_width = ceil (rmax [0] - rmin [0]); 834 int new_width = ceil (rmax [0] - rmin [0]);
759 int new_height = ceil (rmax [1] - rmin [1]); 835 int new_height = ceil (rmax [1] - rmin [1]);
760 836
761 m = mat3x3::translate (-x, -y) * m * mat3x3::translate (x, y); 837 mat3x3 inv = (mat3x3::translate (-x, -y) * m * mat3x3::translate (x, y)).inverse ();
762 838
763 mat3x3 inv = m.invert (); 839 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 840
772 XTransform xfrm; 841 XTransform xfrm;
773 842
774 for (int i = 0; i < 3; ++i) 843 for (int i = 0; i < 3; ++i)
775 for (int j = 0; j < 3; ++j) 844 for (int j = 0; j < 3; ++j)
776 xfrm.matrix [i][j] = XDoubleToFixed (inv [i][j]); 845 xfrm.matrix [i][j] = XDoubleToFixed (inv [i][j]);
777 846
778 XRenderSetPictureFilter (dpy, src, "good", 0, 0); 847 XRenderSetPictureFilter (cc.dpy, cc.src, "good", 0, 0);
779 XRenderSetPictureTransform (dpy, src, &xfrm); 848 XRenderSetPictureTransform (cc.dpy, cc.src, &xfrm);
780 XRenderComposite (dpy, PictOpSrc, src, None, dst, sx, sy, 0, 0, 0, 0, new_width, new_height); 849 XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, sx, sy, 0, 0, 0, 0, new_width, new_height);
781 850
782 XRenderFreePicture (dpy, src);
783 XRenderFreePicture (dpy, dst);
784
785 return img; 851 return cc;
786} 852}
787 853
788rxvt_img * 854rxvt_img *
789rxvt_img::scale (int new_width, int new_height) 855rxvt_img::scale (int new_width, int new_height)
790{ 856{
803} 869}
804 870
805rxvt_img * 871rxvt_img *
806rxvt_img::rotate (int cx, int cy, nv phi) 872rxvt_img::rotate (int cx, int cy, nv phi)
807{ 873{
808#if 0
809 { c, -s, cx - c * cx + s * cy },
810 { s, c, cy - s * cx - c * cy },
811 { 0, 0, 1 }
812#endif
813
814 move (-cx, -cy); 874 move (-cx, -cy);
815 rxvt_img *img = transform (mat3x3::rotate (phi)); 875 rxvt_img *img = transform (mat3x3::rotate (phi));
816 move ( cx, cy); 876 move ( cx, cy);
817 img->move (cx, cy); 877 img->move (cx, cy);
818 878
823rxvt_img::convert_format (XRenderPictFormat *new_format, const rgba &bg) 883rxvt_img::convert_format (XRenderPictFormat *new_format, const rgba &bg)
824{ 884{
825 if (new_format == format) 885 if (new_format == format)
826 return clone (); 886 return clone ();
827 887
828 rxvt_img *img = new rxvt_img (s, new_format, x, y, w, h, repeat); 888 composer cc (this, new rxvt_img (s, new_format, x, y, w, h, repeat));
829 img->alloc ();
830 889
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; 890 int op = PictOpSrc;
835 891
836 if (format->direct.alphaMask && !new_format->direct.alphaMask) 892 if (format->direct.alphaMask && !new_format->direct.alphaMask)
837 { 893 {
838 // does it have to be that complicated 894 // does it have to be that complicated
839 XRenderColor rc = { bg.r, bg.g, bg.b, bg.a }; 895 XRenderColor rc = { bg.r, bg.g, bg.b, bg.a };
840 XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h); 896 XRenderFillRectangle (cc.dpy, PictOpSrc, cc.dst, &rc, 0, 0, w, h);
841 897
842 op = PictOpOver; 898 op = PictOpOver;
843 } 899 }
844 900
845 XRenderComposite (dpy, op, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); 901 XRenderComposite (cc.dpy, op, cc.src, None, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
846 902
847 XRenderFreePicture (dpy, src); 903 return cc;
848 XRenderFreePicture (dpy, dst); 904}
905
906rxvt_img *
907rxvt_img::tint (const rgba &c)
908{
909 composer cc (this);
910 cc.mask (true);
911 cc.fill (c);
912
913 XRenderComposite (cc.dpy, PictOpSrc, cc.src, cc.msk, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
914
915 return cc;
916}
917
918rxvt_img *
919rxvt_img::shade (nv factor, rgba c)
920{
921 clamp_it (factor, -1., 1.);
922 factor++;
923
924 if (factor > 1)
925 {
926 c.r = c.r * (2 - factor);
927 c.g = c.g * (2 - factor);
928 c.b = c.b * (2 - factor);
929 }
930 else
931 {
932 c.r = c.r * factor;
933 c.g = c.g * factor;
934 c.b = c.b * factor;
935 }
936
937 rxvt_img *img = this->tint (c);
938
939 if (factor > 1)
940 {
941 c.a = 0xffff;
942 c.r =
943 c.g =
944 c.b = 0xffff * (factor - 1);
945
946 img->brightness (c.r, c.g, c.b, c.a);
947 }
849 948
850 return img; 949 return img;
851} 950}
852 951
853rxvt_img * 952rxvt_img *
854rxvt_img::blend (rxvt_img *img, nv factor) 953rxvt_img::filter (const char *name, int nparams, nv *params)
855{ 954{
856 rxvt_img *img2 = clone (); 955 composer cc (this);
857 Display *dpy = s->display->dpy;
858 Picture src = img->picture ();
859 Picture dst = XRenderCreatePicture (dpy, img2->pm, img2->format, 0, 0);
860 Picture mask = create_xrender_mask (dpy, img->pm, False, False);
861 956
862 XRenderColor mask_c; 957 XFixed *xparams = rxvt_temp_buf<XFixed> (nparams);
863 958
864 mask_c.alpha = float_to_component (factor); 959 for (int i = 0; i < nparams; ++i)
865 mask_c.red = 960 xparams [i] = XDoubleToFixed (params [i]);
866 mask_c.green =
867 mask_c.blue = 0;
868 XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1);
869 961
962 XRenderSetPictureFilter (cc.dpy, cc.src, name, xparams, nparams);
963
870 XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, w, h); 964 XRenderComposite (cc.dpy, PictOpSrc, cc.src, 0, cc.dst, 0, 0, 0, 0, 0, 0, w, h);
871 965
872 XRenderFreePicture (dpy, src);
873 XRenderFreePicture (dpy, dst);
874 XRenderFreePicture (dpy, mask);
875
876 return img2; 966 return cc;
877} 967}
878 968
879#endif 969#endif
880 970

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines