Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes
nsImageWin Class Reference

#include <nsImageWin.h>

Inheritance diagram for nsImageWin:
Inheritance graph
[legend]
Collaboration diagram for nsImageWin:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsImageWin ()
 
Constructor for nsImageWin dc - 11/20/98
 ~nsImageWin ()
 
destructor for nsImageWin dc - 11/20/98
virtual NS_DECL_ISUPPORTS PRInt32 GetBytesPix ()
virtual PRInt32 GetHeight ()
 Get the height for the pixelmap - dwc 2/1/99.
virtual PRBool GetIsRowOrderTopToBottom ()
 Get whether rows are organized top to bottom, or bottom to top - syd 3/29/99.
virtual PRInt32 GetWidth ()
 Get the width for the pixelmap - dwc 2/1/99.
virtual PRUint8GetBits ()
 
See documentation in nsImageWin.h Get a pointer to the bits for the pixelmap.
virtual PRInt32 GetLineStride ()
 Get the number of bytes needed to get to the next scanline for the pixelmap - dwc 2/1/99.
virtual PRBool GetHasAlphaMask ()
 Get whether this image has an alpha mask.
NS_IMETHOD Draw (nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
 
See documentation in nsIImageWin.h 3/27/00 dwc
NS_IMETHOD Draw (nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
 
See documentation in nsIImageWin.h 3/27/00 dwc
NS_IMETHOD DrawToImage (nsIImage *aDstImage, nscoord aDX, nscoord aDY, nscoord aDWidth, nscoord aDHeight)
 
This blends together GIF's for the animation...
virtual nsColorMapGetColorMap ()
 Get the colormap for the nsIImage - dwc 2/1/99.
virtual void ImageUpdated (nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect)
 
See documentation in nsIImageWin.h 3/27/00 dwc
virtual PRBool GetIsImageComplete ()
 
See documentation in nsIImage.h
virtual nsresult Init (PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements)
 
See documentation in nsIImageWin.h 3/27/00 dwc
virtual nsresult Optimize (nsIDeviceContext *aContext)
 
Create an optimized bitmap dc - 11/20/98
virtual PRUint8GetAlphaBits ()
 Get a pointer to the bits for the alpha mask - dwc 2/1/99.
virtual PRInt32 GetAlphaLineStride ()
 Get the number of bytes per scanline for the alpha mask - dwc 2/1/99.
NS_IMETHOD DrawTile (nsIRenderingContext &aContext, nsIDrawingSurface *aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, PRInt32 aPadX, PRInt32 aPadY, const nsRect &aTileRect)
 
See documentation in nsIRenderingContext.h
PRIntn GetSizeHeader ()
 Return the header size of the Device Independent Bitmap(DIB).
PRIntn GetSizeImage ()
 Return the image size of the Device Independent Bitmap(DIB).
PRInt32 CalcBytesSpan (PRUint32 aWidth)
 Calculate the number of bytes spaned for this image for a given width.
virtual PRInt8 GetAlphaDepth ()
 Get the alpha depth for the image mask - lordpixel 2001/05/16.
voidGetBitInfo ()
 Get the DIB specific informations for this bitmap.
NS_IMETHOD LockImagePixels (PRBool aMaskPixels)
 
Lock down the image pixels
NS_IMETHOD UnlockImagePixels (PRBool aMaskPixels)
 
Unlock the pixels, optimize this nsImageWin
NS_IMETHOD CreateDDB ()
 Create a DDB out of the imagebits, and destroy the imagebits.
NS_IMETHOD RemoveDDB ()
 Removes the DBB, restoring the imagebits if necessary.

Static Public Attributes

static PRInt32 gPlatform = GetPlatform()
static PRInt32 gOsMajorVersion = GetOsMajorVersion()

Private Member Functions

void CleanUpDIB ()
 Clean the device Independent bits that could be allocated by this object.
void CleanUpDDB ()
 Clean the device dependent bits that could be allocated by this object.
void CreateImageWithAlphaBits (HDC TheHDC)
void DrawComposited24 (unsigned char *aBits, PRUint8 *aImageRGB, PRUint32 aStrideRGB, PRUint8 *aImageAlpha, PRUint32 aStrideAlpha, int aWidth, int aHeight)
 
This is a helper routine to do the blending for the DrawComposited method 1/04/02 dwc
nsresult DrawComposited (HDC TheHDC, int aDX, int aDY, int aDWidth, int aDHeight, int aSX, int aSY, int aSWidth, int aSHeight, int aOrigDWidth, int aOrigDHeight)
 
Blend the image into a 24 bit buffer.
nsresult ConvertDDBtoDIB ()
 Recreate a device independent image from a device dependent image (DDB) Does not remove the DDB.
nsresult PrintDDB (nsIDrawingSurface *aSurface, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight, PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight, PRUint32 aROP)
 Print a DDB dc - 05/20/99.
PRBool ProgressiveDoubleBlit (nsIDeviceContext *aContext, nsIDrawingSurface *aSurface, PRInt32 aSXOffset, PRInt32 aSYOffset, nsRect aDestRect)
 Progressively double the bitmap size as we blit.
void BlitImage (HDC aDstDC, HDC aDstMaskDC, PRInt32 aDstX, PRInt32 aDstY, PRInt32 aWidth, PRInt32 aHeight, HDC aSrcDC, HDC aSrcMaskDC, PRInt32 aSrcX, PRInt32 aSrcY, PRBool aUseAlphaBlend)
 Draw Image and Mask (if one exists) to another set of DCs.
PRUint8 PaletteMatch (PRUint8 r, PRUint8 g, PRUint8 b)
 Get an index in the palette that matches as closly as possible the passed in RGB colors dc - 4/20/2000.

Static Private Member Functions

static PRBool CanAlphaBlend (void)
static void TimerCallBack (nsITimer *aTimer, void *aClosure)

Private Attributes

PRPackedBool mInitialized
PRPackedBool mWantsOptimization
PRPackedBool mIsOptimized
PRPackedBool mIsLocked
PRPackedBool mDIBTemp
PRPackedBool mImagePreMultiplied
PRInt8 mNumBytesPixel
PRInt16 mNumPaletteColors
PRInt32 mSizeImage
PRInt32 mRowBytes
PRUint8mImageBits
nsColorMapmColorMap
PRInt32 mDecodedX1
PRInt32 mDecodedY1
PRInt32 mDecodedX2
PRInt32 mDecodedY2
PRUint8mAlphaBits
PRInt8 mAlphaDepth
PRInt32 mARowBytes
PRInt8 mImageCache
HBITMAP mHBitmap
LPBITMAPINFOHEADER mBHead
nsCOMPtr< nsITimermTimer

Static Private Attributes

static ALPHABLENDPROC gAlphaBlend = NULL

Detailed Description

Definition at line 81 of file nsImageWin.h.


Constructor & Destructor Documentation


destructor for nsImageWin dc - 11/20/98

Definition at line 106 of file nsImageWin.cpp.

{
  if (mTimer)
    mTimer->Cancel();

  CleanUpDDB();
  CleanUpDIB();

  if (mBHead) {
    delete[] mBHead;
    mBHead = nsnull;
  }
  if (mAlphaBits) {
    delete [] mAlphaBits;
    mAlphaBits = nsnull;
  }
}

Here is the call graph for this function:


Member Function Documentation

void nsImageWin::BlitImage ( HDC  aDstDC,
HDC  aDstMaskDC,
PRInt32  aDstX,
PRInt32  aDstY,
PRInt32  aWidth,
PRInt32  aHeight,
HDC  aSrcDC,
HDC  aSrcMaskDC,
PRInt32  aSrcX,
PRInt32  aSrcY,
PRBool  aUseAlphaBlend 
) [private]

Draw Image and Mask (if one exists) to another set of DCs.

Parameters:
aDstDCWhere aSrcDC will be drawn to
aDstMaskDCWhere aMaskDC will be drawn to. If same as aDstDC and there's a aSrcMaskDC, blending occurs.
aDstXx-pos of where to start drawing to
aDstYy-pos of where to start drawing to
aWidthWidth to copy from src to dst
aHeightHeight to copy from src to dst
aSrcDCSource Image
aSrcMaskDCSource Mask. If nsnull, aDstMaskDC will be ignored
aSrcXcopy src starting at this x position
aSrcYcopy src starting at this y position
aUseAlphaBlendWhen True, aDstSrc is a 32-bit DC storing alpha information in the 4th byte, so use AlphaBlend API instead of BitBlt. When False, BitBlt is used.

Definition at line 1370 of file nsImageWin.cpp.

{
  if (aUseAlphaBlend) {
    BLENDFUNCTION blendFunction;
    blendFunction.BlendOp = AC_SRC_OVER;
    blendFunction.BlendFlags = 0;
    blendFunction.SourceConstantAlpha = 255;
    blendFunction.AlphaFormat = 1;
    gAlphaBlend(aDstDC, aDstX, aDstY, aWidth, aHeight,
                aSrcDC, aSrcX, aSrcY, aWidth, aHeight, blendFunction);
  } else {
    if (aSrcMaskDC) {
      if (aDstMaskDC == aDstDC) {
        ::BitBlt(aDstDC, aDstX, aDstY, aWidth, aHeight,
                 aSrcMaskDC, aSrcX, aSrcY, SRCAND);
        ::BitBlt(aDstDC, aDstX, aDstY, aWidth, aHeight,
                 aSrcDC, aSrcX, aSrcY, SRCPAINT);
      } else {
        ::BitBlt(aDstMaskDC, aDstX, aDstY, aWidth, aHeight,
                 aSrcMaskDC, aSrcX, aSrcY, SRCCOPY);
        ::BitBlt(aDstDC, aDstX, aDstY, aWidth, aHeight,
                  aSrcDC, aSrcX, aSrcY, SRCCOPY);
      }
    } else {
      ::BitBlt(aDstDC, aDstX, aDstY, aWidth, aHeight,
               aSrcDC, aSrcX, aSrcY, SRCCOPY);
    }
  }
}

Here is the caller graph for this function:

Calculate the number of bytes spaned for this image for a given width.


Calculate the number of bytes in a span for this image dc - 11/20/98

Parameters:
aWidthis the width to calculate the number of bytes for
Returns:
the number of bytes in this span
Parameters:
aWidth- The width to calulate the number of bytes from
Returns:
Number of bytes for the span

Definition at line 1578 of file nsImageWin.cpp.

{
  PRInt32 spanBytes;


  spanBytes = (aWidth * mBHead->biBitCount) >> 5;


  if (((PRUint32)mBHead->biWidth * mBHead->biBitCount) & 0x1F) 
    spanBytes++;


  spanBytes <<= 2;


  return(spanBytes);
}
PRBool nsImageWin::CanAlphaBlend ( void  ) [static, private]

Definition at line 1407 of file nsImageWin.cpp.

{
#ifdef WINCE
  gAlphaBlend = nsnull;
  return PR_FALSE;
#else
  static PRBool alreadyChecked = PR_FALSE;

  if (!alreadyChecked) {
    OSVERSIONINFO os;
    
    os.dwOSVersionInfoSize = sizeof(os);
    ::GetVersionEx(&os);
    // If running on Win98, disable using AlphaBlend()
    // to avoid Win98 AlphaBlend() bug
    if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
        os.dwMajorVersion != 4 || os.dwMinorVersion != 10) {
      gAlphaBlend = (ALPHABLENDPROC)::GetProcAddress(::LoadLibrary("msimg32"),
              "AlphaBlend");
    }
    alreadyChecked = PR_TRUE;
  }

  return gAlphaBlend != NULL;
#endif
}

Here is the caller graph for this function:

Clean the device dependent bits that could be allocated by this object.


See documentation in nsImageWin.h 4/05/00 dwc

dc - 04/05/00

Definition at line 1623 of file nsImageWin.cpp.

{
  if (mHBitmap != nsnull) {
    if (mTimer) {
      mTimer->Cancel();
      mTimer = nsnull;
    }

    ::DeleteObject(mHBitmap);
    mHBitmap = nsnull;
  }
  mIsOptimized = PR_FALSE;
}

Here is the caller graph for this function:

Clean the device Independent bits that could be allocated by this object.


See documentation in nsImageWin.h 4/05/00 dwc

dc - 04/05/00

Definition at line 1602 of file nsImageWin.cpp.

{
  if (mImageBits != nsnull) {
    delete [] mImageBits;
    mImageBits = nsnull;
  }


  // Should be an ISupports, so we can release
  if (mColorMap != nsnull){
    delete [] mColorMap->Index;
    delete mColorMap;
    mColorMap = nsnull;
  }
}

Here is the caller graph for this function:

Recreate a device independent image from a device dependent image (DDB) Does not remove the DDB.


recreate a device independent image from a device dependent image (DDB) Does not remove the DDB

Returns:
the result of the operation, if NS_OK a DIB was created.

Definition at line 1690 of file nsImageWin.cpp.

{
  HDC                 memPrDC;

  if (mImageBits)
    return NS_OK;

  if (!mInitialized || mHBitmap == nsnull)
    return NS_ERROR_FAILURE;

  memPrDC = ::CreateDC("DISPLAY", NULL, NULL, NULL);
  if (!memPrDC)
    return NS_ERROR_FAILURE;

  // Allocate the image bits
  mImageBits = new unsigned char[mSizeImage];
  if (!mImageBits) {
    ::DeleteDC(memPrDC);
    return NS_ERROR_OUT_OF_MEMORY;
  }

  PRInt32 retVal = 
    ::GetDIBits(memPrDC, mHBitmap, 0, mBHead->biHeight,
                mImageBits, (LPBITMAPINFO)mBHead,
                256 == mNumPaletteColors ? DIB_PAL_COLORS : DIB_RGB_COLORS);

  ::GdiFlush();
  ::DeleteDC(memPrDC);

  if (retVal == 0) {
    delete [] mImageBits;
    mImageBits = nsnull;
    return NS_ERROR_FAILURE;
  }
  
  // If we converted a 8 bit alpha back to bits, those bits are pre-multiplied
  if (mAlphaDepth == 8)
    mImagePreMultiplied = PR_TRUE;

  return NS_OK;
}

Here is the caller graph for this function:

Create a DDB out of the imagebits, and destroy the imagebits.

Definition at line 1449 of file nsImageWin.cpp.

{
  if (!mWantsOptimization || mIsOptimized) {
    // Timer only exists when mIsOptimized.  Push timer forwards.
    if (mTimer)
      mTimer->SetDelay(GFX_MS_REMOVE_DBB);

    return NS_OK;
  }

  // we used to set a flag because a valid HDC may not be ready, 
  // like at startup, but now we just roll our own HDC for the given screen.

  //
  // Some images should not be converted to DDB...
  //
  // Windows 95/98/Me: DDB size cannot exceed ~16MB in size.
  // We also can not optimize empty images, or 8-bit alpha depth images on
  // Win98 due to a Windows API bug.
  //
  // On Windows 95/98/Me, GDI resources are very limited.  Windows NT has more,
  // but is still rather limited. Create DDBs on these platforms only for
  // large (> 128k) images to minimize GDI handle usage.
  // See bug 205893, bug 204374, and bug 216430 for more info on the situation.
  // Bottom-line: we need a better accounting mechanism to avoid exceeding the
  // system's GDI object limit.  The rather arbitrary size limitation imposed
  // here is based on the typical size of the Mozilla memory cache.  This is 
  // most certainly the wrong place to impose this policy, but we do it for
  // now as a stop-gap measure.
  //
  if ((gOsMajorVersion <= VER_OSMAJOR_WIN9598MENT &&
       (mSizeImage >= 0xFF0000 || mSizeImage < 0x20000)) ||
      (mAlphaDepth == 8 && !CanAlphaBlend())) {
    return NS_OK;
  }

  HDC TheHDC = ::CreateCompatibleDC(NULL);
  
  if (TheHDC != NULL){
    // Temporary fix for bug 135226 until we do better decode-time
    // dithering and paletized storage of images. Bail on the 
    // optimization to DDB if we're on a paletted device.
    int rasterCaps = ::GetDeviceCaps(TheHDC, RASTERCAPS);
    if (RC_PALETTE == (rasterCaps & RC_PALETTE)) {
      ::DeleteDC(TheHDC);
      return NS_OK;
    }
  
    // we have to install the correct bitmap to get a good DC going
    int planes = ::GetDeviceCaps(TheHDC, PLANES);
    int bpp = ::GetDeviceCaps(TheHDC, BITSPIXEL);

    HBITMAP  tBitmap = ::CreateBitmap(1,1,planes,bpp,NULL);
    HBITMAP oldbits = (HBITMAP)::SelectObject(TheHDC,tBitmap);

    if (mAlphaDepth == 8) {
      CreateImageWithAlphaBits(TheHDC);
    } else {
      // Apparently, DIBs use less resources than DDBs.
      // On Windows 95/98/Me/NT, use DIBs to save resources.  On remaining
      // platforms, use DDBs.  DDBs draw at the same speed or faster when
      // drawn to a DDB surface.  This is another temporary solution until
      // we manage our resources better.
      if (gOsMajorVersion <= VER_OSMAJOR_WIN9598MENT) {
        LPVOID bits;
        mHBitmap = ::CreateDIBSection(TheHDC, (LPBITMAPINFO)mBHead,
          256 == mNumPaletteColors ? DIB_PAL_COLORS : DIB_RGB_COLORS,
          &bits, NULL, 0);

        if (mHBitmap) {
          memcpy(bits, mImageBits, mSizeImage);
          mIsOptimized = PR_TRUE;
        } else {
          mIsOptimized = PR_FALSE;
        }
      } else {
        mHBitmap = ::CreateDIBitmap(TheHDC, mBHead, CBM_INIT, mImageBits,
                                    (LPBITMAPINFO)mBHead,
                                    256 == mNumPaletteColors ? DIB_PAL_COLORS
                                                             : DIB_RGB_COLORS);
        mIsOptimized = (mHBitmap != 0);
      }
    }
    if (mIsOptimized) {
      ::GdiFlush();
      CleanUpDIB();

      if (mTimer) {
        mTimer->SetDelay(GFX_MS_REMOVE_DBB);
      } else {
        mTimer = do_CreateInstance("@mozilla.org/timer;1");
        if (mTimer)
          mTimer->InitWithFuncCallback(nsImageWin::TimerCallBack, this,
                                       GFX_MS_REMOVE_DBB,
                                       nsITimer::TYPE_ONE_SHOT);
      }
    }
    ::SelectObject(TheHDC,oldbits);
    ::DeleteObject(tBitmap);
    ::DeleteDC(TheHDC);
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsImageWin::CreateImageWithAlphaBits ( HDC  TheHDC) [private]

Definition at line 394 of file nsImageWin.cpp.

{
  unsigned char *imageWithAlphaBits;
  ALPHA32BITMAPINFO bmi(mBHead->biWidth, mBHead->biHeight);
  mHBitmap = ::CreateDIBSection(TheHDC, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS,
                                (LPVOID *)&imageWithAlphaBits, NULL, 0);


  if (!mHBitmap) {
    mIsOptimized = PR_FALSE;
    return;
  }
  
  if (256 == mNumPaletteColors) {
    for (int y = 0; y < mBHead->biHeight; y++) {
      unsigned char *imageWithAlphaRow = imageWithAlphaBits + y * mBHead->biWidth * 4;
      unsigned char *imageRow = mImageBits + y * mRowBytes;
      unsigned char *alphaRow = mAlphaBits + y * mARowBytes;


      for (int x = 0; x < mBHead->biWidth;
           x++, imageWithAlphaRow += 4, imageRow++, alphaRow++) {
        FAST_DIVIDE_BY_255(imageWithAlphaRow[0],
                           mColorMap->Index[3 * (*imageRow)] * *alphaRow);
        FAST_DIVIDE_BY_255(imageWithAlphaRow[1],
                           mColorMap->Index[3 * (*imageRow) + 1] * *alphaRow);
        FAST_DIVIDE_BY_255(imageWithAlphaRow[2],
                           mColorMap->Index[3 * (*imageRow) + 2] * *alphaRow);
        imageWithAlphaRow[3] = *alphaRow;
      }
    }
  } else if (mImagePreMultiplied) {
    for (int y = 0; y < mBHead->biHeight; y++) {
      unsigned char *imageWithAlphaRow = imageWithAlphaBits + y * mBHead->biWidth * 4;
      unsigned char *imageRow = mImageBits + y * mRowBytes;
      unsigned char *alphaRow = mAlphaBits + y * mARowBytes;

      for (int x = 0; x < mBHead->biWidth;
          x++, imageWithAlphaRow += 4, imageRow += 3, alphaRow++) {
        memcpy(imageWithAlphaRow, imageRow, 3);
        imageWithAlphaRow[3] = *alphaRow;
      }
    }
  } else {
    for (int y = 0; y < mBHead->biHeight; y++) {
      unsigned char *imageWithAlphaRow = imageWithAlphaBits + y * mBHead->biWidth * 4;
      unsigned char *imageRow = mImageBits + y * mRowBytes;
      unsigned char *alphaRow = mAlphaBits + y * mARowBytes;


      for (int x = 0; x < mBHead->biWidth;
          x++, imageWithAlphaRow += 4, imageRow += 3, alphaRow++) {
        FAST_DIVIDE_BY_255(imageWithAlphaRow[0], imageRow[0] * *alphaRow);
        FAST_DIVIDE_BY_255(imageWithAlphaRow[1], imageRow[1] * *alphaRow);
        FAST_DIVIDE_BY_255(imageWithAlphaRow[2], imageRow[2] * *alphaRow);
        imageWithAlphaRow[3] = *alphaRow;
      }
    }
  }
  mIsOptimized = PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsImageWin::Draw ( nsIRenderingContext aContext,
nsIDrawingSurface aSurface,
PRInt32  aX,
PRInt32  aY,
PRInt32  aWidth,
PRInt32  aHeight 
) [virtual]


See documentation in nsIImageWin.h 3/27/00 dwc

Implements nsIImage.

Definition at line 798 of file nsImageWin.cpp.

{
  return Draw(aContext, aSurface, 0, 0, mBHead->biWidth, mBHead->biHeight, aX, aY, aWidth, aHeight);
}

Here is the caller graph for this function:

NS_IMETHODIMP nsImageWin::Draw ( nsIRenderingContext aContext,
nsIDrawingSurface aSurface,
PRInt32  aSX,
PRInt32  aSY,
PRInt32  aSWidth,
PRInt32  aSHeight,
PRInt32  aDX,
PRInt32  aDY,
PRInt32  aDWidth,
PRInt32  aDHeight 
) [virtual]


See documentation in nsIImageWin.h 3/27/00 dwc

Implements nsIImage.

Definition at line 461 of file nsImageWin.cpp.

{
  if (mBHead == nsnull || 
      aSWidth < 0 || aDWidth < 0 || aSHeight < 0 || aDHeight < 0)
    return NS_ERROR_FAILURE;

  if (0 == aSWidth || 0 == aDWidth || 0 == aSHeight || 0 == aDHeight)
    return NS_OK;

  if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1)
    return NS_OK;

  PRInt32 origSHeight = aSHeight, origDHeight = aDHeight;
  PRInt32 origSWidth = aSWidth, origDWidth = aDWidth;

  // limit the size of the blit to the amount of the image read in
  if (aSX + aSWidth > mDecodedX2) {
    aDWidth -= ((aSX + aSWidth - mDecodedX2) * origDWidth) / origSWidth;
    aSWidth -= (aSX + aSWidth) - mDecodedX2;
  }
  if (aSX < mDecodedX1) {
    aDX += ((mDecodedX1 - aSX) * origDWidth) / origSWidth;
    aSX = mDecodedX1;
  }

  if (aSY + aSHeight > mDecodedY2) {
    aDHeight -= ((aSY + aSHeight - mDecodedY2) * origDHeight) / origSHeight;
    aSHeight -= (aSY + aSHeight) - mDecodedY2;
  }
  if (aSY < mDecodedY1) {
    aDY += ((mDecodedY1 - aSY) * origDHeight) / origSHeight;
    aSY = mDecodedY1;
  }

  if (aDWidth <= 0 || aDHeight <= 0)
    return NS_OK;

  // Translate to bottom-up coordinates for the source bitmap
  PRInt32 srcy = mBHead->biHeight - (aSY + aSHeight);

  HDC     TheHDC;
  ((nsDrawingSurfaceWin *)aSurface)->GetDC(&TheHDC);
  if (!TheHDC)
    return NS_ERROR_FAILURE;

  // find out if the surface is a printer.
  PRInt32 canRaster;
  ((nsDrawingSurfaceWin *)aSurface)->GetTECHNOLOGY(&canRaster);

  CreateDDB();

  PRBool didComposite = PR_FALSE;
  if (!mIsOptimized || !mHBitmap) {
    DWORD rop = SRCCOPY;

    if (mAlphaBits) {
      if (1 == mAlphaDepth) {
        MONOBITMAPINFO  bmi(mBHead->biWidth, mBHead->biHeight);

        if (canRaster == DT_RASPRINTER) {
          CompositeBitsInMemory(TheHDC, aDX, aDY, aDWidth, aDHeight,
                                aSX, aSY, aSWidth, aSHeight,
                                srcy, mAlphaBits, &bmi, mImageBits, mBHead,
                                mNumPaletteColors);
          didComposite = PR_TRUE;
        } else {
          // Put the mask down
          ::StretchDIBits(TheHDC, aDX, aDY, aDWidth, aDHeight,
                          aSX, srcy, aSWidth, aSHeight, mAlphaBits,
                          (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCAND);
          rop = SRCPAINT;
        }
      } else if (8 == mAlphaDepth) {
        nsresult rv = DrawComposited(TheHDC, aDX, aDY, aDWidth, aDHeight,
                                     aSX, srcy, aSWidth, aSHeight,
                                     origDWidth, origDHeight);
        if (NS_FAILED(rv)) {
          ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
          return rv;
        }
        didComposite = PR_TRUE;
      }
    } // mAlphaBits

    // Put the Image down
    if (!didComposite) {
      ::StretchDIBits(TheHDC, aDX, aDY, aDWidth, aDHeight,
                      aSX, srcy, aSWidth, aSHeight, mImageBits,
                      (LPBITMAPINFO)mBHead, 256 == mNumPaletteColors ? 
                      DIB_PAL_COLORS : DIB_RGB_COLORS, rop);
    }
  } else {
    // Optimized.  mHBitmap contains the DDB
    DWORD rop = SRCCOPY;

    if (canRaster == DT_RASPRINTER) {
      // To Printer
      if (mAlphaBits && mAlphaDepth == 1) {
        MONOBITMAPINFO  bmi(mBHead->biWidth, mBHead->biHeight);
        if (mImageBits) {
          CompositeBitsInMemory(TheHDC, aDX, aDY, aDWidth, aDHeight,
                                aSX, aSY, aSWidth, aSHeight, srcy,
                                mAlphaBits, &bmi, mImageBits, mBHead,
                                mNumPaletteColors);
          didComposite = PR_TRUE;  
        } else {
          ConvertDDBtoDIB(); // Create mImageBits
          if (mImageBits) {  
            CompositeBitsInMemory(TheHDC, aDX, aDY, aDWidth, aDHeight,
                                  aSX, aSY, aSWidth, aSHeight, srcy,
                                  mAlphaBits,
                                  &bmi, mImageBits, mBHead,
                                  mNumPaletteColors);
            // Clean up the image bits    
            delete [] mImageBits;
            mImageBits = nsnull;
            didComposite = PR_TRUE;         
          } else {
            NS_WARNING("Could not composite bits in memory because conversion to DIB failed\n");
          }
        } // mImageBits
      } // mAlphaBits && mAlphaDepth == 1

      if (!didComposite && 
          (GetDeviceCaps(TheHDC, RASTERCAPS) & (RC_BITBLT | RC_STRETCHBLT)))
        PrintDDB(aSurface, aDX, aDY, aDWidth, aDHeight,
                 aSX, srcy, aSWidth, aSHeight, rop);

    } else { 
      // we are going to the device that created this DDB

      // Get srcDC from the drawing surface of aContext's (RenderingContext)
      // DeviceContext.  Should be the same each time.
      nsIDeviceContext    *dx;
      aContext.GetDeviceContext(dx);
      
      nsIDrawingSurface*     ds;
      NS_STATIC_CAST(nsDeviceContextWin*, dx)->GetDrawingSurface(aContext, ds);

      nsDrawingSurfaceWin *srcDS = (nsDrawingSurfaceWin *)ds;
      if (!srcDS) {
        NS_RELEASE(dx);
        ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
        return NS_ERROR_FAILURE;
      }      

      HDC                 srcDC;
      srcDS->GetDC(&srcDC);

      // Draw the Alpha/Mask
      if (mAlphaBits && mAlphaDepth == 1) {
        MONOBITMAPINFO  bmi(mBHead->biWidth, mBHead->biHeight);
        ::StretchDIBits(TheHDC, aDX, aDY, aDWidth, aDHeight,
                        aSX, srcy, aSWidth, aSHeight, mAlphaBits,
                        (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCAND);
        rop = SRCPAINT;
      }

      // Draw the Image
      HBITMAP oldBits = (HBITMAP)::SelectObject(srcDC, mHBitmap);
      if (8 == mAlphaDepth) {
        BLENDFUNCTION blendFunction;
        blendFunction.BlendOp = AC_SRC_OVER;
        blendFunction.BlendFlags = 0;
        blendFunction.SourceConstantAlpha = 255;
        blendFunction.AlphaFormat = 1;  // AC_SRC_ALPHA
        gAlphaBlend(TheHDC, aDX, aDY, aDWidth, aDHeight, 
                    srcDC, aSX, aSY, aSWidth, aSHeight, blendFunction);
      } else { 
        ::StretchBlt(TheHDC, aDX, aDY, aDWidth, aDHeight, 
                     srcDC, aSX, aSY, aSWidth, aSHeight, rop);
      }
      ::SelectObject(srcDC, oldBits);
      srcDS->ReleaseDC();
      NS_RELEASE(dx);
    }
  }
  ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();

  return NS_OK;
}

Here is the call graph for this function:

nsresult nsImageWin::DrawComposited ( HDC  TheHDC,
int  aDX,
int  aDY,
int  aDWidth,
int  aDHeight,
int  aSX,
int  aSY,
int  aSWidth,
int  aSHeight,
int  aOrigDWidth,
int  aOrigDHeight 
) [private]


Blend the image into a 24 bit buffer.

. using an 8 bit alpha mask 1/04/02 dwc

Definition at line 675 of file nsImageWin.cpp.

{
  HDC memDC = ::CreateCompatibleDC(TheHDC);
  if (!memDC)
    return NS_ERROR_OUT_OF_MEMORY;
  unsigned char *screenBits;

  PRBool scaling = PR_FALSE;
  /* Both scaled and unscaled images come through this code */
  if ((aDWidth != aSWidth) || (aDHeight != aSHeight)) {
    scaling = PR_TRUE;
    aDWidth = aOrigDWidth;
    aDHeight = aOrigDHeight;
    aSWidth = mBHead->biWidth;
    aSHeight = mBHead->biHeight;
  }

  ALPHA24BITMAPINFO bmi(aDWidth, aDHeight);
  HBITMAP tmpBitmap = ::CreateDIBSection(memDC, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS,
                                         (LPVOID *)&screenBits, NULL, 0);
  if (!tmpBitmap) {
    ::DeleteDC(memDC);
    NS_WARNING("nsImageWin::DrawComposited failed to create tmpBitmap\n");
    return NS_ERROR_OUT_OF_MEMORY;
  }
  HBITMAP oldBitmap = (HBITMAP)::SelectObject(memDC, tmpBitmap);
  if (!oldBitmap || oldBitmap == (HBITMAP)GDI_ERROR) {
    ::DeleteObject(tmpBitmap);
    ::DeleteDC(memDC);
    return NS_ERROR_OUT_OF_MEMORY;
  }

  /* Copy from the HDC */
  BOOL retval = ::BitBlt(memDC, 0, 0, aDWidth, aDHeight,
                         TheHDC, aDX, aDY, SRCCOPY);
  if (!retval || !::GdiFlush()) {
    /* select the old object again... */
    ::SelectObject(memDC, oldBitmap);
    ::DeleteObject(tmpBitmap);
    ::DeleteDC(memDC);
    return NS_ERROR_FAILURE;
  }

  PRUint8 *imageRGB, *imageAlpha;
  PRUint32 strideRGB, strideAlpha;

  if (scaling) {
    /* Scale our image to match */
    imageRGB = (PRUint8 *)nsMemory::Alloc(3*aDWidth*aDHeight);
    imageAlpha = (PRUint8 *)nsMemory::Alloc(aDWidth*aDHeight);

    if (!imageRGB || !imageAlpha) {
      if (imageRGB)
        nsMemory::Free(imageRGB);
      if (imageAlpha)
        nsMemory::Free(imageAlpha);
      ::SelectObject(memDC, oldBitmap);
      ::DeleteObject(tmpBitmap);
      ::DeleteDC(memDC);
      return NS_ERROR_FAILURE;
    }

    strideRGB = 3 * aDWidth;
    strideAlpha = aDWidth;
    RectStretch(aSWidth, aSHeight, aDWidth, aDHeight,
                0, 0, aDWidth-1, aDHeight-1,
                mImageBits, mRowBytes, imageRGB, strideRGB, 24);
    RectStretch(aSWidth, aSHeight, aDWidth, aDHeight,
                0, 0, aDWidth-1, aDHeight-1,
                mAlphaBits, mARowBytes, imageAlpha, strideAlpha, 8);
  } else {
    imageRGB = mImageBits + aSY * mRowBytes + aSX * 3;
    imageAlpha = mAlphaBits + aSY * mARowBytes + aSX;
    strideRGB = mRowBytes;
    strideAlpha = mARowBytes;
  }

  /* Do composite */
  DrawComposited24(screenBits, imageRGB, strideRGB, imageAlpha, strideAlpha,
                   aDWidth, aDHeight);

  if (scaling) {
    /* Free scaled images */
    nsMemory::Free(imageRGB);
    nsMemory::Free(imageAlpha);
  }

  /* Copy back to the HDC */
  /* Use StretchBlt instead of BitBlt here so that we get proper dithering */
  if (scaling) {
    /* only copy back the valid portion of the image */
    retval = ::StretchBlt(TheHDC, aDX, aDY,
                          aDWidth, (mDecodedY2*aDHeight + aSHeight - 1)/aSHeight,
                          memDC, 0, 0,
                          aDWidth, (mDecodedY2*aDHeight + aSHeight - 1)/aSHeight,
                          SRCCOPY);
  } else {
    retval = ::StretchBlt(TheHDC, aDX, aDY, aDWidth, aDHeight,
                          memDC, 0, 0, aDWidth, aDHeight, SRCCOPY);
  }

  if (!retval) {
    ::SelectObject(memDC, oldBitmap);
    ::DeleteObject(tmpBitmap);
    ::DeleteDC(memDC);
    return NS_ERROR_FAILURE;
  }

  /* we're done, ignore possible further errors */
  ::SelectObject(memDC, oldBitmap);
  ::DeleteObject(tmpBitmap);
  ::DeleteDC(memDC);
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsImageWin::DrawComposited24 ( unsigned char *  aBits,
PRUint8 aImageRGB,
PRUint32  aStrideRGB,
PRUint8 aImageAlpha,
PRUint32  aStrideAlpha,
int  aWidth,
int  aHeight 
) [private]


This is a helper routine to do the blending for the DrawComposited method 1/04/02 dwc

Definition at line 649 of file nsImageWin.cpp.

{
  PRInt32 targetRowBytes = ((aWidth * 3) + 3) & ~3;
  for (int y = 0; y < aHeight; y++) {
    unsigned char *targetRow = aBits + y * targetRowBytes;
    unsigned char *imageRow = aImageRGB + y * aStrideRGB;
    unsigned char *alphaRow = aImageAlpha + y * aStrideAlpha;

    for (int x = 0; x < aWidth;
         x++, targetRow += 3, imageRow += 3, alphaRow++) {
      unsigned alpha = *alphaRow;
      MOZ_BLEND(targetRow[0], targetRow[0], imageRow[0], alpha);
      MOZ_BLEND(targetRow[1], targetRow[1], imageRow[1], alpha);
      MOZ_BLEND(targetRow[2], targetRow[2], imageRow[2], alpha);
    }
  }
}

Here is the caller graph for this function:

NS_IMETHODIMP nsImageWin::DrawTile ( nsIRenderingContext aContext,
nsIDrawingSurface aSurface,
PRInt32  aSXOffset,
PRInt32  aSYOffset,
PRInt32  aPadX,
PRInt32  aPadY,
const nsRect aTileRect 
) [virtual]


See documentation in nsIRenderingContext.h

Implements nsIImage.

Definition at line 808 of file nsImageWin.cpp.

{
  NS_ASSERTION(!aDestRect.IsEmpty(), "DrawTile doesn't work with empty rects");
  if (mDecodedX2 < mDecodedX1 || mDecodedY2 < mDecodedY1)
    return NS_OK;

  float           scale;
  unsigned char   *targetRow,*imageRow,*alphaRow;
  PRInt32         x0, y0, x1, y1, destScaledWidth, destScaledHeight;
  PRInt32         validWidth,validHeight,validX,validY,targetRowBytes;
  PRInt32         x,y,width,height,canRaster;
  nsCOMPtr<nsIDeviceContext> theDeviceContext;
  HDC             theHDC;
  nscoord         ScaledTileWidth,ScaledTileHeight;
  PRBool          padded = (aPadX || aPadY);

  ((nsDrawingSurfaceWin *)aSurface)->GetTECHNOLOGY(&canRaster);
  aContext.GetDeviceContext(*getter_AddRefs(theDeviceContext));

  // We can Progressive Double Blit if we aren't printing to a printer, and
  // we aren't a 256 color image, and we don't have an unoptimized 8 bit alpha.
  if ((canRaster != DT_RASPRINTER) && (256 != mNumPaletteColors) &&
      !(mAlphaDepth == 8 && !mIsOptimized) && !padded)
    if (ProgressiveDoubleBlit(theDeviceContext, aSurface,
                              aSXOffset, aSYOffset, aDestRect))
      return NS_OK;
  theDeviceContext->GetCanonicalPixelScale(scale);

  destScaledWidth  = PR_MAX(PRInt32(mBHead->biWidth*scale), 1);
  destScaledHeight = PR_MAX(PRInt32(mBHead->biHeight*scale), 1);
  
  validX = 0;
  validY = 0;
  validWidth  = mBHead->biWidth;
  validHeight = mBHead->biHeight;
  
  // limit the image rectangle to the size of the image data which
  // has been validated.
  if (mDecodedY2 < mBHead->biHeight) {
    validHeight = mDecodedY2 - mDecodedY1;
    destScaledHeight = PR_MAX(PRInt32(validHeight*scale), 1);
  }
  if (mDecodedX2 < mBHead->biWidth) {
    validWidth = mDecodedX2 - mDecodedX1;
    destScaledWidth = PR_MAX(PRInt32(validWidth*scale), 1);
  }
  if (mDecodedY1 > 0) {   
    validHeight -= mDecodedY1;
    destScaledHeight = PR_MAX(PRInt32(validHeight*scale), 1);
    validY = mDecodedY1;
  }
  if (mDecodedX1 > 0) {
    validWidth -= mDecodedX1;
    destScaledWidth = PR_MAX(PRInt32(validWidth*scale), 1);
    validX = mDecodedX1; 
  }

  // put the DestRect into absolute coordintes of the device
  y0 = aDestRect.y - aSYOffset;
  x0 = aDestRect.x - aSXOffset;
  y1 = aDestRect.y + aDestRect.height;
  x1 = aDestRect.x + aDestRect.width;


  // this is the width and height of the image in pixels
  // we need to map this to the pixel height of the device
  ScaledTileWidth = PR_MAX(PRInt32(mBHead->biWidth*scale), 1);
  ScaledTileHeight = PR_MAX(PRInt32(mBHead->biHeight*scale), 1);

  // do alpha depth equal to 8 here.. this needs some special attention
  if (mAlphaDepth == 8 && !mIsOptimized && !padded) {
    unsigned char *screenBits=nsnull,*adjAlpha,*adjImage,*adjScreen;
    HDC           memDC=nsnull;
    HBITMAP       tmpBitmap=nsnull,oldBitmap;
    unsigned char alpha;
    PRInt32       targetBytesPerPixel,imageBytesPerPixel;

    if (!mImageBits) {
      ConvertDDBtoDIB();
    }

    // draw the alpha and the bitmap to an offscreen buffer.. for the blend.. first 
    ((nsDrawingSurfaceWin *)aSurface)->GetDC(&theHDC);
    if (theHDC) {
    // create a buffer for the blend            
      memDC = CreateCompatibleDC(theHDC);
      width = aDestRect.width;
      height = aDestRect.height;

      ALPHA24BITMAPINFO bmi(width, height);
      tmpBitmap = ::CreateDIBSection(memDC, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, (LPVOID *)&screenBits, NULL, 0);
      oldBitmap = (HBITMAP)::SelectObject(memDC, tmpBitmap);

      // number of bytes in a row on a 32 bit boundary
      targetRowBytes = (bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) >> 5;  // number of 32 bit longs
      if (((PRUint32)bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) & 0x1F) { // make sure its a multiple of 32
        targetRowBytes++;     // or else there will not be enough bytes per line
      }
      targetRowBytes <<= 2;   // divide by 4 to get the number of bytes from the number of 32 bit longs

      targetBytesPerPixel = bmi.bmiHeader.biBitCount/8;
    }

    if (!tmpBitmap) {
      if (memDC) {
        ::DeleteDC(memDC);
      }
      // this failed..and will fall into the slow blitting code
      NS_WARNING("The Creation of the tmpBitmap failed \n");
    } else {
      // Copy from the HDC to the memory DC
      // this will be the image on the screen into a buffer for the blend.
      ::StretchBlt(memDC, 0, 0, width, height,theHDC, aDestRect.x, aDestRect.y, width, height, SRCCOPY);
      ::GdiFlush();
  
      imageBytesPerPixel = mBHead->biBitCount/8;

      // windows bitmaps start at the bottom.. and go up.  This messes up the offsets for the
      // image and tiles.. so I reverse the the direction.. to go (the normal way) from top to bottom.
      adjScreen = screenBits + ((height-1) * targetRowBytes);
      adjImage = mImageBits + ((validHeight-1) * mRowBytes);
      adjAlpha = mAlphaBits + ((validHeight-1) * mARowBytes);


      for (int y = 0,byw=aSYOffset; y < height; y++,byw++) {

        if (byw >= ScaledTileHeight) {
          byw = 0;
        }

        targetRow = adjScreen - (y * targetRowBytes);
        imageRow = adjImage - (byw * mRowBytes);
        alphaRow = adjAlpha - (byw * mARowBytes);

        // we only need this adjustment at the beginning of each row
        imageRow += (aSXOffset*imageBytesPerPixel);
        alphaRow += aSXOffset;

        for (int x=0,bxw=aSXOffset;x<width;x++,targetRow+=targetBytesPerPixel,imageRow+=imageBytesPerPixel,bxw++, alphaRow++) {
          // if we went past the row width of our buffer.. go back and start again
          if (bxw>=ScaledTileWidth) {
            bxw = 0;
            imageRow = adjImage - (byw * mRowBytes);
            alphaRow = adjAlpha - (byw * mARowBytes);
          }

          alpha = *alphaRow;

          MOZ_BLEND(targetRow[0], targetRow[0], imageRow[0], alpha);
          MOZ_BLEND(targetRow[1], targetRow[1], imageRow[1], alpha);
          MOZ_BLEND(targetRow[2], targetRow[2], imageRow[2], alpha);
        }
      }

      // copy the blended image back to the screen
      ::StretchBlt(theHDC, aDestRect.x, aDestRect.y, width, height,memDC, 0, 0, width, height, SRCCOPY);

      ::SelectObject(memDC, oldBitmap);
      ::DeleteObject(tmpBitmap);
      ::DeleteDC(memDC);
  
    return(NS_OK);
    } 
  }

  // if we got to this point.. everything else failed.. and the slow blit backstop
  // will finish this tiling
  for (y=y0;y<y1;y+=ScaledTileHeight+aPadY*scale) {
    for (x=x0;x<x1;x+=ScaledTileWidth+aPadX*scale) {
    Draw(aContext, aSurface,
         0, 0, PR_MIN(validWidth, x1-x), PR_MIN(validHeight, y1-y),
         x, y, PR_MIN(destScaledWidth, x1-x), PR_MIN(destScaledHeight, y1-y));
    }
  } 
  return(NS_OK);
}

Here is the call graph for this function:

NS_IMETHODIMP nsImageWin::DrawToImage ( nsIImage aDstImage,
nscoord  aDX,
nscoord  aDY,
nscoord  aDWidth,
nscoord  aDHeight 
) [virtual]


This blends together GIF's for the animation...

called by gfxImageFrame currently does not support and 8bit blend. Assumed for animated GIF's only 07/09/2002 dwc

Parameters:
aDstImage-- destination where to copy to
aDX-- x location of the image
aDY-- y location of the image
aDWidth-- width of the image
aDHeight-- height of the image

Implements nsIImage.

Definition at line 1819 of file nsImageWin.cpp.

{
  NS_ASSERTION(mAlphaDepth <= 1, "nsImageWin::DrawToImage can only handle 0 & 1 bit Alpha");

  if (mAlphaDepth > 1)
    return NS_ERROR_UNEXPECTED;

  nsImageWin *dest = NS_STATIC_CAST(nsImageWin *, aDstImage);

  if (!dest)
    return NS_ERROR_FAILURE;

  if (aDX >= dest->mBHead->biWidth || aDY >= dest->mBHead->biHeight)
    return NS_OK;

  if (!dest->mImageBits)
    return NS_ERROR_FAILURE;
     
  if (!dest->mIsOptimized) {
    // set up some local variable to make things run faster in the loop
    PRUint8  *rgbPtr = 0, *alphaPtr = 0;
    PRUint32 rgbStride, alphaStride;
    PRInt32  srcHeight;
    PRUint8  *dstRgbPtr = 0, *dstAlphaPtr = 0;
    PRUint32 dstRgbStride, dstAlphaStride;
    PRInt32  dstHeight;

    rgbPtr = mImageBits;
    rgbStride = mRowBytes;
    alphaPtr = mAlphaBits;
    alphaStride = mARowBytes;
    srcHeight = mBHead->biHeight;

    dstRgbPtr = dest->mImageBits;
    dstRgbStride = dest->mRowBytes;
    dstAlphaPtr = dest->mAlphaBits;
    dstAlphaStride = dest->mARowBytes;
    dstHeight = dest->mBHead->biHeight;


    PRInt32 y;
    PRInt32 ValidWidth = (aDWidth < (dest->mBHead->biWidth - aDX)) ?
                         aDWidth : (dest->mBHead->biWidth - aDX);
    PRInt32 ValidHeight = (aDHeight < (dstHeight - aDY)) ?
                          aDHeight : (dstHeight - aDY);
    PRUint8 *dst;
    PRUint8 *src;

    // now composite the two images together
    switch (mAlphaDepth) {
    case 1:
      {
        PRUint8 *dstAlpha;
        PRUint8 *alpha;
        PRUint8 offset = aDX & 0x7; // x starts at 0


        for (y=0; y<ValidHeight; y++) {
          dst = dstRgbPtr +
                (dstHeight - (aDY+y) - 1) * dstRgbStride +
                (3 * aDX);
          dstAlpha = dstAlphaPtr + (dstHeight - (aDY+y) - 1) * dstAlphaStride;
          src = rgbPtr + (srcHeight - y - 1)*rgbStride;
          alpha = alphaPtr + (srcHeight - y - 1)*alphaStride;
          for (int x = 0;
               x < ValidWidth;
               x += 8, dst +=  3 * 8, src +=  3 * 8) {
            PRUint8 alphaPixels = *alpha++;
            if (alphaPixels == 0) {
              // all 8 transparent; jump forward
              continue;
            }


            // 1 or more bits are set, handle dstAlpha now - may not be aligned.
            // Are all 8 of these alpha pixels used?
            if (x+7 >= ValidWidth) {
              alphaPixels &= 0xff << (8 - (ValidWidth-x)); // no, mask off unused
              if (alphaPixels == 0)
                continue;  // no 1 alpha pixels left
            }
            if (offset == 0) {
              dstAlpha[(aDX+x)>>3] |= alphaPixels; // the cheap aligned case
            } else {
              dstAlpha[(aDX+x)>>3]       |= alphaPixels >> offset;
              // avoid write if no 1's to write - also avoids going past end of array
              PRUint8 alphaTemp = alphaPixels << (8U - offset);
              if (alphaTemp & 0xff)
                dstAlpha[((aDX+x)>>3) + 1] |= alphaTemp;
            }


            if (alphaPixels == 0xff) {
              // fix - could speed up by gathering a run of 0xff's and doing 1 memcpy
              // all 8 pixels set; copy and jump forward
              memcpy(dst,src,8*3);
              continue;
            } else {
              // else mix of 1's and 0's in alphaPixels, do 1 bit at a time
              // Don't go past end of line!
              PRUint8 *d = dst, *s = src;
              for (PRUint8 aMask = 1<<7, j = 0; aMask && j < ValidWidth-x; aMask >>= 1, j++) {
                // if this pixel is opaque then copy into the destination image
                if (alphaPixels & aMask) {
                  // might be faster with *d++ = *s++ 3 times?
                  d[0] = s[0];
                  d[1] = s[1];
                  d[2] = s[2];
                  // dstAlpha bit already set
                }
                d += 3;
                s += 3;
              }
            }
          }
        }
      }
      break;
    case 0:
    default:
      dst = dstRgbPtr + (dstHeight - aDY - 1) * dstRgbStride + 3 * aDX;
      src = rgbPtr + (srcHeight - 1) * rgbStride;

      for (y = 0; y < ValidHeight; y++) {
        memcpy(dst, src,  3 * ValidWidth);
        dst -= dstRgbStride;
        src -= rgbStride;
      }
    }
    nsRect rect(aDX, aDY, ValidWidth, ValidHeight);
    dest->ImageUpdated(nsnull, 0, &rect);
  } else {
    // dst's Image is optimized (dest->mHBitmap is linked to dest->mImageBits), so just paint on it
    if (!dest->mHBitmap)
      return NS_ERROR_UNEXPECTED;
      
    HDC dstMemDC = ::CreateCompatibleDC(nsnull);
    HBITMAP oldDstBits;
    DWORD rop;

    oldDstBits = (HBITMAP)::SelectObject(dstMemDC, dest->mHBitmap);
    rop = SRCCOPY;

    if (mAlphaBits) {
      if (1==mAlphaDepth) {
        MONOBITMAPINFO  bmi(mBHead->biWidth, mBHead->biHeight);

        ::StretchDIBits(dstMemDC, aDX, aDY, aDWidth, aDHeight,
                        0, 0,mBHead->biWidth, mBHead->biHeight, mAlphaBits,
                        (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, SRCAND);
        rop = SRCPAINT;
      }
    }

    if (8 == mAlphaDepth) {
      nsresult rv = DrawComposited(dstMemDC, aDX, aDY, aDWidth, aDHeight,
                                   0, 0, mBHead->biWidth, mBHead->biHeight,
                                   aDWidth, aDHeight);
      if (NS_FAILED(rv)) {
        ::SelectObject(dstMemDC, oldDstBits);
        ::DeleteDC(dstMemDC);
        return rv;
      }
    } 
    
    // Copy/Paint our rgb to dest
    if (mIsOptimized && mHBitmap) {
      // We are optimized, use Stretchblt
      HDC srcMemDC = ::CreateCompatibleDC(nsnull);
      HBITMAP oldSrcBits;
      oldSrcBits = (HBITMAP)::SelectObject(srcMemDC, mHBitmap);
       
      ::StretchBlt(dstMemDC, aDX, aDY, aDWidth, aDHeight, srcMemDC, 
                   0, 0, mBHead->biWidth, mBHead->biHeight, rop);
      
      ::SelectObject(srcMemDC, oldSrcBits);
      ::DeleteDC(srcMemDC);
    } else {
      ::StretchDIBits(dstMemDC, aDX, aDY, aDWidth, aDHeight, 
                      0, 0, mBHead->biWidth, mBHead->biHeight, mImageBits,
                      (LPBITMAPINFO)mBHead, DIB_RGB_COLORS, rop);
    }
    ::SelectObject(dstMemDC, oldDstBits);
    ::DeleteDC(dstMemDC);
  }


  return NS_OK;
}

Here is the call graph for this function:

virtual PRUint8* nsImageWin::GetAlphaBits ( ) [inline, virtual]

Get a pointer to the bits for the alpha mask - dwc 2/1/99.

Returns:
address of the alpha mask pixel array

Implements nsIImage.

Definition at line 112 of file nsImageWin.h.

{ return mAlphaBits; }
virtual PRInt8 nsImageWin::GetAlphaDepth ( ) [inline, virtual]

Get the alpha depth for the image mask - lordpixel 2001/05/16.

Returns:
the alpha mask depth for the image, ie, 0, 1 or 8

Implements nsIImage.

Definition at line 147 of file nsImageWin.h.

{return(mAlphaDepth);}
virtual PRInt32 nsImageWin::GetAlphaLineStride ( ) [inline, virtual]

Get the number of bytes per scanline for the alpha mask - dwc 2/1/99.

Returns:
The number of bytes in each scanline

Implements nsIImage.

Definition at line 113 of file nsImageWin.h.

{ return mARowBytes; }
void* nsImageWin::GetBitInfo ( ) [inline, virtual]

Get the DIB specific informations for this bitmap.

dc - 10/29/98

Returns:
VOID

Implements nsIImage.

Definition at line 154 of file nsImageWin.h.

{return mBHead;}
PRUint8 * nsImageWin::GetBits ( ) [virtual]


See documentation in nsImageWin.h Get a pointer to the bits for the pixelmap.

Will convert to DIB if only stored in optimized HBITMAP form. Using this routine will set the mDIBTemp flag to true so the next unlock will destroy this memory

Returns:
address of the DIB pixel array

Implements nsIImage.

Definition at line 1794 of file nsImageWin.cpp.

{
  // if mImageBits did not exist.. then
  if (!mImageBits) {
    ConvertDDBtoDIB();
    mDIBTemp = PR_TRUE;   // only set to true if the DIB is being created here as temporary
  }


  return mImageBits;


} // GetBits

Here is the call graph for this function:

virtual NS_DECL_ISUPPORTS PRInt32 nsImageWin::GetBytesPix ( ) [inline, virtual]
See also:
nsIImage.h

Implements nsIImage.

Definition at line 91 of file nsImageWin.h.

{ return mNumBytesPixel; }
virtual nsColorMap* nsImageWin::GetColorMap ( ) [inline, virtual]

Get the colormap for the nsIImage - dwc 2/1/99.

Returns:
if non null, the colormap for the pixelmap,otherwise the image is not color mapped

Implements nsIImage.

Definition at line 107 of file nsImageWin.h.

{return mColorMap;}
virtual PRBool nsImageWin::GetHasAlphaMask ( ) [inline, virtual]

Get whether this image has an alpha mask.

Preferable to testing if GetAlphaBits() is non-null. - sfraser 10/19/99

Returns:
PR_TRUE if the image has an alpha mask, PR_FALSE otherwise

Implements nsIImage.

Definition at line 98 of file nsImageWin.h.

{ return mAlphaBits != nsnull; }
virtual PRInt32 nsImageWin::GetHeight ( ) [inline, virtual]

Get the height for the pixelmap - dwc 2/1/99.

Returns:
The height in pixels for the pixelmap

Implements nsIImage.

Definition at line 92 of file nsImageWin.h.

{ return mBHead->biHeight; }


See documentation in nsIImage.h

Implements nsIImage.

Definition at line 274 of file nsImageWin.cpp.

                                      {
  return mInitialized &&
         mDecodedX1 == 0 &&
         mDecodedY1 == 0 &&
         mDecodedX2 == mBHead->biWidth &&
         mDecodedY2 == mBHead->biHeight;
}
virtual PRBool nsImageWin::GetIsRowOrderTopToBottom ( ) [inline, virtual]

Get whether rows are organized top to bottom, or bottom to top - syd 3/29/99.

Returns:
PR_TRUE if top to bottom, else PR_FALSE

Implements nsIImage.

Definition at line 93 of file nsImageWin.h.

{ return PR_FALSE; }
virtual PRInt32 nsImageWin::GetLineStride ( ) [inline, virtual]

Get the number of bytes needed to get to the next scanline for the pixelmap - dwc 2/1/99.

Returns:
The number of bytes in each scanline

Implements nsIImage.

Definition at line 96 of file nsImageWin.h.

{ return mRowBytes; }
PRIntn nsImageWin::GetSizeHeader ( ) [inline]

Return the header size of the Device Independent Bitmap(DIB).

Returns:
size of header in bytes

Definition at line 126 of file nsImageWin.h.

{return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * mNumPaletteColors;}
PRIntn nsImageWin::GetSizeImage ( ) [inline]

Return the image size of the Device Independent Bitmap(DIB).

dc - 10/29/98

Returns:
size of image in bytes

Definition at line 133 of file nsImageWin.h.

{ return mSizeImage; }
virtual PRInt32 nsImageWin::GetWidth ( ) [inline, virtual]

Get the width for the pixelmap - dwc 2/1/99.

Returns:
The width in pixels for the pixelmap

Implements nsIImage.

Definition at line 94 of file nsImageWin.h.

{ return mBHead->biWidth; }
void nsImageWin::ImageUpdated ( nsIDeviceContext aContext,
PRUint8  aFlags,
nsRect aUpdateRect 
) [virtual]


See documentation in nsIImageWin.h 3/27/00 dwc

Implements nsIImage.

Definition at line 260 of file nsImageWin.cpp.

{
  mDecodedX1 = PR_MIN(mDecodedX1, aUpdateRect->x);
  mDecodedY1 = PR_MIN(mDecodedY1, aUpdateRect->y);

  if (aUpdateRect->YMost() > mDecodedY2)
    mDecodedY2 = aUpdateRect->YMost();
  if (aUpdateRect->XMost() > mDecodedX2)
    mDecodedX2 = aUpdateRect->XMost();
}

Here is the caller graph for this function:

nsresult nsImageWin::Init ( PRInt32  aWidth,
PRInt32  aHeight,
PRInt32  aDepth,
nsMaskRequirements  aMaskRequirements 
) [virtual]


See documentation in nsIImageWin.h 3/27/00 dwc

Implements nsIImage.

Definition at line 132 of file nsImageWin.cpp.

{
  if (mInitialized)
    return NS_ERROR_FAILURE;

  if (8 == aDepth) {
    mNumPaletteColors = 256;
    mNumBytesPixel = 1;
  } else if (24 == aDepth) {
    mNumBytesPixel = 3;
  } else {
    NS_ASSERTION(PR_FALSE, "unexpected image depth");
    return NS_ERROR_UNEXPECTED;
  }

  // limit images to 64k pixels on a side (~55 feet on a 100dpi monitor)
  const PRInt32 k64KLimit = 0x0000FFFF;
  if (aWidth > k64KLimit || aHeight > k64KLimit)
    return NS_ERROR_FAILURE;

  if (0 == mNumPaletteColors) {
    // space for the header only (no color table)
    mBHead = (LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFO)];
  } else {
    // Space for the header and the palette. Since we'll be using DIB_PAL_COLORS
    // the color table is an array of 16-bit unsigned integers that specify an
    // index into the currently realized logical palette
    mBHead = (LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER) +
                                          (256 * sizeof(WORD))];
  }
  if (!mBHead)
    return NS_ERROR_OUT_OF_MEMORY;

  mBHead->biSize = sizeof(BITMAPINFOHEADER);
  mBHead->biWidth = aWidth;
  mBHead->biHeight = aHeight;
  mBHead->biPlanes = 1;
  mBHead->biBitCount = (WORD)aDepth;
  mBHead->biCompression = BI_RGB;
  mBHead->biSizeImage = 0;     // not compressed, so we dont need this to be set
  mBHead->biXPelsPerMeter = 0;
  mBHead->biYPelsPerMeter = 0;
  mBHead->biClrUsed = mNumPaletteColors;
  mBHead->biClrImportant = mNumPaletteColors;

  // Compute the size of the image
  mRowBytes = CalcBytesSpan(mBHead->biWidth);
  mSizeImage = mRowBytes * mBHead->biHeight; // no compression

  // Allocate the image bits
  mImageBits = new unsigned char[mSizeImage];
  if (!mImageBits) {
    delete[] mBHead;
    mBHead = nsnull;
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // Need to clear the entire buffer so an incrementally loaded image
  // will not have garbage rendered for the unloaded bits.
/* XXX: Since there is a performance hit for doing the clear we need
   a different solution. For now, we will let garbage be drawn for
   incrementally loaded images. Need a solution where only the portion
   of the image that has been loaded is asked to draw.
    if (mImageBits != nsnull) {
      memset(mImageBits, 128, mSizeImage);
    }
*/

  if (256 == mNumPaletteColors) {
    // Initialize the array of indexes into the logical palette
    WORD* palIndx = (WORD*)(((LPBYTE)mBHead) + mBHead->biSize);
    for (WORD index = 0; index < 256; index++) {
      *palIndx++ = index;
    }
  }

  // Allocate mask image bits if requested
  if (aMaskRequirements != nsMaskRequirements_kNoMask) {
    if (nsMaskRequirements_kNeeds1Bit == aMaskRequirements) {
      mARowBytes = (aWidth + 7) / 8;
      mAlphaDepth = 1;
    }else{
      //NS_ASSERTION(nsMaskRequirements_kNeeds8Bit == aMaskRequirements,
      // "unexpected mask depth");
      mARowBytes = aWidth;
      mAlphaDepth = 8;
    }

    // 32-bit align each row
    mARowBytes = (mARowBytes + 3) & ~0x3;
    mAlphaBits = new unsigned char[mARowBytes * aHeight];
    if (!mAlphaBits) {
      delete[] mBHead;
      mBHead = nsnull;
      delete[] mImageBits;
      mImageBits = nsnull;
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }


  // XXX Let's only do this if we actually have a palette...
  mColorMap = new nsColorMap;

  if (mColorMap != nsnull) {
    mColorMap->NumColors = mNumPaletteColors;
    mColorMap->Index = nsnull;
    if (mColorMap->NumColors > 0) {
      mColorMap->Index = new PRUint8[3 * mColorMap->NumColors];

      // XXX Note: I added this because purify claims that we make a
      // copy of the memory (which we do!). I'm not sure if this
      // matters or not, but this shutup purify.
      memset(mColorMap->Index, 0, sizeof(PRUint8) * (3 * mColorMap->NumColors));
    }
  }

  mInitialized = PR_TRUE;
  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHODIMP nsImageWin::LockImagePixels ( PRBool  aMaskPixels) [virtual]


Lock down the image pixels

Implements nsIImage.

Definition at line 1737 of file nsImageWin.cpp.

{
  /*  if (!mHBitmap) return NS_ERROR_NOT_INITIALIZED;
   ... and do Windows locking of image pixels here, if necessary */


  mIsLocked = PR_TRUE;


  return NS_OK;
}
nsresult nsImageWin::Optimize ( nsIDeviceContext aContext) [virtual]


Create an optimized bitmap dc - 11/20/98

Parameters:
aContext- The device context to use for the optimization

Implements nsIImage.

Definition at line 1440 of file nsImageWin.cpp.

{
  // Do the actual optimizing when we first use the image (draw it)
  // This saves on GDI resources.
  mWantsOptimization = PR_TRUE;
  return NS_OK;
}
PRUint8 nsImageWin::PaletteMatch ( PRUint8  r,
PRUint8  g,
PRUint8  b 
) [private]

Get an index in the palette that matches as closly as possible the passed in RGB colors dc - 4/20/2000.

Parameters:
aR- Red component of the color to match
aG- Green component of the color to match
aB- Blue component of the color to match
Returns:
- The closest palette match
nsresult nsImageWin::PrintDDB ( nsIDrawingSurface aSurface,
PRInt32  aDX,
PRInt32  aDY,
PRInt32  aDWidth,
PRInt32  aDHeight,
PRInt32  aSX,
PRInt32  aSY,
PRInt32  aSWidth,
PRInt32  aSHeight,
PRUint32  aROP 
) [private]

Print a DDB dc - 05/20/99.


See documentation in nsIImage.h - dwc 5/20/99

Parameters:
aSurface- The drawingsurface to create the DIB from.
aDX- x location to place image
aDY- y location to place image
aDWidth- width of DIB
aDHeight- height of DIB
aSX- x location of rect to use
aSY- y location to rect to use (in bitmap, not image, so "upside down" from Mozilla's coordinates)
aSWidth- width of rect to use
aSHeight- height of rect to use
Returns:
the result of the operation, if NS_OK, then the pixelmap is unoptimized

Definition at line 1644 of file nsImageWin.cpp.

{
  HDC   theHDC;
  UINT  palType;


  if (mIsOptimized == PR_TRUE){
    if (mHBitmap != nsnull){
      ConvertDDBtoDIB();
      ((nsDrawingSurfaceWin *)aSurface)->GetDC(&theHDC);


      if (mBHead->biBitCount == 8) {
        palType = DIB_PAL_COLORS;
      } else {
        palType = DIB_RGB_COLORS;
      }


      ::StretchDIBits(theHDC, aDX, aDY, aDWidth, aDHeight,
                      aSX, aSY, aSWidth, aSHeight, mImageBits,
                      (LPBITMAPINFO)mBHead, palType, aROP);


      // we are finished with this, so delete it           
      if (mImageBits != nsnull) {
        delete [] mImageBits;
        mImageBits = nsnull;
      }
    }
  }


  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsImageWin::ProgressiveDoubleBlit ( nsIDeviceContext aContext,
nsIDrawingSurface aSurface,
PRInt32  aSXOffset,
PRInt32  aSYOffset,
nsRect  aDestRect 
) [private]

Progressively double the bitmap size as we blit.


See documentation in nsImageWin.h

. very fast way to tile

Returns:
if TRUE, no errors

Definition at line 993 of file nsImageWin.cpp.

{
  /*
    (aSXOffset, aSYOffset) is the offset into our image that we want to start
    drawing from.  We start drawing at (aDestRect.x, aDestRect.y)

    - Find first full tile
    - progressivly double blit until end of tile area.  What's left will be at
      maximum a strip on the top and a strip on the left side that has not been
      blitted.
    Then, in no particular order:
    - blit the top strip using a row we already put down
    - blit the left strip using a column we already put down
    - blit the very topleft, since it will be left out
  */

  HDC theHDC;
  void *screenBits; // We never use the bits, but we need to pass a variable in
                    // to create a DIB

  ((nsDrawingSurfaceWin *)aSurface)->GetDC(&theHDC);
  if (!theHDC)
    return PR_FALSE;

  // create an imageDC
  HDC imgDC = ::CreateCompatibleDC(theHDC);
  if (!imgDC) {
    ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
    return PR_FALSE;
  }

  CreateDDB();

  nsPaletteInfo palInfo;
  aContext->GetPaletteInfo(palInfo);
  if (palInfo.isPaletteDevice && palInfo.palette) {
#ifndef WINCE
    ::SetStretchBltMode(imgDC, HALFTONE);
#endif
    ::SelectPalette(imgDC, (HPALETTE)palInfo.palette, TRUE);
    ::RealizePalette(imgDC);
  }

  // Create a maskDC, and fill it with mAlphaBits
  HDC maskDC = nsnull;
  HBITMAP oldImgMaskBits = nsnull;
  HBITMAP maskBits;
  HBITMAP mTmpHBitmap = nsnull;
  if (mAlphaDepth == 1) {
    maskDC = ::CreateCompatibleDC(theHDC);
    if (!maskDC) {
      ::DeleteDC(imgDC);
      ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
      return PR_FALSE;
    }

    MONOBITMAPINFO bmi(mBHead->biWidth, mBHead->biHeight);
    maskBits  = ::CreateDIBSection(theHDC, (LPBITMAPINFO)&bmi,
                                   DIB_RGB_COLORS, &screenBits, NULL, 0);
    if (!maskBits) {
      ::DeleteDC(imgDC);
      ::DeleteDC(maskDC);
      ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
      return PR_FALSE;
    }

    oldImgMaskBits = (HBITMAP)::SelectObject(maskDC, maskBits);
    ::SetDIBitsToDevice(maskDC, 0, 0, mBHead->biWidth, mBHead->biHeight,
                        0, 0, 0, mBHead->biHeight, mAlphaBits,
                        (LPBITMAPINFO)&bmi, DIB_RGB_COLORS);
  }


  // Fill imageDC with our image
  HBITMAP oldImgBits = nsnull;
  if (!mIsOptimized || !mHBitmap) {
    // Win 95/98/ME can't do > 0xFF0000 DDBs.
    if (gPlatform == VER_PLATFORM_WIN32_WINDOWS) {
      int bytesPerPix = ::GetDeviceCaps(imgDC, BITSPIXEL) / 8;
      if (mBHead->biWidth * mBHead->biHeight * bytesPerPix > 0xFF0000) {
        ::DeleteDC(imgDC);
        if (maskDC) {
          if (oldImgMaskBits)
            ::SelectObject(maskDC, oldImgMaskBits);
          ::DeleteObject(maskBits);
          ::DeleteDC(maskDC);
        }
        ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
        return PR_FALSE;
      }
    }
    mTmpHBitmap = ::CreateCompatibleBitmap(theHDC, mDecodedX2, mDecodedY2);
    if (!mTmpHBitmap) {
      ::DeleteDC(imgDC);
      if (maskDC) {
        if (oldImgMaskBits)
          ::SelectObject(maskDC, oldImgMaskBits);
        ::DeleteObject(maskBits);
        ::DeleteDC(maskDC);
      }
      ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();
      return PR_FALSE;
    }
    oldImgBits = (HBITMAP)::SelectObject(imgDC, mTmpHBitmap);
    ::StretchDIBits(imgDC, 0, 0, mBHead->biWidth, mBHead->biHeight,
                    0, 0, mBHead->biWidth, mBHead->biHeight,
                    mImageBits, (LPBITMAPINFO)mBHead,
                    256 == mNumPaletteColors ? DIB_PAL_COLORS : DIB_RGB_COLORS,
                    SRCCOPY);
  } else {
    oldImgBits = (HBITMAP)::SelectObject(imgDC, mHBitmap);
  }

  PRBool result = PR_TRUE;
  PRBool useAlphaBlend = mAlphaDepth == 8 && mIsOptimized;

  PRInt32 firstWidth = mBHead->biWidth - aSXOffset;
  PRInt32 firstHeight = mBHead->biHeight - aSYOffset;

  if (aDestRect.width > firstWidth + mBHead->biWidth ||
      aDestRect.height > firstHeight + mBHead->biHeight) {
    PRInt32 firstPartialWidth = aSXOffset == 0 ? 0 : firstWidth;
    PRInt32 firstPartialHeight = aSYOffset == 0 ? 0 : firstHeight;
    PRBool hasFullImageWidth = aDestRect.width - firstPartialWidth >= mBHead->biWidth;
    PRBool hasFullImageHeight = aDestRect.height - firstPartialHeight >= mBHead->biHeight;

    HDC dstDC = theHDC;               // Defaulting to drawing to theHDC
    HDC dstMaskDC = nsnull;           // No Alpha DC by default
    HBITMAP dstMaskHBitmap = nsnull;  // No Alpha HBITMAP by default either..
    HBITMAP oldDstBits, oldDstMaskBits;
    HBITMAP dstHBitmap;

    do {  // Use a do to help with cleanup
      nsRect storedDstRect;

      // dstDC will only be used if we have an alpha.  It is not needed for
      // images without an alpha because we can directly doubleblit onto theHDC
      if (mAlphaDepth != 0) {
        // We have an alpha, which means we can't p. doubleblit directly onto
        // theHDC.  We must create a temporary DC, p. doubleblit into that, and
        // then draw the whole thing to theHDC

        storedDstRect = aDestRect;
        aDestRect.x = 0;
        aDestRect.y = 0;
        // The last p. doubleblit is very slow.. it's faster to draw to theHDC
        // twice.  So only progressive doubleblit up to 1/2 of the tiling area
        // that requires full tiles.
        if (aDestRect.height - firstPartialHeight >= mBHead->biHeight * 2)
          aDestRect.height = PR_ROUNDUP(PRInt32(ceil(aDestRect.height / 2.0)),
                                        mBHead->biHeight)
                             + firstPartialHeight;

        // Win 95/98/ME can't do > 0xFF0000 DDBs.
        // Note: This should be extremely rare.  We'd need a tile area (before
        //       it was split in 1/2 above) of 2048x4080 @ 4 bytesPerPix before
        //       we hit this.
        if (gPlatform == VER_PLATFORM_WIN32_WINDOWS) {
          int bytesPerPix = (mAlphaDepth == 8) ? 4 :
                            ::GetDeviceCaps(theHDC, BITSPIXEL) / 8;
          if (aDestRect.width * aDestRect.height * bytesPerPix > 0xFF0000) {
            result = PR_FALSE;
            break;
          }
        }

        // make a temporary offscreen DC
        dstDC = ::CreateCompatibleDC(theHDC);
        if (!dstDC) {
          result = PR_FALSE;
          break;
        }

        // Create HBITMAP for the new DC
        if (mAlphaDepth == 8) {
          // Create a bitmap of 1 plane, 32 bit color depth
          // Can't use ::CreateBitmap, since the resulting HBITMAP will only be
          // able to be selected into a compatible HDC (ie. User is @ 24 bit, you
          // can't select the 32 HBITMAP into the HDC.)
          ALPHA32BITMAPINFO bmi(aDestRect.width, aDestRect.height);
          dstHBitmap = ::CreateDIBSection(theHDC, (LPBITMAPINFO)&bmi,
                                          DIB_RGB_COLORS, &screenBits, NULL, 0);
        } else {
          // Create a normal bitmap for the image, and a monobitmap for alpha
          dstHBitmap = ::CreateCompatibleBitmap(theHDC, aDestRect.width,
                                                aDestRect.height);
          if (dstHBitmap) {
            dstMaskDC = ::CreateCompatibleDC(theHDC);
            if (dstMaskDC) {
              MONOBITMAPINFO bmi(aDestRect.width, aDestRect.height);
              dstMaskHBitmap = ::CreateDIBSection(theHDC, (LPBITMAPINFO)&bmi,
                                                  DIB_RGB_COLORS, &screenBits,
                                                  NULL, 0);
              if (dstMaskHBitmap) {
                oldDstMaskBits = (HBITMAP)::SelectObject(dstMaskDC,
                                                         dstMaskHBitmap);
              } else {
                result = PR_FALSE;
                break;
              }
            } // dstMaskDC
          } // dstHBitmap
        }
        if (!dstHBitmap) {
          result = PR_FALSE;
          break;
        }

        oldDstBits = (HBITMAP)::SelectObject(dstDC, dstHBitmap);
      } // (mAlphaDepth != 0)


      PRInt32 imgX = hasFullImageWidth ? 0 : aSXOffset;
      PRInt32 imgW = PR_MIN(mBHead->biWidth - imgX, aDestRect.width);
      PRInt32 imgY = hasFullImageHeight ? 0 : aSYOffset;
      PRInt32 imgH = PR_MIN(mBHead->biHeight - imgY, aDestRect.height);

      // surfaceDestPoint is the first position in the destination where we will
      // be putting (0,0) of our image down.
      nsPoint surfaceDestPoint(aDestRect.x, aDestRect.y);
      if (aSXOffset != 0 && hasFullImageWidth)
        surfaceDestPoint.x += firstWidth;
      if (aSYOffset != 0 && hasFullImageHeight)
        surfaceDestPoint.y += firstHeight;

      // Plunk one down
      BlitImage(dstDC, dstMaskDC,
                surfaceDestPoint.x, surfaceDestPoint.y, imgW, imgH,
                imgDC, maskDC, imgX, imgY, PR_FALSE);
      if (!hasFullImageHeight && imgH != aDestRect.height) {
        // Since we aren't drawing a full image in height, there's an area above
        // that we can blit to too.
        BlitImage(dstDC, dstMaskDC, surfaceDestPoint.x, surfaceDestPoint.y + imgH,
                          imgW, aDestRect.height - imgH,
                  imgDC, maskDC, imgX, 0, PR_FALSE);
        imgH = aDestRect.height;
      }
      if (!hasFullImageWidth && imgW != aDestRect.width) {
        BlitImage(dstDC, dstMaskDC, surfaceDestPoint.x + imgW, surfaceDestPoint.y,
                          aDestRect.width - imgW, imgH,
                  imgDC, maskDC, 0, imgY, PR_FALSE);
        imgW = aDestRect.width;
      }


      nsRect surfaceDestRect;
      nsRect surfaceSrcRect(surfaceDestPoint.x, surfaceDestPoint.y, imgW, imgH);

      // Progressively DoubleBlit a Row
      if (hasFullImageWidth) {
        while (surfaceSrcRect.XMost() < aDestRect.XMost()) {
          surfaceDestRect.x = surfaceSrcRect.XMost();
          surfaceDestRect.width = surfaceSrcRect.width;
          if (surfaceDestRect.XMost() >= aDestRect.XMost())
            surfaceDestRect.width = aDestRect.XMost() - surfaceDestRect.x;

          BlitImage(dstDC, dstMaskDC, surfaceDestRect.x, surfaceSrcRect.y,
                            surfaceDestRect.width, surfaceSrcRect.height,
                    dstDC, dstMaskDC, surfaceSrcRect.x, surfaceSrcRect.y,
                    PR_FALSE);
          surfaceSrcRect.width += surfaceDestRect.width;
        }
      }

      // Progressively DoubleBlit a column
      if (hasFullImageHeight) {
        while (surfaceSrcRect.YMost() < aDestRect.YMost()) {
          surfaceDestRect.y = surfaceSrcRect.YMost();
          surfaceDestRect.height = surfaceSrcRect.height;
          if (surfaceDestRect.YMost() >= aDestRect.YMost())
            surfaceDestRect.height = aDestRect.YMost() - surfaceDestRect.y;

          BlitImage(dstDC, dstMaskDC, surfaceSrcRect.x, surfaceDestRect.y,
                            surfaceSrcRect.width, surfaceDestRect.height,
                    dstDC, dstMaskDC, surfaceSrcRect.x, surfaceSrcRect.y,
                    PR_FALSE);
          surfaceSrcRect.height += surfaceDestRect.height;
        }
      }

      // blit to topleft.  This could be done before p doubleblitting
      if (surfaceDestPoint.y != aDestRect.y && surfaceDestPoint.x != aDestRect.x)
          BlitImage(dstDC, dstMaskDC, aDestRect.x, aDestRect.y,
                    firstWidth, firstHeight,
                    dstDC, dstMaskDC,
                    surfaceDestPoint.x + aSXOffset, surfaceDestPoint.y + aSYOffset,
                    PR_FALSE);
      // blit top row
      if (surfaceDestPoint.y != aDestRect.y)
          BlitImage(dstDC, dstMaskDC, surfaceDestPoint.x, aDestRect.y,
                    surfaceSrcRect.width, firstHeight,
                    dstDC, dstMaskDC, surfaceDestPoint.x, surfaceDestPoint.y + aSYOffset,
                    PR_FALSE);

      // blit left column
      if (surfaceDestPoint.x != aDestRect.x)
        BlitImage(dstDC, dstMaskDC, aDestRect.x, surfaceDestPoint.y,
                  firstWidth, surfaceSrcRect.height,
                  dstDC, dstMaskDC, surfaceDestPoint.x + aSXOffset, surfaceDestPoint.y,
                  PR_FALSE);

      if (mAlphaDepth != 0) {
        // blit temporary dstDC (& dstMaskDC, if one exists) to theHDC
        BlitImage(theHDC, theHDC, storedDstRect.x, storedDstRect.y,
                  aDestRect.width, aDestRect.height,
                  dstDC, dstMaskDC, 0, 0, useAlphaBlend);
        // blit again to 2nd part of tile area
        if (storedDstRect.height > aDestRect.height)
          BlitImage(theHDC, theHDC, storedDstRect.x, storedDstRect.y + aDestRect.height,
                    aDestRect.width, storedDstRect.height - aDestRect.height,
                    dstDC, dstMaskDC, 0, firstPartialHeight, useAlphaBlend);
      }
    } while (PR_FALSE);

    if (mAlphaDepth != 0) {
      if (dstDC) {
        if (dstHBitmap) {
          ::SelectObject(dstDC, oldDstBits);
          ::DeleteObject(dstHBitmap);
        }
        ::DeleteDC(dstDC);
      }
      if (dstMaskDC) {
        if (dstMaskHBitmap) {
          ::SelectObject(dstMaskDC, oldDstMaskBits);
          ::DeleteObject(dstMaskHBitmap);
        }
        ::DeleteDC(dstMaskDC);
      }
    }
  } else {
    // up to 4 image parts.
    // top-left
    BlitImage(theHDC, theHDC,
              aDestRect.x, aDestRect.y, firstWidth, firstHeight,
              imgDC, maskDC, aSXOffset, aSYOffset, useAlphaBlend);

    // bottom-right
    if (aDestRect.width - firstWidth > 0 && aDestRect.height - firstHeight > 0)
      BlitImage(theHDC, theHDC,
                aDestRect.x + firstWidth, aDestRect.y + firstHeight,
                aDestRect.width - firstWidth, aDestRect.height - firstHeight,
                imgDC, maskDC, 0, 0, useAlphaBlend);

    // bottom-left
    if (aDestRect.height - firstHeight > 0)
      BlitImage(theHDC, theHDC, aDestRect.x, aDestRect.y + firstHeight,
                firstWidth, aDestRect.height - firstHeight,
                imgDC, maskDC, aSXOffset, 0, useAlphaBlend);

    // top-right
    if (aDestRect.width - firstWidth > 0)
      BlitImage(theHDC, theHDC, aDestRect.x + firstWidth, aDestRect.y,
                aDestRect.width - firstWidth, firstHeight,
                imgDC, maskDC, 0, aSYOffset, useAlphaBlend);
  }

  if (oldImgBits)
    ::SelectObject(imgDC, oldImgBits);
  if (mTmpHBitmap)
    ::DeleteObject(mTmpHBitmap);
  ::DeleteDC(imgDC);
  if (maskDC) {
    if (oldImgMaskBits)
      ::SelectObject(maskDC, oldImgMaskBits);
    ::DeleteObject(maskBits);
    ::DeleteDC(maskDC);
  }
  ((nsDrawingSurfaceWin *)aSurface)->ReleaseDC();

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Removes the DBB, restoring the imagebits if necessary.

Definition at line 1555 of file nsImageWin.cpp.

{
  if (!mIsOptimized && mHBitmap == nsnull)
    return NS_OK;

  if (!mImageBits) {
    nsresult rv = ConvertDDBtoDIB();
    if (NS_FAILED(rv))
      return rv;
  }

  CleanUpDDB();
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsImageWin::TimerCallBack ( nsITimer aTimer,
void aClosure 
) [static, private]

Definition at line 2077 of file nsImageWin.cpp.

{
  nsImageWin *entry = NS_STATIC_CAST(nsImageWin*, aClosure);
  if (!entry)
    return;

  if (NS_FAILED(entry->RemoveDDB())) {
    // Try again later.  Can't SetDelay while timer is being called, so
    // create a new timer instead
    entry->mTimer = do_CreateInstance("@mozilla.org/timer;1");
    if (entry->mTimer)
      entry->mTimer->InitWithFuncCallback(nsImageWin::TimerCallBack, entry,
                                          GFX_MS_REMOVE_DBB,
                                          nsITimer::TYPE_ONE_SHOT);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Unlock the pixels, optimize this nsImageWin

Implements nsIImage.

Definition at line 1754 of file nsImageWin.cpp.

{
  mIsLocked = PR_FALSE;
  // if memory was allocated temporarily by GetBits, it can now be deleted safely
  if (mDIBTemp == PR_TRUE) {
    // get rid of this memory
    if (mImageBits != nsnull) {
      delete [] mImageBits;
      mImageBits = nsnull;
      }


    mDIBTemp = PR_FALSE;
  }


  /* if (!mHBitmap)
    return NS_ERROR_NOT_INITIALIZED;
  
  if (aMaskPixels && !mAlphamHBitmap)
    return NS_ERROR_NOT_INITIALIZED;


   ... and do Windows unlocking of image pixels here, if necessary */


  return NS_OK;
}

Member Data Documentation

Definition at line 292 of file nsImageWin.h.

Definition at line 162 of file nsImageWin.h.

Definition at line 161 of file nsImageWin.h.

Definition at line 285 of file nsImageWin.h.

PRInt8 nsImageWin::mAlphaDepth [private]

Definition at line 286 of file nsImageWin.h.

Definition at line 287 of file nsImageWin.h.

LPBITMAPINFOHEADER nsImageWin::mBHead [private]

Definition at line 290 of file nsImageWin.h.

Definition at line 277 of file nsImageWin.h.

Definition at line 279 of file nsImageWin.h.

Definition at line 281 of file nsImageWin.h.

Definition at line 280 of file nsImageWin.h.

Definition at line 282 of file nsImageWin.h.

Definition at line 270 of file nsImageWin.h.

HBITMAP nsImageWin::mHBitmap [private]

Definition at line 289 of file nsImageWin.h.

Definition at line 276 of file nsImageWin.h.

PRInt8 nsImageWin::mImageCache [private]

Definition at line 288 of file nsImageWin.h.

Definition at line 271 of file nsImageWin.h.

Definition at line 266 of file nsImageWin.h.

Definition at line 269 of file nsImageWin.h.

Definition at line 268 of file nsImageWin.h.

PRInt8 nsImageWin::mNumBytesPixel [private]

Definition at line 272 of file nsImageWin.h.

Definition at line 273 of file nsImageWin.h.

Definition at line 275 of file nsImageWin.h.

Definition at line 274 of file nsImageWin.h.

Definition at line 294 of file nsImageWin.h.

Definition at line 267 of file nsImageWin.h.


The documentation for this class was generated from the following files: