mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
b=622184; implement webgl colour conversion/premultiplication semantics; r=joe, a=b
This commit is contained in:
parent
ba2c53afe2
commit
44d1f1a0b6
@ -3198,9 +3198,17 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
|
||||
{
|
||||
gfxImageSurface *surf = nsnull;
|
||||
|
||||
PRUint32 flags =
|
||||
nsLayoutUtils::SFE_WANT_NEW_SURFACE |
|
||||
nsLayoutUtils::SFE_WANT_IMAGE_SURFACE;
|
||||
|
||||
if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE)
|
||||
flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
|
||||
if (!mPixelStorePremultiplyAlpha)
|
||||
flags |= nsLayoutUtils::SFE_NO_PREMULTIPLY_ALPHA;
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(imageOrCanvas,
|
||||
nsLayoutUtils::SFE_WANT_NEW_SURFACE | nsLayoutUtils::SFE_WANT_IMAGE_SURFACE);
|
||||
nsLayoutUtils::SurfaceFromElement(imageOrCanvas, flags);
|
||||
if (!res.mSurface)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
@ -4011,7 +4019,7 @@ WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum interna
|
||||
isurf->Width(), isurf->Height(), isurf->Stride(), 0,
|
||||
format, type,
|
||||
isurf->Data(), byteLength,
|
||||
srcFormat, PR_TRUE);
|
||||
srcFormat, mPixelStorePremultiplyAlpha);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -148,6 +148,13 @@
|
||||
(GFX_PREMULTIPLY(g,a) << 8) | \
|
||||
(GFX_PREMULTIPLY(b,a))
|
||||
|
||||
/**
|
||||
* Macro to pack the 4 8-bit channels (A,R,G,B)
|
||||
* into a 32-bit packed NON-premultiplied pixel.
|
||||
*/
|
||||
#define GFX_PACKED_PIXEL_NO_PREMULTIPLY(a,r,g,b) \
|
||||
(((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
|
||||
|
||||
|
||||
/**
|
||||
* A color value, storing red, green, blue and alpha components.
|
||||
|
@ -3567,6 +3567,11 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
|
||||
PRBool forceCopy = (aSurfaceFlags & SFE_WANT_NEW_SURFACE) != 0;
|
||||
PRBool wantImageSurface = (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) != 0;
|
||||
|
||||
if (aSurfaceFlags & SFE_NO_PREMULTIPLY_ALPHA) {
|
||||
forceCopy = PR_TRUE;
|
||||
wantImageSurface = PR_TRUE;
|
||||
}
|
||||
|
||||
// If it's a <canvas>, we may be able to just grab its internal surface
|
||||
nsCOMPtr<nsIDOMHTMLCanvasElement> domCanvas = do_QueryInterface(aElement);
|
||||
if (node && domCanvas) {
|
||||
@ -3601,6 +3606,12 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
|
||||
return result;
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = node->NodePrincipal();
|
||||
|
||||
result.mSurface = surf;
|
||||
@ -3714,9 +3725,14 @@ nsLayoutUtils::SurfaceFromElement(nsIDOMElement *aElement,
|
||||
PRUint32 whichFrame = (aSurfaceFlags & SFE_WANT_FIRST_FRAME)
|
||||
? (PRUint32) imgIContainer::FRAME_FIRST
|
||||
: (PRUint32) imgIContainer::FRAME_CURRENT;
|
||||
PRUint32 frameFlags = imgIContainer::FLAG_SYNC_DECODE;
|
||||
if (aSurfaceFlags & SFE_NO_COLORSPACE_CONVERSION)
|
||||
frameFlags |= imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION;
|
||||
if (aSurfaceFlags & SFE_NO_PREMULTIPLY_ALPHA)
|
||||
frameFlags |= imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
|
||||
nsRefPtr<gfxASurface> framesurf;
|
||||
rv = imgContainer->GetFrame(whichFrame,
|
||||
imgIContainer::FLAG_SYNC_DECODE,
|
||||
frameFlags,
|
||||
getter_AddRefs(framesurf));
|
||||
if (NS_FAILED(rv))
|
||||
return result;
|
||||
|
@ -1209,7 +1209,13 @@ public:
|
||||
SFE_WANT_IMAGE_SURFACE = 1 << 1,
|
||||
/* Whether to extract the first frame (as opposed to the
|
||||
current frame) in the case that the element is an image. */
|
||||
SFE_WANT_FIRST_FRAME = 1 << 2
|
||||
SFE_WANT_FIRST_FRAME = 1 << 2,
|
||||
/* Whether we should skip colorspace/gamma conversion */
|
||||
SFE_NO_COLORSPACE_CONVERSION = 1 << 3,
|
||||
/* Whether we should skip premultiplication -- the resulting
|
||||
image will always be an image surface, and must not be given to
|
||||
Thebes for compositing! */
|
||||
SFE_NO_PREMULTIPLY_ALPHA = 1 << 4
|
||||
};
|
||||
|
||||
struct SurfaceFromElementResult {
|
||||
|
@ -115,6 +115,8 @@ nsJPEGDecoder::nsJPEGDecoder()
|
||||
mInProfile = nsnull;
|
||||
mTransform = nsnull;
|
||||
|
||||
mCMSMode = 0;
|
||||
|
||||
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
|
||||
("nsJPEGDecoder::nsJPEGDecoder: Creating JPEG decoder %p",
|
||||
this));
|
||||
@ -141,6 +143,10 @@ nsJPEGDecoder::~nsJPEGDecoder()
|
||||
void
|
||||
nsJPEGDecoder::InitInternal()
|
||||
{
|
||||
mCMSMode = gfxPlatform::GetCMSMode();
|
||||
if ((mDecodeFlags & DECODER_NO_COLORSPACE_CONVERSION) != 0)
|
||||
mCMSMode = eCMSMode_Off;
|
||||
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
mInfo.err = jpeg_std_error(&mErr.pub);
|
||||
/* mInfo.err = jpeg_std_error(&mErr.pub); */
|
||||
@ -244,9 +250,8 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
|
||||
/* We're doing a full decode. */
|
||||
JOCTET *profile;
|
||||
PRUint32 profileLength;
|
||||
eCMSMode cmsMode = gfxPlatform::GetCMSMode();
|
||||
|
||||
if ((cmsMode != eCMSMode_Off) &&
|
||||
if ((mCMSMode != eCMSMode_Off) &&
|
||||
read_icc_profile(&mInfo, &profile, &profileLength) &&
|
||||
(mInProfile = qcms_profile_from_memory(profile, profileLength)) != NULL) {
|
||||
free(profile);
|
||||
@ -412,7 +417,7 @@ nsJPEGDecoder::WriteInternal(const char *aBuffer, PRUint32 aCount)
|
||||
}
|
||||
|
||||
/* Force to use our YCbCr to Packed RGB converter when possible */
|
||||
if (!mTransform && (gfxPlatform::GetCMSMode() != eCMSMode_All) &&
|
||||
if (!mTransform && (mCMSMode != eCMSMode_All) &&
|
||||
mInfo.jpeg_color_space == JCS_YCbCr && mInfo.out_color_space == JCS_RGB) {
|
||||
/* Special case for the most common case: transform from YCbCr direct into packed ARGB */
|
||||
mInfo.out_color_components = 4; /* Packed ARGB pixels are always 4 bytes...*/
|
||||
@ -607,7 +612,7 @@ nsJPEGDecoder::OutputScanlines(PRBool* suspend)
|
||||
cmyk_convert_rgb((JSAMPROW)imageRow, mInfo.output_width);
|
||||
sampleRow += mInfo.output_width;
|
||||
}
|
||||
if (gfxPlatform::GetCMSMode() == eCMSMode_All) {
|
||||
if (mCMSMode == eCMSMode_All) {
|
||||
/* No embedded ICC profile - treat as sRGB */
|
||||
qcms_transform *transform = gfxPlatform::GetCMSRGBTransform();
|
||||
if (transform) {
|
||||
|
@ -123,6 +123,8 @@ public:
|
||||
qcms_transform *mTransform;
|
||||
|
||||
PRPackedBool mReading;
|
||||
|
||||
PRUint32 mCMSMode;
|
||||
};
|
||||
|
||||
} // namespace imagelib
|
||||
|
@ -86,7 +86,8 @@ nsPNGDecoder::nsPNGDecoder() :
|
||||
mCMSLine(nsnull), interlacebuf(nsnull),
|
||||
mInProfile(nsnull), mTransform(nsnull),
|
||||
mHeaderBuf(nsnull), mHeaderBytesRead(0),
|
||||
mChannels(0), mFrameIsHidden(PR_FALSE)
|
||||
mChannels(0), mFrameIsHidden(PR_FALSE),
|
||||
mCMSMode(0), mDisablePremultipliedAlpha(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
@ -216,6 +217,10 @@ void nsPNGDecoder::EndImageFrame()
|
||||
void
|
||||
nsPNGDecoder::InitInternal()
|
||||
{
|
||||
mCMSMode = gfxPlatform::GetCMSMode();
|
||||
if ((mDecodeFlags & DECODER_NO_COLORSPACE_CONVERSION) != 0)
|
||||
mCMSMode = eCMSMode_Off;
|
||||
mDisablePremultipliedAlpha = (mDecodeFlags & DECODER_NO_PREMULTIPLY_ALPHA) != 0;
|
||||
|
||||
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
static png_byte color_chunks[]=
|
||||
@ -264,7 +269,7 @@ nsPNGDecoder::InitInternal()
|
||||
|
||||
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
/* Ignore unused chunks */
|
||||
if (gfxPlatform::GetCMSMode() == eCMSMode_Off)
|
||||
if (mCMSMode == eCMSMode_Off)
|
||||
png_set_keep_unknown_chunks(mPNG, 1, color_chunks, 2);
|
||||
|
||||
png_set_keep_unknown_chunks(mPNG, 1, unused_chunks,
|
||||
@ -272,7 +277,7 @@ nsPNGDecoder::InitInternal()
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
|
||||
if (gfxPlatform::GetCMSMode() != eCMSMode_Off)
|
||||
if (mCMSMode != eCMSMode_Off)
|
||||
png_set_chunk_malloc_max(mPNG, 4000000L);
|
||||
#endif
|
||||
|
||||
@ -531,7 +536,7 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
qcms_data_type inType;
|
||||
PRUint32 intent = -1;
|
||||
PRUint32 pIntent;
|
||||
if (gfxPlatform::GetCMSMode() != eCMSMode_Off) {
|
||||
if (decoder->mCMSMode != eCMSMode_Off) {
|
||||
intent = gfxPlatform::GetRenderingIntent();
|
||||
decoder->mInProfile = PNGGetColorProfile(png_ptr, info_ptr,
|
||||
color_type, &inType, &pIntent);
|
||||
@ -554,9 +559,12 @@ nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
|
||||
(qcms_intent)intent);
|
||||
} else {
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
PNGDoGammaCorrection(png_ptr, info_ptr);
|
||||
|
||||
if (gfxPlatform::GetCMSMode() == eCMSMode_All) {
|
||||
// only do gamma correction if CMS isn't entirely disabled
|
||||
if (decoder->mCMSMode != eCMSMode_Off)
|
||||
PNGDoGammaCorrection(png_ptr, info_ptr);
|
||||
|
||||
if (decoder->mCMSMode == eCMSMode_All) {
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA || num_trans)
|
||||
decoder->mTransform = gfxPlatform::GetCMSRGBATransform();
|
||||
else
|
||||
@ -745,11 +753,20 @@ nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
|
||||
break;
|
||||
case gfxASurface::ImageFormatARGB32:
|
||||
{
|
||||
for (PRUint32 x=width; x>0; --x) {
|
||||
*cptr32++ = GFX_PACKED_PIXEL(line[3], line[0], line[1], line[2]);
|
||||
if (line[3] != 0xff)
|
||||
rowHasNoAlpha = PR_FALSE;
|
||||
line += 4;
|
||||
if (!decoder->mDisablePremultipliedAlpha) {
|
||||
for (PRUint32 x=width; x>0; --x) {
|
||||
*cptr32++ = GFX_PACKED_PIXEL(line[3], line[0], line[1], line[2]);
|
||||
if (line[3] != 0xff)
|
||||
rowHasNoAlpha = PR_FALSE;
|
||||
line += 4;
|
||||
}
|
||||
} else {
|
||||
for (PRUint32 x=width; x>0; --x) {
|
||||
*cptr32++ = GFX_PACKED_PIXEL_NO_PREMULTIPLY(line[3], line[0], line[1], line[2]);
|
||||
if (line[3] != 0xff)
|
||||
rowHasNoAlpha = PR_FALSE;
|
||||
line += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -92,6 +92,10 @@ public:
|
||||
PRPackedBool mFrameHasNoAlpha;
|
||||
PRPackedBool mFrameIsHidden;
|
||||
|
||||
// whether CMS or premultiplied alpha are forced off
|
||||
PRUint32 mCMSMode;
|
||||
PRPackedBool mDisablePremultipliedAlpha;
|
||||
|
||||
/*
|
||||
* libpng callbacks
|
||||
*
|
||||
|
@ -133,10 +133,19 @@ interface imgIContainer : nsISupports
|
||||
* available data before the call returns. It is an error to pass this flag
|
||||
* from a call stack that originates in a decoder (ie, from a decoder
|
||||
* observer event).
|
||||
*
|
||||
* FLAG_DECODE_NO_PREMULTIPLY_ALPHA: Do not premultiply alpha if
|
||||
* it's not already premultiplied in the image data.
|
||||
*
|
||||
* FLAG_DECODE_NO_COLORSPACE_CONVERSION: Do not do any colorspace conversion;
|
||||
* ignore any embedded profiles, and don't convert to any particular destination
|
||||
* space.
|
||||
*/
|
||||
|
||||
const long FLAG_NONE = 0x0;
|
||||
const long FLAG_SYNC_DECODE = 0x1;
|
||||
const long FLAG_DECODE_NO_PREMULTIPLY_ALPHA = 0x2;
|
||||
const long FLAG_DECODE_NO_COLORSPACE_CONVERSION = 0x4;
|
||||
|
||||
/**
|
||||
* Constants for specifying various "special" frames.
|
||||
|
@ -45,7 +45,8 @@ namespace mozilla {
|
||||
namespace imagelib {
|
||||
|
||||
Decoder::Decoder()
|
||||
: mFrameCount(0)
|
||||
: mDecodeFlags(0)
|
||||
, mFrameCount(0)
|
||||
, mFailCode(NS_OK)
|
||||
, mInitialized(false)
|
||||
, mSizeDecode(false)
|
||||
|
@ -122,6 +122,16 @@ public:
|
||||
bool HasDecoderError() { return NS_FAILED(mFailCode); };
|
||||
nsresult GetDecoderError() { return mFailCode; };
|
||||
|
||||
// flags. Keep these in sync with imgIContainer.idl.
|
||||
// SetDecodeFlags must be called before Init(), otherwise
|
||||
// default flags are assumed.
|
||||
enum {
|
||||
DECODER_NO_PREMULTIPLY_ALPHA = 0x2,
|
||||
DECODER_NO_COLORSPACE_CONVERSION = 0x4
|
||||
};
|
||||
void SetDecodeFlags(PRUint32 aFlags) { mDecodeFlags = aFlags; }
|
||||
PRUint32 GetDecodeFlags() { return mDecodeFlags; }
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
@ -166,6 +176,8 @@ protected:
|
||||
*/
|
||||
nsRefPtr<RasterImage> mImage;
|
||||
|
||||
PRUint32 mDecodeFlags;
|
||||
|
||||
private:
|
||||
nsCOMPtr<imgIDecoderObserver> mObserver;
|
||||
|
||||
|
@ -69,6 +69,10 @@
|
||||
|
||||
using namespace mozilla::imagelib;
|
||||
|
||||
// a mask for flags that will affect the decoding
|
||||
#define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION)
|
||||
#define DECODE_FLAGS_DEFAULT 0
|
||||
|
||||
/* Accounting for compressed data */
|
||||
#if defined(PR_LOGGING)
|
||||
static PRLogModuleInfo *gCompressedImageAccountingLog = PR_NewLogModule ("CompressedImageAccounting");
|
||||
@ -178,6 +182,7 @@ NS_IMPL_ISUPPORTS5(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
RasterImage::RasterImage(imgStatusTracker* aStatusTracker) :
|
||||
Image(aStatusTracker), // invoke superclass's constructor
|
||||
mSize(0,0),
|
||||
mFrameDecodeFlags(DECODE_FLAGS_DEFAULT),
|
||||
mAnim(nsnull),
|
||||
mLoopCount(-1),
|
||||
mObserver(nsnull),
|
||||
@ -340,7 +345,21 @@ RasterImage::ExtractFrame(PRUint32 aWhichFrame,
|
||||
img->SetSize(aRegion.width, aRegion.height);
|
||||
img->mDecoded = PR_TRUE; // Also, we need to mark the image as decoded
|
||||
img->mHasBeenDecoded = PR_TRUE;
|
||||
img->mFrameDecodeFlags = aFlags & DECODE_FLAGS_MASK;
|
||||
|
||||
if (img->mFrameDecodeFlags != mFrameDecodeFlags) {
|
||||
// if we can't discard, then we're screwed; we have no way
|
||||
// to re-decode. Similarly if we aren't allowed to do a sync
|
||||
// decode.
|
||||
if (!(aFlags & FLAG_SYNC_DECODE))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
ForceDiscard();
|
||||
|
||||
mFrameDecodeFlags = img->mFrameDecodeFlags;
|
||||
}
|
||||
|
||||
// If a synchronous decode was requested, do it
|
||||
if (aFlags & FLAG_SYNC_DECODE) {
|
||||
rv = SyncDecode();
|
||||
@ -590,6 +609,20 @@ RasterImage::CopyFrame(PRUint32 aWhichFrame,
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
|
||||
if (desiredDecodeFlags != mFrameDecodeFlags) {
|
||||
// if we can't discard, then we're screwed; we have no way
|
||||
// to re-decode. Similarly if we aren't allowed to do a sync
|
||||
// decode.
|
||||
if (!(aFlags & FLAG_SYNC_DECODE))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
ForceDiscard();
|
||||
|
||||
mFrameDecodeFlags = desiredDecodeFlags;
|
||||
}
|
||||
|
||||
// If requested, synchronously flush any data we have lying around to the decoder
|
||||
if (aFlags & FLAG_SYNC_DECODE) {
|
||||
rv = SyncDecode();
|
||||
@ -648,6 +681,21 @@ RasterImage::GetFrame(PRUint32 aWhichFrame,
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
|
||||
if (desiredDecodeFlags != mFrameDecodeFlags) {
|
||||
// if we can't discard, then we're screwed; we have no way
|
||||
// to re-decode. Similarly if we aren't allowed to do a sync
|
||||
// decode.
|
||||
if (!(aFlags & FLAG_SYNC_DECODE))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
if (!CanForciblyDiscard() || mDecoder || mAnim)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
ForceDiscard();
|
||||
|
||||
mFrameDecodeFlags = desiredDecodeFlags;
|
||||
}
|
||||
|
||||
// If the caller requested a synchronous decode, do it
|
||||
if (aFlags & FLAG_SYNC_DECODE) {
|
||||
rv = SyncDecode();
|
||||
@ -1996,10 +2044,10 @@ RasterImage::GetKeys(PRUint32 *count, char ***keys)
|
||||
}
|
||||
|
||||
void
|
||||
RasterImage::Discard()
|
||||
RasterImage::Discard(bool force)
|
||||
{
|
||||
// We should be ok for discard
|
||||
NS_ABORT_IF_FALSE(CanDiscard(), "Asked to discard but can't!");
|
||||
NS_ABORT_IF_FALSE(force ? CanForciblyDiscard() : CanDiscard(), "Asked to discard but can't!");
|
||||
|
||||
// We should never discard when we have an active decoder
|
||||
NS_ABORT_IF_FALSE(!mDecoder, "Asked to discard with open decoder!");
|
||||
@ -2024,6 +2072,9 @@ RasterImage::Discard()
|
||||
if (observer)
|
||||
observer->OnDiscard(nsnull);
|
||||
|
||||
if (force)
|
||||
DiscardTracker::Remove(&mDiscardTrackerNode);
|
||||
|
||||
// Log
|
||||
PR_LOG(gCompressedImageAccountingLog, PR_LOG_DEBUG,
|
||||
("CompressedImageAccounting: discarded uncompressed image "
|
||||
@ -2050,6 +2101,13 @@ RasterImage::CanDiscard() {
|
||||
mDecoded); // ...and have something to discard.
|
||||
}
|
||||
|
||||
PRBool
|
||||
RasterImage::CanForciblyDiscard() {
|
||||
return (mDiscardable && // ...Enabled at creation time...
|
||||
mHasSourceData && // ...have the source data...
|
||||
mDecoded); // ...and have something to discard.
|
||||
}
|
||||
|
||||
// Helper method to tell us whether the clock is currently running for
|
||||
// discarding this image. Mainly for assertions.
|
||||
PRBool
|
||||
@ -2110,6 +2168,7 @@ RasterImage::InitDecoder(bool aDoSizeDecode)
|
||||
// Initialize the decoder
|
||||
nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
|
||||
mDecoder->SetSizeDecode(aDoSizeDecode);
|
||||
mDecoder->SetDecodeFlags(mFrameDecodeFlags);
|
||||
mDecoder->Init(this, observer);
|
||||
CONTAINER_ENSURE_SUCCESS(mDecoder->GetDecoderError());
|
||||
|
||||
@ -2273,8 +2332,11 @@ RasterImage::RequestDecode()
|
||||
}
|
||||
|
||||
|
||||
// If we have a size decode open, interrupt it and shut it down
|
||||
if (mDecoder && mDecoder->IsSizeDecode()) {
|
||||
// If we have a size decode open, interrupt it and shut it down; or if
|
||||
// the decoder has different flags than what we need
|
||||
if (mDecoder &&
|
||||
(mDecoder->IsSizeDecode() || mDecoder->GetDecodeFlags() != mFrameDecodeFlags))
|
||||
{
|
||||
rv = ShutdownDecoder(eShutdownIntent_Interrupted);
|
||||
CONTAINER_ENSURE_SUCCESS(rv);
|
||||
}
|
||||
@ -2324,8 +2386,11 @@ RasterImage::SyncDecode()
|
||||
// disallow this type of call in the API, and check for it in API methods.
|
||||
NS_ABORT_IF_FALSE(!mInDecoder, "Yikes, forcing sync in reentrant call!");
|
||||
|
||||
// If we have a size decode open, shut it down
|
||||
if (mDecoder && mDecoder->IsSizeDecode()) {
|
||||
// If we have a size decoder open, or one with different flags than
|
||||
// what we need, shut it down
|
||||
if (mDecoder &&
|
||||
(mDecoder->IsSizeDecode() || mDecoder->GetDecodeFlags() != mFrameDecodeFlags))
|
||||
{
|
||||
rv = ShutdownDecoder(eShutdownIntent_Interrupted);
|
||||
CONTAINER_ENSURE_SUCCESS(rv);
|
||||
}
|
||||
@ -2384,8 +2449,23 @@ RasterImage::Draw(gfxContext *aContext,
|
||||
if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Illegal -- you can't draw with non-default decode flags.
|
||||
// (Disabling colorspace conversion might make sense to allow, but
|
||||
// we don't currently.)
|
||||
if ((aFlags & DECODE_FLAGS_MASK) != DECODE_FLAGS_DEFAULT)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aContext);
|
||||
|
||||
// We can only draw with the default decode flags
|
||||
if (mFrameDecodeFlags != DECODE_FLAGS_DEFAULT) {
|
||||
if (!CanForciblyDiscard())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
ForceDiscard();
|
||||
|
||||
mFrameDecodeFlags = DECODE_FLAGS_DEFAULT;
|
||||
}
|
||||
|
||||
// If a synchronous draw is requested, flush anything that might be sitting around
|
||||
if (aFlags & FLAG_SYNC_DECODE) {
|
||||
nsresult rv = SyncDecode();
|
||||
|
@ -213,7 +213,8 @@ public:
|
||||
PRUint32 GetSourceDataSize();
|
||||
|
||||
/* Triggers discarding. */
|
||||
void Discard();
|
||||
void Discard(bool force = false);
|
||||
void ForceDiscard() { Discard(/* force = */ true); }
|
||||
|
||||
/* Callbacks for decoders */
|
||||
nsresult SetFrameDisposalMethod(PRUint32 aFrameNum,
|
||||
@ -450,7 +451,17 @@ private:
|
||||
private: // data
|
||||
|
||||
nsIntSize mSize;
|
||||
|
||||
|
||||
// Whether mFrames below were decoded using any special flags.
|
||||
// Some flags (e.g. unpremultiplied data) may not be compatible
|
||||
// with the browser's needs for displaying the image to the user.
|
||||
// As such, we may need to redecode if we're being asked for
|
||||
// a frame with different flags. 0 indicates default flags.
|
||||
//
|
||||
// Valid flag bits are imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA
|
||||
// and imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION.
|
||||
PRUint32 mFrameDecodeFlags;
|
||||
|
||||
//! All the frames of the image
|
||||
// IMPORTANT: if you use mFrames in a method, call EnsureImageIsDecoded() first
|
||||
// to ensure that the frames actually exist (they may have been discarded to save
|
||||
@ -530,6 +541,7 @@ private: // data
|
||||
// Helpers
|
||||
void DoError();
|
||||
PRBool CanDiscard();
|
||||
PRBool CanForciblyDiscard();
|
||||
PRBool DiscardingActive();
|
||||
PRBool StoringSourceData();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user