summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2022-07-08 07:24:42 +0200
committerBenjamin Otte <otte@redhat.com>2022-07-08 07:29:09 +0200
commitad2f4a27be8c205c0e5033a8170df7af248bd9d2 (patch)
treefe9cc9fba2c03701606a2b34b5b8e86d29a36a5e
parentfd4a717ddae5cd47c029d51dc413bad034f62f1e (diff)
downloadgtk+-ad2f4a27be8c205c0e5033a8170df7af248bd9d2.tar.gz
canvas: Completely rework bounds computation
Instead of using a descriptive language to describe how to compute the bounds, just set a vfunc and let the application provide a function. That saves a lot of code - but makes the canvas rely on user code.
-rw-r--r--demos/gtk-demo/canvas_intro.c58
-rw-r--r--demos/gtk-demo/canvas_planarity.c127
-rw-r--r--demos/gtk-demo/canvas_puzzle.c68
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkcanvas.c106
-rw-r--r--gtk/gtkcanvas.h2
-rw-r--r--gtk/gtkcanvasbox.c203
-rw-r--r--gtk/gtkcanvasbox.h45
-rw-r--r--gtk/gtkcanvasboxprivate.h34
-rw-r--r--gtk/gtkcanvasitem.c274
-rw-r--r--gtk/gtkcanvasitem.h14
-rw-r--r--gtk/gtkcanvasitemprivate.h8
-rw-r--r--gtk/gtkcanvasvector.c181
-rw-r--r--gtk/gtkcanvasvector.h75
-rw-r--r--gtk/gtkcanvasvectorimpl.c512
-rw-r--r--gtk/gtkcanvasvectorprivate.h115
-rw-r--r--gtk/gtktypes.h1
-rw-r--r--gtk/meson.build3
18 files changed, 372 insertions, 1455 deletions
diff --git a/demos/gtk-demo/canvas_intro.c b/demos/gtk-demo/canvas_intro.c
index 2ef1846321..4bf99fb3ec 100644
--- a/demos/gtk-demo/canvas_intro.c
+++ b/demos/gtk-demo/canvas_intro.c
@@ -10,31 +10,51 @@
#define WIDTH 400
#define HEIGHT 300
+static gboolean
+center_item (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer unused)
+{
+ const GtkCanvasBox *viewport;
+ GtkWidget *widget;
+ int width, height;
+
+ /* We need to check if the viewport is available.
+ * If the canvas was scrolling, it might not be avaiable yet.
+ */
+ viewport = gtk_canvas_get_viewport (gtk_canvas_item_get_canvas (ci));
+ if (viewport == NULL)
+ return FALSE;
+
+ /* Measure the widget min for min so that it will line-break. */
+ widget = gtk_canvas_item_get_widget (ci);
+ gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, &width, NULL, NULL, NULL);
+ gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, width, &height, NULL, NULL, NULL);
+
+ /* Initialize the bounds for this widget:
+ * - the point is the center of the canvas' viewport
+ * - the size is the one we just computed
+ * - we want the origin point to be at the center
+ */
+ gtk_canvas_box_init (out_box,
+ viewport->size.width * 0.5,
+ viewport->size.height * 0.5,
+ 0, 0,
+ 0.5, 0.5);
+
+ return TRUE;
+}
+
static void
bind_item (GtkListItemFactory *factory,
GtkCanvasItem *ci)
{
- GtkCanvasVector *point;
- const GtkCanvasVector *size;
- GtkCanvasBox *box;
-
gtk_canvas_item_set_widget (ci, gtk_canvas_item_get_item (ci));
- /* Also center the item, so we do something interesting */
- point = gtk_canvas_vector_new (0, 0);
- box = gtk_canvas_box_new (point,
- gtk_canvas_get_viewport_size (gtk_canvas_item_get_canvas (ci)),
- 0.0, 0.0);
- gtk_canvas_vector_free (point);
-
- point = gtk_canvas_vector_new_from_box (box, 0.5, 0.5);
- gtk_canvas_box_free (box);
- size = gtk_canvas_vector_get_item_measure (ci, GTK_CANVAS_ITEM_MEASURE_MIN_FOR_MIN);
- box = gtk_canvas_box_new (point, size, 0.5, 0.5);
- gtk_canvas_vector_free (point);
-
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
+ /* Set a function to compute the position */
+ gtk_canvas_item_set_compute_bounds (ci,
+ center_item,
+ NULL, NULL);
}
GtkWidget *
diff --git a/demos/gtk-demo/canvas_planarity.c b/demos/gtk-demo/canvas_planarity.c
index 93ab37571b..f10c84fa34 100644
--- a/demos/gtk-demo/canvas_planarity.c
+++ b/demos/gtk-demo/canvas_planarity.c
@@ -78,7 +78,7 @@ struct _PlanarityVertex
{
GObject parent_instance;
- graphene_point_t position;
+ GtkOrigin position;
};
#define PLANARITY_TYPE_VERTEX (planarity_vertex_get_type ())
@@ -97,14 +97,15 @@ planarity_vertex_init (PlanarityVertex *self)
}
static PlanarityVertex *
-planarity_vertex_new (float x,
- float y)
+planarity_vertex_new (float horizontal,
+ float vertical)
{
PlanarityVertex *self;
self = g_object_new (PLANARITY_TYPE_VERTEX, NULL);
- graphene_point_init (&self->position, x, y);
+ self->position.horizontal = horizontal;
+ self->position.vertical = vertical;
return self;
}
@@ -147,54 +148,83 @@ planarity_edge_new (PlanarityVertex *from,
return edge;
}
-static void
-set_item_position (GtkCanvasItem *ci)
+static gboolean
+set_vertex_bounds (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer user_data)
{
PlanarityVertex *vertex = gtk_canvas_item_get_item (ci);
- GtkCanvasVector *point, *size;
- GtkCanvasBox *box, *viewport;
- float x = vertex->position.x;
- float y = vertex->position.y;
-
- point = gtk_canvas_vector_new (0, 0);
- viewport = gtk_canvas_box_new (point,
- gtk_canvas_get_viewport_size (gtk_canvas_item_get_canvas (ci)),
- 0.0, 0.0);
- gtk_canvas_vector_free (point);
-
- point = gtk_canvas_vector_new_from_box (viewport, x, y);
- gtk_canvas_box_free (viewport);
- size = gtk_canvas_vector_new (0, 0);
- box = gtk_canvas_box_new (point, size, x, y);
- gtk_canvas_vector_free (point);
- gtk_canvas_vector_free (size);
-
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
+ const GtkCanvasBox *viewport;
+
+ viewport = gtk_canvas_get_viewport (gtk_canvas_item_get_canvas (ci));
+ if (viewport == NULL)
+ return FALSE;
+
+ gtk_canvas_box_init (out_box,
+ viewport->size.width * vertex->position.horizontal,
+ viewport->size.height * vertex->position.vertical,
+ 0, 0,
+ vertex->position.horizontal,
+ vertex->position.vertical);
+
+ return TRUE;
}
static void
-move_item (GtkGestureDrag *gesture,
- double x,
- double y,
- GtkCanvasItem *ci)
+move_vertex (GtkGestureDrag *gesture,
+ double x,
+ double y,
+ GtkCanvasItem *ci)
{
GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
- GtkWidget *widget = gtk_canvas_item_get_widget (ci);
PlanarityVertex *vertex = gtk_canvas_item_get_item (ci);
- x /= (gtk_widget_get_width (GTK_WIDGET (canvas)) - gtk_widget_get_width (widget));
- y /= (gtk_widget_get_height (GTK_WIDGET (canvas)) - gtk_widget_get_height (widget));
+ x /= gtk_widget_get_width (GTK_WIDGET (canvas));
+ y /= gtk_widget_get_height (GTK_WIDGET (canvas));
+
+ vertex->position.horizontal = CLAMP (vertex->position.horizontal + x, 0, 1);
+ vertex->position.vertical = CLAMP (vertex->position.vertical + y, 0, 1);
- vertex->position = GRAPHENE_POINT_INIT (CLAMP (vertex->position.x + x, 0, 1), CLAMP (vertex->position.y + y, 0, 1));
- set_item_position (ci);
+ gtk_canvas_item_invalidate_bounds (ci);
+}
+
+static gboolean
+set_edge_bounds (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer user_data)
+{
+ PlanarityEdge *edge = gtk_canvas_item_get_item (ci);
+ GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
+ GtkCanvasItem *from_item, *to_item;
+ const GtkCanvasBox *from_box, *to_box;
+ graphene_rect_t from_rect, to_rect;
+ graphene_point_t from_center, to_center;
+
+ from_item = gtk_canvas_lookup_item (canvas, edge->from);
+ to_item = gtk_canvas_lookup_item (canvas, edge->to);
+ from_box = gtk_canvas_item_get_allocation (from_item);
+ to_box = gtk_canvas_item_get_allocation (to_item);
+ if (from_box == NULL || to_box == NULL)
+ return FALSE;
+
+ gtk_canvas_box_to_rect (from_box, &from_rect);
+ gtk_canvas_box_to_rect (to_box, &to_rect);
+ graphene_rect_get_center (&from_rect, &from_center);
+ graphene_rect_get_center (&to_rect, &to_center);
+
+ gtk_canvas_box_init (out_box,
+ from_center.x, from_center.y,
+ to_center.x - from_center.x,
+ to_center.y - from_center.y,
+ 0, 0);
+
+ return TRUE;
}
static void
bind_item (GtkListItemFactory *factory,
GtkCanvasItem *ci)
{
- GtkCanvasBox *box;
gpointer item;
item = gtk_canvas_item_get_item (ci);
@@ -207,34 +237,17 @@ bind_item (GtkListItemFactory *factory,
widget = gtk_image_new_from_icon_name ("media-record-symbolic");
gtk_image_set_icon_size (GTK_IMAGE (widget), GTK_ICON_SIZE_LARGE);
gesture = gtk_gesture_drag_new ();
- g_signal_connect (gesture, "drag-update", G_CALLBACK (move_item), ci);
- g_signal_connect (gesture, "drag-end", G_CALLBACK (move_item), ci);
+ g_signal_connect (gesture, "drag-update", G_CALLBACK (move_vertex), ci);
+ g_signal_connect (gesture, "drag-end", G_CALLBACK (move_vertex), ci);
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
gtk_canvas_item_set_widget (ci, widget);
- set_item_position (ci);
+ gtk_canvas_item_set_compute_bounds (ci, set_vertex_bounds, NULL, NULL);
}
else if (PLANARITY_IS_EDGE (item))
{
- GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
- PlanarityEdge *edge = PLANARITY_EDGE (item);
- GtkCanvasItem *from_item, *to_item;
- const GtkCanvasBox *from_box, *to_box;
- GtkCanvasVector *from_point, *to_point;
-
gtk_canvas_item_set_widget (ci, gtk_diagonal_line_new ());
-
- from_item = gtk_canvas_lookup_item (canvas, edge->from);
- to_item = gtk_canvas_lookup_item (canvas, edge->to);
- from_box = gtk_canvas_box_get_item_allocation (from_item);
- to_box = gtk_canvas_box_get_item_allocation (to_item);
- from_point = gtk_canvas_vector_new_from_box (from_box, 0.5, 0.5);
- to_point = gtk_canvas_vector_new_from_box (to_box, 0.5, 0.5);
- box = gtk_canvas_box_new_points (from_point, to_point);
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
- gtk_canvas_vector_free (from_point);
- gtk_canvas_vector_free (to_point);
+ gtk_canvas_item_set_compute_bounds (ci, set_edge_bounds, NULL, NULL);
}
}
diff --git a/demos/gtk-demo/canvas_puzzle.c b/demos/gtk-demo/canvas_puzzle.c
index f1ee30703b..4fe20c3327 100644
--- a/demos/gtk-demo/canvas_puzzle.c
+++ b/demos/gtk-demo/canvas_puzzle.c
@@ -9,32 +9,25 @@
#include "puzzlepiece.h"
-static void
-set_item_position (GtkCanvasItem *ci,
- float x,
- float y)
+static gboolean
+set_position_from_origin (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer user_data)
{
- GtkCanvasVector *point, *size;
- GtkCanvasBox *box, *viewport;
-
- x = CLAMP (x, 0, 1);
- y = CLAMP (y, 0, 1);
-
- point = gtk_canvas_vector_new (0, 0);
- viewport = gtk_canvas_box_new (point,
- gtk_canvas_get_viewport_size (gtk_canvas_item_get_canvas (ci)),
- 0.0, 0.0);
- gtk_canvas_vector_free (point);
-
- point = gtk_canvas_vector_new_from_box (viewport, x, y);
- gtk_canvas_box_free (viewport);
- size = gtk_canvas_vector_new (0, 0);
- box = gtk_canvas_box_new (point, size, x, y);
- gtk_canvas_vector_free (point);
- gtk_canvas_vector_free (size);
-
- gtk_canvas_item_set_bounds (ci, box);
- gtk_canvas_box_free (box);
+ GtkOrigin *origin = g_object_get_data (G_OBJECT (ci), "position");
+ const GtkCanvasBox *viewport = gtk_canvas_get_viewport (gtk_canvas_item_get_canvas (ci));
+
+ if (viewport == NULL)
+ return FALSE;
+
+ gtk_canvas_box_init (out_box,
+ viewport->size.width * origin->horizontal,
+ viewport->size.height * origin->vertical,
+ 0, 0,
+ origin->horizontal,
+ origin->vertical);
+
+ return TRUE;
}
static void
@@ -44,14 +37,15 @@ move_item (GtkGestureDrag *gesture,
GtkCanvasItem *ci)
{
GtkCanvas *canvas = gtk_canvas_item_get_canvas (ci);
- graphene_rect_t bounds;
+ GtkOrigin *origin = g_object_get_data (G_OBJECT (ci), "position");
- if (!gtk_canvas_box_eval (gtk_canvas_item_get_bounds (ci), &bounds))
- return;
+ origin->horizontal += x / gtk_widget_get_width (GTK_WIDGET (canvas));
+ origin->vertical += y / gtk_widget_get_height (GTK_WIDGET (canvas));
+ origin->horizontal = CLAMP (origin->horizontal, 0, 1);
+ origin->vertical = CLAMP (origin->vertical, 0, 1);
+ g_print ("%g %g\n", origin->horizontal, origin->vertical);
- set_item_position (ci,
- (bounds.origin.x + x) / (gtk_widget_get_width (GTK_WIDGET (canvas)) - bounds.size.width),
- (bounds.origin.y + y) / (gtk_widget_get_height (GTK_WIDGET (canvas)) - bounds.size.height));
+ gtk_canvas_item_invalidate_bounds (ci);
}
static void
@@ -60,6 +54,7 @@ bind_item (GtkListItemFactory *factory,
{
GtkWidget *widget;
GtkGesture *gesture;
+ GtkOrigin *origin;
widget = gtk_picture_new_for_paintable (gtk_canvas_item_get_item (ci));
gtk_picture_set_can_shrink (GTK_PICTURE (widget), FALSE);
@@ -69,8 +64,15 @@ bind_item (GtkListItemFactory *factory,
gtk_widget_add_controller (widget, GTK_EVENT_CONTROLLER (gesture));
gtk_canvas_item_set_widget (ci, widget);
- /* Also center the item, so we do something interesting */
- set_item_position (ci, g_random_double (), g_random_double ());
+ /* Set a random position */
+ origin = g_new (GtkOrigin, 1);
+ origin->horizontal = g_random_double ();
+ origin->vertical = g_random_double ();
+ g_object_set_data_full (G_OBJECT (ci), "position", origin, g_free);
+
+ gtk_canvas_item_set_compute_bounds (ci,
+ set_position_from_origin,
+ NULL, NULL);
}
static GListModel *
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 010d0fed01..051471c6f6 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -62,7 +62,6 @@
#include <gtk/gtkcanvas.h>
#include <gtk/gtkcanvasbox.h>
#include <gtk/gtkcanvasitem.h>
-#include <gtk/gtkcanvasvector.h>
#include <gtk/gtkcellarea.h>
#include <gtk/gtkcellareabox.h>
#include <gtk/gtkcellareacontext.h>
diff --git a/gtk/gtkcanvas.c b/gtk/gtkcanvas.c
index 2d5527ea08..2a78fddfa2 100644
--- a/gtk/gtkcanvas.c
+++ b/gtk/gtkcanvas.c
@@ -23,7 +23,6 @@
#include "gtkcanvasbox.h"
#include "gtkcanvasitemprivate.h"
-#include "gtkcanvasvectorprivate.h"
#include "gtkintl.h"
#include "gtklistitemfactory.h"
#include "gtkwidgetprivate.h"
@@ -53,7 +52,8 @@ struct _GtkCanvas
GtkCanvasItems items;
GHashTable *item_lookup;
- GtkCanvasVector viewport_size;
+ GtkCanvasBox viewport;
+ guint viewport_valid : 1;
};
enum
@@ -164,7 +164,6 @@ gtk_canvas_finalize (GObject *object)
GtkCanvas *self = GTK_CANVAS (object);
g_hash_table_unref (self->item_lookup);
- gtk_canvas_vector_finish (&self->viewport_size);
G_OBJECT_CLASS (gtk_canvas_parent_class)->finalize (object);
}
@@ -218,15 +217,17 @@ gtk_canvas_set_property (GObject *object,
}
static void
-gtk_canvas_validate_variables (GtkCanvas *self)
+gtk_canvas_invalidate_allocation (GtkCanvas *self)
{
int i;
+ self->viewport_valid = FALSE;
+
for (i = 0; i < gtk_canvas_items_get_size (&self->items); i++)
{
GtkCanvasItem *ci = gtk_canvas_items_get (&self->items, i);
- gtk_canvas_item_validate_variables (ci);
+ gtk_canvas_item_invalidate_allocation (ci);
}
}
@@ -240,9 +241,13 @@ gtk_canvas_allocate (GtkWidget *widget,
gboolean missing, force, success;
gsize i;
- gtk_canvas_validate_variables (self);
+ gtk_canvas_invalidate_allocation (self);
- gtk_canvas_vector_init_constant (gtk_canvas_vector_get_variable (&self->viewport_size), width, height);
+ self->viewport_valid = TRUE;
+ gtk_canvas_box_init (&self->viewport,
+ 0, 0,
+ width, height,
+ 0, 0);
force = FALSE;
do
@@ -254,71 +259,17 @@ gtk_canvas_allocate (GtkWidget *widget,
for (i = 0; i < gtk_canvas_items_get_size (&self->items); i++)
{
GtkCanvasItem *ci = gtk_canvas_items_get (&self->items, i);
- GtkWidget *child = gtk_canvas_item_get_widget (ci);
- const GtkCanvasBox *bounds;
- graphene_rect_t rect;
- int x, y, w, h;
- if (child == NULL || gtk_canvas_item_has_allocation (ci))
+ if (gtk_canvas_item_has_allocation (ci))
continue;
- bounds = gtk_canvas_item_get_bounds (ci);
- if (!gtk_canvas_box_eval (bounds, &rect))
- {
- if (force)
- {
- rect = *graphene_rect_zero ();
- /* XXX: set force to FALSE? */
- }
- else
- {
- missing = TRUE;
- continue;
- }
- }
-
- if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
- {
- gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, &w, NULL, NULL, NULL);
- w = MAX (w, ceil (ABS (rect.size.width)));
- gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL);
- h = MAX (h, ceil (ABS (rect.size.height)));
- }
- else
- {
- gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL);
- h = MAX (h, ceil (ABS (rect.size.height)));
- gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL);
- w = MAX (w, ceil (ABS (rect.size.width)));
- }
-
- if (rect.size.width < 0)
- w = -w;
- if (rect.size.height < 0)
- h = -h;
- if (ABS (w) > ABS (rect.size.width) || ABS (h) > ABS (rect.size.height))
- {
- graphene_vec2_t origin;
-
- if (!gtk_canvas_vector_eval (gtk_canvas_box_get_origin (bounds), &origin))
- graphene_vec2_init_from_vec2 (&origin, graphene_vec2_zero ());
-
- if (ABS (w) > ABS (rect.size.width))
- x = round (rect.origin.x + graphene_vec2_get_x (&origin) * (rect.size.width - w));
- else
- x = round (rect.origin.x);
- if (ABS (h) > ABS (rect.size.height))
- y = round (rect.origin.y + graphene_vec2_get_y (&origin) * (rect.size.height - h));
- else
- y = round (rect.origin.y);
- }
- else
+ if (!gtk_canvas_item_allocate (ci, force))
{
- x = round (rect.origin.x);
- y = round (rect.origin.y);
+ g_assert (!force);
+ missing = TRUE;
+ continue;
}
- gtk_canvas_item_allocate (ci, &GRAPHENE_RECT_INIT (x, y, w, h));
success = TRUE;
}
if (!success)
@@ -380,8 +331,6 @@ static void
gtk_canvas_init (GtkCanvas *self)
{
self->item_lookup = g_hash_table_new (g_direct_hash, g_direct_equal);
-
- gtk_canvas_vector_init_variable (&self->viewport_size, "viewport.size");
}
/**
@@ -554,8 +503,23 @@ gtk_canvas_lookup_item (GtkCanvas *self,
return g_hash_table_lookup (self->item_lookup, item);
}
-const GtkCanvasVector *
-gtk_canvas_get_viewport_size (GtkCanvas *self)
+/**
+ * gtk_canvas_get_viewport:
+ * @self: a `GtkCanvas`
+ *
+ * Gets the viewport of the canvas. If no viewport is available,
+ * in particular if it has not been determined during size
+ * allocation, %NULL is returned.
+ *
+ * Returns: The viewport
+ **/
+const GtkCanvasBox *
+gtk_canvas_get_viewport (GtkCanvas *self)
{
- return &self->viewport_size;
+ g_return_val_if_fail (GTK_IS_CANVAS (self), NULL);
+
+ if (!self->viewport_valid)
+ return NULL;
+
+ return &self->viewport;
}
diff --git a/gtk/gtkcanvas.h b/gtk/gtkcanvas.h
index 75e8f8b093..98e7a398e8 100644
--- a/gtk/gtkcanvas.h
+++ b/gtk/gtkcanvas.h
@@ -54,7 +54,7 @@ GtkCanvasItem * gtk_canvas_lookup_item (GtkCanvas
gpointer item);
GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_get_viewport_size (GtkCanvas *self);
+const GtkCanvasBox * gtk_canvas_get_viewport (GtkCanvas *self);
G_END_DECLS
diff --git a/gtk/gtkcanvasbox.c b/gtk/gtkcanvasbox.c
index 56388c2bab..cb5a175afa 100644
--- a/gtk/gtkcanvasbox.c
+++ b/gtk/gtkcanvasbox.c
@@ -29,141 +29,12 @@
#include "config.h"
-#include "gtkcanvasboxprivate.h"
-
-/* {{{ Boilerplate */
+#include "gtkcanvasbox.h"
G_DEFINE_BOXED_TYPE (GtkCanvasBox, gtk_canvas_box,
gtk_canvas_box_copy,
gtk_canvas_box_free)
-void
-gtk_canvas_box_init (GtkCanvasBox *self,
- const GtkCanvasVector *point,
- const GtkCanvasVector *size,
- const GtkCanvasVector *origin)
-{
- gtk_canvas_vector_init_copy (&self->point, point);
- gtk_canvas_vector_init_copy (&self->size, size);
- gtk_canvas_vector_init_copy (&self->origin, origin);
-}
-
-void
-gtk_canvas_box_init_copy (GtkCanvasBox *self,
- const GtkCanvasBox *source)
-{
- gtk_canvas_box_init (self, &source->point, &source->size, &source->origin);
-}
-
-void
-gtk_canvas_box_finish (GtkCanvasBox *self)
-{
- gtk_canvas_vector_finish (&self->point);
- gtk_canvas_vector_finish (&self->size);
- gtk_canvas_vector_finish (&self->origin);
-}
-
-void
-gtk_canvas_box_init_variable (GtkCanvasBox *self,
- const char *format,
- ...)
-{
- char *name;
- va_list args;
-
- va_start (args, format);
- name = g_strdup_vprintf (format, args);
- va_end (args);
-
- gtk_canvas_vector_init_variable (&self->point, "%s.point", name);
- gtk_canvas_vector_init_variable (&self->size, "%s.size", name);
- gtk_canvas_vector_init_variable (&self->origin, "%s.origin", name);
-
- g_free (name);
-}
-
-void
-gtk_canvas_box_update_variable (GtkCanvasBox *self,
- const GtkCanvasBox *other)
-{
- gtk_canvas_vector_init_copy (gtk_canvas_vector_get_variable (&self->point), &other->point);
- gtk_canvas_vector_init_copy (gtk_canvas_vector_get_variable (&self->size), &other->size);
- gtk_canvas_vector_init_copy (gtk_canvas_vector_get_variable (&self->origin), &other->origin);
-}
-
-/**
- * gtk_canvas_box_new_points:
- * @point1: the first point
- * @point2: the second point
- *
- * Creates a new box describing the rectangle between the two
- * points
- *
- * Returns: a new box
- **/
-GtkCanvasBox *
-gtk_canvas_box_new_points (const GtkCanvasVector *point1,
- const GtkCanvasVector *point2)
-{
- GtkCanvasVector size, origin;
- GtkCanvasBox *result;
- graphene_vec2_t minus_one;
-
- g_return_val_if_fail (point1 != NULL, NULL);
- g_return_val_if_fail (point2 != NULL, NULL);
-
- graphene_vec2_init (&minus_one, -1.f, -1.f);
- gtk_canvas_vector_init_sum (&size,
- graphene_vec2_one (),
- point2,
- &minus_one,
- point1,
- NULL);
- gtk_canvas_vector_init_constant (&origin, 0, 0);
- result = g_slice_new (GtkCanvasBox);
- gtk_canvas_box_init (result, (GtkCanvasVector *) point1, &size, &origin);
- gtk_canvas_vector_finish (&size);
- gtk_canvas_vector_finish (&origin);
-
- return result;
-}
-
-/**
- * gtk_canvas_box_new:
- * @point: the origin point of the box
- * @size: size of the box
- * @origin_x: x coordinate of origin
- * @origin_y: y coordinate of origin
- *
- * Creates a new box of the given size relative to the given point.
- * The origin describes where in the box the point is located.
- * (0, 0) means the point describes the top left of the box, (1, 1)
- * describes the bottom right, and (0.5, 0.5) is the center.
- *
- * Returns: a new box
- **/
-GtkCanvasBox *
-gtk_canvas_box_new (const GtkCanvasVector *point,
- const GtkCanvasVector *size,
- float origin_x,
- float origin_y)
-{
- GtkCanvasBox *self;
- GtkCanvasVector origin;
-
- g_return_val_if_fail (point != NULL, NULL);
- g_return_val_if_fail (size != NULL, NULL);
-
- gtk_canvas_vector_init_constant (&origin, origin_x, origin_y);
-
- self = g_slice_new (GtkCanvasBox);
- gtk_canvas_box_init (self, point, size, &origin);
-
- gtk_canvas_vector_finish (&origin);
-
- return self;
-}
-
GtkCanvasBox *
gtk_canvas_box_copy (const GtkCanvasBox *self)
{
@@ -171,8 +42,7 @@ gtk_canvas_box_copy (const GtkCanvasBox *self)
g_return_val_if_fail (self != NULL, NULL);
- copy = g_slice_new (GtkCanvasBox);
- gtk_canvas_box_init_copy (copy, self);
+ copy = g_slice_dup (GtkCanvasBox, self);
return copy;
}
@@ -180,59 +50,32 @@ gtk_canvas_box_copy (const GtkCanvasBox *self)
void
gtk_canvas_box_free (GtkCanvasBox *self)
{
- gtk_canvas_box_finish (self);
-
g_slice_free (GtkCanvasBox, self);
}
-gboolean
-gtk_canvas_box_eval (const GtkCanvasBox *self,
- graphene_rect_t *rect)
-{
- graphene_vec2_t point, size, origin;
-
- g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (rect != NULL, FALSE);
-
- if (!gtk_canvas_vector_eval (&self->point, &point) ||
- !gtk_canvas_vector_eval (&self->size, &size) ||
- !gtk_canvas_vector_eval (&self->origin, &origin))
- {
- *rect = *graphene_rect_zero ();
- return FALSE;
- }
-
- graphene_vec2_multiply (&origin, &size, &origin);
- graphene_vec2_subtract (&point, &origin, &point);
-
- *rect = GRAPHENE_RECT_INIT (graphene_vec2_get_x (&point),
- graphene_vec2_get_y (&point),
- graphene_vec2_get_x (&size),
- graphene_vec2_get_y (&size));
-
- return TRUE;
-}
-
-const GtkCanvasVector *
-gtk_canvas_box_get_point (const GtkCanvasBox *self)
-{
- g_return_val_if_fail (self != NULL, NULL);
-
- return &self->point;
-}
-
-const GtkCanvasVector *
-gtk_canvas_box_get_size (const GtkCanvasBox *self)
+void
+gtk_canvas_box_init (GtkCanvasBox *self,
+ float point_x,
+ float point_y,
+ float width,
+ float height,
+ float origin_horizontal,
+ float origin_vertical)
{
- g_return_val_if_fail (self != NULL, NULL);
-
- return &self->size;
+ self->point.x = point_x;
+ self->point.y = point_y;
+ self->size.width = width;
+ self->size.height = height;
+ self->origin.horizontal = origin_horizontal;
+ self->origin.vertical = origin_vertical;
}
-const GtkCanvasVector *
-gtk_canvas_box_get_origin (const GtkCanvasBox *self)
+void
+gtk_canvas_box_to_rect (const GtkCanvasBox *self,
+ graphene_rect_t *rect)
{
- g_return_val_if_fail (self != NULL, NULL);
-
- return &self->origin;
+ rect->size = self->size;
+ rect->origin = GRAPHENE_POINT_INIT (self->point.x - self->origin.horizontal * self->size.width,
+ self->point.y - self->origin.vertical * self->size.height);
+ graphene_rect_normalize (rect);
}
diff --git a/gtk/gtkcanvasbox.h b/gtk/gtkcanvasbox.h
index 2f08699f5a..e9bba1bc83 100644
--- a/gtk/gtkcanvasbox.h
+++ b/gtk/gtkcanvasbox.h
@@ -30,6 +30,20 @@
G_BEGIN_DECLS
+typedef struct _GtkOrigin GtkOrigin;
+
+struct _GtkOrigin {
+ float horizontal;
+ float vertical;
+};
+
+struct _GtkCanvasBox
+{
+ graphene_point_t point;
+ graphene_size_t size;
+ GtkOrigin origin;
+};
+
#define GTK_TYPE_CANVAS_BOX (gtk_canvas_box_get_type ())
GDK_AVAILABLE_IN_ALL
@@ -41,30 +55,17 @@ GDK_AVAILABLE_IN_ALL
void gtk_canvas_box_free (GtkCanvasBox *self);
GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_box_get_point (const GtkCanvasBox *self) G_GNUC_PURE;
-GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_box_get_size (const GtkCanvasBox *self) G_GNUC_PURE;
-GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_box_get_origin (const GtkCanvasBox *self) G_GNUC_PURE;
-
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_canvas_box_eval (const GtkCanvasBox *self,
- graphene_rect_t *rect) G_GNUC_WARN_UNUSED_RESULT;
-
-GDK_AVAILABLE_IN_ALL
-GtkCanvasBox * gtk_canvas_box_new (const GtkCanvasVector *point,
- const GtkCanvasVector *size,
- float origin_x,
- float origin_y);
-GDK_AVAILABLE_IN_ALL
-GtkCanvasBox * gtk_canvas_box_new_points (const GtkCanvasVector *point1,
- const GtkCanvasVector *point2);
+void gtk_canvas_box_init (GtkCanvasBox *self,
+ float point_x,
+ float point_y,
+ float width,
+ float height,
+ float origin_horizontal,
+ float origin_vertical);
GDK_AVAILABLE_IN_ALL
-const GtkCanvasBox * gtk_canvas_box_get_item_bounds (GtkCanvasItem *item);
-GDK_AVAILABLE_IN_ALL
-const GtkCanvasBox * gtk_canvas_box_get_item_allocation (GtkCanvasItem *item);
-
+void gtk_canvas_box_to_rect (const GtkCanvasBox *self,
+ graphene_rect_t *rect);
G_END_DECLS
#endif /* __GTK_BOX_H__ */
diff --git a/gtk/gtkcanvasboxprivate.h b/gtk/gtkcanvasboxprivate.h
deleted file mode 100644
index 1d6256495e..0000000000
--- a/gtk/gtkcanvasboxprivate.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __GTK_CANVAS_BOX_PRIVATE_H__
-#define __GTK_CANVAS_BOX_PRIVATE_H__
-
-#include "gtkcanvasbox.h"
-
-#include "gtkcanvasvectorprivate.h"
-
-G_BEGIN_DECLS
-
-struct _GtkCanvasBox
-{
- GtkCanvasVector point;
- GtkCanvasVector size;
- GtkCanvasVector origin;
-};
-
-
-void gtk_canvas_box_init (GtkCanvasBox *self,
- const GtkCanvasVector *point,
- const GtkCanvasVector *size,
- const GtkCanvasVector *origin);
-void gtk_canvas_box_init_copy (GtkCanvasBox *self,
- const GtkCanvasBox *source);
-void gtk_canvas_box_finish (GtkCanvasBox *self);
-
-void gtk_canvas_box_init_variable (GtkCanvasBox *self,
- const char *format,
- ...) G_GNUC_PRINTF(2,3);
-void gtk_canvas_box_update_variable (GtkCanvasBox *self,
- const GtkCanvasBox *other);
-
-G_END_DECLS
-
-#endif /* __GTK_CANVAS_BOX_PRIVATE_H__ */
diff --git a/gtk/gtkcanvasitem.c b/gtk/gtkcanvasitem.c
index 0ed91e7291..e19c9017e1 100644
--- a/gtk/gtkcanvasitem.c
+++ b/gtk/gtkcanvasitem.c
@@ -22,7 +22,7 @@
#include "gtkcanvasitemprivate.h"
#include "gtkcanvas.h"
-#include "gtkcanvasboxprivate.h"
+#include "gtkcanvasbox.h"
#include "gtkintl.h"
#include "gtklistitemfactoryprivate.h"
#include "gtkwidget.h"
@@ -41,17 +41,19 @@ struct _GtkCanvasItem
GtkCanvas *canvas;
gpointer item;
GtkWidget *widget;
+ GtkCanvasItemComputeBoundsFunc compute_bounds_func;
+ gpointer user_data;
+ GDestroyNotify user_destroy;
+
GtkCanvasBox bounds;
- GtkCanvasBox bounds_var;
- GtkCanvasBox allocation_var;
+ GtkCanvasBox allocation;
- GtkCanvasVector size_vecs[4];
+ guint has_allocation : 1;
};
enum
{
PROP_0,
- PROP_BOUNDS,
PROP_CANVAS,
PROP_ITEM,
PROP_WIDGET,
@@ -74,23 +76,12 @@ gtk_canvas_item_dispose (GObject *object)
g_assert (self->item == NULL);
g_assert (self->widget == NULL);
- G_OBJECT_CLASS (gtk_canvas_item_parent_class)->dispose (object);
-}
+ if (self->user_destroy)
+ self->user_destroy (self->user_data);
+ self->user_destroy = NULL;
+ self->user_data = NULL;
-static void
-gtk_canvas_item_finalize (GObject *object)
-{
- GtkCanvasItem *self = GTK_CANVAS_ITEM (object);
- int i;
-
- for (i = 0; i < 4; i++)
- gtk_canvas_vector_finish (&self->size_vecs[i]);
-
- gtk_canvas_box_finish (&self->bounds);
- gtk_canvas_box_finish (&self->bounds_var);
- gtk_canvas_box_finish (&self->allocation_var);
-
- G_OBJECT_CLASS (gtk_canvas_item_parent_class)->finalize (object);
+ G_OBJECT_CLASS (gtk_canvas_item_parent_class)->dispose (object);
}
static void
@@ -103,10 +94,6 @@ gtk_canvas_item_get_property (GObject *object,
switch (property_id)
{
- case PROP_BOUNDS:
- g_value_set_boxed (value, &self->bounds);
- break;
-
case PROP_CANVAS:
g_value_set_object (value, self->canvas);
break;
@@ -135,10 +122,6 @@ gtk_canvas_item_set_property (GObject *object,
switch (property_id)
{
- case PROP_BOUNDS:
- gtk_canvas_item_set_bounds (self, g_value_get_boxed (value));
- break;
-
case PROP_WIDGET:
gtk_canvas_item_set_widget (self, g_value_get_object (value));
break;
@@ -155,21 +138,10 @@ gtk_canvas_item_class_init (GtkCanvasItemClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gtk_canvas_item_dispose;
- gobject_class->finalize = gtk_canvas_item_finalize;
gobject_class->get_property = gtk_canvas_item_get_property;
gobject_class->set_property = gtk_canvas_item_set_property;
/**
- * GtkCanvasItem:bounds: (attributes org.gtk.Property.get=gtk_canvas_item_get_bounds org.gtk.Property.set=gtk_canvas_item_set_bounds)
- *
- * The bounds to place the widget into.
- */
- properties[PROP_BOUNDS] =
- g_param_spec_boxed ("bounds", NULL, NULL,
- GTK_TYPE_CANVAS_BOX,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- /**
* GtkCanvasItem:canvas: (attributes org.gtk.Property.get=gtk_canvas_item_get_canvas org.gtk.Property.set=gtk_canvas_item_set_canvas)
*
* The canvas this item belongs to or %NULL if the canvas has been destroyed
@@ -205,17 +177,6 @@ gtk_canvas_item_class_init (GtkCanvasItemClass *klass)
static void
gtk_canvas_item_init (GtkCanvasItem *self)
{
- gtk_canvas_vector_init_variable (&self->size_vecs[0], "item%p.min_for_min", self);
- gtk_canvas_vector_init_variable (&self->size_vecs[1], "item%p.min_for_nat", self);
- gtk_canvas_vector_init_variable (&self->size_vecs[2], "item%p.nat_for_min", self);
- gtk_canvas_vector_init_variable (&self->size_vecs[3], "item%p.nat_for_nat", self);
-
- gtk_canvas_vector_init_constant (&self->bounds.point, 0, 0);
- gtk_canvas_vector_init_copy (&self->bounds.size, &self->size_vecs[GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT]);
- gtk_canvas_vector_init_constant (&self->bounds.origin, 0.5, 0.5);
- gtk_canvas_box_init_variable (&self->bounds_var, "item%p.bounds", self);
- gtk_canvas_box_update_variable (&self->bounds_var, &self->bounds);
- gtk_canvas_box_init_variable (&self->allocation_var, "item%p.allocation", self);
}
GtkCanvasItem *
@@ -236,70 +197,72 @@ gtk_canvas_item_new (GtkCanvas *canvas,
}
void
-gtk_canvas_item_validate_variables (GtkCanvasItem *self)
+gtk_canvas_item_invalidate_allocation (GtkCanvasItem *self)
{
- int w[4], h[4], i;
+ self->has_allocation = FALSE;
+}
- if (self->widget == NULL)
+gboolean
+gtk_canvas_item_allocate (GtkCanvasItem *self,
+ gboolean force)
+{
+ int w, h;
+
+ g_assert (!self->has_allocation);
+
+ if (!self->compute_bounds_func)
{
- memset (w, 0, sizeof (w));
- memset (h, 0, sizeof (h));
+ gtk_canvas_box_init (&self->bounds, 0, 0, 0, 0, 0.5, 0.5);
}
- else
+ else if (!self->compute_bounds_func (self, &self->bounds, self->user_data))
+ {
+ if (!force)
+ return FALSE;
+ gtk_canvas_box_init (&self->bounds, 0, 0, 0, 0, 0.5, 0.5);
+ }
+
+ if (self->widget)
{
if (gtk_widget_get_request_mode (self->widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
{
- gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, -1, &w[0], &w[2], NULL, NULL);
- w[1] = w[0];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, w[0], &h[0], &h[1], NULL, NULL);
- w[3] = w[2];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, w[2], &h[2], &h[3], NULL, NULL);
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, -1, &w, NULL, NULL, NULL);
+ w = MAX (w, ceil (ABS (self->bounds.size.width)));
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL);
+ h = MAX (h, ceil (ABS (self->bounds.size.height)));
}
else
{
- gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, -1, &h[0], &h[2], NULL, NULL);
- h[1] = h[0];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, h[0], &w[0], &w[1], NULL, NULL);
- h[3] = h[2];
- gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, h[2], &w[2], &w[3], NULL, NULL);
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL);
+ h = MAX (h, ceil (ABS (self->bounds.size.height)));
+ gtk_widget_measure (self->widget, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL);
+ w = MAX (w, ceil (ABS (self->bounds.size.width)));
}
- }
- for (i = 0; i < 4; i++)
+ if (self->bounds.size.width >= 0)
+ w = MAX (self->bounds.size.width, w);
+ else
+ w = MIN (self->bounds.size.width, -w);
+ if (self->bounds.size.height >= 0)
+ h = MAX (self->bounds.size.height, h);
+ else
+ h = MIN (self->bounds.size.height, -h);
+ }
+ else
{
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->size_vecs[i]),
- 0, 0);
+ w = 0;
+ h = 0;
}
- gtk_canvas_vector_init_invalid (
- gtk_canvas_vector_get_variable (&self->allocation_var.point));
- gtk_canvas_vector_init_invalid (
- gtk_canvas_vector_get_variable (&self->allocation_var.size));
- gtk_canvas_vector_init_invalid (
- gtk_canvas_vector_get_variable (&self->allocation_var.origin));
-}
+ gtk_canvas_box_init (&self->allocation,
+ round (self->bounds.point.x - self->bounds.origin.horizontal * w)
+ + self->bounds.origin.horizontal * w,
+ round (self->bounds.point.y - self->bounds.origin.vertical * h)
+ + self->bounds.origin.vertical * h,
+ w, h,
+ self->bounds.origin.horizontal, self->bounds.origin.vertical);
+ self->has_allocation = TRUE;
-void
-gtk_canvas_item_allocate (GtkCanvasItem *self,
- graphene_rect_t *rect)
-{
- graphene_vec2_t origin;
-
- if (!gtk_canvas_vector_eval (&self->bounds.origin, &origin))
- graphene_vec2_init_from_vec2 (&origin, graphene_vec2_zero ());
-
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->allocation_var.point),
- rect->origin.x + graphene_vec2_get_x (&origin) * rect->size.width,
- rect->origin.y + graphene_vec2_get_y (&origin) * rect->size.height);
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->allocation_var.size),
- rect->size.width, rect->size.height);
- gtk_canvas_vector_init_constant (
- gtk_canvas_vector_get_variable (&self->allocation_var.origin),
- graphene_vec2_get_x (&origin),
- graphene_vec2_get_y (&origin));
+ return TRUE;
}
void
@@ -312,13 +275,9 @@ gtk_canvas_item_allocate_widget (GtkCanvasItem *self,
if (self->widget == NULL)
return;
- if (!gtk_canvas_box_eval (&self->allocation_var, &allocation))
- {
- /* gtkcanvas.c will not call this function otherwise */
- g_assert_not_reached ();
- }
-
+ gtk_canvas_box_to_rect (&self->allocation, &allocation);
graphene_rect_normalize (&allocation);
+
gtk_widget_size_allocate (self->widget,
&(GtkAllocation) {
allocation.origin.x - dx,
@@ -331,32 +290,7 @@ gtk_canvas_item_allocate_widget (GtkCanvasItem *self,
gboolean
gtk_canvas_item_has_allocation (GtkCanvasItem *self)
{
- return !gtk_canvas_vector_is_invalid (gtk_canvas_vector_get_variable (&self->allocation_var.point));
-}
-
-const GtkCanvasVector *
-gtk_canvas_vector_get_item_measure (GtkCanvasItem *item,
- GtkCanvasItemMeasure measure)
-{
- g_return_val_if_fail (GTK_IS_CANVAS_ITEM (item), NULL);
-
- return &item->size_vecs[measure];
-}
-
-const GtkCanvasBox *
-gtk_canvas_box_get_item_bounds (GtkCanvasItem *item)
-{
- g_return_val_if_fail (GTK_IS_CANVAS_ITEM (item), NULL);
-
- return &item->bounds_var;
-}
-
-const GtkCanvasBox *
-gtk_canvas_box_get_item_allocation (GtkCanvasItem *item)
-{
- g_return_val_if_fail (GTK_IS_CANVAS_ITEM (item), NULL);
-
- return &item->allocation_var;
+ return self->has_allocation;
}
/**
@@ -395,45 +329,99 @@ gtk_canvas_item_get_item (GtkCanvasItem *self)
}
/**
- * gtk_canvas_item_set_bounds: (attributes org.gtk.Method.set_property=bounds)
+ * gtk_canvas_item_set_compute_bounds:
* @self: a `GtkCanvasItem`
- * @bounds: (transfer none): the bounds to allocate the widget in
+ * @compute_bounds_func: the function to compute bounds
+ * @user_data: (nullable): user data to pass to @compute_bounds_func
+ * @user_destroy: destroy notify for @user_data
+ *
+ * Sets the function to call to compute bounds during allocation.
*
- * Sets the box to allocate the widget into.
+ * This function may be called multiple times if it returned %FALSE
+ * previously.
+ *
+ * Because of that the function is expected to be pure - not set
+ * any properties or have other side effects - and idempotent -
+ * return the same result if called multiple times in order.
*/
void
-gtk_canvas_item_set_bounds (GtkCanvasItem *self,
- const GtkCanvasBox *bounds)
+gtk_canvas_item_set_compute_bounds (GtkCanvasItem *self,
+ GtkCanvasItemComputeBoundsFunc compute_bounds_func,
+ gpointer user_data,
+ GDestroyNotify user_destroy)
{
g_return_if_fail (GTK_IS_CANVAS_ITEM (self));
- g_return_if_fail (bounds != NULL);
- gtk_canvas_box_init_copy (&self->bounds, bounds);
- gtk_canvas_box_update_variable (&self->bounds_var, bounds);
+ if (self->user_destroy)
+ self->user_destroy (self->user_data);
+
+ self->compute_bounds_func = compute_bounds_func;
+ self->user_data = user_data;
+ self->user_destroy = user_destroy;
+}
+
+void
+gtk_canvas_item_invalidate_bounds (GtkCanvasItem *self)
+{
+ g_return_if_fail (GTK_IS_CANVAS_ITEM (self));
if (self->canvas)
gtk_widget_queue_allocate (GTK_WIDGET (self->canvas));
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BOUNDS]);
}
/**
- * gtk_canvas_item_get_bounds: (attributes org.gtk.Method.get_property=bounds)
+ * gtk_canvas_item_get_bounds:
* @self: a `GtkCanvasItem`
*
* Gets the bounds that are used to allocate the widget
*
- * Returns: (transfer none): The bounds
+ * If the bounds are not known yet - for example when called during the size
+ * allocation phase before this item has succesfully computed its bounds -
+ * this function returns %NULL.
+ *
+ * See also gtk_canvas_item_get_allocation().
+ *
+ * Returns: (transfer none) (nullable): The bounds
*/
const GtkCanvasBox *
gtk_canvas_item_get_bounds (GtkCanvasItem *self)
{
g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+ if (!self->has_allocation)
+ return NULL;
+
return &self->bounds;
}
/**
+ * gtk_canvas_item_get_allocation:
+ * @self: a `GtkCanvasItem`
+ *
+ * Gets the allocation assigned to the widget.
+ *
+ * If the bounds are not known yet - for example when called during the size
+ * allocation phase before this item has succesfully computed its bounds -
+ * this function returns %NULL.
+ *
+ * Compared with gtk_canvas_item_get_bounds(), this function returns the actual
+ * box used to allocate the widget, which may be different from the bounds
+ * to conform to its size requirements.
+ *
+ * Returns: (transfer none) (nullable): The allocation
+ */
+const GtkCanvasBox *
+gtk_canvas_item_get_allocation (GtkCanvasItem *self)
+{
+ g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+
+ if (!self->has_allocation)
+ return NULL;
+
+ return &self->allocation;
+}
+
+/**
* gtk_canvas_item_set_widget: (attributes org.gtk.Method.set_property=widget)
* @self: a `GtkCanvasItem`
* @widget: (nullable) (transfer none): the widget to use
diff --git a/gtk/gtkcanvasitem.h b/gtk/gtkcanvasitem.h
index 15f3ae7bf4..488656aa2f 100644
--- a/gtk/gtkcanvasitem.h
+++ b/gtk/gtkcanvasitem.h
@@ -35,6 +35,9 @@ G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkCanvasItem, gtk_canvas_item, GTK, CANVAS_ITEM, GObject)
+typedef gboolean (* GtkCanvasItemComputeBoundsFunc) (GtkCanvasItem *ci,
+ GtkCanvasBox *out_box,
+ gpointer user_data);
GDK_AVAILABLE_IN_ALL
GtkCanvas * gtk_canvas_item_get_canvas (GtkCanvasItem *self);
GDK_AVAILABLE_IN_ALL
@@ -47,10 +50,17 @@ GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_canvas_item_get_widget (GtkCanvasItem *self);
GDK_AVAILABLE_IN_ALL
-void gtk_canvas_item_set_bounds (GtkCanvasItem *self,
- const GtkCanvasBox *box);
+void gtk_canvas_item_set_compute_bounds (GtkCanvasItem *self,
+ GtkCanvasItemComputeBoundsFunc compute_bounds_func,
+ gpointer user_data,
+ GDestroyNotify user_destroy);
+GDK_AVAILABLE_IN_ALL
+void gtk_canvas_item_invalidate_bounds (GtkCanvasItem *self);
+
GDK_AVAILABLE_IN_ALL
const GtkCanvasBox * gtk_canvas_item_get_bounds (GtkCanvasItem *self);
+GDK_AVAILABLE_IN_ALL
+const GtkCanvasBox * gtk_canvas_item_get_allocation (GtkCanvasItem *self);
G_END_DECLS
diff --git a/gtk/gtkcanvasitemprivate.h b/gtk/gtkcanvasitemprivate.h
index cf1adbfc24..f52377cecd 100644
--- a/gtk/gtkcanvasitemprivate.h
+++ b/gtk/gtkcanvasitemprivate.h
@@ -3,16 +3,14 @@
#include "gtkcanvasitem.h"
-#include "gtkcanvasvectorprivate.h"
-
G_BEGIN_DECLS
GtkCanvasItem * gtk_canvas_item_new (GtkCanvas *canvas,
gpointer item);
-void gtk_canvas_item_validate_variables (GtkCanvasItem *self);
-void gtk_canvas_item_allocate (GtkCanvasItem *self,
- graphene_rect_t *rect);
+void gtk_canvas_item_invalidate_allocation (GtkCanvasItem *self);
+gboolean gtk_canvas_item_allocate (GtkCanvasItem *self,
+ gboolean force);
void gtk_canvas_item_allocate_widget (GtkCanvasItem *self,
float dx,
float dy);
diff --git a/gtk/gtkcanvasvector.c b/gtk/gtkcanvasvector.c
deleted file mode 100644
index 8ba16b073f..0000000000
--- a/gtk/gtkcanvasvector.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright © 2022 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-/**
- * GtkCanvasVector:
- *
- * `GtkCanvasVector` describes a point, size or scale in the coordinate
- * system of a `GtkCanvas`.
- *
- * Vectors are automatically-updating expressions that can track other vectors
- * in the canvas, and constructing the vectors to place `GtkCanvasItem`s on the
- * canvas is the main thing about `GtkCanvas`.
- */
-
-#include "config.h"
-
-#include "gtkcanvasvectorprivate.h"
-
-#include "gtkcanvasboxprivate.h"
-
-G_DEFINE_BOXED_TYPE (GtkCanvasVector, gtk_canvas_vector,
- gtk_canvas_vector_copy,
- gtk_canvas_vector_free)
-
-static GtkCanvasVector *
-gtk_canvas_vector_alloc (void)
-{
- return g_slice_new (GtkCanvasVector);
-}
-
-/**
- * gtk_canvas_vector_new:
- * @x: x coordinate
- * @y: y coordinate
- *
- * Creates a new vector at the given coordinate.
- *
- * Returns: a new vector
- **/
-GtkCanvasVector *
-gtk_canvas_vector_new (float x,
- float y)
-{
- GtkCanvasVector *self;
-
- self = gtk_canvas_vector_alloc ();
- gtk_canvas_vector_init_constant (self, x, y);
-
- return self;
-}
-
-/**
- * gtk_canvas_vector_new_from_box:
- * @box: a box
- * @origin_x: x coordinate of box origin
- * @origin_y: y coordinate of box origin
- *
- * Creates a vector relative to the given box.
- *
- * The origin describes where in the box the vector is, with
- * (0, 0) being the top left and (1, 1) being the bottom right
- * corner of the box.
- *
- * Returns: a new vector
- **/
-GtkCanvasVector *
-gtk_canvas_vector_new_from_box (const GtkCanvasBox *box,
- float origin_x,
- float origin_y)
-{
- GtkCanvasVector *self;
- GtkCanvasVector mult;
- graphene_vec2_t origin, minus_one;
-
- g_return_val_if_fail (box != NULL, NULL);
-
- graphene_vec2_init (&origin, origin_x, origin_y);
- graphene_vec2_init (&minus_one, -1, -1);
- gtk_canvas_vector_init_multiply (&mult, &box->origin, &box->size);
-
- self = gtk_canvas_vector_alloc ();
- gtk_canvas_vector_init_sum (self,
- graphene_vec2_one (),
- &box->point,
- &origin,
- &box->size,
- &minus_one,
- &mult,
- NULL);
-
- gtk_canvas_vector_finish (&mult);
-
- return self;
-}
-
-/**
- * gtk_canvas_vector_new_distance:
- * @from: point from where to compute the distance
- * @to: point to where to compute the distance
- *
- * Creates a size for the given distance. Note that both width and height
- * can be negative if the coordinate of @to is smaller than @from in the
- * corresponding dimension.
- *
- * Returns: a new size
- **/
-GtkCanvasVector *
-gtk_canvas_vector_new_distance (const GtkCanvasVector *from,
- const GtkCanvasVector *to)
-{
- GtkCanvasVector *self;
- graphene_vec2_t minus_one;
-
- g_return_val_if_fail (from != NULL, NULL);
- g_return_val_if_fail (to != NULL, NULL);
-
- graphene_vec2_init (&minus_one, -1.f, -1.f);
-
- self = gtk_canvas_vector_alloc ();
- gtk_canvas_vector_init_sum (self,
- graphene_vec2_one (),
- from,
- &minus_one,
- to,
- NULL);
-
- return self;
-}
-
-char *
-gtk_canvas_vector_to_string (const GtkCanvasVector *self)
-{
- GString *string;
-
- g_return_val_if_fail (self != NULL, NULL);
-
- string = g_string_new ("");
-
- gtk_canvas_vector_print (self, string);
-
- return g_string_free (string, FALSE);
-}
-
-GtkCanvasVector *
-gtk_canvas_vector_copy (const GtkCanvasVector *self)
-{
- GtkCanvasVector *copy;
-
- g_return_val_if_fail (self != NULL, NULL);
-
- copy = gtk_canvas_vector_alloc ();
- gtk_canvas_vector_init_copy (copy, self);
-
- return copy;
-}
-
-void
-gtk_canvas_vector_free (GtkCanvasVector *self)
-{
- gtk_canvas_vector_finish (self);
-
- g_slice_free (GtkCanvasVector, self);
-}
-
diff --git a/gtk/gtkcanvasvector.h b/gtk/gtkcanvasvector.h
deleted file mode 100644
index 7af8fc2f7b..0000000000
--- a/gtk/gtkcanvasvector.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright © 2022 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-#ifndef __GTK_CANVAS_VECTOR_H__
-#define __GTK_CANVAS_VECTOR_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtktypes.h>
-#include <graphene.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CANVAS_VECTOR (gtk_canvas_vector_get_type ())
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_canvas_vector_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkCanvasVector * gtk_canvas_vector_copy (const GtkCanvasVector *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_canvas_vector_free (GtkCanvasVector *self);
-
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_canvas_vector_eval (const GtkCanvasVector *self,
- graphene_vec2_t *result) G_GNUC_WARN_UNUSED_RESULT;
-GDK_AVAILABLE_IN_ALL
-char * gtk_canvas_vector_to_string (const GtkCanvasVector *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_canvas_vector_print (const GtkCanvasVector *self,
- GString *string);
-
-GDK_AVAILABLE_IN_ALL
-GtkCanvasVector * gtk_canvas_vector_new (float x,
- float y);
-GDK_AVAILABLE_IN_ALL
-GtkCanvasVector * gtk_canvas_vector_new_distance (const GtkCanvasVector *from,
- const GtkCanvasVector *to);
-GDK_AVAILABLE_IN_ALL
-GtkCanvasVector * gtk_canvas_vector_new_from_box (const GtkCanvasBox *box,
- float origin_x,
- float origin_y);
-
-typedef enum {
- GTK_CANVAS_ITEM_MEASURE_MIN_FOR_MIN,
- GTK_CANVAS_ITEM_MEASURE_MIN_FOR_NAT,
- GTK_CANVAS_ITEM_MEASURE_NAT_FOR_MIN,
- GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT
-} GtkCanvasItemMeasure;
-
-GDK_AVAILABLE_IN_ALL
-const GtkCanvasVector * gtk_canvas_vector_get_item_measure (GtkCanvasItem *item,
- GtkCanvasItemMeasure measure);
-G_END_DECLS
-
-#endif /* __GTK_VECTOR_H__ */
diff --git a/gtk/gtkcanvasvectorimpl.c b/gtk/gtkcanvasvectorimpl.c
deleted file mode 100644
index 6b1d657b38..0000000000
--- a/gtk/gtkcanvasvectorimpl.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright © 2022 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-/**
- * GtkCanvasVector:
- *
- * `GtkCanvasVector` describes a vector in a `GtkCanvas`.
- */
-
-#include "config.h"
-
-#include "gtkcanvasvectorprivate.h"
-
-/* {{{ Boilerplate */
-
-struct _GtkCanvasVectorClass
-{
- const char *type_name;
-
- void (* copy) (GtkCanvasVector *self,
- const GtkCanvasVector *source);
- void (* finish) (GtkCanvasVector *self);
- void (* print) (const GtkCanvasVector *self,
- GString *string);
- gboolean (* eval) (const GtkCanvasVector *self,
- graphene_vec2_t *result);
-};
-
-/* }}} */
-/* {{{ INVALID */
-
-static void
-gtk_canvas_vector_invalid_copy (GtkCanvasVector *vector,
- const GtkCanvasVector *source_vector)
-{
- gtk_canvas_vector_init_invalid (vector);
-}
-
-static void
-gtk_canvas_vector_invalid_finish (GtkCanvasVector *vector)
-{
-}
-
-static void
-gtk_canvas_vector_invalid_print (const GtkCanvasVector *vector,
- GString *string)
-{
- g_string_append (string, "#error");
-}
-
-static gboolean
-gtk_canvas_vector_invalid_eval (const GtkCanvasVector *vector,
- graphene_vec2_t *result)
-{
- return FALSE;
-}
-
-static const GtkCanvasVectorClass GTK_CANVAS_VECTOR_INVALID_CLASS =
-{
- "GtkCanvasVectorInvalid",
- gtk_canvas_vector_invalid_copy,
- gtk_canvas_vector_invalid_finish,
- gtk_canvas_vector_invalid_print,
- gtk_canvas_vector_invalid_eval,
-};
-
-void
-gtk_canvas_vector_init_invalid (GtkCanvasVector *vector)
-{
- vector->class = &GTK_CANVAS_VECTOR_INVALID_CLASS;
-}
-
-gboolean
-gtk_canvas_vector_is_invalid (GtkCanvasVector *vector)
-{
- return vector->class == &GTK_CANVAS_VECTOR_INVALID_CLASS;
-}
-
-/* }}} */
-/* {{{ CONSTANT */
-
-static void
-gtk_canvas_vector_constant_copy (GtkCanvasVector *vector,
- const GtkCanvasVector *source_vector)
-{
- const GtkCanvasVectorConstant *source = &source_vector->constant;
-
- gtk_canvas_vector_init_constant_from_vector (vector, &source->value);
-}
-
-static void
-gtk_canvas_vector_constant_finish (GtkCanvasVector *vector)
-{
-}
-
-static void
-gtk_canvas_vector_constant_print (const GtkCanvasVector *vector,
- GString *string)
-{
- const GtkCanvasVectorConstant *self = &vector->constant;
-
- g_string_append_printf (string, "[%g, %g]",
- graphene_vec2_get_x (&self->value),
- graphene_vec2_get_y (&self->value));
-}
-
-static gboolean
-gtk_canvas_vector_constant_eval (const GtkCanvasVector *vector,
- graphene_vec2_t *result)
-{
- const GtkCanvasVectorConstant *self = &vector->constant;
-
- graphene_vec2_init_from_vec2 (result, &self->value);
-
- return TRUE;
-}
-
-static const GtkCanvasVectorClass GTK_CANVAS_VECTOR_CONSTANT_CLASS =
-{
- "GtkCanvasVectorConstant",
- gtk_canvas_vector_constant_copy,
- gtk_canvas_vector_constant_finish,
- gtk_canvas_vector_constant_print,
- gtk_canvas_vector_constant_eval,
-};
-
-void
-gtk_canvas_vector_init_constant_from_vector (GtkCanvasVector *vector,
- const graphene_vec2_t *value)
-{
- GtkCanvasVectorConstant *self = &vector->constant;
-
- self->class = &GTK_CANVAS_VECTOR_CONSTANT_CLASS;
- graphene_vec2_init_from_vec2 (&self->value, value);
-}
-
-void
-gtk_canvas_vector_init_constant (GtkCanvasVector *vector,
- float x,
- float y)
-{
- graphene_vec2_t v;
-
- graphene_vec2_init (&v, x, y);
- gtk_canvas_vector_init_constant_from_vector (vector, &v);
-}
-
-/* }}} */
-/* {{{ SUM */
-
-static void
-gtk_canvas_vector_sum_copy (GtkCanvasVector *vector,
- const GtkCanvasVector *source_vector);
-
-static void
-gtk_canvas_vector_sum_finish (GtkCanvasVector *vector)
-{
- GtkCanvasVectorSum *self = &vector->sum;
- gsize i;
-
- for (i = 0; i < self->n_summands; i++)
- {
- gtk_canvas_vector_finish (&self->summands[i].value);
- }
-
- g_free (self->summands);
-}
-
-static void
-gtk_canvas_vector_sum_print (const GtkCanvasVector *vector,
- GString *string)
-{
- const GtkCanvasVectorSum *self = &vector->sum;
- gsize i;
-
- for (i = 0; i < self->n_summands; i++)
- {
- if (i > 0)
- g_string_append (string, " + ");
- if (!graphene_vec2_equal (&self->summands[i].scale, graphene_vec2_one()))
- {
- g_string_append_printf (string, "[%g, %g] * ",
- graphene_vec2_get_x (&self->summands[i].scale),
- graphene_vec2_get_y (&self->summands[i].scale));
- }
- gtk_canvas_vector_print (&self->summands[i].value, string);
- }
-}
-
-static gboolean
-gtk_canvas_vector_sum_eval (const GtkCanvasVector *vector,
- graphene_vec2_t *result)
-{
- const GtkCanvasVectorSum *self = &vector->sum;
- gsize i;
-
- if (!gtk_canvas_vector_eval (&self->summands[0].value, result))
- return FALSE;
- graphene_vec2_multiply (&self->summands[0].scale, result, result);
-
- for (i = 1; i < self->n_summands; i++)
- {
- graphene_vec2_t tmp;
-
- if (!gtk_canvas_vector_eval (&self->summands[i].value, &tmp))
- return FALSE;
- graphene_vec2_multiply (&self->summands[i].scale, &tmp, &tmp);
- graphene_vec2_add (&tmp, result, result);
- }
-
- return TRUE;
-}
-
-static const GtkCanvasVectorClass GTK_CANVAS_VECTOR_SUM_CLASS =
-{
- "GtkCanvasVectorSum",
- gtk_canvas_vector_sum_copy,
- gtk_canvas_vector_sum_finish,
- gtk_canvas_vector_sum_print,
- gtk_canvas_vector_sum_eval,
-};
-
-static void
-gtk_canvas_vector_sum_copy (GtkCanvasVector *vector,
- const GtkCanvasVector *source_vector)
-{
- GtkCanvasVectorSum *self = &vector->sum;
- const GtkCanvasVectorSum *source = &source_vector->sum;
- gsize i;
-
- self->class = &GTK_CANVAS_VECTOR_SUM_CLASS;
- self->summands = g_new (GtkCanvasVectorSummand, source->n_summands);
- self->n_summands = source->n_summands;
- for (i = 0; i < self->n_summands; i++)
- {
- graphene_vec2_init_from_vec2 (&self->summands[i].scale,
- &source->summands[i].scale);
- gtk_canvas_vector_init_copy (&self->summands[i].value,
- &source->summands[i].value);
- }
-}
-
-void
-gtk_canvas_vector_init_sum (GtkCanvasVector *vector,
- const graphene_vec2_t *scale,
- ...)
-{
- GtkCanvasVectorSum *self = &vector->sum;
- GArray *array;
- GtkCanvasVectorSummand summand;
- va_list args;
-
- g_assert (scale != NULL);
-
- self->class = &GTK_CANVAS_VECTOR_SUM_CLASS;
-
- array = g_array_new (FALSE, FALSE, sizeof (GtkCanvasVectorSummand));
- va_start (args, scale);
-
- while (scale)
- {
- graphene_vec2_init_from_vec2 (&summand.scale, scale);
- gtk_canvas_vector_init_copy (&summand.value, va_arg (args, const GtkCanvasVector *));
- g_array_append_val (array, summand);
- scale = va_arg (args, const graphene_vec2_t *);
- }
- va_end (args);
-
- self->n_summands = array->len;
- self->summands = (GtkCanvasVectorSummand *) g_array_free (array, FALSE);
-}
-
-/* }}} */
-/* {{{ MULTIPLY */
-
-static void
-gtk_canvas_vector_multiply_copy (GtkCanvasVector *vector,
- const GtkCanvasVector *source_vector)
-{
- const GtkCanvasVectorMultiply *source = &source_vector->multiply;
-
- gtk_canvas_vector_init_multiply (vector, source->a, source->b);
-}
-
-static void
-gtk_canvas_vector_multiply_finish (GtkCanvasVector *vector)
-{
- const GtkCanvasVectorMultiply *self = &vector->multiply;
-
- gtk_canvas_vector_free (self->a);
- gtk_canvas_vector_free (self->b);
-}
-
-static void
-gtk_canvas_vector_multiply_print (const GtkCanvasVector *vector,
- GString *string)
-{
- const GtkCanvasVectorMultiply *self = &vector->multiply;
-
- gtk_canvas_vector_print (self->a, string);
- g_string_append (string, " * ");
- gtk_canvas_vector_print (self->b, string);
-}
-
-static gboolean
-gtk_canvas_vector_multiply_eval (const GtkCanvasVector *vector,
- graphene_vec2_t *result)
-{
- const GtkCanvasVectorMultiply *self = &vector->multiply;
- graphene_vec2_t a, b;
-
- if (!gtk_canvas_vector_eval (self->a, &a) ||
- !gtk_canvas_vector_eval (self->b, &b))
- return FALSE;
-
- graphene_vec2_multiply (&a, &b, result);
- return TRUE;
-}
-
-static const GtkCanvasVectorClass GTK_CANVAS_VECTOR_MULTIPLY_CLASS =
-{
- "GtkCanvasVectorMultiply",
- gtk_canvas_vector_multiply_copy,
- gtk_canvas_vector_multiply_finish,
- gtk_canvas_vector_multiply_print,
- gtk_canvas_vector_multiply_eval,
-};
-
-void
-gtk_canvas_vector_init_multiply (GtkCanvasVector *vector,
- const GtkCanvasVector *a,
- const GtkCanvasVector *b)
-{
- GtkCanvasVectorMultiply *self = &vector->multiply;
-
- self->class = &GTK_CANVAS_VECTOR_MULTIPLY_CLASS;
-
- self->a = gtk_canvas_vector_copy (a);
- self->b = gtk_canvas_vector_copy (b);
-}
-
-/* }}} */
-/* {{{ VARIABLE */
-
-static void
-gtk_canvas_vector_init_variable_with_variable (GtkCanvasVector *vector,
- const char *name,
- GtkCanvasVector *variable);
-
-static void
-gtk_canvas_vector_variable_copy (GtkCanvasVector *vector,
- const GtkCanvasVector *source_vector)
-{
- const GtkCanvasVectorVariable *source = &source_vector->variable;
-
- gtk_canvas_vector_init_variable_with_variable (vector,
- source->name,
- g_rc_box_acquire (source->variable));
-}
-
-static void
-gtk_canvas_vector_variable_finish (GtkCanvasVector *vector)
-{
- const GtkCanvasVectorVariable *self = &vector->variable;
-
- g_free (self->name);
- g_rc_box_release (self->variable);
-}
-
-static void
-gtk_canvas_vector_variable_print (const GtkCanvasVector *vector,
- GString *string)
-{
- const GtkCanvasVectorVariable *self = &vector->variable;
-
- g_string_append (string, self->name);
-}
-
-static gboolean
-gtk_canvas_vector_variable_eval (const GtkCanvasVector *vector,
- graphene_vec2_t *result)
-{
- const GtkCanvasVectorVariable *self = &vector->variable;
-
- return gtk_canvas_vector_eval (self->variable, result);
-}
-
-static const GtkCanvasVectorClass GTK_CANVAS_VECTOR_VARIABLE_CLASS =
-{
- "GtkCanvasVectorVariable",
- gtk_canvas_vector_variable_copy,
- gtk_canvas_vector_variable_finish,
- gtk_canvas_vector_variable_print,
- gtk_canvas_vector_variable_eval,
-};
-
-static void
-gtk_canvas_vector_init_variable_with_variable (GtkCanvasVector *vector,
- const char *name,
- GtkCanvasVector *variable)
-{
- GtkCanvasVectorVariable *self = &vector->variable;
-
- self->class = &GTK_CANVAS_VECTOR_VARIABLE_CLASS;
-
- self->name = g_strdup (name);
- self->variable = variable;
-}
-
-void
-gtk_canvas_vector_init_variable (GtkCanvasVector *vector,
- const char *format,
- ...)
-{
- GtkCanvasVector *variable;
- char *name;
- va_list args;
-
- variable = g_rc_box_new (GtkCanvasVector);
- gtk_canvas_vector_init_invalid (variable);
-
- va_start (args, format);
- name = g_strdup_vprintf (format, args);
- va_end (args);
-
- gtk_canvas_vector_init_variable_with_variable (vector, name, variable);
-
- g_free (name);
-}
-
-GtkCanvasVector *
-gtk_canvas_vector_get_variable (GtkCanvasVector *vector)
-{
- GtkCanvasVectorVariable *self = &vector->variable;
-
- g_return_val_if_fail (self->class == &GTK_CANVAS_VECTOR_VARIABLE_CLASS, NULL);
-
- return self->variable;
-}
-
-/* }}} */
-/* {{{ PUBLIC API */
-
-void
-gtk_canvas_vector_init_copy (GtkCanvasVector *self,
- const GtkCanvasVector *source)
-{
- source->class->copy (self, source);
-}
-
-void
-gtk_canvas_vector_finish (GtkCanvasVector *self)
-{
- self->class->finish (self);
-}
-
-/**
- * gtk_canvas_vector_eval:
- * @self: a `GtkCanvasVector`
- * @result: (out) (caller-allocates): The current value
- * of the vector
- *
- * Evaluates the given vector and returns its x and y value.
- *
- * If the vector currently has no value - because it
- * references and object that has been deleted or because
- * the value is in the process of being updated - %FALSE
- * is returned. Think of this as an exception being raised.
- *
- * Returns: %FALSE if the vector currently has no value.
- **/
-gboolean
-gtk_canvas_vector_eval (const GtkCanvasVector *self,
- graphene_vec2_t *result)
-{
- g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (result != NULL, FALSE);
-
- if (self->class->eval (self, result))
- return TRUE;
-
- graphene_vec2_init_from_vec2 (result, graphene_vec2_zero ());
- return FALSE;
-}
-
-void
-gtk_canvas_vector_print (const GtkCanvasVector *self,
- GString *string)
-{
- g_return_if_fail (self != NULL);
- g_return_if_fail (string != NULL);
-
- self->class->print (self, string);
-}
-
diff --git a/gtk/gtkcanvasvectorprivate.h b/gtk/gtkcanvasvectorprivate.h
deleted file mode 100644
index 86171e62fb..0000000000
--- a/gtk/gtkcanvasvectorprivate.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright © 2022 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_CANVAS_VECTOR_PRIVATE_H__
-#define __GTK_CANVAS_VECTOR_PRIVATE_H__
-
-#include "gtkcanvasvector.h"
-
-#include <graphene.h>
-
-G_BEGIN_DECLS
-
-typedef struct _GtkCanvasVector GtkCanvasVector;
-typedef struct _GtkCanvasVectorClass GtkCanvasVectorClass;
-typedef struct _GtkCanvasVectorConstant GtkCanvasVectorConstant;
-typedef struct _GtkCanvasVectorMultiply GtkCanvasVectorMultiply;
-typedef struct _GtkCanvasVectorSum GtkCanvasVectorSum;
-typedef struct _GtkCanvasVectorSummand GtkCanvasVectorSummand;
-typedef struct _GtkCanvasVectorVariable GtkCanvasVectorVariable;
-
-struct _GtkCanvasVectorConstant
-{
- const GtkCanvasVectorClass *class;
-
- graphene_vec2_t value;
-};
-
-struct _GtkCanvasVectorMultiply
-{
- const GtkCanvasVectorClass *class;
-
- GtkCanvasVector *a;
- GtkCanvasVector *b;
-};
-
-struct _GtkCanvasVectorSum
-{
- const GtkCanvasVectorClass *class;
-
- graphene_vec2_t constant;
-
- gsize n_summands;
- GtkCanvasVectorSummand *summands;
-};
-
-struct _GtkCanvasVectorVariable
-{
- const GtkCanvasVectorClass *class;
-
- char *name;
- /* a GtkRcBox */
- GtkCanvasVector *variable;
-};
-
-struct _GtkCanvasVector
-{
- union {
- const GtkCanvasVectorClass *class;
- GtkCanvasVectorConstant constant;
- GtkCanvasVectorMultiply multiply;
- GtkCanvasVectorSum sum;
- GtkCanvasVectorVariable variable;
- };
-};
-
-struct _GtkCanvasVectorSummand
-{
- graphene_vec2_t scale;
- GtkCanvasVector value;
-};
-
-
-void gtk_canvas_vector_init_copy (GtkCanvasVector *self,
- const GtkCanvasVector *source);
-void gtk_canvas_vector_finish (GtkCanvasVector *self);
-
-void gtk_canvas_vector_init_invalid (GtkCanvasVector *vector);
-void gtk_canvas_vector_init_constant (GtkCanvasVector *vector,
- float x,
- float y);
-void gtk_canvas_vector_init_constant_from_vector (GtkCanvasVector *vector,
- const graphene_vec2_t *value);
-void gtk_canvas_vector_init_sum (GtkCanvasVector *vector,
- const graphene_vec2_t *scale,
- ...) G_GNUC_NULL_TERMINATED;
-void gtk_canvas_vector_init_multiply (GtkCanvasVector *vector,
- const GtkCanvasVector *a,
- const GtkCanvasVector *b);
-
-void gtk_canvas_vector_init_variable (GtkCanvasVector *vector,
- const char *format,
- ...) G_GNUC_PRINTF(2,3);
-GtkCanvasVector * gtk_canvas_vector_get_variable (GtkCanvasVector *vector);
-
-gboolean gtk_canvas_vector_is_invalid (GtkCanvasVector *vector);
-
-G_END_DECLS
-
-#endif /* __GTK_CANVAS_VECTOR_PRIVATE_H__ */
diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h
index da949a6bd9..cbf6045163 100644
--- a/gtk/gtktypes.h
+++ b/gtk/gtktypes.h
@@ -40,7 +40,6 @@ typedef struct _GtkBuilderScope GtkBuilderScope;
typedef struct _GtkCanvas GtkCanvas;
typedef struct _GtkCanvasBox GtkCanvasBox;
typedef struct _GtkCanvasItem GtkCanvasItem;
-typedef struct _GtkCanvasVector GtkCanvasVector;
typedef struct _GtkCssStyleChange GtkCssStyleChange;
typedef struct _GtkEventController GtkEventController;
typedef struct _GtkGesture GtkGesture;
diff --git a/gtk/meson.build b/gtk/meson.build
index 594808de9e..35b2774400 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -32,7 +32,6 @@ gtk_private_sources = files([
'gtkbuilderprecompile.c',
'gtkbuiltinicon.c',
'gtkcellareaboxcontext.c',
- 'gtkcanvasvectorimpl.c',
'gtkcoloreditor.c',
'gtkcolorplane.c',
'gtkcolorpicker.c',
@@ -186,7 +185,6 @@ gtk_public_sources = files([
'gtkcanvas.c',
'gtkcanvasbox.c',
'gtkcanvasitem.c',
- 'gtkcanvasvector.c',
'gtkcellarea.c',
'gtkcellareabox.c',
'gtkcellareacontext.c',
@@ -481,7 +479,6 @@ gtk_public_headers = files([
'gtkcanvas.h',
'gtkcanvasbox.h',
'gtkcanvasitem.h',
- 'gtkcanvasvector.h',
'gtkcenterbox.h',
'gtkcenterlayout.h',
'gtkcellarea.h',