static void _cpml_sanity_put_intersections_with_segment(gint i) { CpmlPrimitive primitive; CpmlSegment segment; CpmlPair pair; /* Set primitive 1.1 and segment to 2 * so there is an intersection point in (1,1) */ cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&primitive, &segment); cpml_segment_next(&segment); switch (i) { case 1: cpml_primitive_put_intersections_with_segment(NULL, &segment, 2, &pair); break; case 2: cpml_primitive_put_intersections_with_segment(&primitive, NULL, 2, &pair); break; case 3: cpml_primitive_put_intersections_with_segment(&primitive, &segment, 2, NULL); break; default: g_test_trap_assert_failed(); break; } }
static void _adg_do_operation(AdgPath *path, cairo_path_data_t *path_data) { AdgPathPrivate *data; AdgAction action; CpmlSegment segment; CpmlPrimitive current; cairo_path_data_t current_org; data = path->data; action = data->operation.action; cpml_segment_from_cairo(&segment, _adg_read_cairo_path(path)); /* Construct the current primitive, that is the primitive to be * mixed with the last primitive with the specified operation. * Its org is a copy of the end point of the last primitive: it can be * modified without affecting anything else. It is expected the operation * functions will add to @path the primitives required but NOT to add * @current, as this one will be inserted automatically. */ current.segment = &segment; current.org = ¤t_org; current.data = path_data; cpml_pair_to_cairo(&data->cp, ¤t_org); _adg_do_action(path, action, ¤t); }
static void _cpml_method_get_n_points(void) { CpmlSegment segment; CpmlPrimitive primitive; size_t n_points; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); /* Line */ cpml_primitive_from_segment(&primitive, &segment); n_points = cpml_primitive_get_n_points(&primitive); g_assert_cmpuint(n_points, ==, 2); /* Arc */ cpml_primitive_next(&primitive); n_points = cpml_primitive_get_n_points(&primitive); g_assert_cmpuint(n_points, ==, 3); /* Curve */ cpml_primitive_next(&primitive); n_points = cpml_primitive_get_n_points(&primitive); g_assert_cmpuint(n_points, ==, 4); /* Close: although the end point is not needed, the CPML API * returns 2 points to treat this primitive as a CPML_LINE */ cpml_primitive_next(&primitive); n_points = cpml_primitive_get_n_points(&primitive); g_assert_cmpuint(n_points, ==, 2); }
static void _adg_rescan(AdgPath *path) { AdgPathPrivate *data; CpmlSegment segment; CpmlPrimitive current, *last, *over; data = path->data; last = &data->last; over = &data->over; last->segment = NULL; last->org = NULL; last->data = NULL; over->segment = NULL; over->org = NULL; over->data = NULL; /* When no data is present, just bail out */ if (! cpml_segment_from_cairo(&segment, _adg_read_cairo_path(path))) return; do { cpml_primitive_from_segment(¤t, &segment); do { cpml_primitive_copy(over, last); cpml_primitive_copy(last, ¤t); } while (cpml_primitive_next(¤t)); } while (cpml_segment_next(&segment)); }
static void _cpml_method_put_pair_at(void) { CpmlSegment segment; CpmlPrimitive primitive; CpmlPair pair; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); /* Line */ cpml_primitive_from_segment(&primitive, &segment); cpml_primitive_put_pair_at(&primitive, 0, &pair); adg_assert_isapprox(pair.x, 0); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_pair_at(&primitive, 1, &pair); adg_assert_isapprox(pair.x, 3); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_pair_at(&primitive, 0.5, &pair); adg_assert_isapprox(pair.x, 1.5); adg_assert_isapprox(pair.y, 1); /* Arc */ cpml_primitive_next(&primitive); cpml_primitive_put_pair_at(&primitive, 0, &pair); adg_assert_isapprox(pair.x, 3); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_pair_at(&primitive, 1, &pair); adg_assert_isapprox(pair.x, 6); adg_assert_isapprox(pair.y, 7); cpml_primitive_put_pair_at(&primitive, 0.5, &pair); adg_assert_isapprox(pair.x, 3.669); adg_assert_isapprox(pair.y, 4.415); /* Close */ cpml_primitive_next(&primitive); /* TODO: not yet implemented * cpml_primitive_put_pair_at(&primitive, 0, &pair); * adg_assert_isapprox(pair.x, 6); * adg_assert_isapprox(pair.y, 7); * cpml_primitive_put_pair_at(&primitive, 1, &pair); * adg_assert_isapprox(pair.x, -2); * adg_assert_isapprox(pair.y, 2); * cpml_primitive_put_pair_at(&primitive, 0.5, &pair); * adg_assert_isapprox(pair.x, 1); * adg_assert_isapprox(pair.y, 1); */ /* Close */ cpml_primitive_next(&primitive); cpml_primitive_put_pair_at(&primitive, 0, &pair); adg_assert_isapprox(pair.x, -2); adg_assert_isapprox(pair.y, 2); cpml_primitive_put_pair_at(&primitive, 1, &pair); adg_assert_isapprox(pair.x, 0); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_pair_at(&primitive, 0.5, &pair); adg_assert_isapprox(pair.x, -1); adg_assert_isapprox(pair.y, 1.5); }
static void _cpml_method_put_vector_at(void) { CpmlSegment segment; CpmlPrimitive primitive; CpmlVector vector; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); /* Line */ cpml_primitive_from_segment(&primitive, &segment); cpml_primitive_put_vector_at(&primitive, 0, &vector); adg_assert_isapprox(vector.x, 3); adg_assert_isapprox(vector.y, 0); cpml_primitive_put_vector_at(&primitive, 1, &vector); adg_assert_isapprox(vector.x, 3); adg_assert_isapprox(vector.y, 0); cpml_primitive_put_vector_at(&primitive, 0.5, &vector); adg_assert_isapprox(vector.x, 3); adg_assert_isapprox(vector.y, 0); /* Arc */ cpml_primitive_next(&primitive); cpml_primitive_put_vector_at(&primitive, 0, &vector); adg_assert_isapprox(vector.x, -0.077); adg_assert_isapprox(vector.y, 0.997); cpml_primitive_put_vector_at(&primitive, 1, &vector); adg_assert_isapprox(vector.x, 0.844); adg_assert_isapprox(vector.y, 0.537); cpml_primitive_put_vector_at(&primitive, 0.5, &vector); adg_assert_isapprox(vector.x, 0.447); adg_assert_isapprox(vector.y, 0.894); /* Close */ cpml_primitive_next(&primitive); /* TODO: not yet implemented * cpml_primitive_put_vector_at(&primitive, 0, &vector); * adg_assert_isapprox(vector.x, 6); * adg_assert_isapprox(vector.y, 7); * cpml_primitive_put_vector_at(&primitive, 1, &vector); * adg_assert_isapprox(vector.x, -2); * adg_assert_isapprox(vector.y, 2); * cpml_primitive_put_vector_at(&primitive, 0.5, &vector); * adg_assert_isapprox(vector.x, 1); * adg_assert_isapprox(vector.y, 1); */ /* Close */ cpml_primitive_next(&primitive); cpml_primitive_put_vector_at(&primitive, 0, &vector); adg_assert_isapprox(vector.x, 2); adg_assert_isapprox(vector.y, -1); cpml_primitive_put_vector_at(&primitive, 1, &vector); adg_assert_isapprox(vector.x, 2); adg_assert_isapprox(vector.y, -1); cpml_primitive_put_vector_at(&primitive, 0.5, &vector); adg_assert_isapprox(vector.x, 2); adg_assert_isapprox(vector.y, -1); }
static void _cpml_method_from_segment(void) { CpmlSegment segment; CpmlPrimitive primitive; g_assert_true(cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path())); cpml_primitive_from_segment(&primitive, &segment); g_assert_nonnull(primitive.segment); g_assert_nonnull(primitive.org); g_assert_nonnull(primitive.data); }
static void _cpml_method_put_intersections(void) { CpmlSegment segment; CpmlPrimitive primitive1, primitive2; CpmlPair pair[2]; /* Set primitive1 to 1.1 (first segment, first primitive) */ cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&primitive1, &segment); /* Set primitive2 to 2.1 (second segment, first primitive) */ cpml_segment_next(&segment); cpml_primitive_from_segment(&primitive2, &segment); /* primitive1 (1.1) does not intersect primitive2 (2.1) */ g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 0); cpml_primitive_next(&primitive2); /* primitive1 (1.1) intersects primitive2 (2.2) in (1, 1) */ g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 1); adg_assert_isapprox(pair[0].x, 1); adg_assert_isapprox(pair[0].y, 1); g_assert_cmpint(cpml_primitive_is_inside(&primitive1, pair), ==, 1); g_assert_cmpint(cpml_primitive_is_inside(&primitive2, pair), ==, 1); /* Check the intersection is not returned when not requested */ g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 0, pair), ==, 0); cpml_primitive_next(&primitive1); /* primitive1 (1.2) does not intersect primitive2 (2.2) */ g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 0); cpml_primitive_next(&primitive1); /* primitive1 (1.3) does not intersect primitive2 (2.2) */ g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 0); cpml_primitive_next(&primitive1); /* primitive1 (1.4) intersects primitive2 (2.2), but outside their boundaries */ g_assert_cmpuint(cpml_primitive_put_intersections(&primitive1, &primitive2, 2, pair), ==, 1); adg_assert_isapprox(pair[0].x, 1); adg_assert_isapprox(pair[0].y, -1); g_assert_cmpint(cpml_primitive_is_inside(&primitive1, pair), ==, 0); g_assert_cmpint(cpml_primitive_is_inside(&primitive2, pair), ==, 0); }
static void _cpml_method_get_length(void) { CpmlSegment segment; CpmlPrimitive primitive; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_segment_next(&segment); cpml_primitive_from_segment(&primitive, &segment); adg_assert_isapprox(cpml_primitive_get_length(&primitive), 1); cpml_primitive_next(&primitive); adg_assert_isapprox(cpml_primitive_get_length(&primitive), 2); }
static void _cpml_method_put_extents(void) { CpmlSegment segment; CpmlPrimitive primitive; CpmlExtents extents; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); /* Line */ cpml_primitive_from_segment(&primitive, &segment); cpml_primitive_put_extents(&primitive, &extents); g_assert_true(extents.is_defined); adg_assert_isapprox(extents.org.x, 0); adg_assert_isapprox(extents.org.y, 1); adg_assert_isapprox(extents.size.x, 3); adg_assert_isapprox(extents.size.y, 0); /* Arc: the extents are computed precisely... let's ensure * at least all the 3 points are included */ cpml_primitive_next(&primitive); cpml_primitive_put_extents(&primitive, &extents); g_assert_true(extents.is_defined); g_assert_cmpfloat(extents.org.x, <=, 3); g_assert_cmpfloat(extents.org.y, <=, 1); g_assert_cmpfloat(extents.size.x, >=, 3); g_assert_cmpfloat(extents.size.y, >=, 6); /* Curve: actually the extents are computed by using the * convex hull (hence the exact coordinates of the points) */ cpml_primitive_next(&primitive); cpml_primitive_put_extents(&primitive, &extents); g_assert_true(extents.is_defined); adg_assert_isapprox(extents.org.x, -2); adg_assert_isapprox(extents.org.y, 2); adg_assert_isapprox(extents.size.x, 12); adg_assert_isapprox(extents.size.y, 9); /* Close */ cpml_primitive_next(&primitive); cpml_primitive_put_extents(&primitive, &extents); g_assert_true(extents.is_defined); adg_assert_isapprox(extents.org.x, -2); adg_assert_isapprox(extents.org.y, 1); adg_assert_isapprox(extents.size.x, 2); adg_assert_isapprox(extents.size.y, 1); }
static void _cpml_method_put_intersections_with_segment(void) { CpmlSegment segment; CpmlPrimitive primitive; CpmlPair pair[4]; /* Set primitive to first segment, first primitive */ cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&primitive, &segment); /* Set segment to the second segment */ cpml_segment_next(&segment); /* primitive (1.1) intersects segment (2) in (1, 1) */ g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment, 4, pair), ==, 1); adg_assert_isapprox(pair[0].x, 1); adg_assert_isapprox(pair[0].y, 1); cpml_primitive_next(&primitive); /* primitive (1.1) does not intersect segment (2) */ g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment, 4, pair), ==, 0); /* Set primitive to second segment, first primitive */ cpml_primitive_from_segment(&primitive, &segment); /* Set segment to the first segment */ cpml_segment_reset(&segment); /* primitive (2.1) intersects segment (1) in extrapolation. * TODO: change this behavior! They must not intersect. */ g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment, 4, pair), ==, 1); adg_assert_isapprox(pair[0].x, 2); adg_assert_isapprox(pair[0].y, 0); cpml_primitive_next(&primitive); /* primitive (2.2) wrongly intersects segment (1) */ g_assert_cmpuint(cpml_primitive_put_intersections_with_segment(&primitive, &segment, 4, pair), ==, 1); adg_assert_isapprox(pair[0].x, 2); adg_assert_isapprox(pair[0].y, 0); }
static void _cpml_method_copy_data(void) { CpmlSegment segment; CpmlPrimitive original, *primitive; int n; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&original, &segment); /* Check incompatible primitives are not copied */ primitive = cpml_primitive_deep_dup(&original); ++primitive->data[0].header.length; g_assert_cmpint(cpml_primitive_copy_data(primitive, &original), ==, 0); --primitive->data[0].header.length; ++primitive->data[0].header.type; g_assert_cmpint(cpml_primitive_copy_data(primitive, &original), ==, 0); --primitive->data[0].header.type; do { primitive = cpml_primitive_deep_dup(&original); ++primitive->org->point.x; ++primitive->org->point.y; for (n = 1; n < primitive->data[0].header.length; ++n) { ++primitive->data[n].point.x; ++primitive->data[n].point.y; } g_assert_cmpfloat(primitive->org->point.x, !=, original.org->point.x); g_assert_cmpfloat(primitive->org->point.y, !=, original.org->point.y); for (n = 1; n < primitive->data[0].header.length; ++n) { g_assert_cmpfloat(primitive->data[n].point.x, !=, original.data[n].point.x); g_assert_cmpfloat(primitive->data[n].point.y, !=, original.data[n].point.y); } g_assert_cmpint(cpml_primitive_copy_data(primitive, &original), ==, 1); adg_assert_isapprox(primitive->org->point.x, original.org->point.x); adg_assert_isapprox(primitive->org->point.y, original.org->point.y); for (n = 1; n < primitive->data[0].header.length; ++n) { adg_assert_isapprox(primitive->data[n].point.x, original.data[n].point.x); adg_assert_isapprox(primitive->data[n].point.y, original.data[n].point.y); } g_free(primitive); } while (cpml_primitive_next(&original)); }
static void _cpml_behavior_browsing(void) { CpmlSegment segment; CpmlPrimitive primitive, primitive_copy; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&primitive, &segment); adg_assert_isapprox((primitive.org)->point.x, 0); adg_assert_isapprox((primitive.org)->point.y, 1); g_assert_cmpint((primitive.data)->header.type, ==, CPML_LINE); g_assert_true(cpml_primitive_next(&primitive)); adg_assert_isapprox((primitive.org)->point.x, 3); adg_assert_isapprox((primitive.org)->point.y, 1); g_assert_cmpint((primitive.data)->header.type, ==, CPML_ARC); g_assert_true(cpml_primitive_next(&primitive)); adg_assert_isapprox((primitive.org)->point.x, 6); adg_assert_isapprox((primitive.org)->point.y, 7); g_assert_cmpint((primitive.data)->header.type, ==, CPML_CURVE); g_assert_true(cpml_primitive_next(&primitive)); adg_assert_isapprox((primitive.org)->point.x, -2); adg_assert_isapprox((primitive.org)->point.y, 2); g_assert_cmpint((primitive.data)->header.type, ==, CPML_CLOSE); g_assert_false(cpml_primitive_next(&primitive)); cpml_primitive_reset(&primitive); g_assert_true(cpml_primitive_next(&primitive)); cpml_primitive_reset(&primitive); cpml_primitive_reset(&primitive); g_assert_true(cpml_primitive_next(&primitive)); g_assert_true(cpml_primitive_next(&primitive)); g_assert_true(cpml_primitive_next(&primitive)); g_assert_false(cpml_primitive_next(&primitive)); cpml_primitive_copy(&primitive_copy, &primitive); g_assert_false(cpml_primitive_next(&primitive_copy)); cpml_primitive_reset(&primitive); g_assert_false(cpml_primitive_next(&primitive_copy)); cpml_primitive_reset(&primitive_copy); g_assert_true(cpml_primitive_next(&primitive_copy)); }
static void _cpml_sanity_from_segment(gint i) { CpmlPrimitive primitive; CpmlSegment segment; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); switch (i) { case 1: cpml_primitive_from_segment(NULL, &segment); break; case 2: cpml_primitive_from_segment(&primitive, NULL); break; default: g_test_trap_assert_failed(); break; } }
static void _cpml_method_copy(void) { CpmlSegment segment; CpmlPrimitive original; CpmlPrimitive primitive = { NULL, NULL, NULL }; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&original, &segment); g_assert_false(original.segment == primitive.segment); g_assert_false(original.org == primitive.org); g_assert_false(original.data == primitive.data); cpml_primitive_copy(&primitive, &original); g_assert_true(original.segment == primitive.segment); g_assert_true(original.org == primitive.org); g_assert_true(original.data == primitive.data); }
static void _cpml_method_put_point(void) { CpmlSegment segment; CpmlPrimitive primitive; CpmlPair pair; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); /* Line */ cpml_primitive_from_segment(&primitive, &segment); cpml_primitive_put_point(&primitive, 0, &pair); adg_assert_isapprox(pair.x, 0); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_point(&primitive, 1, &pair); adg_assert_isapprox(pair.x, 3); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_point(&primitive, 2, &pair); adg_assert_isapprox(pair.x, 3); adg_assert_isapprox(pair.y, 1); /* The negative indices are checked only against CPML_LINE */ cpml_primitive_put_point(&primitive, -1, &pair); adg_assert_isapprox(pair.x, 3); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_point(&primitive, -2, &pair); adg_assert_isapprox(pair.x, 0); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_point(&primitive, -3, &pair); adg_assert_isapprox(pair.x, 0); adg_assert_isapprox(pair.y, 1); /* Arc */ cpml_primitive_next(&primitive); cpml_primitive_put_point(&primitive, 0, &pair); adg_assert_isapprox(pair.x, 3); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_point(&primitive, 1, &pair); adg_assert_isapprox(pair.x, 4); adg_assert_isapprox(pair.y, 5); cpml_primitive_put_point(&primitive, 2, &pair); adg_assert_isapprox(pair.x, 6); adg_assert_isapprox(pair.y, 7); cpml_primitive_put_point(&primitive, 3, &pair); adg_assert_isapprox(pair.x, 6); adg_assert_isapprox(pair.y, 7); /* Curve */ cpml_primitive_next(&primitive); cpml_primitive_put_point(&primitive, 0, &pair); adg_assert_isapprox(pair.x, 6); adg_assert_isapprox(pair.y, 7); cpml_primitive_put_point(&primitive, 1, &pair); adg_assert_isapprox(pair.x, 8); adg_assert_isapprox(pair.y, 9); cpml_primitive_put_point(&primitive, 2, &pair); adg_assert_isapprox(pair.x, 10); adg_assert_isapprox(pair.y, 11); cpml_primitive_put_point(&primitive, 3, &pair); adg_assert_isapprox(pair.x, -2); adg_assert_isapprox(pair.y, 2); cpml_primitive_put_point(&primitive, 4, &pair); adg_assert_isapprox(pair.x, -2); adg_assert_isapprox(pair.y, 2); /* Close */ cpml_primitive_next(&primitive); cpml_primitive_put_point(&primitive, 0, &pair); adg_assert_isapprox(pair.x, -2); adg_assert_isapprox(pair.y, 2); cpml_primitive_put_point(&primitive, 1, &pair); adg_assert_isapprox(pair.x, 0); adg_assert_isapprox(pair.y, 1); cpml_primitive_put_point(&primitive, 2, &pair); adg_assert_isapprox(pair.x, 0); adg_assert_isapprox(pair.y, 1); }
static void _cpml_method_set_point(void) { gsize data_size; CpmlSegment original, *segment; CpmlPrimitive primitive; CpmlPair pair, pair2; int equality; /* Work on a copy to not modify the original path data */ cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path()); data_size = original.num_data * sizeof(cairo_path_data_t); segment = cpml_segment_deep_dup(&original); /* Line */ cpml_primitive_from_segment(&primitive, segment); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, ==, 0); cpml_primitive_put_point(&primitive, 0, &pair); pair.x += 1; cpml_primitive_set_point(&primitive, 0, &pair); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); pair.x -= 1; cpml_primitive_set_point(&primitive, 0, &pair); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, ==, 0); cpml_primitive_put_point(&primitive, 1, &pair); pair.y += 1; cpml_primitive_set_point(&primitive, 1, &pair); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); /* On a CPML_LINE primitives, -1 and 1 indices are equals */ cpml_primitive_put_point(&primitive, -1, &pair2); adg_assert_isapprox(pair.x, pair2.x); adg_assert_isapprox(pair.y, pair2.y); memcpy(segment->data, original.data, data_size); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, ==, 0); cpml_primitive_put_point(&primitive, 2, &pair); pair.x += 1; pair.y += 1; /* This should be a NOP without segfaults */ cpml_primitive_set_point(&primitive, 2, &pair); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, ==, 0); /* From now on, memcpy() is assumed to force equality (as already * proved by the previous assertions) and pair2 is used as a * different-from-everything pair, that is setting pair2 on any * point will break the equality between segment->data and * original.data */ pair2.x = 12345; pair2.y = 54321; /* Arc */ cpml_primitive_next(&primitive); cpml_primitive_set_point(&primitive, 0, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 1, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 2, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 3, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, ==, 0); /* Curve */ cpml_primitive_next(&primitive); cpml_primitive_set_point(&primitive, 0, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 1, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 2, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 3, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 4, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, ==, 0); /* Close */ cpml_primitive_next(&primitive); cpml_primitive_set_point(&primitive, 0, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 1, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, !=, 0); memcpy(segment->data, original.data, data_size); cpml_primitive_set_point(&primitive, 2, &pair2); equality = memcmp(original.data, segment->data, data_size); g_assert_cmpint(equality, ==, 0); g_free(segment); }
static void _cpml_method_get_closest_pos(void) { CpmlSegment segment; CpmlPrimitive primitive; CpmlPair pair; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&primitive, &segment); /* Line */ pair.x = 0; pair.y = 1; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); pair.x = 3; pair.y = 1; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); pair.x = -1; pair.y = -1; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); pair.x = 4; pair.y = 2; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); pair.x = 1.5; pair.y = 0; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0.5); /* Arc */ cpml_primitive_next(&primitive); /* TODO: not yet implemented * pair.x = 3; pair.y = 1; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); * pair.x = 6; pair.y = 7; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); * pair.x = 0; pair.y = 0; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); * pair.x = 10; pair.y = 10; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); */ /* Close */ cpml_primitive_next(&primitive); /* TODO: not yet implemented * pair.x = 6; pair.y = 7; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); * pair.x = -2; pair.y = 2; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); * pair.x = 10; pair.y = 10; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); * pair.x = 0; pair.y = 0; * adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); */ /* Close */ cpml_primitive_next(&primitive); pair.x = -2; pair.y = 2; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); pair.x = 0; pair.y = 1; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); pair.x = -3; pair.y = 3; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0); pair.x = 1; pair.y = 0; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 1); pair.x = -1; pair.y = 1.5; adg_assert_isapprox(cpml_primitive_get_closest_pos(&primitive, &pair), 0.5); }
static void _cpml_method_offset(void) { CpmlSegment original, *segment; CpmlPrimitive primitive, line, curve; CpmlPrimitive *backup; /* Work on a copy to avoid modifying the original cairo path */ cpml_segment_from_cairo(&original, (cairo_path_t *) adg_test_path()); segment = cpml_segment_deep_dup(&original); cpml_primitive_from_segment(&primitive, segment); /* Offsetting and de-offsetting can introduce rounding errors * so we use adg_assert_isapprox instead of g_assert_cmpfloat */ /* Line */ cpml_primitive_copy(&line, &primitive); cpml_primitive_offset(&primitive, 1); adg_assert_isapprox((primitive.org)->point.x, 0); adg_assert_isapprox((primitive.org)->point.y, 2); adg_assert_isapprox(primitive.data[1].point.x, 3); adg_assert_isapprox(primitive.data[1].point.y, 2); cpml_primitive_offset(&primitive, -1); adg_assert_isapprox((primitive.org)->point.x, 0); adg_assert_isapprox((primitive.org)->point.y, 1); adg_assert_isapprox(primitive.data[1].point.x, 3); adg_assert_isapprox(primitive.data[1].point.y, 1); /* Arc */ cpml_primitive_next(&primitive); cpml_primitive_offset(&primitive, 1); adg_assert_isapprox((primitive.org)->point.x, 2.003); adg_assert_isapprox((primitive.org)->point.y, 0.923); adg_assert_isapprox(primitive.data[1].point.x, 3.156); adg_assert_isapprox(primitive.data[1].point.y, 5.537); adg_assert_isapprox(primitive.data[2].point.x, 5.463); adg_assert_isapprox(primitive.data[2].point.y, 7.844); cpml_primitive_offset(&primitive, -1); adg_assert_isapprox((primitive.org)->point.x, 3); adg_assert_isapprox((primitive.org)->point.y, 1); adg_assert_isapprox(primitive.data[1].point.x, 4); adg_assert_isapprox(primitive.data[1].point.y, 5); adg_assert_isapprox(primitive.data[2].point.x, 6); adg_assert_isapprox(primitive.data[2].point.y, 7); /* Curve */ cpml_primitive_next(&primitive); cpml_primitive_copy(&curve, &primitive); /* The offset algorithm for curves is an approximation, so * offsetting +1 and -1 does not return the original curve. * Keeping a backup around to restore the original data. */ backup = cpml_primitive_deep_dup(&curve); /* Testing different algorithms */ cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_GEOMETRICAL); cpml_primitive_offset(&primitive, 1); adg_assert_isapprox((primitive.org)->point.x, 5.293); adg_assert_isapprox((primitive.org)->point.y, 7.707); adg_assert_isapprox(primitive.data[1].point.x, 7.889); adg_assert_isapprox(primitive.data[1].point.y, 8.515); adg_assert_isapprox(primitive.data[2].point.x, 11.196); adg_assert_isapprox(primitive.data[2].point.y, 9.007); adg_assert_isapprox(primitive.data[3].point.x, -1.4); adg_assert_isapprox(primitive.data[3].point.y, 1.2); cpml_primitive_copy_data(&primitive, backup); cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_BAIOCA); cpml_primitive_offset(&primitive, 1); adg_assert_isapprox((primitive.org)->point.x, 5.293); adg_assert_isapprox((primitive.org)->point.y, 7.707); adg_assert_isapprox(primitive.data[1].point.x, 6.901); adg_assert_isapprox(primitive.data[1].point.y, 9.315); adg_assert_isapprox(primitive.data[2].point.x, 10.806); adg_assert_isapprox(primitive.data[2].point.y, 10.355); adg_assert_isapprox(primitive.data[3].point.x, -1.4); adg_assert_isapprox(primitive.data[3].point.y, 1.2); cpml_primitive_copy_data(&primitive, backup); cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_HANDCRAFT); cpml_primitive_offset(&primitive, 1); adg_assert_isapprox((primitive.org)->point.x, 5.293); adg_assert_isapprox((primitive.org)->point.y, 7.707); adg_assert_isapprox(primitive.data[1].point.x, -5.758); adg_assert_isapprox(primitive.data[1].point.y, -3.344); adg_assert_isapprox(primitive.data[2].point.x, 24.987); adg_assert_isapprox(primitive.data[2].point.y, 20.99); adg_assert_isapprox(primitive.data[3].point.x, -1.4); adg_assert_isapprox(primitive.data[3].point.y, 1.2); cpml_primitive_copy_data(&primitive, backup); g_free(backup); cpml_curve_offset_algorithm(CPML_CURVE_OFFSET_ALGORITHM_DEFAULT); /* Close: this primitive does not own data points but should * modify the points of the previous and next primitives */ cpml_primitive_next(&primitive); cpml_primitive_offset(&primitive, 1); adg_assert_isapprox((curve.org)->point.x, 6); adg_assert_isapprox((curve.org)->point.y, 7); adg_assert_isapprox(curve.data[3].point.x, -1.553); adg_assert_isapprox(curve.data[3].point.y, 2.894); adg_assert_isapprox((line.org)->point.x, 0.447); adg_assert_isapprox((line.org)->point.y, 1.894); adg_assert_isapprox(line.data[1].point.x, 3); adg_assert_isapprox(line.data[1].point.y, 1); cpml_primitive_offset(&primitive, -1); adg_assert_isapprox((curve.org)->point.x, 6); adg_assert_isapprox((curve.org)->point.y, 7); adg_assert_isapprox(curve.data[3].point.x, -2); adg_assert_isapprox(curve.data[3].point.y, 2); adg_assert_isapprox((line.org)->point.x, 0); adg_assert_isapprox((line.org)->point.y, 1); adg_assert_isapprox(line.data[1].point.x, 3); adg_assert_isapprox(line.data[1].point.y, 1); g_free(segment); }
static gboolean _adg_append_operation(AdgPath *path, AdgAction action, ...) { AdgPathPrivate *data; AdgOperation *operation; va_list var_args; data = path->data; if (data->last.data == NULL) { g_warning(_("%s: requested a '%s' operation on a path without current primitive"), G_STRLOC, _adg_action_name(action)); return FALSE; } operation = &data->operation; if (operation->action != ADG_ACTION_NONE) { g_warning(_("%s: requested a '%s' operation while a '%s' operation was active"), G_STRLOC, _adg_action_name(action), _adg_action_name(operation->action)); /* XXX: http://dev.entidi.com/p/adg/issues/50/ */ return FALSE; } va_start(var_args, action); switch (action) { case ADG_ACTION_CHAMFER: operation->data.chamfer.delta1 = va_arg(var_args, double); operation->data.chamfer.delta2 = va_arg(var_args, double); break; case ADG_ACTION_FILLET: operation->data.fillet.radius = va_arg(var_args, double); break; case ADG_ACTION_NONE: va_end(var_args); return TRUE; default: g_warning(_("%s: %d path operation not recognized"), G_STRLOC, action); va_end(var_args); return FALSE; } operation->action = action; va_end(var_args); if (data->last.data[0].header.type == CPML_CLOSE) { /* Special case: an action with the close primitive should * be resolved now by changing the close primitive to a * line-to and using it as second operand and use the first * primitive of the current segment as first operand */ guint length; cairo_path_data_t *path_data; CpmlSegment segment; CpmlPrimitive current; length = data->cairo.array->len; /* Ensure the close path primitive is not the only data */ g_return_val_if_fail(length > 1, FALSE); /* Allocate one more item once for all to accept the * conversion from a close to line-to primitive */ data->cairo.array = g_array_set_size(data->cairo.array, length + 1); path_data = (cairo_path_data_t *) data->cairo.array->data; --data->cairo.array->len; /* Set segment and current (the first primitive of segment) */ cpml_segment_from_cairo(&segment, _adg_read_cairo_path(path)); while (cpml_segment_next(&segment)) ; cpml_primitive_from_segment(¤t, &segment); /* Convert close path to a line-to primitive */ ++data->cairo.array->len; path_data[length - 1].header.type = CPML_LINE; path_data[length - 1].header.length = 2; path_data[length] = *current.org; data->last.segment = &segment; data->last.org = &path_data[length - 2]; data->last.data = &path_data[length - 1]; _adg_do_action(path, action, ¤t); } return TRUE; }