/* -*- 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 #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 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& 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 BaseScaleFactors2D ConvertTo() const { return BaseScaleFactors2D(NewT(xScale), NewT(yScale)); } // Convert to a ScaleFactor. Asserts that the scales are, in fact, equal. ScaleFactor ToScaleFactor() const { // Avoid implicit narrowing from double to float. An explicit conversion // may be done with `scales.ConvertTo().ToScaleFactor()` if desired. static_assert(std::is_same_v); MOZ_ASSERT(AreScalesSame()); return ScaleFactor(xScale); } // Convert to a SizeTyped. Eventually, we should replace all uses of SizeTyped // to represent scales with ScaleFactors2D, and remove this function. SizeTyped ToSize() const { return SizeTyped(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 BaseScaleFactors2D operator/( const BaseScaleFactors2D& aOther) const { return BaseScaleFactors2D(xScale / aOther.xScale, yScale / aOther.yScale); } template BaseScaleFactors2D operator/( const BaseScaleFactors2D& aOther) const { return BaseScaleFactors2D(xScale / aOther.xScale, yScale / aOther.yScale); } template BaseScaleFactors2D operator*( const BaseScaleFactors2D& aOther) const { return BaseScaleFactors2D(xScale * aOther.xScale, yScale * aOther.yScale); } template BaseScaleFactors2D operator*( const BaseScaleFactors2D& aOther) const { return BaseScaleFactors2D(xScale * aOther.xScale, yScale * aOther.yScale); } BaseScaleFactors2D operator*( const BaseScaleFactors2D& aOther) const { return BaseScaleFactors2D(xScale * aOther.xScale, yScale * aOther.yScale); } template BaseScaleFactors2D operator*( const ScaleFactor& aOther) const { return *this * BaseScaleFactors2D(aOther); } template BaseScaleFactors2D operator*( const ScaleFactor& aOther) const { return *this * BaseScaleFactors2D(aOther); } BaseScaleFactors2D operator*( const ScaleFactor& aOther) const { return *this * BaseScaleFactors2D(aOther); } template BaseScaleFactors2D operator/( const ScaleFactor& aOther) const { return *this / BaseScaleFactors2D(aOther); } template BaseScaleFactors2D operator/( const ScaleFactor& aOther) const { return *this / BaseScaleFactors2D(aOther); } template friend BaseScaleFactors2D operator*( const ScaleFactor& aA, const BaseScaleFactors2D& aB) { return BaseScaleFactors2D(aA) * aB; } template friend BaseScaleFactors2D operator/( const ScaleFactor& aA, const BaseScaleFactors2D& aB) { return BaseScaleFactors2D(aA) / aB; } static BaseScaleFactors2D FromUnknownScale( const BaseScaleFactors2D& scale) { return BaseScaleFactors2D(scale.xScale, scale.yScale); } BaseScaleFactors2D ToUnknownScale() const { return BaseScaleFactors2D(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 using ScaleFactors2D = BaseScaleFactors2D; template using ScaleFactors2DDouble = BaseScaleFactors2D; } // namespace gfx } // namespace mozilla #endif /* MOZILLA_GFX_SCALEFACTORS2D_H_ */