[gtk] widget: Add gtk_widget_compute_transform



commit dbf0654e5b52e1cfd983cd8382185adb5feff095
Author: Timm Bäder <mail baedert org>
Date:   Sun Feb 17 08:47:09 2019 +0100

    widget: Add gtk_widget_compute_transform

 docs/reference/gtk/gtk4-sections.txt |   1 +
 gtk/gtkwidget.c                      | 128 +++++++++++++++++++++++------------
 gtk/gtkwidget.h                      |   4 ++
 3 files changed, 90 insertions(+), 43 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 9ddc0c6c96..b6785ed0c5 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -4541,6 +4541,7 @@ gtk_widget_get_allocated_size
 gtk_widget_get_width
 gtk_widget_get_height
 gtk_widget_compute_bounds
+gtk_widget_compute_transform
 gtk_widget_contains
 gtk_widget_pick
 gtk_widget_get_can_default
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 0ba379e23a..42e43a28f6 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -820,11 +820,11 @@ gtk_widget_real_pick (GtkWidget *widget,
        child = _gtk_widget_get_prev_sibling (child))
     {
       GtkWidget *picked;
-      int dx, dy;
+      double dx, dy;
 
-      gtk_widget_get_origin_relative_to_parent (child, &dx, &dy);
+      gtk_widget_translate_coordinatesf (widget, child, x, y, &dx, &dy);
 
-      picked = gtk_widget_pick (child, x - dx, y - dy);
+      picked = gtk_widget_pick (child, dx, dy);
       if (picked)
         return picked;
     }
@@ -4507,54 +4507,31 @@ gtk_widget_translate_coordinatesf (GtkWidget  *src_widget,
                                    double     *dest_x,
                                    double     *dest_y)
 {
-  GtkWidget *ancestor;
-  GtkWidget *parent;
+  graphene_matrix_t transform;
+  graphene_point_t p;
 
   g_return_val_if_fail (GTK_IS_WIDGET (src_widget), FALSE);
   g_return_val_if_fail (GTK_IS_WIDGET (dest_widget), FALSE);
 
-  ancestor = gtk_widget_common_ancestor (src_widget, dest_widget);
-  if (!ancestor)
+  if (!gtk_widget_compute_transform (src_widget, dest_widget, &transform))
     {
       if (dest_x)
         *dest_x = 0;
+
       if (dest_y)
         *dest_y = 0;
-      return FALSE;
-    }
-
 
-  parent = src_widget;
-  while (parent != ancestor)
-    {
-      int origin_x, origin_y;
-
-      gtk_widget_get_origin_relative_to_parent (parent, &origin_x, &origin_y);
-
-      src_x += origin_x;
-      src_y += origin_y;
-
-      parent = _gtk_widget_get_parent (parent);
+      return FALSE;
     }
 
-  parent = dest_widget;
-  while (parent != ancestor)
-    {
-      int origin_x, origin_y;
-
-      gtk_widget_get_origin_relative_to_parent (parent, &origin_x, &origin_y);
-
-      src_x -= origin_x;
-      src_y -= origin_y;
-
-      parent = _gtk_widget_get_parent (parent);
-    }
+  graphene_point_init (&p, src_x, src_y);
+  graphene_matrix_transform_point (&transform, &p, &p);
 
   if (dest_x)
-    *dest_x = src_x;
+    *dest_x = p.x;
 
   if (dest_y)
-    *dest_y = src_y;
+    *dest_y = p.y;
 
   return TRUE;
 }
@@ -11300,6 +11277,74 @@ gtk_widget_pick (GtkWidget *widget,
   return GTK_WIDGET_GET_CLASS (widget)->pick (widget, x, y);
 }
 
+/**
+ * gtk_widget_compute_transform:
+ * @widget: a #GtkWidget
+ * @target: the target widget that the matrix will transform to
+ * @out_transform: (out caller-allocates): location to
+ *   store the final transformation
+ *
+ * Computes a matrix suitable to describe a transformation from
+ * @widget's coordinate system into @target's coordinate system.
+ *
+ * Returns: %TRUE if the transform could be computed, %FALSE otherwise.
+ *   The transform can not be computed in certain cases, for example when
+ *   @widget and @target do not share a common ancestor.
+ */
+gboolean
+gtk_widget_compute_transform (GtkWidget         *widget,
+                              GtkWidget         *target,
+                              graphene_matrix_t *out_transform)
+{
+  GtkWidget *parent;
+  GtkWidget *ancestor;
+  graphene_matrix_t transform;
+
+  g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+  g_return_val_if_fail (GTK_IS_WIDGET (target), FALSE);
+  g_return_val_if_fail (out_transform != NULL, FALSE);
+
+  ancestor = gtk_widget_common_ancestor (widget, target);
+
+  if (!ancestor)
+    return FALSE;
+
+  graphene_matrix_init_identity (&transform);
+  parent = widget;
+  while (parent != ancestor)
+    {
+      GtkWidgetPrivate *priv = gtk_widget_get_instance_private (parent);
+
+      graphene_matrix_multiply (&transform, &priv->transform, &transform);
+
+      parent = priv->parent;
+    }
+
+  g_assert (parent == ancestor);
+
+  {
+    graphene_matrix_t down_transform;
+    graphene_matrix_t inv;
+
+    graphene_matrix_init_identity (&down_transform);
+
+    while (parent != ancestor)
+      {
+        graphene_matrix_multiply (&down_transform, &parent->priv->transform, &down_transform);
+        parent = parent->priv->parent;
+      }
+
+    graphene_matrix_inverse (&down_transform, &inv);
+
+    graphene_matrix_multiply (&transform, &inv, &transform);
+  }
+
+
+  *out_transform = transform;
+
+  return TRUE;
+}
+
 /**
  * gtk_widget_compute_bounds:
  * @widget: the #GtkWidget to query
@@ -11323,26 +11368,23 @@ gtk_widget_compute_bounds (GtkWidget       *widget,
                            GtkWidget       *target,
                            graphene_rect_t *out_bounds)
 {
+  graphene_matrix_t transform;
   GtkCssBoxes boxes;
-  int x, y;
 
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
   g_return_val_if_fail (GTK_IS_WIDGET (target), FALSE);
   g_return_val_if_fail (out_bounds != NULL, FALSE);
 
-  if (!gtk_widget_translate_coordinates (widget,
-                                         target,
-                                         0, 0,
-                                         &x, &y))
+  if (!gtk_widget_compute_transform (widget, target, &transform))
     {
       graphene_rect_init_from_rect (out_bounds, graphene_rect_zero ());
       return FALSE;
     }
 
   gtk_css_boxes_init (&boxes, widget);
-  graphene_rect_offset_r (gtk_css_boxes_get_border_rect (&boxes),
-                          x, y,
-                          out_bounds);
+  graphene_matrix_transform_bounds (&transform,
+                                    gtk_css_boxes_get_border_rect (&boxes),
+                                    out_bounds);
 
   return TRUE;
 }
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index e912b6e612..f62049a894 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -614,6 +614,10 @@ GDK_AVAILABLE_IN_ALL
 void                  gtk_widget_get_allocation         (GtkWidget     *widget,
                                                          GtkAllocation *allocation);
 GDK_AVAILABLE_IN_ALL
+gboolean              gtk_widget_compute_transform      (GtkWidget         *widget,
+                                                         GtkWidget         *target,
+                                                         graphene_matrix_t *out_transform);
+GDK_AVAILABLE_IN_ALL
 gboolean              gtk_widget_compute_bounds         (GtkWidget     *widget,
                                                          GtkWidget     *target,
                                                          graphene_rect_t *out_bounds);


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