static void _adg_do_chamfer(AdgPath *path, CpmlPrimitive *current) { AdgPathPrivate *data; CpmlPrimitive *last; gdouble delta1, delta2; gdouble len1, len2; CpmlPair pair; data = path->data; last = &data->last; delta1 = data->operation.data.chamfer.delta1; len1 = cpml_primitive_get_length(last); if (delta1 >= len1) { g_warning(_("%s: first chamfer delta of %lf is greather than the available %lf length"), G_STRLOC, delta1, len1); return; } delta2 = data->operation.data.chamfer.delta2; len2 = cpml_primitive_get_length(current); if (delta2 >= len2) { g_warning(_("%s: second chamfer delta of %lf is greather than the available %lf length"), G_STRLOC, delta1, len1); return; } /* Change the end point of the last primitive */ cpml_primitive_put_pair_at(last, 1. - delta1 / len1, &pair); cpml_primitive_set_point(last, -1, &pair); /* Change the start point of the current primitive */ cpml_primitive_put_pair_at(current, delta2 / len2, &pair); cpml_primitive_set_point(current, 0, &pair); /* Add the chamfer line */ data->operation.action = ADG_ACTION_NONE; adg_path_append(path, CPML_LINE, &pair); }
static void offset(CpmlPrimitive *line, double offset) { CpmlPair p1, p2; CpmlVector normal; cpml_primitive_put_point(line, 0, &p1); cpml_primitive_put_point(line, -1, &p2); put_vector_at(line, 0, &normal); cpml_vector_normal(&normal); cpml_vector_set_length(&normal, offset); p1.x += normal.x; p1.y += normal.y; p2.x += normal.x; p2.y += normal.y; cpml_primitive_set_point(line, 0, &p1); cpml_primitive_set_point(line, -1, &p2); }
static void _cpml_sanity_set_point(gint i) { CpmlSegment segment; CpmlPrimitive primitive; CpmlPair pair = { 1, 1 }; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&primitive, &segment); switch (i) { case 1: cpml_primitive_set_point(NULL, 1, &pair); break; case 2: cpml_primitive_set_point(&primitive, 1, NULL); break; default: g_test_trap_assert_failed(); break; } }
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 _adg_do_fillet(AdgPath *path, CpmlPrimitive *current) { AdgPathPrivate *data; CpmlPrimitive *last, *current_dup, *last_dup; gdouble radius, offset, pos; CpmlPair center, vector, p[3]; data = path->data; last = &data->last; current_dup = cpml_primitive_deep_dup(current); last_dup = cpml_primitive_deep_dup(last); radius = data->operation.data.fillet.radius; offset = _adg_is_convex(last_dup, current_dup) ? -radius : radius; /* Find the center of the fillet from the intersection between * the last and current primitives offseted by radius */ cpml_primitive_offset(current_dup, offset); cpml_primitive_offset(last_dup, offset); if (cpml_primitive_put_intersections(current_dup, last_dup, 1, ¢er) == 0) { g_warning(_("%s: fillet with radius of %lf is not applicable here"), G_STRLOC, radius); g_free(current_dup); g_free(last_dup); return; } /* Compute the start point of the fillet */ pos = cpml_primitive_get_closest_pos(last_dup, ¢er); cpml_primitive_put_vector_at(last_dup, pos, &vector); cpml_vector_set_length(&vector, offset); cpml_vector_normal(&vector); p[0].x = center.x - vector.x; p[0].y = center.y - vector.y; /* Compute the mid point of the fillet */ cpml_pair_from_cairo(&vector, current->org); vector.x -= center.x; vector.y -= center.y; cpml_vector_set_length(&vector, radius); p[1].x = center.x + vector.x; p[1].y = center.y + vector.y; /* Compute the end point of the fillet */ pos = cpml_primitive_get_closest_pos(current_dup, ¢er); cpml_primitive_put_vector_at(current_dup, pos, &vector); cpml_vector_set_length(&vector, offset); cpml_vector_normal(&vector); p[2].x = center.x - vector.x; p[2].y = center.y - vector.y; g_free(current_dup); g_free(last_dup); /* Change the end point of the last primitive */ cpml_primitive_set_point(last, -1, &p[0]); /* Change the start point of the current primitive */ cpml_primitive_set_point(current, 0, &p[2]); /* Add the fillet arc */ data->operation.action = ADG_ACTION_NONE; adg_path_append(path, CPML_ARC, &p[1], &p[2]); }