Milán Major

netscape-revival

1 branch
Code

sun-java/awt.bad/win/awt_image.cpp

/*
 * @(#)awt_image.cpp	1.39 96/01/05 Patrick P. Chan
 *
 * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */

/* 


NOTE: ALL THE DITHERING CODE WAS QUICKLY SLAPPED TOGETHER.  IT NEEDS
A LOT OF CLEAN-UP WORK AND TESTING. 


*/
#include "awt_dc.h"
#include "awt_palette.h"
#include "awt_image.h"
#include "awt_querydc.h"
#include "awt_graphics.h"
#include "math.h"
#include "malloc.h"
#include "awt_imagescale.h"
#include "awt_toolkit.h"

extern "C" {
#include "java_awt_Rectangle.h"
#include "java_awt_Color.h"
#include "sun_awt_image_OffScreenImageSource.h"
#include "sun_awt_image_ImageRepresentation.h"
#include "java_awt_image_ImageConsumer.h"
#include "java_awt_image_ImageObserver.h"
#include "sun_awt_windows_WGraphics.h"
};


#define IMAGE_SIZEINFO (java_awt_image_ImageObserver_WIDTH |	\
			java_awt_image_ImageObserver_HEIGHT)

#define IMAGE_DRAWINFO (java_awt_image_ImageObserver_WIDTH |	\
			java_awt_image_ImageObserver_SOMEBITS |	\
			java_awt_image_ImageObserver_HEIGHT)

#define IMAGE_OFFSCRNINFO (java_awt_image_ImageObserver_WIDTH |		\
			   java_awt_image_ImageObserver_HEIGHT |	\
			   java_awt_image_ImageObserver_SOMEBITS |	\
			   java_awt_image_ImageObserver_ALLBITS)


#ifdef ENABLE_DEBUG_NEW
#define new DEBUG_NEW
#endif


#define HINTS_DITHERFLAGS   (java_awt_image_ImageConsumer_TOPDOWNLEFTRIGHT)
#define HINTS_SCANLINEFLAGS (java_awt_image_ImageConsumer_COMPLETESCANLINES)

const int COLOR4 = 0;
const int COLOR8 = 1;

ColorInfo g_colorInfo[2];

/* efficiently map an RGB value to a pixel value */
#define RGBMAP(pColorInfo, r, g, b)	 \
	((pColorInfo)->m_rgbCube[(int)((r) + CMAP_BIAS) >> (int)(8L - CMAP_BITS)]\
	 	[(int)((g) + CMAP_BIAS) >> (int)(8L - CMAP_BITS)]\
	 	[(int)((b) + CMAP_BIAS) >> (int)(8L - CMAP_BITS)])

#define COMPOSE24(I, r, g, b)		\
	((((b) & 0xffL) << ((I)->bOff)) |	\
	 (((g) & 0xffL) << ((I)->gOff)) |	\
	 (((r) & 0xffL) << ((I)->rOff)))


#define SetRGBQUAD(p, r, g, b)	\
{				\
	(p)->rgbRed = r;	\
	(p)->rgbGreen = g;	\
	(p)->rgbBlue = b;	\
	(p)->rgbReserved = 0;	\
}




#define WIDTHBYTES(i)     ((unsigned long)(((i) + 3) & (~3L)))  /* ULONG aligned ! */
#define DIBWIDTHBYTES(bi) (long)WIDTHBYTES((long)bi.biWidth * (long)(bi.biBitCount>>3))

#define IMAGE_SIZEINFO (java_awt_image_ImageObserver_WIDTH |	\
			java_awt_image_ImageObserver_HEIGHT)

//#define DEBUG_IMAGE


// Initialize static variables
int AwtImage::m_bitspixel = 0;

// This is data structure holds the common colormap that is used to paint
// all images.  When an image is painted, the BITMAPINFOHEADER of 
// the image is copied into m_pBitmapInfo and then m_pBitmapInfo is used to
// paint the image.  This strategy eliminates an alloc/free when painting
// an image.

AwtImage::AwtImage() : AwtObject(NULL)
{
    m_awtObjType = AWT_IMAGE;
    m_selectMask = 0;
    
    // Back pointer to the java_awt_image_ImageRepresentation
    m_pJavaObject = NULL;

    // Dimension of the original image
    m_nSrcW = 0;
    m_nSrcH = 0;

    // Dimension of the resulting image
    m_nDstW = 0;
    m_nDstH = 0;
    
    // Size of the conversion buffer
    m_nBufScan  = 0;

    // Rendering hints
    m_nHints    = 0;

    // The dithering  and alpha error buffers
    m_pDitherErrors = NULL;
    m_pAlphaErrors  = NULL;

    // The pixel recoding buffer.
    m_pRecode    = NULL;
    m_pIsRecoded = NULL;

    // The pixel delivery tracking fields
    m_nLastLine = 0;
    m_pSeen     = NULL;
    m_hRgn      = NULL;

    // Consumer buffer for both 24 and 8 bit images.
    m_hDIB        = NULL;
    m_pBitmapData = NULL;
    m_pBitmapInfo = NULL;

    // Handle to the bitmap.  May be NULL.
    m_hBitmap     = NULL;
    m_hOldBitmap  = NULL;
    
    // Non-NULL if image was converted to an icon.
    m_hIcon = NULL;

    // Transparency information
    m_bHasTransparentPixels = FALSE;
    m_hTransparencyMask     = NULL;
    m_pTransparencyData     = NULL;
    m_pTransMaskInfo        = NULL;
    m_hTransDIB             = NULL;

    m_bgcolor               = RGB(0, 0, 0);

    // Non-NULL if inage is an off-screen image.
    m_pAwtDC      = NULL;

    // Image palette information
    m_pAwtPalette = NULL;
    m_hPal        = NULL;

    m_pRGBQuad    = NULL;
    m_bitPerPixel = 8;
    m_hBMPDC      = NULL; 
    m_hMaskDC     = NULL;
}

AwtImage::~AwtImage()
{
 if( m_hDIB != NULL)
 {
    GlobalFree(m_hDIB);
 }
 if( m_pBitmapInfo != NULL )
 {
    free(m_pBitmapInfo);
 }

 if( m_hTransDIB != NULL)
 {
    GlobalFree(m_hTransDIB);
 }
 if( m_pTransMaskInfo != NULL )
 {
    free(m_pTransMaskInfo);
 }

 if(m_hBitmap != NULL)
 {
   if (m_pAwtDC) {
      VERIFY(::SelectObject(m_pAwtDC->GetDC(), m_hOldBitmap));
   }
   VERIFY(::DeleteObject(m_hBitmap));
   m_hBitmap  = NULL;
 }
 if(m_hTransparencyMask != NULL)
 {
   VERIFY(::DeleteObject(m_hTransparencyMask));
   m_hTransparencyMask = NULL;
 }


 if(m_hBMPDC != NULL)
 {
   VERIFY(::DeleteDC(m_hBMPDC));
   m_hBMPDC = NULL;
 }
 if(m_hMaskDC != NULL)
 {
   VERIFY(::DeleteDC(m_hMaskDC));
   m_hMaskDC = NULL;
 }

    if (m_pAwtDC != NULL) {
        HDC hdc = m_pAwtDC->GetDC();
        
        // disconnect yourself from the DC object
        m_pAwtDC->ResetTargetObject(); // zero m_pTargetObj in AwtDC
        m_pAwtDC->ResetDC(); // zero m_hObject in AwtDC
        m_pAwtDC->Release(); // release awt dc object
        m_pAwtDC = 0;

        VERIFY(::DeleteDC(hdc));
    }

	if (m_pDitherErrors) {
	    delete []m_pDitherErrors;
	}
	if (m_pAlphaErrors) {
	    delete []m_pAlphaErrors;
	}
	if (m_pRecode) {
	    delete []m_pRecode;
	}
	if (m_pIsRecoded) {
	    delete []m_pIsRecoded;
	}
	if (m_pSeen) {
	    delete []m_pSeen;
	}
	if (m_hRgn) {
	    VERIFY(::DeleteObject(m_hRgn));
	}
}


