gecko-dev/gfx/public/nsRegion.h

277 строки
8.0 KiB
C++

/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Dainis Jonitis,
* <Dainis_Jonitis@swh-t.lv>. Portions created by Dainis Jonitis are
* Copyright (C) 2001 Dainis Jonitis. All Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsRegion_h__
#define nsRegion_h__
// Implementation of region.
// Region is represented as circular double-linked list of nsRegion::RgnRect structures.
// Rectangles in this list do not overlap and are sorted by (y, x) coordinates.
#include "nsRect.h"
// Special version of nsRect structure for speed optimizations in nsRegion code.
// Most important functions could be made inline and be sure that passed rectangles
// will always be non-empty.
struct nsRectFast : public nsRect
{
nsRectFast () {} // No need to call parent constructor to set default values
nsRectFast (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) : nsRect (aX, aY, aWidth, aHeight) {}
nsRectFast (const nsRect& aRect) : nsRect (aRect) {}
#if 1 // Override nsRect methods to make them inline. Do not check for emptiness.
PRBool Contains (const nsRectFast &aRect) const
{
return (PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
(aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost()));
}
PRBool Intersects (const nsRectFast &aRect) const
{
return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
(aRect.x < XMost()) && (aRect.y < YMost()));
}
PRBool IntersectRect (const nsRectFast &aRect1, const nsRectFast &aRect2)
{
const nscoord xmost = PR_MIN (aRect1.XMost(), aRect2.XMost());
x = PR_MAX (aRect1.x, aRect2.x);
width = xmost - x;
if (width <= 0) return PR_FALSE;
const nscoord ymost = PR_MIN (aRect1.YMost(), aRect2.YMost());
y = PR_MAX (aRect1.y, aRect2.y);
height = ymost - y;
if (height <= 0) return PR_FALSE;
return PR_TRUE;
}
void UnionRect (const nsRectFast &aRect1, const nsRectFast &aRect2)
{
const nscoord xmost = PR_MAX (aRect1.XMost(), aRect2.XMost());
const nscoord ymost = PR_MAX (aRect1.YMost(), aRect2.YMost());
x = PR_MIN (aRect1.x, aRect2.x);
y = PR_MIN (aRect1.y, aRect2.y);
width = xmost - x;
height = ymost - y;
}
#endif
};
class NS_GFX nsRegion
{
friend class nsRegionRectIterator;
friend class RgnRectMemoryAllocator;
struct NS_GFX RgnRect : public nsRectFast
{
RgnRect* prev;
RgnRect* next;
RgnRect () {} // No need to call parent constructor to set default values
RgnRect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) : nsRectFast (aX, aY, aWidth, aHeight) {}
RgnRect (const nsRectFast& aRect) : nsRectFast (aRect) {}
inline void* operator new (size_t) CPP_THROW_NEW;
inline void operator delete (void* aRect, size_t);
RgnRect& operator = (const RgnRect& aRect) // Do not overwrite prev/next pointers
{
x = aRect.x;
y = aRect.y;
width = aRect.width;
height = aRect.height;
return *this;
}
};
public:
nsRegion () { Init(); }
nsRegion (const nsRectFast& aRect) { Init(); Copy(aRect); }
~nsRegion () { SetToElements (0); }
nsRegion& Copy (const nsRegion& aRegion);
nsRegion& Copy (const nsRectFast& aRect);
nsRegion& And (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& And (const nsRegion& aRegion, const nsRectFast& aRect);
nsRegion& And (const nsRectFast& aRect, const nsRegion& aRegion)
{
return And (aRegion, aRect);
}
nsRegion& And (const nsRectFast& aRect1, const nsRectFast& aRect2)
{
nsRectFast TmpRect;
// Force generic nsRect::IntersectRect to handle empty rectangles!
TmpRect.nsRect::IntersectRect (aRect1, aRect2);
return Copy (TmpRect);
}
nsRegion& Or (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& Or (const nsRegion& aRegion, const nsRectFast& aRect);
nsRegion& Or (const nsRectFast& aRect, const nsRegion& aRegion)
{
return Or (aRegion, aRect);
}
nsRegion& Or (const nsRectFast& aRect1, const nsRectFast& aRect2)
{
nsRegion TmpRegion;
TmpRegion.Copy (aRect1);
return Or (TmpRegion, aRect2);
}
nsRegion& Xor (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& Xor (const nsRegion& aRegion, const nsRectFast& aRect);
nsRegion& Xor (const nsRectFast& aRect, const nsRegion& aRegion)
{
return Xor (aRegion, aRect);
}
nsRegion& Xor (const nsRectFast& aRect1, const nsRectFast& aRect2)
{
nsRegion TmpRegion;
TmpRegion.Copy (aRect1);
return Xor (TmpRegion, aRect2);
}
nsRegion& Sub (const nsRegion& aRgn1, const nsRegion& aRgn2);
nsRegion& Sub (const nsRegion& aRegion, const nsRectFast& aRect);
nsRegion& Sub (const nsRectFast& aRect, const nsRegion& aRegion)
{
nsRegion TmpRegion;
TmpRegion.Copy (aRect);
return Sub (TmpRegion, aRegion);
}
nsRegion& Sub (const nsRectFast& aRect1, const nsRectFast& aRect2)
{
nsRegion TmpRegion;
TmpRegion.Copy (aRect1);
return Sub (TmpRegion, aRect2);
}
nsRect GetBounds () const
{
return mBoundRect;
}
void MoveBy (PRInt32 aXOffset, PRInt32 aYOffset);
void SetEmpty ()
{
SetToElements (0);
mBoundRect.SetRect (0, 0, 0, 0);
}
PRBool IsEmpty () const { return mRectCount == 0; }
PRBool IsComplex () const { return mRectCount > 1; }
PRBool IsEqual (const nsRegion& aRegion) const;
PRUint32 GetNumRects () const { return mRectCount; }
private:
PRUint32 mRectCount;
RgnRect* mCurRect;
RgnRect mRectListHead;
nsRectFast mBoundRect;
void Init ();
void InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect)
{
aNewRect->prev = aRelativeRect->prev;
aNewRect->next = aRelativeRect;
aRelativeRect->prev->next = aNewRect;
aRelativeRect->prev = aNewRect;
mCurRect = aNewRect;
mRectCount++;
}
void InsertAfter (RgnRect* aNewRect, RgnRect* aRelativeRect)
{
aNewRect->prev = aRelativeRect;
aNewRect->next = aRelativeRect->next;
aRelativeRect->next->prev = aNewRect;
aRelativeRect->next = aNewRect;
mCurRect = aNewRect;
mRectCount++;
}
void SetToElements (PRUint32 aCount);
RgnRect* Remove (RgnRect* aRect);
void InsertInPlace (RgnRect* aRect, PRBool aOptimizeOnFly = PR_FALSE);
void SaveLinkChain ();
void RestoreLinkChain ();
void Optimize ();
void SubRegion (const nsRegion& aRegion, nsRegion& aResult) const;
void SubRect (const nsRectFast& aRect, nsRegion& aResult, nsRegion& aCompleted) const;
void SubRect (const nsRectFast& aRect, nsRegion& aResult) const
{ SubRect (aRect, aResult, aResult); }
void Merge (const nsRegion& aRgn1, const nsRegion& aRgn2);
void MoveInto (nsRegion& aDestRegion, const RgnRect* aStartRect);
void MoveInto (nsRegion& aDestRegion)
{ MoveInto (aDestRegion, mRectListHead.next); }
nsRegion (const nsRegion& aRegion); // Prevent copying of regions
nsRegion& operator = (const nsRegion& aRegion);
};
// Allow read-only access to region rectangles by iterating the list
class nsRegionRectIterator
{
const nsRegion* mRegion;
const nsRegion::RgnRect* mCurPtr;
public:
nsRegionRectIterator (const nsRegion& aRegion)
{
mRegion = &aRegion;
mCurPtr = &aRegion.mRectListHead;
}
const nsRectFast* Next ()
{
mCurPtr = mCurPtr->next;
return (mCurPtr != &mRegion->mRectListHead) ? mCurPtr : nsnull;
}
const nsRectFast* Prev ()
{
mCurPtr = mCurPtr->prev;
return (mCurPtr != &mRegion->mRectListHead) ? mCurPtr : nsnull;
}
void Reset ()
{
mCurPtr = &mRegion->mRectListHead;
}
};
#endif