Bug 391295 - "APNG blending mode APNG_BLEND_OP_SOURCE not implemented" [p=asmith15@littlesvr.ca (Andrew Smith) r=stuart a1.9=damons]

This commit is contained in:
reed@reedloden.com 2007-10-23 12:33:20 -07:00
parent 4ef4d7e3ce
commit 918a9ce9c1
6 changed files with 56 additions and 5 deletions

View File

@ -57,7 +57,7 @@ native nsRectRef(nsIntRect &);
* @author Stuart Parmenter <pavlov@netscape.com>
* @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;
};

View File

@ -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)

View File

@ -80,4 +80,5 @@ private:
PRInt32 mTimeout; // -1 means display forever
nsIntPoint mOffset;
PRInt32 mDisposalMethod;
PRInt8 mBlendMethod;
};

View File

@ -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); */
}

View File

@ -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.
*

View File

@ -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.