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.
26 _cpml_behavior_browsing(void)
29 g_assert_cmpint(cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path()), ==, 1);
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
);
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
);
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
);
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
);
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);
78 _cpml_sanity_from_cairo(gint i
)
80 cairo_path_t
*path
= (cairo_path_t
*) adg_test_path();
85 cpml_segment_from_cairo(NULL
, path
);
88 cpml_segment_from_cairo(&segment
, NULL
);
91 g_test_trap_assert_failed();
97 _cpml_sanity_copy(gint i
)
100 cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path());
104 cpml_segment_copy(NULL
, &segment
);
107 cpml_segment_copy(&segment
, NULL
);
110 g_test_trap_assert_failed();
116 _cpml_sanity_copy_data(gint i
)
119 cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path());
123 cpml_segment_copy_data(NULL
, &segment
);
126 cpml_segment_copy_data(&segment
, NULL
);
129 g_test_trap_assert_failed();
135 _cpml_sanity_get_length(gint i
)
139 cpml_segment_get_length(NULL
);
142 g_test_trap_assert_failed();
148 _cpml_sanity_put_intersections(gint i
)
150 CpmlSegment segment1
, segment2
;
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
);
160 cpml_segment_put_intersections(NULL
, &segment2
, 2, &pair
);
163 cpml_segment_put_intersections(&segment1
, NULL
, 2, &pair
);
166 cpml_segment_put_intersections(&segment1
, &segment2
, 2, NULL
);
169 g_test_trap_assert_failed();
175 _cpml_sanity_offset(gint i
)
179 cpml_segment_offset(NULL
, 1);
182 g_test_trap_assert_failed();
188 _cpml_sanity_transform(gint i
)
191 cairo_matrix_t matrix
;
193 cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path());
194 cairo_matrix_init_identity(&matrix
);
198 cpml_segment_transform(NULL
, &matrix
);
201 cpml_segment_transform(&segment
, NULL
);
204 g_test_trap_assert_failed();
210 _cpml_sanity_reverse(gint i
)
214 cpml_segment_reverse(NULL
);
217 g_test_trap_assert_failed();
223 _cpml_sanity_to_cairo(gint i
)
227 cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path());
231 cpml_segment_to_cairo(NULL
, adg_test_cairo_context());
234 cpml_segment_to_cairo(&segment
, NULL
);
236 g_test_trap_assert_failed();
242 _cpml_sanity_dump(gint i
)
246 cpml_segment_dump(NULL
);
249 g_test_trap_assert_failed();
255 _cpml_method_from_cairo(void)
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 }},
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 */
275 cairo_path_t noop_path
= {
276 CAIRO_STATUS_SUCCESS
,
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
,
295 cairo_path_t invalid_path2
= {
296 CAIRO_STATUS_SUCCESS
,
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);
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
);
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
);
338 g_assert_cmpint(cpml_segment_copy_data(segment
, &original
), ==, 0);
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
);
366 _cpml_method_get_length(void)
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
);
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
);
384 /* TODO: Bézier curve length not yet implemented
385 * g_assert_cmpfloat(cpml_segment_get_length(&segment), >, 0); */
387 cpml_segment_next(&segment
);
390 adg_assert_isapprox(cpml_segment_get_length(&segment
), 13.114);
392 cpml_segment_next(&segment
);
395 adg_assert_isapprox(cpml_segment_get_length(&segment
), 0);
399 _cpml_method_put_intersections(void)
401 CpmlSegment segment1
, segment2
;
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);
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);
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);
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
);
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
);
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
);
534 _cpml_method_to_cairo(void)
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);
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
));
557 _cpml_method_dump(gint i
)
563 cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path());
564 cpml_segment_dump(&segment
);
567 g_test_trap_assert_passed();
568 g_test_trap_assert_stderr_unmatched("?");
569 g_test_trap_assert_stdout("*move*line*arc*curve*close*");
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);