예제 #1
0
static void
_cpml_sanity_put_intersections(gint i)
{
    CpmlSegment segment;
    CpmlPrimitive primitive1, primitive2;
    CpmlPair pair;

    /* Set primitive1 to 1.1 and primitive 2 to 2.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(&primitive1, &segment);

    cpml_segment_next(&segment);
    cpml_primitive_from_segment(&primitive2, &segment);
    cpml_primitive_next(&primitive2);

    switch (i) {
    case 1:
        cpml_primitive_put_intersections(NULL, &primitive2, 2, &pair);
        break;
    case 2:
        cpml_primitive_put_intersections(&primitive1, NULL, 2, &pair);
        break;
    case 3:
        cpml_primitive_put_intersections(&primitive1, &primitive2, 2, NULL);
        break;
    default:
        g_test_trap_assert_failed();
        break;
    }
}
예제 #2
0
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);
}
예제 #3
0
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);
}
예제 #4
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * 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));
}
예제 #5
0
파일: adg-path.c 프로젝트: bert/adg
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(&current, &segment);
        do {
            cpml_primitive_copy(over, last);
            cpml_primitive_copy(last, &current);
        } while (cpml_primitive_next(&current));
    } while (cpml_segment_next(&segment));
}
예제 #6
0
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);
}
예제 #7
0
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);
}
예제 #8
0
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);
}
예제 #9
0
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;
    }
}
예제 #10
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * cpml_segment_to_cairo:
 * @segment: a #CpmlSegment
 * @cr: the destination cairo context
 *
 * Appends the path of @segment to @cr. The segment is "flattened",
 * that is %CPML_ARC primitives are approximated by one or more
 * %CPML_CURVE using cpml_arc_to_cairo(). Check its documentation
 * for further details.
 *
 * Since: 1.0
 **/
void
cpml_segment_to_cairo(const CpmlSegment *segment, cairo_t *cr)
{
    CpmlPrimitive primitive;

    cpml_primitive_from_segment(&primitive, (CpmlSegment *) segment);

    do {
        cpml_primitive_to_cairo(&primitive, cr);
    } while (cpml_primitive_next(&primitive));
}
예제 #11
0
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);
}
예제 #12
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * cpml_segment_dump:
 * @segment: a #CpmlSegment
 *
 * Dumps the specified @segment to stdout. Useful for debugging purposes.
 *
 * Since: 1.0
 **/
void
cpml_segment_dump(const CpmlSegment *segment)
{
    CpmlPrimitive primitive;
    int first_call = 1;

    cpml_primitive_from_segment(&primitive, (CpmlSegment *) segment);

    do {
        cpml_primitive_dump(&primitive, first_call);
        first_call = 0;
    } while (cpml_primitive_next(&primitive));
}
예제 #13
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * cpml_segment_put_extents:
 * @segment: a #CpmlSegment
 * @extents: where to store the extents
 *
 * Gets the whole extents of @segment.
 *
 * Since: 1.0
 **/
void
cpml_segment_put_extents(const CpmlSegment *segment, CpmlExtents *extents)
{
    CpmlPrimitive primitive;
    CpmlExtents primitive_extents;

    extents->is_defined = 0;

    cpml_primitive_from_segment(&primitive, (CpmlSegment *) segment);

    do {
        cpml_primitive_put_extents(&primitive, &primitive_extents);
        cpml_extents_add(extents, &primitive_extents);
    } while (cpml_primitive_next(&primitive));
}
예제 #14
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);
}
예제 #15
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * cpml_segment_get_length:
 * @segment: a #CpmlSegment
 *
 * Gets the whole length of @segment.
 *
 * Returns: the requested length
 *
 * Since: 1.0
 **/
