diff options
author | Benjamin Otte <otte@redhat.com> | 2022-07-02 19:24:43 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2022-07-05 07:37:47 +0200 |
commit | 9eedd3f5acd09bece2c1436b1c061277c53b5ba5 (patch) | |
tree | 638aee3be317dda782059277ed519d99aa50950c | |
parent | d329c904b88d6a22074959aa9cf0475da7f140f1 (diff) | |
download | gtk+-9eedd3f5acd09bece2c1436b1c061277c53b5ba5.tar.gz |
canvas: Redo points and sizes
Instead of lots of special cases, just have 3 types:
* sums
* constants
* variables
And implement it in a new GtkCanvasVec2 struct and use it for points and
sizes.
Simplifies te code a lot.
Requires some changes though so that now all variables are
preinitialized instead of queried on demand.
-rw-r--r-- | demos/gtk-demo/canvas_intro.c | 2 | ||||
-rw-r--r-- | demos/gtk-demo/canvas_puzzle.c | 2 | ||||
-rw-r--r-- | gtk/gtkcanvas.c | 30 | ||||
-rw-r--r-- | gtk/gtkcanvasbox.c | 91 | ||||
-rw-r--r-- | gtk/gtkcanvasboxprivate.h | 17 | ||||
-rw-r--r-- | gtk/gtkcanvasitem.c | 78 | ||||
-rw-r--r-- | gtk/gtkcanvasitemprivate.h | 7 | ||||
-rw-r--r-- | gtk/gtkcanvaspoint.c | 227 | ||||
-rw-r--r-- | gtk/gtkcanvaspoint.h | 4 | ||||
-rw-r--r-- | gtk/gtkcanvaspointprivate.h | 52 | ||||
-rw-r--r-- | gtk/gtkcanvassize.c | 432 | ||||
-rw-r--r-- | gtk/gtkcanvassizeprivate.h | 84 | ||||
-rw-r--r-- | gtk/gtkcanvasvec2.c | 343 | ||||
-rw-r--r-- | gtk/gtkcanvasvec2private.h | 99 | ||||
-rw-r--r-- | gtk/meson.build | 1 |
15 files changed, 695 insertions, 774 deletions
diff --git a/demos/gtk-demo/canvas_intro.c b/demos/gtk-demo/canvas_intro.c index 7216b7a7e7..715bb2529f 100644 --- a/demos/gtk-demo/canvas_intro.c +++ b/demos/gtk-demo/canvas_intro.c @@ -27,7 +27,7 @@ bind_item (GtkListItemFactory *factory, 0.0, 0.0); gtk_canvas_point_free (point); - point = gtk_canvas_point_new_from_box (box, 0.5, 0.5, 0, 0); + point = gtk_canvas_point_new_from_box (box, 0.5, 0.5); gtk_canvas_box_free (box); size = gtk_canvas_size_new_measure_item (ci, GTK_CANVAS_ITEM_MEASURE_MIN_FOR_MIN); box = gtk_canvas_box_new (point, size, 0.5, 0.5); diff --git a/demos/gtk-demo/canvas_puzzle.c b/demos/gtk-demo/canvas_puzzle.c index 07b0d5f66d..c30d24a346 100644 --- a/demos/gtk-demo/canvas_puzzle.c +++ b/demos/gtk-demo/canvas_puzzle.c @@ -27,7 +27,7 @@ set_item_position (GtkCanvasItem *ci, 0.0, 0.0); gtk_canvas_point_free (point); - point = gtk_canvas_point_new_from_box (viewport, x, y, 0, 0); + point = gtk_canvas_point_new_from_box (viewport, x, y); gtk_canvas_box_free (viewport); size = gtk_canvas_size_new (0, 0); box = gtk_canvas_box_new (point, size, x, y); diff --git a/gtk/gtkcanvas.c b/gtk/gtkcanvas.c index e7047be63f..a1aef6f566 100644 --- a/gtk/gtkcanvas.c +++ b/gtk/gtkcanvas.c @@ -23,7 +23,8 @@ #include "gtkcanvasbox.h" #include "gtkcanvasitemprivate.h" -#include "gtkcanvassizeprivate.h" +#include "gtkcanvassize.h" +#include "gtkcanvasvec2private.h" #include "gtkintl.h" #include "gtklistitemfactory.h" #include "gtkwidgetprivate.h" @@ -53,7 +54,7 @@ struct _GtkCanvas GtkCanvasItems items; GHashTable *item_lookup; - GtkCanvasSize viewport_size; + GtkCanvasVec2 viewport_size; }; enum @@ -164,7 +165,7 @@ gtk_canvas_finalize (GObject *object) GtkCanvas *self = GTK_CANVAS (object); g_hash_table_unref (self->item_lookup); - gtk_canvas_size_finish (&self->viewport_size); + gtk_canvas_vec2_finish (&self->viewport_size); G_OBJECT_CLASS (gtk_canvas_parent_class)->finalize (object); } @@ -218,6 +219,19 @@ gtk_canvas_set_property (GObject *object, } static void +gtk_canvas_validate_variables (GtkCanvas *self) +{ + int i; + + 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); + } +} + +static void gtk_canvas_allocate (GtkWidget *widget, int width, int height, @@ -226,8 +240,9 @@ gtk_canvas_allocate (GtkWidget *widget, GtkCanvas *self = GTK_CANVAS (widget); gsize i; - self->viewport_size.reference.reference->width = width; - self->viewport_size.reference.reference->height = height; + gtk_canvas_validate_variables (self); + + gtk_canvas_vec2_init_constant (gtk_canvas_vec2_get_variable (&self->viewport_size), width, height); for (i = 0; i < gtk_canvas_items_get_size (&self->items); i++) { @@ -317,8 +332,7 @@ gtk_canvas_init (GtkCanvas *self) { self->item_lookup = g_hash_table_new (g_direct_hash, g_direct_equal); - gtk_canvas_size_init_reference (&self->viewport_size, - g_rc_box_new0 (graphene_size_t)); + gtk_canvas_vec2_init_variable (&self->viewport_size); } /** @@ -494,5 +508,5 @@ gtk_canvas_lookup_item (GtkCanvas *self, const GtkCanvasSize * gtk_canvas_get_viewport_size (GtkCanvas *self) { - return &self->viewport_size; + return (const GtkCanvasSize *) &self->viewport_size; } diff --git a/gtk/gtkcanvasbox.c b/gtk/gtkcanvasbox.c index 48b31fdc92..52dac1f7cc 100644 --- a/gtk/gtkcanvasbox.c +++ b/gtk/gtkcanvasbox.c @@ -31,9 +31,6 @@ #include "gtkcanvasboxprivate.h" -#include "gtkcanvaspointprivate.h" -#include "gtkcanvassizeprivate.h" - /* {{{ Boilerplate */ G_DEFINE_BOXED_TYPE (GtkCanvasBox, gtk_canvas_box, @@ -41,33 +38,28 @@ G_DEFINE_BOXED_TYPE (GtkCanvasBox, gtk_canvas_box, gtk_canvas_box_free) void -gtk_canvas_box_init (GtkCanvasBox *self, - const GtkCanvasPoint *point, - const GtkCanvasSize *size, - float origin_x, - float origin_y) +gtk_canvas_box_init (GtkCanvasBox *self, + const GtkCanvasVec2 *point, + const GtkCanvasVec2 *size, + const graphene_vec2_t *origin) { - gtk_canvas_point_init_copy (&self->point, point); - gtk_canvas_size_init_copy (&self->size, size); - self->origin_x = origin_x; - self->origin_y = origin_y; + gtk_canvas_vec2_init_copy (&self->point, point); + gtk_canvas_vec2_init_copy (&self->size, size); + graphene_vec2_init_from_vec2 (&self->origin, origin); } void gtk_canvas_box_init_copy (GtkCanvasBox *self, const GtkCanvasBox *source) { - gtk_canvas_point_init_copy (&self->point, &source->point); - gtk_canvas_size_init_copy (&self->size, &source->size); - self->origin_x = source->origin_x; - self->origin_y = source->origin_y; + gtk_canvas_box_init (self, &source->point, &source->size, &source->origin); } void gtk_canvas_box_finish (GtkCanvasBox *self) { - gtk_canvas_point_finish (&self->point); - gtk_canvas_size_finish (&self->size); + gtk_canvas_vec2_finish (&self->point); + gtk_canvas_vec2_finish (&self->size); } /** @@ -84,15 +76,23 @@ GtkCanvasBox * gtk_canvas_box_new_points (const GtkCanvasPoint *point1, const GtkCanvasPoint *point2) { - GtkCanvasSize size; + GtkCanvasVec2 size; GtkCanvasBox *result; + graphene_vec2_t minus_one; g_return_val_if_fail (point1 != NULL, NULL); g_return_val_if_fail (point2 != NULL, NULL); - gtk_canvas_size_init_distance (&size, point1, point2); - result = gtk_canvas_box_new (point1, &size, 0, 0); - gtk_canvas_size_finish (&size); + graphene_vec2_init (&minus_one, -1.f, -1.f); + gtk_canvas_vec2_init_sum (&size, + graphene_vec2_one (), + point2, + &minus_one, + point1, + NULL); + result = g_slice_new (GtkCanvasBox); + gtk_canvas_box_init (result, (GtkCanvasVec2 *) point1, &size, graphene_vec2_zero ()); + gtk_canvas_vec2_finish (&size); return result; } @@ -118,13 +118,18 @@ gtk_canvas_box_new (const GtkCanvasPoint *point, float origin_y) { GtkCanvasBox *self; + graphene_vec2_t origin; g_return_val_if_fail (point != NULL, NULL); g_return_val_if_fail (size != NULL, NULL); - self = g_slice_new (GtkCanvasBox); + graphene_vec2_init (&origin, origin_x, origin_y); - gtk_canvas_box_init (self, point, size, origin_x, origin_y); + self = g_slice_new (GtkCanvasBox); + gtk_canvas_box_init (self, + (GtkCanvasVec2 *) point, + (GtkCanvasVec2 *) size, + &origin); return self; } @@ -132,9 +137,14 @@ gtk_canvas_box_new (const GtkCanvasPoint *point, GtkCanvasBox * gtk_canvas_box_copy (const GtkCanvasBox *self) { + GtkCanvasBox *copy; + g_return_val_if_fail (self != NULL, NULL); - return gtk_canvas_box_new (&self->point, &self->size, self->origin_x, self->origin_y); + copy = g_slice_new (GtkCanvasBox); + gtk_canvas_box_init_copy (copy, self); + + return copy; } void @@ -149,15 +159,28 @@ gboolean gtk_canvas_box_eval (const GtkCanvasBox *self, graphene_rect_t *rect) { + graphene_vec2_t point, size, tmp; + g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (rect != NULL, FALSE); - if (gtk_canvas_point_eval (&self->point, &rect->origin.x, &rect->origin.y) && - gtk_canvas_size_eval (&self->size, &rect->size.width, &rect->size.height)) - return TRUE; + if (!gtk_canvas_vec2_eval (&self->point, &point) || + !gtk_canvas_vec2_eval (&self->size, &size)) + { + *rect = *graphene_rect_zero (); + return FALSE; + } + + graphene_vec2_multiply (&self->origin, &size, &tmp); + graphene_vec2_subtract (&point, &tmp, &point); + + graphene_rect_init (rect, + graphene_vec2_get_x (&point), + graphene_vec2_get_y (&point), + graphene_vec2_get_x (&size), + graphene_vec2_get_y (&size)); - *rect = *graphene_rect_zero (); - return FALSE; + return TRUE; } const GtkCanvasPoint * @@ -165,7 +188,7 @@ gtk_canvas_box_get_point (const GtkCanvasBox *self) { g_return_val_if_fail (self != NULL, NULL); - return &self->point; + return (GtkCanvasPoint *) &self->point; } const GtkCanvasSize * @@ -173,7 +196,7 @@ gtk_canvas_box_get_size (const GtkCanvasBox *self) { g_return_val_if_fail (self != NULL, NULL); - return &self->size; + return (GtkCanvasSize *) &self->size; } void @@ -184,7 +207,7 @@ gtk_canvas_box_get_origin (const GtkCanvasBox *self, g_return_if_fail (self != NULL); if (x) - *x = self->origin_x; + *x = graphene_vec2_get_x (&self->origin); if (y) - *y = self->origin_y; + *y = graphene_vec2_get_y (&self->origin); } diff --git a/gtk/gtkcanvasboxprivate.h b/gtk/gtkcanvasboxprivate.h index 82baa5fb2a..99e7e7f084 100644 --- a/gtk/gtkcanvasboxprivate.h +++ b/gtk/gtkcanvasboxprivate.h @@ -3,25 +3,22 @@ #include "gtkcanvasbox.h" -#include "gtkcanvaspointprivate.h" -#include "gtkcanvassizeprivate.h" +#include "gtkcanvasvec2private.h" G_BEGIN_DECLS struct _GtkCanvasBox { - GtkCanvasPoint point; - GtkCanvasSize size; - float origin_x; - float origin_y; + GtkCanvasVec2 point; + GtkCanvasVec2 size; + graphene_vec2_t origin; }; void gtk_canvas_box_init (GtkCanvasBox *self, - const GtkCanvasPoint *point, - const GtkCanvasSize *size, - float origin_x, - float origin_y); + const GtkCanvasVec2 *point, + const GtkCanvasVec2 *size, + const graphene_vec2_t *origin); void gtk_canvas_box_init_copy (GtkCanvasBox *self, const GtkCanvasBox *source); void gtk_canvas_box_finish (GtkCanvasBox *self); diff --git a/gtk/gtkcanvasitem.c b/gtk/gtkcanvasitem.c index 1a56374a9b..b5def0b8ba 100644 --- a/gtk/gtkcanvasitem.c +++ b/gtk/gtkcanvasitem.c @@ -23,8 +23,6 @@ #include "gtkcanvas.h" #include "gtkcanvasboxprivate.h" -#include "gtkcanvaspointprivate.h" -#include "gtkcanvassizeprivate.h" #include "gtkintl.h" #include "gtklistitemfactoryprivate.h" #include "gtkwidget.h" @@ -44,6 +42,8 @@ struct _GtkCanvasItem gpointer item; GtkWidget *widget; GtkCanvasBox bounds; + + GtkCanvasVec2 size_vecs[4]; }; enum @@ -78,6 +78,18 @@ gtk_canvas_item_dispose (GObject *object) } static void +gtk_canvas_item_finalize (GObject *object) +{ + GtkCanvasItem *self = GTK_CANVAS_ITEM (object); + int i; + + for (i = 0; i < 4; i++) + gtk_canvas_vec2_finish (&self->size_vecs[i]); + + G_OBJECT_CLASS (gtk_canvas_item_parent_class)->finalize (object); +} + +static void gtk_canvas_item_get_property (GObject *object, guint property_id, GValue *value, @@ -139,6 +151,7 @@ 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; @@ -188,14 +201,14 @@ gtk_canvas_item_class_init (GtkCanvasItemClass *klass) static void gtk_canvas_item_init (GtkCanvasItem *self) { - GtkCanvasPoint point; - GtkCanvasSize size; - - gtk_canvas_point_init (&point, 0, 0); - gtk_canvas_size_init_measure_item (&size, self, GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT); - gtk_canvas_box_init (&self->bounds, &point, &size, 0, 0); - gtk_canvas_size_finish (&size); - gtk_canvas_point_finish (&point); + int i; + + for (i = 0; i < 4; i++) + gtk_canvas_vec2_init_variable (&self->size_vecs[i]); + + gtk_canvas_vec2_init_constant (&self->bounds.point, 0, 0); + gtk_canvas_vec2_init_copy (&self->bounds.size, &self->size_vecs[GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT]); + graphene_vec2_init (&self->bounds.origin, 0, 0); } GtkCanvasItem * @@ -215,6 +228,51 @@ gtk_canvas_item_new (GtkCanvas *canvas, return self; } +void +gtk_canvas_item_validate_variables (GtkCanvasItem *self) +{ + int w[4], h[4], i; + + if (self->widget == NULL) + { + memset (w, 0, sizeof (w)); + memset (h, 0, sizeof (h)); + } + else + { + 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); + } + 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); + } + } + + for (i = 0; i < 4; i++) + { + gtk_canvas_vec2_init_constant ( + gtk_canvas_vec2_get_variable (&self->size_vecs[i]), + 0, 0); + } +} + +const GtkCanvasVec2 * +gtk_canvas_item_get_measure_vec2 (GtkCanvasItem *self, + GtkCanvasItemMeasurement measure) +{ + return &self->size_vecs[measure]; +} + /** * gtk_canvas_item_get_canvas: (attributes org.gtk.Method.get_property=canvas) * @self: a `GtkCanvasItem` diff --git a/gtk/gtkcanvasitemprivate.h b/gtk/gtkcanvasitemprivate.h index f22916e925..49724204ff 100644 --- a/gtk/gtkcanvasitemprivate.h +++ b/gtk/gtkcanvasitemprivate.h @@ -3,11 +3,18 @@ #include "gtkcanvasitem.h" +#include "gtkcanvassize.h" +#include "gtkcanvasvec2private.h" + G_BEGIN_DECLS GtkCanvasItem * gtk_canvas_item_new (GtkCanvas *canvas, gpointer item); +void gtk_canvas_item_validate_variables (GtkCanvasItem *self); +const GtkCanvasVec2 * gtk_canvas_item_get_measure_vec2 (GtkCanvasItem *self, + GtkCanvasItemMeasurement measure); + void gtk_canvas_item_clear_canvas (GtkCanvasItem *self); void gtk_canvas_item_setup (GtkCanvasItem *self, diff --git a/gtk/gtkcanvaspoint.c b/gtk/gtkcanvaspoint.c index df812b5cf4..e5536ebc7a 100644 --- a/gtk/gtkcanvaspoint.c +++ b/gtk/gtkcanvaspoint.c @@ -26,121 +26,24 @@ #include "config.h" -#include "gtkcanvaspointprivate.h" +#include "gtkcanvaspoint.h" -#include "gtkcanvasbox.h" - -/* {{{ Boilerplate */ - -struct _GtkCanvasPointClass -{ - const char *type_name; - - void (* copy) (GtkCanvasPoint *self, - const GtkCanvasPoint *source); - void (* finish) (GtkCanvasPoint *self); - gboolean (* eval) (const GtkCanvasPoint *self, - float *x, - float *y); -}; +#include "gtkcanvasboxprivate.h" +#include "gtkcanvasvec2private.h" G_DEFINE_BOXED_TYPE (GtkCanvasPoint, gtk_canvas_point, gtk_canvas_point_copy, gtk_canvas_point_free) -static gpointer -gtk_canvas_point_alloc (const GtkCanvasPointClass *class) -{ - GtkCanvasPoint *self = g_slice_new (GtkCanvasPoint); - - self->class = class; - - return self; -} - -void -gtk_canvas_point_init_copy (GtkCanvasPoint *self, - const GtkCanvasPoint *source) -{ - self->class = source->class; - self->class->copy (self, source); -} - -void -gtk_canvas_point_finish (GtkCanvasPoint *self) -{ - self->class->finish (self); -} - -/* }}} */ -/* {{{ OFFSET */ - -static void -gtk_canvas_point_offset_copy (GtkCanvasPoint *point, - const GtkCanvasPoint *source_point) +struct _GtkCanvasPoint { - GtkCanvasPointOffset *self = &point->offset; - const GtkCanvasPointOffset *source = &source_point->offset; - - *self = *source; - - if (source->other) - self->other = gtk_canvas_point_copy (source->other); -} - -static void -gtk_canvas_point_offset_finish (GtkCanvasPoint *point) -{ - GtkCanvasPointOffset *self = &point->offset; - - if (self->other) - gtk_canvas_point_free (self->other); -} - -static gboolean -gtk_canvas_point_offset_eval (const GtkCanvasPoint *point, - float *x, - float *y) -{ - const GtkCanvasPointOffset *self = &point->offset; - - if (self->other != NULL) - { - if (!gtk_canvas_point_eval (self->other, x, y)) - return FALSE; - - *x += self->dx; - *y += self->dy; - } - else - { - *x = self->dx; - *y = self->dy; - } - - return TRUE; -} - -static const GtkCanvasPointClass GTK_CANVAS_POINT_OFFSET_CLASS = -{ - "GtkCanvasPointOffset", - gtk_canvas_point_offset_copy, - gtk_canvas_point_offset_finish, - gtk_canvas_point_offset_eval, + GtkCanvasVec2 vec2; }; -void -gtk_canvas_point_init (GtkCanvasPoint *point, - float x, - float y) +static GtkCanvasPoint * +gtk_canvas_point_alloc (void) { - GtkCanvasPointOffset *self = &point->offset; - - self->class = >K_CANVAS_POINT_OFFSET_CLASS; - - self->other = NULL; - self->dx = x; - self->dy = y; + return g_slice_new (GtkCanvasPoint); } /** @@ -158,68 +61,17 @@ gtk_canvas_point_new (float x, { GtkCanvasPoint *self; - self = gtk_canvas_point_alloc (>K_CANVAS_POINT_OFFSET_CLASS); - - gtk_canvas_point_init (self, x, y); + self = gtk_canvas_point_alloc (); + gtk_canvas_vec2_init_constant (&self->vec2, x, y); return self; } -/* }}} */ -/* {{{ BOX */ - -static void -gtk_canvas_point_box_copy (GtkCanvasPoint *point, - const GtkCanvasPoint *source_point) -{ - GtkCanvasPointBox *self = &point->box; - const GtkCanvasPointBox *source = &source_point->box; - - *self = *source; - - self->box = gtk_canvas_box_copy (source->box); -} - -static void -gtk_canvas_point_box_finish (GtkCanvasPoint *point) -{ - GtkCanvasPointBox *self = &point->box; - - gtk_canvas_box_free (self->box); -} - -static gboolean -gtk_canvas_point_box_eval (const GtkCanvasPoint *point, - float *x, - float *y) -{ - const GtkCanvasPointBox *self = &point->box; - graphene_rect_t rect; - - if (!gtk_canvas_box_eval (self->box, &rect)) - return FALSE; - - *x = rect.origin.x + self->offset_x + self->origin_x * rect.size.width; - *y = rect.origin.y + self->offset_y + self->origin_y * rect.size.height; - - return TRUE; -} - -static const GtkCanvasPointClass GTK_CANVAS_POINT_BOX_CLASS = -{ - "GtkCanvasPointBox", - gtk_canvas_point_box_copy, - gtk_canvas_point_box_finish, - gtk_canvas_point_box_eval, -}; - /** * gtk_canvas_point_new_from_box: * @box: a box * @origin_x: x coordinate of box origin * @origin_y: y coordinate of box origin - * @offset_x: offset in x direction - * @offset_y: offset in y direction * * Creates a point relative to the given box. * @@ -227,35 +79,31 @@ static const GtkCanvasPointClass GTK_CANVAS_POINT_BOX_CLASS = * (0, 0) being the top left and (1, 1) being the bottom right * corner of the box. * - * The offset is then added to the origin. It may be negative. - * * Returns: a new point **/ GtkCanvasPoint * gtk_canvas_point_new_from_box (const GtkCanvasBox *box, float origin_x, - float origin_y, - float offset_x, - float offset_y) + float origin_y) { - GtkCanvasPointBox *self; - + GtkCanvasPoint *self; + graphene_vec2_t origin; + g_return_val_if_fail (box != NULL, NULL); - - self = gtk_canvas_point_alloc (>K_CANVAS_POINT_BOX_CLASS); - - self->box = gtk_canvas_box_copy (box); - self->origin_x = origin_x; - self->origin_y = origin_y; - self->offset_x = offset_x; - self->offset_y = offset_y; - - return (GtkCanvasPoint *) self; + + graphene_vec2_init (&origin, origin_x, origin_y); + graphene_vec2_subtract (&origin, &box->origin, &origin); + + self = gtk_canvas_point_alloc (); + gtk_canvas_vec2_init_sum (&self->vec2, + graphene_vec2_one (), + &box->point, + &origin, + &box->size, + NULL); + return self; } -/* }}} */ -/* {{{ PUBLIC API */ - GtkCanvasPoint * gtk_canvas_point_copy (const GtkCanvasPoint *self) { @@ -263,9 +111,8 @@ gtk_canvas_point_copy (const GtkCanvasPoint *self) g_return_val_if_fail (self != NULL, NULL); - copy = gtk_canvas_point_alloc (self->class); - - gtk_canvas_point_init_copy (copy, self); + copy = gtk_canvas_point_alloc (); + gtk_canvas_vec2_init_copy (©->vec2, &self->vec2); return copy; } @@ -273,7 +120,7 @@ gtk_canvas_point_copy (const GtkCanvasPoint *self) void gtk_canvas_point_free (GtkCanvasPoint *self) { - gtk_canvas_point_finish (self); + gtk_canvas_vec2_finish (&self->vec2); g_slice_free (GtkCanvasPoint, self); } @@ -283,15 +130,21 @@ gtk_canvas_point_eval (const GtkCanvasPoint *self, float *x, float *y) { + graphene_vec2_t vec2; + g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (x != NULL, FALSE); g_return_val_if_fail (y != NULL, FALSE); - if (self->class->eval (self, x, y)) - return TRUE; + if (!gtk_canvas_vec2_eval (&self->vec2, &vec2)) + { + *x = 0; + *y = 0; + return FALSE; + } - *x = 0; - *y = 0; - return FALSE; + *x = graphene_vec2_get_x (&vec2); + *y = graphene_vec2_get_y (&vec2); + return TRUE; } diff --git a/gtk/gtkcanvaspoint.h b/gtk/gtkcanvaspoint.h index 5a35ba3423..f59db58e1a 100644 --- a/gtk/gtkcanvaspoint.h +++ b/gtk/gtkcanvaspoint.h @@ -50,9 +50,7 @@ GtkCanvasPoint * gtk_canvas_point_new (float GDK_AVAILABLE_IN_ALL GtkCanvasPoint * gtk_canvas_point_new_from_box (const GtkCanvasBox *box, float origin_x, - float origin_y, - float offset_x, - float offset_y); + float origin_y); GDK_AVAILABLE_IN_ALL GtkCanvasPoint * gtk_canvas_point_new_from_item (GtkCanvasItem *item, float origin_x, diff --git a/gtk/gtkcanvaspointprivate.h b/gtk/gtkcanvaspointprivate.h deleted file mode 100644 index 1d10efa6b3..0000000000 --- a/gtk/gtkcanvaspointprivate.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __GTK_CANVAS_POINT_PRIVATE_H__ -#define __GTK_CANVAS_POINT_PRIVATE_H__ - -#include "gtkcanvaspoint.h" - -G_BEGIN_DECLS - -typedef struct _GtkCanvasPointClass GtkCanvasPointClass; -typedef struct _GtkCanvasPointBox GtkCanvasPointBox; -typedef struct _GtkCanvasPointItem GtkCanvasPointItem; -typedef struct _GtkCanvasPointOffset GtkCanvasPointOffset; - -struct _GtkCanvasPointBox -{ - const GtkCanvasPointClass *class; - - GtkCanvasBox *box; - float origin_x; - float origin_y; - float offset_x; - float offset_y; -}; - -struct _GtkCanvasPointOffset -{ - const GtkCanvasPointClass *class; - - GtkCanvasPoint *other; - float dx; - float dy; -}; - -struct _GtkCanvasPoint -{ - union { - const GtkCanvasPointClass *class; - GtkCanvasPointBox box; - GtkCanvasPointOffset offset; - }; -}; - - -void gtk_canvas_point_init (GtkCanvasPoint * point, - float x, - float y); -void gtk_canvas_point_init_copy (GtkCanvasPoint *self, - const GtkCanvasPoint *source); -void gtk_canvas_point_finish (GtkCanvasPoint *self); - -G_END_DECLS - -#endif /* __GTK_CANVAS_POINT_PRIVATE_H__ */ diff --git a/gtk/gtkcanvassize.c b/gtk/gtkcanvassize.c index 81fcba2d19..a706def6af 100644 --- a/gtk/gtkcanvassize.c +++ b/gtk/gtkcanvassize.c @@ -26,94 +26,28 @@ #include "config.h" -#include "gtkcanvassizeprivate.h" +#include "gtkcanvassize.h" -#include "gtkcanvasbox.h" -#include "gtkcanvasitem.h" +#include "gtkcanvasboxprivate.h" +#include "gtkcanvasitemprivate.h" #include "gtkcanvaspoint.h" -#include "gtkwidget.h" - -/* {{{ Boilerplate */ - -struct _GtkCanvasSizeClass -{ - const char *type_name; - - void (* copy) (GtkCanvasSize *self, - const GtkCanvasSize *source); - void (* finish) (GtkCanvasSize *self); - gboolean (* eval) (const GtkCanvasSize *self, - float *width, - float *height); -}; +#include "gtkcanvasvec2private.h" G_DEFINE_BOXED_TYPE (GtkCanvasSize, gtk_canvas_size, gtk_canvas_size_copy, gtk_canvas_size_free) -static gpointer -gtk_canvas_size_alloc (const GtkCanvasSizeClass *class) -{ - GtkCanvasSize *self = g_slice_new (GtkCanvasSize); - - self->class = class; - - return self; -} - -void -gtk_canvas_size_init_copy (GtkCanvasSize *self, - const GtkCanvasSize *source) -{ - self->class = source->class; - self->class->copy (self, source); -} - -void -gtk_canvas_size_finish (GtkCanvasSize *self) -{ - self->class->finish (self); -} - -/* }}} */ -/* {{{ ABSOLUTE */ - -static void -gtk_canvas_size_absolute_copy (GtkCanvasSize *size, - const GtkCanvasSize *source_size) +struct _GtkCanvasSize { - GtkCanvasSizeAbsolute *self = &size->absolute; - const GtkCanvasSizeAbsolute *source = &source_size->absolute; - - *self = *source; -} - -static void -gtk_canvas_size_absolute_finish (GtkCanvasSize *size) -{ -} + GtkCanvasVec2 vec2; +}; -static gboolean -gtk_canvas_size_absolute_eval (const GtkCanvasSize *size, - float *width, - float *height) +static GtkCanvasSize * +gtk_canvas_size_alloc (void) { - const GtkCanvasSizeAbsolute *self = &size->absolute; - - *width = self->width; - *height = self->height; - - return TRUE; + return g_slice_new (GtkCanvasSize); } -static const GtkCanvasSizeClass GTK_CANVAS_SIZE_ABSOLUTE_CLASS = -{ - "GtkCanvasSizeAbsolute", - gtk_canvas_size_absolute_copy, - gtk_canvas_size_absolute_finish, - gtk_canvas_size_absolute_eval, -}; - /** * gtk_canvas_size_new: * @width: width of the size @@ -127,63 +61,14 @@ GtkCanvasSize * gtk_canvas_size_new (float width, float height) { - GtkCanvasSizeAbsolute *self; - - self = gtk_canvas_size_alloc (>K_CANVAS_SIZE_ABSOLUTE_CLASS); - self->width = width; - self->height = height; - - return (GtkCanvasSize *) self; -} - -/* }}} */ -/* {{{ BOX */ - -static void -gtk_canvas_size_box_copy (GtkCanvasSize *size, - const GtkCanvasSize *source_size) -{ - GtkCanvasSizeBox *self = &size->box; - const GtkCanvasSizeBox *source = &source_size->box; - - *self = *source; - - self->box = gtk_canvas_box_copy (source->box); -} - -static void -gtk_canvas_size_box_finish (GtkCanvasSize *size) -{ - GtkCanvasSizeBox *self = &size->box; - - gtk_canvas_box_free (self->box); -} - -static gboolean -gtk_canvas_size_box_eval (const GtkCanvasSize *size, - float *width, - float *height) -{ - const GtkCanvasSizeBox *self = &size->box; - graphene_rect_t rect; - - if (!gtk_canvas_box_eval (self->box, &rect)) - return FALSE; + GtkCanvasSize *self; - *width = rect.size.width; - *height = rect.size.height; + self = gtk_canvas_size_alloc (); + gtk_canvas_vec2_init_constant (&self->vec2, width, height); - return TRUE; + return self; } -static const GtkCanvasSizeClass GTK_CANVAS_SIZE_BOX_CLASS = -{ - "GtkCanvasSizeBox", - gtk_canvas_size_box_copy, - gtk_canvas_size_box_finish, - gtk_canvas_size_box_eval, -}; - /** * gtk_canvas_size_new_from_box: * @box: a box @@ -195,76 +80,12 @@ static const GtkCanvasSizeClass GTK_CANVAS_SIZE_BOX_CLASS = GtkCanvasSize * gtk_canvas_size_new_from_box (const GtkCanvasBox *box) { - GtkCanvasSizeBox *self; - - g_return_val_if_fail (box != NULL, NULL); - - self = gtk_canvas_size_alloc (>K_CANVAS_SIZE_BOX_CLASS); - - /* FIXME: We could potentially just copy the box's size here */ - self->box = gtk_canvas_box_copy (box); - - return (GtkCanvasSize *) self; -} - -/* }}} */ -/* {{{ DISTANCE */ - -static void -gtk_canvas_size_distance_copy (GtkCanvasSize *size, - const GtkCanvasSize *source_size) -{ - const GtkCanvasSizeDistance *source = &source_size->distance; - - gtk_canvas_size_init_distance (size, source->from, source->to); -} - -static void -gtk_canvas_size_distance_finish (GtkCanvasSize *size) -{ - GtkCanvasSizeDistance *self = &size->distance; - - gtk_canvas_point_free (self->from); - gtk_canvas_point_free (self->to); -} - -static gboolean -gtk_canvas_size_distance_eval (const GtkCanvasSize *size, - float *width, - float *height) -{ - const GtkCanvasSizeDistance *self = &size->distance; - float x1, y1, x2, y2; - - if (!gtk_canvas_point_eval (self->from, &x1, &y1) || - !gtk_canvas_point_eval (self->from, &x2, &y2)) - return FALSE; - - *width = x1 - x2; - *height = y1 - y2; - - return TRUE; -} - -static const GtkCanvasSizeClass GTK_CANVAS_SIZE_DISTANCE_CLASS = -{ - "GtkCanvasSizeDistance", - gtk_canvas_size_distance_copy, - gtk_canvas_size_distance_finish, - gtk_canvas_size_distance_eval, -}; + GtkCanvasSize *self; -void -gtk_canvas_size_init_distance (GtkCanvasSize *size, - const GtkCanvasPoint *from, - const GtkCanvasPoint *to) -{ - GtkCanvasSizeDistance *self = &size->distance; - - self->class = >K_CANVAS_SIZE_DISTANCE_CLASS; + self = gtk_canvas_size_alloc (); + gtk_canvas_vec2_init_copy (&self->vec2, &box->size); - self->from = gtk_canvas_point_copy (from); - self->to = gtk_canvas_point_copy (to); + return self; } /** @@ -273,7 +94,8 @@ gtk_canvas_size_init_distance (GtkCanvasSize *size, * @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 @to is smaller than @from in the corresponding dimension. + * can be negative if the coordinate of @to is smaller than @from in the + * corresponding dimension. * * Returns: a new size **/ @@ -282,134 +104,24 @@ gtk_canvas_size_new_distance (const GtkCanvasPoint *from, const GtkCanvasPoint *to) { GtkCanvasSize *self; + graphene_vec2_t minus_one; g_return_val_if_fail (from != NULL, NULL); g_return_val_if_fail (to != NULL, NULL); - self = gtk_canvas_size_alloc (>K_CANVAS_SIZE_DISTANCE_CLASS); + graphene_vec2_init (&minus_one, -1.f, -1.f); - gtk_canvas_size_init_distance (self, from, to); + self = gtk_canvas_size_alloc (); + gtk_canvas_vec2_init_sum (&self->vec2, + graphene_vec2_one (), + from, + &minus_one, + to, + NULL); return self; } -/* }}} */ -/* {{{ MEASURE */ - -static void -gtk_canvas_size_measure_copy (GtkCanvasSize *size, - const GtkCanvasSize *source_size) -{ - const GtkCanvasSizeMeasure *source = &source_size->measure; - - gtk_canvas_size_init_measure_item (size, source->item, source->measure); -} - -static void -gtk_canvas_size_measure_finish (GtkCanvasSize *size) -{ -} - -static gboolean -gtk_canvas_size_measure_eval (const GtkCanvasSize *size, - float *width, - float *height) -{ - const GtkCanvasSizeMeasure *self = &size->measure; - GtkWidget *widget; - int w, h; - - if (self->item == NULL) - return FALSE; - - widget = gtk_canvas_item_get_widget (self->item); - if (widget == NULL) - { - *width = 0; - *height = 0; - return TRUE; - } - - if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) - { - switch (self->measure) - { - case GTK_CANVAS_ITEM_MEASURE_MIN_FOR_MIN: - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, &w, NULL, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL); - break; - case GTK_CANVAS_ITEM_MEASURE_MIN_FOR_NAT: - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, NULL, &w, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, w, &h, NULL, NULL, NULL); - break; - case GTK_CANVAS_ITEM_MEASURE_NAT_FOR_MIN: - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, &w, NULL, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, w, NULL, &h, NULL, NULL); - break; - case GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT: - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, NULL, &w, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, w, NULL, &h, NULL, NULL); - break; - default: - g_assert_not_reached (); - w = h = 0; - break; - } - } - else - { - switch (self->measure) - { - case GTK_CANVAS_ITEM_MEASURE_MIN_FOR_MIN: - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL); - break; - case GTK_CANVAS_ITEM_MEASURE_MIN_FOR_NAT: - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, -1, NULL, &h, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, h, &w, NULL, NULL, NULL); - break; - case GTK_CANVAS_ITEM_MEASURE_NAT_FOR_MIN: - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, -1, &h, NULL, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, h, NULL, &w, NULL, NULL); - break; - case GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT: - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, -1, NULL, &h, NULL, NULL); - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, h, NULL, &w, NULL, NULL); - break; - default: - g_assert_not_reached (); - w = h = 0; - break; - } - } - - *width = w; - *height = h; - - return TRUE; -} - -static const GtkCanvasSizeClass GTK_CANVAS_SIZE_MEASURE_CLASS = -{ - "GtkCanvasSizeMeasure", - gtk_canvas_size_measure_copy, - gtk_canvas_size_measure_finish, - gtk_canvas_size_measure_eval, -}; - -void -gtk_canvas_size_init_measure_item (GtkCanvasSize *size, - GtkCanvasItem *item, - GtkCanvasItemMeasurement measure) -{ - GtkCanvasSizeMeasure *self = &size->measure; - - self->class = >K_CANVAS_SIZE_MEASURE_CLASS; - - self->item = item; - self->measure = measure; -} - /** * gtk_canvas_size_new_measure_item: * @item: the item @@ -428,68 +140,13 @@ gtk_canvas_size_new_measure_item (GtkCanvasItem *item, g_return_val_if_fail (GTK_IS_CANVAS_ITEM (item), NULL); - self = gtk_canvas_size_alloc (>K_CANVAS_SIZE_MEASURE_CLASS); - - gtk_canvas_size_init_measure_item (self, item, measure); + self = gtk_canvas_size_alloc (); + gtk_canvas_vec2_init_copy (&self->vec2, + gtk_canvas_item_get_measure_vec2 (item, measure)); return self; } -/* }}} */ -/* {{{ REFERENCE */ - -static void -gtk_canvas_size_reference_copy (GtkCanvasSize *size, - const GtkCanvasSize *source_size) -{ - const GtkCanvasSizeReference *source = &source_size->reference; - - gtk_canvas_size_init_reference (size, g_rc_box_acquire (source->reference)); -} - -static void -gtk_canvas_size_reference_finish (GtkCanvasSize *size) -{ - const GtkCanvasSizeReference *self = &size->reference; - - g_rc_box_release (self->reference); -} - -static gboolean -gtk_canvas_size_reference_eval (const GtkCanvasSize *size, - float *width, - float *height) -{ - const GtkCanvasSizeReference *self = &size->reference; - - *width = self->reference->width; - *height = self->reference->height; - - return TRUE; -} - -static const GtkCanvasSizeClass GTK_CANVAS_SIZE_REFERENCE_CLASS = -{ - "GtkCanvasSizeReference", - gtk_canvas_size_reference_copy, - gtk_canvas_size_reference_finish, - gtk_canvas_size_reference_eval, -}; - -void -gtk_canvas_size_init_reference (GtkCanvasSize *size, - graphene_size_t *reference) -{ - GtkCanvasSizeReference *self = &size->reference; - - self->class = >K_CANVAS_SIZE_REFERENCE_CLASS; - - self->reference = reference; -} - -/* }}} */ -/* {{{ PUBLIC API */ - GtkCanvasSize * gtk_canvas_size_copy (const GtkCanvasSize *self) { @@ -497,9 +154,8 @@ gtk_canvas_size_copy (const GtkCanvasSize *self) g_return_val_if_fail (self != NULL, NULL); - copy = gtk_canvas_size_alloc (self->class); - - gtk_canvas_size_init_copy (copy, self); + copy = gtk_canvas_size_alloc (); + gtk_canvas_vec2_init_copy (©->vec2, &self->vec2); return copy; } @@ -507,7 +163,9 @@ gtk_canvas_size_copy (const GtkCanvasSize *self) void gtk_canvas_size_free (GtkCanvasSize *self) { - gtk_canvas_size_finish (self); + g_return_if_fail (self != NULL); + + gtk_canvas_vec2_finish (&self->vec2); g_slice_free (GtkCanvasSize, self); } @@ -517,15 +175,21 @@ gtk_canvas_size_eval (const GtkCanvasSize *self, float *width, float *height) { + graphene_vec2_t vec2; + g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (width != NULL, FALSE); g_return_val_if_fail (height != NULL, FALSE); - if (self->class->eval (self, width, height)) - return TRUE; + if (!gtk_canvas_vec2_eval (&self->vec2, &vec2)) + { + *width = 0; + *height = 0; + return FALSE; + } - *width = 0; - *height = 0; - return FALSE; + *width = graphene_vec2_get_x (&vec2); + *height = graphene_vec2_get_y (&vec2); + return TRUE; } diff --git a/gtk/gtkcanvassizeprivate.h b/gtk/gtkcanvassizeprivate.h deleted file mode 100644 index fa8dd4cc6b..0000000000 --- a/gtk/gtkcanvassizeprivate.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef __GTK_CANVAS_SIZE_PRIVATE_H__ -#define __GTK_CANVAS_SIZE_PRIVATE_H__ - -#include "gtkcanvassize.h" - -#include <graphene.h> - -G_BEGIN_DECLS - -typedef struct _GtkCanvasSizeClass GtkCanvasSizeClass; -typedef struct _GtkCanvasSizeAbsolute GtkCanvasSizeAbsolute; -typedef struct _GtkCanvasSizeBox GtkCanvasSizeBox; -typedef struct _GtkCanvasSizeDistance GtkCanvasSizeDistance; -typedef struct _GtkCanvasSizeMeasure GtkCanvasSizeMeasure; -typedef struct _GtkCanvasSizeReference GtkCanvasSizeReference; - -struct _GtkCanvasSizeAbsolute -{ - const GtkCanvasSizeClass *class; - - float width; - float height; -}; - -struct _GtkCanvasSizeBox -{ - const GtkCanvasSizeClass *class; - - GtkCanvasBox *box; -}; - -struct _GtkCanvasSizeDistance -{ - const GtkCanvasSizeClass *class; - - GtkCanvasPoint *from; - GtkCanvasPoint *to; -}; - -struct _GtkCanvasSizeMeasure -{ - const GtkCanvasSizeClass *class; - - GtkCanvasItem *item; - GtkCanvasItemMeasurement measure; -}; - -struct _GtkCanvasSizeReference -{ - const GtkCanvasSizeClass *class; - - graphene_size_t *reference; -}; - -struct _GtkCanvasSize -{ - union { - const GtkCanvasSizeClass *class; - GtkCanvasSizeAbsolute absolute; - GtkCanvasSizeBox box; - GtkCanvasSizeDistance distance; - GtkCanvasSizeMeasure measure; - GtkCanvasSizeReference reference; - }; -}; - - -void gtk_canvas_size_init_distance (GtkCanvasSize *size, - const GtkCanvasPoint *from, - const GtkCanvasPoint *to); -void gtk_canvas_size_init_measure_item (GtkCanvasSize *self, - GtkCanvasItem *item, - GtkCanvasItemMeasurement measure); -void gtk_canvas_size_init_copy (GtkCanvasSize *self, - const GtkCanvasSize *source); -void gtk_canvas_size_finish (GtkCanvasSize *self); - -/* NB: Takes ownership of reference */ -void gtk_canvas_size_init_reference (GtkCanvasSize *size, - graphene_size_t *reference); - -G_END_DECLS - -#endif /* __GTK_CANVAS_SIZE_PRIVATE_H__ */ diff --git a/gtk/gtkcanvasvec2.c b/gtk/gtkcanvasvec2.c new file mode 100644 index 0000000000..dfba1b10b0 --- /dev/null +++ b/gtk/gtkcanvasvec2.c @@ -0,0 +1,343 @@ +/* + * 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> + */ + + +/** + * GtkCanvasVec2: + * + * `GtkCanvasVec2` describes a vec2 in a `GtkCanvas`. + */ + +#include "config.h" + +#include "gtkcanvasvec2private.h" + +/* {{{ Boilerplate */ + +struct _GtkCanvasVec2Class +{ + const char *type_name; + + void (* copy) (GtkCanvasVec2 *self, + const GtkCanvasVec2 *source); + void (* finish) (GtkCanvasVec2 *self); + gboolean (* eval) (const GtkCanvasVec2 *self, + graphene_vec2_t *result); +}; + +/* }}} */ +/* {{{ INVALID */ + +static void +gtk_canvas_vec2_invalid_copy (GtkCanvasVec2 *vec2, + const GtkCanvasVec2 *source_vec2) +{ + gtk_canvas_vec2_init_invalid (vec2); +} + +static void +gtk_canvas_vec2_invalid_finish (GtkCanvasVec2 *vec2) +{ +} + +static gboolean +gtk_canvas_vec2_invalid_eval (const GtkCanvasVec2 *vec2, + graphene_vec2_t *result) +{ + return FALSE; +} + +static const GtkCanvasVec2Class GTK_CANVAS_VEC2_INVALID_CLASS = +{ + "GtkCanvasVec2Invalid", + gtk_canvas_vec2_invalid_copy, + gtk_canvas_vec2_invalid_finish, + gtk_canvas_vec2_invalid_eval, +}; + +void +gtk_canvas_vec2_init_invalid (GtkCanvasVec2 *vec2) +{ + vec2->class = >K_CANVAS_VEC2_INVALID_CLASS; +} + +/* }}} */ +/* {{{ CONSTANT */ + +static void +gtk_canvas_vec2_constant_copy (GtkCanvasVec2 *vec2, + const GtkCanvasVec2 *source_vec2) +{ + const GtkCanvasVec2Constant *source = &source_vec2->constant; + + gtk_canvas_vec2_init_constant_from_vec2 (vec2, &source->value); +} + +static void +gtk_canvas_vec2_constant_finish (GtkCanvasVec2 *vec2) +{ +} + +static gboolean +gtk_canvas_vec2_constant_eval (const GtkCanvasVec2 *vec2, + graphene_vec2_t *result) +{ + const GtkCanvasVec2Constant *self = &vec2->constant; + + graphene_vec2_init_from_vec2 (result, &self->value); + + return TRUE; +} + +static const GtkCanvasVec2Class GTK_CANVAS_VEC2_CONSTANT_CLASS = +{ + "GtkCanvasVec2Constant", + gtk_canvas_vec2_constant_copy, + gtk_canvas_vec2_constant_finish, + gtk_canvas_vec2_constant_eval, +}; + +void +gtk_canvas_vec2_init_constant_from_vec2 (GtkCanvasVec2 *vec2, + const graphene_vec2_t *value) +{ + GtkCanvasVec2Constant *self = &vec2->constant; + + self->class = >K_CANVAS_VEC2_CONSTANT_CLASS; + graphene_vec2_init_from_vec2 (&self->value, value); +} + +void +gtk_canvas_vec2_init_constant (GtkCanvasVec2 *vec2, + float x, + float y) +{ + graphene_vec2_t v; + + graphene_vec2_init (&v, x, y); + gtk_canvas_vec2_init_constant_from_vec2 (vec2, &v); +} + +/* }}} */ +/* {{{ SUM */ + +static void +gtk_canvas_vec2_sum_copy (GtkCanvasVec2 *vec2, + const GtkCanvasVec2 *source_vec2); + +static void +gtk_canvas_vec2_sum_finish (GtkCanvasVec2 *vec2) +{ + GtkCanvasVec2Sum *self = &vec2->sum; + gsize i; + + for (i = 0; i < self->n_summands; i++) + { + gtk_canvas_vec2_finish (&self->summands[i].value); + } + + g_free (self->summands); +} + +static gboolean +gtk_canvas_vec2_sum_eval (const GtkCanvasVec2 *vec2, + graphene_vec2_t *result) +{ + const GtkCanvasVec2Sum *self = &vec2->sum; + gsize i; + + if (!gtk_canvas_vec2_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_vec2_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 GtkCanvasVec2Class GTK_CANVAS_VEC2_SUM_CLASS = +{ + "GtkCanvasVec2Sum", + gtk_canvas_vec2_sum_copy, + gtk_canvas_vec2_sum_finish, + gtk_canvas_vec2_sum_eval, +}; + +static void +gtk_canvas_vec2_sum_copy (GtkCanvasVec2 *vec2, + const GtkCanvasVec2 *source_vec2) +{ + GtkCanvasVec2Sum *self = &vec2->sum; + const GtkCanvasVec2Sum *source = &source_vec2->sum; + gsize i; + + self->class = >K_CANVAS_VEC2_SUM_CLASS; + self->summands = g_new (GtkCanvasVec2Summand, 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_vec2_init_copy (&self->summands[i].value, + &source->summands[i].value); + } + +} + +void +gtk_canvas_vec2_init_sum (GtkCanvasVec2 *vec2, + const graphene_vec2_t *scale, + ...) +{ + GtkCanvasVec2Sum *self = &vec2->sum; + GArray *array; + GtkCanvasVec2Summand summand; + va_list args; + + g_assert (scale != NULL); + + self->class = >K_CANVAS_VEC2_SUM_CLASS; + + array = g_array_new (FALSE, FALSE, sizeof (GtkCanvasVec2Summand)); + va_start (args, scale); + + while (scale) + { + graphene_vec2_init_from_vec2 (&summand.scale, scale); + gtk_canvas_vec2_init_copy (&summand.value, va_arg (args, const GtkCanvasVec2 *)); + g_array_append_val (array, summand); + scale = va_arg (args, const graphene_vec2_t *); + } + va_end (args); + + self->n_summands = array->len; + self->summands = (GtkCanvasVec2Summand *) g_array_free (array, FALSE); +} + +/* }}} */ +/* {{{ VARIABLE */ + +static void +gtk_canvas_vec2_init_variable_with_variable (GtkCanvasVec2 *vec2, + GtkCanvasVec2 *variable); + +static void +gtk_canvas_vec2_variable_copy (GtkCanvasVec2 *vec2, + const GtkCanvasVec2 *source_vec2) +{ + const GtkCanvasVec2Variable *source = &source_vec2->variable; + + gtk_canvas_vec2_init_variable_with_variable (vec2, g_rc_box_acquire (source->variable)); +} + +static void +gtk_canvas_vec2_variable_finish (GtkCanvasVec2 *vec2) +{ + const GtkCanvasVec2Variable *self = &vec2->variable; + + g_rc_box_release (self->variable); +} + +static gboolean +gtk_canvas_vec2_variable_eval (const GtkCanvasVec2 *vec2, + graphene_vec2_t *result) +{ + const GtkCanvasVec2Variable *self = &vec2->variable; + + return gtk_canvas_vec2_eval (self->variable, result); +} + +static const GtkCanvasVec2Class GTK_CANVAS_VEC2_VARIABLE_CLASS = +{ + "GtkCanvasVec2Variable", + gtk_canvas_vec2_variable_copy, + gtk_canvas_vec2_variable_finish, + gtk_canvas_vec2_variable_eval, +}; + +static void +gtk_canvas_vec2_init_variable_with_variable (GtkCanvasVec2 *vec2, + GtkCanvasVec2 *variable) +{ + GtkCanvasVec2Variable *self = &vec2->variable; + + self->class = >K_CANVAS_VEC2_VARIABLE_CLASS; + + self->variable = variable; +} + +void +gtk_canvas_vec2_init_variable (GtkCanvasVec2 *vec2) +{ + GtkCanvasVec2 *variable; + + variable = g_rc_box_new (GtkCanvasVec2); + gtk_canvas_vec2_init_invalid (variable); + + gtk_canvas_vec2_init_variable_with_variable (vec2, variable); +} + +GtkCanvasVec2 * +gtk_canvas_vec2_get_variable (GtkCanvasVec2 *vec2) +{ + GtkCanvasVec2Variable *self = &vec2->variable; + + g_return_val_if_fail (self->class == >K_CANVAS_VEC2_VARIABLE_CLASS, NULL); + + return self->variable; +} + +/* }}} */ +/* {{{ PUBLIC API */ + +void +gtk_canvas_vec2_init_copy (GtkCanvasVec2 *self, + const GtkCanvasVec2 *source) +{ + source->class->copy (self, source); +} + +void +gtk_canvas_vec2_finish (GtkCanvasVec2 *self) +{ + self->class->finish (self); +} + +gboolean +gtk_canvas_vec2_eval (const GtkCanvasVec2 *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; +} + diff --git a/gtk/gtkcanvasvec2private.h b/gtk/gtkcanvasvec2private.h new file mode 100644 index 0000000000..b8ad4875b8 --- /dev/null +++ b/gtk/gtkcanvasvec2private.h @@ -0,0 +1,99 @@ +/* + * 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_VEC2_PRIVATE_H__ +#define __GTK_CANVAS_VEC2_PRIVATE_H__ + +#include <glib.h> +#include <graphene.h> + +G_BEGIN_DECLS + +typedef struct _GtkCanvasVec2 GtkCanvasVec2; +typedef struct _GtkCanvasVec2Class GtkCanvasVec2Class; +typedef struct _GtkCanvasVec2Constant GtkCanvasVec2Constant; +typedef struct _GtkCanvasVec2Sum GtkCanvasVec2Sum; +typedef struct _GtkCanvasVec2Summand GtkCanvasVec2Summand; +typedef struct _GtkCanvasVec2Variable GtkCanvasVec2Variable; + +struct _GtkCanvasVec2Constant +{ + const GtkCanvasVec2Class *class; + + graphene_vec2_t value; +}; + +struct _GtkCanvasVec2Sum +{ + const GtkCanvasVec2Class *class; + + graphene_vec2_t constant; + + gsize n_summands; + GtkCanvasVec2Summand *summands; +}; + +struct _GtkCanvasVec2Variable +{ + const GtkCanvasVec2Class *class; + + /* a GtkRcBox */ + GtkCanvasVec2 *variable; +}; + +struct _GtkCanvasVec2 +{ + union { + const GtkCanvasVec2Class *class; + GtkCanvasVec2Constant constant; + GtkCanvasVec2Sum sum; + GtkCanvasVec2Variable variable; + }; +}; + +struct _GtkCanvasVec2Summand +{ + graphene_vec2_t scale; + GtkCanvasVec2 value; +}; + + +void gtk_canvas_vec2_init_copy (GtkCanvasVec2 *self, + const GtkCanvasVec2 *source); +void gtk_canvas_vec2_finish (GtkCanvasVec2 *self); + +gboolean gtk_canvas_vec2_eval (const GtkCanvasVec2 *self, + graphene_vec2_t *result); + +void gtk_canvas_vec2_init_invalid (GtkCanvasVec2 *vec2); +void gtk_canvas_vec2_init_constant (GtkCanvasVec2 *vec2, + float x, + float y); +void gtk_canvas_vec2_init_constant_from_vec2 (GtkCanvasVec2 *vec2, + const graphene_vec2_t *value); +void gtk_canvas_vec2_init_sum (GtkCanvasVec2 *vec2, + const graphene_vec2_t *scale, + ...) G_GNUC_NULL_TERMINATED; + +void gtk_canvas_vec2_init_variable (GtkCanvasVec2 *vec2); +GtkCanvasVec2 * gtk_canvas_vec2_get_variable (GtkCanvasVec2 *vec2); + +G_END_DECLS + +#endif /* __GTK_CANVAS_VEC2_PRIVATE_H__ */ diff --git a/gtk/meson.build b/gtk/meson.build index 63f01bbea8..93db1fb16c 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -32,6 +32,7 @@ gtk_private_sources = files([ 'gtkbuilderprecompile.c', 'gtkbuiltinicon.c', 'gtkcellareaboxcontext.c', + 'gtkcanvasvec2.c', 'gtkcoloreditor.c', 'gtkcolorplane.c', 'gtkcolorpicker.c', |