Bug 1187386 (Part 2) - Rework decoder code to avoid calling Decode::GetImage(). r=tn

This commit is contained in:
Seth Fowler 2015-07-31 07:29:03 -07:00
parent d5de49efd5
commit a1c94fd9c5
11 changed files with 91 additions and 46 deletions

View File

@ -127,6 +127,22 @@ public:
return NS_ERROR_NOT_AVAILABLE;
}
/**
* Set the requested sample size for this decoder. Used to implement the
* -moz-sample-size media fragment.
*
* XXX(seth): Support for -moz-sample-size will be removed in bug 1120056.
*/
virtual void SetSampleSize(int aSampleSize) { }
/**
* Set the requested resolution for this decoder. Used to implement the
* -moz-resolution media fragment.
*
* XXX(seth): Support for -moz-resolution will be removed in bug 1118926.
*/
virtual void SetResolution(const gfx::IntSize& aResolution) { }
/**
* Set whether should send partial invalidations.
*

View File

@ -110,6 +110,8 @@ DecoderFactory::CreateDecoder(DecoderType aType,
SourceBuffer* aSourceBuffer,
const Maybe<IntSize>& aTargetSize,
uint32_t aFlags,
int aSampleSize,
const IntSize& aResolution,
bool aIsRedecode,
bool aImageIsTransient,
bool aImageIsLocked)
@ -125,6 +127,8 @@ DecoderFactory::CreateDecoder(DecoderType aType,
decoder->SetMetadataDecode(false);
decoder->SetIterator(aSourceBuffer->Iterator());
decoder->SetFlags(aFlags);
decoder->SetSampleSize(aSampleSize);
decoder->SetResolution(aResolution);
decoder->SetSendPartialInvalidations(!aIsRedecode);
decoder->SetImageIsTransient(aImageIsTransient);
@ -151,7 +155,9 @@ DecoderFactory::CreateDecoder(DecoderType aType,
/* static */ already_AddRefed<Decoder>
DecoderFactory::CreateMetadataDecoder(DecoderType aType,
RasterImage* aImage,
SourceBuffer* aSourceBuffer)
SourceBuffer* aSourceBuffer,
int aSampleSize,
const IntSize& aResolution)
{
if (aType == DecoderType::UNKNOWN) {
return nullptr;
@ -164,6 +170,8 @@ DecoderFactory::CreateMetadataDecoder(DecoderType aType,
// Initialize the decoder.
decoder->SetMetadataDecode(true);
decoder->SetIterator(aSourceBuffer->Iterator());
decoder->SetSampleSize(aSampleSize);
decoder->SetResolution(aResolution);
decoder->Init();
if (NS_FAILED(decoder->GetDecoderError())) {

View File

@ -56,6 +56,10 @@ public:
* downscale-during-decode.
* @param aFlags Flags specifying what type of output the decoder should
* produce; see GetDecodeFlags() in RasterImage.h.
* @param aSampleSize The sample size requested using #-moz-samplesize (or 0
* if none).
* @param aResolution The resolution requested using #-moz-resolution (or an
* empty rect if none).
* @param aIsRedecode Specify 'true' if this image has been decoded before.
* @param aImageIsTransient Specify 'true' if this image is transient.
* @param aImageIsLocked Specify 'true' if this image is locked for the
@ -68,6 +72,8 @@ public:
SourceBuffer* aSourceBuffer,
const Maybe<gfx::IntSize>& aTargetSize,
uint32_t aFlags,
int aSampleSize,
const gfx::IntSize& aResolution,
bool aIsRedecode,
bool aImageIsTransient,
bool aImageIsLocked);
@ -83,11 +89,17 @@ public:
* notifications as decoding progresses.
* @param aSourceBuffer The SourceBuffer which the decoder will read its data
* from.
* @param aSampleSize The sample size requested using #-moz-samplesize (or 0
* if none).
* @param aResolution The resolution requested using #-moz-resolution (or an
* empty rect if none).
*/
static already_AddRefed<Decoder>
CreateMetadataDecoder(DecoderType aType,
RasterImage* aImage,
SourceBuffer* aSourceBuffer);
SourceBuffer* aSourceBuffer,
int aSampleSize,
const gfx::IntSize& aResolution);
private:
virtual ~DecoderFactory() = 0;

