doc: update copyright line for 2021
[adg.git] / src / cpml / tests / test-segment.c
blob59a83002f512622a596b610da85207b2dabb39da
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2021 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #include <adg-test.h>
22 #include <cpml.h>
25 static void
26 _cpml_behavior_browsing(void)
28 CpmlSegment segment;
29 g_assert_cmpint(cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()), ==, 1);
31 /* First segment */
32 g_assert_cmpint(segment.data[0].header.type, ==, CPML_MOVE);
33 g_assert_cmpint(segment.data[2].header.type, ==, CPML_LINE);
35 cpml_segment_reset(&segment);
36 cpml_segment_reset(&segment);
37 g_assert_cmpint(segment.num_data, ==, 12);
38 g_assert_cmpint(segment.data[0].header.type, ==, CPML_MOVE);
39 g_assert_cmpint(segment.data[2].header.type, ==, CPML_LINE);
40 g_assert_cmpint(segment.data[4].header.type, ==, CPML_ARC);
41 g_assert_cmpint(segment.data[7].header.type, ==, CPML_CURVE);
42 g_assert_cmpint(segment.data[11].header.type, ==, CPML_CLOSE);
44 /* Second segment */
45 g_assert_cmpint(cpml_segment_next(&segment), ==, 1);
46 g_assert_cmpint(segment.num_data, ==, 6);
47 g_assert_cmpint(segment.data[0].header.type, ==, CPML_MOVE);
48 g_assert_cmpint(segment.data[2].header.type, ==, CPML_LINE);
49 g_assert_cmpint(segment.data[4].header.type, ==, CPML_LINE);
51 /* Third segment */
52 g_assert_cmpint(cpml_segment_next(&segment), ==, 1);
53 g_assert_cmpint(segment.num_data, ==, 7);
54 g_assert_cmpint(segment.data[0].header.type, ==, CPML_MOVE);
55 g_assert_cmpint(segment.data[2].header.type, ==, CPML_CURVE);
56 g_assert_cmpint(segment.data[6].header.type, ==, CPML_CLOSE);
58 /* Forth segment */
59 g_assert_cmpint(cpml_segment_next(&segment), ==, 1);
60 g_assert_cmpint(segment.num_data, ==, 8);
61 g_assert_cmpint(segment.data[0].header.type, ==, CPML_MOVE);
62 g_assert_cmpint(segment.data[2].header.type, ==, CPML_ARC);
63 g_assert_cmpint(segment.data[5].header.type, ==, CPML_ARC);
65 /* Fifth segment */
66 g_assert_cmpint(cpml_segment_next(&segment), ==, 1);
67 g_assert_cmpint(segment.num_data, ==, 3);
68 g_assert_cmpint(segment.data[0].header.type, ==, CPML_MOVE);
69 g_assert_cmpint(segment.data[2].header.type, ==, CPML_CLOSE);
71 g_assert_cmpint(cpml_segment_next(&segment), ==, 0);
73 cpml_segment_reset(&segment);
74 g_assert_cmpint(segment.num_data, ==, 12);
77 static void
78 _cpml_sanity_from_cairo(gint i)
80 cairo_path_t *path = (cairo_path_t *) adg_test_path();
81 CpmlSegment segment;
83 switch (i) {
84 case 1:
85 cpml_segment_from_cairo(NULL, path);
86 break;
87 case 2:
88 cpml_segment_from_cairo(&segment, NULL);
89 break;
90 default:
91 g_test_trap_assert_failed();
92 break;
96 static void
97 _cpml_sanity_copy(gint i)
99 CpmlSegment segment;
100 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
102 switch (i) {
103 case 1:
104 cpml_segment_copy(NULL, &segment);
105 break;
106 case 2:
107 cpml_segment_copy(&segment, NULL);
108 break;
109 default:
110 g_test_trap_assert_failed();
111 break;
115 static void
116 _cpml_sanity_copy_data(gint i)
118 CpmlSegment segment;
119 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
121 switch (i) {
122 case 1:
123 cpml_segment_copy_data(NULL, &segment);
124 break;
125 case 2:
126 cpml_segment_copy_data(&segment, NULL);
127 break;
128 default:
129 g_test_trap_assert_failed();
130 break;
134 static void
135 _cpml_sanity_get_length(gint i)
137 switch (i) {
138 case 1:
139 cpml_segment_get_length(NULL);
140 break;
141 default:
142 g_test_trap_assert_failed();
143 break;
147 static void
148 _cpml_sanity_put_intersections(gint i)
150 CpmlSegment segment1, segment2;
151 CpmlPair pair;
153 /* Segment 1 and segment 2 intersects at least in (1,1) */
154 cpml_segment_from_cairo(&segment1, (cairo_path_t *) adg_test_path());
155 cpml_segment_copy(&segment2, &segment1);
156 cpml_segment_next(&segment2);
158 switch (i) {
159 case 1:
160 cpml_segment_put_intersections(NULL, &segment2, 2, &pair);
161 break;
162 case 2:
163 cpml_segment_put_intersections(&segment1, NULL, 2, &pair);
164 break;
165 case 3:
166 cpml_segment_put_intersections(&segment1, &segment2, 2, NULL);
167 break;
168 default:
169 g_test_trap_assert_failed();
170 break;
174 static void
175 _cpml_sanity_offset(gint i)
177 switch (i) {
178 case 1:
179 cpml_segment_offset(NULL, 1);
180 break;
181 default:
182 g_test_trap_assert_failed();
183 break;
187 static void
188 _cpml_sanity_transform(gint i)
190 CpmlSegment segment;
191 cairo_matrix_t matrix;
193 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
194 cairo_matrix_init_identity(&matrix);
196 switch (i) {
197 case 1:
198 cpml_segment_transform(NULL, &matrix);
199 break;
200 case 2:
201 cpml_segment_transform(&segment, NULL);
202 break;
203 default:
204 g_test_trap_assert_failed();
205 break;
209 static void
210 _cpml_sanity_reverse(gint i)
212 switch (i) {
213 case 1:
214 cpml_segment_reverse(NULL);
215 break;
216 default:
217 g_test_trap_assert_failed();
218 break;
222 static void
223 _cpml_sanity_to_cairo(gint i)
225 CpmlSegment segment;
227 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
229 switch (i) {
230 case 1:
231 cpml_segment_to_cairo(NULL, adg_test_cairo_context());
232 break;
233 case 2:
234 cpml_segment_to_cairo(&segment, NULL);
235 default:
236 g_test_trap_assert_failed();
237 break;
241 static void
242 _cpml_sanity_dump(gint i)
244 switch (i) {
245 case 1:
246 cpml_segment_dump(NULL);
247 break;
248 default:
249 g_test_trap_assert_failed();
250 break;
254 static void
255 _cpml_method_from_cairo(void)
257 CpmlSegment segment;
258 cairo_path_data_t noop_data[] = {
259 /* Useless heading primitives */
260 { .header = { CPML_MOVE, 2 }},
261 { .point = { 0, 1 }},
262 { .header = { CPML_MOVE, 4 }},
263 { .point = { 2, 3 }},
264 { .point = { 4, 5 }},
265 { .point = { 6, 7 }},
266 { .header = { CPML_MOVE, 2 }},
267 { .point = { 8, 9 }}
269 cairo_path_data_t invalid_primitive[] = {
270 { .header = { CPML_MOVE, 2 }},
271 { .point = { 0, 1 }},
272 { .header = { CPML_ARC, 2 }}, /* Should be CPML_ARC, 3 */
273 { .point = { 2, 3 }}
275 cairo_path_t noop_path = {
276 CAIRO_STATUS_SUCCESS,
277 noop_data,
278 G_N_ELEMENTS(noop_data)
280 cairo_path_t empty_path = {
281 CAIRO_STATUS_SUCCESS,
282 adg_test_path()->data,
285 cairo_path_t basic_path = {
286 CAIRO_STATUS_SUCCESS,
287 adg_test_path()->data,
290 cairo_path_t invalid_path1 = {
291 CAIRO_STATUS_SUCCESS,
292 adg_test_path()->data,
293 3 /* Should be 4 */
295 cairo_path_t invalid_path2 = {
296 CAIRO_STATUS_SUCCESS,
297 invalid_primitive,
298 G_N_ELEMENTS(invalid_primitive)
301 g_assert_cmpint(cpml_segment_from_cairo(&segment, &noop_path), ==, 0);
302 g_assert_cmpint(cpml_segment_from_cairo(&segment, &empty_path), ==, 0);
303 g_assert_cmpint(cpml_segment_from_cairo(&segment, &basic_path), ==, 1);
304 g_assert_cmpint(cpml_segment_from_cairo(&segment, &invalid_path1), ==, 0);
305 g_assert_cmpint(cpml_segment_from_cairo(&segment, &invalid_path2), ==, 0);
306 g_assert_cmpint(cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()), ==, 1);
309 static void
310 _cpml_method_copy(void)
312 CpmlSegment original;
313 CpmlSegment segment = { NULL, NULL, 0 };
315 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
316 g_assert_true(segment.path != original.path);
317 g_assert_true(segment.data != original.data);
318 g_assert_cmpint(segment.num_data, !=, original.num_data);
319 cpml_segment_copy(&segment, &original);
320 g_assert_true(segment.path == original.path);
321 g_assert_true(segment.data == original.data);
322 g_assert_cmpint(segment.num_data, ==, original.num_data);
325 static void
326 _cpml_method_copy_data(void)
328 CpmlSegment original, *segment;
330 /* Let's take the second segment as source */
331 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
332 cpml_segment_next(&original);
333 g_assert_cmpint(original.num_data, ==, 6);
335 /* Check incompatible segments are not copied */
336 segment = cpml_segment_deep_dup(&original);
337 ++segment->num_data;
338 g_assert_cmpint(cpml_segment_copy_data(segment, &original), ==, 0);
339 --segment->num_data;
341 /* Test data copy */
342 ++segment->data[1].point.x;
343 ++segment->data[1].point.y;
344 ++segment->data[3].point.x;
345 ++segment->data[3].point.y;
346 ++segment->data[5].point.x;
347 ++segment->data[5].point.y;
348 g_assert_cmpfloat(segment->data[1].point.x, !=, original.data[1].point.x);
349 g_assert_cmpfloat(segment->data[1].point.y, !=, original.data[1].point.y);
350 g_assert_cmpfloat(segment->data[3].point.x, !=, original.data[3].point.x);
351 g_assert_cmpfloat(segment->data[3].point.y, !=, original.data[3].point.y);
352 g_assert_cmpfloat(segment->data[5].point.x, !=, original.data[5].point.x);
353 g_assert_cmpfloat(segment->data[5].point.y, !=, original.data[5].point.y);
354 g_assert_cmpint(cpml_segment_copy_data(segment, &original), ==, 1);
355 adg_assert_isapprox(segment->data[1].point.x, original.data[1].point.x);
356 adg_assert_isapprox(segment->data[1].point.y, original.data[1].point.y);
357 adg_assert_isapprox(segment->data[3].point.x, original.data[3].point.x);
358 adg_assert_isapprox(segment->data[3].point.y, original.data[3].point.y);
359 adg_assert_isapprox(segment->data[5].point.x, original.data[5].point.x);
360 adg_assert_isapprox(segment->data[5].point.y, original.data[5].point.y);
362 g_free(segment);
365 static void
366 _cpml_method_get_length(void)
368 CpmlSegment segment;
370 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
372 /* First segment: not a round number so avoiding == */
373 g_assert_cmpfloat(cpml_segment_get_length(&segment), >, 0);
375 cpml_segment_next(&segment);
377 /* Second segment */
378 adg_assert_isapprox(cpml_segment_get_length(&segment), 3);
379 adg_assert_isapprox(cpml_segment_get_length(&segment), 3);
381 cpml_segment_next(&segment);
383 /* Third segment */
384 /* TODO: Bézier curve length not yet implemented
385 * g_assert_cmpfloat(cpml_segment_get_length(&segment), >, 0); */
387 cpml_segment_next(&segment);
389 /* Forth segment */
390 adg_assert_isapprox(cpml_segment_get_length(&segment), 13.114);
392 cpml_segment_next(&segment);
394 /* Fifth segment */
395 adg_assert_isapprox(cpml_segment_get_length(&segment), 0);
398 static void
399 _cpml_method_put_intersections(void)
401 CpmlSegment segment1, segment2;
402 CpmlPair pair[10];
404 cpml_segment_from_cairo(&segment1, (cairo_path_t *) adg_test_path());
405 cpml_segment_copy(&segment2, &segment1);
407 cpml_segment_next(&segment2);
409 /* The first segment intersects the second segment in (1, 1). */
410 g_assert_cmpuint(cpml_segment_put_intersections(&segment1, &segment2, 10, pair), ==, 1);
411 adg_assert_isapprox(pair[0].x, 1);
412 adg_assert_isapprox(pair[0].y, 1);
414 cpml_segment_next(&segment2);
416 g_assert_cmpuint(cpml_segment_put_intersections(&segment1, &segment2, 10, pair), ==, 0);
419 static void
420 _cpml_method_offset(void)
422 CpmlSegment original, *segment;
424 /* Work on a copy to avoid modifying adg_test_path() data */
425 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
426 segment = cpml_segment_deep_dup(&original);
428 /* TODO: provide tests for arcs and curves */
429 cpml_segment_offset(segment, 1);
430 g_free(segment);
432 cpml_segment_next(&original);
433 segment = cpml_segment_deep_dup(&original);
434 cpml_segment_offset(segment, 1);
436 g_assert_cmpint(segment->data[0].header.type, ==, CPML_MOVE);
437 adg_assert_isapprox(segment->data[1].point.x, 0);
438 adg_assert_isapprox(segment->data[1].point.y, 1);
440 g_assert_cmpint(segment->data[2].header.type, ==, CPML_LINE);
441 adg_assert_isapprox(segment->data[3].point.x, 0);
442 adg_assert_isapprox(segment->data[3].point.y, 1);
444 g_assert_cmpint(segment->data[4].header.type, ==, CPML_LINE);
445 adg_assert_isapprox(segment->data[5].point.x, 0);
446 adg_assert_isapprox(segment->data[5].point.y, 2);
448 g_free(segment);
451 static void
452 _cpml_method_transform(void)
454 CpmlSegment original, *segment;
455 cairo_matrix_t matrix;
457 /* Work on a copy to avoid modifying adg_test_path() data */
458 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
459 segment = cpml_segment_deep_dup(&original);
461 cairo_matrix_init_translate(&matrix, 1, 2);
462 cpml_segment_transform(segment, &matrix);
464 g_assert_cmpint(segment->data[0].header.type, ==, CPML_MOVE);
465 adg_assert_isapprox(segment->data[1].point.x, 1);
466 adg_assert_isapprox(segment->data[1].point.y, 3);
468 g_assert_cmpint(segment->data[2].header.type, ==, CPML_LINE);
469 adg_assert_isapprox(segment->data[3].point.x, 4);
470 adg_assert_isapprox(segment->data[3].point.y, 3);
472 g_assert_cmpint(segment->data[4].header.type, ==, CPML_ARC);
473 adg_assert_isapprox(segment->data[5].point.x, 5);
474 adg_assert_isapprox(segment->data[5].point.y, 7);
475 adg_assert_isapprox(segment->data[6].point.x, 7);
476 adg_assert_isapprox(segment->data[6].point.y, 9);
478 g_assert_cmpint(segment->data[7].header.type, ==, CPML_CURVE);
479 adg_assert_isapprox(segment->data[8].point.x, 9);
480 adg_assert_isapprox(segment->data[8].point.y, 11);
481 adg_assert_isapprox(segment->data[9].point.x, 11);
482 adg_assert_isapprox(segment->data[9].point.y, 13);
483 adg_assert_isapprox(segment->data[10].point.x, -1);
484 adg_assert_isapprox(segment->data[10].point.y, 4);
486 g_assert_cmpint(segment->data[11].header.type, ==, CPML_CLOSE);
488 g_free(segment);
491 #include <stdio.h>
492 static void
493 _cpml_method_reverse(void)
495 CpmlSegment original, *segment;
497 /* Work on a copy to avoid modifying adg_test_path() data */
498 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
499 segment = cpml_segment_deep_dup(&original);
501 /* First segment */
502 cpml_segment_reverse(segment);
504 g_assert_cmpint(segment->num_data, ==, 12);
506 g_assert_cmpint(segment->data[0].header.type, ==, CPML_MOVE);
507 adg_assert_isapprox(segment->data[1].point.x, -2);
508 adg_assert_isapprox(segment->data[1].point.y, 2);
510 g_assert_cmpint(segment->data[2].header.type, ==, CPML_CURVE);
511 adg_assert_isapprox(segment->data[3].point.x, 10);
512 adg_assert_isapprox(segment->data[3].point.y, 11);
513 adg_assert_isapprox(segment->data[4].point.x, 8);
514 adg_assert_isapprox(segment->data[4].point.y, 9);
515 adg_assert_isapprox(segment->data[5].point.x, 6);
516 adg_assert_isapprox(segment->data[5].point.y, 7);
518 g_assert_cmpint(segment->data[6].header.type, ==, CPML_ARC);
519 adg_assert_isapprox(segment->data[7].point.x, 4);
520 adg_assert_isapprox(segment->data[7].point.y, 5);
521 adg_assert_isapprox(segment->data[8].point.x, 3);
522 adg_assert_isapprox(segment->data[8].point.y, 1);
524 g_assert_cmpint(segment->data[9].header.type, ==, CPML_LINE);
525 adg_assert_isapprox(segment->data[10].point.x, 0);
526 adg_assert_isapprox(segment->data[10].point.y, 1);
528 g_assert_cmpint(segment->data[11].header.type, ==, CPML_CLOSE);
530 g_free(segment);
533 static void
534 _cpml_method_to_cairo(void)
536 cairo_t *cr;
537 CpmlSegment segment;
538 int length, last_length;
540 cr = adg_test_cairo_context();
541 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
543 g_assert_cmpint(adg_test_cairo_num_data(cr), ==, 0);
545 length = 0;
546 do {
547 last_length = length;
548 cpml_segment_to_cairo(&segment, cr);
549 length = adg_test_cairo_num_data(cr);
550 g_assert_cmpint(length, >, last_length);
551 } while (cpml_segment_next(&segment));
553 cairo_destroy(cr);
556 static void
557 _cpml_method_dump(gint i)
559 CpmlSegment segment;
561 switch (i) {
562 case 1:
563 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
564 cpml_segment_dump(&segment);
565 break;
566 default:
567 g_test_trap_assert_passed();
568 g_test_trap_assert_stderr_unmatched("?");
569 g_test_trap_assert_stdout("*move*line*arc*curve*close*");
570 break;
576 main(int argc, char *argv[])
578 adg_test_init(&argc, &argv);
580 g_test_add_func("/cpml/segment/behavior/browsing", _cpml_behavior_browsing);
582 adg_test_add_traps("/cpml/segment/sanity/from-cairo", _cpml_sanity_from_cairo, 2);
583 adg_test_add_traps("/cpml/segment/sanity/copy", _cpml_sanity_copy, 2);
584 adg_test_add_traps("/cpml/segment/sanity/copy-data", _cpml_sanity_copy_data, 2);
585 adg_test_add_traps("/cpml/segment/sanity/get-length", _cpml_sanity_get_length, 1);
586 adg_test_add_traps("/cpml/segment/sanity/put-intersections", _cpml_sanity_put_intersections, 3);
587 adg_test_add_traps("/cpml/segment/sanity/offset", _cpml_sanity_offset, 1);
588 adg_test_add_traps("/cpml/segment/sanity/transform", _cpml_sanity_transform, 2);
589 adg_test_add_traps("/cpml/segment/sanity/reverse", _cpml_sanity_reverse, 1);
590 adg_test_add_traps("/cpml/segment/sanity/to-cairo", _cpml_sanity_to_cairo, 2);
591 adg_test_add_traps("/cpml/segment/sanity/dump", _cpml_sanity_dump, 1);
593 g_test_add_func("/cpml/segment/method/from-cairo", _cpml_method_from_cairo);
594 g_test_add_func("/cpml/segment/method/copy", _cpml_method_copy);
595 g_test_add_func("/cpml/segment/method/copy-data", _cpml_method_copy_data);
596 g_test_add_func("/cpml/segment/method/get-length", _cpml_method_get_length);
597 g_test_add_func("/cpml/segment/method/put-intersections", _cpml_method_put_intersections);
598 g_test_add_func("/cpml/segment/method/offset", _cpml_method_offset);
599 g_test_add_func("/cpml/segment/method/transform", _cpml_method_transform);
600 g_test_add_func("/cpml/segment/method/reverse", _cpml_method_reverse);
601 g_test_add_func("/cpml/segment/method/to-cairo", _cpml_method_to_cairo);
602 adg_test_add_traps("/cpml/segment/method/dump", _cpml_method_dump, 1);
604 return g_test_run();