pub const ext = @import("ext.zig");
const gly = @This();

const std = @import("std");
const compat = @import("compat");
const gio = @import("gio2");
const gobject = @import("gobject2");
const glib = @import("glib2");
const gmodule = @import("gmodule2");
/// Image creator
///
/// ```c
/// `include` <glycin.h>
///
/// GlyCreator *creator = gly_creator_new("image/jpeg", NULL);
///
/// if (!creator)
///   return;
///
/// // Create frame with a single red pixel
/// guint8 data[] = {255, 0, 0};
/// gsize length = sizeof(data);
/// GBytes *texture = g_bytes_new(data, length);
/// GlyNewFrame *new_frame = gly_creator_add_frame(creator, 1, 1, GLY_MEMORY_R8G8B8, texture, NULL);
///
/// // Create JPEG
/// GlyEncodedImage *encoded_image = gly_creator_create(creator, NULL);
///
/// if (encoded_image)
/// {
///   GBytes *binary_data = gly_encoded_image_get_data(encoded_image);
///   if (binary_data)
///   {
///     // Write image to file
///     GFile *file = g_file_new_for_path("test.jpg");
///     g_file_replace_contents(
///         file,
///         g_bytes_get_data(binary_data, NULL),
///         g_bytes_get_size(binary_data),
///         NULL,
///         FALSE,
///         G_FILE_CREATE_NONE,
///         NULL,
///         NULL,
///         NULL);
///   }
/// }
/// ```
pub const Creator = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gly.CreatorClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const mime_type = struct {
            pub const name = "mime-type";

            pub const Type = ?[*:0]u8;
        };

        pub const sandbox_selector = struct {
            pub const name = "sandbox-selector";

            pub const Type = gly.SandboxSelector;
        };
    };

    pub const signals = struct {};

    extern fn gly_creator_new(p_mime_type: [*:0]const u8, p_error: ?*?*glib.Error) ?*gly.Creator;
    pub const new = gly_creator_new;

    extern fn gly_creator_add_frame(p_creator: *Creator, p_width: u32, p_height: u32, p_memory_format: gly.MemoryFormat, p_texture: *glib.Bytes, p_error: ?*?*glib.Error) ?*gly.NewFrame;
    pub const addFrame = gly_creator_add_frame;

    extern fn gly_creator_add_frame_with_stride(p_creator: *Creator, p_width: u32, p_height: u32, p_stride: u32, p_memory_format: gly.MemoryFormat, p_texture: *glib.Bytes, p_error: ?*?*glib.Error) ?*gly.NewFrame;
    pub const addFrameWithStride = gly_creator_add_frame_with_stride;

    /// Add metadata that are stored as key-value pairs.
    /// A prominent example are PNG's `tEXt` chunks.
    ///
    /// If an entry with `key` already exists, it will be replaced.
    extern fn gly_creator_add_metadata_key_value(p_creator: *Creator, p_key: [*:0]const u8, p_value: [*:0]const u8) c_int;
    pub const addMetadataKeyValue = gly_creator_add_metadata_key_value;

    extern fn gly_creator_create(p_image: *Creator, p_error: ?*?*glib.Error) ?*gly.EncodedImage;
    pub const create = gly_creator_create;

    /// Asynchronous version of `Creator.create`.
    extern fn gly_creator_create_async(p_creator: *Creator, p_cancellable: ?*gio.Cancellable, p_callback: ?gio.AsyncReadyCallback, p_user_data: ?*anyopaque) void;
    pub const createAsync = gly_creator_create_async;

    /// Finishes the `Creator.createAsync` call.
    extern fn gly_creator_create_finish(p_creator: *Creator, p_result: *gio.AsyncResult, p_error: ?*?*glib.Error) ?*gly.EncodedImage;
    pub const createFinish = gly_creator_create_finish;

    extern fn gly_creator_set_encoding_compression(p_creator: *Creator, p_compression: u8) c_int;
    pub const setEncodingCompression = gly_creator_set_encoding_compression;

    extern fn gly_creator_set_encoding_quality(p_creator: *Creator, p_quality: u8) c_int;
    pub const setEncodingQuality = gly_creator_set_encoding_quality;

    /// Selects which sandbox mechanism should be used. The default without calling this function is `SandboxSelector``.AUTO`.
    extern fn gly_creator_set_sandbox_selector(p_creator: *Creator, p_sandbox_selector: gly.SandboxSelector) c_int;
    pub const setSandboxSelector = gly_creator_set_sandbox_selector;

    extern fn gly_creator_get_type() usize;
    pub const getGObjectType = gly_creator_get_type;

    extern fn g_object_ref(p_self: *gly.Creator) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gly.Creator) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *Creator, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Encoded image
