LCOV - code coverage report
Current view: top level - image - SurfacePipeFactory.h (source / functions) Hit Total Coverage
Test: output.info Lines: 26 59 44.1 %
Date: 2017-07-14 16:53:18 Functions: 5 19 26.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       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             : #ifndef mozilla_image_SurfacePipeFactory_h
       8             : #define mozilla_image_SurfacePipeFactory_h
       9             : 
      10             : #include "SurfacePipe.h"
      11             : #include "SurfaceFilters.h"
      12             : 
      13             : namespace mozilla {
      14             : namespace image {
      15             : 
      16             : namespace detail {
      17             : 
      18             : /**
      19             :  * FilterPipeline is a helper template for SurfacePipeFactory that determines
      20             :  * the full type of the sequence of SurfaceFilters that a sequence of
      21             :  * configuration structs corresponds to. To make this work, all configuration
      22             :  * structs must include a typedef 'Filter' that identifies the SurfaceFilter
      23             :  * they configure.
      24             :  */
      25             : template <typename... Configs>
      26             : struct FilterPipeline;
      27             : 
      28             : template <typename Config, typename... Configs>
      29             : struct FilterPipeline<Config, Configs...>
      30             : {
      31             :   typedef typename Config::template Filter<typename FilterPipeline<Configs...>::Type> Type;
      32             : };
      33             : 
      34             : template <typename Config>
      35             : struct FilterPipeline<Config>
      36             : {
      37             :   typedef typename Config::Filter Type;
      38             : };
      39             : 
      40             : } // namespace detail
      41             : 
      42             : /**
      43             :  * Flags for SurfacePipeFactory, used in conjuction with the factory functions
      44             :  * in SurfacePipeFactory to enable or disable various SurfacePipe
      45             :  * functionality.
      46             :  */
      47             : enum class SurfacePipeFlags
      48             : {
      49             :   DEINTERLACE         = 1 << 0,  // If set, deinterlace the image.
      50             : 
      51             :   ADAM7_INTERPOLATE   = 1 << 1,  // If set, the caller is deinterlacing the
      52             :                                  // image using ADAM7, and we may want to
      53             :                                  // interpolate it for better intermediate results.
      54             : 
      55             :   FLIP_VERTICALLY     = 1 << 2,  // If set, flip the image vertically.
      56             : 
      57             :   PROGRESSIVE_DISPLAY = 1 << 3   // If set, we expect the image to be displayed
      58             :                                  // progressively. This enables features that
      59             :                                  // result in a better user experience for
      60             :                                  // progressive display but which may be more
      61             :                                  // computationally expensive.
      62             : };
      63         220 : MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SurfacePipeFlags)
      64             : 
      65             : class SurfacePipeFactory
      66             : {
      67             : public:
      68             :   /**
      69             :    * Creates and initializes a normal (i.e., non-paletted) SurfacePipe.
      70             :    *
      71             :    * @param aDecoder The decoder whose current frame the SurfacePipe will write
      72             :    *                 to.
      73             :    * @param aFrameNum Which frame the SurfacePipe will write to. This will be 0
      74             :    *                  for non-animated images.
      75             :    * @param aInputSize The original size of the image.
      76             :    * @param aOutputSize The size the SurfacePipe should output. Must be the same
      77             :    *                    as @aInputSize or smaller. If smaller, the image will be
      78             :    *                    downscaled during decoding.
      79             :    * @param aFrameRect The portion of the image that actually contains data.
      80             :    * @param aFormat The surface format of the image; generally B8G8R8A8 or
      81             :    *                B8G8R8X8.
      82             :    * @param aFlags Flags enabling or disabling various functionality for the
      83             :    *               SurfacePipe; see the SurfacePipeFlags documentation for more
      84             :    *               information.
      85             :    *
      86             :    * @return A SurfacePipe if the parameters allowed one to be created
      87             :    *         successfully, or Nothing() if the SurfacePipe could not be
      88             :    *         initialized.
      89             :    */
      90             :   static Maybe<SurfacePipe>
      91          48 :   CreateSurfacePipe(Decoder* aDecoder,
      92             :                     uint32_t aFrameNum,
      93             :                     const nsIntSize& aInputSize,
      94             :                     const nsIntSize& aOutputSize,
      95             :                     const nsIntRect& aFrameRect,
      96             :                     gfx::SurfaceFormat aFormat,
      97             :                     SurfacePipeFlags aFlags)
      98             :   {
      99          48 :     const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE);
     100          48 :     const bool flipVertically = bool(aFlags & SurfacePipeFlags::FLIP_VERTICALLY);
     101          48 :     const bool progressiveDisplay = bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY);
     102          48 :     const bool downscale = aInputSize != aOutputSize;
     103             :     const bool removeFrameRect =
     104          48 :       !aFrameRect.IsEqualEdges(nsIntRect(0, 0, aInputSize.width, aInputSize.height));
     105             : 
     106             :     // Don't interpolate if we're sure we won't show this surface to the user
     107             :     // until it's completely decoded. The final pass of an ADAM7 image doesn't
     108             :     // need interpolation, so we only need to interpolate if we'll be displaying
     109             :     // the image while it's still being decoded.
     110         144 :     const bool adam7Interpolate = bool(aFlags & SurfacePipeFlags::ADAM7_INTERPOLATE) &&
     111          48 :                                   progressiveDisplay;
     112             : 
     113          48 :     if (deinterlace && adam7Interpolate) {
     114           0 :       MOZ_ASSERT_UNREACHABLE("ADAM7 deinterlacing is handled by libpng");
     115             :       return Nothing();
     116             :     }
     117             : 
     118             :     // Construct configurations for the SurfaceFilters. Note that the order of
     119             :     // these filters is significant. We want to deinterlace or interpolate raw
     120             :     // input rows, before any other transformations, and we want to remove the
     121             :     // frame rect (which may involve adding blank rows or columns to the image)
     122             :     // before any downscaling, so that the new rows and columns are taken into
     123             :     // account.
     124          48 :     DeinterlacingConfig<uint32_t> deinterlacingConfig { progressiveDisplay };
     125             :     ADAM7InterpolatingConfig interpolatingConfig;
     126          48 :     RemoveFrameRectConfig removeFrameRectConfig { aFrameRect };
     127          48 :     DownscalingConfig downscalingConfig { aInputSize, aFormat };
     128             :     SurfaceConfig surfaceConfig { aDecoder, aFrameNum, aOutputSize,
     129          48 :                                   aFormat, flipVertically };
     130             : 
     131          96 :     Maybe<SurfacePipe> pipe;
     132             : 
     133          48 :     if (downscale) {
     134           0 :       if (removeFrameRect) {
     135           0 :         if (deinterlace) {
     136           0 :           pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig,
     137           0 :                           downscalingConfig, surfaceConfig);
     138           0 :         } else if (adam7Interpolate) {
     139           0 :           pipe = MakePipe(interpolatingConfig, removeFrameRectConfig,
     140           0 :                           downscalingConfig, surfaceConfig);
     141             :         } else {  // (deinterlace and adam7Interpolate are false)
     142           0 :           pipe = MakePipe(removeFrameRectConfig, downscalingConfig, surfaceConfig);
     143             :         }
     144             :       } else {  // (removeFrameRect is false)
     145           0 :         if (deinterlace) {
     146           0 :           pipe = MakePipe(deinterlacingConfig, downscalingConfig, surfaceConfig);
     147           0 :         } else if (adam7Interpolate) {
     148           0 :           pipe = MakePipe(interpolatingConfig, downscalingConfig, surfaceConfig);
     149             :         } else {  // (deinterlace and adam7Interpolate are false)
     150           0 :           pipe = MakePipe(downscalingConfig, surfaceConfig);
     151             :         }
     152             :       }
     153             :     } else {  // (downscale is false)
     154          48 :       if (removeFrameRect) {
     155           0 :         if (deinterlace) {
     156           0 :           pipe = MakePipe(deinterlacingConfig, removeFrameRectConfig, surfaceConfig);
     157           0 :         } else if (adam7Interpolate) {
     158           0 :           pipe = MakePipe(interpolatingConfig, removeFrameRectConfig, surfaceConfig);
     159             :         } else {  // (deinterlace and adam7Interpolate are false)
     160           0 :           pipe = MakePipe(removeFrameRectConfig, surfaceConfig);
     161             :         }
     162             :       } else {  // (removeFrameRect is false)
     163          48 :         if (deinterlace) {
     164           0 :           pipe = MakePipe(deinterlacingConfig, surfaceConfig);
     165          48 :         } else if (adam7Interpolate) {
     166           0 :           pipe = MakePipe(interpolatingConfig, surfaceConfig);
     167             :         } else {  // (deinterlace and adam7Interpolate are false)
     168          48 :           pipe = MakePipe(surfaceConfig);
     169             :         }
     170             :       }
     171             :     }
     172             : 
     173          48 :     return pipe;
     174             :   }
     175             : 
     176             :   /**
     177             :    * Creates and initializes a paletted SurfacePipe.
     178             :    *
     179             :    * XXX(seth): We'll remove all support for paletted surfaces in bug 1247520,
     180             :    * which means we can remove CreatePalettedSurfacePipe() entirely.
     181             :    *
     182             :    * @param aDecoder The decoder whose current frame the SurfacePipe will write
     183             :    *                 to.
     184             :    * @param aFrameNum Which frame the SurfacePipe will write to. This will be 0
     185             :    *                  for non-animated images.
     186             :    * @param aInputSize The original size of the image.
     187             :    * @param aFrameRect The portion of the image that actually contains data.
     188             :    * @param aFormat The surface format of the image; generally B8G8R8A8 or
     189             :    *                B8G8R8X8.
     190             :    * @param aPaletteDepth The palette depth of the image.
     191             :    * @param aFlags Flags enabling or disabling various functionality for the
     192             :    *               SurfacePipe; see the SurfacePipeFlags documentation for more
     193             :    *               information.
     194             :    *
     195             :    * @return A SurfacePipe if the parameters allowed one to be created
     196             :    *         successfully, or Nothing() if the SurfacePipe could not be
     197             :    *         initialized.
     198             :    */
     199             :   static Maybe<SurfacePipe>
     200           0 :   CreatePalettedSurfacePipe(Decoder* aDecoder,
     201             :                             uint32_t aFrameNum,
     202             :                             const nsIntSize& aInputSize,
     203             :                             const nsIntRect& aFrameRect,
     204             :                             gfx::SurfaceFormat aFormat,
     205             :                             uint8_t aPaletteDepth,
     206             :                             SurfacePipeFlags aFlags)
     207             :   {
     208           0 :     const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE);
     209           0 :     const bool flipVertically = bool(aFlags & SurfacePipeFlags::FLIP_VERTICALLY);
     210           0 :     const bool progressiveDisplay = bool(aFlags & SurfacePipeFlags::PROGRESSIVE_DISPLAY);
     211             : 
     212             :     // Construct configurations for the SurfaceFilters.
     213           0 :     DeinterlacingConfig<uint8_t> deinterlacingConfig { progressiveDisplay };
     214             :     PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aFrameNum, aInputSize,
     215             :                                                   aFrameRect, aFormat, aPaletteDepth,
     216           0 :                                                   flipVertically };
     217             : 
     218           0 :     Maybe<SurfacePipe> pipe;
     219             : 
     220           0 :     if (deinterlace) {
     221           0 :       pipe = MakePipe(deinterlacingConfig, palettedSurfaceConfig);
     222             :     } else {
     223           0 :       pipe = MakePipe(palettedSurfaceConfig);
     224             :     }
     225             : 
     226           0 :     return pipe;
     227             :   }
     228             : 
     229             : private:
     230             :   template <typename... Configs>
     231             :   static Maybe<SurfacePipe>
     232          48 :   MakePipe(Configs... aConfigs)
     233             :   {
     234          96 :     auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>();
     235          48 :     nsresult rv = pipe->Configure(aConfigs...);
     236          48 :     if (NS_FAILED(rv)) {
     237           0 :       return Nothing();
     238             :     }
     239             : 
     240          48 :     return Some(SurfacePipe { Move(pipe) } );
     241             :   }
     242             : 
     243             :   virtual ~SurfacePipeFactory() = 0;
     244             : };
     245             : 
     246             : } // namespace image
     247             : } // namespace mozilla
     248             : 
     249             : #endif // mozilla_image_SurfacePipeFactory_h

Generated by: LCOV version 1.13