//-------------------------------------------------------------------------
//
// Detach the m_pAwtDC. It's time to destroy the dc we allocated
// on GetDC()
//
//-------------------------------------------------------------------------
void AwtImage::Detach(HDC hdc)
{
    if (hdc)
        ::DeleteDC(hdc);
}


//-------------------------------------------------------------------------
//
// Get the dc for this component 
//
//-------------------------------------------------------------------------
HDC AwtImage::GetDC()
{
    HWND hWndDesktop = ::GetDesktopWindow();
    HDC hDC    = ::GetWindowDC(hWndDesktop);
    HDC hRetDC = ::CreateCompatibleDC(hDC);
    VERIFY(::ReleaseDC(hWndDesktop, hDC));

    return hRetDC;
}


#ifdef DEBUG_IMAGE
void AwtImage::PrintRGBQUADS(RGBQUAD *pRgbq, int numColors)
{
   char buf[100];

   for(int i=0; i<numColors; i++)
   {
      wsprintf(buf, "{%d,%d,%d}\n",pRgbq[i].rgbRed,
                                 pRgbq[i].rgbGreen,
                                 pRgbq[i].rgbBlue);
      OutputDebugString(buf);
   }
}
#endif

void AwtImage::InitRGBQUADS(RGBQUAD *pRgbq, int numColors)
{
   for(int i=0; i<numColors; i++)
   {
						pRgbq[i].rgbRed      = 0;
						pRgbq[i].rgbGreen    = 0,
						pRgbq[i].rgbBlue     = 0;
						pRgbq[i].rgbReserved = 0;
   }
}


//-------------------------------------------------------------------------
// Note that for both 8 bit and 24 bit input image source we use a 8 bit 
// destination buffer.
// Due to this in case of 24 bit source, we would be dooing a 24 bit to 8 bit
// conversion and then blting onto the screen. This is fine in case of a 8 bit
// output device. But in case of 24 bit output device htis conversion is redundant. 
// But a inherent advantage in this scheme is that we will save on memory as we 
// would be storing a 24 bit image as a 8 bit DIB.
//-------------------------------------------------------------------------
void AwtImage::Alloc8BitConsumerBuffer()
{
    if (m_pBitmapData == NULL) {
        int numColors = 256; // 0-256

        m_nBufScan = (m_nDstW + 3) & (~3L);

        m_pBitmapInfo = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+numColors*sizeof(RGBQUAD));
        m_pRGBQuad    = (RGBQUAD*)((BYTE*)m_pBitmapInfo + sizeof(BITMAPINFOHEADER));

        // Initialize the palette colors to BLACK (ie. RGB(0,0,0))
        InitRGBQUADS(m_pRGBQuad, numColors);

        // Get the palette colors and set them in the dib.
        if(m_pAwtPalette != NULL) {
            m_pAwtPalette->GetRGBQUADS(m_pRGBQuad); 
        }

#ifdef DEBUG_IMAGE
        PrintRGBQUADS(m_pRGBQuad, numColors);
#endif

        m_pBitmapInfo->bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
        m_pBitmapInfo->bmiHeader.biWidth           = m_nDstW;//m_nBufScan;
        m_pBitmapInfo->bmiHeader.biHeight          = m_nDstH; // DIB Origin is at lower left corner
        m_pBitmapInfo->bmiHeader.biPlanes          = 1;	//nb: NOT equal to planes from GIF
        m_pBitmapInfo->bmiHeader.biBitCount        = 8;
        m_pBitmapInfo->bmiHeader.biCompression     = BI_RGB;
        m_pBitmapInfo->bmiHeader.biSizeImage       = 0;
        m_pBitmapInfo->bmiHeader.biXPelsPerMeter   = 0;
        m_pBitmapInfo->bmiHeader.biYPelsPerMeter   = 0;
        m_pBitmapInfo->bmiHeader.biClrUsed         = numColors;
        m_pBitmapInfo->bmiHeader.biClrImportant    = numColors;


        m_hDIB = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 
                               (long)m_pBitmapInfo->bmiHeader.biHeight * DIBWIDTHBYTES(m_pBitmapInfo->bmiHeader));
        CHECK_NULL(m_hDIB, "OutOfMemoryError");

        m_pBitmapData = (BYTE  FAR *)GlobalLock(m_hDIB);
        m_hBitmap = NULL;
    }
}


//-------------------------------------------------------------------------
// This is not used now and should be used when we have a 24 bit image source.
// Righ now we use the 8 bit destination. This should change to a 24 bit 
// destination code when we plan on doing image editting and hence have more 
// accuracy.
//-------------------------------------------------------------------------

void AwtImage::Alloc24BitConsumerBuffer()
{
    if (m_pBitmapData == NULL) 
    {
        m_pBitmapInfo   = (BITMAPINFO*)malloc(sizeof(BITMAPINFO));
       // Get the palette colors and set them in the dib.
        m_pBitmapInfo->bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
        m_pBitmapInfo->bmiHeader.biWidth           = m_nDstW;
        m_pBitmapInfo->bmiHeader.biHeight          = m_nDstH; // DIB Origin is at lower left corner
        m_pBitmapInfo->bmiHeader.biPlanes          = 1;	//nb: NOT equal to planes from GIF
        m_pBitmapInfo->bmiHeader.biBitCount        = 24;
        m_pBitmapInfo->bmiHeader.biCompression     = BI_RGB;
        m_pBitmapInfo->bmiHeader.biSizeImage       = 0;
        m_pBitmapInfo->bmiHeader.biXPelsPerMeter   = 0;
        m_pBitmapInfo->bmiHeader.biYPelsPerMeter   = 0;
        m_pBitmapInfo->bmiHeader.biClrUsed         = 0;
        m_pBitmapInfo->bmiHeader.biClrImportant    = 0;


        m_hDIB = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 
                            (long)m_pBitmapInfo->bmiHeader.biHeight * DIBWIDTHBYTES(m_pBitmapInfo->bmiHeader));
        CHECK_NULL(m_hDIB, "OutOfMemoryError");

        m_pBitmapData = (BYTE FAR *)GlobalLock(m_hDIB);
        m_hBitmap = NULL;
        m_nBufScan = DIBWIDTHBYTES(m_pBitmapInfo->bmiHeader);
    }
}


