summaryrefslogtreecommitdiff
path: root/gfx/2d/ScaleFactors2D.h
blob: 6de32d7f2855fa885c05e03b6a9987237f51a817 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef MOZILLA_GFX_SCALEFACTORS2D_H_
#define MOZILLA_GFX_SCALEFACTORS2D_H_

#include <ostream>

#include "mozilla/Attributes.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/gfx/ScaleFactor.h"

#include "gfxPoint.h"

namespace mozilla {
namespace gfx {

/*
 * This class is like ScaleFactor, but allows different scales on the x and
 * y axes.
 */
template<class src, class dst>
struct ScaleFactors2D {
  float xScale;
  float yScale;

  constexpr ScaleFactors2D() : xScale(1.0), yScale(1.0) {}
  constexpr ScaleFactors2D(const ScaleFactors2D<src, dst>& aCopy)
    : xScale(aCopy.xScale), yScale(aCopy.yScale) {}
  constexpr ScaleFactors2D(float aXScale, float aYScale)
    : xScale(aXScale), yScale(aYScale) {}
  // Layout code often uses gfxSize to represent a pair of x/y scales.
  explicit constexpr ScaleFactors2D(const gfxSize& aSize)
    : xScale(aSize.width), yScale(aSize.height) {}

  // "Upgrade" from a ScaleFactor.
  // This is deliberately 'explicit' so that the treatment of a single scale
  // number as both the x- and y-scale in a context where they are allowed to
  // be different, is more visible.
  explicit constexpr ScaleFactors2D(const ScaleFactor<src, dst>& aScale)
    : xScale(aScale.scale), yScale(aScale.scale) {}

  bool AreScalesSame() const {
    return FuzzyEqualsMultiplicative(xScale, yScale);
  }

  // Convert to a ScaleFactor. Asserts that the scales are, in fact, equal.
  ScaleFactor<src, dst> ToScaleFactor() const {
    MOZ_ASSERT(AreScalesSame());
    return ScaleFactor<src, dst>(xScale);
  }

  bool operator==(const ScaleFactors2D<src, dst>& aOther) const {
    return xScale == aOther.xScale && yScale == aOther.yScale;
  }

  bool operator!=(const ScaleFactors2D<src, dst>& aOther) const {
    return !(*this == aOther);
  }

  friend std::ostream& operator<<(std::ostream& aStream,
                                  const ScaleFactors2D<src, dst>& aScale) {
    if (aScale.AreScalesSame()) {
      return aStream << aScale.xScale;
    } else {
      return aStream << '(' << aScale.xScale << ',' << aScale.yScale << ')';
    }
  }

  template<class other>
  ScaleFactors2D<other, dst> operator/(const ScaleFactors2D<src, other>& aOther) const {
    return ScaleFactors2D<other, dst>(xScale / aOther.xScale, yScale / aOther.yScale);
  }

  template<class other>
  ScaleFactors2D<src, other> operator/(const ScaleFactors2D<other, dst>& aOther) const {
    return ScaleFactors2D<src, other>(xScale / aOther.xScale, yScale / aOther.yScale);
  }

  template<class other>
  ScaleFactors2D<src, other> operator*(const ScaleFactors2D<dst, other>& aOther) const {
    return ScaleFactors2D<src, other>(xScale * aOther.xScale, yScale * aOther.yScale);
  }

  template<class other>
  ScaleFactors2D<other, dst> operator*(const ScaleFactors2D<other, src>& aOther) const {
    return ScaleFactors2D<other, dst>(xScale * aOther.xScale, yScale * aOther.yScale);
  }

  template<class other>
  ScaleFactors2D<src, other> operator*(const ScaleFactor<dst, other>& aOther) const {
    return *this * ScaleFactors2D<dst, other>(aOther);
  }

  template<class other>
  ScaleFactors2D<other, dst> operator*(const ScaleFactor<other, src>& aOther) const {
    return *this * ScaleFactors2D<other, src>(aOther);
  }

  template<class other>
  ScaleFactors2D<src, other> operator/(const ScaleFactor<other, dst>& aOther) const {
    return *this / ScaleFactors2D<other, dst>(aOther);
  }

  template<class other>
  ScaleFactors2D<other, dst> operator/(const ScaleFactor<src, other>& aOther) const {
    return *this / ScaleFactors2D<src, other>(aOther);
  }

  template<class other>
  friend ScaleFactors2D<other, dst> operator*(const ScaleFactor<other, src>& aA,
                                              const ScaleFactors2D<src, dst>& aB) {
    return ScaleFactors2D<other, src>(aA) * aB;
  }

  template<class other>
  friend ScaleFactors2D<other, src> operator/(const ScaleFactor<other, dst>& aA,
                                              const ScaleFactors2D<src, dst>& aB) {
    return ScaleFactors2D<other, src>(aA) / aB;
  }

  // Divide two scales of the same units, yielding a scale with no units,
  // represented as a gfxSize. This can mean e.g. the cahnge in a particular
  // scale from one frame to the next.
  gfxSize operator/(const ScaleFactors2D& aOther) const {
    return gfxSize(xScale / aOther.xScale, yScale / aOther.yScale);
  }
};

} // namespace gfx
} // namespace mozilla

#endif /* MOZILLA_GFX_SCALEFACTORS2D_H_ */