/*
* Copyright 2001-2009, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT license.
*
* Authors:
* Stephan Aßmus, superstippi@gmx.de
* Marc Flerackers, mflerackers@androme.be
* Marcus Overhagen
*/
#include <Polygon.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <AffineTransform.h>
// Limit to avoid integer overflow when calculating the size to allocate
#define MAX_POINT_COUNT 10000000
BPolygon::BPolygon(const BPoint* points, int32 count)
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
_AddPoints(points, count, true);
}
BPolygon::BPolygon(const BPolygon& other)
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
*this = other;
}
BPolygon::BPolygon(const BPolygon* other)
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
*this = *other;
}
BPolygon::BPolygon()
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
}
BPolygon::~BPolygon()
{
free(fPoints);
}
BPolygon&
BPolygon::operator=(const BPolygon& other)
{
// Make sure we aren't trying to perform a "self assignment".
if (this == &other)
return *this;
free(fPoints);
fPoints = NULL;
fCount = 0;
fBounds.Set(0.0f, 0.0f, -1.0f, -1.0f);
if (_AddPoints(other.fPoints, other.fCount, false))
fBounds = other.fBounds;
return *this;
}
BRect
BPolygon::Frame() const
{
return fBounds;
}
void
BPolygon::AddPoints(const BPoint* points, int32 count)
{
_AddPoints(points, count, true);
}
int32
BPolygon::CountPoints() const
{
return fCount;
}
void
BPolygon::MapTo(BRect source, BRect destination)
{
for (uint32 i = 0; i < fCount; i++)
_MapPoint(fPoints + i, source, destination);
_MapRectangle(&fBounds, source, destination);
}
void
BPolygon::PrintToStream() const
{
for (uint32 i = 0; i < fCount; i++)
fPoints[i].PrintToStream();
}
//void
//BPolygon::TransformBy(const BAffineTransform& transform)
//{
// transform.Apply(fPoints, (int32)fCount);
// _ComputeBounds();
//}
//
//
//BPolygon&
//BPolygon::TransformBySelf(const BAffineTransform& transform)
//{
// TransformBy(transform);
// return *this;
//}
//
//
//BPolygon
//BPolygon::TransformByCopy(const BAffineTransform& transform) const
//{
// BPolygon copy(this);
// copy.TransformBy(transform);
// return copy;
//}
// #pragma mark - BPolygon private methods
bool
BPolygon::_AddPoints(const BPoint* points, int32 count, bool computeBounds)
{
if (points == NULL || count <= 0)
return false;
if (count > MAX_POINT_COUNT || (fCount + count) > MAX_POINT_COUNT) {
fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") - too many points"
"\n", count);
return false;
}
BPoint* newPoints = (BPoint*)realloc((void*)fPoints, (fCount + count)
* sizeof(BPoint));
if (newPoints == NULL) {
fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") out of memory\n",
count);
return false;
}
fPoints = newPoints;
memcpy((void*)(fPoints + fCount), points, count * sizeof(BPoint));
fCount += count;
if (computeBounds)
_ComputeBounds();
return true;
}
void
BPolygon::_ComputeBounds()
{
if (fCount == 0) {
fBounds = BRect(0.0, 0.0, -1.0f, -1.0f);
return;
}
fBounds = BRect(fPoints[0], fPoints[0]);
for (uint32 i = 1; i < fCount; i++) {
if (fPoints[i].x < fBounds.left)
fBounds.left = fPoints[i].x;
if (fPoints[i].y < fBounds.top)
fBounds.top = fPoints[i].y;
if (fPoints[i].x > fBounds.right)
fBounds.right = fPoints[i].x;
if (fPoints[i].y > fBounds.bottom)
fBounds.bottom = fPoints[i].y;
}
}
void
BPolygon::_MapPoint(BPoint* point, const BRect& source,
const BRect& destination)
{
point->x = (point->x - source.left) * destination.Width() / source.Width()
+ destination.left;
point->y = (point->y - source.top) * destination.Height() / source.Height()
+ destination.top;
}
void
BPolygon::_MapRectangle(BRect* rect, const BRect& source,
const BRect& destination)
{
BPoint leftTop = rect->LeftTop();
BPoint bottomRight = rect->RightBottom();
_MapPoint(&leftTop, source, destination);
_MapPoint(&bottomRight, source, destination);
*rect = BRect(leftTop, bottomRight);
}
↑ V630 The 'realloc' function is used to allocate memory for an array of objects which are classes containing constructors.