Owen Taylor <[EMAIL PROTECTED]> wrote:

> I've put up some screenshots at:
>
>  http://people.redhat.com/otaylor/fonts/gamma-screenshots/
>
> I also discovered a major one-character bug in my last patch
> (*, /, what's the difference...) that prevented it from
> working with anything but a black foreground. New fixed
> version is attached.

Ahem. I also discovered a cut-n-paste error that prevented it
from working with anything other than gray... ;)

Here's the patch to the patch, and the patched patch.

--- gamma.diff  Tue Jul 23 14:39:46 2002
+++ gammafixed.diff     Tue Jul 23 14:35:25 2002
@@ -177,8 +177,8 @@
 +    if (src_a)
 +    {
 +      *dst_r = fromDouble(src_a, (double)color->color.red / color->color.alpha, t);
-+      *dst_g = fromDouble(src_a, (double)color->color.red / color->color.alpha, t);
-+      *dst_b = fromDouble(src_a, (double)color->color.red / color->color.alpha, t);
++      *dst_g = fromDouble(src_a, (double)color->color.green / color->color.alpha, t);
++      *dst_b = fromDouble(src_a, (double)color->color.blue / color->color.alpha, t);
 +    }
 +    else
 +      *dst_r = *dst_g = *dst_b = 0;
--- fcpackage.02-06-21.10-39/Xft/xftcore.c.gamma        Sun Jun 23 10:35:12 2002
+++ fcpackage.02-06-21.10-39/Xft/xftcore.c      Sun Jun 23 17:00:05 2002
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include "xftint.h"
 #include <X11/Xmd.h>
