--- rxvt-unicode/src/rxvtimg.C 2012/06/12 18:25:57 1.80 +++ 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 () { @@ -560,12 +578,12 @@ int oy = mat_apply (matrix, 1, x, y); // calculate new pixel bounding box coordinates - double rmin[2], rmax[2]; + double d [2], rmin[2], rmax[2]; for (int i = 0; i < 2; ++i) { double v; - v = mat_apply (matrix, i, 0, 0); rmin [i] = rmax [i] = v; + v = mat_apply (matrix, i, 0, 0); rmin [i] = rmax [i] = v; d [i] = v; v = mat_apply (matrix, i, w, 0); min_it (rmin [i], v); max_it (rmax [i], v); v = mat_apply (matrix, i, 0, h); min_it (rmin [i], v); max_it (rmax [i], v); v = mat_apply (matrix, i, w, h); min_it (rmin [i], v); max_it (rmax [i], v); @@ -580,7 +598,7 @@ double inv[3][3]; mat_invert (matrix, inv); - rxvt_img *img = new rxvt_img (s, format, ox - dx, oy - dy, new_width, new_height, repeat); + rxvt_img *img = new rxvt_img (s, format, ox - dx - d [0], oy - dy - d [1], new_width, new_height, repeat); img->alloc (); Display *dpy = s->display->dpy; @@ -633,24 +651,24 @@ double c = cos (phi); double matrix[3][3] = { - //{ c, -s, cx - c * cx + s * cy }, - //{ s, c, cy - s * cx - c * cy }, - //{ 0, 0, 1 } - { c, -s, 0 }, - { s, c, 0 }, - { 0, 0, 1 } + { c, -s, cx - c * cx + s * cy }, + { s, c, cy - s * cx - c * cy }, + { 0, 0, 1 } + //{ c, -s, 0 }, + //{ s, c, 0 }, + //{ 0, 0, 1 } }; - move (-cx, -cy); + //move (-cx, -cy); rxvt_img *img = transform (matrix); - move ( cx, cy); - img->move (cx, cy); + //move ( cx, cy); + //img->move (cx, cy); return img; } 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;