API: Add gsk_path_transform

This is an obvious operation to want for paths.
This commit is contained in:
Matthias Clasen
2022-04-06 22:27:55 -04:00
parent 61468e810c
commit 28cb5ee985
2 changed files with 98 additions and 0 deletions

View File

@@ -24,6 +24,7 @@
#include "gskcurveprivate.h"
#include "gskpathbuilder.h"
#include "gskstrokeprivate.h"
#include "gsktransform.h"
#include "gdk/gdkprivate.h"
@@ -1282,6 +1283,99 @@ gsk_path_is_convex (GskPath *self)
return gsk_contour_is_convex (gsk_path_get_contour (self, 0));
}
typedef struct
{
GskTransform *transform;
GskPathBuilder *builder;
} TransformData;
static gboolean
transform_cb (GskPathOperation op,
const graphene_point_t *pts,
gsize n_pts,
float weight,
gpointer user_data)
{
TransformData *data = user_data;
graphene_point_t tp[4];
switch (op)
{
case GSK_PATH_CLOSE:
gsk_path_builder_close (data->builder);
break;
case GSK_PATH_MOVE:
gsk_transform_transform_point (data->transform, &pts[0], &tp[0]);
gsk_path_builder_move_to (data->builder, tp[0].x, tp[0].y);
break;
case GSK_PATH_LINE:
gsk_transform_transform_point (data->transform, &pts[1], &tp[1]);
gsk_path_builder_line_to (data->builder, tp[1].x, tp[1].y);
break;
case GSK_PATH_QUAD:
gsk_transform_transform_point (data->transform, &pts[1], &tp[1]);
gsk_transform_transform_point (data->transform, &pts[2], &tp[2]);
gsk_path_builder_quad_to (data->builder,
tp[1].x, tp[1].y,
tp[2].x, tp[2].y);
break;
case GSK_PATH_CUBIC:
gsk_transform_transform_point (data->transform, &pts[1], &tp[1]);
gsk_transform_transform_point (data->transform, &pts[2], &tp[2]);
gsk_transform_transform_point (data->transform, &pts[3], &tp[3]);
gsk_path_builder_cubic_to (data->builder,
tp[1].x, tp[1].y,
tp[2].x, tp[2].y,
tp[3].x, tp[3].y);
break;
case GSK_PATH_CONIC:
gsk_transform_transform_point (data->transform, &pts[1], &tp[1]);
gsk_transform_transform_point (data->transform, &pts[3], &tp[3]);
gsk_path_builder_conic_to (data->builder,
tp[1].x, tp[1].y,
tp[3].x, tp[3].y,
weight);
break;
default:
g_assert_not_reached ();
}
return TRUE;
}
/**
* gsk_path_transform:
* @self: a `GskPath`
* @transform: the transform to apply
*
* Applies the transform to all points of @self
* and returns the resulting path.
*
* Returns: a new `GskPath`
*/
GskPath *
gsk_path_transform (GskPath *self,
GskTransform *transform)
{
TransformData data;
data.transform = transform;
data.builder = gsk_path_builder_new ();
gsk_path_foreach (self,
GSK_PATH_FOREACH_ALLOW_CUBIC | GSK_PATH_FOREACH_ALLOW_CONIC,
transform_cb,
&data);
return gsk_path_builder_free_to_path (data.builder);
}
/**
* gsk_path_stroke:
* @self: a `GskPath`

View File

@@ -116,6 +116,10 @@ gboolean gsk_path_foreach (GskPath
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_reverse (GskPath *self);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_transform (GskPath *self,
GskTransform *transform);
GDK_AVAILABLE_IN_ALL
GskPath * gsk_path_stroke (GskPath *self,
GskStroke *stroke);