path: Change semantics of gtk_path_builder_add_segment()
Allow start >= end to mean that the path continues at the beginning after reaching the end until it reaches the point at @end.
This commit is contained in:
@@ -76,6 +76,7 @@ struct _GskContourClass
|
||||
void (* add_segment) (const GskContour *contour,
|
||||
GskPathBuilder *builder,
|
||||
gpointer measure_data,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end);
|
||||
int (* get_winding) (const GskContour *contour,
|
||||
@@ -395,6 +396,7 @@ static void
|
||||
gsk_rect_contour_add_segment (const GskContour *contour,
|
||||
GskPathBuilder *builder,
|
||||
gpointer measure_data,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end)
|
||||
{
|
||||
@@ -404,7 +406,8 @@ gsk_rect_contour_add_segment (const GskContour *contour,
|
||||
|
||||
if (start < w)
|
||||
{
|
||||
gsk_path_builder_move_to (builder, self->x + start * (w / self->width), self->y);
|
||||
if (emit_move_to)
|
||||
gsk_path_builder_move_to (builder, self->x + start * (w / self->width), self->y);
|
||||
if (end <= w)
|
||||
{
|
||||
gsk_path_builder_line_to (builder, self->x + end * (w / self->width), self->y);
|
||||
@@ -417,7 +420,7 @@ gsk_rect_contour_add_segment (const GskContour *contour,
|
||||
|
||||
if (start < h)
|
||||
{
|
||||
if (start >= 0)
|
||||
if (start >= 0 && emit_move_to)
|
||||
gsk_path_builder_move_to (builder, self->x + self->width, self->y + start * (h / self->height));
|
||||
if (end <= h)
|
||||
{
|
||||
@@ -431,7 +434,7 @@ gsk_rect_contour_add_segment (const GskContour *contour,
|
||||
|
||||
if (start < w)
|
||||
{
|
||||
if (start >= 0)
|
||||
if (start >= 0 && emit_move_to)
|
||||
gsk_path_builder_move_to (builder, self->x + (w - start) * (w / self->width), self->y + self->height);
|
||||
if (end <= w)
|
||||
{
|
||||
@@ -445,7 +448,7 @@ gsk_rect_contour_add_segment (const GskContour *contour,
|
||||
|
||||
if (start < h)
|
||||
{
|
||||
if (start >= 0)
|
||||
if (start >= 0 && emit_move_to)
|
||||
gsk_path_builder_move_to (builder, self->x, self->y + (h - start) * (h / self->height));
|
||||
if (end <= h)
|
||||
{
|
||||
@@ -776,6 +779,7 @@ static void
|
||||
gsk_circle_contour_add_segment (const GskContour *contour,
|
||||
GskPathBuilder *builder,
|
||||
gpointer measure_data,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end)
|
||||
{
|
||||
@@ -784,6 +788,8 @@ gsk_circle_contour_add_segment (const GskContour *contour,
|
||||
float length = self->radius * DEG_TO_RAD (delta);
|
||||
GskContour *segment;
|
||||
|
||||
if (!emit_move_to)
|
||||
g_warning ("FIXME: somebody needs to decompose contours into segments differently");
|
||||
segment = gsk_circle_contour_new (&self->center, self->radius,
|
||||
self->start_angle + start/length * delta,
|
||||
self->start_angle + end/length * delta);
|
||||
@@ -1340,6 +1346,7 @@ static void
|
||||
gsk_standard_contour_add_segment (const GskContour *contour,
|
||||
GskPathBuilder *builder,
|
||||
gpointer measure_data,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end)
|
||||
{
|
||||
@@ -1391,7 +1398,8 @@ gsk_standard_contour_add_segment (const GskContour *contour,
|
||||
{
|
||||
gsk_curve_segment (&curve, start_progress, end_progress, &cut);
|
||||
start_point = gsk_curve_get_start_point (&cut);
|
||||
gsk_path_builder_move_to (builder, start_point->x, start_point->y);
|
||||
if (emit_move_to)
|
||||
gsk_path_builder_move_to (builder, start_point->x, start_point->y);
|
||||
gsk_curve_builder_to (&cut, builder);
|
||||
return;
|
||||
}
|
||||
@@ -1399,12 +1407,13 @@ gsk_standard_contour_add_segment (const GskContour *contour,
|
||||
gsk_curve_split (&curve, start_progress, NULL, &cut);
|
||||
|
||||
start_point = gsk_curve_get_start_point (&cut);
|
||||
gsk_path_builder_move_to (builder, start_point->x, start_point->y);
|
||||
if (emit_move_to)
|
||||
gsk_path_builder_move_to (builder, start_point->x, start_point->y);
|
||||
gsk_curve_builder_to (&cut, builder);
|
||||
i = start_measure->op + 1;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
else
|
||||
i = emit_move_to ? 0 : 1;
|
||||
|
||||
for (; i < (end_measure ? end_measure->op : self->n_ops - 1); i++)
|
||||
{
|
||||
@@ -1718,10 +1727,11 @@ void
|
||||
gsk_contour_add_segment (const GskContour *self,
|
||||
GskPathBuilder *builder,
|
||||
gpointer measure_data,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end)
|
||||
{
|
||||
self->klass->add_segment (self, builder, measure_data, start, end);
|
||||
self->klass->add_segment (self, builder, measure_data, emit_move_to, start, end);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -90,6 +90,7 @@ int gsk_contour_get_winding (const GskContou
|
||||
void gsk_contour_add_segment (const GskContour *self,
|
||||
GskPathBuilder *builder,
|
||||
gpointer measure_data,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end);
|
||||
gboolean gsk_contour_get_stroke_bounds (const GskContour *self,
|
||||
|
||||
@@ -530,40 +530,16 @@ gsk_path_measure_in_fill (GskPathMeasure *self,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gsk_path_builder_add_segment:
|
||||
* @self: a #GskPathBuilder
|
||||
* @measure: the #GskPathMeasure to take the segment to
|
||||
* @start: start distance into the path
|
||||
* @end: end distance into the path
|
||||
*
|
||||
* Adds to @self the segment of @measure inbetween @start and @end.
|
||||
*
|
||||
* The distances are given relative to the length of @measure's path,
|
||||
* from 0 for the beginning of the path to
|
||||
* gsk_path_measure_get_length() for the end of the path. The values
|
||||
* will be clamped to that range.
|
||||
*
|
||||
* If @start >= @end after clamping, no path will be added.
|
||||
**/
|
||||
void
|
||||
gsk_path_builder_add_segment (GskPathBuilder *self,
|
||||
GskPathMeasure *measure,
|
||||
float start,
|
||||
float end)
|
||||
static void
|
||||
gsk_path_builder_add_segment_chunk (GskPathBuilder *self,
|
||||
GskPathMeasure *measure,
|
||||
gboolean emit_move_to,
|
||||
float start,
|
||||
float end)
|
||||
{
|
||||
gsize i;
|
||||
g_assert (start < end);
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (measure != NULL);
|
||||
|
||||
start = gsk_path_measure_clamp_distance (measure, start);
|
||||
end = gsk_path_measure_clamp_distance (measure, end);
|
||||
if (start >= end)
|
||||
return;
|
||||
|
||||
for (i = measure->first; i < measure->last; i++)
|
||||
for (gsize i = measure->first; i < measure->last; i++)
|
||||
{
|
||||
if (measure->measures[i].length < start)
|
||||
{
|
||||
@@ -576,6 +552,7 @@ gsk_path_builder_add_segment (GskPathBuilder *self,
|
||||
gsk_contour_add_segment (gsk_path_get_contour (measure->path, i),
|
||||
self,
|
||||
measure->measures[i].contour_data,
|
||||
emit_move_to,
|
||||
start,
|
||||
len);
|
||||
end -= len;
|
||||
@@ -588,6 +565,64 @@ gsk_path_builder_add_segment (GskPathBuilder *self,
|
||||
end -= measure->measures[i].length;
|
||||
gsk_path_builder_add_contour (self, gsk_contour_dup (gsk_path_get_contour (measure->path, i)));
|
||||
}
|
||||
emit_move_to = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_path_builder_add_segment:
|
||||
* @self: a #GskPathBuilder
|
||||
* @measure: the #GskPathMeasure to take the segment to
|
||||
* @start: start distance into the path
|
||||
* @end: end distance into the path
|
||||
*
|
||||
* Adds to @self the segment of @measure from @start to @end.
|
||||
*
|
||||
* The distances are given relative to the length of @measure's path,
|
||||
* from 0 for the beginning of the path to
|
||||
* gsk_path_measure_get_length() for the end of the path. The values
|
||||
* will be clamped to that range.
|
||||
*
|
||||
* If @start >= @end after clamping, the path will first add the segment
|
||||
* from @start to the end of the path, and then add the segment from
|
||||
* the beginning to @end. If the path is closed, these segments will
|
||||
* be connected.
|
||||
**/
|
||||
void
|
||||
gsk_path_builder_add_segment (GskPathBuilder *self,
|
||||
GskPathMeasure *measure,
|
||||
float start,
|
||||
float end)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (measure != NULL);
|
||||
|
||||
start = gsk_path_measure_clamp_distance (measure, start);
|
||||
end = gsk_path_measure_clamp_distance (measure, end);
|
||||
|
||||
if (start < end)
|
||||
{
|
||||
gsk_path_builder_add_segment_chunk (self, measure, TRUE, start, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the path is closed, we can connect the 2 subpaths. */
|
||||
gboolean closed = gsk_path_measure_is_closed (measure);
|
||||
gboolean need_move_to = !closed;
|
||||
|
||||
if (start < measure->length)
|
||||
gsk_path_builder_add_segment_chunk (self, measure,
|
||||
TRUE,
|
||||
start, measure->length);
|
||||
else
|
||||
need_move_to = TRUE;
|
||||
|
||||
if (end > 0)
|
||||
gsk_path_builder_add_segment_chunk (self, measure,
|
||||
need_move_to,
|
||||
0, end);
|
||||
if (start == end && closed)
|
||||
gsk_path_builder_close (self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -609,7 +609,10 @@ test_segment_start (void)
|
||||
path1 = gsk_path_builder_free_to_path (builder);
|
||||
measure1 = gsk_path_measure_new (path1);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
|
||||
if (seg_length == 0)
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_measure_get_length (measure), gsk_path_measure_get_length (measure1), epsilon);
|
||||
else
|
||||
g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure1);
|
||||
gsk_path_unref (path1);
|
||||
@@ -642,7 +645,10 @@ test_segment_end (void)
|
||||
path1 = gsk_path_builder_free_to_path (builder);
|
||||
measure1 = gsk_path_measure_new (path1);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
|
||||
if (seg_length == 0)
|
||||
g_assert_cmpfloat_with_epsilon (gsk_path_measure_get_length (measure), gsk_path_measure_get_length (measure1), epsilon);
|
||||
else
|
||||
g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure1);
|
||||
gsk_path_unref (path1);
|
||||
@@ -655,8 +661,8 @@ test_segment_end (void)
|
||||
static void
|
||||
test_segment_chunk (void)
|
||||
{
|
||||
GskPath *path, *path1;
|
||||
GskPathMeasure *measure, *measure1;
|
||||
GskPath *path, *path1, *path2;
|
||||
GskPathMeasure *measure, *measure1, *measure2;
|
||||
GskPathBuilder *builder;
|
||||
float epsilon, length;
|
||||
guint i;
|
||||
@@ -677,6 +683,15 @@ test_segment_chunk (void)
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (length / 2, gsk_path_measure_get_length (measure1), epsilon);
|
||||
|
||||
builder = gsk_path_builder_new ();
|
||||
gsk_path_builder_add_segment (builder, measure, seg_start + length / 2, seg_start);
|
||||
path2 = gsk_path_builder_free_to_path (builder);
|
||||
measure2 = gsk_path_measure_new (path2);
|
||||
|
||||
g_assert_cmpfloat_with_epsilon (length / 2, gsk_path_measure_get_length (measure2), epsilon);
|
||||
|
||||
gsk_path_measure_unref (measure2);
|
||||
gsk_path_unref (path2);
|
||||
gsk_path_measure_unref (measure1);
|
||||
gsk_path_unref (path1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user