From 51e57a31c5305204553d4e6765b7dfb5ba7b677e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 7 Jul 2015 10:18:24 +0800
Subject: [PATCH] ClutterActor: Add an inverse of the
 relative_transform_to_point function

clutter_actor_transform_stage_point() transforms a coordinate from the
stage coordinate space to the actor coordinate space, but does so with
some loss of accuracy because it casts the input coordinate to int.
The accuracy loss is often negigible, but sometimes, for example for
Wayland compositors, it can cause issues. Therefore provide API for
more accurate transformation from the stage coordinate space to actor
coordinate space by providing a helper that does the inverse of
clutter_actor_relative_transform_to_point().

https://bugzilla.gnome.org/show_bug.cgi?id=752752
---
 clutter/clutter-actor.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
 clutter/clutter-actor.h |  6 ++++++
 2 files changed, 58 insertions(+)

diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c
index 0305b74..114c1b7 100644
--- a/clutter/clutter-actor.c
+++ b/clutter/clutter-actor.c
@@ -2789,6 +2789,58 @@ clutter_actor_apply_relative_transform_to_point (ClutterActor        *self,
   cogl_matrix_transform_point (&matrix, &vertex->x, &vertex->y, &vertex->z, &w);
 }
 
+/**
+ * clutter_actor_apply_inverse_relative_transform_to_point:
+ * @self: A #ClutterActor
+ * @ancestor: (allow-none): A #ClutterActor ancestor, or %NULL to use the
+ *   default #ClutterStage
+ * @point: A point as #ClutterVertex
+ * @vertex: (out caller-allocates): The translated #ClutterVertex
+ *
+ * Transforms @point in coordinates relative to the ancestor actor into
+ * actor relative coordinates using the relevant transform stack (i.e. scale,
+ * rotation, etc).
+ *
+ * If @ancestor is %NULL the ancestor will be the #ClutterStage. In
+ * this case, the coordinates used will be the coordinates on
+ * the stage before the projection is applied.
+ *
+ * Note that this function is the inverse of
+ * clutter_actor_apply_relative_transform_to_point().
+ *
+ * Since: 1.24
+ */
+void
+clutter_actor_apply_inverse_relative_transform_to_point (ClutterActor        *self,
+                                                         ClutterActor        *ancestor,
+                                                         const ClutterVertex *point,
+                                                         ClutterVertex       *vertex)
+{
+  gfloat w;
+  CoglMatrix matrix;
+
+  g_return_if_fail (CLUTTER_IS_ACTOR (self));
+  g_return_if_fail (ancestor == NULL || CLUTTER_IS_ACTOR (ancestor));
+  g_return_if_fail (point != NULL);
+  g_return_if_fail (vertex != NULL);
+
+  *vertex = *point;
+  w = 1.0;
+
+  if (ancestor == NULL)
+    ancestor = _clutter_actor_get_stage_internal (self);
+
+  if (ancestor == NULL)
+    {
+      *vertex = *point;
+      return;
+    }
+
+  _clutter_actor_get_relative_transformation_matrix (self, ancestor, &matrix);
+  cogl_matrix_get_inverse (&matrix, &matrix);
+  cogl_matrix_transform_point (&matrix, &vertex->x, &vertex->y, &vertex->z, &w);
+}
+
 static gboolean
 _clutter_actor_fully_transform_vertices (ClutterActor *self,
                                          const ClutterVertex *vertices_in,
diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h
index a71ca27..753b393 100644
--- a/clutter/clutter-actor.h
+++ b/clutter/clutter-actor.h
@@ -806,6 +806,12 @@ void                            clutter_actor_apply_relative_transform_to_point
                                                                                  const ClutterVertex        *point,
                                                                                  ClutterVertex              *vertex);
 
+CLUTTER_AVAILABLE_IN_1_24
+void                            clutter_actor_apply_inverse_relative_transform_to_point (ClutterActor         *self,
+                                                                                         ClutterActor         *ancestor,
+                                                                                         const ClutterVertex  *point,
+                                                                                         ClutterVertex        *vertex);
+
 /* Implicit animations */
 CLUTTER_AVAILABLE_IN_1_10
 void                            clutter_actor_save_easing_state                 (ClutterActor               *self);
-- 
2.1.0