diff options
author | Benjamin Otte <otte@redhat.com> | 2019-03-01 06:24:33 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2019-03-04 23:15:06 +0100 |
commit | 4916280883f7850e17e025150be7c6ab25a8efc9 (patch) | |
tree | 827468dd6604547d3cf51f01995b50aec98c0ce4 | |
parent | 0e1a50366a738389cce5d92b978ce0d07a5ab951 (diff) | |
download | gtk+-4916280883f7850e17e025150be7c6ab25a8efc9.tar.gz |
transform: Add more API
In particular, add a per-category querying API for the matrix:
- gsk_transform_to_translate()
- gsk_transform_to_affine()
- gsk_transform_to_2d()
- gsk_transform_to_matrix()
This way, code can use the relevant one for the given category.
-rw-r--r-- | docs/reference/gsk/gsk4-sections.txt | 5 | ||||
-rw-r--r-- | gsk/gsktransform.c | 300 | ||||
-rw-r--r-- | gsk/gsktransform.h | 24 | ||||
-rw-r--r-- | gsk/gsktransformprivate.h | 6 |
4 files changed, 329 insertions, 6 deletions
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt index 0b4b4e1de5..9ebdc9df84 100644 --- a/docs/reference/gsk/gsk4-sections.txt +++ b/docs/reference/gsk/gsk4-sections.txt @@ -156,6 +156,9 @@ gsk_transform_unref gsk_transform_print gsk_transform_to_string gsk_transform_to_matrix +gsk_transform_to_2d +gsk_transform_to_affine +gsk_transform_to_translate <SUBSECTION> gsk_transform_identity gsk_transform_transform @@ -171,6 +174,8 @@ gsk_transform_equal <SUBSECTION> gsk_transform_get_transform_type gsk_transform_get_next +<SUBSECTION> +gsk_transform_transform_bounds <SUBSECTION Private> GSK_TYPE_TRANSFORM gsk_transform_get_type diff --git a/gsk/gsktransform.c b/gsk/gsktransform.c index c7a3c72229..788a58de26 100644 --- a/gsk/gsktransform.c +++ b/gsk/gsktransform.c @@ -59,11 +59,21 @@ struct _GskTransformClass GskMatrixCategory (* categorize) (GskTransform *transform); void (* to_matrix) (GskTransform *transform, graphene_matrix_t *out_matrix); + gboolean (* apply_2d) (GskTransform *transform, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy); gboolean (* apply_affine) (GskTransform *transform, float *out_scale_x, float *out_scale_y, float *out_dx, float *out_dy); + gboolean (* apply_translate) (GskTransform *transform, + float *out_dx, + float *out_dy); void (* print) (GskTransform *transform, GString *string); GskTransform * (* apply) (GskTransform *transform, @@ -148,6 +158,18 @@ gsk_identity_transform_to_matrix (GskTransform *transform, } static gboolean +gsk_identity_transform_apply_2d (GskTransform *transform, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy) +{ + return TRUE; +} + +static gboolean gsk_identity_transform_apply_affine (GskTransform *transform, float *out_scale_x, float *out_scale_y, @@ -157,6 +179,14 @@ gsk_identity_transform_apply_affine (GskTransform *transform, return TRUE; } +static gboolean +gsk_identity_transform_apply_translate (GskTransform *transform, + float *out_dx, + float *out_dy) +{ + return TRUE; +} + static void gsk_identity_transform_print (GskTransform *transform, GString *string) @@ -186,7 +216,9 @@ static const GskTransformClass GSK_IDENTITY_TRANSFORM_CLASS = gsk_identity_transform_finalize, gsk_identity_transform_categorize, gsk_identity_transform_to_matrix, + gsk_identity_transform_apply_2d, gsk_identity_transform_apply_affine, + gsk_identity_transform_apply_translate, gsk_identity_transform_print, gsk_identity_transform_apply, gsk_identity_transform_equal, @@ -249,6 +281,18 @@ gsk_matrix_transform_to_matrix (GskTransform *transform, } static gboolean +gsk_matrix_transform_apply_2d (GskTransform *transform, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy) +{ + return FALSE; +} + +static gboolean gsk_matrix_transform_apply_affine (GskTransform *transform, float *out_scale_x, float *out_scale_y, @@ -282,6 +326,33 @@ gsk_matrix_transform_apply_affine (GskTransform *transform, } } +static gboolean +gsk_matrix_transform_apply_translate (GskTransform *transform, + float *out_dx, + float *out_dy) +{ + GskMatrixTransform *self = (GskMatrixTransform *) transform; + + switch (self->category) + { + case GSK_MATRIX_CATEGORY_UNKNOWN: + case GSK_MATRIX_CATEGORY_ANY: + case GSK_MATRIX_CATEGORY_INVERTIBLE: + case GSK_MATRIX_CATEGORY_2D_AFFINE: + default: + return FALSE; + + case GSK_MATRIX_CATEGORY_2D_TRANSLATE: + *out_dx += graphene_matrix_get_value (&self->matrix, 3, 0); + *out_dy += graphene_matrix_get_value (&self->matrix, 3, 1); + return TRUE; + + case GSK_MATRIX_CATEGORY_IDENTITY: + return TRUE; + } + return TRUE; +} + static void string_append_double (GString *string, double d) @@ -341,7 +412,9 @@ static const GskTransformClass GSK_TRANSFORM_TRANSFORM_CLASS = gsk_matrix_transform_finalize, gsk_matrix_transform_categorize, gsk_matrix_transform_to_matrix, + gsk_matrix_transform_apply_2d, gsk_matrix_transform_apply_affine, + gsk_matrix_transform_apply_translate, gsk_matrix_transform_print, gsk_matrix_transform_apply, gsk_matrix_transform_equal, @@ -413,6 +486,26 @@ gsk_translate_transform_to_matrix (GskTransform *transform, } static gboolean +gsk_translate_transform_apply_2d (GskTransform *transform, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy) +{ + GskTranslateTransform *self = (GskTranslateTransform *) transform; + + if (self->point.z != 0.0) + return FALSE; + + *out_dx += *out_xx * self->point.x + *out_xy * self->point.y; + *out_dy += *out_yx * self->point.x + *out_yy * self->point.y; + + return TRUE; +} + +static gboolean gsk_translate_transform_apply_affine (GskTransform *transform, float *out_scale_x, float *out_scale_y, @@ -430,6 +523,22 @@ gsk_translate_transform_apply_affine (GskTransform *transform, return TRUE; } +static gboolean +gsk_translate_transform_apply_translate (GskTransform *transform, + float *out_dx, + float *out_dy) +{ + GskTranslateTransform *self = (GskTranslateTransform *) transform; + + if (self->point.z != 0.0) + return FALSE; + + *out_dx += self->point.x; + *out_dy += self->point.y; + + return TRUE; +} + static GskTransform * gsk_translate_transform_apply (GskTransform *transform, GskTransform *apply_to) @@ -479,7 +588,9 @@ static const GskTransformClass GSK_TRANSLATE_TRANSFORM_CLASS = gsk_translate_transform_finalize, gsk_translate_transform_categorize, gsk_translate_transform_to_matrix, + gsk_translate_transform_apply_2d, gsk_translate_transform_apply_affine, + gsk_translate_transform_apply_translate, gsk_translate_transform_print, gsk_translate_transform_apply, gsk_translate_transform_equal, @@ -558,6 +669,19 @@ gsk_rotate_transform_to_matrix (GskTransform *transform, } static gboolean +gsk_rotate_transform_apply_2d (GskTransform *transform, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy) +{ + /* FIXME: Do the right thing for normal rotations */ + return FALSE; +} + +static gboolean gsk_rotate_transform_apply_affine (GskTransform *transform, float *out_scale_x, float *out_scale_y, @@ -567,6 +691,14 @@ gsk_rotate_transform_apply_affine (GskTransform *transform, return FALSE; } +static gboolean +gsk_rotate_transform_apply_translate (GskTransform *transform, + float *out_dx, + float *out_dy) +{ + return FALSE; +} + static GskTransform * gsk_rotate_transform_apply (GskTransform *transform, GskTransform *apply_to) @@ -626,7 +758,9 @@ static const GskTransformClass GSK_ROTATE_TRANSFORM_CLASS = gsk_rotate_transform_finalize, gsk_rotate_transform_categorize, gsk_rotate_transform_to_matrix, + gsk_rotate_transform_apply_2d, gsk_rotate_transform_apply_affine, + gsk_rotate_transform_apply_translate, gsk_rotate_transform_print, gsk_rotate_transform_apply, gsk_rotate_transform_equal, @@ -712,6 +846,28 @@ gsk_scale_transform_to_matrix (GskTransform *transform, } static gboolean +gsk_scale_transform_apply_2d (GskTransform *transform, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy) +{ + GskScaleTransform *self = (GskScaleTransform *) transform; + + if (self->factor_z != 1.0) + return FALSE; + + *out_xx *= self->factor_x; + *out_yx *= self->factor_x; + *out_xy *= self->factor_y; + *out_yy *= self->factor_y; + + return TRUE; +} + +static gboolean gsk_scale_transform_apply_affine (GskTransform *transform, float *out_scale_x, float *out_scale_y, @@ -729,6 +885,14 @@ gsk_scale_transform_apply_affine (GskTransform *transform, return TRUE; } +static gboolean +gsk_scale_transform_apply_translate (GskTransform *transform, + float *out_dx, + float *out_dy) +{ + return FALSE; +} + static GskTransform * gsk_scale_transform_apply (GskTransform *transform, GskTransform *apply_to) @@ -787,7 +951,9 @@ static const GskTransformClass GSK_SCALE_TRANSFORM_CLASS = gsk_scale_transform_finalize, gsk_scale_transform_categorize, gsk_scale_transform_to_matrix, + gsk_scale_transform_apply_2d, gsk_scale_transform_apply_affine, + gsk_scale_transform_apply_translate, gsk_scale_transform_print, gsk_scale_transform_apply, gsk_scale_transform_equal, @@ -1001,6 +1167,84 @@ gsk_transform_to_matrix (GskTransform *self, graphene_matrix_multiply (&m, out_matrix, out_matrix); } +/** + * gsk_transform_to_2d: + * @m: a #GskTransform + * @out_xx: (out): return location for the xx member + * @out_yx: (out): return location for the yx member + * @out_xy: (out): return location for the xy member + * @out_yy: (out): return location for the yy member + * @out_dx: (out): return location for the x0 member + * @out_dy: (out): return location for the y0 member + * + * Converts a #GskTransform to a 2D transformation + * matrix, if the given matrix is compatible. + * + * The returned values have the following layout: + * + * |[<!-- language="plain" --> + * | xx yx | | a b 0 | + * | xy yy | = | c d 0 | + * | x0 y0 | | tx ty 1 | + * ]| + * + * This function can be used to convert between a #GskTransform + * and a matrix type from other 2D drawing libraries, in particular + * Cairo. + * + * Returns: %TRUE if the matrix is compatible with an 2D + * transformation matrix. + */ +gboolean +gsk_transform_to_2d (GskTransform *self, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy) +{ + if (self == NULL) + { + *out_xx = 1.0f; + *out_yx = 0.0f; + *out_xy = 0.0f; + *out_yy = 1.0f; + *out_dx = 0.0f; + *out_dy = 0.0f; + return TRUE; + } + + if (!gsk_transform_to_2d (self->next, + out_xx, out_yx, + out_xy, out_yy, + out_dx, out_dy)) + return FALSE; + + return self->transform_class->apply_2d (self, + out_xx, out_yx, + out_xy, out_yy, + out_dx, out_dy); +} + +/** + * gsk_transform_to_affine: + * @m: a #GskTransform + * @out_scale_x: (out): return location for the scale + * factor in the x direction + * @out_scale_y: (out): return location for the scale + * factor in the y direction + * @out_dx: (out): return location for the translation + * in the x direction + * @out_dy: (out): return location for the translation + * in the y direction + * + * Converts a #GskTransform to 2D affine transformation + * factors, if the given matrix is compatible. + * + * Returns: %TRUE if the matrix is compatible with an 2D + * affine transformation. + */ gboolean gsk_transform_to_affine (GskTransform *self, float *out_scale_x, @@ -1028,6 +1272,40 @@ gsk_transform_to_affine (GskTransform *self, } /** + * gsk_transform_to_translate: + * @m: a #GskTransform + * @out_dx: (out): return location for the translation + * in the x direction + * @out_dy: (out): return location for the translation + * in the y direction + * + * Converts a #GskTransform to a translation operation, + * if the given matrix is compatible. + * + * Returns: %TRUE if the matrix is compatible with a + * translation transformation. + */ +gboolean +gsk_transform_to_translate (GskTransform *self, + float *out_dx, + float *out_dy) +{ + if (self == NULL) + { + *out_dx = 0.0f; + *out_dy = 0.0f; + return TRUE; + } + + if (!gsk_transform_to_translate (self->next, + out_dx, out_dy)) + return FALSE; + + return self->transform_class->apply_translate (self, + out_dx, out_dy); +} + +/** * gsk_transform_transform: * @next: (allow-none) (transfer full): Transform to apply @other to * @other: (allow-none): Transform to apply @@ -1111,3 +1389,25 @@ gsk_transform_new (void) { return gsk_transform_alloc (&GSK_IDENTITY_TRANSFORM_CLASS, NULL); } + +/** + * gsk_transform_transform_bounds: + * @self: a #GskTransform + * @rect: a #graphene_rect_t + * @out_rect: (out caller-allocates): return location for the bounds + * of the transformed rectangle + * + * Transforms a #graphene_rect_t using the given matrix @m. The + * result is the bounding box containing the coplanar quad. + **/ +void +gsk_transform_transform_bounds (GskTransform *self, + const graphene_rect_t *rect, + graphene_rect_t *out_rect) +{ + graphene_matrix_t mat; + + /* XXX: vfuncify */ + gsk_transform_to_matrix (self, &mat); + graphene_matrix_transform_bounds (&mat, rect, out_rect); +} diff --git a/gsk/gsktransform.h b/gsk/gsktransform.h index b8393aca60..fd3dd7a2e1 100644 --- a/gsk/gsktransform.h +++ b/gsk/gsktransform.h @@ -57,6 +57,25 @@ GDK_AVAILABLE_IN_ALL void gsk_transform_to_matrix (GskTransform *self, graphene_matrix_t *out_matrix); GDK_AVAILABLE_IN_ALL +gboolean gsk_transform_to_2d (GskTransform *self, + float *out_xx, + float *out_yx, + float *out_xy, + float *out_yy, + float *out_dx, + float *out_dy) G_GNUC_WARN_UNUSED_RESULT; +GDK_AVAILABLE_IN_ALL +gboolean gsk_transform_to_affine (GskTransform *self, + float *out_scale_x, + float *out_scale_y, + float *out_dx, + float *out_dy) G_GNUC_WARN_UNUSED_RESULT; +GDK_AVAILABLE_IN_ALL +gboolean gsk_transform_to_translate (GskTransform *self, + float *out_dx, + float *out_dy) G_GNUC_WARN_UNUSED_RESULT; + +GDK_AVAILABLE_IN_ALL gboolean gsk_transform_equal (GskTransform *first, GskTransform *second) G_GNUC_PURE; @@ -94,6 +113,11 @@ GskTransform * gsk_transform_scale_3d (GskTransform float factor_z); GDK_AVAILABLE_IN_ALL +void gsk_transform_transform_bounds (GskTransform *self, + const graphene_rect_t *rect, + graphene_rect_t *out_rect); + +GDK_AVAILABLE_IN_ALL GskTransformType gsk_transform_get_transform_type (GskTransform *self) G_GNUC_PURE; GDK_AVAILABLE_IN_ALL GskTransform * gsk_transform_get_next (GskTransform *self) G_GNUC_PURE; diff --git a/gsk/gsktransformprivate.h b/gsk/gsktransformprivate.h index 68eacaf786..0aba516f25 100644 --- a/gsk/gsktransformprivate.h +++ b/gsk/gsktransformprivate.h @@ -30,12 +30,6 @@ G_BEGIN_DECLS GskMatrixCategory gsk_transform_categorize (GskTransform *self); -gboolean gsk_transform_to_affine (GskTransform *self, - float *scale_x, - float *scale_y, - float *dx, - float *dy) G_GNUC_WARN_UNUSED_RESULT; - GskTransform * gsk_transform_matrix_with_category (GskTransform *next, const graphene_matrix_t*matrix, GskMatrixCategory category); |