LCOV - code coverage report
Current view: top level - gfx/src - TiledRegion.h (source / functions) Hit Total Coverage
Test: output.info Lines: 35 54 64.8 %
Date: 2017-07-14 16:53:18 Functions: 12 13 92.3 %
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 MOZILLA_GFX_TILEDREGION_H_
       8             : #define MOZILLA_GFX_TILEDREGION_H_
       9             : 
      10             : #include "mozilla/ArrayView.h"
      11             : #include "mozilla/gfx/Rect.h"
      12             : #include "mozilla/Move.h"
      13             : #include "nsRegion.h"
      14             : #include "pixman.h"
      15             : 
      16             : namespace mozilla {
      17             : namespace gfx {
      18             : 
      19             : // See TiledRegion.cpp for documentation on TiledRegionImpl.
      20         450 : class TiledRegionImpl {
      21             : public:
      22         697 :   void Clear() { mRects.Clear(); }
      23             :   bool AddRect(const pixman_box32_t& aRect);
      24             :   bool Intersects(const pixman_box32_t& aRect) const;
      25             :   bool Contains(const pixman_box32_t& aRect) const;
      26         196 :   operator ArrayView<pixman_box32_t>() const { return ArrayView<pixman_box32_t>(mRects); }
      27             : 
      28             : private:
      29             :   nsTArray<pixman_box32_t> mRects;
      30             : };
      31             : 
      32             : /**
      33             :  * A auto-simplifying region type that supports one rectangle per tile.
      34             :  * The virtual tile grid is anchored at (0, 0) and has quadratic tiles whose
      35             :  * size is hard-coded as kTileSize in TiledRegion.cpp.
      36             :  * A TiledRegion starts out empty. You can add rectangles or (regular) regions
      37             :  * into it by calling Add(). Add() is a mutating union operation (similar to
      38             :  * OrWith on nsRegion) that's *not* exact, because it will enlarge the region as
      39             :  * necessary to satisfy the "one rectangle per tile" requirement.
      40             :  * Tiled regions convert implicitly to the underlying regular region type.
      41             :  * The only way to remove parts from a TiledRegion is by calling SetEmpty().
      42             :  */
      43             : template<typename RegionT>
      44         211 : class TiledRegion {
      45             : public:
      46             :   typedef typename RegionT::RectType RectT;
      47             : 
      48         239 :   TiledRegion()
      49         239 :     : mCoversBounds(false)
      50         239 :   {}
      51             : 
      52             :   TiledRegion(const TiledRegion& aOther)
      53             :     : mBounds(aOther.mBounds)
      54             :     , mImpl(aOther.mImpl)
      55             :     , mCoversBounds(false)
      56             :   {}
      57             : 
      58             :   TiledRegion(TiledRegion&& aOther)
      59             :     : mBounds(aOther.mBounds)
      60             :     , mImpl(Move(aOther.mImpl))
      61             :     , mCoversBounds(false)
      62             :   {}
      63             : 
      64         730 :   RegionT GetRegion() const
      65             :   {
      66         730 :     if (mBounds.IsEmpty()) {
      67         534 :       return RegionT();
      68             :     }
      69         196 :     if (mCoversBounds) {
      70             :       // Rect limit hit or allocation failed, treat as 1 rect.
      71           0 :       return RegionT(mBounds);
      72             :     }
      73         196 :     return RegionT(mImpl);
      74             :   }
      75             : 
      76             :   TiledRegion& operator=(const TiledRegion& aOther)
      77             :   {
      78             :     if (&aOther != this) {
      79             :       mBounds = aOther.mBounds;
      80             :       mImpl = aOther.mImpl;
      81             :       mCoversBounds = aOther.mCoversBounds;
      82             :     }
      83             :     return *this;
      84             :   }
      85             : 
      86           3 :   void Add(const RectT& aRect)
      87             :   {
      88           3 :     if (aRect.IsEmpty()) {
      89           6 :       return;
      90             :     }
      91             : 
      92           0 :     Maybe<RectT> newBounds = mBounds.SafeUnion(aRect);
      93           0 :     if (!newBounds) {
      94           0 :       return;
      95             :     }
      96           0 :     mBounds = newBounds.value();
      97           0 :     MOZ_ASSERT(!mBounds.Overflows());
      98             : 
      99           0 :     if (mCoversBounds) {
     100           0 :       return;
     101             :     }
     102             : 
     103           0 :     if (!mImpl.AddRect(RectToBox(aRect))) {
     104           0 :       FallBackToBounds();
     105             :     }
     106             :   }
     107             : 
     108         364 :   void Add(const RegionT& aRegion)
     109             :   {
     110         728 :     Maybe<RectT> newBounds = mBounds.SafeUnion(aRegion.GetBounds());
     111         364 :     if (!newBounds) {
     112           0 :       return;
     113             :     }
     114         364 :     mBounds = newBounds.value();
     115         364 :     MOZ_ASSERT(!mBounds.Overflows());
     116             : 
     117         364 :     if (mCoversBounds) {
     118           0 :       return;
     119             :     }
     120             : 
     121         670 :     for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
     122         306 :       RectT r = iter.Get();
     123         306 :       if (r.IsEmpty() || r.Overflows()) {
     124             :         // This can happen if e.g. a negative-width rect was wrapped into a
     125             :         // region. Treat it the same as we would if such a rect was passed to
     126             :         // the Add(const RectT&) function.
     127           0 :         continue;
     128             :       }
     129         306 :       if (!mImpl.AddRect(RectToBox(r))) {
     130           0 :         FallBackToBounds();
     131           0 :         return;
     132             :       }
     133             :     }
     134             :   }
     135             : 
     136         164 :   bool IsEmpty() const { return mBounds.IsEmpty(); }
     137             : 
     138         697 :   void SetEmpty()
     139             :   {
     140         697 :     mBounds.SetEmpty();
     141         697 :     mImpl.Clear();
     142         697 :     mCoversBounds = false;
     143         697 :   }
     144             : 
     145             :   RectT GetBounds() const { return mBounds; }
     146             :   bool CoversBounds() const { return mCoversBounds; }
     147             : 
     148             :   bool Intersects(const RectT& aRect) const
     149             :   {
     150             :     if (aRect.IsEmpty()) {
     151             :       return true;
     152             :     }
     153             :     if (aRect.Overflows() || !mBounds.Intersects(aRect)) {
     154             :       return false;
     155             :     }
     156             :     if (mCoversBounds) {
     157             :       return true;
     158             :     }
     159             : 
     160             :     return mImpl.Intersects(RectToBox(aRect));
     161             :   }
     162             : 
     163             :   bool Contains(const RectT& aRect) const
     164             :   {
     165             :     if (aRect.IsEmpty()) {
     166             :       return true;
     167             :     }
     168             :     if (aRect.Overflows() || !mBounds.Contains(aRect)) {
     169             :       return false;
     170             :     }
     171             :     if (mCoversBounds) {
     172             :       return true;
     173             :     }
     174             :     return mImpl.Contains(RectToBox(aRect));
     175             :   }
     176             : 
     177             : private:
     178             : 
     179           0 :   void FallBackToBounds()
     180             :   {
     181           0 :     mCoversBounds = true;
     182           0 :     mImpl.Clear();
     183           0 :   }
     184             : 
     185         306 :   static pixman_box32_t RectToBox(const RectT& aRect)
     186             :   {
     187         306 :     MOZ_ASSERT(!aRect.IsEmpty());
     188         306 :     MOZ_ASSERT(!aRect.Overflows());
     189         306 :     return { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
     190             :   }
     191             : 
     192             :   RectT mBounds;
     193             :   TiledRegionImpl mImpl;
     194             : 
     195             :   // mCoversBounds is true if we bailed out due to a large number of tiles.
     196             :   // mCoversBounds being true means that this TiledRegion is just a simple
     197             :   // rectangle (our mBounds).
     198             :   // Once set to true, the TiledRegion will stay in this state until SetEmpty
     199             :   // is called.
     200             :   bool mCoversBounds;
     201             : };
     202             : 
     203             : typedef TiledRegion<IntRegion> TiledIntRegion;
     204             : 
     205             : } // namespace gfx
     206             : } // namespace mozilla
     207             : 
     208             : #endif /* MOZILLA_GFX_TILEDREGION_H_ */

Generated by: LCOV version 1.13