xref: /haiku/src/kits/interface/Polygon.cpp (revision b028e77473189065f2baefc6f5e10d451cf591e2)
1 /*
2  * Copyright 2001-2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Marc Flerackers, mflerackers@androme.be
7  */
8 
9 
10 #include <Polygon.h>
11 
12 #include <stdlib.h>
13 #include <string.h>
14 
15 
16 BPolygon::BPolygon(const BPoint *ptArray, int32 numPoints)
17 	:
18 	fBounds(0.0, 0.0, 0.0, 0.0),
19 	fCount(numPoints),
20 	fPoints(NULL)
21 {
22 	if (fCount > 0) {
23 		fPoints = (BPoint*)malloc(numPoints * sizeof(BPoint));
24 
25 		// Note the use of memcpy here.  The assumption is that an array of BPoints can
26 		// be copied bit by bit and not use a copy constructor or an assignment
27 		// operator.  This breaks the containment of BPoint but will result in better
28 		// performance.  An example where the memcpy will fail would be if BPoint begins
29 		// to do lazy copying through reference counting.  By copying the bits, we will
30 		// copy reference counting state which will not be relevant at the destination.
31 		// Luckily, BPoint is a very simple class which isn't likely to change much.
32 		//
33 		// Similar use of memcpy appears later in this implementation also.
34 
35 		memcpy(fPoints, ptArray, numPoints * sizeof(BPoint));
36 		_ComputeBounds();
37 	}
38 }
39 
40 
41 BPolygon::BPolygon(const BPolygon *poly)
42 {
43 	*this = *poly;
44 }
45 
46 
47 BPolygon::BPolygon()
48 	:
49 	fBounds(0.0, 0.0, 0.0, 0.0),
50 	fCount(0),
51 	fPoints(NULL)
52 {
53 }
54 
55 
56 BPolygon::~BPolygon()
57 {
58 	free(fPoints);
59 }
60 
61 
62 BPolygon &
63 BPolygon::operator=(const BPolygon &from)
64 {
65 	// Make sure we aren't trying to perform a "self assignment".
66 	if (this != &from) {
67 		fBounds = from.fBounds;
68 		fCount = from.fCount;
69 		if (fCount > 0) {
70 			fPoints = (BPoint*)malloc(fCount * sizeof(BPoint));
71 			memcpy(fPoints, from.fPoints, fCount * sizeof(BPoint));
72 		}
73 	}
74 	return *this;
75 }
76 
77 
78 BRect
79 BPolygon::Frame() const
80 {
81 	return fBounds;
82 }
83 
84 
85 void
86 BPolygon::AddPoints(const BPoint *ptArray, int32 numPoints)
87 {
88 	if (numPoints > 0) {
89 		fPoints = (BPoint*)realloc(fPoints, (fCount + numPoints) * sizeof(BPoint));
90 		memcpy(fPoints + fCount + numPoints, ptArray, numPoints  * sizeof(BPoint));
91 		fCount += numPoints;
92 		_ComputeBounds();
93 	}
94 }
95 
96 
97 int32
98 BPolygon::CountPoints() const
99 {
100 	return fCount;
101 }
102 
103 
104 void
105 BPolygon::MapTo(BRect srcRect, BRect dstRect)
106 {
107 	for (int32 i = 0; i < fCount; i++)
108 		_MapPoint(fPoints + i, srcRect, dstRect);
109 	_MapRectangle(&fBounds, srcRect, dstRect);
110 }
111 
112 
113 void
114 BPolygon::PrintToStream () const
115 {
116 	for (int32 i = 0; i < fCount; i++)
117 		fPoints[i].PrintToStream();
118 }
119 
120 
121 void
122 BPolygon::_ComputeBounds()
123 {
124 	if (fCount == 0) {
125 		fBounds = BRect(0.0, 0.0, 0.0, 0.0);
126 		return;
127 	}
128 
129 	fBounds = BRect(fPoints[0], fPoints[0]);
130 
131 	for (int32 i = 1; i < fCount; i++) {
132 		if (fPoints[i].x < fBounds.left)
133 			fBounds.left = fPoints[i].x;
134 		if (fPoints[i].y < fBounds.top)
135 			fBounds.top = fPoints[i].y;
136 		if (fPoints[i].x > fBounds.right)
137 			fBounds.right = fPoints[i].x;
138 		if (fPoints[i].y > fBounds.bottom)
139 			fBounds.bottom = fPoints[i].y;
140 	}
141 }
142 
143 
144 void
145 BPolygon::_MapPoint(BPoint *point, BRect srcRect, BRect dstRect)
146 {
147 	point->x = (point->x - srcRect.left) * dstRect.Width() / srcRect.Width()
148 		+ dstRect.left;
149 	point->y = (point->y - srcRect.top) * dstRect.Height() / srcRect.Height()
150 		+ dstRect.top;
151 }
152 
153 
154 void
155 BPolygon::_MapRectangle(BRect *rect, BRect srcRect, BRect dstRect)
156 {
157 	BPoint leftTop = rect->LeftTop();
158 	BPoint bottomRight = rect->RightBottom();
159 
160 	_MapPoint(&leftTop, srcRect, dstRect);
161 	_MapPoint(&bottomRight, srcRect, dstRect);
162 
163 	*rect = BRect(leftTop, bottomRight);
164 }
165