1815c3862SAxel Dörfler/*
233d568aeSStephan Aßmus * Copyright 2001-2009, Haiku Inc. All rights reserved.
333d568aeSStephan Aßmus * Distributed under the terms of the MIT license.
4815c3862SAxel Dörfler *
5815c3862SAxel Dörfler * Authors:
6b955a4caSJohn Scipione *		Stephan A��mus, superstippi@gmx.de
7815c3862SAxel Dörfler *		Marc Flerackers, mflerackers@androme.be
8f668d91bSMarcus Overhagen *		Marcus Overhagen
9815c3862SAxel Dörfler */
10815c3862SAxel Dörfler
11b955a4caSJohn Scipione
12815c3862SAxel Dörfler#include <Polygon.h>
13815c3862SAxel Dörfler
14f668d91bSMarcus Overhagen#include <stdio.h>
15b955a4caSJohn Scipione#include <stdlib.h>
16815c3862SAxel Dörfler#include <string.h>
17815c3862SAxel Dörfler
1833d568aeSStephan Aßmus#include <AffineTransform.h>
1933d568aeSStephan Aßmus
20815c3862SAxel Dörfler
21f668d91bSMarcus Overhagen// Limit to avoid integer overflow when calculating the size to allocate
22f668d91bSMarcus Overhagen#define MAX_POINT_COUNT 10000000
23f668d91bSMarcus Overhagen
24f668d91bSMarcus Overhagen
2533d568aeSStephan AßmusBPolygon::BPolygon(const BPoint* points, int32 count)
26815c3862SAxel Dörfler	:
2733d568aeSStephan Aßmus	fBounds(0.0f, 0.0f, -1.0f, -1.0f),
2833d568aeSStephan Aßmus	fCount(0),
29815c3862SAxel Dörfler	fPoints(NULL)
30815c3862SAxel Dörfler{
3133d568aeSStephan Aßmus	_AddPoints(points, count, true);
3233d568aeSStephan Aßmus}
3333d568aeSStephan Aßmus
3433d568aeSStephan Aßmus
3533d568aeSStephan AßmusBPolygon::BPolygon(const BPolygon& other)
3633d568aeSStephan Aßmus	:
3733d568aeSStephan Aßmus	fBounds(0.0f, 0.0f, -1.0f, -1.0f),
3833d568aeSStephan Aßmus	fCount(0),
3933d568aeSStephan Aßmus	fPoints(NULL)
4033d568aeSStephan Aßmus{
4133d568aeSStephan Aßmus	*this = other;
42815c3862SAxel Dörfler}
43815c3862SAxel Dörfler
44815c3862SAxel Dörfler
4533d568aeSStephan AßmusBPolygon::BPolygon(const BPolygon* other)
46f668d91bSMarcus Overhagen	:
4733d568aeSStephan Aßmus	fBounds(0.0f, 0.0f, -1.0f, -1.0f),
48f668d91bSMarcus Overhagen	fCount(0),
49f668d91bSMarcus Overhagen	fPoints(NULL)
50815c3862SAxel Dörfler{
5133d568aeSStephan Aßmus	*this = *other;
52815c3862SAxel Dörfler}
53815c3862SAxel Dörfler
54815c3862SAxel Dörfler
55815c3862SAxel DörflerBPolygon::BPolygon()
56815c3862SAxel Dörfler	:
5733d568aeSStephan Aßmus	fBounds(0.0f, 0.0f, -1.0f, -1.0f),
58815c3862SAxel Dörfler	fCount(0),
59815c3862SAxel Dörfler	fPoints(NULL)
60815c3862SAxel Dörfler{
61815c3862SAxel Dörfler}
62815c3862SAxel Dörfler
63815c3862SAxel Dörfler
64815c3862SAxel DörflerBPolygon::~BPolygon()
65815c3862SAxel Dörfler{
66815c3862SAxel Dörfler	free(fPoints);
67815c3862SAxel Dörfler}
68815c3862SAxel Dörfler
69815c3862SAxel Dörfler
7033d568aeSStephan AßmusBPolygon&
7133d568aeSStephan AßmusBPolygon::operator=(const BPolygon& other)
72815c3862SAxel Dörfler{
73815c3862SAxel Dörfler	// Make sure we aren't trying to perform a "self assignment".
7433d568aeSStephan Aßmus	if (this == &other)
7533d568aeSStephan Aßmus		return *this;
7633d568aeSStephan Aßmus
7733d568aeSStephan Aßmus	free(fPoints);
7833d568aeSStephan Aßmus	fPoints = NULL;
7933d568aeSStephan Aßmus	fCount = 0;
8033d568aeSStephan Aßmus	fBounds.Set(0.0f, 0.0f, -1.0f, -1.0f);
8133d568aeSStephan Aßmus
8233d568aeSStephan Aßmus	if (_AddPoints(other.fPoints, other.fCount, false))
8333d568aeSStephan Aßmus		fBounds = other.fBounds;
8433d568aeSStephan Aßmus
85815c3862SAxel Dörfler	return *this;
86815c3862SAxel Dörfler}
87815c3862SAxel Dörfler
88815c3862SAxel Dörfler
89815c3862SAxel DörflerBRect
90815c3862SAxel DörflerBPolygon::Frame() const
91815c3862SAxel Dörfler{
92815c3862SAxel Dörfler	return fBounds;
93815c3862SAxel Dörfler}
94815c3862SAxel Dörfler
95815c3862SAxel Dörfler
96815c3862SAxel Dörflervoid
9733d568aeSStephan AßmusBPolygon::AddPoints(const BPoint* points, int32 count)
98815c3862SAxel Dörfler{
9933d568aeSStephan Aßmus	_AddPoints(points, count, true);
100815c3862SAxel Dörfler}
101815c3862SAxel Dörfler
102815c3862SAxel Dörfler
103815c3862SAxel Dörflerint32
104815c3862SAxel DörflerBPolygon::CountPoints() const
105815c3862SAxel Dörfler{
106815c3862SAxel Dörfler	return fCount;
107815c3862SAxel Dörfler}
108815c3862SAxel Dörfler
109815c3862SAxel Dörfler
110815c3862SAxel Dörflervoid
111b955a4caSJohn ScipioneBPolygon::MapTo(BRect source, BRect destination)
112815c3862SAxel Dörfler{
113f668d91bSMarcus Overhagen	for (uint32 i = 0; i < fCount; i++)
114b955a4caSJohn Scipione		_MapPoint(fPoints + i, source, destination);
115b955a4caSJohn Scipione
116b955a4caSJohn Scipione	_MapRectangle(&fBounds, source, destination);
117815c3862SAxel Dörfler}
118815c3862SAxel Dörfler
119815c3862SAxel Dörfler
120815c3862SAxel Dörflervoid
121b955a4caSJohn ScipioneBPolygon::PrintToStream() const
122815c3862SAxel Dörfler{
123f668d91bSMarcus Overhagen	for (uint32 i = 0; i < fCount; i++)
124815c3862SAxel Dörfler		fPoints[i].PrintToStream();
125815c3862SAxel Dörfler}
126815c3862SAxel Dörfler
127815c3862SAxel Dörfler
12833d568aeSStephan Aßmus//void
12933d568aeSStephan Aßmus//BPolygon::TransformBy(const BAffineTransform& transform)
13033d568aeSStephan Aßmus//{
13133d568aeSStephan Aßmus//	transform.Apply(fPoints, (int32)fCount);
13233d568aeSStephan Aßmus//	_ComputeBounds();
13333d568aeSStephan Aßmus//}
13433d568aeSStephan Aßmus//
13533d568aeSStephan Aßmus//
13633d568aeSStephan Aßmus//BPolygon&
13733d568aeSStephan Aßmus//BPolygon::TransformBySelf(const BAffineTransform& transform)
13833d568aeSStephan Aßmus//{
13933d568aeSStephan Aßmus//	TransformBy(transform);
14033d568aeSStephan Aßmus//	return *this;
14133d568aeSStephan Aßmus//}
14233d568aeSStephan Aßmus//
14333d568aeSStephan Aßmus//
14433d568aeSStephan Aßmus//BPolygon
14533d568aeSStephan Aßmus//BPolygon::TransformByCopy(const BAffineTransform& transform) const
14633d568aeSStephan Aßmus//{
14733d568aeSStephan Aßmus//	BPolygon copy(this);
14833d568aeSStephan Aßmus//	copy.TransformBy(transform);
14933d568aeSStephan Aßmus//	return copy;
15033d568aeSStephan Aßmus//}
15133d568aeSStephan Aßmus
15233d568aeSStephan Aßmus
153b955a4caSJohn Scipione// #pragma mark - BPolygon private methods
15433d568aeSStephan Aßmus
15533d568aeSStephan Aßmus
15633d568aeSStephan Aßmusbool
15733d568aeSStephan AßmusBPolygon::_AddPoints(const BPoint* points, int32 count, bool computeBounds)
15833d568aeSStephan Aßmus{
15933d568aeSStephan Aßmus	if (points == NULL || count <= 0)
16033d568aeSStephan Aßmus		return false;
16133d568aeSStephan Aßmus	if (count > MAX_POINT_COUNT || (fCount + count) > MAX_POINT_COUNT) {
1629be774b5SAlex Smith		fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") - too many points"
1639be774b5SAlex Smith			"\n", count);
16433d568aeSStephan Aßmus		return false;
16533d568aeSStephan Aßmus	}
16611c5023aSStephan Aßmus
1673ca2e85bSAugustin Cavalier	BPoint* newPoints = (BPoint*)realloc((void*)fPoints, (fCount + count)
16833d568aeSStephan Aßmus		* sizeof(BPoint));
16933d568aeSStephan Aßmus	if (newPoints == NULL) {
1709be774b5SAlex Smith		fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") out of memory\n",
1719be774b5SAlex Smith			count);
17233d568aeSStephan Aßmus		return false;
17333d568aeSStephan Aßmus	}
17411c5023aSStephan Aßmus
17533d568aeSStephan Aßmus	fPoints = newPoints;
1763ca2e85bSAugustin Cavalier	memcpy((void*)(fPoints + fCount), points, count * sizeof(BPoint));
17733d568aeSStephan Aßmus	fCount += count;
17811c5023aSStephan Aßmus
17933d568aeSStephan Aßmus	if (computeBounds)
18033d568aeSStephan Aßmus		_ComputeBounds();
18111c5023aSStephan Aßmus
18233d568aeSStephan Aßmus	return true;
18311c5023aSStephan Aßmus}
18411c5023aSStephan Aßmus
18511c5023aSStephan Aßmus
186815c3862SAxel Dörflervoid
187815c3862SAxel DörflerBPolygon::_ComputeBounds()
188815c3862SAxel Dörfler{
189815c3862SAxel Dörfler	if (fCount == 0) {
19033d568aeSStephan Aßmus		fBounds = BRect(0.0, 0.0, -1.0f, -1.0f);
191815c3862SAxel Dörfler		return;
192815c3862SAxel Dörfler	}
193815c3862SAxel Dörfler
194815c3862SAxel Dörfler	fBounds = BRect(fPoints[0], fPoints[0]);
195815c3862SAxel Dörfler
196f668d91bSMarcus Overhagen	for (uint32 i = 1; i < fCount; i++) {
197815c3862SAxel Dörfler		if (fPoints[i].x < fBounds.left)
198815c3862SAxel Dörfler			fBounds.left = fPoints[i].x;
199b955a4caSJohn Scipione
200815c3862SAxel Dörfler		if (fPoints[i].y < fBounds.top)
201815c3862SAxel Dörfler			fBounds.top = fPoints[i].y;
202b955a4caSJohn Scipione
203815c3862SAxel Dörfler		if (fPoints[i].x > fBounds.right)
204815c3862SAxel Dörfler			fBounds.right = fPoints[i].x;
205b955a4caSJohn Scipione
206815c3862SAxel Dörfler		if (fPoints[i].y > fBounds.bottom)
207815c3862SAxel Dörfler			fBounds.bottom = fPoints[i].y;
208815c3862SAxel Dörfler	}
209815c3862SAxel Dörfler}
210815c3862SAxel Dörfler
211815c3862SAxel Dörfler
212815c3862SAxel Dörflervoid
213b955a4caSJohn ScipioneBPolygon::_MapPoint(BPoint* point, const BRect& source,
214b955a4caSJohn Scipione	const BRect& destination)
215815c3862SAxel Dörfler{
216b955a4caSJohn Scipione	point->x = (point->x - source.left) * destination.Width() / source.Width()
217b955a4caSJohn Scipione		+ destination.left;
218b955a4caSJohn Scipione	point->y = (point->y - source.top) * destination.Height() / source.Height()
219b955a4caSJohn Scipione		+ destination.top;
220815c3862SAxel Dörfler}
221815c3862SAxel Dörfler
222815c3862SAxel Dörfler
223815c3862SAxel Dörflervoid
224b955a4caSJohn ScipioneBPolygon::_MapRectangle(BRect* rect, const BRect& source,
225b955a4caSJohn Scipione	const BRect& destination)
226815c3862SAxel Dörfler{
227815c3862SAxel Dörfler	BPoint leftTop = rect->LeftTop();
228815c3862SAxel Dörfler	BPoint bottomRight = rect->RightBottom();
229815c3862SAxel Dörfler
230b955a4caSJohn Scipione	_MapPoint(&leftTop, source, destination);
231b955a4caSJohn Scipione	_MapPoint(&bottomRight, source, destination);
232815c3862SAxel Dörfler
233815c3862SAxel Dörfler	*rect = BRect(leftTop, bottomRight);
234815c3862SAxel Dörfler}
235