+#include <math.h>
 
 void
 XftRectCore (XftDraw       *draw,
@@ -367,6 +368,64 @@
 }
 
 /*
+ * These functions define the sRGB curve that we use for gamma correction;
+ * because of the linear ramp at the beginning, the sRGB curve allows
+ * a much more manageable lookup table than a straight x**2.2 gamma curve
+ *
+ * Apparently, the values of ADJGAMA and OFFSET were chosen to minimize
+ * the difference between the sRGB function and X**2.2; the free parameters
+ * here really are GAMMA (=2.2) and THRESHOLD.
+ */
+#define THRESHOLD 0.03928 /* Very close to 10./255 */
+#define OFFSET 0.055
+#define ADJGAMMA 2.4
+#define SLOPE 12.92    /* gammaCurve (THRESHOLD) / THRESHOLD */
+
+static double
+gammaCurve(double x)
+{
+    if (x <= THRESHOLD)
+        return x / SLOPE;
+    else
+        return pow(((OFFSET + x) / (1 + OFFSET)), ADJGAMMA);
+}
+
+static double
+gammaCurveInv(double y)
+{
+    if (y <= THRESHOLD / SLOPE)
+        return y * SLOPE;
+    else
+        return pow(y, 1/ADJGAMMA) * (1 + OFFSET) - OFFSET;
+}
+
+static CARD16 gammaTable5[32];
+static CARD16 gammaTable6[64];
+static CARD16 gammaTable8[256];
+static CARD8 gammaTableInv[4096];
+
+static void
+gammaTablePrepare(void)
+{
+    static int prepared = 0;
+    int i;
+
+    if (!prepared)
+    {
+       for (i = 0; i < 32; i++)
+           gammaTable5[i] = 4095 * gammaCurve(i/31.) + 0.5;
+       for (i = 0; i < 64; i++)
+           gammaTable6[i] = 4095 * gammaCurve(i/63.) + 0.5;
+       for (i = 0; i < 256; i++)
+           gammaTable8[i] = 4095 * gammaCurve(i/255.) + 0.5;
+       for (i = 0; i < 4096; i++)
+           gammaTableInv[i] = 255 * gammaCurveInv(i/4095.) + 0.5;
+
+       prepared = 1;
+    }
+}
+
+/*
  * As simple anti-aliasing is likely to be common, there are three
  * optimized versions for the usual true color pixel formats (888, 565, 555).
  * Other formats are handled by the general case
@@ -387,13 +446,35 @@
 #define cvt0555to8888(s)    (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
                             ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \
                             ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000)))
+#define cvt0555to8888(s)    (((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
+                            ((((s) << 6) & 0xf800) | (((s) >> 0) & 0x300)) | \
+                            ((((s) << 9) & 0xf80000) | (((s) << 4) & 0x70000)))
+
+#define XftGet8(v,i)   ((CARD16) (CARD8) ((v) >> i))
 
+#define cvt0888toGamma12(d,s) (d##_r = gammaTable8[XftGet8(s,16)], \
+                               d##_g = gammaTable8[XftGet8(s,8)],  \
+                               d##_b = gammaTable8[XftGet8(s,0)])
+#define cvt0565toGamma12(d,s) (d##_r = gammaTable5[((s) & 0xf800) >> 11], \
+                               d##_g = gammaTable6[((s) & 0x07e0) >> 5],  \
+                               d##_b = gammaTable5[((s) & 0x1f)])
+#define cvt0555toGamma12(d,s) (d##_r = gammaTable5[((s) & 0x7c00) >> 10], \
+                               d##_g = gammaTable5[((s) & 0x03e0) >> 5],  \
+                               d##_b = gammaTable5[((s) & 0x001f)])
+
+#define cvtGamma12to0888(s) (gammaTableInv[s##_r] << 16 | \
+                            gammaTableInv[s##_g] << 8|   \
+                            gammaTableInv[s##_b]);
+#define cvtGamma12to0565(s) (((gammaTableInv[s##_r] << 8) & 0xf800) | \
+                            ((gammaTableInv[s##_g] << 3) & 0x07e0) | \
+                            ((gammaTableInv[s##_b] >> 3)))
+#define cvtGamma12to0555(s) (((gammaTableInv[s##_r] << 7) & 0x7c00) | \
+                            ((gammaTableInv[s##_g] << 3) & 0x03e0) | \
+                            ((gammaTableInv[s##_b] >> 3)))
 
 #define XftIntMult(a,b,t) ( (t) = (a) * (b) + 0x80, ( ( ( (t)>>8 ) + (t) )>>8 ) )
 #define XftIntDiv(a,b)  (((CARD16) (a) * 255) / (b))
 
-#define XftGet8(v,i)   ((CARD16) (CARD8) ((v) >> i))
-
 /*
  * There are two ways of handling alpha -- either as a single unified value or
  * a separate value for each component, hence each macro must have two
@@ -402,16 +483,48 @@
  * this difference will have two versions using the same convention.
  */
 
+#define XftDeclare3(var) CARD32 var##_r, var##_g, var##_b
+#define XftDeclare4(var) CARD32 var##_a, var##_r, var##_g, var##_b
+#define XftAssign3(dst,src) (dst##_r = src##_r, \
+                            dst##_b = src##_b, \
+                            dst##_g = src##_g)
+#define XftAssignRGB(dst,r,g,b) (dst##_r = r, \
+                                dst##_b = b, \
+                                dst##_g = g)
+
 #define XftOverU(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),(a),(t)) + XftGet8(x,i),\
                           (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
 
 #define XftOverC(x,y,i,a,t) ((t) = XftIntMult(XftGet8(y,i),XftGet8(a,i),(t)) + 
XftGet8(x,i),\
                            (CARD32) ((CARD8) ((t) | (0 - ((t) >> 8)))) << (i))
 