pub const EncodedImage = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gly.EncodedImageClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const data = struct {
            pub const name = "data";

            pub const Type = ?*glib.Bytes;
        };
    };

    pub const signals = struct {};

    extern fn gly_encoded_image_get_data(p_encoded_image: *EncodedImage) *glib.Bytes;
    pub const getData = gly_encoded_image_get_data;

    extern fn gly_encoded_image_get_type() usize;
    pub const getGObjectType = gly_encoded_image_get_type;

    extern fn g_object_ref(p_self: *gly.EncodedImage) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gly.EncodedImage) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *EncodedImage, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// A frame of an image often being the complete image.
pub const Frame = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gly.FrameClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    /// Image data arranged according to `Frame.getMemoryFormat`
    extern fn gly_frame_get_buf_bytes(p_frame: *Frame) *glib.Bytes;
    pub const getBufBytes = gly_frame_get_buf_bytes;

    /// Returns the CICP (coding-independent code point) for the frames texture.
    /// This value is `NULL` if no CICP is used.
    extern fn gly_frame_get_color_cicp(p_frame: *Frame) ?*gly.Cicp;
    pub const getColorCicp = gly_frame_get_color_cicp;

    /// Duration to show frame for animations.
    ///
    /// If the value is zero, the image is not animated.
    extern fn gly_frame_get_delay(p_frame: *Frame) i64;
    pub const getDelay = gly_frame_get_delay;

    /// Height for image data in pixels
    extern fn gly_frame_get_height(p_frame: *Frame) u32;
    pub const getHeight = gly_frame_get_height;

    /// Format of the image data in `gly.Frame.getBufBytes`
    extern fn gly_frame_get_memory_format(p_frame: *Frame) gly.MemoryFormat;
    pub const getMemoryFormat = gly_frame_get_memory_format;

    /// Width of a row for image data in bytes
    extern fn gly_frame_get_stride(p_frame: *Frame) u32;
    pub const getStride = gly_frame_get_stride;

    /// Width for image data in pixels
    extern fn gly_frame_get_width(p_frame: *Frame) u32;
    pub const getWidth = gly_frame_get_width;

    extern fn gly_frame_get_type() usize;
    pub const getGObjectType = gly_frame_get_type;

    extern fn g_object_ref(p_self: *gly.Frame) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gly.Frame) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *Frame, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Defines which parts of an image to load.
///
/// ::: warning
///     Loaders can and frequently will ignore instructions set in
///     `GlyFrameRequest`. The reason is that for most loaders
///     many instructions don't have a meaningful interpretation.
pub const FrameRequest = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gly.FrameRequestClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const loop_animation = struct {
            pub const name = "loop-animation";

            pub const Type = c_int;
        };

        pub const scale_height = struct {
            pub const name = "scale-height";

            pub const Type = c_uint;
        };

        pub const scale_width = struct {
            pub const name = "scale-width";

            pub const Type = c_uint;
        };
    };

    pub const signals = struct {};

    /// Creates a new frame request.
    extern fn gly_frame_request_new() *gly.FrameRequest;
    pub const new = gly_frame_request_new;

    /// Controls if first frame is returned after last frame
    ///
    /// By default, this option is set to `TRUE`, returning the first frame, if
    /// the previously requested frame was the last frame.
    extern fn gly_frame_request_set_loop_animation(p_frame_request: *FrameRequest, p_loop_animation: c_int) void;
    pub const setLoopAnimation = gly_frame_request_set_loop_animation;

    /// Set maximum dimensions for the frame. The texture will be scaled
    /// to be within the maximum dimensions while keeping its aspect ratio.
    /// This option is especially useful to SVGs which will be rendered at
    /// the respective size.
    ///
    /// ::: warning
    ///     Most loaders will ignore this option. Currently, only the SVG
    ///     loader is known to obey it.
    extern fn gly_frame_request_set_scale(p_frame_request: *FrameRequest, p_width: u32, p_height: u32) void;
    pub const setScale = gly_frame_request_set_scale;

    extern fn gly_frame_request_get_type() usize;
    pub const getGObjectType = gly_frame_request_get_type;

    extern fn g_object_ref(p_self: *gly.FrameRequest) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gly.FrameRequest) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *FrameRequest, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Image handle containing metadata and allowing frame requests.
