tor-browser

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

Coord.h (7451B)


      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_GFX_COORD_H_
      8 #define MOZILLA_GFX_COORD_H_
      9 
     10 #include "mozilla/Attributes.h"
     11 #include "mozilla/FloatingPoint.h"
     12 #include "Types.h"
     13 #include "BaseCoord.h"
     14 
     15 #include <cmath>
     16 #include <type_traits>
     17 
     18 namespace mozilla {
     19 
     20 namespace gfx {
     21 
     22 template <class Units, class Rep = int32_t>
     23 struct IntCoordTyped;
     24 template <class Units, class F = Float>
     25 struct CoordTyped;
     26 
     27 }  // namespace gfx
     28 
     29 }  // namespace mozilla
     30 
     31 namespace std {
     32 
     33 template <class Units, class Rep>
     34 struct common_type<mozilla::gfx::IntCoordTyped<Units, Rep>, float> {
     35  using type = mozilla::gfx::CoordTyped<Units, common_type_t<Rep, float>>;
     36 };
     37 
     38 template <class Units, class Rep>
     39 struct common_type<mozilla::gfx::IntCoordTyped<Units, Rep>, double> {
     40  using type = mozilla::gfx::CoordTyped<Units, common_type_t<Rep, double>>;
     41 };
     42 
     43 template <class Units, class Rep>
     44 struct common_type<mozilla::gfx::IntCoordTyped<Units, Rep>, int32_t> {
     45  using type = mozilla::gfx::IntCoordTyped<Units, common_type_t<Rep, int32_t>>;
     46 };
     47 
     48 template <class Units, class Rep>
     49 struct common_type<mozilla::gfx::IntCoordTyped<Units, Rep>, uint32_t> {
     50  using type = mozilla::gfx::IntCoordTyped<Units, common_type_t<Rep, uint32_t>>;
     51 };
     52 
     53 template <class Units, class F, class T>
     54 struct common_type<mozilla::gfx::CoordTyped<Units, F>, T> {
     55  using type = mozilla::gfx::CoordTyped<Units, common_type_t<F, T>>;
     56 };
     57 
     58 // With a few exceptions, we use CoordTyped values with a float representation.
     59 // These are the types for which we have short typedefs like
     60 // CSSCoord, and the types expected in most interfaces.
     61 // So, for float inputs, keep the results as float even if the other
     62 // operand is a double, accepting a slight loss of precision.
     63 template <class Units, class T>
     64 struct common_type<mozilla::gfx::CoordTyped<Units, float>, T> {
     65  using type = mozilla::gfx::CoordTyped<Units, float>;
     66 };
     67 
     68 }  // namespace std
     69 
     70 namespace mozilla {
     71 
     72 template <typename>
     73 struct IsPixel;
     74 
     75 namespace gfx {
     76 
     77 // Should only be used to define generic typedefs like Coord, Point, etc.
     78 struct UnknownUnits {};
     79 
     80 // This is a base class that provides mixed-type operator overloads between
     81 // a strongly-typed Coord and a Primitive value. It is needed to avoid
     82 // ambiguities at mixed-type call sites, because Coord classes are implicitly
     83 // convertible to their underlying value type. As we transition more of our code
     84 // to strongly-typed classes, we may be able to remove some or all of these
     85 // overloads.
     86 
     87 template <bool Enable, class Coord, class Primitive>
     88 struct CoordOperatorsHelper {
     89  // Using SFINAE (Substitution Failure Is Not An Error) to suppress redundant
     90  // operators
     91 };
     92 
     93 template <class Coord, class Primitive>
     94 struct CoordOperatorsHelper<true, Coord, Primitive> {
     95  friend bool operator==(Coord aA, Primitive aB) { return aA.value == aB; }
     96  friend bool operator==(Primitive aA, Coord aB) { return aA == aB.value; }
     97  friend bool operator!=(Coord aA, Primitive aB) { return aA.value != aB; }
     98  friend bool operator!=(Primitive aA, Coord aB) { return aA != aB.value; }
     99 
    100  friend auto operator+(Coord aA, Primitive aB) { return aA.value + aB; }
    101  friend auto operator+(Primitive aA, Coord aB) { return aA + aB.value; }
    102  friend auto operator-(Coord aA, Primitive aB) { return aA.value - aB; }
    103  friend auto operator-(Primitive aA, Coord aB) { return aA - aB.value; }
    104  friend auto operator*(Coord aCoord, Primitive aScale) {
    105    return std::common_type_t<Coord, Primitive>(aCoord.value * aScale);
    106  }
    107  friend auto operator*(Primitive aScale, Coord aCoord) {
    108    return aCoord * aScale;
    109  }
    110  friend auto operator/(Coord aCoord, Primitive aScale) {
    111    return std::common_type_t<Coord, Primitive>(aCoord.value / aScale);
    112  }
    113  // 'scale / coord' is intentionally omitted because it doesn't make sense.
    114 };
    115 
    116 template <class Units, class Rep>
    117 struct MOZ_EMPTY_BASES IntCoordTyped
    118    : public BaseCoord<Rep, IntCoordTyped<Units, Rep>>,
    119      public CoordOperatorsHelper<true, IntCoordTyped<Units, Rep>, float>,
    120      public CoordOperatorsHelper<true, IntCoordTyped<Units, Rep>, double> {
    121  static_assert(IsPixel<Units>::value,
    122                "'Units' must be a coordinate system tag");
    123 
    124  using Super = BaseCoord<Rep, IntCoordTyped<Units, Rep>>;
    125 
    126  constexpr IntCoordTyped() : Super() {
    127    static_assert(sizeof(IntCoordTyped) == sizeof(Rep),
    128                  "Would be unfortunate otherwise!");
    129  }
    130  template <class T, typename = typename std::enable_if_t<
    131                         std::is_integral_v<T> || std::is_enum_v<T>>>
    132  constexpr MOZ_IMPLICIT IntCoordTyped(T aValue) : Super(aValue) {
    133    static_assert(sizeof(IntCoordTyped) == sizeof(Rep),
    134                  "Would be unfortunate otherwise!");
    135  }
    136 };
    137 
    138 template <class Units, class F>
    139 struct MOZ_EMPTY_BASES CoordTyped
    140    : public BaseCoord<F, CoordTyped<Units, F>>,
    141      public CoordOperatorsHelper<!std::is_same_v<F, int32_t>,
    142                                  CoordTyped<Units, F>, int32_t>,
    143      public CoordOperatorsHelper<!std::is_same_v<F, uint32_t>,
    144                                  CoordTyped<Units, F>, uint32_t>,
    145      public CoordOperatorsHelper<!std::is_same_v<F, double>,
    146                                  CoordTyped<Units, F>, double>,
    147      public CoordOperatorsHelper<!std::is_same_v<F, float>,
    148                                  CoordTyped<Units, F>, float> {
    149  static_assert(IsPixel<Units>::value,
    150                "'Units' must be a coordinate system tag");
    151 
    152  using Super = BaseCoord<F, CoordTyped<Units, F>>;
    153 
    154  constexpr CoordTyped() : Super() {
    155    static_assert(sizeof(CoordTyped) == sizeof(F),
    156                  "Would be unfortunate otherwise!");
    157  }
    158  constexpr MOZ_IMPLICIT CoordTyped(F aValue) : Super(aValue) {
    159    static_assert(sizeof(CoordTyped) == sizeof(F),
    160                  "Would be unfortunate otherwise!");
    161  }
    162  explicit constexpr CoordTyped(const IntCoordTyped<Units>& aCoord)
    163      : Super(F(aCoord.value)) {
    164    static_assert(sizeof(CoordTyped) == sizeof(F),
    165                  "Would be unfortunate otherwise!");
    166  }
    167 
    168  void Round() { this->value = floor(this->value + 0.5); }
    169  void Truncate() { this->value = int32_t(this->value); }
    170 
    171  IntCoordTyped<Units> Rounded() const {
    172    return IntCoordTyped<Units>(int32_t(floor(this->value + 0.5)));
    173  }
    174  IntCoordTyped<Units> Truncated() const {
    175    return IntCoordTyped<Units>(int32_t(this->value));
    176  }
    177 };
    178 
    179 typedef CoordTyped<UnknownUnits> Coord;
    180 
    181 }  // namespace gfx
    182 
    183 template <class Units, class F>
    184 static MOZ_ALWAYS_INLINE bool FuzzyEqualsAdditive(
    185    gfx::CoordTyped<Units, F> aValue1, gfx::CoordTyped<Units, F> aValue2,
    186    gfx::CoordTyped<Units, F> aEpsilon =
    187        detail::FuzzyEqualsEpsilon<F>::value()) {
    188  return FuzzyEqualsAdditive(aValue1.value, aValue2.value, aEpsilon.value);
    189 }
    190 
    191 template <class Units, class F>
    192 static MOZ_ALWAYS_INLINE bool FuzzyEqualsMultiplicative(
    193    gfx::CoordTyped<Units, F> aValue1, gfx::CoordTyped<Units, F> aValue2,
    194    gfx::CoordTyped<Units, F> aEpsilon =
    195        detail::FuzzyEqualsEpsilon<F>::value()) {
    196  return FuzzyEqualsMultiplicative(aValue1.value, aValue2.value,
    197                                   aEpsilon.value);
    198 }
    199 
    200 }  // namespace mozilla
    201 
    202 #endif /* MOZILLA_GFX_COORD_H_ */