Bug 816362 - Refactor imgTools::DecodeImageData to remove imgIContainer argument and use ImageFactory. r=joe

This commit is contained in:
Seth Fowler 2012-12-17 17:35:07 -08:00
parent 722faa2cd1
commit 170cc5a604
6 changed files with 86 additions and 69 deletions

View File

@ -14,29 +14,44 @@ interface nsIDOMDocument;
interface imgIScriptedNotificationObserver;
interface imgINotificationObserver;
[scriptable, builtinclass, uuid(98bd5bf9-87eb-4d92-81b1-4cd10c64f7b2)]
[scriptable, builtinclass, uuid(4c2383a4-931c-484d-8c4a-973590f66e3f)]
interface imgITools : nsISupports
{
/**
* decodeImage
* Caller provides an input stream and mimetype. We read from the stream
* and decompress it (according to the specified mime type) and return
* the resulting imgIContainer.
*
* @param aStream
* An input stream for an encoded image file.
* @param aMimeType
* Type of image in the stream.
*/
imgIContainer decodeImage(in nsIInputStream aStream,
in ACString aMimeType);
/**
* decodeImageData
* Caller provides an input stream and mimetype. We read from the stream
* and decompress it (according to the specified mime type) and return
* the resulting imgIContainer. (If the caller already has a container,
* it can be provided as input to be reused).
* the resulting imgIContainer.
*
* This method is deprecated and will be removed at some time in the future;
* new code should use |decodeImage|.
*
* @param aStream
* An input stream for an encoded image file.
* @param aMimeType
* Type of image in the stream.
* @param aContainer
* An imgIContainer holding the decoded image. Specify |null| when
* calling to have one created, otherwise specify a container to
* be used. It is an error to pass an already-initialized container
* as aContainer.
* An imgIContainer holding the decoded image will be returned via
* this parameter. It is an error to provide any initial value but
* |null|.
*/
void decodeImageData(in nsIInputStream aStream,
in ACString aMimeType,
inout imgIContainer aContainer);
[deprecated] void decodeImageData(in nsIInputStream aStream,
in ACString aMimeType,
inout imgIContainer aContainer);
/**
* encodeImage

View File

@ -117,6 +117,20 @@ BadImage(nsRefPtr<T>& image)
}
/* static */ already_AddRefed<Image>
ImageFactory::CreateAnonymousImage(const nsCString& aMimeType)
{
nsresult rv;
nsRefPtr<RasterImage> newImage = new RasterImage();
rv = newImage->Init(nullptr, aMimeType.get(), "<unknown>", Image::INIT_FLAG_NONE);
NS_ENSURE_SUCCESS(rv, BadImage(newImage));
return newImage.forget();
}
/* static */ already_AddRefed<Image>
ImageFactory::CreateRasterImage(nsIRequest* aRequest,
imgStatusTracker* aStatusTracker,
const nsCString& aMimeType,

View File

@ -35,6 +35,14 @@ struct ImageFactory
nsIURI* aURI,
bool aIsMultiPart,
uint32_t aInnerWindowId);
/**
* Creates a new image which isn't associated with a URI or loaded through
* the usual image loading mechanism.
*
* @param aMimeType The mimetype of the image.
*/
static already_AddRefed<Image> CreateAnonymousImage(const nsCString& aMimeType);
private:
// Factory functions that create specific types of image containers.

View File

@ -22,7 +22,7 @@
#include "nsStreamUtils.h"
#include "nsNetUtil.h"
#include "nsContentUtils.h"
#include "RasterImage.h"
#include "ImageFactory.h"
#include "ScriptedNotificationObserver.h"
#include "imgIScriptedNotificationObserver.h"
@ -47,35 +47,33 @@ imgTools::~imgTools()
/* destructor code */
}
NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr,
const nsACString& aMimeType,
imgIContainer **aContainer)
{
NS_ABORT_IF_FALSE(*aContainer == nullptr,
"Cannot provide an existing image container to DecodeImageData");
return DecodeImage(aInStr, aMimeType, aContainer);
}
NS_IMETHODIMP imgTools::DecodeImage(nsIInputStream* aInStr,
const nsACString& aMimeType,
imgIContainer **aContainer)
{
nsresult rv;
RasterImage* image; // convenience alias for *aContainer
nsRefPtr<Image> image;
NS_ENSURE_ARG_POINTER(aInStr);
// XXX(seth) This needs to be switched over to use ImageFactory, but we need
// to be sure that no callers actually provide an existing imgIContainer first.
// Create a new image container to hold the decoded data.
nsAutoCString mimeType(aMimeType);
image = ImageFactory::CreateAnonymousImage(mimeType);
// If the caller didn't provide an imgIContainer, create one.
if (*aContainer) {
NS_ABORT_IF_FALSE((*aContainer)->GetType() == imgIContainer::TYPE_RASTER,
"wrong type of imgIContainer for decoding into");
image = static_cast<RasterImage*>(*aContainer);
} else {
*aContainer = image = new RasterImage();
NS_ADDREF(image);
}
// Initialize the Image. If we're using the one from the caller, we
// require that it not be initialized.
nsCString mimeType(aMimeType);
rv = image->Init(nullptr, mimeType.get(), "<unknown>", Image::INIT_FLAG_NONE);
NS_ENSURE_SUCCESS(rv, rv);
if (image->HasError())
return NS_ERROR_FAILURE;
// Prepare the input stream.
nsCOMPtr<nsIInputStream> inStream = aInStr;
if (!NS_InputStreamIsBuffered(aInStr)) {
nsCOMPtr<nsIInputStream> bufStream;
@ -84,27 +82,21 @@ NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr,
inStream = bufStream;
}
// Figure out how much data we've been passed
// Figure out how much data we've been passed.
uint64_t length;
rv = inStream->Available(&length);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(length <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
// Send the source data to the Image. WriteToRasterImage always
// consumes everything it gets if it doesn't run out of memory.
uint32_t bytesRead;
rv = inStream->ReadSegments(RasterImage::WriteToRasterImage,
static_cast<void*>(image),
(uint32_t)length, &bytesRead);
// Send the source data to the Image.
rv = image->OnImageDataAvailable(nullptr, nullptr, inStream, 0, uint32_t(length));
NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(bytesRead == length || image->HasError(),
"WriteToRasterImage should consume everything or the image must be in error!");
// Let the Image know we've sent all the data
// Let the Image know we've sent all the data.
rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK);
NS_ENSURE_SUCCESS(rv, rv);
// All done
// All done.
NS_ADDREF(*aContainer = image.get());
return NS_OK;
}

