예제 #1
0
//************************************************************************
BOOL CDib::LoadFromResource(HINSTANCE hInstance, LPCSTR szResource, BOOL fDecodeRLE)
//************************************************************************
{
	HRSRC hDibRes;
	HGLOBAL hDib;
	LPTR lpDib;
	LPBITMAPINFO lpbmInfo; 
	DWORD dwBits;

	if ( !(hDibRes = FindResource(hInstance, szResource, RT_BITMAP)) )
		return(FALSE);
	if (! (hDib = LoadResource(hInstance, hDibRes)) )
		return(FALSE);
	lpDib = (LPTR)LockResource(hDib);
	if (!lpDib)
		return(FALSE);
	lpbmInfo = (LPBITMAPINFO)lpDib;
	m_bmiHeader = lpbmInfo->bmiHeader;
	FixHeader();
	hmemcpy(m_rgbQuad, lpbmInfo->bmiColors, GetNumColors() * sizeof(RGBQUAD));
	lpDib += m_bmiHeader.biSize + (GetNumColors() * sizeof(RGBQUAD));

	// Can we get enough memory to hold the DIB bits
	if ( (m_lp = AllocX( dwBits = GetSizeImage(), GMEM_ZEROINIT )) != NULL )
		hmemcpy(m_lp, lpDib, dwBits);
	UnlockResource(hDib);
	FreeResource(hDib);

	return(CheckDecodeRLE(fDecodeRLE));
}
예제 #2
0
// ---
static WORD GetPaletteSize( LPSTR lpBI ) 	{
	// if handle to DIB is invalid, return 0 
	if (lpBI == NULL)	
  	return 0;

 // calculate the size required by the palette 
  BOOL bWin30;

  bWin30 = (IS_WIN30_DIB (lpBI));
  
  if (bWin30)
		return (WORD)(GetNumColors(lpBI) * sizeof(RGBQUAD));
  else
	  return (WORD)(GetNumColors(lpBI) * sizeof(RGBTRIPLE));
}
예제 #3
0
// Returns a buffer filled with the bitmap file header in little endian:
// Signature 2 bytes 'BM'
// FileSize	 4 bytes File size in bytes
// reserved	 4 bytes unused (=0)
// DataOffset	 4 bytes File offset to Raster Data
// Returns true if successful
bool nsICODecoder::FillBitmapFileHeaderBuffer(PRInt8 *bfh) 
{
  memset(bfh, 0, 14);
  bfh[0] = 'B';
  bfh[1] = 'M';
  PRInt32 dataOffset = 0;
  PRInt32 fileSize = 0;
  dataOffset = BFH_LENGTH + BITMAPINFOSIZE;

  // The color table is present only if BPP is <= 8
  if (mDirEntry.mBitCount <= 8) {
    PRUint16 numColors = GetNumColors();
    if (numColors == (PRUint16)-1) {
      return false;
    }
    dataOffset += 4 * numColors;
    fileSize = dataOffset + GetRealWidth() * GetRealHeight();
  } else {
    fileSize = dataOffset + (mDirEntry.mBitCount * GetRealWidth() * 
                             GetRealHeight()) / 8;
  }

  fileSize = NATIVE32_TO_LITTLE(fileSize);
  memcpy(bfh + 2, &fileSize, sizeof(fileSize));
  dataOffset = NATIVE32_TO_LITTLE(dataOffset);
  memcpy(bfh + 10, &dataOffset, sizeof(dataOffset));
  return true;
}
예제 #4
0
BOOL eglDib::LoadBitmapFromFile(const char *filename)
{
	HANDLE	hFile;
	DWORD	FileSize, ReadCount;
	hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(INVALID_HANDLE_VALUE == hFile)
	{
		return FALSE;
	}
	FileSize = GetFileSize(hFile, NULL);
	if(mBMPFileHeader)
		free(mBMPFileHeader);

	mBMPFileHeader = (BITMAPFILEHEADER*)malloc(FileSize);
	ReadFile(hFile, mBMPFileHeader, FileSize, &ReadCount, NULL);
	CloseHandle(hFile);

	mRawData  = (PBYTE)mBMPFileHeader + mBMPFileHeader->bfOffBits;
	mBMPInfo  = (BITMAPINFO*)((PBYTE)mBMPFileHeader+sizeof(BITMAPFILEHEADER));
	mBMPInfoHeader = (BITMAPINFOHEADER*)((PBYTE)mBMPFileHeader+sizeof(BITMAPFILEHEADER));
	mRGBTable = (RGBQUAD*)((PBYTE)mBMPInfoHeader + mBMPInfoHeader->biSize);
	if(mBMPInfoHeader->biBitCount == 8)
	{
		CreateLogicalPallete();
	}
	mNumColors= GetNumColors();
	return TRUE;
}
예제 #5
0
// Given the input 'filter' option, return an OR'd bit-set of filters to try.
static uint32_t GetFilterMap(const uint8_t* alpha, int width, int height,
                             int filter, int effort_level) {
  uint32_t bit_map = 0U;
  if (filter == WEBP_FILTER_FAST) {
    // Quick estimate of the best candidate.
    int try_filter_none = (effort_level > 3);
    const int kMinColorsForFilterNone = 16;
    const int kMaxColorsForFilterNone = 192;
    const int num_colors = GetNumColors(alpha, width, height, width);
    // For low number of colors, NONE yeilds better compression.
    filter = (num_colors <= kMinColorsForFilterNone) ? WEBP_FILTER_NONE :
             EstimateBestFilter(alpha, width, height, width);
    bit_map |= 1 << filter;
    // For large number of colors, try FILTER_NONE in addition to the best
    // filter as well.
    if (try_filter_none || num_colors > kMaxColorsForFilterNone) {
      bit_map |= 1 << WEBP_FILTER_NONE;
    }
  } else if (filter == WEBP_FILTER_NONE) {
    bit_map = 1 << WEBP_FILTER_NONE;
  } else {  // WEBP_FILTER_BEST
    bit_map = (1 << WEBP_FILTER_LAST) - 1;  // try all.
  }
  return bit_map;
}
예제 #6
0
//************************************************************************
void CDib::FixHeader()
//************************************************************************
{
m_bmiHeader.biSizeImage = GetSizeImage();
m_bmiHeader.biClrUsed = GetNumColors();
if ( !m_bmiHeader.biClrUsed && m_bmiHeader.biCompression == BI_BITFIELDS )
	; // m_bmiHeader.biClrUsed = 3;					   
}
예제 #7
0
// Map the colors of the DIB (using GetNearestPaletteIndex) to a palette
//************************************************************************
void CDib::MapToPalette( HPALETTE hpal )
//************************************************************************
{
	int n, nDibColors;
	LPBYTE lpBits;
	LPRGBQUAD lpRgb;
	BYTE xlat[256];
	DWORD SizeImage;
	BOOL bChanged;

	if ( !hpal )
		return;

	if ( m_bmiHeader.biBitCount != 8 )
		return;

	if ( GetColorTableType() == DIB_PAL_COLORS )
		return;

	//	build a xlat table. from the current DIB colors to the given palette
	nDibColors = GetNumColors();
	lpRgb = GetColors();
	bChanged = NO;
	for ( n=0; n<nDibColors; n++ )
		{
		xlat[n] = (BYTE)GetNearestPaletteIndex( hpal,
			RGB(lpRgb->rgbRed, lpRgb->rgbGreen, lpRgb->rgbBlue) );
		if ( xlat[n] != n )
			bChanged = YES;
		lpRgb++;
		}

	if ( !bChanged )
		{
		// Now reset the DIB color table to match the palette
		SetColorTable( hpal, DIB_RGB_COLORS );
		return;
		}

	// translate the DIB bits
	lpBits = (LPBYTE)GetPtr();
	SizeImage = GetSizeImage();
	switch (m_bmiHeader.biCompression)
		{
		case BI_RLE8:
			xlatRle8(lpBits, SizeImage, xlat);
			break;

		case BI_RGB:
			xlatClut8(lpBits, SizeImage, xlat);
			break;
		}

	// Now reset the DIB color table to match the palette
	SetColorTable( hpal, DIB_RGB_COLORS );
}
예제 #8
0
const unsigned char *
avtColorTables::GetColors(const std::string &ctName)
{
    const unsigned char *retval = NULL;
    int index;
    if((index = ctAtts->GetColorTableIndex(ctName)) != -1)
    {
        const ColorControlPointList &ct = ctAtts->operator[](index);
        ct.GetColors(tmpColors, GetNumColors());
        retval = tmpColors;
    }

    return retval;
}
예제 #9
0
// Save a palette to an open MMIO handle
BOOL CDIBPal::Save(HMMIO hmmio)
{
    // Create a RIFF chunk for a PAL file
    MMCKINFO ckFile;
    ckFile.cksize = 0; // corrected later
    ckFile.fccType = mmioFOURCC('P','A','L',' ');
    if (mmioCreateChunk(hmmio,
                        &ckFile,
                        MMIO_CREATERIFF) != 0) {
        TRACE("Failed to create RIFF-PAL chunk");
        return FALSE;
    }
    // create the LOGPALETTE data which will become
    // the data chunk
    int iColors = GetNumColors();
    ASSERT(iColors > 0);
    int iSize = sizeof(LOGPALETTE)
                + (iColors-1) * sizeof(PALETTEENTRY);
    LOGPALETTE* plp = (LOGPALETTE*) malloc(iSize);
    ASSERT(plp);
    plp->palVersion = 0x300;
    plp->palNumEntries = iColors;
    GetPaletteEntries(0, iColors, plp->palPalEntry);
    // create the data chunk
    MMCKINFO ckData;
    ckData.cksize = iSize; 
    ckData.ckid = mmioFOURCC('d','a','t','a');
    if (mmioCreateChunk(hmmio,
                        &ckData,
                        0) != 0) {
        TRACE("Failed to create data chunk");
        return FALSE;
    }
    // write the data chunk
    if (mmioWrite(hmmio,
                 (char*)plp,
                 iSize) != iSize) {
        TRACE("Failed to write data chunk");
        free(plp);
        return FALSE;
    }
    free(plp);
    // Ascend from the data chunk which will correct the length
    mmioAscend(hmmio, &ckData, 0);
    // Ascend from the RIFF/PAL chunk
    mmioAscend(hmmio, &ckFile, 0);

    return TRUE;
}
예제 #10
0
//////////////////
// Create the palette. Use halftone palette for hi-color bitmaps.
//
HPALETTE PLWinBmpEx::CreatePalette(void)
{
    // should not already have palette
    ASSERT( m_pal == 0 );

    HPALETTE hRet = HPALETTE(0);
    if (m_pClrTab)
    {
        // RGBQUAD* colors = new RGBQUAD[MAXPALCOLORS];
        UINT nColors = GetNumColors();  // 256, really...
        // Allocate memory for logical palette
        int len = sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * nColors;
        LOGPALETTE* pLogPal = (LOGPALETTE*)new char[len];
        if (!pLogPal)
            return hRet;

        // set version and number of palette entries
        pLogPal->palVersion = PALVERSION;
        pLogPal->palNumEntries = (WORD) nColors;

        // copy color entries
        for (UINT i = 0; i < nColors; i++)
        {
            PLBYTE * pb = (PLBYTE *) (m_pClrTab+i);
            pLogPal->palPalEntry[i].peRed   = pb[PL_RGBA_RED  ];
            pLogPal->palPalEntry[i].peGreen = pb[PL_RGBA_GREEN];
            pLogPal->palPalEntry[i].peBlue  = pb[PL_RGBA_BLUE ];
            pLogPal->palPalEntry[i].peFlags = 0;
        }

        // create the palette and destroy LOGPAL
        hRet = ::CreatePalette(pLogPal);
        delete [] (char*)pLogPal;
    }
    else
    {
        // If the file itself did not contain a colormap, we will use
        // a default palette and rely on DrawDib's halftoning.
        // When displaying higher-color images on 8bpp hardware,
        // this is suboptimal though. Ideally we should build the
        // palette according to an histogram of the actual RGB values.
        // "SeeDib" from MS Source Code Samples does that nicely
        HDC dcScreen = ::GetWindowDC(NULL);
        hRet = ::CreateHalftonePalette(dcScreen);
        ::ReleaseDC (NULL, dcScreen);

    }
    return hRet;
}
예제 #11
0
// ****************************************************************************
//  Method:  avtColorTables::GetAlphas
//
//  Purpose:
//    Like GetColors, but gets the alpha values instead.
//
//  Arguments:
//   ctName : The name of the color table for which we want the colors.
//
//  Programmer:  Jeremy Meredith
//  Creation:    February 20, 2009
//
// ****************************************************************************
const unsigned char *
avtColorTables::GetAlphas(const std::string &ctName)
{
    unsigned char dummy[256*3];
    const unsigned char *retval = NULL;
    int index;
    if((index = ctAtts->GetColorTableIndex(ctName)) != -1)
    {
        const ColorControlPointList &ct = ctAtts->operator[](index);
        ct.GetColors(dummy, GetNumColors(), tmpAlphas);
        retval = tmpAlphas;
    }

    return retval;
}
예제 #12
0
void CDIBPal::Draw(HDC hDC, RECT* pRect, BOOL bBkgnd)
{
    int iColors = GetNumColors();
    HPALETTE hOldPal = ::SelectPalette(hDC, (HPALETTE)m_hObject, bBkgnd);
    ::RealizePalette(hDC);
    int i, j, top, left, bottom, right, w, h;
    w = pRect->right - pRect->left;
    h = pRect->bottom - pRect->top;
    for (j=0, top=pRect->top; j<16 && iColors; j++, top=bottom) {
        bottom = pRect->top + (j+1) * h / 16 + 1;
        for(i=0, left=pRect->left; i<16 && iColors; i++, left=right) {
            right = pRect->left + (i+1) * w / 16 + 1;
            CBrush br (PALETTEINDEX(j * 16 + i));
            HBRUSH brold = (HBRUSH)::SelectObject(hDC, br.m_hObject);
            ::Rectangle(hDC, left-1, top-1, right, bottom);
            ::SelectObject(hDC, brold);
            iColors--;
        }
    }
    ::SelectPalette(hDC, hOldPal, FALSE);
}
예제 #13
0
void CDIBPal::Draw(CDC* pDC, CRect* pRect, BOOL bBkgnd)
{
#if 0
    int iColors = GetNumColors();
    CPalette *pOldPal = pDC->SelectPalette(this, bBkgnd);
    pDC->RealizePalette();
    int i, j, top, left, bottom, right;
    for (j=0, top=0; j<16 && iColors; j++, top=bottom) {
        bottom = (j+1) * pRect->bottom / 16 + 1;
        for(i=0, left=0; i<16 && iColors; i++, left=right) {
            right = (i+1) * pRect->right / 16 + 1;
            CBrush br (PALETTEINDEX(j * 16 + i));
            CBrush *brold = pDC->SelectObject(&br);
            pDC->Rectangle(left-1, top-1, right, bottom);
            pDC->SelectObject(brold);
            iColors--;
        }
    }
    pDC->SelectPalette(pOldPal, FALSE);
#else
    Draw(pDC->GetSafeHdc(), pRect, bBkgnd);
#endif
}
예제 #14
0
void
nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount, DecodeStrategy aStrategy)
{
  NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");

  if (!aCount) {
    if (mContainedDecoder) {
      WriteToContainedDecoder(aBuffer, aCount, aStrategy);
    }
    return;
  }

  while (aCount && (mPos < ICONCOUNTOFFSET)) { // Skip to the # of icons.
    if (mPos == 2) { // if the third byte is 1: This is an icon, 2: a cursor
      if ((*aBuffer != 1) && (*aBuffer != 2)) {
        PostDataError();
        return;
      }
      mIsCursor = (*aBuffer == 2);
    }
    mPos++; aBuffer++; aCount--;
  }

  if (mPos == ICONCOUNTOFFSET && aCount >= 2) {
    mNumIcons = LittleEndian::readUint16(reinterpret_cast<const uint16_t*>(aBuffer));
    aBuffer += 2;
    mPos += 2;
    aCount -= 2;
  }

  if (mNumIcons == 0)
    return; // Nothing to do.

  uint16_t colorDepth = 0;
  nsIntSize prefSize = mImage.GetRequestedResolution();
  if (prefSize.width == 0 && prefSize.height == 0) {
    prefSize.SizeTo(PREFICONSIZE, PREFICONSIZE);
  }

  // A measure of the difference in size between the entry we've found
  // and the requested size. We will choose the smallest image that is
  // >= requested size (i.e. we assume it's better to downscale a larger
  // icon than to upscale a smaller one).
  int32_t diff = INT_MIN;

  // Loop through each entry's dir entry
  while (mCurrIcon < mNumIcons) { 
    if (mPos >= DIRENTRYOFFSET + (mCurrIcon * sizeof(mDirEntryArray)) && 
        mPos < DIRENTRYOFFSET + ((mCurrIcon + 1) * sizeof(mDirEntryArray))) {
      uint32_t toCopy = sizeof(mDirEntryArray) - 
                        (mPos - DIRENTRYOFFSET - mCurrIcon * sizeof(mDirEntryArray));
      if (toCopy > aCount) {
        toCopy = aCount;
      }
      memcpy(mDirEntryArray + sizeof(mDirEntryArray) - toCopy, aBuffer, toCopy);
      mPos += toCopy;
      aCount -= toCopy;
      aBuffer += toCopy;
    }
    if (aCount == 0)
      return; // Need more data

    IconDirEntry e;
    if (mPos == (DIRENTRYOFFSET + ICODIRENTRYSIZE) + 
                (mCurrIcon * sizeof(mDirEntryArray))) {
      mCurrIcon++;
      ProcessDirEntry(e);
      // We can't use GetRealWidth and GetRealHeight here because those operate
      // on mDirEntry, here we are going through each item in the directory.
      // Calculate the delta between this image's size and the desired size,
      // so we can see if it is better than our current-best option.
      // In the case of several equally-good images, we use the last one.
      int32_t delta = (e.mWidth == 0 ? 256 : e.mWidth) - prefSize.width +
                      (e.mHeight == 0 ? 256 : e.mHeight) - prefSize.height;
      if (e.mBitCount >= colorDepth &&
          ((diff < 0 && delta >= diff) || (delta >= 0 && delta <= diff))) {
        diff = delta;
        mImageOffset = e.mImageOffset;

        // ensure mImageOffset is >= size of the direntry headers (bug #245631)
        uint32_t minImageOffset = DIRENTRYOFFSET + 
                                  mNumIcons * sizeof(mDirEntryArray);
        if (mImageOffset < minImageOffset) {
          PostDataError();
          return;
        }

        colorDepth = e.mBitCount;
        memcpy(&mDirEntry, &e, sizeof(IconDirEntry));
      }
    }
  }

  if (mPos < mImageOffset) {
    // Skip to (or at least towards) the desired image offset
    uint32_t toSkip = mImageOffset - mPos;
    if (toSkip > aCount)
      toSkip = aCount;

    mPos    += toSkip;
    aBuffer += toSkip;
    aCount  -= toSkip;
  }

  // If we are within the first PNGSIGNATURESIZE bytes of the image data,
  // then we have either a BMP or a PNG.  We use the first PNGSIGNATURESIZE
  // bytes to determine which one we have.
  if (mCurrIcon == mNumIcons && mPos >= mImageOffset && 
      mPos < mImageOffset + PNGSIGNATURESIZE)
  {
    uint32_t toCopy = PNGSIGNATURESIZE - (mPos - mImageOffset);
    if (toCopy > aCount) {
      toCopy = aCount;
    }

    memcpy(mSignature + (mPos - mImageOffset), aBuffer, toCopy);
    mPos += toCopy;
    aCount -= toCopy;
    aBuffer += toCopy;

    mIsPNG = !memcmp(mSignature, nsPNGDecoder::pngSignatureBytes, 
                     PNGSIGNATURESIZE);
    if (mIsPNG) {
      mContainedDecoder = new nsPNGDecoder(mImage);
      mContainedDecoder->SetObserver(mObserver);
      mContainedDecoder->SetSizeDecode(IsSizeDecode());
      mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength,
                                           mColormap, mColormapSize,
                                           mCurrentFrame);
      if (!WriteToContainedDecoder(mSignature, PNGSIGNATURESIZE, aStrategy)) {
        return;
      }
    }
  }

  // If we have a PNG, let the PNG decoder do all of the rest of the work
  if (mIsPNG && mContainedDecoder && mPos >= mImageOffset + PNGSIGNATURESIZE) {
    if (!WriteToContainedDecoder(aBuffer, aCount, aStrategy)) {
      return;
    }

    if (!HasSize() && mContainedDecoder->HasSize()) {
      PostSize(mContainedDecoder->GetImageMetadata().GetWidth(),
               mContainedDecoder->GetImageMetadata().GetHeight());
    }

    mPos += aCount;
    aBuffer += aCount;
    aCount = 0;

    // Raymond Chen says that 32bpp only are valid PNG ICOs
    // http://blogs.msdn.com/b/oldnewthing/archive/2010/10/22/10079192.aspx
    if (!IsSizeDecode() &&
        !static_cast<nsPNGDecoder*>(mContainedDecoder.get())->IsValidICO()) {
      PostDataError();
    }
    return;
  }

  // We've processed all of the icon dir entries and are within the 
  // bitmap info size
  if (!mIsPNG && mCurrIcon == mNumIcons && mPos >= mImageOffset && 
      mPos >= mImageOffset + PNGSIGNATURESIZE && 
      mPos < mImageOffset + BITMAPINFOSIZE) {

    // As we were decoding, we did not know if we had a PNG signature or the
    // start of a bitmap information header.  At this point we know we had
    // a bitmap information header and not a PNG signature, so fill the bitmap
    // information header with the data it should already have.
    memcpy(mBIHraw, mSignature, PNGSIGNATURESIZE);

    // We've found the icon.
    uint32_t toCopy = sizeof(mBIHraw) - (mPos - mImageOffset);
    if (toCopy > aCount)
      toCopy = aCount;

    memcpy(mBIHraw + (mPos - mImageOffset), aBuffer, toCopy);
    mPos += toCopy;
    aCount -= toCopy;
    aBuffer += toCopy;
  }

  // If we have a BMP inside the ICO and we have read the BIH header
  if (!mIsPNG && mPos == mImageOffset + BITMAPINFOSIZE) {

    // Make sure we have a sane value for the bitmap information header
    int32_t bihSize = ExtractBIHSizeFromBitmap(reinterpret_cast<int8_t*>(mBIHraw));
    if (bihSize != BITMAPINFOSIZE) {
      PostDataError();
      return;
    }
    // We are extracting the BPP from the BIH header as it should be trusted 
    // over the one we have from the icon header
    mBPP = ExtractBPPFromBitmap(reinterpret_cast<int8_t*>(mBIHraw));
    
    // Init the bitmap decoder which will do most of the work for us
    // It will do everything except the AND mask which isn't present in bitmaps
    // bmpDecoder is for local scope ease, it will be freed by mContainedDecoder
    nsBMPDecoder *bmpDecoder = new nsBMPDecoder(mImage);
    mContainedDecoder = bmpDecoder;
    bmpDecoder->SetUseAlphaData(true);
    mContainedDecoder->SetObserver(mObserver);
    mContainedDecoder->SetSizeDecode(IsSizeDecode());
    mContainedDecoder->InitSharedDecoder(mImageData, mImageDataLength,
                                         mColormap, mColormapSize,
                                         mCurrentFrame);

    // The ICO format when containing a BMP does not include the 14 byte
    // bitmap file header. To use the code of the BMP decoder we need to 
    // generate this header ourselves and feed it to the BMP decoder.
    int8_t bfhBuffer[BMPFILEHEADERSIZE];
    if (!FillBitmapFileHeaderBuffer(bfhBuffer)) {
      PostDataError();
      return;
    }
    if (!WriteToContainedDecoder((const char*)bfhBuffer, sizeof(bfhBuffer), aStrategy)) {
      return;
    }

    // Setup the cursor hot spot if one is present
    SetHotSpotIfCursor();

    // Fix the ICO height from the BIH.
    // Fix the height on the BIH to be /2 so our BMP decoder will understand.
    if (!FixBitmapHeight(reinterpret_cast<int8_t*>(mBIHraw))) {
      PostDataError();
      return;
    }

    // Fix the ICO width from the BIH.
    if (!FixBitmapWidth(reinterpret_cast<int8_t*>(mBIHraw))) {
      PostDataError();
      return;
    }

    // Write out the BMP's bitmap info header
    if (!WriteToContainedDecoder(mBIHraw, sizeof(mBIHraw), aStrategy)) {
      return;
    }

    PostSize(mContainedDecoder->GetImageMetadata().GetWidth(),
             mContainedDecoder->GetImageMetadata().GetHeight());

    // We have the size. If we're doing a size decode, we got what
    // we came for.
    if (IsSizeDecode())
      return;

    // Sometimes the ICO BPP header field is not filled out
    // so we should trust the contained resource over our own
    // information.
    mBPP = bmpDecoder->GetBitsPerPixel();

    // Check to make sure we have valid color settings
    uint16_t numColors = GetNumColors();
    if (numColors == (uint16_t)-1) {
      PostDataError();
      return;
    }
  }

  // If we have a BMP
  if (!mIsPNG && mContainedDecoder && mPos >= mImageOffset + BITMAPINFOSIZE) {
    uint16_t numColors = GetNumColors();
    if (numColors == (uint16_t)-1) {
      PostDataError();
      return;
    }
    // Feed the actual image data (not including headers) into the BMP decoder
    uint32_t bmpDataOffset = mDirEntry.mImageOffset + BITMAPINFOSIZE;
    uint32_t bmpDataEnd = mDirEntry.mImageOffset + BITMAPINFOSIZE + 
                          static_cast<nsBMPDecoder*>(mContainedDecoder.get())->GetCompressedImageSize() +
                          4 * numColors;

    // If we are feeding in the core image data, but we have not yet
    // reached the ICO's 'AND buffer mask'
    if (mPos >= bmpDataOffset && mPos < bmpDataEnd) {

      // Figure out how much data the BMP decoder wants
      uint32_t toFeed = bmpDataEnd - mPos;
      if (toFeed > aCount) {
        toFeed = aCount;
      }

      if (!WriteToContainedDecoder(aBuffer, toFeed, aStrategy)) {
        return;
      }

      mPos += toFeed;
      aCount -= toFeed;
      aBuffer += toFeed;
    }
  
    // If the bitmap is fully processed, treat any left over data as the ICO's
    // 'AND buffer mask' which appears after the bitmap resource.
    if (!mIsPNG && mPos >= bmpDataEnd) {
      // There may be an optional AND bit mask after the data.  This is
      // only used if the alpha data is not already set. The alpha data 
      // is used for 32bpp bitmaps as per the comment in ICODecoder.h
      // The alpha mask should be checked in all other cases.
      if (static_cast<nsBMPDecoder*>(mContainedDecoder.get())->GetBitsPerPixel() != 32 || 
          !static_cast<nsBMPDecoder*>(mContainedDecoder.get())->HasAlphaData()) {
        uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up
        if (mPos == bmpDataEnd) {
          mPos++;
          mRowBytes = 0;
          mCurLine = GetRealHeight();
          mRow = (uint8_t*)moz_realloc(mRow, rowSize);
          if (!mRow) {
            PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
            return;
          }
        }

        // Ensure memory has been allocated before decoding.
        NS_ABORT_IF_FALSE(mRow, "mRow is null");
        if (!mRow) {
          PostDataError();
          return;
        }

        while (mCurLine > 0 && aCount > 0) {
          uint32_t toCopy = std::min(rowSize - mRowBytes, aCount);
          if (toCopy) {
            memcpy(mRow + mRowBytes, aBuffer, toCopy);
            aCount -= toCopy;
            aBuffer += toCopy;
            mRowBytes += toCopy;
          }
          if (rowSize == mRowBytes) {
            mCurLine--;
            mRowBytes = 0;

            uint32_t* imageData = 
              static_cast<nsBMPDecoder*>(mContainedDecoder.get())->GetImageData();
            if (!imageData) {
              PostDataError();
              return;
            }
            uint32_t* decoded = imageData + mCurLine * GetRealWidth();
            uint32_t* decoded_end = decoded + GetRealWidth();
            uint8_t* p = mRow, *p_end = mRow + rowSize; 
            while (p < p_end) {
              uint8_t idx = *p++;
              for (uint8_t bit = 0x80; bit && decoded<decoded_end; bit >>= 1) {
                // Clear pixel completely for transparency.
                if (idx & bit) {
                  *decoded = 0;
                }
                decoded++;
              }
            }
          }
        }
      }
예제 #15
0
/*
 * GenerateConfiguration - write out a config file
 */
vi_rc GenerateConfiguration( const char *fname, bool is_cmdline )
{
    FILE        *fp;
    int         i;
    char        token[128];
    const char  *str;
    char        *buff;
    int         num;
    rgb         c;
    const char  *res;
    char        tmpstr[MAX_STR];

    if( fname == NULL ) {
        fname = CFG_NAME;
    }
    fp = fopen( fname, "w" );
    if( fp == NULL ) {
        return( ERR_FILE_OPEN );
    }
    isCmdLine = is_cmdline;
    buff = MemAllocUnsafe( VBUF_SIZE );
    if( buff != NULL ) {
        setvbuf( fp, buff, _IOFBF, VBUF_SIZE );
    }
    MyFprintf( fp, "#\n# %s configuration file\n# %s\n#\n",
#if defined( __WIN__ )
    banner1w1( "Text Editor for Windows" ), banner1w2( _VI_VERSION_ ) );
#else
    banner1w1( "Vi Text Editor" ), banner1w2( _VI_VERSION_ ) );
#endif
    if( is_cmdline ) {
        GetDateTimeString( token );
        MyFprintf( fp, "# File generated on %s\n#\n", token );
    }

    writeTitle( fp, "Hook script assignments" );
    doHookAssign( fp, SRC_HOOK_WRITE );
    doHookAssign( fp, SRC_HOOK_READ );
    doHookAssign( fp, SRC_HOOK_BUFFIN );
    doHookAssign( fp, SRC_HOOK_BUFFOUT );
    doHookAssign( fp, SRC_HOOK_COMMAND );
    doHookAssign( fp, SRC_HOOK_MODIFIED );
    doHookAssign( fp, SRC_HOOK_MENU );
    doHookAssign( fp, SRC_HOOK_MOUSE_LINESEL );
    doHookAssign( fp, SRC_HOOK_MOUSE_CHARSEL );

    writeTitle( fp, "General Settings" );
    num = GetNumberOfTokens( SetVarTokens );
    for( i = 0; i < num; i++ ) {
        if( i == SETVAR_T_TILECOLOR || i == SETVAR_T_FIGNORE || i == SETVAR_T_FILENAME ) {
            continue;
        }
        res = GetASetVal( GetTokenStringCVT( SetVarTokens, i, token, true ), tmpstr );
        switch( i ) {
        case SETVAR_T_STATUSSTRING:
        case SETVAR_T_FILEENDSTRING:
        case SETVAR_T_HISTORYFILE:
        case SETVAR_T_TMPDIR:
            /* strings with possible spaces */
            MyFprintf( fp, "set %s = \"%s\"\n", token, res );
            break;
        case SETVAR_T_GADGETSTRING:
            if( !IsGadgetStringChanged( res ) )
                break;
            // fall through
        default:
            MyFprintf( fp, "set %s = %s\n", token, res );
            break;
        }
    }

    writeTitle( fp, "Boolean Settings" );
    num = GetNumberOfTokens( SetFlagTokens );
    for( i = 0; i < num; i++ ) {
        str = GetASetVal( GetTokenStringCVT( SetFlagTokens, i, token, true ), tmpstr );
        MyFprintf( fp, "set %s%s\n", (*str == '0') ? "no" : "", token );
    }
    writeTitle( fp, "Match pairs" );
    for( i = INITIAL_MATCH_COUNT; i < MatchCount; i += 2 ) {
        MyFprintf( fp, "match /" );
        outputMatchData( fp, MatchData[i] );
        outputMatchData( fp, MatchData[i + 1] );
        MyFprintf( fp, "\n" );
    }

    writeTitle( fp, "Command Mode Mappings" );
    doMaps( fp, KeyMaps, "" );
    writeTitle( fp, "Insert Mode Mappings" );
    doMaps( fp, InputKeyMaps, "!" );

    writeTitle( fp, "Color Settings" );
    for( i = 0; i < GetNumColors(); i++ ) {
        if( GetColorSetting( i, &c ) ) {
            MyFprintf( fp, "setcolor %d %d %d %d\n", i, c.red, c.green, c.blue );
        }
    }

#ifdef __WIN__
    writeTitle( fp, "Font Settings" );
    BarfFontData( fp );
#endif

    writeTitle( fp, "Window Configuration" );
    doWindow( fp, PCL_T_COMMANDWINDOW, &cmdlinew_info, false );
    doWindow( fp, PCL_T_STATUSWINDOW, &statusw_info, false );
    doWindow( fp, PCL_T_COUNTWINDOW, &repcntw_info, false );
    doWindow( fp, PCL_T_EDITWINDOW, &editw_info, false );
    doWindow( fp, PCL_T_FILECWINDOW, &filecw_info, false );
    doWindow( fp, PCL_T_DIRWINDOW, &dirw_info, false );
    doWindow( fp, PCL_T_FILEWINDOW, &filelistw_info, false );
    doWindow( fp, PCL_T_MESSAGEWINDOW, &messagew_info, false );
#ifndef __WIN__
    doWindow( fp, PCL_T_SETWINDOW, &setw_info, false );
    doWindow( fp, PCL_T_LINENUMBERWINDOW, &linenumw_info, false );
    doWindow( fp, PCL_T_EXTRAINFOWINDOW, &extraw_info, false );
    doWindow( fp, PCL_T_SETVALWINDOW, &setvalw_info, false );
    doWindow( fp, PCL_T_MENUWINDOW, &menuw_info, false );
    doWindow( fp, PCL_T_MENUBARWINDOW, &menubarw_info, true );
    doWindow( fp, PCL_T_ACTIVEMENUWINDOW, &activemenu_info, true );
    doWindow( fp, PCL_T_GREYEDMENUWINDOW, &greyedmenu_info, true );
    doWindow( fp, PCL_T_ACTIVEGREYEDMENUWINDOW, &activegreyedmenu_info, true );
#endif

    writeTitle( fp, "Menu Configuration" );
    BarfMenuData( fp );

#ifdef __WIN__
    writeTitle( fp, "ToolBar Configuration" );
    BarfToolBarData( fp );
#endif

    writeTitle( fp, "File Type Source" );
    FTSBarfData( fp );

    fclose( fp );
    if( is_cmdline ) {
        Message1( "Configuration file \"%s\" generated", fname );
    }

    MemFree( buff );
    return( DO_NOT_CLEAR_MESSAGE_WINDOW );

} /* GenerateConfiguration */
예제 #16
0
/*
 * GenerateConfiguration - write out a config file
 */
vi_rc GenerateConfiguration( char *fname, bool is_cmdline )
{
    FILE        *f;
    int         i;
    char        token[128];
    char        *str;
    char        boolstr[3];
    char        *buff;
    int         num;
    rgb         c;
    char        *fmt;
    char        *res;

    if( fname == NULL ) {
        fname = CFG_NAME;
    }
    f = fopen( fname, "w" );
    if( f == NULL ) {
        return( ERR_FILE_OPEN );
    }
    isCmdLine = is_cmdline;
    buff = MemAllocUnsafe( VBUF_SIZE );
    if( buff != NULL ) {
        setvbuf( f, buff, _IOFBF, VBUF_SIZE );
    }
    MyFprintf( f, "#\n# WATCOM %s %s configuration file\n# %s\n#\n",
               TITLE, VERSIONT, AUTHOR );
    if( is_cmdline ) {
        GetDateTimeString( token );
        MyFprintf( f, "# File generated on %s\n#\n", token );
    }

    writeTitle( f, "Hook script assignments" );
    doHookAssign( f, SRC_HOOK_WRITE );
    doHookAssign( f, SRC_HOOK_READ );
    doHookAssign( f, SRC_HOOK_BUFFIN );
    doHookAssign( f, SRC_HOOK_BUFFOUT );
    doHookAssign( f, SRC_HOOK_COMMAND );
    doHookAssign( f, SRC_HOOK_MODIFIED );
    doHookAssign( f, SRC_HOOK_MENU );
    doHookAssign( f, SRC_HOOK_MOUSE_LINESEL );
    doHookAssign( f, SRC_HOOK_MOUSE_CHARSEL );

    writeTitle( f, "General Settings" );
    num = GetNumberOfTokens( SetTokens1 );
    for( i = 0; i < num; i++ ) {
        if( i == SET1_T_TILECOLOR || i == SET1_T_FIGNORE || i == SET1_T_FILENAME ) {
            continue;
        }
        strcpy( token, GetTokenString( SetTokens1, i ) );
        strlwr( token );
        res = GetASetVal( token );
        if( i == SET1_T_STATUSSTRING || i == SET1_T_FILEENDSTRING ||
            i == SET1_T_HISTORYFILE || i == SET1_T_TMPDIR ) {    /* strings with possible spaces */
            fmt = "set %s = \"%s\"\n";
        } else {
            fmt = "set %s = %s\n";
        }
        MyFprintf( f, fmt, token, res );
    }

    writeTitle( f, "Boolean Settings" );
    num = GetNumberOfTokens( SetTokens2 );
    for( i = 0; i < num; i++ ) {
        strcpy( token, GetTokenString( SetTokens2, i ) );
        strlwr( token );
        str = GetASetVal( token );
        boolstr[0] = 0;
        if( str[0] == '0' ) {
            boolstr[0] = 'n';
            boolstr[1] = 'o';
            boolstr[2] = 0;
        }
        MyFprintf( f, "set %s%s\n", boolstr, token );
    }
    writeTitle( f, "Match pairs" );
    for( i = INITIAL_MATCH_COUNT; i < MatchCount; i += 2 ) {
        MyFprintf( f, "match /" );
        outputMatchData( f, MatchData[i] );
        outputMatchData( f, MatchData[i + 1] );
        MyFprintf( f, "\n" );
    }

    writeTitle( f, "Command Mode Mappings" );
    doMaps( f, KeyMaps, "" );
    writeTitle( f, "Insert Mode Mappings" );
    doMaps( f, InputKeyMaps, "!" );

    writeTitle( f, "Color Settings" );
    for( i = 0; i < GetNumColors(); i++ ) {
        if( GetColorSetting( i, &c ) ) {
            MyFprintf( f, "setcolor %d %d %d %d\n", i, c.red, c.green, c.blue );
        }
    }

#ifdef __WIN__
    writeTitle( f, "Font Settings" );
    BarfFontData( f );
#endif

    writeTitle( f, "Window Configuration" );
    doWindow( f, PCL_T_COMMANDWINDOW, &cmdlinew_info, FALSE );
    doWindow( f, PCL_T_STATUSWINDOW, &statusw_info, FALSE );
    doWindow( f, PCL_T_COUNTWINDOW, &repcntw_info, FALSE );
    doWindow( f, PCL_T_EDITWINDOW, &editw_info, FALSE );
    doWindow( f, PCL_T_FILECWINDOW, &filecw_info, FALSE );
    doWindow( f, PCL_T_DIRWINDOW, &dirw_info, FALSE );
    doWindow( f, PCL_T_FILEWINDOW, &filelistw_info, FALSE );
    doWindow( f, PCL_T_MESSAGEWINDOW, &messagew_info, FALSE );
#ifndef __WIN__
    doWindow( f, PCL_T_SETWINDOW, &setw_info, FALSE );
    doWindow( f, PCL_T_LINENUMBERWINDOW, &linenumw_info, FALSE );
    doWindow( f, PCL_T_EXTRAINFOWINDOW, &extraw_info, FALSE );
    doWindow( f, PCL_T_SETVALWINDOW, &setvalw_info, FALSE );
    doWindow( f, PCL_T_MENUWINDOW, &menuw_info, FALSE );
    doWindow( f, PCL_T_MENUBARWINDOW, &menubarw_info, TRUE );
    doWindow( f, PCL_T_ACTIVEMENUWINDOW, &activemenu_info, TRUE );
    doWindow( f, PCL_T_GREYEDMENUWINDOW, &greyedmenu_info, TRUE );
    doWindow( f, PCL_T_ACTIVEGREYEDMENUWINDOW, &activegreyedmenu_info, TRUE );
#endif

    writeTitle( f, "Menu Configuration" );
    BarfMenuData( f );

#ifdef __WIN__
    writeTitle( f, "ToolBar Configuration" );
    BarfToolBarData( f );
#endif

    writeTitle( f, "File Type Source" );
    FTSBarfData( f );

    fclose( f );
    if( is_cmdline ) {
        Message1( "Configuration file \"%s\" generated", fname );
    }

    MemFree( buff );
    return( DO_NOT_CLEAR_MESSAGE_WINDOW );

} /* GenerateConfiguration */
예제 #17
0
// Create a GDI palette from a DIB color table
//************************************************************************
HPALETTE CDib::CreatePalette()
//************************************************************************
{
// create an identity palette from the DIB's color table
return ( CreateIdentityPalette( GetColors(), GetNumColors() ) );
}
예제 #18
0
//	Will read a file in DIB format and return a global HANDLE to its
//	BITMAPINFO.	 This function will work with both "old" and "new"
//	bitmap formats, but will always return a "new" BITMAPINFO
//************************************************************************
BOOL CDib::ReadBitmapInfo( HFILE fh )
//************************************************************************
{
	DWORD off, size;
	HANDLE hbi = NULL;
	int i, nNumColors;
	LPRGBQUAD pRgb;
	BITMAPINFOHEADER bi;
	BITMAPCOREHEADER bc;
	BITMAPFILEHEADER bf;

	if ( fh < 0 )
		return FALSE;

	off = _llseek(fh,0L,SEEK_CUR);

	if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
		return FALSE;

	// do we have a RC HEADER?
	if (bf.bfType != BFT_BITMAP)
		{
		bf.bfOffBits = 0L;
		_llseek(fh,off,SEEK_SET);
		}

	if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
		return FALSE;

	// what type of bitmap info is this?
	if ( (size = bi.biSize) == sizeof(BITMAPCOREHEADER) )
		{
			bc = *(LPBITMAPCOREHEADER)&bi;
			bi.biSize				= sizeof(BITMAPINFOHEADER);
			bi.biWidth				= (DWORD)bc.bcWidth;
			bi.biHeight				= (DWORD)bc.bcHeight;
			bi.biPlanes				= (UINT)bc.bcPlanes;
			bi.biBitCount			= (UINT)bc.bcBitCount;
			bi.biCompression		= BI_RGB;
			bi.biSizeImage			= 0;
			bi.biXPelsPerMeter		= 0;
			bi.biYPelsPerMeter		= 0;
			bi.biClrUsed			= 0;
			bi.biClrImportant		= 0;
			_llseek(fh,(long)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
		}

	//!!! hack for BI_BITFIELDS
	if ( bi.biCompression == BI_BITFIELDS && !bi.biClrUsed )
		bi.biClrUsed = 3;

	// Copy in the bitmap info header
	m_bmiHeader = bi;
	FixHeader();
	nNumColors = GetNumColors();
	pRgb = GetColors();

	if (nNumColors)
		{
		if (size == sizeof(BITMAPCOREHEADER))
			{
			// convert old color table (3 byte entries) to new (4 byte entries)
			_lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));

			for (i=nNumColors-1; i>=0; i--)
				{
				RGBQUAD rgb;

				rgb.rgbRed		= ((LPRGBTRIPLE)pRgb)[i].rgbtRed;
				rgb.rgbBlue		= ((LPRGBTRIPLE)pRgb)[i].rgbtBlue;
				rgb.rgbGreen	= ((LPRGBTRIPLE)pRgb)[i].rgbtGreen;
				rgb.rgbReserved = (BYTE)0;

				pRgb[i] = rgb;
				}
			}
		else
			{
			_lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
			}
		}

	if (bf.bfOffBits)
		_llseek(fh,off + bf.bfOffBits,SEEK_SET);

	return TRUE;
}
예제 #19
0
void
nsICODecoder::WriteInternal(const char* aBuffer, PRUint32 aCount)
{
  NS_ABORT_IF_FALSE(!HasError(), "Shouldn't call WriteInternal after error!");

  if (!aCount) // aCount=0 means EOF
    return;

  while (aCount && (mPos < ICONCOUNTOFFSET)) { // Skip to the # of icons.
    if (mPos == 2) { // if the third byte is 1: This is an icon, 2: a cursor
      if ((*aBuffer != 1) && (*aBuffer != 2)) {
        PostDataError();
        return;
      }
      mIsCursor = (*aBuffer == 2);
    }
    mPos++; aBuffer++; aCount--;
  }

  if (mPos == ICONCOUNTOFFSET && aCount >= 2) {
    mNumIcons = LITTLE_TO_NATIVE16(((PRUint16*)aBuffer)[0]);
    aBuffer += 2;
    mPos += 2;
    aCount -= 2;
  }

  if (mNumIcons == 0)
    return; // Nothing to do.

  PRUint16 colorDepth = 0;
  // Loop through each entry's dir entry
  while (mCurrIcon < mNumIcons) { 
    if (mPos >= DIRENTRYOFFSET + (mCurrIcon * sizeof(mDirEntryArray)) && 
        mPos < DIRENTRYOFFSET + ((mCurrIcon + 1) * sizeof(mDirEntryArray))) {
      PRUint32 toCopy = sizeof(mDirEntryArray) - 
                        (mPos - DIRENTRYOFFSET - mCurrIcon * sizeof(mDirEntryArray));
      if (toCopy > aCount) {
        toCopy = aCount;
      }
      memcpy(mDirEntryArray + sizeof(mDirEntryArray) - toCopy, aBuffer, toCopy);
      mPos += toCopy;
      aCount -= toCopy;
      aBuffer += toCopy;
    }
    if (aCount == 0)
      return; // Need more data

    IconDirEntry e;
    if (mPos == (DIRENTRYOFFSET + ICODIRENTRYSIZE) + 
                (mCurrIcon * sizeof(mDirEntryArray))) {
      mCurrIcon++;
      ProcessDirEntry(e);
      // We can't use GetRealWidth and GetRealHeight here because those operate
      // on mDirEntry, here we are going through each item in the directory
      if (((e.mWidth == 0 ? 256 : e.mWidth) == PREFICONSIZE && 
           (e.mHeight == 0 ? 256 : e.mHeight) == PREFICONSIZE && 
           (e.mBitCount >= colorDepth)) ||
          (mCurrIcon == mNumIcons && mImageOffset == 0)) {
        mImageOffset = e.mImageOffset;

        // ensure mImageOffset is >= size of the direntry headers (bug #245631)
        PRUint32 minImageOffset = DIRENTRYOFFSET + 
                                  mNumIcons * sizeof(mDirEntryArray);
        if (mImageOffset < minImageOffset) {
          PostDataError();
          return;
        }

        colorDepth = e.mBitCount;
        memcpy(&mDirEntry, &e, sizeof(IconDirEntry));
      }
    }
  }

  if (mPos < mImageOffset) {
    // Skip to (or at least towards) the desired image offset
    PRUint32 toSkip = mImageOffset - mPos;
    if (toSkip > aCount)
      toSkip = aCount;

    mPos    += toSkip;
    aBuffer += toSkip;
    aCount  -= toSkip;
  }

  // If we are within the first PNGSIGNATURESIZE bytes of the image data,
  // then we have either a BMP or a PNG.  We use the first PNGSIGNATURESIZE
  // bytes to determine which one we have.
  if (mCurrIcon == mNumIcons && mPos >= mImageOffset && 
      mPos < mImageOffset + PNGSIGNATURESIZE)
  {
    PRUint32 toCopy = PNGSIGNATURESIZE - (mPos - mImageOffset);
    if (toCopy > aCount) {
      toCopy = aCount;
    }

    memcpy(mSignature + (mPos - mImageOffset), aBuffer, toCopy);
    mPos += toCopy;
    aCount -= toCopy;
    aBuffer += toCopy;

    mIsPNG = !memcmp(mSignature, nsPNGDecoder::pngSignatureBytes, 
                     PNGSIGNATURESIZE);
    if (mIsPNG) {
      mContainedDecoder = new nsPNGDecoder();
      mContainedDecoder->InitSharedDecoder(mImage, mObserver);
      mContainedDecoder->Write(mSignature, PNGSIGNATURESIZE);
      mDataError = mContainedDecoder->HasDataError();
      if (mContainedDecoder->HasDataError()) {
        return;
      }
    }
  }

  // If we have a PNG, let the PNG decoder do all of the rest of the work
  if (mIsPNG && mContainedDecoder && mPos >= mImageOffset + PNGSIGNATURESIZE) {
    mContainedDecoder->Write(aBuffer, aCount);
    mDataError = mContainedDecoder->HasDataError();
    if (mContainedDecoder->HasDataError()) {
      return;
    }
    mPos += aCount;
    aBuffer += aCount;
    aCount = 0;

    // Raymond Chen says that 32bpp only are valid PNG ICOs
    // http://blogs.msdn.com/b/oldnewthing/archive/2010/10/22/10079192.aspx
    if (static_cast<nsPNGDecoder*>(mContainedDecoder.get())->HasValidInfo() && 
        static_cast<nsPNGDecoder*>(mContainedDecoder.get())->GetPixelDepth() != 32) {
      PostDataError();
    }
    return;
  }

  // We've processed all of the icon dir entries and are within the 
  // bitmap info size
  if (!mIsPNG && mCurrIcon == mNumIcons && mPos >= mImageOffset && 
      mPos >= mImageOffset + PNGSIGNATURESIZE && 
      mPos < mImageOffset + BITMAPINFOSIZE) {

    // As we were decoding, we did not know if we had a PNG signature or the
    // start of a bitmap information header.  At this point we know we had
    // a bitmap information header and not a PNG signature, so fill the bitmap
    // information header with the data it should already have.
    memcpy(mBIHraw, mSignature, PNGSIGNATURESIZE);

    // We've found the icon.
    PRUint32 toCopy = sizeof(mBIHraw) - (mPos - mImageOffset);
    if (toCopy > aCount)
      toCopy = aCount;

    memcpy(mBIHraw + (mPos - mImageOffset), aBuffer, toCopy);
    mPos += toCopy;
    aCount -= toCopy;
    aBuffer += toCopy;
  }

  // If we have a BMP inside the ICO and we have read the BIH header
  if (!mIsPNG && mPos == mImageOffset + BITMAPINFOSIZE) {

    // Make sure we have a sane value for the bitmap information header
    PRInt32 bihSize = ExtractBIHSizeFromBitmap(reinterpret_cast<PRInt8*>(mBIHraw));
    if (bihSize != BITMAPINFOSIZE) {
      PostDataError();
      return;
    }
    // We are extracting the BPP from the BIH header as it should be trusted 
    // over the one we have from the icon header
    mBPP = ExtractBPPFromBitmap(reinterpret_cast<PRInt8*>(mBIHraw));
    
    // Init the bitmap decoder which will do most of the work for us
    // It will do everything except the AND mask which isn't present in bitmaps
    // bmpDecoder is for local scope ease, it will be freed by mContainedDecoder
    nsBMPDecoder *bmpDecoder = new nsBMPDecoder(); 
    mContainedDecoder = bmpDecoder;
    bmpDecoder->SetUseAlphaData(PR_TRUE);
    mContainedDecoder->SetSizeDecode(IsSizeDecode());
    mContainedDecoder->InitSharedDecoder(mImage, mObserver);

    // The ICO format when containing a BMP does not include the 14 byte
    // bitmap file header. To use the code of the BMP decoder we need to 
    // generate this header ourselves and feed it to the BMP decoder.
    PRInt8 bfhBuffer[BMPFILEHEADERSIZE];
    if (!FillBitmapFileHeaderBuffer(bfhBuffer)) {
      PostDataError();
      return;
    }
    mContainedDecoder->Write((const char*)bfhBuffer, sizeof(bfhBuffer));
    mDataError = mContainedDecoder->HasDataError();
    if (mContainedDecoder->HasDataError()) {
      return;
    }

    // Setup the cursor hot spot if one is present
    SetHotSpotIfCursor();

    // Fix the height on the BMP resource
    FillBitmapInformationBufferHeight((PRInt8*)mBIHraw);

    // Write out the BMP's bitmap info header
    mContainedDecoder->Write(mBIHraw, sizeof(mBIHraw));
    mDataError = mContainedDecoder->HasDataError();
    if (mContainedDecoder->HasDataError()) {
      return;
    }

    // We have the size. If we're doing a size decode, we got what
    // we came for.
    if (IsSizeDecode())
      return;

    // Sometimes the ICO BPP header field is not filled out
    // so we should trust the contained resource over our own
    // information.
    mBPP = bmpDecoder->GetBitsPerPixel();

    // Check to make sure we have valid color settings
    PRUint16 numColors = GetNumColors();
    if (numColors == (PRUint16)-1) {
      PostDataError();
      return;
    }
  }

  // If we have a BMP
  if (!mIsPNG && mContainedDecoder && mPos >= mImageOffset + BITMAPINFOSIZE) {
    PRUint16 numColors = GetNumColors();
    if (numColors == (PRUint16)-1) {
      PostDataError();
      return;
    }
    // Feed the actual image data (not including headers) into the BMP decoder
    PRInt32 bmpDataOffset = mDirEntry.mImageOffset + BITMAPINFOSIZE;
    PRInt32 bmpDataEnd = mDirEntry.mImageOffset + BITMAPINFOSIZE + 
                         static_cast<nsBMPDecoder*>(mContainedDecoder.get())->GetCompressedImageSize() +
                         4 * numColors;

    // If we are feeding in the core image data, but we have not yet
    // reached the ICO's 'AND buffer mask'
    if (mPos >= bmpDataOffset && mPos < bmpDataEnd) {

      // Figure out how much data the BMP decoder wants
      PRUint32 toFeed = bmpDataEnd - mPos;
      if (toFeed > aCount) {
        toFeed = aCount;
      }

      mContainedDecoder->Write(aBuffer, toFeed);
      mDataError = mContainedDecoder->HasDataError();
      if (mContainedDecoder->HasDataError()) {
        return;
      }

      mPos += toFeed;
      aCount -= toFeed;
      aBuffer += toFeed;
    }
  
    // If the bitmap is fully processed, treat any left over data as the ICO's
    // 'AND buffer mask' which appears after the bitmap resource.
    if (!mIsPNG && mPos >= bmpDataEnd) {
      // There may be an optional AND bit mask after the data.  This is
      // only used if the alpha data is not already set. The alpha data 
      // is used for 32bpp bitmaps as per the comment in ICODecoder.h
      // The alpha mask should be checked in all other cases.
      if (static_cast<nsBMPDecoder*>(mContainedDecoder.get())->GetBitsPerPixel() != 32 || 
          !static_cast<nsBMPDecoder*>(mContainedDecoder.get())->HasAlphaData()) {
        PRUint32 rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up
        if (mPos == bmpDataEnd) {
          mPos++;
          mRowBytes = 0;
          mCurLine = GetRealHeight();
          mRow = (PRUint8*)moz_realloc(mRow, rowSize);
          if (!mRow) {
            PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
            return;
          }
        }

        // Ensure memory has been allocated before decoding.
        NS_ABORT_IF_FALSE(mRow, "mRow is null");
        NS_ABORT_IF_FALSE(mImage, "mImage is null");
        if (!mRow || !mImage) {
          PostDataError();
          return;
        }

        while (mCurLine > 0 && aCount > 0) {
          PRUint32 toCopy = NS_MIN(rowSize - mRowBytes, aCount);
          if (toCopy) {
            memcpy(mRow + mRowBytes, aBuffer, toCopy);
            aCount -= toCopy;
            aBuffer += toCopy;
            mRowBytes += toCopy;
          }
          if (rowSize == mRowBytes) {
            mCurLine--;
            mRowBytes = 0;

            PRUint32* imageData = 
              static_cast<nsBMPDecoder*>(mContainedDecoder.get())->GetImageData();
            if (!imageData) {
              PostDataError();
              return;
            }
            PRUint32* decoded = imageData + mCurLine * GetRealWidth();
            PRUint32* decoded_end = decoded + GetRealWidth();
            PRUint8* p = mRow, *p_end = mRow + rowSize; 
            while (p < p_end) {
              PRUint8 idx = *p++;
              for (PRUint8 bit = 0x80; bit && decoded<decoded_end; bit >>= 1) {
                // Clear pixel completely for transparency.
                if (idx & bit) {
                  *decoded = 0;
                }
                decoded++;
              }
            }
          }
        }
      }