/* Canvas.c generated by valac 0.56.18-dirty, the Vala compiler
 * generated from Canvas.vala, do not modify */

/*
 * Copyright 2024 elementary, Inc. (https://elementary.io)
 * SPDX-License-Identifier: LGPL-2.0-or-later
 */

#include "gala.h"
#include <glib.h>
#include <float.h>
#include <math.h>
#include <cogl/cogl.h>
#include <clutter/clutter.h>
#include <cairo-gobject.h>
#include <glib-object.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

enum  {
	GALA_DRAWING_CANVAS_0_PROPERTY,
	GALA_DRAWING_CANVAS_NUM_PROPERTIES
};
static GParamSpec* gala_drawing_canvas_properties[GALA_DRAWING_CANVAS_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _cairo_surface_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_surface_destroy (var), NULL)))
#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL)))
#define _clutter_paint_node_unref0(var) ((var == NULL) ? NULL : (var = (clutter_paint_node_unref (var), NULL)))
enum  {
	GALA_DRAWING_CANVAS_DRAW_SIGNAL,
	GALA_DRAWING_CANVAS_NUM_SIGNALS
};
static guint gala_drawing_canvas_signals[GALA_DRAWING_CANVAS_NUM_SIGNALS] = {0};
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _GalaDrawingCanvasPrivate {
	gint width;
	gint height;
	gfloat scale_factor;
	CoglContext* cogl_context;
	CoglTexture* texture;
	CoglBitmap* bitmap;
	gboolean dirty;
};

static gint GalaDrawingCanvas_private_offset;
static gpointer gala_drawing_canvas_parent_class = NULL;
static ClutterContentInterface * gala_drawing_canvas_clutter_content_parent_iface = NULL;

static void gala_drawing_canvas_real_attached (ClutterContent* base,
                                        ClutterActor* actor);
static void gala_drawing_canvas_real_detached (ClutterContent* base,
                                        ClutterActor* actor);
static void gala_drawing_canvas_emit_draw (GalaDrawingCanvas* self);
static gboolean gala_drawing_canvas_real_get_preferred_size (ClutterContent* base,
                                                      gfloat* out_width,
                                                      gfloat* out_height);
static void gala_drawing_canvas_real_invalidate (ClutterContent* base);
static void gala_drawing_canvas_real_invalidate_size (ClutterContent* base);
static void gala_drawing_canvas_real_paint_content (ClutterContent* base,
                                             ClutterActor* actor,
                                             ClutterPaintNode* root,
                                             ClutterPaintContext* paint_context);
static void g_cclosure_user_marshal_VOID__BOXED_INT_INT (GClosure * closure,
                                                  GValue * return_value,
                                                  guint n_param_values,
                                                  const GValue * param_values,
                                                  gpointer invocation_hint,
                                                  gpointer marshal_data);
static void gala_drawing_canvas_finalize (GObject * obj);
static GType gala_drawing_canvas_get_type_once (void);

