tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Downscaler.h (4880B)


      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 /**
      8 * Downscaler is a high-quality, streaming image downscaler based upon Skia's
      9 * scaling implementation.
     10 */
     11 
     12 #ifndef mozilla_image_Downscaler_h
     13 #define mozilla_image_Downscaler_h
     14 
     15 #include "mozilla/Maybe.h"
     16 #include "mozilla/UniquePtr.h"
     17 #include "gfxPoint.h"
     18 #include "nsRect.h"
     19 #include "mozilla/gfx/ConvolutionFilter.h"
     20 #include "mozilla/gfx/Matrix.h"
     21 
     22 namespace mozilla {
     23 namespace image {
     24 
     25 /**
     26 * DownscalerInvalidRect wraps two invalidation rects: one in terms of the
     27 * original image size, and one in terms of the target size.
     28 */
     29 struct DownscalerInvalidRect {
     30  nsIntRect mOriginalSizeRect;
     31  nsIntRect mTargetSizeRect;
     32 };
     33 
     34 /**
     35 * Downscaler is a high-quality, streaming image downscaler based upon Skia's
     36 * scaling implementation.
     37 *
     38 * Decoders can construct a Downscaler once they know their target size, then
     39 * call BeginFrame() for each frame they decode. They should write a decoded row
     40 * into the buffer returned by RowBuffer(), and then call CommitRow() to signal
     41 * that they have finished.
     42 *
     43 
     44 * Because invalidations need to be computed in terms of the scaled version of
     45 * the image, Downscaler also tracks them. Decoders can call HasInvalidation()
     46 * and TakeInvalidRect() instead of tracking invalidations themselves.
     47 */
     48 class Downscaler {
     49 public:
     50  /// Constructs a new Downscaler which to scale to size @aTargetSize.
     51  explicit Downscaler(const nsIntSize& aTargetSize);
     52  ~Downscaler();
     53 
     54  const nsIntSize& OriginalSize() const { return mOriginalSize; }
     55  const nsIntSize& TargetSize() const { return mTargetSize; }
     56  const nsIntSize FrameSize() const {
     57    return nsIntSize(mFrameRect.Width(), mFrameRect.Height());
     58  }
     59  const gfx::MatrixScalesDouble& Scale() const { return mScale; }
     60 
     61  /**
     62   * Begins a new frame and reinitializes the Downscaler.
     63   *
     64   * @param aOriginalSize The original size of this frame, before scaling.
     65   * @param aFrameRect The region of  the original image which has data.
     66   *                   Every pixel outside @aFrameRect is considered blank and
     67   *                   has zero alpha.
     68   * @param aOutputBuffer The buffer to which the Downscaler should write its
     69   *                      output; this is the same buffer where the Decoder
     70   *                      would write its output when not downscaling during
     71   *                      decode.
     72   * @param aFormat The format of this frame. Performance is a little better if
     73   *                it is opaque.
     74   * @param aFlipVertically If true, output rows will be written to the output
     75   *                        buffer in reverse order vertically, which matches
     76   *                        the way they are stored in some image formats.
     77   */
     78  nsresult BeginFrame(const nsIntSize& aOriginalSize,
     79                      const Maybe<nsIntRect>& aFrameRect,
     80                      uint8_t* aOutputBuffer, gfx::SurfaceFormat aFormat,
     81                      bool aFlipVertically = false);
     82 
     83  bool IsFrameComplete() const {
     84    return mCurrentInLine >= mOriginalSize.height;
     85  }
     86 
     87  /// Retrieves the buffer into which the Decoder should write each row.
     88  uint8_t* RowBuffer() {
     89    return mRowBuffer.get() + mFrameRect.X() * sizeof(uint32_t);
     90  }
     91 
     92  /// Clears the current row buffer.
     93  void ClearRow() { ClearRestOfRow(0); }
     94 
     95  /// Clears the current row buffer starting at @aStartingAtCol.
     96  void ClearRestOfRow(uint32_t aStartingAtCol);
     97 
     98  /// Signals that the decoder has finished writing a row into the row buffer.
     99  void CommitRow();
    100 
    101  /// Returns true if there is a non-empty invalid rect available.
    102  bool HasInvalidation() const;
    103 
    104  /// Takes the Downscaler's current invalid rect and resets it.
    105  DownscalerInvalidRect TakeInvalidRect();
    106 
    107  /**
    108   * Resets the Downscaler's position in the image, for a new progressive pass
    109   * over the same frame. Because the same data structures can be reused, this
    110   * is more efficient than calling BeginFrame.
    111   */
    112  void ResetForNextProgressivePass();
    113 
    114 private:
    115  void DownscaleInputLine();
    116  void ReleaseWindow();
    117  void SkipToRow(int32_t aRow);
    118 
    119  nsIntSize mOriginalSize;
    120  nsIntSize mTargetSize;
    121  nsIntRect mFrameRect;
    122  gfx::MatrixScalesDouble mScale;
    123 
    124  uint8_t* mOutputBuffer;
    125 
    126  UniquePtr<uint8_t[]> mRowBuffer;
    127  UniquePtr<uint8_t*[]> mWindow;
    128 
    129  gfx::ConvolutionFilter mXFilter;
    130  gfx::ConvolutionFilter mYFilter;
    131 
    132  int32_t mWindowCapacity;
    133 
    134  int32_t mLinesInBuffer;
    135  int32_t mPrevInvalidatedLine;
    136  int32_t mCurrentOutLine;
    137  int32_t mCurrentInLine;
    138 
    139  gfx::SurfaceFormat mFormat;
    140  bool mFlipVertically : 1;
    141 };
    142 
    143 }  // namespace image
    144 }  // namespace mozilla
    145 
    146 #endif  // mozilla_image_Downscaler_h