tor-browser

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

AspectRatio.h (5379B)


      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_AspectRatio_h
      8 #define mozilla_AspectRatio_h
      9 
     10 /* The aspect ratio of a box, in a "width / height" format. */
     11 
     12 #include <algorithm>
     13 #include <limits>
     14 
     15 #include "mozilla/gfx/BaseSize.h"
     16 #include "nsCoord.h"
     17 
     18 namespace IPC {
     19 template <typename T>
     20 struct ParamTraits;
     21 }  // namespace IPC
     22 
     23 namespace mozilla {
     24 
     25 enum class LogicalAxis : uint8_t;
     26 class LogicalSize;
     27 class WritingMode;
     28 
     29 enum class UseBoxSizing : uint8_t {
     30  // The aspect ratio works with content box dimensions always.
     31  No,
     32  // The aspect ratio works with the dimensions of the box specified by
     33  // box-sizing.
     34  Yes,
     35 };
     36 
     37 struct AspectRatio {
     38  friend struct IPC::ParamTraits<mozilla::AspectRatio>;
     39 
     40  AspectRatio() = default;
     41  explicit AspectRatio(float aRatio,
     42                       UseBoxSizing aUseBoxSizing = UseBoxSizing::No)
     43      : mRatio(std::max(aRatio, 0.0f)), mUseBoxSizing(aUseBoxSizing) {}
     44 
     45  static AspectRatio FromSize(float aWidth, float aHeight,
     46                              UseBoxSizing aUseBoxSizing = UseBoxSizing::No) {
     47    if (aWidth == 0.0f || aHeight == 0.0f) {
     48      // For the degenerate ratio, we don't care about which box sizing we are
     49      // using, so using default constructor is fine.
     50      return AspectRatio();
     51    }
     52    return AspectRatio(aWidth / aHeight, aUseBoxSizing);
     53  }
     54 
     55  template <typename T, typename Sub, typename Coord>
     56  static AspectRatio FromSize(const gfx::BaseSize<T, Sub, Coord>& aSize) {
     57    return FromSize(aSize.Width(), aSize.Height());
     58  }
     59 
     60  explicit operator bool() const { return mRatio != 0.0f; }
     61 
     62  nscoord ApplyTo(nscoord aCoord) const {
     63    MOZ_DIAGNOSTIC_ASSERT(*this);
     64    return NSCoordSaturatingNonnegativeMultiply(aCoord, mRatio);
     65  }
     66 
     67  float ApplyToFloat(float aFloat) const {
     68    MOZ_DIAGNOSTIC_ASSERT(*this);
     69    return mRatio * aFloat;
     70  }
     71 
     72  // Inverts the ratio, in order to get the height / width ratio.
     73  [[nodiscard]] AspectRatio Inverted() const {
     74    if (!*this) {
     75      return AspectRatio();
     76    }
     77    // Clamp to a small epsilon, in case mRatio is absurdly large & produces
     78    // 0.0f in the division here (so that valid ratios always generate other
     79    // valid ratios when inverted).
     80    return AspectRatio(
     81        std::max(std::numeric_limits<float>::epsilon(), 1.0f / mRatio),
     82        mUseBoxSizing);
     83  }
     84 
     85  [[nodiscard]] inline AspectRatio ConvertToWritingMode(
     86      const WritingMode& aWM) const;
     87 
     88  /**
     89   * This method computes the ratio-dependent size by the ratio-determining size
     90   * and aspect-ratio (i.e. preferred aspect ratio). Basically this function
     91   * will be used in the calculation of 'auto' sizes when the preferred
     92   * aspect ratio is not 'auto'.
     93   *
     94   * @param aRatioDependentAxis  The ratio depenedent axis of the box.
     95   * @param aWM  The writing mode of the box.
     96   * @param aRatioDetermingSize  The content-box size on the ratio determining
     97   *                             axis. Basically, we use this size and |mRatio|
     98   *                             to compute the size on the ratio-dependent
     99   *                             axis.
    100   * @param aContentBoxSizeToBoxSizingAdjust  The border padding box size
    101   *                                          adjustment. We need this because
    102   *                                          aspect-ratio should take the
    103   *                                          box-sizing into account if its
    104   *                                          style is '<ratio>'. If its style
    105   *                                          is 'auto & <ratio>', we should use
    106   *                                          content-box dimensions always.
    107   *                                          If the callers want the ratio to
    108   *                                          apply to the content-box size, we
    109   *                                          should pass a zero LogicalSize.
    110   *                                          If mUseBoxSizing is No, we ignore
    111   *                                          this parameter because we should
    112   *                                          use content box dimensions always.
    113   *
    114   * The return value is the content-box size on the ratio-dependent axis.
    115   * Plese see the definition of the ratio-dependent axis and the
    116   * ratio-determining axis in the spec:
    117   * https://drafts.csswg.org/css-sizing-4/#aspect-ratio
    118   */
    119  [[nodiscard]] nscoord ComputeRatioDependentSize(
    120      LogicalAxis aRatioDependentAxis, const WritingMode& aWM,
    121      nscoord aRatioDeterminingSize,
    122      const LogicalSize& aContentBoxSizeToBoxSizingAdjust) const;
    123 
    124  bool operator==(const AspectRatio&) const = default;
    125  bool operator!=(const AspectRatio&) const = default;
    126 
    127  bool operator<(const AspectRatio& aOther) const {
    128    MOZ_ASSERT(
    129        mUseBoxSizing == aOther.mUseBoxSizing,
    130        "Do not compare AspectRatio if their mUseBoxSizing are different.");
    131    return mRatio < aOther.mRatio;
    132  }
    133 
    134 private:
    135  // 0.0f represents no aspect ratio.
    136  float mRatio = 0.0f;
    137  UseBoxSizing mUseBoxSizing = UseBoxSizing::No;
    138 };
    139 
    140 }  // namespace mozilla
    141 
    142 #endif  // mozilla_AspectRatio_h