static inline gpointer
gala_drawing_canvas_get_instance_private (GalaDrawingCanvas* self)
{
	return G_STRUCT_MEMBER_P (self, GalaDrawingCanvas_private_offset);
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
gala_drawing_canvas_real_attached (ClutterContent* base,
                                   ClutterActor* actor)
{
	GalaDrawingCanvas * self;
	ClutterBackend* _tmp0_;
	CoglContext* _tmp1_;
	CoglContext* _tmp2_;
	self = (GalaDrawingCanvas*) base;
	g_return_if_fail (actor != NULL);
	_tmp0_ = clutter_get_default_backend ();
	_tmp1_ = clutter_backend_get_cogl_context (_tmp0_);
	_tmp2_ = _g_object_ref0 (_tmp1_);
	_g_object_unref0 (self->priv->cogl_context);
	self->priv->cogl_context = _tmp2_;
}

static void
gala_drawing_canvas_real_detached (ClutterContent* base,
                                   ClutterActor* actor)
{
	GalaDrawingCanvas * self;
	self = (GalaDrawingCanvas*) base;
	g_return_if_fail (actor != NULL);
	_g_object_unref0 (self->priv->cogl_context);
	self->priv->cogl_context = NULL;
}

static void
gala_drawing_canvas_emit_draw (GalaDrawingCanvas* self)
{
	CoglContext* _tmp0_;
	gint real_width = 0;
	gint real_height = 0;
	CoglBitmap* _tmp1_;
	CoglBuffer* buffer = NULL;
	CoglBitmap* _tmp4_;
	CoglBuffer* _tmp5_;
	CoglBuffer* _tmp6_;
	CoglBuffer* _tmp7_;
	void* data = NULL;
	CoglBuffer* _tmp8_;
	void* _tmp9_;
	cairo_surface_t* surface = NULL;
	gboolean mapped_buffer = FALSE;
	void* _tmp10_;
	cairo_surface_t* _tmp15_;
	cairo_t* cr = NULL;
	cairo_surface_t* _tmp16_;
	cairo_t* _tmp17_;
	cairo_t* _tmp18_;
	cairo_t* _tmp19_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->cogl_context;
	_vala_return_if_fail (((self->priv->width > 0) && (self->priv->height > 0)) && (_tmp0_ != NULL), "width > 0 && height > 0 && cogl_context != null");
	self->priv->dirty = TRUE;
	real_width = (gint) ceilf (self->priv->width * self->priv->scale_factor);
	real_height = (gint) ceilf (self->priv->height * self->priv->scale_factor);
	_tmp1_ = self->priv->bitmap;
	if (_tmp1_ == NULL) {
		CoglContext* _tmp2_;
		CoglBitmap* _tmp3_;
		_tmp2_ = self->priv->cogl_context;
		_tmp3_ = cogl_bitmap_new_with_size (_tmp2_, (guint) real_width, (guint) real_height, COGL_PIXEL_FORMAT_CAIRO_ARGB32_COMPAT);
		_g_object_unref0 (self->priv->bitmap);
		self->priv->bitmap = _tmp3_;
	}
	_tmp4_ = self->priv->bitmap;
	_tmp5_ = cogl_bitmap_get_buffer (_tmp4_);
	buffer = _tmp5_;
	_tmp6_ = buffer;
	if (_tmp6_ == NULL) {
		return;
	}
	_tmp7_ = buffer;
	cogl_buffer_set_update_hint (_tmp7_, COGL_BUFFER_UPDATE_HINT_DYNAMIC);
	_tmp8_ = buffer;
	_tmp9_ = cogl_buffer_map (_tmp8_, COGL_BUFFER_ACCESS_READ_WRITE, COGL_BUFFER_MAP_HINT_DISCARD);
	data = _tmp9_;
	_tmp10_ = data;
	if (_tmp10_ != NULL) {
		gint bitmap_stride = 0;
		CoglBitmap* _tmp11_;
		void* _tmp12_;
		cairo_surface_t* _tmp13_;
		_tmp11_ = self->priv->bitmap;
		bitmap_stride = cogl_bitmap_get_rowstride (_tmp11_);
		_tmp12_ = data;
		_tmp13_ = cairo_image_surface_create_for_data ((guchar*) _tmp12_, CAIRO_FORMAT_ARGB32, real_width, real_height, bitmap_stride);
		_cairo_surface_destroy0 (surface);
		surface = _tmp13_;
		mapped_buffer = TRUE;
	} else {
		cairo_surface_t* _tmp14_;
		_tmp14_ = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, real_width, real_height);
		_cairo_surface_destroy0 (surface);
		surface = _tmp14_;
		mapped_buffer = FALSE;
	}
	_tmp15_ = surface;
	cairo_surface_set_device_scale (_tmp15_, (gdouble) self->priv->scale_factor, (gdouble) self->priv->scale_factor);
	_tmp16_ = surface;
	_tmp17_ = cairo_create (_tmp16_);
	cr = _tmp17_;
	_tmp18_ = cr;
	cr = NULL;
	_tmp19_ = _tmp18_;
	g_signal_emit (self, gala_drawing_canvas_signals[GALA_DRAWING_CANVAS_DRAW_SIGNAL], 0, _tmp19_, self->priv->width, self->priv->height);
	_cairo_destroy0 (_tmp19_);
	if (mapped_buffer) {
		CoglBuffer* _tmp20_;
		_tmp20_ = buffer;
		cogl_buffer_unmap (_tmp20_);
	} else {
		gint size = 0;
		cairo_surface_t* _tmp21_;
		CoglBuffer* _tmp22_;
		cairo_surface_t* _tmp23_;
		guchar* _tmp24_;
		_tmp21_ = surface;
		size = cairo_image_surface_get_stride (_tmp21_) * self->priv->height;
		_tmp22_ = buffer;
		_tmp23_ = surface;
		_tmp24_ = cairo_image_surface_get_data (_tmp23_);
		cogl_buffer_set_data (_tmp22_, (gsize) 0, _tmp24_, (gsize) size);
	}
	_cairo_destroy0 (cr);
	_cairo_surface_destroy0 (surface);
}

