mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1184996 (Part 1) - Create decoders with a DecoderFactory. r=tn
This commit is contained in:
parent
191c75a743
commit
f0851b622a
177
image/DecoderFactory.cpp
Normal file
177
image/DecoderFactory.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DecoderFactory.h"
|
||||
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "Decoder.h"
|
||||
#include "nsPNGDecoder.h"
|
||||
#include "nsGIFDecoder2.h"
|
||||
#include "nsJPEGDecoder.h"
|
||||
#include "nsBMPDecoder.h"
|
||||
#include "nsICODecoder.h"
|
||||
#include "nsIconDecoder.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
namespace image {
|
||||
|
||||
/* static */ DecoderType
|
||||
DecoderFactory::GetDecoderType(const char* aMimeType)
|
||||
{
|
||||
// By default we don't know.
|
||||
DecoderType type = DecoderType::UNKNOWN;
|
||||
|
||||
// PNG
|
||||
if (!strcmp(aMimeType, IMAGE_PNG)) {
|
||||
type = DecoderType::PNG;
|
||||
} else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
|
||||
type = DecoderType::PNG;
|
||||
|
||||
// GIF
|
||||
} else if (!strcmp(aMimeType, IMAGE_GIF)) {
|
||||
type = DecoderType::GIF;
|
||||
|
||||
// JPEG
|
||||
} else if (!strcmp(aMimeType, IMAGE_JPEG)) {
|
||||
type = DecoderType::JPEG;
|
||||
} else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
|
||||
type = DecoderType::JPEG;
|
||||
} else if (!strcmp(aMimeType, IMAGE_JPG)) {
|
||||
type = DecoderType::JPEG;
|
||||
|
||||
// BMP
|
||||
} else if (!strcmp(aMimeType, IMAGE_BMP)) {
|
||||
type = DecoderType::BMP;
|
||||
} else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
|
||||
type = DecoderType::BMP;
|
||||
|
||||
// ICO
|
||||
} else if (!strcmp(aMimeType, IMAGE_ICO)) {
|
||||
type = DecoderType::ICO;
|
||||
} else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
|
||||
type = DecoderType::ICO;
|
||||
|
||||
// Icon
|
||||
} else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
|
||||
type = DecoderType::ICON;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static already_AddRefed<Decoder>
|
||||
GetDecoder(DecoderType aType,
|
||||
RasterImage* aImage,
|
||||
bool aIsRedecode)
|
||||
{
|
||||
nsRefPtr<Decoder> decoder;
|
||||
|
||||
switch (aType) {
|
||||
case DecoderType::PNG:
|
||||
decoder = new nsPNGDecoder(aImage);
|
||||
break;
|
||||
case DecoderType::GIF:
|
||||
decoder = new nsGIFDecoder2(aImage);
|
||||
break;
|
||||
case DecoderType::JPEG:
|
||||
// If we have all the data we don't want to waste cpu time doing
|
||||
// a progressive decode.
|
||||
decoder = new nsJPEGDecoder(aImage,
|
||||
aIsRedecode ? Decoder::SEQUENTIAL
|
||||
: Decoder::PROGRESSIVE);
|
||||
break;
|
||||
case DecoderType::BMP:
|
||||
decoder = new nsBMPDecoder(aImage);
|
||||
break;
|
||||
case DecoderType::ICO:
|
||||
decoder = new nsICODecoder(aImage);
|
||||
break;
|
||||
case DecoderType::ICON:
|
||||
decoder = new nsIconDecoder(aImage);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
|
||||
}
|
||||
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Decoder>
|
||||
DecoderFactory::CreateDecoder(DecoderType aType,
|
||||
RasterImage* aImage,
|
||||
SourceBuffer* aSourceBuffer,
|
||||
const Maybe<IntSize>& aTargetSize,
|
||||
uint32_t aFlags,
|
||||
bool aIsRedecode,
|
||||
bool aImageIsTransient,
|
||||
bool aImageIsLocked)
|
||||
{
|
||||
if (aType == DecoderType::UNKNOWN) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Decoder> decoder = GetDecoder(aType, aImage, aIsRedecode);
|
||||
MOZ_ASSERT(decoder, "Should have a decoder now");
|
||||
|
||||
// Initialize the decoder.
|
||||
decoder->SetSizeDecode(false);
|
||||
decoder->SetIterator(aSourceBuffer->Iterator());
|
||||
decoder->SetFlags(aFlags);
|
||||
decoder->SetSendPartialInvalidations(!aIsRedecode);
|
||||
decoder->SetImageIsTransient(aImageIsTransient);
|
||||
|
||||
if (aImageIsLocked) {
|
||||
decoder->SetImageIsLocked();
|
||||
}
|
||||
|
||||
// Set a target size for downscale-during-decode if applicable.
|
||||
if (aTargetSize) {
|
||||
DebugOnly<nsresult> rv = decoder->SetTargetSize(*aTargetSize);
|
||||
MOZ_ASSERT(nsresult(rv) != NS_ERROR_NOT_AVAILABLE,
|
||||
"We're downscale-during-decode but decoder doesn't support it?");
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
|
||||
}
|
||||
|
||||
decoder->Init();
|
||||
if (NS_FAILED(decoder->GetDecoderError())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Decoder>
|
||||
DecoderFactory::CreateMetadataDecoder(DecoderType aType,
|
||||
RasterImage* aImage,
|
||||
SourceBuffer* aSourceBuffer)
|
||||
{
|
||||
if (aType == DecoderType::UNKNOWN) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Decoder> decoder =
|
||||
GetDecoder(aType, aImage, /* aIsRedecode = */ false);
|
||||
MOZ_ASSERT(decoder, "Should have a decoder now");
|
||||
|
||||
// Initialize the decoder.
|
||||
decoder->SetSizeDecode(true);
|
||||
decoder->SetIterator(aSourceBuffer->Iterator());
|
||||
|
||||
decoder->Init();
|
||||
if (NS_FAILED(decoder->GetDecoderError())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
103
image/DecoderFactory.h
Normal file
103
image/DecoderFactory.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_image_DecoderFactory_h
|
||||
#define mozilla_image_DecoderFactory_h
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsACString;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
class Decoder;
|
||||
class RasterImage;
|
||||
class SourceBuffer;
|
||||
|
||||
enum class DecoderType
|
||||
{
|
||||
PNG,
|
||||
GIF,
|
||||
JPEG,
|
||||
BMP,
|
||||
ICO,
|
||||
ICON,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
class DecoderFactory
|
||||
{
|
||||
public:
|
||||
/// @return the type of decoder which is appropriate for @aMimeType.
|
||||
static DecoderType GetDecoderType(const char* aMimeType);
|
||||
|
||||
/**
|
||||
* Creates and initializes a decoder of type @aType. The decoder will send
|
||||
* notifications to @aImage.
|
||||
*
|
||||
* XXX(seth): @aIsRedecode, @aImageIsTransient, and @aImageIsLocked should
|
||||
* really be part of @aFlags. This requires changes to the way that decoder
|
||||
* flags work, though. See bug 1185800.
|
||||
*
|
||||
* @param aType Which type of decoder to create - JPEG, PNG, etc.
|
||||
* @param aImage The image will own the decoder and which should receive
|
||||
* notifications as decoding progresses.
|
||||
* @param aSourceBuffer The SourceBuffer which the decoder will read its data
|
||||
* from.
|
||||
* @param aTargetSize If not Nothing(), the target size which the image should
|
||||
* be scaled to during decoding. It's an error to specify
|
||||
* a target size for a decoder type which doesn't support
|
||||
* downscale-during-decode.
|
||||
* @param aFlags Flags specifying what type of output the decoder should
|
||||
* produce; see GetDecodeFlags() in RasterImage.h.
|
||||
* @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
|
||||
* lifetime of this decoder, and should be unlocked
|
||||
* when the decoder finishes.
|
||||
*/
|
||||
static already_AddRefed<Decoder>
|
||||
CreateDecoder(DecoderType aType,
|
||||
RasterImage* aImage,
|
||||
SourceBuffer* aSourceBuffer,
|
||||
const Maybe<gfx::IntSize>& aTargetSize,
|
||||
uint32_t aFlags,
|
||||
bool aIsRedecode,
|
||||
bool aImageIsTransient,
|
||||
bool aImageIsLocked);
|
||||
|
||||
/**
|
||||
* Creates and initializes a metadata decoder of type @aType. This decoder
|
||||
* will only decode the image's header, extracting metadata like the size of
|
||||
* the image. No actual image data will be decoded and no surfaces will be
|
||||
* allocated. The decoder will send notifications to @aImage.
|
||||
*
|
||||
* XXX(seth): A metadata decode is called a "size decode" in most of ImageLib,
|
||||
* but we are going to move away from that term, as it's both confusing to
|
||||
* people and increasingly inaccurate.
|
||||
*
|
||||
* @param aType Which type of decoder to create - JPEG, PNG, etc.
|
||||
* @param aImage The image will own the decoder and which should receive
|
||||
* notifications as decoding progresses.
|
||||
* @param aSourceBuffer The SourceBuffer which the decoder will read its data
|
||||
* from.
|
||||
*/
|
||||
static already_AddRefed<Decoder>
|
||||
CreateMetadataDecoder(DecoderType aType,
|
||||
RasterImage* aImage,
|
||||
SourceBuffer* aSourceBuffer);
|
||||
|
||||
private:
|
||||
virtual ~DecoderFactory() = 0;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_image_DecoderFactory_h
|
@ -3,8 +3,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsMimeTypes.h"
|
||||
|
||||
#include "Image.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
@ -69,52 +67,6 @@ ImageResource::~ImageResource()
|
||||
mProgressTracker->ResetImage();
|
||||
}
|
||||
|
||||
// Translates a mimetype into a concrete decoder
|
||||
Image::eDecoderType
|
||||
Image::GetDecoderType(const char* aMimeType)
|
||||
{
|
||||
// By default we don't know
|
||||
eDecoderType rv = eDecoderType_unknown;
|
||||
|
||||
// PNG
|
||||
if (!strcmp(aMimeType, IMAGE_PNG)) {
|
||||
rv = eDecoderType_png;
|
||||
|
||||
} else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
|
||||
rv = eDecoderType_png;
|
||||
|
||||
// GIF
|
||||
} else if (!strcmp(aMimeType, IMAGE_GIF)) {
|
||||
rv = eDecoderType_gif;
|
||||
|
||||
// JPEG
|
||||
} else if (!strcmp(aMimeType, IMAGE_JPEG)) {
|
||||
rv = eDecoderType_jpeg;
|
||||
} else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
|
||||
rv = eDecoderType_jpeg;
|
||||
} else if (!strcmp(aMimeType, IMAGE_JPG)) {
|
||||
rv = eDecoderType_jpeg;
|
||||
|
||||
// BMP
|
||||
} else if (!strcmp(aMimeType, IMAGE_BMP)) {
|
||||
rv = eDecoderType_bmp;
|
||||
} else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
|
||||
rv = eDecoderType_bmp;
|
||||
|
||||
// ICO
|
||||
} else if (!strcmp(aMimeType, IMAGE_ICO)) {
|
||||
rv = eDecoderType_ico;
|
||||
} else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
|
||||
rv = eDecoderType_ico;
|
||||
|
||||
// Icon
|
||||
} else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
|
||||
rv = eDecoderType_icon;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
ImageResource::IncrementAnimationConsumers()
|
||||
{
|
||||
|
@ -129,18 +129,6 @@ private:
|
||||
class Image : public imgIContainer
|
||||
{
|
||||
public:
|
||||
// Mimetype translation
|
||||
enum eDecoderType {
|
||||
eDecoderType_png = 0,
|
||||
eDecoderType_gif = 1,
|
||||
eDecoderType_jpeg = 2,
|
||||
eDecoderType_bmp = 3,
|
||||
eDecoderType_ico = 4,
|
||||
eDecoderType_icon = 5,
|
||||
eDecoderType_unknown = 6
|
||||
};
|
||||
static eDecoderType GetDecoderType(const char* aMimeType);
|
||||
|
||||
/**
|
||||
* Flags for Image initialization.
|
||||
*
|
||||
|
@ -21,18 +21,12 @@
|
||||
#include "ImageRegion.h"
|
||||
#include "Layers.h"
|
||||
#include "LookupResult.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfaceCache.h"
|
||||
#include "FrameAnimator.h"
|
||||
|
||||
#include "nsPNGDecoder.h"
|
||||
#include "nsGIFDecoder2.h"
|
||||
#include "nsJPEGDecoder.h"
|
||||
#include "nsBMPDecoder.h"
|
||||
#include "nsICODecoder.h"
|
||||
#include "nsIconDecoder.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
@ -282,8 +276,8 @@ RasterImage::Init(const char* aMimeType,
|
||||
// Use the MIME type to select a decoder type, and make sure there *is* a
|
||||
// decoder for this MIME type.
|
||||
NS_ENSURE_ARG_POINTER(aMimeType);
|
||||
mDecoderType = GetDecoderType(aMimeType);
|
||||
if (mDecoderType == eDecoderType_unknown) {
|
||||
mDecoderType = DecoderFactory::GetDecoderType(aMimeType);
|
||||
if (mDecoderType == DecoderType::UNKNOWN) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -1339,64 +1333,28 @@ RasterImage::CreateDecoder(const Maybe<IntSize>& aSize, uint32_t aFlags)
|
||||
MOZ_ASSERT(!mHasSize, "Should not do unnecessary size decodes");
|
||||
}
|
||||
|
||||
// Instantiate the appropriate decoder.
|
||||
nsRefPtr<Decoder> decoder;
|
||||
switch (mDecoderType) {
|
||||
case eDecoderType_png:
|
||||
decoder = new nsPNGDecoder(this);
|
||||
break;
|
||||
case eDecoderType_gif:
|
||||
decoder = new nsGIFDecoder2(this);
|
||||
break;
|
||||
case eDecoderType_jpeg:
|
||||
// If we have all the data we don't want to waste cpu time doing
|
||||
// a progressive decode.
|
||||
decoder = new nsJPEGDecoder(this,
|
||||
mHasBeenDecoded ? Decoder::SEQUENTIAL :
|
||||
Decoder::PROGRESSIVE);
|
||||
break;
|
||||
case eDecoderType_bmp:
|
||||
decoder = new nsBMPDecoder(this);
|
||||
break;
|
||||
case eDecoderType_ico:
|
||||
decoder = new nsICODecoder(this);
|
||||
break;
|
||||
case eDecoderType_icon:
|
||||
decoder = new nsIconDecoder(this);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
|
||||
}
|
||||
|
||||
MOZ_ASSERT(decoder, "Should have a decoder now");
|
||||
|
||||
// Initialize the decoder.
|
||||
decoder->SetSizeDecode(!aSize);
|
||||
decoder->SetSendPartialInvalidations(!mHasBeenDecoded);
|
||||
decoder->SetImageIsTransient(mTransient);
|
||||
decoder->SetFlags(aFlags);
|
||||
|
||||
bool imageIsLocked = false;
|
||||
if (!mHasBeenDecoded && aSize) {
|
||||
// Lock the image while we're decoding, so that it doesn't get evicted from
|
||||
// the SurfaceCache before we have a chance to realize that it's animated.
|
||||
// The corresponding unlock happens in FinalizeDecoder.
|
||||
LockImage();
|
||||
decoder->SetImageIsLocked();
|
||||
imageIsLocked = true;
|
||||
}
|
||||
|
||||
decoder->SetIterator(mSourceBuffer->Iterator());
|
||||
|
||||
// Set a target size for downscale-during-decode if applicable.
|
||||
if (mDownscaleDuringDecode && aSize && *aSize != mSize) {
|
||||
DebugOnly<nsresult> rv = decoder->SetTargetSize(*aSize);
|
||||
MOZ_ASSERT(nsresult(rv) != NS_ERROR_NOT_AVAILABLE,
|
||||
"We're downscale-during-decode but decoder doesn't support it?");
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Bad downscale-during-decode target size?");
|
||||
nsRefPtr<Decoder> decoder;
|
||||
if (aSize) {
|
||||
Maybe<IntSize> targetSize = mSize != *aSize ? aSize : Nothing();
|
||||
decoder = DecoderFactory::CreateDecoder(mDecoderType, this, mSourceBuffer,
|
||||
targetSize, aFlags, mHasBeenDecoded,
|
||||
mTransient, imageIsLocked);
|
||||
} else {
|
||||
decoder = DecoderFactory::CreateMetadataDecoder(mDecoderType, this,
|
||||
mSourceBuffer);
|
||||
}
|
||||
|
||||
decoder->Init();
|
||||
|
||||
if (NS_FAILED(decoder->GetDecoderError())) {
|
||||
// Make sure DecoderFactory was able to create a decoder successfully.
|
||||
if (!decoder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "LookupResult.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "DecodePool.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "Orientation.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
@ -376,7 +377,7 @@ private: // data
|
||||
uint32_t mLockCount;
|
||||
|
||||
// The type of decoder this image needs. Computed from the MIME type in Init().
|
||||
eDecoderType mDecoderType;
|
||||
DecoderType mDecoderType;
|
||||
|
||||
// How many times we've decoded this image.
|
||||
// This is currently only used for statistics
|
||||
|
@ -32,9 +32,11 @@
|
||||
// undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
|
||||
#undef GetCurrentTime
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
using namespace gfx;
|
||||
|
||||
namespace image {
|
||||
|
||||
NS_IMPL_ISUPPORTS(SVGDocumentWrapper,
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "Image.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "prtime.h"
|
||||
@ -2475,7 +2476,8 @@ imgLoader::SupportImageWithMimeType(const char* aMimeType,
|
||||
return true;
|
||||
}
|
||||
|
||||
return Image::GetDecoderType(mimeType.get()) != Image::eDecoderType_unknown;
|
||||
DecoderType type = DecoderFactory::GetDecoderType(mimeType.get());
|
||||
return type != DecoderType::UNKNOWN;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -50,6 +50,7 @@ UNIFIED_SOURCES += [
|
||||
'ClippedImage.cpp',
|
||||
'DecodePool.cpp',
|
||||
'Decoder.cpp',
|
||||
'DecoderFactory.cpp',
|
||||
'DynamicImage.cpp',
|
||||
'FrameAnimator.cpp',
|
||||
'FrozenImage.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user