LCOV - code coverage report
Current view: top level - image - DecoderFactory.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 66 141 46.8 %
Date: 2017-07-14 16:53:18 Functions: 5 8 62.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "DecoderFactory.h"
       7             : 
       8             : #include "nsMimeTypes.h"
       9             : #include "mozilla/RefPtr.h"
      10             : 
      11             : #include "AnimationSurfaceProvider.h"
      12             : #include "Decoder.h"
      13             : #include "IDecodingTask.h"
      14             : #include "nsPNGDecoder.h"
      15             : #include "nsGIFDecoder2.h"
      16             : #include "nsJPEGDecoder.h"
      17             : #include "nsBMPDecoder.h"
      18             : #include "nsICODecoder.h"
      19             : #include "nsIconDecoder.h"
      20             : 
      21             : namespace mozilla {
      22             : 
      23             : using namespace gfx;
      24             : 
      25             : namespace image {
      26             : 
      27             : /* static */ DecoderType
      28          24 : DecoderFactory::GetDecoderType(const char* aMimeType)
      29             : {
      30             :   // By default we don't know.
      31          24 :   DecoderType type = DecoderType::UNKNOWN;
      32             : 
      33             :   // PNG
      34          24 :   if (!strcmp(aMimeType, IMAGE_PNG)) {
      35          18 :     type = DecoderType::PNG;
      36           6 :   } else if (!strcmp(aMimeType, IMAGE_X_PNG)) {
      37           0 :     type = DecoderType::PNG;
      38           6 :   } else if (!strcmp(aMimeType, IMAGE_APNG)) {
      39           0 :     type = DecoderType::PNG;
      40             : 
      41             :   // GIF
      42           6 :   } else if (!strcmp(aMimeType, IMAGE_GIF)) {
      43           1 :     type = DecoderType::GIF;
      44             : 
      45             :   // JPEG
      46           5 :   } else if (!strcmp(aMimeType, IMAGE_JPEG)) {
      47           0 :     type = DecoderType::JPEG;
      48           5 :   } else if (!strcmp(aMimeType, IMAGE_PJPEG)) {
      49           0 :     type = DecoderType::JPEG;
      50           5 :   } else if (!strcmp(aMimeType, IMAGE_JPG)) {
      51           0 :     type = DecoderType::JPEG;
      52             : 
      53             :   // BMP
      54           5 :   } else if (!strcmp(aMimeType, IMAGE_BMP)) {
      55           0 :     type = DecoderType::BMP;
      56           5 :   } else if (!strcmp(aMimeType, IMAGE_BMP_MS)) {
      57           0 :     type = DecoderType::BMP;
      58             : 
      59             :   // ICO
      60           5 :   } else if (!strcmp(aMimeType, IMAGE_ICO)) {
      61           0 :     type = DecoderType::ICO;
      62           5 :   } else if (!strcmp(aMimeType, IMAGE_ICO_MS)) {
      63           0 :     type = DecoderType::ICO;
      64             : 
      65             :   // Icon
      66           5 :   } else if (!strcmp(aMimeType, IMAGE_ICON_MS)) {
      67           0 :     type = DecoderType::ICON;
      68             :   }
      69             : 
      70          24 :   return type;
      71             : }
      72             : 
      73             : /* static */ already_AddRefed<Decoder>
      74          33 : DecoderFactory::GetDecoder(DecoderType aType,
      75             :                            RasterImage* aImage,
      76             :                            bool aIsRedecode)
      77             : {
      78          66 :   RefPtr<Decoder> decoder;
      79             : 
      80          33 :   switch (aType) {
      81             :     case DecoderType::PNG:
      82          31 :       decoder = new nsPNGDecoder(aImage);
      83          31 :       break;
      84             :     case DecoderType::GIF:
      85           2 :       decoder = new nsGIFDecoder2(aImage);
      86           2 :       break;
      87             :     case DecoderType::JPEG:
      88             :       // If we have all the data we don't want to waste cpu time doing
      89             :       // a progressive decode.
      90             :       decoder = new nsJPEGDecoder(aImage,
      91             :                                   aIsRedecode ? Decoder::SEQUENTIAL
      92           0 :                                               : Decoder::PROGRESSIVE);
      93           0 :       break;
      94             :     case DecoderType::BMP:
      95           0 :       decoder = new nsBMPDecoder(aImage);
      96           0 :       break;
      97             :     case DecoderType::ICO:
      98           0 :       decoder = new nsICODecoder(aImage);
      99           0 :       break;
     100             :     case DecoderType::ICON:
     101           0 :       decoder = new nsIconDecoder(aImage);
     102           0 :       break;
     103             :     default:
     104           0 :       MOZ_ASSERT_UNREACHABLE("Unknown decoder type");
     105             :   }
     106             : 
     107          66 :   return decoder.forget();
     108             : }
     109             : 
     110             : /* static */ already_AddRefed<IDecodingTask>
     111          12 : DecoderFactory::CreateDecoder(DecoderType aType,
     112             :                               NotNull<RasterImage*> aImage,
     113             :                               NotNull<SourceBuffer*> aSourceBuffer,
     114             :                               const IntSize& aIntrinsicSize,
     115             :                               const IntSize& aOutputSize,
     116             :                               DecoderFlags aDecoderFlags,
     117             :                               SurfaceFlags aSurfaceFlags)
     118             : {
     119          12 :   if (aType == DecoderType::UNKNOWN) {
     120           0 :     return nullptr;
     121             :   }
     122             : 
     123             :   // Create an anonymous decoder. Interaction with the SurfaceCache and the
     124             :   // owning RasterImage will be mediated by DecodedSurfaceProvider.
     125             :   RefPtr<Decoder> decoder =
     126          24 :     GetDecoder(aType, nullptr, bool(aDecoderFlags & DecoderFlags::IS_REDECODE));
     127          12 :   MOZ_ASSERT(decoder, "Should have a decoder now");
     128             : 
     129             :   // Initialize the decoder.
     130          12 :   decoder->SetMetadataDecode(false);
     131          12 :   decoder->SetIterator(aSourceBuffer->Iterator());
     132          12 :   decoder->SetOutputSize(aOutputSize);
     133          12 :   decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::FIRST_FRAME_ONLY);
     134          12 :   decoder->SetSurfaceFlags(aSurfaceFlags);
     135             : 
     136          12 :   if (NS_FAILED(decoder->Init())) {
     137           0 :     return nullptr;
     138             :   }
     139             : 
     140             :   // Create a DecodedSurfaceProvider which will manage the decoding process and
     141             :   // make this decoder's output available in the surface cache.
     142             :   SurfaceKey surfaceKey =
     143          24 :     RasterSurfaceKey(aOutputSize, aSurfaceFlags, PlaybackType::eStatic);
     144             :   NotNull<RefPtr<DecodedSurfaceProvider>> provider =
     145          24 :     WrapNotNull(new DecodedSurfaceProvider(aImage,
     146             :                                            surfaceKey,
     147          60 :                                            WrapNotNull(decoder)));
     148             : 
     149             :   // Attempt to insert the surface provider into the surface cache right away so
     150             :   // we won't trigger any more decoders with the same parameters.
     151          12 :   if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) {
     152           0 :     return nullptr;
     153             :   }
     154             : 
     155             :   // Return the surface provider in its IDecodingTask guise.
     156          24 :   RefPtr<IDecodingTask> task = provider.get();
     157          12 :   return task.forget();
     158             : }
     159             : 
     160             : /* static */ already_AddRefed<IDecodingTask>
     161           2 : DecoderFactory::CreateAnimationDecoder(DecoderType aType,
     162             :                                        NotNull<RasterImage*> aImage,
     163             :                                        NotNull<SourceBuffer*> aSourceBuffer,
     164             :                                        const IntSize& aIntrinsicSize,
     165             :                                        DecoderFlags aDecoderFlags,
     166             :                                        SurfaceFlags aSurfaceFlags)
     167             : {
     168           2 :   if (aType == DecoderType::UNKNOWN) {
     169           0 :     return nullptr;
     170             :   }
     171             : 
     172           2 :   MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG,
     173             :              "Calling CreateAnimationDecoder for non-animating DecoderType");
     174             : 
     175             :   // Create an anonymous decoder. Interaction with the SurfaceCache and the
     176             :   // owning RasterImage will be mediated by AnimationSurfaceProvider.
     177           4 :   RefPtr<Decoder> decoder = GetDecoder(aType, nullptr, /* aIsRedecode = */ true);
     178           2 :   MOZ_ASSERT(decoder, "Should have a decoder now");
     179             : 
     180             :   // Initialize the decoder.
     181           2 :   decoder->SetMetadataDecode(false);
     182           2 :   decoder->SetIterator(aSourceBuffer->Iterator());
     183           2 :   decoder->SetDecoderFlags(aDecoderFlags | DecoderFlags::IS_REDECODE);
     184           2 :   decoder->SetSurfaceFlags(aSurfaceFlags);
     185             : 
     186           2 :   if (NS_FAILED(decoder->Init())) {
     187           0 :     return nullptr;
     188             :   }
     189             : 
     190             :   // Create an AnimationSurfaceProvider which will manage the decoding process
     191             :   // and make this decoder's output available in the surface cache.
     192             :   SurfaceKey surfaceKey =
     193           4 :     RasterSurfaceKey(aIntrinsicSize, aSurfaceFlags, PlaybackType::eAnimated);
     194             :   NotNull<RefPtr<AnimationSurfaceProvider>> provider =
     195           4 :     WrapNotNull(new AnimationSurfaceProvider(aImage,
     196             :                                              surfaceKey,
     197          10 :                                              WrapNotNull(decoder)));
     198             : 
     199             :   // Attempt to insert the surface provider into the surface cache right away so
     200             :   // we won't trigger any more decoders with the same parameters.
     201           2 :   if (SurfaceCache::Insert(provider) != InsertOutcome::SUCCESS) {
     202           0 :     return nullptr;
     203             :   }
     204             : 
     205             :   // Return the surface provider in its IDecodingTask guise.
     206           4 :   RefPtr<IDecodingTask> task = provider.get();
     207           2 :   return task.forget();
     208             : }
     209             : 
     210             : /* static */ already_AddRefed<IDecodingTask>
     211          19 : DecoderFactory::CreateMetadataDecoder(DecoderType aType,
     212             :                                       NotNull<RasterImage*> aImage,
     213             :                                       NotNull<SourceBuffer*> aSourceBuffer)
     214             : {
     215          19 :   if (aType == DecoderType::UNKNOWN) {
     216           0 :     return nullptr;
     217             :   }
     218             : 
     219             :   RefPtr<Decoder> decoder =
     220          38 :     GetDecoder(aType, aImage, /* aIsRedecode = */ false);
     221          19 :   MOZ_ASSERT(decoder, "Should have a decoder now");
     222             : 
     223             :   // Initialize the decoder.
     224          19 :   decoder->SetMetadataDecode(true);
     225          19 :   decoder->SetIterator(aSourceBuffer->Iterator());
     226             : 
     227          19 :   if (NS_FAILED(decoder->Init())) {
     228           0 :     return nullptr;
     229             :   }
     230             : 
     231          57 :   RefPtr<IDecodingTask> task = new MetadataDecodingTask(WrapNotNull(decoder));
     232          19 :   return task.forget();
     233             : }
     234             : 
     235             : /* static */ already_AddRefed<Decoder>
     236           0 : DecoderFactory::CreateDecoderForICOResource(DecoderType aType,
     237             :                                             NotNull<SourceBuffer*> aSourceBuffer,
     238             :                                             NotNull<nsICODecoder*> aICODecoder,
     239             :                                             const Maybe<uint32_t>& aDataOffset
     240             :                                               /* = Nothing() */)
     241             : {
     242             :   // Create the decoder.
     243           0 :   RefPtr<Decoder> decoder;
     244           0 :   switch (aType) {
     245             :     case DecoderType::BMP:
     246           0 :       MOZ_ASSERT(aDataOffset);
     247           0 :       decoder = new nsBMPDecoder(aICODecoder->GetImageMaybeNull(), *aDataOffset);
     248           0 :       break;
     249             : 
     250             :     case DecoderType::PNG:
     251           0 :       MOZ_ASSERT(!aDataOffset);
     252           0 :       decoder = new nsPNGDecoder(aICODecoder->GetImageMaybeNull());
     253           0 :       break;
     254             : 
     255             :     default:
     256           0 :       MOZ_ASSERT_UNREACHABLE("Invalid ICO resource decoder type");
     257             :       return nullptr;
     258             :   }
     259             : 
     260           0 :   MOZ_ASSERT(decoder);
     261             : 
     262             :   // Initialize the decoder, copying settings from @aICODecoder.
     263           0 :   MOZ_ASSERT(!aICODecoder->IsMetadataDecode());
     264           0 :   decoder->SetMetadataDecode(aICODecoder->IsMetadataDecode());
     265           0 :   decoder->SetIterator(aSourceBuffer->Iterator());
     266           0 :   decoder->SetOutputSize(aICODecoder->OutputSize());
     267           0 :   decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags());
     268           0 :   decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags());
     269           0 :   decoder->SetFinalizeFrames(false);
     270             : 
     271           0 :   if (NS_FAILED(decoder->Init())) {
     272           0 :     return nullptr;
     273             :   }
     274             : 
     275           0 :   return decoder.forget();
     276             : }
     277             : 
     278             : /* static */ already_AddRefed<Decoder>
     279           0 : DecoderFactory::CreateAnonymousDecoder(DecoderType aType,
     280             :                                        NotNull<SourceBuffer*> aSourceBuffer,
     281             :                                        const Maybe<IntSize>& aOutputSize,
     282             :                                        SurfaceFlags aSurfaceFlags)
     283             : {
     284           0 :   if (aType == DecoderType::UNKNOWN) {
     285           0 :     return nullptr;
     286             :   }
     287             : 
     288             :   RefPtr<Decoder> decoder =
     289           0 :     GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
     290           0 :   MOZ_ASSERT(decoder, "Should have a decoder now");
     291             : 
     292             :   // Initialize the decoder.
     293           0 :   decoder->SetMetadataDecode(false);
     294           0 :   decoder->SetIterator(aSourceBuffer->Iterator());
     295             : 
     296             :   // Anonymous decoders are always transient; we don't want to optimize surfaces
     297             :   // or do any other expensive work that might be wasted.
     298           0 :   DecoderFlags decoderFlags = DecoderFlags::IMAGE_IS_TRANSIENT;
     299             : 
     300             :   // Without an image, the decoder can't store anything in the SurfaceCache, so
     301             :   // callers will only be able to retrieve the most recent frame via
     302             :   // Decoder::GetCurrentFrame(). That means that anonymous decoders should
     303             :   // always be first-frame-only decoders, because nobody ever wants the *last*
     304             :   // frame.
     305           0 :   decoderFlags |= DecoderFlags::FIRST_FRAME_ONLY;
     306             : 
     307           0 :   decoder->SetDecoderFlags(decoderFlags);
     308           0 :   decoder->SetSurfaceFlags(aSurfaceFlags);
     309             : 
     310             :   // Set an output size for downscale-during-decode if requested.
     311           0 :   if (aOutputSize) {
     312           0 :     decoder->SetOutputSize(*aOutputSize);
     313             :   }
     314             : 
     315           0 :   if (NS_FAILED(decoder->Init())) {
     316           0 :     return nullptr;
     317             :   }
     318             : 
     319           0 :   return decoder.forget();
     320             : }
     321             : 
     322             : /* static */ already_AddRefed<Decoder>
     323           0 : DecoderFactory::CreateAnonymousMetadataDecoder(DecoderType aType,
     324             :                                                NotNull<SourceBuffer*> aSourceBuffer)
     325             : {
     326           0 :   if (aType == DecoderType::UNKNOWN) {
     327           0 :     return nullptr;
     328             :   }
     329             : 
     330             :   RefPtr<Decoder> decoder =
     331           0 :     GetDecoder(aType, /* aImage = */ nullptr, /* aIsRedecode = */ false);
     332           0 :   MOZ_ASSERT(decoder, "Should have a decoder now");
     333             : 
     334             :   // Initialize the decoder.
     335           0 :   decoder->SetMetadataDecode(true);
     336           0 :   decoder->SetIterator(aSourceBuffer->Iterator());
     337           0 :   decoder->SetDecoderFlags(DecoderFlags::FIRST_FRAME_ONLY);
     338             : 
     339           0 :   if (NS_FAILED(decoder->Init())) {
     340           0 :     return nullptr;
     341             :   }
     342             : 
     343           0 :   return decoder.forget();
     344             : }
     345             : 
     346             : } // namespace image
     347             : } // namespace mozilla

Generated by: LCOV version 1.13