static gboolean
gala_drawing_canvas_real_get_preferred_size (ClutterContent* base,
                                             gfloat* out_width,
                                             gfloat* out_height)
{
	GalaDrawingCanvas * self;
	gfloat _vala_out_width = 0.0F;
	gfloat _vala_out_height = 0.0F;
	gboolean _tmp0_ = FALSE;
	gboolean result;
	self = (GalaDrawingCanvas*) base;
	if (self->priv->width < 0) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = self->priv->width < 0;
	}
	if (_tmp0_) {
		_vala_out_width = (gfloat) 0;
		_vala_out_height = (gfloat) 0;
		result = FALSE;
		if (out_width) {
			*out_width = _vala_out_width;
		}
		if (out_height) {
			*out_height = _vala_out_height;
		}
		return result;
	}
	_vala_out_width = ceilf (self->priv->width * self->priv->scale_factor);
	_vala_out_height = ceilf (self->priv->height * self->priv->scale_factor);
	result = TRUE;
	if (out_width) {
		*out_width = _vala_out_width;
	}
	if (out_height) {
		*out_height = _vala_out_height;
	}
	return result;
}

static void
gala_drawing_canvas_real_invalidate (ClutterContent* base)
{
	GalaDrawingCanvas * self;
	gboolean _tmp0_ = FALSE;
	self = (GalaDrawingCanvas*) base;
	_g_object_unref0 (self->priv->bitmap);
	self->priv->bitmap = NULL;
	if (self->priv->width <= 0) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = self->priv->height <= 0;
	}
	if (_tmp0_) {
		return;
	}
	gala_drawing_canvas_emit_draw (self);
}

static void
gala_drawing_canvas_real_invalidate_size (ClutterContent* base)
{
	GalaDrawingCanvas * self;
	self = (GalaDrawingCanvas*) base;
}