void AwtImage::AllocConsumerBuffer(HColorModel * hCM)
{
    ColorModel *pCM  = (ColorModel *)unhand(hCM);
    int bitsPerPixel = (int)pCM->pixel_bits;

    /*
    CHECK_BOUNDARY_CONDITION( (bitsPerPixel != 8 && bitsPerPixel != 24 && 
                               bitsPerPixel != 32 ),
                               "Image source format unsupported" );
    */
    //
    // bitsPerPixel MUST be either 8, 24, 32.  
    // If color depth is 32 bits per pixel create a 24 bit buffer...
    //
    if(GetDepth(hCM) <= 8) {
        Alloc8BitConsumerBuffer();
    } else {
        Alloc24BitConsumerBuffer();
    }
}


	long AwtImage::GetDepth(HColorModel *colormodel) 
 {
    ColorModel *pCM  = (ColorModel *)unhand(colormodel);
    int bitsPerPixel = pCM->pixel_bits;
    //CHECK_BOUNDARY_CONDITION_RETURN((bitsPerPixel != 8 && bitsPerPixel != 24 && bitsPerPixel != 32),"Image source fornat unsupported", 8);

     HWND hWnd = ::GetDesktopWindow();
     HDC hDC=::GetDC(hWnd);

     int devcap = ::GetDeviceCaps(hDC, RASTERCAPS);
     int devBitsPerPixel = 0;
     if( (devcap & RC_PALETTE)  > 0)
     {
       // This is a palette  supporting device. So, create a palette with 
       // size same as that of in the device palette.
       devBitsPerPixel = ::GetDeviceCaps(hDC, BITSPIXEL);
     }
  	 ::ReleaseDC(hWnd, hDC);


    if(  (bitsPerPixel    <= 8)
       ||(devBitsPerPixel == 8)
      )
    {
      return 8;
    }
    else
    {
      return 24;
    }
 }



MaskBits *AwtImage::GetMaskBuf(BOOL create) 
{
    HWND hWndDesktop;
    HDC hDC;
    if (m_pTransparencyData == NULL && create) {
        int32_t nPaddedWidth = (m_nDstW + 31) & (~31L);
        int32_t dibWd        = (nPaddedWidth) >> 3L;

        m_pTransMaskInfo = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+2*sizeof(RGBQUAD));

        m_pTransMaskInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
        m_pTransMaskInfo->bmiHeader.biWidth         = m_nDstW;
        m_pTransMaskInfo->bmiHeader.biHeight        = m_nDstH;
        m_pTransMaskInfo->bmiHeader.biPlanes        = 1;
        m_pTransMaskInfo->bmiHeader.biBitCount      = 1;
        m_pTransMaskInfo->bmiHeader.biCompression   = BI_RGB;
        m_pTransMaskInfo->bmiHeader.biSizeImage     = 0;
        m_pTransMaskInfo->bmiHeader.biXPelsPerMeter = 0;
        m_pTransMaskInfo->bmiHeader.biYPelsPerMeter = 0;
        m_pTransMaskInfo->bmiHeader.biClrUsed       = 2;
        m_pTransMaskInfo->bmiHeader.biClrImportant  = 2;

        SetRGBQUAD(&(m_pTransMaskInfo->bmiColors[0]), 255, 255, 255);
        SetRGBQUAD(&(m_pTransMaskInfo->bmiColors[1]), 0, 0, 0);

        hWndDesktop = ::GetDesktopWindow();
        hDC = ::GetWindowDC(hWndDesktop);

        m_hTransDIB = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 
                                    (long)m_pTransMaskInfo->bmiHeader.biHeight * dibWd);

        if (m_hTransDIB) {
            m_pTransparencyData = (void FAR *)GlobalLock(m_hTransDIB);
        } else {
            //REMIND: Report malloc error?
            ASSERT(0);
            m_pTransparencyData = NULL;
        }

        m_hTransparencyMask = NULL;

       
        if (m_pTransparencyData != NULL) {
            if ((m_nHints & HINTS_SCANLINEFLAGS) != 0) {
                //memset(m_pTransparencyData, 0xff, (nPaddedWidth*m_nDstH)>>3);
                //memset(m_pTransparencyData, 0xff, (nPaddedWidth*m_nDstH)>>3);
            } else {
                //REMIND: Clean this
                //memset(m_pTransparencyData, 0xff, (nPaddedWidth*m_nDstH)>>3);
                if (m_hRgn != NULL) {
                    RECT rect;
                    HBRUSH hBrush = (HBRUSH)::GetStockObject( BLACK_BRUSH );
                    HDC hMemDC    = ::CreateCompatibleDC(hDC);

                    ::SelectObject(hMemDC, m_hTransparencyMask);
                    ::SelectClipRgn(hMemDC, m_hRgn);
                    rect.left   = 0;
                    rect.top    = 0;
                    rect.right  = (int)m_nDstW;
                    rect.bottom = (int)m_nDstH;

                    ::FillRect(hMemDC, &rect, hBrush);

                    // Select a NULL region before deleting the DC
                    ::SelectClipRgn(hMemDC, NULL);
                    VERIFY(::DeleteDC(hMemDC));
                    // The HBRUSH is a stock object, so dont delete it
                }
            }
        }
        VERIFY(::ReleaseDC(hWndDesktop, hDC));
    }
    // Getting the mask data invalidates the values of the transparent pixels
    m_bgcolor = 0;
    return (MaskBits *) m_pTransparencyData;
}

DitherError *AwtImage::GetDitherBuf(int x1, int y1, int x2, int y2)
{
    if ((m_nHints & HINTS_DITHERFLAGS) != 0) {
	if (m_pDitherErrors == 0) {
	    int size = sizeof(DitherError) * (m_nDstW + 2);
	    m_pDitherErrors = new DitherError[m_nDstW + 2];
	    if (m_pDitherErrors) {
		memset(m_pDitherErrors, 0, size);
	    }
	}
    }
    return m_pDitherErrors;
}

AlphaError *AwtImage::AlphaSetup(int x1, int y1, int x2, int y2, BOOL create)
{
    if ((m_nHints & HINTS_DITHERFLAGS) != 0) {
	if (create && m_pAlphaErrors == 0) {
	    int size = sizeof(AlphaError) * (m_nDstW + 2);
	    m_pAlphaErrors = new AlphaError[m_nDstW + 2];
	    if (m_pAlphaErrors) {
		memset(m_pAlphaErrors, 0, size);
	    }
	}
    }
    return m_pAlphaErrors;
}

void AwtImage::BufDone(int x1, int y1, int x2, int y2) {
    int ytop = y1;
    if ((m_nHints & HINTS_SCANLINEFLAGS) != 0) {
	int l;
	if (m_pSeen == NULL) {
	    m_pSeen = new char[m_nDstH];
	    memset(m_pSeen, 0, m_nDstH);
	}
	char FAR *pB = ((char FAR *) m_pBitmapData) + y1 * m_nBufScan;
	char FAR *pM = (char FAR *) m_pTransparencyData;
	int tscan;
	if (pM != NULL) {
	    tscan = ((m_nDstW + 31) & (~31L)) >> 3L;
	    pM += y1 * tscan;
	}
	for (l = y1 - 1; l >= 0; l--) {
	    if (m_pSeen[l]) {
		break;
	    }
	    memcpy(pB - m_nBufScan, pB, m_nBufScan);
	    pB -= m_nBufScan;
	    if (pM != NULL) {
		memcpy(pM - tscan, pM, tscan);
		pM -= tscan;
	    }
	    ytop = l;
	}
	for (l = y1; l < y2; l++) {
	    m_pSeen[l] = 1;
	}
    } else {
	HRGN hR = ::CreateRectRgn(x1, y1, x2, y2);
	if (m_hRgn == NULL) {
	    m_hRgn = hR;
	} else {
	    ::CombineRgn(m_hRgn, m_hRgn, hR, RGN_OR);
	    ::DeleteObject(hR);
	}
    }
    if (m_nLastLine < y2) {
	m_nLastLine = y2;
    }
    Hjava_awt_Rectangle *newbits = unhand(m_pJavaObject)->newbits;
    if (newbits != 0) {
	Classjava_awt_Rectangle *pNB = unhand(newbits);
	pNB->x = x1;
	pNB->y = ytop;
	pNB->width = x2 - x1;
	pNB->height = y2 - ytop;
    }
};