pub const Image = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gly.ImageClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    /// See `Image.getWidth`
    extern fn gly_image_get_height(p_image: *Image) u32;
    pub const getHeight = gly_image_get_height;

    /// Get metadata that are stored as key-value pairs.
    /// A prominent example are PNG's `tEXt` and `zTXt` chunks.
    ///
    /// ::: note
    ///     In contrast to gdk-pixbuf's *option* feature, the
    ///     keys do not carry prefixes like `tEXt::` or `zTXt::`.
    extern fn gly_image_get_metadata_key_value(p_image: *Image, p_key: [*:0]const u8) ?[*:0]u8;
    pub const getMetadataKeyValue = gly_image_get_metadata_key_value;

    /// Get the list of available keys for `Image.getMetadataKeyValue`.
    extern fn gly_image_get_metadata_keys(p_image: *Image) [*][*:0]u8;
    pub const getMetadataKeys = gly_image_get_metadata_keys;

    /// Returns detected MIME type of the file
    extern fn gly_image_get_mime_type(p_image: *Image) [*:0]const u8;
    pub const getMimeType = gly_image_get_mime_type;

    extern fn gly_image_get_specific_frame(p_image: *Image, p_frame_request: *gly.FrameRequest, p_error: ?*?*glib.Error) ?*gly.Frame;
    pub const getSpecificFrame = gly_image_get_specific_frame;

    /// Asynchronous version of `Image.getSpecificFrame`.
    extern fn gly_image_get_specific_frame_async(p_image: *Image, p_frame_request: *gly.FrameRequest, p_cancellable: ?*gio.Cancellable, p_callback: ?gio.AsyncReadyCallback, p_user_data: ?*anyopaque) void;
    pub const getSpecificFrameAsync = gly_image_get_specific_frame_async;

    /// Finishes the `Image.getSpecificFrameAsync` call.
    extern fn gly_image_get_specific_frame_finish(p_image: *Image, p_result: *gio.AsyncResult, p_error: ?*?*glib.Error) ?*gly.Frame;
    pub const getSpecificFrameFinish = gly_image_get_specific_frame_finish;

    /// Get the image orientation
    ///
    /// The image orientation is given in Exif format. The function is
    /// guaranteed to only return values from 1 to 8.
    ///
    /// If `Loader.setApplyTransformations` is set to `FALSE`,
    /// the orientation has to be corrected manually to display the image
    /// correctly.
    extern fn gly_image_get_transformation_orientation(p_image: *Image) u16;
    pub const getTransformationOrientation = gly_image_get_transformation_orientation;

    /// Early width information.
    ///
    /// This information is often correct. However, it should only be used for
    /// an early rendering estimates. For everything else, the specific frame
    /// information should be used. See `Frame.getWidth`.
    extern fn gly_image_get_width(p_image: *Image) u32;
    pub const getWidth = gly_image_get_width;

    /// Synchronously loads texture and information of the next frame.
    ///
    /// For single still images, this can only be called once.
    /// For animated images, this function will loop to the first frame, when the last frame is reached.
    extern fn gly_image_next_frame(p_image: *Image, p_error: ?*?*glib.Error) ?*gly.Frame;
    pub const nextFrame = gly_image_next_frame;

    /// Asynchronous version of `Image.nextFrame`.
    extern fn gly_image_next_frame_async(p_image: *Image, p_cancellable: ?*gio.Cancellable, p_callback: ?gio.AsyncReadyCallback, p_user_data: ?*anyopaque) void;
    pub const nextFrameAsync = gly_image_next_frame_async;

    /// Finishes the `Image.nextFrameAsync` call.
    extern fn gly_image_next_frame_finish(p_image: *Image, p_result: *gio.AsyncResult, p_error: ?*?*glib.Error) ?*gly.Frame;
    pub const nextFrameFinish = gly_image_next_frame_finish;

    extern fn gly_image_get_type() usize;
    pub const getGObjectType = gly_image_get_type;

    extern fn g_object_ref(p_self: *gly.Image) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gly.Image) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *Image, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// `Loader` prepares loading an image.
