diff options
Diffstat (limited to 'gfx/2d/ScaleFactors2D.h')
-rw-r--r-- | gfx/2d/ScaleFactors2D.h | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/gfx/2d/ScaleFactors2D.h b/gfx/2d/ScaleFactors2D.h new file mode 100644 index 0000000000..c557e3cec6 --- /dev/null +++ b/gfx/2d/ScaleFactors2D.h @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "mozilla/gfx/Point.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, class T> +struct BaseScaleFactors2D { + T xScale; + T yScale; + + constexpr BaseScaleFactors2D() : xScale(1.0), yScale(1.0) {} + constexpr BaseScaleFactors2D(const BaseScaleFactors2D& aCopy) + : xScale(aCopy.xScale), yScale(aCopy.yScale) {} + constexpr BaseScaleFactors2D(T aXScale, T aYScale) + : xScale(aXScale), yScale(aYScale) {} + // Layout code often uses gfxSize to represent a pair of x/y scales. + explicit constexpr BaseScaleFactors2D(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 BaseScaleFactors2D(const ScaleFactor<Src, Dst>& aScale) + : xScale(aScale.scale), yScale(aScale.scale) {} + + bool AreScalesSame() const { + return FuzzyEqualsMultiplicative(xScale, yScale); + } + + // Convert the underlying floating point type storing the scale factors + // to that of NewT. + template <typename NewT> + BaseScaleFactors2D<Src, Dst, NewT> ConvertTo() const { + return BaseScaleFactors2D<Src, Dst, NewT>(NewT(xScale), NewT(yScale)); + } + + // Convert to a ScaleFactor. Asserts that the scales are, in fact, equal. + ScaleFactor<Src, Dst> ToScaleFactor() const { + // Avoid implicit narrowing from double to float. An explicit conversion + // may be done with `scales.ConvertTo<float>().ToScaleFactor()` if desired. + static_assert(std::is_same_v<T, float>); + MOZ_ASSERT(AreScalesSame()); + return ScaleFactor<Src, Dst>(xScale); + } + + // Convert to a SizeTyped. Eventually, we should replace all uses of SizeTyped + // to represent scales with ScaleFactors2D, and remove this function. + SizeTyped<UnknownUnits, T> ToSize() const { + return SizeTyped<UnknownUnits, T>(xScale, yScale); + } + + BaseScaleFactors2D& operator=(const BaseScaleFactors2D&) = default; + + bool operator==(const BaseScaleFactors2D& aOther) const { + return xScale == aOther.xScale && yScale == aOther.yScale; + } + + bool operator!=(const BaseScaleFactors2D& aOther) const { + return !(*this == aOther); + } + + friend std::ostream& operator<<(std::ostream& aStream, + const BaseScaleFactors2D& aScale) { + if (aScale.AreScalesSame()) { + return aStream << aScale.xScale; + } else { + return aStream << '(' << aScale.xScale << ',' << aScale.yScale << ')'; + } + } + + template <class Other> + BaseScaleFactors2D<Other, Dst, T> operator/( + const BaseScaleFactors2D<Src, Other, T>& aOther) const { + return BaseScaleFactors2D<Other, Dst, T>(xScale / aOther.xScale, + yScale / aOther.yScale); + } + + template <class Other> + BaseScaleFactors2D<Src, Other, T> operator/( + const BaseScaleFactors2D<Other, Dst, T>& aOther) const { + return BaseScaleFactors2D<Src, Other, T>(xScale / aOther.xScale, + yScale / aOther.yScale); + } + + template <class Other> + BaseScaleFactors2D<Src, Other, T> operator*( + const BaseScaleFactors2D<Dst, Other, T>& aOther) const { + return BaseScaleFactors2D<Src, Other, T>(xScale * aOther.xScale, + yScale * aOther.yScale); + } + + template <class Other> + BaseScaleFactors2D<Other, Dst, T> operator*( + const BaseScaleFactors2D<Other, Src, T>& aOther) const { + return BaseScaleFactors2D<Other, Dst, T>(xScale * aOther.xScale, + yScale * aOther.yScale); + } + + BaseScaleFactors2D<Src, Src, T> operator*( + const BaseScaleFactors2D<Dst, Src, T>& aOther) const { + return BaseScaleFactors2D<Src, Src, T>(xScale * aOther.xScale, + yScale * aOther.yScale); + } + + template <class Other> + BaseScaleFactors2D<Src, Other, T> operator*( + const ScaleFactor<Dst, Other>& aOther) const { + return *this * BaseScaleFactors2D<Dst, Other, T>(aOther); + } + + template <class Other> + BaseScaleFactors2D<Other, Dst, T> operator*( + const ScaleFactor<Other, Src>& aOther) const { + return *this * BaseScaleFactors2D<Other, Src, T>(aOther); + } + + BaseScaleFactors2D<Src, Src, T> operator*( + const ScaleFactor<Dst, Src>& aOther) const { + return *this * BaseScaleFactors2D<Dst, Src, T>(aOther); + } + + template <class Other> + BaseScaleFactors2D<Src, Other, T> operator/( + const ScaleFactor<Other, Dst>& aOther) const { + return *this / BaseScaleFactors2D<Other, Dst, T>(aOther); + } + + template <class Other> + BaseScaleFactors2D<Other, Dst, T> operator/( + const ScaleFactor<Src, Other>& aOther) const { + return *this / BaseScaleFactors2D<Src, Other, T>(aOther); + } + + template <class Other> + friend BaseScaleFactors2D<Other, Dst, T> operator*( + const ScaleFactor<Other, Src>& aA, const BaseScaleFactors2D& aB) { + return BaseScaleFactors2D<Other, Src, T>(aA) * aB; + } + + template <class Other> + friend BaseScaleFactors2D<Other, Src, T> operator/( + const ScaleFactor<Other, Dst>& aA, const BaseScaleFactors2D& aB) { + return BaseScaleFactors2D<Other, Src, T>(aA) / aB; + } + + static BaseScaleFactors2D<Src, Dst, T> FromUnknownScale( + const BaseScaleFactors2D<UnknownUnits, UnknownUnits, T>& scale) { + return BaseScaleFactors2D<Src, Dst, T>(scale.xScale, scale.yScale); + } + + BaseScaleFactors2D<UnknownUnits, UnknownUnits, T> ToUnknownScale() const { + return BaseScaleFactors2D<UnknownUnits, UnknownUnits, T>(xScale, yScale); + } + + friend BaseScaleFactors2D Min(const BaseScaleFactors2D& aA, + const BaseScaleFactors2D& aB) { + return BaseScaleFactors2D(std::min(aA.xScale, aB.xScale), + std::min(aA.yScale, aB.yScale)); + } + + friend BaseScaleFactors2D Max(const BaseScaleFactors2D& aA, + const BaseScaleFactors2D& aB) { + return BaseScaleFactors2D(std::max(aA.xScale, aB.xScale), + std::max(aA.yScale, aB.yScale)); + } +}; + +template <class Src, class Dst> +using ScaleFactors2D = BaseScaleFactors2D<Src, Dst, float>; + +template <class Src, class Dst> +using ScaleFactors2DDouble = BaseScaleFactors2D<Src, Dst, double>; + +} // namespace gfx +} // namespace mozilla + +#endif /* MOZILLA_GFX_SCALEFACTORS2D_H_ */ |