diff --git a/mozilla/gfx/idl/gfxIImageFrame.idl b/mozilla/gfx/idl/gfxIImageFrame.idl index 7658a233216..9779af4627b 100644 --- a/mozilla/gfx/idl/gfxIImageFrame.idl +++ b/mozilla/gfx/idl/gfxIImageFrame.idl @@ -57,7 +57,7 @@ native nsRectRef(nsIntRect &); * @author Stuart Parmenter * @version 0.1 */ -[scriptable, uuid(2502c898-73bd-4da5-8fae-21cf7a492f64)] +[scriptable, uuid(7292afa2-3b94-424d-97d5-51ce2f04c0fe)] interface gfxIImageFrame : nsISupports { /** @@ -156,4 +156,8 @@ interface gfxIImageFrame : nsISupports * moment */ attribute long frameDisposalMethod; + + /* PNG specific methods */ + + attribute long blendMethod; }; diff --git a/mozilla/gfx/src/shared/gfxImageFrame.cpp b/mozilla/gfx/src/shared/gfxImageFrame.cpp index 060667c14d3..8ac40d9dc71 100644 --- a/mozilla/gfx/src/shared/gfxImageFrame.cpp +++ b/mozilla/gfx/src/shared/gfxImageFrame.cpp @@ -46,7 +46,8 @@ gfxImageFrame::gfxImageFrame() : mInitialized(PR_FALSE), mMutable(PR_TRUE), mTimeout(100), - mDisposalMethod(0) + mDisposalMethod(0), /* imgIContainer::kDisposeNotSpecified */ + mBlendMethod(1) /* imgIContainer::kBlendOver */ { /* member initializers and constructor code */ } @@ -343,6 +344,24 @@ NS_IMETHODIMP gfxImageFrame::SetFrameDisposalMethod(PRInt32 aFrameDisposalMethod return NS_OK; } +/* attribute long blendMethod; */ +NS_IMETHODIMP gfxImageFrame::GetBlendMethod(PRInt32 *aBlendMethod) +{ + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + *aBlendMethod = mBlendMethod; + return NS_OK; +} +NS_IMETHODIMP gfxImageFrame::SetBlendMethod(PRInt32 aBlendMethod) +{ + if (!mInitialized) + return NS_ERROR_NOT_INITIALIZED; + + mBlendMethod = (PRInt8)aBlendMethod; + return NS_OK; +} + NS_IMETHODIMP gfxImageFrame::GetInterface(const nsIID & aIID, void * *result) { if (!mInitialized) diff --git a/mozilla/gfx/src/shared/gfxImageFrame.h b/mozilla/gfx/src/shared/gfxImageFrame.h index d9f251461e5..80108af75af 100644 --- a/mozilla/gfx/src/shared/gfxImageFrame.h +++ b/mozilla/gfx/src/shared/gfxImageFrame.h @@ -80,4 +80,5 @@ private: PRInt32 mTimeout; // -1 means display forever nsIntPoint mOffset; PRInt32 mDisposalMethod; + PRInt8 mBlendMethod; }; diff --git a/mozilla/modules/libpr0n/decoders/png/nsPNGDecoder.cpp b/mozilla/modules/libpr0n/decoders/png/nsPNGDecoder.cpp index 83b74d378e2..0b00ef52d61 100644 --- a/mozilla/modules/libpr0n/decoders/png/nsPNGDecoder.cpp +++ b/mozilla/modules/libpr0n/decoders/png/nsPNGDecoder.cpp @@ -136,13 +136,13 @@ void nsPNGDecoder::SetAnimFrameInfo() { png_uint_16 delay_num, delay_den; /* in seconds */ png_byte dispose_op; + png_byte blend_op; PRInt32 timeout; /* in milliseconds */ delay_num = png_get_next_frame_delay_num(mPNG, mInfo); delay_den = png_get_next_frame_delay_den(mPNG, mInfo); dispose_op = png_get_next_frame_dispose_op(mPNG, mInfo); - - // XXX need to handle blend_op here! + blend_op = png_get_next_frame_blend_op(mPNG, mInfo); if (delay_num == 0) { timeout = 0; // gfxImageFrame::SetTimeout() will set to a minimum @@ -163,6 +163,11 @@ void nsPNGDecoder::SetAnimFrameInfo() mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeClear); else mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeKeep); + + if (blend_op == PNG_BLEND_OP_SOURCE) + mFrame->SetBlendMethod(imgIContainer::kBlendSource); + /*else // 'over' is the default for a gfxImageFrame + mFrame->SetBlendMethod(imgIContainer::kBlendOver); */ } diff --git a/mozilla/modules/libpr0n/public/imgIContainer.idl b/mozilla/modules/libpr0n/public/imgIContainer.idl index 6897fb737ee..cc750212898 100644 --- a/mozilla/modules/libpr0n/public/imgIContainer.idl +++ b/mozilla/modules/libpr0n/public/imgIContainer.idl @@ -68,6 +68,16 @@ interface imgIContainer : nsISupports const long kDisposeClear = 2; // Clear the frame's area, revealing bg const long kDisposeRestorePrevious = 3; // Restore the previous (composited) frame + /* + * "Blend" method indicates how the current image is combined with the + * previous image. + */ + const long kBlendSource = 0; // All color components of the frame, including alpha, + // overwrite the current contents of the frame's + // output buffer region + const long kBlendOver = 1; // The frame should be composited onto the output buffer + // based on its alpha, using a simple OVER operation + /** * Create a new \a aWidth x \a aHeight sized image container. * diff --git a/mozilla/modules/libpr0n/src/imgContainer.cpp b/mozilla/modules/libpr0n/src/imgContainer.cpp index 616fc7de32f..ac1816b334e 100644 --- a/mozilla/modules/libpr0n/src/imgContainer.cpp +++ b/mozilla/modules/libpr0n/src/imgContainer.cpp @@ -943,7 +943,7 @@ nsresult imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, } // Check if the frame we are composing wants the previous image restored afer - // it is done. Don't store it (again) if last frame wanted it's image restored + // it is done. Don't store it (again) if last frame wanted its image restored // too if ((nextFrameDisposalMethod == imgIContainer::kDisposeRestorePrevious) && (prevFrameDisposalMethod != imgIContainer::kDisposeRestorePrevious)) { @@ -1089,7 +1089,19 @@ nsresult imgContainer::DrawFrameTo(gfxIImageFrame *aSrc, dstImg->GetSurface(getter_AddRefs(dstSurf)); gfxContext dst(dstSurf); + + // first clear the surface if the blend flag says so + PRInt32 blendMethod; + aSrc->GetBlendMethod(&blendMethod); + gfxContext::GraphicsOperator defaultOperator = dst.CurrentOperator(); + if (blendMethod == imgIContainer::kBlendSource) { + dst.SetOperator(gfxContext::OPERATOR_CLEAR); + dst.Rectangle(gfxRect(aDstRect.x, aDstRect.y, aDstRect.width, aDstRect.height)); + dst.Fill(); + } + dst.NewPath(); + dst.SetOperator(defaultOperator); // We don't use PixelSnappedRectangleAndSetPattern because if // these coords aren't already pixel aligned, we've lost // before we've even begun.