--- rxvt-unicode/src/background.C 2012/04/12 10:22:50 1.206 +++ rxvt-unicode/src/background.C 2012/05/11 12:21:22 1.209 @@ -5,7 +5,7 @@ * All portions of code are copyright by their respective author/s. * Copyright (c) 2005-2008 Marc Lehmann * Copyright (c) 2007 Sasha Vasko - * Copyright (c) 2010 Emanuele Giaquinta + * Copyright (c) 2010-2012 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -350,8 +350,9 @@ XImage *ximage; char *data, *line; int bytes_per_pixel; - int width_r, width_g, width_b; - int sh_r, sh_g, sh_b; + int width_r, width_g, width_b, width_a; + int sh_r, sh_g, sh_b, sh_a; + uint32_t alpha_mask; int rowstride; int channels; unsigned char *row; @@ -359,6 +360,14 @@ if (visual->c_class != TrueColor) return false; +#if XRENDER + XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); + if (format) + alpha_mask = (uint32_t)format->direct.alphaMask << format->direct.alpha; + else +#endif + alpha_mask = 0; + if (depth == 24 || depth == 32) bytes_per_pixel = 4; else if (depth == 15 || depth == 16) @@ -369,13 +378,15 @@ width_r = ecb_popcount32 (visual->red_mask); width_g = ecb_popcount32 (visual->green_mask); width_b = ecb_popcount32 (visual->blue_mask); + width_a = ecb_popcount32 (alpha_mask); - if (width_r > 8 || width_g > 8 || width_b > 8) + if (width_r > 8 || width_g > 8 || width_b > 8 || width_a > 8) return false; sh_r = ecb_ctz32 (visual->red_mask); sh_g = ecb_ctz32 (visual->green_mask); sh_b = ecb_ctz32 (visual->blue_mask); + sh_a = ecb_ctz32 (alpha_mask); if (width > INT_MAX / height / bytes_per_pixel) return false; @@ -399,16 +410,43 @@ row = gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * channels; line = data; + rgba c (0, 0, 0); + + if (channels == 4 && alpha_mask == 0) + { + pix_colors[Color_bg].get (c); + c.r >>= 8; + c.g >>= 8; + c.b >>= 8; + } + for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { unsigned char *pixel = row + x * channels; uint32_t value; + unsigned char r, g, b, a; - value = ((pixel[0] >> (8 - width_r)) << sh_r) - | ((pixel[1] >> (8 - width_g)) << sh_g) - | ((pixel[2] >> (8 - width_b)) << sh_b); + if (channels == 4) + { + a = pixel[3]; + r = (pixel[0] * a + c.r * (0xff - a)) / 0xff; + g = (pixel[1] * a + c.g * (0xff - a)) / 0xff; + b = (pixel[2] * a + c.b * (0xff - a)) / 0xff; + } + else + { + a = 0xff; + r = pixel[0]; + g = pixel[1]; + b = pixel[2]; + } + + value = ((r >> (8 - width_r)) << sh_r) + | ((g >> (8 - width_g)) << sh_g) + | ((b >> (8 - width_b)) << sh_b) + | ((a >> (8 - width_a)) << sh_a); if (bytes_per_pixel == 4) ((uint32_t *)line)[x] = value; @@ -1146,6 +1184,7 @@ void rxvt_term::tint_ximage (Visual *visual, XImage *ximage) { + unsigned int size_r, size_g, size_b; int sh_r, sh_g, sh_b; uint32_t mask_r, mask_g, mask_b; uint32_t *lookup, *lookup_r, *lookup_g, *lookup_b; @@ -1160,63 +1199,21 @@ mask_b = visual->blue_mask; /* boring lookup table pre-initialization */ - switch (ximage->depth) - { - case 15: - if ((mask_r != 0x7c00) || - (mask_g != 0x03e0) || - (mask_b != 0x001f)) - return; - lookup = (uint32_t *) malloc (sizeof (uint32_t)*(32+32+32)); - lookup_r = lookup; - lookup_g = lookup+32; - lookup_b = lookup+32+32; - sh_r = 10; - sh_g = 5; - sh_b = 0; - break; - case 16: - if ((mask_r != 0xf800) || - (mask_g != 0x07e0) || - (mask_b != 0x001f)) - return; - lookup = (uint32_t *) malloc (sizeof (uint32_t)*(32+64+32)); - lookup_r = lookup; - lookup_g = lookup+32; - lookup_b = lookup+32+64; - sh_r = 11; - sh_g = 5; - sh_b = 0; - break; - case 24: - if ((mask_r != 0xff0000) || - (mask_g != 0x00ff00) || - (mask_b != 0x0000ff)) - return; - lookup = (uint32_t *) malloc (sizeof (uint32_t)*(256+256+256)); - lookup_r = lookup; - lookup_g = lookup+256; - lookup_b = lookup+256+256; - sh_r = 16; - sh_g = 8; - sh_b = 0; - break; - case 32: - if ((mask_r != 0xff0000) || - (mask_g != 0x00ff00) || - (mask_b != 0x0000ff)) - return; - lookup = (uint32_t *) malloc (sizeof (uint32_t)*(256+256+256)); - lookup_r = lookup; - lookup_g = lookup+256; - lookup_b = lookup+256+256; - sh_r = 16; - sh_g = 8; - sh_b = 0; - break; - default: - return; /* we do not support this color depth */ - } + sh_r = ecb_ctz32 (mask_r); + sh_g = ecb_ctz32 (mask_g); + sh_b = ecb_ctz32 (mask_b); + + size_r = mask_r >> sh_r; + size_g = mask_g >> sh_g; + size_b = mask_b >> sh_b; + + if (size_r++ > 255 || size_g++ > 255 || size_b++ > 255) + return; + + lookup = (uint32_t *)malloc (sizeof (uint32_t) * (size_r + size_g + size_b)); + lookup_r = lookup; + lookup_g = lookup + size_r; + lookup_b = lookup + size_r + size_g; rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); @@ -1248,25 +1245,21 @@ /* apply table to input image (replacing colors by newly calculated ones) */ if (ximage->bits_per_pixel == 32 - && (ximage->depth == 24 || ximage->depth == 32) && ximage->byte_order == host_byte_order) { - uint32_t *p1, *pf, *p, *pl; - p1 = (uint32_t *) ximage->data; - pf = (uint32_t *) (ximage->data + ximage->height * ximage->bytes_per_line); + char *line = ximage->data; - while (p1 < pf) + for (int y = 0; y < ximage->height; y++) { - p = p1; - pl = p1 + ximage->width; - for (; p < pl; p++) + uint32_t *p = (uint32_t *)line; + for (int x = 0; x < ximage->width; x++) { - *p = lookup_r[(*p & 0xff0000) >> 16] | - lookup_g[(*p & 0x00ff00) >> 8] | - lookup_b[(*p & 0x0000ff)] | - (*p & 0xff000000); + *p = lookup_r[(*p & mask_r) >> sh_r] | + lookup_g[(*p & mask_g) >> sh_g] | + lookup_b[(*p & mask_b) >> sh_b]; + p++; } - p1 = (uint32_t *) ((char *) p1 + ximage->bytes_per_line); + line += ximage->bytes_per_line; } } else