doc: update copyright line for 2021
[adg.git] / src / cpml / tests / test-primitive.c
blob0d297b9c130e98c34ec879685eea9c53c134c818
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>
23 #include <string.h>
26 static void
27 _cpml_behavior_browsing(void)
29 CpmlSegment segment;
30 CpmlPrimitive primitive, primitive_copy;
32 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
34 cpml_primitive_from_segment(&primitive, &segment);
35 adg_assert_isapprox((primitive.org)->point.x, 0);
36 adg_assert_isapprox((primitive.org)->point.y, 1);
37 g_assert_cmpint((primitive.data)->header.type, ==, CPML_LINE);
38 g_assert_true(cpml_primitive_next(&primitive));
39 adg_assert_isapprox((primitive.org)->point.x, 3);
40 adg_assert_isapprox((primitive.org)->point.y, 1);
41 g_assert_cmpint((primitive.data)->header.type, ==, CPML_ARC);
42 g_assert_true(cpml_primitive_next(&primitive));
43 adg_assert_isapprox((primitive.org)->point.x, 6);
44 adg_assert_isapprox((primitive.org)->point.y, 7);
45 g_assert_cmpint((primitive.data)->header.type, ==, CPML_CURVE);
46 g_assert_true(cpml_primitive_next(&primitive));
47 adg_assert_isapprox((primitive.org)->point.x, -2);
48 adg_assert_isapprox((primitive.org)->point.y, 2);
49 g_assert_cmpint((primitive.data)->header.type, ==, CPML_CLOSE);
50 g_assert_false(cpml_primitive_next(&primitive));
52 cpml_primitive_reset(&primitive);
53 g_assert_true(cpml_primitive_next(&primitive));
54 cpml_primitive_reset(&primitive);
55 cpml_primitive_reset(&primitive);
56 g_assert_true(cpml_primitive_next(&primitive));
57 g_assert_true(cpml_primitive_next(&primitive));
58 g_assert_true(cpml_primitive_next(&primitive));
59 g_assert_false(cpml_primitive_next(&primitive));
61 cpml_primitive_copy(&primitive_copy, &primitive);
62 g_assert_false(cpml_primitive_next(&primitive_copy));
63 cpml_primitive_reset(&primitive);
64 g_assert_false(cpml_primitive_next(&primitive_copy));
65 cpml_primitive_reset(&primitive_copy);
66 g_assert_true(cpml_primitive_next(&primitive_copy));
69 static void
70 _cpml_sanity_type(gint i)
72 switch (i) {
73 case 1:
74 cpml_primitive_type(NULL);
75 break;
76 default:
77 g_test_trap_assert_failed();
78 break;
82 static void
83 _cpml_sanity_from_segment(gint i)
85 CpmlPrimitive primitive;
86 CpmlSegment segment;
88 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
90 switch (i) {
91 case 1:
92 cpml_primitive_from_segment(NULL, &segment);
93 break;
94 case 2:
95 cpml_primitive_from_segment(&primitive, NULL);
96 break;
97 default:
98 g_test_trap_assert_failed();
99 break;
103 static void
104 _cpml_sanity_copy(gint i)
106 CpmlPrimitive primitive;
107 CpmlSegment segment;
109 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
110 cpml_primitive_from_segment(&primitive, &segment);
112 switch (i) {
113 case 1:
114 cpml_primitive_copy(NULL, &primitive);
115 break;
116 case 2:
117 cpml_primitive_copy(&primitive, NULL);
118 break;
119 default:
120 g_test_trap_assert_failed();
121 break;
125 static void
126 _cpml_sanity_copy_data(gint i)
128 CpmlPrimitive primitive;
129 CpmlSegment segment;
131 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
132 cpml_primitive_from_segment(&primitive, &segment);
134 switch (i) {
135 case 1:
136 cpml_primitive_copy_data(NULL, &primitive);
137 break;
138 case 2:
139 cpml_primitive_copy_data(&primitive, NULL);
140 break;
141 default:
142 g_test_trap_assert_failed();
143 break;
147 static void
148 _cpml_sanity_get_n_points(gint i)
150 switch (i) {
151 case 1:
152 cpml_primitive_get_n_points(NULL);
153 break;
154 default:
155 g_test_trap_assert_failed();
156 break;
160 static void
161 _cpml_sanity_get_length(gint i)
163 switch (i) {
164 case 1:
165 cpml_primitive_get_length(NULL);
166 break;
167 default:
168 g_test_trap_assert_failed();
169 break;
173 static void
174 _cpml_sanity_put_extents(gint i)
176 CpmlSegment segment;
177 CpmlPrimitive primitive;
178 CpmlExtents extents;
180 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
181 cpml_primitive_from_segment(&primitive, &segment);
183 switch (i) {
184 case 1:
185 cpml_primitive_put_extents(NULL, &extents);
186 break;
187 case 2:
188 cpml_primitive_put_extents(&primitive, NULL);
189 break;
190 default:
191 g_test_trap_assert_failed();
192 break;
196 static void
197 _cpml_sanity_put_pair_at(gint i)
199 CpmlSegment segment;
200 CpmlPrimitive primitive;
201 CpmlPair pair;
203 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
204 cpml_primitive_from_segment(&primitive, &segment);
206 switch (i) {
207 case 1:
208 cpml_primitive_put_pair_at(NULL, 1, &pair);
209 break;
210 case 2:
211 cpml_primitive_put_pair_at(&primitive, 1, NULL);
212 break;
213 default:
214 g_test_trap_assert_failed();
215 break;
219 static void
220 _cpml_sanity_put_vector_at(gint i)
222 CpmlSegment segment;
223 CpmlPrimitive primitive;
224 CpmlVector vector;
226 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
227 cpml_primitive_from_segment(&primitive, &segment);
229 switch (i) {
230 case 1:
231 cpml_primitive_put_vector_at(NULL, 1, &vector);
232 break;
233 case 2:
234 cpml_primitive_put_vector_at(&primitive, 1, NULL);
235 break;
236 default:
237 g_test_trap_assert_failed();
238 break;
242 static void
243 _cpml_sanity_get_closest_pos(gint i)
245 CpmlSegment segment;
246 CpmlPrimitive primitive;
247 CpmlPair pair = { 1, 1 };
249 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
250 cpml_primitive_from_segment(&primitive, &segment);
252 switch (i) {
253 case 1:
254 cpml_primitive_get_closest_pos(NULL, &pair);
255 break;
256 case 2:
257 cpml_primitive_get_closest_pos(&primitive, NULL);
258 break;
259 default:
260 g_test_trap_assert_failed();
261 break;
265 static void
266 _cpml_sanity_set_point(gint i)
268 CpmlSegment segment;
269 CpmlPrimitive primitive;
270 CpmlPair pair = { 1, 1 };
272 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
273 cpml_primitive_from_segment(&primitive, &segment);
275 switch (i) {
276 case 1:
277 cpml_primitive_set_point(NULL, 1, &pair);
278 break;
279 case 2:
280 cpml_primitive_set_point(&primitive, 1, NULL);
281 break;
282 default:
283 g_test_trap_assert_failed();
284 break;
288 static void
289 _cpml_sanity_put_point(gint i)
291 CpmlSegment segment;
292 CpmlPrimitive primitive;
293 CpmlPair pair;
295 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
296 cpml_primitive_from_segment(&primitive, &segment);
298 switch (i) {
299 case 1:
300 cpml_primitive_put_point(NULL, 0, &pair);
301 break;
302 case 2:
303 cpml_primitive_put_point(&primitive, 0, NULL);
304 break;
305 default:
306 g_test_trap_assert_failed();
307 break;
311 static void
312 _cpml_sanity_put_intersections(gint i)
314 CpmlSegment segment;
315 CpmlPrimitive primitive1, primitive2;
316 CpmlPair pair;
318 /* Set primitive1 to 1.1 and primitive 2 to 2.2,
319 * so there is an intersection point in (1, 1) */
320 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
321 cpml_primitive_from_segment(&primitive1, &segment);
323 cpml_segment_next(&segment);
324 cpml_primitive_from_segment(&primitive2, &segment);
325 cpml_primitive_next(&primitive2);
327 switch (i) {
328 case 1:
329 cpml_primitive_put_intersections(NULL, &primitive2, 2, &pair);
330 break;
331 case 2:
332 cpml_primitive_put_intersections(&primitive1, NULL, 2, &pair);
333 break;
334 case 3:
335 cpml_primitive_put_intersections(&primitive1, &primitive2, 2, NULL);
336 break;
337 default:
338 g_test_trap_assert_failed();
339 break;
343 static void
344 _cpml_sanity_put_intersections_with_segment(gint i)
346 CpmlPrimitive primitive;
347 CpmlSegment segment;
348 CpmlPair pair;
350 /* Set primitive 1.1 and segment to 2
351 * so there is an intersection point in (1,1) */
352 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
353 cpml_primitive_from_segment(&primitive, &segment);
355 cpml_segment_next(&segment);
357 switch (i) {
358 case 1:
359 cpml_primitive_put_intersections_with_segment(NULL, &segment, 2, &pair);
360 break;
361 case 2:
362 cpml_primitive_put_intersections_with_segment(&primitive, NULL, 2, &pair);
363 break;
364 case 3:
365 cpml_primitive_put_intersections_with_segment(&primitive, &segment, 2, NULL);
366 break;
367 default:
368 g_test_trap_assert_failed();
369 break;
373 static void
374 _cpml_sanity_join(gint i)
376 CpmlSegment segment;
377 CpmlPrimitive primitive;
379 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
380 cpml_primitive_from_segment(&primitive, &segment);
382 switch (i) {
383 case 1:
384 cpml_primitive_join(NULL, &primitive);
385 break;
386 case 2:
387 cpml_primitive_join(&primitive, NULL);
388 break;
389 default:
390 g_test_trap_assert_failed();
391 break;
395 static void
396 _cpml_sanity_offset(gint i)
398 switch (i) {
399 case 1:
400 cpml_primitive_offset(NULL, 1);
401 break;
402 default:
403 g_test_trap_assert_failed();
404 break;
408 static void
409 _cpml_sanity_dump(gint i)
411 switch (i) {
412 case 1:
413 cpml_segment_dump(NULL);
414 break;
415 default:
416 g_test_trap_assert_failed();
417 break;
421 static void
422 _cpml_sanity_to_cairo(gint i)
424 CpmlSegment segment;
425 CpmlPrimitive primitive;
427 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
428 cpml_primitive_from_segment(&primitive, &segment);
430 switch (i) {
431 case 1:
432 cpml_primitive_to_cairo(NULL, adg_test_cairo_context());
433 break;
434 case 2:
435 cpml_primitive_to_cairo(&primitive, NULL);
436 break;
437 default:
438 g_test_trap_assert_failed();
439 break;
443 static void
444 _cpml_method_type(void)
446 CpmlSegment segment;
447 CpmlPrimitive primitive;
449 g_assert_true(cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()));
451 cpml_primitive_from_segment(&primitive, &segment);
452 g_assert_cmpint(cpml_primitive_type(&primitive), ==, CPML_LINE);
454 cpml_primitive_next(&primitive);
455 g_assert_cmpint(cpml_primitive_type(&primitive), ==, CPML_ARC);
457 cpml_primitive_next(&primitive);
458 g_assert_cmpint(cpml_primitive_type(&primitive), ==, CPML_CURVE);
460 cpml_primitive_next(&primitive);
461 g_assert_cmpint(cpml_primitive_type(&primitive), ==, CPML_CLOSE);
464 static void
465 _cpml_method_from_segment(void)
467 CpmlSegment segment;
468 CpmlPrimitive primitive;
470 g_assert_true(cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()));
472 cpml_primitive_from_segment(&primitive, &segment);
473 g_assert_nonnull(primitive.segment);
474 g_assert_nonnull(primitive.org);
475 g_assert_nonnull(primitive.data);
478 static void
479 _cpml_method_copy(void)
481 CpmlSegment segment;
482 CpmlPrimitive original;
483 CpmlPrimitive primitive = { NULL, NULL, NULL };
485 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
486 cpml_primitive_from_segment(&original, &segment);
488 g_assert_false(original.segment == primitive.segment);
489 g_assert_false(original.org == primitive.org);
490 g_assert_false(original.data == primitive.data);
492 cpml_primitive_copy(&primitive, &original);
494 g_assert_true(original.segment == primitive.segment);
495 g_assert_true(original.org == primitive.org);
496 g_assert_true(original.data == primitive.data);
499 static void
500 _cpml_method_copy_data(void)
502 CpmlSegment segment;
503 CpmlPrimitive original, *primitive;
504 int n;
506 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
507 cpml_primitive_from_segment(&original, &segment);
509 /* Check incompatible primitives are not copied */
510 primitive = cpml_primitive_deep_dup(&original);
511 ++primitive->data[0].header.length;
512 g_assert_cmpint(cpml_primitive_copy_data(primitive, &original), ==, 0);
513 --primitive->data[0].header.length;
514 ++primitive->data[0].header.type;
515 g_assert_cmpint(cpml_primitive_copy_data(primitive, &original), ==, 0);
516 --primitive->data[0].header.type;
518 do {
519 primitive = cpml_primitive_deep_dup(&original);
520 ++primitive->org->point.x;
521 ++primitive->org->point.y;
522 for (n = 1; n < primitive->data[0].header.length; ++n) {
523 ++primitive->data[n].point.x;
524 ++primitive->data[n].point.y;
526 g_assert_cmpfloat(primitive->org->point.x, !=, original.org->point.x);
527 g_assert_cmpfloat(primitive->org->point.y, !=, original.org->point.y);
528 for (n = 1; n < primitive->data[0].header.length; ++n) {
529 g_assert_cmpfloat(primitive->data[n].point.x, !=, original.data[n].point.x);
530 g_assert_cmpfloat(primitive->data[n].point.y, !=, original.data[n].point.y);
532 g_assert_cmpint(cpml_primitive_copy_data(primitive, &original), ==, 1);
533 adg_assert_isapprox(primitive->org->point.x, original.org->point.x);
534 adg_assert_isapprox(primitive->org->point.y, original.org->point.y);
535 for (n = 1; n < primitive->data[0].header.length; ++n) {
536 adg_assert_isapprox(primitive->data[n].point.x, original.data[n].point.x);
537 adg_assert_isapprox(primitive->data[n].point.y, original.data[n].point.y);
539 g_free(primitive);
540 } while (cpml_primitive_next(&original));
543 static void
544 _cpml_method_type_get_n_points(void)
546 size_t n_points;
548 n_points = cpml_primitive_type_get_n_points(CPML_MOVE);
549 g_assert_cmpuint(n_points, ==, 0);
551 n_points = cpml_primitive_type_get_n_points(CPML_LINE);
552 g_assert_cmpuint(n_points, ==, 2);
554 n_points = cpml_primitive_type_get_n_points(CPML_ARC);
555 g_assert_cmpuint(n_points, ==, 3);
557 n_points = cpml_primitive_type_get_n_points(CPML_CURVE);
558 g_assert_cmpuint(n_points, ==, 4);
560 n_points = cpml_primitive_type_get_n_points(CPML_CLOSE);
561 g_assert_cmpuint(n_points, ==, 2);
564 static void
565 _cpml_method_get_n_points(void)
567 CpmlSegment segment;
568 CpmlPrimitive primitive;
569 size_t n_points;
571 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
573 /* Line */
574 cpml_primitive_from_segment(&primitive, &segment);
575 n_points = cpml_primitive_get_n_points(&primitive);
576 g_assert_cmpuint(n_points, ==, 2);
578 /* Arc */
579 cpml_primitive_next(&primitive);
580 n_points = cpml_primitive_get_n_points(&primitive);
581 g_assert_cmpuint(n_points, ==, 3);
583 /* Curve */
584 cpml_primitive_next(&primitive);
585 n_points = cpml_primitive_get_n_points(&primitive);
586 g_assert_cmpuint(n_points, ==, 4);
588 /* Close: although the end point is not needed, the CPML API
589 * returns 2 points to treat this primitive as a CPML_LINE */
590 cpml_primitive_next(&primitive);
591 n_points = cpml_primitive_get_n_points(&primitive);
592 g_assert_cmpuint(n_points, ==, 2);
595 static void
596 _cpml_method_get_length(void)
598 CpmlSegment segment;
599 CpmlPrimitive primitive;
601 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
602 cpml_segment_next(&segment);
603 cpml_primitive_from_segment(&primitive, &segment);
605 adg_assert_isapprox(cpml_primitive_get_length(&primitive), 1);
607 cpml_primitive_next(&primitive);
608 adg_assert_isapprox(cpml_primitive_get_length(&primitive), 2);
611 static void
612 _cpml_method_put_extents(void)
614 CpmlSegment segment;
615 CpmlPrimitive primitive;
616 CpmlExtents extents;
618 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
620 /* Line */
621 cpml_primitive_from_segment(&primitive, &segment);
622 cpml_primitive_put_extents(&primitive, &extents);
623 g_assert_true(extents.is_defined);
624 adg_assert_isapprox(extents.org.x, 0);
625 adg_assert_isapprox(extents.org.y, 1);
626 adg_assert_isapprox(extents.size.x, 3);
627 adg_assert_isapprox(extents.size.y, 0);
629 /* Arc: the extents are computed precisely... let's ensure
630 * at least all the 3 points are included */
631 cpml_primitive_next(&primitive);
632 cpml_primitive_put_extents(&primitive, &extents);
633 g_assert_true(extents.is_defined);
634 g_assert_cmpfloat(extents.org.x, <=, 3);
635 g_assert_cmpfloat(extents.org.y, <=, 1);
636 g_assert_cmpfloat(extents.size.x, >=, 3);
637 g_assert_cmpfloat(extents.size.y, >=, 6);
639 /* Curve: actually the extents are computed by using the
640 * convex hull (hence the exact coordinates of the points) */
641 cpml_primitive_next(&primitive);
642 cpml_primitive_put_extents(&primitive, &extents);
643 g_assert_true(extents.is_defined);
644 adg_assert_isapprox(extents.org.x, -2);
645 adg_assert_isapprox(extents.org.y, 2);
646 adg_assert_isapprox(extents.size.x, 12);
647 adg_assert_isapprox(extents.size.y, 9);
649 /* Close */
650 cpml_primitive_next(&primitive);
651 cpml_primitive_put_extents(&primitive, &extents);
652 g_assert_true(extents.is_defined);
653 adg_assert_isapprox(extents.org.x, -2);
654 adg_assert_isapprox(extents.org.y, 1);
655 adg_assert_isapprox(extents.size.x, 2);
656 adg_assert_isapprox(extents.size.y, 1);
659 static void
660 _cpml_method_put_pair_at(void)
662 CpmlSegment segment;
663 CpmlPrimitive primitive;
664 CpmlPair pair;
666 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
668 /* Line */
669 cpml_primitive_from_segment(&primitive, &segment);
670 cpml_primitive_put_pair_at(&primitive, 0, &pair);
671 adg_assert_isapprox(pair.x, 0);
672 adg_assert_isapprox(pair.y, 1);
673 cpml_primitive_put_pair_at(&primitive, 1, &pair);
674 adg_assert_isapprox(pair.x, 3);
675 adg_assert_isapprox(pair.y, 1);
676 cpml_primitive_put_pair_at(&primitive, 0.5, &pair);
677 adg_assert_isapprox(pair.x, 1.5);
678 adg_assert_isapprox(pair.y, 1);
680 /* Arc */
681 cpml_primitive_next(&primitive);
682 cpml_primitive_put_pair_at(&primitive, 0, &pair);
683 adg_assert_isapprox(pair.x, 3);
684 adg_assert_isapprox(pair.y, 1);
685 cpml_primitive_put_pair_at(&primitive, 1, &pair);
686 adg_assert_isapprox(pair.x, 6);
687 adg_assert_isapprox(pair.y, 7);
688 cpml_primitive_put_pair_at(&primitive, 0.5, &pair);
689 adg_assert_isapprox(pair.x, 3.669);
690 adg_assert_isapprox(pair.y, 4.415);
692 /* Close */
693 cpml_primitive_next(&primitive);
694 /* TODO: not yet implemented
695 * cpml_primitive_put_pair_at(&primitive, 0, &pair);
696 * adg_assert_isapprox(pair.x, 6);
697 * adg_assert_isapprox(pair.y, 7);
698 * cpml_primitive_put_pair_at(&primitive, 1, &pair);
699 * adg_assert_isapprox(pair.x, -2);
700 * adg_assert_isapprox(pair.y, 2);
701 * cpml_primitive_put_pair_at(&primitive, 0.5, &pair);
702 * adg_assert_isapprox(pair.x, 1);
703 * adg_assert_isapprox(pair.y, 1); */
705 /* Close */
706 cpml_primitive_next(&primitive);
707 cpml_primitive_put_pair_at(&primitive, 0, &pair);
708 adg_assert_isapprox(pair.x, -2);
709 adg_assert_isapprox(pair.y, 2);
710 cpml_primitive_put_pair_at(&primitive, 1, &pair);
711 adg_assert_isapprox(pair.x, 0);
712 adg_assert_isapprox(pair.y, 1);
713 cpml_primitive_put_pair_at(&primitive, 0.5, &pair);
714 adg_assert_isapprox(pair.x, -1);
715 adg_assert_isapprox(pair.y, 1.5);
718 static void
719 _cpml_method_put_vector_at(void)
721 CpmlSegment segment;
722 CpmlPrimitive primitive;
723 CpmlVector vector;
725 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
727 /* Line */
728 cpml_primitive_from_segment(&primitive, &segment);
729 cpml_primitive_put_vector_at(&primitive, 0, &vector);
730 adg_assert_isapprox(vector.x, 3);
731 adg_assert_isapprox(vector.y, 0);
732 cpml_primitive_put_vector_at(&primitive, 1, &vector);
733 adg_assert_isapprox(vector.x, 3);
734 adg_assert_isapprox(vector.y, 0);
735 cpml_primitive_put_vector_at(&primitive, 0.5, &vector);
736 adg_assert_isapprox(vector.x, 3);
737 adg_assert_isapprox(vector.y, 0);
739 /* Arc */
740 cpml_primitive_next(&primitive);
741 cpml_primitive_put_vector_at(&primitive, 0, &vector);
742 adg_assert_isapprox(vector.x, -0.077);
743 adg_assert_isapprox(vector.y, 0.997);
744 cpml_primitive_put_vector_at(&primitive, 1, &vector);
745 adg_assert_isapprox(vector.x, 0.844);
746 adg_assert_isapprox(vector.y, 0.537);
747 cpml_primitive_put_vector_at(&primitive, 0.5, &vector);
748 adg_assert_isapprox(vector.x, 0.447);
749 adg_assert_isapprox(vector.y, 0.894);
751 /* Close */
752 cpml_primitive_next(&primitive);
753 /* TODO: not yet implemented
754 * cpml_primitive_put_vector_at(&primitive, 0, &vector);
755 * adg_assert_isapprox(vector.x, 6);
756 * adg_assert_isapprox(vector.y, 7);
757 * cpml_primitive_put_vector_at(&primitive, 1, &vector);
758 * adg_assert_isapprox(vector.x, -2);
759 * adg_assert_isapprox(vector.y, 2);
760 * cpml_primitive_put_vector_at(&primitive, 0.5, &vector);
761 * adg_assert_isapprox(vector.x, 1);
762 * adg_assert_isapprox(vector.y, 1); */
764 /* Close */
765 cpml_primitive_next(&primitive);
766 cpml_primitive_put_vector_at(&primitive, 0, &vector);
767 adg_assert_isapprox(vector.x, 2);
768 adg_assert_isapprox(vector.y, -1);
769 cpml_primitive_put_vector_at(&primitive, 1, &vector);
770 adg_assert_isapprox(vector.x, 2);
771 adg_assert_isapprox(vector.y, -1);
772 cpml_primitive_put_vector_at(&primitive, 0.5, &vector);
773 adg_assert_isapprox(vector.x, 2);
774 adg_assert_isapprox(vector.y, -1);
777 static void
778 _cpml_method_get_closest_pos(void)
780 CpmlSegment segment;
781 CpmlPrimitive primitive;
782 CpmlPair pair;
784 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
785 cpml_primitive_from_segment(&primitive, &segment);
787 /* Line */
788 pair.x = 0; pair.y = 1;
789 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
790 pair.x = 3; pair.y = 1;
791 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
792 pair.x = -1; pair.y = -1;
793 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
794 pair.x = 4; pair.y = 2;
795 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
796 pair.x = 1.5; pair.y = 0;
797 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0.5);
799 /* Arc */
800 cpml_primitive_next(&primitive);
801 /* TODO: not yet implemented
802 * pair.x = 3; pair.y = 1;
803 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
804 * pair.x = 6; pair.y = 7;
805 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
806 * pair.x = 0; pair.y = 0;
807 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
808 * pair.x = 10; pair.y = 10;
809 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
812 /* Close */
813 cpml_primitive_next(&primitive);
814 /* TODO: not yet implemented
815 * pair.x = 6; pair.y = 7;
816 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
817 * pair.x = -2; pair.y = 2;
818 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
819 * pair.x = 10; pair.y = 10;
820 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
821 * pair.x = 0; pair.y = 0;
822 * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
825 /* Close */
826 cpml_primitive_next(&primitive);
827 pair.x = -2; pair.y = 2;
828 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
829 pair.x = 0; pair.y = 1;
830 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
831 pair.x = -3; pair.y = 3;
832 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0);
833 pair.x = 1; pair.y = 0;
834 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1);
835 pair.x = -1; pair.y = 1.5;
836 adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0.5);
839 static void
840 _cpml_method_set_point(void)
842 gsize data_size;
843 CpmlSegment original, *segment;
844 CpmlPrimitive primitive;
845 CpmlPair pair, pair2;
846 int equality;
848 /* Work on a copy to not modify the original path data */
849 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
850 data_size = original.num_data * sizeof(cairo_path_data_t);
851 segment = cpml_segment_deep_dup(&original);
853 /* Line */
854 cpml_primitive_from_segment(&primitive, segment);
856 equality = memcmp(original.data, segment->data, data_size);
857 g_assert_cmpint(equality, ==, 0);
858 cpml_primitive_put_point(&primitive, 0, &pair);
859 pair.x += 1;
860 cpml_primitive_set_point(&primitive, 0, &pair);
861 equality = memcmp(original.data, segment->data, data_size);
862 g_assert_cmpint(equality, !=, 0);
863 pair.x -= 1;
864 cpml_primitive_set_point(&primitive, 0, &pair);
865 equality = memcmp(original.data, segment->data, data_size);
866 g_assert_cmpint(equality, ==, 0);
867 cpml_primitive_put_point(&primitive, 1, &pair);
868 pair.y += 1;
869 cpml_primitive_set_point(&primitive, 1, &pair);
870 equality = memcmp(original.data, segment->data, data_size);
871 g_assert_cmpint(equality, !=, 0);
872 /* On a CPML_LINE primitives, -1 and 1 indices are equals */
873 cpml_primitive_put_point(&primitive, -1, &pair2);
874 adg_assert_isapprox(pair.x, pair2.x);
875 adg_assert_isapprox(pair.y, pair2.y);
876 memcpy(segment->data, original.data, data_size);
877 equality = memcmp(original.data, segment->data, data_size);
878 g_assert_cmpint(equality, ==, 0);
879 cpml_primitive_put_point(&primitive, 2, &pair);
880 pair.x += 1;
881 pair.y += 1;
882 /* This should be a NOP without segfaults */
883 cpml_primitive_set_point(&primitive, 2, &pair);
884 equality = memcmp(original.data, segment->data, data_size);
885 g_assert_cmpint(equality, ==, 0);
887 /* From now on, memcpy() is assumed to force equality (as already
888 * proved by the previous assertions) and pair2 is used as a
889 * different-from-everything pair, that is setting pair2 on any
890 * point will break the equality between segment->data and
891 * original.data
893 pair2.x = 12345;
894 pair2.y = 54321;
896 /* Arc */
897 cpml_primitive_next(&primitive);
899 cpml_primitive_set_point(&primitive, 0, &pair2);
900 equality = memcmp(original.data, segment->data, data_size);
901 g_assert_cmpint(equality, !=, 0);
902 memcpy(segment->data, original.data, data_size);
903 cpml_primitive_set_point(&primitive, 1, &pair2);
904 equality = memcmp(original.data, segment->data, data_size);
905 g_assert_cmpint(equality, !=, 0);
906 memcpy(segment->data, original.data, data_size);
907 cpml_primitive_set_point(&primitive, 2, &pair2);
908 equality = memcmp(original.data, segment->data, data_size);
909 g_assert_cmpint(equality, !=, 0);
910 memcpy(segment->data, original.data, data_size);
911 cpml_primitive_set_point(&primitive, 3, &pair2);
912 equality = memcmp(original.data, segment->data, data_size);
913 g_assert_cmpint(equality, ==, 0);
915 /* Curve */
916 cpml_primitive_next(&primitive);
918 cpml_primitive_set_point(&primitive, 0, &pair2);
919 equality = memcmp(original.data, segment->data, data_size);
920 g_assert_cmpint(equality, !=, 0);
921 memcpy(segment->data, original.data, data_size);
922 cpml_primitive_set_point(&primitive, 1, &pair2);
923 equality = memcmp(original.data, segment->data, data_size);
924 g_assert_cmpint(equality, !=, 0);
925 memcpy(segment->data, original.data, data_size);
926 cpml_primitive_set_point(&primitive, 2, &pair2);
927 equality = memcmp(original.data, segment->data, data_size);
928 g_assert_cmpint(equality, !=, 0);
929 memcpy(segment->data, original.data, data_size);
930 cpml_primitive_set_point(&primitive, 3, &pair2);
931 equality = memcmp(original.data, segment->data, data_size);
932 g_assert_cmpint(equality, !=, 0);
933 memcpy(segment->data, original.data, data_size);
934 cpml_primitive_set_point(&primitive, 4, &pair2);
935 equality = memcmp(original.data, segment->data, data_size);
936 g_assert_cmpint(equality, ==, 0);
938 /* Close */
939 cpml_primitive_next(&primitive);
941 cpml_primitive_set_point(&primitive, 0, &pair2);
942 equality = memcmp(original.data, segment->data, data_size);
943 g_assert_cmpint(equality, !=, 0);
944 memcpy(segment->data, original.data, data_size);
945 cpml_primitive_set_point(&primitive, 1, &pair2);
946 equality = memcmp(original.data, segment->data, data_size);
947 g_assert_cmpint(equality, !=, 0);
948 memcpy(segment->data, original.data, data_size);
949 cpml_primitive_set_point(&primitive, 2, &pair2);
950 equality = memcmp(original.data, segment->data, data_size);
951 g_assert_cmpint(equality, ==, 0);
953 g_free(segment);
956 static void
957 _cpml_method_put_point(void)
959 CpmlSegment segment;
960 CpmlPrimitive primitive;
961 CpmlPair pair;
963 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
965 /* Line */
966 cpml_primitive_from_segment(&primitive, &segment);
968 cpml_primitive_put_point(&primitive, 0, &pair);
969 adg_assert_isapprox(pair.x, 0);
970 adg_assert_isapprox(pair.y, 1);
971 cpml_primitive_put_point(&primitive, 1, &pair);
972 adg_assert_isapprox(pair.x, 3);
973 adg_assert_isapprox(pair.y, 1);
974 cpml_primitive_put_point(&primitive, 2, &pair);
975 adg_assert_isapprox(pair.x, 3);
976 adg_assert_isapprox(pair.y, 1);
977 /* The negative indices are checked only against CPML_LINE */
978 cpml_primitive_put_point(&primitive, -1, &pair);
979 adg_assert_isapprox(pair.x, 3);
980 adg_assert_isapprox(pair.y, 1);
981 cpml_primitive_put_point(&primitive, -2, &pair);
982 adg_assert_isapprox(pair.x, 0);
983 adg_assert_isapprox(pair.y, 1);
984 cpml_primitive_put_point(&primitive, -3, &pair);
985 adg_assert_isapprox(pair.x, 0);
986 adg_assert_isapprox(pair.y, 1);
988 /* Arc */
989 cpml_primitive_next(&primitive);
991 cpml_primitive_put_point(&primitive, 0, &pair);
992 adg_assert_isapprox(pair.x, 3);
993 adg_assert_isapprox(pair.y, 1);
994 cpml_primitive_put_point(&primitive, 1, &pair);
995 adg_assert_isapprox(pair.x, 4);
996 adg_assert_isapprox(pair.y, 5);
997 cpml_primitive_put_point(&primitive, 2, &pair);
998 adg_assert_isapprox(pair.x, 6);
999 adg_assert_isapprox(pair.y, 7);
1000 cpml_primitive_put_point(&primitive, 3, &pair);
1001 adg_assert_isapprox(pair.x, 6);
1002 adg_assert_isapprox(pair.y, 7);
1004 /* Curve */
1005 cpml_primitive_next(&primitive);
1007 cpml_primitive_put_point(&primitive, 0, &pair);
1008 adg_assert_isapprox(pair.x, 6);
1009 adg_assert_isapprox(pair.y, 7);
1010 cpml_primitive_put_point(&primitive, 1, &pair);
1011 adg_assert_isapprox(pair.x, 8);
1012 adg_assert_isapprox(pair.y, 9);
1013 cpml_primitive_put_point(&primitive, 2, &pair);
1014 adg_assert_isapprox(pair.x, 10);
1015 adg_assert_isapprox(pair.y, 11);
1016 cpml_primitive_put_point(&primitive, 3, &pair);
1017 adg_assert_isapprox(pair.x, -2);
1018 adg_assert_isapprox(pair.y, 2);
1019 cpml_primitive_put_point(&primitive, 4, &pair);
1020 adg_assert_isapprox(pair.x, -2);
1021 adg_assert_isapprox(pair.y, 2);
1023 /* Close */
1024 cpml_primitive_next(&primitive);
1026 cpml_primitive_put_point(&primitive, 0, &pair);
1027 adg_assert_isapprox(pair.x, -2);
1028 adg_assert_isapprox(pair.y, 2);
1029 cpml_primitive_put_point(&primitive, 1, &pair);
1030 adg_assert_isapprox(pair.x, 0);
1031 adg_assert_isapprox(pair.y, 1);
1032 cpml_primitive_put_point(&primitive, 2, &pair);
1033 adg_assert_isapprox(pair.x, 0);
1034 adg_assert_isapprox(pair.y, 1);
1037 static void
1038 _cpml_method_put_intersections(void)
1040 CpmlSegment segment;
1041 CpmlPrimitive primitive1, primitive2;
1042 CpmlPair pair[2];
1044 /* Set primitive1 to 1.1 (first segment, first primitive) */
1045 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
1046 cpml_primitive_from_segment(&primitive1, &segment);
1048 /* Set primitive2 to 2.1 (second segment, first primitive) */
1049 cpml_segment_next(&segment);
1050 cpml_primitive_from_segment(&primitive2, &segment);
1052 /* primitive1 (1.1) does not intersect primitive2 (2.1) */
1053 g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 0);
1055 cpml_primitive_next(&primitive2);
1057 /* primitive1 (1.1) intersects primitive2 (2.2) in (1, 1) */
1058 g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 1);
1059 adg_assert_isapprox(pair[0].x, 1);
1060 adg_assert_isapprox(pair[0].y, 1);
1061 g_assert_cmpint(cpml_primitive_is_inside(&primitive1, pair), ==, 1);
1062 g_assert_cmpint(cpml_primitive_is_inside(&primitive2, pair), ==, 1);
1064 /* Check the intersection is not returned when not requested */
1065 g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 0, pair), ==, 0);
1067 cpml_primitive_next(&primitive1);
1069 /* primitive1 (1.2) does not intersect primitive2 (2.2) */
1070 // TODO: g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 0);
1072 cpml_primitive_next(&primitive1);
1074 /* primitive1 (1.3) does not intersect primitive2 (2.2) */
1075 g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 0);
1077 cpml_primitive_next(&primitive1);
1079 /* primitive1 (1.4) intersects primitive2 (2.2), but outside their boundaries */
1080 g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 1);
1081 adg_assert_isapprox(pair[0].x, 1);
1082 adg_assert_isapprox(pair[0].y, -1);
1083 g_assert_cmpint(cpml_primitive_is_inside(&primitive1, pair), ==, 0);
1084 g_assert_cmpint(cpml_primitive_is_inside(&primitive2, pair), ==, 0);
1087 static void
1088 _cpml_method_put_intersections_circle_line(void)
1090 /* Destination */
1091 CpmlPair pair[2];
1093 /* Line (-4, 4) .. (4, 4) */
1094 cairo_path_data_t line_data[] = {
1095 { .header = { CPML_MOVE, 2 }},
1096 { .point = { -4, 4 }},
1098 { .header = { CPML_LINE, 2 }},
1099 { .point = { 4, 4 }}
1101 CpmlPrimitive line = {
1102 NULL,
1103 &line_data[1],
1104 &line_data[2]
1107 /* Arc PI .. -PI of radius 3 in (0, 0) */
1108 cairo_path_data_t arc_data[] = {
1109 { .header = { CPML_MOVE, 2 }},
1110 { .point = { 0, 3 }},
1112 { .header = { CPML_ARC, 3 }},
1113 { .point = { 3, 0 }},
1114 { .point = { 0, -3 }}
1116 CpmlPrimitive arc = {
1117 NULL,
1118 &arc_data[1],
1119 &arc_data[2]
1122 /* Intersection between arc and line (-4, 4) .. (4, 4) */
1123 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 0);
1124 g_assert_cmpuint(cpml_primitive_put_intersections(&line, &arc, 2, pair), ==, 0);
1126 /* Intersection between arc and line (-4, 0) .. (4, 0) */
1127 line_data[1].point.y = line_data[3].point.y = 0;
1129 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 2);
1130 adg_assert_isapprox(pair[0].x, 3);
1131 adg_assert_isapprox(pair[0].y, 0);
1132 adg_assert_isapprox(pair[1].x, -3);
1133 adg_assert_isapprox(pair[1].y, 0);
1135 g_assert_cmpuint(cpml_primitive_put_intersections(&line, &arc, 2, pair), ==, 2);
1136 adg_assert_isapprox(pair[0].x, 3);
1137 adg_assert_isapprox(pair[0].y, 0);
1138 adg_assert_isapprox(pair[1].x, -3);
1139 adg_assert_isapprox(pair[1].y, 0);
1141 /* Intersection between arc and line (4, 1) .. (4, 1) */
1142 line_data[1].point.y = line_data[3].point.y = 1;
1144 g_assert_cmpuint(cpml_primitive_put_intersections(&line, &arc, 2, pair), ==, 2);
1145 adg_assert_isapprox(pair[0].x, 2.82842712);
1146 adg_assert_isapprox(pair[0].y, 1);
1147 adg_assert_isapprox(pair[1].x, -2.82842712);
1148 adg_assert_isapprox(pair[1].y, 1);
1150 /* Intersection between arc and line (0, -4) .. (0, 4) */
1151 line_data[1].point.y = -4;
1152 line_data[3].point.y = 4;
1153 line_data[1].point.x = line_data[3].point.x = 0;
1155 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 2);
1156 adg_assert_isapprox(pair[0].x, 0);
1157 adg_assert_isapprox(pair[0].y, 3);
1158 adg_assert_isapprox(pair[1].x, 0);
1159 adg_assert_isapprox(pair[1].y, -3);
1161 /* Intersection between arc and line (1, -4) .. (1, 4) */
1162 line_data[1].point.x = line_data[3].point.x = 1;
1164 g_assert_cmpuint(cpml_primitive_put_intersections(&line, &arc, 2, pair), ==, 2);
1165 adg_assert_isapprox(pair[0].x, 1);
1166 adg_assert_isapprox(pair[0].y, 2.82842712);
1167 adg_assert_isapprox(pair[1].x, 1);
1168 adg_assert_isapprox(pair[1].y, -2.82842712);
1170 /* Intersection between arc and line (-3, -4) .. (-3, 4) */
1171 line_data[1].point.x = line_data[3].point.x = -3;
1173 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 1);
1174 adg_assert_isapprox(pair[0].x, -3);
1175 adg_assert_isapprox(pair[0].y, 0);
1177 /* Intersection between arc and line (3, -4) .. (3, 4) */
1178 line_data[1].point.x = line_data[3].point.x = 3;
1180 g_assert_cmpuint(cpml_primitive_put_intersections(&line, &arc, 2, pair), ==, 1);
1181 adg_assert_isapprox(pair[0].x, 3);
1182 adg_assert_isapprox(pair[0].y, 0);
1184 /* Intersection between arc and line (-4, -3) .. (4, -3) */
1185 line_data[1].point.x = -4;
1186 line_data[3].point.x = 4;
1187 line_data[1].point.y = line_data[3].point.y = -3;
1189 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 1);
1190 adg_assert_isapprox(pair[0].x, 0);
1191 adg_assert_isapprox(pair[0].y, -3);
1193 /* Intersection between arc and line (-4, 3) .. (4, 3) */
1194 line_data[1].point.y = line_data[3].point.y = 3;
1196 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 1);
1197 adg_assert_isapprox(pair[0].x, 0);
1198 adg_assert_isapprox(pair[0].y, 3);
1200 /* Intersection between arc and line (-4, 1) .. (3, 3) */
1201 line_data[1].point.x = -4;
1202 line_data[1].point.y = -1;
1203 line_data[3].point.x = line_data[3].point.y = 3;
1205 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 2);
1206 adg_assert_isapprox(pair[0].x, 1.86384016);
1207 adg_assert_isapprox(pair[0].y, 2.3507658);
1208 adg_assert_isapprox(pair[1].x, -2.97153247);
1209 adg_assert_isapprox(pair[1].y, -0.412304266);
1211 /* Translate the original primitives by (+10, +20) and check that the
1212 * intersections translate of the same amount too */
1213 line_data[1].point.x += 10;
1214 line_data[3].point.x += 10;
1215 arc_data[1].point.x += 10;
1216 arc_data[3].point.x += 10;
1217 arc_data[4].point.x += 10;
1218 line_data[1].point.y += 20;
1219 line_data[3].point.y += 20;
1220 arc_data[1].point.y += 20;
1221 arc_data[3].point.y += 20;
1222 arc_data[4].point.y += 20;
1224 g_assert_cmpuint(cpml_primitive_put_intersections(&arc, &line, 2, pair), ==, 2);
1225 adg_assert_isapprox(pair[0].x, 11.86384016);
1226 adg_assert_isapprox(pair[0].y, 22.3507658);
1227 adg_assert_isapprox(pair[1].x, 7.02846753);
1228 adg_assert_isapprox(pair[1].y, 19.587695734);
1231 static void
1232 _cpml_method_put_intersections_with_segment(void)
1234 CpmlSegment segment1, segment2;
1235 CpmlPrimitive primitive;
1236 CpmlPair pair[4];
1238 /* Initialize segment1 and segment2 */
1239 cpml_segment_from_cairo(&segment1, (cairo_path_t *) adg_test_path());
1240 cpml_segment_from_cairo(&segment2, (cairo_path_t *) adg_test_path());
1241 cpml_segment_next(&segment2);
1243 /* primitive 1 segment1 intersects segment2 in (1, 1) */
1244 cpml_primitive_from_segment(&primitive, &segment1);
1245 g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment2, 4, pair), ==, 1);
1246 adg_assert_isapprox(pair[0].x, 1);
1247 adg_assert_isapprox(pair[0].y, 1);
1249 /* primitive 2 segment1 does not intersect segment2 */
1250 cpml_primitive_next(&primitive);
1251 g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment2, 4, pair), ==, 0);
1253 /* primitive 1 segment2 does not intersect segment1 */
1254 cpml_primitive_from_segment(&primitive, &segment2);
1255 g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment1, 4, pair), ==, 0);
1257 /* primitive 2 segment2 intersects segment1 in (1, 1) */
1258 cpml_primitive_next(&primitive);
1259 g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment1, 4, pair), ==, 1);
1260 adg_assert_isapprox(pair[0].x, 1);
1261 adg_assert_isapprox(pair[0].y, 1);
1264 static void
1265 _cpml_method_offset(void)
1267 CpmlSegment original, *segment;
1268 CpmlPrimitive primitive, line, curve;
1269 CpmlPrimitive *backup;
1271 /* Work on a copy to avoid modifying the original cairo path */
1272 cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path());
1273 segment = cpml_segment_deep_dup(&original);
1274 cpml_primitive_from_segment(&primitive, segment);
1276 /* Offsetting and de-offsetting can introduce rounding errors
1277 * so we use adg_assert_isapprox instead of g_assert_cmpfloat */
1279 /* Line */
1280 cpml_primitive_copy(&line, &primitive);
1281 cpml_primitive_offset(&primitive, 1);
1282 adg_assert_isapprox((primitive.org)->point.x, 0);
1283 adg_assert_isapprox((primitive.org)->point.y, 2);
1284 adg_assert_isapprox(primitive.data[1].point.x, 3);
1285 adg_assert_isapprox(primitive.data[1].point.y, 2);
1286 cpml_primitive_offset(&primitive, -1);
1287 adg_assert_isapprox((primitive.org)->point.x, 0);
1288 adg_assert_isapprox((primitive.org)->point.y, 1);
1289 adg_assert_isapprox(primitive.data[1].point.x, 3);
1290 adg_assert_isapprox(primitive.data[1].point.y, 1);
1292 /* Arc */
1293 cpml_primitive_next(&primitive);
1294 cpml_primitive_offset(&primitive, 1);
1295 adg_assert_isapprox((primitive.org)->point.x, 2.003);
1296 adg_assert_isapprox((primitive.org)->point.y, 0.923);
1297 adg_assert_isapprox(primitive.data[1].point.x, 3.156);
1298 adg_assert_isapprox(primitive.data[1].point.y, 5.537);
1299 adg_assert_isapprox(primitive.data[2].point.x, 5.463);
1300 adg_assert_isapprox(primitive.data[2].point.y, 7.844);
1301 cpml_primitive_offset(&primitive, -1);
1302 adg_assert_isapprox((primitive.org)->point.x, 3);
1303 adg_assert_isapprox((primitive.org)->point.y, 1);
1304 adg_assert_isapprox(primitive.data[1].point.x, 4);
1305 adg_assert_isapprox(primitive.data[1].point.y, 5);
1306 adg_assert_isapprox(primitive.data[2].point.x, 6);
1307 adg_assert_isapprox(primitive.data[2].point.y, 7);
1309 /* Curve */
1310 cpml_primitive_next(&primitive);
1311 cpml_primitive_copy(&curve, &primitive);
1312 /* The offset algorithm for curves is an approximation, so
1313 * offsetting +1 and -1 does not return the original curve.
1314 * Keeping a backup around to restore the original data.
1316 backup = cpml_primitive_deep_dup(&curve);
1317 /* Testing different algorithms */
1318 cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_GEOMETRICAL);
1319 cpml_primitive_offset(&primitive, 1);
1320 adg_assert_isapprox((primitive.org)->point.x, 5.293);
1321 adg_assert_isapprox((primitive.org)->point.y, 7.707);
1322 adg_assert_isapprox(primitive.data[1].point.x, 7.889);
1323 adg_assert_isapprox(primitive.data[1].point.y, 8.515);
1324 adg_assert_isapprox(primitive.data[2].point.x, 11.196);
1325 adg_assert_isapprox(primitive.data[2].point.y, 9.007);
1326 adg_assert_isapprox(primitive.data[3].point.x, -1.4);
1327 adg_assert_isapprox(primitive.data[3].point.y, 1.2);
1328 cpml_primitive_copy_data(&primitive, backup);
1329 cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_BAIOCA);
1330 cpml_primitive_offset(&primitive, 1);
1331 adg_assert_isapprox((primitive.org)->point.x, 5.293);
1332 adg_assert_isapprox((primitive.org)->point.y, 7.707);
1333 adg_assert_isapprox(primitive.data[1].point.x, 6.901);
1334 adg_assert_isapprox(primitive.data[1].point.y, 9.315);
1335 adg_assert_isapprox(primitive.data[2].point.x, 10.806);
1336 adg_assert_isapprox(primitive.data[2].point.y, 10.355);
1337 adg_assert_isapprox(primitive.data[3].point.x, -1.4);
1338 adg_assert_isapprox(primitive.data[3].point.y, 1.2);
1339 cpml_primitive_copy_data(&primitive, backup);
1340 cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_HANDCRAFT);
1341 cpml_primitive_offset(&primitive, 1);
1342 adg_assert_isapprox((primitive.org)->point.x, 5.293);
1343 adg_assert_isapprox((primitive.org)->point.y, 7.707);
1344 adg_assert_isapprox(primitive.data[1].point.x, -5.758);
1345 adg_assert_isapprox(primitive.data[1].point.y, -3.344);
1346 adg_assert_isapprox(primitive.data[2].point.x, 24.987);
1347 adg_assert_isapprox(primitive.data[2].point.y, 20.99);
1348 adg_assert_isapprox(primitive.data[3].point.x, -1.4);
1349 adg_assert_isapprox(primitive.data[3].point.y, 1.2);
1350 cpml_primitive_copy_data(&primitive, backup);
1352 g_free(backup);
1353 cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_DEFAULT);
1355 /* Close: this primitive does not own data points but should
1356 * modify the points of the previous and next primitives */
1357 cpml_primitive_next(&primitive);
1358 cpml_primitive_offset(&primitive, 1);
1359 adg_assert_isapprox((curve.org)->point.x, 6);
1360 adg_assert_isapprox((curve.org)->point.y, 7);
1361 adg_assert_isapprox(curve.data[3].point.x, -1.553);
1362 adg_assert_isapprox(curve.data[3].point.y, 2.894);
1363 adg_assert_isapprox((line.org)->point.x, 0.447);
1364 adg_assert_isapprox((line.org)->point.y, 1.894);
1365 adg_assert_isapprox(line.data[1].point.x, 3);
1366 adg_assert_isapprox(line.data[1].point.y, 1);
1367 cpml_primitive_offset(&primitive, -1);
1368 adg_assert_isapprox((curve.org)->point.x, 6);
1369 adg_assert_isapprox((curve.org)->point.y, 7);
1370 adg_assert_isapprox(curve.data[3].point.x, -2);
1371 adg_assert_isapprox(curve.data[3].point.y, 2);
1372 adg_assert_isapprox((line.org)->point.x, 0);
1373 adg_assert_isapprox((line.org)->point.y, 1);
1374 adg_assert_isapprox(line.data[1].point.x, 3);
1375 adg_assert_isapprox(line.data[1].point.y, 1);
1377 g_free(segment);
1380 static void
1381 _cpml_method_join(void)
1383 cairo_path_data_t path_data[] = {
1384 { .header = { CPML_MOVE, 2 }},
1385 { .point = { 0, 0 }},
1387 { .header = { CPML_LINE, 2 }},
1388 { .point = { 2, 0 }},
1390 { .header = { CPML_LINE, 2 }},
1391 { .point = { 2, 2 }},
1393 { .header = { CPML_LINE, 2 }},
1394 { .point = { 1, 2 }},
1396 { .header = { CPML_LINE, 2 }},
1397 { .point = { 1, -2 }}
1399 cairo_path_t path = {
1400 CAIRO_STATUS_SUCCESS,
1401 path_data,
1402 G_N_ELEMENTS(path_data)
1404 CpmlSegment segment;
1405 CpmlPrimitive primitive1, primitive2;
1407 cpml_segment_from_cairo(&segment, &path);
1409 cpml_primitive_from_segment(&primitive1, &segment);
1410 cpml_primitive_copy(&primitive2, &primitive1);
1411 cpml_primitive_next(&primitive2);
1413 /* primitive1 and primitive2 are already joint */
1414 g_assert_cmpint(cpml_primitive_join(&primitive1, &primitive2), ==, 1);
1415 adg_assert_isapprox((primitive2.org)->point.x, 2);
1416 adg_assert_isapprox((primitive2.org)->point.y, 0);
1418 cpml_primitive_next(&primitive2);
1419 /* Now primitive1 and primitive2 are divergent,
1420 * hence cannot be joined */
1421 g_assert_cmpint(cpml_primitive_join(&primitive1, &primitive2), ==, 0);
1423 cpml_primitive_next(&primitive2);
1424 g_assert_cmpint(cpml_primitive_join(&primitive1, &primitive2), ==, 1);
1425 adg_assert_isapprox((primitive2.org)->point.x, 1);
1426 adg_assert_isapprox((primitive2.org)->point.y, 0);
1429 static void
1430 _cpml_method_to_cairo(void)
1432 cairo_t *cr;
1433 CpmlSegment segment;
1434 CpmlPrimitive primitive;
1435 int length, last_length;
1437 cr = adg_test_cairo_context();
1438 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
1439 cpml_primitive_from_segment(&primitive, &segment);
1441 g_assert_cmpint(adg_test_cairo_num_data(cr), ==, 0);
1443 length = 0;
1444 do {
1445 last_length = length;
1446 cpml_primitive_to_cairo(&primitive, cr);
1447 length = adg_test_cairo_num_data(cr);
1448 g_assert_cmpint(length, >, last_length);
1449 } while (cpml_primitive_next(&primitive));
1451 cairo_destroy(cr);
1454 static void
1455 _cpml_method_dump(gint i)
1457 CpmlSegment segment;
1458 CpmlPrimitive primitive;
1460 switch (i) {
1461 case 1:
1462 cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
1463 cpml_primitive_from_segment(&primitive, &segment);
1464 cpml_primitive_dump(&primitive, 1);
1466 cpml_primitive_next(&primitive);
1467 cpml_primitive_dump(&primitive, 1);
1468 break;
1469 case 2:
1470 g_test_trap_assert_passed();
1471 g_test_trap_assert_stderr_unmatched("?");
1472 g_test_trap_assert_stdout("*NULL*");
1473 g_test_trap_assert_stdout("*move*");
1474 g_test_trap_assert_stdout("*line*");
1480 main(int argc, char *argv[])
1482 adg_test_init(&argc, &argv);
1484 g_test_add_func("/cpml/primitive/behavior/browsing", _cpml_behavior_browsing);
1486 adg_test_add_traps("/cpml/primitive/sanity/type", _cpml_sanity_type, 1);
1487 adg_test_add_traps("/cpml/primitive/sanity/from-segment", _cpml_sanity_from_segment, 2);
1488 adg_test_add_traps("/cpml/primitive/sanity/copy", _cpml_sanity_copy, 2);
1489 adg_test_add_traps("/cpml/primitive/sanity/copy-data", _cpml_sanity_copy_data, 2);
1490 adg_test_add_traps("/cpml/primitive/sanity/get-n-points", _cpml_sanity_get_n_points, 1);
1491 adg_test_add_traps("/cpml/primitive/sanity/get-length", _cpml_sanity_get_length, 1);
1492 adg_test_add_traps("/cpml/primitive/sanity/put-extents", _cpml_sanity_put_extents, 2);
1493 adg_test_add_traps("/cpml/primitive/sanity/put-pair-at", _cpml_sanity_put_pair_at, 2);
1494 adg_test_add_traps("/cpml/primitive/sanity/put-vector-at", _cpml_sanity_put_vector_at, 2);
1495 adg_test_add_traps("/cpml/primitive/sanity/get-closest-pos", _cpml_sanity_get_closest_pos, 2);
1496 adg_test_add_traps("/cpml/primitive/sanity/set-point", _cpml_sanity_set_point, 2);
1497 adg_test_add_traps("/cpml/primitive/sanity/put-point", _cpml_sanity_put_point, 2);
1498 adg_test_add_traps("/cpml/primitive/sanity/put-intersections", _cpml_sanity_put_intersections, 3);
1499 adg_test_add_traps("/cpml/primitive/sanity/put-intersections-with-segment", _cpml_sanity_put_intersections_with_segment, 3);
1500 adg_test_add_traps("/cpml/primitive/sanity/offset", _cpml_sanity_offset, 1);
1501 adg_test_add_traps("/cpml/primitive/sanity/join", _cpml_sanity_join, 2);
1502 adg_test_add_traps("/cpml/primitive/sanity/to-cairo", _cpml_sanity_to_cairo, 2);
1503 adg_test_add_traps("/cpml/primitive/sanity/dump", _cpml_sanity_dump, 1);
1505 g_test_add_func("/cpml/primitive/method/type", _cpml_method_type);
1506 g_test_add_func("/cpml/primitive/method/from-segment", _cpml_method_from_segment);
1507 g_test_add_func("/cpml/primitive/method/copy", _cpml_method_copy);
1508 g_test_add_func("/cpml/primitive/method/copy-data", _cpml_method_copy_data);
1509 g_test_add_func("/cpml/primitive/method/type-get-n-points", _cpml_method_type_get_n_points);
1510 g_test_add_func("/cpml/primitive/method/get-n-points", _cpml_method_get_n_points);
1511 g_test_add_func("/cpml/primitive/method/get-length", _cpml_method_get_length);
1512 g_test_add_func("/cpml/primitive/method/put-extents", _cpml_method_put_extents);
1513 g_test_add_func("/cpml/primitive/method/put-pair-at", _cpml_method_put_pair_at);
1514 g_test_add_func("/cpml/primitive/method/put-vector-at", _cpml_method_put_vector_at);
1515 g_test_add_func("/cpml/primitive/method/get-closest-pos", _cpml_method_get_closest_pos);
1516 g_test_add_func("/cpml/primitive/method/set-point", _cpml_method_set_point);
1517 g_test_add_func("/cpml/primitive/method/put-point", _cpml_method_put_point);
1518 g_test_add_func("/cpml/primitive/method/put-intersections", _cpml_method_put_intersections);
1519 g_test_add_func("/cpml/primitive/method/put-intersections/circle-line", _cpml_method_put_intersections_circle_line);
1520 g_test_add_func("/cpml/primitive/method/put-intersections-with-segment", _cpml_method_put_intersections_with_segment);
1521 g_test_add_func("/cpml/primitive/method/offset", _cpml_method_offset);
1522 g_test_add_func("/cpml/primitive/method/join", _cpml_method_join);
1523 g_test_add_func("/cpml/primitive/method/to-cairo", _cpml_method_to_cairo);
1524 adg_test_add_traps("/cpml/primitive/method/dump", _cpml_method_dump, 1);
1526 return g_test_run();