void AwtImage::Init(HImageRepresentation *pJavaObject, HColorModel *cmh)
{
    m_pJavaObject = pJavaObject;
    m_nDstW  = unhand(pJavaObject)->width;
    m_nDstH  = unhand(pJavaObject)->height;
    m_nSrcW  = unhand(pJavaObject)->srcW;
    m_nSrcH  = unhand(pJavaObject)->srcH;
    m_nHints = unhand(pJavaObject)->hints;

    if(cmh != NULL)
    {
        //m_pAwtPalette = AwtToolkit::GetImagePalette();
        m_pAwtPalette = AwtToolkit::GetToolkitDefaultPalette();
        m_pAwtPalette->AddRef();
        m_hPal = m_pAwtPalette->GetPalette();
    }
}

BOOL AwtImage::Create(HImageRepresentation *pJavaObject,
		      long nW, long nH)
{
 /*
 ** This routine sets up a DC with a compatible DDB where all Graphics operations
 ** can be done. It is called from hte offscreeninit api. 
 ** This routine and Graphics routines share a commmon DC.
 ** This is because, a single bitmap can be drawn into from multiple 
 ** graphics contexts got via getGraphics.
 ** This shared DC is used only when there is graphics to do.
 ** When a image is to be copied and blted this shared DC is not used.
 ** This is checked in Graphics::DrawImage which then calls the image->draw()
 ** function. The image->draw() function takes care of transparent bitmaps and
 ** directly blts it from the DIB.
 ** REMIND: When does this bitmap get deleted?
 **         There is no image dispose for this image to be deleted.
 **         GC will pick it up when irh is not referenced anymore.
 ** BUG:    There is no way of drawing into a DIB which has been filled with a image.
 */
    HDC hDC, hDDC;
    RECT rect;
    long nPaddedWidth = (nW + 3) & ~0x3L;

    m_pJavaObject = pJavaObject;
    m_nDstW  = m_nSrcW = nW;
    m_nDstH  = m_nSrcH = nH;

    rect.left   = 0;
    rect.top    = 0;
    rect.right  = nW;
    rect.bottom = nH;

    m_pAwtDC = AwtDC::Create((IDCService *)this);
    ASSERT( m_pAwtDC->m_refCount == 1 );
/// m_pAwtDC->AddRef();
    hDC = m_pAwtDC->Lock(NULL);
    m_pAwtDC->SetRgn(NULL, &rect);

    hDDC      = ::GetWindowDC( ::GetDesktopWindow() );
    m_hBitmap = ::CreateCompatibleBitmap(hDDC, nW, nH);
    VERIFY(::ReleaseDC(::GetDesktopWindow(), hDDC));
    VERIFY( m_hOldBitmap = (HBITMAP)::SelectObject(hDC, m_hBitmap));

    ::FillRect(hDC, &rect, (HBRUSH)::GetStockObject( WHITE_BRUSH ));
    //VERIFY(::SetBkMode(hDC, TRANSPARENT) != NULL);

    m_pAwtDC->Unlock(NULL);
    return (m_hBitmap  != NULL);
}


BOOL AwtImage::freeRenderData(BOOL force) 
{
    BOOL ret;

    if (m_pDitherErrors) {
        delete []m_pDitherErrors;
        m_pDitherErrors = NULL;
    }
    
    if (m_pAlphaErrors) {
        delete []m_pAlphaErrors;
        m_pAlphaErrors = NULL;
    }
    
    if (m_pRecode) {
        delete []m_pRecode;
        m_pRecode = NULL;
    }
    
    if (m_pIsRecoded) {
        delete []m_pIsRecoded;
        m_pIsRecoded = NULL;
    }
    
    if (m_pSeen) {
        delete []m_pSeen;
        m_pSeen = NULL;
    }
    
    if (m_hRgn) {
        VERIFY(::DeleteObject(m_hRgn));
        m_hRgn = NULL;
    }

    ret = (!force && (m_nHints & HINTS_DITHERFLAGS) == 0);
    m_nHints |= HINTS_DITHERFLAGS;

    return ret;
}

// <<Not properly cleaning up icons.>>
// <<Also, we're redithering which isn't great>>
#ifdef _WIN32
HICON AwtImage::ToIcon() {
	if (m_hIcon != NULL) {
		return m_hIcon;
	}
	if (m_pBitmapData != NULL) {
		int nW = ::GetSystemMetrics(SM_CXICON);
		int nH = ::GetSystemMetrics(SM_CYICON);
 		BYTE *pMask = NULL;
		HDC hDC;
		ICONINFO iconInfo;
		HBITMAP hMask;

		// Invert the bitmap data.

		hMask = m_hTransparencyMask;
		if (!hMask) {
			pMask = new BYTE[nW * nH / 8];
			memset(pMask, 0, nW * nH / 8);
			hMask= ::CreateBitmap(nW, nH, 1, 1, pMask);
		}
		iconInfo.fIcon = TRUE;
		iconInfo.hbmMask = hMask;
                VERIFY( hDC = ::GetWindowDC(::GetDesktopWindow()) );
		iconInfo.hbmColor = GetDDB(hDC);
                VERIFY( ::ReleaseDC(::GetDesktopWindow(), hDC) );
		m_hIcon = ::CreateIconIndirect(&iconInfo);
		VERIFY(::DeleteObject(hMask));

		// free resources.
		if (pMask) {
			delete [] pMask;
		}
	}
	return m_hIcon;
}

#else   // !WIN32

#pragma message("AwtImage::ToIcon(...) is unimplemented.")
HICON AwtImage::ToIcon() {
    return NULL;
}
#endif  // _WIN32



#ifdef DEBUG_IMAGE
void AwtImage::PrintImage()
{
   char buf[100];
   BYTE FAR *bp = m_pBitmapData;
   int scanLineSize = (m_nSrcW + 3) & ~0x3L;//ULONG Aligned.

   for(int i=0; i<m_nSrcH; i++)
   {
      bp=m_pBitmapData+(i*scanLineSize);
      for(int j=0; j<m_nSrcW; j++)
      {
        wsprintf(buf, "%d ", *bp++);
        OutputDebugString(buf);
      }
      wsprintf(buf, "\n");
      OutputDebugString(buf);
   }
}