+#define XftOverO(x,y,a,t) ((t) = XftIntMult(y,255-(a),(t)) + x,\
+                          (0xfff & ((t) | (0 - ((t) >> 12)))))
+
+#define XftOver3U(d,x,y,a,t) (d##_r = XftOverO(x##_r,y##_r,a,t##_r), \
+                             d##_g = XftOverO(x##_g,y##_g,a,t##_g), \
+                             d##_b = XftOverO(x##_b,y##_r,a,t##_b))
+#define XftOver3C(d,x,y,a,t) (d##_r = XftOverO(x##_r,y##_r,a##_r,t##_r), \
+                             d##_g = XftOverO(x##_g,y##_g,a##_g,t##_g), \
+                             d##_b = XftOverO(x##_b,y##_r,a##_b,t##_b))
+
 #define XftInU(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),(a),(t)) << (i))
 
 #define XftInC(x,i,a,t) ((CARD32) XftIntMult(XftGet8(x,i),XftGet8(a,i),(t)) << (i))
 
+#define XftInO(x,a,t) (XftIntMult(x,a,t))
+
+#define XftIn4U(d,x,a,t) (d##_a = XftInO(x##_a,a,t##_a), \
+                         d##_r = XftInO(x##_r,a,t##_r), \
+                         d##_g = XftInO(x##_g,a,t##_g), \
+                         d##_b = XftInO(x##_b,a,t##_b))
+#define XftIn3C(dc,da,x,a,m,t1,t2) (dc##_r = XftInO(x##_r,XftGet8(m,16),t1##_r), \
+                                   da##_r = XftInO(a,XftGet8(m,16),t2##_r), \
+                                   dc##_g = XftInO(x##_g,XftGet8(m,8),t1##_g), \
+                                   da##_g = XftInO(a,XftGet8(m,8),t2##_g), \
+                                   dc##_b = XftInO(x##_b,XftGet8(m,0),t1##_b), \
+                                   da##_b = XftInO(a,XftGet8(m,0),t2##_b))
+
 #define XftGen(x,y,i,ax,ay,t,u,v) ((t) = (XftIntMult(XftGet8(y,i),ay,(u)) + \
                                         XftIntMult(XftGet8(x,i),ax,(v))),\
                                  (CARD32) ((CARD8) ((t) | \
@@ -449,36 +562,69 @@
 }
 
 static void
+colorToGamma12 (XftColor *color,
+               CARD32   *dst_r,
+               CARD32   *dst_g,
+               CARD32   *dst_b)
+{
+    CARD32 src_a = color->color.alpha >> 8;
+    CARD32 t;
+
+#define fromDouble(a,d,t) XftIntMult(a,(gammaCurve(d) + (0.5 / 4095.)) * 4095, t)
+       
+    if (src_a)
+    {
+       *dst_r = fromDouble(src_a, (double)color->color.red / color->color.alpha, t);
+       *dst_g = fromDouble(src_a, (double)color->color.green / color->color.alpha, t);
+       *dst_b = fromDouble(src_a, (double)color->color.blue / color->color.alpha, t);
+    }
+    else
+       *dst_r = *dst_g = *dst_b = 0;
+}
+
+#define cvtColorToGamma12(dst,color) colorToGamma12(color, &dst##_r, &dst##_g, 
+&dst##_b)
+#define cvtColorToGamma12r(dst,color) colorToGamma12(color, &dst##_b, &dst##_g, 
+&dst##_r)
+
+static void
 _XftSmoothGlyphGray8888 (XImage            *image,
                         XftGlyph   *xftg,
                         int        x,
                         int        y,
                         XftColor   *color)
 {
-    CARD32     src, srca;
-    CARD32     r, g, b;
-    CARD32     *dstLine, *dst, d;
+    XftDeclare4(src);
+    XftDeclare3(dst);
+    CARD32      src;
+    CARD32      r, g, b;
+    CARD32     *dstLine, *dst;
     CARD8      *maskLine, *mask, m;
     int                dstStride, maskStride;
     int                width, height;
     int                w;
 
-    srca = color->color.alpha >> 8;
+    gammaTablePrepare();
+
+    src_a = color->color.alpha >> 8;
     
     /* This handles only RGB and BGR */
-    g = (color->color.green & 0xff00);
+    src_g = gammaTable8[color->color.green >> 8];
+    g = color->color.green & 0xff00;
     if (image->red_mask == 0xff0000)
     {
        r = (color->color.red & 0xff00) << 8;
        b = color->color.blue >> 8;
+
+       cvtColorToGamma12(src, color);
     }
     else
     {
-       r = color->color.red >> 8;
        b = (color->color.blue & 0xff00) << 8;
+       r = color->color.red >> 8;
+
+       cvtColorToGamma12r(src, color);
     }
-    src = (srca << 24) | r | g | b;
-    
+    src = r | g | b;
+
     width = xftg->metrics.width;
     height = xftg->metrics.height;
     
@@ -503,15 +649,29 @@
            m = *mask++;
            if (m == 0xff)
            {
-               if (srca == 0xff)
+               if (src_a == 0xff)
                    *dst = src;
                else
-                   *dst = fbOver24 (src, *dst);
+               {
+                   XftDeclare3(tmpdst);
+                   XftDeclare3(scratch1);
+
+                   cvt0888toGamma12(tmpdst, *dst);
+                   XftOver3U(dst, src, tmpdst, src_a, scratch1);
+                   *dst = cvtGamma12to0888(dst);
+               }
            }
            else if (m)
            {
-               d = fbIn (src, m);
-               *dst = fbOver24 (d, *dst);
+               XftDeclare3(tmpdst);
+               XftDeclare4(tmpsrc);
+               XftDeclare4(scratch1);
+               XftDeclare3(scratch2);
+
+               cvt0888toGamma12(tmpdst, *dst);
+               XftIn4U(tmpsrc, src, m, scratch1);
+               XftOver3U(dst, tmpsrc, tmpdst, tmpsrc_a, scratch2);
+               *dst = cvtGamma12to0888(dst);
            }
            dst++;
        }
@@ -525,16 +685,19 @@
                        int         y,
                        XftColor    *color)
 {
-    CARD32     src, srca;
+    XftDeclare4(src);
+    XftDeclare3(dst);
+    CARD16      src;
     CARD32     r, g, b;
-    CARD32     d;
     CARD16     *dstLine, *dst;
     CARD8      *maskLine, *mask, m;
     int                dstStride, maskStride;
     int                width, height;
     int                w;
 
-    srca = color->color.alpha >> 8;
+    gammaTablePrepare();
+
+    src_a = color->color.alpha >> 8;
     
     /* This handles only RGB and BGR */
     g = (color->color.green & 0xff00);
@@ -542,13 +705,17 @@
     {
        r = (color->color.red & 0xff00) << 8;
        b = color->color.blue >> 8;
+
+       cvtColorToGamma12(src, color);
     }
     else
     {
        r = color->color.red >> 8;
        b = (color->color.blue & 0xff00) << 8;
+
+       cvtColorToGamma12r(src, color);
     }
-    src = (srca << 24) | r | g | b;
+    src = cvt8888to0565(r | g | b);
     
     width = xftg->metrics.width;
     height = xftg->metrics.height;
@@ -574,20 +741,29 @@
            m = *mask++;
            if (m == 0xff)
            {
-               if (srca == 0xff)
-                   d = src;
+               if (src_a == 0xff)
+                   *dst = src;
                else
                {
-                   d = *dst;
-                   d = fbOver24 (src, cvt0565to8888(d));
+                   XftDeclare3(tmpdst);
+                   XftDeclare3(scratch1);
+
+                   cvt0565toGamma12(tmpdst, *dst);
+                   XftOver3U(dst, src, tmpdst, src_a, scratch1);
+                   *dst = cvtGamma12to0565(dst);
                }
-               *dst = cvt8888to0565(d);
            }
            else if (m)
            {
-               d = *dst;
-               d = fbOver24 (fbIn(src,m), cvt0565to8888(d));
-               *dst = cvt8888to0565(d);
+               XftDeclare3(tmpdst);
+               XftDeclare4(tmpsrc);
+               XftDeclare4(scratch1);
+               XftDeclare3(scratch2);
+
+               cvt0565toGamma12(tmpdst, *dst);
+               XftIn4U(tmpsrc, src, m, scratch1);
+               XftOver3U(dst, tmpsrc, tmpdst, tmpsrc_a, scratch2);
+               *dst = cvtGamma12to0565(dst);
            }
            dst++;
        }
