michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #ifndef nsRegion_h__ michael@0: #define nsRegion_h__ michael@0: michael@0: #include // for size_t michael@0: #include // for uint32_t, uint64_t michael@0: #include // for int32_t michael@0: #include "gfxCore.h" // for NS_GFX michael@0: #include "nsCoord.h" // for nscoord michael@0: #include "nsError.h" // for nsresult michael@0: #include "nsPoint.h" // for nsIntPoint, nsPoint michael@0: #include "nsRect.h" // for nsIntRect, nsRect michael@0: #include "nsMargin.h" // for nsIntMargin michael@0: #include "nsStringGlue.h" // for nsCString michael@0: #include "xpcom-config.h" // for CPP_THROW_NEW michael@0: michael@0: class nsIntRegion; michael@0: michael@0: #include "pixman.h" michael@0: michael@0: /* For information on the internal representation look at pixman-region.c michael@0: * michael@0: * This replaces an older homebrew implementation of nsRegion. The michael@0: * representation used here may use more rectangles than nsRegion however, the michael@0: * representation is canonical. This means that there's no need for an michael@0: * Optimize() method because for a paticular region there is only one michael@0: * representation. This means that nsIntRegion will have more predictable michael@0: * performance characteristics than the old nsRegion and should not become michael@0: * degenerate. michael@0: * michael@0: * The pixman region code originates from X11 which has spread to a variety of michael@0: * projects including Qt, Gtk, Wine. It should perform reasonably well. michael@0: */ michael@0: michael@0: class nsRegionRectIterator; michael@0: michael@0: class nsRegion michael@0: { michael@0: michael@0: friend class nsRegionRectIterator; michael@0: michael@0: public: michael@0: nsRegion () { pixman_region32_init(&mImpl); } michael@0: nsRegion (const nsRect& aRect) { pixman_region32_init_rect(&mImpl, michael@0: aRect.x, michael@0: aRect.y, michael@0: aRect.width, michael@0: aRect.height); } michael@0: nsRegion (const nsRegion& aRegion) { pixman_region32_init(&mImpl); pixman_region32_copy(&mImpl,aRegion.Impl()); } michael@0: ~nsRegion () { pixman_region32_fini(&mImpl); } michael@0: nsRegion& operator = (const nsRect& aRect) { Copy (aRect); return *this; } michael@0: nsRegion& operator = (const nsRegion& aRegion) { Copy (aRegion); return *this; } michael@0: bool operator==(const nsRegion& aRgn) const michael@0: { michael@0: return IsEqual(aRgn); michael@0: } michael@0: michael@0: void Swap(nsRegion* aOther) michael@0: { michael@0: pixman_region32_t tmp = mImpl; michael@0: mImpl = aOther->mImpl; michael@0: aOther->mImpl = tmp; michael@0: } michael@0: michael@0: static michael@0: nsresult InitStatic() michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: static michael@0: void ShutdownStatic() {} michael@0: michael@0: nsRegion& And(const nsRegion& aRgn1, const nsRegion& aRgn2) michael@0: { michael@0: pixman_region32_intersect(&mImpl, aRgn1.Impl(), aRgn2.Impl()); michael@0: return *this; michael@0: } michael@0: nsRegion& And(const nsRect& aRect, const nsRegion& aRegion) michael@0: { michael@0: return And(aRegion, aRect); michael@0: } michael@0: nsRegion& And(const nsRegion& aRegion, const nsRect& aRect) michael@0: { michael@0: pixman_region32_intersect_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height); michael@0: return *this; michael@0: } michael@0: nsRegion& And(const nsRect& aRect1, const nsRect& aRect2) michael@0: { michael@0: nsRect TmpRect; michael@0: michael@0: TmpRect.IntersectRect(aRect1, aRect2); michael@0: return Copy(TmpRect); michael@0: } michael@0: michael@0: nsRegion& Or(const nsRegion& aRgn1, const nsRegion& aRgn2) michael@0: { michael@0: pixman_region32_union(&mImpl, aRgn1.Impl(), aRgn2.Impl()); michael@0: return *this; michael@0: } michael@0: nsRegion& Or(const nsRegion& aRegion, const nsRect& aRect) michael@0: { michael@0: pixman_region32_union_rect(&mImpl, aRegion.Impl(), aRect.x, aRect.y, aRect.width, aRect.height); michael@0: return *this; michael@0: } michael@0: nsRegion& Or(const nsRect& aRect, const nsRegion& aRegion) michael@0: { michael@0: return Or(aRegion, aRect); michael@0: } michael@0: nsRegion& Or(const nsRect& aRect1, const nsRect& aRect2) michael@0: { michael@0: Copy (aRect1); michael@0: return Or (*this, aRect2); michael@0: } michael@0: michael@0: nsRegion& Xor(const nsRegion& aRgn1, const nsRegion& aRgn2) michael@0: { michael@0: // this could be implemented better if pixman had direct michael@0: // support for xoring regions. michael@0: nsRegion p; michael@0: p.Sub(aRgn1, aRgn2); michael@0: nsRegion q; michael@0: q.Sub(aRgn2, aRgn1); michael@0: return Or(p, q); michael@0: } michael@0: nsRegion& Xor(const nsRegion& aRegion, const nsRect& aRect) michael@0: { michael@0: return Xor(aRegion, nsRegion(aRect)); michael@0: } michael@0: nsRegion& Xor(const nsRect& aRect, const nsRegion& aRegion) michael@0: { michael@0: return Xor(nsRegion(aRect), aRegion); michael@0: } michael@0: nsRegion& Xor(const nsRect& aRect1, const nsRect& aRect2) michael@0: { michael@0: return Xor(nsRegion(aRect1), nsRegion(aRect2)); michael@0: } michael@0: michael@0: nsRegion ToAppUnits (nscoord aAppUnitsPerPixel) const; michael@0: nsRegion& Sub(const nsRegion& aRgn1, const nsRegion& aRgn2) michael@0: { michael@0: pixman_region32_subtract(&mImpl, aRgn1.Impl(), aRgn2.Impl()); michael@0: return *this; michael@0: } michael@0: nsRegion& Sub(const nsRegion& aRegion, const nsRect& aRect) michael@0: { michael@0: return Sub(aRegion, nsRegion(aRect)); michael@0: } michael@0: nsRegion& Sub(const nsRect& aRect, const nsRegion& aRegion) michael@0: { michael@0: return Sub(nsRegion(aRect), aRegion); michael@0: } michael@0: nsRegion& Sub(const nsRect& aRect1, const nsRect& aRect2) michael@0: { michael@0: Copy(aRect1); michael@0: return Sub(*this, aRect2); michael@0: } michael@0: michael@0: bool Contains (const nsRect& aRect) const michael@0: { michael@0: pixman_box32_t box = RectToBox(aRect); michael@0: return pixman_region32_contains_rectangle(Impl(), &box) == PIXMAN_REGION_IN; michael@0: } michael@0: bool Contains (const nsRegion& aRgn) const; michael@0: bool Intersects (const nsRect& aRect) const; michael@0: michael@0: void MoveBy (int32_t aXOffset, int32_t aYOffset) michael@0: { michael@0: MoveBy (nsPoint (aXOffset, aYOffset)); michael@0: } michael@0: void MoveBy (nsPoint aPt) { pixman_region32_translate(&mImpl, aPt.x, aPt.y); } michael@0: void SetEmpty () michael@0: { michael@0: pixman_region32_clear(&mImpl); michael@0: } michael@0: michael@0: nsRegion MovedBy(int32_t aXOffset, int32_t aYOffset) const michael@0: { michael@0: return MovedBy(nsPoint(aXOffset, aYOffset)); michael@0: } michael@0: nsRegion MovedBy(const nsPoint& aPt) const michael@0: { michael@0: nsRegion copy(*this); michael@0: copy.MoveBy(aPt); michael@0: return copy; michael@0: } michael@0: michael@0: nsRegion Intersect(const nsRegion& aOther) const michael@0: { michael@0: nsRegion intersection; michael@0: intersection.And(*this, aOther); michael@0: return intersection; michael@0: } michael@0: michael@0: void Inflate(const nsMargin& aMargin); michael@0: michael@0: nsRegion Inflated(const nsMargin& aMargin) const michael@0: { michael@0: nsRegion copy(*this); michael@0: copy.Inflate(aMargin); michael@0: return copy; michael@0: } michael@0: michael@0: bool IsEmpty () const { return !pixman_region32_not_empty(Impl()); } michael@0: bool IsComplex () const { return GetNumRects() > 1; } michael@0: bool IsEqual (const nsRegion& aRegion) const michael@0: { michael@0: return pixman_region32_equal(Impl(), aRegion.Impl()); michael@0: } michael@0: uint32_t GetNumRects () const { return pixman_region32_n_rects(Impl()); } michael@0: const nsRect GetBounds () const { return BoxToRect(mImpl.extents); } michael@0: uint64_t Area () const; michael@0: // Converts this region from aFromAPP, an appunits per pixel ratio, to michael@0: // aToAPP. This applies nsRect::ConvertAppUnitsRoundOut/In to each rect of michael@0: // the region. michael@0: nsRegion ConvertAppUnitsRoundOut (int32_t aFromAPP, int32_t aToAPP) const; michael@0: nsRegion ConvertAppUnitsRoundIn (int32_t aFromAPP, int32_t aToAPP) const; michael@0: nsRegion& ScaleRoundOut(float aXScale, float aYScale); michael@0: nsRegion& ScaleInverseRoundOut(float aXScale, float aYScale); michael@0: nsIntRegion ScaleToOutsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const; michael@0: nsIntRegion ScaleToInsidePixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const; michael@0: nsIntRegion ScaleToNearestPixels (float aXScale, float aYScale, nscoord aAppUnitsPerPixel) const; michael@0: nsIntRegion ToOutsidePixels (nscoord aAppUnitsPerPixel) const; michael@0: nsIntRegion ToNearestPixels (nscoord aAppUnitsPerPixel) const; michael@0: michael@0: /** michael@0: * Gets the largest rectangle contained in the region. michael@0: * @param aContainingRect if non-empty, we choose a rectangle that michael@0: * maximizes the area intersecting with aContainingRect (and break ties by michael@0: * then choosing the largest rectangle overall) michael@0: */ michael@0: nsRect GetLargestRectangle (const nsRect& aContainingRect = nsRect()) const; michael@0: michael@0: /** michael@0: * Make sure the region has at most aMaxRects by adding area to it michael@0: * if necessary. The simplified region will be a superset of the michael@0: * original region. The simplified region's bounding box will be michael@0: * the same as for the current region. michael@0: */ michael@0: void SimplifyOutward (uint32_t aMaxRects); michael@0: /** michael@0: * Simplify the region by adding at most aThreshold area between spans of michael@0: * rects. The simplified region will be a superset of the original region. michael@0: * The simplified region's bounding box will be the same as for the current michael@0: * region. michael@0: */ michael@0: void SimplifyOutwardByArea(uint32_t aThreshold); michael@0: /** michael@0: * Make sure the region has at most aMaxRects by removing area from michael@0: * it if necessary. The simplified region will be a subset of the michael@0: * original region. michael@0: */ michael@0: void SimplifyInward (uint32_t aMaxRects); michael@0: michael@0: nsCString ToString() const; michael@0: private: michael@0: pixman_region32_t mImpl; michael@0: michael@0: nsIntRegion ToPixels(nscoord aAppUnitsPerPixel, bool aOutsidePixels) const; michael@0: michael@0: nsRegion& Copy (const nsRegion& aRegion) michael@0: { michael@0: pixman_region32_copy(&mImpl, aRegion.Impl()); michael@0: return *this; michael@0: } michael@0: michael@0: nsRegion& Copy (const nsRect& aRect) michael@0: { michael@0: // pixman needs to distinguish between an empty region and a region michael@0: // with one rect so that it can return a different number of rectangles. michael@0: // Empty rect: data = empty_box michael@0: // 1 rect: data = null michael@0: // >1 rect: data = rects michael@0: if (aRect.IsEmpty()) { michael@0: pixman_region32_clear(&mImpl); michael@0: } else { michael@0: pixman_box32_t box = RectToBox(aRect); michael@0: pixman_region32_reset(&mImpl, &box); michael@0: } michael@0: return *this; michael@0: } michael@0: michael@0: static inline pixman_box32_t RectToBox(const nsRect &aRect) michael@0: { michael@0: pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() }; michael@0: return box; michael@0: } michael@0: michael@0: static inline pixman_box32_t RectToBox(const nsIntRect &aRect) michael@0: { michael@0: pixman_box32_t box = { aRect.x, aRect.y, aRect.XMost(), aRect.YMost() }; michael@0: return box; michael@0: } michael@0: michael@0: michael@0: static inline nsRect BoxToRect(const pixman_box32_t &aBox) michael@0: { michael@0: return nsRect(aBox.x1, aBox.y1, michael@0: aBox.x2 - aBox.x1, michael@0: aBox.y2 - aBox.y1); michael@0: } michael@0: michael@0: pixman_region32_t* Impl() const michael@0: { michael@0: return const_cast(&mImpl); michael@0: } michael@0: michael@0: }; michael@0: michael@0: michael@0: class NS_GFX nsRegionRectIterator michael@0: { michael@0: const nsRegion* mRegion; michael@0: int i; michael@0: int n; michael@0: nsRect rect; michael@0: pixman_box32_t *boxes; michael@0: michael@0: public: michael@0: nsRegionRectIterator (const nsRegion& aRegion) michael@0: { michael@0: mRegion = &aRegion; michael@0: i = 0; michael@0: boxes = pixman_region32_rectangles(aRegion.Impl(), &n); michael@0: } michael@0: michael@0: const nsRect* Next () michael@0: { michael@0: if (i == n) michael@0: return nullptr; michael@0: rect = nsRegion::BoxToRect(boxes[i]); michael@0: i++; michael@0: return ▭ michael@0: } michael@0: michael@0: const nsRect* Prev () michael@0: { michael@0: if (i == -1) michael@0: return nullptr; michael@0: rect = nsRegion::BoxToRect(boxes[i]); michael@0: i--; michael@0: return ▭ michael@0: } michael@0: michael@0: void Reset () michael@0: { michael@0: i = 0; michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * nsIntRegions use int32_t coordinates and nsIntRects. michael@0: */ michael@0: class NS_GFX nsIntRegion michael@0: { michael@0: friend class nsIntRegionRectIterator; michael@0: friend class nsRegion; michael@0: michael@0: public: michael@0: nsIntRegion () {} michael@0: nsIntRegion (const nsIntRect& aRect) : mImpl (ToRect(aRect)) {} michael@0: nsIntRegion (const nsIntRegion& aRegion) : mImpl (aRegion.mImpl) {} michael@0: nsIntRegion& operator = (const nsIntRect& aRect) { mImpl = ToRect (aRect); return *this; } michael@0: nsIntRegion& operator = (const nsIntRegion& aRegion) { mImpl = aRegion.mImpl; return *this; } michael@0: michael@0: bool operator==(const nsIntRegion& aRgn) const michael@0: { michael@0: return IsEqual(aRgn); michael@0: } michael@0: michael@0: void Swap(nsIntRegion* aOther) michael@0: { michael@0: mImpl.Swap(&aOther->mImpl); michael@0: } michael@0: michael@0: nsIntRegion& And (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) michael@0: { michael@0: mImpl.And (aRgn1.mImpl, aRgn2.mImpl); michael@0: return *this; michael@0: } michael@0: nsIntRegion& And (const nsIntRegion& aRegion, const nsIntRect& aRect) michael@0: { michael@0: mImpl.And (aRegion.mImpl, ToRect (aRect)); michael@0: return *this; michael@0: } michael@0: nsIntRegion& And (const nsIntRect& aRect, const nsIntRegion& aRegion) michael@0: { michael@0: return And (aRegion, aRect); michael@0: } michael@0: nsIntRegion& And (const nsIntRect& aRect1, const nsIntRect& aRect2) michael@0: { michael@0: nsIntRect TmpRect; michael@0: michael@0: TmpRect.IntersectRect (aRect1, aRect2); michael@0: mImpl = ToRect (TmpRect); michael@0: return *this; michael@0: } michael@0: michael@0: nsIntRegion& Or (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) michael@0: { michael@0: mImpl.Or (aRgn1.mImpl, aRgn2.mImpl); michael@0: return *this; michael@0: } michael@0: nsIntRegion& Or (const nsIntRegion& aRegion, const nsIntRect& aRect) michael@0: { michael@0: mImpl.Or (aRegion.mImpl, ToRect (aRect)); michael@0: return *this; michael@0: } michael@0: nsIntRegion& Or (const nsIntRect& aRect, const nsIntRegion& aRegion) michael@0: { michael@0: return Or (aRegion, aRect); michael@0: } michael@0: nsIntRegion& Or (const nsIntRect& aRect1, const nsIntRect& aRect2) michael@0: { michael@0: mImpl = ToRect (aRect1); michael@0: return Or (*this, aRect2); michael@0: } michael@0: michael@0: nsIntRegion& Xor (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) michael@0: { michael@0: mImpl.Xor (aRgn1.mImpl, aRgn2.mImpl); michael@0: return *this; michael@0: } michael@0: nsIntRegion& Xor (const nsIntRegion& aRegion, const nsIntRect& aRect) michael@0: { michael@0: mImpl.Xor (aRegion.mImpl, ToRect (aRect)); michael@0: return *this; michael@0: } michael@0: nsIntRegion& Xor (const nsIntRect& aRect, const nsIntRegion& aRegion) michael@0: { michael@0: return Xor (aRegion, aRect); michael@0: } michael@0: nsIntRegion& Xor (const nsIntRect& aRect1, const nsIntRect& aRect2) michael@0: { michael@0: mImpl = ToRect (aRect1); michael@0: return Xor (*this, aRect2); michael@0: } michael@0: michael@0: nsIntRegion& Sub (const nsIntRegion& aRgn1, const nsIntRegion& aRgn2) michael@0: { michael@0: mImpl.Sub (aRgn1.mImpl, aRgn2.mImpl); michael@0: return *this; michael@0: } michael@0: nsIntRegion& Sub (const nsIntRegion& aRegion, const nsIntRect& aRect) michael@0: { michael@0: mImpl.Sub (aRegion.mImpl, ToRect (aRect)); michael@0: return *this; michael@0: } michael@0: nsIntRegion& Sub (const nsIntRect& aRect, const nsIntRegion& aRegion) michael@0: { michael@0: return Sub (nsIntRegion (aRect), aRegion); michael@0: } michael@0: nsIntRegion& Sub (const nsIntRect& aRect1, const nsIntRect& aRect2) michael@0: { michael@0: mImpl = ToRect (aRect1); michael@0: return Sub (*this, aRect2); michael@0: } michael@0: michael@0: bool Contains (const nsIntRect& aRect) const michael@0: { michael@0: return mImpl.Contains (ToRect (aRect)); michael@0: } michael@0: bool Contains (const nsIntRegion& aRgn) const michael@0: { michael@0: return mImpl.Contains (aRgn.mImpl); michael@0: } michael@0: bool Intersects (const nsIntRect& aRect) const michael@0: { michael@0: return mImpl.Intersects (ToRect (aRect)); michael@0: } michael@0: michael@0: void MoveBy (int32_t aXOffset, int32_t aYOffset) michael@0: { michael@0: MoveBy (nsIntPoint (aXOffset, aYOffset)); michael@0: } michael@0: void MoveBy (nsIntPoint aPt) michael@0: { michael@0: mImpl.MoveBy (aPt.x, aPt.y); michael@0: } michael@0: nsIntRegion MovedBy(int32_t aXOffset, int32_t aYOffset) const michael@0: { michael@0: return MovedBy(nsIntPoint(aXOffset, aYOffset)); michael@0: } michael@0: nsIntRegion MovedBy(const nsIntPoint& aPt) const michael@0: { michael@0: nsIntRegion copy(*this); michael@0: copy.MoveBy(aPt); michael@0: return copy; michael@0: } michael@0: michael@0: nsIntRegion Intersect(const nsIntRegion& aOther) const michael@0: { michael@0: nsIntRegion intersection; michael@0: intersection.And(*this, aOther); michael@0: return intersection; michael@0: } michael@0: michael@0: void Inflate(const nsIntMargin& aMargin) michael@0: { michael@0: mImpl.Inflate(nsMargin(aMargin.top, aMargin.right, aMargin.bottom, aMargin.left)); michael@0: } michael@0: nsIntRegion Inflated(const nsIntMargin& aMargin) const michael@0: { michael@0: nsIntRegion copy(*this); michael@0: copy.Inflate(aMargin); michael@0: return copy; michael@0: } michael@0: michael@0: void SetEmpty () michael@0: { michael@0: mImpl.SetEmpty (); michael@0: } michael@0: michael@0: bool IsEmpty () const { return mImpl.IsEmpty (); } michael@0: bool IsComplex () const { return mImpl.IsComplex (); } michael@0: bool IsEqual (const nsIntRegion& aRegion) const michael@0: { michael@0: return mImpl.IsEqual (aRegion.mImpl); michael@0: } michael@0: uint32_t GetNumRects () const { return mImpl.GetNumRects (); } michael@0: nsIntRect GetBounds () const { return FromRect (mImpl.GetBounds ()); } michael@0: uint64_t Area () const { return mImpl.Area(); } michael@0: nsRegion ToAppUnits (nscoord aAppUnitsPerPixel) const; michael@0: nsIntRect GetLargestRectangle (const nsIntRect& aContainingRect = nsIntRect()) const michael@0: { michael@0: return FromRect (mImpl.GetLargestRectangle( ToRect(aContainingRect) )); michael@0: } michael@0: michael@0: nsIntRegion& ScaleRoundOut (float aXScale, float aYScale) michael@0: { michael@0: mImpl.ScaleRoundOut(aXScale, aYScale); michael@0: return *this; michael@0: } michael@0: michael@0: /** michael@0: * Make sure the region has at most aMaxRects by adding area to it michael@0: * if necessary. The simplified region will be a superset of the michael@0: * original region. The simplified region's bounding box will be michael@0: * the same as for the current region. michael@0: */ michael@0: void SimplifyOutward (uint32_t aMaxRects) michael@0: { michael@0: mImpl.SimplifyOutward (aMaxRects); michael@0: } michael@0: void SimplifyOutwardByArea (uint32_t aThreshold) michael@0: { michael@0: mImpl.SimplifyOutwardByArea (aThreshold); michael@0: } michael@0: /** michael@0: * Make sure the region has at most aMaxRects by removing area from michael@0: * it if necessary. The simplified region will be a subset of the michael@0: * original region. michael@0: */ michael@0: void SimplifyInward (uint32_t aMaxRects) michael@0: { michael@0: mImpl.SimplifyInward (aMaxRects); michael@0: } michael@0: michael@0: nsCString ToString() const { return mImpl.ToString(); } michael@0: michael@0: private: michael@0: nsRegion mImpl; michael@0: michael@0: static nsRect ToRect(const nsIntRect& aRect) michael@0: { michael@0: return nsRect (aRect.x, aRect.y, aRect.width, aRect.height); michael@0: } michael@0: static nsIntRect FromRect(const nsRect& aRect) michael@0: { michael@0: return nsIntRect (aRect.x, aRect.y, aRect.width, aRect.height); michael@0: } michael@0: }; michael@0: michael@0: class NS_GFX nsIntRegionRectIterator michael@0: { michael@0: nsRegionRectIterator mImpl; michael@0: nsIntRect mTmp; michael@0: michael@0: public: michael@0: nsIntRegionRectIterator (const nsIntRegion& aRegion) : mImpl (aRegion.mImpl) {} michael@0: michael@0: const nsIntRect* Next () michael@0: { michael@0: const nsRect* r = mImpl.Next(); michael@0: if (!r) michael@0: return nullptr; michael@0: mTmp = nsIntRegion::FromRect (*r); michael@0: return &mTmp; michael@0: } michael@0: michael@0: const nsIntRect* Prev () michael@0: { michael@0: const nsRect* r = mImpl.Prev(); michael@0: if (!r) michael@0: return nullptr; michael@0: mTmp = nsIntRegion::FromRect (*r); michael@0: return &mTmp; michael@0: } michael@0: michael@0: void Reset () michael@0: { michael@0: mImpl.Reset (); michael@0: } michael@0: }; michael@0: #endif