void AwtImage::Print24BitImage()
{
   char buf[100];
   BYTE FAR *bp = m_pBitmapData;
   int scanLineSize = (m_nSrcW*3 + 3) & ~0x3;//ULONG Aligned.

   for(int i=0; i<m_nSrcH; i++)
   {
      bp=m_pBitmapData+(i*scanLineSize);
      for(int j=0; j<m_nSrcW; j++)
      {
        wsprintf(buf, "(%d %d %d) ", *bp++,*bp++,*bp++);
        OutputDebugString(buf);
      }
      wsprintf(buf, "\n");
      OutputDebugString(buf);
   }
}
#endif //DEBUG_IMAGE







/*
 * A note on the rop codes used below:
 *
 * In BitBlt, Windows uses the low order 8 bits of the high order word
 * (bits 16-23) to control how to combine the current brush, the source
 * bitmap, and the destination device.  Each bit refers to what to set
 * the resulting bit to based on a particular combination of 1 or 0 bits
 * in the 3 inputs as follows:
 *
 * B0 - brush  bit is 0,    B1 - brush  bit is 1
 * S0 - source bit is 0,    S1 - source bit is 1
 * D0 - dest   bit is 0,    D1 - dest   bit is 1
 *
 * bit 16 - B0, S0, D0
 * bit 17 - B0, S0, D1
 * bit 18 - B0, S1, D0
 * bit 19 - B0, S1, D1
 * bit 20 - B1, S0, D0
 * bit 21 - B1, S0, D1
 * bit 22 - B1, S1, D0
 * bit 23 - B1, S1, D1
 *
 * Thus, if bit 16 is 1, then a 1 bit is stored in the destination if
 * B0, S0, D0, that is all 3 corresponding bits of the brush, the source
 * bitmap, and the original destination pixel are 0.
 */
//------------------------------------------------------------------------
// Notes: As per AWT api we would never be able to tell when the image is
// completely read in. This is because the image consumer method setBytePixels
// accepts rectangular destination co-ordinates, which means that any part
// of the image can be read in at any point of time! and also irh does not 
// provide a flag to indicate the end of image. 
// Due to this we would not be able to delete the DIB at a certain point 
// of time. Hence we keep the DIB around and recreate the DDB for every draw.
// Also, if we kept the DDB around it will take up GDI resources. This means
// for images like the moleculeviewer applet which creates atleast 40 small 
// images we will loose on GDI heavily. This happens in old Awt too.
// So, in order to save on a duplicate copy, save on GDI resources and be 
// portable accross Win-16, recreating the DDB and associated DCs is the 
// best bet.
//------------------------------------------------------------------------

void AwtImage::Draw(HDC hDC, long nX, long nY,
		    DWORD xormode, COLORREF xorcolor, HBRUSH xorBrush,
		    HColor  *c)
{
    HBITMAP hBitmap     = NULL;
    HBITMAP hOldBmpB    = NULL;
    HBITMAP hOldBmpM    = NULL;
    UINT    result      = 0;


    VERIFY( m_pBitmapData );
    //PrintImage();
    //Print24BitImage();

    //
    // Select and Realize the image's palette into the DC if one
    // is available...
    //
    if (m_hPal != NULL) {
        VERIFY( ::SelectPalette(hDC, m_hPal, TRUE) );
        //VERIFY( ::SelectPalette(hDC, m_hPal, FALSE) );
        result = ::RealizePalette(hDC);
    }

    m_hBMPDC = ::CreateCompatibleDC(hDC);
    VERIFY( m_hBMPDC );

    if(m_hBitmap == NULL) {
        m_hBitmap = ::CreateCompatibleBitmap(hDC, GetWidth(), GetHeight());
        VERIFY( m_hBitmap );
    }

    if( (m_hBitmap != NULL) &&(m_pBitmapData != NULL) ) {
        ::SetDIBits(hDC, m_hBitmap, 0, GetHeight(), m_pBitmapData, 
                    m_pBitmapInfo, DIB_RGB_COLORS );
    }

    m_hMaskDC = ::CreateCompatibleDC(hDC);
    VERIFY( m_hMaskDC );

    if( (m_hTransparencyMask == NULL) && (m_pTransparencyData != NULL) ) {
        m_hTransparencyMask = ::CreateCompatibleBitmap(hDC, GetWidth(), GetHeight());
        VERIFY( m_hTransparencyMask );
    }

    if( (m_hTransparencyMask != NULL) && (m_pTransparencyData != NULL) ) {
        ::SetDIBits(hDC, m_hTransparencyMask, 0, GetHeight(), m_pTransparencyData, 
                    m_pTransMaskInfo , DIB_RGB_COLORS );
    }



    hBitmap = GetDDB(hDC);
    VERIFY( hBitmap );

    if (m_hTransparencyMask) {
        hOldBmpB = (HBITMAP)::SelectObject(m_hBMPDC, hBitmap);
        /*///////////////
            VERIFY( ::BitBlt(hDC, 0, 0, m_nDstW, m_nLastLine,
                             m_hBMPDC, 0, 0, SRCCOPY) );
            ::GdiFlush();
        *////////////////

        hOldBmpM = (HBITMAP)::SelectObject(m_hMaskDC, m_hTransparencyMask);
        /*///////////////
            VERIFY( ::BitBlt(hDC, 0, 0, m_nDstW, m_nLastLine,
                             m_hMaskDC, 0, 0, SRCCOPY) );
            ::GdiFlush();
        *////////////////

        COLORREF color;
        HBRUSH hBrush;
        DWORD rop;

        if (xormode) {
            hBrush = xorBrush;
            color  = xorcolor;
            rop    = 0x00e20000L;
        } 
        else if (c == 0) {
            hBrush = NULL;
            color  = PALETTERGB(0, 0, 0);
            rop    = 0x00220000L;
        } 
        else {
            DWORD javaColor = c->obj->value;

            hBrush = NULL;
            color  = PALETTERGB((javaColor >> 16L) & 0xff,
                                (javaColor >> 8L)  & 0xff,
                                (javaColor)        & 0xff);
            rop    = 0x00e20000L;
        }


///     if (color != m_bgcolor) 
	{
            HBRUSH hOldBrush = NULL;

            if (!xormode && c != 0) {
                hBrush = ::CreateSolidBrush(color);
            }

            if (hBrush != NULL) {
                hOldBrush = (HBRUSH) ::SelectObject(m_hBMPDC, hBrush);
            }

            VERIFY( ::BitBlt(m_hBMPDC, 0, 0, m_nDstW, m_nLastLine,
                             m_hMaskDC, 0, 0, rop) );
            /*///////////////
                VERIFY( ::BitBlt(hDC, 0, 0, m_nDstW, m_nLastLine,
                                 m_hBMPDC, 0, 0, SRCCOPY) );
                ::GdiFlush();
            *////////////////

            if (hBrush != NULL) {
                VERIFY( ::SelectObject(m_hBMPDC, hOldBrush) );
            }

            if (!xormode && c != 0) {
                VERIFY(::DeleteObject(hBrush));
            }
            m_bgcolor = color;
        }

        if (xormode || c != 0) {
            VERIFY( ::BitBlt(hDC, nX, nY, m_nDstW, m_nLastLine,
                             m_hBMPDC, 0, 0,
                             xormode ? 0x00960000L : SRCCOPY) );
        } else {
            VERIFY( ::BitBlt(hDC, nX, nY, m_nDstW, m_nLastLine,
                             m_hMaskDC, 0, 0, SRCAND) );

            //::GdiFlush();

            VERIFY( ::BitBlt(hDC, nX, nY, m_nDstW, m_nLastLine,
                             m_hBMPDC, 0, 0, SRCPAINT) );
            //::GdiFlush();
        }

    } 
    //
    // No transparency mask...
    //
    else {
        int hasRgn;
        HRGN hR  = NULL;

        if (m_hRgn != NULL) {

#ifdef _WIN32
            hR = ::CreateRectRgn(0, 0, 0, 0);
            hasRgn = ::GetClipRgn(hDC, hR);
#else   // !_WIN32
            RECT rcClip;

            hasRgn = ::GetClipBox(hDC, &rcClip);
            hR     = ::CreateRectRgn(rcClip.left, rcClip.top,
                                     rcClip.right, rcClip.bottom);
            hasRgn = ((hasRgn == SIMPLEREGION) || (hasRgn == COMPLEXREGION));
#endif  // !_WIN32

            VERIFY( ::OffsetClipRgn(hDC, -nX, -nY) != ERROR );

#ifdef _WIN32
            VERIFY( ::ExtSelectClipRgn(hDC, m_hRgn, RGN_AND) != ERROR );
#else
            //REMIND: What do we do here? There is no such call in win16
            ASSERT(0);
#endif
            VERIFY(::OffsetClipRgn(hDC, nX, nY) != ERROR);
        }

        hOldBmpB = (HBITMAP)::SelectObject(m_hBMPDC, hBitmap);
        VERIFY( ::BitBlt(hDC, nX, nY, m_nDstW, m_nLastLine,
                         m_hBMPDC, 0, 0,
                         xormode ? 0x00960000L : SRCCOPY) );
        //::GdiFlush();
        /*
        if (m_hRgn != NULL) {
            if (hasRgn) {
                VERIFY( ::SelectClipRgn(hDC, hR) != ERROR );
            } else {
                VERIFY( ::SelectClipRgn(hDC, NULL) != ERROR );
            }
        }
        */

        if (hR != NULL) {
            VERIFY( ::SelectClipRgn(hDC, NULL) != ERROR );
            VERIFY( ::DeleteObject(hR) );
        }

    }

    //
    // Finished drawing... Now clean everything up...
    //
    if (hOldBmpB != NULL) {
        VERIFY( ::SelectObject(m_hBMPDC, hOldBmpB) );
    }

    if (hOldBmpM != NULL) {
        VERIFY(::SelectObject(m_hMaskDC, hOldBmpM));
    }

    if (m_hBitmap != NULL) {
        VERIFY(::DeleteObject(m_hBitmap));
        m_hBitmap  = NULL;
    }

    if (m_hTransparencyMask != NULL) { 
        VERIFY(::DeleteObject(m_hTransparencyMask));
        m_hTransparencyMask = NULL;
    }

    if (m_hBMPDC != NULL) {
        VERIFY( ::DeleteDC(m_hBMPDC) );
        m_hBMPDC = NULL;
    }

    if (m_hMaskDC != NULL) {
        VERIFY( ::DeleteDC(m_hMaskDC) );
        m_hMaskDC = NULL;
    }
}



