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_SCALEFACTORS2D_H_
8 #define MOZILLA_GFX_SCALEFACTORS2D_H_
9 
10 #include <ostream>
11 
12 #include "mozilla/Attributes.h"
13 #include "mozilla/FloatingPoint.h"
14 #include "mozilla/gfx/ScaleFactor.h"
15 
16 #include "gfxPoint.h"
17 
18 namespace mozilla {
19 namespace gfx {
20 
21 /*
22  * This class is like ScaleFactor, but allows different scales on the x and
23  * y axes.
24  */
25 template <class src, class dst>
26 struct ScaleFactors2D {
27   float xScale;
28   float yScale;
29 
ScaleFactors2DScaleFactors2D30   constexpr ScaleFactors2D() : xScale(1.0), yScale(1.0) {}
ScaleFactors2DScaleFactors2D31   constexpr ScaleFactors2D(const ScaleFactors2D<src, dst>& aCopy)
32       : xScale(aCopy.xScale), yScale(aCopy.yScale) {}
ScaleFactors2DScaleFactors2D33   constexpr ScaleFactors2D(float aXScale, float aYScale)
34       : xScale(aXScale), yScale(aYScale) {}
35   // Layout code often uses gfxSize to represent a pair of x/y scales.
ScaleFactors2DScaleFactors2D36   explicit constexpr ScaleFactors2D(const gfxSize& aSize)
37       : xScale(aSize.width), yScale(aSize.height) {}
38 
39   // "Upgrade" from a ScaleFactor.
40   // This is deliberately 'explicit' so that the treatment of a single scale
41   // number as both the x- and y-scale in a context where they are allowed to
42   // be different, is more visible.
ScaleFactors2DScaleFactors2D43   explicit constexpr ScaleFactors2D(const ScaleFactor<src, dst>& aScale)
44       : xScale(aScale.scale), yScale(aScale.scale) {}
45 
AreScalesSameScaleFactors2D46   bool AreScalesSame() const {
47     return FuzzyEqualsMultiplicative(xScale, yScale);
48   }
49 
50   // Convert to a ScaleFactor. Asserts that the scales are, in fact, equal.
ToScaleFactorScaleFactors2D51   ScaleFactor<src, dst> ToScaleFactor() const {
52     MOZ_ASSERT(AreScalesSame());
53     return ScaleFactor<src, dst>(xScale);
54   }
55 
56   ScaleFactors2D<src, dst>& operator=(const ScaleFactors2D<src, dst>&) =
57       default;
58 
59   bool operator==(const ScaleFactors2D<src, dst>& aOther) const {
60     return xScale == aOther.xScale && yScale == aOther.yScale;
61   }
62 
63   bool operator!=(const ScaleFactors2D<src, dst>& aOther) const {
64     return !(*this == aOther);
65   }
66 
67   friend std::ostream& operator<<(std::ostream& aStream,
68                                   const ScaleFactors2D<src, dst>& aScale) {
69     if (aScale.AreScalesSame()) {
70       return aStream << aScale.xScale;
71     } else {
72       return aStream << '(' << aScale.xScale << ',' << aScale.yScale << ')';
73     }
74   }
75 
76   template <class other>
77   ScaleFactors2D<other, dst> operator/(
78       const ScaleFactors2D<src, other>& aOther) const {
79     return ScaleFactors2D<other, dst>(xScale / aOther.xScale,
80                                       yScale / aOther.yScale);
81   }
82 
83   template <class other>
84   ScaleFactors2D<src, other> operator/(
85       const ScaleFactors2D<other, dst>& aOther) const {
86     return ScaleFactors2D<src, other>(xScale / aOther.xScale,
87                                       yScale / aOther.yScale);
88   }
89 
90   template <class other>
91   ScaleFactors2D<src, other> operator*(
92       const ScaleFactors2D<dst, other>& aOther) const {
93     return ScaleFactors2D<src, other>(xScale * aOther.xScale,
94                                       yScale * aOther.yScale);
95   }
96 
97   template <class other>
98   ScaleFactors2D<other, dst> operator*(
99       const ScaleFactors2D<other, src>& aOther) const {
100     return ScaleFactors2D<other, dst>(xScale * aOther.xScale,
101                                       yScale * aOther.yScale);
102   }
103 
104   template <class other>
105   ScaleFactors2D<src, other> operator*(
106       const ScaleFactor<dst, other>& aOther) const {
107     return *this * ScaleFactors2D<dst, other>(aOther);
108   }
109 
110   template <class other>
111   ScaleFactors2D<other, dst> operator*(
112       const ScaleFactor<other, src>& aOther) const {
113     return *this * ScaleFactors2D<other, src>(aOther);
114   }
115 
116   template <class other>
117   ScaleFactors2D<src, other> operator/(
118       const ScaleFactor<other, dst>& aOther) const {
119     return *this / ScaleFactors2D<other, dst>(aOther);
120   }
121 
122   template <class other>
123   ScaleFactors2D<other, dst> operator/(
124       const ScaleFactor<src, other>& aOther) const {
125     return *this / ScaleFactors2D<src, other>(aOther);
126   }
127 
128   template <class other>
129   friend ScaleFactors2D<other, dst> operator*(
130       const ScaleFactor<other, src>& aA, const ScaleFactors2D<src, dst>& aB) {
131     return ScaleFactors2D<other, src>(aA) * aB;
132   }
133 
134   template <class other>
135   friend ScaleFactors2D<other, src> operator/(
136       const ScaleFactor<other, dst>& aA, const ScaleFactors2D<src, dst>& aB) {
137     return ScaleFactors2D<other, src>(aA) / aB;
138   }
139 
140   // Divide two scales of the same units, yielding a scale with no units,
141   // represented as a gfxSize. This can mean e.g. the cahnge in a particular
142   // scale from one frame to the next.
143   gfxSize operator/(const ScaleFactors2D& aOther) const {
144     return gfxSize(xScale / aOther.xScale, yScale / aOther.yScale);
145   }
146 };
147 
148 }  // namespace gfx
149 }  // namespace mozilla
150 
151 #endif /* MOZILLA_GFX_SCALEFACTORS2D_H_ */
152