xref: /haiku/src/tests/kits/interface/bregion/RegionTestcase.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 /*
2 	$Id: RegionTestcase.cpp 7533 2004-05-12 06:37:18Z jackburton $
3 
4 	This file implements a base class for all tests of the Haiku
5 	BRegion code.
6 
7 	*/
8 
9 
10 #include "RegionTestcase.h"
11 #include <Region.h>
12 #include <Rect.h>
13 
14 #include <assert.h>
15 #include <math.h>
16 
17 
18 /*
19  *  Method:  RegionTestcase::RegionTestcase()
20  *   Descr:  This is the constructor for this class.
21  */
22 
23 RegionTestcase::RegionTestcase(std::string name) :
24 	TestCase(name)
25 {
26 	const int numRectsPerRegion = 3;
27 
28 	float theRegions[][numRectsPerRegion][4] =
29 		{
30 			{
31 				{10.0, 10.0, 50.0, 50.0},
32 				{25.0, 10.0, 75.0, 40.0},
33 				{70.0, 100.0, 90.0, 120.0}
34 			},
35 			{
36 				{15.0, 15.0, 45.0, 45.0},
37 				{30.0, 15.0, 70.0, 35.0},
38 				{75.0, 105.0, 85.0, 115.0}
39 			},
40 			{
41 				{15.0, 15.0, 55.0, 55.0},
42 				{30.0, 15.0, 80.0, 45.0},
43 				{75.0, 105.0, 95.0, 125.0}
44 			},
45 			{
46 				{210.0, 210.0, 250.0, 250.0},
47 				{225.0, 210.0, 275.0, 240.0},
48 				{270.0, 300.0, 290.0, 320.0}
49 			},
50 			{
51 				{-50.0, -50.0, -10.0, -10.0},
52 				{-75.0, -40.0, -25.0, -10.0},
53 				{-90.0, -120.0, -70.0, -100.0}
54 			},
55 			{
56 				{-50.0, -30.0, 100.0, 120.0},
57 				{-140.0, 120.0, 340.0, 905.0},
58 				{-90.0, -120.0, 90.0, 120.0}
59 			},
60 			{
61 				// A test to see if our BRegion can handle non integers
62 				// rects coordinates (as R5 do)
63 				{10.3, 10.8, 50.2, 50.9},
64 				{25.1, 10.7, 75.8, 40.4},
65 				{70.6, 100.6, 90.1, 120.3}
66 			},
67 			{
68 				{15.0, 25.0, 75.0, 80.0},
69 				{30.0, 15.0, 80.0, 45.0},
70 				{60.0, 20.0, 95.0, 225.0}
71 			},
72 			// These two regions were added to test our implementation
73 			// against the "Pahtz matrix test" (see interface kit
74 			// mailing list archives (April 2004) for more info)
75 			{
76 				{0.0, 50.0, 47.0, 50.0},
77 				{99.0, 50.0, 399.0, 50.0},
78 				{-100.0, -20.0, 100.0, -20.0}
79 			},
80 			{
81 				{0.0, 50.0, 47.0, 50.0},
82 				{100.0, 50.0, 399.0, 50.0},
83 				{-100.0, -20.0, 100.0, -20.0}
84 			}
85 		};
86 
87 	const int numTestRegions = sizeof(theRegions) / sizeof(theRegions[0]);
88 
89 	listOfRegions.AddItem(new BRegion);
90 	for(int regionNum = 0; regionNum < numTestRegions; regionNum++) {
91 		BRegion *tempRegion = new BRegion;
92 		for(int rectNum = 0; rectNum < numRectsPerRegion; rectNum++) {
93 			tempRegion->Include(BRect(theRegions[regionNum][rectNum][0],
94 			                          theRegions[regionNum][rectNum][1],
95 			                          theRegions[regionNum][rectNum][2],
96 			                          theRegions[regionNum][rectNum][3]));
97 		}
98 		listOfRegions.AddItem(tempRegion);
99 	}
100 }
101 
102 
103 /*
104  *  Method:  RegionTestcase::~RegionTestcase()
105  *   Descr:  This is the destructor for this class.
106  */
107 
108 RegionTestcase::~RegionTestcase()
109 {
110 	while(!listOfRegions.IsEmpty()) {
111 		delete static_cast<BRegion *>(listOfRegions.RemoveItem(int32(0)));
112 	}
113 }
114 
115 
116 /*
117  *  Method:  RegionTestcase::GetPointsInRect()
118  *   Descr:  This member function returns an array of BPoints on the edge and
119  *           inside the passed in BRect.  It also returns the number of points
120  *           in the array.
121  */
122 
123 int RegionTestcase::GetPointsInRect(BRect theRect, BPoint **pointArrayPtr)
124 {
125 	*pointArrayPtr = pointArray;
126 	if (!theRect.IsValid()) {
127 		return(0);
128 	}
129 
130 	float xIncrement = (theRect.Width() + 1.0) / (numPointsPerSide - 1);
131 	float yIncrement = (theRect.Height() + 1.0) / (numPointsPerSide - 1);
132 
133 	int numPoints = 0;
134 
135 	for(int i = 0; i < numPointsPerSide; i++) {
136 		float xCoord = theRect.left + (i * xIncrement);
137 		if (i == numPointsPerSide - 1) {
138 			xCoord = theRect.right;
139 		}
140 		for(int j = 0; j < numPointsPerSide; j++) {
141 			float yCoord = theRect.top + (j * yIncrement);
142 			if (j == numPointsPerSide - 1) {
143 				yCoord = theRect.bottom;
144 			}
145 			pointArray[numPoints].Set(floor(xCoord), floor(yCoord));
146 			assert(theRect.Contains(pointArray[numPoints]));
147 			numPoints++;
148 		}
149 	}
150 	return(numPoints);
151 }
152 
153 
154 /*
155  *  Method:  RegionTestcase::CheckFrame()
156  *   Descr:  This member function checks that the BRegion's frame matches
157  *           the regions contents.
158  */
159 
160 void RegionTestcase::CheckFrame(BRegion *theRegion)
161 {
162 	BRect theFrame = theRegion->Frame();
163 	if (theFrame.IsValid()) {
164 		assert(!RegionIsEmpty(theRegion));
165 
166 		BRect testFrame = theRegion->RectAt(0);
167 		assert(theFrame.Contains(testFrame));
168 
169 		for(int i = 1; i < theRegion->CountRects(); i++) {
170 			BRect tempRect = theRegion->RectAt(i);
171 			assert(theFrame.Contains(tempRect));
172 			testFrame = testFrame | tempRect;
173 		}
174 		assert(testFrame == theFrame);
175 	} else {
176 		assert(RegionIsEmpty(theRegion));
177 	}
178 }
179 
180 
181 /*
182  *  Method:  RegionTestcase::RegionsAreEqual()
183  *   Descr:  This member function returns true if the two BRegion's passed
184  *           in are the same, otherwise it returns false.
185  */
186 
187 bool RegionTestcase::RegionsAreEqual(BRegion *regionA, BRegion *regionB)
188 {
189 	bool result = false;
190 
191 	if (regionA->CountRects() == regionB->CountRects()) {
192 		bool gotAMatch = true;
193 		for(int i = 0; i < regionA->CountRects(); i++) {
194 			gotAMatch = false;
195 			for(int j = 0; j < regionB->CountRects(); j++) {
196 				if (regionA->RectAt(i) == regionB->RectAt(j)) {
197 					gotAMatch = true;
198 					break;
199 				}
200 			}
201 			if (!gotAMatch) {
202 				break;
203 			}
204 		}
205 		if (gotAMatch) {
206 			result = true;
207 		}
208 	}
209 
210 	if (!result) {
211 		BRegion tempRegion(*regionA);
212 
213 		tempRegion.Exclude(regionB);
214 		if (RegionIsEmpty(&tempRegion)) {
215 			tempRegion = *regionB;
216 			tempRegion.Exclude(regionA);
217 			if (RegionIsEmpty(&tempRegion)) {
218 				result = true;
219 			}
220 		}
221 	}
222 
223 	if (result) {
224 		assert(regionA->Frame() == regionB->Frame());
225 		if (regionA->CountRects() == 0) {
226 			assert(RegionIsEmpty(regionA));
227 			assert(RegionIsEmpty(regionB));
228 		}
229 	}
230 	return(result);
231 }
232 
233 
234 /*
235  *  Method:  RegionTestcase::RegionsIsEmpty()
236  *   Descr:  This member function returns true if the BRegion passed
237  *           in is an empty region, otherwise it returns false.
238  */
239 
240 bool RegionTestcase::RegionIsEmpty(BRegion *theRegion)
241 {
242 	if (theRegion->CountRects() == 0) {
243 		assert(!theRegion->Frame().IsValid());
244 		return(true);
245 	}
246 	assert(theRegion->Frame().IsValid());
247 	return(false);
248 }
249 
250 
251 /*
252  *  Method:  RegionTestcase::PerformTest()
253  *   Descr:  This member function iterates over the set of BRegion's for
254  *           testing and calls testOneRegion() for each region.  Then it
255  *           calls testTwoRegions() for each pair of regions (including
256  *           when the two regions are the same).
257  */
258 
259 void RegionTestcase::PerformTest(void)
260 {
261 	int numItems = listOfRegions.CountItems();
262 
263 	for(int i = 0; i < numItems; i++) {
264 		BRegion *testRegion = static_cast<BRegion *>(listOfRegions.ItemAt(i));
265 
266 		CheckFrame(testRegion);
267 		testOneRegion(testRegion);
268 	}
269 	for(int i = 0; i < numItems; i++) {
270 		BRegion *testRegionA = static_cast<BRegion *>(listOfRegions.ItemAt(i));
271 
272 		for(int j = 0; j < numItems; j++) {
273 			BRegion *testRegionB = static_cast<BRegion *>(listOfRegions.ItemAt(j));
274 
275 			testTwoRegions(testRegionA, testRegionB);
276 		}
277 	}
278 }
279