diff --git a/gfx/2d/ScaleFactors2D.h b/gfx/2d/ScaleFactors2D.h new file mode 100644 index 00000000000..16dfbce3532 --- /dev/null +++ b/gfx/2d/ScaleFactors2D.h @@ -0,0 +1,136 @@ +/* -*- 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 +#include + +#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 +struct ScaleFactors2D { + float xScale; + float yScale; + + MOZ_CONSTEXPR ScaleFactors2D() : xScale(1.0), yScale(1.0) {} + MOZ_CONSTEXPR ScaleFactors2D(const ScaleFactors2D& aCopy) + : xScale(aCopy.xScale), yScale(aCopy.yScale) {} + MOZ_CONSTEXPR ScaleFactors2D(float aXScale, float aYScale) + : xScale(aXScale), yScale(aYScale) {} + // Layout code often uses gfxSize to represent a pair of x/y scales. + explicit MOZ_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 MOZ_CONSTEXPR ScaleFactors2D(const ScaleFactor& 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 ToScaleFactor() const { + MOZ_ASSERT(AreScalesSame()); + return ScaleFactor(xScale); + } + + bool operator==(const ScaleFactors2D& aOther) const { + return xScale == aOther.xScale && yScale == aOther.yScale; + } + + bool operator!=(const ScaleFactors2D& aOther) const { + return !(*this == aOther); + } + + friend std::ostream& operator<<(std::ostream& aStream, + const ScaleFactors2D& aScale) { + if (aScale.AreScalesSame()) { + return aStream << aScale.xScale; + } else { + return aStream << '(' << aScale.xScale << ',' << aScale.yScale << ')'; + } + } + + template + ScaleFactors2D operator/(const ScaleFactors2D& aOther) const { + return ScaleFactors2D(xScale / aOther.xScale, yScale / aOther.yScale); + } + + template + ScaleFactors2D operator/(const ScaleFactors2D& aOther) const { + return ScaleFactors2D(xScale / aOther.xScale, yScale / aOther.yScale); + } + + template + ScaleFactors2D operator*(const ScaleFactors2D& aOther) const { + return ScaleFactors2D(xScale * aOther.xScale, yScale * aOther.yScale); + } + + template + ScaleFactors2D operator*(const ScaleFactors2D& aOther) const { + return ScaleFactors2D(xScale * aOther.xScale, yScale * aOther.yScale); + } + + template + ScaleFactors2D operator*(const ScaleFactor& aOther) const { + return *this * ScaleFactors2D(aOther); + } + + template + ScaleFactors2D operator*(const ScaleFactor& aOther) const { + return *this * ScaleFactors2D(aOther); + } + + template + ScaleFactors2D operator/(const ScaleFactor& aOther) const { + return *this / ScaleFactors2D(aOther); + } + + template + ScaleFactors2D operator/(const ScaleFactor& aOther) const { + return *this / ScaleFactors2D(aOther); + } + + template + friend ScaleFactors2D operator*(const ScaleFactor& aA, + const ScaleFactors2D& aB) { + return ScaleFactors2D(aA) * aB; + } + + template + friend ScaleFactors2D operator/(const ScaleFactor& aA, + const ScaleFactors2D& aB) { + return ScaleFactors2D(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); + } +}; + +} +} + +#endif /* MOZILLA_GFX_SCALEFACTORS2D_H_ */ diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index 3df42d79d20..169c6281b58 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -32,6 +32,7 @@ EXPORTS.mozilla.gfx += [ 'Rect.h', 'Scale.h', 'ScaleFactor.h', + 'ScaleFactors2D.h', 'SourceSurfaceCairo.h', 'Tools.h', 'Types.h', diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index e93468742ad..76c0f65c1a9 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -513,6 +513,24 @@ struct ParamTraits< mozilla::gfx::ScaleFactor > } }; +template +struct ParamTraits< mozilla::gfx::ScaleFactors2D > +{ + typedef mozilla::gfx::ScaleFactors2D paramType; + + static void Write(Message* msg, const paramType& param) + { + WriteParam(msg, param.xScale); + WriteParam(msg, param.yScale); + } + + static bool Read(const Message* msg, void** iter, paramType* result) + { + return (ReadParam(msg, iter, &result->xScale) && + ReadParam(msg, iter, &result->yScale)); + } +}; + template struct ParamTraits< mozilla::gfx::PointTyped > { diff --git a/layout/base/Units.h b/layout/base/Units.h index eeefa583c8e..24f65444b75 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -11,6 +11,7 @@ #include "mozilla/gfx/Point.h" #include "mozilla/gfx/Rect.h" #include "mozilla/gfx/ScaleFactor.h" +#include "mozilla/gfx/ScaleFactors2D.h" #include "nsRect.h" #include "nsMargin.h" #include "mozilla/AppUnits.h" @@ -122,6 +123,28 @@ typedef gfx::ScaleFactor ParentLayerToLayerScale; typedef gfx::ScaleFactor ParentLayerToScreenScale; typedef gfx::ScaleFactor ParentLayerToParentLayerScale; +typedef gfx::ScaleFactors2D CSSToLayoutDeviceScale2D; +typedef gfx::ScaleFactors2D CSSToLayerScale2D; +typedef gfx::ScaleFactors2D CSSToScreenScale2D; +typedef gfx::ScaleFactors2D CSSToParentLayerScale2D; +typedef gfx::ScaleFactors2D LayoutDeviceToCSSScale2D; +typedef gfx::ScaleFactors2D LayoutDeviceToLayerScale2D; +typedef gfx::ScaleFactors2D LayoutDeviceToScreenScale2D; +typedef gfx::ScaleFactors2D LayoutDeviceToParentLayerScale2D; +typedef gfx::ScaleFactors2D LayerToCSSScale2D; +typedef gfx::ScaleFactors2D LayerToLayoutDeviceScale2D; +typedef gfx::ScaleFactors2D LayerToRenderTargetScale2D; +typedef gfx::ScaleFactors2D LayerToScreenScale2D; +typedef gfx::ScaleFactors2D LayerToParentLayerScale2D; +typedef gfx::ScaleFactors2D RenderTargetToScreenScale2D; +typedef gfx::ScaleFactors2D ScreenToCSSScale2D; +typedef gfx::ScaleFactors2D ScreenToLayoutDeviceScale2D; +typedef gfx::ScaleFactors2D ScreenToLayerScale2D; +typedef gfx::ScaleFactors2D ScreenToParentLayerScale2D; +typedef gfx::ScaleFactors2D ParentLayerToLayerScale2D; +typedef gfx::ScaleFactors2D ParentLayerToScreenScale2D; +typedef gfx::ScaleFactors2D ParentLayerToParentLayerScale2D; + /* * The pixels that content authors use to specify sizes in. */ @@ -376,6 +399,18 @@ gfx::PointTyped operator/(const gfx::PointTyped& aPoint, const gfx::Sc aPoint.y / aScale.scale); } +template +gfx::PointTyped operator*(const gfx::PointTyped& aPoint, const gfx::ScaleFactors2D& aScale) { + return gfx::PointTyped(aPoint.x * aScale.xScale, + aPoint.y * aScale.yScale); +} + +template +gfx::PointTyped operator/(const gfx::PointTyped& aPoint, const gfx::ScaleFactors2D& aScale) { + return gfx::PointTyped(aPoint.x / aScale.xScale, + aPoint.y / aScale.yScale); +} + template gfx::RectTyped operator*(const gfx::RectTyped& aRect, const gfx::ScaleFactor& aScale) { return gfx::RectTyped(aRect.x * aScale.scale, @@ -392,6 +427,22 @@ gfx::RectTyped operator/(const gfx::RectTyped& aRect, const gfx::Scale aRect.height / aScale.scale); } +template +gfx::RectTyped operator*(const gfx::RectTyped& aRect, const gfx::ScaleFactors2D& aScale) { + return gfx::RectTyped(aRect.x * aScale.xScale, + aRect.y * aScale.yScale, + aRect.width * aScale.xScale, + aRect.height * aScale.yScale); +} + +template +gfx::RectTyped operator/(const gfx::RectTyped& aRect, const gfx::ScaleFactors2D& aScale) { + return gfx::RectTyped(aRect.x / aScale.xScale, + aRect.y / aScale.yScale, + aRect.width / aScale.xScale, + aRect.height / aScale.yScale); +} + template gfx::RectTyped operator*(const gfx::IntRectTyped& aRect, const gfx::ScaleFactor& aScale) { return gfx::RectTyped(float(aRect.x) * aScale.scale, @@ -408,6 +459,22 @@ gfx::RectTyped operator/(const gfx::IntRectTyped& aRect, const gfx::Sc float(aRect.height) / aScale.scale); } +template +gfx::RectTyped operator*(const gfx::IntRectTyped& aRect, const gfx::ScaleFactors2D& aScale) { + return gfx::RectTyped(float(aRect.x) * aScale.xScale, + float(aRect.y) * aScale.yScale, + float(aRect.width) * aScale.xScale, + float(aRect.height) * aScale.yScale); +} + +template +gfx::RectTyped operator/(const gfx::IntRectTyped& aRect, const gfx::ScaleFactors2D& aScale) { + return gfx::RectTyped(float(aRect.x) / aScale.xScale, + float(aRect.y) / aScale.yScale, + float(aRect.width) / aScale.xScale, + float(aRect.height) / aScale.yScale); +} + template gfx::SizeTyped operator*(const gfx::SizeTyped& aSize, const gfx::ScaleFactor& aScale) { return gfx::SizeTyped(aSize.width * aScale.scale, @@ -420,6 +487,18 @@ gfx::SizeTyped operator/(const gfx::SizeTyped& aSize, const gfx::Scale aSize.height / aScale.scale); } +template +gfx::SizeTyped operator*(const gfx::SizeTyped& aSize, const gfx::ScaleFactors2D& aScale) { + return gfx::SizeTyped(aSize.width * aScale.xScale, + aSize.height * aScale.yScale); +} + +template +gfx::SizeTyped operator/(const gfx::SizeTyped& aSize, const gfx::ScaleFactors2D& aScale) { + return gfx::SizeTyped(aSize.width / aScale.xScale, + aSize.height / aScale.yScale); +} + template gfx::SizeTyped operator*(const gfx::IntSizeTyped& aSize, const gfx::ScaleFactor& aScale) { return gfx::SizeTyped(float(aSize.width) * aScale.scale, @@ -432,6 +511,18 @@ gfx::SizeTyped operator/(const gfx::IntSizeTyped& aSize, const gfx::Sc float(aSize.height) / aScale.scale); } +template +gfx::SizeTyped operator*(const gfx::IntSizeTyped& aSize, const gfx::ScaleFactors2D& aScale) { + return gfx::SizeTyped(float(aSize.width) * aScale.xScale, + float(aSize.height) * aScale.yScale); +} + +template +gfx::SizeTyped operator/(const gfx::IntSizeTyped& aSize, const gfx::ScaleFactors2D& aScale) { + return gfx::SizeTyped(float(aSize.width) / aScale.xScale, + float(aSize.height) / aScale.yScale); +} + template gfx::MarginTyped operator*(const gfx::MarginTyped& aMargin, const gfx::ScaleFactor& aScale) { return gfx::MarginTyped(aMargin.top * aScale.scale, @@ -448,6 +539,22 @@ gfx::MarginTyped operator/(const gfx::MarginTyped& aMargin, const gfx: aMargin.left / aScale.scale); } +template +gfx::MarginTyped operator*(const gfx::MarginTyped& aMargin, const gfx::ScaleFactors2D& aScale) { + return gfx::MarginTyped(aMargin.top * aScale.yScale, + aMargin.right * aScale.xScale, + aMargin.bottom * aScale.yScale, + aMargin.left * aScale.xScale); +} + +template +gfx::MarginTyped operator/(const gfx::MarginTyped& aMargin, const gfx::ScaleFactors2D& aScale) { + return gfx::MarginTyped(aMargin.top / aScale.yScale, + aMargin.right / aScale.xScale, + aMargin.bottom / aScale.yScale, + aMargin.left / aScale.xScale); +} + } #endif