summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2019-03-01 06:24:33 +0100
committerBenjamin Otte <otte@redhat.com>2019-03-04 23:15:06 +0100
commit4916280883f7850e17e025150be7c6ab25a8efc9 (patch)
tree827468dd6604547d3cf51f01995b50aec98c0ce4
parent0e1a50366a738389cce5d92b978ce0d07a5ab951 (diff)
downloadgtk+-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.txt5
-rw-r--r--gsk/gsktransform.c300
-rw-r--r--gsk/gsktransform.h24
-rw-r--r--gsk/gsktransformprivate.h6
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);