Beispiel #1
0
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));
}
Beispiel #2
0
/**
 * 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));
}
Beispiel #3
0
static void
_cpml_sanity_copy(gint i)
{
    CpmlPrimitive primitive;
    CpmlSegment segment;

    cpml_segment_from_cairo(&segment, (cairo_path_t *) adg_test_path());
    cpml_primitive_from_segment(&primitive, &segment);

    switch (i) {
    case 1:
        cpml_primitive_copy(NULL, &primitive);
        break;
    case 2:
        cpml_primitive_copy(&primitive, NULL);
        break;
    default:
        g_test_trap_assert_failed();
        break;
    }
}
Beispiel #4
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));
}
Beispiel #5
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);
}
Beispiel #6
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);
}