#define SET_BYTE_PIXELS_SIG	"(IIIILjava/awt/image/ColorModel;[BII)V"

#define HINTS_OFFSCREENSEND (java_awt_image_ImageConsumer_TOPDOWNLEFTRIGHT |  \
			     java_awt_image_ImageConsumer_COMPLETESCANLINES | \
			     java_awt_image_ImageConsumer_SINGLEPASS)


void AwtImage::sendPixels(OffScreenImageSource *osis)
{
    HImageConsumer *ich = osis->theConsumer;
    struct execenv *ee;
    struct Hjava_awt_image_ColorModel *cm;
    HObject *pixh;
    char *buf;
    int32_t i, j=0;
    HDC hDC;

    ee = EE();
    if (osis->theConsumer == 0) {
	return;
    }
    /*
    cm = getColorModel();
    execute_java_dynamic_method(ee, (HObject *) osis->theConsumer,
				"setColorModel",
				"(Ljava/awt/image/ColorModel;)V",
				cm);
    */


    if (osis->theConsumer == 0 || exceptionOccurred(ee)) {
	return;
    }
    execute_java_dynamic_method(ee, (HObject *) osis->theConsumer,
				"setHints",
				"(I)V",
				HINTS_OFFSCREENSEND);
    if (osis->theConsumer == 0 || exceptionOccurred(ee)) {
	return;
    }
    int32_t nPaddedWidth = (m_nDstW + 3L) & (~3L);
    pixh = (HObject *) ArrayAlloc(T_BYTE, nPaddedWidth);
    buf = (char *) unhand(pixh);
    VERIFY( hDC = ::GetWindowDC(::GetDesktopWindow()) );
    BITMAPINFO *pBitmapInfo = (BITMAPINFO*) malloc(sizeof(BITMAPINFO)
						   + 256*sizeof(RGBQUAD));
    pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pBitmapInfo->bmiHeader.biWidth = m_nDstW; 
    pBitmapInfo->bmiHeader.biHeight = m_nDstH;
    pBitmapInfo->bmiHeader.biPlanes = 1;
    pBitmapInfo->bmiHeader.biBitCount = 8;
    pBitmapInfo->bmiHeader.biCompression = BI_RGB;
    pBitmapInfo->bmiHeader.biSizeImage = nPaddedWidth * m_nDstH;
    pBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
    pBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
    pBitmapInfo->bmiHeader.biClrUsed = 256;
    pBitmapInfo->bmiHeader.biClrImportant = 256;
    //BYTE FAR *pTemp = new BYTE[nPaddedWidth * pBitmapInfo->bmiHeader.biHeight];


    HGLOBAL   hDIB =
    GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 
     (long)pBitmapInfo->bmiHeader.biHeight * nPaddedWidth );
    CHECK_NULL(hDIB, "OutOfMemoryError");
    BYTE FAR *pTemp = (BYTE  FAR *)GlobalLock(hDIB);

#ifdef _WIN32
    pBitmapInfo->bmiHeader.biHeight = -pBitmapInfo->bmiHeader.biHeight;
#else
    pBitmapInfo->bmiHeader.biHeight = pBitmapInfo->bmiHeader.biHeight;
#endif
    HBITMAP hBitmap = NULL;
    if(  (m_hBitmap     == NULL) 
       &&(m_pBitmapData != NULL)
      )
    {
        // This is the case when the DIB is filled and our bitmap
        // will be created and destroyed after each draw.
        // We do not use the DIB as is because the original DIB may
        // be either 24 bit or 8 bits. But this routine will return 
        // 8 bit only. 
        hBitmap = ::CreateCompatibleBitmap(hDC, GetWidth(), GetHeight());
        VERIFY( hBitmap );

        if( (hBitmap != NULL) &&(m_pBitmapData != NULL) ) {
            ::SetDIBits(hDC, hBitmap, 0, GetHeight(), m_pBitmapData, 
                        m_pBitmapInfo, DIB_RGB_COLORS );
        }
    }
    else
    {
       hBitmap =  m_hBitmap;
    }


    VERIFY(::GetDIBits(hDC, hBitmap, 0, m_nDstH, pTemp,
		       pBitmapInfo, DIB_RGB_COLORS));

    if(  (hBitmap   != NULL)
       &&(m_hBitmap != hBitmap)
      )
    {
       VERIFY(::DeleteObject(hBitmap));
       hBitmap  = NULL;
    }

    m_pRGBQuad  = (RGBQUAD*)((BYTE*)pBitmapInfo + sizeof(BITMAPINFOHEADER));    
    cm = getColorModel(m_pRGBQuad);
    execute_java_dynamic_method(ee, (HObject *) osis->theConsumer,
				"setColorModel",
				"(Ljava/awt/image/ColorModel;)V",
				cm);
    
    
