LCOV - code coverage report
Current view: top level - gfx/2d - Rect.h (source / functions) Hit Total Coverage
Test: output.info Lines: 101 124 81.5 %
Date: 2017-07-14 16:53:18 Functions: 82 116 70.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: c++; tab-width: 2; 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_RECT_H_
       7             : #define MOZILLA_GFX_RECT_H_
       8             : 
       9             : #include "BaseRect.h"
      10             : #include "BaseMargin.h"
      11             : #include "NumericTools.h"
      12             : #include "Point.h"
      13             : #include "Tools.h"
      14             : #include "mozilla/Maybe.h"
      15             : 
      16             : #include <cmath>
      17             : 
      18             : namespace mozilla {
      19             : 
      20             : template <typename> struct IsPixel;
      21             : 
      22             : namespace gfx {
      23             : 
      24             : template<class units, class F> struct RectTyped;
      25             : 
      26             : template<class units>
      27             : struct IntMarginTyped:
      28             :     public BaseMargin<int32_t, IntMarginTyped<units> >,
      29             :     public units {
      30             :     static_assert(IsPixel<units>::value,
      31             :                   "'units' must be a coordinate system tag");
      32             : 
      33             :     typedef BaseMargin<int32_t, IntMarginTyped<units> > Super;
      34             : 
      35        1137 :     IntMarginTyped() : Super() {}
      36         856 :     IntMarginTyped(int32_t aTop, int32_t aRight, int32_t aBottom, int32_t aLeft) :
      37         856 :         Super(aTop, aRight, aBottom, aLeft) {}
      38             : 
      39             :     // XXX When all of the code is ported, the following functions to convert
      40             :     // to and from unknown types should be removed.
      41             : 
      42           0 :     static IntMarginTyped<units> FromUnknownMargin(const IntMarginTyped<UnknownUnits>& aMargin) {
      43           0 :         return IntMarginTyped<units>(aMargin.top, aMargin.right,
      44           0 :                                      aMargin.bottom, aMargin.left);
      45             :     }
      46             : 
      47             :     IntMarginTyped<UnknownUnits> ToUnknownMargin() const {
      48             :         return IntMarginTyped<UnknownUnits>(this->top, this->right,
      49             :                                             this->bottom, this->left);
      50             :     }
      51             : };
      52             : typedef IntMarginTyped<UnknownUnits> IntMargin;
      53             : 
      54             : template<class units, class F = Float>
      55             : struct MarginTyped:
      56             :     public BaseMargin<F, MarginTyped<units, F> >,
      57             :     public units {
      58             :     static_assert(IsPixel<units>::value,
      59             :                   "'units' must be a coordinate system tag");
      60             : 
      61             :     typedef BaseMargin<F, MarginTyped<units, F> > Super;
      62             : 
      63         324 :     MarginTyped() : Super() {}
      64         243 :     MarginTyped(F aTop, F aRight, F aBottom, F aLeft) :
      65         243 :         Super(aTop, aRight, aBottom, aLeft) {}
      66          36 :     explicit MarginTyped(const IntMarginTyped<units>& aMargin) :
      67          72 :         Super(F(aMargin.top), F(aMargin.right),
      68         108 :               F(aMargin.bottom), F(aMargin.left)) {}
      69             : };
      70             : typedef MarginTyped<UnknownUnits> Margin;
      71             : typedef MarginTyped<UnknownUnits, double> MarginDouble;
      72             : 
      73             : template<class units>
      74             : IntMarginTyped<units> RoundedToInt(const MarginTyped<units>& aMargin)
      75             : {
      76             :   return IntMarginTyped<units>(int32_t(floorf(aMargin.top + 0.5f)),
      77             :                                int32_t(floorf(aMargin.right + 0.5f)),
      78             :                                int32_t(floorf(aMargin.bottom + 0.5f)),
      79             :                                int32_t(floorf(aMargin.left + 0.5f)));
      80             : }
      81             : 
      82             : template<class units>
      83             : struct IntRectTyped :
      84             :     public BaseRect<int32_t, IntRectTyped<units>, IntPointTyped<units>, IntSizeTyped<units>, IntMarginTyped<units> >,
      85             :     public units {
      86             :     static_assert(IsPixel<units>::value,
      87             :                   "'units' must be a coordinate system tag");
      88             : 
      89             :     typedef BaseRect<int32_t, IntRectTyped<units>, IntPointTyped<units>, IntSizeTyped<units>, IntMarginTyped<units> > Super;
      90             :     typedef IntRectTyped<units> Self;
      91             :     typedef IntParam<int32_t> ToInt;
      92             : 
      93       31692 :     IntRectTyped() : Super() {}
      94         523 :     IntRectTyped(const IntPointTyped<units>& aPos, const IntSizeTyped<units>& aSize) :
      95         523 :         Super(aPos, aSize) {}
      96             : 
      97       12138 :     IntRectTyped(ToInt aX, ToInt aY, ToInt aWidth, ToInt aHeight) :
      98       12138 :         Super(aX.value, aY.value, aWidth.value, aHeight.value) {}
      99             : 
     100           0 :     static IntRectTyped<units> RoundIn(float aX, float aY, float aW, float aH) {
     101           0 :       return IntRectTyped<units>::RoundIn(RectTyped<units, float>(aX, aY, aW, aH));
     102             :     }
     103             : 
     104          99 :     static IntRectTyped<units> RoundOut(float aX, float aY, float aW, float aH) {
     105          99 :       return IntRectTyped<units>::RoundOut(RectTyped<units, float>(aX, aY, aW, aH));
     106             :     }
     107             : 
     108             :     static IntRectTyped<units> Round(float aX, float aY, float aW, float aH) {
     109             :       return IntRectTyped<units>::Round(RectTyped<units, float>(aX, aY, aW, aH));
     110             :     }
     111             : 
     112           2 :     static IntRectTyped<units> Truncate(float aX, float aY, float aW, float aH) {
     113           4 :       return IntRectTyped<units>(IntPointTyped<units>::Truncate(aX, aY),
     114           6 :                                  IntSizeTyped<units>::Truncate(aW, aH));
     115             :     }
     116             : 
     117          35 :     static IntRectTyped<units> RoundIn(const RectTyped<units, float>& aRect) {
     118          35 :       auto tmp(aRect);
     119          35 :       tmp.RoundIn();
     120          70 :       return IntRectTyped(int32_t(tmp.x), int32_t(tmp.y),
     121         105 :                           int32_t(tmp.width), int32_t(tmp.height));
     122             :     }
     123             : 
     124         297 :     static IntRectTyped<units> RoundOut(const RectTyped<units, float>& aRect) {
     125         297 :       auto tmp(aRect);
     126         297 :       tmp.RoundOut();
     127         594 :       return IntRectTyped(int32_t(tmp.x), int32_t(tmp.y),
     128         891 :                           int32_t(tmp.width), int32_t(tmp.height));
     129             :     }
     130             : 
     131             :     static IntRectTyped<units> Round(const RectTyped<units, float>& aRect) {
     132             :       auto tmp(aRect);
     133             :       tmp.Round();
     134             :       return IntRectTyped(int32_t(tmp.x), int32_t(tmp.y),
     135             :                           int32_t(tmp.width), int32_t(tmp.height));
     136             :     }
     137             : 
     138           1 :     static IntRectTyped<units> Truncate(const RectTyped<units, float>& aRect) {
     139           1 :       return IntRectTyped::Truncate(aRect.x, aRect.y, aRect.width, aRect.height);
     140             :     }
     141             : 
     142             :     // Rounding isn't meaningful on an integer rectangle.
     143             :     void Round() {}
     144             :     void RoundIn() {}
     145             :     void RoundOut() {}
     146             : 
     147             :     // XXX When all of the code is ported, the following functions to convert
     148             :     // to and from unknown types should be removed.
     149             : 
     150         160 :     static IntRectTyped<units> FromUnknownRect(const IntRectTyped<UnknownUnits>& rect) {
     151         160 :         return IntRectTyped<units>(rect.x, rect.y, rect.width, rect.height);
     152             :     }
     153             : 
     154        1898 :     IntRectTyped<UnknownUnits> ToUnknownRect() const {
     155        1898 :         return IntRectTyped<UnknownUnits>(this->x, this->y, this->width, this->height);
     156             :     }
     157             : 
     158        1498 :     bool Overflows() const {
     159        1498 :       CheckedInt<int32_t> xMost = this->x;
     160        1498 :       xMost += this->width;
     161        1498 :       CheckedInt<int32_t> yMost = this->y;
     162        1498 :       yMost += this->height;
     163        1498 :       return !xMost.isValid() || !yMost.isValid();
     164             :     }
     165             : 
     166             :     // Same as Union(), but in the cases where aRect is non-empty, the union is
     167             :     // done while guarding against overflow. If an overflow is detected, Nothing
     168             :     // is returned.
     169         364 :     MOZ_MUST_USE Maybe<Self> SafeUnion(const Self& aRect) const
     170             :     {
     171         364 :       if (this->IsEmpty()) {
     172         206 :         return aRect.Overflows() ? Nothing() : Some(aRect);
     173         158 :       } else if (aRect.IsEmpty()) {
     174           0 :         return Some(*static_cast<const Self*>(this));
     175             :       } else {
     176         158 :         return this->SafeUnionEdges(aRect);
     177             :       }
     178             :     }
     179             : 
     180             :     // Same as UnionEdges, but guards against overflow. If an overflow is detected,
     181             :     // Nothing is returned.
     182         158 :     MOZ_MUST_USE Maybe<Self> SafeUnionEdges(const Self& aRect) const
     183             :     {
     184         158 :       if (this->Overflows() || aRect.Overflows()) {
     185           0 :         return Nothing();
     186             :       }
     187             :       // If neither |this| nor |aRect| overflow, then their XMost/YMost values
     188             :       // should be safe to use.
     189         158 :       CheckedInt<int32_t> newX = std::min(this->x, aRect.x);
     190         158 :       CheckedInt<int32_t> newY = std::min(this->y, aRect.y);
     191         158 :       CheckedInt<int32_t> newXMost = std::max(this->XMost(), aRect.XMost());
     192         158 :       CheckedInt<int32_t> newYMost = std::max(this->YMost(), aRect.YMost());
     193         158 :       CheckedInt<int32_t> newW = newXMost - newX;
     194         158 :       CheckedInt<int32_t> newH = newYMost - newY;
     195         158 :       if (!newW.isValid() || !newH.isValid()) {
     196           0 :         return Nothing();
     197             :       }
     198         158 :       return Some(Self(newX.value(), newY.value(), newW.value(), newH.value()));
     199             :     }
     200             : 
     201             :     // This is here only to keep IPDL-generated code happy. DO NOT USE.
     202          47 :     bool operator==(const IntRectTyped<units>& aRect) const
     203             :     {
     204          47 :       return IntRectTyped<units>::IsEqualEdges(aRect);
     205             :     }
     206             : 
     207           0 :     void InflateToMultiple(const IntSizeTyped<units>& aTileSize)
     208             :     {
     209           0 :       if (this->IsEmpty()) {
     210           0 :         return;
     211             :       }
     212             : 
     213           0 :       int32_t yMost = this->YMost();
     214           0 :       int32_t xMost = this->XMost();
     215             : 
     216           0 :       this->x = mozilla::RoundDownToMultiple(this->x, aTileSize.width);
     217           0 :       this->y = mozilla::RoundDownToMultiple(this->y, aTileSize.height);
     218           0 :       xMost = mozilla::RoundUpToMultiple(xMost, aTileSize.width);
     219           0 :       yMost = mozilla::RoundUpToMultiple(yMost, aTileSize.height);
     220             : 
     221           0 :       this->width = xMost - this->x;
     222           0 :       this->height = yMost - this->y;
     223             :     }
     224             : 
     225             : };
     226             : typedef IntRectTyped<UnknownUnits> IntRect;
     227             : 
     228             : template<class units, class F = Float>
     229             : struct RectTyped :
     230             :     public BaseRect<F, RectTyped<units, F>, PointTyped<units, F>, SizeTyped<units, F>, MarginTyped<units, F> >,
     231             :     public units {
     232             :     static_assert(IsPixel<units>::value,
     233             :                   "'units' must be a coordinate system tag");
     234             : 
     235             :     typedef BaseRect<F, RectTyped<units, F>, PointTyped<units, F>, SizeTyped<units, F>, MarginTyped<units, F> > Super;
     236             : 
     237        2446 :     RectTyped() : Super() {}
     238         486 :     RectTyped(const PointTyped<units, F>& aPos, const SizeTyped<units, F>& aSize) :
     239         486 :         Super(aPos, aSize) {}
     240       12223 :     RectTyped(F _x, F _y, F _width, F _height) :
     241       12223 :         Super(_x, _y, _width, _height) {}
     242         472 :     explicit RectTyped(const IntRectTyped<units>& rect) :
     243         944 :         Super(F(rect.x), F(rect.y),
     244        1416 :               F(rect.width), F(rect.height)) {}
     245             : 
     246         718 :     void NudgeToIntegers()
     247             :     {
     248         718 :       NudgeToInteger(&(this->x));
     249         718 :       NudgeToInteger(&(this->y));
     250         718 :       NudgeToInteger(&(this->width));
     251         718 :       NudgeToInteger(&(this->height));
     252         718 :     }
     253             : 
     254         674 :     bool ToIntRect(IntRectTyped<units> *aOut) const
     255             :     {
     256        1348 :       *aOut = IntRectTyped<units>(int32_t(this->X()), int32_t(this->Y()),
     257        1348 :                                   int32_t(this->Width()), int32_t(this->Height()));
     258        1348 :       return RectTyped<units, F>(F(aOut->x), F(aOut->y),
     259        1348 :                                  F(aOut->width), F(aOut->height))
     260        2696 :              .IsEqualEdges(*this);
     261             :     }
     262             : 
     263             :     // XXX When all of the code is ported, the following functions to convert to and from
     264             :     // unknown types should be removed.
     265             : 
     266           0 :     static RectTyped<units, F> FromUnknownRect(const RectTyped<UnknownUnits, F>& rect) {
     267           0 :         return RectTyped<units, F>(rect.x, rect.y, rect.width, rect.height);
     268             :     }
     269             : 
     270           6 :     RectTyped<UnknownUnits, F> ToUnknownRect() const {
     271           6 :         return RectTyped<UnknownUnits, F>(this->x, this->y, this->width, this->height);
     272             :     }
     273             : 
     274             :     // This is here only to keep IPDL-generated code happy. DO NOT USE.
     275           0 :     bool operator==(const RectTyped<units, F>& aRect) const
     276             :     {
     277           0 :       return RectTyped<units, F>::IsEqualEdges(aRect);
     278             :     }
     279             : };
     280             : typedef RectTyped<UnknownUnits> Rect;
     281             : typedef RectTyped<UnknownUnits, double> RectDouble;
     282             : 
     283             : template<class units>
     284         176 : IntRectTyped<units> RoundedToInt(const RectTyped<units>& aRect)
     285             : {
     286         176 :   RectTyped<units> copy(aRect);
     287         176 :   copy.Round();
     288         176 :   return IntRectTyped<units>(int32_t(copy.x),
     289         176 :                              int32_t(copy.y),
     290         176 :                              int32_t(copy.width),
     291         704 :                              int32_t(copy.height));
     292             : }
     293             : 
     294             : template<class units>
     295          35 : IntRectTyped<units> RoundedIn(const RectTyped<units>& aRect)
     296             : {
     297          35 :   return IntRectTyped<units>::RoundIn(aRect);
     298             : }
     299             : 
     300             : template<class units>
     301         198 : IntRectTyped<units> RoundedOut(const RectTyped<units>& aRect)
     302             : {
     303         198 :   return IntRectTyped<units>::RoundOut(aRect);
     304             : }
     305             : 
     306             : template<class units>
     307           1 : IntRectTyped<units> TruncatedToInt(const RectTyped<units>& aRect) {
     308           1 :   return IntRectTyped<units>::Truncate(aRect);
     309             : }
     310             : 
     311             : template<class units>
     312          28 : RectTyped<units> IntRectToRect(const IntRectTyped<units>& aRect)
     313             : {
     314          28 :   return RectTyped<units>(aRect.x, aRect.y, aRect.width, aRect.height);
     315             : }
     316             : 
     317             : // Convenience function for intersecting two rectangles wrapped in Maybes.
     318             : template <typename T>
     319             : Maybe<T>
     320        1134 : IntersectMaybeRects(const Maybe<T>& a, const Maybe<T>& b)
     321             : {
     322        1134 :   if (!a) {
     323         809 :     return b;
     324         325 :   } else if (!b) {
     325         276 :     return a;
     326             :   } else {
     327          49 :     return Some(a->Intersect(*b));
     328             :   }
     329             : }
     330             : 
     331             : } // namespace gfx
     332             : } // namespace mozilla
     333             : 
     334             : #endif /* MOZILLA_GFX_RECT_H_ */

Generated by: LCOV version 1.13