From c068c2122df3015c23dace66b58d8b841234716e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 3 Jul 2014 19:44:24 +0200 Subject: [PATCH] gradient: Support alpha values in colors Designers got used to RGBA support in GTK+, so the colors we pick up from there might well have an alpha channel; update our gradient rendering to support this - eventually we should probably port that code to cairo ... --- src/ui/gradient.c | 76 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/ui/gradient.c b/src/ui/gradient.c index b62d54846..eb738084b 100644 --- a/src/ui/gradient.c +++ b/src/ui/gradient.c @@ -74,14 +74,14 @@ blank_pixbuf (int width, int height) g_return_val_if_fail (height > 0, NULL); /* Always align rows to 32-bit boundaries */ - rowstride = 4 * ((3 * width + 3) / 4); + rowstride = 4 * ((4 * width + 4) / 4); buf = g_try_malloc (height * rowstride); if (!buf) return NULL; return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, - FALSE, 8, + TRUE, 8, width, height, rowstride, free_buffer, NULL); } @@ -193,8 +193,8 @@ meta_gradient_create_interwoven (int width, { int i, j, k, l, ll; - long r1, g1, b1, dr1, dg1, db1; - long r2, g2, b2, dr2, dg2, db2; + long r1, g1, b1, a1, dr1, dg1, db1, da1; + long r2, g2, b2, a2, dr2, dg2, db2, da2; GdkPixbuf *pixbuf; unsigned char *ptr; unsigned char *pixels; @@ -210,18 +210,22 @@ meta_gradient_create_interwoven (int width, r1 = (long)(colors1[0].red*0xffffff); g1 = (long)(colors1[0].green*0xffffff); b1 = (long)(colors1[0].blue*0xffffff); + a1 = (long)(colors1[0].alpha*0xffffff); r2 = (long)(colors2[0].red*0xffffff); g2 = (long)(colors2[0].green*0xffffff); b2 = (long)(colors2[0].blue*0xffffff); + a2 = (long)(colors2[0].alpha*0xffffff); dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height; dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height; db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height; + da1 = ((colors1[1].alpha-colors1[0].alpha)*0xffffff)/(int)height; dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height; dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height; db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height; + db2 = ((colors2[1].alpha-colors2[0].alpha)*0xffffff)/(int)height; for (i=0,k=0,l=0,ll=thickness1; i>16); ptr[1] = (unsigned char) (g1>>16); ptr[2] = (unsigned char) (b1>>16); + ptr[3] = (unsigned char) (a1>>16); } else { ptr[0] = (unsigned char) (r2>>16); ptr[1] = (unsigned char) (g2>>16); ptr[2] = (unsigned char) (b2>>16); + ptr[3] = (unsigned char) (a2>>16); } for (j=1; j <= width/2; j *= 2) - memcpy (&(ptr[j*3]), ptr, j*3); - memcpy (&(ptr[j*3]), ptr, (width - j)*3); + memcpy (&(ptr[j*4]), ptr, j*4); + memcpy (&(ptr[j*4]), ptr, (width - j)*4); if (++l == ll) { @@ -261,10 +267,12 @@ meta_gradient_create_interwoven (int width, r1+=dr1; g1+=dg1; b1+=db1; + a1+=da1; r2+=dr2; g2+=dg2; b2+=db2; + a2+=da2; } return pixbuf; @@ -289,12 +297,12 @@ meta_gradient_create_horizontal (int width, int height, const GdkRGBA *to) { int i; - long r, g, b, dr, dg, db; + long r, g, b, a, dr, dg, db, da; GdkPixbuf *pixbuf; unsigned char *ptr; unsigned char *pixels; - int r0, g0, b0; - int rf, gf, bf; + int r0, g0, b0, a0; + int rf, gf, bf, af; int rowstride; pixbuf = blank_pixbuf (width, height); @@ -308,26 +316,32 @@ meta_gradient_create_horizontal (int width, int height, r0 = (guchar) (from->red * 0xff); g0 = (guchar) (from->green * 0xff); b0 = (guchar) (from->blue * 0xff); + a0 = (guchar) (from->alpha * 0xff); rf = (guchar) (to->red * 0xff); gf = (guchar) (to->green * 0xff); bf = (guchar) (to->blue * 0xff); + af = (guchar) (to->alpha * 0xff); r = r0 << 16; g = g0 << 16; b = b0 << 16; + a = a0 << 16; dr = ((rf-r0)<<16)/(int)width; dg = ((gf-g0)<<16)/(int)width; db = ((bf-b0)<<16)/(int)width; + da = ((af-a0)<<16)/(int)width; /* render the first line */ for (i=0; i>16); *(ptr++) = (unsigned char)(g>>16); *(ptr++) = (unsigned char)(b>>16); + *(ptr++) = (unsigned char)(a>>16); r += dr; g += dg; b += db; + a += da; } /* copy the first line to the other lines */ @@ -357,11 +371,11 @@ meta_gradient_create_vertical (int width, int height, const GdkRGBA *to) { int i, j; - long r, g, b, dr, dg, db; + long r, g, b, a, dr, dg, db, da; GdkPixbuf *pixbuf; unsigned char *ptr; - int r0, g0, b0; - int rf, gf, bf; + int r0, g0, b0, a0; + int rf, gf, bf, af; int rowstride; unsigned char *pixels; @@ -375,17 +389,21 @@ meta_gradient_create_vertical (int width, int height, r0 = (guchar) (from->red * 0xff); g0 = (guchar) (from->green * 0xff); b0 = (guchar) (from->blue * 0xff); + a0 = (guchar) (from->alpha * 0xff); rf = (guchar) (to->red * 0xff); gf = (guchar) (to->green * 0xff); bf = (guchar) (to->blue * 0xff); + af = (guchar) (to->alpha * 0xff); r = r0<<16; g = g0<<16; b = b0<<16; + a = a0<<16; dr = ((rf-r0)<<16)/(int)height; dg = ((gf-g0)<<16)/(int)height; db = ((bf-b0)<<16)/(int)height; + da = ((af-a0)<<16)/(int)height; for (i=0; i>16); ptr[1] = (unsigned char)(g>>16); ptr[2] = (unsigned char)(b>>16); + ptr[3] = (unsigned char)(a>>16); for (j=1; j <= width/2; j *= 2) - memcpy (&(ptr[j*3]), ptr, j*3); - memcpy (&(ptr[j*3]), ptr, (width - j)*3); + memcpy (&(ptr[j*4]), ptr, j*4); + memcpy (&(ptr[j*4]), ptr, (width - j)*4); r+=dr; g+=dg; b+=db; + a+=da; } return pixbuf; } @@ -456,12 +476,12 @@ meta_gradient_create_diagonal (int width, int height, ptr = gdk_pixbuf_get_pixels (tmp); a = ((float)(width - 1))/((float)(height - 1)); - width = width * 3; + width = width * 4; /* copy the first line to the other lines with corresponding offset */ for (j=0, offset=0.0; j>16); *ptr++ = (unsigned char)(g>>16); *ptr++ = (unsigned char)(b>>16); + *ptr++ = (unsigned char)(a>>16); r += dr; g += dg; b += db; + a += da; k++; } r = (long)(colors[i].red * 0xffffff); g = (long)(colors[i].green * 0xffffff); b = (long)(colors[i].blue * 0xffffff); + a = (long)(colors[i].alpha * 0xffffff); } for (j=k; j>16); *ptr++ = (unsigned char)(g>>16); *ptr++ = (unsigned char)(b>>16); + *ptr++ = (unsigned char)(a>>16); } /* copy the first line to the other lines */ @@ -548,7 +574,7 @@ meta_gradient_create_multi_vertical (int width, int height, int count) { int i, j, k; - long r, g, b, dr, dg, db; + long r, g, b, a, dr, dg, db, da; GdkPixbuf *pixbuf; unsigned char *ptr, *tmp, *pixels; int height2; @@ -578,33 +604,38 @@ meta_gradient_create_multi_vertical (int width, int height, r = (long)(colors[0].red * 0xffffff); g = (long)(colors[0].green * 0xffffff); b = (long)(colors[0].blue * 0xffffff); + a = (long)(colors[0].alpha * 0xffffff); for (i=1; i>16); ptr[1] = (unsigned char)(g>>16); ptr[2] = (unsigned char)(b>>16); + ptr[3] = (unsigned char)(a>>16); for (x=1; x <= width/2; x *= 2) - memcpy (&(ptr[x*3]), ptr, x*3); - memcpy (&(ptr[x*3]), ptr, (width - x)*3); + memcpy (&(ptr[x*4]), ptr, x*4); + memcpy (&(ptr[x*4]), ptr, (width - x)*4); ptr += rowstride; r += dr; g += dg; b += db; + a += da; k++; } r = (long)(colors[i].red * 0xffffff); g = (long)(colors[i].green * 0xffffff); b = (long)(colors[i].blue * 0xffffff); + a = (long)(colors[i].alpha * 0xffffff); } if (k>16); ptr[1] = (unsigned char) (g>>16); ptr[2] = (unsigned char) (b>>16); + ptr[3] = (unsigned char) (a>>16); for (x=1; x <= width/2; x *= 2) - memcpy (&(ptr[x*3]), ptr, x*3); - memcpy (&(ptr[x*3]), ptr, (width - x)*3); + memcpy (&(ptr[x*4]), ptr, x*4); + memcpy (&(ptr[x*4]), ptr, (width - x)*4); ptr += rowstride;