[gtk/wip/otte/transform: 28/41] transform: Add more API



commit 4916280883f7850e17e025150be7c6ab25a8efc9
Author: Benjamin Otte <otte redhat com>
Date:   Fri Mar 1 06:24:33 2019 +0100

    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.

 docs/reference/gsk/gsk4-sections.txt |   5 +
 gsk/gsktransform.c                   | 300 +++++++++++++++++++++++++++++++++++
 gsk/gsktransform.h                   |  24 +++
 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,
@@ -147,6 +157,18 @@ gsk_identity_transform_to_matrix (GskTransform      *transform,
   graphene_matrix_init_identity (out_matrix);
 }
 
+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,
@@ -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,
@@ -248,6 +280,18 @@ gsk_matrix_transform_to_matrix (GskTransform      *transform,
   graphene_matrix_init_from_matrix (out_matrix, &self->matrix);
 }
 
+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,
@@ -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,
@@ -412,6 +485,26 @@ gsk_translate_transform_to_matrix (GskTransform      *transform,
   graphene_matrix_init_translate (out_matrix, &self->point);
 }
 
+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,
@@ -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,
@@ -557,6 +668,19 @@ gsk_rotate_transform_to_matrix (GskTransform      *transform,
   graphene_matrix_init_rotate (out_matrix, self->angle, &self->axis);
 }
 
+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,
@@ -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,
@@ -711,6 +845,28 @@ gsk_scale_transform_to_matrix (GskTransform      *transform,
   graphene_matrix_init_scale (out_matrix, self->factor_x, self->factor_y, self->factor_z);
 }
 
+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,
@@ -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,
@@ -1027,6 +1271,40 @@ gsk_transform_to_affine (GskTransform *self,
                                               out_dx, out_dy);
 }
 
+/**
+ * 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
@@ -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;
 
@@ -93,6 +112,11 @@ GskTransform *          gsk_transform_scale_3d                  (GskTransform
                                                                  float                           factor_y,
                                                                  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
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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]