LCOV - code coverage report
Current view: top level - gfx/2d - Coord.h (source / functions) Hit Total Coverage
Test: output.info Lines: 5 11 45.5 %
Date: 2017-07-14 16:53:18 Functions: 68 79 86.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef MOZILLA_GFX_COORD_H_
       7             : #define MOZILLA_GFX_COORD_H_
       8             : 
       9             : #include "mozilla/Attributes.h"
      10             : #include "mozilla/TypeTraits.h" // For IsSame
      11             : #include "Types.h"
      12             : #include "BaseCoord.h"
      13             : 
      14             : #include <cmath>
      15             : 
      16             : namespace mozilla {
      17             : 
      18             : template <typename> struct IsPixel;
      19             : 
      20             : namespace gfx {
      21             : 
      22             : template <class units> struct IntCoordTyped;
      23             : template <class units, class F = Float> struct CoordTyped;
      24             : 
      25             : // CommonType<coord, primitive> is a metafunction that returns the type of the
      26             : // result of an arithmetic operation on the underlying type of a strongly-typed
      27             : // coordinate type 'coord', and a primitive type 'primitive'. C++ rules for
      28             : // arithmetic conversions are designed to avoid losing information - for
      29             : // example, the result of adding an int and a float is a float - and we want
      30             : // the same behaviour when mixing our coordinate types with primitive types.
      31             : // We get C++ to compute the desired result type using 'decltype'.
      32             : 
      33             : template <class coord, class primitive>
      34             : struct CommonType;
      35             : 
      36             : template <class units, class primitive>
      37             : struct CommonType<IntCoordTyped<units>, primitive> {
      38             :     typedef decltype(int32_t() + primitive()) type;
      39             : };
      40             : 
      41             : template <class units, class F, class primitive>
      42             : struct CommonType<CoordTyped<units, F>, primitive> {
      43             :     typedef decltype(F() + primitive()) type;
      44             : };
      45             : 
      46             : // This is a base class that provides mixed-type operator overloads between
      47             : // a strongly-typed Coord and a primitive value. It is needed to avoid
      48             : // ambiguities at mixed-type call sites, because Coord classes are implicitly
      49             : // convertible to their underlying value type. As we transition more of our code
      50             : // to strongly-typed classes, we may be able to remove some or all of these
      51             : // overloads.
      52             : 
      53             : template <bool B, class coord, class primitive>
      54       74094 : struct CoordOperatorsHelper {
      55             :   // Using SFINAE (Substitution Failure Is Not An Error) to suppress redundant
      56             :   // operators
      57             : };
      58             : 
      59             : template <class coord, class primitive>
      60      259150 : struct CoordOperatorsHelper<true, coord, primitive> {
      61             :   friend bool operator==(coord aA, primitive aB) {
      62             :     return aA.value == aB;
      63             :   }
      64             :   friend bool operator==(primitive aA, coord aB) {
      65             :     return aA == aB.value;
      66             :   }
      67             :   friend bool operator!=(coord aA, primitive aB) {
      68             :     return aA.value != aB;
      69             :   }
      70             :   friend bool operator!=(primitive aA, coord aB) {
      71             :     return aA != aB.value;
      72             :   }
      73             : 
      74             :   typedef typename CommonType<coord, primitive>::type result_type;
      75             : 
      76             :   friend result_type operator+(coord aA, primitive aB) {
      77             :     return aA.value + aB;
      78             :   }
      79             :   friend result_type operator+(primitive aA, coord aB) {
      80             :     return aA + aB.value;
      81             :   }
      82             :   friend result_type operator-(coord aA, primitive aB) {
      83             :     return aA.value - aB;
      84             :   }
      85             :   friend result_type operator-(primitive aA, coord aB) {
      86             :     return aA - aB.value;
      87             :   }
      88           0 :   friend result_type operator*(coord aCoord, primitive aScale) {
      89           0 :     return aCoord.value * aScale;
      90             :   }
      91           0 :   friend result_type operator*(primitive aScale, coord aCoord) {
      92           0 :     return aScale * aCoord.value;
      93             :   }
      94           0 :   friend result_type operator/(coord aCoord, primitive aScale) {
      95           0 :     return aCoord.value / aScale;
      96             :   }
      97             :   // 'scale / coord' is intentionally omitted because it doesn't make sense.
      98             : };
      99             : 
     100             : // Note: 'IntCoordTyped<units>' and 'CoordTyped<units>' do not derive from
     101             : // 'units' to work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61959.
     102             : 
     103             : template<class units>
     104             : struct IntCoordTyped :
     105             :   public BaseCoord< int32_t, IntCoordTyped<units> >,
     106             :   public CoordOperatorsHelper< true, IntCoordTyped<units>, float >,
     107             :   public CoordOperatorsHelper< true, IntCoordTyped<units>, double > {
     108             :   static_assert(IsPixel<units>::value,
     109             :                 "'units' must be a coordinate system tag");
     110             : 
     111             :   typedef BaseCoord< int32_t, IntCoordTyped<units> > Super;
     112             : 
     113             :   constexpr IntCoordTyped() : Super() {}
     114       18434 :   constexpr MOZ_IMPLICIT IntCoordTyped(int32_t aValue) : Super(aValue) {}
     115             : };
     116             : 
     117             : template<class units, class F>
     118             : struct CoordTyped :
     119             :   public BaseCoord< F, CoordTyped<units, F> >,
     120             :   public CoordOperatorsHelper< !IsSame<F, int32_t>::value, CoordTyped<units, F>, int32_t >,
     121             :   public CoordOperatorsHelper< !IsSame<F, uint32_t>::value, CoordTyped<units, F>, uint32_t >,
     122             :   public CoordOperatorsHelper< !IsSame<F, double>::value, CoordTyped<units, F>, double >,
     123             :   public CoordOperatorsHelper< !IsSame<F, float>::value, CoordTyped<units, F>, float > {
     124             :   static_assert(IsPixel<units>::value,
     125             :                 "'units' must be a coordinate system tag");
     126             : 
     127             :   typedef BaseCoord< F, CoordTyped<units, F> > Super;
     128             : 
     129        1448 :   constexpr CoordTyped() : Super() {}
     130       72646 :   constexpr MOZ_IMPLICIT CoordTyped(F aValue) : Super(aValue) {}
     131             :   explicit constexpr CoordTyped(const IntCoordTyped<units>& aCoord) : Super(F(aCoord.value)) {}
     132             : 
     133             :   void Round() {
     134             :     this->value = floor(this->value + 0.5);
     135             :   }
     136             :   void Truncate() {
     137             :     this->value = int32_t(this->value);
     138             :   }
     139             : 
     140             :   IntCoordTyped<units> Rounded() const {
     141             :     return IntCoordTyped<units>(int32_t(floor(this->value + 0.5)));
     142             :   }
     143             :   IntCoordTyped<units> Truncated() const {
     144             :     return IntCoordTyped<units>(int32_t(this->value));
     145             :   }
     146             : };
     147             : 
     148             : } // namespace gfx
     149             : } // namespace mozilla
     150             : 
     151             : #endif /* MOZILLA_GFX_COORD_H_ */

Generated by: LCOV version 1.13