247 lines
7.6 KiB
Diff
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 */
|