LCOV - code coverage report
Current view: top level - layout/base - UnitTransforms.h (source / functions) Hit Total Coverage
Test: output.info Lines: 46 69 66.7 %
Date: 2017-07-14 16:53:18 Functions: 37 62 59.7 %
Legend: Lines: hit not hit

          Line data    Source code
       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 MOZ_UNIT_TRANSFORMS_H_
       8             : #define MOZ_UNIT_TRANSFORMS_H_
       9             : 
      10             : #include "Units.h"
      11             : #include "mozilla/gfx/Matrix.h"
      12             : #include "mozilla/Maybe.h"
      13             : #include "nsRegion.h"
      14             : 
      15             : namespace mozilla {
      16             : 
      17             : // Convenience functions for converting an entity from one strongly-typed
      18             : // coordinate system to another without changing the values it stores (this
      19             : // can be thought of as a cast).
      20             : // To use these functions, you must provide a justification for each use!
      21             : // Feel free to add more justifications to PixelCastJustification, along with
      22             : // a comment that explains under what circumstances it is appropriate to use.
      23             : 
      24             : enum class PixelCastJustification : uint8_t {
      25             :   // For the root layer, Screen Pixel = Parent Layer Pixel.
      26             :   ScreenIsParentLayerForRoot,
      27             :   // On the layout side, Screen Pixel = LayoutDevice at the outer-window level.
      28             :   LayoutDeviceIsScreenForBounds,
      29             :   // For the root layer, Render Target Pixel = Parent Layer Pixel.
      30             :   RenderTargetIsParentLayerForRoot,
      31             :   // For the root composition size we want to view it as layer pixels in any layer
      32             :   ParentLayerToLayerForRootComposition,
      33             :   // The Layer coordinate space for one layer is the ParentLayer coordinate
      34             :   // space for its children
      35             :   MovingDownToChildren,
      36             :   // The transform that is usually used to convert between two coordinate
      37             :   // systems is not available (for example, because the object that stores it
      38             :   // is being destroyed), so fall back to the identity.
      39             :   TransformNotAvailable,
      40             :   // When an OS event is initially constructed, its reference point is
      41             :   // technically in screen pixels, as it has not yet accounted for any
      42             :   // asynchronous transforms. This justification is for viewing the initial
      43             :   // reference point as a screen point. The reverse is useful when synthetically
      44             :   // created WidgetEvents need to be converted back to InputData.
      45             :   LayoutDeviceIsScreenForUntransformedEvent,
      46             :   // Similar to LayoutDeviceIsScreenForUntransformedEvent, PBrowser handles
      47             :   // some widget/tab dimension information as the OS does -- in screen units.
      48             :   LayoutDeviceIsScreenForTabDims,
      49             :   // A combination of LayoutDeviceIsScreenForBounds and
      50             :   // ScreenIsParentLayerForRoot, which is how we're using it.
      51             :   LayoutDeviceIsParentLayerForRCDRSF,
      52             :   // Used to treat the product of AsyncTransformComponentMatrix objects
      53             :   // as an AsyncTransformMatrix. See the definitions of these matrices in
      54             :   // LayersTypes.h for details.
      55             :   MultipleAsyncTransforms,
      56             :   // We have reason to believe a layer doesn't have a local transform.
      57             :   // Should only be used if we've already checked or asserted this.
      58             :   NoTransformOnLayer,
      59             :   // When building non-rasterized WebRender layers (e.g.
      60             :   // WebRenderDisplayItemLayer, or anything else that doesn't deal in textures),
      61             :   // there is no "resolution" and so the LayoutDevicePixel space is equal to the
      62             :   // LayerPixel space.
      63             :   WebRenderHasUnitResolution
      64             : };
      65             : 
      66             : template <class TargetUnits, class SourceUnits>
      67           0 : gfx::CoordTyped<TargetUnits> ViewAs(const gfx::CoordTyped<SourceUnits>& aCoord, PixelCastJustification) {
      68           0 :   return gfx::CoordTyped<TargetUnits>(aCoord.value);
      69             : }
      70             : template <class TargetUnits, class SourceUnits>
      71          27 : gfx::SizeTyped<TargetUnits> ViewAs(const gfx::SizeTyped<SourceUnits>& aSize, PixelCastJustification) {
      72          27 :   return gfx::SizeTyped<TargetUnits>(aSize.width, aSize.height);
      73             : }
      74             : template <class TargetUnits, class SourceUnits>
      75           8 : gfx::IntSizeTyped<TargetUnits> ViewAs(const gfx::IntSizeTyped<SourceUnits>& aSize, PixelCastJustification) {
      76           8 :   return gfx::IntSizeTyped<TargetUnits>(aSize.width, aSize.height);
      77             : }
      78             : template <class TargetUnits, class SourceUnits>
      79          33 : gfx::PointTyped<TargetUnits> ViewAs(const gfx::PointTyped<SourceUnits>& aPoint, PixelCastJustification) {
      80          33 :   return gfx::PointTyped<TargetUnits>(aPoint.x, aPoint.y);
      81             : }
      82             : template <class TargetUnits, class SourceUnits>
      83           7 : gfx::IntPointTyped<TargetUnits> ViewAs(const gfx::IntPointTyped<SourceUnits>& aPoint, PixelCastJustification) {
      84           7 :   return gfx::IntPointTyped<TargetUnits>(aPoint.x, aPoint.y);
      85             : }
      86             : template <class TargetUnits, class SourceUnits>
      87           0 : gfx::RectTyped<TargetUnits> ViewAs(const gfx::RectTyped<SourceUnits>& aRect, PixelCastJustification) {
      88           0 :   return gfx::RectTyped<TargetUnits>(aRect.x, aRect.y, aRect.width, aRect.height);
      89             : }
      90             : template <class TargetUnits, class SourceUnits>
      91         241 : gfx::IntRectTyped<TargetUnits> ViewAs(const gfx::IntRectTyped<SourceUnits>& aRect, PixelCastJustification) {
      92         241 :   return gfx::IntRectTyped<TargetUnits>(aRect.x, aRect.y, aRect.width, aRect.height);
      93             : }
      94             : template <class TargetUnits, class SourceUnits>
      95             : gfx::MarginTyped<TargetUnits> ViewAs(const gfx::MarginTyped<SourceUnits>& aMargin, PixelCastJustification) {
      96             :   return gfx::MarginTyped<TargetUnits>(aMargin.top, aMargin.right, aMargin.bottom, aMargin.left);
      97             : }
      98             : template <class TargetUnits, class SourceUnits>
      99             : gfx::IntMarginTyped<TargetUnits> ViewAs(const gfx::IntMarginTyped<SourceUnits>& aMargin, PixelCastJustification) {
     100             :   return gfx::IntMarginTyped<TargetUnits>(aMargin.top, aMargin.right, aMargin.bottom, aMargin.left);
     101             : }
     102             : template <class TargetUnits, class SourceUnits>
     103         121 : gfx::IntRegionTyped<TargetUnits> ViewAs(const gfx::IntRegionTyped<SourceUnits>& aRegion, PixelCastJustification) {
     104         121 :   return gfx::IntRegionTyped<TargetUnits>::FromUnknownRegion(aRegion.ToUnknownRegion());
     105             : }
     106             : template <class NewTargetUnits, class OldTargetUnits, class SourceUnits>
     107           0 : gfx::ScaleFactor<SourceUnits, NewTargetUnits> ViewTargetAs(
     108             :     const gfx::ScaleFactor<SourceUnits, OldTargetUnits>& aScaleFactor,
     109             :     PixelCastJustification) {
     110           0 :   return gfx::ScaleFactor<SourceUnits, NewTargetUnits>(aScaleFactor.scale);
     111             : }
     112             : template <class TargetUnits, class SourceUnits>
     113          29 : Maybe<gfx::IntRectTyped<TargetUnits>> ViewAs(const Maybe<gfx::IntRectTyped<SourceUnits>>& aRect, PixelCastJustification aJustification) {
     114          29 :   if (aRect.isSome()) {
     115           0 :     return Some(ViewAs<TargetUnits>(aRect.value(), aJustification));
     116             :   }
     117          29 :   return Nothing();
     118             : }
     119             : // Unlike the other functions in this category, this function takes the
     120             : // target matrix type, rather than its source and target unit types, as
     121             : // the explicit template argument, so an example invocation is:
     122             : //    ViewAs<ScreenToLayerMatrix4x4>(otherTypedMatrix, justification)
     123             : // The reason is that if it took the source and target unit types as two
     124             : // template arguments, there may be some confusion as to which is the
     125             : // source and which is the target.
     126             : template <class TargetMatrix, class SourceMatrixSourceUnits, class SourceMatrixTargetUnits>
     127         109 : TargetMatrix ViewAs(
     128             :     const gfx::Matrix4x4Typed<SourceMatrixSourceUnits, SourceMatrixTargetUnits>& aMatrix,
     129             :     PixelCastJustification) {
     130         109 :   return TargetMatrix::FromUnknownMatrix(aMatrix.ToUnknownMatrix());
     131             : }
     132             : 
     133             : // Convenience functions for casting untyped entities to typed entities.
     134             : // Using these functions does not require a justification, but once we convert
     135             : // all code to use strongly typed units they should not be needed any longer.
     136             : template <class TargetUnits>
     137             : gfx::PointTyped<TargetUnits> ViewAs(const gfxPoint& aPoint) {
     138             :   return gfx::PointTyped<TargetUnits>(aPoint.x, aPoint.y);
     139             : }
     140             : template <class TargetUnits>
     141             : gfx::PointTyped<TargetUnits> ViewAs(const gfx::Point& aPoint) {
     142             :   return gfx::PointTyped<TargetUnits>(aPoint.x, aPoint.y);
     143             : }
     144             : template <class TargetUnits>
     145           0 : gfx::RectTyped<TargetUnits> ViewAs(const gfx::Rect& aRect) {
     146           0 :   return gfx::RectTyped<TargetUnits>(aRect.x, aRect.y, aRect.width, aRect.height);
     147             : }
     148             : template <class TargetUnits>
     149             : gfx::IntSizeTyped<TargetUnits> ViewAs(const nsIntSize& aSize) {
     150             :   return gfx::IntSizeTyped<TargetUnits>(aSize.width, aSize.height);
     151             : }
     152             : template <class TargetUnits>
     153        1507 : gfx::IntPointTyped<TargetUnits> ViewAs(const nsIntPoint& aPoint) {
     154        1507 :   return gfx::IntPointTyped<TargetUnits>(aPoint.x, aPoint.y);
     155             : }
     156             : template <class TargetUnits>
     157        1557 : gfx::IntRectTyped<TargetUnits> ViewAs(const nsIntRect& aRect) {
     158        1557 :   return gfx::IntRectTyped<TargetUnits>(aRect.x, aRect.y, aRect.width, aRect.height);
     159             : }
     160             : template <class TargetUnits>
     161         121 : gfx::IntRegionTyped<TargetUnits> ViewAs(const nsIntRegion& aRegion) {
     162         121 :   return gfx::IntRegionTyped<TargetUnits>::FromUnknownRegion(aRegion);
     163             : }
     164             : // Unlike the other functions in this category, this function takes the
     165             : // target matrix type, rather than its source and target unit types, as
     166             : // the template argument, so an example invocation is:
     167             : //    ViewAs<ScreenToLayerMatrix4x4>(untypedMatrix)
     168             : // The reason is that if it took the source and target unit types as two
     169             : // template arguments, there may be some confusion as to which is the
     170             : // source and which is the target.
     171             : template <class TypedMatrix>
     172         752 : TypedMatrix ViewAs(const gfx::Matrix4x4& aMatrix) {
     173         752 :   return TypedMatrix::FromUnknownMatrix(aMatrix);
     174             : }
     175             : 
     176             : // Convenience functions for transforming an entity from one strongly-typed
     177             : // coordinate system to another using the provided transformation matrix.
     178             : template <typename TargetUnits, typename SourceUnits>
     179             : static gfx::PointTyped<TargetUnits>
     180           0 : TransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     181             :             const gfx::PointTyped<SourceUnits>& aPoint)
     182             : {
     183           0 :   return aTransform.TransformPoint(aPoint);
     184             : }
     185             : template <typename TargetUnits, typename SourceUnits>
     186             : static gfx::IntPointTyped<TargetUnits>
     187             : TransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     188             :             const gfx::IntPointTyped<SourceUnits>& aPoint)
     189             : {
     190             :   return RoundedToInt(TransformBy(aTransform, gfx::PointTyped<SourceUnits>(aPoint)));
     191             : }
     192             : template <typename TargetUnits, typename SourceUnits>
     193             : static gfx::RectTyped<TargetUnits>
     194         550 : TransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     195             :             const gfx::RectTyped<SourceUnits>& aRect)
     196             : {
     197         550 :   return aTransform.TransformBounds(aRect);
     198             : }
     199             : template <typename TargetUnits, typename SourceUnits>
     200             : static gfx::IntRectTyped<TargetUnits>
     201          69 : TransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     202             :             const gfx::IntRectTyped<SourceUnits>& aRect)
     203             : {
     204          69 :   return RoundedToInt(TransformBy(aTransform, gfx::RectTyped<SourceUnits>(aRect)));
     205             : }
     206             : template <typename TargetUnits, typename SourceUnits>
     207             : static gfx::IntRegionTyped<TargetUnits>
     208         121 : TransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     209             :             const gfx::IntRegionTyped<SourceUnits>& aRegion)
     210             : {
     211         242 :   return ViewAs<TargetUnits>(aRegion.ToUnknownRegion().Transform(
     212         242 :       aTransform.ToUnknownMatrix()));
     213             : }
     214             : 
     215             : // Transform |aVector|, which is anchored at |aAnchor|, by the given transform
     216             : // matrix, yielding a point in |TargetUnits|.
     217             : // The anchor is necessary because with 3D tranforms, the location of the
     218             : // vector can affect the result of the transform.
     219             : template <typename TargetUnits, typename SourceUnits>
     220             : static gfx::PointTyped<TargetUnits>
     221           0 : TransformVector(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     222             :                 const gfx::PointTyped<SourceUnits>& aVector,
     223             :                 const gfx::PointTyped<SourceUnits>& aAnchor)
     224             : {
     225           0 :   gfx::PointTyped<TargetUnits> transformedStart = TransformBy(aTransform, aAnchor);
     226           0 :   gfx::PointTyped<TargetUnits> transformedEnd = TransformBy(aTransform, aAnchor + aVector);
     227           0 :   return transformedEnd - transformedStart;
     228             : }
     229             : 
     230             : // UntransformBy() and UntransformVector() are like TransformBy() and
     231             : // TransformVector(), respectively, but are intended for cases where
     232             : // the transformation matrix is the inverse of a 3D projection. When
     233             : // using such transforms, the resulting Point4D is only meaningful
     234             : // if it has a positive w-coordinate. To handle this, these functions
     235             : // return a Maybe object which contains a value if and only if the
     236             : // result is meaningful
     237             : template <typename TargetUnits, typename SourceUnits>
     238             : static Maybe<gfx::PointTyped<TargetUnits>>
     239          24 : UntransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     240             :               const gfx::PointTyped<SourceUnits>& aPoint)
     241             : {
     242          24 :   gfx::Point4DTyped<TargetUnits> point = aTransform.ProjectPoint(aPoint);
     243          24 :   if (!point.HasPositiveWCoord()) {
     244           0 :     return Nothing();
     245             :   }
     246          24 :   return Some(point.As2DPoint());
     247             : }
     248             : template <typename TargetUnits, typename SourceUnits>
     249             : static Maybe<gfx::IntPointTyped<TargetUnits>>
     250           1 : UntransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     251             :               const gfx::IntPointTyped<SourceUnits>& aPoint)
     252             : {
     253           1 :   gfx::PointTyped<SourceUnits> p = aPoint;
     254           1 :   gfx::Point4DTyped<TargetUnits> point = aTransform.ProjectPoint(p);
     255           1 :   if (!point.HasPositiveWCoord()) {
     256           0 :     return Nothing();
     257             :   }
     258           1 :   return Some(RoundedToInt(point.As2DPoint()));
     259             : }
     260             : 
     261             : // The versions of UntransformBy() that take a rectangle also take a clip,
     262             : // which represents the bounds within which the target must fall. The
     263             : // result of the transform is intersected with this clip, and is considered
     264             : // meaningful if the intersection is not empty.
     265             : template <typename TargetUnits, typename SourceUnits>
     266             : static Maybe<gfx::RectTyped<TargetUnits>>
     267         115 : UntransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     268             :               const gfx::RectTyped<SourceUnits>& aRect,
     269             :               const gfx::RectTyped<TargetUnits>& aClip)
     270             : {
     271         115 :   gfx::RectTyped<TargetUnits> rect = aTransform.ProjectRectBounds(aRect, aClip);
     272         115 :   if (rect.IsEmpty()) {
     273          11 :     return Nothing();
     274             :   }
     275         104 :   return Some(rect);
     276             : }
     277             : template <typename TargetUnits, typename SourceUnits>
     278             : static Maybe<gfx::IntRectTyped<TargetUnits>>
     279             : UntransformBy(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     280             :               const gfx::IntRectTyped<SourceUnits>& aRect,
     281             :               const gfx::IntRectTyped<TargetUnits>& aClip)
     282             : {
     283             :   gfx::RectTyped<TargetUnits> rect = aTransform.ProjectRectBounds(aRect, aClip);
     284             :   if (rect.IsEmpty()) {
     285             :     return Nothing();
     286             :   }
     287             :   return Some(RoundedToInt(rect));
     288             : }
     289             : 
     290             : template <typename TargetUnits, typename SourceUnits>
     291             : static Maybe<gfx::PointTyped<TargetUnits>>
     292           0 : UntransformVector(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransform,
     293             :                   const gfx::PointTyped<SourceUnits>& aVector,
     294             :                   const gfx::PointTyped<SourceUnits>& aAnchor)
     295             : {
     296           0 :   gfx::Point4DTyped<TargetUnits> projectedAnchor = aTransform.ProjectPoint(aAnchor);
     297           0 :   gfx::Point4DTyped<TargetUnits> projectedTarget = aTransform.ProjectPoint(aAnchor + aVector);
     298           0 :   if (!projectedAnchor.HasPositiveWCoord() || !projectedTarget.HasPositiveWCoord()){
     299           0 :     return Nothing();
     300             :   }
     301           0 :   return Some(projectedTarget.As2DPoint() - projectedAnchor.As2DPoint());
     302             : }
     303             : 
     304             : } // namespace mozilla
     305             : 
     306             : #endif

Generated by: LCOV version 1.13