double
cpml_segment_get_length(const CpmlSegment *segment)
{
    CpmlPrimitive primitive;
    double length;

    cpml_primitive_from_segment(&primitive, (CpmlSegment *) segment);
    length = 0;

    do {
        length += cpml_primitive_get_length(&primitive);
    } while (cpml_primitive_next(&primitive));

    return length;
}
예제 #16
0
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);
}
예제 #17
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * cpml_segment_put_pair_at:
 * @segment: a #CpmlSegment
 * @pos:     the position value
 * @pair:    the destination #CpmlPair
 *
 * Gets the coordinates of the point lying on @segment at position
 * @pos. @pos is an homogeneous factor where 0 is the start point,
 * 1 the end point, 0.5 the mid point and so on.
 * The relation <constant>0 < @pos < 1</constant> should be satisfied,
 * although some cases accept value outside this range.
 *
 * <important>
 * <title>TODO</title>
 * <itemizedlist>
 * <listitem>The actual implementation returns only the start and end points,
 *           that is only when @pos is 0 or 1.</listitem>
 * </itemizedlist>
 * </important>
 *
 * Since: 1.0
 **/
void
cpml_segment_put_pair_at(const CpmlSegment *segment, double pos,
                         CpmlPair *pair)
{
    CpmlPrimitive primitive;

    cpml_primitive_from_segment(&primitive, (CpmlSegment *) segment);

    /* Handle the common cases: start and end points */
    if (pos == 0) {
        cpml_primitive_put_pair_at(&primitive, 0, pair);
    } if (pos == 1) {
        while (cpml_primitive_next(&primitive))
            ;
        cpml_primitive_put_pair_at(&primitive, 1, pair);
    }
}
예제 #18
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));
}
예제 #19
0
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));
}
예제 #20
0
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);
}
예제 #21
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * cpml_segment_put_intersections:
 * @segment:  the first #CpmlSegment
 * @segment2: the second #CpmlSegment
 * @n_dest:   maximum number of intersections to return
 * @dest:     the destination vector of #CpmlPair
 *
 * Computes the intersections between @segment and @segment2 and
 * returns the found points in @dest. If the intersections are more
 * than @n_dest, only the first @n_dest pairs are stored in @dest.
 *
 * To get the job done, the primitives of @segment are sequentially
 * scanned for intersections with any primitive in @segment2. This
 * means @segment has a higher precedence over @segment2.
 *
 * Returns: the number of intersections found
 *
 * Since: 1.0
 **/
size_t
cpml_segment_put_intersections(const CpmlSegment *segment,
                               const CpmlSegment *segment2,
                               size_t n_dest, CpmlPair *dest)
{
    CpmlPrimitive portion;
    size_t partial, total;

    cpml_primitive_from_segment(&portion, (CpmlSegment *) segment);
    total = 0;

    do {
        partial = cpml_primitive_put_intersections_with_segment(&portion,
                                                                segment2,
                                                                n_dest - total,
                                                                dest + total);
        total += partial;
    } while (total < n_dest && cpml_primitive_next(&portion));

    return total;
}
예제 #22
0
파일: cpml-segment.c 프로젝트: bert/adg
/**
 * cpml_segment_transform:
 * @segment: a #CpmlSegment
 * @matrix: the matrix to be applied
 *
 * Applies @matrix on all the points of @segment.
 *
 * Since: 1.0
 **/
void
cpml_segment_transform(CpmlSegment *segment, const cairo_matrix_t *matrix)
{
    CpmlPrimitive primitive;
    cairo_path_data_t *data;
    size_t n_points;

    cpml_primitive_from_segment(&primitive, segment);
    cairo_matrix_transform_point(matrix, &(primitive.org)->point.x,
                                 &(primitive.org)->point.y);

    do {
        data = primitive.data;
        if (data->header.type != CPML_CLOSE) {
            n_points = cpml_primitive_get_n_points(&primitive);

            while (--n_points > 0) {
                ++data;
                cairo_matrix_transform_point(matrix,
                                             &data->point.x, &data->point.y);
            }
        }
    } while (cpml_primitive_next(&primitive));
}
예제 #23
0
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);
}
예제 #24
0
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);
}
예제 #25
0
파일: adg-path.c 프로젝트: bert/adg
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(&current, &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, &current);
    }

    return TRUE;
}
예제 #26
0
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);
}
예제 #27
0
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);
}