xref: /trunk/main/basegfx/test/basegfx2d.cxx (revision 131e08e2)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 
25 // MARKER(update_precomp.py): autogen include statement, do not remove
26 #include "precompiled_basegfx.hxx"
27 // autogenerated file with codegen.pl
28 
29 #include "preextstl.h"
30 #include "gtest/gtest.h"
31 #include "postextstl.h"
32 
33 #include <basegfx/matrix/b2dhommatrix.hxx>
34 #include <basegfx/polygon/b2dpolygon.hxx>
35 #include <basegfx/polygon/b2dpolygontools.hxx>
36 #include <basegfx/curve/b2dcubicbezier.hxx>
37 #include <basegfx/curve/b2dbeziertools.hxx>
38 #include <basegfx/polygon/b2dpolypolygontools.hxx>
39 #include <basegfx/polygon/b2dpolygonclipper.hxx>
40 #include <basegfx/polygon/b2dpolypolygon.hxx>
41 #include <basegfx/range/b2dpolyrange.hxx>
42 #include <basegfx/numeric/ftools.hxx>
43 #include <basegfx/color/bcolor.hxx>
44 #include <basegfx/color/bcolortools.hxx>
45 
46 #include <basegfx/tools/debugplotter.hxx>
47 
48 #include <iostream>
49 #include <fstream>
50 
51 using namespace ::basegfx;
52 
53 
54 namespace basegfx2d
55 {
56 
57 class b2dsvgdimpex : public ::testing::Test
58 {
59 protected:
60     ::rtl::OUString aPath0;
61     ::rtl::OUString aPath1;
62     ::rtl::OUString aPath2;
63     ::rtl::OUString aPath3;
64 
65 public:
66     // initialise your test code values here.
SetUp()67     virtual void SetUp()
68     {
69         // simple rectangle
70         aPath0 = ::rtl::OUString::createFromAscii(
71             "M 10 10-10 10-10-10 10-10Z" );
72 
73         // simple bezier polygon
74         aPath1 = ::rtl::OUString::createFromAscii(
75             "m11430 0c-8890 3810 5715 6985 5715 6985 "
76             "0 0-17145-1905-17145-1905 0 0 22860-10160 "
77             "16510 6350-6350 16510-3810-11430-3810-11430z" );
78 
79         // '@' as a bezier polygon
80         aPath2 = ::rtl::OUString::createFromAscii(
81             "m1917 1114c-89-189-233-284-430-284-167 "
82             "0-306 91-419 273-113 182-170 370-170 564 "
83             "0 145 33 259 98 342 65 84 150 126 257 126 "
84             "77 0 154-19 231-57 77-38 147-97 210-176 63"
85             "-79 99-143 109-190 38-199 76-398 114-598z"
86             "m840 1646c-133 73-312 139-537 197-225 57"
87             "-440 86-644 87-483-1-866-132-1150-392-284"
88             "-261-426-619-426-1076 0-292 67-560 200-803 "
89             "133-243 321-433 562-569 241-136 514-204 821"
90             "-204 405 0 739 125 1003 374 264 250 396 550 "
91             "396 899 0 313-88 576-265 787-177 212-386 318"
92             "-627 318-191 0-308-94-352-281-133 187-315 281"
93             "-546 281-172 0-315-67-428-200-113-133-170-301"
94             "-170-505 0-277 90-527 271-751 181-223 394"
95             "-335 640-335 196 0 353 83 470 250 13-68 26"
96             "-136 41-204 96 0 192 0 288 0-74 376-148 752"
97             "-224 1128-21 101-31 183-31 245 0 39 9 70 26 "
98             "93 17 24 39 36 67 36 145 0 279-80 400-240 121"
99             "-160 182-365 182-615 0-288-107-533-322-734"
100             "-215-201-487-301-816-301-395 0-715 124-960 "
101             "373-245 249-368 569-368 958 0 385 119 685 "
102             "357 900 237 216 557 324 958 325 189-1 389-27 "
103             "600-77 211-52 378-110 503-174 27 70 54 140 81 210z" );
104 
105         // first part of 'Hello World' as a line polygon
106         aPath3 = ::rtl::OUString::createFromAscii(
107             "m1598 125h306v2334h-306v-1105h-1293v1105h-305v"
108             "-2334h305v973h1293zm2159 1015 78-44 85 235-91 "
109             "47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102"
110             "-4-97-12-91-19-85-26-40-16-39-18-38-20-36-22-34"
111             "-24-33-26-32-27-30-30-29-31-27-33-25-33-23-36-21"
112             "-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3"
113             "-98 11-94 17-89 24-84 31-79 37-75 22-35 23-34 24"
114             "-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35"
115             "-18 37-17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 "
116             "78 10 37 9 37 9 36 12 35 14 33 15 33 17 32 19 31 "
117             "21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 "
118             "34 18 36 30 74 23 80 17 84 10 89 3 94v78h-1277l6 "
119             "75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 "
120             "23 17 22 19 21 19 20 21 18 21 18 23 16 23 14 24 "
121             "14 26 12 26 11 27 10 28 8 59 13 63 7 67 3 80-3 81"
122             "-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l"
123             "-7-51-11-49-14-46-17-43-21-40-24-38-27-36-31-32"
124             "-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 "
125             "2-46 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32"
126             "-29 34-26 38-23 41-20 44-17 47zm1648-1293h288v"
127             "2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 "
128             "91-4 91 4 85 12 42 8 39 11 39 13 38 14 36 17 35 18 "
129             "34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 23 "
130             "34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100"
131             "-11 95-16 89-24 85-31 80-37 74-21 35-23 35-25 32-26 "
132             "32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17"
133             "-38 14-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9"
134             "-40-10-39-13-37-14-36-17-35-18-34-21-33-22-31-24-30"
135             "-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80"
136             "-24-85-17-89-11-95-3-100 3-101 11-95 17-90 24-85 30"
137             "-79 38-75 21-35 23-35 25-32 26-32 28-30 29-28 30-26 "
138             "31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z" );
139     }
140 
TearDown()141     virtual void TearDown()
142     {
143     }
144 }; // class b2dsvgdimpex
145 
TEST_F(b2dsvgdimpex,impex)146 TEST_F(b2dsvgdimpex,impex)
147 {
148     B2DPolyPolygon aPoly;
149     ::rtl::OUString aExport;
150 
151     ASSERT_TRUE(tools::importFromSvgD( aPoly, aPath0, false, 0 )) << "importing simple rectangle from SVG-D";
152     aExport = tools::exportToSvgD( aPoly, true, true, false );
153     const char* sExportString = "m10 10h-20v-20h20z";
154     ASSERT_TRUE(!aExport.compareToAscii(sExportString) ) << "exporting rectangle to SVG-D";
155     ASSERT_TRUE(tools::importFromSvgD( aPoly, aExport, false, 0 )) << "importing simple rectangle from SVG-D (round-trip";
156     aExport = tools::exportToSvgD( aPoly, true, true, false );
157     ASSERT_TRUE(!aExport.compareToAscii(sExportString)) << "exporting rectangle to SVG-D (round-trip)";
158 
159     ASSERT_TRUE(tools::importFromSvgD( aPoly, aPath1, false, 0 )) << "importing simple bezier polygon from SVG-D";
160     aExport = tools::exportToSvgD( aPoly, true, true, false );
161 
162 	// Adaptions for B2DPolygon bezier change (see #i77162#):
163 	//
164 	// The import/export of aPath1 does not reproduce aExport again. This is
165 	// correct since aPath1 contains a segment with non-used control points
166 	// which gets exported now correctly as 'l' and also a point (#4, index 3)
167 	// with C2 continuity which produces a 's' staement now.
168 	//
169 	// The old SVGexport identified nun-used ControlVectors erraneously as bezier segments
170 	// because the 2nd vector at the start point was used, even when added
171 	// with start point was identical to end point. Exactly for that reason
172 	// i reworked the B2DPolygon to use prev, next control points.
173 	//
174 	// so for correct unit test i add the new exported string here as sExportStringSimpleBezier
175 	// and compare to it.
176 	const char* sExportStringSimpleBezier =
177 		"m11430 0c-8890 3810 5715 6985 5715 6985"
178 		"l-17145-1905c0 0 22860-10160 16510 6350"
179 		"s-3810-11430-3810-11430z";
180 	ASSERT_TRUE(!aExport.compareToAscii(sExportStringSimpleBezier)) << "exporting bezier polygon to SVG-D";
181 
182 	// Adaptions for B2DPolygon bezier change (see #i77162#):
183 	//
184 	// a 2nd good test is that re-importing of aExport has to create the same
185 	// B2DPolPolygon again:
186 	B2DPolyPolygon aReImport;
187     ASSERT_TRUE(tools::importFromSvgD( aReImport, aExport, false, 0)) << "importing simple bezier polygon from SVG-D";
188     ASSERT_TRUE(aReImport == aPoly) << "re-imported polygon needs to be identical";
189 
190     ASSERT_TRUE(tools::importFromSvgD( aPoly, aPath2, false, 0)) << "importing '@' from SVG-D";
191     aExport = tools::exportToSvgD( aPoly, true, true, false );
192 
193 	// Adaptions for B2DPolygon bezier change (see #i77162#):
194 	//
195 	// same here, the corrected export with the corrected B2DPolygon is simply more efficient,
196 	// so i needed to change the compare string. Also adding the re-import comparison below.
197 	const char* sExportString1 =
198 		"m1917 1114c-89-189-233-284-430-284-167 0-306 91-419 273s-170 370-17"
199 		"0 564c0 145 33 259 98 342 65 84 150 126 257 126q115.5 0 231-57s147-97 210-176 99-143 109-190c38-199 76-398 114"
200 		"-598zm840 1646c-133 73-312 139-537 197-225 57-440 86-644 87-483-1-866-132-1150-392-284-261-426-619-426-1076 0-"
201 		"292 67-560 200-803s321-433 562-569 514-204 821-204c405 0 739 125 1003 374 264 250 396 550 396 899 0 313-88 576"
202 		"-265 787q-265.5 318-627 318c-191 0-308-94-352-281-133 187-315 281-546 281-172 0-315-67-428-200s-170-301-170-50"
203 		"5c0-277 90-527 271-751 181-223 394-335 640-335 196 0 353 83 470 250 13-68 26-136 41-204q144 0 288 0c-74 376-14"
204 		"8 752-224 1128-21 101-31 183-31 245 0 39 9 70 26 93 17 24 39 36 67 36 145 0 279-80 400-240s182-365 182-615c0-2"
205 		"88-107-533-322-734s-487-301-816-301c-395 0-715 124-960 373s-368 569-368 958q0 577.5 357 900c237 216 557 324 95"
206 		"8 325 189-1 389-27 600-77 211-52 378-110 503-174q40.5 105 81 210z";
207     ASSERT_TRUE(tools::importFromSvgD( aReImport, aExport, false, 0)) << "re-importing '@' from SVG-D";
208     ASSERT_TRUE(aReImport == aPoly) << "re-imported '@' needs to be identical";
209 
210     ASSERT_TRUE(!aExport.compareToAscii(sExportString1)) << "exporting '@' to SVG-D";
211     ASSERT_TRUE(tools::importFromSvgD( aPoly, aExport, false, 0 )) << "importing '@' from SVG-D (round-trip)";
212     aExport = tools::exportToSvgD( aPoly, true, true, false );
213     ASSERT_TRUE(!aExport.compareToAscii(sExportString1)) << "exporting '@' to SVG-D (round-trip)";
214 
215 
216     ASSERT_TRUE(tools::importFromSvgD( aPoly, aPath3, false, 0 )) << "importing complex polygon from SVG-D";
217     aExport = tools::exportToSvgD( aPoly, true, true, false );
218     const char* sExportString2 =
219         "m1598 125h306v2334h-306v-1105h-1293v1105h-305v-2334h305v973h1293"
220         "zm2159 1015 78-44 85 235-91 47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102-4-97"
221         "-12-91-19-85-26-40-16-39-18-38-20-36-22-34-24-33-26-32-27-30-30-29-31-27-33-25-3"
222         "3-23-36-21-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3-98 11-94 17-89 24-84 3"
223         "1-79 37-75 22-35 23-34 24-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35-18 37-"
224         "17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 78 10 37 9 37 9 36 12 35 14 33 15 33 1"
225         "7 32 19 31 21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 34 18 36 30 74 23 80 "
226         "17 84 10 89 3 94v78h-1277l6 75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 23 1"
227         "7 22 19 21 19 20 21 18 21 18 23 16 23 14 24 14 26 12 26 11 27 10 28 8 59 13 63 7"
228         " 67 3 80-3 81-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l-7-51-11-49-14-46-1"
229         "7-43-21-40-24-38-27-36-31-32-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 2-4"
230         "6 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32-29 34-26 38-23 41-20 44-17 47zm1648"
231         "-1293h288v2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 91-4 91 4 85 12 42 "
232         "8 39 11 39 13 38 14 36 17 35 18 34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 "
233         "23 34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100-11 95-16 89-24 85-31 80-37"
234         " 74-21 35-23 35-25 32-26 32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17-38 1"
235         "4-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9-40-10-39-13-37-14-36-17-35-18-34-2"
236         "1-33-22-31-24-30-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80-24-85-17-89-"
237         "11-95-3-100 3-101 11-95 17-90 24-85 30-79 38-75 21-35 23-35 25-32 26-32 28-30 29"
238         "-28 30-26 31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z";
239     ASSERT_TRUE(!aExport.compareToAscii(sExportString2)) << "exporting complex polygon to SVG-D";
240     ASSERT_TRUE(tools::importFromSvgD( aPoly, aExport, false, 0 )) << "importing complex polygon from SVG-D (round-trip)";
241     aExport = tools::exportToSvgD( aPoly, true, true, false );
242     ASSERT_TRUE(!aExport.compareToAscii(sExportString2)) << "exporting complex polygon to SVG-D (round-trip)";
243 
244     const B2DPolygon aRect(
245         tools::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) ));
246     aExport = tools::exportToSvgD( B2DPolyPolygon(aRect), false, false, false );
247 
248 	const char* sExportStringRect = "M0 0H4000V4000H0Z";
249 	ASSERT_TRUE(!aExport.compareToAscii(sExportStringRect)) << "exporting to rectangle svg-d string";
250 }
251 
252 class b2dpolyrange : public ::testing::Test
253 {
254 public:
SetUp()255     virtual void SetUp()
256     {}
257 
TearDown()258     virtual void TearDown()
259     {}
260 };
261 
TEST_F(b2dpolyrange,check)262 TEST_F(b2dpolyrange, check)
263 {
264     B2DPolyRange aRange;
265     aRange.appendElement(B2DRange(0,0,1,1),ORIENTATION_POSITIVE);
266     aRange.appendElement(B2DRange(2,2,3,3),ORIENTATION_POSITIVE);
267 
268     ASSERT_TRUE(aRange.count() == 2) << "simple poly range - count";
269     ASSERT_TRUE(aRange.getElement(0).head == B2DRange(0,0,1,1)) << "simple poly range - first element";
270     ASSERT_TRUE(aRange.getElement(1).head == B2DRange(2,2,3,3)) << "simple poly range - second element";
271 
272     // B2DPolyRange relies on correctly orientated rects
273     const B2DRange aRect(0,0,1,1);
274     ASSERT_TRUE(tools::getOrientation(tools::createPolygonFromRect(aRect)) == ORIENTATION_POSITIVE ) <<
275         "createPolygonFromRect - correct orientation";
276 }
277 
278 
279 class b2dbeziertools : public ::testing::Test
280 {
281 protected:
282     B2DCubicBezier aHalfCircle; 					// not exactly, but a look-alike
283     B2DCubicBezier aQuarterCircle; 					// not exactly, but a look-alike
284     B2DCubicBezier aLoop; 							// identical endpoints, curve goes back to where it started
285     B2DCubicBezier aStraightLineDistinctEndPoints;	// truly a line
286     B2DCubicBezier aStraightLineDistinctEndPoints2;	// truly a line, with slightly different control points
287     B2DCubicBezier aStraightLineIdenticalEndPoints;	// degenerate case of aLoop
288     B2DCubicBezier aStraightLineIdenticalEndPoints2;// degenerate case of aLoop, with slightly different control points
289     B2DCubicBezier aCrossing;						// curve self-intersects somewhere in the middle
290     B2DCubicBezier aCusp;							// curve has a point of undefined tangency
291 
292 
293 public:
294     // initialise your test code values here.
SetUp()295     virtual void SetUp()
296     {
297         const B2DPoint a00(0.0, 0.0);
298         const B2DPoint a10(1.0, 0.0);
299         const B2DPoint a11(1.0, 1.0);
300         const B2DPoint a01(0.0, 1.0);
301         const B2DPoint middle( 0.5, 0.5 );
302         const B2DPoint quarterDown( 0.25, 0.25 );
303         const B2DPoint quarterUp( 0.75, 0.75 );
304 
305         aHalfCircle 	= B2DCubicBezier(a00, a01, a11, a10);
306 
307 		// The spline control points become
308 		//
309 		// 	(R * cos(A), R * sin(A))
310 		// 	(R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
311 		// 	(R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
312 		// 	(R * cos(B), R * sin(B))
313 		//
314 		// where	h = 4/3 * R * tan ((B-A)/4)
315         //
316         // with R being the radius, A start angle and B end angle (A < B).
317         //
318         // (This calculation courtesy Carl Worth, himself based on
319         // Michael Goldapp and Dokken/Daehlen)
320 
321         // Choosing R=1, A=0, B=pi/2
322         const double h( 4.0/3.0 * tan(M_PI/8.0) );
323         aQuarterCircle 	= B2DCubicBezier(a10 + B2DPoint(1.0,0.0),
324                                          B2DPoint(B2DPoint( 1.0, h ) + B2DPoint(1.0,0.0)),
325                                          B2DPoint(B2DPoint( h, 1.0) + B2DPoint(1.0,0.0)),
326                                          a01 + B2DPoint(1.0,0.0));
327 
328         aCusp 			= B2DCubicBezier(a00 + B2DPoint(2.0,0.0),
329                                          B2DPoint(a11 + B2DPoint(2.0,0.0)),
330                                          B2DPoint(a01 + B2DPoint(2.0,0.0)),
331                                          a10 + B2DPoint(2.0,0.0));
332 
333         aLoop			= B2DCubicBezier(a00 + B2DPoint(3.0,0.0),
334                                          B2DPoint(a01 + B2DPoint(3.0,0.0)),
335                                          B2DPoint(a10 + B2DPoint(3.0,0.0)),
336                                          a00 + B2DPoint(3.0,0.0));
337 
338         aStraightLineDistinctEndPoints  = B2DCubicBezier(a00 + B2DPoint(4.0,0.0),
339                                                          B2DPoint(middle + B2DPoint(4.0,0.0)),
340                                                          B2DPoint(middle + B2DPoint(4.0,0.0)),
341                                                          a11 + B2DPoint(4.0,0.0));
342 
343         aStraightLineDistinctEndPoints2  = B2DCubicBezier(a00 + B2DPoint(5.0,0.0),
344                                                           B2DPoint(quarterDown + B2DPoint(5.0,0.0)),
345                                                           B2DPoint(quarterUp + B2DPoint(5.0,0.0)),
346                                                           a11 + B2DPoint(5.0,0.0));
347 
348         aStraightLineIdenticalEndPoints = B2DCubicBezier(a00 + B2DPoint(6.0,0.0),
349                                                          B2DPoint(a11 + B2DPoint(6.0,0.0)),
350                                                          B2DPoint(a11 + B2DPoint(6.0,0.0)),
351                                                          a00 + B2DPoint(6.0,0.0));
352 
353         aStraightLineIdenticalEndPoints2 = B2DCubicBezier(a00 + B2DPoint(7.0,0.0),
354                                                           B2DPoint(quarterDown + B2DPoint(7.0,0.0)),
355                                                           B2DPoint(quarterUp + B2DPoint(7.0,0.0)),
356                                                           a00 + B2DPoint(7.0,0.0));
357 
358         aCrossing		= B2DCubicBezier(a00 + B2DPoint(8.0,0.0),
359                                          B2DPoint(B2DPoint(2.0,2.0) + B2DPoint(8.0,0.0)),
360                                          B2DPoint(B2DPoint(-1.0,2.0) + B2DPoint(8.0,0.0)),
361                                          a10 + B2DPoint(8.0,0.0));
362 
363         ::std::ofstream output("bez_testcases.gnuplot");
364         DebugPlotter aPlotter( "Original curves",
365                                output );
366 
367         aPlotter.plot( aHalfCircle,
368                        "half circle" );
369         aPlotter.plot( aQuarterCircle,
370                        "quarter circle" );
371         aPlotter.plot( aCusp,
372                        "cusp" );
373         aPlotter.plot( aLoop,
374                        "loop" );
375         aPlotter.plot( aStraightLineDistinctEndPoints,
376                        "straight line 0" );
377         aPlotter.plot( aStraightLineDistinctEndPoints2,
378                        "straight line 1" );
379         aPlotter.plot( aStraightLineIdenticalEndPoints,
380                        "straight line 2" );
381         aPlotter.plot( aStraightLineIdenticalEndPoints2,
382                        "straight line 3" );
383         aPlotter.plot( aCrossing,
384                        "crossing" );
385 
386         // break up a complex bezier (loopy, spiky or self intersecting)
387         // into simple segments (left to right)
388         B2DCubicBezier aSegment = aCrossing;
389 		double fExtremePos(0.0);
390 
391         aPlotter.plot( aSegment, "segment" );
392 		while(aSegment.getMinimumExtremumPosition(fExtremePos))
393 		{
394             aSegment.split(fExtremePos, 0, &aSegment);
395 	        aPlotter.plot( aSegment, "segment" );
396 		}
397     }
398 
TearDown()399     virtual void TearDown()
400     {
401     }
402 }; // class b2dbeziertools
403 
TEST_F(b2dbeziertools,adaptiveByDistance)404 TEST_F(b2dbeziertools, adaptiveByDistance)
405 {
406     ::std::ofstream output("bez_adaptiveByDistance.gnuplot");
407     DebugPlotter aPlotter( "distance-adaptive subdivision",
408                            output );
409 
410     const double fBound( 0.0001 );
411     B2DPolygon result;
412 
413     aHalfCircle.adaptiveSubdivideByDistance(result, fBound);
414     aPlotter.plot(result,
415                   "half circle"); result.clear();
416 
417     aQuarterCircle.adaptiveSubdivideByDistance(result, fBound);
418     aPlotter.plot(result,
419                   "quarter circle"); result.clear();
420 
421     aLoop.adaptiveSubdivideByDistance(result, fBound);
422     aPlotter.plot(result,
423                   "loop"); result.clear();
424 
425     aStraightLineDistinctEndPoints.adaptiveSubdivideByDistance(result, fBound);
426     aPlotter.plot(result,
427                   "straight line 0"); result.clear();
428 
429     aStraightLineDistinctEndPoints2.adaptiveSubdivideByDistance(result, fBound);
430     aPlotter.plot(result,
431                   "straight line 1"); result.clear();
432 
433     aStraightLineIdenticalEndPoints.adaptiveSubdivideByDistance(result, fBound);
434     aPlotter.plot(result,
435                   "straight line 2"); result.clear();
436 
437     aStraightLineIdenticalEndPoints2.adaptiveSubdivideByDistance(result, fBound);
438     aPlotter.plot(result,
439                   "straight line 3"); result.clear();
440 
441     aCrossing.adaptiveSubdivideByDistance(result, fBound);
442     aPlotter.plot(result,
443                   "straight line 4"); result.clear();
444 
445     aCusp.adaptiveSubdivideByDistance(result, fBound);
446     aPlotter.plot(result,
447                   "straight line 5"); result.clear();
448 
449     ASSERT_TRUE( true ) << "adaptiveByDistance";
450 }
451 
TEST_F(b2dbeziertools,adaptiveByAngle)452 TEST_F(b2dbeziertools, adaptiveByAngle)
453 {
454     const double fBound( 5.0 );
455     B2DPolygon result;
456 
457     ::std::ofstream output("bez_adaptiveByAngle.gnuplot");
458     DebugPlotter aPlotter( "angle-adaptive subdivision",
459                            output );
460 
461     aHalfCircle.adaptiveSubdivideByAngle(result, fBound, true);
462     aPlotter.plot(result,
463                   "half circle"); result.clear();
464 
465     aQuarterCircle.adaptiveSubdivideByAngle(result, fBound, true);
466     aPlotter.plot(result,
467                   "quarter cirle"); result.clear();
468 
469     aLoop.adaptiveSubdivideByAngle(result, fBound, true);
470     aPlotter.plot(result,
471                   "loop"); result.clear();
472 
473     aStraightLineDistinctEndPoints.adaptiveSubdivideByAngle(result, fBound, true);
474     aPlotter.plot(result,
475                   "straight line 0"); result.clear();
476 
477     aStraightLineDistinctEndPoints2.adaptiveSubdivideByAngle(result, fBound, true);
478     aPlotter.plot(result,
479                   "straight line 1"); result.clear();
480 
481     aStraightLineIdenticalEndPoints.adaptiveSubdivideByAngle(result, fBound, true);
482     aPlotter.plot(result,
483                   "straight line 2"); result.clear();
484 
485     aStraightLineIdenticalEndPoints2.adaptiveSubdivideByAngle(result, fBound, true);
486     aPlotter.plot(result,
487                   "straight line 3"); result.clear();
488 
489     aCrossing.adaptiveSubdivideByAngle(result, fBound, true);
490     aPlotter.plot(result,
491                   "straight line 4"); result.clear();
492 
493     aCusp.adaptiveSubdivideByAngle(result, fBound, true);
494     aPlotter.plot(result,
495                   "straight line 5"); result.clear();
496 
497     ASSERT_TRUE( true ) << "adaptiveByAngle";
498 }
499 
500 
501 class b2dcubicbezier : public ::testing::Test
502 {
503 public:
504     // initialise your test code values here.
SetUp()505     virtual void SetUp()
506     {
507     }
508 
TearDown()509     virtual void TearDown()
510     {
511     }
512 }; // class b2dcubicbezier
513 
514 
515 class b2dhommatrix : public ::testing::Test
516 {
517 protected:
518     B2DHomMatrix	maIdentity;
519     B2DHomMatrix	maScale;
520     B2DHomMatrix	maTranslate;
521     B2DHomMatrix	maShear;
522     B2DHomMatrix	maAffine;
523     B2DHomMatrix	maPerspective;
524 
525 public:
526     // initialise your test code values here.
SetUp()527     virtual void SetUp()
528     {
529         // setup some test matrices
530         maIdentity.identity(); // force compact layout
531         maIdentity.set(0,0, 1.0);
532         maIdentity.set(0,1, 0.0);
533         maIdentity.set(0,2, 0.0);
534         maIdentity.set(1,0, 0.0);
535         maIdentity.set(1,1, 1.0);
536         maIdentity.set(1,2, 0.0);
537 
538         maScale.identity(); // force compact layout
539         maScale.set(0,0, 2.0);
540         maScale.set(1,1, 20.0);
541 
542         maTranslate.identity(); // force compact layout
543         maTranslate.set(0,2, 20.0);
544         maTranslate.set(1,2, 2.0);
545 
546         maShear.identity(); // force compact layout
547         maShear.set(0,1, 3.0);
548         maShear.set(1,0, 7.0);
549         maShear.set(1,1, 22.0);
550 
551         maAffine.identity(); // force compact layout
552         maAffine.set(0,0, 1.0);
553         maAffine.set(0,1, 2.0);
554         maAffine.set(0,2, 3.0);
555         maAffine.set(1,0, 4.0);
556         maAffine.set(1,1, 5.0);
557         maAffine.set(1,2, 6.0);
558 
559         maPerspective.set(0,0, 1.0);
560         maPerspective.set(0,1, 2.0);
561         maPerspective.set(0,2, 3.0);
562         maPerspective.set(1,0, 4.0);
563         maPerspective.set(1,1, 5.0);
564         maPerspective.set(1,2, 6.0);
565         maPerspective.set(2,0, 7.0);
566         maPerspective.set(2,1, 8.0);
567         maPerspective.set(2,2, 9.0);
568     }
569 
TearDown()570     virtual void TearDown()
571     {
572     }
573 
impFillMatrix(B2DHomMatrix & rSource,double fScaleX,double fScaleY,double fShearX,double fRotate)574     void impFillMatrix(B2DHomMatrix& rSource, double fScaleX, double fScaleY, double fShearX, double fRotate)
575     {
576         // fill rSource with a linear combination of scale, shear and rotate
577         rSource.identity();
578         rSource.scale(fScaleX, fScaleY);
579         rSource.shearX(fShearX);
580         rSource.rotate(fRotate);
581     }
582 
impDecomposeComposeTest(double fScaleX,double fScaleY,double fShearX,double fRotate)583     bool impDecomposeComposeTest(double fScaleX, double fScaleY, double fShearX, double fRotate)
584     {
585         // linear combine matrix with given values
586         B2DHomMatrix aSource;
587         impFillMatrix(aSource, fScaleX, fScaleY, fShearX, fRotate);
588 
589         // decompose that matrix
590         B2DTuple aDScale;
591         B2DTuple aDTrans;
592         double fDRot;
593         double fDShX;
594         bool bWorked = aSource.decompose(aDScale, aDTrans, fDRot, fDShX);
595 
596         // linear combine another matrix with decomposition results
597         B2DHomMatrix aRecombined;
598         impFillMatrix(aRecombined, aDScale.getX(), aDScale.getY(), fDShX, fDRot);
599 
600         // if decomposition worked, matrices need to be the same
601         return bWorked && aSource == aRecombined;
602     }
603 }; // class b2dhommatrix
604 
605 
TEST_F(b2dhommatrix,equal)606 TEST_F(b2dhommatrix, equal)
607 {
608     B2DHomMatrix	aIdentity;
609     B2DHomMatrix	aScale;
610     B2DHomMatrix	aTranslate;
611     B2DHomMatrix	aShear;
612     B2DHomMatrix	aAffine;
613     B2DHomMatrix	aPerspective;
614 
615     // setup some test matrices
616     aIdentity.identity(); // force compact layout
617     aIdentity.set(0,0, 1.0);
618     aIdentity.set(0,1, 0.0);
619     aIdentity.set(0,2, 0.0);
620     aIdentity.set(1,0, 0.0);
621     aIdentity.set(1,1, 1.0);
622     aIdentity.set(1,2, 0.0);
623 
624     aScale.identity(); // force compact layout
625     aScale.set(0,0, 2.0);
626     aScale.set(1,1, 20.0);
627 
628     aTranslate.identity(); // force compact layout
629     aTranslate.set(0,2, 20.0);
630     aTranslate.set(1,2, 2.0);
631 
632     aShear.identity(); // force compact layout
633     aShear.set(0,1, 3.0);
634     aShear.set(1,0, 7.0);
635     aShear.set(1,1, 22.0);
636 
637     aAffine.identity(); // force compact layout
638     aAffine.set(0,0, 1.0);
639     aAffine.set(0,1, 2.0);
640     aAffine.set(0,2, 3.0);
641     aAffine.set(1,0, 4.0);
642     aAffine.set(1,1, 5.0);
643     aAffine.set(1,2, 6.0);
644 
645     aPerspective.set(0,0, 1.0);
646     aPerspective.set(0,1, 2.0);
647     aPerspective.set(0,2, 3.0);
648     aPerspective.set(1,0, 4.0);
649     aPerspective.set(1,1, 5.0);
650     aPerspective.set(1,2, 6.0);
651     aPerspective.set(2,0, 7.0);
652     aPerspective.set(2,1, 8.0);
653     aPerspective.set(2,2, 9.0);
654 
655     ASSERT_TRUE(aIdentity == maIdentity) << "operator==: identity matrix";
656     ASSERT_TRUE(aScale == maScale) << "operator==: scale matrix";
657     ASSERT_TRUE(aTranslate == maTranslate) << "operator==: translate matrix";
658     ASSERT_TRUE(aShear == maShear) << "operator==: shear matrix";
659     ASSERT_TRUE(aAffine == maAffine) << "operator==: affine matrix";
660     ASSERT_TRUE(aPerspective == maPerspective) << "operator==: perspective matrix";
661 }
662 
TEST_F(b2dhommatrix,identity)663 TEST_F(b2dhommatrix, identity)
664 {
665     B2DHomMatrix ident;
666 
667     ASSERT_TRUE(maIdentity == ident) << "identity";
668 }
669 
TEST_F(b2dhommatrix,scale)670 TEST_F(b2dhommatrix, scale)
671 {
672     B2DHomMatrix mat;
673     mat.scale(2.0,20.0);
674     ASSERT_TRUE(maScale == mat) << "scale";
675 }
676 
TEST_F(b2dhommatrix,translate)677 TEST_F(b2dhommatrix, translate)
678 {
679     B2DHomMatrix mat;
680     mat.translate(20.0,2.0);
681     ASSERT_TRUE(maTranslate == mat) << "translate";
682 }
683 
TEST_F(b2dhommatrix,shear)684 TEST_F(b2dhommatrix, shear)
685 {
686     B2DHomMatrix mat;
687     mat.shearX(3.0);
688     mat.shearY(7.0);
689     ASSERT_TRUE(maShear == mat) << "translate";
690 }
691 
TEST_F(b2dhommatrix,multiply)692 TEST_F(b2dhommatrix, multiply)
693 {
694     B2DHomMatrix affineAffineProd;
695 
696     affineAffineProd.set(0,0, 9);
697     affineAffineProd.set(0,1, 12);
698     affineAffineProd.set(0,2, 18);
699     affineAffineProd.set(1,0, 24);
700     affineAffineProd.set(1,1, 33);
701     affineAffineProd.set(1,2, 48);
702 
703     B2DHomMatrix affinePerspectiveProd;
704 
705     affinePerspectiveProd.set(0,0, 30);
706     affinePerspectiveProd.set(0,1, 36);
707     affinePerspectiveProd.set(0,2, 42);
708     affinePerspectiveProd.set(1,0, 66);
709     affinePerspectiveProd.set(1,1, 81);
710     affinePerspectiveProd.set(1,2, 96);
711     affinePerspectiveProd.set(2,0, 7);
712     affinePerspectiveProd.set(2,1, 8);
713     affinePerspectiveProd.set(2,2, 9);
714 
715     B2DHomMatrix perspectiveAffineProd;
716 
717     perspectiveAffineProd.set(0,0, 9);
718     perspectiveAffineProd.set(0,1, 12);
719     perspectiveAffineProd.set(0,2, 18);
720     perspectiveAffineProd.set(1,0, 24);
721     perspectiveAffineProd.set(1,1, 33);
722     perspectiveAffineProd.set(1,2, 48);
723     perspectiveAffineProd.set(2,0, 39);
724     perspectiveAffineProd.set(2,1, 54);
725     perspectiveAffineProd.set(2,2, 78);
726 
727     B2DHomMatrix perspectivePerspectiveProd;
728 
729     perspectivePerspectiveProd.set(0,0, 30);
730     perspectivePerspectiveProd.set(0,1, 36);
731     perspectivePerspectiveProd.set(0,2, 42);
732     perspectivePerspectiveProd.set(1,0, 66);
733     perspectivePerspectiveProd.set(1,1, 81);
734     perspectivePerspectiveProd.set(1,2, 96);
735     perspectivePerspectiveProd.set(2,0, 102);
736     perspectivePerspectiveProd.set(2,1, 126);
737     perspectivePerspectiveProd.set(2,2, 150);
738 
739     B2DHomMatrix temp;
740 
741     temp = maAffine;
742     temp*=maAffine;
743     ASSERT_TRUE(temp == affineAffineProd) << "multiply: both compact";
744 
745     temp = maPerspective;
746     temp*=maAffine;
747     ASSERT_TRUE(temp == affinePerspectiveProd) << "multiply: first compact";
748 
749     temp = maAffine;
750     temp*=maPerspective;
751     ASSERT_TRUE(temp == perspectiveAffineProd) << "multiply: second compact";
752 
753     temp = maPerspective;
754     temp*=maPerspective;
755     ASSERT_TRUE(temp == perspectivePerspectiveProd) << "multiply: none compact";
756 }
757 
758 
TEST_F(b2dhommatrix,decompose)759 TEST_F(b2dhommatrix, decompose)
760 {
761     // test matrix decompositions. Each matrix decomposed and rebuilt
762     // using the decompose result should be the same as before. Test
763     // with all ranges of values. Translations are not tested since these
764     // are just the two rightmost values and uncritical
765     static double fSX(10.0);
766     static double fSY(12.0);
767     static double fR(45.0 * F_PI180);
768     static double fS(15.0 * F_PI180);
769 
770     // check all possible scaling combinations
771     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, 0.0, 0.0)) << "decompose: error test A1";
772     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, 0.0, 0.0)) << "decompose: error test A2";
773     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, 0.0, 0.0)) << "decompose: error test A3";
774     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, 0.0, 0.0)) << "decompose: error test A4";
775 
776     // check all possible scaling combinations with positive rotation
777     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, 0.0, fR)) << "decompose: error test B1";
778     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, 0.0, fR)) << "decompose: error test B2";
779     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, 0.0, fR)) << "decompose: error test B3";
780     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, 0.0, fR)) << "decompose: error test B4";
781 
782     // check all possible scaling combinations with negative rotation
783     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, 0.0, -fR)) << "decompose: error test C1";
784     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, 0.0, -fR)) << "decompose: error test C2";
785     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, 0.0, -fR)) << "decompose: error test C3";
786     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, 0.0, -fR)) << "decompose: error test C4";
787 
788     // check all possible scaling combinations with positive shear
789     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, tan(fS), 0.0)) << "decompose: error test D1";
790     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, tan(fS), 0.0)) << "decompose: error test D2";
791     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, tan(fS), 0.0)) << "decompose: error test D3";
792     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, tan(fS), 0.0)) << "decompose: error test D4";
793 
794     // check all possible scaling combinations with negative shear
795     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, tan(-fS), 0.0)) << "decompose: error test E1";
796     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, tan(-fS), 0.0)) << "decompose: error test E2";
797     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, tan(-fS), 0.0)) << "decompose: error test E3";
798     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, tan(-fS), 0.0)) << "decompose: error test E4";
799 
800     // check all possible scaling combinations with positive rotate and positive shear
801     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, tan(fS), fR)) << "decompose: error test F1";
802     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, tan(fS), fR)) << "decompose: error test F2";
803     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, tan(fS), fR)) << "decompose: error test F3";
804     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, tan(fS), fR)) << "decompose: error test F4";
805 
806     // check all possible scaling combinations with negative rotate and positive shear
807     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, tan(fS), -fR)) << "decompose: error test G1";
808     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, tan(fS), -fR)) << "decompose: error test G2";
809     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, tan(fS), -fR)) << "decompose: error test G3";
810     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, tan(fS), -fR)) << "decompose: error test G4";
811 
812     // check all possible scaling combinations with positive rotate and negative shear
813     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, tan(-fS), fR)) << "decompose: error test H1";
814     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, tan(-fS), fR)) << "decompose: error test H2";
815     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, tan(-fS), fR)) << "decompose: error test H3";
816     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, tan(-fS), fR)) << "decompose: error test H4";
817 
818     // check all possible scaling combinations with negative rotate and negative shear
819     ASSERT_TRUE(impDecomposeComposeTest(fSX, fSY, tan(-fS), -fR)) << "decompose: error test I1";
820     ASSERT_TRUE(impDecomposeComposeTest(-fSX, fSY, tan(-fS), -fR)) << "decompose: error test I2";
821     ASSERT_TRUE(impDecomposeComposeTest(fSX, -fSY, tan(-fS), -fR)) << "decompose: error test I3";
822     ASSERT_TRUE(impDecomposeComposeTest(-fSX, -fSY, tan(-fS), -fR)) << "decompose: error test I4";
823 }
824 
825 
826 class b2dhompoint : public ::testing::Test
827 {
828 public:
829     // initialise your test code values here.
SetUp()830     virtual void SetUp()
831     {
832     }
833 
TearDown()834     virtual void TearDown()
835     {
836     }
837 }; // class b2dhompoint
838 
839 
840 class b2dpoint : public ::testing::Test
841 {
842 public:
843     // initialise your test code values here.
SetUp()844     virtual void SetUp()
845     {
846     }
847 
TearDown()848     virtual void TearDown()
849     {
850     }
851 }; // class b2dpoint
852 
853 
854 class b2dpolygon : public ::testing::Test
855 {
856 public:
857     // initialise your test code values here.
SetUp()858     virtual void SetUp()
859     {
860     }
861 
TearDown()862     virtual void TearDown()
863     {
864     }
865 }; // class b2dpolygon
866 
TEST_F(b2dpolygon,testBasics)867 TEST_F(b2dpolygon, testBasics)
868 {
869     B2DPolygon aPoly;
870 
871     aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3));
872 
873     ASSERT_TRUE(aPoly.getB2DPoint(0) == B2DPoint(3,3)) << "#1 first polygon point wrong";
874     ASSERT_TRUE(aPoly.getPrevControlPoint(0) == B2DPoint(2,2)) << "#1 first control point wrong";
875     ASSERT_TRUE(aPoly.getNextControlPoint(0) == B2DPoint(3,3)) << "#1 second control point wrong";
876     ASSERT_TRUE(aPoly.isNextControlPointUsed(0) == false) << "next control point not used";
877 
878     aPoly.setNextControlPoint(0,B2DPoint(4,4));
879     ASSERT_TRUE(aPoly.getNextControlPoint(0) == B2DPoint(4,4)) << "#1.1 second control point wrong";
880     ASSERT_TRUE(aPoly.isNextControlPointUsed(0) == true) << "next control point used";
881     ASSERT_TRUE(aPoly.areControlPointsUsed() == true) << "areControlPointsUsed() wrong";
882     ASSERT_TRUE(aPoly.getContinuityInPoint(0) == CONTINUITY_C2) << "getContinuityInPoint() wrong";
883 
884     aPoly.resetControlPoints();
885     ASSERT_TRUE(aPoly.getB2DPoint(0) == B2DPoint(3,3)) << "resetControlPoints() did not clear";
886     ASSERT_TRUE(aPoly.getPrevControlPoint(0) == B2DPoint(3,3)) << "resetControlPoints() did not clear";
887     ASSERT_TRUE(aPoly.getNextControlPoint(0) == B2DPoint(3,3)) << "resetControlPoints() did not clear";
888     ASSERT_TRUE(aPoly.areControlPointsUsed() == false) << "areControlPointsUsed() wrong #2";
889 
890     aPoly.clear();
891     aPoly.append(B2DPoint(0,0));
892     aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3));
893 
894     ASSERT_TRUE(aPoly.getB2DPoint(0) == B2DPoint(0,0)) << "#2 first polygon point wrong";
895     ASSERT_TRUE(aPoly.getPrevControlPoint(0) == B2DPoint(0,0)) << "#2 first control point wrong";
896     ASSERT_TRUE(aPoly.getNextControlPoint(0) == B2DPoint(1,1)) << "#2 second control point wrong";
897     ASSERT_TRUE(aPoly.getPrevControlPoint(1) == B2DPoint(2,2)) << "#2 third control point wrong";
898     ASSERT_TRUE(aPoly.getNextControlPoint(1) == B2DPoint(3,3)) << "#2 fourth control point wrong";
899     ASSERT_TRUE(aPoly.getB2DPoint(1) == B2DPoint(3,3)) << "#2 second polygon point wrong";
900 }
901 
902 class b2dpolygontools : public ::testing::Test
903 {
904 public:
905     // initialise your test code values here.
SetUp()906     virtual void SetUp()
907     {
908     }
909 
TearDown()910     virtual void TearDown()
911     {
912     }
913 }; // class b2dpolygontools
914 
TEST_F(b2dpolygontools,testIsRectangle)915 TEST_F(b2dpolygontools, testIsRectangle)
916 {
917     B2DPolygon aRect1(
918         tools::createPolygonFromRect(
919             B2DRange(0,0,1,1) ) );
920 
921     B2DPolygon aRect2;
922     aRect2.append( B2DPoint(0,0) );
923     aRect2.append( B2DPoint(1,0) );
924     aRect2.append( B2DPoint(1,.5));
925     aRect2.append( B2DPoint(1,1) );
926     aRect2.append( B2DPoint(0,1) );
927     aRect2.setClosed(true);
928 
929     B2DPolygon aNonRect1;
930     aNonRect1.append( B2DPoint(0,0) );
931     aNonRect1.append( B2DPoint(1,0) );
932     aNonRect1.append( B2DPoint(1,1) );
933     aNonRect1.append( B2DPoint(0.5,1) );
934     aNonRect1.append( B2DPoint(0.5,0) );
935     aNonRect1.setClosed(true);
936 
937     B2DPolygon aNonRect2;
938     aNonRect2.append( B2DPoint(0,0) );
939     aNonRect2.append( B2DPoint(1,1) );
940     aNonRect2.append( B2DPoint(1,0) );
941     aNonRect2.append( B2DPoint(0,1) );
942     aNonRect2.setClosed(true);
943 
944     B2DPolygon aNonRect3;
945     aNonRect3.append( B2DPoint(0,0) );
946     aNonRect3.append( B2DPoint(1,0) );
947     aNonRect3.append( B2DPoint(1,1) );
948     aNonRect3.setClosed(true);
949 
950     B2DPolygon aNonRect4;
951     aNonRect4.append( B2DPoint(0,0) );
952     aNonRect4.append( B2DPoint(1,0) );
953     aNonRect4.append( B2DPoint(1,1) );
954     aNonRect4.append( B2DPoint(0,1) );
955 
956     B2DPolygon aNonRect5;
957     aNonRect5.append( B2DPoint(0,0) );
958     aNonRect5.append( B2DPoint(1,0) );
959     aNonRect5.append( B2DPoint(1,1) );
960     aNonRect5.append( B2DPoint(0,1) );
961     aNonRect5.setControlPoints(1,B2DPoint(1,0),B2DPoint(-11,0));
962     aNonRect5.setClosed(true);
963 
964     ASSERT_TRUE(tools::isRectangle( aRect1 )) << "checking rectangle-ness of rectangle 1";
965     ASSERT_TRUE(tools::isRectangle( aRect2 )) << "checking rectangle-ness of rectangle 2";
966     ASSERT_TRUE(!tools::isRectangle( aNonRect1 )) << "checking non-rectangle-ness of polygon 1";
967     ASSERT_TRUE(!tools::isRectangle( aNonRect2 )) << "checking non-rectangle-ness of polygon 2";
968     ASSERT_TRUE(!tools::isRectangle( aNonRect3 )) << "checking non-rectangle-ness of polygon 3";
969     ASSERT_TRUE(!tools::isRectangle( aNonRect4 )) << "checking non-rectangle-ness of polygon 4";
970     ASSERT_TRUE(!tools::isRectangle( aNonRect5 )) << "checking non-rectangle-ness of polygon 5";
971 }
972 
973 class b2dpolypolygon : public ::testing::Test
974 {
975 public:
976     // initialise your test code values here.
SetUp()977     virtual void SetUp()
978     {
979     }
980 
TearDown()981     virtual void TearDown()
982     {
983     }
984 }; // class b2dpolypolygon
985 
986 
987 class b2dquadraticbezier : public ::testing::Test
988 {
989 public:
990     // initialise your test code values here.
SetUp()991     virtual void SetUp()
992     {
993     }
994 
TearDown()995     virtual void TearDown()
996     {
997     }
998 }; // class b2dquadraticbezier
999 
1000 
1001 class b2drange : public ::testing::Test
1002 {
1003 public:
1004     // initialise your test code values here.
SetUp()1005     virtual void SetUp()
1006     {
1007     }
1008 
TearDown()1009     virtual void TearDown()
1010     {
1011     }
1012 }; // class b2drange
1013 
1014 
1015 class b2dtuple : public ::testing::Test
1016 {
1017 public:
1018     // initialise your test code values here.
SetUp()1019     virtual void SetUp()
1020     {
1021     }
1022 
TearDown()1023     virtual void TearDown()
1024     {
1025     }
1026 }; // class b2dtuple
1027 
1028 
1029 class b2dvector : public ::testing::Test
1030 {
1031 public:
1032     // initialise your test code values here.
SetUp()1033     virtual void SetUp()
1034     {
1035     }
1036 
TearDown()1037     virtual void TearDown()
1038     {
1039     }
1040 }; // class b2dvector
1041 
1042 class bcolor : public ::testing::Test
1043 {
1044 protected:
1045     BColor maWhite;
1046     BColor maBlack;
1047     BColor maRed;
1048     BColor maGreen;
1049     BColor maBlue;
1050     BColor maYellow;
1051     BColor maMagenta;
1052     BColor maCyan;
1053 
1054 public:
bcolor()1055     bcolor() :
1056         maWhite(1,1,1),
1057         maBlack(0,0,0),
1058         maRed(1,0,0),
1059         maGreen(0,1,0),
1060         maBlue(0,0,1),
1061         maYellow(1,1,0),
1062         maMagenta(1,0,1),
1063         maCyan(0,1,1)
1064     {}
1065 
1066 
1067     // initialise your test code values here.
SetUp()1068     virtual void SetUp()
1069     {
1070     }
1071 
TearDown()1072     virtual void TearDown()
1073     {
1074     }
1075 }; // class bcolor
1076 
TEST_F(bcolor,hslTest)1077 TEST_F(bcolor, hslTest)
1078 {
1079     ASSERT_TRUE(tools::rgb2hsl(maWhite) == BColor(0,0,1)) << "white";
1080     ASSERT_TRUE(tools::rgb2hsl(maBlack) == BColor(0,0,0)) << "black";
1081     ASSERT_TRUE(tools::rgb2hsl(maRed) == BColor(0,1,0.5)) << "red";
1082     ASSERT_TRUE(tools::rgb2hsl(maGreen) == BColor(120,1,0.5)) << "green";
1083     ASSERT_TRUE(tools::rgb2hsl(maBlue) == BColor(240,1,0.5)) << "blue";
1084     ASSERT_TRUE(tools::rgb2hsl(maYellow) == BColor(60,1,0.5)) << "yellow";
1085     ASSERT_TRUE(tools::rgb2hsl(maMagenta) == BColor(300,1,0.5)) << "magenta";
1086     ASSERT_TRUE(tools::rgb2hsl(maCyan) == BColor(180,1,0.5)) << "cyan";
1087     ASSERT_TRUE(tools::rgb2hsl(BColor(0,0.5,1)) == BColor(210,1,0.5)) << "third hue case";
1088 
1089     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maWhite)) == maWhite) << "roundtrip white";
1090     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maBlack)) == maBlack) << "roundtrip black";
1091     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maRed)) == maRed) << "roundtrip red";
1092     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maGreen)) == maGreen) << "roundtrip green";
1093     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maBlue)) == maBlue) << "roundtrip blue";
1094     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maYellow)) == maYellow) << "roundtrip yellow";
1095     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maMagenta)) == maMagenta) << "roundtrip magenta";
1096     ASSERT_TRUE(tools::hsl2rgb(tools::rgb2hsl(maCyan)) == maCyan) << "roundtrip cyan";
1097 
1098     ASSERT_TRUE(tools::rgb2hsl(maWhite*.1) == BColor(0,0,.1)) << "grey10";
1099     ASSERT_TRUE(tools::rgb2hsl(maWhite*.9) == BColor(0,0,.9)) << "grey90";
1100     ASSERT_TRUE(tools::rgb2hsl(maRed*.5) == BColor(0,1,0.25)) << "red/2";
1101     ASSERT_TRUE(tools::rgb2hsl(maGreen*.5) == BColor(120,1,0.25)) << "green/2";
1102     ASSERT_TRUE(tools::rgb2hsl(maBlue*.5) == BColor(240,1,0.25)) << "blue/2";
1103     ASSERT_TRUE(tools::rgb2hsl(maYellow*.5) == BColor(60,1,0.25)) << "yellow/2";
1104     ASSERT_TRUE(tools::rgb2hsl(maMagenta*.5) == BColor(300,1,0.25)) << "magenta/2";
1105     ASSERT_TRUE(tools::rgb2hsl(maCyan*.5) == BColor(180,1,0.25)) << "cyan/2";
1106 
1107     ASSERT_TRUE(tools::rgb2hsl(BColor(.75,.25,.25)) == BColor(0,.5,.5)) << "pastel";
1108 }
1109 
TEST_F(bcolor,hsvTest)1110 TEST_F(bcolor, hsvTest)
1111 {
1112     ASSERT_TRUE(tools::rgb2hsv(maWhite) == BColor(0,0,1)) << "white";
1113     ASSERT_TRUE(tools::rgb2hsv(maBlack) == BColor(0,0,0)) << "black";
1114     ASSERT_TRUE(tools::rgb2hsv(maRed) == BColor(0,1,1)) << "red";
1115     ASSERT_TRUE(tools::rgb2hsv(maGreen) == BColor(120,1,1)) << "green";
1116     ASSERT_TRUE(tools::rgb2hsv(maBlue) == BColor(240,1,1)) << "blue";
1117     ASSERT_TRUE(tools::rgb2hsv(maYellow) == BColor(60,1,1)) << "yellow";
1118     ASSERT_TRUE(tools::rgb2hsv(maMagenta) == BColor(300,1,1)) << "magenta";
1119     ASSERT_TRUE(tools::rgb2hsv(maCyan) == BColor(180,1,1)) << "cyan";
1120 
1121     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maWhite)) == maWhite) << "roundtrip white";
1122     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maBlack)) == maBlack) << "roundtrip black";
1123     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maRed)) == maRed) << "roundtrip red";
1124     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maGreen)) == maGreen) << "roundtrip green";
1125     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maBlue)) == maBlue) << "roundtrip blue";
1126     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maYellow)) == maYellow) << "roundtrip yellow";
1127     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maMagenta)) == maMagenta) << "roundtrip magenta";
1128     ASSERT_TRUE(tools::hsv2rgb(tools::rgb2hsv(maCyan)) == maCyan) << "roundtrip cyan";
1129 
1130     ASSERT_TRUE(tools::rgb2hsv(maWhite*.1) == BColor(0,0,.1)) << "grey10";
1131     ASSERT_TRUE(tools::rgb2hsv(maWhite*.9) == BColor(0,0,.9)) << "grey90";
1132     ASSERT_TRUE(tools::rgb2hsv(maRed*.5) == BColor(0,1,0.5)) << "red/2";
1133     ASSERT_TRUE(tools::rgb2hsv(maGreen*.5) == BColor(120,1,0.5)) << "green/2";
1134     ASSERT_TRUE(tools::rgb2hsv(maBlue*.5) == BColor(240,1,0.5)) << "blue/2";
1135     ASSERT_TRUE(tools::rgb2hsv(maYellow*.5) == BColor(60,1,0.5)) << "yellow/2";
1136     ASSERT_TRUE(tools::rgb2hsv(maMagenta*.5) == BColor(300,1,0.5)) << "magenta/2";
1137     ASSERT_TRUE(tools::rgb2hsv(maCyan*.5) == BColor(180,1,0.5)) << "cyan/2";
1138 
1139     ASSERT_TRUE(tools::rgb2hsv(BColor(.5,.25,.25)) == BColor(0,.5,.5)) << "pastel";
1140 }
1141 
TEST_F(bcolor,ciexyzTest)1142 TEST_F(bcolor, ciexyzTest)
1143 {
1144     tools::rgb2ciexyz(maWhite);
1145     tools::rgb2ciexyz(maBlack);
1146     tools::rgb2ciexyz(maRed);
1147     tools::rgb2ciexyz(maGreen);
1148     tools::rgb2ciexyz(maBlue);
1149     tools::rgb2ciexyz(maYellow);
1150     tools::rgb2ciexyz(maMagenta);
1151     tools::rgb2ciexyz(maCyan);
1152 }
1153 
1154 // -----------------------------------------------------------------------------
1155 
1156 } // namespace basegfx2d
1157 
1158