diff --git a/image/public/imgITools.idl b/image/public/imgITools.idl index 62d3b7e54458..82eb71cac42b 100644 --- a/image/public/imgITools.idl +++ b/image/public/imgITools.idl @@ -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 diff --git a/image/src/ImageFactory.cpp b/image/src/ImageFactory.cpp index a73f8720e348..5d0e180e037a 100644 --- a/image/src/ImageFactory.cpp +++ b/image/src/ImageFactory.cpp @@ -117,6 +117,20 @@ BadImage(nsRefPtr& image) } /* static */ already_AddRefed +ImageFactory::CreateAnonymousImage(const nsCString& aMimeType) +{ + nsresult rv; + + nsRefPtr newImage = new RasterImage(); + + rv = newImage->Init(nullptr, aMimeType.get(), "", Image::INIT_FLAG_NONE); + NS_ENSURE_SUCCESS(rv, BadImage(newImage)); + + return newImage.forget(); +} + +/* static */ already_AddRefed + ImageFactory::CreateRasterImage(nsIRequest* aRequest, imgStatusTracker* aStatusTracker, const nsCString& aMimeType, diff --git a/image/src/ImageFactory.h b/image/src/ImageFactory.h index abc0e915264f..72a8983afb87 100644 --- a/image/src/ImageFactory.h +++ b/image/src/ImageFactory.h @@ -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 CreateAnonymousImage(const nsCString& aMimeType); + private: // Factory functions that create specific types of image containers. diff --git a/image/src/imgTools.cpp b/image/src/imgTools.cpp index 1a6e9db9e5a7..750522171237 100644 --- a/image/src/imgTools.cpp +++ b/image/src/imgTools.cpp @@ -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; 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(*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(), "", Image::INIT_FLAG_NONE); - NS_ENSURE_SUCCESS(rv, rv); + if (image->HasError()) + return NS_ERROR_FAILURE; + // Prepare the input stream. nsCOMPtr inStream = aInStr; if (!NS_InputStreamIsBuffered(aInStr)) { nsCOMPtr 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(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; } diff --git a/image/src/imgTools.h b/image/src/imgTools.h index 02ccbab56c89..be39ebc0ae44 100644 --- a/image/src/imgTools.h +++ b/image/src/imgTools.h @@ -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 diff --git a/image/test/unit/test_imgtools.js b/image/test/unit/test_imgtools.js index adee0520d552..ee4e05e486d8 100644 --- a/image/test/unit/test_imgtools.js +++ b/image/test/unit/test_imgtools.js @@ -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