static double get_closest_pos(const CpmlPrimitive *line, const CpmlPair *pair) { CpmlPair p1_4[4]; CpmlVector normal; CpmlPair dummy; double pos; cpml_primitive_put_point(line, 0, &p1_4[0]); cpml_primitive_put_point(line, -1, &p1_4[1]); normal.x = p1_4[1].x - p1_4[0].x; normal.y = p1_4[1].y - p1_4[0].y; cpml_vector_normal(&normal); cpml_pair_copy(&p1_4[2], pair); p1_4[3].x = pair->x + normal.x; p1_4[3].y = pair->y + normal.y; /* Ensure to return 0 if intersection() fails */ pos = 0; /* The destination pair cannot be NULL to avoid crashes */ intersection(p1_4, &dummy, &pos); /* Clamp the result to 0..1 */ if (pos < 0) pos = 0; else if (pos > 1.) pos = 1.; return pos; }
static double get_length(const CpmlPrimitive *line) { CpmlPair p1, p2; cpml_primitive_put_point(line, 0, &p1); cpml_primitive_put_point(line, -1, &p2); return cpml_pair_distance(&p1, &p2); }
static void put_vector_at(const CpmlPrimitive *line, double pos, CpmlVector *vector) { CpmlPair p1, p2; cpml_primitive_put_point(line, 0, &p1); cpml_primitive_put_point(line, -1, &p2); vector->x = p2.x - p1.x; vector->y = p2.y - p1.y; }
static void put_pair_at(const CpmlPrimitive *line, double pos, CpmlPair *pair) { CpmlPair p1, p2; cpml_primitive_put_point(line, 0, &p1); cpml_primitive_put_point(line, -1, &p2); pair->x = p1.x + (p2.x - p1.x) * pos; pair->y = p1.y + (p2.y - p1.y) * pos; }
static size_t put_intersections(const CpmlPrimitive *line, const CpmlPrimitive *primitive, size_t n_dest, CpmlPair *dest) { CpmlPair p1_4[4]; cpml_primitive_put_point(line, 0, &p1_4[0]); cpml_primitive_put_point(line, -1, &p1_4[1]); cpml_primitive_put_point(primitive, 0, &p1_4[2]); cpml_primitive_put_point(primitive, -1, &p1_4[3]); return intersection(p1_4, dest, NULL) ? 1 : 0; }
static void put_extents(const CpmlPrimitive *line, CpmlExtents *extents) { CpmlPair p1, p2; extents->is_defined = 0; cpml_primitive_put_point(line, 0, &p1); cpml_primitive_put_point(line, -1, &p2); cpml_extents_pair_add(extents, &p1); cpml_extents_pair_add(extents, &p2); }
/** * cpml_segment_offset: * @segment: a #CpmlSegment * @offset: the offset distance * * Offsets a segment of the specified amount, that is builds a "parallel" * segment at the @offset distance from the original one and returns the * result by replacing the original @segment. * * <important> * <title>TODO</title> * <itemizedlist> * <listitem>Closed path are not yet managed: an elegant solution is not * so obvious: use <function>cpml_close_offset</function> when * will be available.</listitem> * <listitem>Degenerated primitives, such as lines of length 0, are not * managed properly.</listitem> * </itemizedlist> * </important> * * Since: 1.0 **/ void cpml_segment_offset(CpmlSegment *segment, double offset) { CpmlPrimitive primitive; CpmlPrimitive last_primitive; CpmlPair old_end; cairo_path_data_t org, *old_org; int first_cycle; cpml_primitive_from_segment(&primitive, segment); first_cycle = 1; do { if (! first_cycle) { cpml_pair_to_cairo(&old_end, &org); old_org = primitive.org; primitive.org = &org; } cpml_primitive_put_point(&primitive, -1, &old_end); cpml_primitive_offset(&primitive, offset); if (! first_cycle) { cpml_primitive_join(&last_primitive, &primitive); primitive.org = old_org; } cpml_primitive_copy(&last_primitive, &primitive); first_cycle = 0; } while (cpml_primitive_next(&primitive)); }
static void put_extents(const CpmlPrimitive *arc, CpmlExtents *extents) { double r, start, end; CpmlPair center, pair; extents->is_defined = 0; if (!cpml_arc_info(arc, ¢er, &r, &start, &end)) return; /* Add the right quadrant point if needed */ if (ANGLE_INCLUDED(0) || ANGLE_INCLUDED(M_PI * 2)) { pair.x = center.x + r; pair.y = center.y; cpml_extents_pair_add(extents, &pair); } /* Add the bottom quadrant point if needed */ if (ANGLE_INCLUDED(M_PI_2) || ANGLE_INCLUDED(M_PI_2 * 5)) { pair.x = center.x; pair.y = center.y + r; cpml_extents_pair_add(extents, &pair); } /* Add the left quadrant point if needed */ if (ANGLE_INCLUDED(M_PI)) { pair.x = center.x - r; pair.y = center.y; cpml_extents_pair_add(extents, &pair); } /* Add the top quadrant point if needed */ if (ANGLE_INCLUDED(M_PI_2 * 3) || ANGLE_INCLUDED(-M_PI_2)) { pair.x = center.x; pair.y = center.y - r; cpml_extents_pair_add(extents, &pair); } /* Add the start point */ cpml_primitive_put_point(arc, 0, &pair); cpml_extents_pair_add(extents, &pair); /* Add the end point */ cpml_primitive_put_point(arc, -1, &pair); cpml_extents_pair_add(extents, &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_put_point(gint i) { CpmlSegment segment; CpmlPrimitive primitive; CpmlPair pair; cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path()); cpml_primitive_from_segment(&primitive, &segment); switch (i) { case 1: cpml_primitive_put_point(NULL, 0, &pair); break; case 2: cpml_primitive_put_point(&primitive, 0, NULL); break; default: g_test_trap_assert_failed(); break; } }
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); }