View File

@ -221,6 +221,29 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
aProgressTracker->SetImage(newImage);
newImage->SetProgressTracker(aProgressTracker);
nsAutoCString ref;
aURI->GetRef(ref);
net::nsMediaFragmentURIParser parser(ref);
if (parser.HasResolution()) {
newImage->SetRequestedResolution(parser.GetResolution());
}
if (parser.HasSampleSize()) {
/* Get our principal */
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
nsCOMPtr<nsIPrincipal> principal;
if (chan) {
nsContentUtils::GetSecurityManager()
->GetChannelResultPrincipal(chan, getter_AddRefs(principal));
}
if ((principal &&
principal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED) ||
gfxPrefs::ImageMozSampleSizeEnabled()) {
newImage->SetRequestedSampleSize(parser.GetSampleSize());
}
}
rv = newImage->Init(aMimeType.get(), aImageFlags);
NS_ENSURE_SUCCESS(rv, BadImage(newImage));
@ -245,29 +268,6 @@ ImageFactory::CreateRasterImage(nsIRequest* aRequest,
}
}
nsAutoCString ref;
aURI->GetRef(ref);
net::nsMediaFragmentURIParser parser(ref);
if (parser.HasResolution()) {
newImage->SetRequestedResolution(parser.GetResolution());
}
if (parser.HasSampleSize()) {
/* Get our principal */
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
nsCOMPtr<nsIPrincipal> principal;
if (chan) {
nsContentUtils::GetSecurityManager()
->GetChannelResultPrincipal(chan, getter_AddRefs(principal));
}
if ((principal &&
principal->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED) ||
gfxPrefs::ImageMozSampleSizeEnabled()) {
newImage->SetRequestedSampleSize(parser.GetSampleSize());
}
}
return newImage.forget();
}

View File

