overlay/net-libs/xulrunner/files/fix-animated-gifs.patch

247 lines
7.6 KiB
Diff

# HG changeset patch
# User Rafał Mużyło <galtgendo@o2.pl>
# Parent 69e253891ca3839b6d4b8f5cb7c0e6950bb66902
Fix animated gif flickering bug 597174
diff --git a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp
--- a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp
+++ b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp
@@ -197,30 +197,29 @@ static NS_METHOD ReadDataOut(nsIInputStr
}
// Push any new rows according to mCurrentPass/mLastFlushedPass and
// mCurrentRow/mLastFlushedRow. Note: caller is responsible for
// updating mlastFlushed{Row,Pass}.
nsresult
nsGIFDecoder2::FlushImageData(PRUint32 fromRow, PRUint32 rows)
{
- nsIntRect r(0, fromRow, mGIFStruct.width, rows);
+ nsIntRect r(mGIFStruct.x_offset, mGIFStruct.y_offset + fromRow, mGIFStruct.width, rows);
// Update image
nsresult rv = mImageContainer->FrameUpdated(mGIFStruct.images_decoded, r);
if (NS_FAILED(rv)) {
return rv;
}
// Offset to the frame position
// Only notify observer(s) for first frame
if (!mGIFStruct.images_decoded && mObserver) {
PRUint32 imgCurFrame;
mImageContainer->GetCurrentFrameIndex(&imgCurFrame);
- r.y += mGIFStruct.y_offset;
mObserver->OnDataAvailable(nsnull, imgCurFrame == PRUint32(mGIFStruct.images_decoded), &r);
}
return NS_OK;
}
nsresult
nsGIFDecoder2::FlushImageData()
{
diff --git a/modules/libpr0n/src/imgContainer.cpp b/modules/libpr0n/src/imgContainer.cpp
--- a/modules/libpr0n/src/imgContainer.cpp
+++ b/modules/libpr0n/src/imgContainer.cpp
@@ -415,16 +415,18 @@ nsresult imgContainer::InternalAddFrameH
nsAutoPtr<imgFrame> frame(aFrame);
if (paletteData && paletteLength)
frame->GetPaletteData(paletteData, paletteLength);
frame->GetImageData(imageData, imageLength);
+ frame->LockImageData();
+
mFrames.InsertElementAt(framenum, frame.forget());
mNumFrames++;
return NS_OK;
}
nsresult imgContainer::InternalAddFrame(PRUint32 framenum,
PRInt32 aX, PRInt32 aY,
@@ -440,16 +442,21 @@ nsresult imgContainer::InternalAddFrame(
return NS_ERROR_INVALID_ARG;
nsAutoPtr<imgFrame> frame(new imgFrame());
NS_ENSURE_TRUE(frame, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = frame->Init(aX, aY, aWidth, aHeight, aFormat, aPaletteDepth);
NS_ENSURE_SUCCESS(rv, rv);
+ if (mFrames.Length() > 0) {
+ imgFrame *prevframe = mFrames.ElementAt(mFrames.Length() - 1);
+ prevframe->UnlockImageData();
+ }
+
if (mFrames.Length() == 0) {
return InternalAddFrameHelper(framenum, frame.forget(), imageData, imageLength,
paletteData, paletteLength);
}
if (mFrames.Length() == 1) {
// Since we're about to add our second frame, initialize animation stuff
if (!ensureAnimExists())
diff --git a/modules/libpr0n/src/imgFrame.cpp b/modules/libpr0n/src/imgFrame.cpp
--- a/modules/libpr0n/src/imgFrame.cpp
+++ b/modules/libpr0n/src/imgFrame.cpp
@@ -152,16 +152,17 @@ imgFrame::imgFrame() :
mBlendMethod(1), /* imgIContainer::kBlendOver */
mSinglePixel(PR_FALSE),
mNeverUseDeviceSurface(PR_FALSE),
mFormatChanged(PR_FALSE),
mCompositingFailed(PR_FALSE)
#ifdef USE_WIN_SURFACE
, mIsDDBSurface(PR_FALSE)
#endif
+ , mLocked(PR_FALSE)
{
static PRBool hasCheckedOptimize = PR_FALSE;
if (!hasCheckedOptimize) {
if (PR_GetEnv("MOZ_DISABLE_IMAGE_OPTIMIZE")) {
gDisableOptimize = PR_TRUE;
}
hasCheckedOptimize = PR_TRUE;
}
@@ -413,18 +414,17 @@ void imgFrame::Draw(gfxContext *aContext
nsRefPtr<gfxASurface> surface;
gfxImageSurface::gfxImageFormat format;
NS_ASSERTION(!sourceRect.Intersect(subimage).IsEmpty(),
"We must be allowed to sample *some* source pixels!");
PRBool doTile = !imageRect.Contains(sourceRect);
if (doPadding || doPartialDecode) {
- gfxRect available = gfxRect(mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height) +
- gfxPoint(aPadding.left, aPadding.top);
+ gfxRect available = gfxRect(mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height);
if (!doTile && !mSinglePixel) {
// Not tiling, and we have a surface, so we can account for
// padding and/or a partial decode just by twiddling parameters.
// First, update our user-space fill rect.
sourceRect = sourceRect.Intersect(available);
gfxMatrix imageSpaceToUserSpace = userSpaceToImageSpace;
imageSpaceToUserSpace.Invert();
@@ -708,17 +708,17 @@ nsresult imgFrame::ImageUpdated(const ns
mem->IsLowMemory(&lowMemory);
if (lowMemory)
return NS_ERROR_OUT_OF_MEMORY;
mDecoded.UnionRect(mDecoded, aUpdateRect);
// clamp to bounds, in case someone sends a bogus updateRect (I'm looking at
// you, gif decoder)
- nsIntRect boundsRect(0, 0, mSize.width, mSize.height);
+ nsIntRect boundsRect(mOffset, mSize);
mDecoded.IntersectRect(mDecoded, boundsRect);
#ifdef XP_MACOSX
if (mQuartzSurface)
mQuartzSurface->Flush();
#endif
return NS_OK;
}
@@ -806,17 +806,23 @@ void imgFrame::GetPaletteData(PRUint32 *
*aPalette = (PRUint32 *) mPalettedImageData;
*length = PaletteDataLength();
}
}
nsresult imgFrame::LockImageData()
{
if (mPalettedImageData)
- return NS_OK;
+ return NS_ERROR_NOT_AVAILABLE;
+
+ NS_ABORT_IF_FALSE(!mLocked, "Trying to lock already locked image data.");
+ if (mLocked) {
+ return NS_ERROR_FAILURE;
+ }
+ mLocked = PR_TRUE;
if ((mOptSurface || mSinglePixel) && !mImageSurface) {
// Recover the pixels
mImageSurface = new gfxImageSurface(gfxIntSize(mSize.width, mSize.height),
gfxImageSurface::ImageFormatARGB32);
if (!mImageSurface || mImageSurface->CairoStatus())
return NS_ERROR_OUT_OF_MEMORY;
@@ -832,23 +838,35 @@ nsresult imgFrame::LockImageData()
#ifdef USE_WIN_SURFACE
mWinSurface = nsnull;
#endif
#ifdef XP_MACOSX
mQuartzSurface = nsnull;
#endif
}
+ if (mImageSurface)
+ mImageSurface->Flush();
+
return NS_OK;
}
nsresult imgFrame::UnlockImageData()
{
if (mPalettedImageData)
- return NS_OK;
+ return NS_ERROR_NOT_AVAILABLE;
+
+ NS_ABORT_IF_FALSE(mLocked, "Unlocking an unlocked image!");
+ if (!mLocked) {
+ return NS_ERROR_FAILURE;
+ }
+ mLocked = PR_FALSE;
+
+ if (mImageSurface)
+ mImageSurface->MarkDirty();
#ifdef XP_MACOSX
if (mQuartzSurface)
mQuartzSurface->Flush();
#endif
return NS_OK;
}
@@ -895,17 +913,17 @@ PRInt32 imgFrame::GetBlendMethod() const
void imgFrame::SetBlendMethod(PRInt32 aBlendMethod)
{
mBlendMethod = (PRInt8)aBlendMethod;
}
PRBool imgFrame::ImageComplete() const
{
- return mDecoded == nsIntRect(0, 0, mSize.width, mSize.height);
+ return mDecoded == nsIntRect(mOffset, mSize);
}
// A hint from the image decoders that this image has no alpha, even
// though we created is ARGB32. This changes our format to RGB24,
// which in turn will cause us to Optimize() to RGB24. Has no effect
// after Optimize() is called, though in all cases it will be just a
// performance win -- the pixels are still correct and have the A byte
// set to 0xff.
diff --git a/modules/libpr0n/src/imgFrame.h b/modules/libpr0n/src/imgFrame.h
--- a/modules/libpr0n/src/imgFrame.h
+++ b/modules/libpr0n/src/imgFrame.h
@@ -167,16 +167,17 @@ private: // data
gfxASurface::gfxImageFormat mFormat;
PRInt8 mPaletteDepth;
PRInt8 mBlendMethod;
PRPackedBool mSinglePixel;
PRPackedBool mNeverUseDeviceSurface;
PRPackedBool mFormatChanged;
PRPackedBool mCompositingFailed;
+ PRPackedBool mLocked;
#ifdef XP_WIN
PRPackedBool mIsDDBSurface;
#endif
};
#endif /* imgFrame_h */