///
/// The following example shows how to obtain a `Gdk.Texture`. It uses
/// [GlyGtk4](https://gnome.pages.gitlab.gnome.org/glycin/libglycin-gtk4)
/// for this.
///
/// ```c
/// `include` <glycin-gtk4.h>
///
/// file = g_file_new_for_path ("test.png");
/// loader = gly_loader_new (file);
/// image = gly_loader_load (loader, NULL);
/// if (image)
///   {
///     frame = gly_image_next_frame (image, NULL);
///     if (frame)
///       {
///         texture = gly_gtk_frame_get_texture (frame);
///         g_print ("Image height: `d`\n", gdk_texture_get_height (texture));
///         image_widget = gtk_image_new_from_paintable (GDK_PAINTABLE (texture));
///       }
///   }
/// ```
pub const Loader = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gly.LoaderClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const apply_transformation = struct {
            pub const name = "apply-transformation";

            pub const Type = c_int;
        };

        pub const bytes = struct {
            pub const name = "bytes";

            pub const Type = ?*glib.Bytes;
        };

        pub const cancellable = struct {
            pub const name = "cancellable";

            pub const Type = ?*gio.Cancellable;
        };

        pub const file = struct {
            pub const name = "file";

            pub const Type = ?*gio.File;
        };

        pub const memory_format_selection = struct {
            pub const name = "memory-format-selection";

            pub const Type = gly.MemoryFormatSelection;
        };

        pub const sandbox_selector = struct {
            pub const name = "sandbox-selector";

            pub const Type = gly.SandboxSelector;
        };

        pub const stream = struct {
            pub const name = "stream";

            pub const Type = ?*gio.InputStream;
        };
    };

    pub const signals = struct {};

    /// Returns a list of MIME types currently supported for loading images.
    ///
    /// This list is generated from the config on first use of a loader or
    /// call of this function and cached afterwards. Hence, the first call
    /// can be blocking.
    extern fn gly_loader_get_mime_types() [*][*:0]u8;
    pub const getMimeTypes = gly_loader_get_mime_types;

    /// Async variant of `Loader.getMimeTypes`
    extern fn gly_loader_get_mime_types_async(p_cancellable: ?*gio.Cancellable, p_callback: ?gio.AsyncReadyCallback, p_user_data: ?*anyopaque) void;
    pub const getMimeTypesAsync = gly_loader_get_mime_types_async;

    /// Finishes the `Loader.getMimeTypesAsync` call.
    extern fn gly_loader_get_mime_types_finish(p_result: *gio.AsyncResult, p_error: ?*?*glib.Error) ?[*][*:0]u8;
    pub const getMimeTypesFinish = gly_loader_get_mime_types_finish;

    /// Creates a new loader for a file.
    extern fn gly_loader_new(p_file: *gio.File) *gly.Loader;
    pub const new = gly_loader_new;

    /// Creates a new loader for bytes.
    extern fn gly_loader_new_for_bytes(p_bytes: *glib.Bytes) *gly.Loader;
    pub const newForBytes = gly_loader_new_for_bytes;

    /// Creates a new loader for a stream.
    extern fn gly_loader_new_for_stream(p_stream: *gio.InputStream) *gly.Loader;
    pub const newForStream = gly_loader_new_for_stream;

    /// Synchronously loads an image and returns an `Image` when successful.
    extern fn gly_loader_load(p_loader: *Loader, p_error: ?*?*glib.Error) ?*gly.Image;
    pub const load = gly_loader_load;

    /// Asynchronous version of `Loader.load`.
    extern fn gly_loader_load_async(p_loader: *Loader, p_cancellable: ?*gio.Cancellable, p_callback: ?gio.AsyncReadyCallback, p_user_data: ?*anyopaque) void;
    pub const loadAsync = gly_loader_load_async;

    /// Finishes the `Loader.loadAsync` call.
    extern fn gly_loader_load_finish(p_loader: *Loader, p_result: *gio.AsyncResult, p_error: ?*?*glib.Error) ?*gly.Image;
    pub const loadFinish = gly_loader_load_finish;

    /// Sets which memory formats can be returned by the loader
    ///
    /// If the memory format doesn't match one of the selected formats, the
    /// format will be transformed into the best suitable format selected.
    extern fn gly_loader_set_accepted_memory_formats(p_loader: *Loader, p_memory_format_selection: gly.MemoryFormatSelection) void;
    pub const setAcceptedMemoryFormats = gly_loader_set_accepted_memory_formats;

    /// Set whether to apply transformations to texture
    ///
    /// When enabled, transformations like image orientation are applied to the
    /// texture data.
    ///
    /// This option is enabled by default.
    extern fn gly_loader_set_apply_transformations(p_loader: *Loader, p_apply_transformations: c_int) void;
    pub const setApplyTransformations = gly_loader_set_apply_transformations;

    /// Selects which sandbox mechanism should be used. The default without calling this function is `SandboxSelector``.AUTO`.
    extern fn gly_loader_set_sandbox_selector(p_loader: *Loader, p_sandbox_selector: gly.SandboxSelector) void;
    pub const setSandboxSelector = gly_loader_set_sandbox_selector;

    extern fn gly_loader_get_type() usize;
    pub const getGObjectType = gly_loader_get_type;

    extern fn g_object_ref(p_self: *gly.Loader) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gly.Loader) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *Loader, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// New frame
