bug-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

xgps/XGBitmap alpha transparacy fix


From: Wim Oudshoorn
Subject: xgps/XGBitmap alpha transparacy fix
Date: Wed, 27 Sep 2000 20:19:28 +0200

NOTE:
The mailing list does not seem to work.  I never saw
my original mail `Newbie tries again', some mail
only get delivered after 4 days and I get some mail
multiple times.
Is this because it is moderated?  Is the mailing list
configured in such a way that you never receive your
own e-mail.
Altogether, it makes me quite unsure if my mails
ever get received, and if I get all the mail sent
to the mailing lists.

Greetings,
Wim Oudshoorn.

--

BUG description:
- Displaying images with a non trivial
(not completely transparant or completely opaque) does
not work on all colordepths. (At least not on 16bpp)

REPRODUCE:
- run GWorkspace-0.1.2 in 16bpp with the default
  NSGlobalDomain GraphicCompositing
set.  Notice that the folder icons are not quite correct.

FIX below, only tested on 16bpp.

ChangeLog:

2000-09-27  Willem Rein Oudshoorn  <woudshoo@sctcorp.com>

        * XGBitmap.m:
        Added macros to convert between RGB and X11 pixel values
        (_pixmap_combine_alpha, _bitmap_combine_alpha):
        Combined all XGDM_FAST methods in one block of code.
        Fixed some bugs in the bitmanipulations.


Result DIFF:
diff -c ~/test/gstep-core-0.6.6/xgps/Source/XGBitmap.m xgps/Source/XGBitmap.m

(Note that, the ~/test/.. file is the originial file and
        xgps/Source/XGBitmap.m is the new file.

Sorry I never got the hang of diff, I always mess up the pathnames etc.)

---------------------------------------------------------------------------
*** /home/wim/test/gstep-core-0.6.6/xgps/Source/XGBitmap.m      Mon Aug  7  
16:49:02 2000
--- xgps/Source/XGBitmap.m      Wed Sep 27 19:54:22 2000
***************
*** 42,47 ****
--- 42,92 ----
  #include <Foundation/NSDebug.h>
  #include <Foundation/NSUserDefaults.h>

+ /* Macros that make it easier to convert
+    between (r,g,b) <--> pixels.
+ */
+
+ #define VARIABLES_DECLARATION \
+         unsigned char _rshift, _gshift, _bshift, _ashift; \
+         unsigned int  _rmask,  _gmask,  _bmask,  _amask; \
+         unsigned char _rwidth, _gwidth, _bwidth, _awidth
+
+
+
+ #define InitRGBShiftsAndMasks(rs,rw,gs,gw,bs,bw,as,aw) { \
+         _rshift = rs;              \
+         _rmask  = (1<<rw) -1;      \
+         _rwidth = rw;              \
+         _gshift = gs;              \
+       _gmask  = (1<<gw) -1;      \
+         _gwidth = gw;              \
+       _bshift = bs;              \
+       _bmask  = (1<<bw) -1;      \
+         _bwidth = bw;              \
+         _amask  = (1<<aw) -1;      \
+         _ashift = as;              \
+         _awidth = aw;              \
+        } while(0)
+
+
+ #define PixelToRGB(pixel,r,g,b) { \
+         r = (pixel >> _rshift) & _rmask; \
+         g = (pixel >> _gshift) & _gmask; \
+         b = (pixel >> _bshift) & _bmask; \
+         } while(0)
+
+ /* Note that RGBToPixel assumes that the
+    r,g,b values are in the correct domain.
+    If not, the value is nonsense.
+ */
+
+ #define RGBToPixel(r,g,b, pixel) { \
+         pixel = ((r) << _rshift)  \
+                |((g) << _gshift)  \
+                |((b) << _bshift); \
+         } while(0)
+
+
  /* Composite source image (pixmap) onto a destination image with alpha.
     Only works for op=Sover now */
  int
***************
*** 54,100 ****
    unsigned long  pixel;
    unsigned short oldAlpha = 0;
    unsigned long  oldPixel = 0;
!   unsigned char  oldAr = 0;
!   unsigned char        oldAg = 0;
!   unsigned char        oldAb = 0;
    unsigned char        oldBr = 0;
    unsigned char        oldBg = 0;
    unsigned char        oldBb = 0;

!   if (drawMechanism == XGDM_FAST15 || drawMechanism == XGDM_FAST16)
      {
!       unsigned  rshift, gshift;
        unsigned        row;
!       rshift = 11; gshift = 6;
!       if (drawMechanism == XGDM_FAST15)
!               {
!         rshift = 10;
!         gshift = 5;
        }
-
        for (row = 0; row < NSHeight(drect); row++)
        {
          unsigned      col;

          for (col = 0; col < NSWidth(drect); col++)
            {
!             int r, g, b, alpha;
              pixel = XGetPixel(source_im->image,
                                col+origin_x, row+origin_y);
!             r = (pixel >> rshift) & 0x1f;
!             g = (pixel >> 5)  & 0x1f;
!             b = pixel & 0x1f;
              pixel = 255;
              if (source_alpha)
                pixel = XGetPixel(source_alpha->image,
                                  col+origin_x, row+origin_y);
!             alpha = pixel >> 3;
              if (alpha == 0)
                continue;               // background unchanged.
!             if (alpha != 31)
!               {
!                 unsigned short        ialpha = 31 - alpha;
!
                  /*
                   * Get the background pixel and convert to RGB.
                   */
--- 99,163 ----
    unsigned long  pixel;
    unsigned short oldAlpha = 0;
    unsigned long  oldPixel = 0;
!   unsigned short oldAr = 0;
!   unsigned short oldAg = 0;
!   unsigned short oldAb = 0;
    unsigned char        oldBr = 0;
    unsigned char        oldBg = 0;
    unsigned char        oldBb = 0;

!   if (drawMechanism == XGDM_FAST15
!       || drawMechanism == XGDM_FAST16
!       || drawMechanism == XGDM_FAST32
!       || drawMechanism == XGDM_FAST32_BGR)
      {
!       VARIABLES_DECLARATION;
        unsigned        row;
!
!       switch (drawMechanism)
!       {
!       case XGDM_FAST15:
!         InitRGBShiftsAndMasks(10,5,5,5,0,5,0,8);
!         break;
!       case XGDM_FAST16:
!         InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
!         break;
!       case XGDM_FAST32:
!         InitRGBShiftsAndMasks(16,8,8,8,0,8,0,8);
!         break;
!       case XGDM_FAST32_BGR:
!         InitRGBShiftsAndMasks(0,8,8,8,16,8,0,8);
!         break;
!       default:
!         NSLog(@"Huh? Backend confused about XGDrawMechanism");
!         //Try something.  With a bit of luck we see
!         //which picture goes wrong.
!         InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
        }
        for (row = 0; row < NSHeight(drect); row++)
        {
          unsigned      col;

          for (col = 0; col < NSWidth(drect); col++)
            {
!             unsigned r, g, b, alpha;
              pixel = XGetPixel(source_im->image,
                                col+origin_x, row+origin_y);
!
!             PixelToRGB(pixel,r,g,b);
!
              pixel = 255;
              if (source_alpha)
                pixel = XGetPixel(source_alpha->image,
                                  col+origin_x, row+origin_y);
!
!             alpha = (pixel >> _ashift) & _amask;
!       
              if (alpha == 0)
                continue;               // background unchanged.
!             if (alpha != _amask)
!               { // We really have something to mix!
!                 unsigned short        ialpha = _amask - alpha;
                  /*
                   * Get the background pixel and convert to RGB.
                   */
***************
*** 102,169 ****
                  if (pixel != oldPixel)
                    {
                      oldPixel = pixel;
!                     oldBb = pixel & 0x1f;
!                     pixel >>= gshift;
!                     oldBg = pixel & 0x1f;
!                     pixel >>= 5;
!                     oldBr = pixel;
!                     oldAlpha = 0;
!                   }
!                 if (alpha != oldAlpha)
!                   {
!                     oldAlpha = alpha;
!                     oldAr = ialpha * oldBr;
!                     oldAg = ialpha * oldBg;
!                     oldAb = ialpha * oldBb;
!                   }
!               
!                 // mix in alpha to produce RGB out
!                 r = (oldAr + (r*alpha))/31;
!                 g = (oldAg + (g*alpha))/31;
!                 b = (oldAb + (b*alpha))/31;
!               }
!             pixel = (((r << 5) + g) << gshift) + b;
!             XPutPixel(dest_im->image, col, row, pixel);
!             if (dest_alpha)
!               XPutPixel(dest_alpha->image, col, row, (alpha << 3));
!           }
!       }
!     }
!   else if (drawMechanism == XGDM_FAST32)
!     {
!       unsigned                row;
!
!       for (row = 0; row < NSHeight(drect); row++)
!       {
!         unsigned      col;
!
!         for (col = 0; col < NSWidth(drect); col++)
!           {
!             int r, g, b, alpha;
!             pixel = XGetPixel(source_im->image,
!                               col+origin_x, row+origin_y);
!             r = (pixel >> 16) & 0xff;
!             g = (pixel >> 8)  & 0xff;
!             b = pixel & 0xff;
!             pixel = 255;
!             if (source_alpha)
!               pixel = XGetPixel(source_alpha->image,
!                                 col+origin_x, row+origin_y);
!             alpha = pixel & 0xff;
!             if (alpha == 0)
!               continue;               // background unchanged.
!
!             if (alpha != 255)
!               {
!                 unsigned short        ialpha = 255 - alpha;
!
!                 pixel = XGetPixel(dest_im->image, col, row);
!                 if (pixel != oldPixel)
!                   {
!                     oldPixel = pixel;
!                     oldBr = (pixel & 0xff0000) >> 16;
!                     oldBg = (pixel & 0xff00) >> 8;
!                     oldBb = pixel & 0xff;
                      oldAlpha = 0;
                    }
                  if (alpha != oldAlpha)
--- 165,171 ----
                  if (pixel != oldPixel)
                    {
                      oldPixel = pixel;
!                     PixelToRGB(pixel, oldBr,oldBg,oldBb);
                      oldAlpha = 0;
                    }
                  if (alpha != oldAlpha)
***************
*** 175,245 ****
                    }
                
                  // mix in alpha to produce RGB out
!                 r = (oldAr + (r*alpha))/255;
!                 g = (oldAg + (g*alpha))/255;
!                 b = (oldAb + (b*alpha))/255;
                }
!             pixel = (((r << 8) + g) << 8) + b;
              XPutPixel(dest_im->image, col, row, pixel);
              if (dest_alpha)
!               XPutPixel(dest_alpha->image, col, row, alpha);
!           }
!       }
!     }
!   else if (drawMechanism == XGDM_FAST32_BGR)
!     {
!       unsigned          row;
!
!       for (row = 0; row < NSHeight(drect); row++)
!       {
!         unsigned      col;
!       
!         for (col = 0; col < NSWidth(drect); col++)
!           {
!             int r, g, b, alpha;
!             pixel = XGetPixel(source_im->image,
!                               col+origin_x, row+origin_y);
!             b = (pixel >> 16) & 0xff;
!             r = (pixel >> 8)  & 0xff;
!             g = pixel & 0xff;
!             pixel = 255;
!             if (source_alpha)
!               pixel = XGetPixel(source_alpha->image,
!                                 col+origin_x, row+origin_y);
!             alpha = pixel & 0xff;
!             if (alpha == 0)
!               continue;               // background unchanged.
!
!             if (alpha != 255)
!               {
!                 unsigned short    ialpha = 255 - alpha;
!               
!                 pixel = XGetPixel(dest_im->image, col, row);
!                 if (pixel != oldPixel)
!                   {
!                     oldPixel = pixel;
!                     oldBb = (pixel & 0xff0000) >> 16;
!                     oldBg = (pixel & 0xff00) >> 8;
!                     oldBr = pixel & 0xff;
!                     oldAlpha = 0;
!                   }
!                 if (alpha != oldAlpha)
!                   {
!                     oldAlpha = alpha;
!                     oldAr = ialpha * oldBr;
!                     oldAg = ialpha * oldBg;
!                     oldAb = ialpha * oldBb;
!                   }
!               
!                 // mix in alpha to produce RGB out
!                 r = (oldAr + (r*alpha))/255;
!                 g = (oldAg + (g*alpha))/255;
!                 b = (oldAb + (b*alpha))/255;
!               }
!             pixel = (((b << 8) + g) << 8) + r;
!             XPutPixel(dest_im->image, col, row, pixel);
!             if (dest_alpha)
!               XPutPixel(dest_alpha->image, col, row, alpha);
            }
        }
      }
--- 177,190 ----
                    }
                
                  // mix in alpha to produce RGB out
!                 r = (oldAr + (r*alpha))/_amask;
!                 g = (oldAg + (g*alpha))/_amask;
!                 b = (oldAb + (b*alpha))/_amask;
                }
!             RGBToPixel(r,g,b,pixel);
              XPutPixel(dest_im->image, col, row, pixel);
              if (dest_alpha)
!               XPutPixel(dest_alpha->image, col, row, alpha << _ashift );
            }
        }
      }
***************
*** 354,727 ****
  {
    XColor      c0;
    XColor      c1;

!   if (numColors == 3 || (numColors == 4 && usesAlpha)
!       || numColors == 1 || (numColors == 2 && usesAlpha))
      {
!       BOOL colorimage;
!       unsigned long           pixel;
!       unsigned short  oldAlpha = 0;
!       unsigned long   oldPixel = 0;
!       unsigned char           oldAr = 0;
!       unsigned char           oldAg = 0;
!       unsigned char           oldAb = 0;
!       unsigned char           oldBr = 0;
!       unsigned char           oldBg = 0;
!       unsigned char           oldBb = 0;
!
!       colorimage = NO;
!       if (numColors == 3 || (numColors == 4 && usesAlpha))
!       colorimage = YES;
!
!       if (drawMechanism == XGDM_FAST15 || drawMechanism == XGDM_FAST16)
!         {
!           unsigned  rshift, gshift;
!           unsigned    row;
!           rshift = 11; gshift = 6;
!           if (drawMechanism == XGDM_FAST15)
!                   {
!             rshift = 10;
!             gshift = 5;
!           }
!
!         for (row = 0; row < height; row++)
!           {
!             unsigned  col;
!
!             for (col = 0; col < width; col++)
!               {
!                 unsigned short alpha;
!                 unsigned char r, g, b;
!                 if (colorimage)
!                   {
!                     r = *image_data++;
!                     g = *image_data++;
!                     b = *image_data++;
!                   }
!                 else
!                   r = g = b = *image_data++;
!                 if (row >= NSHeight(drect) || col >= NSWidth(drect))
!                   {
!                     if (usesAlpha)
!                       image_data++;
!                     continue;
!                   }
!
!                 /*
!                  * Convert 8-bit components down to the 5-bit values
!                  * that the display system can actually handle.
!                  */
!                 r >>= 3;
!                 g >>= 3;
!                 b >>= 3;
!                 if (usesAlpha)
!                   {
!                     alpha = (unsigned short)*image_data++;
!                     if (dest_alpha)
!                       XPutPixel(dest_alpha->image, col, row, alpha);
!                     if (alpha == 0)
!                       continue;               // background unchanged.
!
!                     alpha >>= 3;              // Convert to 5-bit.
!
!                     if (alpha != 31)
!                       {
!                         unsigned short        ialpha = 31 - alpha;
!
!                         /*
!                          * Get the background pixel and convert to RGB.
!                          */
!                         pixel = XGetPixel(dest_im->image, col, row);
!                         if (pixel != oldPixel)
!                           {
!                             oldPixel = pixel;
!                             oldBb = pixel & 0x1f;
!                             pixel >>= gshift;
!                             oldBg = pixel & 0x1f;
!                             pixel >>= 5;
!                             oldBr = pixel;
!                             oldAlpha = 0;
!                           }
!                         if (alpha != oldAlpha)
!                           {
!                             oldAlpha = alpha;
!                             oldAr = ialpha * oldBr;
!                             oldAg = ialpha * oldBg;
!                             oldAb = ialpha * oldBb;
!                           }
!
!                         // mix in alpha to produce RGB out
!                         r = (oldAr + (r*alpha))/31;
!                         g = (oldAg + (g*alpha))/31;
!                         b = (oldAb + (b*alpha))/31;
!                       }
!                   }
!                 pixel = (((r << 5) + g) << gshift) + b;
!                 XPutPixel(dest_im->image, col, row, pixel);
!               }
!           }
!       }
!       else if (drawMechanism == XGDM_FAST32)
!       {
!         unsigned              row;
!
!         for (row = 0; row < height; row++)
!           {
!             unsigned  col;
!
!             for (col = 0; col < width; col++)
!               {
!                 unsigned short        alpha;
!                 unsigned char r, g, b;
!                 if (colorimage)
!                   {
!                     r = *image_data++;
!                     g = *image_data++;
!                     b = *image_data++;
!                   }
!                 else
!                   r = g = b = *image_data++;
!                 if (row >= NSHeight(drect) || col >= NSWidth(drect))
!                   {
!                     if (usesAlpha)
!                       image_data++;
!                     continue;
!                   }
!
!                 if (usesAlpha)
!                   {
!
!                     alpha = (unsigned short)*image_data++;
!                     if (dest_alpha)
!                       XPutPixel(dest_alpha->image, col, row, alpha);
!                     if (alpha == 0)
!                       continue;               // background unchanged.
!
!                     if (alpha != 255)
!                       {
!                         unsigned short        ialpha = 255 - alpha;
!
!                         pixel = XGetPixel(dest_im->image, col, row);
!                         if (pixel != oldPixel)
!                           {
!                             oldPixel = pixel;
!                             oldBr = (pixel & 0xff0000) >> 16;
!                             oldBg = (pixel & 0xff00) >> 8;
!                             oldBb = pixel & 0xff;
!                             oldAlpha = 0;
!                           }
!                         if (alpha != oldAlpha)
!                           {
!                             oldAlpha = alpha;
!                             oldAr = ialpha * oldBr;
!                             oldAg = ialpha * oldBg;
!                             oldAb = ialpha * oldBb;
!                           }
!
!                         // mix in alpha to produce RGB out
!                         r = (oldAr + (r*alpha))/255;
!                         g = (oldAg + (g*alpha))/255;
!                         b = (oldAb + (b*alpha))/255;
!                       }
!                   }
!                 pixel = (((r << 8) + g) << 8) + b;
!                 XPutPixel(dest_im->image, col, row, pixel);
!               }
!           }
!       }
!       else if (drawMechanism == XGDM_FAST32_BGR)
!       {
!         unsigned          row;
!
!         for (row = 0; row < height; row++)
!           {
!             unsigned      col;
!
!             for (col = 0; col < width; col++)
!               {
!                 unsigned short        alpha;
!                 unsigned char r, g, b;
!                 if (colorimage)
!                   {
!                     r = *image_data++;
!                     g = *image_data++;
!                     b = *image_data++;
!                   }
!                 else
!                   r = g = b = *image_data++;
!                 if (row >= NSHeight(drect) || col >= NSWidth(drect))
!                   {
!                     if (usesAlpha)
!                       image_data++;
!                     continue;
!                   }
!
!                 if (usesAlpha)
!                   {
!                     alpha = (unsigned short)*image_data++;
!                     if (dest_alpha)
!                       XPutPixel(dest_alpha->image, col, row, alpha);
!                     if (alpha == 0)
!                       continue;           // background unchanged.
!
!                     if (alpha != 255)
!                       {
!                         unsigned short    ialpha = 255 - alpha;
!
!                         pixel = XGetPixel(dest_im->image, col, row);
!                         if (pixel != oldPixel)
!                           {
!                             oldPixel = pixel;
!                             oldBb = (pixel & 0xff0000) >> 16;
!                             oldBg = (pixel & 0xff00) >> 8;
!                             oldBr = pixel & 0xff;
!                             oldAlpha = 0;
!                           }
!                         if (alpha != oldAlpha)
!                           {
!                             oldAlpha = alpha;
!                             oldAr = ialpha * oldBr;
!                             oldAg = ialpha * oldBg;
!                             oldAb = ialpha * oldBb;
!                           }
!
!                         // mix in alpha to produce RGB out
!                         r = (oldAr + (r*alpha))/255;
!                         g = (oldAg + (g*alpha))/255;
!                         b = (oldAb + (b*alpha))/255;
!                       }
!                   }
!                 pixel = (((b << 8) + g) << 8) + r;
!                 XPutPixel(dest_im->image, col, row, pixel);
!               }
!           }
!       }
!       else
!       {
!         XColor                c2, a2;
!         unsigned              row, oldAlpha = 65537;
!
!         /*
!          * This block of code should be totally portable as it uses the
!          * 'official' X mechanism for converting from pixel values to
!          * RGB color values - on the downside, it's very slow.
!          */
!         pixel = (unsigned long)-1;    // Never valid?
!         c2.pixel = pixel;
!
!         for (row = 0; row < height; row++)
!           {
!             unsigned  col;
!
!             for (col = 0; col < width; col++)
!               {
!                 unsigned short alpha;
!                 unsigned char r, g, b;
!                 if (colorimage)
!                   {
!                     r = *image_data++;
!                     g = *image_data++;
!                     b = *image_data++;
!                   }
!                 else
!                   r = g = b = *image_data++;
!                 if (row >= NSHeight(drect) || col >= NSWidth(drect))
!                   {
!                     if (usesAlpha)
!                       image_data++;
!                     continue;
!                   }
!
!                 if (usesAlpha)
!                   {
!                     alpha = (unsigned short)*image_data++;
!                     if (alpha != oldAlpha)
!                       {
!                         oldAlpha = alpha;
!                         a2.red = alpha << 8;
!                         a2.green = alpha << 8;
!                         a2.blue = alpha << 8;
!                         XAllocColor(context->dpy, context->cmap, &a2);
!                       }
!                     if (dest_alpha)
!                       XPutPixel(dest_alpha->image, col, row, a2.pixel);
!                     if (alpha == 0)
!                       continue;               // background unchanged.
!
!                     if (alpha == 255)
!                       {
!                         c1.red = r << 8;
!                         c1.green = g << 8;
!                         c1.blue = b << 8;
!                       }
!                     else
!                       {
!                         unsigned short        ialpha = 255 - alpha;
!
!                         /*
!                          * RGB color components in X are 16-bit values -
!                          * but our bitmap contains 8-bit values so we must
!                          * adjust our values up to 16-bit, which we can do
!                          * by increasing their alpha component by 256.
!                          */
!                         alpha <<= 8;
!
!                         /*
!                          * Get the background pixel and convert to RGB if
!                          * we haven't already done the conversion earlier.
!                          */
!                         c0.pixel = XGetPixel(dest_im->image, col, row);
!                         if (c0.pixel != pixel)
!                           {
!                             pixel = c0.pixel;
!                             XQueryColor(context->dpy, context->cmap, &c0);
!                           }
!
!                         // mix in alpha to produce RGB out
!                         c1.red = ((c0.red*ialpha) + (r*alpha))/255;
!                         c1.green = ((c0.green*ialpha) + (g*alpha))/255;
!                         c1.blue = ((c0.blue*ialpha) + (b*alpha))/255;
!                       }
!                   }
!                 else
!                   {
!                     /*
!                      * Simply convert our 8-bit RGB values to X-style
!                      * 16-bit values, then determine the X colormap
!                      * entry and set the pixel.
!                      */
!                     c1.red = r << 8;
!                     c1.green = g << 8;
!                     c1.blue = b << 8;
!                   }
!
!                 /*
!                  * Convert the X RGB value to a colormap entry if we
!                  * don't already have one.  Then set the pixel.
!                  * NB.  XAllocColor() will not necessarily return a
!                  * color with exactly the rgb components we gave it, so
!                  * we must record those components beforehand.
!                  */
!                 if (c2.pixel == (unsigned long)-1
!                     || c2.red != c1.red
!                     || c2.green != c1.green
!                     || c2.blue != c1.blue)
!                   {
!                     c2.red = c1.red;
!                     c2.green = c1.green;
!                     c2.blue = c1.blue;
!                     XAllocColor(context->dpy, context->cmap, &c1);
!                     c2.pixel = c1.pixel;
!                   }
!                 XPutPixel(dest_im->image, col, row, c1.pixel);
!               }
!           }
!       }
      }
!   else
      {
        NSLog(@"Backend cannot handle images with %d colors", numColors);
      }
    return 0;
  }

--- 299,559 ----
  {
    XColor      c0;
    XColor      c1;
+   BOOL          colorimage = NO;

!   if (numColors == 3 || (numColors == 4 && usesAlpha))
      {
!       colorimage = YES;
      }
!   else if ( ! (numColors == 1 || (numColors == 2 && usesAlpha)))
      {
        NSLog(@"Backend cannot handle images with %d colors", numColors);
+       return 0;
      }
+
+   {
+     unsigned long     pixel;
+     unsigned short    oldAlpha = 0;
+     unsigned long     oldPixel = 0;
+     unsigned short    oldAr = 0;
+     unsigned short    oldAg = 0;
+     unsigned short    oldAb = 0;
+     unsigned char     oldBr = 0;
+     unsigned char     oldBg = 0;
+     unsigned char     oldBb = 0;
+
+     /* Two cases, the *_FAST* method, which
+        is covered in the first a part of the if
+        clause.
+        When no FAST method is available (or recognized)
+        use the `official' X mechanism.  This is
+        covered in the else clause */
+
+     if (drawMechanism == XGDM_FAST15
+       || drawMechanism == XGDM_FAST16
+       || drawMechanism == XGDM_FAST32
+       || drawMechanism == XGDM_FAST32_BGR)
+       {
+       VARIABLES_DECLARATION;
+       unsigned        row;
+       
+       switch (drawMechanism)
+         {
+         case XGDM_FAST15:
+           InitRGBShiftsAndMasks(10,5,5,5,0,5,0,8);
+           break;
+         case XGDM_FAST16:
+           InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
+           break;
+         case XGDM_FAST32:
+           InitRGBShiftsAndMasks(16,8,8,8,0,8,0,8);
+           break;
+         case XGDM_FAST32_BGR:
+           InitRGBShiftsAndMasks(0,8,8,8,16,8,0,8);
+           break;
+         default:
+           NSLog(@"Huh? Backend confused about XGDrawMechanism");
+           //Try something.  With a bit of luck we see
+           //which picture goes wrong.
+           InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8);
+         }
+
+       for (row = 0; row < height; row++)
+         {
+           unsigned    col;
+       
+           for (col = 0; col < width; col++)
+             {
+               unsigned short alpha;
+               unsigned short r, g, b;
+
+               if (colorimage)
+                 {
+                   r = *image_data++;
+                   g = *image_data++;
+                   b = *image_data++;
+                 }
+               else
+                 r = g = b = *image_data++;
+
+               if (row >= NSHeight(drect) || col >= NSWidth(drect))
+                 {
+                   if (usesAlpha)
+                     image_data++;
+                   continue;
+                 }
+               
+               /*
+                * Convert 8-bit components down to the 5-bit values
+                * that the display system can actually handle.
+                */
+               r >>= (8 - _rwidth);
+               g >>= (8 - _gwidth);
+               b >>= (8 - _bwidth);
+
+               if (usesAlpha)
+                 {
+                   alpha = (unsigned short)*image_data++;
+                   if (dest_alpha)
+                     XPutPixel(dest_alpha->image, col, row, alpha);
+                   if (alpha == 0)
+                     continue;         // background unchanged.
+               
+                   if (alpha != _amask)
+                     {
+                       unsigned short  ialpha = _amask - alpha;
+                       /*
+                        * Get the background pixel and convert to RGB.
+                        */
+                       pixel = XGetPixel(dest_im->image, col, row);
+                       if (pixel != oldPixel)
+                         {
+                           oldPixel = pixel;
+                           PixelToRGB(pixel,oldBr,oldBg,oldBb);
+                           oldAlpha = 0;
+                         }
+                       if (alpha != oldAlpha)
+                         {
+                           oldAlpha = alpha;
+                           oldAr = ialpha * oldBr;
+                           oldAg = ialpha * oldBg;
+                           oldAb = ialpha * oldBb;
+                         }
+                       
+                       // mix in alpha to produce RGB out
+                       r = (oldAr + (r * alpha)) / _amask;
+                       g = (oldAg + (g * alpha)) / _amask;
+                       b = (oldAb + (b * alpha)) / _amask;
+                     }
+                 }
+               RGBToPixel(r,g,b,pixel);
+               XPutPixel(dest_im->image, col, row, pixel);
+             }
+         }
+       }
+     else
+       {
+       XColor          c2, a2;
+       unsigned       row, oldAlpha = 65537;
+
+       /*
+        * This block of code should be totally portable as it uses the
+        * 'official' X mechanism for converting from pixel values to
+        * RGB color values - on the downside, it's very slow.
+        */
+       pixel = (unsigned long)-1;      // Never valid?
+       c2.pixel = pixel;
+       
+       for (row = 0; row < height; row++)
+         {
+           unsigned    col;
+       
+           for (col = 0; col < width; col++)
+             {
+               unsigned short alpha;
+               unsigned char   r, g, b;
+
+               if (colorimage)
+                 {
+                   r = *image_data++;
+                   g = *image_data++;
+                   b = *image_data++;
+                 }
+               else
+                 r = g = b = *image_data++;
+               if (row >= NSHeight(drect) || col >= NSWidth(drect))
+                 {
+                   if (usesAlpha)
+                     image_data++;
+                   continue;
+                 }
+               
+               if (usesAlpha)
+                 {
+                   alpha = (unsigned short)*image_data++;
+                   if (alpha != oldAlpha)
+                     {
+                       oldAlpha = alpha;
+                       a2.red = alpha << 8;
+                       a2.green = alpha << 8;
+                       a2.blue = alpha << 8;
+                       XAllocColor(context->dpy, context->cmap, &a2);
+                     }
+                   if (dest_alpha)
+                     XPutPixel(dest_alpha->image, col, row, a2.pixel);
+                   if (alpha == 0)
+                     continue;         // background unchanged.
+               
+                   if (alpha == 255)
+                     {
+                       c1.red = r << 8;
+                       c1.green = g << 8;
+                       c1.blue = b << 8;
+                     }
+                   else
+                     {
+                       unsigned short  ialpha = 255 - alpha;
+                       
+                       /*
+                        * RGB color components in X are 16-bit values -
+                        * but our bitmap contains 8-bit values so we must
+                        * adjust our values up to 16-bit, which we can do
+                        * by increasing their alpha component by 256.
+                        */
+                       alpha <<= 8;
+                       
+                       /*
+                        * Get the background pixel and convert to RGB if
+                        * we haven't already done the conversion earlier.
+                        */
+                       c0.pixel = XGetPixel(dest_im->image, col, row);
+                       if (c0.pixel != pixel)
+                         {
+                           pixel = c0.pixel;
+                           XQueryColor(context->dpy, context->cmap, &c0);
+                         }
+                       
+                       // mix in alpha to produce RGB out
+                       c1.red = ((c0.red*ialpha) + (r*alpha))/255;
+                       c1.green = ((c0.green*ialpha) + (g*alpha))/255;
+                       c1.blue = ((c0.blue*ialpha) + (b*alpha))/255;
+                     }
+                 }
+               else
+                 {
+                   /*
+                    * Simply convert our 8-bit RGB values to X-style
+                    * 16-bit values, then determine the X colormap
+                    * entry and set the pixel.
+                    */
+                   c1.red = r << 8;
+                   c1.green = g << 8;
+                   c1.blue = b << 8;
+                 }
+               
+               /*
+                * Convert the X RGB value to a colormap entry if we
+                * don't already have one.  Then set the pixel.
+                * NB.  XAllocColor() will not necessarily return a
+                * color with exactly the rgb components we gave it, so
+                * we must record those components beforehand.
+                */
+               if (c2.pixel == (unsigned long)-1
+                   || c2.red != c1.red
+                   || c2.green != c1.green
+                   || c2.blue != c1.blue)
+                 {
+                   c2.red = c1.red;
+                   c2.green = c1.green;
+                   c2.blue = c1.blue;
+                   XAllocColor(context->dpy, context->cmap, &c1);
+                   c2.pixel = c1.pixel;
+                 }
+               XPutPixel(dest_im->image, col, row, c1.pixel);
+             }
+         }
+       }
+   }
    return 0;
  }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]