View File

@ -8,11 +8,11 @@
#include "gfxContext.h"
#define NS_IMGTOOLS_CID \
{ /* fd9a9e8a-a77b-496a-b7bb-263df9715149 */ \
0xfd9a9e8a, \
0xa77b, \
0x496a, \
{0xb7, 0xbb, 0x26, 0x3d, 0xf9, 0x71, 0x51, 0x49} \
{ /* 4c2383a4-931c-484d-8c4a-973590f66e3f */ \
0x4c2383a4, \
0x931c, \
0x484d, \
{0x8c, 0x4a, 0x97, 0x35, 0x90, 0xf6, 0x6e, 0x3f} \
}
class imgTools : public imgITools

View File

@ -149,6 +149,8 @@ var imgFile = do_get_file(imgName);
var istream = getFileInputStream(imgFile);
do_check_eq(istream.available(), 8415);
// Use decodeImageData for this test even though it's deprecated to ensure that
// it correctly forwards to decodeImage and continues to work.
var outParam = { value: null };
imgTools.decodeImageData(istream, inMimeType, outParam);
var container = outParam.value;
@ -209,9 +211,7 @@ imgFile = do_get_file(imgName);
istream = getFileInputStream(imgFile);
do_check_eq(istream.available(), 3494);
outParam = {};
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
container = imgTools.decodeImage(istream, inMimeType);
// It's not easy to look at the pixel values from JS, so just
// check the container's size.
@ -273,9 +273,7 @@ imgFile = do_get_file(imgName);
istream = getFileInputStream(imgFile);
do_check_eq(istream.available(), 1406);
outParam = { value: null };
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
container = imgTools.decodeImage(istream, inMimeType);
// It's not easy to look at the pixel values from JS, so just
// check the container's size.
@ -333,9 +331,7 @@ imgFile = do_get_file(imgName);
istream = getFileInputStream(imgFile);
do_check_eq(istream.available(), 1809);
outParam = { value: null };
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
container = imgTools.decodeImage(istream, inMimeType);
// It's not easy to look at the pixel values from JS, so just
// check the container's size.
@ -443,9 +439,7 @@ imgFile = do_get_file(imgName);
istream = getFileInputStream(imgFile);
do_check_eq(istream.available(), 3494);
outParam = {};
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
container = imgTools.decodeImage(istream, inMimeType);
// It's not easy to look at the pixel values from JS, so just
// check the container's size.
@ -663,9 +657,7 @@ for(var i=0; i<testData.length; ++i) {
imgFile = do_get_file(dict["preImage"]);
istream = getFileInputStream(imgFile);
var outParam = { value: null };
imgTools.decodeImageData(istream, dict["preImageMimeType"], outParam);
var container = outParam.value;
var container = imgTools.decodeImage(istream, dict["preImageMimeType"]);
istream = imgTools.encodeImage(container, dict["refImageMimeType"]);
@ -701,11 +693,9 @@ do_check_eq(istream.available(), 17759);
var errsrc = "none";
try {
outParam = { value: null };
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
container = imgTools.decodeImage(istream, inMimeType);
// We should never hit this - decodeImageData throws an assertion because the
// We should never hit this - decodeImage throws an assertion because the
// image decoded doesn't have enough frames.
try {
istream = imgTools.encodeImage(container, "image/png");
@ -733,9 +723,7 @@ imgFile = do_get_file(imgName);
istream = getFileInputStream(imgFile);
do_check_eq(istream.available(), 4286);
outParam = { value: null };
imgTools.decodeImageData(istream, inMimeType, outParam);
container = outParam.value;
container = imgTools.decodeImage(istream, inMimeType);
var props = container.QueryInterface(Ci.nsIProperties);