Bug 98252 - assume 8-bit alpha channels are really 0- or 1-bit until

proven otherwise.  r=rjesup,pavlov, sr=attinasi
This commit is contained in:
tor%cs.brown.edu 2001-09-27 01:16:59 +00:00
Родитель e0d617ebf0
Коммит 8b042de390
2 изменённых файлов: 89 добавлений и 44 удалений

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

@ -33,6 +33,9 @@
#define IsFlagSet(a,b) ((a) & (b))
#define NS_GET_BIT(rowptr, x) (rowptr[(x)>>3] & (1<<(7-(x)&0x7)))
#define NS_SET_BIT(rowptr, x) (rowptr[(x)>>3] |= (1<<(7-(x)&0x7)))
// Defining this will trace the allocation of images. This includes
// ctor, dtor and update.
//#define TRACE_IMAGE_ALLOCATION
@ -61,17 +64,16 @@ nsImageGTK::nsImageGTK()
mWidth = 0;
mHeight = 0;
mDepth = 0;
mAlphaBits = nsnull;
mAlphaBits = mTrueAlphaBits = nsnull;
mAlphaPixmap = nsnull;
mImagePixmap = nsnull;
mAlphaDepth = 0;
mAlphaDepth = mTrueAlphaDepth = 0;
mRowBytes = 0;
mSizeImage = 0;
mAlphaHeight = 0;
mAlphaWidth = 0;
mNaturalWidth = 0;
mNaturalHeight = 0;
mAlphaValid = PR_FALSE;
mIsSpacer = PR_TRUE;
mPendingUpdate = PR_FALSE;
@ -86,15 +88,20 @@ nsImageGTK::nsImageGTK()
nsImageGTK::~nsImageGTK()
{
if(nsnull != mImageBits) {
delete[] (PRUint8*)mImageBits;
delete[] mImageBits;
mImageBits = nsnull;
}
if (nsnull != mAlphaBits) {
delete[] (PRUint8*)mAlphaBits;
delete[] mAlphaBits;
mAlphaBits = nsnull;
}
if (nsnull != mTrueAlphaBits) {
delete[] mTrueAlphaBits;
mTrueAlphaBits = nsnull;
}
if (mAlphaPixmap) {
gdk_pixmap_unref(mAlphaPixmap);
}
@ -117,15 +124,20 @@ nsresult nsImageGTK::Init(PRInt32 aWidth, PRInt32 aHeight,
g_return_val_if_fail ((aWidth != 0) || (aHeight != 0), NS_ERROR_FAILURE);
if (nsnull != mImageBits) {
delete[] (PRUint8*)mImageBits;
delete[] mImageBits;
mImageBits = nsnull;
}
if (nsnull != mAlphaBits) {
delete[] (PRUint8*)mAlphaBits;
delete[] mAlphaBits;
mAlphaBits = nsnull;
}
if (nsnull != mTrueAlphaBits) {
delete[] mTrueAlphaBits;
mTrueAlphaBits = nsnull;
}
if (nsnull != mAlphaPixmap) {
gdk_pixmap_unref(mAlphaPixmap);
mAlphaPixmap = nsnull;
@ -177,6 +189,16 @@ nsresult nsImageGTK::Init(PRInt32 aWidth, PRInt32 aHeight,
mAlphaHeight = 0;
break;
case nsMaskRequirements_kNeeds8Bit:
mTrueAlphaRowBytes = aWidth;
mTrueAlphaDepth = 8;
// 32-bit align each row
mTrueAlphaRowBytes = (mTrueAlphaRowBytes + 3) & ~0x3;
mTrueAlphaBits = new PRUint8[mTrueAlphaRowBytes * aHeight];
// FALL THROUGH
case nsMaskRequirements_kNeeds1Bit:
mAlphaRowBytes = (aWidth + 7) / 8;
mAlphaDepth = 1;
@ -185,22 +207,15 @@ nsresult nsImageGTK::Init(PRInt32 aWidth, PRInt32 aHeight,
mAlphaRowBytes = (mAlphaRowBytes + 3) & ~0x3;
mAlphaBits = new PRUint8[mAlphaRowBytes * aHeight];
mAlphaWidth = aWidth;
mAlphaHeight = aHeight;
break;
case nsMaskRequirements_kNeeds8Bit:
mAlphaRowBytes = aWidth;
mAlphaDepth = 8;
// 32-bit align each row
mAlphaRowBytes = (mAlphaRowBytes + 3) & ~0x3;
mAlphaBits = new PRUint8[mAlphaRowBytes * aHeight];
memset(mAlphaBits, 0, mAlphaRowBytes*aHeight);
mAlphaWidth = aWidth;
mAlphaHeight = aHeight;
break;
}
if (aMaskRequirements == nsMaskRequirements_kNeeds8Bit)
mAlphaDepth = 0;
return NS_OK;
}
@ -243,7 +258,10 @@ PRBool nsImageGTK::IsOptimized()
PRUint8 *nsImageGTK::GetAlphaBits()
{
return mAlphaBits;
if (mTrueAlphaBits)
return mTrueAlphaBits;
else
return mAlphaBits;
}
PRInt32 nsImageGTK::GetAlphaWidth()
@ -259,7 +277,10 @@ PRInt32 nsImageGTK::GetAlphaHeight()
PRInt32
nsImageGTK::GetAlphaLineStride()
{
return mAlphaRowBytes;
if (mTrueAlphaBits)
return mTrueAlphaRowBytes;
else
return mAlphaRowBytes;
}
nsIImage *nsImageGTK::DuplicateImage()
@ -310,16 +331,44 @@ void nsImageGTK::UpdateCachedImage()
right = left + rect->width;
// check if the image has an all-opaque 8-bit alpha mask
if ((mAlphaDepth==8) && !mAlphaValid) {
for (unsigned y=rect->y; (y<bottom) && !mAlphaValid; y++) {
unsigned char *alpha = mAlphaBits + mAlphaRowBytes*y + left;
if ((mTrueAlphaDepth==8) && (mAlphaDepth<mTrueAlphaDepth)) {
for (unsigned y=rect->y;
(y<bottom) && (mAlphaDepth<mTrueAlphaDepth);
y++) {
unsigned char *alpha = mTrueAlphaBits + mTrueAlphaRowBytes*y + left;
unsigned char *mask = mAlphaBits + mAlphaRowBytes*y;
for (unsigned x=left; x<right; x++) {
if (*(alpha++)!=255) {
mAlphaValid=PR_TRUE;
switch (*(alpha++)) {
case 255:
NS_SET_BIT(mask,x);
break;
case 0:
if (mAlphaDepth != 8)
mAlphaDepth=1;
break;
default:
mAlphaDepth=8;
break;
}
}
}
if (mAlphaDepth==8) {
if (mImagePixmap) {
gdk_pixmap_unref(mImagePixmap);
mImagePixmap = 0;
}
if (mAlphaPixmap) {
gdk_pixmap_unref(mAlphaPixmap);
mAlphaPixmap = 0;
}
if (mAlphaBits) {
delete [] mAlphaBits;
mAlphaBits = mTrueAlphaBits;
mAlphaRowBytes = mTrueAlphaRowBytes;
mTrueAlphaBits = 0;
}
}
}
// check if the image is a spacer
@ -379,12 +428,7 @@ void nsImageGTK::UpdateCachedImage()
}
}
if (mAlphaValid && mImagePixmap) {
gdk_pixmap_unref(mImagePixmap);
mImagePixmap = 0;
}
if (!mAlphaValid) {
if (mAlphaDepth != 8) {
CreateOffscreenPixmap(mWidth, mHeight);
if (!sXbitGC)
sXbitGC = gdk_gc_new(mImagePixmap);
@ -398,7 +442,7 @@ void nsImageGTK::UpdateCachedImage()
rect->x, rect->y);
}
}
mUpdateRegion.Empty();
mPendingUpdate = PR_FALSE;
mFlags = nsImageUpdateFlags_kBitsChanged; // this should be 0'd out by Draw()
@ -455,7 +499,7 @@ nsImageGTK::DrawScaled(nsIRenderingContext &aContext,
CreateAlphaBitmap(mWidth, mHeight);
}
if ((mAlphaDepth==8) && mAlphaValid) {
if (mAlphaDepth==8) {
DrawComposited(aContext, aSurface,
aSX, aSY, aSWidth, aSHeight,
aDX, aDY, aDWidth, aDHeight);
@ -605,7 +649,7 @@ nsImageGTK::Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
if (aDWidth <= 0 || aDHeight <= 0 || aSWidth <= 0 || aSHeight <= 0)
return NS_OK;
if ((mAlphaDepth==8) && mAlphaValid) {
if (mAlphaDepth==8) {
DrawComposited(aContext, aSurface,
aSX, aSY, aSWidth, aSHeight,
aDX, aDY, aSWidth, aSHeight);
@ -1261,7 +1305,7 @@ nsImageGTK::Draw(nsIRenderingContext &aContext,
if ((mAlphaDepth==1) && mIsSpacer)
return NS_OK;
if ((mAlphaDepth==8) && mAlphaValid) {
if (mAlphaDepth==8) {
DrawComposited(aContext, aSurface, 0, 0, aWidth, aHeight, aX, aY, aWidth, aHeight);
return NS_OK;
}
@ -1472,7 +1516,7 @@ NS_IMETHODIMP nsImageGTK::DrawTile(nsIRenderingContext &aContext,
return NS_OK;
}
if (partial || ((mAlphaDepth == 8) && mAlphaValid)) {
if (partial || (mAlphaDepth == 8)) {
#ifdef DEBUG_TILING
printf("Warning: using slow tiling\n");
#endif
@ -1695,9 +1739,6 @@ NS_IMETHODIMP nsImageGTK::DrawToImage(nsIImage* aDstImage,
PRUint8 *src = rgbPtr + y*rgbStride;
PRUint8 *alpha = alphaPtr + y*alphaStride;
for (int x=0; x<aDWidth; x++, dst+=3, src+=3) {
#define NS_GET_BIT(rowptr, x) (rowptr[(x)>>3] & (1<<(7-(x)&0x7)))
#define NS_SET_BIT(rowptr, x) (rowptr[(x)>>3] |= (1<<(7-(x)&0x7)))
// if this pixel is opaque then copy into the destination image
if (NS_GET_BIT(alpha, x)) {
dst[0] = src[0];
@ -1705,9 +1746,6 @@ NS_IMETHODIMP nsImageGTK::DrawToImage(nsIImage* aDstImage,
dst[2] = src[2];
NS_SET_BIT(dstAlpha, aDX+x);
}
#undef NS_GET_BIT
#undef NS_SET_BIT
}
}
break;

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

@ -123,7 +123,12 @@ public:
* @update - lordpixel 2001/05/16
* @return the alpha mask depth for the image, ie, 0, 1 or 8
*/
virtual PRInt8 GetAlphaDepth() {return(mAlphaDepth);}
virtual PRInt8 GetAlphaDepth() {
if (mTrueAlphaBits)
return mTrueAlphaDepth;
else
return mAlphaDepth;
}
virtual void MoveAlphaMask(PRInt32 aX, PRInt32 aY);
NS_IMETHOD LockImagePixels(PRBool aMaskPixels);
@ -189,6 +194,7 @@ private:
PRUint8 *mImageBits;
GdkPixmap *mImagePixmap;
PRUint8 *mTrueAlphaBits;
PRUint8 *mAlphaBits;
GdkPixmap *mAlphaPixmap;
@ -209,10 +215,11 @@ private:
// alpha layer members
PRInt16 mAlphaRowBytes; // alpha bytes per row
PRInt16 mTrueAlphaRowBytes; // alpha bytes per row
PRInt16 mAlphaWidth; // alpha layer width
PRInt16 mAlphaHeight; // alpha layer height
PRInt8 mAlphaDepth; // alpha layer depth
PRPackedBool mAlphaValid;
PRInt8 mTrueAlphaDepth; // alpha layer depth
PRPackedBool mIsSpacer;
PRPackedBool mPendingUpdate;