static void
gala_drawing_canvas_real_paint_content (ClutterContent* base,
                                        ClutterActor* actor,
                                        ClutterPaintNode* root,
                                        ClutterPaintContext* paint_context)
{
	GalaDrawingCanvas * self;
	CoglBitmap* _tmp0_;
	CoglTexture* _tmp1_;
	CoglTexture* _tmp4_;
	ClutterPaintNode* node = NULL;
	CoglTexture* _tmp5_;
	ClutterPaintNode* _tmp6_;
	ClutterPaintNode* _tmp7_;
	self = (GalaDrawingCanvas*) base;
	g_return_if_fail (actor != NULL);
	g_return_if_fail (root != NULL);
	g_return_if_fail (paint_context != NULL);
	_tmp0_ = self->priv->bitmap;
	if (_tmp0_ == NULL) {
		return;
	}
	if (self->priv->dirty) {
		_g_object_unref0 (self->priv->texture);
		self->priv->texture = NULL;
	}
	_tmp1_ = self->priv->texture;
	if (_tmp1_ == NULL) {
		CoglBitmap* _tmp2_;
		CoglTexture2D* _tmp3_;
		_tmp2_ = self->priv->bitmap;
		_tmp3_ = (CoglTexture2D*) cogl_texture_2d_new_from_bitmap (_tmp2_);
		_g_object_unref0 (self->priv->texture);
		self->priv->texture = (CoglTexture*) _tmp3_;
	}
	_tmp4_ = self->priv->texture;
	if (_tmp4_ == NULL) {
		return;
	}
	_tmp5_ = self->priv->texture;
	_tmp6_ = clutter_actor_create_texture_paint_node (actor, _tmp5_);
	node = _tmp6_;
	_tmp7_ = node;
	clutter_paint_node_add_child (root, _tmp7_);
	self->priv->dirty = FALSE;
	_clutter_paint_node_unref0 (node);
}

void
gala_drawing_canvas_set_size (GalaDrawingCanvas* self,
                              gint new_width,
                              gint new_height)
{
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (self != NULL);
	_vala_return_if_fail ((new_width >= -1) && (new_height >= -1), "new_width >= -1 && new_height >= -1");
	if (new_width == self->priv->width) {
		_tmp0_ = new_height == self->priv->height;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		return;
	}
	self->priv->width = new_width;
	self->priv->height = new_height;
	clutter_content_invalidate ((ClutterContent*) self);
}

void
gala_drawing_canvas_set_scale_factor (GalaDrawingCanvas* self,
                                      gfloat new_scale_factor)
{
	g_return_if_fail (self != NULL);
	_vala_return_if_fail (new_scale_factor > 0.0f, "new_scale_factor > 0.0f");
	if (new_scale_factor != self->priv->scale_factor) {
		self->priv->scale_factor = new_scale_factor;
		clutter_content_invalidate ((ClutterContent*) self);
	}
}

GalaDrawingCanvas*
gala_drawing_canvas_construct (GType object_type)
{
	GalaDrawingCanvas * self = NULL;
	self = (GalaDrawingCanvas*) g_object_new (object_type, NULL);
	return self;
}

GalaDrawingCanvas*
gala_drawing_canvas_new (void)
{
	return gala_drawing_canvas_construct (GALA_DRAWING_TYPE_CANVAS);
}

static void
g_cclosure_user_marshal_VOID__BOXED_INT_INT (GClosure * closure,
                                             GValue * return_value,
                                             guint n_param_values,
                                             const GValue * param_values,
                                             gpointer invocation_hint,
                                             gpointer marshal_data)
{
	typedef void (*GMarshalFunc_VOID__BOXED_INT_INT) (gpointer data1, gpointer arg_1, gint arg_2, gint arg_3, gpointer data2);
	register GMarshalFunc_VOID__BOXED_INT_INT callback;
	register GCClosure * cc;
	register gpointer data1;
	register gpointer data2;
	cc = (GCClosure *) closure;
	g_return_if_fail (n_param_values == 4);
	if (G_CCLOSURE_SWAP_DATA (closure)) {
		data1 = closure->data;
		data2 = param_values->data[0].v_pointer;
	} else {
		data1 = param_values->data[0].v_pointer;
		data2 = closure->data;
	}
	callback = (GMarshalFunc_VOID__BOXED_INT_INT) (marshal_data ? marshal_data : cc->callback);
	callback (data1, g_value_get_boxed (param_values + 1), g_value_get_int (param_values + 2), g_value_get_int (param_values + 3), data2);
}

