… | |
… | |
170 | src = srcimg->picture (); |
170 | src = srcimg->picture (); |
171 | dst = this->dstimg->picture (); |
171 | dst = this->dstimg->picture (); |
172 | } |
172 | } |
173 | |
173 | |
174 | ecb_noinline |
174 | ecb_noinline |
175 | void mask (bool rgb = true, int x = 1, int y = 1) |
175 | void mask (bool rgb = true, int w = 1, int h = 1) |
176 | { |
176 | { |
177 | Pixmap pixmap = XCreatePixmap (dpy, srcimg->pm, x, y, rgb ? 32 : 8); |
177 | Pixmap pixmap = XCreatePixmap (dpy, srcimg->pm, w, h, rgb ? 32 : 8); |
178 | |
178 | |
179 | XRenderPictFormat *format = XRenderFindStandardFormat (dpy, rgb ? PictStandardARGB32 : PictStandardA8); |
179 | XRenderPictFormat *format = XRenderFindStandardFormat (dpy, rgb ? PictStandardARGB32 : PictStandardA8); |
180 | XRenderPictureAttributes pa; |
180 | XRenderPictureAttributes pa; |
181 | pa.repeat = RepeatNormal; |
181 | pa.repeat = RepeatNormal; |
182 | pa.component_alpha = rgb; |
182 | pa.component_alpha = rgb; |
… | |
… | |
594 | XRenderFreePicture (dpy, tmp); |
594 | XRenderFreePicture (dpy, tmp); |
595 | |
595 | |
596 | return img; |
596 | return img; |
597 | } |
597 | } |
598 | |
598 | |
|
|
599 | rxvt_img * |
|
|
600 | rxvt_img::muladd (nv mul, nv add) |
|
|
601 | { |
|
|
602 | // STEP 1: double the image width, fill all odd columns with white (==1) |
|
|
603 | |
|
|
604 | composer cc (this, new rxvt_img (s, format, 0, 0, w * 2, h, repeat)); |
|
|
605 | |
|
|
606 | // why the hell does XRenderSetPictureTransform want a writable matrix :( |
|
|
607 | // that keeps us from just static const'ing this matrix. |
|
|
608 | XTransform h_double = { |
|
|
609 | 32768, 0, 0, |
|
|
610 | 0, 65536, 0, |
|
|
611 | 0, 0, 65536 |
|
|
612 | }; |
|
|
613 | |
|
|
614 | XRenderSetPictureFilter (cc.dpy, cc.src, "nearest", 0, 0); |
|
|
615 | XRenderSetPictureTransform (cc.dpy, cc.src, &h_double); |
|
|
616 | XRenderComposite (cc.dpy, PictOpSrc, cc.src, None, cc.dst, 0, 0, 0, 0, 0, 0, w * 2, h); |
|
|
617 | |
|
|
618 | cc.mask (false, 2, 1); |
|
|
619 | |
|
|
620 | static const XRenderColor c0 = { 0, 0, 0, 0 }; |
|
|
621 | XRenderFillRectangle (cc.dpy, PictOpSrc, cc.msk, &c0, 0, 0, 1, 1); |
|
|
622 | static const XRenderColor c1 = { 65535, 65535, 65535, 65535 }; |
|
|
623 | XRenderFillRectangle (cc.dpy, PictOpSrc, cc.msk, &c1, 1, 0, 1, 1); |
|
|
624 | |
|
|
625 | Picture white = XRenderCreateSolidFill (cc.dpy, &c1); |
|
|
626 | |
|
|
627 | XRenderComposite (cc.dpy, PictOpOver, white, cc.msk, cc.dst, 0, 0, 0, 0, 0, 0, w * 2, h); |
|
|
628 | |
|
|
629 | XRenderFreePicture (cc.dpy, white); |
|
|
630 | |
|
|
631 | // STEP 2: convolve the image with a 3x1 filter |
|
|
632 | // a 2x1 filter would obviously suffice, but given the total lack of specification |
|
|
633 | // for xrender, I expect different xrender implementations to randomly diverge. |
|
|
634 | // we also halve the image, and hope for the best (again, for lack of specs). |
|
|
635 | composer cc2 (cc.dstimg); |
|
|
636 | |
|
|
637 | XFixed kernel [] = { |
|
|
638 | XDoubleToFixed (3), XDoubleToFixed (1), |
|
|
639 | XDoubleToFixed (0), XDoubleToFixed (mul), XDoubleToFixed (add) |
|
|
640 | }; |
|
|
641 | |
|
|
642 | XTransform h_halve = { |
|
|
643 | 131072, 0, 0, |
|
|
644 | 0, 65536, 0, |
|
|
645 | 0, 0, 65536 |
|
|
646 | }; |
|
|
647 | |
|
|
648 | XRenderSetPictureFilter (cc.dpy, cc2.src, "nearest", 0, 0); |
|
|
649 | XRenderSetPictureTransform (cc.dpy, cc2.src, &h_halve); |
|
|
650 | XRenderSetPictureFilter (cc.dpy, cc2.src, FilterConvolution, kernel, ecb_array_length (kernel)); |
|
|
651 | |
|
|
652 | XRenderComposite (cc.dpy, PictOpSrc, cc2.src, None, cc2.dst, 0, 0, 0, 0, 0, 0, w * 2, h); |
|
|
653 | |
|
|
654 | return cc2; |
|
|
655 | } |
|
|
656 | |
599 | ecb_noinline static void |
657 | ecb_noinline static void |
600 | extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc) |
658 | extract (int32_t cl0, int32_t cl1, int32_t &c, unsigned short &xc) |
601 | { |
659 | { |
602 | int32_t x = clamp (c, cl0, cl1); |
660 | int32_t x = clamp (c, cl0, cl1); |
603 | c -= x; |
661 | c -= x; |