… | |
… | |
402 | { |
402 | { |
403 | GError *err = 0; |
403 | GError *err = 0; |
404 | GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err); |
404 | GdkPixbuf *pb = gdk_pixbuf_new_from_file (filename, &err); |
405 | |
405 | |
406 | if (!pb) |
406 | if (!pb) |
|
|
407 | try |
|
|
408 | { |
407 | rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message); |
409 | rxvt_fatal ("rxvt_img::new_from_file: %s\n", err->message); |
|
|
410 | } |
|
|
411 | catch (...) |
|
|
412 | { |
|
|
413 | g_error_free (err); |
|
|
414 | throw; |
|
|
415 | } |
408 | |
416 | |
409 | rxvt_img *img = new_from_pixbuf (s, pb); |
417 | rxvt_img *img = new_from_pixbuf (s, pb); |
410 | |
418 | |
411 | g_object_unref (pb); |
419 | g_object_unref (pb); |
412 | |
420 | |
… | |
… | |
598 | rxvt_img * |
606 | rxvt_img * |
599 | rxvt_img::muladd (nv mul, nv add) |
607 | rxvt_img::muladd (nv mul, nv add) |
600 | { |
608 | { |
601 | // STEP 1: double the image width, fill all odd columns with white (==1) |
609 | // STEP 1: double the image width, fill all odd columns with white (==1) |
602 | |
610 | |
603 | composer cc (this, new rxvt_img (d, format, 0, 0, w * 2, h, repeat)); |
611 | rxvt_img *img = new rxvt_img (d, format, 0, 0, w * 2, h, repeat); |
|
|
612 | composer cc (this, img); |
604 | |
613 | |
605 | // why the hell does XRenderSetPictureTransform want a writable matrix :( |
614 | // why the hell does XRenderSetPictureTransform want a writable matrix :( |
606 | // that keeps us from just static const'ing this matrix. |
615 | // that keeps us from just static const'ing this matrix. |
607 | XTransform h_double = { |
616 | XTransform h_double = { |
608 | 0x08000, 0, 0, |
617 | 0x08000, 0, 0, |
… | |
… | |
629 | |
638 | |
630 | // STEP 2: convolve the image with a 3x1 filter |
639 | // STEP 2: convolve the image with a 3x1 filter |
631 | // a 2x1 filter would obviously suffice, but given the total lack of specification |
640 | // a 2x1 filter would obviously suffice, but given the total lack of specification |
632 | // for xrender, I expect different xrender implementations to randomly diverge. |
641 | // for xrender, I expect different xrender implementations to randomly diverge. |
633 | // we also halve the image, and hope for the best (again, for lack of specs). |
642 | // we also halve the image, and hope for the best (again, for lack of specs). |
634 | composer cc2 (cc.dstimg); |
643 | composer cc2 (img); |
635 | |
644 | |
636 | XFixed kernel [] = { |
645 | XFixed kernel [] = { |
637 | XDoubleToFixed (3), XDoubleToFixed (1), |
646 | XDoubleToFixed (3), XDoubleToFixed (1), |
638 | XDoubleToFixed (0), XDoubleToFixed (mul), XDoubleToFixed (add) |
647 | XDoubleToFixed (0), XDoubleToFixed (mul), XDoubleToFixed (add) |
639 | }; |
648 | }; |
… | |
… | |
648 | XRenderSetPictureTransform (cc.dpy, cc2.src, &h_halve); |
657 | XRenderSetPictureTransform (cc.dpy, cc2.src, &h_halve); |
649 | XRenderSetPictureFilter (cc.dpy, cc2.src, FilterConvolution, kernel, ecb_array_length (kernel)); |
658 | XRenderSetPictureFilter (cc.dpy, cc2.src, FilterConvolution, kernel, ecb_array_length (kernel)); |
650 | |
659 | |
651 | XRenderComposite (cc.dpy, PictOpSrc, cc2.src, None, cc2.dst, 0, 0, 0, 0, 0, 0, w * 2, h); |
660 | XRenderComposite (cc.dpy, PictOpSrc, cc2.src, None, cc2.dst, 0, 0, 0, 0, 0, 0, w * 2, h); |
652 | |
661 | |
|
|
662 | delete img; |
|
|
663 | |
653 | return cc2; |
664 | return cc2; |
654 | } |
665 | } |
655 | |
666 | |
656 | ecb_noinline static void |
667 | ecb_noinline static void |
657 | extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc) |
668 | extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc) |
… | |
… | |
681 | Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); |
692 | Picture dst = XRenderCreatePicture (dpy, pm, format, 0, 0); |
682 | |
693 | |
683 | // loop should not be needed for brightness, as only -1..1 makes sense |
694 | // loop should not be needed for brightness, as only -1..1 makes sense |
684 | //while (r | g | b | a) |
695 | //while (r | g | b | a) |
685 | { |
696 | { |
686 | unsigned short xr, xg, xb, xa; |
|
|
687 | XRenderColor mask_c; |
697 | XRenderColor mask_c; |
688 | |
698 | |
689 | if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha)) |
699 | if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha)) |
690 | XRenderFillRectangle (dpy, PictOpAdd, dst, &mask_c, 0, 0, w, h); |
700 | XRenderFillRectangle (dpy, PictOpAdd, dst, &mask_c, 0, 0, w, h); |
691 | |
701 | |
… | |
… | |
723 | cc.mask (true); |
733 | cc.mask (true); |
724 | |
734 | |
725 | //TODO: this operator does not yet implement some useful contrast |
735 | //TODO: this operator does not yet implement some useful contrast |
726 | while (r | g | b | a) |
736 | while (r | g | b | a) |
727 | { |
737 | { |
728 | unsigned short xr, xg, xb, xa; |
|
|
729 | XRenderColor mask_c; |
738 | XRenderColor mask_c; |
730 | |
739 | |
731 | if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha)) |
740 | if (extract (0, 65535, r, g, b, a, mask_c.red, mask_c.green, mask_c.blue, mask_c.alpha)) |
732 | { |
741 | { |
733 | XRenderFillRectangle (cc.dpy, PictOpSrc, cc.msk, &mask_c, 0, 0, 1, 1); |
742 | XRenderFillRectangle (cc.dpy, PictOpSrc, cc.msk, &mask_c, 0, 0, 1, 1); |