#ifdef _WIN32
    for (i = 0; i < m_nDstH; i++) 
#else
    for (i = (m_nDstH-1); i >=0 ; i--) 
#endif
    {
	      if (osis->theConsumer == 0) 
       {
	          break;
	      }
	      memcpy(buf, &pTemp[i * nPaddedWidth], m_nDstW);
	      execute_java_dynamic_method(ee, (HObject *) osis->theConsumer,
				    "setPixels",
				    SET_BYTE_PIXELS_SIG,
				    0, j, m_nDstW, 1,
				    cm, pixh, 0, nPaddedWidth);
	       if (exceptionOccurred(ee)) 
        {
	           break;
	       }
       j++;
    }
    //delete [] pTemp;
    GlobalFree(hDIB);
    VERIFY( ::ReleaseDC(::GetDesktopWindow(), hDC) );
    free(pBitmapInfo);
    if (buf == 0) {
	/* This can never happen, but we need to make a reference to buf
	 * at the bottom of this function so the buffer doesn't move
	 * while we are using it.
	 */
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return;
    }
}


#define SetRGBQUAD(p, r, g, b)	\
    {				\
	(p)->rgbRed      = r;	\
	(p)->rgbGreen    = g;	\
	(p)->rgbBlue     = b;	\
	(p)->rgbReserved = 0;	\
    }


void AwtImage::DisposePalette()
{
    if (m_pBitmapInfo) {
        free(m_pBitmapInfo);
        m_pBitmapInfo = NULL;
    }

    if (m_pTransMaskInfo) {
        free(m_pTransMaskInfo);
        m_pTransMaskInfo = NULL;
    }

    if (m_pAwtPalette != NULL) {
        m_pAwtPalette->Release();
        m_pAwtPalette = NULL;
    }   

    if (g_colorInfo[COLOR4].m_pPaletteColors) {
        free(g_colorInfo[COLOR4].m_pPaletteColors);
        g_colorInfo[COLOR4].m_pPaletteColors = NULL;
    }
}


struct Hjava_awt_image_ColorModel *AwtImage::getColorModel(RGBQUAD *pRGBQuad)
{
    struct Hjava_awt_image_ColorModel *awt_colormodel;
    HArrayOfByte *hR = (HArrayOfByte *) ArrayAlloc(T_BYTE, 256);
    HArrayOfByte *hG = (HArrayOfByte *) ArrayAlloc(T_BYTE, 256);
    HArrayOfByte *hB = (HArrayOfByte *) ArrayAlloc(T_BYTE, 256);
    char *aBase, *a;
    RGBQUAD *c, *cBase;
    
    cBase = pRGBQuad;
    //cBase = g_colorInfo[1].m_pPaletteColors;
    /* These loops copy backwards so that the aBase pointer won't
     * be dropped by the optimizer and allow the garbage collector
     * to move the array being initialized.
     */
    aBase = unhand(hR)->body;
    for (a = aBase + 255, c = cBase + 255; a >= aBase; a--, c--) {
	*a = c->rgbRed;
    }
    aBase = unhand(hG)->body;
    for (a = aBase + 255, c = cBase + 255; a >= aBase; a--, c--) {
	*a = c->rgbGreen;
    }
    aBase = unhand(hB)->body;
    for (a = aBase + 255, c = cBase + 255; a >= aBase; a--, c--) {
	*a = c->rgbBlue;
    }
    awt_colormodel = (struct Hjava_awt_image_ColorModel *)
	execute_java_constructor(EE(),
				 "java/awt/image/IndexColorModel",
				 0, "(II[B[B[B)",
				 8, 256, hR, hG, hB);
    return awt_colormodel;
}

#define STATIC_COLOR_OFFSET 10


// -----------------------------------------------------------------------
// Copy the image into a DIB with origin at lower left hand corner.
// This handles the IndexColorModel case.
// -----------------------------------------------------------------------
long
AwtImage::copyImagePartInto8BitBuffer(
			      int bgcolor, int srcX, int srcY,
			      int srcW, int srcH, BYTE *srcpix,
			      int srcOff)
{
    int32_t scanLineSize = (m_nSrcW + 3) & ~0x3L;//ULONG Aligned.
    BYTE FAR *srcStartByte = (BYTE FAR *)srcpix+srcOff;
    BYTE FAR *dstStartLine = m_pBitmapData
                          +((m_nSrcH-srcY-1)*scanLineSize); 
   BYTE FAR *dstStartByte = dstStartLine+srcX;
   CHECK_BOUNDARY_CONDITION_RETURN(( (dstStartByte+srcW) > (dstStartLine+scanLineSize) ),"Destination buffer overshoot", AWT_IMAGE_COPY_FAILURE);

   for(int i=0; i<srcH; i++)
   {
   /*
#ifdef  _WIN32
     memcpy(dstStartByte, srcStartByte,  srcW);
#else
     _fmemccpy( dstStartByte, srcStartByte, 0, srcW);
#endif
*/
      for(int j=0; j<srcW; j++)
      {
         *dstStartByte++ = (BYTE)((*srcStartByte++)+STATIC_COLOR_OFFSET);
      }
     //dstStartLine-=scanLineSize;
     //dstStartByte = dstStartLine+srcX;
     dstStartByte = (dstStartLine-=scanLineSize)+srcX; 
   }
   return AWT_IMAGE_COPY_SUCCESS;
}


// -----------------------------------------------------------------------
//
// Copy the image into a DIB with origin at lower left hand corner.
// The first cut assumes a dcm will have a default masks set.
// This handles the DirectColorModel case.
// REMIND: Try getRed from Java colormodel once this works and the cm is 
//         different from index or direct.
// -----------------------------------------------------------------------

long
AwtImage::copyImagePartInto24BitBuffer(
			      int bgcolor, int srcX, int srcY,
			      int srcW, int srcH, int *srcpix,
			      int srcOff)
{
   int scanLineSize = (m_nSrcW*3 + 3) & ~0x3L;//ULONG Aligned.
   int FAR *srcStartInt = (int FAR *)srcpix+srcOff;
   BYTE FAR *dstStartLine = m_pBitmapData
                          +((m_nSrcH-srcY-1)*scanLineSize); 
   BYTE FAR *dstStartByte = dstStartLine+(srcX*3);
   int pixel = 0;
   CHECK_BOUNDARY_CONDITION_RETURN(( (dstStartByte+(srcW*3)) > (dstStartLine+scanLineSize) ),"Destination buffer overshoot", 0);
   for(int i=0; i<srcH; i++)
   {
      for(int j=0; j<srcW; j++)
      {
         *dstStartByte++ = (BYTE)(GETBLUE (*srcStartInt));
         *dstStartByte++ = (BYTE)(GETGREEN(*srcStartInt));
         *dstStartByte++ = (BYTE)(GETRED  (*srcStartInt++));
      }
      dstStartByte = (dstStartLine-=scanLineSize)+(srcX*3); 
   }
   m_nLastLine += srcH;
   return AWT_IMAGE_COPY_SUCCESS;
}