@ -1445,8 +1445,8 @@ RasterImage::Decode(const IntSize& aSize, uint32_t aFlags)
// Create a decoder.
nsRefPtr<Decoder> decoder =
DecoderFactory::CreateDecoder(mDecoderType, this, mSourceBuffer, targetSize,
aFlags, mHasBeenDecoded, mTransient,
imageIsLocked);
aFlags, mRequestedSampleSize, mRequestedResolution,
mHasBeenDecoded, mTransient, imageIsLocked);
// Make sure DecoderFactory was able to create a decoder successfully.
if (!decoder) {
@ -1499,7 +1499,9 @@ RasterImage::DecodeMetadata(uint32_t aFlags)
// Create a decoder.
nsRefPtr<Decoder> decoder =
DecoderFactory::CreateMetadataDecoder(mDecoderType, this, mSourceBuffer);
DecoderFactory::CreateMetadataDecoder(mDecoderType, this, mSourceBuffer,
mRequestedSampleSize,
mRequestedResolution);
// Make sure DecoderFactory was able to create a decoder successfully.
if (!decoder) {

View File

@ -269,18 +269,11 @@ public:
mRequestedResolution = requestedResolution;
}
nsIntSize GetRequestedResolution() {
return mRequestedResolution;
}
/* Provide a hint for the requested dimension of the resulting image. */
void SetRequestedSampleSize(int requestedSampleSize) {
mRequestedSampleSize = requestedSampleSize;
}
int GetRequestedSampleSize() {
return mRequestedSampleSize;
}
nsCString GetURIString() {
nsCString spec;
if (GetURI()) {

View File

@ -266,9 +266,10 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
}
uint16_t colorDepth = 0;
nsIntSize prefSize = mImage->GetRequestedResolution();
if (prefSize.width == 0 && prefSize.height == 0) {
prefSize.SizeTo(PREFICONSIZE, PREFICONSIZE);
// If we didn't get a #-moz-resolution, default to PREFICONSIZE.
if (mResolution.width == 0 && mResolution.height == 0) {
mResolution.SizeTo(PREFICONSIZE, PREFICONSIZE);
}
// A measure of the difference in size between the entry we've found
@ -306,8 +307,8 @@ nsICODecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
// Calculate the delta between this image's size and the desired size,
// so we can see if it is better than our current-best option.
// In the case of several equally-good images, we use the last one.
int32_t delta = (e.mWidth == 0 ? 256 : e.mWidth) - prefSize.width +
(e.mHeight == 0 ? 256 : e.mHeight) - prefSize.height;
int32_t delta = (e.mWidth == 0 ? 256 : e.mWidth) - mResolution.width +
(e.mHeight == 0 ? 256 : e.mHeight) - mResolution.height;
if (e.mBitCount >= colorDepth &&
((diff < 0 && delta >= diff) || (delta >= 0 && delta <= diff))) {
diff = delta;

View File

@ -36,6 +36,11 @@ public:
return mDirEntry.mHeight == 0 ? 256 : mDirEntry.mHeight;
}
virtual void SetResolution(const gfx::IntSize& aResolution) override
{
mResolution = aResolution;
}
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
virtual void FinishInternal() override;
virtual void FinishWithErrorInternal() override;
@ -76,6 +81,7 @@ private:
// Obtains the number of colors from the BPP, mBPP must be filled in
uint16_t GetNumColors();
gfx::IntSize mResolution; // The requested -moz-resolution for this icon.
uint16_t mBPP; // Stores the images BPP
uint32_t mPos; // Keeps track of the position we have decoded up until
uint16_t mNumIcons; // Stores the number of icons in the ICO file

View File

@ -84,6 +84,7 @@ nsJPEGDecoder::nsJPEGDecoder(RasterImage* aImage,
Decoder::DecodeStyle aDecodeStyle)
: Decoder(aImage)
, mDecodeStyle(aDecodeStyle)
, mSampleSize(0)
{
mState = JPEG_HEADER;
mReading = true;
@ -248,10 +249,10 @@ nsJPEGDecoder::WriteInternal(const char* aBuffer, uint32_t aCount)
return; // I/O suspension
}
int sampleSize = GetImage()->GetRequestedSampleSize();
if (sampleSize > 0) {
// If we have a sample size specified for -moz-sample-size, use it.
if (mSampleSize > 0) {
mInfo.scale_num = 1;
mInfo.scale_denom = sampleSize;
mInfo.scale_denom = mSampleSize;
}
// Used to set up image size so arrays can be allocated

View File

@ -57,6 +57,11 @@ public:
virtual nsresult SetTargetSize(const nsIntSize& aSize) override;
virtual void SetSampleSize(int aSampleSize) override
{
mSampleSize = aSampleSize;
}
virtual void InitInternal() override;
virtual void WriteInternal(const char* aBuffer, uint32_t aCount) override;
virtual void FinishInternal() override;
@ -103,6 +108,8 @@ public:
const Decoder::DecodeStyle mDecodeStyle;
uint32_t mCMSMode;
int mSampleSize;
};
} // namespace image

View File

@ -176,9 +176,8 @@ nsPNGDecoder::CreateFrame(png_uint_32 aXOffset, png_uint_32 aYOffset,
MOZ_LOG(GetPNGDecoderAccountingLog(), LogLevel::Debug,
("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created "
"image frame with %dx%d pixels in container %p",
aWidth, aHeight,
GetImage()));
"image frame with %dx%d pixels for decoder %p",
aWidth, aHeight, this));
#ifdef PNG_APNG_SUPPORTED
if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL)) {