A slightly different region implementation, not tested or anything
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15236 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
7e68917fe7
commit
5c2728e222
529
src/tests/kits/interface/NewRegion/ClipRegion.cpp
Normal file
529
src/tests/kits/interface/NewRegion/ClipRegion.cpp
Normal file
@ -0,0 +1,529 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "clipping.h"
|
||||
#include "ClipRegion.h"
|
||||
|
||||
#include <Debug.h>
|
||||
|
||||
const static int32 kMaxPoints = 1024;
|
||||
const static int32 kMaxVerticalExtent = 0x10000000;
|
||||
const static int32 kMaxPositive = 0x7ffffffd;
|
||||
const static int32 kMaxNegative = 0x80000003;
|
||||
const static int32 kInitialDataSize = 8;
|
||||
|
||||
|
||||
ClipRegion::ClipRegion()
|
||||
:
|
||||
fDataSize(0),
|
||||
fData(NULL)
|
||||
{
|
||||
_Resize(kInitialDataSize);
|
||||
_Invalidate();
|
||||
}
|
||||
|
||||
|
||||
ClipRegion::ClipRegion(const ClipRegion ®ion)
|
||||
:
|
||||
fDataSize(0),
|
||||
fData(NULL)
|
||||
{
|
||||
*this = region;
|
||||
}
|
||||
|
||||
|
||||
ClipRegion::ClipRegion(const clipping_rect &rect)
|
||||
:
|
||||
fDataSize(0),
|
||||
fData(NULL)
|
||||
{
|
||||
Set(rect);
|
||||
}
|
||||
|
||||
|
||||
ClipRegion::ClipRegion(const BRect &rect)
|
||||
:
|
||||
fDataSize(0),
|
||||
fData(NULL)
|
||||
{
|
||||
Set(rect);
|
||||
}
|
||||
|
||||
|
||||
ClipRegion::ClipRegion(const clipping_rect *rects, const int32 &count)
|
||||
:
|
||||
fDataSize(0),
|
||||
fData(NULL)
|
||||
{
|
||||
Set(rects, count);
|
||||
}
|
||||
|
||||
|
||||
ClipRegion::~ClipRegion()
|
||||
{
|
||||
free(fData);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Set(const clipping_rect &rect)
|
||||
{
|
||||
if (!valid_rect(rect) || (fDataSize <= 1 && !_Resize(kInitialDataSize)))
|
||||
_Invalidate();
|
||||
else {
|
||||
fCount = 1;
|
||||
fData[0] = fBound = rect;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Set(const BRect &rect)
|
||||
{
|
||||
Set(to_clipping_rect(rect));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Set(const clipping_rect *rects, const int32 &count)
|
||||
{
|
||||
_Invalidate();
|
||||
_Append(rects, count);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ClipRegion::Intersects(const clipping_rect &rect) const
|
||||
{
|
||||
if (!rects_intersect(rect, fBound))
|
||||
return false;
|
||||
|
||||
for (int32 c = 0; c < fCount; c++) {
|
||||
if (rects_intersect(fData[c], rect))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ClipRegion::Intersects(const BRect &rect) const
|
||||
{
|
||||
return Intersects(to_clipping_rect(rect));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ClipRegion::Contains(const BPoint &pt) const
|
||||
{
|
||||
// If the point doesn't lie within the region's bounds,
|
||||
// don't even try it against the region's rects.
|
||||
if (!point_in(fBound, pt))
|
||||
return false;
|
||||
|
||||
for (int32 c = 0; c < fCount; c++) {
|
||||
if (point_in(fData[c], pt))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::OffsetBy(const int32 &dh, const int32 &dv)
|
||||
{
|
||||
if (fCount > 0) {
|
||||
for (int32 c = 0; c < fCount; c++)
|
||||
offset_rect(fData[c], dh, dv);
|
||||
|
||||
offset_rect(fBound, dh, dv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::OffsetBy(const BPoint &point)
|
||||
{
|
||||
return OffsetBy((int32)point.x, (int32)point.y);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::IntersectWith(const clipping_rect &rect)
|
||||
{
|
||||
if (!rects_intersect(rect, fBound))
|
||||
_Invalidate();
|
||||
else
|
||||
_IntersectWith(rect);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::IntersectWith(const BRect &rect)
|
||||
{
|
||||
IntersectWith(to_clipping_rect(rect));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::IntersectWith(const ClipRegion ®ion)
|
||||
{
|
||||
clipping_rect intersection = sect_rect(fBound, region.fBound);
|
||||
|
||||
if (fCount == 0 || region.fCount == 0 || !valid_rect(intersection))
|
||||
_Invalidate();
|
||||
|
||||
else if (fCount == 1 && region.fCount == 1)
|
||||
Set(intersection);
|
||||
|
||||
else if (fCount > 1 && region.fCount == 1)
|
||||
_IntersectWith(region.fBound);
|
||||
|
||||
else if (fCount == 1 && region.fCount > 1) {
|
||||
ClipRegion dest = region;
|
||||
dest._IntersectWith(fBound);
|
||||
_Adopt(dest);
|
||||
|
||||
} else
|
||||
_IntersectWithComplex(region);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Include(const clipping_rect &rect)
|
||||
{
|
||||
// The easy case first: if the rectangle completely contains
|
||||
// ourself, the union is the rectangle itself.
|
||||
if (rect.top <= fBound.top
|
||||
&& rect.bottom >= fBound.bottom
|
||||
&& rect.left <= fBound.left
|
||||
&& rect.right >= fBound.right)
|
||||
Set(rect);
|
||||
else {
|
||||
const ClipRegion region(rect);
|
||||
_IncludeComplex(region);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Include(const BRect &rect)
|
||||
{
|
||||
Include(to_clipping_rect(rect));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Include(const ClipRegion ®ion)
|
||||
{
|
||||
if (region.fCount == 0)
|
||||
return;
|
||||
|
||||
if (fCount == 0)
|
||||
*this = region;
|
||||
|
||||
else if (region.fBound.top > fBound.bottom)
|
||||
_Append(region);
|
||||
|
||||
else if (fBound.top > region.fBound.bottom)
|
||||
_Append(region, true);
|
||||
/*
|
||||
else if (regionA->bound.left > regionB->bound.right)
|
||||
OrRegionNoX(*regionB, *regionA, dest);
|
||||
|
||||
else if (regionB->bound.left > regionA->bound.right)
|
||||
OrRegionNoX(*regionA, *regionB, dest);
|
||||
*/
|
||||
else if (region.fCount == 1)
|
||||
Include(region.fBound);
|
||||
|
||||
else if (fCount == 1) {
|
||||
ClipRegion dest = region;
|
||||
dest.Include(fBound);
|
||||
_Adopt(dest);
|
||||
} else
|
||||
_IncludeComplex(region);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Exclude(const clipping_rect &rect)
|
||||
{
|
||||
const ClipRegion region(rect);
|
||||
Exclude(region);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Exclude(const BRect &rect)
|
||||
{
|
||||
const ClipRegion region(rect);
|
||||
Exclude(region);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::Exclude(const ClipRegion ®ion)
|
||||
{
|
||||
if (fCount == 0)
|
||||
return;
|
||||
|
||||
if (region.fCount == 0 || !rects_intersect(fBound, region.fBound))
|
||||
*this = region;
|
||||
else
|
||||
_ExcludeComplex(region);
|
||||
}
|
||||
|
||||
|
||||
ClipRegion &
|
||||
ClipRegion::operator=(const ClipRegion ®ion)
|
||||
{
|
||||
const int32 size = region.fDataSize > 0 ? region.fDataSize : kInitialDataSize;
|
||||
if (_Resize(size, false)) {
|
||||
fBound = region.fBound;
|
||||
fCount = region.fCount;
|
||||
memcpy(fData, region.fData, fCount * sizeof(clipping_rect));
|
||||
} else
|
||||
_Invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// private methods
|
||||
void
|
||||
ClipRegion::_IntersectWithComplex(const ClipRegion ®ion)
|
||||
{
|
||||
ClipRegion dest(*this);
|
||||
|
||||
for (int32 f = 0; f < fCount; f++) {
|
||||
for (int32 s = 0; s < region.fCount; s++) {
|
||||
clipping_rect testRect = sect_rect(fData[f], region.fData[s]);
|
||||
if (valid_rect(testRect))
|
||||
dest._AddRect(testRect);
|
||||
}
|
||||
}
|
||||
|
||||
if (dest.fCount > 1)
|
||||
dest._SortRects();
|
||||
|
||||
_Adopt(dest);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_IntersectWith(const clipping_rect &rect)
|
||||
{
|
||||
ASSERT(rects_intersect(rect, fBound));
|
||||
|
||||
// The easy case first: We already know that the region intersects,
|
||||
// with the passed rect, so we check if the rect completely contains
|
||||
// the region.
|
||||
// If it's the case, the intersection is exactly the region itself.
|
||||
if (rect.top <= fBound.top && rect.bottom >= fBound.bottom
|
||||
&& rect.left <= fBound.left && rect.right >= fBound.right)
|
||||
return;
|
||||
|
||||
// Otherwise, we add the intersections of the region's rects
|
||||
// with the passed rect
|
||||
ClipRegion dest;
|
||||
for (int32 x = 0; x < fCount; x++) {
|
||||
clipping_rect testRect = sect_rect(rect, fData[x]);
|
||||
if (valid_rect(testRect))
|
||||
dest._AddRect(testRect);
|
||||
}
|
||||
_Adopt(dest);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_IncludeComplex(const ClipRegion ®ion)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_ExcludeComplex(const ClipRegion ®ion)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Helper method to swap two rects
|
||||
static inline void
|
||||
SwapRects(clipping_rect &rect, clipping_rect &anotherRect)
|
||||
{
|
||||
clipping_rect tmpRect = rect;
|
||||
rect = anotherRect;
|
||||
anotherRect = tmpRect;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_SortRects()
|
||||
{
|
||||
bool again;
|
||||
|
||||
if (fCount == 2) {
|
||||
if (fData[0].top > fData[1].top)
|
||||
SwapRects(fData[0], fData[1]);
|
||||
|
||||
} else if (fCount > 2) {
|
||||
do {
|
||||
again = false;
|
||||
for (int32 c = 1; c < fCount; c++) {
|
||||
if (fData[c - 1].top > fData[c].top) {
|
||||
SwapRects(fData[c - 1], fData[c]);
|
||||
again = true;
|
||||
}
|
||||
}
|
||||
} while (again);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_AddRect(const clipping_rect &rect)
|
||||
{
|
||||
ASSERT(fCount >= 0);
|
||||
ASSERT(fDataSize >= 0);
|
||||
ASSERT(valid_rect(rect));
|
||||
|
||||
// Should we just reallocate the memory and
|
||||
// copy the rect ?
|
||||
bool addRect = true;
|
||||
|
||||
if (fCount > 0) {
|
||||
// Wait! We could merge the rect with one of the
|
||||
// existing rectangles, if it's adiacent.
|
||||
// We just check it against the last rectangle, since
|
||||
// we are keeping them sorted by their "top" coordinates.
|
||||
int32 last = fCount - 1;
|
||||
if (rect.left == fData[last].left && rect.right == fData[last].right
|
||||
&& rect.top == fData[last].bottom + 1) {
|
||||
|
||||
fData[last].bottom = rect.bottom;
|
||||
addRect = false;
|
||||
|
||||
} else if (rect.top == fData[last].top && rect.bottom == fData[last].bottom) {
|
||||
if (rect.left == fData[last].right + 1) {
|
||||
|
||||
fData[last].right = rect.right;
|
||||
addRect = false;
|
||||
|
||||
} else if (rect.right == fData[last].left - 1) {
|
||||
|
||||
fData[last].left = rect.left;
|
||||
addRect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We weren't lucky.... just add the rect as a new one
|
||||
if (addRect) {
|
||||
if (fDataSize <= fCount)
|
||||
_Resize(fCount + 16);
|
||||
|
||||
fData[fCount] = rect;
|
||||
|
||||
fCount++;
|
||||
}
|
||||
|
||||
_RecalculateBounds(rect);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_RecalculateBounds(const clipping_rect &rect)
|
||||
{
|
||||
if (fCount <= 0)
|
||||
return;
|
||||
|
||||
if (rect.top < fBound.top)
|
||||
fBound.top = rect.top;
|
||||
if (rect.left < fBound.left)
|
||||
fBound.left = rect.left;
|
||||
if (rect.right > fBound.right)
|
||||
fBound.right = rect.right;
|
||||
if (rect.bottom > fBound.bottom)
|
||||
fBound.bottom = rect.bottom;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_Append(const ClipRegion ®ion, const bool &aboveThis)
|
||||
{
|
||||
if (aboveThis) {
|
||||
ClipRegion dest = region;
|
||||
for (int32 c = 0; c < fCount; c++)
|
||||
dest._AddRect(fData[c]);
|
||||
_Adopt(dest);
|
||||
} else {
|
||||
for (int32 c = 0; c < region.fCount; c++)
|
||||
_AddRect(region.fData[c]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_Append(const clipping_rect *rects, const int32 &count, const bool &aboveThis)
|
||||
{
|
||||
if (aboveThis) {
|
||||
ClipRegion dest;
|
||||
dest.Set(rects, count);
|
||||
for (int32 c = 0; c < fCount; c++)
|
||||
dest._AddRect(fData[c]);
|
||||
_Adopt(dest);
|
||||
} else {
|
||||
for (int32 c = 0; c < count; c++)
|
||||
_AddRect(rects[c]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_Invalidate()
|
||||
{
|
||||
fCount = 0;
|
||||
fBound.left = kMaxPositive;
|
||||
fBound.top = kMaxPositive;
|
||||
fBound.right = kMaxNegative;
|
||||
fBound.bottom = kMaxNegative;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ClipRegion::_Resize(const int32 &newSize, const bool &keepOld)
|
||||
{
|
||||
if (!keepOld) {
|
||||
free(fData);
|
||||
fData = (clipping_rect *)malloc(newSize * sizeof(clipping_rect));
|
||||
} else
|
||||
fData = (clipping_rect *)realloc(fData, newSize * sizeof(clipping_rect));
|
||||
|
||||
if (fData == NULL)
|
||||
return false;
|
||||
|
||||
fDataSize = newSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ClipRegion::_Adopt(ClipRegion ®ion)
|
||||
{
|
||||
free(fData);
|
||||
fData = region.fData;
|
||||
fDataSize = region.fDataSize;
|
||||
fCount = region.fCount;
|
||||
fBound = region.fBound;
|
||||
|
||||
region._Invalidate();
|
||||
region.fDataSize = 0;
|
||||
region.fData = NULL;
|
||||
}
|
||||
|
||||
|
83
src/tests/kits/interface/NewRegion/ClipRegion.h
Normal file
83
src/tests/kits/interface/NewRegion/ClipRegion.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef __CLIPREGION_H
|
||||
#define __CLIPREGION_H
|
||||
|
||||
#include "Region.h" // for clipping_rect
|
||||
|
||||
class ServerLink;
|
||||
|
||||
class ClipRegion {
|
||||
public:
|
||||
ClipRegion();
|
||||
ClipRegion(const ClipRegion ®ion);
|
||||
ClipRegion(const BRegion ®ion);
|
||||
ClipRegion(const clipping_rect &rect);
|
||||
ClipRegion(const BRect &rect);
|
||||
ClipRegion(const clipping_rect *rects, const int32 &count);
|
||||
|
||||
~ClipRegion();
|
||||
|
||||
clipping_rect Frame() const { return fBound; }
|
||||
clipping_rect RectAt(const int32 &index) const
|
||||
{
|
||||
if (index >= 0 && index < fCount)
|
||||
return fData[index];
|
||||
clipping_rect rect = { 0, 0, -1, -1 };
|
||||
return rect;
|
||||
}
|
||||
|
||||
int32 CountRects() const { return fCount; }
|
||||
|
||||
void Set(const clipping_rect &rect);
|
||||
void Set(const BRect &rect);
|
||||
void Set(const clipping_rect *rects, const int32 &count);
|
||||
|
||||
bool Intersects(const clipping_rect &rect) const;
|
||||
bool Intersects(const BRect &rect) const;
|
||||
bool Intersects(const ClipRegion ®ion) const;
|
||||
|
||||
bool Contains(const BPoint &point) const;
|
||||
|
||||
void OffsetBy(const int32 &dx, const int32 &dy);
|
||||
void OffsetBy(const BPoint &point);
|
||||
|
||||
void Include(const clipping_rect &rect);
|
||||
void Include(const BRect &rect);
|
||||
void Include(const ClipRegion ®ion);
|
||||
|
||||
void Exclude(const clipping_rect &rect);
|
||||
void Exclude(const BRect &rect);
|
||||
void Exclude(const ClipRegion ®ion);
|
||||
|
||||
void IntersectWith(const clipping_rect &rect);
|
||||
void IntersectWith(const BRect &rect);
|
||||
void IntersectWith(const ClipRegion ®ion);
|
||||
|
||||
ClipRegion &operator=(const ClipRegion ®ion);
|
||||
|
||||
status_t ReadFromLink(ServerLink &link);
|
||||
status_t WriteToLink(ServerLink &link);
|
||||
|
||||
private:
|
||||
int32 fCount;
|
||||
int32 fDataSize;
|
||||
clipping_rect fBound;
|
||||
clipping_rect *fData;
|
||||
|
||||
void _Append(const ClipRegion ®ion, const bool &aboveThis = false);
|
||||
void _Append(const clipping_rect *rects, const int32 &count, const bool &aboveThis = false);
|
||||
|
||||
void _IntersectWithComplex(const ClipRegion ®ion);
|
||||
void _IntersectWith(const clipping_rect &rect);
|
||||
void _IncludeComplex(const ClipRegion ®ion);
|
||||
void _ExcludeComplex(const ClipRegion ®ion);
|
||||
|
||||
void _SortRects();
|
||||
void _AddRect(const clipping_rect &rect);
|
||||
void _RecalculateBounds(const clipping_rect &newRect);
|
||||
|
||||
void _Invalidate();
|
||||
bool _Resize(const int32 &newSize, const bool &keepOld = true);
|
||||
void _Adopt(ClipRegion ®ion);
|
||||
};
|
||||
|
||||
#endif // __CLIPREGION_H
|
348
src/tests/kits/interface/NewRegion/Region.cpp
Normal file
348
src/tests/kits/interface/NewRegion/Region.cpp
Normal file
@ -0,0 +1,348 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2003-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: Region.cpp
|
||||
// Author: Stefano Ceccherini (burton666@libero.it)
|
||||
// Description: Region class consisting of multiple rectangles
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Notes: As now, memory is always allocated and never freed (except on destruction,
|
||||
// or sometimes when a copy is made).
|
||||
// This let us be a bit faster since we don't do many reallocations.
|
||||
// But that means that even an empty region could "waste" much space, if it contained
|
||||
// many rects before being emptied.
|
||||
// I.E: a region which contains 24 rects allocates more than 24 * 4 * sizeof(int32)
|
||||
// = 96 * sizeof(int32) bytes. If we call MakeEmpty(), that region will contain no rects,
|
||||
// but it will still keep the allocated memory.
|
||||
// This shouldnt' be an issue, since usually BRegions are just used for calculations,
|
||||
// and don't last so long.
|
||||
// Anyway, we can change that behaviour if we want, but BeOS's BRegion seems to behave exactly
|
||||
// like this.
|
||||
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <Debug.h>
|
||||
#include <Region.h>
|
||||
|
||||
#include <clipping.h>
|
||||
#include <ClipRegion.h>
|
||||
|
||||
|
||||
|
||||
/*! \brief Initializes a region. The region will have no rects,
|
||||
and its bound will be invalid.
|
||||
*/
|
||||
BRegion::BRegion()
|
||||
:
|
||||
fRegion(new (nothrow) ClipRegion)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Initializes a region to be a copy of another.
|
||||
\param region The region to copy.
|
||||
*/
|
||||
BRegion::BRegion(const BRegion ®ion)
|
||||
:
|
||||
fRegion(new (nothrow) ClipRegion(*region.fRegion))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Initializes a region to contain a BRect.
|
||||
\param rect The BRect to set the region to.
|
||||
*/
|
||||
BRegion::BRegion(const BRect rect)
|
||||
:
|
||||
fRegion(new (nothrow) ClipRegion(to_clipping_rect(rect)))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Frees the allocated memory.
|
||||
*/
|
||||
BRegion::~BRegion()
|
||||
{
|
||||
delete fRegion;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Returns the bounds of the region.
|
||||
\return A BRect which represents the bounds of the region.
|
||||
*/
|
||||
BRect
|
||||
BRegion::Frame() const
|
||||
{
|
||||
return fRegion ? to_BRect(fRegion->Frame()) : BRect();
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Returns the bounds of the region as a clipping_rect (which has integer coordinates).
|
||||
\return A clipping_rect which represents the bounds of the region.
|
||||
*/
|
||||
clipping_rect
|
||||
BRegion::FrameInt() const
|
||||
{
|
||||
return fRegion ? fRegion->Frame() : to_clipping_rect(BRect());
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Returns the regions's BRect at the given index.
|
||||
\param index The index (zero based) of the wanted rectangle.
|
||||
\return If the given index is valid, it returns the BRect at that index,
|
||||
otherwise, it returns an invalid BRect.
|
||||
*/
|
||||
BRect
|
||||
BRegion::RectAt(int32 index)
|
||||
{
|
||||
return fRegion ? to_BRect(fRegion->RectAt(index)) : BRect();
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Returns the regions's clipping_rect at the given index.
|
||||
\param index The index (zero based) of the wanted rectangle.
|
||||
\return If the given index is valid, it returns the clipping_rect at that index,
|
||||
otherwise, it returns an invalid clipping_rect.
|
||||
*/
|
||||
clipping_rect
|
||||
BRegion::RectAtInt(int32 index)
|
||||
{
|
||||
return fRegion ? fRegion->RectAt(index) : to_clipping_rect(BRect());
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Counts the region rects.
|
||||
\return An int32 which is the total number of rects in the region.
|
||||
*/
|
||||
int32
|
||||
BRegion::CountRects()
|
||||
{
|
||||
return fRegion ? fRegion->CountRects() : 0;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Set the region to contain just the given BRect.
|
||||
\param newBounds A BRect.
|
||||
*/
|
||||
void
|
||||
BRegion::Set(BRect newBounds)
|
||||
{
|
||||
Set(to_clipping_rect(newBounds));
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Set the region to contain just the given clipping_rect.
|
||||
\param newBounds A clipping_rect.
|
||||
*/
|
||||
void
|
||||
BRegion::Set(clipping_rect newBounds)
|
||||
{
|
||||
if (fRegion)
|
||||
fRegion->Set(newBounds);
|
||||
else
|
||||
fRegion = new (nothrow) ClipRegion(newBounds);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Check if the region has any area in common with the given BRect.
|
||||
\param rect The BRect to check the region against to.
|
||||
\return \ctrue if the region has any area in common with the BRect, \cfalse if not.
|
||||
*/
|
||||
bool
|
||||
BRegion::Intersects(BRect rect) const
|
||||
{
|
||||
return fRegion ? fRegion->Intersects(to_clipping_rect(rect)) : false;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Check if the region has any area in common with the given clipping_rect.
|
||||
\param rect The clipping_rect to check the region against to.
|
||||
\return \ctrue if the region has any area in common with the clipping_rect, \cfalse if not.
|
||||
*/
|
||||
bool
|
||||
BRegion::Intersects(clipping_rect rect) const
|
||||
{
|
||||
return fRegion ? fRegion->Intersects(rect) : false;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Check if the region contains the given BPoint.
|
||||
\param pt The BPoint to be checked.
|
||||
\return \ctrue if the region contains the BPoint, \cfalse if not.
|
||||
*/
|
||||
bool
|
||||
BRegion::Contains(BPoint pt) const
|
||||
{
|
||||
return fRegion ? fRegion->Contains(pt) : false;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Check if the region contains the given coordinates.
|
||||
\param x The \cx coordinate of the point to be checked.
|
||||
\param y The \cy coordinate of the point to be checked.
|
||||
\return \ctrue if the region contains the point, \cfalse if not.
|
||||
*/
|
||||
bool
|
||||
BRegion::Contains(int32 x, int32 y)
|
||||
{
|
||||
if (fRegion == NULL)
|
||||
return false;
|
||||
|
||||
const BPoint pt(x, y);
|
||||
return fRegion->Contains(pt);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Prints the BRegion to stdout.
|
||||
*/
|
||||
void
|
||||
BRegion::PrintToStream() const
|
||||
{
|
||||
if (fRegion == NULL)
|
||||
return;
|
||||
|
||||
Frame().PrintToStream();
|
||||
|
||||
for (int32 c = 0; c < fRegion->CountRects(); c++) {
|
||||
clipping_rect rect = fRegion->RectAt(c);
|
||||
printf("data = BRect(l:%ld.0, t:%ld.0, r:%ld.0, b:%ld.0)\n",
|
||||
rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Offsets all region's rects, and bounds by the given values.
|
||||
\param dh The horizontal offset.
|
||||
\param dv The vertical offset.
|
||||
*/
|
||||
void
|
||||
BRegion::OffsetBy(int32 dh, int32 dv)
|
||||
{
|
||||
if (fRegion != NULL)
|
||||
fRegion->OffsetBy(dh, dv);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Empties the region, so that it doesn't include any rect, and invalidates its bounds.
|
||||
*/
|
||||
void
|
||||
BRegion::MakeEmpty()
|
||||
{
|
||||
clipping_rect invalid = { 0, 0, -1, -1 };
|
||||
Set(invalid);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region, so that it includes the given BRect.
|
||||
\param rect The BRect to be included by the region.
|
||||
*/
|
||||
void
|
||||
BRegion::Include(BRect rect)
|
||||
{
|
||||
Include(to_clipping_rect(rect));
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region, so that it includes the given clipping_rect.
|
||||
\param rect The clipping_rect to be included by the region.
|
||||
*/
|
||||
void
|
||||
BRegion::Include(clipping_rect rect)
|
||||
{
|
||||
if (fRegion != NULL)
|
||||
fRegion->Include(rect);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region, so that it includes the area of the given region.
|
||||
\param region The region to be included.
|
||||
*/
|
||||
void
|
||||
BRegion::Include(const BRegion *region)
|
||||
{
|
||||
if (fRegion != NULL)
|
||||
fRegion->Include(*region->fRegion);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region, excluding the area represented by the given BRect.
|
||||
\param rect The BRect to be excluded.
|
||||
*/
|
||||
void
|
||||
BRegion::Exclude(BRect rect)
|
||||
{
|
||||
if (fRegion)
|
||||
fRegion->Exclude(to_clipping_rect(rect));
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region, excluding the area represented by the given clipping_rect.
|
||||
\param rect The clipping_rect to be excluded.
|
||||
*/
|
||||
void
|
||||
BRegion::Exclude(clipping_rect rect)
|
||||
{
|
||||
if (fRegion)
|
||||
fRegion->Exclude(rect);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region, excluding the area contained in the given BRegion.
|
||||
\param region The BRegion to be excluded.
|
||||
*/
|
||||
void
|
||||
BRegion::Exclude(const BRegion *region)
|
||||
{
|
||||
if (fRegion)
|
||||
fRegion->Exclude(*region->fRegion);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region, so that it will contain just the area in common with the given BRegion.
|
||||
\param region the BRegion to intersect to.
|
||||
*/
|
||||
void
|
||||
BRegion::IntersectWith(const BRegion *region)
|
||||
{
|
||||
if (fRegion)
|
||||
fRegion->IntersectWith(*region->fRegion);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Modifies the region to be a copy of the given BRegion.
|
||||
\param region the BRegion to copy.
|
||||
\return This function always returns \c *this.
|
||||
*/
|
||||
BRegion &
|
||||
BRegion::operator=(const BRegion ®ion)
|
||||
{
|
||||
if (®ion != this) {
|
||||
delete fRegion;
|
||||
fRegion = new (nothrow) ClipRegion(*region.fRegion);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
71
src/tests/kits/interface/NewRegion/Region.h
Normal file
71
src/tests/kits/interface/NewRegion/Region.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*******************************************************************************
|
||||
/
|
||||
/ File: Region.h
|
||||
/
|
||||
/ Description: BRegion represents an area that's composed of individual
|
||||
/ rectangles.
|
||||
/
|
||||
/ Copyright 1992-98, Be Incorporated, All Rights Reserved
|
||||
/
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _REGION_H
|
||||
#define _REGION_H
|
||||
|
||||
#include <BeBuild.h>
|
||||
#include <Rect.h>
|
||||
|
||||
namespace BPrivate {
|
||||
class ServerLink;
|
||||
};
|
||||
|
||||
|
||||
/* Integer rect used to define a cliping rectangle. All bounds are included */
|
||||
/* Moved from DirectWindow.h */
|
||||
typedef struct {
|
||||
int32 left;
|
||||
int32 top;
|
||||
int32 right;
|
||||
int32 bottom;
|
||||
} clipping_rect;
|
||||
|
||||
|
||||
/*----- BRegion class --------------------------------------------*/
|
||||
class ClipRegion;
|
||||
class BRegion {
|
||||
public:
|
||||
BRegion();
|
||||
BRegion(const BRegion ®ion);
|
||||
BRegion(const BRect rect);
|
||||
virtual ~BRegion();
|
||||
|
||||
BRegion &operator=(const BRegion &from);
|
||||
|
||||
BRect Frame() const;
|
||||
clipping_rect FrameInt() const;
|
||||
BRect RectAt(int32 index);
|
||||
clipping_rect RectAtInt(int32 index);
|
||||
int32 CountRects();
|
||||
void Set(BRect newBounds);
|
||||
void Set(clipping_rect newBounds);
|
||||
bool Intersects(BRect r) const;
|
||||
bool Intersects(clipping_rect r) const;
|
||||
bool Contains(BPoint pt) const;
|
||||
bool Contains(int32 x, int32 y);
|
||||
void PrintToStream() const;
|
||||
void OffsetBy(int32 dh, int32 dv);
|
||||
void MakeEmpty();
|
||||
void Include(BRect r);
|
||||
void Include(clipping_rect r);
|
||||
void Include(const BRegion*);
|
||||
void Exclude(BRect r);
|
||||
void Exclude(clipping_rect r);
|
||||
void Exclude(const BRegion*);
|
||||
void IntersectWith(const BRegion*);
|
||||
|
||||
/*----- Private or reserved -----------------------------------------*/
|
||||
private:
|
||||
ClipRegion *fRegion;
|
||||
};
|
||||
|
||||
#endif /* _REGION_H */
|
172
src/tests/kits/interface/NewRegion/clipping.h
Normal file
172
src/tests/kits/interface/NewRegion/clipping.h
Normal file
@ -0,0 +1,172 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2004, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: clipping.h
|
||||
// Author: Stefano Ceccherini (burton666@libero.it)
|
||||
// Description: Helper methods to manipulate clipping_rects
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef __CLIPPING_H
|
||||
#define __CLIPPING_H
|
||||
|
||||
#include <Region.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
/* Some methods to manipulate clipping_rects.
|
||||
basically you can do almost everything you do with
|
||||
BRects, just that clipping_rects can only have integer
|
||||
coordinates (a thing that makes these perfect for drawing
|
||||
calculations).
|
||||
*/
|
||||
|
||||
|
||||
// Returns the union of the given rects.
|
||||
static inline clipping_rect
|
||||
union_rect(const clipping_rect &r1, const clipping_rect &r2)
|
||||
{
|
||||
clipping_rect rect;
|
||||
|
||||
rect.left = min_c(r1.left, r2.left);
|
||||
rect.top = min_c(r1.top, r2.top);
|
||||
rect.right = max_c(r1.right, r2.right);
|
||||
rect.bottom = max_c(r1.bottom, r2.bottom);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
// Returns the intersection of the given rects.
|
||||
// The caller should check if the returned rect is valid. If it isn't valid,
|
||||
// then the two rectangles don't intersect.
|
||||
static inline clipping_rect
|
||||
sect_rect(const clipping_rect &r1, const clipping_rect &r2)
|
||||
{
|
||||
clipping_rect rect;
|
||||
|
||||
rect.left = max_c(r1.left, r2.left);
|
||||
rect.top = max_c(r1.top, r2.top);
|
||||
rect.right = min_c(r1.right, r2.right);
|
||||
rect.bottom = min_c(r1.bottom, r2.bottom);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
// Adds the given offsets to the given rect.
|
||||
static inline void
|
||||
offset_rect(clipping_rect &rect, int32 x, int32 y)
|
||||
{
|
||||
rect.left += x;
|
||||
rect.top += y;
|
||||
rect.right += x;
|
||||
rect.bottom += y;
|
||||
}
|
||||
|
||||
|
||||
// Converts the given clipping_rect to a BRect
|
||||
static inline BRect
|
||||
to_BRect(const clipping_rect &rect)
|
||||
{
|
||||
return BRect((float)rect.left, (float)rect.top, (float)rect.right, (float)rect.bottom);
|
||||
}
|
||||
|
||||
|
||||
// Converts the given BRect to a clipping_rect.
|
||||
static inline clipping_rect
|
||||
to_clipping_rect(const BRect &rect)
|
||||
{
|
||||
clipping_rect clipRect;
|
||||
|
||||
clipRect.left = (int32)floor(rect.left);
|
||||
clipRect.top = (int32)floor(rect.top);
|
||||
clipRect.right = (int32)ceil(rect.right);
|
||||
clipRect.bottom = (int32)ceil(rect.bottom);
|
||||
|
||||
return clipRect;
|
||||
}
|
||||
|
||||
|
||||
// Checks if the given point lies in the given rect's area
|
||||
static inline bool
|
||||
point_in(const clipping_rect &rect, int32 px, int32 py)
|
||||
{
|
||||
if (px >= rect.left && px <= rect.right
|
||||
&& py >= rect.top && py <= rect.bottom)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Same as above, but it accepts a BPoint parameter
|
||||
static inline bool
|
||||
point_in(const clipping_rect &rect, const BPoint &pt)
|
||||
{
|
||||
if (pt.x >= rect.left && pt.x <= rect.right
|
||||
&& pt.y >= rect.top && pt.y <= rect.bottom)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Checks if the rect is valid
|
||||
static inline bool
|
||||
valid_rect(const clipping_rect &rect)
|
||||
{
|
||||
if (rect.left <= rect.right && rect.top <= rect.bottom)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Checks if the two rects intersect.
|
||||
static inline bool
|
||||
rects_intersect(const clipping_rect &rectA, const clipping_rect &rectB)
|
||||
{
|
||||
// We behave like BRect::Intersects() does:
|
||||
// we return false if one of the two rects is not valid
|
||||
if (!valid_rect(rectA) || !valid_rect(rectB))
|
||||
return false;
|
||||
|
||||
// TODO: Is there a better algorithm ?
|
||||
// the one we used is faster than
|
||||
// ' return valid_rect(sect_rect(rectA, rectB)); ', though.
|
||||
|
||||
return !(rectA.left > rectB.right || rectA.top > rectB.bottom
|
||||
|| rectA.right < rectB.left || rectA.bottom < rectB.top);
|
||||
}
|
||||
|
||||
|
||||
// Returns the width of the given rect.
|
||||
static inline int32
|
||||
rect_width(const clipping_rect &rect)
|
||||
{
|
||||
return rect.right - rect.left;
|
||||
}
|
||||
|
||||
|
||||
// Returns the height of the given rect.
|
||||
static inline int32
|
||||
rect_height(const clipping_rect &rect)
|
||||
{
|
||||
return rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
#endif // __CLIPPING_H
|
18
src/tests/kits/interface/NewRegion/main.cpp
Normal file
18
src/tests/kits/interface/NewRegion/main.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "clipping.h"
|
||||
#include "Region.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
BRegion region(BRect(10, 10, 20, 20));
|
||||
|
||||
BRegion other(BRect(15, 15, 50, 19));
|
||||
region.IntersectWith(&other);
|
||||
if (region.Intersects(other.Frame()))
|
||||
printf("Okay!\n");
|
||||
|
||||
|
||||
region.PrintToStream();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user