@@ -601,16 +777,19 @@
                        int         y,
                        XftColor    *color)
 {
-    CARD32     src, srca;
+    XftDeclare4(src);
+    XftDeclare3(dst);
+    CARD16      src;
     CARD32     r, g, b;
-    CARD32     d;
     CARD16     *dstLine, *dst;
     CARD8      *maskLine, *mask, m;
     int                dstStride, maskStride;
     int                width, height;
     int                w;
 
-    srca = color->color.alpha >> 8;
+    gammaTablePrepare();
+
+    src_a = color->color.alpha >> 8;
     
     /* This handles only RGB and BGR */
     g = (color->color.green & 0xff00);
@@ -618,13 +797,17 @@
     {
        r = (color->color.red & 0xff00) << 8;
        b = color->color.blue >> 8;
+
+       cvtColorToGamma12(src, color);
     }
     else
     {
        r = color->color.red >> 8;
        b = (color->color.blue & 0xff00) << 8;
+
+       cvtColorToGamma12r(src, color);
     }
-    src = (srca << 24) | r | g | b;
+    src = cvt8888to0555(r | g | b);
     
     width = xftg->metrics.width;
     height = xftg->metrics.height;
@@ -650,20 +833,29 @@
            m = *mask++;
            if (m == 0xff)
            {
-               if (srca == 0xff)
-                   d = src;
+               if (src_a == 0xff)
+                   *dst = src;
                else
                {
-                   d = *dst;
-                   d = fbOver24 (src, cvt0555to8888(d));
+                   XftDeclare3(tmpdst);
+                   XftDeclare3(scratch1);
+                   
+                   cvt0555toGamma12(tmpdst, *dst);
+                   XftOver3U(dst, src, tmpdst, src_a, scratch1);
+                   *dst = cvtGamma12to0555(dst);
                }
-               *dst = cvt8888to0555(d);
            }
            else if (m)
            {
-               d = *dst;
-               d = fbOver24 (fbIn(src,m), cvt0555to8888(d));
-               *dst = cvt8888to0555(d);
+               XftDeclare3(tmpdst);
+               XftDeclare4(tmpsrc);
+               XftDeclare4(scratch1);
+               XftDeclare3(scratch2);
+
+               cvt0555toGamma12(tmpdst, *dst);
+               XftIn4U(tmpsrc, src, m, scratch1);
+               XftOver3U(dst, tmpsrc, tmpdst, tmpsrc_a, scratch2);
+               *dst = cvtGamma12to0555(dst);
            }
            dst++;
        }