// API from Java side.


extern "C" {
void
sun_awt_image_ImageRepresentation_offscreenInit(HImageRepresentation *irh)
{
    CHECK_NULL(irh, "ImageRepresentation is null.");

    ImageRepresentation * ir = unhand(irh);
    CHECK_BOUNDARY_CONDITION((ir->width <= 0 || ir->height <= 0),"IllegalArgumentException");


    AwtImage *pImage = new AwtImage;
    CHECK_NULL(pImage, "OutOfMemoryError");
    if (!pImage->Create(irh, ir->width, ir->height)) 
    {
	      SignalError(0, JAVAPKG "OutOfMemoryError", 0);
	      delete pImage;
    } 
    else 
    {
	     unhand(irh)->pData = (long)pImage;
	     unhand(irh)->availinfo = IMAGE_OFFSCRNINFO;
    }
}

long
sun_awt_image_ImageRepresentation_setBytePixels(HImageRepresentation *irh,
						long x, long y,
						long w, long h,
						HColorModel *cmh, HArrayOfByte *arrh,
						long off, long scansize)
{
    CHECK_BOUNDARY_CONDITION_RETURN((irh == 0 || cmh == 0 || arrh == 0),"NullPointerException", -1);
    //CHECK_BOUNDARY_CONDITION_RETURN((w <= 0 || h <= 0),"IllegalArgumentException", -1);
    if((w <= 0 || h <= 0))
    {
       return -1;
    }
    CHECK_BOUNDARY_CONDITION_RETURN(((long)obj_length(arrh) < (scansize * h)),"ArrayIndexOutOfBoundsException", -1);

    long ret=0;
    AwtImage *pImage = (AwtImage *) unhand(irh)->pData;
    if (pImage == NULL &&
	        (unhand(irh)->availinfo & IMAGE_SIZEINFO) == IMAGE_SIZEINFO)
    {
		pImage = new AwtImage();
		pImage->Init(irh, cmh); // Will init m_pAwtPalette
		unhand(irh)->pData = (long) pImage;
    }

    CHECK_NULL_AND_RETURN(pImage, "OutOfMemoryError", ret);
    ret = pImage->GenericImageConvert(cmh, 0, x, y, w, h,
					   unhand(arrh), off, 8, scansize,
					   pImage->GetSrcWidth(),
					   pImage->GetSrcHeight(),
					   pImage->GetWidth(),
					   pImage->GetHeight(),
					   pImage);
    return ret;
}

long
sun_awt_image_ImageRepresentation_setIntPixels(HImageRepresentation * irh,
					       long x, long y, long w, long h,
					       HColorModel * cmh, HArrayOfInt  *arrh,
					       long off, long scansize)
{
    CHECK_BOUNDARY_CONDITION_RETURN((irh == 0 || cmh == 0 || arrh == 0),"NullPointerException", -1);
    //CHECK_BOUNDARY_CONDITION_RETURN((w <= 0 || h <= 0),"IllegalArgumentException", -1);
    if((w <= 0 || h <= 0))
    {
       return -1;
    }
    CHECK_BOUNDARY_CONDITION_RETURN(((long)obj_length(arrh) < (scansize * h)),"ArrayIndexOutOfBoundsException", -1);

    long ret=0;
    AwtImage *pImage = (AwtImage *) unhand(irh)->pData;
    if (pImage == NULL &&
	        (unhand(irh)->availinfo & IMAGE_SIZEINFO) == IMAGE_SIZEINFO)
    {
	      pImage = new AwtImage();
	      pImage->Init(irh, cmh);
       /*
       if( pImage->m_pAwtPalette != NULL )
       {
          switch (pImage->m_pAwtPalette->GetBitsPerPixel())
          {
             // Right now we support only 24 bit RGB input.
             case 24:
             {
               // Never called as this case is handled by 
               // the setIntPixels. But may be used later if 
               // we send continuous byte streams even for 24 bit.
        	      pImage->Alloc24BitConsumerBuffer();
               break;
             }
             default :
               break;
          }
       }
       */
	      unhand(irh)->pData = (long) pImage;
    }

    CHECK_NULL_AND_RETURN(pImage, "OutOfMemoryError", -1);
    ret = pImage->GenericImageConvert(cmh, 0, x, y, w, h,
					   unhand(arrh), off, 32, scansize,
					   pImage->GetSrcWidth(),
					   pImage->GetSrcHeight(),
					   pImage->GetWidth(),
					   pImage->GetHeight(),
					   pImage);
    return ret;
}

long
sun_awt_image_ImageRepresentation_finish(HImageRepresentation * irh, long force)
{
    int ret = 0;
    CHECK_NULL_AND_RETURN(irh, "NullPointerException", ret);
    AwtImage *pImage = (AwtImage *) unhand(irh)->pData;

    if (pImage != 0) 
    {
     	 ret = pImage->freeRenderData(force);
    }
    return ret;
}

void
sun_awt_image_ImageRepresentation_imageDraw(HImageRepresentation * irh, HGraphics *gh,
					    long x, long y,
					    HColor *c)
{
    HWGraphics *self;
    CHECK_BOUNDARY_CONDITION((irh == 0 || gh == 0),"NullPointerException");
    self = (HWGraphics *)gh;
    ImageRepresentation *ir = unhand(irh);
    //CHECK_BOUNDARY_CONDITION(((ir->availinfo & IMAGE_DRAWINFO) != IMAGE_DRAWINFO),"NullPointerException");

    AwtImage *pImage = (AwtImage *)ir->pData;
    AwtGraphics *pGraphics = (AwtGraphics *)unhand(self)->pData;
	if (pGraphics != NULL && pImage != NULL) 
	{
		pGraphics->DrawImage(pImage, x, y, c);
	}
}

void
sun_awt_image_ImageRepresentation_disposeImage(HImageRepresentation * irh)
{
//REMIND: This is never called. from any peers.!!

    CHECK_NULL(irh, "NullPointerException");
    AwtImage *pImage = (AwtImage *) unhand(irh)->pData;
    if (pImage != NULL) 
    {
	      delete pImage;
	      unhand(irh)->pData = NULL;
    }
}

void
sun_awt_image_OffScreenImageSource_sendPixels(HOffScreenImageSource *osish)
{
    OffScreenImageSource * osis = unhand(osish);
    HImageRepresentation * irh = osis->baseIR;
    ImageRepresentation * ir;

    CHECK_NULL(irh, "NullPointerException");
    ir = unhand(irh);

    CHECK_BOUNDARY_CONDITION(((ir->availinfo & IMAGE_OFFSCRNINFO) != IMAGE_OFFSCRNINFO),"IllegalAccessError");
    AwtImage *pImage = (AwtImage *) unhand(irh)->pData;
    if (pImage == NULL &&
	        (unhand(irh)->availinfo & IMAGE_SIZEINFO) == IMAGE_SIZEINFO)
    {
	      pImage = new AwtImage();
	      pImage->Init(irh, NULL);
	      unhand(irh)->pData = (long) pImage;
    }
    CHECK_NULL(pImage, "OutOfMemoryError");
    pImage->sendPixels(osis);
}

};  // end of extern "C"