LCOV - code coverage report
Current view: top level - image - imgTools.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 34 214 15.9 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  *
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "imgTools.h"
       8             : 
       9             : #include "DecodePool.h"
      10             : #include "gfxUtils.h"
      11             : #include "mozilla/gfx/2D.h"
      12             : #include "mozilla/gfx/Logging.h"
      13             : #include "mozilla/RefPtr.h"
      14             : #include "nsCOMPtr.h"
      15             : #include "nsIDocument.h"
      16             : #include "nsError.h"
      17             : #include "imgLoader.h"
      18             : #include "imgICache.h"
      19             : #include "imgIContainer.h"
      20             : #include "imgIEncoder.h"
      21             : #include "nsNetUtil.h" // for NS_NewBufferedInputStream
      22             : #include "nsStreamUtils.h"
      23             : #include "nsStringStream.h"
      24             : #include "nsContentUtils.h"
      25             : #include "nsProxyRelease.h"
      26             : #include "ImageFactory.h"
      27             : #include "Image.h"
      28             : #include "ScriptedNotificationObserver.h"
      29             : #include "imgIScriptedNotificationObserver.h"
      30             : #include "gfxPlatform.h"
      31             : #include "jsfriendapi.h"
      32             : 
      33             : using namespace mozilla::gfx;
      34             : 
      35             : namespace mozilla {
      36             : namespace image {
      37             : 
      38             : namespace {
      39             : 
      40             : class ImageDecoderHelper final : public Runnable
      41             :                                , public nsIInputStreamCallback
      42             : {
      43             : public:
      44             :   NS_DECL_ISUPPORTS_INHERITED
      45             : 
      46           0 :   ImageDecoderHelper(already_AddRefed<image::Image> aImage,
      47             :                      already_AddRefed<nsIInputStream> aInputStream,
      48             :                      nsIEventTarget* aEventTarget,
      49             :                      imgIContainerCallback* aCallback,
      50             :                      nsIEventTarget* aCallbackEventTarget)
      51           0 :     : Runnable("ImageDecoderHelper")
      52           0 :     , mImage(std::move(aImage))
      53           0 :     , mInputStream(std::move(aInputStream))
      54             :     , mEventTarget(aEventTarget)
      55             :     , mCallback(aCallback)
      56             :     , mCallbackEventTarget(aCallbackEventTarget)
      57           0 :     , mStatus(NS_OK)
      58             :   {
      59           0 :     MOZ_ASSERT(NS_IsMainThread());
      60           0 :   }
      61             : 
      62             :   NS_IMETHOD
      63           0 :   Run() override
      64             :   {
      65             :     // This runnable is dispatched on the Image thread when reading data, but
      66             :     // at the end, it goes back to the main-thread in order to complete the
      67             :     // operation.
      68           0 :     if (NS_IsMainThread()) {
      69             :       // Let the Image know we've sent all the data.
      70           0 :       mImage->OnImageDataComplete(nullptr, nullptr, mStatus, true);
      71             : 
      72           0 :       RefPtr<ProgressTracker> tracker = mImage->GetProgressTracker();
      73           0 :       tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
      74             : 
      75           0 :       nsCOMPtr<imgIContainer> container;
      76           0 :       if (NS_SUCCEEDED(mStatus)) {
      77           0 :         container = do_QueryInterface(mImage);
      78             :       }
      79             : 
      80           0 :       mCallback->OnImageReady(container, mStatus);
      81             :       return NS_OK;
      82             :     }
      83             : 
      84             :     uint64_t length;
      85           0 :     nsresult rv = mInputStream->Available(&length);
      86           0 :     if (rv == NS_BASE_STREAM_CLOSED) {
      87           0 :       return OperationCompleted(NS_OK);
      88             :     }
      89             : 
      90           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
      91           0 :       return OperationCompleted(rv);
      92             :     }
      93             : 
      94             :     // Nothing else to read, but maybe we just need to wait.
      95           0 :     if (length == 0) {
      96             :       nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
      97           0 :         do_QueryInterface(mInputStream);
      98           0 :       if (asyncInputStream) {
      99           0 :         rv = asyncInputStream->AsyncWait(this, 0, 0, mEventTarget);
     100           0 :         if (NS_WARN_IF(NS_FAILED(rv))) {
     101           0 :           return OperationCompleted(rv);
     102             :         }
     103             :         return NS_OK;
     104             :       }
     105             : 
     106             :       // We really have nothing else to read.
     107           0 :       if (length == 0) {
     108           0 :         return OperationCompleted(NS_OK);
     109             :       }
     110             :     }
     111             : 
     112             :     // Send the source data to the Image.
     113           0 :     rv = mImage->OnImageDataAvailable(nullptr, nullptr, mInputStream, 0,
     114           0 :                                       uint32_t(length));
     115           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     116           0 :       return OperationCompleted(rv);
     117             :     }
     118             : 
     119           0 :     rv = mEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
     120           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     121           0 :       return OperationCompleted(rv);
     122             :     }
     123             : 
     124             :     return NS_OK;
     125             :   }
     126             : 
     127             :   NS_IMETHOD
     128           0 :   OnInputStreamReady(nsIAsyncInputStream* aAsyncInputStream) override
     129             :   {
     130           0 :     MOZ_ASSERT(!NS_IsMainThread());
     131           0 :     return Run();
     132             :   }
     133             : 
     134             :   nsresult
     135           0 :   OperationCompleted(nsresult aStatus)
     136             :   {
     137           0 :     MOZ_ASSERT(!NS_IsMainThread());
     138             : 
     139           0 :     mStatus = aStatus;
     140           0 :     mCallbackEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
     141           0 :     return NS_OK;
     142             :   }
     143             : 
     144             : private:
     145           0 :   ~ImageDecoderHelper()
     146           0 :   {
     147             :     NS_ReleaseOnMainThreadSystemGroup("ImageDecoderHelper::mImage",
     148           0 :                                       mImage.forget());
     149             :     NS_ReleaseOnMainThreadSystemGroup("ImageDecoderHelper::mCallback",
     150           0 :                                       mCallback.forget());
     151           0 :   }
     152             : 
     153             :   RefPtr<image::Image> mImage;
     154             : 
     155             :   nsCOMPtr<nsIInputStream> mInputStream;
     156             :   nsCOMPtr<nsIEventTarget> mEventTarget;
     157             :   nsCOMPtr<imgIContainerCallback> mCallback;
     158             :   nsCOMPtr<nsIEventTarget> mCallbackEventTarget;
     159             : 
     160             :   nsresult mStatus;
     161             : };
     162             : 
     163           0 : NS_IMPL_ISUPPORTS_INHERITED(ImageDecoderHelper, Runnable,
     164             :                             nsIInputStreamCallback)
     165             : 
     166             : } // anonymous
     167             : 
     168             : /* ========== imgITools implementation ========== */
     169             : 
     170             : 
     171             : 
     172          43 : NS_IMPL_ISUPPORTS(imgTools, imgITools)
     173             : 
     174           6 : imgTools::imgTools()
     175             : {
     176             :   /* member initializers and constructor code */
     177           2 : }
     178             : 
     179           0 : imgTools::~imgTools()
     180             : {
     181             :   /* destructor code */
     182           0 : }
     183             : 
     184             : NS_IMETHODIMP
     185           0 : imgTools::DecodeImageFromArrayBuffer(JS::HandleValue aArrayBuffer,
     186             :                                      const nsACString& aMimeType,
     187             :                                      JSContext* aCx,
     188             :                                      imgIContainer** aContainer)
     189             : {
     190           0 :   if (!aArrayBuffer.isObject()) {
     191             :     return NS_ERROR_FAILURE;
     192             :   }
     193             : 
     194             :   JS::Rooted<JSObject*> obj(aCx,
     195           0 :                             js::UnwrapArrayBuffer(&aArrayBuffer.toObject()));
     196           0 :   if (!obj) {
     197             :     return NS_ERROR_FAILURE;
     198             :   }
     199             : 
     200           0 :   uint8_t* bufferData = nullptr;
     201           0 :   uint32_t bufferLength = 0;
     202           0 :   bool isSharedMemory = false;
     203             : 
     204             :   js::GetArrayBufferLengthAndData(obj, &bufferLength, &isSharedMemory,
     205           0 :                                   &bufferData);
     206           0 :   return DecodeImageFromBuffer((char*)bufferData, bufferLength, aMimeType,
     207           0 :                                aContainer);
     208             : }
     209             : 
     210             : NS_IMETHODIMP
     211           4 : imgTools::DecodeImageFromBuffer(const char* aBuffer, uint32_t aSize,
     212             :                                 const nsACString& aMimeType,
     213             :                                 imgIContainer** aContainer)
     214             : {
     215           4 :   MOZ_ASSERT(NS_IsMainThread());
     216             : 
     217           4 :   NS_ENSURE_ARG_POINTER(aBuffer);
     218             : 
     219             :   // Create a new image container to hold the decoded data.
     220           4 :   nsAutoCString mimeType(aMimeType);
     221             :   RefPtr<image::Image> image =
     222           0 :     ImageFactory::CreateAnonymousImage(mimeType, aSize);
     223          12 :   RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
     224             : 
     225           4 :   if (image->HasError()) {
     226             :     return NS_ERROR_FAILURE;
     227             :   }
     228             : 
     229             :   // Let's create a temporary inputStream.
     230           0 :   nsCOMPtr<nsIInputStream> stream;
     231          12 :   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
     232             :                                       aBuffer, aSize,
     233           0 :                                       NS_ASSIGNMENT_DEPEND);
     234           0 :   NS_ENSURE_SUCCESS(rv, rv);
     235           0 :   MOZ_ASSERT(stream);
     236           4 :   MOZ_ASSERT(NS_InputStreamIsBuffered(stream));
     237             : 
     238           0 :   rv = image->OnImageDataAvailable(nullptr, nullptr, stream, 0,
     239           0 :                                    aSize);
     240           4 :   NS_ENSURE_SUCCESS(rv, rv);
     241             : 
     242             :   // Let the Image know we've sent all the data.
     243           0 :   rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
     244           0 :   tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
     245           4 :   NS_ENSURE_SUCCESS(rv, rv);
     246             : 
     247             :   // All done.
     248           0 :   image.forget(aContainer);
     249           4 :   return NS_OK;
     250             : }
     251             : 
     252             : NS_IMETHODIMP
     253           0 : imgTools::DecodeImageAsync(nsIInputStream* aInStr,
     254             :                            const nsACString& aMimeType,
     255             :                            imgIContainerCallback* aCallback,
     256             :                            nsIEventTarget* aEventTarget)
     257             : {
     258           0 :   MOZ_ASSERT(NS_IsMainThread());
     259             : 
     260           0 :   NS_ENSURE_ARG_POINTER(aInStr);
     261           0 :   NS_ENSURE_ARG_POINTER(aCallback);
     262           0 :   NS_ENSURE_ARG_POINTER(aEventTarget);
     263             : 
     264             :   nsresult rv;
     265             : 
     266             :   // Let's continuing the reading on a separate thread.
     267           0 :   DecodePool* decodePool = DecodePool::Singleton();
     268           0 :   MOZ_ASSERT(decodePool);
     269             : 
     270           0 :   RefPtr<nsIEventTarget> target = decodePool->GetIOEventTarget();
     271           0 :   NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
     272             : 
     273             :   // Prepare the input stream.
     274           0 :   nsCOMPtr<nsIInputStream> stream = aInStr;
     275           0 :   if (!NS_InputStreamIsBuffered(aInStr)) {
     276           0 :     nsCOMPtr<nsIInputStream> bufStream;
     277           0 :     rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
     278           0 :                                    stream.forget(), 1024);
     279           0 :     NS_ENSURE_SUCCESS(rv, rv);
     280           0 :     stream = bufStream.forget();
     281             :   }
     282             : 
     283             :   // Create a new image container to hold the decoded data.
     284           0 :   nsAutoCString mimeType(aMimeType);
     285           0 :   RefPtr<image::Image> image = ImageFactory::CreateAnonymousImage(mimeType, 0);
     286             : 
     287             :   // Already an error?
     288           0 :   if (image->HasError()) {
     289             :     return NS_ERROR_FAILURE;
     290             :   }
     291             : 
     292             :   RefPtr<ImageDecoderHelper> helper =
     293           0 :     new ImageDecoderHelper(image.forget(), stream.forget(), target, aCallback,
     294           0 :                            aEventTarget);
     295           0 :   rv = target->Dispatch(helper.forget(), NS_DISPATCH_NORMAL);
     296           0 :   NS_ENSURE_SUCCESS(rv, rv);
     297             : 
     298             :   return NS_OK;
     299             : }
     300             : 
     301             : /**
     302             :  * This takes a DataSourceSurface rather than a SourceSurface because some
     303             :  * of the callers have a DataSourceSurface and we don't want to call
     304             :  * GetDataSurface on such surfaces since that may incure a conversion to
     305             :  * SurfaceType::DATA which we don't need.
     306             :  */
     307             : static nsresult
     308           1 : EncodeImageData(DataSourceSurface* aDataSurface,
     309             :                 DataSourceSurface::ScopedMap& aMap,
     310             :                 const nsACString& aMimeType,
     311             :                 const nsAString& aOutputOptions,
     312             :                 nsIInputStream** aStream)
     313             : {
     314           1 :   MOZ_ASSERT(aDataSurface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
     315             :              aDataSurface->GetFormat() == SurfaceFormat::B8G8R8X8,
     316             :              "We're assuming B8G8R8A8/X8");
     317             : 
     318             :   // Get an image encoder for the media type
     319             :   nsAutoCString encoderCID(
     320           4 :     NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType);
     321             : 
     322           0 :   nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
     323           1 :   if (!encoder) {
     324             :     return NS_IMAGELIB_ERROR_NO_ENCODER;
     325             :   }
     326             : 
     327           0 :   IntSize size = aDataSurface->GetSize();
     328           1 :   uint32_t dataLength = aMap.GetStride() * size.height;
     329             : 
     330             :   // Encode the bitmap
     331           3 :   nsresult rv = encoder->InitFromData(aMap.GetData(),
     332             :                                       dataLength,
     333           1 :                                       size.width,
     334             :                                       size.height,
     335           1 :                                       aMap.GetStride(),
     336             :                                       imgIEncoder::INPUT_FORMAT_HOSTARGB,
     337           0 :                                       aOutputOptions);
     338           1 :   NS_ENSURE_SUCCESS(rv, rv);
     339             : 
     340           0 :   encoder.forget(aStream);
     341           1 :   return NS_OK;
     342             : }
     343             : 
     344             : static nsresult
     345           1 : EncodeImageData(DataSourceSurface* aDataSurface,
     346             :                 const nsACString& aMimeType,
     347             :                 const nsAString& aOutputOptions,
     348             :                 nsIInputStream** aStream)
     349             : {
     350           0 :   DataSourceSurface::ScopedMap map(aDataSurface, DataSourceSurface::READ);
     351           1 :   if (!map.IsMapped()) {
     352             :     return NS_ERROR_FAILURE;
     353             :   }
     354             : 
     355           1 :   return EncodeImageData(aDataSurface, map, aMimeType, aOutputOptions, aStream);
     356             : }
     357             : 
     358             : NS_IMETHODIMP
     359           0 : imgTools::EncodeImage(imgIContainer* aContainer,
     360             :                       const nsACString& aMimeType,
     361             :                       const nsAString& aOutputOptions,
     362             :                       nsIInputStream** aStream)
     363             : {
     364             :   // Use frame 0 from the image container.
     365             :   RefPtr<SourceSurface> frame =
     366           0 :     aContainer->GetFrame(imgIContainer::FRAME_FIRST,
     367           0 :                          imgIContainer::FLAG_SYNC_DECODE);
     368           0 :   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
     369             : 
     370           0 :   RefPtr<DataSourceSurface> dataSurface;
     371             : 
     372           0 :   if (frame->GetFormat() == SurfaceFormat::B8G8R8A8 ||
     373           0 :       frame->GetFormat() == SurfaceFormat::B8G8R8X8) {
     374           0 :     dataSurface = frame->GetDataSurface();
     375             :   } else {
     376             :     // Convert format to SurfaceFormat::B8G8R8A8
     377             :     dataSurface = gfxUtils::
     378           0 :       CopySurfaceToDataSourceSurfaceWithFormat(frame,
     379           0 :                                                SurfaceFormat::B8G8R8A8);
     380             :   }
     381             : 
     382           0 :   NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
     383             : 
     384           0 :   return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream);
     385             : }
     386             : 
     387             : NS_IMETHODIMP
     388           1 : imgTools::EncodeScaledImage(imgIContainer* aContainer,
     389             :                             const nsACString& aMimeType,
     390             :                             int32_t aScaledWidth,
     391             :                             int32_t aScaledHeight,
     392             :                             const nsAString& aOutputOptions,
     393             :                             nsIInputStream** aStream)
     394             : {
     395           1 :   NS_ENSURE_ARG(aScaledWidth >= 0 && aScaledHeight >= 0);
     396             : 
     397             :   // If no scaled size is specified, we'll just encode the image at its
     398             :   // original size (no scaling).
     399           0 :   if (aScaledWidth == 0 && aScaledHeight == 0) {
     400           0 :     return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream);
     401             :   }
     402             : 
     403             :   // Retrieve the image's size.
     404           0 :   int32_t imageWidth = 0;
     405           0 :   int32_t imageHeight = 0;
     406           0 :   aContainer->GetWidth(&imageWidth);
     407           1 :   aContainer->GetHeight(&imageHeight);
     408             : 
     409             :   // If the given width or height is zero we'll replace it with the image's
     410             :   // original dimensions.
     411             :   IntSize scaledSize(aScaledWidth == 0 ? imageWidth : aScaledWidth,
     412           4 :                      aScaledHeight == 0 ? imageHeight : aScaledHeight);
     413             : 
     414             :   // Use frame 0 from the image container.
     415             :   RefPtr<SourceSurface> frame =
     416           2 :     aContainer->GetFrameAtSize(scaledSize,
     417             :                                imgIContainer::FRAME_FIRST,
     418             :                                imgIContainer::FLAG_HIGH_QUALITY_SCALING |
     419           0 :                                imgIContainer::FLAG_SYNC_DECODE);
     420           1 :   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
     421             : 
     422             :   // If the given surface is the right size/format, we can encode it directly.
     423           0 :   if (scaledSize == frame->GetSize() &&
     424           0 :       (frame->GetFormat() == SurfaceFormat::B8G8R8A8 ||
     425           0 :        frame->GetFormat() == SurfaceFormat::B8G8R8X8)) {
     426           0 :     RefPtr<DataSourceSurface> dataSurface = frame->GetDataSurface();
     427           0 :     if (dataSurface) {
     428           1 :       return EncodeImageData(dataSurface, aMimeType, aOutputOptions, aStream);
     429             :     }
     430             :   }
     431             : 
     432             :   // Otherwise we need to scale it using a draw target.
     433             :   RefPtr<DataSourceSurface> dataSurface =
     434           0 :     Factory::CreateDataSourceSurface(scaledSize, SurfaceFormat::B8G8R8A8);
     435           0 :   if (NS_WARN_IF(!dataSurface)) {
     436             :     return NS_ERROR_FAILURE;
     437             :   }
     438             : 
     439           0 :   DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::READ_WRITE);
     440           0 :   if (!map.IsMapped()) {
     441             :     return NS_ERROR_FAILURE;
     442             :   }
     443             : 
     444             :   RefPtr<DrawTarget> dt =
     445           0 :     Factory::CreateDrawTargetForData(BackendType::SKIA,
     446             :                                      map.GetData(),
     447           0 :                                      dataSurface->GetSize(),
     448             :                                      map.GetStride(),
     449           0 :                                      SurfaceFormat::B8G8R8A8);
     450           0 :   if (!dt) {
     451           0 :     gfxWarning() << "imgTools::EncodeImage failed in CreateDrawTargetForData";
     452           0 :     return NS_ERROR_OUT_OF_MEMORY;
     453             :   }
     454             : 
     455           0 :   IntSize frameSize = frame->GetSize();
     456           0 :   dt->DrawSurface(frame,
     457           0 :                   Rect(0, 0, scaledSize.width, scaledSize.height),
     458           0 :                   Rect(0, 0, frameSize.width, frameSize.height),
     459           0 :                   DrawSurfaceOptions(),
     460           0 :                   DrawOptions(1.0f, CompositionOp::OP_SOURCE));
     461             : 
     462           0 :   return EncodeImageData(dataSurface, map, aMimeType, aOutputOptions, aStream);
     463             : }
     464             : 
     465             : NS_IMETHODIMP
     466           0 : imgTools::EncodeCroppedImage(imgIContainer* aContainer,
     467             :                              const nsACString& aMimeType,
     468             :                              int32_t aOffsetX,
     469             :                              int32_t aOffsetY,
     470             :                              int32_t aWidth,
     471             :                              int32_t aHeight,
     472             :                              const nsAString& aOutputOptions,
     473             :                              nsIInputStream** aStream)
     474             : {
     475           0 :   NS_ENSURE_ARG(aOffsetX >= 0 && aOffsetY >= 0 && aWidth >= 0 && aHeight >= 0);
     476             : 
     477             :   // Offsets must be zero when no width and height are given or else we're out
     478             :   // of bounds.
     479           0 :   NS_ENSURE_ARG(aWidth + aHeight > 0 || aOffsetX + aOffsetY == 0);
     480             : 
     481             :   // If no size is specified then we'll preserve the image's original dimensions
     482             :   // and don't need to crop.
     483           0 :   if (aWidth == 0 && aHeight == 0) {
     484           0 :     return EncodeImage(aContainer, aMimeType, aOutputOptions, aStream);
     485             :   }
     486             : 
     487             :   // Use frame 0 from the image container.
     488             :   RefPtr<SourceSurface> frame =
     489           0 :     aContainer->GetFrame(imgIContainer::FRAME_FIRST,
     490           0 :                          imgIContainer::FLAG_SYNC_DECODE);
     491           0 :   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
     492             : 
     493           0 :   int32_t frameWidth = frame->GetSize().width;
     494           0 :   int32_t frameHeight = frame->GetSize().height;
     495             : 
     496             :   // If the given width or height is zero we'll replace it with the image's
     497             :   // original dimensions.
     498           0 :   if (aWidth == 0) {
     499             :     aWidth = frameWidth;
     500           0 :   } else if (aHeight == 0) {
     501           0 :     aHeight = frameHeight;
     502             :   }
     503             : 
     504             :   // Check that the given crop rectangle is within image bounds.
     505           0 :   NS_ENSURE_ARG(frameWidth >= aOffsetX + aWidth &&
     506             :                 frameHeight >= aOffsetY + aHeight);
     507             : 
     508             :   RefPtr<DataSourceSurface> dataSurface =
     509           0 :     Factory::CreateDataSourceSurface(IntSize(aWidth, aHeight),
     510             :                                      SurfaceFormat::B8G8R8A8,
     511           0 :                                      /* aZero = */ true);
     512           0 :   if (NS_WARN_IF(!dataSurface)) {
     513             :     return NS_ERROR_FAILURE;
     514             :   }
     515             : 
     516           0 :   DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::READ_WRITE);
     517           0 :   if (!map.IsMapped()) {
     518             :     return NS_ERROR_FAILURE;
     519             :   }
     520             : 
     521             :   RefPtr<DrawTarget> dt =
     522           0 :     Factory::CreateDrawTargetForData(BackendType::SKIA,
     523             :                                      map.GetData(),
     524           0 :                                      dataSurface->GetSize(),
     525             :                                      map.GetStride(),
     526           0 :                                      SurfaceFormat::B8G8R8A8);
     527           0 :   if (!dt) {
     528           0 :     gfxWarning() <<
     529           0 :       "imgTools::EncodeCroppedImage failed in CreateDrawTargetForData";
     530           0 :     return NS_ERROR_OUT_OF_MEMORY;
     531             :   }
     532           0 :   dt->CopySurface(frame,
     533           0 :                   IntRect(aOffsetX, aOffsetY, aWidth, aHeight),
     534           0 :                   IntPoint(0, 0));
     535             : 
     536           0 :   return EncodeImageData(dataSurface, map, aMimeType, aOutputOptions, aStream);
     537             : }
     538             : 
     539             : NS_IMETHODIMP
     540           0 : imgTools::CreateScriptedObserver(imgIScriptedNotificationObserver* aInner,
     541             :                                  imgINotificationObserver** aObserver)
     542             : {
     543           0 :   NS_ADDREF(*aObserver = new ScriptedNotificationObserver(aInner));
     544           0 :   return NS_OK;
     545             : }
     546             : 
     547             : NS_IMETHODIMP
     548           0 : imgTools::GetImgLoaderForDocument(nsIDocument* aDoc, imgILoader** aLoader)
     549             : {
     550           0 :   NS_IF_ADDREF(*aLoader = nsContentUtils::GetImgLoaderForDocument(aDoc));
     551           0 :   return NS_OK;
     552             : }
     553             : 
     554             : NS_IMETHODIMP
     555           0 : imgTools::GetImgCacheForDocument(nsIDocument* aDoc, imgICache** aCache)
     556             : {
     557           0 :   nsCOMPtr<imgILoader> loader;
     558           0 :   nsresult rv = GetImgLoaderForDocument(aDoc, getter_AddRefs(loader));
     559           0 :   NS_ENSURE_SUCCESS(rv, rv);
     560             :   return CallQueryInterface(loader, aCache);
     561             : }
     562             : 
     563             : } // namespace image
     564             : } // namespace mozilla

Generated by: LCOV version 1.13-14-ga5dd952