[gtk/path-work-rebased: 974/1045] testsuite: Add tests for in_fill()
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/path-work-rebased: 974/1045] testsuite: Add tests for in_fill()
- Date: Thu, 7 Apr 2022 19:09:25 +0000 (UTC)
commit 6468ebadf4cc0f4b64bb88b30f594952d2d655d6
Author: Benjamin Otte <otte redhat com>
Date: Mon Nov 30 04:22:06 2020 +0100
testsuite: Add tests for in_fill()
Add a test for measure_in_fill. Also test some
special cases involving horizontal edges.
testsuite/gsk/path-special-cases.c | 38 +++++++++
testsuite/gsk/path.c | 165 +++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+)
---
diff --git a/testsuite/gsk/path-special-cases.c b/testsuite/gsk/path-special-cases.c
index 04a575ac1f..d4431419ff 100644
--- a/testsuite/gsk/path-special-cases.c
+++ b/testsuite/gsk/path-special-cases.c
@@ -306,6 +306,43 @@ test_serialize_custom_contours (void)
gsk_path_unref (path1);
}
+static void
+test_path_winding (void)
+{
+ struct {
+ const char *path;
+ graphene_point_t point;
+ gboolean result;
+ } tests[] = {
+ { "M 150 103 L 250 100 L 300 103 L 250 180 Z", GRAPHENE_POINT_INIT (175, 100), FALSE },
+ { "M 100 100 L 300 200 L 300 0 Z", GRAPHENE_POINT_INIT (250, 100), TRUE },
+ { "M 100 100 L 300 200 L 300 0 Z", GRAPHENE_POINT_INIT (400, 100), FALSE},
+ { "M 100 100 L 200 100 L 300 200 L 300 0 Z", GRAPHENE_POINT_INIT (50, 100), FALSE },
+ { "M 100 100 L 200 100 L 300 200 L 300 0 Z", GRAPHENE_POINT_INIT (150, 100), TRUE },
+ { "M 100 100 L 200 100 L 300 200 L 300 0 Z", GRAPHENE_POINT_INIT (250, 100), TRUE },
+ { "M 100 100 L 200 100 L 300 200 L 300 0 Z", GRAPHENE_POINT_INIT (400, 100), FALSE },
+ /* the following check that our elementary contours wind as expected.
+ * our rect contour is clockwise, our circle contour is counterclockwise
+ */
+ { "M100,100h100v100h-100z M200,150A50,50,0,1,0,100,150A50,50,0,1,0,200,150z", GRAPHENE_POINT_INIT
(150,150), FALSE },
+ };
+ GskPath *path;
+ GskPathMeasure *measure;
+ gboolean res;
+
+ for (int i = 0; i < G_N_ELEMENTS (tests); i++)
+ {
+ path = gsk_path_parse (tests[i].path);
+ measure = gsk_path_measure_new (path);
+
+ res = gsk_path_measure_in_fill (measure, &tests[i].point, GSK_FILL_RULE_WINDING);
+ g_assert_true (res == tests[i].result);
+
+ gsk_path_measure_unref (measure);
+ gsk_path_unref (path);
+ }
+}
+
int
main (int argc,
char *argv[])
@@ -314,6 +351,7 @@ main (int argc,
g_test_add_func ("/path/rsvg-parse", test_rsvg_parse);
g_test_add_func ("/path/serialize-custom-contours", test_serialize_custom_contours);
+ g_test_add_func ("/path/winding", test_path_winding);
return g_test_run ();
}
diff --git a/testsuite/gsk/path.c b/testsuite/gsk/path.c
index 3490981262..8cef3bc632 100644
--- a/testsuite/gsk/path.c
+++ b/testsuite/gsk/path.c
@@ -886,6 +886,169 @@ test_parse (void)
}
}
+#define N_PATHS 3
+static void
+test_in_fill_union (void)
+{
+ GskPath *path;
+ GskPathMeasure *measure, *measures[N_PATHS];
+ GskPathBuilder *builder;
+ guint i, j, k;
+
+ for (i = 0; i < 100; i++)
+ {
+ builder = gsk_path_builder_new ();
+ for (k = 0; k < N_PATHS; k++)
+ {
+ path = create_random_path (G_MAXUINT);
+ measures[k] = gsk_path_measure_new (path);
+ gsk_path_builder_add_path (builder, path);
+ gsk_path_unref (path);
+ }
+ path = gsk_path_builder_free_to_path (builder);
+ measure = gsk_path_measure_new (path);
+ gsk_path_unref (path);
+
+ for (j = 0; j < 100; j++)
+ {
+ graphene_point_t test = GRAPHENE_POINT_INIT (g_test_rand_double_range (-1000, 1000),
+ g_test_rand_double_range (-1000, 1000));
+ GskFillRule fill_rule;
+
+ for (fill_rule = GSK_FILL_RULE_WINDING; fill_rule <= GSK_FILL_RULE_EVEN_ODD; fill_rule++)
+ {
+ guint n_in_fill = 0;
+ gboolean in_fill;
+
+ for (k = 0; k < N_PATHS; k++)
+ {
+ if (gsk_path_measure_in_fill (measures[k], &test, GSK_FILL_RULE_EVEN_ODD))
+ n_in_fill++;
+ }
+
+ in_fill = gsk_path_measure_in_fill (measure, &test, GSK_FILL_RULE_EVEN_ODD);
+
+ switch (fill_rule)
+ {
+ case GSK_FILL_RULE_WINDING:
+ if (n_in_fill == 0)
+ g_assert_false (in_fill);
+ else if (n_in_fill == 1)
+ g_assert_true (in_fill);
+ /* else we can't say anything because the winding rule doesn't give enough info */
+ break;
+
+ case GSK_FILL_RULE_EVEN_ODD:
+ g_assert_cmpint (in_fill, ==, n_in_fill & 1);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ }
+
+ gsk_path_measure_unref (measure);
+ for (k = 0; k < N_PATHS; k++)
+ {
+ gsk_path_measure_unref (measures[k]);
+ }
+ }
+}
+#undef N_PATHS
+
+/* This is somewhat sucky because using foreach breaks up the contours
+ * (like rects and circles) and replaces everything with the standard
+ * contour.
+ * But at least it extensively tests the standard contour.
+ */
+static gboolean
+rotate_path_cb (GskPathOperation op,
+ const graphene_point_t *pts,
+ gsize n_pts,
+ gpointer user_data)
+{
+ GskPathBuilder **builders = user_data;
+
+ switch (op)
+ {
+ case GSK_PATH_MOVE:
+ gsk_path_builder_move_to (builders[0], pts[0].x, pts[0].y);
+ gsk_path_builder_move_to (builders[1], pts[0].y, -pts[0].x);
+ break;
+
+ case GSK_PATH_CLOSE:
+ gsk_path_builder_close (builders[0]);
+ gsk_path_builder_close (builders[1]);
+ break;
+
+ case GSK_PATH_LINE:
+ gsk_path_builder_line_to (builders[0], pts[1].x, pts[1].y);
+ gsk_path_builder_line_to (builders[1], pts[1].y, -pts[1].x);
+ break;
+
+ case GSK_PATH_CURVE:
+ gsk_path_builder_curve_to (builders[0], pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
+ gsk_path_builder_curve_to (builders[1], pts[1].y, -pts[1].x, pts[2].y, -pts[2].x, pts[3].y, -pts[3].x);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+test_in_fill_rotated (void)
+{
+ GskPath *path;
+ GskPathBuilder *builders[2];
+ GskPathMeasure *measures[2];
+ guint i, j;
+
+#define N_FILL_RULES 2
+ /* if this triggers, you added a new enum value to GskFillRule, so the define above needs
+ * an update */
+ g_assert_null (g_enum_get_value (g_type_class_ref (GSK_TYPE_FILL_RULE), N_FILL_RULES));
+
+ for (i = 0; i < 100; i++)
+ {
+ path = create_random_path (G_MAXUINT);
+ builders[0] = gsk_path_builder_new ();
+ builders[1] = gsk_path_builder_new ();
+ gsk_path_foreach (path, rotate_path_cb, builders);
+ gsk_path_unref (path);
+
+ path = gsk_path_builder_free_to_path (builders[0]);
+ measures[0] = gsk_path_measure_new (path);
+ gsk_path_unref (path);
+ path = gsk_path_builder_free_to_path (builders[1]);
+ measures[1] = gsk_path_measure_new (path);
+ gsk_path_unref (path);
+
+ for (j = 0; j < 100; j++)
+ {
+ GskFillRule fill_rule = g_random_int_range (0, N_FILL_RULES);
+ float x = g_test_rand_double_range (-1000, 1000);
+ float y = g_test_rand_double_range (-1000, 1000);
+
+ g_assert_cmpint (gsk_path_measure_in_fill (measures[0], &GRAPHENE_POINT_INIT (x, y), fill_rule),
+ ==,
+ gsk_path_measure_in_fill (measures[1], &GRAPHENE_POINT_INIT (y, -x), fill_rule));
+ g_assert_cmpint (gsk_path_measure_in_fill (measures[0], &GRAPHENE_POINT_INIT (y, x), fill_rule),
+ ==,
+ gsk_path_measure_in_fill (measures[1], &GRAPHENE_POINT_INIT (x, -y), fill_rule));
+ }
+
+ gsk_path_measure_unref (measures[0]);
+ gsk_path_measure_unref (measures[1]);
+ }
+#undef N_FILL_RULES
+}
+
int
main (int argc,
char *argv[])
@@ -901,6 +1064,8 @@ main (int argc,
g_test_add_func ("/path/closest_point", test_closest_point);
g_test_add_func ("/path/closest_point_for_point", test_closest_point_for_point);
g_test_add_func ("/path/parse", test_parse);
+ g_test_add_func ("/path/in-fill-union", test_in_fill_union);
+ g_test_add_func ("/path/in-fill-rotated", test_in_fill_rotated);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]