--- rxvt-unicode/src/rxvtimg.C 2012/06/12 19:00:57 1.81 +++ rxvt-unicode/src/rxvtimg.C 2012/06/14 18:06:15 1.83 @@ -4,6 +4,26 @@ #if HAVE_IMG +static XRenderPictFormat * +find_alpha_format_for (Display *dpy, XRenderPictFormat *format) +{ + if (format->direct.alphaMask) + return format; // already has alpha + + // try to find a suitable alpha format, one bit alpha is enough for our purposes + if (format->type == PictTypeDirect) + for (int n = 0; XRenderPictFormat *f = XRenderFindFormat (dpy, 0, 0, n); ++n) + if (f->direct.alphaMask + && f->type == PictTypeDirect + && ecb_popcount32 (f->direct.redMask ) >= ecb_popcount32 (format->direct.redMask ) + && ecb_popcount32 (f->direct.greenMask) >= ecb_popcount32 (format->direct.greenMask) + && ecb_popcount32 (f->direct.blueMask ) >= ecb_popcount32 (format->direct.blueMask )) + return f; + + // should be a very good fallback + return XRenderFindStandardFormat (dpy, PictStandardARGB32); +} + rxvt_img::rxvt_img (rxvt_screen *screen, XRenderPictFormat *format, int x, int y, int width, int height, int repeat) : s(screen), x(x), y(y), w(width), h(height), format(format), repeat(repeat), pm(0), ref(0) @@ -226,11 +246,9 @@ } void -rxvt_img::fill (const rxvt_color &c) +rxvt_img::fill (const rgba &c) { - rgba cc; - c.get (cc); - XRenderColor rc = { cc.r, cc.g, cc.b, cc.a }; + XRenderColor rc = { c.r, c.g, c.b, c.a }; Display *dpy = s->display->dpy; Picture src = src_picture (); @@ -238,6 +256,31 @@ XRenderFreePicture (dpy, src); } +void +rxvt_img::add_alpha () +{ + if (format->direct.alphaMask) + return; + + Display *dpy = s->display->dpy; + + rxvt_img *img = new rxvt_img (s, find_alpha_format_for (dpy, format), x, y, w, h, repeat); + img->alloc (); + + Picture src = src_picture (); + Picture dst = XRenderCreatePicture (dpy, img->pm, img->format, 0, 0); + + XRenderComposite (dpy, PictOpSrc, src, None, dst, 0, 0, 0, 0, 0, 0, w, h); + + XRenderFreePicture (dpy, src); + XRenderFreePicture (dpy, dst); + + ::swap (img->ref, ref); + ::swap (img->pm , pm ); + + delete img; +} + static void get_gaussian_kernel (int radius, int width, double *kernel, XFixed *params) { @@ -399,12 +442,7 @@ rxvt_img *img = new rxvt_img (s, format, x, y, w, h, repeat); img->alloc (); - - { - rxvt_color empty; - empty.set (s, rgba (0, 0, 0, 0)); - img->fill (empty); - } + img->fill (rgba (0, 0, 0, 0)); // premultiply (yeah, these are not exact, sue me or fix it) r = (r * (a >> 8)) >> 8; @@ -446,26 +484,6 @@ return new rxvt_img (*this); } -static XRenderPictFormat * -find_alpha_format_for (Display *dpy, XRenderPictFormat *format) -{ - if (format->direct.alphaMask) - return format; // already has alpha - - // try to find a suitable alpha format, one bit alpha is enough for our purposes - if (format->type == PictTypeDirect) - for (int n = 0; XRenderPictFormat *f = XRenderFindFormat (dpy, 0, 0, n); ++n) - if (f->direct.alphaMask - && f->type == PictTypeDirect - && ecb_popcount32 (f->direct.redMask ) >= ecb_popcount32 (format->direct.redMask ) - && ecb_popcount32 (f->direct.greenMask) >= ecb_popcount32 (format->direct.greenMask) - && ecb_popcount32 (f->direct.blueMask ) >= ecb_popcount32 (format->direct.blueMask )) - return f; - - // should be a very good fallback - return XRenderFindStandardFormat (dpy, PictStandardARGB32); -} - rxvt_img * rxvt_img::reify () { @@ -650,7 +668,7 @@ } rxvt_img * -rxvt_img::convert_format (XRenderPictFormat *new_format, const rxvt_color &bg) +rxvt_img::convert_format (XRenderPictFormat *new_format, const rgba &bg) { if (new_format == format) return clone (); @@ -666,10 +684,7 @@ if (format->direct.alphaMask && !new_format->direct.alphaMask) { // does it have to be that complicated - rgba c; - bg.get (c); - - XRenderColor rc = { c.r, c.g, c.b, 0xffff }; + XRenderColor rc = { bg.r, bg.g, bg.b, bg.a }; XRenderFillRectangle (dpy, PictOpSrc, dst, &rc, 0, 0, w, h); op = PictOpOver;