зеркало из https://github.com/mozilla/gecko-dev.git
Bug 696569 - Allow for non-premultiplied data for canvases - r=bjacob,joedrew
This commit is contained in:
Родитель
680806e579
Коммит
f23bc53c69
|
@ -67,6 +67,10 @@ class nsICanvasElementExternal : public nsISupports {
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASELEMENTEXTERNAL_IID)
|
||||
|
||||
enum {
|
||||
RenderFlagPremultAlpha = 0x1
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the size in pixels of this canvas element
|
||||
*/
|
||||
|
@ -77,7 +81,8 @@ public:
|
|||
* to the given gfxContext at the origin of its coordinate space.
|
||||
*/
|
||||
NS_IMETHOD RenderContextsExternal(gfxContext *ctx,
|
||||
gfxPattern::GraphicsFilter aFilter) = 0;
|
||||
gfxPattern::GraphicsFilter aFilter,
|
||||
PRUint32 aFlags = RenderFlagPremultAlpha) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasElementExternal, NS_ICANVASELEMENTEXTERNAL_IID)
|
||||
|
|
|
@ -74,6 +74,10 @@ public:
|
|||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
|
||||
|
||||
enum {
|
||||
RenderFlagPremultAlpha = 0x1
|
||||
};
|
||||
|
||||
// This method should NOT hold a ref to aParentCanvas; it will be called
|
||||
// with nsnull when the element is going away.
|
||||
NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas) = 0;
|
||||
|
@ -85,7 +89,9 @@ public:
|
|||
NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height) = 0;
|
||||
|
||||
// Render the canvas at the origin of the given gfxContext
|
||||
NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter) = 0;
|
||||
NS_IMETHOD Render(gfxContext *ctx,
|
||||
gfxPattern::GraphicsFilter aFilter,
|
||||
PRUint32 aFlags = RenderFlagPremultAlpha) = 0;
|
||||
|
||||
// Gives you a stream containing the image represented by this context.
|
||||
// The format is given in aMimeTime, for example "image/png".
|
||||
|
|
|
@ -561,7 +561,7 @@ WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f)
|
||||
WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f, PRUint32 aFlags)
|
||||
{
|
||||
if (!gl)
|
||||
return NS_OK;
|
||||
|
@ -572,7 +572,15 @@ WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f)
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
gl->ReadPixelsIntoImageSurface(0, 0, mWidth, mHeight, surf);
|
||||
gfxUtils::PremultiplyImageSurface(surf);
|
||||
|
||||
bool srcPremultAlpha = mOptions.premultipliedAlpha;
|
||||
bool dstPremultAlpha = aFlags & RenderFlagPremultAlpha;
|
||||
|
||||
if (!srcPremultAlpha && dstPremultAlpha) {
|
||||
gfxUtils::PremultiplyImageSurface(surf);
|
||||
} else if (srcPremultAlpha && !dstPremultAlpha) {
|
||||
gfxUtils::UnpremultiplyImageSurface(surf);
|
||||
}
|
||||
|
||||
nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
|
||||
pat->SetFilter(f);
|
||||
|
@ -608,7 +616,8 @@ WebGLContext::GetInputStream(const char* aMimeType,
|
|||
|
||||
nsRefPtr<gfxContext> tmpcx = new gfxContext(surf);
|
||||
// Use Render() to make sure that appropriate y-flip gets applied
|
||||
nsresult rv = Render(tmpcx, gfxPattern::FILTER_NEAREST);
|
||||
PRUint32 flags = mOptions.premultipliedAlpha ? RenderFlagPremultAlpha : 0;
|
||||
nsresult rv = Render(tmpcx, gfxPattern::FILTER_NEAREST, flags);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -625,11 +634,22 @@ WebGLContext::GetInputStream(const char* aMimeType,
|
|||
if (!encoder)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
int format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
|
||||
if (!mOptions.premultipliedAlpha) {
|
||||
// We need to convert to INPUT_FORMAT_RGBA, otherwise
|
||||
// we are automatically considered premult, and unpremult'd.
|
||||
// Yes, it is THAT silly.
|
||||
// Except for different lossy conversions by color,
|
||||
// we could probably just change the label, and not change the data.
|
||||
gfxUtils::ConvertBGRAtoRGBA(surf);
|
||||
format = imgIEncoder::INPUT_FORMAT_RGBA;
|
||||
}
|
||||
|
||||
rv = encoder->InitFromData(surf->Data(),
|
||||
mWidth * mHeight * 4,
|
||||
mWidth, mHeight,
|
||||
surf->Stride(),
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
format,
|
||||
nsDependentString(aEncoderOptions));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -542,7 +542,9 @@ public:
|
|||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
NS_IMETHOD Reset()
|
||||
{ /* (InitializeWithSurface) */ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter f);
|
||||
NS_IMETHOD Render(gfxContext *ctx,
|
||||
gfxPattern::GraphicsFilter f,
|
||||
PRUint32 aFlags = RenderFlagPremultAlpha);
|
||||
NS_IMETHOD GetInputStream(const char* aMimeType,
|
||||
const PRUnichar* aEncoderOptions,
|
||||
nsIInputStream **aStream);
|
||||
|
|
|
@ -351,7 +351,9 @@ public:
|
|||
void Initialize(nsIDocShell *shell, PRInt32 width, PRInt32 height);
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
|
||||
bool EnsureSurface();
|
||||
NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter);
|
||||
NS_IMETHOD Render(gfxContext *ctx,
|
||||
gfxPattern::GraphicsFilter aFilter,
|
||||
PRUint32 aFlags = RenderFlagPremultAlpha);
|
||||
NS_IMETHOD GetInputStream(const char* aMimeType,
|
||||
const PRUnichar* aEncoderOptions,
|
||||
nsIInputStream **aStream);
|
||||
|
@ -1278,7 +1280,7 @@ nsCanvasRenderingContext2D::SetIsIPC(bool isIPC)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter)
|
||||
nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter, PRUint32 aFlags)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -1303,6 +1305,14 @@ nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter a
|
|||
if (mOpaque)
|
||||
ctx->SetOperator(op);
|
||||
|
||||
if (!(aFlags & RenderFlagPremultAlpha)) {
|
||||
nsRefPtr<gfxASurface> curSurface = ctx->CurrentSurface();
|
||||
nsRefPtr<gfxImageSurface> gis = curSurface->GetAsImageSurface();
|
||||
NS_ABORT_IF_FALSE(gis, "If non-premult alpha, must be able to get image surface!");
|
||||
|
||||
gfxUtils::UnpremultiplyImageSurface(gis);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -406,7 +406,9 @@ public:
|
|||
NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
NS_IMETHOD Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter);
|
||||
NS_IMETHOD Render(gfxContext *ctx,
|
||||
gfxPattern::GraphicsFilter aFilter,
|
||||
PRUint32 aFlags = RenderFlagPremultAlpha);
|
||||
NS_IMETHOD GetInputStream(const char* aMimeType,
|
||||
const PRUnichar* aEncoderOptions,
|
||||
nsIInputStream **aStream);
|
||||
|
@ -1382,7 +1384,7 @@ nsCanvasRenderingContext2DAzure::SetIsIPC(bool isIPC)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCanvasRenderingContext2DAzure::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter)
|
||||
nsCanvasRenderingContext2DAzure::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter, PRUint32 aFlags)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -1414,6 +1416,14 @@ nsCanvasRenderingContext2DAzure::Render(gfxContext *ctx, gfxPattern::GraphicsFil
|
|||
if (mOpaque)
|
||||
ctx->SetOperator(op);
|
||||
|
||||
if (!(aFlags & RenderFlagPremultAlpha)) {
|
||||
nsRefPtr<gfxASurface> curSurface = ctx->CurrentSurface();
|
||||
nsRefPtr<gfxImageSurface> gis = curSurface->GetAsImageSurface();
|
||||
NS_ABORT_IF_FALSE(gis, "If non-premult alpha, must be able to get image surface!");
|
||||
|
||||
gfxUtils::UnpremultiplyImageSurface(gis);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
conformance/context/premultiplyalpha-test.html
|
||||
conformance/misc/uninitialized-test.html
|
||||
conformance/programs/gl-get-active-attribute.html
|
||||
conformance/textures/texture-mips.html
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
conformance/context/premultiplyalpha-test.html
|
||||
conformance/glsl/misc/glsl-function-nodes.html
|
||||
conformance/more/conformance/quickCheckAPI-S_V.html
|
||||
conformance/programs/program-test.html
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
conformance/context/premultiplyalpha-test.html
|
||||
conformance/glsl/functions/glsl-function-atan.html
|
||||
conformance/glsl/functions/glsl-function-atan-xy.html
|
||||
conformance/more/conformance/quickCheckAPI-S_V.html
|
||||
|
|
|
@ -142,7 +142,9 @@ public:
|
|||
* nsICanvasElementExternal -- for use outside of content/layout
|
||||
*/
|
||||
NS_IMETHOD_(nsIntSize) GetSizeExternal();
|
||||
NS_IMETHOD RenderContextsExternal(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter);
|
||||
NS_IMETHOD RenderContextsExternal(gfxContext *aContext,
|
||||
gfxPattern::GraphicsFilter aFilter,
|
||||
PRUint32 aFlags = RenderFlagPremultAlpha);
|
||||
|
||||
virtual bool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
|
|
|
@ -794,12 +794,12 @@ nsHTMLCanvasElement::GetSizeExternal()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasElement::RenderContextsExternal(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter)
|
||||
nsHTMLCanvasElement::RenderContextsExternal(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, PRUint32 aFlags)
|
||||
{
|
||||
if (!mCurrentContext)
|
||||
return NS_OK;
|
||||
|
||||
return mCurrentContext->Render(aContext, aFilter);
|
||||
return mCurrentContext->Render(aContext, aFilter, aFlags);
|
||||
}
|
||||
|
||||
nsresult NS_NewCanvasRenderingContext2DThebes(nsIDOMCanvasRenderingContext2D** aResult);
|
||||
|
|
|
@ -184,6 +184,8 @@ struct THEBES_API gfxRGBA {
|
|||
* The color value is interpreted based on colorType;
|
||||
* all values use the native platform endianness.
|
||||
*
|
||||
* Resulting gfxRGBA stores non-premultiplied data.
|
||||
*
|
||||
* @see gfxRGBA::Packed
|
||||
*/
|
||||
gfxRGBA(PRUint32 c, PackedColorType colorType = PACKED_ABGR) {
|
||||
|
|
|
@ -210,6 +210,51 @@ gfxUtils::UnpremultiplyImageSurface(gfxImageSurface *aSourceSurface,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxUtils::ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface,
|
||||
gfxImageSurface *aDestSurface) {
|
||||
if (!aDestSurface)
|
||||
aDestSurface = aSourceSurface;
|
||||
|
||||
NS_ABORT_IF_FALSE(aSourceSurface->Format() == aDestSurface->Format() &&
|
||||
aSourceSurface->Width() == aDestSurface->Width() &&
|
||||
aSourceSurface->Height() == aDestSurface->Height() &&
|
||||
aSourceSurface->Stride() == aDestSurface->Stride(),
|
||||
"Source and destination surfaces don't have identical characteristics");
|
||||
|
||||
NS_ABORT_IF_FALSE(aSourceSurface->Stride() == aSourceSurface->Width() * 4,
|
||||
"Source surface stride isn't tightly packed");
|
||||
|
||||
NS_ABORT_IF_FALSE(aSourceSurface->Format() == gfxASurface::ImageFormatARGB32,
|
||||
"Surfaces must be ARGB32");
|
||||
|
||||
PRUint8 *src = aSourceSurface->Data();
|
||||
PRUint8 *dst = aDestSurface->Data();
|
||||
|
||||
PRUint32 dim = aSourceSurface->Width() * aSourceSurface->Height();
|
||||
PRUint8 *srcEnd = src + 4*dim;
|
||||
|
||||
if (src == dst) {
|
||||
PRUint8 buffer[4];
|
||||
for (; src != srcEnd; src += 4) {
|
||||
buffer[0] = src[2];
|
||||
buffer[1] = src[1];
|
||||
buffer[2] = src[0];
|
||||
|
||||
src[0] = buffer[0];
|
||||
src[1] = buffer[1];
|
||||
src[2] = buffer[2];
|
||||
}
|
||||
} else {
|
||||
for (; src != srcEnd; src += 4, dst += 4) {
|
||||
dst[0] = src[2];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[0];
|
||||
dst[3] = src[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
IsSafeImageTransformComponent(gfxFloat aValue)
|
||||
{
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
static void UnpremultiplyImageSurface(gfxImageSurface *aSurface,
|
||||
gfxImageSurface *aDestSurface = nsnull);
|
||||
|
||||
static void ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface,
|
||||
gfxImageSurface *aDestSurface = nsnull);
|
||||
|
||||
/**
|
||||
* Draw something drawable while working around limitations like bad support
|
||||
* for EXTEND_PAD, lack of source-clipping, or cairo / pixman bugs with
|
||||
|
|
|
@ -209,6 +209,9 @@ void nsPNGDecoder::EndImageFrame()
|
|||
if (mFrameHasNoAlpha)
|
||||
mImage.SetFrameHasNoAlpha(numFrames - 1);
|
||||
|
||||
// PNG is always non-premult
|
||||
mImage.SetFrameAsNonPremult(numFrames - 1, true);
|
||||
|
||||
PostInvalidation(mFrameRect);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -300,6 +300,13 @@ Decoder::PostDecodeDone()
|
|||
NS_ABORT_IF_FALSE(!mDecodeDone, "Decode already done!");
|
||||
mDecodeDone = true;
|
||||
|
||||
// Set premult before DecodingComplete(), since DecodingComplete() calls Optimize()
|
||||
int frames = GetFrameCount();
|
||||
bool isNonPremult = GetDecodeFlags() & DECODER_NO_PREMULTIPLY_ALPHA;
|
||||
for (int i = 0; i < frames; i++) {
|
||||
mImage.SetFrameAsNonPremult(i, isNonPremult);
|
||||
}
|
||||
|
||||
// Notify
|
||||
mImage.DecodingComplete();
|
||||
if (mObserver) {
|
||||
|
|
|
@ -150,8 +150,8 @@ public:
|
|||
// SetDecodeFlags must be called before Init(), otherwise
|
||||
// default flags are assumed.
|
||||
enum {
|
||||
DECODER_NO_PREMULTIPLY_ALPHA = 0x2,
|
||||
DECODER_NO_COLORSPACE_CONVERSION = 0x4
|
||||
DECODER_NO_PREMULTIPLY_ALPHA = 0x2, // imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA
|
||||
DECODER_NO_COLORSPACE_CONVERSION = 0x4 // imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION
|
||||
};
|
||||
void SetDecodeFlags(PRUint32 aFlags) { mDecodeFlags = aFlags; }
|
||||
PRUint32 GetDecodeFlags() { return mDecodeFlags; }
|
||||
|
|
|
@ -1324,6 +1324,25 @@ RasterImage::SetFrameHasNoAlpha(PRUint32 aFrameNum)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::SetFrameAsNonPremult(PRUint32 aFrameNum, bool aIsNonPremult)
|
||||
{
|
||||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ABORT_IF_FALSE(aFrameNum < mFrames.Length(), "Invalid frame index!");
|
||||
if (aFrameNum >= mFrames.Length())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
imgFrame* frame = GetImgFrame(aFrameNum);
|
||||
NS_ABORT_IF_FALSE(frame, "Calling SetFrameAsNonPremult on frame that doesn't exist!");
|
||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
||||
|
||||
frame->SetAsNonPremult(aIsNonPremult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
RasterImage::DecodingComplete()
|
||||
{
|
||||
|
|
|
@ -244,6 +244,7 @@ public:
|
|||
nsresult SetFrameTimeout(PRUint32 aFrameNum, PRInt32 aTimeout);
|
||||
nsresult SetFrameBlendMethod(PRUint32 aFrameNum, PRInt32 aBlendMethod);
|
||||
nsresult SetFrameHasNoAlpha(PRUint32 aFrameNum);
|
||||
nsresult SetFrameAsNonPremult(PRUint32 aFrameNum, bool aIsNonPremult);
|
||||
|
||||
/**
|
||||
* Sets the size of the container. This should only be called by the
|
||||
|
|
|
@ -145,12 +145,13 @@ imgFrame::imgFrame() :
|
|||
mSinglePixel(false),
|
||||
mNeverUseDeviceSurface(false),
|
||||
mFormatChanged(false),
|
||||
mCompositingFailed(false)
|
||||
mCompositingFailed(false),
|
||||
mNonPremult(false),
|
||||
#ifdef USE_WIN_SURFACE
|
||||
, mIsDDBSurface(false)
|
||||
mIsDDBSurface(false),
|
||||
#endif
|
||||
, mLocked(false)
|
||||
, mInformedDiscardTracker(false)
|
||||
mLocked(false),
|
||||
mInformedDiscardTracker(false)
|
||||
{
|
||||
static bool hasCheckedOptimize = false;
|
||||
if (!hasCheckedOptimize) {
|
||||
|
@ -254,6 +255,11 @@ nsresult imgFrame::Optimize()
|
|||
if (mPalettedImageData || mOptSurface || mSinglePixel)
|
||||
return NS_OK;
|
||||
|
||||
// Don't do single-color opts on non-premult data.
|
||||
// Cairo doesn't support non-premult single-colors.
|
||||
if (mNonPremult)
|
||||
return NS_OK;
|
||||
|
||||
/* Figure out if the entire image is a constant color */
|
||||
|
||||
// this should always be true
|
||||
|
@ -270,11 +276,12 @@ nsresult imgFrame::Optimize()
|
|||
if (mFormat == gfxASurface::ImageFormatARGB32 ||
|
||||
mFormat == gfxASurface::ImageFormatRGB24)
|
||||
{
|
||||
mSinglePixelColor = gfxRGBA
|
||||
(firstPixel,
|
||||
(mFormat == gfxImageSurface::ImageFormatRGB24 ?
|
||||
gfxRGBA::PACKED_XRGB :
|
||||
gfxRGBA::PACKED_ARGB_PREMULTIPLIED));
|
||||
// Should already be premult if desired.
|
||||
gfxRGBA::PackedColorType inputType = gfxRGBA::PACKED_XRGB;
|
||||
if (mFormat == gfxASurface::ImageFormatARGB32)
|
||||
inputType = gfxRGBA::PACKED_ARGB_PREMULTIPLIED;
|
||||
|
||||
mSinglePixelColor = gfxRGBA(firstPixel, inputType);
|
||||
|
||||
mSinglePixel = true;
|
||||
|
||||
|
@ -434,6 +441,7 @@ imgFrame::SurfaceForDrawing(bool aDoPadding,
|
|||
}
|
||||
tmpCtx.Rectangle(available);
|
||||
tmpCtx.Fill();
|
||||
|
||||
return SurfaceWithFormat(new gfxSurfaceDrawable(surface, size), format);
|
||||
}
|
||||
|
||||
|
@ -517,6 +525,8 @@ nsresult imgFrame::Extract(const nsIntRect& aRegion, imgFrame** aResult)
|
|||
mFormat, mPaletteDepth);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
subImage->SetAsNonPremult(mNonPremult);
|
||||
|
||||
// scope to destroy ctx
|
||||
{
|
||||
gfxContext ctx(subImage->ThebesSurface());
|
||||
|
@ -772,6 +782,11 @@ void imgFrame::SetHasNoAlpha()
|
|||
}
|
||||
}
|
||||
|
||||
void imgFrame::SetAsNonPremult(bool aIsNonPremult)
|
||||
{
|
||||
mNonPremult = aIsNonPremult;
|
||||
}
|
||||
|
||||
bool imgFrame::GetCompositingFailed() const
|
||||
{
|
||||
return mCompositingFailed;
|
||||
|
|
|
@ -92,6 +92,7 @@ public:
|
|||
bool ImageComplete() const;
|
||||
|
||||
void SetHasNoAlpha();
|
||||
void SetAsNonPremult(bool aIsNonPremult);
|
||||
|
||||
bool GetCompositingFailed() const;
|
||||
void SetCompositingFailed(bool val);
|
||||
|
@ -180,6 +181,7 @@ private: // data
|
|||
// Total length is PaletteDataLength() + GetImageDataLength().
|
||||
PRUint8* mPalettedImageData;
|
||||
|
||||
// Note that the data stored in gfxRGBA is *non-alpha-premultiplied*.
|
||||
gfxRGBA mSinglePixelColor;
|
||||
|
||||
PRInt32 mTimeout; // -1 means display forever
|
||||
|
@ -192,6 +194,7 @@ private: // data
|
|||
bool mNeverUseDeviceSurface;
|
||||
bool mFormatChanged;
|
||||
bool mCompositingFailed;
|
||||
bool mNonPremult;
|
||||
/** Indicates if the image data is currently locked */
|
||||
bool mLocked;
|
||||
|
||||
|
|
|
@ -4050,8 +4050,9 @@ nsLayoutUtils::SurfaceFromElement(dom::Element* aElement,
|
|||
|
||||
bool forceCopy = (aSurfaceFlags & SFE_WANT_NEW_SURFACE) != 0;
|
||||
bool wantImageSurface = (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) != 0;
|
||||
bool premultAlpha = (aSurfaceFlags & SFE_NO_PREMULTIPLY_ALPHA) == 0;
|
||||
|
||||
if (aSurfaceFlags & SFE_NO_PREMULTIPLY_ALPHA) {
|
||||
if (!premultAlpha) {
|
||||
forceCopy = true;
|
||||
wantImageSurface = true;
|
||||
}
|
||||
|
@ -4082,7 +4083,8 @@ nsLayoutUtils::SurfaceFromElement(dom::Element* aElement,
|
|||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||
// XXX shouldn't use the external interface, but maybe we can layerify this
|
||||
rv = canvas->RenderContextsExternal(ctx, gfxPattern::FILTER_NEAREST);
|
||||
PRUint32 flags = premultAlpha ? nsHTMLCanvasElement::RenderFlagPremultAlpha : 0;
|
||||
rv = canvas->RenderContextsExternal(ctx, gfxPattern::FILTER_NEAREST, flags);
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
}
|
||||
|
@ -4091,12 +4093,6 @@ nsLayoutUtils::SurfaceFromElement(dom::Element* aElement,
|
|||
// in case this is being used by -moz-element()
|
||||
canvas->MarkContextClean();
|
||||
|
||||
if (aSurfaceFlags & SFE_NO_PREMULTIPLY_ALPHA) {
|
||||
// we can modify this surface since we force a copy above when
|
||||
// when NO_PREMULTIPLY_ALPHA is set
|
||||
gfxUtils::UnpremultiplyImageSurface(static_cast<gfxImageSurface*>(surf.get()));
|
||||
}
|
||||
|
||||
result.mSurface = surf;
|
||||
result.mSize = size;
|
||||
result.mPrincipal = aElement->NodePrincipal();
|
||||
|
|
Загрузка…
Ссылка в новой задаче