1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2015 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 g_assert_cmpfloat(segment
->data
[1].point
.x
, ==, original
.data
[1].point
.x
);
356 g_assert_cmpfloat(segment
->data
[1].point
.y
, ==, original
.data
[1].point
.y
);
357 g_assert_cmpfloat(segment
->data
[3].point
.x
, ==, original
.data
[3].point
.x
);
358 g_assert_cmpfloat(segment
->data
[3].point
.y
, ==, original
.data
[3].point
.y
);
359 g_assert_cmpfloat(segment
->data
[5].point
.x
, ==, original
.data
[5].point
.x
);
360 g_assert_cmpfloat(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 g_assert_cmpfloat(cpml_segment_get_length(&segment
), ==, 3);
379 g_assert_cmpfloat(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 g_assert_cmpfloat(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 * TODO: avoid extrapolated intersections! Check
411 * cpml_primitive_put_intersections */
412 g_assert_cmpuint(cpml_segment_put_intersections(&segment1
, &segment2
, 10, pair
), ==, 3);
413 g_assert_cmpfloat(pair
[0].x
, ==, 1);
414 g_assert_cmpfloat(pair
[0].y
, ==, 1);
415 g_assert_cmpfloat(pair
[1].x
, ==, 2);
416 g_assert_cmpfloat(pair
[1].y
, ==, 0);
418 cpml_segment_next(&segment2
);
420 g_assert_cmpuint(cpml_segment_put_intersections(&segment1
, &segment2
, 10, pair
), ==, 1);
424 _cpml_method_offset(void)
426 CpmlSegment original
, *segment
;
428 /* Work on a copy to avoid modifying adg_test_path() data */
429 cpml_segment_from_cairo(&original
, (cairo_path_t
*) adg_test_path());
430 segment
= cpml_segment_deep_dup(&original
);
432 /* TODO: provide tests for arcs and curves */
433 cpml_segment_offset(segment
, 1);
436 cpml_segment_next(&original
);
437 segment
= cpml_segment_deep_dup(&original
);
438 cpml_segment_offset(segment
, 1);
440 g_assert_cmpint(segment
->data
[0].header
.type
, ==, CPML_MOVE
);
441 g_assert_cmpfloat(segment
->data
[1].point
.x
, ==, 0);
442 g_assert_cmpfloat(segment
->data
[1].point
.y
, ==, 1);
444 g_assert_cmpint(segment
->data
[2].header
.type
, ==, CPML_LINE
);
445 g_assert_cmpfloat(segment
->data
[3].point
.x
, ==, 0);
446 g_assert_cmpfloat(segment
->data
[3].point
.y
, ==, 1);
448 g_assert_cmpint(segment
->data
[4].header
.type
, ==, CPML_LINE
);
449 g_assert_cmpfloat(segment
->data
[5].point
.x
, ==, 0);
450 g_assert_cmpfloat(segment
->data
[5].point
.y
, ==, 2);
456 _cpml_method_transform(void)
458 CpmlSegment original
, *segment
;
459 cairo_matrix_t matrix
;
461 /* Work on a copy to avoid modifying adg_test_path() data */
462 cpml_segment_from_cairo(&original
, (cairo_path_t
*) adg_test_path());
463 segment
= cpml_segment_deep_dup(&original
);
465 cairo_matrix_init_translate(&matrix
, 1, 2);
466 cpml_segment_transform(segment
, &matrix
);
468 g_assert_cmpint(segment
->data
[0].header
.type
, ==, CPML_MOVE
);
469 g_assert_cmpfloat(segment
->data
[1].point
.x
, ==, 1);
470 g_assert_cmpfloat(segment
->data
[1].point
.y
, ==, 3);
472 g_assert_cmpint(segment
->data
[2].header
.type
, ==, CPML_LINE
);
473 g_assert_cmpfloat(segment
->data
[3].point
.x
, ==, 4);
474 g_assert_cmpfloat(segment
->data
[3].point
.y
, ==, 3);
476 g_assert_cmpint(segment
->data
[4].header
.type
, ==, CPML_ARC
);
477 g_assert_cmpfloat(segment
->data
[5].point
.x
, ==, 5);
478 g_assert_cmpfloat(segment
->data
[5].point
.y
, ==, 7);
479 g_assert_cmpfloat(segment
->data
[6].point
.x
, ==, 7);
480 g_assert_cmpfloat(segment
->data
[6].point
.y
, ==, 9);
482 g_assert_cmpint(segment
->data
[7].header
.type
, ==, CPML_CURVE
);
483 g_assert_cmpfloat(segment
->data
[8].point
.x
, ==, 9);
484 g_assert_cmpfloat(segment
->data
[8].point
.y
, ==, 11);
485 g_assert_cmpfloat(segment
->data
[9].point
.x
, ==, 11);
486 g_assert_cmpfloat(segment
->data
[9].point
.y
, ==, 13);
487 g_assert_cmpfloat(segment
->data
[10].point
.x
, ==, -1);
488 g_assert_cmpfloat(segment
->data
[10].point
.y
, ==, 4);
490 g_assert_cmpint(segment
->data
[11].header
.type
, ==, CPML_CLOSE
);
497 _cpml_method_reverse(void)
499 CpmlSegment original
, *segment
;
501 /* Work on a copy to avoid modifying adg_test_path() data */
502 cpml_segment_from_cairo(&original
, (cairo_path_t
*) adg_test_path());
503 segment
= cpml_segment_deep_dup(&original
);
506 cpml_segment_reverse(segment
);
508 g_assert_cmpint(segment
->num_data
, ==, 12);
510 g_assert_cmpint(segment
->data
[0].header
.type
, ==, CPML_MOVE
);
511 g_assert_cmpfloat(segment
->data
[1].point
.x
, ==, -2);
512 g_assert_cmpfloat(segment
->data
[1].point
.y
, ==, 2);
514 g_assert_cmpint(segment
->data
[2].header
.type
, ==, CPML_CURVE
);
515 g_assert_cmpfloat(segment
->data
[3].point
.x
, ==, 10);
516 g_assert_cmpfloat(segment
->data
[3].point
.y
, ==, 11);
517 g_assert_cmpfloat(segment
->data
[4].point
.x
, ==, 8);
518 g_assert_cmpfloat(segment
->data
[4].point
.y
, ==, 9);
519 g_assert_cmpfloat(segment
->data
[5].point
.x
, ==, 6);
520 g_assert_cmpfloat(segment
->data
[5].point
.y
, ==, 7);
522 g_assert_cmpint(segment
->data
[6].header
.type
, ==, CPML_ARC
);
523 g_assert_cmpfloat(segment
->data
[7].point
.x
, ==, 4);
524 g_assert_cmpfloat(segment
->data
[7].point
.y
, ==, 5);
525 g_assert_cmpfloat(segment
->data
[8].point
.x
, ==, 3);
526 g_assert_cmpfloat(segment
->data
[8].point
.y
, ==, 1);
528 g_assert_cmpint(segment
->data
[9].header
.type
, ==, CPML_LINE
);
529 g_assert_cmpfloat(segment
->data
[10].point
.x
, ==, 0);
530 g_assert_cmpfloat(segment
->data
[10].point
.y
, ==, 1);
532 g_assert_cmpint(segment
->data
[11].header
.type
, ==, CPML_CLOSE
);
538 _cpml_method_to_cairo(void)
542 int length
, last_length
;
544 cr
= adg_test_cairo_context();
545 cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path());
547 g_assert_cmpint(adg_test_cairo_num_data(cr
), ==, 0);
551 last_length
= length
;
552 cpml_segment_to_cairo(&segment
, cr
);
553 length
= adg_test_cairo_num_data(cr
);
554 g_assert_cmpint(length
, >, last_length
);
555 } while (cpml_segment_next(&segment
));
561 _cpml_method_dump(gint i
)
567 cpml_segment_from_cairo(&segment
, (cairo_path_t
*) adg_test_path());
568 cpml_segment_dump(&segment
);
571 g_test_trap_assert_passed();
572 g_test_trap_assert_stderr_unmatched("?");
573 g_test_trap_assert_stdout("*move*line*arc*curve*close*");
580 main(int argc
, char *argv
[])
582 adg_test_init(&argc
, &argv
);
584 g_test_add_func("/cpml/segment/behavior/browsing", _cpml_behavior_browsing
);
586 adg_test_add_traps("/cpml/segment/sanity/from-cairo", _cpml_sanity_from_cairo
, 2);
587 adg_test_add_traps("/cpml/segment/sanity/copy", _cpml_sanity_copy
, 2);
588 adg_test_add_traps("/cpml/segment/sanity/copy-data", _cpml_sanity_copy_data
, 2);
589 adg_test_add_traps("/cpml/segment/sanity/get-length", _cpml_sanity_get_length
, 1);
590 adg_test_add_traps("/cpml/segment/sanity/put-intersections", _cpml_sanity_put_intersections
, 3);
591 adg_test_add_traps("/cpml/segment/sanity/offset", _cpml_sanity_offset
, 1);
592 adg_test_add_traps("/cpml/segment/sanity/transform", _cpml_sanity_transform
, 2);
593 adg_test_add_traps("/cpml/segment/sanity/reverse", _cpml_sanity_reverse
, 1);
594 adg_test_add_traps("/cpml/segment/sanity/to-cairo", _cpml_sanity_to_cairo
, 2);
595 adg_test_add_traps("/cpml/segment/sanity/dump", _cpml_sanity_dump
, 1);
597 g_test_add_func("/cpml/segment/method/from-cairo", _cpml_method_from_cairo
);
598 g_test_add_func("/cpml/segment/method/copy", _cpml_method_copy
);
599 g_test_add_func("/cpml/segment/method/copy-data", _cpml_method_copy_data
);
600 g_test_add_func("/cpml/segment/method/get-length", _cpml_method_get_length
);
601 g_test_add_func("/cpml/segment/method/put-intersections", _cpml_method_put_intersections
);
602 g_test_add_func("/cpml/segment/method/offset", _cpml_method_offset
);
603 g_test_add_func("/cpml/segment/method/transform", _cpml_method_transform
);
604 g_test_add_func("/cpml/segment/method/reverse", _cpml_method_reverse
);
605 g_test_add_func("/cpml/segment/method/to-cairo", _cpml_method_to_cairo
);
606 adg_test_add_traps("/cpml/segment/method/dump", _cpml_method_dump
, 1);