static void
gala_drawing_canvas_class_init (GalaDrawingCanvasClass * klass,
                                gpointer klass_data)
{
	gala_drawing_canvas_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GalaDrawingCanvas_private_offset);
	G_OBJECT_CLASS (klass)->finalize = gala_drawing_canvas_finalize;
	gala_drawing_canvas_signals[GALA_DRAWING_CANVAS_DRAW_SIGNAL] = g_signal_new ("draw", GALA_DRAWING_TYPE_CANVAS, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__BOXED_INT_INT, G_TYPE_NONE, 3, cairo_gobject_context_get_type (), G_TYPE_INT, G_TYPE_INT);
}

static void
gala_drawing_canvas_clutter_content_interface_init (ClutterContentInterface * iface,
                                                    gpointer iface_data)
{
	gala_drawing_canvas_clutter_content_parent_iface = g_type_interface_peek_parent (iface);
	iface->attached = (void (*) (ClutterContent*, ClutterActor*)) gala_drawing_canvas_real_attached;
	iface->detached = (void (*) (ClutterContent*, ClutterActor*)) gala_drawing_canvas_real_detached;
	iface->get_preferred_size = (gboolean (*) (ClutterContent*, gfloat*, gfloat*)) gala_drawing_canvas_real_get_preferred_size;
	iface->invalidate = (void (*) (ClutterContent*)) gala_drawing_canvas_real_invalidate;
	iface->invalidate_size = (void (*) (ClutterContent*)) gala_drawing_canvas_real_invalidate_size;
	iface->paint_content = (void (*) (ClutterContent*, ClutterActor*, ClutterPaintNode*, ClutterPaintContext*)) gala_drawing_canvas_real_paint_content;
}

static void
gala_drawing_canvas_instance_init (GalaDrawingCanvas * self,
                                   gpointer klass)
{
	self->priv = gala_drawing_canvas_get_instance_private (self);
	self->priv->width = -1;
	self->priv->height = -1;
	self->priv->scale_factor = 1.0f;
	self->priv->texture = NULL;
	self->priv->bitmap = NULL;
	self->priv->dirty = FALSE;
}

static void
gala_drawing_canvas_finalize (GObject * obj)
{
	GalaDrawingCanvas * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GALA_DRAWING_TYPE_CANVAS, GalaDrawingCanvas);
	_g_object_unref0 (self->priv->cogl_context);
	_g_object_unref0 (self->priv->texture);
	_g_object_unref0 (self->priv->bitmap);
	G_OBJECT_CLASS (gala_drawing_canvas_parent_class)->finalize (obj);
}

 G_GNUC_NO_INLINE static GType
gala_drawing_canvas_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GalaDrawingCanvasClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gala_drawing_canvas_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GalaDrawingCanvas), 0, (GInstanceInitFunc) gala_drawing_canvas_instance_init, NULL };
	static const GInterfaceInfo clutter_content_info = { (GInterfaceInitFunc) gala_drawing_canvas_clutter_content_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
	GType gala_drawing_canvas_type_id;
	gala_drawing_canvas_type_id = g_type_register_static (G_TYPE_OBJECT, "GalaDrawingCanvas", &g_define_type_info, 0);
	g_type_add_interface_static (gala_drawing_canvas_type_id, clutter_content_get_type (), &clutter_content_info);
	GalaDrawingCanvas_private_offset = g_type_add_instance_private (gala_drawing_canvas_type_id, sizeof (GalaDrawingCanvasPrivate));
	return gala_drawing_canvas_type_id;
}

GType
gala_drawing_canvas_get_type (void)
{
	static gsize gala_drawing_canvas_type_id__once = 0;
	if (g_once_init_enter (&gala_drawing_canvas_type_id__once)) {
		GType gala_drawing_canvas_type_id;
		gala_drawing_canvas_type_id = gala_drawing_canvas_get_type_once ();
		g_once_init_leave (&gala_drawing_canvas_type_id__once, gala_drawing_canvas_type_id);
	}
	return gala_drawing_canvas_type_id__once;
}

