Bug 1062066 (Part 3) - Only mark BMP surfaces as transparent if they actually have alpha data. r=tn

This commit is contained in:
Seth Fowler 2015-09-08 22:07:09 -07:00
parent 1d9c6c1973
commit 4010153517
3 changed files with 14 additions and 38 deletions

View File

@ -122,15 +122,6 @@ nsBMPDecoder::GetCompressedImageSize() const
return pixelArraySize;
}
// Obtains whether or not a BMP file had alpha data in its 4th byte
// for 32BPP bitmaps. Only use after the bitmap has been processed.
bool
nsBMPDecoder::HasAlphaData() const
{
return mHaveAlphaData;
}
void
nsBMPDecoder::FinishInternal()
{
@ -147,7 +138,7 @@ nsBMPDecoder::FinishInternal()
nsIntRect r(0, 0, mBIH.width, GetHeight());
PostInvalidation(r);
if (mUseAlphaData) {
if (mUseAlphaData && mHaveAlphaData) {
PostFrameStop(Opacity::SOME_TRANSPARENCY);
} else {
PostFrameStop(Opacity::OPAQUE);
@ -664,28 +655,11 @@ nsBMPDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
case 32:
while (lpos > 0) {
if (mUseAlphaData) {
if (!mHaveAlphaData && p[3]) {
// Non-zero alpha byte detected! Clear previous
// pixels that we have already processed.
// This works because we know that if we
// are reaching here then the alpha data in byte
// 4 has been right all along. And we know it
// has been set to 0 the whole time, so that
// means that everything is transparent so far.
uint32_t* start = reinterpret_cast<uint32_t*>
(mImageData) + GetWidth() *
(mCurLine - 1);
uint32_t heightDifference = GetHeight() -
mCurLine + 1;
uint32_t pixelCount = GetWidth() *
heightDifference;
memset(start, 0, pixelCount * sizeof(uint32_t));
if (MOZ_UNLIKELY(!mHaveAlphaData && p[3])) {
PostHasTransparency();
mHaveAlphaData = true;
}
SetPixel(d, p[2], p[1], p[0], mHaveAlphaData ? p[3] : 0xFF);
SetPixel(d, p[2], p[1], p[0], p[3]);
} else {
SetPixel(d, p[2], p[1], p[0]);
}

View File

@ -46,7 +46,10 @@ public:
// Obtains whether or not a BMP file had alpha data in its 4th byte
// for 32BPP bitmaps. Only use after the bitmap has been processed.
bool HasAlphaData() const;
bool HasAlphaData() const { return mHaveAlphaData; }
/// Marks this BMP as having alpha data (due to e.g. an ICO alpha mask).
void SetHasAlphaData() { mHaveAlphaData = true; }
virtual void WriteInternal(const char* aBuffer,
uint32_t aCount) override;

View File

@ -532,14 +532,14 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// 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) {
nsRefPtr<nsBMPDecoder> bmpDecoder =
static_cast<nsBMPDecoder*>(mContainedDecoder.get());
// 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()) {
if (bmpDecoder->GetBitsPerPixel() != 32 || !bmpDecoder->HasAlphaData()) {
uint32_t rowSize = ((GetRealWidth() + 31) / 32) * 4; // + 31 to round up
if (mPos == bmpDataEnd) {
mPos++;
@ -573,9 +573,7 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
mCurLine--;
mRowBytes = 0;
uint32_t* imageData =
static_cast<nsBMPDecoder*>(mContainedDecoder.get())->
GetImageData();
uint32_t* imageData = bmpDecoder->GetImageData();
if (!imageData) {
PostDataError();
return;
@ -601,7 +599,8 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// If any bits are set in sawTransparency, then we know at least one
// pixel was transparent.
if (sawTransparency) {
PostHasTransparency();
PostHasTransparency();
bmpDecoder->SetHasAlphaData();
}
}
}