pub const NewFrame = opaque {
    pub const Parent = gobject.Object;
    pub const Implements = [_]type{};
    pub const Class = gly.NewFrameClass;
    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gly_new_frame_set_color_icc_profile(p_new_frame: *NewFrame, p_icc_profile: *glib.Bytes) c_int;
    pub const setColorIccProfile = gly_new_frame_set_color_icc_profile;

    extern fn gly_new_frame_get_type() usize;
    pub const getGObjectType = gly_new_frame_get_type;

    extern fn g_object_ref(p_self: *gly.NewFrame) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gly.NewFrame) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *NewFrame, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// See ITU-T H.273
pub const Cicp = extern struct {
    f_color_primaries: u8,
    f_transfer_characteristics: u8,
    f_matrix_coefficients: u8,
    f_video_full_range_flag: u8,

    extern fn gly_cicp_copy(p_cicp: *Cicp) *gly.Cicp;
    pub const copy = gly_cicp_copy;

    extern fn gly_cicp_free(p_cicp: *Cicp) void;
    pub const free = gly_cicp_free;

    extern fn gly_cicp_get_type() usize;
    pub const getGObjectType = gly_cicp_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CreatorClass = extern struct {
    pub const Instance = gly.Creator;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *CreatorClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const EncodedImageClass = extern struct {
    pub const Instance = gly.EncodedImage;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *EncodedImageClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const FrameClass = extern struct {
    pub const Instance = gly.Frame;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *FrameClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const FrameRequestClass = extern struct {
    pub const Instance = gly.FrameRequest;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *FrameRequestClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const ImageClass = extern struct {
    pub const Instance = gly.Image;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *ImageClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const LoaderClass = extern struct {
    pub const Instance = gly.Loader;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *LoaderClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const NewFrameClass = extern struct {
    pub const Instance = gly.NewFrame;

    f_parent_class: gobject.ObjectClass,

    pub fn as(p_instance: *NewFrameClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Errors that can appear while loading images.
pub const LoaderError = enum(c_int) {
    failed = 0,
    unknown_image_format = 1,
    no_more_frames = 2,
    _,

    /// Error quark for `GlyLoaderError`
    extern fn gly_loader_error_quark() glib.Quark;
    pub const quark = gly_loader_error_quark;

    extern fn gly_loader_error_get_type() usize;
    pub const getGObjectType = gly_loader_error_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Memory format
pub const MemoryFormat = enum(c_int) {
    b8g8r8a8_premultiplied = 0,
    a8r8g8b8_premultiplied = 1,
    r8g8b8a8_premultiplied = 2,
    b8g8r8a8 = 3,
    a8r8g8b8 = 4,
    r8g8b8a8 = 5,
    a8b8g8r8 = 6,
    r8g8b8 = 7,
    b8g8r8 = 8,
    r16g16b16 = 9,
    r16g16b16a16_premultiplied = 10,
    r16g16b16a16 = 11,
    r16g16b16_float = 12,
    r16g16b16a16_float = 13,
    r32g32b32_float = 14,
    r32g32b32a32_float_premultiplied = 15,
    r32g32b32a32_float = 16,
    g8a8_premultiplied = 17,
    g8a8 = 18,
    g8 = 19,
    g16a16_premultiplied = 20,
    g16a16 = 21,
    g16 = 22,
    _,

    /// Whether a memory format has an alpha channel
    extern fn gly_memory_format_has_alpha(p_memory_format: gly.MemoryFormat) c_int;
    pub const hasAlpha = gly_memory_format_has_alpha;

    /// Whether a memory format has an alpha channel and the color values are
    /// premultiplied with the alpha value
    extern fn gly_memory_format_is_premultiplied(p_memory_format: gly.MemoryFormat) c_int;
    pub const isPremultiplied = gly_memory_format_is_premultiplied;

    extern fn gly_memory_format_get_type() usize;
    pub const getGObjectType = gly_memory_format_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Sandbox mechanisms
///
/// ::: warning
///     Using `GLY_SANDBOX_SELECTOR_NOT_SANDBOXED` will disable an important security layer that sandboxes loaders. It is only intended for testing and development purposes.
pub const SandboxSelector = enum(c_int) {
    auto = 0,
    bwrap = 1,
    flatpak_spawn = 2,
    not_sandboxed = 3,
    _,

    extern fn gly_sandbox_selector_get_type() usize;
    pub const getGObjectType = gly_sandbox_selector_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Memory format selection
pub const MemoryFormatSelection = packed struct(c_uint) {
    b8g8r8a8_premultiplied: bool = false,
    a8r8g8b8_premultiplied: bool = false,
    r8g8b8a8_premultiplied: bool = false,
    b8g8r8a8: bool = false,
    a8r8g8b8: bool = false,
    r8g8b8a8: bool = false,
    a8b8g8r8: bool = false,
    r8g8b8: bool = false,
    b8g8r8: bool = false,
    r16g16b16: bool = false,
    r16g16b16a16_premultiplied: bool = false,
    r16g16b16a16: bool = false,
    r16g16b16_float: bool = false,
    r16g16b16a16_float: bool = false,
    r32g32b32_float: bool = false,
    r32g32b32a32_float_premultiplied: bool = false,
    r32g32b32a32_float: bool = false,
    g8a8_premultiplied: bool = false,
    g8a8: bool = false,
    g8: bool = false,
    g16a16_premultiplied: bool = false,
    g16a16: bool = false,
    g16: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_b8g8r8a8_premultiplied: MemoryFormatSelection = @bitCast(@as(c_uint, 1));
    pub const flags_a8r8g8b8_premultiplied: MemoryFormatSelection = @bitCast(@as(c_uint, 2));
    pub const flags_r8g8b8a8_premultiplied: MemoryFormatSelection = @bitCast(@as(c_uint, 4));
    pub const flags_b8g8r8a8: MemoryFormatSelection = @bitCast(@as(c_uint, 8));
    pub const flags_a8r8g8b8: MemoryFormatSelection = @bitCast(@as(c_uint, 16));
    pub const flags_r8g8b8a8: MemoryFormatSelection = @bitCast(@as(c_uint, 32));
    pub const flags_a8b8g8r8: MemoryFormatSelection = @bitCast(@as(c_uint, 64));
    pub const flags_r8g8b8: MemoryFormatSelection = @bitCast(@as(c_uint, 128));
    pub const flags_b8g8r8: MemoryFormatSelection = @bitCast(@as(c_uint, 256));
    pub const flags_r16g16b16: MemoryFormatSelection = @bitCast(@as(c_uint, 512));
    pub const flags_r16g16b16a16_premultiplied: MemoryFormatSelection = @bitCast(@as(c_uint, 1024));
    pub const flags_r16g16b16a16: MemoryFormatSelection = @bitCast(@as(c_uint, 2048));
    pub const flags_r16g16b16_float: MemoryFormatSelection = @bitCast(@as(c_uint, 4096));
    pub const flags_r16g16b16a16_float: MemoryFormatSelection = @bitCast(@as(c_uint, 8192));
    pub const flags_r32g32b32_float: MemoryFormatSelection = @bitCast(@as(c_uint, 16384));
    pub const flags_r32g32b32a32_float_premultiplied: MemoryFormatSelection = @bitCast(@as(c_uint, 32768));
    pub const flags_r32g32b32a32_float: MemoryFormatSelection = @bitCast(@as(c_uint, 65536));
    pub const flags_g8a8_premultiplied: MemoryFormatSelection = @bitCast(@as(c_uint, 131072));
    pub const flags_g8a8: MemoryFormatSelection = @bitCast(@as(c_uint, 262144));
    pub const flags_g8: MemoryFormatSelection = @bitCast(@as(c_uint, 524288));
    pub const flags_g16a16_premultiplied: MemoryFormatSelection = @bitCast(@as(c_uint, 1048576));
    pub const flags_g16a16: MemoryFormatSelection = @bitCast(@as(c_uint, 2097152));
    pub const flags_g16: MemoryFormatSelection = @bitCast(@as(c_uint, 4194304));
    extern fn gly_memory_format_selection_get_type() usize;
    pub const getGObjectType = gly_memory_format_selection_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const LoaderGetMimeTypesDoneFunc = *const fn (p_mime_types: [*][*:0]u8, p_data: ?*anyopaque) callconv(.c) void;

test {
    @setEvalBranchQuota(100_000);
    std.testing.refAllDecls(@This());
    std.testing.refAllDecls(ext);
}
