tests: avoid 3P arcs lying on the same line
[adg.git] / src / cpml / tests / test-segment.c
blobabb7196a123ff8b44efc557ac0b989a6a5890f1b
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.
21 #include <adg-test.h>
22 #include <cpml.h>
25 static void
26 _cpml_test_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_test_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_test_sanity_get_length(gint i)
99 switch (i) {
100 case 1:
101 cpml_segment_get_length(NULL);
102 break;
103 default:
104 g_test_trap_assert_failed();
105 break;
109 static void
110 _cpml_test_sanity_put_intersections(gint i)
112 CpmlSegment segment1, segment2;
113 CpmlPair pair;
115 /* Segment 1 and segment 2 intersects at least in (1,1) */
116 cpml_segment_from_cairo(&segment1, (cairo_path_t *) adg_test_path());
117 cpml_segment_copy(&segment2, &segment1);
118 cpml_segment_next(&segment2);
120 switch (i) {
121 case 1:
122 cpml_segment_put_intersections(NULL, &segment2, 2, &pair);
123 break;
124 case 2:
125 cpml_segment_put_intersections(&segment1, NULL, 2, &pair);
126 break;
127 case 3:
128 cpml_segment_put_intersections(&segment1, &segment2, 2, NULL);
129 break;
130 default:
131 g_test_trap_assert_failed();
132 break;
136 static void
137 _cpml_test_sanity_offset(gint i)
139 switch (i) {
140 case 1:
141 cpml_segment_offset(NULL, 1);
142 break;
143 default:
144 g_test_trap_assert_failed();
145 break;
149 static void
150 _cpml_test_sanity_transform(gint i)
152 CpmlSegment segment;
153 cairo_matrix_t matrix;
155 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
156 cairo_matrix_init_identity(&matrix);
158 switch (i) {
159 case 1:
160 cpml_segment_transform(NULL, &matrix);
161 break;
162 case 2:
163 cpml_segment_transform(&segment, NULL);
164 break;
165 default:
166 g_test_trap_assert_failed();
167 break;
171 static void
172 _cpml_test_sanity_reverse(gint i)
174 switch (i) {
175 case 1:
176 cpml_segment_reverse(NULL);
177 break;
178 default:
179 g_test_trap_assert_failed();
180 break;
184 static void
185 _cpml_test_sanity_to_cairo(gint i)
187 CpmlSegment segment;
189 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
191 switch (i) {
192 case 1:
193 cpml_segment_to_cairo(NULL, adg_test_cairo_context());
194 break;
195 case 2:
196 cpml_segment_to_cairo(&segment, NULL);
197 default:
198 g_test_trap_assert_failed();
199 break;
203 static void
204 _cpml_test_sanity_dump(gint i)
206 switch (i) {
207 case 1:
208 cpml_segment_dump(NULL);
209 break;
210 default:
211 g_test_trap_assert_failed();
212 break;
216 static void
217 _cpml_test_from_cairo(void)
219 CpmlSegment segment;
220 cairo_path_data_t noop_data[] = {
221 /* Useless heading primitives */
222 { .header = { CPML_MOVE, 2 }},
223 { .point = { 0, 1 }},
224 { .header = { CPML_MOVE, 4 }},
225 { .point = { 2, 3 }},
226 { .point = { 4, 5 }},
227 { .point = { 6, 7 }},
228 { .header = { CPML_MOVE, 2 }},
229 { .point = { 8, 9 }}
231 cairo_path_data_t invalid_primitive[] = {
232 { .header = { CPML_MOVE, 2 }},
233 { .point = { 0, 1 }},
234 { .header = { CPML_ARC, 2 }}, /* Should be CPML_ARC, 3 */
235 { .point = { 2, 3 }}
237 cairo_path_t noop_path = {
238 CAIRO_STATUS_SUCCESS,
239 noop_data,
240 G_N_ELEMENTS(noop_data)
242 cairo_path_t empty_path = {
243 CAIRO_STATUS_SUCCESS,
244 adg_test_path()->data,
247 cairo_path_t basic_path = {
248 CAIRO_STATUS_SUCCESS,
249 adg_test_path()->data,
252 cairo_path_t invalid_path1 = {
253 CAIRO_STATUS_SUCCESS,
254 adg_test_path()->data,
255 3 /* Should be 4 */
257 cairo_path_t invalid_path2 = {
258 CAIRO_STATUS_SUCCESS,
259 invalid_primitive,
260 G_N_ELEMENTS(invalid_primitive)
263 g_assert_cmpint(cpml_segment_from_cairo(&segment, &noop_path), ==, 0);
264 g_assert_cmpint(cpml_segment_from_cairo(&segment, &empty_path), ==, 0);
265 g_assert_cmpint(cpml_segment_from_cairo(&segment, &basic_path), ==, 1);
266 g_assert_cmpint(cpml_segment_from_cairo(&segment, &invalid_path1), ==, 0);
267 g_assert_cmpint(cpml_segment_from_cairo(&segment, &invalid_path2), ==, 0);
268 g_assert_cmpint(cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()), ==, 1);
271 static void
272 _cpml_test_get_length(void)
274 CpmlSegment segment;
276 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
278 /* First segment: not a round number so avoiding == */
279 g_assert_cmpfloat(cpml_segment_get_length(&segment), >, 0);
281 cpml_segment_next(&segment);
283 /* Second segment */
284 g_assert_cmpfloat(cpml_segment_get_length(&segment), ==, 3);
285 g_assert_cmpfloat(cpml_segment_get_length(&segment), ==, 3);
287 cpml_segment_next(&segment);
289 /* Third segment */
290 /* TODO: Bézier curve length not yet implemented
291 * g_assert_cmpfloat(cpml_segment_get_length(&segment), >, 0); */
293 cpml_segment_next(&segment);
295 /* Forth segment */
296 adg_assert_isapprox(cpml_segment_get_length(&segment), 13.114);
298 cpml_segment_next(&segment);
300 /* Fifth segment */
301 g_assert_cmpfloat(cpml_segment_get_length(&segment), ==, 0);
304 static void
305 _cpml_test_put_intersections(void)
307 CpmlSegment segment1, segment2;
308 CpmlPair pair[10];
310 cpml_segment_from_cairo(&segment1, (cairo_path_t *) adg_test_path());
311 cpml_segment_copy(&segment2, &segment1);
313 cpml_segment_next(&segment2);
315 /* The first segment intersects the second segment in (1, 1).
316 * TODO: avoid extrapolated intersections! Check
317 * cpml_primitive_put_intersections */
318 g_assert_cmpuint(cpml_segment_put_intersections(&segment1, &segment2, 10, pair), ==, 3);
319 g_assert_cmpfloat(pair[0].x, ==, 1);
320 g_assert_cmpfloat(pair[0].y, ==, 1);
321 g_assert_cmpfloat(pair[1].x, ==, 2);
322 g_assert_cmpfloat(pair[1].y, ==, 0);
324 cpml_segment_next(&segment2);
326 g_assert_cmpuint(cpml_segment_put_intersections(&segment1, &segment2, 10, pair), ==, 1);
329 static void
330 _cpml_test_offset(void)
332 CpmlSegment original, *segment;
334 /* Work on a copy to avoid modifying adg_test_path() data */
335 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
336 segment = cpml_segment_deep_dup(&original);
338 /* TODO: provide tests for arcs and curves */
339 cpml_segment_offset(segment, 1);
340 g_free(segment);
342 cpml_segment_next(&original);
343 segment = cpml_segment_deep_dup(&original);
344 cpml_segment_offset(segment, 1);
346 g_assert_cmpint(segment->data[0].header.type, ==, CPML_MOVE);
347 g_assert_cmpfloat(segment->data[1].point.x, ==, 0);
348 g_assert_cmpfloat(segment->data[1].point.y, ==, 1);
350 g_assert_cmpint(segment->data[2].header.type, ==, CPML_LINE);
351 g_assert_cmpfloat(segment->data[3].point.x, ==, 0);
352 g_assert_cmpfloat(segment->data[3].point.y, ==, 1);
354 g_assert_cmpint(segment->data[4].header.type, ==, CPML_LINE);
355 g_assert_cmpfloat(segment->data[5].point.x, ==, 0);
356 g_assert_cmpfloat(segment->data[5].point.y, ==, 2);
358 g_free(segment);
361 static void
362 _cpml_test_transform(void)
364 CpmlSegment original, *segment;
365 cairo_matrix_t matrix;
367 /* Work on a copy to avoid modifying adg_test_path() data */
368 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
369 segment = cpml_segment_deep_dup(&original);
371 cairo_matrix_init_translate(&matrix, 1, 2);
372 cpml_segment_transform(segment, &matrix);
374 g_assert_cmpint(segment->data[0].header.type, ==, CPML_MOVE);
375 g_assert_cmpfloat(segment->data[1].point.x, ==, 1);
376 g_assert_cmpfloat(segment->data[1].point.y, ==, 3);
378 g_assert_cmpint(segment->data[2].header.type, ==, CPML_LINE);
379 g_assert_cmpfloat(segment->data[3].point.x, ==, 4);
380 g_assert_cmpfloat(segment->data[3].point.y, ==, 3);
382 g_assert_cmpint(segment->data[4].header.type, ==, CPML_ARC);
383 g_assert_cmpfloat(segment->data[5].point.x, ==, 5);
384 g_assert_cmpfloat(segment->data[5].point.y, ==, 7);
385 g_assert_cmpfloat(segment->data[6].point.x, ==, 7);
386 g_assert_cmpfloat(segment->data[6].point.y, ==, 9);
388 g_assert_cmpint(segment->data[7].header.type, ==, CPML_CURVE);
389 g_assert_cmpfloat(segment->data[8].point.x, ==, 9);
390 g_assert_cmpfloat(segment->data[8].point.y, ==, 11);
391 g_assert_cmpfloat(segment->data[9].point.x, ==, 11);
392 g_assert_cmpfloat(segment->data[9].point.y, ==, 13);
393 g_assert_cmpfloat(segment->data[10].point.x, ==, -1);
394 g_assert_cmpfloat(segment->data[10].point.y, ==, 4);
396 g_assert_cmpint(segment->data[11].header.type, ==, CPML_CLOSE);
398 g_free(segment);
401 #include <stdio.h>
402 static void
403 _cpml_test_reverse(void)
405 CpmlSegment original, *segment;
407 /* Work on a copy to avoid modifying adg_test_path() data */
408 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
409 segment = cpml_segment_deep_dup(&original);
411 /* First segment */
412 cpml_segment_reverse(segment);
414 g_assert_cmpint(segment->num_data, ==, 12);
416 g_assert_cmpint(segment->data[0].header.type, ==, CPML_MOVE);
417 g_assert_cmpfloat(segment->data[1].point.x, ==, -2);
418 g_assert_cmpfloat(segment->data[1].point.y, ==, 2);
420 g_assert_cmpint(segment->data[2].header.type, ==, CPML_CURVE);
421 g_assert_cmpfloat(segment->data[3].point.x, ==, 10);
422 g_assert_cmpfloat(segment->data[3].point.y, ==, 11);
423 g_assert_cmpfloat(segment->data[4].point.x, ==, 8);
424 g_assert_cmpfloat(segment->data[4].point.y, ==, 9);
425 g_assert_cmpfloat(segment->data[5].point.x, ==, 6);
426 g_assert_cmpfloat(segment->data[5].point.y, ==, 7);
428 g_assert_cmpint(segment->data[6].header.type, ==, CPML_ARC);
429 g_assert_cmpfloat(segment->data[7].point.x, ==, 4);
430 g_assert_cmpfloat(segment->data[7].point.y, ==, 5);
431 g_assert_cmpfloat(segment->data[8].point.x, ==, 3);
432 g_assert_cmpfloat(segment->data[8].point.y, ==, 1);
434 g_assert_cmpint(segment->data[9].header.type, ==, CPML_LINE);
435 g_assert_cmpfloat(segment->data[10].point.x, ==, 0);
436 g_assert_cmpfloat(segment->data[10].point.y, ==, 1);
438 g_assert_cmpint(segment->data[11].header.type, ==, CPML_CLOSE);
440 g_free(segment);
443 static void
444 _cpml_test_to_cairo(void)
446 cairo_t *cr;
447 CpmlSegment segment;
448 int length, last_length;
450 cr = adg_test_cairo_context();
451 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
453 g_assert_cmpint(adg_test_cairo_num_data(cr), ==, 0);
455 length = 0;
456 do {
457 last_length = length;
458 cpml_segment_to_cairo(&segment, cr);
459 length = adg_test_cairo_num_data(cr);
460 g_assert_cmpint(length, >, last_length);
461 } while (cpml_segment_next(&segment));
463 cairo_destroy(cr);
466 static void
467 _cpml_test_dump(gint i)
469 CpmlSegment segment;
471 switch (i) {
472 case 1:
473 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
474 cpml_segment_dump(&segment);
475 break;
476 default:
477 g_test_trap_assert_passed();
478 g_test_trap_assert_stderr_unmatched("?");
479 g_test_trap_assert_stdout("*move*line*arc*curve*close*");
480 break;
486 main(int argc, char *argv[])
488 adg_test_init(&argc, &argv);
490 g_test_add_func("/cpml/segment/behavior/browsing", _cpml_test_browsing);
492 adg_test_add_traps("/cpml/segment/sanity/from-cairo", _cpml_test_sanity_from_cairo, 2);
493 adg_test_add_traps("/cpml/segment/sanity/get-length", _cpml_test_sanity_get_length, 1);
494 adg_test_add_traps("/cpml/segment/sanity/put-intersections", _cpml_test_sanity_put_intersections, 3);
495 adg_test_add_traps("/cpml/segment/sanity/offset", _cpml_test_sanity_offset, 1);
496 adg_test_add_traps("/cpml/segment/sanity/transform", _cpml_test_sanity_transform, 2);
497 adg_test_add_traps("/cpml/segment/sanity/reverse", _cpml_test_sanity_reverse, 1);
498 adg_test_add_traps("/cpml/segment/sanity/to-cairo", _cpml_test_sanity_to_cairo, 2);
499 adg_test_add_traps("/cpml/segment/sanity/dump", _cpml_test_sanity_dump, 1);
501 g_test_add_func("/cpml/segment/method/from-cairo", _cpml_test_from_cairo);
502 g_test_add_func("/cpml/segment/method/get-length", _cpml_test_get_length);
503 g_test_add_func("/cpml/segment/method/put-intersections", _cpml_test_put_intersections);
504 g_test_add_func("/cpml/segment/method/offset", _cpml_test_offset);
505 g_test_add_func("/cpml/segment/method/transform", _cpml_test_transform);
506 g_test_add_func("/cpml/segment/method/reverse", _cpml_test_reverse);
507 g_test_add_func("/cpml/segment/method/to-cairo", _cpml_test_to_cairo);
508 adg_test_add_traps("/cpml/segment/method/dump", _cpml_test_dump, 1);
510 return g_test_run();