@@ -677,22 +869,22 @@
                     int        y,
                     XftColor   *color)
 {
-    CARD32         src, srca;
+    XftDeclare4(src);
+    XftDeclare3(dst);
     int                    r_shift, r_len;
     int                    g_shift, g_len;
     int                    b_shift, b_len;
     CARD8          *maskLine, *mask, m;
     int                    maskStride;
-    CARD32         d;
     unsigned long   pixel;
     int                    width, height;
     int                    w, tx;
     
-    srca = color->color.alpha >> 8;
-    src = (srca << 24 |
-          (color->color.red & 0xff00) << 8 |
-          (color->color.green & 0xff00) |
-          (color->color.blue) >> 8);
+    gammaTablePrepare();
+
+    src_a = color->color.alpha >> 8;
+    cvtColorToGamma12 (src, color);
+    
     x -= xftg->metrics.x;
     y -= xftg->metrics.y;
     width = xftg->metrics.width;
@@ -716,31 +908,42 @@
            m = *mask++;
            if (m == 0xff)
            {
-               if (srca == 0xff)
-                   d = src;
+               if (src_a == 0xff)
+                   XftAssign3(dst,src);
                else
                {
+                   XftDeclare3(tmpdst);
+                   XftDeclare3(scratch1);
+               
                    pixel = XGetPixel (image, tx, y);
-                   d = (_XftGetField (pixel, r_shift, r_len) << 16 |
-                        _XftGetField (pixel, g_shift, g_len) << 8 |
-                        _XftGetField (pixel, b_shift, b_len));
-                   d = fbOver24 (src, d);
+                   XftAssignRGB(tmpdst,
+                                gammaTable8[_XftGetField (pixel, r_shift, r_len)],
+                                gammaTable8[_XftGetField (pixel, g_shift, g_len)],
+                                gammaTable8[_XftGetField (pixel, b_shift, b_len)]);
+                   XftOver3U(dst, src, tmpdst, src_a, scratch1);
                }
-               pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
-                        _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
-                        _XftPutField ((d      ) & 0xff, b_shift, b_len));
+               pixel = (_XftPutField (gammaTableInv[dst_r], r_shift, r_len) |
+                        _XftPutField (gammaTableInv[dst_g], g_shift, g_len) |
+                        _XftPutField (gammaTableInv[dst_b], b_shift, b_len));
                XPutPixel (image, tx, y, pixel);
            }
            else if (m)
            {
+               XftDeclare3(tmpdst);
+               XftDeclare4(tmpsrc);
+               XftDeclare4(scratch1);
+               XftDeclare3(scratch2);
+               
                pixel = XGetPixel (image, tx, y);
-               d = (_XftGetField (pixel, r_shift, r_len) << 16 |
-                    _XftGetField (pixel, g_shift, g_len) << 8 |
-                    _XftGetField (pixel, b_shift, b_len));
-               d = fbOver24 (fbIn(src,m), d);
-               pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
-                        _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
-                        _XftPutField ((d      ) & 0xff, b_shift, b_len));
+               XftAssignRGB(tmpdst,
+                            gammaTable8[_XftGetField (pixel, r_shift, r_len)],
+                            gammaTable8[_XftGetField (pixel, g_shift, g_len)],
+                            gammaTable8[_XftGetField (pixel, b_shift, b_len)]);
+               XftIn4U(tmpsrc, src, m, scratch1);
+               XftOver3U(dst, tmpsrc, tmpdst, tmpsrc_a, scratch2);
+               pixel = (_XftPutField (gammaTableInv[dst_r], r_shift, r_len) |
+                        _XftPutField (gammaTableInv[dst_g], g_shift, g_len) |
+                        _XftPutField (gammaTableInv[dst_b], b_shift, b_len));
                XPutPixel (image, tx, y, pixel);
            }
            tx++;
