Bug 360000 - make 32-bit favicons with transparency work correctly in cairo

p=Alfred Kayser <alfredkayser@nl.ibm.com>, r=pavlov, sr=tor
This commit is contained in:
asqueella%gmail.com 2007-01-17 10:39:10 +00:00
Родитель bdb682ff0b
Коммит cfd265046f
3 изменённых файлов: 53 добавлений и 36 удалений

Просмотреть файл

@ -229,24 +229,22 @@ private:
}; };
/** Sets the pixel data in aDecoded to the given values. /** Sets the pixel data in aDecoded to the given values.
* The variable passed in as aDecoded will be moved on 3 bytes! */ * The variable passed in as aDecoded will be moved on 3 or 4 bytes! */
inline void SetPixel(PRUint8*& aDecoded, PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue, PRUint8 aAlpha = 0xFF) inline void SetPixel(PRUint8*& aDecoded, PRUint8 aRed, PRUint8 aGreen, PRUint8 aBlue, PRUint8 aAlpha = 0xFF)
{ {
#if defined(MOZ_CAIRO_GFX) #if defined(MOZ_CAIRO_GFX)
#ifdef IS_LITTLE_ENDIAN // This is not skipping for pixels where aAlpha happen to be 0xFF
// BGRX // This will also make the compiler skip this part completely when
*aDecoded++ = aBlue; // inlining SetPixel when aAlpha is not specified
*aDecoded++ = aGreen; if (aAlpha != 0xFF) {
*aDecoded++ = aRed; #define DO_PREMULTIPLY(c_) ((PRUint16(c_) * PRUint16(aAlpha) + 127) / 255)
*aDecoded++ = aAlpha; aBlue = DO_PREMULTIPLY(aBlue);
#else aGreen = DO_PREMULTIPLY(aGreen);
// XRGB aRed = DO_PREMULTIPLY(aRed);
*aDecoded++ = aAlpha; #undef DO_PREMULTIPLY
*aDecoded++ = aRed; }
*aDecoded++ = aGreen; *(PRUint32*)aDecoded = (aAlpha << 24) | (aRed << 16) | (aGreen << 8) | aBlue;
*aDecoded++ = aBlue; aDecoded += 4;
#endif
#else // MOZ_CAIRO_GFX #else // MOZ_CAIRO_GFX
#if defined(XP_MAC) || defined(XP_MACOSX) #if defined(XP_MAC) || defined(XP_MACOSX)
@ -266,11 +264,7 @@ inline void SetPixel(PRUint8*& aDecoded, PRUint8 aRed, PRUint8 aGreen, PRUint8 a
inline void SetPixel(PRUint8*& aDecoded, PRUint8 idx, colorTable* aColors) inline void SetPixel(PRUint8*& aDecoded, PRUint8 idx, colorTable* aColors)
{ {
PRUint8 red, green, blue; SetPixel(aDecoded, aColors[idx].red, aColors[idx].green, aColors[idx].blue);
red = aColors[idx].red;
green = aColors[idx].green;
blue = aColors[idx].blue;
SetPixel(aDecoded, red, green, blue);
} }
/** Sets two (or one if aCount = 1) pixels /** Sets two (or one if aCount = 1) pixels

Просмотреть файл

@ -96,6 +96,7 @@ nsresult nsICODecoder::SetImageData()
return NS_OK; return NS_OK;
} }
#ifndef MOZ_CAIRO_GFX
nsresult nsICODecoder::SetAlphaData() nsresult nsICODecoder::SetAlphaData()
{ {
// Alpha data was already set if bpp == 32 // Alpha data was already set if bpp == 32
@ -131,6 +132,7 @@ nsresult nsICODecoder::SetAlphaData()
free(alphaRow); free(alphaRow);
return NS_OK; return NS_OK;
} }
#endif
PRUint32 nsICODecoder::CalcAlphaRowSize() PRUint32 nsICODecoder::CalcAlphaRowSize()
{ {
@ -150,7 +152,9 @@ nsICODecoder::nsICODecoder()
mHaveAlphaData = 0; mHaveAlphaData = 0;
mDecodingAndMask = PR_FALSE; mDecodingAndMask = PR_FALSE;
mDecodedBuffer = nsnull; mDecodedBuffer = nsnull;
#ifndef MOZ_CAIRO_GFX
mAlphaBuffer = nsnull; mAlphaBuffer = nsnull;
#endif
} }
nsICODecoder::~nsICODecoder() nsICODecoder::~nsICODecoder()
@ -174,9 +178,11 @@ NS_IMETHODIMP nsICODecoder::Init(imgILoad *aLoad)
NS_IMETHODIMP nsICODecoder::Close() NS_IMETHODIMP nsICODecoder::Close()
{ {
if (mObserver) {
mObserver->OnStopContainer(nsnull, mImage); mObserver->OnStopContainer(nsnull, mImage);
mObserver->OnStopDecode(nsnull, NS_OK, nsnull); mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
mObserver = nsnull; mObserver = nsnull;
}
mImage = nsnull; mImage = nsnull;
mFrame = nsnull; mFrame = nsnull;
@ -197,7 +203,9 @@ NS_IMETHODIMP nsICODecoder::Close()
mDecodingAndMask = PR_FALSE; mDecodingAndMask = PR_FALSE;
free(mDecodedBuffer); free(mDecodedBuffer);
#ifndef MOZ_CAIRO_GFX
free(mAlphaBuffer); free(mAlphaBuffer);
#endif
return NS_OK; return NS_OK;
} }
@ -410,6 +418,7 @@ nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
if (!mDecodedBuffer) if (!mDecodedBuffer)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
#ifndef MOZ_CAIRO_GFX
PRUint32 alphaRowSize; PRUint32 alphaRowSize;
mFrame->GetAlphaBytesPerRow(&alphaRowSize); mFrame->GetAlphaBytesPerRow(&alphaRowSize);
nsAutoArrayPtr<PRUint8> alphaRow; // Will only be used if bpp == 32 nsAutoArrayPtr<PRUint8> alphaRow; // Will only be used if bpp == 32
@ -418,6 +427,7 @@ nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
if (!alphaRow) if (!alphaRow)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
#endif
// Ensure memory has been allocated before decoding. If we get this far // Ensure memory has been allocated before decoding. If we get this far
// without allocated memory, the file is most likely invalid. // without allocated memory, the file is most likely invalid.
@ -442,10 +452,11 @@ nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
} }
if (rowSize == mRowBytes) { if (rowSize == mRowBytes) {
mCurLine--; mCurLine--;
PRUint8* decoded = mDecodedBuffer + (mCurLine * mDirEntry.mWidth * GFXBYTESPERPIXEL); PRUint8* d = mDecodedBuffer + (mCurLine * mDirEntry.mWidth * GFXBYTESPERPIXEL);
PRUint8* p = mRow; PRUint8* p = mRow;
PRUint8* d = decoded; #ifndef MOZ_CAIRO_GFX
PRUint8* alphaPos = alphaRow; // only used if bpp == 32 PRUint8* alphaPos = alphaRow; // only used if bpp == 32
#endif
PRUint32 lpos = mDirEntry.mWidth; PRUint32 lpos = mDirEntry.mWidth;
switch (mBIH.bpp) { switch (mBIH.bpp) {
case 1: case 1:
@ -484,18 +495,24 @@ nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
p+=2; p+=2;
} }
break; break;
case 32:
case 24: case 24:
while (lpos > 0) { while (lpos > 0) {
#ifdef MOZ_CAIRO_GFX
SetPixel(d, p[2], p[1], p[0], (mBIH.bpp == 32) ? p[3] : 0xff);
#else
SetPixel(d, p[2], p[1], p[0]); SetPixel(d, p[2], p[1], p[0]);
#endif
p += 3; p += 3;
--lpos; --lpos;
if (mBIH.bpp == 32) }
mHaveAlphaData |= *alphaPos++ = *p++; // Alpha value break;
case 32:
while (lpos > 0) {
#ifdef MOZ_CAIRO_GFX
SetPixel(d, p[2], p[1], p[0], p[3]);
mHaveAlphaData |= p[3]; // Alpha value
#else
SetPixel(d, p[2], p[1], p[0]);
mHaveAlphaData |= *alphaPos++ = p[3]; // Alpha value
#endif
p += 4;
--lpos;
} }
break; break;
default: default:
@ -508,9 +525,11 @@ nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
mRowBytes = 0; mRowBytes = 0;
#ifndef MOZ_CAIRO_GFX
// If 32 bit image, gotta set the alpha data here // If 32 bit image, gotta set the alpha data here
if (mBIH.bpp == 32) if (mBIH.bpp == 32)
mFrame->SetAlphaData(alphaRow, alphaRowSize, mCurLine * alphaRowSize); mFrame->SetAlphaData(alphaRow, alphaRowSize, mCurLine * alphaRowSize);
#endif
} }
} while (!mDecodingAndMask && aCount > 0); } while (!mDecodingAndMask && aCount > 0);
@ -580,7 +599,7 @@ nsresult nsICODecoder::ProcessData(const char* aBuffer, PRUint32 aCount) {
// We complement the value, since our method of storing // We complement the value, since our method of storing
// transparency is opposite what Win32 uses in its masks. // transparency is opposite what Win32 uses in its masks.
*decoded = (idx & bit) ? 0x00 : 0xff; *decoded = (idx & bit) ? 0x00 : 0xff;
decoded += 4; decoded += GFXBYTESPERPIXEL;
} }
} }
#else #else

Просмотреть файл

@ -97,7 +97,9 @@ private:
void ProcessInfoHeader(); void ProcessInfoHeader();
nsresult SetImageData(); nsresult SetImageData();
#ifndef MOZ_CAIRO_GFX
nsresult SetAlphaData(); nsresult SetAlphaData();
#endif
PRUint32 CalcAlphaRowSize(); PRUint32 CalcAlphaRowSize();
@ -106,9 +108,6 @@ private:
nsCOMPtr<imgIContainer> mImage; nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame; nsCOMPtr<gfxIImageFrame> mFrame;
PRUint8 mHaveAlphaData;
PRPackedBool mDecodingAndMask;
PRUint32 mPos; PRUint32 mPos;
PRUint16 mNumIcons; PRUint16 mNumIcons;
PRUint16 mCurrIcon; PRUint16 mCurrIcon;
@ -130,8 +129,13 @@ private:
nsresult mStatus; nsresult mStatus;
PRUint8* mDecodedBuffer; PRUint8* mDecodedBuffer;
#ifndef MOZ_CAIRO_GFX
PRUint8* mAlphaBuffer; PRUint8* mAlphaBuffer;
#endif
PRUint8 mHaveAlphaData;
PRPackedBool mIsCursor; PRPackedBool mIsCursor;
PRPackedBool mDecodingAndMask;
}; };