Bump version to 5.0-14
[LibreOffice.git] / basegfx / test / basegfx2d.cxx
blobc23159c5df0f53fab41709e0614c212fea9ecb9a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <cppunit/TestAssert.h>
21 #include <cppunit/TestFixture.h>
22 #include <cppunit/extensions/HelperMacros.h>
23 #include <cppunit/plugin/TestPlugIn.h>
25 #include <basegfx/matrix/b2dhommatrix.hxx>
26 #include <basegfx/matrix/b2dhommatrixtools.hxx>
27 #include <basegfx/polygon/b2dpolygon.hxx>
28 #include <basegfx/polygon/b2dpolygontools.hxx>
29 #include <basegfx/curve/b2dcubicbezier.hxx>
30 #include <basegfx/curve/b2dbeziertools.hxx>
31 #include <basegfx/polygon/b2dpolypolygontools.hxx>
32 #include <basegfx/polygon/b2dpolygonclipper.hxx>
33 #include <basegfx/polygon/b2dpolypolygon.hxx>
34 #include <basegfx/polygon/b2dtrapezoid.hxx>
35 #include <basegfx/range/b2irange.hxx>
36 #include <basegfx/range/b2ibox.hxx>
37 #include <basegfx/range/b1drange.hxx>
38 #include <basegfx/range/b1irange.hxx>
39 #include <basegfx/range/b1ibox.hxx>
40 #include <basegfx/range/b2drange.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>
46 #include <basegfx/tools/rectcliptools.hxx>
48 #include <iostream>
49 #include <fstream>
51 #include <boxclipper.hxx>
53 using namespace ::basegfx;
55 namespace basegfx2d
57 class b2dsvgdimpex : public CppUnit::TestFixture
59 private:
60 OUString aPath0;
61 OUString aPath1;
62 OUString aPath2;
63 OUString aPath3;
65 public:
66 // initialise your test code values here.
67 void setUp() SAL_OVERRIDE
69 // simple rectangle
70 aPath0 = "M 10 10-10 10-10-10 10-10Z";
72 // simple bezier polygon
73 aPath1 = "m11430 0c-8890 3810 5715 6985 5715 6985 "
74 "0 0-17145-1905-17145-1905 0 0 22860-10160 "
75 "16510 6350-6350 16510-3810-11430-3810-11430z";
77 // '@' as a bezier polygon
78 aPath2 = "m1917 1114c-89-189-233-284-430-284-167 "
79 "0-306 91-419 273-113 182-170 370-170 564 "
80 "0 145 33 259 98 342 65 84 150 126 257 126 "
81 "77 0 154-19 231-57 77-38 147-97 210-176 63"
82 "-79 99-143 109-190 38-199 76-398 114-598z"
83 "m840 1646c-133 73-312 139-537 197-225 57"
84 "-440 86-644 87-483-1-866-132-1150-392-284"
85 "-261-426-619-426-1076 0-292 67-560 200-803 "
86 "133-243 321-433 562-569 241-136 514-204 821"
87 "-204 405 0 739 125 1003 374 264 250 396 550 "
88 "396 899 0 313-88 576-265 787-177 212-386 318"
89 "-627 318-191 0-308-94-352-281-133 187-315 281"
90 "-546 281-172 0-315-67-428-200-113-133-170-301"
91 "-170-505 0-277 90-527 271-751 181-223 394"
92 "-335 640-335 196 0 353 83 470 250 13-68 26"
93 "-136 41-204 96 0 192 0 288 0-74 376-148 752"
94 "-224 1128-21 101-31 183-31 245 0 39 9 70 26 "
95 "93 17 24 39 36 67 36 145 0 279-80 400-240 121"
96 "-160 182-365 182-615 0-288-107-533-322-734"
97 "-215-201-487-301-816-301-395 0-715 124-960 "
98 "373-245 249-368 569-368 958 0 385 119 685 "
99 "357 900 237 216 557 324 958 325 189-1 389-27 "
100 "600-77 211-52 378-110 503-174 27 70 54 140 81 210z";
102 // first part of 'Hello World' as a line polygon
103 aPath3 = "m1598 125h306v2334h-306v-1105h-1293v1105h-305v"
104 "-2334h305v973h1293zm2159 1015 78-44 85 235-91 "
105 "47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102"
106 "-4-97-12-91-19-85-26-40-16-39-18-38-20-36-22-34"
107 "-24-33-26-32-27-30-30-29-31-27-33-25-33-23-36-21"
108 "-36-19-38-18-40-16-40-26-86-18-91-11-97-4-103 3"
109 "-98 11-94 17-89 24-84 31-79 37-75 22-35 23-34 24"
110 "-33 27-32 28-30 29-28 31-27 31-24 33-22 34-21 35"
111 "-18 37-17 38-14 38-13 41-11 41-8 86-12 91-4 82 4 "
112 "78 10 37 9 37 9 36 12 35 14 33 15 33 17 32 19 31 "
113 "21 30 22 30 25 55 54 26 29 24 31 22 32 21 33 19 "
114 "34 18 36 30 74 23 80 17 84 10 89 3 94v78h-1277l6 "
115 "75 10 70 14 66 19 62 23 57 13 26 14 26 15 25 17 "
116 "23 17 22 19 21 19 20 21 18 21 18 23 16 23 14 24 "
117 "14 26 12 26 11 27 10 28 8 59 13 63 7 67 3 80-3 81"
118 "-9 79-14 80-21 78-26 79-32zm-1049-808-12 53h963l"
119 "-7-51-11-49-14-46-17-43-21-40-24-38-27-36-31-32"
120 "-33-29-35-25-37-22-38-17-40-14-41-9-42-6-44-2-48 "
121 "2-46 6-44 9-42 13-40 17-38 21-36 24-34 28-32 32"
122 "-29 34-26 38-23 41-20 44-17 47zm1648-1293h288v"
123 "2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 "
124 "91-4 91 4 85 12 42 8 39 11 39 13 38 14 36 17 35 18 "
125 "34 20 33 23 31 24 30 26 29 28 28 30 26 32 25 33 23 "
126 "34 21 35 37 75 31 80 24 84 16 90 11 94 3 100-3 100"
127 "-11 95-16 89-24 85-31 80-37 74-21 35-23 35-25 32-26 "
128 "32-28 30-29 28-30 26-31 24-33 22-34 21-35 18-36 17"
129 "-38 14-39 13-39 10-42 9-85 12-91 4-91-4-86-12-41-9"
130 "-40-10-39-13-37-14-36-17-35-18-34-21-33-22-31-24-30"
131 "-26-29-28-28-30-26-32-25-32-23-35-21-35-38-74-30-80"
132 "-24-85-17-89-11-95-3-100 3-101 11-95 17-90 24-85 30"
133 "-79 38-75 21-35 23-35 25-32 26-32 28-30 29-28 30-26 "
134 "31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z";
137 void tearDown() SAL_OVERRIDE
141 void impex()
143 B2DPolyPolygon aPoly;
144 OUString aExport;
146 CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D",
147 tools::importFromSvgD( aPoly, aPath0, false, 0 ));
148 aExport = tools::exportToSvgD( aPoly, true, true, false );
149 const char* sExportString = "m10 10h-20v-20h20z";
150 CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D",
151 aExport.equalsAscii(sExportString) );
152 CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D (round-trip",
153 tools::importFromSvgD( aPoly, aExport, false, 0 ));
154 aExport = tools::exportToSvgD( aPoly, true, true, false );
155 CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D (round-trip)",
156 aExport.equalsAscii(sExportString));
158 CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D",
159 tools::importFromSvgD( aPoly, aPath1, false, 0 ));
160 aExport = tools::exportToSvgD( aPoly, true, true, false );
162 // Adaptions for B2DPolygon bezier change (see #i77162#):
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.
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.
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 CPPUNIT_ASSERT_MESSAGE("exporting bezier polygon to SVG-D", aExport.equalsAscii(sExportStringSimpleBezier));
182 // Adaptions for B2DPolygon bezier change (see #i77162#):
184 // a 2nd good test is that re-importing of aExport has to create the same
185 // B2DPolPolygon again:
186 B2DPolyPolygon aReImport;
187 CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", tools::importFromSvgD( aReImport, aExport, false, 0));
188 CPPUNIT_ASSERT_MESSAGE("re-imported polygon needs to be identical", aReImport == aPoly);
190 CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D", tools::importFromSvgD( aPoly, aPath2, false, NULL));
191 aExport = tools::exportToSvgD( aPoly, true, true, false );
193 // Adaptions for B2DPolygon bezier change (see #i77162#):
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 CPPUNIT_ASSERT_MESSAGE("re-importing '@' from SVG-D", tools::importFromSvgD( aReImport, aExport, false, 0));
208 CPPUNIT_ASSERT_MESSAGE("re-imported '@' needs to be identical", aReImport == aPoly);
210 CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D", aExport.equalsAscii(sExportString1));
211 CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D (round-trip",
212 tools::importFromSvgD( aPoly, aExport, false, 0 ));
213 aExport = tools::exportToSvgD( aPoly, true, true, false );
214 CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D (round-trip)",
215 aExport.equalsAscii(sExportString1));
217 CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D",
218 tools::importFromSvgD( aPoly, aPath3, false, 0 ));
219 aExport = tools::exportToSvgD( aPoly, true, true, false );
220 const char* sExportString2 =
221 "m1598 125h306v2334h-306v-1105h-1293v1105h-305v-2334h305v973h1293"
222 "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"
223 "-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"
224 "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"
225 "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-"
226 "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"
227 "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 "
228 "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"
229 "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"
230 " 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"
231 "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"
232 "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"
233 "-1293h288v2459h-288zm752-2459h288v2459h-288zm1286-1750 86-11 91-4 91 4 85 12 42 "
234 "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 "
235 "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"
236 " 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"
237 "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"
238 "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-"
239 "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"
240 "-28 30-26 31-24 33-22 34-20 35-18 36-16 37-15 39-12 40-11z";
241 CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D",
242 aExport.equalsAscii(sExportString2));
243 CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D (round-trip",
244 tools::importFromSvgD( aPoly, aExport, false, 0 ));
245 aExport = tools::exportToSvgD( aPoly, true, true, false );
246 CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D (round-trip)",
247 aExport.equalsAscii(sExportString2));
249 const B2DPolygon aRect(
250 tools::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) ));
251 aExport = tools::exportToSvgD( B2DPolyPolygon(aRect), false, false, false );
253 const char* sExportStringRect = "M0 0H4000V4000H0Z";
254 CPPUNIT_ASSERT_MESSAGE("exporting to rectangle svg-d string",
255 aExport.equalsAscii(sExportStringRect));
258 // Change the following lines only, if you add, remove or rename
259 // member functions of the current class,
260 // because these macros are need by auto register mechanism.
262 CPPUNIT_TEST_SUITE(b2dsvgdimpex);
263 CPPUNIT_TEST(impex);
264 CPPUNIT_TEST_SUITE_END();
265 }; // class b2dsvgdimpex
267 class b2drange : public CppUnit::TestFixture
269 private:
270 public:
271 void check()
273 CPPUNIT_ASSERT_MESSAGE("simple range rounding from double to integer",
274 fround(B2DRange(1.2, 2.3, 3.5, 4.8)) == B2IRange(1, 2, 4, 5));
277 // Change the following lines only, if you add, remove or rename
278 // member functions of the current class,
279 // because these macros are need by auto register mechanism.
281 CPPUNIT_TEST_SUITE(b2drange);
282 CPPUNIT_TEST(check);
283 CPPUNIT_TEST_SUITE_END();
286 class b2dpolyrange : public CppUnit::TestFixture
288 private:
289 public:
290 void check()
292 B2DPolyRange aRange;
293 aRange.appendElement(B2DRange(0,0,1,1),ORIENTATION_POSITIVE);
294 aRange.appendElement(B2DRange(2,2,3,3),ORIENTATION_POSITIVE);
296 CPPUNIT_ASSERT_MESSAGE("simple poly range - count",
297 aRange.count() == 2);
298 CPPUNIT_ASSERT_MESSAGE("simple poly range - first element",
299 aRange.getElement(0).head == B2DRange(0,0,1,1));
300 CPPUNIT_ASSERT_MESSAGE("simple poly range - second element",
301 aRange.getElement(1).head == B2DRange(2,2,3,3));
303 // B2DPolyRange relies on correctly orientated rects
304 const B2DRange aRect(0,0,1,1);
305 CPPUNIT_ASSERT_MESSAGE("createPolygonFromRect - correct orientation",
306 tools::getOrientation(
307 tools::createPolygonFromRect(aRect)) == ORIENTATION_POSITIVE );
310 // Change the following lines only, if you add, remove or rename
311 // member functions of the current class,
312 // because these macros are need by auto register mechanism.
314 CPPUNIT_TEST_SUITE(b2dpolyrange);
315 CPPUNIT_TEST(check);
316 CPPUNIT_TEST_SUITE_END();
319 class b2dhommatrix : public CppUnit::TestFixture
321 private:
322 B2DHomMatrix maIdentity;
323 B2DHomMatrix maScale;
324 B2DHomMatrix maTranslate;
325 B2DHomMatrix maShear;
326 B2DHomMatrix maAffine;
327 B2DHomMatrix maPerspective;
329 public:
330 // initialise your test code values here.
331 void setUp() SAL_OVERRIDE
333 // setup some test matrices
334 maIdentity.identity(); // force compact layout
335 maIdentity.set(0,0, 1.0);
336 maIdentity.set(0,1, 0.0);
337 maIdentity.set(0,2, 0.0);
338 maIdentity.set(1,0, 0.0);
339 maIdentity.set(1,1, 1.0);
340 maIdentity.set(1,2, 0.0);
342 maScale.identity(); // force compact layout
343 maScale.set(0,0, 2.0);
344 maScale.set(1,1, 20.0);
346 maTranslate.identity(); // force compact layout
347 maTranslate.set(0,2, 20.0);
348 maTranslate.set(1,2, 2.0);
350 maShear.identity(); // force compact layout
351 maShear.set(0,1, 3.0);
352 maShear.set(1,0, 7.0);
353 maShear.set(1,1, 22.0);
355 maAffine.identity(); // force compact layout
356 maAffine.set(0,0, 1.0);
357 maAffine.set(0,1, 2.0);
358 maAffine.set(0,2, 3.0);
359 maAffine.set(1,0, 4.0);
360 maAffine.set(1,1, 5.0);
361 maAffine.set(1,2, 6.0);
363 maPerspective.set(0,0, 1.0);
364 maPerspective.set(0,1, 2.0);
365 maPerspective.set(0,2, 3.0);
366 maPerspective.set(1,0, 4.0);
367 maPerspective.set(1,1, 5.0);
368 maPerspective.set(1,2, 6.0);
369 maPerspective.set(2,0, 7.0);
370 maPerspective.set(2,1, 8.0);
371 maPerspective.set(2,2, 9.0);
374 void tearDown() SAL_OVERRIDE
378 void equal()
380 B2DHomMatrix aIdentity;
381 B2DHomMatrix aScale;
382 B2DHomMatrix aTranslate;
383 B2DHomMatrix aShear;
384 B2DHomMatrix aAffine;
385 B2DHomMatrix aPerspective;
387 // setup some test matrices
388 aIdentity.identity(); // force compact layout
389 aIdentity.set(0,0, 1.0);
390 aIdentity.set(0,1, 0.0);
391 aIdentity.set(0,2, 0.0);
392 aIdentity.set(1,0, 0.0);
393 aIdentity.set(1,1, 1.0);
394 aIdentity.set(1,2, 0.0);
396 aScale.identity(); // force compact layout
397 aScale.set(0,0, 2.0);
398 aScale.set(1,1, 20.0);
400 aTranslate.identity(); // force compact layout
401 aTranslate.set(0,2, 20.0);
402 aTranslate.set(1,2, 2.0);
404 aShear.identity(); // force compact layout
405 aShear.set(0,1, 3.0);
406 aShear.set(1,0, 7.0);
407 aShear.set(1,1, 22.0);
409 aAffine.identity(); // force compact layout
410 aAffine.set(0,0, 1.0);
411 aAffine.set(0,1, 2.0);
412 aAffine.set(0,2, 3.0);
413 aAffine.set(1,0, 4.0);
414 aAffine.set(1,1, 5.0);
415 aAffine.set(1,2, 6.0);
417 aPerspective.set(0,0, 1.0);
418 aPerspective.set(0,1, 2.0);
419 aPerspective.set(0,2, 3.0);
420 aPerspective.set(1,0, 4.0);
421 aPerspective.set(1,1, 5.0);
422 aPerspective.set(1,2, 6.0);
423 aPerspective.set(2,0, 7.0);
424 aPerspective.set(2,1, 8.0);
425 aPerspective.set(2,2, 9.0);
427 CPPUNIT_ASSERT_MESSAGE("operator==: identity matrix", aIdentity == maIdentity);
428 CPPUNIT_ASSERT_MESSAGE("operator==: scale matrix", aScale == maScale);
429 CPPUNIT_ASSERT_MESSAGE("operator==: translate matrix", aTranslate == maTranslate);
430 CPPUNIT_ASSERT_MESSAGE("operator==: shear matrix", aShear == maShear);
431 CPPUNIT_ASSERT_MESSAGE("operator==: affine matrix", aAffine == maAffine);
432 CPPUNIT_ASSERT_MESSAGE("operator==: perspective matrix", aPerspective == maPerspective);
435 void identity()
437 B2DHomMatrix ident;
439 CPPUNIT_ASSERT_MESSAGE("identity", maIdentity == ident);
442 void scale()
444 B2DHomMatrix mat;
445 mat.scale(2.0,20.0);
446 CPPUNIT_ASSERT_MESSAGE("scale", maScale == mat);
449 void rotate()
451 B2DHomMatrix mat;
452 mat.rotate(90*F_PI180);
453 CPPUNIT_ASSERT_MESSAGE("rotate pi/2 yields exact matrix",
454 mat.get(0,0) == 0.0 &&
455 mat.get(0,1) == -1.0 &&
456 mat.get(0,2) == 0.0 &&
457 mat.get(1,0) == 1.0 &&
458 mat.get(1,1) == 0.0 &&
459 mat.get(1,2) == 0.0);
460 mat.rotate(90*F_PI180);
461 CPPUNIT_ASSERT_MESSAGE("rotate pi yields exact matrix",
462 mat.get(0,0) == -1.0 &&
463 mat.get(0,1) == 0.0 &&
464 mat.get(0,2) == 0.0 &&
465 mat.get(1,0) == 0.0 &&
466 mat.get(1,1) == -1.0 &&
467 mat.get(1,2) == 0.0);
468 mat.rotate(90*F_PI180);
469 CPPUNIT_ASSERT_MESSAGE("rotate 3/2 pi yields exact matrix",
470 mat.get(0,0) == 0.0 &&
471 mat.get(0,1) == 1.0 &&
472 mat.get(0,2) == 0.0 &&
473 mat.get(1,0) == -1.0 &&
474 mat.get(1,1) == 0.0 &&
475 mat.get(1,2) == 0.0);
476 mat.rotate(90*F_PI180);
477 CPPUNIT_ASSERT_MESSAGE("rotate 2 pi yields exact matrix",
478 mat.get(0,0) == 1.0 &&
479 mat.get(0,1) == 0.0 &&
480 mat.get(0,2) == 0.0 &&
481 mat.get(1,0) == 0.0 &&
482 mat.get(1,1) == 1.0 &&
483 mat.get(1,2) == 0.0);
486 void translate()
488 B2DHomMatrix mat;
489 mat.translate(20.0,2.0);
490 CPPUNIT_ASSERT_MESSAGE("translate", maTranslate == mat);
493 void shear()
495 B2DHomMatrix mat;
496 mat.shearX(3.0);
497 mat.shearY(7.0);
498 CPPUNIT_ASSERT_MESSAGE("translate", maShear == mat);
501 void multiply()
503 B2DHomMatrix affineAffineProd;
505 affineAffineProd.set(0,0, 9);
506 affineAffineProd.set(0,1, 12);
507 affineAffineProd.set(0,2, 18);
508 affineAffineProd.set(1,0, 24);
509 affineAffineProd.set(1,1, 33);
510 affineAffineProd.set(1,2, 48);
512 B2DHomMatrix affinePerspectiveProd;
514 affinePerspectiveProd.set(0,0, 30);
515 affinePerspectiveProd.set(0,1, 36);
516 affinePerspectiveProd.set(0,2, 42);
517 affinePerspectiveProd.set(1,0, 66);
518 affinePerspectiveProd.set(1,1, 81);
519 affinePerspectiveProd.set(1,2, 96);
520 affinePerspectiveProd.set(2,0, 7);
521 affinePerspectiveProd.set(2,1, 8);
522 affinePerspectiveProd.set(2,2, 9);
524 B2DHomMatrix perspectiveAffineProd;
526 perspectiveAffineProd.set(0,0, 9);
527 perspectiveAffineProd.set(0,1, 12);
528 perspectiveAffineProd.set(0,2, 18);
529 perspectiveAffineProd.set(1,0, 24);
530 perspectiveAffineProd.set(1,1, 33);
531 perspectiveAffineProd.set(1,2, 48);
532 perspectiveAffineProd.set(2,0, 39);
533 perspectiveAffineProd.set(2,1, 54);
534 perspectiveAffineProd.set(2,2, 78);
536 B2DHomMatrix perspectivePerspectiveProd;
538 perspectivePerspectiveProd.set(0,0, 30);
539 perspectivePerspectiveProd.set(0,1, 36);
540 perspectivePerspectiveProd.set(0,2, 42);
541 perspectivePerspectiveProd.set(1,0, 66);
542 perspectivePerspectiveProd.set(1,1, 81);
543 perspectivePerspectiveProd.set(1,2, 96);
544 perspectivePerspectiveProd.set(2,0, 102);
545 perspectivePerspectiveProd.set(2,1, 126);
546 perspectivePerspectiveProd.set(2,2, 150);
548 B2DHomMatrix temp;
550 temp = maAffine;
551 temp*=maAffine;
552 CPPUNIT_ASSERT_MESSAGE("multiply: both compact", temp == affineAffineProd);
554 temp = maPerspective;
555 temp*=maAffine;
556 CPPUNIT_ASSERT_MESSAGE("multiply: first compact", temp == affinePerspectiveProd);
558 temp = maAffine;
559 temp*=maPerspective;
560 CPPUNIT_ASSERT_MESSAGE("multiply: second compact", temp == perspectiveAffineProd);
562 temp = maPerspective;
563 temp*=maPerspective;
564 CPPUNIT_ASSERT_MESSAGE("multiply: none compact", temp == perspectivePerspectiveProd);
567 void impFillMatrix(B2DHomMatrix& rSource, double fScaleX, double fScaleY, double fShearX, double fRotate)
569 // fill rSource with a linear combination of scale, shear and rotate
570 rSource.identity();
571 rSource.scale(fScaleX, fScaleY);
572 rSource.shearX(fShearX);
573 rSource.rotate(fRotate);
576 bool impDecomposeComposeTest(double fScaleX, double fScaleY, double fShearX, double fRotate)
578 // linear combine matrix with given values
579 B2DHomMatrix aSource;
580 impFillMatrix(aSource, fScaleX, fScaleY, fShearX, fRotate);
582 // decompose that matrix
583 B2DTuple aDScale;
584 B2DTuple aDTrans;
585 double fDRot;
586 double fDShX;
587 bool bWorked = aSource.decompose(aDScale, aDTrans, fDRot, fDShX);
589 // linear combine another matrix with decomposition results
590 B2DHomMatrix aRecombined;
591 impFillMatrix(aRecombined, aDScale.getX(), aDScale.getY(), fDShX, fDRot);
593 // if decomposition worked, matrices need to be the same
594 return bWorked && aSource == aRecombined;
597 void decompose()
599 // test matrix decompositions. Each matrix decomposed and rebuilt
600 // using the decompose result should be the same as before. Test
601 // with all ranges of values. Translations are not tested since these
602 // are just the two rightmost values and uncritical
603 static double fSX(10.0);
604 static double fSY(12.0);
605 static double fR(45.0 * F_PI180);
606 static double fS(15.0 * F_PI180);
608 // check all possible scaling combinations
609 CPPUNIT_ASSERT_MESSAGE("decompose: error test A1", impDecomposeComposeTest(fSX, fSY, 0.0, 0.0));
610 CPPUNIT_ASSERT_MESSAGE("decompose: error test A2", impDecomposeComposeTest(-fSX, fSY, 0.0, 0.0));
611 CPPUNIT_ASSERT_MESSAGE("decompose: error test A3", impDecomposeComposeTest(fSX, -fSY, 0.0, 0.0));
612 CPPUNIT_ASSERT_MESSAGE("decompose: error test A4", impDecomposeComposeTest(-fSX, -fSY, 0.0, 0.0));
614 // check all possible scaling combinations with positive rotation
615 CPPUNIT_ASSERT_MESSAGE("decompose: error test B1", impDecomposeComposeTest(fSX, fSY, 0.0, fR));
616 CPPUNIT_ASSERT_MESSAGE("decompose: error test B2", impDecomposeComposeTest(-fSX, fSY, 0.0, fR));
617 CPPUNIT_ASSERT_MESSAGE("decompose: error test B3", impDecomposeComposeTest(fSX, -fSY, 0.0, fR));
618 CPPUNIT_ASSERT_MESSAGE("decompose: error test B4", impDecomposeComposeTest(-fSX, -fSY, 0.0, fR));
620 // check all possible scaling combinations with negative rotation
621 CPPUNIT_ASSERT_MESSAGE("decompose: error test C1", impDecomposeComposeTest(fSX, fSY, 0.0, -fR));
622 CPPUNIT_ASSERT_MESSAGE("decompose: error test C2", impDecomposeComposeTest(-fSX, fSY, 0.0, -fR));
623 CPPUNIT_ASSERT_MESSAGE("decompose: error test C3", impDecomposeComposeTest(fSX, -fSY, 0.0, -fR));
624 CPPUNIT_ASSERT_MESSAGE("decompose: error test C4", impDecomposeComposeTest(-fSX, -fSY, 0.0, -fR));
626 // check all possible scaling combinations with positive shear
627 CPPUNIT_ASSERT_MESSAGE("decompose: error test D1", impDecomposeComposeTest(fSX, fSY, tan(fS), 0.0));
628 CPPUNIT_ASSERT_MESSAGE("decompose: error test D2", impDecomposeComposeTest(-fSX, fSY, tan(fS), 0.0));
629 CPPUNIT_ASSERT_MESSAGE("decompose: error test D3", impDecomposeComposeTest(fSX, -fSY, tan(fS), 0.0));
630 CPPUNIT_ASSERT_MESSAGE("decompose: error test D4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), 0.0));
632 // check all possible scaling combinations with negative shear
633 CPPUNIT_ASSERT_MESSAGE("decompose: error test E1", impDecomposeComposeTest(fSX, fSY, tan(-fS), 0.0));
634 CPPUNIT_ASSERT_MESSAGE("decompose: error test E2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), 0.0));
635 CPPUNIT_ASSERT_MESSAGE("decompose: error test E3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), 0.0));
636 CPPUNIT_ASSERT_MESSAGE("decompose: error test E4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), 0.0));
638 // check all possible scaling combinations with positive rotate and positive shear
639 CPPUNIT_ASSERT_MESSAGE("decompose: error test F1", impDecomposeComposeTest(fSX, fSY, tan(fS), fR));
640 CPPUNIT_ASSERT_MESSAGE("decompose: error test F2", impDecomposeComposeTest(-fSX, fSY, tan(fS), fR));
641 CPPUNIT_ASSERT_MESSAGE("decompose: error test F3", impDecomposeComposeTest(fSX, -fSY, tan(fS), fR));
642 CPPUNIT_ASSERT_MESSAGE("decompose: error test F4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), fR));
644 // check all possible scaling combinations with negative rotate and positive shear
645 CPPUNIT_ASSERT_MESSAGE("decompose: error test G1", impDecomposeComposeTest(fSX, fSY, tan(fS), -fR));
646 CPPUNIT_ASSERT_MESSAGE("decompose: error test G2", impDecomposeComposeTest(-fSX, fSY, tan(fS), -fR));
647 CPPUNIT_ASSERT_MESSAGE("decompose: error test G3", impDecomposeComposeTest(fSX, -fSY, tan(fS), -fR));
648 CPPUNIT_ASSERT_MESSAGE("decompose: error test G4", impDecomposeComposeTest(-fSX, -fSY, tan(fS), -fR));
650 // check all possible scaling combinations with positive rotate and negative shear
651 CPPUNIT_ASSERT_MESSAGE("decompose: error test H1", impDecomposeComposeTest(fSX, fSY, tan(-fS), fR));
652 CPPUNIT_ASSERT_MESSAGE("decompose: error test H2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), fR));
653 CPPUNIT_ASSERT_MESSAGE("decompose: error test H3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), fR));
654 CPPUNIT_ASSERT_MESSAGE("decompose: error test H4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), fR));
656 // check all possible scaling combinations with negative rotate and negative shear
657 CPPUNIT_ASSERT_MESSAGE("decompose: error test I1", impDecomposeComposeTest(fSX, fSY, tan(-fS), -fR));
658 CPPUNIT_ASSERT_MESSAGE("decompose: error test I2", impDecomposeComposeTest(-fSX, fSY, tan(-fS), -fR));
659 CPPUNIT_ASSERT_MESSAGE("decompose: error test I3", impDecomposeComposeTest(fSX, -fSY, tan(-fS), -fR));
660 CPPUNIT_ASSERT_MESSAGE("decompose: error test I4", impDecomposeComposeTest(-fSX, -fSY, tan(-fS), -fR));
662 // cover special case of 180 degree rotation
663 B2DHomMatrix aTest=tools::createScaleShearXRotateTranslateB2DHomMatrix(
664 6425,3938,
666 180*F_PI180,
667 10482,4921);
668 // decompose that matrix
669 B2DTuple aDScale;
670 B2DTuple aDTrans;
671 double fDRot;
672 double fDShX;
673 aTest.decompose(aDScale, aDTrans, fDRot, fDShX);
674 CPPUNIT_ASSERT_MESSAGE("decompose: error test J1", aDScale.getX() == 6425 && aDScale.getY() == 3938);
675 CPPUNIT_ASSERT_MESSAGE("decompose: error test J1", aDTrans.getX() == 10482 && aDTrans.getY() == 4921);
676 CPPUNIT_ASSERT_MESSAGE("decompose: error test J1", fDRot == 180*F_PI180);
679 // Change the following lines only, if you add, remove or rename
680 // member functions of the current class,
681 // because these macros are need by auto register mechanism.
683 CPPUNIT_TEST_SUITE(b2dhommatrix);
684 CPPUNIT_TEST(equal);
685 CPPUNIT_TEST(identity);
686 CPPUNIT_TEST(scale);
687 CPPUNIT_TEST(translate);
688 CPPUNIT_TEST(rotate);
689 CPPUNIT_TEST(shear);
690 CPPUNIT_TEST(multiply);
691 CPPUNIT_TEST(decompose);
692 CPPUNIT_TEST_SUITE_END();
694 }; // class b2dhommatrix
696 class b2dpoint : public CppUnit::TestFixture
698 public:
699 // insert your test code here.
700 // this is only demonstration code
701 void EmptyMethod()
703 // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
706 // Change the following lines only, if you add, remove or rename
707 // member functions of the current class,
708 // because these macros are need by auto register mechanism.
710 CPPUNIT_TEST_SUITE(b2dpoint);
711 CPPUNIT_TEST(EmptyMethod);
712 CPPUNIT_TEST_SUITE_END();
713 }; // class b2dpoint
715 class b2dpolygon : public CppUnit::TestFixture
717 public:
718 // insert your test code here.
719 void testBasics()
721 B2DPolygon aPoly;
723 aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3));
725 CPPUNIT_ASSERT_MESSAGE("#1 first polygon point wrong",
726 aPoly.getB2DPoint(0) == B2DPoint(3,3));
727 CPPUNIT_ASSERT_MESSAGE("#1 first control point wrong",
728 aPoly.getPrevControlPoint(0) == B2DPoint(2,2));
729 CPPUNIT_ASSERT_MESSAGE("#1 second control point wrong",
730 aPoly.getNextControlPoint(0) == B2DPoint(3,3));
731 CPPUNIT_ASSERT_MESSAGE("next control point not used",
732 !aPoly.isNextControlPointUsed(0));
734 aPoly.setNextControlPoint(0,B2DPoint(4,4));
735 CPPUNIT_ASSERT_MESSAGE("#1.1 second control point wrong",
736 aPoly.getNextControlPoint(0) == B2DPoint(4,4));
737 CPPUNIT_ASSERT_MESSAGE("next control point used",
738 aPoly.isNextControlPointUsed(0));
739 CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong",
740 aPoly.areControlPointsUsed());
741 CPPUNIT_ASSERT_MESSAGE("getContinuityInPoint() wrong",
742 aPoly.getContinuityInPoint(0) == CONTINUITY_C2);
744 aPoly.resetControlPoints();
745 CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear",
746 aPoly.getB2DPoint(0) == B2DPoint(3,3));
747 CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear",
748 aPoly.getPrevControlPoint(0) == B2DPoint(3,3));
749 CPPUNIT_ASSERT_MESSAGE("resetControlPoints() did not clear",
750 aPoly.getNextControlPoint(0) == B2DPoint(3,3));
751 CPPUNIT_ASSERT_MESSAGE("areControlPointsUsed() wrong #2",
752 !aPoly.areControlPointsUsed());
754 aPoly.clear();
755 aPoly.append(B2DPoint(0,0));
756 aPoly.appendBezierSegment(B2DPoint(1,1),B2DPoint(2,2),B2DPoint(3,3));
758 CPPUNIT_ASSERT_MESSAGE("#2 first polygon point wrong",
759 aPoly.getB2DPoint(0) == B2DPoint(0,0));
760 CPPUNIT_ASSERT_MESSAGE("#2 first control point wrong",
761 aPoly.getPrevControlPoint(0) == B2DPoint(0,0));
762 CPPUNIT_ASSERT_MESSAGE("#2 second control point wrong",
763 aPoly.getNextControlPoint(0) == B2DPoint(1,1));
764 CPPUNIT_ASSERT_MESSAGE("#2 third control point wrong",
765 aPoly.getPrevControlPoint(1) == B2DPoint(2,2));
766 CPPUNIT_ASSERT_MESSAGE("#2 fourth control point wrong",
767 aPoly.getNextControlPoint(1) == B2DPoint(3,3));
768 CPPUNIT_ASSERT_MESSAGE("#2 second polygon point wrong",
769 aPoly.getB2DPoint(1) == B2DPoint(3,3));
771 // Change the following lines only, if you add, remove or rename
772 // member functions of the current class,
773 // because these macros are need by auto register mechanism.
775 CPPUNIT_TEST_SUITE(b2dpolygon);
776 CPPUNIT_TEST(testBasics);
777 CPPUNIT_TEST_SUITE_END();
778 }; // class b2dpolygon
780 class b2dpolygontools : public CppUnit::TestFixture
782 public:
783 // insert your test code here.
784 // this is only demonstration code
785 void testIsRectangle()
787 B2DPolygon aRect1(
788 tools::createPolygonFromRect(
789 B2DRange(0,0,1,1) ) );
791 B2DPolygon aRect2;
792 aRect2.append( B2DPoint(0,0) );
793 aRect2.append( B2DPoint(1,0) );
794 aRect2.append( B2DPoint(1,.5));
795 aRect2.append( B2DPoint(1,1) );
796 aRect2.append( B2DPoint(0,1) );
797 aRect2.setClosed(true);
799 B2DPolygon aNonRect1;
800 aNonRect1.append( B2DPoint(0,0) );
801 aNonRect1.append( B2DPoint(1,0) );
802 aNonRect1.append( B2DPoint(1,1) );
803 aNonRect1.append( B2DPoint(0.5,1) );
804 aNonRect1.append( B2DPoint(0.5,0) );
805 aNonRect1.setClosed(true);
807 B2DPolygon aNonRect2;
808 aNonRect2.append( B2DPoint(0,0) );
809 aNonRect2.append( B2DPoint(1,1) );
810 aNonRect2.append( B2DPoint(1,0) );
811 aNonRect2.append( B2DPoint(0,1) );
812 aNonRect2.setClosed(true);
814 B2DPolygon aNonRect3;
815 aNonRect3.append( B2DPoint(0,0) );
816 aNonRect3.append( B2DPoint(1,0) );
817 aNonRect3.append( B2DPoint(1,1) );
818 aNonRect3.setClosed(true);
820 B2DPolygon aNonRect4;
821 aNonRect4.append( B2DPoint(0,0) );
822 aNonRect4.append( B2DPoint(1,0) );
823 aNonRect4.append( B2DPoint(1,1) );
824 aNonRect4.append( B2DPoint(0,1) );
826 B2DPolygon aNonRect5;
827 aNonRect5.append( B2DPoint(0,0) );
828 aNonRect5.append( B2DPoint(1,0) );
829 aNonRect5.append( B2DPoint(1,1) );
830 aNonRect5.append( B2DPoint(0,1) );
831 aNonRect5.setControlPoints(1,B2DPoint(1,0),B2DPoint(-11,0));
832 aNonRect5.setClosed(true);
834 CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 1",
835 tools::isRectangle( aRect1 ));
836 CPPUNIT_ASSERT_MESSAGE("checking rectangle-ness of rectangle 2",
837 tools::isRectangle( aRect2 ));
838 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 1",
839 !tools::isRectangle( aNonRect1 ));
840 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 2",
841 !tools::isRectangle( aNonRect2 ));
842 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 3",
843 !tools::isRectangle( aNonRect3 ));
844 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 4",
845 !tools::isRectangle( aNonRect4 ));
846 CPPUNIT_ASSERT_MESSAGE("checking non-rectangle-ness of polygon 5",
847 !tools::isRectangle( aNonRect5 ));
850 // Change the following lines only, if you add, remove or rename
851 // member functions of the current class,
852 // because these macros are need by auto register mechanism.
854 CPPUNIT_TEST_SUITE(b2dpolygontools);
855 CPPUNIT_TEST(testIsRectangle);
856 CPPUNIT_TEST_SUITE_END();
857 }; // class b2dpolygontools
859 class b2dpolypolygon : public CppUnit::TestFixture
861 public:
862 // insert your test code here.
863 void testTrapezoidHelper()
865 B2DPolygon aPolygon;
866 // provoke the PointBlockAllocator to exercise the freeIfLast path
867 for(int i = 0; i < 16 * 10; i++)
869 B2DPoint aPoint(getRandomOrdinal(1000), getRandomOrdinal(1000));
870 aPolygon.append(aPoint);
872 // scatter some duplicate points in to stress things more.
873 for(int i = 0; i < 16 * 10; i++)
875 aPolygon.insert(getRandomOrdinal(aPolygon.count() - 1),
876 aPolygon.getB2DPoint(getRandomOrdinal(aPolygon.count() - 1)));
878 B2DPolygon aPolygonOffset;
879 // duplicate the polygon and offset it slightly.
880 for(size_t i = 0; i < aPolygon.count(); i++)
882 B2DPoint aPoint(aPolygon.getB2DPoint(i));
883 aPoint += B2DPoint(0.5-getRandomOrdinal(1),0.5-getRandomOrdinal(1));
885 B2DPolyPolygon aPolyPolygon;
886 aPolyPolygon.append(aPolygon);
887 aPolyPolygon.append(aPolygonOffset);
888 B2DTrapezoidVector aVector;
889 basegfx::tools::trapezoidSubdivide(aVector, aPolyPolygon);
890 CPPUNIT_ASSERT_MESSAGE("more than zero sub-divided trapezoids",
891 aVector.size() > 0);
894 // Change the following lines only, if you add, remove or rename
895 // member functions of the current class,
896 // because these macros are need by auto register mechanism.
898 CPPUNIT_TEST_SUITE(b2dpolypolygon);
899 CPPUNIT_TEST(testTrapezoidHelper);
900 CPPUNIT_TEST_SUITE_END();
901 }; // class b2dpolypolygon
903 class b1Xrange : public CppUnit::TestFixture
905 public:
906 template<class Type> void implCheck()
908 // test interval axioms
909 // (http://en.wikipedia.org/wiki/Interval_%28mathematics%29)
910 Type aRange;
911 CPPUNIT_ASSERT_MESSAGE("default ctor - empty range", aRange.isEmpty());
912 CPPUNIT_ASSERT_MESSAGE("center - get cop-out value since range is empty", aRange.getCenter()==0);
914 // degenerate interval
915 aRange.expand(1);
916 CPPUNIT_ASSERT_MESSAGE("degenerate range - still, not empty!", !aRange.isEmpty());
917 CPPUNIT_ASSERT_MESSAGE("degenerate range - size of 0", aRange.getRange() == 0);
918 CPPUNIT_ASSERT_MESSAGE("same value as degenerate range - is inside range", aRange.isInside(1));
919 CPPUNIT_ASSERT_MESSAGE("center - must be the single range value", aRange.getCenter()==1);
921 // proper interval
922 aRange.expand(2);
923 CPPUNIT_ASSERT_MESSAGE("proper range - size of 1", aRange.getRange() == 1);
924 CPPUNIT_ASSERT_MESSAGE("smaller value of range - is inside *closed* range", aRange.isInside(1));
925 CPPUNIT_ASSERT_MESSAGE("larger value of range - is inside *closed* range", aRange.isInside(2));
927 // center for proper interval that works for ints, too
928 aRange.expand(3);
929 CPPUNIT_ASSERT_MESSAGE("center - must be half of the range", aRange.getCenter()==2);
931 // check overlap
932 Type aRange2(0,1);
933 CPPUNIT_ASSERT_MESSAGE("range overlapping *includes* upper bound", aRange.overlaps(aRange2));
934 CPPUNIT_ASSERT_MESSAGE("range overlapping *includes* upper bound, but only barely", !aRange.overlapsMore(aRange2));
936 Type aRange3(0,2);
937 CPPUNIT_ASSERT_MESSAGE("range overlapping is fully overlapping now", aRange.overlapsMore(aRange3));
939 // check intersect
940 Type aRange4(3,4);
941 aRange.intersect(aRange4);
942 CPPUNIT_ASSERT_MESSAGE("range intersection is yielding empty range!", !aRange.isEmpty());
944 Type aRange5(5,6);
945 aRange.intersect(aRange5);
946 CPPUNIT_ASSERT_MESSAGE("range intersection is yielding nonempty range!", aRange.isEmpty());
948 // just so that this compiles -
949 Type aRange6( aRange );
950 (void)aRange6;
953 void check()
955 implCheck<B1DRange>();
956 implCheck<B1IRange>();
959 // Change the following lines only, if you add, remove or rename
960 // member functions of the current class,
961 // because these macros are need by auto register mechanism.
963 CPPUNIT_TEST_SUITE(b1Xrange);
964 CPPUNIT_TEST(check);
965 CPPUNIT_TEST_SUITE_END();
966 }; // class b1Xrange
968 class b1ibox : public CppUnit::TestFixture
970 public:
971 void TestBox()
973 // test axioms - markedly different from proper mathematical
974 // intervals (behaviour modelled after how polygon fill
975 // algorithms fill pixels)
976 B1IBox aBox;
977 CPPUNIT_ASSERT_MESSAGE("default ctor - empty range", aBox.isEmpty());
979 // degenerate box
980 aBox.expand(1);
981 CPPUNIT_ASSERT_MESSAGE("degenerate box - still empty!", aBox.isEmpty());
982 CPPUNIT_ASSERT_MESSAGE("degenerate box - size of 0", aBox.getRange() == 0);
983 CPPUNIT_ASSERT_MESSAGE("same value as degenerate box - is outside (since empty)", !aBox.isInside(1));
984 CPPUNIT_ASSERT_MESSAGE("center - get cop-out value since box is empty", aBox.getCenter()==0);
986 // proper box
987 aBox.expand(2);
988 CPPUNIT_ASSERT_MESSAGE("proper box - size of 1", aBox.getRange() == 1);
989 CPPUNIT_ASSERT_MESSAGE("smaller value of box", aBox.isInside(1));
990 CPPUNIT_ASSERT_MESSAGE("larger value of box - must be outside", !aBox.isInside(2));
992 // center for proper box that works for ints, too
993 aBox.expand(4);
994 CPPUNIT_ASSERT_MESSAGE("center - must be center pixel of the box", aBox.getCenter()==2);
996 // check overlap, which is markedly different from Range
997 B1IBox aBox2(0,1);
998 CPPUNIT_ASSERT_MESSAGE("box overlapping *excludes* upper bound", !aBox.overlaps(aBox2));
1000 B1IBox aBox3(0,2);
1001 CPPUNIT_ASSERT_MESSAGE("box overlapping then includes upper bound-1", aBox.overlaps(aBox3));
1003 // check intersect
1004 B1IBox aBox4(4,5);
1005 aBox.intersect(aBox4);
1006 CPPUNIT_ASSERT_MESSAGE("box intersection is yielding nonempty box!", aBox.isEmpty());
1008 B1IBox aBox5(2,5);
1009 aBox5.intersect(aBox4);
1010 CPPUNIT_ASSERT_MESSAGE("box intersection is yielding empty box!", !aBox5.isEmpty());
1012 // just so that this compiles -
1013 B1IBox aBox6( aBox );
1014 (void)aBox6;
1017 // Change the following lines only, if you add, remove or rename
1018 // member functions of the current class,
1019 // because these macros are need by auto register mechanism.
1021 CPPUNIT_TEST_SUITE(b1ibox);
1022 CPPUNIT_TEST(TestBox);
1023 CPPUNIT_TEST_SUITE_END();
1024 }; // class b1ibox
1026 class b2Xrange : public CppUnit::TestFixture
1028 public:
1029 template<class Type> void implCheck()
1031 // cohen sutherland clipping
1032 Type aRange(0,0,10,10);
1034 CPPUNIT_ASSERT_MESSAGE("(0,0) is outside range!",
1035 tools::getCohenSutherlandClipFlags(B2IPoint(0,0),aRange) == 0);
1036 CPPUNIT_ASSERT_MESSAGE("(-1,-1) is inside range!",
1037 tools::getCohenSutherlandClipFlags(B2IPoint(-1,-1),aRange) ==
1038 (tools::RectClipFlags::LEFT|tools::RectClipFlags::TOP));
1039 CPPUNIT_ASSERT_MESSAGE("(10,10) is outside range!",
1040 tools::getCohenSutherlandClipFlags(B2IPoint(10,10),aRange) == 0);
1041 CPPUNIT_ASSERT_MESSAGE("(11,11) is inside range!",
1042 tools::getCohenSutherlandClipFlags(B2IPoint(11,11),aRange) ==
1043 (tools::RectClipFlags::RIGHT|tools::RectClipFlags::BOTTOM));
1045 // just so that this compiles -
1046 Type aRange1( aRange );
1047 (void)aRange1;
1050 void check()
1052 implCheck<B2DRange>();
1053 implCheck<B2IRange>();
1056 // Change the following lines only, if you add, remove or rename
1057 // member functions of the current class,
1058 // because these macros are need by auto register mechanism.
1060 CPPUNIT_TEST_SUITE(b2Xrange);
1061 CPPUNIT_TEST(check);
1062 CPPUNIT_TEST_SUITE_END();
1063 }; // class b2Xrange
1065 class b2ibox : public CppUnit::TestFixture
1067 public:
1068 void TestBox()
1070 // cohen sutherland clipping
1071 B2IBox aBox(0,0,10,10);
1073 CPPUNIT_ASSERT_MESSAGE("(0,0) is outside range!",
1074 tools::getCohenSutherlandClipFlags(B2IPoint(0,0),aBox) == 0);
1075 CPPUNIT_ASSERT_MESSAGE("(-1,-1) is inside range!",
1076 tools::getCohenSutherlandClipFlags(B2IPoint(-1,-1),aBox) ==
1077 (tools::RectClipFlags::LEFT|tools::RectClipFlags::TOP));
1078 CPPUNIT_ASSERT_MESSAGE("(9,9) is outside range!",
1079 tools::getCohenSutherlandClipFlags(B2IPoint(9,9),aBox) == 0);
1080 CPPUNIT_ASSERT_MESSAGE("(10,10) is inside range!",
1081 tools::getCohenSutherlandClipFlags(B2IPoint(10,10),aBox) ==
1082 (tools::RectClipFlags::RIGHT|tools::RectClipFlags::BOTTOM));
1084 // just so that this compiles -
1085 B2IBox aBox1( aBox );
1086 (void)aBox1;
1089 // Change the following lines only, if you add, remove or rename
1090 // member functions of the current class,
1091 // because these macros are need by auto register mechanism.
1092 CPPUNIT_TEST_SUITE(b2ibox);
1093 CPPUNIT_TEST(TestBox);
1094 CPPUNIT_TEST_SUITE_END();
1095 }; // class b2ibox
1097 class b2dtuple : public CppUnit::TestFixture
1099 public:
1100 // insert your test code here.
1101 // this is only demonstration code
1102 void EmptyMethod()
1104 // CPPUNIT_ASSERT_MESSAGE("a message", 1 == 1);
1107 // Change the following lines only, if you add, remove or rename
1108 // member functions of the current class,
1109 // because these macros are need by auto register mechanism.
1111 CPPUNIT_TEST_SUITE(b2dtuple);
1112 CPPUNIT_TEST(EmptyMethod);
1113 CPPUNIT_TEST_SUITE_END();
1114 }; // class b2dtuple
1116 class bcolor : public CppUnit::TestFixture
1118 BColor maWhite;
1119 BColor maBlack;
1120 BColor maRed;
1121 BColor maGreen;
1122 BColor maBlue;
1123 BColor maYellow;
1124 BColor maMagenta;
1125 BColor maCyan;
1127 public:
1128 bcolor() :
1129 maWhite(1,1,1),
1130 maBlack(0,0,0),
1131 maRed(1,0,0),
1132 maGreen(0,1,0),
1133 maBlue(0,0,1),
1134 maYellow(1,1,0),
1135 maMagenta(1,0,1),
1136 maCyan(0,1,1)
1139 // insert your test code here.
1140 void hslTest()
1142 CPPUNIT_ASSERT_MESSAGE("white",
1143 tools::rgb2hsl(maWhite) == BColor(0,0,1));
1144 CPPUNIT_ASSERT_MESSAGE("black",
1145 tools::rgb2hsl(maBlack) == BColor(0,0,0));
1146 CPPUNIT_ASSERT_MESSAGE("red",
1147 tools::rgb2hsl(maRed) == BColor(0,1,0.5));
1148 CPPUNIT_ASSERT_MESSAGE("green",
1149 tools::rgb2hsl(maGreen) == BColor(120,1,0.5));
1150 CPPUNIT_ASSERT_MESSAGE("blue",
1151 tools::rgb2hsl(maBlue) == BColor(240,1,0.5));
1152 CPPUNIT_ASSERT_MESSAGE("yellow",
1153 tools::rgb2hsl(maYellow) == BColor(60,1,0.5));
1154 CPPUNIT_ASSERT_MESSAGE("magenta",
1155 tools::rgb2hsl(maMagenta) == BColor(300,1,0.5));
1156 CPPUNIT_ASSERT_MESSAGE("cyan",
1157 tools::rgb2hsl(maCyan) == BColor(180,1,0.5));
1158 CPPUNIT_ASSERT_MESSAGE("third hue case",
1159 tools::rgb2hsl(BColor(0,0.5,1)) == BColor(210,1,0.5));
1161 CPPUNIT_ASSERT_MESSAGE("roundtrip white",
1162 tools::hsl2rgb(tools::rgb2hsl(maWhite)) == maWhite);
1163 CPPUNIT_ASSERT_MESSAGE("roundtrip black",
1164 tools::hsl2rgb(tools::rgb2hsl(maBlack)) == maBlack);
1165 CPPUNIT_ASSERT_MESSAGE("roundtrip red",
1166 tools::hsl2rgb(tools::rgb2hsl(maRed)) == maRed);
1167 CPPUNIT_ASSERT_MESSAGE("roundtrip green",
1168 tools::hsl2rgb(tools::rgb2hsl(maGreen)) == maGreen);
1169 CPPUNIT_ASSERT_MESSAGE("roundtrip blue",
1170 tools::hsl2rgb(tools::rgb2hsl(maBlue)) == maBlue);
1171 CPPUNIT_ASSERT_MESSAGE("roundtrip yellow",
1172 tools::hsl2rgb(tools::rgb2hsl(maYellow)) == maYellow);
1173 CPPUNIT_ASSERT_MESSAGE("roundtrip magenta",
1174 tools::hsl2rgb(tools::rgb2hsl(maMagenta)) == maMagenta);
1175 CPPUNIT_ASSERT_MESSAGE("roundtrip cyan",
1176 tools::hsl2rgb(tools::rgb2hsl(maCyan)) == maCyan);
1178 CPPUNIT_ASSERT_MESSAGE("grey10",
1179 tools::rgb2hsl(maWhite*.1) == BColor(0,0,.1));
1180 CPPUNIT_ASSERT_MESSAGE("grey90",
1181 tools::rgb2hsl(maWhite*.9) == BColor(0,0,.9));
1182 CPPUNIT_ASSERT_MESSAGE("red/2",
1183 tools::rgb2hsl(maRed*.5) == BColor(0,1,0.25));
1184 CPPUNIT_ASSERT_MESSAGE("green/2",
1185 tools::rgb2hsl(maGreen*.5) == BColor(120,1,0.25));
1186 CPPUNIT_ASSERT_MESSAGE("blue/2",
1187 tools::rgb2hsl(maBlue*.5) == BColor(240,1,0.25));
1188 CPPUNIT_ASSERT_MESSAGE("yellow/2",
1189 tools::rgb2hsl(maYellow*.5) == BColor(60,1,0.25));
1190 CPPUNIT_ASSERT_MESSAGE("magenta/2",
1191 tools::rgb2hsl(maMagenta*.5) == BColor(300,1,0.25));
1192 CPPUNIT_ASSERT_MESSAGE("cyan/2",
1193 tools::rgb2hsl(maCyan*.5) == BColor(180,1,0.25));
1195 CPPUNIT_ASSERT_MESSAGE("pastel",
1196 tools::rgb2hsl(BColor(.75,.25,.25)) == BColor(0,.5,.5));
1199 // insert your test code here.
1200 void hsvTest()
1202 CPPUNIT_ASSERT_MESSAGE("white",
1203 tools::rgb2hsv(maWhite) == BColor(0,0,1));
1204 CPPUNIT_ASSERT_MESSAGE("black",
1205 tools::rgb2hsv(maBlack) == BColor(0,0,0));
1206 CPPUNIT_ASSERT_MESSAGE("red",
1207 tools::rgb2hsv(maRed) == BColor(0,1,1));
1208 CPPUNIT_ASSERT_MESSAGE("green",
1209 tools::rgb2hsv(maGreen) == BColor(120,1,1));
1210 CPPUNIT_ASSERT_MESSAGE("blue",
1211 tools::rgb2hsv(maBlue) == BColor(240,1,1));
1212 CPPUNIT_ASSERT_MESSAGE("yellow",
1213 tools::rgb2hsv(maYellow) == BColor(60,1,1));
1214 CPPUNIT_ASSERT_MESSAGE("magenta",
1215 tools::rgb2hsv(maMagenta) == BColor(300,1,1));
1216 CPPUNIT_ASSERT_MESSAGE("cyan",
1217 tools::rgb2hsv(maCyan) == BColor(180,1,1));
1219 CPPUNIT_ASSERT_MESSAGE("roundtrip white",
1220 tools::hsv2rgb(tools::rgb2hsv(maWhite)) == maWhite);
1221 CPPUNIT_ASSERT_MESSAGE("roundtrip black",
1222 tools::hsv2rgb(tools::rgb2hsv(maBlack)) == maBlack);
1223 CPPUNIT_ASSERT_MESSAGE("roundtrip red",
1224 tools::hsv2rgb(tools::rgb2hsv(maRed)) == maRed);
1225 CPPUNIT_ASSERT_MESSAGE("roundtrip green",
1226 tools::hsv2rgb(tools::rgb2hsv(maGreen)) == maGreen);
1227 CPPUNIT_ASSERT_MESSAGE("roundtrip blue",
1228 tools::hsv2rgb(tools::rgb2hsv(maBlue)) == maBlue);
1229 CPPUNIT_ASSERT_MESSAGE("roundtrip yellow",
1230 tools::hsv2rgb(tools::rgb2hsv(maYellow)) == maYellow);
1231 CPPUNIT_ASSERT_MESSAGE("roundtrip magenta",
1232 tools::hsv2rgb(tools::rgb2hsv(maMagenta)) == maMagenta);
1233 CPPUNIT_ASSERT_MESSAGE("roundtrip cyan",
1234 tools::hsv2rgb(tools::rgb2hsv(maCyan)) == maCyan);
1236 CPPUNIT_ASSERT_MESSAGE("grey10",
1237 tools::rgb2hsv(maWhite*.1) == BColor(0,0,.1));
1238 CPPUNIT_ASSERT_MESSAGE("grey90",
1239 tools::rgb2hsv(maWhite*.9) == BColor(0,0,.9));
1240 CPPUNIT_ASSERT_MESSAGE("red/2",
1241 tools::rgb2hsv(maRed*.5) == BColor(0,1,0.5));
1242 CPPUNIT_ASSERT_MESSAGE("green/2",
1243 tools::rgb2hsv(maGreen*.5) == BColor(120,1,0.5));
1244 CPPUNIT_ASSERT_MESSAGE("blue/2",
1245 tools::rgb2hsv(maBlue*.5) == BColor(240,1,0.5));
1246 CPPUNIT_ASSERT_MESSAGE("yellow/2",
1247 tools::rgb2hsv(maYellow*.5) == BColor(60,1,0.5));
1248 CPPUNIT_ASSERT_MESSAGE("magenta/2",
1249 tools::rgb2hsv(maMagenta*.5) == BColor(300,1,0.5));
1250 CPPUNIT_ASSERT_MESSAGE("cyan/2",
1251 tools::rgb2hsv(maCyan*.5) == BColor(180,1,0.5));
1253 CPPUNIT_ASSERT_MESSAGE("pastel",
1254 tools::rgb2hsv(BColor(.5,.25,.25)) == BColor(0,.5,.5));
1257 void ciexyzTest()
1259 tools::rgb2ciexyz(maWhite);
1260 tools::rgb2ciexyz(maBlack);
1261 tools::rgb2ciexyz(maRed);
1262 tools::rgb2ciexyz(maGreen);
1263 tools::rgb2ciexyz(maBlue);
1264 tools::rgb2ciexyz(maYellow);
1265 tools::rgb2ciexyz(maMagenta);
1266 tools::rgb2ciexyz(maCyan);
1269 // Change the following lines only, if you add, remove or rename
1270 // member functions of the current class,
1271 // because these macros are need by auto register mechanism.
1273 CPPUNIT_TEST_SUITE(bcolor);
1274 CPPUNIT_TEST(hslTest);
1275 CPPUNIT_TEST(hsvTest);
1276 CPPUNIT_TEST(ciexyzTest);
1277 CPPUNIT_TEST_SUITE_END();
1278 }; // class b2dvector
1280 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dsvgdimpex);
1281 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2drange);
1282 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolyrange);
1283 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dhommatrix);
1284 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpoint);
1285 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygon);
1286 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolygontools);
1287 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dpolypolygon);
1288 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b1Xrange);
1289 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b1ibox);
1290 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2Xrange);
1291 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2ibox);
1292 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::b2dtuple);
1293 CPPUNIT_TEST_SUITE_REGISTRATION(basegfx2d::bcolor);
1294 } // namespace basegfx2d
1296 CPPUNIT_PLUGIN_IMPLEMENT();
1298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */