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_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_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_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 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; }