diff options
Diffstat (limited to '')
-rw-r--r-- | layout/base/Units.h | 936 |
1 files changed, 936 insertions, 0 deletions
diff --git a/layout/base/Units.h b/layout/base/Units.h new file mode 100644 index 0000000000..61d0d5761c --- /dev/null +++ b/layout/base/Units.h @@ -0,0 +1,936 @@ +/* -*- 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 MOZ_UNITS_H_ +#define MOZ_UNITS_H_ + +#include <type_traits> + +#include "mozilla/gfx/Coord.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/gfx/Rect.h" +#include "mozilla/gfx/RectAbsolute.h" +#include "mozilla/gfx/ScaleFactor.h" +#include "mozilla/gfx/ScaleFactors2D.h" +#include "nsMargin.h" +#include "nsRect.h" +#include "nsRegion.h" +#include "mozilla/AppUnits.h" + +namespace mozilla { + +template <typename T> +struct IsPixel : std::false_type {}; + +// See struct declaration for a description of each unit type. +struct CSSPixel; +struct LayoutDevicePixel; +struct LayerPixel; +struct CSSTransformedLayerPixel; +struct RenderTargetPixel; +struct ScreenPixel; +struct ParentLayerPixel; +struct DesktopPixel; +struct ImagePixel; +struct ExternalPixel; + +template <> +struct IsPixel<CSSPixel> : std::true_type {}; +template <> +struct IsPixel<LayoutDevicePixel> : std::true_type {}; +template <> +struct IsPixel<LayerPixel> : std::true_type {}; +template <> +struct IsPixel<CSSTransformedLayerPixel> : std::true_type {}; +template <> +struct IsPixel<RenderTargetPixel> : std::true_type {}; +template <> +struct IsPixel<ImagePixel> : std::true_type {}; +template <> +struct IsPixel<ScreenPixel> : std::true_type {}; +template <> +struct IsPixel<ParentLayerPixel> : std::true_type {}; +template <> +struct IsPixel<DesktopPixel> : std::true_type {}; +template <> +struct IsPixel<ExternalPixel> : std::true_type {}; + +typedef gfx::CoordTyped<CSSPixel> CSSCoord; +typedef gfx::IntCoordTyped<CSSPixel> CSSIntCoord; +typedef gfx::PointTyped<CSSPixel> CSSPoint; +typedef gfx::IntPointTyped<CSSPixel> CSSIntPoint; +typedef gfx::SizeTyped<CSSPixel> CSSSize; +typedef gfx::IntSizeTyped<CSSPixel> CSSIntSize; +typedef gfx::RectTyped<CSSPixel> CSSRect; +typedef gfx::IntRectTyped<CSSPixel> CSSIntRect; +typedef gfx::MarginTyped<CSSPixel> CSSMargin; +typedef gfx::IntMarginTyped<CSSPixel> CSSIntMargin; +typedef gfx::IntRegionTyped<CSSPixel> CSSIntRegion; + +typedef gfx::CoordTyped<LayoutDevicePixel> LayoutDeviceCoord; +typedef gfx::IntCoordTyped<LayoutDevicePixel> LayoutDeviceIntCoord; +typedef gfx::PointTyped<LayoutDevicePixel> LayoutDevicePoint; +typedef gfx::IntPointTyped<LayoutDevicePixel> LayoutDeviceIntPoint; +typedef gfx::SizeTyped<LayoutDevicePixel> LayoutDeviceSize; +typedef gfx::IntSizeTyped<LayoutDevicePixel> LayoutDeviceIntSize; +typedef gfx::RectTyped<LayoutDevicePixel> LayoutDeviceRect; +typedef gfx::IntRectTyped<LayoutDevicePixel> LayoutDeviceIntRect; +typedef gfx::MarginTyped<LayoutDevicePixel> LayoutDeviceMargin; +typedef gfx::IntMarginTyped<LayoutDevicePixel> LayoutDeviceIntMargin; +typedef gfx::IntRegionTyped<LayoutDevicePixel> LayoutDeviceIntRegion; + +typedef gfx::CoordTyped<LayerPixel> LayerCoord; +typedef gfx::IntCoordTyped<LayerPixel> LayerIntCoord; +typedef gfx::PointTyped<LayerPixel> LayerPoint; +typedef gfx::IntPointTyped<LayerPixel> LayerIntPoint; +typedef gfx::SizeTyped<LayerPixel> LayerSize; +typedef gfx::IntSizeTyped<LayerPixel> LayerIntSize; +typedef gfx::RectTyped<LayerPixel> LayerRect; +typedef gfx::RectAbsoluteTyped<LayerPixel> LayerRectAbsolute; +typedef gfx::IntRectTyped<LayerPixel> LayerIntRect; +typedef gfx::MarginTyped<LayerPixel> LayerMargin; +typedef gfx::IntMarginTyped<LayerPixel> LayerIntMargin; +typedef gfx::IntRegionTyped<LayerPixel> LayerIntRegion; + +typedef gfx::CoordTyped<CSSTransformedLayerPixel> CSSTransformedLayerCoord; +typedef gfx::IntCoordTyped<CSSTransformedLayerPixel> + CSSTransformedLayerIntCoord; +typedef gfx::PointTyped<CSSTransformedLayerPixel> CSSTransformedLayerPoint; +typedef gfx::IntPointTyped<CSSTransformedLayerPixel> + CSSTransformedLayerIntPoint; +typedef gfx::SizeTyped<CSSTransformedLayerPixel> CSSTransformedLayerSize; +typedef gfx::IntSizeTyped<CSSTransformedLayerPixel> CSSTransformedLayerIntSize; +typedef gfx::RectTyped<CSSTransformedLayerPixel> CSSTransformedLayerRect; +typedef gfx::IntRectTyped<CSSTransformedLayerPixel> CSSTransformedLayerIntRect; +typedef gfx::MarginTyped<CSSTransformedLayerPixel> CSSTransformedLayerMargin; +typedef gfx::IntMarginTyped<CSSTransformedLayerPixel> + CSSTransformedLayerIntMargin; +typedef gfx::IntRegionTyped<CSSTransformedLayerPixel> + CSSTransformedLayerIntRegion; + +typedef gfx::PointTyped<RenderTargetPixel> RenderTargetPoint; +typedef gfx::IntPointTyped<RenderTargetPixel> RenderTargetIntPoint; +typedef gfx::SizeTyped<RenderTargetPixel> RenderTargetSize; +typedef gfx::IntSizeTyped<RenderTargetPixel> RenderTargetIntSize; +typedef gfx::RectTyped<RenderTargetPixel> RenderTargetRect; +typedef gfx::IntRectTyped<RenderTargetPixel> RenderTargetIntRect; +typedef gfx::MarginTyped<RenderTargetPixel> RenderTargetMargin; +typedef gfx::IntMarginTyped<RenderTargetPixel> RenderTargetIntMargin; +typedef gfx::IntRegionTyped<RenderTargetPixel> RenderTargetIntRegion; + +typedef gfx::PointTyped<ImagePixel> ImagePoint; +typedef gfx::IntPointTyped<ImagePixel> ImageIntPoint; +typedef gfx::SizeTyped<ImagePixel> ImageSize; +typedef gfx::IntSizeTyped<ImagePixel> ImageIntSize; +typedef gfx::RectTyped<ImagePixel> ImageRect; +typedef gfx::IntRectTyped<ImagePixel> ImageIntRect; + +typedef gfx::CoordTyped<ScreenPixel> ScreenCoord; +typedef gfx::IntCoordTyped<ScreenPixel> ScreenIntCoord; +typedef gfx::PointTyped<ScreenPixel> ScreenPoint; +typedef gfx::IntPointTyped<ScreenPixel> ScreenIntPoint; +typedef gfx::SizeTyped<ScreenPixel> ScreenSize; +typedef gfx::IntSizeTyped<ScreenPixel> ScreenIntSize; +typedef gfx::RectTyped<ScreenPixel> ScreenRect; +typedef gfx::IntRectTyped<ScreenPixel> ScreenIntRect; +typedef gfx::MarginTyped<ScreenPixel> ScreenMargin; +typedef gfx::IntMarginTyped<ScreenPixel> ScreenIntMargin; +typedef gfx::IntRegionTyped<ScreenPixel> ScreenIntRegion; + +typedef gfx::CoordTyped<ParentLayerPixel> ParentLayerCoord; +typedef gfx::IntCoordTyped<ParentLayerPixel> ParentLayerIntCoord; +typedef gfx::PointTyped<ParentLayerPixel> ParentLayerPoint; +typedef gfx::IntPointTyped<ParentLayerPixel> ParentLayerIntPoint; +typedef gfx::SizeTyped<ParentLayerPixel> ParentLayerSize; +typedef gfx::IntSizeTyped<ParentLayerPixel> ParentLayerIntSize; +typedef gfx::RectTyped<ParentLayerPixel> ParentLayerRect; +typedef gfx::IntRectTyped<ParentLayerPixel> ParentLayerIntRect; +typedef gfx::MarginTyped<ParentLayerPixel> ParentLayerMargin; +typedef gfx::IntMarginTyped<ParentLayerPixel> ParentLayerIntMargin; +typedef gfx::IntRegionTyped<ParentLayerPixel> ParentLayerIntRegion; + +typedef gfx::CoordTyped<DesktopPixel> DesktopCoord; +typedef gfx::IntCoordTyped<DesktopPixel> DesktopIntCoord; +typedef gfx::PointTyped<DesktopPixel> DesktopPoint; +typedef gfx::IntPointTyped<DesktopPixel> DesktopIntPoint; +typedef gfx::SizeTyped<DesktopPixel> DesktopSize; +typedef gfx::IntSizeTyped<DesktopPixel> DesktopIntSize; +typedef gfx::RectTyped<DesktopPixel> DesktopRect; +typedef gfx::IntRectTyped<DesktopPixel> DesktopIntRect; + +typedef gfx::CoordTyped<ExternalPixel> ExternalCoord; +typedef gfx::IntCoordTyped<ExternalPixel> ExternalIntCoord; +typedef gfx::PointTyped<ExternalPixel> ExternalPoint; +typedef gfx::IntPointTyped<ExternalPixel> ExternalIntPoint; +typedef gfx::SizeTyped<ExternalPixel> ExternalSize; +typedef gfx::IntSizeTyped<ExternalPixel> ExternalIntSize; +typedef gfx::RectTyped<ExternalPixel> ExternalRect; +typedef gfx::IntRectTyped<ExternalPixel> ExternalIntRect; +typedef gfx::MarginTyped<ExternalPixel> ExternalMargin; +typedef gfx::IntMarginTyped<ExternalPixel> ExternalIntMargin; +typedef gfx::IntRegionTyped<ExternalPixel> ExternalIntRegion; + +typedef gfx::ScaleFactor<CSSPixel, CSSPixel> CSSToCSSScale; +typedef gfx::ScaleFactor<CSSPixel, LayoutDevicePixel> CSSToLayoutDeviceScale; +typedef gfx::ScaleFactor<CSSPixel, LayerPixel> CSSToLayerScale; +typedef gfx::ScaleFactor<CSSPixel, ScreenPixel> CSSToScreenScale; +typedef gfx::ScaleFactor<CSSPixel, ParentLayerPixel> CSSToParentLayerScale; +typedef gfx::ScaleFactor<CSSPixel, DesktopPixel> CSSToDesktopScale; +typedef gfx::ScaleFactor<LayoutDevicePixel, CSSPixel> LayoutDeviceToCSSScale; +typedef gfx::ScaleFactor<LayoutDevicePixel, LayerPixel> + LayoutDeviceToLayerScale; +typedef gfx::ScaleFactor<LayoutDevicePixel, ScreenPixel> + LayoutDeviceToScreenScale; +typedef gfx::ScaleFactor<LayoutDevicePixel, ParentLayerPixel> + LayoutDeviceToParentLayerScale; +typedef gfx::ScaleFactor<LayerPixel, CSSPixel> LayerToCSSScale; +typedef gfx::ScaleFactor<LayerPixel, LayoutDevicePixel> + LayerToLayoutDeviceScale; +typedef gfx::ScaleFactor<LayerPixel, RenderTargetPixel> + LayerToRenderTargetScale; +typedef gfx::ScaleFactor<LayerPixel, ScreenPixel> LayerToScreenScale; +typedef gfx::ScaleFactor<LayerPixel, ParentLayerPixel> LayerToParentLayerScale; +typedef gfx::ScaleFactor<RenderTargetPixel, ScreenPixel> + RenderTargetToScreenScale; +typedef gfx::ScaleFactor<ScreenPixel, CSSPixel> ScreenToCSSScale; +typedef gfx::ScaleFactor<ScreenPixel, LayoutDevicePixel> + ScreenToLayoutDeviceScale; +typedef gfx::ScaleFactor<ScreenPixel, LayerPixel> ScreenToLayerScale; +typedef gfx::ScaleFactor<ScreenPixel, ParentLayerPixel> + ScreenToParentLayerScale; +typedef gfx::ScaleFactor<ParentLayerPixel, LayerPixel> ParentLayerToLayerScale; +typedef gfx::ScaleFactor<ParentLayerPixel, ScreenPixel> + ParentLayerToScreenScale; +typedef gfx::ScaleFactor<ParentLayerPixel, ParentLayerPixel> + ParentLayerToParentLayerScale; +typedef gfx::ScaleFactor<DesktopPixel, LayoutDevicePixel> + DesktopToLayoutDeviceScale; +typedef gfx::ScaleFactor<LayoutDevicePixel, DesktopPixel> + LayoutDeviceToDesktopScale; + +typedef gfx::ScaleFactors2D<CSSPixel, LayoutDevicePixel> + CSSToLayoutDeviceScale2D; +typedef gfx::ScaleFactors2D<CSSPixel, LayerPixel> CSSToLayerScale2D; +typedef gfx::ScaleFactors2D<CSSPixel, ScreenPixel> CSSToScreenScale2D; +typedef gfx::ScaleFactors2D<CSSPixel, ParentLayerPixel> CSSToParentLayerScale2D; +typedef gfx::ScaleFactors2D<LayoutDevicePixel, CSSPixel> + LayoutDeviceToCSSScale2D; +typedef gfx::ScaleFactors2D<LayoutDevicePixel, LayerPixel> + LayoutDeviceToLayerScale2D; +typedef gfx::ScaleFactors2D<LayoutDevicePixel, ScreenPixel> + LayoutDeviceToScreenScale2D; +typedef gfx::ScaleFactors2D<LayoutDevicePixel, ParentLayerPixel> + LayoutDeviceToParentLayerScale2D; +typedef gfx::ScaleFactors2D<LayerPixel, CSSPixel> LayerToCSSScale2D; +typedef gfx::ScaleFactors2D<LayerPixel, LayoutDevicePixel> + LayerToLayoutDeviceScale2D; +typedef gfx::ScaleFactors2D<LayerPixel, RenderTargetPixel> + LayerToRenderTargetScale2D; +typedef gfx::ScaleFactors2D<LayerPixel, ScreenPixel> LayerToScreenScale2D; +typedef gfx::ScaleFactors2D<LayerPixel, ParentLayerPixel> + LayerToParentLayerScale2D; +typedef gfx::ScaleFactors2D<RenderTargetPixel, ScreenPixel> + RenderTargetToScreenScale2D; +typedef gfx::ScaleFactors2D<ScreenPixel, CSSPixel> ScreenToCSSScale2D; +typedef gfx::ScaleFactors2D<ScreenPixel, LayoutDevicePixel> + ScreenToLayoutDeviceScale2D; +typedef gfx::ScaleFactors2D<ScreenPixel, ScreenPixel> ScreenToScreenScale2D; +typedef gfx::ScaleFactors2D<ScreenPixel, LayerPixel> ScreenToLayerScale2D; +typedef gfx::ScaleFactors2D<ScreenPixel, ParentLayerPixel> + ScreenToParentLayerScale2D; +typedef gfx::ScaleFactors2D<ParentLayerPixel, LayerPixel> + ParentLayerToLayerScale2D; +typedef gfx::ScaleFactors2D<ParentLayerPixel, ScreenPixel> + ParentLayerToScreenScale2D; +typedef gfx::ScaleFactors2D<ParentLayerPixel, ParentLayerPixel> + ParentLayerToParentLayerScale2D; +typedef gfx::ScaleFactors2D<gfx::UnknownUnits, gfx::UnknownUnits> Scale2D; + +typedef gfx::Matrix4x4Typed<CSSPixel, CSSPixel> CSSToCSSMatrix4x4; +typedef gfx::Matrix4x4Typed<LayoutDevicePixel, LayoutDevicePixel> + LayoutDeviceToLayoutDeviceMatrix4x4; +typedef gfx::Matrix4x4Typed<LayoutDevicePixel, ParentLayerPixel> + LayoutDeviceToParentLayerMatrix4x4; +typedef gfx::Matrix4x4Typed<LayerPixel, ParentLayerPixel> + LayerToParentLayerMatrix4x4; +typedef gfx::Matrix4x4Typed<LayerPixel, ScreenPixel> LayerToScreenMatrix4x4; +typedef gfx::Matrix4x4Typed<ScreenPixel, ScreenPixel> ScreenToScreenMatrix4x4; +typedef gfx::Matrix4x4Typed<ScreenPixel, ParentLayerPixel> + ScreenToParentLayerMatrix4x4; +typedef gfx::Matrix4x4Typed<ParentLayerPixel, LayerPixel> + ParentLayerToLayerMatrix4x4; +typedef gfx::Matrix4x4Typed<ParentLayerPixel, ScreenPixel> + ParentLayerToScreenMatrix4x4; +typedef gfx::Matrix4x4Typed<ParentLayerPixel, ParentLayerPixel> + ParentLayerToParentLayerMatrix4x4; +typedef gfx::Matrix4x4Typed<ParentLayerPixel, RenderTargetPixel> + ParentLayerToRenderTargetMatrix4x4; +typedef gfx::Matrix4x4Typed<ExternalPixel, ParentLayerPixel> + ExternalToParentLayerMatrix4x4; + +/* + * The pixels that content authors use to specify sizes in. + */ +struct CSSPixel { + // Conversions from app units + static CSSCoord FromAppUnits(nscoord aCoord) { + return NSAppUnitsToFloatPixels(aCoord, float(AppUnitsPerCSSPixel())); + } + + static CSSIntCoord FromAppUnitsRounded(nscoord aCoord) { + return NSAppUnitsToIntPixels(aCoord, float(AppUnitsPerCSSPixel())); + } + + static CSSPoint FromAppUnits(const nsPoint& aPoint) { + return CSSPoint(FromAppUnits(aPoint.x), FromAppUnits(aPoint.y)); + } + + static CSSSize FromAppUnits(const nsSize& aSize) { + return CSSSize(FromAppUnits(aSize.width), FromAppUnits(aSize.height)); + } + + static CSSRect FromAppUnits(const nsRect& aRect) { + return CSSRect(FromAppUnits(aRect.x), FromAppUnits(aRect.y), + FromAppUnits(aRect.Width()), FromAppUnits(aRect.Height())); + } + + static CSSMargin FromAppUnits(const nsMargin& aMargin) { + return CSSMargin(FromAppUnits(aMargin.top), FromAppUnits(aMargin.right), + FromAppUnits(aMargin.bottom), FromAppUnits(aMargin.left)); + } + + static CSSIntPoint FromAppUnitsRounded(const nsPoint& aPoint) { + return CSSIntPoint(FromAppUnitsRounded(aPoint.x), + FromAppUnitsRounded(aPoint.y)); + } + + static CSSIntSize FromAppUnitsRounded(const nsSize& aSize) { + return CSSIntSize(FromAppUnitsRounded(aSize.width), + FromAppUnitsRounded(aSize.height)); + } + + static CSSIntRect FromAppUnitsRounded(const nsRect& aRect) { + return CSSIntRect(FromAppUnitsRounded(aRect.x), + FromAppUnitsRounded(aRect.y), + FromAppUnitsRounded(aRect.Width()), + FromAppUnitsRounded(aRect.Height())); + } + + static CSSIntMargin FromAppUnitsRounded(const nsMargin& aMargin) { + return CSSIntMargin( + FromAppUnitsRounded(aMargin.top), FromAppUnitsRounded(aMargin.right), + FromAppUnitsRounded(aMargin.bottom), FromAppUnitsRounded(aMargin.left)); + } + + static CSSIntRect FromAppUnitsToNearest(const nsRect& aRect) { + return CSSIntRect::FromUnknownRect( + aRect.ToNearestPixels(AppUnitsPerCSSPixel())); + } + + static CSSIntRect FromAppUnitsToInside(const nsRect& aRect) { + return CSSIntRect::FromUnknownRect( + aRect.ToInsidePixels(AppUnitsPerCSSPixel())); + } + + // Conversions to app units + + // TODO: We might want an int32_t/CSSIntCoord overload which doesn't do float + // math but we'd need to ensure stuff is clamped to nscoord_MIN/MAX range. + static nscoord ToAppUnits(CSSCoord aCoord) { + return NSFloatPixelsToAppUnits(aCoord, AppUnitsPerCSSPixel()); + } + + static nsPoint ToAppUnits(const CSSPoint& aPoint) { + return nsPoint(ToAppUnits(aPoint.x), ToAppUnits(aPoint.y)); + } + + static nsPoint ToAppUnits(const CSSIntPoint& aPoint) { + return nsPoint(ToAppUnits(CSSCoord(aPoint.x)), + ToAppUnits(CSSCoord(aPoint.y))); + } + + static nsSize ToAppUnits(const CSSSize& aSize) { + return nsSize(ToAppUnits(aSize.width), ToAppUnits(aSize.height)); + } + + static nsSize ToAppUnits(const CSSIntSize& aSize) { + return nsSize(ToAppUnits(aSize.width), ToAppUnits(aSize.height)); + } + + static nsRect ToAppUnits(const CSSRect& aRect) { + return nsRect(ToAppUnits(aRect.x), ToAppUnits(aRect.y), + ToAppUnits(aRect.Width()), ToAppUnits(aRect.Height())); + } + + static nsRect ToAppUnits(const CSSIntRect& aRect) { + return nsRect(ToAppUnits(aRect.x), ToAppUnits(aRect.y), + ToAppUnits(aRect.Width()), ToAppUnits(aRect.Height())); + } + + static nsMargin ToAppUnits(const CSSMargin& aMargin) { + return nsMargin(ToAppUnits(aMargin.top), ToAppUnits(aMargin.right), + ToAppUnits(aMargin.bottom), ToAppUnits(aMargin.left)); + } + + static nsMargin ToAppUnits(const CSSIntMargin& aMargin) { + return nsMargin(ToAppUnits(aMargin.top), ToAppUnits(aMargin.right), + ToAppUnits(aMargin.bottom), ToAppUnits(aMargin.left)); + } + + // Conversion from a given CSS point value. + static CSSCoord FromPoints(float aCoord) { + // One inch / 72. + return aCoord * 96.0f / 72.0f; + } +}; + +/* + * The pixels that are referred to as "device pixels" in layout code. In + * general values measured in LayoutDevicePixels are obtained by dividing a + * value in app units by AppUnitsPerDevPixel(). Conversion between CSS pixels + * and LayoutDevicePixels is affected by: + * 1) the "full zoom" (see nsPresContext::SetFullZoom) + * 2) the "widget scale" (see nsIWidget::GetDefaultScale) + */ +struct LayoutDevicePixel { + static LayoutDeviceCoord FromAppUnits(nscoord aCoord, + nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceCoord( + NSAppUnitsToFloatPixels(aCoord, float(aAppUnitsPerDevPixel))); + } + + static LayoutDeviceIntCoord FromAppUnitsRounded( + nscoord aCoord, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntCoord( + NSAppUnitsToIntPixels(aCoord, float(aAppUnitsPerDevPixel))); + } + + static LayoutDeviceRect FromAppUnits(const nsRect& aRect, + nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceRect(FromAppUnits(aRect.x, aAppUnitsPerDevPixel), + FromAppUnits(aRect.y, aAppUnitsPerDevPixel), + FromAppUnits(aRect.Width(), aAppUnitsPerDevPixel), + FromAppUnits(aRect.Height(), aAppUnitsPerDevPixel)); + } + + static LayoutDeviceSize FromAppUnits(const nsSize& aSize, + nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceSize(FromAppUnits(aSize.width, aAppUnitsPerDevPixel), + FromAppUnits(aSize.height, aAppUnitsPerDevPixel)); + } + + static LayoutDevicePoint FromAppUnits(const nsPoint& aPoint, + nscoord aAppUnitsPerDevPixel) { + return LayoutDevicePoint(FromAppUnits(aPoint.x, aAppUnitsPerDevPixel), + FromAppUnits(aPoint.y, aAppUnitsPerDevPixel)); + } + + static LayoutDeviceMargin FromAppUnits(const nsMargin& aMargin, + nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceMargin( + FromAppUnits(aMargin.top, aAppUnitsPerDevPixel), + FromAppUnits(aMargin.right, aAppUnitsPerDevPixel), + FromAppUnits(aMargin.bottom, aAppUnitsPerDevPixel), + FromAppUnits(aMargin.left, aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntPoint FromAppUnitsRounded( + const nsPoint& aPoint, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntPoint( + FromAppUnitsRounded(aPoint.x, aAppUnitsPerDevPixel), + FromAppUnitsRounded(aPoint.y, aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntRect FromAppUnitsRounded(const nsRect& aRect, + nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntRect( + FromAppUnitsRounded(aRect.x, aAppUnitsPerDevPixel), + FromAppUnitsRounded(aRect.y, aAppUnitsPerDevPixel), + FromAppUnitsRounded(aRect.Width(), aAppUnitsPerDevPixel), + FromAppUnitsRounded(aRect.Height(), aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntPoint FromAppUnitsToNearest( + const nsPoint& aPoint, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntPoint::FromUnknownPoint( + aPoint.ToNearestPixels(aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntRect FromAppUnitsToNearest( + const nsRect& aRect, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntRect::FromUnknownRect( + aRect.ToNearestPixels(aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntRect FromAppUnitsToInside( + const nsRect& aRect, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntRect::FromUnknownRect( + aRect.ToInsidePixels(aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntRect FromAppUnitsToOutside( + const nsRect& aRect, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntRect::FromUnknownRect( + aRect.ToOutsidePixels(aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntSize FromAppUnitsRounded(const nsSize& aSize, + nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntSize( + FromAppUnitsRounded(aSize.width, aAppUnitsPerDevPixel), + FromAppUnitsRounded(aSize.height, aAppUnitsPerDevPixel)); + } + + static LayoutDeviceIntMargin FromAppUnitsRounded( + const nsMargin& aMargin, nscoord aAppUnitsPerDevPixel) { + return LayoutDeviceIntMargin( + FromAppUnitsRounded(aMargin.top, aAppUnitsPerDevPixel), + FromAppUnitsRounded(aMargin.right, aAppUnitsPerDevPixel), + FromAppUnitsRounded(aMargin.bottom, aAppUnitsPerDevPixel), + FromAppUnitsRounded(aMargin.left, aAppUnitsPerDevPixel)); + } + + static nscoord ToAppUnits(LayoutDeviceIntCoord aCoord, + nscoord aAppUnitsPerDevPixel) { + return aCoord * aAppUnitsPerDevPixel; + } + + static nscoord ToAppUnits(int32_t aCoord, nscoord aAppUnitsPerDevPixel) { + return ToAppUnits(LayoutDeviceIntCoord(aCoord), aAppUnitsPerDevPixel); + } + + static nscoord ToAppUnits(LayoutDeviceCoord aCoord, + nscoord aAppUnitsPerDevPixel) { + return NSFloatPixelsToAppUnits(aCoord, aAppUnitsPerDevPixel); + } + + static nscoord ToAppUnits(float aCoord, nscoord aAppUnitsPerDevPixel) { + return ToAppUnits(LayoutDeviceCoord(aCoord), aAppUnitsPerDevPixel); + } + + static nsPoint ToAppUnits(const LayoutDeviceIntPoint& aPoint, + nscoord aAppUnitsPerDevPixel) { + return nsPoint(ToAppUnits(aPoint.x, aAppUnitsPerDevPixel), + ToAppUnits(aPoint.y, aAppUnitsPerDevPixel)); + } + + static nsSize ToAppUnits(const LayoutDeviceIntSize& aSize, + nscoord aAppUnitsPerDevPixel) { + return nsSize(ToAppUnits(aSize.width, aAppUnitsPerDevPixel), + ToAppUnits(aSize.height, aAppUnitsPerDevPixel)); + } + + static nsSize ToAppUnits(const LayoutDeviceSize& aSize, + nscoord aAppUnitsPerDevPixel) { + return nsSize(ToAppUnits(aSize.width, aAppUnitsPerDevPixel), + ToAppUnits(aSize.height, aAppUnitsPerDevPixel)); + } + + static nsRect ToAppUnits(const LayoutDeviceIntRect& aRect, + nscoord aAppUnitsPerDevPixel) { + return nsRect(ToAppUnits(aRect.x, aAppUnitsPerDevPixel), + ToAppUnits(aRect.y, aAppUnitsPerDevPixel), + ToAppUnits(aRect.Width(), aAppUnitsPerDevPixel), + ToAppUnits(aRect.Height(), aAppUnitsPerDevPixel)); + } + + static nsRect ToAppUnits(const LayoutDeviceRect& aRect, + nscoord aAppUnitsPerDevPixel) { + return nsRect(ToAppUnits(aRect.x, aAppUnitsPerDevPixel), + ToAppUnits(aRect.y, aAppUnitsPerDevPixel), + ToAppUnits(aRect.Width(), aAppUnitsPerDevPixel), + ToAppUnits(aRect.Height(), aAppUnitsPerDevPixel)); + } + + static nsMargin ToAppUnits(const LayoutDeviceIntMargin& aMargin, + nscoord aAppUnitsPerDevPixel) { + return nsMargin(ToAppUnits(aMargin.top, aAppUnitsPerDevPixel), + ToAppUnits(aMargin.right, aAppUnitsPerDevPixel), + ToAppUnits(aMargin.bottom, aAppUnitsPerDevPixel), + ToAppUnits(aMargin.left, aAppUnitsPerDevPixel)); + } + + static nsMargin ToAppUnits(const LayoutDeviceMargin& aMargin, + nscoord aAppUnitsPerDevPixel) { + return nsMargin(ToAppUnits(aMargin.top, aAppUnitsPerDevPixel), + ToAppUnits(aMargin.right, aAppUnitsPerDevPixel), + ToAppUnits(aMargin.bottom, aAppUnitsPerDevPixel), + ToAppUnits(aMargin.left, aAppUnitsPerDevPixel)); + } +}; + +/* + * The pixels that layout rasterizes and delivers to the graphics code. + * These also are generally referred to as "device pixels" in layout code. + * Conversion between CSS pixels and LayerPixels is affected by: + * 1) the "display resolution" (see PresShell::SetResolution) + * 2) the "full zoom" (see nsPresContext::SetFullZoom) + * 3) the "widget scale" (see nsIWidget::GetDefaultScale) + * 4) rasterizing at a different scale in the presence of some CSS transforms + */ +struct LayerPixel {}; + +/* + * This is Layer coordinates with the Layer's CSS transform applied. + * It can be thought of as intermediate between LayerPixel and + * ParentLayerPixel, as further applying async transforms to this + * yields ParentLayerPixels. + */ +struct CSSTransformedLayerPixel {}; + +/* + * Layers are always composited to a render target. This unit + * represents one pixel in the render target. Note that for the + * root render target RenderTargetPixel == ScreenPixel. Also + * any ContainerLayer providing an intermediate surface will + * have RenderTargetPixel == LayerPixel. + */ +struct RenderTargetPixel {}; + +/* + * This unit represents one pixel in an image. Image space + * is largely independent of any other space. + */ +struct ImagePixel {}; + +/* + * The pixels that are displayed on the screen. + * On non-OMTC platforms this should be equivalent to LayerPixel units. + * On OMTC platforms these may diverge from LayerPixel units temporarily, + * while an asynchronous zoom is happening, but should eventually converge + * back to LayerPixel units. Some variables (such as those representing + * chrome UI element sizes) that are not subject to content zoom should + * generally be represented in ScreenPixel units. + */ +struct ScreenPixel {}; + +/* The layer coordinates of the parent frame. + * This can be arrived at in three ways: + * - Start with the CSS coordinates of the parent frame, multiply by the + * device scale and the cumulative resolution of the parent frame. + * - Start with the CSS coordinates of current frame, multiply by the device + * scale, the cumulative resolution of the current frame, and the scales + * from the CSS and async transforms of the current frame. + * - Start with global screen coordinates and unapply all CSS and async + * transforms from the root down to and including the parent. + * It's helpful to look at + * https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems to get a picture + * of how the various coordinate systems relate to each other. + */ +struct ParentLayerPixel {}; + +/* + * Pixels in the coordinate space used by the host OS to manage windows on the + * desktop. What these mean varies between OSs: + * - by default (unless implemented differently in platform-specific widget + * code) they are the same as LayoutDevicePixels + * - on Mac OS X, they're "cocoa points", which correspond to device pixels + * on a non-Retina display, and to 2x device pixels on Retina + * - on Windows *without* per-monitor DPI support, they are Windows "logical + * pixels", i.e. device pixels scaled according to the Windows display DPI + * scaling factor (typically one of 1.25, 1.5, 1.75, 2.0...) + * - on Windows *with* per-monitor DPI support, they are physical device pixels + * on each screen; note that this means the scaling between CSS pixels and + * desktop pixels may vary across multiple displays. + */ +struct DesktopPixel {}; + +struct ExternalPixel {}; + +// Operators to apply ScaleFactors directly to Coords, Points, Rects, Sizes and +// Margins + +template <class Src, class Dst> +gfx::CoordTyped<Dst> operator*(const gfx::CoordTyped<Src>& aCoord, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::CoordTyped<Dst>(aCoord.value * aScale.scale); +} + +template <class Src, class Dst> +gfx::CoordTyped<Dst> operator/(const gfx::CoordTyped<Src>& aCoord, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::CoordTyped<Dst>(aCoord.value / aScale.scale); +} + +template <class Src, class Dst> +gfx::PointTyped<Dst> operator*(const gfx::PointTyped<Src>& aPoint, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::PointTyped<Dst>(aPoint.x * aScale.scale, aPoint.y * aScale.scale); +} + +template <class Src, class Dst> +gfx::PointTyped<Dst> operator/(const gfx::PointTyped<Src>& aPoint, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::PointTyped<Dst>(aPoint.x / aScale.scale, aPoint.y / aScale.scale); +} + +template <class Src, class Dst, class F> +gfx::PointTyped<Dst, F> operator*( + const gfx::PointTyped<Src, F>& aPoint, + const gfx::BaseScaleFactors2D<Src, Dst, F>& aScale) { + return gfx::PointTyped<Dst, F>(aPoint.x * aScale.xScale, + aPoint.y * aScale.yScale); +} + +template <class Src, class Dst, class F> +gfx::PointTyped<Dst, F> operator/( + const gfx::PointTyped<Src, F>& aPoint, + const gfx::BaseScaleFactors2D<Dst, Src, F>& aScale) { + return gfx::PointTyped<Dst, F>(aPoint.x / aScale.xScale, + aPoint.y / aScale.yScale); +} + +template <class Src, class Dst> +gfx::PointTyped<Dst> operator*(const gfx::IntPointTyped<Src>& aPoint, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::PointTyped<Dst>(float(aPoint.x) * aScale.scale, + float(aPoint.y) * aScale.scale); +} + +template <class Src, class Dst> +gfx::PointTyped<Dst> operator/(const gfx::IntPointTyped<Src>& aPoint, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::PointTyped<Dst>(float(aPoint.x) / aScale.scale, + float(aPoint.y) / aScale.scale); +} + +template <class Src, class Dst, class F> +gfx::PointTyped<Dst, F> operator*( + const gfx::IntPointTyped<Src>& aPoint, + const gfx::BaseScaleFactors2D<Src, Dst, F>& aScale) { + return gfx::PointTyped<Dst, F>(F(aPoint.x) * aScale.xScale, + F(aPoint.y) * aScale.yScale); +} + +template <class Src, class Dst, class F> +gfx::PointTyped<Dst, F> operator/( + const gfx::IntPointTyped<Src>& aPoint, + const gfx::BaseScaleFactors2D<Dst, Src, F>& aScale) { + return gfx::PointTyped<Dst, F>(F(aPoint.x) / aScale.xScale, + F(aPoint.y) / aScale.yScale); +} + +template <class Src, class Dst> +gfx::RectTyped<Dst> operator*(const gfx::RectTyped<Src>& aRect, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::RectTyped<Dst>(aRect.x * aScale.scale, aRect.y * aScale.scale, + aRect.Width() * aScale.scale, + aRect.Height() * aScale.scale); +} + +template <class Src, class Dst> +gfx::RectTyped<Dst> operator/(const gfx::RectTyped<Src>& aRect, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::RectTyped<Dst>(aRect.x / aScale.scale, aRect.y / aScale.scale, + aRect.Width() / aScale.scale, + aRect.Height() / aScale.scale); +} + +template <class Src, class Dst, class F> +gfx::RectTyped<Dst, F> operator*( + const gfx::RectTyped<Src, F>& aRect, + const gfx::BaseScaleFactors2D<Src, Dst, F>& aScale) { + return gfx::RectTyped<Dst, F>( + aRect.x * aScale.xScale, aRect.y * aScale.yScale, + aRect.Width() * aScale.xScale, aRect.Height() * aScale.yScale); +} + +template <class Src, class Dst, class F> +gfx::RectTyped<Dst, F> operator/( + const gfx::RectTyped<Src, F>& aRect, + const gfx::BaseScaleFactors2D<Dst, Src, F>& aScale) { + return gfx::RectTyped<Dst, F>( + aRect.x / aScale.xScale, aRect.y / aScale.yScale, + aRect.Width() / aScale.xScale, aRect.Height() / aScale.yScale); +} + +template <class Src, class Dst> +gfx::RectTyped<Dst> operator*(const gfx::IntRectTyped<Src>& aRect, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::RectTyped<Dst>(float(aRect.x) * aScale.scale, + float(aRect.y) * aScale.scale, + float(aRect.Width()) * aScale.scale, + float(aRect.Height()) * aScale.scale); +} + +template <class Src, class Dst> +gfx::RectTyped<Dst> operator/(const gfx::IntRectTyped<Src>& aRect, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::RectTyped<Dst>(float(aRect.x) / aScale.scale, + float(aRect.y) / aScale.scale, + float(aRect.Width()) / aScale.scale, + float(aRect.Height()) / aScale.scale); +} + +template <class Src, class Dst, class F> +gfx::RectTyped<Dst, F> operator*( + const gfx::IntRectTyped<Src>& aRect, + const gfx::BaseScaleFactors2D<Src, Dst, F>& aScale) { + return gfx::RectTyped<Dst, F>( + F(aRect.x) * aScale.xScale, F(aRect.y) * aScale.yScale, + F(aRect.Width()) * aScale.xScale, F(aRect.Height()) * aScale.yScale); +} + +template <class Src, class Dst, class F> +gfx::RectTyped<Dst, F> operator/( + const gfx::IntRectTyped<Src>& aRect, + const gfx::BaseScaleFactors2D<Dst, Src, F>& aScale) { + return gfx::RectTyped<Dst, F>( + F(aRect.x) / aScale.xScale, F(aRect.y) / aScale.yScale, + F(aRect.Width()) / aScale.xScale, F(aRect.Height()) / aScale.yScale); +} + +template <class Src, class Dst> +gfx::SizeTyped<Dst> operator*(const gfx::SizeTyped<Src>& aSize, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::SizeTyped<Dst>(aSize.width * aScale.scale, + aSize.height * aScale.scale); +} + +template <class Src, class Dst> +gfx::SizeTyped<Dst> operator/(const gfx::SizeTyped<Src>& aSize, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::SizeTyped<Dst>(aSize.width / aScale.scale, + aSize.height / aScale.scale); +} + +template <class Src, class Dst, class F> +gfx::SizeTyped<Dst, F> operator*( + const gfx::SizeTyped<Src, F>& aSize, + const gfx::BaseScaleFactors2D<Src, Dst, F>& aScale) { + return gfx::SizeTyped<Dst, F>(aSize.width * aScale.xScale, + aSize.height * aScale.yScale); +} + +template <class Src, class Dst, class F> +gfx::SizeTyped<Dst, F> operator/( + const gfx::SizeTyped<Src, F>& aSize, + const gfx::BaseScaleFactors2D<Dst, Src, F>& aScale) { + return gfx::SizeTyped<Dst, F>(aSize.width / aScale.xScale, + aSize.height / aScale.yScale); +} + +template <class Src, class Dst> +gfx::SizeTyped<Dst> operator*(const gfx::IntSizeTyped<Src>& aSize, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::SizeTyped<Dst>(float(aSize.width) * aScale.scale, + float(aSize.height) * aScale.scale); +} + +template <class Src, class Dst> +gfx::SizeTyped<Dst> operator/(const gfx::IntSizeTyped<Src>& aSize, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::SizeTyped<Dst>(float(aSize.width) / aScale.scale, + float(aSize.height) / aScale.scale); +} + +template <class Src, class Dst, class F> +gfx::SizeTyped<Dst, F> operator*( + const gfx::IntSizeTyped<Src>& aSize, + const gfx::BaseScaleFactors2D<Src, Dst, F>& aScale) { + return gfx::SizeTyped<Dst, F>(F(aSize.width) * aScale.xScale, + F(aSize.height) * aScale.yScale); +} + +template <class Src, class Dst, class F> +gfx::SizeTyped<Dst, F> operator/( + const gfx::IntSizeTyped<Src>& aSize, + const gfx::BaseScaleFactors2D<Dst, Src, F>& aScale) { + return gfx::SizeTyped<Dst, F>(F(aSize.width) / aScale.xScale, + F(aSize.height) / aScale.yScale); +} + +template <class Src, class Dst> +gfx::MarginTyped<Dst> operator*(const gfx::MarginTyped<Src>& aMargin, + const gfx::ScaleFactor<Src, Dst>& aScale) { + return gfx::MarginTyped<Dst>( + aMargin.top * aScale.scale, aMargin.right * aScale.scale, + aMargin.bottom * aScale.scale, aMargin.left * aScale.scale); +} + +template <class Src, class Dst> +gfx::MarginTyped<Dst> operator/(const gfx::MarginTyped<Src>& aMargin, + const gfx::ScaleFactor<Dst, Src>& aScale) { + return gfx::MarginTyped<Dst>( + aMargin.top / aScale.scale, aMargin.right / aScale.scale, + aMargin.bottom / aScale.scale, aMargin.left / aScale.scale); +} + +template <class Src, class Dst, class F> +gfx::MarginTyped<Dst, F> operator*( + const gfx::MarginTyped<Src, F>& aMargin, + const gfx::BaseScaleFactors2D<Src, Dst, F>& aScale) { + return gfx::MarginTyped<Dst, F>( + aMargin.top * aScale.yScale, aMargin.right * aScale.xScale, + aMargin.bottom * aScale.yScale, aMargin.left * aScale.xScale); +} + +template <class Src, class Dst, class F> +gfx::MarginTyped<Dst, F> operator/( + const gfx::MarginTyped<Src, F>& aMargin, + const gfx::BaseScaleFactors2D<Dst, Src, F>& aScale) { + return gfx::MarginTyped<Dst, F>( + aMargin.top / aScale.yScale, aMargin.right / aScale.xScale, + aMargin.bottom / aScale.yScale, aMargin.left / aScale.xScale); +} + +// Calculate the max or min or the ratios of the widths and heights of two +// sizes, returning a scale factor in the correct units. + +template <class Src, class Dst> +gfx::ScaleFactor<Src, Dst> MaxScaleRatio(const gfx::SizeTyped<Dst>& aDestSize, + const gfx::SizeTyped<Src>& aSrcSize) { + MOZ_ASSERT(aSrcSize.width != 0 && aSrcSize.height != 0, + "Caller must verify aSrcSize has nonzero components, " + "to avoid division by 0 here"); + return gfx::ScaleFactor<Src, Dst>(std::max( + aDestSize.width / aSrcSize.width, aDestSize.height / aSrcSize.height)); +} + +template <class Src, class Dst> +gfx::ScaleFactor<Src, Dst> MinScaleRatio(const gfx::SizeTyped<Dst>& aDestSize, + const gfx::SizeTyped<Src>& aSrcSize) { + MOZ_ASSERT(aSrcSize.width != 0 && aSrcSize.height != 0, + "Caller must verify aSrcSize has nonzero components, " + "to avoid division by 0 here"); + return gfx::ScaleFactor<Src, Dst>(std::min( + aDestSize.width / aSrcSize.width, aDestSize.height / aSrcSize.height)); +} + +template <typename T> +struct CoordOfImpl; + +template <typename Units> +struct CoordOfImpl<gfx::PointTyped<Units>> { + typedef gfx::CoordTyped<Units> Type; +}; + +template <typename Units> +struct CoordOfImpl<gfx::IntPointTyped<Units>> { + typedef gfx::IntCoordTyped<Units> Type; +}; + +template <typename Units> +struct CoordOfImpl<gfx::RectTyped<Units>> { + typedef gfx::CoordTyped<Units> Type; +}; + +template <typename Units> +struct CoordOfImpl<gfx::IntRectTyped<Units>> { + typedef gfx::IntCoordTyped<Units> Type; +}; + +template <typename Units> +struct CoordOfImpl<gfx::SizeTyped<Units>> { + typedef gfx::CoordTyped<Units> Type; +}; + +template <typename T> +using CoordOf = typename CoordOfImpl<T>::Type; + +} // namespace mozilla + +#endif |