pathmeasure: Add gsk_path_measure_add_segment()
This allows chunking paths, weeee.
This commit is contained in:
@@ -363,6 +363,7 @@ gsk_path_measure_ref
|
|||||||
gsk_path_measure_unref
|
gsk_path_measure_unref
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
gsk_path_measure_get_length
|
gsk_path_measure_get_length
|
||||||
|
gsk_path_measure_add_segment
|
||||||
<SUBSECTION Private>
|
<SUBSECTION Private>
|
||||||
GSK_TYPE_PATH_MEASURE
|
GSK_TYPE_PATH_MEASURE
|
||||||
gsk_path_measure_get_type
|
gsk_path_measure_get_type
|
||||||
|
|||||||
185
gsk/gskpath.c
185
gsk/gskpath.c
@@ -61,6 +61,11 @@ struct _GskContourClass
|
|||||||
gpointer measure_data);
|
gpointer measure_data);
|
||||||
void (* copy) (const GskContour *contour,
|
void (* copy) (const GskContour *contour,
|
||||||
GskContour *dest);
|
GskContour *dest);
|
||||||
|
void (* add_segment) (const GskContour *contour,
|
||||||
|
GskPathBuilder *builder,
|
||||||
|
gpointer measure_data,
|
||||||
|
float start,
|
||||||
|
float end);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GskPath
|
struct _GskPath
|
||||||
@@ -188,6 +193,71 @@ gsk_rect_contour_copy (const GskContour *contour,
|
|||||||
*target = *self;
|
*target = *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_rect_contour_add_segment (const GskContour *contour,
|
||||||
|
GskPathBuilder *builder,
|
||||||
|
gpointer measure_data,
|
||||||
|
float start,
|
||||||
|
float end)
|
||||||
|
{
|
||||||
|
const GskRectContour *self = (const GskRectContour *) contour;
|
||||||
|
float w = ABS (self->width);
|
||||||
|
float h = ABS (self->height);
|
||||||
|
|
||||||
|
if (start < w)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gsk_path_builder_line_to (builder, self->x + self->width, self->y);
|
||||||
|
}
|
||||||
|
start -= w;
|
||||||
|
end -= w;
|
||||||
|
|
||||||
|
if (start < h)
|
||||||
|
{
|
||||||
|
if (start >= 0)
|
||||||
|
gsk_path_builder_move_to (builder, self->x + self->width, self->y + start * (h / self->height));
|
||||||
|
if (end <= h)
|
||||||
|
{
|
||||||
|
gsk_path_builder_line_to (builder, self->x + self->width, self->y + end * (h / self->height));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gsk_path_builder_line_to (builder, self->x + self->width, self->y + self->height);
|
||||||
|
}
|
||||||
|
start -= h;
|
||||||
|
end -= h;
|
||||||
|
|
||||||
|
if (start < w)
|
||||||
|
{
|
||||||
|
if (start >= 0)
|
||||||
|
gsk_path_builder_move_to (builder, self->x + (w - start) * (w / self->width), self->y + self->height);
|
||||||
|
if (end <= w)
|
||||||
|
{
|
||||||
|
gsk_path_builder_line_to (builder, self->x + (w - end) * (w / self->width), self->y + self->height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gsk_path_builder_line_to (builder, self->x, self->y + self->height);
|
||||||
|
}
|
||||||
|
start -= w;
|
||||||
|
end -= w;
|
||||||
|
|
||||||
|
if (start < h)
|
||||||
|
{
|
||||||
|
if (start >= 0)
|
||||||
|
gsk_path_builder_move_to (builder, self->x, self->y + (h - start) * (h / self->height));
|
||||||
|
if (end <= h)
|
||||||
|
{
|
||||||
|
gsk_path_builder_line_to (builder, self->x, self->y + (h - end) * (h / self->height));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gsk_path_builder_line_to (builder, self->x, self->y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const GskContourClass GSK_RECT_CONTOUR_CLASS =
|
static const GskContourClass GSK_RECT_CONTOUR_CLASS =
|
||||||
{
|
{
|
||||||
sizeof (GskRectContour),
|
sizeof (GskRectContour),
|
||||||
@@ -198,7 +268,8 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS =
|
|||||||
gsk_rect_contour_get_bounds,
|
gsk_rect_contour_get_bounds,
|
||||||
gsk_rect_contour_init_measure,
|
gsk_rect_contour_init_measure,
|
||||||
gsk_rect_contour_free_measure,
|
gsk_rect_contour_free_measure,
|
||||||
gsk_rect_contour_copy
|
gsk_rect_contour_copy,
|
||||||
|
gsk_rect_contour_add_segment
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -452,6 +523,102 @@ gsk_standard_contour_copy (const GskContour *contour,
|
|||||||
gsk_standard_contour_init (dest, self->ops, self->n_ops, self->points, self->n_points);
|
gsk_standard_contour_init (dest, self->ops, self->n_ops, self->points, self->n_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_standard_contour_add_segment (const GskContour *contour,
|
||||||
|
GskPathBuilder *builder,
|
||||||
|
gpointer measure_data,
|
||||||
|
float start,
|
||||||
|
float end)
|
||||||
|
{
|
||||||
|
GskStandardContour *self = (GskStandardContour *) contour;
|
||||||
|
gsize i;
|
||||||
|
float length;
|
||||||
|
|
||||||
|
for (i = 0; end > 0 && i < self->n_ops; i ++)
|
||||||
|
{
|
||||||
|
graphene_point_t *pt = &self->points[self->ops[i].point];
|
||||||
|
|
||||||
|
switch (self->ops[i].op)
|
||||||
|
{
|
||||||
|
case GSK_PATH_MOVE:
|
||||||
|
if (start <= 0.0)
|
||||||
|
{
|
||||||
|
gsk_path_builder_move_to (builder, pt[0].x, pt[0].y);
|
||||||
|
start = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CLOSE:
|
||||||
|
case GSK_PATH_LINE:
|
||||||
|
length = graphene_point_distance (&pt[0], &pt[1], NULL, NULL);
|
||||||
|
if (length <= start)
|
||||||
|
{
|
||||||
|
start -= length;
|
||||||
|
end -= length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (start >= 0)
|
||||||
|
{
|
||||||
|
graphene_point_t start_pt;
|
||||||
|
graphene_point_interpolate (&pt[0], &pt[1], start / length, &start_pt);
|
||||||
|
gsk_path_builder_move_to (builder, start_pt.x, start_pt.y);
|
||||||
|
start = -1;
|
||||||
|
}
|
||||||
|
if (length <= end)
|
||||||
|
{
|
||||||
|
gsk_path_builder_line_to (builder, pt[1].x, pt[1].y);
|
||||||
|
end -= length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
graphene_point_t end_pt;
|
||||||
|
graphene_point_interpolate (&pt[0], &pt[1], end / length, &end_pt);
|
||||||
|
gsk_path_builder_line_to (builder, end_pt.x, end_pt.y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_PATH_CURVE:
|
||||||
|
g_warning ("i'm not fat!");
|
||||||
|
length = graphene_point_distance (&pt[0], &pt[3], NULL, NULL);
|
||||||
|
if (length <= start)
|
||||||
|
{
|
||||||
|
start -= length;
|
||||||
|
end -= length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (start >= 0)
|
||||||
|
{
|
||||||
|
graphene_point_t start_pt;
|
||||||
|
graphene_point_interpolate (&pt[0], &pt[3], start / length, &start_pt);
|
||||||
|
gsk_path_builder_move_to (builder, start_pt.x, start_pt.y);
|
||||||
|
start = -1;
|
||||||
|
}
|
||||||
|
if (length <= end)
|
||||||
|
{
|
||||||
|
gsk_path_builder_line_to (builder, pt[3].x, pt[3].y);
|
||||||
|
end -= length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
graphene_point_t end_pt;
|
||||||
|
graphene_point_interpolate (&pt[0], &pt[3], end / length, &end_pt);
|
||||||
|
gsk_path_builder_line_to (builder, end_pt.x, end_pt.y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
|
static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
|
||||||
{
|
{
|
||||||
sizeof (GskStandardContour),
|
sizeof (GskStandardContour),
|
||||||
@@ -462,7 +629,8 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
|
|||||||
gsk_standard_contour_get_bounds,
|
gsk_standard_contour_get_bounds,
|
||||||
gsk_standard_contour_init_measure,
|
gsk_standard_contour_init_measure,
|
||||||
gsk_standard_contour_free_measure,
|
gsk_standard_contour_free_measure,
|
||||||
gsk_standard_contour_copy
|
gsk_standard_contour_copy,
|
||||||
|
gsk_standard_contour_add_segment
|
||||||
};
|
};
|
||||||
|
|
||||||
/* You must ensure the contour has enough size allocated,
|
/* You must ensure the contour has enough size allocated,
|
||||||
@@ -845,6 +1013,19 @@ gsk_path_builder_add_contour (GskPathBuilder *builder,
|
|||||||
builder->contours = g_slist_prepend (builder->contours, copy);
|
builder->contours = g_slist_prepend (builder->contours, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_path_builder_add_contour_segment (GskPathBuilder *builder,
|
||||||
|
GskPath *path,
|
||||||
|
gsize i,
|
||||||
|
gpointer measure_data,
|
||||||
|
float start,
|
||||||
|
float end)
|
||||||
|
{
|
||||||
|
const GskContour *self = path->contours[i];
|
||||||
|
|
||||||
|
self->klass->add_segment (self, builder, measure_data, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_path_builder_new:
|
* gsk_path_builder_new:
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -161,3 +161,62 @@ gsk_path_measure_get_length (GskPathMeasure *self)
|
|||||||
return self->length;
|
return self->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gsk_path_measure_add_segment:
|
||||||
|
* @self: a #GskPathMeasure
|
||||||
|
* @builder: the builder to add the segment to
|
||||||
|
* @start: start distance into the path
|
||||||
|
* @end: end distance into the path
|
||||||
|
*
|
||||||
|
* Adds to @builder the segment of @path inbetween @start and @end.
|
||||||
|
*
|
||||||
|
* The distances are given relative to the length of @self's path,
|
||||||
|
* from 0 for the begginning 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_measure_add_segment (GskPathMeasure *self,
|
||||||
|
GskPathBuilder *builder,
|
||||||
|
float start,
|
||||||
|
float end)
|
||||||
|
{
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
g_return_if_fail (self != NULL);
|
||||||
|
g_return_if_fail (builder != NULL);
|
||||||
|
|
||||||
|
start = CLAMP (start, 0, self->length);
|
||||||
|
end = CLAMP (end, 0, self->length);
|
||||||
|
if (start >= end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < self->n_contours; i++)
|
||||||
|
{
|
||||||
|
if (self->measures[i].length < start)
|
||||||
|
{
|
||||||
|
start -= self->measures[i].length;
|
||||||
|
end -= self->measures[i].length;
|
||||||
|
}
|
||||||
|
else if (start > 0 || end < self->measures[i].length)
|
||||||
|
{
|
||||||
|
float len = MIN (end, self->measures[i].length);
|
||||||
|
gsk_path_builder_add_contour_segment (builder,
|
||||||
|
self->path,
|
||||||
|
i,
|
||||||
|
self->measures[i].contour_data,
|
||||||
|
start,
|
||||||
|
len);
|
||||||
|
start = 0;
|
||||||
|
end -= len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
end -= self->measures[i].length;
|
||||||
|
gsk_path_builder_add_contour (builder, self->path, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <gsk/gsktypes.h>
|
#include <gsk/gskpath.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -44,6 +44,11 @@ void gsk_path_measure_unref (GskPathMeasure
|
|||||||
GDK_AVAILABLE_IN_ALL
|
GDK_AVAILABLE_IN_ALL
|
||||||
float gsk_path_measure_get_length (GskPathMeasure *self);
|
float gsk_path_measure_get_length (GskPathMeasure *self);
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_ALL
|
||||||
|
void gsk_path_measure_add_segment (GskPathMeasure *self,
|
||||||
|
GskPathBuilder *builder,
|
||||||
|
float start,
|
||||||
|
float end);
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GSK_PATH_MEASURE_H__ */
|
#endif /* __GSK_PATH_MEASURE_H__ */
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ void gsk_contour_free_measure (GskPath
|
|||||||
void gsk_path_builder_add_contour (GskPathBuilder *builder,
|
void gsk_path_builder_add_contour (GskPathBuilder *builder,
|
||||||
GskPath *path,
|
GskPath *path,
|
||||||
gsize i);
|
gsize i);
|
||||||
|
void gsk_path_builder_add_contour_segment (GskPathBuilder *builder,
|
||||||
|
GskPath *path,
|
||||||
|
gsize i,
|
||||||
|
gpointer measure_data,
|
||||||
|
float start,
|
||||||
|
float end);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user