@@ -756,21 +959,22 @@
                     int        y,
                     XftColor   *color)
 {
-    CARD32         src, srca;
+    XftDeclare3(src);
+    XftDeclare3(dst);
+    CARD32         src_a;
     int                    r_shift, r_len;
     int                    g_shift, g_len;
     int                    b_shift, b_len;
     CARD32         *mask, ma;
-    CARD32         d;
     unsigned long   pixel;
     int                    width, height;
     int                    w, tx;
     
-    srca = color->color.alpha >> 8;
-    src = (srca << 24 |
-          (color->color.red & 0xff00) << 8 |
-          (color->color.green & 0xff00) |
-          (color->color.blue) >> 8);
+    gammaTablePrepare();
+
+    src_a = color->color.alpha >> 8;
+    cvtColorToGamma12(src, color);
+    
     x -= xftg->metrics.x;
     y -= xftg->metrics.y;
     width = xftg->metrics.width;
@@ -791,45 +995,45 @@
            ma = *mask++;
            if (ma == 0xffffffff)
            {
-               if (srca == 0xff)
-                   d = src;
+               if (src_a == 0xff)
+                   XftAssign3(dst,src);
                else
                {
+                   XftDeclare3(tmpdst);
+                   XftDeclare3(scratch1);
+               
                    pixel = XGetPixel (image, tx, y);
-                   d = (_XftGetField (pixel, r_shift, r_len) << 16 |
-                        _XftGetField (pixel, g_shift, g_len) << 8 |
-                        _XftGetField (pixel, b_shift, b_len));
-                   d = fbOver24 (src, d);
+                   XftAssignRGB(tmpdst,
+                                gammaTable8[_XftGetField (pixel, r_shift, r_len)],
+                                gammaTable8[_XftGetField (pixel, g_shift, g_len)],
+                                gammaTable8[_XftGetField (pixel, b_shift, b_len)]);
+                   XftOver3U(dst, src, tmpdst, src_a, scratch1);
                }
-               pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
-                        _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
-                        _XftPutField ((d      ) & 0xff, b_shift, b_len));
+               pixel = (_XftPutField (gammaTableInv[dst_r], r_shift, r_len) |
+                        _XftPutField (gammaTableInv[dst_g], g_shift, g_len) |
+                        _XftPutField (gammaTableInv[dst_b], b_shift, b_len));
                XPutPixel (image, tx, y, pixel);
            }
            else if (ma)
            {
-               CARD32  m,n,o;
+               XftDeclare3(tmpdst);
+               XftDeclare3(tmpsrc);
+               XftDeclare3(tmpa);
+               XftDeclare3(scratch1);
+               XftDeclare3(scratch2);
+               XftDeclare3(scratch3);
+               
                pixel = XGetPixel (image, tx, y);
-               d = (_XftGetField (pixel, r_shift, r_len) << 16 |
-                    _XftGetField (pixel, g_shift, g_len) << 8 |
-                    _XftGetField (pixel, b_shift, b_len));
-#define XftInOverC(src,srca,msk,dst,i,result) { \
-    CARD16  __a = XftGet8(msk,i); \
-    CARD32  __t, __ta; \
-    CARD32  __i; \
-    __t = XftIntMult (XftGet8(src,i), __a,__i); \
-    __ta = (CARD8) ~XftIntMult (srca, __a,__i); \
-    __t = __t + XftIntMult(XftGet8(dst,i),__ta,__i); \
-    __t = (CARD32) (CARD8) (__t | (-(__t >> 8))); \
-    result = __t << (i); \
-}
-               XftInOverC(src,srca,ma,d,0,m);
-               XftInOverC(src,srca,ma,d,8,n);
-               XftInOverC(src,srca,ma,d,16,o);
-               d = m | n | o;
-               pixel = (_XftPutField ((d >> 16) & 0xff, r_shift, r_len) |
-                        _XftPutField ((d >>  8) & 0xff, g_shift, g_len) |
-                        _XftPutField ((d      ) & 0xff, b_shift, b_len));
+               XftAssignRGB(tmpdst,
+                            gammaTable8[_XftGetField (pixel, r_shift, r_len)],
+                            gammaTable8[_XftGetField (pixel, g_shift, g_len)],
+                            gammaTable8[_XftGetField (pixel, b_shift, b_len)]);
+               XftIn3C(tmpsrc, tmpa, src, src_a, ma, scratch1, scratch2);
+               XftOver3C(dst, tmpsrc, tmpdst, tmpa, scratch3);
+               
+               pixel = (_XftPutField (gammaTableInv[dst_r], r_shift, r_len) |
+                        _XftPutField (gammaTableInv[dst_g], g_shift, g_len) |
+                        _XftPutField (gammaTableInv[dst_b], b_shift, b_len));
                XPutPixel (image, tx, y, pixel);
            }
            tx++;

Reply via email to