pathbuilder: Redo semantics for starting curves

We now always have a "current point" which is either the last point an
operation was made to, or (0, 0) if no drawing operation has
been made yet.

Adding a contour of any kind to the builder will always update the
current point to that contour's end point.
This commit is contained in:
Benjamin Otte
2020-11-28 06:46:26 +01:00
committed by Matthias Clasen
parent b87095330a
commit 098c402a97
3 changed files with 87 additions and 19 deletions

View File

@@ -54,6 +54,9 @@ struct _GskContourClass
GString *string);
gboolean (* get_bounds) (const GskContour *contour,
graphene_rect_t *bounds);
void (* get_start_end) (const GskContour *self,
graphene_point_t *start,
graphene_point_t *end);
gboolean (* foreach) (const GskContour *contour,
float tolerance,
GskPathForeachFunc func,
@@ -214,6 +217,20 @@ gsk_rect_contour_get_bounds (const GskContour *contour,
return TRUE;
}
static void
gsk_rect_contour_get_start_end (const GskContour *contour,
graphene_point_t *start,
graphene_point_t *end)
{
const GskRectContour *self = (const GskRectContour *) contour;
if (start)
*start = GRAPHENE_POINT_INIT (self->x, self->y);
if (end)
*end = GRAPHENE_POINT_INIT (self->x, self->y);
}
static gboolean
gsk_rect_contour_foreach (const GskContour *contour,
float tolerance,
@@ -472,6 +489,7 @@ static const GskContourClass GSK_RECT_CONTOUR_CLASS =
gsk_rect_contour_get_flags,
gsk_rect_contour_print,
gsk_rect_contour_get_bounds,
gsk_rect_contour_get_start_end,
gsk_rect_contour_foreach,
gsk_rect_contour_init_measure,
gsk_rect_contour_free_measure,
@@ -564,6 +582,20 @@ gsk_circle_contour_get_bounds (const GskContour *contour,
return TRUE;
}
static void
gsk_circle_contour_get_start_end (const GskContour *contour,
graphene_point_t *start,
graphene_point_t *end)
{
const GskCircleContour *self = (const GskCircleContour *) contour;
if (start)
*start = GSK_CIRCLE_POINT_INIT (self, self->start_angle);
if (end)
*end = GSK_CIRCLE_POINT_INIT (self, self->end_angle);
}
typedef struct
{
GskPathForeachFunc func;
@@ -758,6 +790,7 @@ static const GskContourClass GSK_CIRCLE_CONTOUR_CLASS =
gsk_circle_contour_get_flags,
gsk_circle_contour_print,
gsk_circle_contour_get_bounds,
gsk_circle_contour_get_start_end,
gsk_circle_contour_foreach,
gsk_circle_contour_init_measure,
gsk_circle_contour_free_measure,
@@ -944,6 +977,20 @@ gsk_standard_contour_get_bounds (const GskContour *contour,
return bounds->size.width > 0 && bounds->size.height > 0;
}
static void
gsk_standard_contour_get_start_end (const GskContour *contour,
graphene_point_t *start,
graphene_point_t *end)
{
const GskStandardContour *self = (const GskStandardContour *) contour;
if (start)
*start = self->points[0];
if (end)
*end = self->points[self->n_points - 1];
}
typedef struct
{
float start;
@@ -1398,6 +1445,7 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
gsk_standard_contour_get_flags,
gsk_standard_contour_print,
gsk_standard_contour_get_bounds,
gsk_standard_contour_get_start_end,
gsk_standard_contour_foreach,
gsk_standard_contour_init_measure,
gsk_standard_contour_free_measure,
@@ -1484,6 +1532,14 @@ gsk_contour_free_measure (GskPath *path,
self->klass->free_measure (self, data);
}
void
gsk_contour_get_start_end (const GskContour *self,
graphene_point_t *start,
graphene_point_t *end)
{
self->klass->get_start_end (self, start, end);
}
void
gsk_contour_get_point (GskPath *path,
gsize i,

View File

@@ -77,6 +77,7 @@ struct _GskPathBuilder
GSList *contours; /* (reverse) list of already recorded contours */
GskPathFlags flags; /* flags for the current path */
graphene_point_t current_point; /* the point all drawing ops start from */
GArray *ops; /* operations for current contour - size == 0 means no current contour */
GArray *points; /* points for the operations */
};
@@ -106,6 +107,10 @@ gsk_path_builder_new (void)
self->ops = g_array_new (FALSE, FALSE, sizeof (GskStandardOperation));
self->points = g_array_new (FALSE, FALSE, sizeof (graphene_point_t));
/* Be explicit here */
self->current_point = GRAPHENE_POINT_INIT (0, 0);
return self;
}
@@ -132,18 +137,29 @@ gsk_path_builder_ref (GskPathBuilder *self)
return self;
}
static void
gsk_path_builder_ensure_current (GskPathBuilder *self)
{
if (self->ops->len != 0)
return;
self->flags = GSK_PATH_FLAT;
g_array_append_vals (self->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1);
g_array_append_val (self->points, self->current_point);
}
static void
gsk_path_builder_append_current (GskPathBuilder *self,
GskPathOperation op,
gsize n_points,
const graphene_point_t *points)
{
g_assert (self->ops->len > 0);
g_assert (self->points->len > 0);
g_assert (n_points > 0);
gsk_path_builder_ensure_current (self);
g_array_append_vals (self->ops, &(GskStandardOperation) { op, builder->points->len - 1 }, 1);
g_array_append_vals (self->ops, &(GskStandardOperation) { op, self->points->len - 1 }, 1);
g_array_append_vals (self->points, points, n_points);
self->current_point = points[n_points - 1];
}
static void
@@ -247,7 +263,7 @@ gsk_path_builder_to_path (GskPathBuilder *self)
gsk_path_builder_end_current (self);
self->contours = g_slist_reverse (builder->contours);
self->contours = g_slist_reverse (self->contours);
path = gsk_path_new_from_contours (self->contours);
@@ -262,7 +278,7 @@ gsk_path_builder_add_contour (GskPathBuilder *self,
{
gsk_path_builder_end_current (self);
self->contours = g_slist_prepend (builder->contours, contour);
self->contours = g_slist_prepend (self->contours, contour);
}
/**
@@ -312,6 +328,8 @@ gsk_path_builder_add_rect (GskPathBuilder *self,
contour = gsk_rect_contour_new (rect);
gsk_path_builder_add_contour (self, contour);
gsk_contour_get_start_end (contour, NULL, &self->current_point);
}
/**
@@ -358,9 +376,9 @@ gsk_path_builder_move_to (GskPathBuilder *self,
gsk_path_builder_end_current (self);
self->flags = GSK_PATH_FLAT;
g_array_append_vals (self->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1);
g_array_append_val (self->points, GRAPHENE_POINT_INIT(x, y));
self->current_point = GRAPHENE_POINT_INIT(x, y);
gsk_path_builder_ensure_current (self);
}
/**
@@ -379,14 +397,8 @@ gsk_path_builder_line_to (GskPathBuilder *self,
{
g_return_if_fail (self != NULL);
if (self->ops->len == 0)
{
gsk_path_builder_move_to (self, x, y);
return;
}
/* skip the line if it goes to the same point */
if (graphene_point_equal (&g_array_index (self->points, graphene_point_t, builder->points->len - 1),
if (graphene_point_equal (&self->current_point,
&GRAPHENE_POINT_INIT (x, y)))
return;
@@ -422,9 +434,6 @@ gsk_path_builder_curve_to (GskPathBuilder *self,
{
g_return_if_fail (self != NULL);
if (self->ops->len == 0)
gsk_path_builder_move_to (self, x1, y1);
self->flags &= ~GSK_PATH_FLAT;
gsk_path_builder_append_current (self,
GSK_PATH_CURVE,

View File

@@ -73,6 +73,9 @@ gpointer gsk_contour_init_measure (GskPath
void gsk_contour_free_measure (GskPath *path,
gsize i,
gpointer data);
void gsk_contour_get_start_end (const GskContour *self,
graphene_point_t *start,
graphene_point_t *end);
void gsk_contour_get_point (GskPath *path,
gsize i,
gpointer measure_data,