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