LCOV - code coverage report
Current view: top level - gfx/src - nsRegion.h (source / functions) Hit Total Coverage
Test: output.info Lines: 244 285 85.6 %
Date: 2017-07-14 16:53:18 Functions: 207 270 76.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             : 
       8             : #ifndef nsRegion_h__
       9             : #define nsRegion_h__
      10             : 
      11             : #include <stddef.h>                     // for size_t
      12             : #include <stdint.h>                     // for uint32_t, uint64_t
      13             : #include <sys/types.h>                  // for int32_t
      14             : #include <ostream>                      // for std::ostream
      15             : #include "nsCoord.h"                    // for nscoord
      16             : #include "nsError.h"                    // for nsresult
      17             : #include "nsPoint.h"                    // for nsIntPoint, nsPoint
      18             : #include "nsRect.h"                     // for mozilla::gfx::IntRect, nsRect
      19             : #include "nsMargin.h"                   // for nsIntMargin
      20             : #include "nsRegionFwd.h"                // for nsIntRegion
      21             : #include "nsStringGlue.h"               // for nsCString
      22             : #include "xpcom-config.h"               // for CPP_THROW_NEW
      23             : #include "mozilla/ArrayView.h"          // for ArrayView
      24             : #include "mozilla/Move.h"               // for mozilla::Move
      25             : #include "mozilla/gfx/MatrixFwd.h"      // for mozilla::gfx::Matrix4x4
      26             : 
      27             : #include "pixman.h"
      28             : 
      29             : /* For information on the internal representation look at pixman-region.c
      30             :  *
      31             :  * This replaces an older homebrew implementation of nsRegion. The
      32             :  * representation used here may use more rectangles than nsRegion however, the
      33             :  * representation is canonical.  This means that there's no need for an
      34             :  * Optimize() method because for a paticular region there is only one
      35             :  * representation. This means that nsIntRegion will have more predictable
      36             :  * performance characteristics than the old nsRegion and should not become
      37             :  * degenerate.
      38             :  *
      39             :  * The pixman region code originates from X11 which has spread to a variety of
      40             :  * projects including Qt, Gtk, Wine. It should perform reasonably well.
      41             :  */
      42             : 
      43             : enum class VisitSide {
      44             :         TOP,
      45             :         BOTTOM,
      46             :         LEFT,
      47             :         RIGHT
      48             : };
      49             : 
      50             : class nsRegion
      51             : {
      52             : public:
      53             :   typedef nsRect RectType;
      54             :   typedef nsPoint PointType;
      55             :   typedef nsMargin MarginType;
      56             : 
      57       27897 :   nsRegion () { pixman_region32_init(&mImpl); }
      58       11392 :   MOZ_IMPLICIT nsRegion (const nsRect& aRect) { pixman_region32_init_rect(&mImpl,
      59        2848 :                                                                           aRect.x,
      60        2848 :                                                                           aRect.y,
      61        2848 :                                                                           aRect.width,
      62        5696 :                                                                           aRect.height); }
      63        1251 :   explicit nsRegion (mozilla::gfx::ArrayView<pixman_box32_t> aRects)
      64        1251 :   {
      65        1251 :     pixman_region32_init_rects(&mImpl, aRects.Data(), aRects.Length());
      66        1250 :   }
      67        6450 :   nsRegion (const nsRegion& aRegion) { pixman_region32_init(&mImpl); pixman_region32_copy(&mImpl,aRegion.Impl()); }
      68        3399 :   nsRegion (nsRegion&& aRegion) { mImpl = aRegion.mImpl; pixman_region32_init(&aRegion.mImpl); }
      69        2059 :   nsRegion& operator = (nsRegion&& aRegion) {
      70        2059 :       pixman_region32_fini(&mImpl);
      71        2059 :       mImpl = aRegion.mImpl;
      72        2059 :       pixman_region32_init(&aRegion.mImpl);
      73        2059 :       return *this;
      74             :   }
      75       41469 :  ~nsRegion () { pixman_region32_fini(&mImpl); }
      76        1512 :   nsRegion& operator = (const nsRect& aRect) { Copy (aRect); return *this; }
      77        5449 :   nsRegion& operator = (const nsRegion& aRegion) { Copy (aRegion); return *this; }
      78             :   bool operator==(const nsRegion& aRgn) const
      79             :   {
      80             :     return IsEqual(aRgn);
      81             :   }
      82             :   bool operator!=(const nsRegion& aRgn) const
      83             :   {
      84             :     return !(*this == aRgn);
      85             :   }
      86             : 
      87             :   friend std::ostream& operator<<(std::ostream& stream, const nsRegion& m);
      88             : 
      89             :   void Swap(nsRegion* aOther)
      90             :   {
      91             :     pixman_region32_t tmp = mImpl;
      92             :     mImpl = aOther->mImpl;
      93             :     aOther->mImpl = tmp;
      94             :   }
      95             : 
      96             :   static
      97           3 :   nsresult InitStatic()
      98             :   {
      99           3 :     return NS_OK;
     100             :   }
     101             : 
     102             :   static
     103           0 :   void ShutdownStatic() {}
     104             : 
     105             :   void AndWith(const nsRegion& aOther)
     106             :   {
     107             :     And(*this, aOther);
     108             :   }
     109             :   void AndWith(const nsRect& aOther)
     110             :   {
     111             :     And(*this, aOther);
     112             :   }
     113        1337 :   nsRegion& And(const nsRegion& aRgn1,   const nsRegion& aRgn2)
     114             :   {
     115        1337 :     pixman_region32_intersect(&mImpl, aRgn1.Impl(), aRgn2.Impl());
     116        1337 :     return *this;
     117             :   }
     118             :   nsRegion& And(const nsRect& aRect, const nsRegion& aRegion)
     119             :   {
     120             :     return And(aRegion, aRect);
     121             :   }
     122        3266 :   nsRegion& And(const nsRegion& aRegion, const nsRect& aRect)
     123             :   {
     124        3266 :     pixman_region32_intersect_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height);
     125        3266 :     return *this;
     126             :   }
     127             :   nsRegion& And(const nsRect& aRect1, const nsRect& aRect2)
     128             :   {
     129             :     nsRect TmpRect;
     130             : 
     131             :     TmpRect.IntersectRect(aRect1, aRect2);
     132             :     return Copy(TmpRect);
     133             :   }
     134             : 
     135        2838 :   nsRegion& OrWith(const nsRegion& aOther)
     136             :   {
     137        2838 :     return Or(*this, aOther);
     138             :   }
     139         587 :   nsRegion& OrWith(const nsRect& aOther)
     140             :   {
     141         587 :     return Or(*this, aOther);
     142             :   }
     143        5964 :   nsRegion& Or(const nsRegion& aRgn1, const nsRegion& aRgn2)
     144             :   {
     145        5964 :     pixman_region32_union(&mImpl, aRgn1.Impl(), aRgn2.Impl());
     146        5964 :     return *this;
     147             :   }
     148        7179 :   nsRegion& Or(const nsRegion& aRegion, const nsRect& aRect)
     149             :   {
     150        7179 :     pixman_region32_union_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height);
     151        7179 :     return *this;
     152             :   }
     153             :   nsRegion& Or(const nsRect& aRect, const nsRegion& aRegion)
     154             :   {
     155             :     return  Or(aRegion, aRect);
     156             :   }
     157         105 :   nsRegion& Or(const nsRect& aRect1, const nsRect& aRect2)
     158             :   {
     159         105 :     Copy (aRect1);
     160         105 :     return Or (*this, aRect2);
     161             :   }
     162             : 
     163             :   nsRegion& XorWith(const nsRegion& aOther)
     164             :   {
     165             :     return Xor(*this, aOther);
     166             :   }
     167             :   nsRegion& XorWith(const nsRect& aOther)
     168             :   {
     169             :     return Xor(*this, aOther);
     170             :   }
     171          66 :   nsRegion& Xor(const nsRegion& aRgn1,   const nsRegion& aRgn2)
     172             :   {
     173             :     // this could be implemented better if pixman had direct
     174             :     // support for xoring regions.
     175         132 :     nsRegion p;
     176          66 :     p.Sub(aRgn1, aRgn2);
     177         132 :     nsRegion q;
     178          66 :     q.Sub(aRgn2, aRgn1);
     179         132 :     return Or(p, q);
     180             :   }
     181          32 :   nsRegion& Xor(const nsRegion& aRegion, const nsRect& aRect)
     182             :   {
     183          32 :     return Xor(aRegion, nsRegion(aRect));
     184             :   }
     185             :   nsRegion& Xor(const nsRect& aRect, const nsRegion& aRegion)
     186             :   {
     187             :     return Xor(nsRegion(aRect), aRegion);
     188             :   }
     189          34 :   nsRegion& Xor(const nsRect& aRect1, const nsRect& aRect2)
     190             :   {
     191          34 :     return Xor(nsRegion(aRect1), nsRegion(aRect2));
     192             :   }
     193             : 
     194             :   nsRegion ToAppUnits (nscoord aAppUnitsPerPixel) const;
     195             : 
     196             :   nsRegion& SubOut(const nsRegion& aOther)
     197             :   {
     198             :     return Sub(*this, aOther);
     199             :   }
     200             :   nsRegion& SubOut(const nsRect& aOther)
     201             :   {
     202             :     return Sub(*this, aOther);
     203             :   }
     204        1648 :   nsRegion& Sub(const nsRegion& aRgn1, const nsRegion& aRgn2)
     205             :   {
     206        1648 :     pixman_region32_subtract(&mImpl, aRgn1.Impl(), aRgn2.Impl());
     207        1648 :     return *this;
     208             :   }
     209          70 :   nsRegion& Sub(const nsRegion& aRegion, const nsRect& aRect)
     210             :   {
     211          70 :     return Sub(aRegion, nsRegion(aRect));
     212             :   }
     213           0 :   nsRegion& Sub(const nsRect& aRect, const nsRegion& aRegion)
     214             :   {
     215           0 :     return Sub(nsRegion(aRect), aRegion);
     216             :   }
     217           0 :   nsRegion& Sub(const nsRect& aRect1, const nsRect& aRect2)
     218             :   {
     219           0 :     Copy(aRect1);
     220           0 :     return Sub(*this, aRect2);
     221             :   }
     222             : 
     223             :   /**
     224             :    * Returns true iff the given point is inside the region. A region
     225             :    * created from a rect (x=0, y=0, w=100, h=100) will NOT contain
     226             :    * the point x=100, y=100.
     227             :    */
     228          46 :   bool Contains (int aX, int aY) const
     229             :   {
     230          46 :     return pixman_region32_contains_point(Impl(), aX, aY, nullptr);
     231             :   }
     232        2969 :   bool Contains (const nsRect& aRect) const
     233             :   {
     234        2969 :     pixman_box32_t box = RectToBox(aRect);
     235        2969 :     return pixman_region32_contains_rectangle(Impl(), &box) == PIXMAN_REGION_IN;
     236             :   }
     237             :   bool Contains (const nsRegion& aRgn) const;
     238             :   bool Intersects (const nsRect& aRect) const;
     239             : 
     240        1961 :   void MoveBy (int32_t aXOffset, int32_t aYOffset)
     241             :   {
     242        1961 :     MoveBy (nsPoint (aXOffset, aYOffset));
     243        1961 :   }
     244        2939 :   void MoveBy (nsPoint aPt) { pixman_region32_translate(&mImpl, aPt.x, aPt.y); }
     245        1758 :   void SetEmpty ()
     246             :   {
     247        1758 :     pixman_region32_clear(&mImpl);
     248        1758 :   }
     249             : 
     250             :   nsRegion MovedBy(int32_t aXOffset, int32_t aYOffset) const
     251             :   {
     252             :     return MovedBy(nsPoint(aXOffset, aYOffset));
     253             :   }
     254           0 :   nsRegion MovedBy(const nsPoint& aPt) const
     255             :   {
     256           0 :     nsRegion copy(*this);
     257           0 :     copy.MoveBy(aPt);
     258           0 :     return copy;
     259             :   }
     260             : 
     261             :   nsRegion Intersect(const nsRegion& aOther) const
     262             :   {
     263             :     nsRegion intersection;
     264             :     intersection.And(*this, aOther);
     265             :     return intersection;
     266             :   }
     267             : 
     268             :   void Inflate(const nsMargin& aMargin);
     269             : 
     270             :   nsRegion Inflated(const nsMargin& aMargin) const
     271             :   {
     272             :     nsRegion copy(*this);
     273             :     copy.Inflate(aMargin);
     274             :     return copy;
     275             :   }
     276             : 
     277       14838 :   bool IsEmpty () const { return !pixman_region32_not_empty(Impl()); }
     278             :   bool IsComplex () const { return GetNumRects() > 1; }
     279        1717 :   bool IsEqual (const nsRegion& aRegion) const
     280             :   {
     281        1717 :     return pixman_region32_equal(Impl(), aRegion.Impl());
     282             :   }
     283        3787 :   uint32_t GetNumRects () const
     284             :   {
     285             :     // Work around pixman bug. Sometimes pixman creates regions with 1 rect
     286             :     // that's empty.
     287        3787 :     uint32_t result = pixman_region32_n_rects(Impl());
     288        3787 :     return (result == 1 && GetBounds().IsEmpty()) ? 0 : result;
     289             :   }
     290        8036 :   const nsRect GetBounds () const { return BoxToRect(mImpl.extents); }
     291             :   uint64_t Area () const;
     292             : 
     293             :   /**
     294             :    * Return this region scaled to a different appunits per pixel (APP) ratio.
     295             :    * This applies nsRect::ScaleToOtherAppUnitsRoundOut/In to each rect of the region.
     296             :    * @param aFromAPP the APP to scale from
     297             :    * @param aToAPP the APP to scale to
     298             :    * @note this can turn an empty region into a non-empty region
     299             :    */
     300             :   MOZ_MUST_USE nsRegion
     301             :     ScaleToOtherAppUnitsRoundOut (int32_t aFromAPP, int32_t aToAPP) const;
     302             :   MOZ_MUST_USE nsRegion
     303             :     ScaleToOtherAppUnitsRoundIn (int32_t aFromAPP, int32_t aToAPP) const;
     304             :   nsRegion& ScaleRoundOut(float aXScale, float aYScale);
     305             :   nsRegion& ScaleInverseRoundOut(float aXScale, float aYScale);
     306             :   nsRegion& Transform (const mozilla::gfx::Matrix4x4 &aTransform);
     307             :   nsIntRegion ScaleToOutsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
     308             :   nsIntRegion ScaleToInsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
     309             :   nsIntRegion ScaleToNearestPixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const;
     310             :   nsIntRegion ToOutsidePixels (nscoord aAppUnitsPerPixel) const;
     311             :   nsIntRegion ToNearestPixels (nscoord aAppUnitsPerPixel) const;
     312             : 
     313             :   /**
     314             :    * Gets the largest rectangle contained in the region.
     315             :    * @param aContainingRect if non-empty, we choose a rectangle that
     316             :    * maximizes the area intersecting with aContainingRect (and break ties by
     317             :    * then choosing the largest rectangle overall)
     318             :    */
     319             :   nsRect GetLargestRectangle (const nsRect& aContainingRect = nsRect()) const;
     320             : 
     321             :   /**
     322             :    * Make sure the region has at most aMaxRects by adding area to it
     323             :    * if necessary. The simplified region will be a superset of the
     324             :    * original region. The simplified region's bounding box will be
     325             :    * the same as for the current region.
     326             :    */
     327             :   void SimplifyOutward (uint32_t aMaxRects);
     328             :   /**
     329             :    * Simplify the region by adding at most aThreshold area between spans of
     330             :    * rects.  The simplified region will be a superset of the original region.
     331             :    * The simplified region's bounding box will be the same as for the current
     332             :    * region.
     333             :    */
     334             :   void SimplifyOutwardByArea(uint32_t aThreshold);
     335             :   /**
     336             :    * Make sure the region has at most aMaxRects by removing area from
     337             :    * it if necessary. The simplified region will be a subset of the
     338             :    * original region.
     339             :    */
     340             :   void SimplifyInward (uint32_t aMaxRects);
     341             : 
     342             :   /**
     343             :    * VisitEdges is a weird kind of function that we use for padding
     344             :    * out surfaces to prevent texture filtering artifacts.
     345             :    * It calls the visitFn callback for each of the exterior edges of
     346             :    * the regions. The top and bottom edges will be expanded 1 pixel
     347             :    * to the left and right if there's an outside corner. The order
     348             :    * the edges are visited is not guaranteed.
     349             :    *
     350             :    * visitFn has a side parameter that can be TOP,BOTTOM,LEFT,RIGHT
     351             :    * and specifies which kind of edge is being visited. x1, y1, x2, y2
     352             :    * are the coordinates of the line. (x1 == x2) || (y1 == y2)
     353             :    */
     354             :   typedef void (*visitFn)(void *closure, VisitSide side, int x1, int y1, int x2, int y2);
     355             :   void VisitEdges(visitFn, void *closure);
     356             : 
     357             :   nsCString ToString() const;
     358             : 
     359        6847 :   class RectIterator
     360             :   {
     361             :     int mCurrent;               // Index of the current entry
     362             :     int mLimit;                 // Index one past the final entry.
     363             :     mutable nsRect mTmp;        // The most recently gotten rectangle.
     364             :     pixman_box32_t *mBoxes;
     365             : 
     366             :   public:
     367        6847 :     explicit RectIterator(const nsRegion& aRegion)
     368        6847 :     {
     369        6847 :       mCurrent = 0;
     370        6847 :       mBoxes = pixman_region32_rectangles(aRegion.Impl(), &mLimit);
     371             :       // Work around pixman bug. Sometimes pixman creates regions with 1 rect
     372             :       // that's empty.
     373        6846 :       if (mLimit == 1 && nsRegion::BoxToRect(mBoxes[0]).IsEmpty()) {
     374           0 :         mLimit = 0;
     375             :       }
     376        6846 :     }
     377             : 
     378       18582 :     bool Done() const { return mCurrent == mLimit; }
     379             : 
     380        4213 :     const nsRect& Get() const
     381             :     {
     382        4213 :       MOZ_ASSERT(!Done());
     383        4213 :       mTmp = nsRegion::BoxToRect(mBoxes[mCurrent]);
     384        4213 :       NS_ASSERTION(!mTmp.IsEmpty(), "Shouldn't return empty rect");
     385        4213 :       return mTmp;
     386             :     }
     387             : 
     388        3790 :     void Next()
     389             :     {
     390        3790 :       MOZ_ASSERT(!Done());
     391        3790 :       mCurrent++;
     392        3790 :     }
     393             :   };
     394             : 
     395        4455 :   RectIterator RectIter() const { return RectIterator(*this); }
     396             : 
     397             : private:
     398             :   pixman_region32_t mImpl;
     399             : 
     400             : #ifndef MOZ_TREE_PIXMAN
     401             :   // For compatibility with pixman versions older than 0.25.2.
     402             :   static inline void
     403             :   pixman_region32_clear(pixman_region32_t *region)
     404             :   {
     405             :     pixman_region32_fini(region);
     406             :     pixman_region32_init(region);
     407             :   }
     408             : #endif
     409             : 
     410             :   nsIntRegion ToPixels(nscoord aAppUnitsPerPixel, bool aOutsidePixels) const;
     411             : 
     412        5449 :   nsRegion& Copy (const nsRegion& aRegion)
     413             :   {
     414        5449 :     pixman_region32_copy(&mImpl, aRegion.Impl());
     415        5449 :     return *this;
     416             :   }
     417             : 
     418        1617 :   nsRegion& Copy (const nsRect& aRect)
     419             :   {
     420             :     // pixman needs to distinguish between an empty region and a region
     421             :     // with one rect so that it can return a different number of rectangles.
     422             :     // Empty rect: data = empty_box
     423             :     //     1 rect: data = null
     424             :     //    >1 rect: data = rects
     425        1617 :     if (aRect.IsEmpty()) {
     426         163 :       pixman_region32_clear(&mImpl);
     427             :     } else {
     428        1454 :       pixman_box32_t box = RectToBox(aRect);
     429        1454 :       pixman_region32_reset(&mImpl, &box);
     430             :     }
     431        1617 :     return *this;
     432             :   }
     433             : 
     434        4760 :   static inline pixman_box32_t RectToBox(const nsRect &aRect)
     435             :   {
     436        4760 :     pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
     437        4761 :     return box;
     438             :   }
     439             : 
     440         435 :   static inline pixman_box32_t RectToBox(const mozilla::gfx::IntRect &aRect)
     441             :   {
     442         435 :     pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() };
     443         435 :     return box;
     444             :   }
     445             : 
     446             : 
     447       16206 :   static inline nsRect BoxToRect(const pixman_box32_t &aBox)
     448             :   {
     449       16206 :     return nsRect(aBox.x1, aBox.y1,
     450       16206 :                   aBox.x2 - aBox.x1,
     451       48618 :                   aBox.y2 - aBox.y1);
     452             :   }
     453             : 
     454       72154 :   pixman_region32_t* Impl() const
     455             :   {
     456       72154 :     return const_cast<pixman_region32_t*>(&mImpl);
     457             :   }
     458             : };
     459             : 
     460             : namespace mozilla {
     461             : namespace gfx {
     462             : 
     463             : /**
     464             :  * BaseIntRegions use int32_t coordinates.
     465             :  */
     466             : template <typename Derived, typename Rect, typename Point, typename Margin>
     467       24357 : class BaseIntRegion
     468             : {
     469             :   friend class ::nsRegion;
     470             : 
     471             :   // Give access to all specializations of IntRegionTyped, not just ones that
     472             :   // derive from this specialization of BaseIntRegion.
     473             :   template <typename units>
     474             :   friend class IntRegionTyped;
     475             : 
     476             : public:
     477             :   typedef Rect RectType;
     478             :   typedef Point PointType;
     479             :   typedef Margin MarginType;
     480             : 
     481       14596 :   BaseIntRegion () {}
     482        2451 :   MOZ_IMPLICIT BaseIntRegion (const Rect& aRect) : mImpl (ToRect(aRect)) {}
     483        1179 :   explicit BaseIntRegion (mozilla::gfx::ArrayView<pixman_box32_t> aRects) : mImpl (aRects) {}
     484        2237 :   BaseIntRegion (const BaseIntRegion& aRegion) : mImpl (aRegion.mImpl) {}
     485        1345 :   BaseIntRegion (BaseIntRegion&& aRegion) : mImpl (mozilla::Move(aRegion.mImpl)) {}
     486             :   Derived& operator = (const Rect& aRect) { mImpl = ToRect (aRect); return This(); }
     487        5061 :   Derived& operator = (const Derived& aRegion) { mImpl = aRegion.mImpl; return This(); }
     488        2059 :   Derived& operator = (Derived&& aRegion) { mImpl = mozilla::Move(aRegion.mImpl); return This(); }
     489             : 
     490        1172 :   bool operator==(const Derived& aRgn) const
     491             :   {
     492        1172 :     return IsEqual(aRgn);
     493             :   }
     494         124 :   bool operator!=(const Derived& aRgn) const
     495             :   {
     496         124 :     return !(*this == aRgn);
     497             :   }
     498             : 
     499             :   friend std::ostream& operator<<(std::ostream& stream, const Derived& m) {
     500             :     return stream << m.mImpl;
     501             :   }
     502             : 
     503             :   void Swap(Derived* aOther)
     504             :   {
     505             :     mImpl.Swap(&aOther->mImpl);
     506             :   }
     507             : 
     508           0 :   void AndWith(const Derived& aOther)
     509             :   {
     510           0 :     And(This(), aOther);
     511           0 :   }
     512        1424 :   void AndWith(const Rect& aOther)
     513             :   {
     514        1424 :     And(This(), aOther);
     515        1424 :   }
     516         391 :   Derived& And  (const Derived& aRgn1,   const Derived& aRgn2)
     517             :   {
     518         391 :     mImpl.And (aRgn1.mImpl, aRgn2.mImpl);
     519         391 :     return This();
     520             :   }
     521        1611 :   Derived& And  (const Derived& aRegion, const Rect& aRect)
     522             :   {
     523        1611 :     mImpl.And (aRegion.mImpl, ToRect (aRect));
     524        1611 :     return This();
     525             :   }
     526           0 :   Derived& And  (const Rect& aRect, const Derived& aRegion)
     527             :   {
     528           0 :     return  And  (aRegion, aRect);
     529             :   }
     530         184 :   Derived& And  (const Rect& aRect1, const Rect& aRect2)
     531             :   {
     532         184 :     Rect TmpRect;
     533             : 
     534         184 :     TmpRect.IntersectRect (aRect1, aRect2);
     535         184 :     mImpl = ToRect (TmpRect);
     536         184 :     return This();
     537             :   }
     538             : 
     539         861 :   Derived& OrWith(const Derived& aOther)
     540             :   {
     541         861 :     return Or(This(), aOther);
     542             :   }
     543         481 :   Derived& OrWith(const Rect& aOther)
     544             :   {
     545         481 :     return Or(This(), aOther);
     546             :   }
     547        1742 :   Derived& Or   (const Derived& aRgn1,   const Derived& aRgn2)
     548             :   {
     549        1742 :     mImpl.Or (aRgn1.mImpl, aRgn2.mImpl);
     550        1742 :     return This();
     551             :   }
     552        1345 :   Derived& Or   (const Derived& aRegion, const Rect& aRect)
     553             :   {
     554        1345 :     mImpl.Or (aRegion.mImpl, ToRect (aRect));
     555        1345 :     return This();
     556             :   }
     557             :   Derived& Or   (const Rect& aRect, const Derived& aRegion)
     558             :   {
     559             :     return  Or   (aRegion, aRect);
     560             :   }
     561           0 :   Derived& Or   (const Rect& aRect1, const Rect& aRect2)
     562             :   {
     563           0 :     mImpl = ToRect (aRect1);
     564           0 :     return Or (This(), aRect2);
     565             :   }
     566             : 
     567             :   Derived& XorWith(const Derived& aOther)
     568             :   {
     569             :     return Xor(This(), aOther);
     570             :   }
     571             :   Derived& XorWith(const Rect& aOther)
     572             :   {
     573             :     return Xor(This(), aOther);
     574             :   }
     575             :   Derived& Xor  (const Derived& aRgn1,   const Derived& aRgn2)
     576             :   {
     577             :     mImpl.Xor (aRgn1.mImpl, aRgn2.mImpl);
     578             :     return This();
     579             :   }
     580          32 :   Derived& Xor  (const Derived& aRegion, const Rect& aRect)
     581             :   {
     582          32 :     mImpl.Xor (aRegion.mImpl, ToRect (aRect));
     583          32 :     return This();
     584             :   }
     585             :   Derived& Xor  (const Rect& aRect, const Derived& aRegion)
     586             :   {
     587             :     return  Xor  (aRegion, aRect);
     588             :   }
     589          32 :   Derived& Xor  (const Rect& aRect1, const Rect& aRect2)
     590             :   {
     591          32 :     mImpl = ToRect (aRect1);
     592          32 :     return Xor (This(), aRect2);
     593             :   }
     594             : 
     595         156 :   Derived& SubOut(const Derived& aOther)
     596             :   {
     597         156 :     return Sub(This(), aOther);
     598             :   }
     599             :   Derived& SubOut(const Rect& aOther)
     600             :   {
     601             :     return Sub(This(), aOther);
     602             :   }
     603         662 :   Derived& Sub  (const Derived& aRgn1,   const Derived& aRgn2)
     604             :   {
     605         662 :     mImpl.Sub (aRgn1.mImpl, aRgn2.mImpl);
     606         662 :     return This();
     607             :   }
     608          70 :   Derived& Sub  (const Derived& aRegion, const Rect& aRect)
     609             :   {
     610          70 :     mImpl.Sub (aRegion.mImpl, ToRect (aRect));
     611          70 :     return This();
     612             :   }
     613           0 :   Derived& Sub  (const Rect& aRect, const Derived& aRegion)
     614             :   {
     615           0 :     return Sub (Derived (aRect), aRegion);
     616             :   }
     617          35 :   Derived& Sub  (const Rect& aRect1, const Rect& aRect2)
     618             :   {
     619          35 :     mImpl = ToRect (aRect1);
     620          35 :     return Sub (This(), aRect2);
     621             :   }
     622             : 
     623             :   /**
     624             :    * Returns true iff the given point is inside the region. A region
     625             :    * created from a rect (x=0, y=0, w=100, h=100) will NOT contain
     626             :    * the point x=100, y=100.
     627             :    */
     628          46 :   bool Contains (int aX, int aY) const
     629             :   {
     630          46 :     return mImpl.Contains(aX, aY);
     631             :   }
     632        2279 :   bool Contains (const Rect& aRect) const
     633             :   {
     634        2279 :     return mImpl.Contains (ToRect (aRect));
     635             :   }
     636        1952 :   bool Contains (const Derived& aRgn) const
     637             :   {
     638        1952 :     return mImpl.Contains (aRgn.mImpl);
     639             :   }
     640        1763 :   bool Intersects (const Rect& aRect) const
     641             :   {
     642        1763 :     return mImpl.Intersects (ToRect (aRect));
     643             :   }
     644             : 
     645        1055 :   void MoveBy (int32_t aXOffset, int32_t aYOffset)
     646             :   {
     647        1055 :     MoveBy (Point (aXOffset, aYOffset));
     648        1055 :   }
     649        1901 :   void MoveBy (Point aPt)
     650             :   {
     651        1901 :     mImpl.MoveBy (aPt.x, aPt.y);
     652        1901 :   }
     653           0 :   Derived MovedBy(int32_t aXOffset, int32_t aYOffset) const
     654             :   {
     655           0 :     return MovedBy(Point(aXOffset, aYOffset));
     656             :   }
     657           0 :   Derived MovedBy(const Point& aPt) const
     658             :   {
     659           0 :     Derived copy(This());
     660           0 :     copy.MoveBy(aPt);
     661           0 :     return copy;
     662             :   }
     663             : 
     664         281 :   Derived Intersect(const Derived& aOther) const
     665             :   {
     666         281 :     Derived intersection;
     667         281 :     intersection.And(This(), aOther);
     668         281 :     return intersection;
     669             :   }
     670             : 
     671           0 :   void Inflate(const Margin& aMargin)
     672             :   {
     673           0 :     mImpl.Inflate(nsMargin(aMargin.top, aMargin.right, aMargin.bottom, aMargin.left));
     674           0 :   }
     675           0 :   Derived Inflated(const Margin& aMargin) const
     676             :   {
     677           0 :     Derived copy(This());
     678           0 :     copy.Inflate(aMargin);
     679           0 :     return copy;
     680             :   }
     681             : 
     682         521 :   void SetEmpty ()
     683             :   {
     684         521 :     mImpl.SetEmpty  ();
     685         521 :   }
     686             : 
     687        4670 :   bool IsEmpty () const { return mImpl.IsEmpty (); }
     688             :   bool IsComplex () const { return mImpl.IsComplex (); }
     689        1717 :   bool IsEqual (const Derived& aRegion) const
     690             :   {
     691        1717 :     return mImpl.IsEqual (aRegion.mImpl);
     692             :   }
     693         293 :   uint32_t GetNumRects () const { return mImpl.GetNumRects (); }
     694        1765 :   Rect GetBounds () const { return FromRect (mImpl.GetBounds ()); }
     695          35 :   uint64_t Area () const { return mImpl.Area(); }
     696          61 :   nsRegion ToAppUnits (nscoord aAppUnitsPerPixel) const
     697             :   {
     698          61 :     nsRegion result;
     699         152 :     for (auto iter = RectIter(); !iter.Done(); iter.Next()) {
     700         182 :       nsRect appRect = ::ToAppUnits(iter.Get(), aAppUnitsPerPixel);
     701          91 :       result.Or(result, appRect);
     702             :     }
     703          61 :     return result;
     704             :   }
     705             :   Rect GetLargestRectangle (const Rect& aContainingRect = Rect()) const
     706             :   {
     707             :     return FromRect (mImpl.GetLargestRectangle( ToRect(aContainingRect) ));
     708             :   }
     709             : 
     710         595 :   Derived& ScaleRoundOut (float aXScale, float aYScale)
     711             :   {
     712         595 :     mImpl.ScaleRoundOut(aXScale, aYScale);
     713         595 :     return This();
     714             :   }
     715             : 
     716             :   Derived& ScaleInverseRoundOut (float aXScale, float aYScale)
     717             :   {
     718             :     mImpl.ScaleInverseRoundOut(aXScale, aYScale);
     719             :     return This();
     720             :   }
     721             : 
     722             :   // Prefer using TransformBy(matrix, region) from UnitTransforms.h,
     723             :   // as applying the transform should typically change the unit system.
     724             :   // TODO(botond): Move this to IntRegionTyped and disable it for
     725             :   //               unit != UnknownUnits.
     726         418 :   Derived& Transform (const mozilla::gfx::Matrix4x4 &aTransform)
     727             :   {
     728         418 :     mImpl.Transform(aTransform);
     729         418 :     return This();
     730             :   }
     731             : 
     732             :   /**
     733             :    * Make sure the region has at most aMaxRects by adding area to it
     734             :    * if necessary. The simplified region will be a superset of the
     735             :    * original region. The simplified region's bounding box will be
     736             :    * the same as for the current region.
     737             :    */
     738        1775 :   void SimplifyOutward (uint32_t aMaxRects)
     739             :   {
     740        1775 :     mImpl.SimplifyOutward (aMaxRects);
     741        1775 :   }
     742           0 :   void SimplifyOutwardByArea (uint32_t aThreshold)
     743             :   {
     744           0 :     mImpl.SimplifyOutwardByArea (aThreshold);
     745           0 :   }
     746             :   /**
     747             :    * Make sure the region has at most aMaxRects by removing area from
     748             :    * it if necessary. The simplified region will be a subset of the
     749             :    * original region.
     750             :    */
     751             :   void SimplifyInward (uint32_t aMaxRects)
     752             :   {
     753             :     mImpl.SimplifyInward (aMaxRects);
     754             :   }
     755             : 
     756             :   typedef void (*visitFn)(void *closure, VisitSide side, int x1, int y1, int x2, int y2);
     757           0 :   void VisitEdges (visitFn visit, void *closure)
     758             :   {
     759           0 :     mImpl.VisitEdges (visit, closure);
     760           0 :   }
     761             : 
     762           0 :   nsCString ToString() const { return mImpl.ToString(); }
     763             : 
     764        2392 :   class RectIterator
     765             :   {
     766             :     nsRegion::RectIterator mImpl; // The underlying iterator.
     767             :     mutable Rect mTmp;            // The most recently gotten rectangle.
     768             : 
     769             :   public:
     770        2392 :     explicit RectIterator(const BaseIntRegion& aRegion)
     771        2392 :       : mImpl(aRegion.mImpl)
     772        2392 :     {}
     773             : 
     774        3664 :     bool Done() const { return mImpl.Done(); }
     775             : 
     776        1384 :     const Rect& Get() const
     777             :     {
     778        1384 :       mTmp = FromRect(mImpl.Get());
     779        1384 :       return mTmp;
     780             :     }
     781             : 
     782        1328 :     void Next() { mImpl.Next(); }
     783             :   };
     784             : 
     785        2392 :   RectIterator RectIter() const { return RectIterator(*this); }
     786             : 
     787             : protected:
     788             :   // Expose enough to derived classes from them to define conversions
     789             :   // between different types of BaseIntRegions.
     790        2838 :   explicit BaseIntRegion(const nsRegion& aImpl) : mImpl(aImpl) {}
     791        2838 :   const nsRegion& Impl() const { return mImpl; }
     792             : private:
     793             :   nsRegion mImpl;
     794             : 
     795       10048 :   static nsRect ToRect(const Rect& aRect)
     796             :   {
     797       10048 :     return nsRect (aRect.x, aRect.y, aRect.width, aRect.height);
     798             :   }
     799        3396 :   static Rect FromRect(const nsRect& aRect)
     800             :   {
     801        3396 :     return Rect (aRect.x, aRect.y, aRect.width, aRect.height);
     802             :   }
     803             : 
     804       17150 :   Derived& This()
     805             :   {
     806       17150 :     return *static_cast<Derived*>(this);
     807             :   }
     808         281 :   const Derived& This() const
     809             :   {
     810         281 :     return *static_cast<const Derived*>(this);
     811             :   }
     812             : };
     813             : 
     814             : template <class units>
     815       24357 : class IntRegionTyped :
     816             :     public BaseIntRegion<IntRegionTyped<units>, IntRectTyped<units>, IntPointTyped<units>, IntMarginTyped<units>>
     817             : {
     818             :   typedef BaseIntRegion<IntRegionTyped<units>, IntRectTyped<units>, IntPointTyped<units>, IntMarginTyped<units>> Super;
     819             : 
     820             :   // Make other specializations of IntRegionTyped friends.
     821             :   template <typename OtherUnits>
     822             :   friend class IntRegionTyped;
     823             : 
     824             :   static_assert(IsPixel<units>::value, "'units' must be a coordinate system tag");
     825             : 
     826             : public:
     827             :   typedef IntRectTyped<units> RectType;
     828             :   typedef IntPointTyped<units> PointType;
     829             :   typedef IntMarginTyped<units> MarginType;
     830             : 
     831             :   // Forward constructors.
     832       14596 :   IntRegionTyped() {}
     833        2451 :   MOZ_IMPLICIT IntRegionTyped(const IntRectTyped<units>& aRect) : Super(aRect) {}
     834        2237 :   IntRegionTyped(const IntRegionTyped& aRegion) : Super(aRegion) {}
     835        1179 :   explicit IntRegionTyped(mozilla::gfx::ArrayView<pixman_box32_t> aRects) : Super(aRects) {}
     836        1345 :   IntRegionTyped(IntRegionTyped&& aRegion) : Super(mozilla::Move(aRegion)) {}
     837             : 
     838             :   // Assignment operators need to be forwarded as well, otherwise the compiler
     839             :   // will declare deleted ones.
     840        5061 :   IntRegionTyped& operator=(const IntRegionTyped& aRegion)
     841             :   {
     842        5061 :     return Super::operator=(aRegion);
     843             :   }
     844        2059 :   IntRegionTyped& operator=(IntRegionTyped&& aRegion)
     845             :   {
     846        2059 :     return Super::operator=(mozilla::Move(aRegion));
     847             :   }
     848             : 
     849         871 :   static IntRegionTyped FromUnknownRegion(const IntRegion& aRegion)
     850             :   {
     851         871 :     return IntRegionTyped(aRegion.Impl());
     852             :   }
     853        1967 :   IntRegion ToUnknownRegion() const
     854             :   {
     855             :     // Need |this->| because Impl() is defined in a dependent base class.
     856        1967 :     return IntRegion(this->Impl());
     857             :   }
     858             : private:
     859             :   // This is deliberately private, so calling code uses FromUnknownRegion().
     860        2838 :   explicit IntRegionTyped(const nsRegion& aRegion) : Super(aRegion) {}
     861             : };
     862             : 
     863             : } // namespace gfx
     864             : } // namespace mozilla
     865             : 
     866             : typedef mozilla::gfx::IntRegion nsIntRegion;
     867             : 
     868             : #endif

Generated by: LCOV version 1.13