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 static cairo_path_data_t data
[] = {
27 { .header
= { CPML_MOVE
, 2 }},
31 { .header
= { CPML_LINE
, 2 }},
35 { .header
= { CPML_ARC
, 3 }},
40 { .header
= { CPML_CURVE
, 4 }},
42 { .point
= { 10, 11 }},
43 { .point
= { 12, 13 }},
46 { .header
= { CPML_CLOSE
, 1 }}
57 _cpml_test_from_segment(void)
60 CpmlPrimitive primitive
;
62 g_assert_true(cpml_segment_from_cairo(&segment
, &path
));
64 cpml_primitive_from_segment(&primitive
, &segment
);
65 g_assert_nonnull(primitive
.segment
);
66 g_assert_nonnull(primitive
.org
);
67 g_assert_nonnull(primitive
.data
);
69 cpml_primitive_from_segment(&primitive
, NULL
);
70 g_assert_null(primitive
.segment
);
71 g_assert_null(primitive
.org
);
72 g_assert_null(primitive
.data
);
74 cpml_primitive_from_segment(&primitive
, &segment
);
75 g_assert_nonnull(primitive
.segment
);
76 g_assert_nonnull(primitive
.org
);
77 g_assert_nonnull(primitive
.data
);
81 _cpml_test_type_get_n_points(void)
85 n_points
= cpml_primitive_type_get_n_points(CPML_MOVE
);
86 g_assert_cmpuint(n_points
, ==, 0);
88 n_points
= cpml_primitive_type_get_n_points(CPML_LINE
);
89 g_assert_cmpuint(n_points
, ==, 2);
91 n_points
= cpml_primitive_type_get_n_points(CPML_ARC
);
92 g_assert_cmpuint(n_points
, ==, 3);
94 n_points
= cpml_primitive_type_get_n_points(CPML_CURVE
);
95 g_assert_cmpuint(n_points
, ==, 4);
97 n_points
= cpml_primitive_type_get_n_points(CPML_CLOSE
);
98 g_assert_cmpuint(n_points
, ==, 2);
102 _cpml_test_get_n_points(void)
105 CpmlPrimitive primitive
;
108 cpml_segment_from_cairo(&segment
, &path
);
111 cpml_primitive_from_segment(&primitive
, &segment
);
112 n_points
= cpml_primitive_get_n_points(&primitive
);
113 g_assert_cmpuint(n_points
, ==, 2);
116 cpml_primitive_next(&primitive
);
117 n_points
= cpml_primitive_get_n_points(&primitive
);
118 g_assert_cmpuint(n_points
, ==, 3);
121 cpml_primitive_next(&primitive
);
122 n_points
= cpml_primitive_get_n_points(&primitive
);
123 g_assert_cmpuint(n_points
, ==, 4);
125 /* Close: although the end point is not needed, the CPML API
126 * returns 2 points to treat this primitive as a CPML_LINE */
127 cpml_primitive_next(&primitive
);
128 n_points
= cpml_primitive_get_n_points(&primitive
);
129 g_assert_cmpuint(n_points
, ==, 2);
133 _cpml_test_set_point(void)
136 cairo_path_data_t data_copy
[G_N_ELEMENTS(data
)];
137 cairo_path_t path_copy
= {
138 CAIRO_STATUS_SUCCESS
,
143 CpmlPrimitive primitive
;
144 CpmlPair pair
, pair2
;
147 size
= sizeof(data_copy
);
148 memcpy(data_copy
, data
, size
);
150 cpml_segment_from_cairo(&segment
, &path_copy
);
153 cpml_primitive_from_segment(&primitive
, &segment
);
155 equality
= memcmp(data_copy
, data
, size
);
156 g_assert_cmpint(equality
, ==, 0);
157 cpml_primitive_put_point(&primitive
, 0, &pair
);
159 cpml_primitive_set_point(&primitive
, 0, &pair
);
160 equality
= memcmp(data_copy
, data
, size
);
161 g_assert_cmpint(equality
, !=, 0);
163 cpml_primitive_set_point(&primitive
, 0, &pair
);
164 equality
= memcmp(data_copy
, data
, size
);
165 g_assert_cmpint(equality
, ==, 0);
166 cpml_primitive_put_point(&primitive
, 1, &pair
);
168 cpml_primitive_set_point(&primitive
, 1, &pair
);
169 equality
= memcmp(data_copy
, data
, size
);
170 g_assert_cmpint(equality
, !=, 0);
171 /* On a CPML_LINE primitives, -1 and 1 indices are equals */
172 cpml_primitive_put_point(&primitive
, -1, &pair2
);
173 g_assert_cmpfloat(pair
.x
, ==, pair2
.x
);
174 g_assert_cmpfloat(pair
.y
, ==, pair2
.y
);
175 memcpy(data_copy
, data
, size
);
176 equality
= memcmp(data_copy
, data
, size
);
177 g_assert_cmpint(equality
, ==, 0);
178 cpml_primitive_put_point(&primitive
, 2, &pair
);
181 /* This should be a NOP without segfaults */
182 cpml_primitive_set_point(&primitive
, 2, &pair
);
183 equality
= memcmp(data_copy
, data
, size
);
184 g_assert_cmpint(equality
, ==, 0);
186 /* From now on, memcpy() is assumed to force equality (as yet
187 * proved by the previous assertions) and pair2 is used as a
188 * different-from-everything pair, that is setting pair2 on any
189 * point will break the equality between data and data_copy
195 cpml_primitive_next(&primitive
);
197 cpml_primitive_set_point(&primitive
, 0, &pair2
);
198 equality
= memcmp(data_copy
, data
, size
);
199 g_assert_cmpint(equality
, !=, 0);
200 memcpy(data_copy
, data
, size
);
201 cpml_primitive_set_point(&primitive
, 1, &pair2
);
202 equality
= memcmp(data_copy
, data
, size
);
203 g_assert_cmpint(equality
, !=, 0);
204 memcpy(data_copy
, data
, size
);
205 cpml_primitive_set_point(&primitive
, 2, &pair2
);
206 equality
= memcmp(data_copy
, data
, size
);
207 g_assert_cmpint(equality
, !=, 0);
208 memcpy(data_copy
, data
, size
);
209 cpml_primitive_set_point(&primitive
, 3, &pair2
);
210 equality
= memcmp(data_copy
, data
, size
);
211 g_assert_cmpint(equality
, ==, 0);
214 cpml_primitive_next(&primitive
);
216 cpml_primitive_set_point(&primitive
, 0, &pair2
);
217 equality
= memcmp(data_copy
, data
, size
);
218 g_assert_cmpint(equality
, !=, 0);
219 memcpy(data_copy
, data
, size
);
220 cpml_primitive_set_point(&primitive
, 1, &pair2
);
221 equality
= memcmp(data_copy
, data
, size
);
222 g_assert_cmpint(equality
, !=, 0);
223 memcpy(data_copy
, data
, size
);
224 cpml_primitive_set_point(&primitive
, 2, &pair2
);
225 equality
= memcmp(data_copy
, data
, size
);
226 g_assert_cmpint(equality
, !=, 0);
227 memcpy(data_copy
, data
, size
);
228 cpml_primitive_set_point(&primitive
, 3, &pair2
);
229 equality
= memcmp(data_copy
, data
, size
);
230 g_assert_cmpint(equality
, !=, 0);
231 memcpy(data_copy
, data
, size
);
232 cpml_primitive_set_point(&primitive
, 4, &pair2
);
233 equality
= memcmp(data_copy
, data
, size
);
234 g_assert_cmpint(equality
, ==, 0);
237 cpml_primitive_next(&primitive
);
239 cpml_primitive_set_point(&primitive
, 0, &pair2
);
240 equality
= memcmp(data_copy
, data
, size
);
241 g_assert_cmpint(equality
, !=, 0);
242 memcpy(data_copy
, data
, size
);
243 cpml_primitive_set_point(&primitive
, 1, &pair2
);
244 equality
= memcmp(data_copy
, data
, size
);
245 g_assert_cmpint(equality
, !=, 0);
246 memcpy(data_copy
, data
, size
);
247 cpml_primitive_set_point(&primitive
, 2, &pair2
);
248 equality
= memcmp(data_copy
, data
, size
);
249 g_assert_cmpint(equality
, ==, 0);
253 _cpml_test_put_point(void)
256 CpmlPrimitive primitive
;
259 cpml_segment_from_cairo(&segment
, &path
);
262 cpml_primitive_from_segment(&primitive
, &segment
);
264 cpml_primitive_put_point(&primitive
, 0, &pair
);
265 g_assert_cmpfloat(pair
.x
, ==, 0);
266 g_assert_cmpfloat(pair
.y
, ==, 1);
267 cpml_primitive_put_point(&primitive
, 1, &pair
);
268 g_assert_cmpfloat(pair
.x
, ==, 2);
269 g_assert_cmpfloat(pair
.y
, ==, 3);
270 cpml_primitive_put_point(&primitive
, 2, &pair
);
271 g_assert_cmpfloat(pair
.x
, ==, 2);
272 g_assert_cmpfloat(pair
.y
, ==, 3);
273 /* The negative indices are checked only against CPML_LINE */
274 cpml_primitive_put_point(&primitive
, -1, &pair
);
275 g_assert_cmpfloat(pair
.x
, ==, 2);
276 g_assert_cmpfloat(pair
.y
, ==, 3);
277 cpml_primitive_put_point(&primitive
, -2, &pair
);
278 g_assert_cmpfloat(pair
.x
, ==, 0);
279 g_assert_cmpfloat(pair
.y
, ==, 1);
280 cpml_primitive_put_point(&primitive
, -3, &pair
);
281 g_assert_cmpfloat(pair
.x
, ==, 0);
282 g_assert_cmpfloat(pair
.y
, ==, 1);
285 cpml_primitive_next(&primitive
);
287 cpml_primitive_put_point(&primitive
, 0, &pair
);
288 g_assert_cmpfloat(pair
.x
, ==, 2);
289 g_assert_cmpfloat(pair
.y
, ==, 3);
290 cpml_primitive_put_point(&primitive
, 1, &pair
);
291 g_assert_cmpfloat(pair
.x
, ==, 4);
292 g_assert_cmpfloat(pair
.y
, ==, 5);
293 cpml_primitive_put_point(&primitive
, 2, &pair
);
294 g_assert_cmpfloat(pair
.x
, ==, 6);
295 g_assert_cmpfloat(pair
.y
, ==, 7);
296 cpml_primitive_put_point(&primitive
, 3, &pair
);
297 g_assert_cmpfloat(pair
.x
, ==, 6);
298 g_assert_cmpfloat(pair
.y
, ==, 7);
301 cpml_primitive_next(&primitive
);
303 cpml_primitive_put_point(&primitive
, 0, &pair
);
304 g_assert_cmpfloat(pair
.x
, ==, 6);
305 g_assert_cmpfloat(pair
.y
, ==, 7);
306 cpml_primitive_put_point(&primitive
, 1, &pair
);
307 g_assert_cmpfloat(pair
.x
, ==, 8);
308 g_assert_cmpfloat(pair
.y
, ==, 9);
309 cpml_primitive_put_point(&primitive
, 2, &pair
);
310 g_assert_cmpfloat(pair
.x
, ==, 10);
311 g_assert_cmpfloat(pair
.y
, ==, 11);
312 cpml_primitive_put_point(&primitive
, 3, &pair
);
313 g_assert_cmpfloat(pair
.x
, ==, 12);
314 g_assert_cmpfloat(pair
.y
, ==, 13);
315 cpml_primitive_put_point(&primitive
, 4, &pair
);
316 g_assert_cmpfloat(pair
.x
, ==, 12);
317 g_assert_cmpfloat(pair
.y
, ==, 13);
320 cpml_primitive_next(&primitive
);
322 cpml_primitive_put_point(&primitive
, 0, &pair
);
323 g_assert_cmpfloat(pair
.x
, ==, 12);
324 g_assert_cmpfloat(pair
.y
, ==, 13);
325 cpml_primitive_put_point(&primitive
, 1, &pair
);
326 g_assert_cmpfloat(pair
.x
, ==, 0);
327 g_assert_cmpfloat(pair
.y
, ==, 1);
328 cpml_primitive_put_point(&primitive
, 2, &pair
);
329 g_assert_cmpfloat(pair
.x
, ==, 0);
330 g_assert_cmpfloat(pair
.y
, ==, 1);
334 _cpml_test_get_length(void)
336 cairo_path_data_t rectangle_data
[] = {
337 { .header
= { CPML_MOVE
, 2 }},
338 { .point
= { 0, 0 }},
340 { .header
= { CPML_LINE
, 2 }},
341 { .point
= { 2, 0 }},
343 { .header
= { CPML_LINE
, 2 }},
344 { .point
= { 2, 1 }},
346 { .header
= { CPML_LINE
, 2 }},
347 { .point
= { 0, 1 }},
349 { .header
= { CPML_CLOSE
, 1 }}
351 cairo_path_t rectangle
= {
352 CAIRO_STATUS_SUCCESS
,
354 G_N_ELEMENTS(rectangle_data
)
357 CpmlPrimitive primitive
;
359 g_assert_cmpfloat(cpml_primitive_get_length(NULL
), ==, 0);
361 cpml_segment_from_cairo(&segment
, &rectangle
);
363 cpml_primitive_from_segment(&primitive
, &segment
);
364 g_assert_cmpfloat(cpml_primitive_get_length(&primitive
), ==, 2);
366 cpml_primitive_next(&primitive
);
367 g_assert_cmpfloat(cpml_primitive_get_length(&primitive
), ==, 1);
369 cpml_primitive_next(&primitive
);
370 g_assert_cmpfloat(cpml_primitive_get_length(&primitive
), ==, 2);
372 cpml_primitive_next(&primitive
);
373 g_assert_cmpfloat(cpml_primitive_get_length(&primitive
), ==, 1);
377 _cpml_test_put_intersections(void)
379 cairo_path_data_t path1_data
[] = {
380 { .header
= { CPML_MOVE
, 2 }},
381 { .point
= { -2, 1 }},
383 { .header
= { CPML_LINE
, 2 }},
384 { .point
= { 2, 1 }},
386 { .header
= { CPML_LINE
, 2 }},
387 { .point
= { 2, 0 }},
389 { .header
= { CPML_LINE
, 2 }},
390 { .point
= { -2, 0 }}
392 { .header
= { CPML_MOVE
, 2 }},
393 { .point
= { 0, -1 }},
395 { .header
= { CPML_LINE
, 2 }},
398 cairo_path_t path1
= {
399 CAIRO_STATUS_SUCCESS
,
401 G_N_ELEMENTS(path1_data
)
403 CAIRO_STATUS_SUCCESS
,
405 G_N_ELEMENTS(path2_data
)
408 CpmlPrimitive primitive
, primitive2
;
411 cpml_segment_from_cairo(&segment
, &path2
);
412 cpml_primitive_from_segment(&primitive
, &segment
);
414 cpml_segment_from_cairo(&segment
, &path1
);
415 cpml_primitive_from_segment(&primitive2
, &segment
);
417 g_assert_cmpint(cpml_primitive_put_intersections(NULL
, &primitive2
, 2, pair
), ==, 0);
418 g_assert_cmpint(cpml_primitive_put_intersections(&primitive
, NULL
, 2, pair
), ==, 0);
419 g_assert_cmpint(cpml_primitive_put_intersections(NULL
, NULL
, 2, pair
), ==, 0);
420 g_assert_cmpint(cpml_primitive_put_intersections(&primitive
, &primitive2
, 0, pair
), ==, 0);
421 g_assert_cmpint(cpml_primitive_put_intersections(&primitive
, &primitive2
, 2, NULL
), ==, 0);
423 /* The first primitive of path1 intersects path2 in (0, 1) */
424 g_assert_cmpint(cpml_primitive_put_intersections(&primitive
, &primitive2
, 2, pair
), ==, 1);
425 g_assert_cmpfloat(pair
[0].x
, ==, 0);
426 g_assert_cmpfloat(pair
[0].y
, ==, 1);
428 /* The second primitive does not intersect */
429 cpml_primitive_next(&primitive2
);
430 g_assert_cmpint(cpml_primitive_put_intersections(&primitive
, &primitive2
, 2, pair
), ==, 0);
432 /* The third primitive intersects in (0, 0) */
433 cpml_primitive_next(&primitive2
);
434 g_assert_cmpint(cpml_primitive_put_intersections(&primitive
, &primitive2
, 2, pair
), ==, 1);
435 g_assert_cmpfloat(pair
[0].x
, ==, 0);
436 g_assert_cmpfloat(pair
[0].y
, ==, 0);
438 g_assert_cmpint(cpml_primitive_put_intersections_with_segment(NULL
, &segment
, 2, pair
), ==, 0);
439 g_assert_cmpint(cpml_primitive_put_intersections_with_segment(&primitive
, NULL
, 2, pair
), ==, 0);
440 g_assert_cmpint(cpml_primitive_put_intersections_with_segment(NULL
, NULL
, 2, pair
), ==, 0);
441 g_assert_cmpint(cpml_primitive_put_intersections_with_segment(&primitive
, &segment
, 0, pair
), ==, 0);
442 g_assert_cmpint(cpml_primitive_put_intersections_with_segment(&primitive
, &segment
, 2, NULL
), ==, 0);
444 /* path2 intesects path1 in two points */
445 g_assert_cmpint(cpml_primitive_put_intersections_with_segment(&primitive
, &segment
, 2, pair
), ==, 2);
446 g_assert_cmpfloat(pair
[0].x
, ==, 0);
447 g_assert_cmpfloat(pair
[0].y
, ==, 1);
448 g_assert_cmpfloat(pair
[1].x
, ==, 0);
449 g_assert_cmpfloat(pair
[1].y
, ==, 0);
453 _cpml_test_join(void)
455 cairo_path_data_t path_data
[] = {
456 { .header
= { CPML_MOVE
, 2 }},
457 { .point
= { 0, 0 }},
459 { .header
= { CPML_LINE
, 2 }},
460 { .point
= { 2, 0 }},
462 { .header
= { CPML_LINE
, 2 }},
463 { .point
= { 2, 2 }},
465 { .header
= { CPML_LINE
, 2 }},
466 { .point
= { 1, 2 }},
468 { .header
= { CPML_LINE
, 2 }},
469 { .point
= { 1, -2 }}
471 cairo_path_t path
= {
472 CAIRO_STATUS_SUCCESS
,
474 G_N_ELEMENTS(path_data
)
477 CpmlPrimitive primitive1
, primitive2
;
479 cpml_segment_from_cairo(&segment
, &path
);
481 cpml_primitive_from_segment(&primitive1
, &segment
);
482 cpml_primitive_copy(&primitive2
, &primitive1
);
483 cpml_primitive_next(&primitive2
);
485 /* primitive1 and primitive2 are already joint */
486 g_assert_cmpint(cpml_primitive_join(&primitive1
, &primitive2
), ==, 1);
487 g_assert_cmpfloat((primitive2
.org
)->point
.x
, ==, 2);
488 g_assert_cmpfloat((primitive2
.org
)->point
.y
, ==, 0);
490 cpml_primitive_next(&primitive2
);
491 /* Now primitive1 and primitive2 are divergent,
492 * hence cannot be joined */
493 g_assert_cmpint(cpml_primitive_join(&primitive1
, &primitive2
), ==, 0);
495 cpml_primitive_next(&primitive2
);
496 g_assert_cmpint(cpml_primitive_join(&primitive1
, &primitive2
), ==, 1);
497 g_assert_cmpfloat((primitive2
.org
)->point
.x
, ==, 1);
498 g_assert_cmpfloat((primitive2
.org
)->point
.y
, ==, 0);
502 _cpml_test_dump(void)
504 #if GLIB_CHECK_VERSION(2, 38, 0)
505 if (g_test_subprocess()) {
507 CpmlPrimitive primitive
;
509 /* This should not crash the process */
510 cpml_primitive_dump(NULL
, 1);
512 cpml_segment_from_cairo(&segment
, &path
);
513 cpml_primitive_from_segment(&primitive
, &segment
);
514 cpml_primitive_dump(&primitive
, 1);
516 cpml_primitive_next(&primitive
);
517 cpml_primitive_dump(&primitive
, 1);
522 g_test_trap_subprocess(NULL
, 0, 0);
523 g_test_trap_assert_passed();
524 g_test_trap_assert_stderr_unmatched("?");
525 g_test_trap_assert_stdout("*NULL*");
526 g_test_trap_assert_stdout("*move*");
527 g_test_trap_assert_stdout("*line*");
532 _cpml_test_browsing(void)
535 CpmlPrimitive primitive
, primitive_copy
;
537 cpml_segment_from_cairo(&segment
, &path
);
539 cpml_primitive_from_segment(&primitive
, &segment
);
540 g_assert_cmpfloat((primitive
.org
)->point
.x
, ==, 0);
541 g_assert_cmpfloat((primitive
.org
)->point
.y
, ==, 1);
542 g_assert_cmpint((primitive
.data
)->header
.type
, ==, CPML_LINE
);
543 g_assert_true(cpml_primitive_next(&primitive
));
544 g_assert_cmpfloat((primitive
.org
)->point
.x
, ==, 2);
545 g_assert_cmpfloat((primitive
.org
)->point
.y
, ==, 3);
546 g_assert_cmpint((primitive
.data
)->header
.type
, ==, CPML_ARC
);
547 g_assert_true(cpml_primitive_next(&primitive
));
548 g_assert_cmpfloat((primitive
.org
)->point
.x
, ==, 6);
549 g_assert_cmpfloat((primitive
.org
)->point
.y
, ==, 7);
550 g_assert_cmpint((primitive
.data
)->header
.type
, ==, CPML_CURVE
);
551 g_assert_true(cpml_primitive_next(&primitive
));
552 g_assert_cmpfloat((primitive
.org
)->point
.x
, ==, 12);
553 g_assert_cmpfloat((primitive
.org
)->point
.y
, ==, 13);
554 g_assert_cmpint((primitive
.data
)->header
.type
, ==, CPML_CLOSE
);
555 g_assert_false(cpml_primitive_next(&primitive
));
557 cpml_primitive_reset(&primitive
);
558 g_assert_true(cpml_primitive_next(&primitive
));
559 cpml_primitive_reset(&primitive
);
560 cpml_primitive_reset(&primitive
);
561 g_assert_true(cpml_primitive_next(&primitive
));
562 g_assert_true(cpml_primitive_next(&primitive
));
563 g_assert_true(cpml_primitive_next(&primitive
));
564 g_assert_false(cpml_primitive_next(&primitive
));
566 cpml_primitive_copy(&primitive_copy
, &primitive
);
567 g_assert_false(cpml_primitive_next(&primitive_copy
));
568 cpml_primitive_reset(&primitive
);
569 g_assert_false(cpml_primitive_next(&primitive_copy
));
570 cpml_primitive_reset(&primitive_copy
);
571 g_assert_true(cpml_primitive_next(&primitive_copy
));
576 main(int argc
, char *argv
[])
578 adg_test_init(&argc
, &argv
);
580 adg_test_add_func("/cpml/primitive/method/from-segment", _cpml_test_from_segment
);
581 adg_test_add_func("/cpml/primitive/method/type-get-n-points", _cpml_test_type_get_n_points
);
582 adg_test_add_func("/cpml/primitive/method/get-n-points", _cpml_test_get_n_points
);
583 adg_test_add_func("/cpml/primitive/method/set-point", _cpml_test_set_point
);
584 adg_test_add_func("/cpml/primitive/method/put-point", _cpml_test_put_point
);
585 adg_test_add_func("/cpml/primitive/method/get-length", _cpml_test_get_length
);
586 adg_test_add_func("/cpml/primitive/method/put-intersections", _cpml_test_put_intersections
);
587 adg_test_add_func("/cpml/primitive/method/join", _cpml_test_join
);
588 adg_test_add_func("/cpml/primitive/method/dump", _cpml_test_dump
);
590 adg_test_add_func("/cpml/primitive/behavior/browsing", _cpml_test_browsing
);