Back to index

lightning-sunbird  0.9+nobinonly
nsX11AlphaBlend.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  * ex: set tabstop=8 softtabstop=2 shiftwidth=2 expandtab:
00003  *
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * ***** BEGIN LICENSE BLOCK *****
00007  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00008  *
00009  * The contents of this file are subject to the Mozilla Public License Version
00010  * 1.1 (the "License"); you may not use this file except in compliance with
00011  * the License. You may obtain a copy of the License at
00012  * http://www.mozilla.org/MPL/
00013  *
00014  * Software distributed under the License is distributed on an "AS IS" basis,
00015  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00016  * for the specific language governing rights and limitations under the
00017  * License.
00018  *
00019  * The Original Code is mozilla.org code.
00020  *
00021  * The Initial Developer of the Original Code is
00022  * Netscape Communications Corporation.
00023  * Portions created by the Initial Developer are Copyright (C) 2001
00024  * the Initial Developer. All Rights Reserved.
00025  *
00026  * Contributor(s):
00027  *   Brian Stell <bstell@netscape.com>
00028  *
00029  * Alternatively, the contents of this file may be used under the terms of
00030  * either of the GNU General Public License Version 2 or later (the "GPL"),
00031  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00032  * in which case the provisions of the GPL or the LGPL are applicable instead
00033  * of those above. If you wish to allow use of your version of this file only
00034  * under the terms of either the GPL or the LGPL, and not to allow others to
00035  * use your version of this file under the terms of the MPL, indicate your
00036  * decision by deleting the provisions above and replace them with the notice
00037  * and other provisions required by the GPL or the LGPL. If you do not delete
00038  * the provisions above, a recipient may use your version of this file under
00039  * the terms of any one of the MPL, the GPL or the LGPL.
00040  *
00041  * ***** END LICENSE BLOCK ***** */
00042 
00043 #include <X11/Xlib.h>
00044 #include <X11/Xutil.h>
00045 #include "gfx-config.h"
00046 #include "nsCRT.h"
00047 #include "nspr.h"
00048 #include "nsAntiAliasedGlyph.h"
00049 #include "nsX11AlphaBlend.h"
00050 
00051 #define ENABLE_X11ALPHA_BLEND_PRINTF 1
00052 
00053 #if ENABLE_X11ALPHA_BLEND_PRINTF
00054 static PRUint32 gX11AlphaBlendDebug;
00055 # include <stdio.h>
00056 #define NS_X11_ALPHA_BLEND_DEBUG   0x01
00057 
00058 #define DEBUG_PRINTF_MACRO(x, type) \
00059             PR_BEGIN_MACRO \
00060               if (gX11AlphaBlendDebug & (type)) { \
00061                 printf x ; \
00062                 printf(", %s %d\n", __FILE__, __LINE__); \
00063               } \
00064             PR_END_MACRO 
00065 
00066 #else /* ENABLE_X11ALPHA_BLEND_PRINTF */
00067 
00068 #define DEBUG_PRINTF_MACRO(x, type) \
00069             PR_BEGIN_MACRO \
00070             PR_END_MACRO 
00071 
00072 #endif /* ENABLE_X11ALPHA_BLEND_PRINTF */
00073 
00074 #define X11ALPHA_BLEND_PRINTF(x) \
00075          DEBUG_PRINTF_MACRO(x, NS_X11_ALPHA_BLEND_DEBUG)
00076 
00077 static void dummy_BlendPixel(XImage *, int x, int y, nscolor color, int a);
00078 #ifdef DEBUG
00079 static void nsBlendPixel555   (XImage *, int x, int y, nscolor color, int a);
00080 static void nsBlendPixel555_br(XImage *, int x, int y, nscolor color, int a);
00081 static void nsBlendPixel565   (XImage *, int x, int y, nscolor color, int a);
00082 static void nsBlendPixel565_br(XImage *, int x, int y, nscolor color, int a);
00083 static void nsBlendPixel888_lsb(XImage *, int x, int y, nscolor color, int a);
00084 static void nsBlendPixel888_msb(XImage *, int x, int y, nscolor color, int a);
00085 static void nsBlendPixel0888   (XImage *, int x, int y, nscolor color, int a);
00086 static void nsBlendPixel0888_br(XImage *, int x, int y, nscolor color, int a);
00087 #else
00088 # define nsBlendPixel555     dummy_BlendPixel
00089 # define nsBlendPixel555_br  dummy_BlendPixel
00090 # define nsBlendPixel565     dummy_BlendPixel
00091 # define nsBlendPixel565_br  dummy_BlendPixel
00092 # define nsBlendPixel888_lsb dummy_BlendPixel
00093 # define nsBlendPixel888_msb dummy_BlendPixel
00094 # define nsBlendPixel0888    dummy_BlendPixel
00095 # define nsBlendPixel0888_br dummy_BlendPixel
00096 #endif
00097 
00098 static void nsBlendMonoImage555   (XImage*,nsAntiAliasedGlyph*,
00099                                    PRUint8*, nscolor, int, int);
00100 static void nsBlendMonoImage555_br(XImage*,nsAntiAliasedGlyph*,
00101                                    PRUint8*, nscolor, int, int);
00102 static void nsBlendMonoImage565   (XImage*,nsAntiAliasedGlyph*,
00103                                    PRUint8*, nscolor, int, int);
00104 static void nsBlendMonoImage565_br(XImage*,nsAntiAliasedGlyph*,
00105                                    PRUint8*, nscolor, int, int);
00106 static void nsBlendMonoImage888_lsb(XImage*,nsAntiAliasedGlyph*,
00107                                     PRUint8*, nscolor, int, int);
00108 static void nsBlendMonoImage888_msb(XImage*,nsAntiAliasedGlyph*,
00109                                     PRUint8*, nscolor, int, int);
00110 static void nsBlendMonoImage0888(XImage*,nsAntiAliasedGlyph*,
00111                                  PRUint8*, nscolor, int, int);
00112 static void nsBlendMonoImage0888_br(XImage*,nsAntiAliasedGlyph*,
00113                                  PRUint8*, nscolor, int, int);
00114 static nscolor nsPixelToNscolor555   (unsigned long aPixel);
00115 static nscolor nsPixelToNscolor565   (unsigned long aPixel);
00116 static nscolor nsPixelToNscolor888_lsb(unsigned long aPixel);
00117 static nscolor nsPixelToNscolor888_msb(unsigned long aPixel);
00118 
00119 static void dummy_BlendMonoImage(XImage *, nsAntiAliasedGlyph *, PRUint8*,
00120                                  nscolor, int, int);
00121 static nscolor dummy_PixelToNSColor(unsigned long);
00122 
00123 // sPixelToNSColor
00124 //
00125 // X11AlphaBlend Globals
00126 //
00127 PRBool         nsX11AlphaBlend::sAvailable;
00128 PRUint16       nsX11AlphaBlend::sBitmapPad;
00129 PRUint16       nsX11AlphaBlend::sBitsPerPixel;
00130 blendGlyph     nsX11AlphaBlend::sBlendMonoImage;
00131 blendPixel     nsX11AlphaBlend::sBlendPixel;
00132 PRUint16       nsX11AlphaBlend::sBytesPerPixel;
00133 int            nsX11AlphaBlend::sDepth;
00134 PRBool         nsX11AlphaBlend::sInited;
00135 pixelToNSColor nsX11AlphaBlend::sPixelToNSColor;
00136 
00137 void
00138 nsX11AlphaBlend::ClearGlobals()
00139 {
00140   sAvailable          = PR_FALSE;
00141   sBitmapPad          = 0;
00142   sBitsPerPixel       = 0;
00143   sBlendMonoImage     = dummy_BlendMonoImage;
00144   sBlendPixel         = dummy_BlendPixel;
00145   sBytesPerPixel      = 1;
00146   sDepth              = 0;
00147   sInited             = PR_FALSE;
00148   sPixelToNSColor     = dummy_PixelToNSColor;
00149 }
00150 
00151 void
00152 nsX11AlphaBlendFreeGlobals()
00153 {
00154   nsX11AlphaBlend::FreeGlobals();
00155 }
00156 
00157 void
00158 nsX11AlphaBlend::FreeGlobals()
00159 {
00160   ClearGlobals();
00161 }
00162 
00163 nsresult
00164 nsX11AlphaBlendInitGlobals(Display *aDisplay)
00165 {
00166   X11ALPHA_BLEND_PRINTF(("initialize X11AlphaBlend"));
00167 
00168   nsresult rv = nsX11AlphaBlend::InitGlobals(aDisplay);
00169 
00170   return rv;
00171 }
00172 
00173 nsresult
00174 nsX11AlphaBlend::InitGlobals(Display *aDisplay)
00175 {
00176   NS_ASSERTION(sInited==PR_FALSE, "InitGlobals called more than once");
00177   // set all the globals to default values
00178 #if ENABLE_X11ALPHA_BLEND_PRINTF
00179   char* debug = PR_GetEnv("NS_ALPHA_BLEND_DEBUG");
00180   if (debug) {
00181     PR_sscanf(debug, "%lX", &gX11AlphaBlendDebug);
00182   }
00183 #endif
00184 
00185   ClearGlobals();
00186   if (!InitLibrary(aDisplay))
00187     return NS_ERROR_NOT_AVAILABLE;
00188 
00189   return NS_OK;
00190 }
00191 
00192 PRBool
00193 nsX11AlphaBlend::InitLibrary(Display *aDisplay)
00194 {
00195   if (sInited)
00196     return sAvailable;
00197 
00198   sInited = PR_TRUE;
00199 
00200   Visual *visual = DefaultVisual(aDisplay,DefaultScreen(aDisplay));
00201   if (visual->c_class != TrueColor) {
00202     X11ALPHA_BLEND_PRINTF(("unsuppored visual class %d", visual->c_class));
00203     return PR_FALSE;
00204   }
00205 
00206   //
00207   // Get an XImage to get the image information
00208   //
00209   Window root_win = RootWindow(aDisplay, DefaultScreen(aDisplay));
00210   XImage *img = XGetImage(aDisplay, root_win, 0, 0, 1, 1, 0xffffffff, ZPixmap);
00211   NS_ASSERTION(img, "InitGlobals: XGetImage failed");
00212   if (!img)
00213     return PR_FALSE;
00214   int byte_order = img->byte_order;
00215   sBitmapPad     = img->bitmap_pad;
00216   sBitsPerPixel  = img->bits_per_pixel;
00217   sDepth         = img->depth;
00218   int blue_mask  = img->blue_mask;
00219   int green_mask = img->green_mask;
00220   int red_mask   = img->red_mask;
00221   XDestroyImage(img);
00222 
00223   PRBool same_byte_order;
00224 #ifdef IS_LITTLE_ENDIAN
00225   X11ALPHA_BLEND_PRINTF(("endian           = little"));
00226   same_byte_order = (byte_order == LSBFirst);
00227 #elif IS_BIG_ENDIAN
00228   X11ALPHA_BLEND_PRINTF(("endian           = big"));
00229   same_byte_order = (byte_order == MSBFirst);
00230 #else
00231 #  error neither IS_LITTLE_ENDIAN or IS_BIG_ENDIAN is defined
00232 #endif
00233 
00234   X11ALPHA_BLEND_PRINTF(("byte_order       = %s", byte_order?"MSB":"LSB"));
00235   X11ALPHA_BLEND_PRINTF(("same_byte_order  = %d", same_byte_order));
00236 
00237   X11ALPHA_BLEND_PRINTF(("sBitmapPad       = %d", sBitmapPad));
00238   X11ALPHA_BLEND_PRINTF(("sDepth           = %d", sDepth));
00239   X11ALPHA_BLEND_PRINTF(("sBitsPerPixel    = %d", sBitsPerPixel));
00240 
00241   if (sBitsPerPixel <= 16)
00242     sBytesPerPixel = 2;
00243   else if (sBitsPerPixel <= 32)
00244     sBytesPerPixel = 4;
00245   else {
00246     X11ALPHA_BLEND_PRINTF(("sBitsPerPixel %d: not supported", sBitsPerPixel));
00247     return PR_FALSE;
00248   }
00249   X11ALPHA_BLEND_PRINTF(("sBytesPerPixel   = %d", sBytesPerPixel));
00250 
00251   if (sBitsPerPixel==16)  {
00252     if ((red_mask==0x7C00) && (green_mask==0x3E0) && (blue_mask==0x1F)) {
00253       // 555
00254       sAvailable           = PR_TRUE;
00255       if (same_byte_order) {
00256         sPixelToNSColor = &nsPixelToNscolor555;
00257         sBlendPixel     = &nsBlendPixel555;
00258         sBlendMonoImage = &nsBlendMonoImage555;
00259       }
00260       else {
00261         sPixelToNSColor = &nsPixelToNscolor555;
00262         sBlendPixel     = &nsBlendPixel555_br;
00263         sBlendMonoImage = &nsBlendMonoImage555_br;
00264       }
00265     }
00266     else if ((red_mask==0xF800) && (green_mask==0x7E0) && (blue_mask==0x1F)) {
00267       // 565
00268       sAvailable           = PR_TRUE;
00269       if (same_byte_order) {
00270         sPixelToNSColor = &nsPixelToNscolor565;
00271         sBlendPixel     = &nsBlendPixel565;
00272         sBlendMonoImage = &nsBlendMonoImage565;
00273       }
00274       else {
00275         sPixelToNSColor = &nsPixelToNscolor565;
00276         sBlendPixel     = &nsBlendPixel565_br;
00277         sBlendMonoImage = &nsBlendMonoImage565_br;
00278       }
00279     }
00280   }
00281   else if (sBitsPerPixel==24)  {
00282     if ((red_mask==0xFF0000) && (green_mask==0xFF00) && (blue_mask==0xFF)) {
00283       // 888
00284       sAvailable           = PR_TRUE;
00285       if (same_byte_order) {
00286         sPixelToNSColor = &nsPixelToNscolor888_lsb;
00287         sBlendPixel     = &nsBlendPixel888_lsb;
00288         sBlendMonoImage = &nsBlendMonoImage888_lsb;
00289       }
00290       else {
00291         sPixelToNSColor = &nsPixelToNscolor888_msb;
00292         sBlendPixel     = &nsBlendPixel888_msb;
00293         sBlendMonoImage = &nsBlendMonoImage888_msb;
00294       }
00295     }
00296   }
00297   else if (sBitsPerPixel==32)  {
00298       // 0888
00299       sAvailable           = PR_TRUE;
00300       if (same_byte_order) {
00301         sPixelToNSColor = &nsPixelToNscolor888_lsb;
00302         sBlendPixel     = &nsBlendPixel0888;
00303         sBlendMonoImage = &nsBlendMonoImage0888;
00304       }
00305       else {
00306         sPixelToNSColor = &nsPixelToNscolor888_lsb;
00307         sBlendPixel     = &nsBlendPixel0888_br;
00308         sBlendMonoImage = &nsBlendMonoImage0888_br;
00309       }
00310   }
00311   else {
00312     sAvailable = PR_FALSE;
00313     NS_ASSERTION(0, "X11AlphaBlend: unsupported framebuffer depth");
00314     goto nsX11AlphaBlend__InitLibrary_error;
00315   }
00316   return sAvailable;
00317 
00318 nsX11AlphaBlend__InitLibrary_error:
00319   // clean everything up but note that init was called
00320   FreeGlobals();
00321   sInited = PR_TRUE;
00322   return(sAvailable);
00323 }
00324 
00325 nscolor
00326 nsX11AlphaBlend::PixelToNSColor(unsigned long aPixel)
00327 {
00328   nscolor color = (*sPixelToNSColor)(aPixel);
00329   return color;
00330 }
00331 
00333 //
00334 // miscellaneous routines in alphabetic order
00335 //
00337 
00338 #ifdef DEBUG
00339 void
00340 AADrawBox(XImage *aXImage,
00341         PRInt32 aX1, PRInt32 aY1,
00342         PRInt32 aWidth, PRInt32 aHeight,
00343         nscolor aColor, PRUint8 aAlpha)
00344 {
00345   PRInt32 i;
00346   blendPixel blendPixelFunc = nsX11AlphaBlend::GetBlendPixel();
00347   if (aWidth<=0 || aHeight<=0)
00348     return;
00349   for (i=1; i<aWidth-1; i++) {
00350     if (i%16 == 0) continue; // let the underlaying color show
00351     (*blendPixelFunc)(aXImage, i+aX1, aY1, aColor, aAlpha);
00352     (*blendPixelFunc)(aXImage, i+aX1, aY1+aHeight-1, aColor, aAlpha);
00353   }
00354   for (i=0; i<aHeight; i++) {
00355     if (i%16 == 0) continue; // let the underlaying color show
00356     (*blendPixelFunc)(aXImage, aX1, i+aY1, aColor, aAlpha);
00357     (*blendPixelFunc)(aXImage, aX1+aWidth-1, i+aY1, aColor, aAlpha);
00358   }
00359 }
00360 #endif
00361 
00362 static void
00363 dummy_BlendPixel(XImage *, int x, int y, nscolor color, int a)
00364 {
00365 }
00366 
00367 static void
00368 dummy_BlendMonoImage(XImage *, nsAntiAliasedGlyph *, PRUint8*, nscolor,
00369                      int, int)
00370 {
00371 }
00372 
00373 static nscolor
00374 dummy_PixelToNSColor(unsigned long color)
00375 {
00376   return 0;
00377 }
00378 
00379 XImage*
00380 nsX11AlphaBlend::GetBackground(Display *aDisplay, int aScreen,
00381                                Drawable aDrawable,
00382                                PRInt32 aX, PRInt32 aY,
00383                                PRUint32 aWidth,  PRUint32 aHeight)
00384 {
00385   PRBool any_offscreen = PR_FALSE;
00386   XImage *ximage;
00387 
00388   //
00389   // get the background
00390   //
00391   // bound the request to inside the window
00392   PRInt32 x_skip = 0;
00393   if (aX < 0) {
00394     x_skip = -aX;
00395     any_offscreen = PR_TRUE;
00396   }
00397   PRInt32 y_skip = 0;
00398   if (aY < 0) {
00399     y_skip = -(aY);
00400     any_offscreen = PR_TRUE;
00401   }
00402   PRInt32 copy_width  = aWidth  - x_skip;
00403   PRInt32 copy_height = aHeight - y_skip;
00404 
00405   Window root;
00406   int win_x, win_y;
00407   unsigned int win_width, win_height, win_border_width, win_depth;
00408   if (!XGetGeometry(aDisplay, aDrawable, &root, &win_x, &win_y,
00409                     &win_width, &win_height, &win_border_width, &win_depth)) {
00410     NS_ASSERTION(0, "XGetGeometry");
00411   }
00412   if ((PRUint32)(aX+x_skip+aWidth) > win_width) {
00413     copy_width = MIN(copy_width, (int)win_width - (aX+x_skip));
00414     any_offscreen = PR_TRUE;
00415   }
00416   if ((PRUint32)(aY+y_skip+aHeight) > win_height) {
00417     copy_height = MIN(copy_height, (int)win_height - (aY+y_skip));
00418     any_offscreen = PR_TRUE;
00419   }
00420 
00421   PRUint32 root_win_width, root_win_height;
00422   root_win_width  = DisplayWidth(aDisplay, aScreen);
00423   root_win_height = DisplayHeight(aDisplay, aScreen);
00424 
00425   if ((PRUint32)(aX+x_skip+aWidth) > root_win_width) {
00426     copy_width = MIN(copy_width, (int)root_win_width - (aX+x_skip));
00427     any_offscreen = PR_TRUE;
00428   }
00429   if ((PRUint32)(aY+y_skip+aHeight) > root_win_height) {
00430     copy_height = MIN(copy_height, (int)root_win_height - (aY+y_skip));
00431     any_offscreen = PR_TRUE;
00432   }
00433   if ((copy_width<=0) || (copy_height<=0))
00434     return nsnull; // nothing visible
00435 
00436   // get the background image
00437   // if any part is off screen XGetImage will fail, so we XCreateImage 
00438   // the image and use XGetSubImage to get the available background pixels
00439   if (any_offscreen) {
00440     char *data = (char *)nsMemory::Alloc(aWidth * aHeight * sBytesPerPixel);
00441     if (!data) {
00442       return nsnull;
00443     }
00444     XImage *super_ximage = XCreateImage(aDisplay,
00445                                  DefaultVisual(aDisplay, aScreen),
00446                                  DefaultDepth(aDisplay, aScreen), ZPixmap,
00447                                  0, data, aWidth, aHeight,
00448                                  sBitmapPad, aWidth*sBytesPerPixel);
00449     if (!super_ximage) {
00450       NS_ASSERTION(super_ximage, "failed to create the super image");
00451       return nsnull;
00452     }
00453     ximage = XGetSubImage(aDisplay, aDrawable,
00454                           aX+x_skip, aY+y_skip, 
00455                           copy_width, copy_height,
00456                           AllPlanes, ZPixmap, super_ximage, x_skip, y_skip);
00457     if (!ximage) {
00458       NS_ASSERTION(ximage, "failed to get the sub image");
00459       XDestroyImage(super_ximage);
00460       return nsnull;
00461     }
00462      ximage = super_ximage;
00463   }
00464   else {
00465     ximage = XGetImage(aDisplay, aDrawable, aX, aY, aWidth, aHeight,
00466                        AllPlanes, ZPixmap);
00467   }
00468 
00469   NS_ASSERTION(ximage, "failed to get the image");
00470   return ximage;
00471 }
00472 
00473 //
00474 // 24 bit color, accessed in a 32 bit number
00475 //
00476 static void
00477 nsBlendMonoImage0888(XImage *ximage, nsAntiAliasedGlyph * glyph,
00478                      PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00479 {
00480   PRUint32 src_a, dst_a;
00481 
00482   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00483   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00484   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00485   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00486   PRUint16 r = NS_GET_R(color);
00487   PRUint16 g = NS_GET_G(color);
00488   PRUint16 b = NS_GET_B(color);
00489 
00490   NS_ASSERTION(((ximage->data-(char*)0)&3)==0,"possible alignment error");
00491   NS_ASSERTION((ximage->bytes_per_line&3)==0,"possible alignment error");
00492   PRUint8 *glyph_p = glyph->GetBuffer();
00493   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00494                              + 4*xOff + (yOff * ximage->bytes_per_line);
00495 
00496   for (int row=0; row<xfer_height; row++) {
00497     PRUint32 *image_p = (PRUint32 *)imageLineStart;
00498     for (int j=0; j<xfer_width; j++,image_p++,glyph_p++) {
00499       src_a = *glyph_p;
00500       if (src_a == 0)
00501         continue;
00502       src_a = aWeightTable[src_a]; // weight the image
00503       PRUint32 dst_pixel = *image_p;
00504       PRUint32 hibits = dst_pixel & 0xFF000000;
00505       if (src_a == 255) {
00506         *image_p = hibits | (r << 16) | (g << 8) + b;
00507         continue;
00508       }
00509       dst_a = 255 - src_a;
00510 
00511       PRUint32 red   = ((r*src_a) + (((dst_pixel>>16)&0xFF) * dst_a)) >> 8;
00512       PRUint32 green = ((g*src_a) + (((dst_pixel>>8) &0xFF) * dst_a)) >> 8;
00513       PRUint32 blue  = ((b*src_a) + (( dst_pixel     &0xFF) * dst_a)) >> 8;
00514       *image_p = hibits | (red << 16) | (green << 8) | blue;
00515     }
00516     glyph_p += -xfer_width + glyph->GetBufferWidth();
00517     imageLineStart += ximage->bytes_per_line;
00518   }
00519 }
00520 
00521 //
00522 // 24 bit color, accessed in a 32 bit number
00523 //
00524 static void
00525 nsBlendMonoImage0888_br(XImage *ximage, nsAntiAliasedGlyph * glyph,
00526                      PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00527 {
00528   PRUint32 src_a, dst_a;
00529 
00530   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00531   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00532   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00533   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00534   PRUint16 r = NS_GET_R(color);
00535   PRUint16 g = NS_GET_G(color);
00536   PRUint16 b = NS_GET_B(color);
00537 
00538   PRUint8 *glyph_p = glyph->GetBuffer();
00539   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00540                              + 4*xOff + (yOff * ximage->bytes_per_line);
00541 
00542   for (int row=0; row<xfer_height; row++) {
00543     PRUint32 *image_p = (PRUint32 *)imageLineStart;
00544     for (int j=0; j<xfer_width; j++,image_p++,glyph_p++) {
00545       src_a = *glyph_p;
00546       if (src_a == 0)
00547         continue;
00548       src_a = aWeightTable[src_a]; // weight the image
00549       PRUint32 dst_pixel = *image_p;
00550       PRUint32 lowbits = dst_pixel & 0x000000FF;
00551       if (src_a == 255) {
00552         *image_p = (b << 24) | (g << 16) + (r << 8) | lowbits;
00553         continue;
00554       }
00555       dst_a = 255 - src_a;
00556 
00557       PRUint32 red   = ((r*src_a) + (((dst_pixel>> 8) &0xFF) * dst_a)) >> 8;
00558       PRUint32 green = ((g*src_a) + (((dst_pixel>>16) &0xFF) * dst_a)) >> 8;
00559       PRUint32 blue  = ((b*src_a) + (((dst_pixel>>24) &0xFF) * dst_a)) >> 8;
00560       *image_p = (blue << 24) | (green << 16) + (red << 8) | lowbits;
00561     }
00562     glyph_p += -xfer_width + glyph->GetBufferWidth();
00563     imageLineStart += ximage->bytes_per_line;
00564   }
00565 }
00566 
00567 //
00568 // 15 bit color, accessed in a 16 bit number
00569 //
00570 static void
00571 nsBlendMonoImage555(XImage *ximage, nsAntiAliasedGlyph * glyph,
00572                     PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00573 {
00574   PRUint16 src_a, dst_a;
00575 
00576   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00577   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00578   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00579   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00580   PRUint16 r = NS_GET_R(color);
00581   PRUint16 g = NS_GET_G(color);
00582   PRUint16 b = NS_GET_B(color);
00583 
00584   PRUint8 *glyph_p = glyph->GetBuffer();
00585   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00586                              + 2*xOff + (yOff * ximage->bytes_per_line);
00587 
00588   for (int row=0; row<xfer_height; row++) {
00589     PRUint16 *image_p = (PRUint16 *)imageLineStart;
00590     for (int j=0; j<xfer_width; j++,image_p++,glyph_p++) {
00591       src_a = *glyph_p;
00592       if (src_a == 0)
00593         continue;
00594       src_a = aWeightTable[src_a]; // weight the image
00595 
00596       if (src_a == 255) {
00597         *image_p = ((r&0xF8)<<7) | ((g&0xF8)<<2) | ((b) >> 3);
00598                    // the long version
00599                    //(((r>>3)&0x1F)<<10) | (((g>>3)&0x1F)<<5) | (((b>>3)&0x1F));
00600         continue;
00601       }
00602       dst_a = 255 - src_a;
00603 
00604       PRUint16 dst_pixel = *image_p;
00605       PRUint16 red   = ((r*src_a) + (((dst_pixel>>7)&0xF8) * dst_a)) >> 8;
00606       PRUint16 green = ((g*src_a) + (((dst_pixel>>2)&0xF8) * dst_a)) >> 8;
00607       PRUint16 blue  = ((b*src_a) + (((dst_pixel<<3)&0xF8) * dst_a)) >> 8;
00608       *image_p = ((red&0xF8)<<7) | ((green&0xF8)<<2) | ((blue) >> 3);
00609     }
00610     glyph_p += -xfer_width + glyph->GetBufferWidth();
00611     imageLineStart += ximage->bytes_per_line;
00612   }
00613 }
00614 
00615 //
00616 // 15 bit color, accessed in a 16 bit number, byte reversed
00617 //
00618 static void
00619 nsBlendMonoImage555_br(XImage *ximage, nsAntiAliasedGlyph * glyph,
00620                     PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00621 {
00622   PRUint16 src_a, dst_a;
00623 
00624   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00625   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00626   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00627   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00628   PRUint16 r = NS_GET_R(color);
00629   PRUint16 g = NS_GET_G(color);
00630   PRUint16 b = NS_GET_B(color);
00631 
00632   PRUint8 *glyph_p = glyph->GetBuffer();
00633   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00634                              + 2*xOff + (yOff * ximage->bytes_per_line);
00635 
00636   for (int row=0; row<xfer_height; row++) {
00637     PRUint16 *image_p = (PRUint16 *)imageLineStart;
00638     for (int j=0; j<xfer_width; j++,image_p++,glyph_p++) {
00639       src_a = *glyph_p;
00640       if (src_a == 0)
00641         continue;
00642       src_a = aWeightTable[src_a]; // weight the image
00643 
00644       if (src_a == 255) {
00645         *image_p =  ((r&0xF8)   >> 1) |
00646                     ((g&0xC0)>> 6) | ((g&0x38)<<10) |
00647                     ((b&0xF8)<< 5);
00648         continue;
00649       }
00650       dst_a = 255 - src_a;
00651 
00652       PRUint16 dst_pixel = *image_p;
00653       // unreversed: --:R7:R6:R5:R4:R3:G7:G6  G5:G4:G3:B7:B6:B5:B4:B3
00654       //   reversed: G5:G4:G3:B7:B6:B5:B4:B3  --:R7:R6:R5:R4:R3:G7:G6
00655       PRUint16 pixel_r =  (dst_pixel>>1) & 0xF8;
00656       PRUint16 pixel_g = ((dst_pixel<<6) & 0xC0) | ((dst_pixel>>10) & 0x38);
00657       PRUint16 pixel_b =  (dst_pixel>>5) & 0xF8;
00658 
00659       PRUint16 red   = ((r*src_a) + (pixel_r * dst_a)) >> 8;
00660       PRUint16 green = ((g*src_a) + (pixel_g * dst_a)) >> 8;
00661       PRUint16 blue  = ((b*src_a) + (pixel_b * dst_a)) >> 8;
00662       *image_p = ((red  &0xF8)>> 1) |
00663                  ((green&0xC0)>> 6) | ((green&0x38)<<10) |
00664                  ((blue &0xF8)<< 5);
00665     }
00666     glyph_p += -xfer_width + glyph->GetBufferWidth();
00667     imageLineStart += ximage->bytes_per_line;
00668   }
00669 }
00670 
00671 //
00672 // 16 bit color, accessed in a 16 bit number
00673 //
00674 static void
00675 nsBlendMonoImage565(XImage *ximage, nsAntiAliasedGlyph * glyph,
00676                     PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00677 {
00678   PRUint16 src_a, dst_a;
00679 
00680   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00681   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00682   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00683   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00684   PRUint16 r = NS_GET_R(color);
00685   PRUint16 g = NS_GET_G(color);
00686   PRUint16 b = NS_GET_B(color);
00687 
00688   PRUint8 *glyph_p = glyph->GetBuffer();
00689   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00690                              + 2*xOff + (yOff * ximage->bytes_per_line);
00691 
00692   for (int row=0; row<xfer_height; row++) {
00693     PRUint16 *image_p = (PRUint16 *)imageLineStart;
00694     for (int j=0; j<xfer_width; j++,image_p++,glyph_p++) {
00695       src_a = *glyph_p;
00696       if (src_a == 0)
00697         continue;
00698       src_a = aWeightTable[src_a]; // weight the image
00699 
00700       if (src_a == 255) {
00701         *image_p = ((r&0xF8)<<8) | ((g&0xFC)<<3) | ((b) >> 3);
00702         continue;
00703       }
00704       dst_a = 255 - src_a;
00705 
00706       PRUint32 dst_pixel = *image_p;
00707       PRUint16 red   = ((r*src_a) + (((dst_pixel>>8)&0xF8) * dst_a)) >> 8;
00708       PRUint16 green = ((g*src_a) + (((dst_pixel>>3)&0xFC) * dst_a)) >> 8;
00709       PRUint16 blue  = ((b*src_a) + (((dst_pixel<<3)&0xF8) * dst_a)) >> 8;
00710       *image_p = ((red&0xF8)<<8) | ((green&0xFC)<<3) | ((blue) >> 3);
00711     }
00712     glyph_p += -xfer_width + glyph->GetBufferWidth();
00713     imageLineStart += ximage->bytes_per_line;
00714   }
00715 }
00716 
00717 //
00718 // 16 bit color, accessed in a 16 bit number, byte reversed
00719 //
00720 static void
00721 nsBlendMonoImage565_br(XImage *ximage, nsAntiAliasedGlyph * glyph,
00722                     PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00723 {
00724   PRUint16 src_a, dst_a;
00725 
00726   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00727   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00728   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00729   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00730   PRUint16 r = NS_GET_R(color);
00731   PRUint16 g = NS_GET_G(color);
00732   PRUint16 b = NS_GET_B(color);
00733 
00734   PRUint8 *glyph_p = glyph->GetBuffer();
00735   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00736                              + 2*xOff + (yOff * ximage->bytes_per_line);
00737 
00738   for (int row=0; row<xfer_height; row++) {
00739     PRUint16 *image_p = (PRUint16 *)imageLineStart;
00740     for (int j=0; j<xfer_width; j++,image_p++,glyph_p++) {
00741       src_a = *glyph_p;
00742       if (src_a == 0)
00743         continue;
00744       src_a = aWeightTable[src_a]; // weight the image
00745       if (src_a == 255) {
00746         *image_p =   (r&0xF8) |
00747                     ((g&0xE0)>> 5) | ((g&0x1C)<<11) |
00748                     ((b&0xF8)<< 5);
00749         continue;
00750       }
00751       dst_a = 255 - src_a;
00752 
00753       PRUint16 dst_pixel = *image_p;
00754       // unreversed: R7:R6:R5:R4:R3:G7:G6:G5  G4:G3:G2:B7:B6:B5:B4:B3
00755       //   reversed: G4:G3:G2:B7:B6:B5:B4:B3  R7:R6:R5:R4:R3:G7:G6:G5
00756       PRUint16 pixel_r =  (dst_pixel)    & 0xF8;
00757       PRUint16 pixel_g = ((dst_pixel<<5) & 0xE0) | ((dst_pixel>>11) & 0x1C);
00758       PRUint16 pixel_b =  (dst_pixel>>5) & 0xF8;
00759 
00760       PRUint16 red   = ((r*src_a) + (pixel_r * dst_a)) >> 8;
00761       PRUint16 green = ((g*src_a) + (pixel_g * dst_a)) >> 8;
00762       PRUint16 blue  = ((b*src_a) + (pixel_b * dst_a)) >> 8;
00763       *image_p =  (red  &0xF8) |
00764                  ((green&0xE0)>> 5) | ((green&0x1C)<<11) |
00765                  ((blue &0xF8)<< 5);
00766     }
00767     glyph_p += -xfer_width + glyph->GetBufferWidth();
00768     imageLineStart += ximage->bytes_per_line;
00769   }
00770 }
00771 
00772 //
00773 // 24 bit color, accessed in a 3*8 bit numbers, little endian
00774 //
00775 static void
00776 nsBlendMonoImage888_lsb(XImage *ximage, nsAntiAliasedGlyph * glyph,
00777                    PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00778 {
00779   PRUint32 src_a, dst_a;
00780 
00781   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00782   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00783   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00784   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00785   PRUint16 r = NS_GET_R(color);
00786   PRUint16 g = NS_GET_G(color);
00787   PRUint16 b = NS_GET_B(color);
00788 
00789   PRUint8 *glyph_p = glyph->GetBuffer();
00790   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00791                              + 3*xOff + (yOff * ximage->bytes_per_line);
00792 
00793   for (int row=0; row<xfer_height; row++) {
00794     PRUint8 *image_p = (PRUint8 *)imageLineStart;
00795     for (int j=0; j<xfer_width; j++,image_p+=3,glyph_p++) {
00796       src_a = *glyph_p;
00797       if (src_a == 0)
00798         continue;
00799       src_a = aWeightTable[src_a]; // weight the image
00800 
00801       if (src_a == 255) {
00802         image_p[2] = r;
00803         image_p[1] = g;
00804         image_p[0] = b;
00805         continue;
00806       }
00807       dst_a = 255 - src_a;
00808       image_p[2] = ((r*src_a) + (image_p[2]*dst_a)) >> 8;
00809       image_p[1] = ((g*src_a) + (image_p[1]*dst_a)) >> 8;
00810       image_p[0] = ((b*src_a) + (image_p[0]*dst_a)) >> 8;
00811     }
00812     glyph_p += -xfer_width + glyph->GetBufferWidth();
00813     imageLineStart += ximage->bytes_per_line;
00814   }
00815 }
00816 
00817 //
00818 // 24 bit color, accessed in a 3*8 bit numbers, big endian
00819 //
00820 static void
00821 nsBlendMonoImage888_msb(XImage *ximage, nsAntiAliasedGlyph * glyph,
00822                    PRUint8 *aWeightTable, nscolor color, int xOff, int yOff)
00823 {
00824   PRUint32 src_a, dst_a;
00825 
00826   int xfer_width  = MIN((int)glyph->GetWidth(),  ximage->width-xOff);
00827   int xfer_height = MIN((int)glyph->GetHeight(), ximage->height-yOff);
00828   NS_ASSERTION(xfer_width==(int)glyph->GetWidth(), "image not wide enough");
00829   NS_ASSERTION(xfer_height==(int)glyph->GetHeight(), "image not tall enough");
00830   PRUint16 r = NS_GET_R(color);
00831   PRUint16 g = NS_GET_G(color);
00832   PRUint16 b = NS_GET_B(color);
00833 
00834   PRUint8 *glyph_p = glyph->GetBuffer();
00835   PRUint8 *imageLineStart = (PRUint8 *)ximage->data
00836                              + 3*xOff + (yOff * ximage->bytes_per_line);
00837 
00838   for (int row=0; row<xfer_height; row++) {
00839     PRUint8 *image_p = (PRUint8 *)imageLineStart;
00840     for (int j=0; j<xfer_width; j++,image_p+=3,glyph_p++) {
00841       src_a = *glyph_p;
00842       if (src_a == 0)
00843         continue;
00844       src_a = aWeightTable[src_a]; // weight the image
00845 
00846       if (src_a == 255) {
00847         image_p[0] = r;
00848         image_p[1] = g;
00849         image_p[2] = b;
00850         continue;
00851       }
00852       dst_a = 255 - src_a;
00853 
00854       image_p[0] = ((r*src_a) + (image_p[2]*dst_a)) >> 8;
00855       image_p[1] = ((g*src_a) + (image_p[1]*dst_a)) >> 8;
00856       image_p[2] = ((b*src_a) + (image_p[0]*dst_a)) >> 8;
00857     }
00858     glyph_p += -xfer_width + glyph->GetBufferWidth();
00859     imageLineStart += ximage->bytes_per_line;
00860   }
00861 }
00862 
00863 #ifdef DEBUG
00864 static void
00865 nsBlendPixel0888(XImage *ximage, int x, int y, nscolor color, int src_a)
00866 {
00867   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
00868   if (src_a <= 0)
00869     return;
00870 
00871   NS_ASSERTION(x<ximage->width,  "x out of bounds");
00872   NS_ASSERTION(y<ximage->height, "y out of bounds");
00873   if ((x >= ximage->width) || (y >= ximage->height))
00874     return;
00875 
00876   PRUint16 r = NS_GET_R(color);
00877   PRUint16 g = NS_GET_G(color);
00878   PRUint16 b = NS_GET_B(color);
00879 
00880   PRUint32 *pPixel = ((PRUint32*)(ximage->data+(y*ximage->bytes_per_line)))+x;
00881   PRUint32 pixel = *pPixel;
00882   PRUint32 hibits = pixel & 0xFF000000;
00883   if (src_a >= 255) {
00884     *pPixel = hibits | (r << 16) | (g << 8) | b;
00885     return;
00886   }
00887 
00888   PRUint32 dst_a = 255 - src_a;
00889   PRUint32 red   = ((r*src_a) + (((pixel>>16)&0xFF) * dst_a)) >> 8;
00890   PRUint32 green = ((g*src_a) + (((pixel>>8) &0xFF) * dst_a)) >> 8;
00891   PRUint32 blue  = ((b*src_a) + (( pixel     &0xFF) * dst_a)) >> 8;
00892   *pPixel = hibits | (red << 16) | (green << 8) | blue;
00893 }
00894 
00895 static void
00896 nsBlendPixel0888_br(XImage *ximage, int x, int y, nscolor color, int src_a)
00897 {
00898   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
00899   if (src_a <= 0)
00900     return;
00901 
00902   NS_ASSERTION(x<ximage->width,  "x out of bounds");
00903   NS_ASSERTION(y<ximage->height, "y out of bounds");
00904   if ((x >= ximage->width) || (y >= ximage->height))
00905     return;
00906 
00907   PRUint16 r = NS_GET_R(color);
00908   PRUint16 g = NS_GET_G(color);
00909   PRUint16 b = NS_GET_B(color);
00910 
00911   PRUint32 *pPixel = ((PRUint32*)(ximage->data+(y*ximage->bytes_per_line)))+x;
00912   PRUint32 pixel = *pPixel;
00913   PRUint32 lowbits = pixel & 0xFF000000;
00914   if (src_a >= 255) {
00915     *pPixel = lowbits | (b << 24) | (g << 16) | (r<<8);
00916     return;
00917   }
00918 
00919   PRUint32 dst_a = 255 - src_a;
00920   PRUint32 red   = ((r*src_a) + (((pixel>>16)&0xFF) * dst_a)) >> 8;
00921   PRUint32 green = ((g*src_a) + (((pixel>>8) &0xFF) * dst_a)) >> 8;
00922   PRUint32 blue  = ((b*src_a) + (( pixel     &0xFF) * dst_a)) >> 8;
00923   *pPixel = lowbits | (blue << 24) | (green << 16) | (red<<8);
00924 }
00925 
00926 static void
00927 nsBlendPixel555(XImage *ximage, int x, int y, nscolor color, int src_a)
00928 {
00929   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
00930   if (src_a <= 0)
00931     return;
00932 
00933   NS_ASSERTION(x<ximage->width,  "x out of bounds");
00934   NS_ASSERTION(y<ximage->height, "y out of bounds");
00935   if ((x >= ximage->width) || (y >= ximage->height))
00936     return;
00937 
00938   PRUint16 r = NS_GET_R(color);
00939   PRUint16 g = NS_GET_G(color);
00940   PRUint16 b = NS_GET_B(color);
00941 
00942   PRUint16 *pPixel = ((PRUint16*)(ximage->data+(y*ximage->bytes_per_line)))+x;
00943   PRUint16 pixel = *pPixel;
00944   if (src_a >= 255) {
00945     *pPixel = ((r&0xF8)<<7) + ((g&0xF8)<<2) + ((b)>>3);
00946     return;
00947   }
00948 
00949   PRUint16 dst_a = 255 - src_a;
00950 
00951   PRUint16 red   = ((r*src_a) + (((pixel>>7) &0xF8) * dst_a)) >> 8;
00952   PRUint16 green = ((g*src_a) + (((pixel>>2) &0xF8) * dst_a)) >> 8;
00953   PRUint16 blue  = ((b*src_a) + (((pixel<<3) &0xF8) * dst_a)) >> 8;
00954   *pPixel = ((red&0xF8)<<7) + ((green&0xF8)<<2) + ((blue)>>3);
00955 }
00956 
00957 static void
00958 nsBlendPixel555_br(XImage *ximage, int x, int y, nscolor color, int src_a)
00959 {
00960   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
00961   if (src_a <= 0)
00962     return;
00963 
00964   NS_ASSERTION(x<ximage->width,  "x out of bounds");
00965   NS_ASSERTION(y<ximage->height, "y out of bounds");
00966   if ((x >= ximage->width) || (y >= ximage->height))
00967     return;
00968 
00969   PRUint16 r = NS_GET_R(color);
00970   PRUint16 g = NS_GET_G(color);
00971   PRUint16 b = NS_GET_B(color);
00972 
00973   PRUint16 *pPixel = ((PRUint16*)(ximage->data+(y*ximage->bytes_per_line)))+x;
00974   PRUint16 pixel = *pPixel;
00975   if (src_a >= 255) {
00976     *pPixel = ((r&0xF8)   >> 1) |
00977               ((g&0xC0)>> 6) | ((g&0x38)<<10) |
00978               ((b&0xF8)<< 5);
00979     return;
00980   }
00981 
00982   PRUint16 dst_a = 255 - src_a;
00983   // unreversed: --:R7:R6:R5:R4:R3:G7:G6  G5:G4:G3:B7:B6:B5:B4:B3
00984   //   reversed: G5:G4:G3:B7:B6:B5:B4:B3  --:R7:R6:R5:R4:R3:G7:G6
00985   PRUint16 pixel_r =  (pixel>>1) & 0xF8;
00986   PRUint16 pixel_g = ((pixel<<6) & 0xC0) | ((pixel>>10) & 0x38);
00987   PRUint16 pixel_b =  (pixel>>5) & 0xF8;
00988 
00989   PRUint16 red   = ((r*src_a) + (pixel_r * dst_a)) >> 8;
00990   PRUint16 green = ((g*src_a) + (pixel_g * dst_a)) >> 8;
00991   PRUint16 blue  = ((b*src_a) + (pixel_b * dst_a)) >> 8;
00992   *pPixel = ((red&0xF8)   >> 1) |
00993             ((green&0xC0)>> 6) | ((green&0x38)<<10) |
00994             ((blue&0xF8)<< 5);
00995 }
00996 
00997 static void
00998 nsBlendPixel565(XImage *ximage, int x, int y, nscolor color, int src_a)
00999 {
01000   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
01001   if (src_a <= 0)
01002     return;
01003 
01004   NS_ASSERTION(x<ximage->width,  "x out of bounds");
01005   NS_ASSERTION(y<ximage->height, "y out of bounds");
01006   if ((x >= ximage->width) || (y >= ximage->height))
01007     return;
01008 
01009   PRUint16 r = NS_GET_R(color);
01010   PRUint16 g = NS_GET_G(color);
01011   PRUint16 b = NS_GET_B(color);
01012 
01013   PRUint16 *pPixel = ((PRUint16*)(ximage->data+(y*ximage->bytes_per_line)))+x;
01014   PRUint16 pixel = *pPixel;
01015   if (src_a >= 255) {
01016     *pPixel = ((r&0xF8)<<8) + ((g&0xFC)<<3) + ((b)>>3);
01017     return;
01018   }
01019 
01020   PRUint16 dst_a = 255 - src_a;
01021 
01022   PRUint16 red   = ((r*src_a) + (((pixel>>8) &0xF8) * dst_a)) >> 8;
01023   PRUint16 green = ((g*src_a) + (((pixel>>3) &0xFC) * dst_a)) >> 8;
01024   PRUint16 blue  = ((b*src_a) + (((pixel<<3) &0xF8) * dst_a)) >> 8;
01025   *pPixel = ((red&0xF8)<<8) + ((green&0xFC)<<3) + ((blue)>>3);
01026 }
01027 
01028 static void
01029 nsBlendPixel565_br(XImage *ximage, int x, int y, nscolor color, int src_a)
01030 {
01031   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
01032   if (src_a <= 0)
01033     return;
01034 
01035   NS_ASSERTION(x<ximage->width,  "x out of bounds");
01036   NS_ASSERTION(y<ximage->height, "y out of bounds");
01037   if ((x >= ximage->width) || (y >= ximage->height))
01038     return;
01039 
01040   PRUint16 r = NS_GET_R(color);
01041   PRUint16 g = NS_GET_G(color);
01042   PRUint16 b = NS_GET_B(color);
01043 
01044   PRUint16 *pPixel = ((PRUint16*)(ximage->data+(y*ximage->bytes_per_line)))+x;
01045   PRUint16 pixel = *pPixel;
01046   if (src_a >= 255) {
01047     *pPixel =   (r&0xF8) |
01048                ((g&0xE0)>> 5) | ((g&0x1C)<<11) |
01049                ((b&0xF8)<< 5);
01050     return;
01051   }
01052 
01053   PRUint16 dst_a = 255 - src_a;
01054   // unreversed: R7:R6:R5:R4:R3:G7:G6:G5  G4:G3:G2:B7:B6:B5:B4:B3
01055   //   reversed: G4:G3:G2:B7:B6:B5:B4:B3  R7:R6:R5:R4:R3:G7:G6:G5
01056   PRUint16 pixel_r =  (pixel)    & 0xF8;
01057   PRUint16 pixel_g = ((pixel<<5) & 0xE0) | ((pixel>>11) & 0x1C);
01058   PRUint16 pixel_b =  (pixel>>5) & 0xF8;
01059 
01060   PRUint16 red   = ((r*src_a) + (pixel_r * dst_a)) >> 8;
01061   PRUint16 green = ((g*src_a) + (pixel_g * dst_a)) >> 8;
01062   PRUint16 blue  = ((b*src_a) + (pixel_b * dst_a)) >> 8;
01063   *pPixel =   (red&0xF8) |
01064              ((green&0xE0)>> 5) | ((green&0x1C)<<11) |
01065              ((blue&0xF8)<< 5);
01066 }
01067 
01068 static void
01069 nsBlendPixel888_lsb(XImage *ximage, int x, int y, nscolor color, int src_a)
01070 {
01071   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
01072   if (src_a <= 0)
01073     return;
01074 
01075   NS_ASSERTION(x<ximage->width,  "x out of bounds");
01076   NS_ASSERTION(y<ximage->height, "y out of bounds");
01077   if ((x >= ximage->width) || (y >= ximage->height))
01078     return;
01079 
01080   PRUint16 r = NS_GET_R(color);
01081   PRUint16 g = NS_GET_G(color);
01082   PRUint16 b = NS_GET_B(color);
01083 
01084   PRUint8 *pPixel = ((PRUint8*)(ximage->data+(y*ximage->bytes_per_line))) + 3*x;
01085   if (src_a >= 255) {
01086     pPixel[2] = r;
01087     pPixel[1] = g;
01088     pPixel[0] = b;
01089     return;
01090   }
01091 
01092   PRUint32 dst_a = 255 - src_a;
01093   pPixel[2] = ((r*src_a) + (pPixel[2] * dst_a)) >> 8;
01094   pPixel[1] = ((g*src_a) + (pPixel[1] * dst_a)) >> 8;
01095   pPixel[0] = ((b*src_a) + (pPixel[0] * dst_a)) >> 8;
01096 }
01097 
01098 static void
01099 nsBlendPixel888_msb(XImage *ximage, int x, int y, nscolor color, int src_a)
01100 {
01101   NS_ASSERTION((src_a>=0)&&(src_a<=255), "Invalid alpha");
01102   if (src_a <= 0)
01103     return;
01104 
01105   NS_ASSERTION(x<ximage->width,  "x out of bounds");
01106   NS_ASSERTION(y<ximage->height, "y out of bounds");
01107   if ((x >= ximage->width) || (y >= ximage->height))
01108     return;
01109 
01110   PRUint16 r = NS_GET_R(color);
01111   PRUint16 g = NS_GET_G(color);
01112   PRUint16 b = NS_GET_B(color);
01113 
01114   PRUint8 *pPixel = ((PRUint8*)(ximage->data+(y*ximage->bytes_per_line))) + 3*x;
01115   if (src_a >= 255) {
01116     pPixel[0] = r;
01117     pPixel[1] = g;
01118     pPixel[2] = b;
01119     return;
01120   }
01121 
01122   PRUint32 dst_a = 255 - src_a;
01123   pPixel[0] = ((r*src_a) + (pPixel[0] * dst_a)) >> 8;
01124   pPixel[1] = ((g*src_a) + (pPixel[1] * dst_a)) >> 8;
01125   pPixel[2] = ((b*src_a) + (pPixel[2] * dst_a)) >> 8;
01126 }
01127 #endif
01128 
01129 
01130 nscolor
01131 nsPixelToNscolor555(unsigned long aPixel)
01132 {
01133   int r = (aPixel>>7)&0xF8;
01134   int g = (aPixel>>2)&0xF8;
01135   int b = (aPixel<<3)&0xF8;
01136   nscolor color = NS_RGB(r,g,b);
01137   return color;
01138 }
01139 
01140 nscolor
01141 nsPixelToNscolor565(unsigned long aPixel)
01142 {
01143   int r = (aPixel>>8)&0xF8;
01144   int g = (aPixel>>3)&0xFC;
01145   int b = (aPixel<<3)&0xF8;
01146   nscolor color = NS_RGB(r,g,b);
01147   return color;
01148 }
01149 
01150 nscolor
01151 nsPixelToNscolor888_lsb(unsigned long aPixel)
01152 {
01153   int r = (aPixel>>16)&0xFF;
01154   int g = (aPixel>> 8)&0xFF;
01155   int b = (aPixel    )&0xFF;
01156   nscolor color = NS_RGB(r,g,b);
01157   return color;
01158 }
01159 
01160 nscolor
01161 nsPixelToNscolor888_msb(unsigned long aPixel)
01162 {
01163   int r = (aPixel    )&0xFF;
01164   int g = (aPixel>> 8)&0xFF;
01165   int b = (aPixel>>16)&0xFF;
01166   nscolor color = NS_RGB(r,g,b);
01167   return color;
01168 }
01169