### ----------------------------------------------------
### -- Imlib2
### -- Licenses: Artistic-2.0
### -- Authors: Naoum Hankache, Henrique Dias
### -- File: lib/Imlib2.rakumod
### ----------------------------------------------------
### -- Chunk 1 of 3
use NativeCall;
use LibraryMake;

enum TextDirection <
	IMLIB_TEXT_TO_RIGHT
	IMLIB_TEXT_TO_LEFT
	IMLIB_TEXT_TO_DOWN
	IMLIB_TEXT_TO_UP
	IMLIB_TEXT_TO_ANGLE>;

enum LoadError <
	IMLIB_LOAD_ERROR_NONE
	IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST
	IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY
	IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ
	IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT
	IMLIB_LOAD_ERROR_PATH_TOO_LONG
	IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT
	IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY
	IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE
	IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS
	IMLIB_LOAD_ERROR_OUT_OF_MEMORY
	IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS
	IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE
	IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE
	IMLIB_LOAD_ERROR_UNKNOWN>;

enum RotationMode <
	IMLIB_ROTATE_NONE
	IMLIB_ROTATE_90_DEGREES
	IMLIB_ROTATE_180_DEGREES
	IMLIB_ROTATE_270_DEGREES>;

enum OperationMode <
	IMLIB_OP_COPY
	IMLIB_OP_ADD
	IMLIB_OP_SUBTRACT
	IMLIB_OP_RESHADE>;

enum FlipMode <
	IMLIB_FLIP_HORIZONTAL
	IMLIB_FLIP_VERTICAL
	IMLIB_FLIP_DIAGONAL>;

enum TileMode <
	IMLIB_TILE_HORIZONTAL
	IMLIB_TILE_VERTICAL
	IMLIB_TILE_BOTH>;

class Imlib2::Border {
	has Int $.left is rw = 0;
	has Int $.right is rw = 0;
	has Int $.top is rw = 0;
	has Int $.bottom is rw = 0;

	sub p6_imlib_init_border(int32, int32, int32, int32)
		returns OpaquePointer  { ... };
    trait_mod:<is>(&p6_imlib_init_border, :native('Imlib2', v1));

	sub p6_imlib_put_border(OpaquePointer, int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&p6_imlib_put_border, :native('Imlib2', v1));

	sub p6_imlib_get_border(OpaquePointer)
		returns CArray[int32]  { ... };
    trait_mod:<is>(&p6_imlib_get_border, :native('Imlib2', v1));

	method init() returns OpaquePointer {
		return p6_imlib_init_border($.left, $.right, $.top, $.bottom);
	}

	method put(OpaquePointer $border) {
		p6_imlib_put_border($border, $.left, $.right, $.top, $.bottom);
	}

	method get(OpaquePointer $border) {
		my @array := p6_imlib_get_border($border);
		$.left = @array[0];
		$.right = @array[1];
		$.top = @array[2];
		$.bottom = @array[3];
	}
}

class Imlib2::Color is repr('CStruct') {
	has int32 $.alpha;
	has int32 $.red;
	has int32 $.green;
	has int32 $.blue;

	# this is a workaround, since NativeCall doesn't yet handle sized ints right
	method alpha() { return $!alpha; }
	method red() { return $!red; }
	method green() { return $!green; }
	method blue() { return $!blue; }
}

class Imlib2::ColorModifier is repr('CPointer') {
	sub imlib_context_set_color_modifier(Imlib2::ColorModifier)
		 { ... };
    trait_mod:<is>(&imlib_context_set_color_modifier, :native('Imlib2', v1));

	method context_set() {
		imlib_context_set_color_modifier(self);
	}
}

class Imlib2::ColorRange is repr('CPointer') {
	sub imlib_context_set_color_range(Imlib2::ColorRange)
		 { ... };
    trait_mod:<is>(&imlib_context_set_color_range, :native('Imlib2', v1));

	method context_set() {
		imlib_context_set_color_range(self);
	}
}

class Imlib2::Font is repr('CPointer') {
	sub imlib_context_set_font(Imlib2::Font)
		 { ... };
    trait_mod:<is>(&imlib_context_set_font, :native('Imlib2', v1));

	method context_set() {
		imlib_context_set_font(self);
	}
}

class Imlib2::Updates is repr('CPointer') {

}

class Imlib2::Image is repr('CPointer') {
	sub imlib_context_set_image(Imlib2::Image)
		 { ... };
    trait_mod:<is>(&imlib_context_set_image, :native('Imlib2', v1));

	sub p6_create_transparent_image(Imlib2::Image, int32)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&p6_create_transparent_image, :native('Imlib2', v1));

	method context_set() {
		imlib_context_set_image(self);
	}

	method create_transparent_image(Int $alpha where 0 .. 255) {
		return p6_create_transparent_image(self, $alpha);
	}
}

class Imlib2::Polygon is repr('CPointer') {
	sub imlib_polygon_add_point(Imlib2::Polygon, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_polygon_add_point, :native('Imlib2', v1));

	sub imlib_polygon_contains_point(Imlib2::Polygon, int32, int32)
		returns int8  { ... };
    trait_mod:<is>(&imlib_polygon_contains_point, :native('Imlib2', v1));

	sub imlib_polygon_get_bounds(Imlib2::Polygon $poly,
			CArray[int32] $px1, CArray[int32] $py1,
			CArray[int32] $px2, CArray[int32] $py2)
		 { ... };
    trait_mod:<is>(&imlib_polygon_get_bounds, :native('Imlib2', v1));

	sub imlib_polygon_free(Imlib2::Polygon)
		 { ... };
    trait_mod:<is>(&imlib_polygon_free, :native('Imlib2', v1));

	method add_point(Int $x, Int $y) {
		imlib_polygon_add_point(self, $x, $y);
	}

	method contains_point(Int $x, Int $y) returns Bool {
		return imlib_polygon_contains_point(self, $x, $y).Bool;
	}

	method get_bounds() {
		my @px1 := CArray[int32].new();
		my @py1 := CArray[int32].new();
		my @px2 := CArray[int32].new();
		my @py2 := CArray[int32].new();
		@px1[0] = @py1[0] = @px2[0] = @py2[0] = 0;

		imlib_polygon_get_bounds(self, @px1, @py1, @px2, @py2);

		return (@px1[0], @py1[0], @px2[0], @py2[0]);
	}

	method free() {
		imlib_polygon_free(self);
	}
}

class Imlib2 is repr('CPointer') {

	### context setting/getting ###

	sub imlib_context_set_dither_mask(int8)
		 { ... };
    trait_mod:<is>(&imlib_context_set_dither_mask, :native('Imlib2', v1));

	sub imlib_context_get_dither_mask()
		returns int8  { ... };
    trait_mod:<is>(&imlib_context_get_dither_mask, :native('Imlib2', v1));

	sub imlib_context_set_anti_alias(int8)
		 { ... };
    trait_mod:<is>(&imlib_context_set_anti_alias, :native('Imlib2', v1));

	sub imlib_context_get_anti_alias()
		returns int8  { ... };
    trait_mod:<is>(&imlib_context_get_anti_alias, :native('Imlib2', v1));

	sub imlib_context_set_mask_alpha_threshold(int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_mask_alpha_threshold, :native('Imlib2', v1));

	sub imlib_context_get_mask_alpha_threshold()
		returns int32  { ... };
    trait_mod:<is>(&imlib_context_get_mask_alpha_threshold, :native('Imlib2', v1));

	sub imlib_context_set_dither(int8)
		 { ... };
    trait_mod:<is>(&imlib_context_set_dither, :native('Imlib2', v1));

	sub imlib_context_get_dither()
		returns int8  { ... };
    trait_mod:<is>(&imlib_context_get_dither, :native('Imlib2', v1));

	sub imlib_context_set_blend(int8)
		 { ... };
    trait_mod:<is>(&imlib_context_set_blend, :native('Imlib2', v1));

	sub imlib_context_get_blend()
		returns int8  { ... };
    trait_mod:<is>(&imlib_context_get_blend, :native('Imlib2', v1));

	sub imlib_context_get_color_modifier()
		returns Imlib2::ColorModifier  { ... };
    trait_mod:<is>(&imlib_context_get_color_modifier, :native('Imlib2', v1));

	sub imlib_context_set_operation(int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_operation, :native('Imlib2', v1));

	sub imlib_context_get_operation()
		returns int32  { ... };
    trait_mod:<is>(&imlib_context_get_operation, :native('Imlib2', v1));

	sub imlib_context_get_font()
		returns Imlib2::Font  { ... };
    trait_mod:<is>(&imlib_context_get_font, :native('Imlib2', v1));

	sub imlib_context_set_direction(int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_direction, :native('Imlib2', v1));

	sub imlib_context_get_direction()
		returns int32  { ... };
    trait_mod:<is>(&imlib_context_get_direction, :native('Imlib2', v1));

	sub imlib_context_set_angle(num64)
		 { ... };
    trait_mod:<is>(&imlib_context_set_angle, :native('Imlib2', v1));

	sub imlib_context_get_angle()
		returns num64  { ... };
    trait_mod:<is>(&imlib_context_get_angle, :native('Imlib2', v1));

	sub imlib_context_set_color(int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_color, :native('Imlib2', v1));

	sub imlib_context_get_color(
			CArray[int32] $red,
			CArray[int32] $green,
			CArray[int32] $blue,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&imlib_context_get_color, :native('Imlib2', v1));

	sub imlib_context_get_imlib_color()
		returns Imlib2::Color  { ... };
    trait_mod:<is>(&imlib_context_get_imlib_color, :native('Imlib2', v1));

	sub imlib_context_set_color_hsva(num32, num32, num32, int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_color_hsva, :native('Imlib2', v1));

	sub imlib_context_get_color_hsva(
			CArray[num32] $hue,
			CArray[num32] $saturation,
			CArray[num32] $value,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&imlib_context_get_color_hsva, :native('Imlib2', v1));

	sub imlib_context_set_color_hlsa(num32, num32, num32, int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_color_hlsa, :native('Imlib2', v1));

	sub imlib_context_get_color_hlsa(
			CArray[num32] $hue,
			CArray[num32] $lightness,
			CArray[num32] $saturation,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&imlib_context_get_color_hlsa, :native('Imlib2', v1));

	sub imlib_context_set_color_cmya(int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_color_cmya, :native('Imlib2', v1));

	sub imlib_context_get_color_cmya(
			CArray[int32] $cyan,
			CArray[int32] $magenta,
			CArray[int32] $yellow,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&imlib_context_get_color_cmya, :native('Imlib2', v1));

	sub imlib_context_get_color_range()
		returns Imlib2::ColorRange  { ... };
    trait_mod:<is>(&imlib_context_get_color_range, :native('Imlib2', v1));

	sub imlib_context_get_image()
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_context_get_image, :native('Imlib2', v1));

	sub imlib_context_set_cliprect(int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_context_set_cliprect, :native('Imlib2', v1));

	sub imlib_context_get_cliprect(CArray[int32] $x, CArray[int32] $y,
			CArray[int32] $w, CArray[int32] $h)
		 { ... };
    trait_mod:<is>(&imlib_context_get_cliprect, :native('Imlib2', v1));

	sub imlib_set_cache_size(int32)
		 { ... };
    trait_mod:<is>(&imlib_set_cache_size, :native('Imlib2', v1));

	sub imlib_get_cache_size()
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_cache_size, :native('Imlib2', v1));

	sub imlib_set_color_usage(int32)
		 { ... };
    trait_mod:<is>(&imlib_set_color_usage, :native('Imlib2', v1));

	sub imlib_get_color_usage()
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_color_usage, :native('Imlib2', v1));

	### loading functions ###

	sub imlib_load_image(Str)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_load_image, :native('Imlib2', v1));

	sub imlib_load_image_immediately(Str)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_load_image_immediately, :native('Imlib2', v1));

	sub imlib_load_image_without_cache(Str)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_load_image_without_cache, :native('Imlib2', v1));

	sub imlib_load_image_immediately_without_cache(Str)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_load_image_immediately_without_cache, :native('Imlib2', v1));

	sub imlib_load_image_with_error_return(Str $filename, CArray[int32] $error_return)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_load_image_with_error_return, :native('Imlib2', v1));

	sub imlib_free_image()
		 { ... };
    trait_mod:<is>(&imlib_free_image, :native('Imlib2', v1));

	sub imlib_free_image_and_decache()
		 { ... };
    trait_mod:<is>(&imlib_free_image_and_decache, :native('Imlib2', v1));

	sub imlib_flush_loaders()
		 { ... };
    trait_mod:<is>(&imlib_flush_loaders, :native('Imlib2', v1));

	### query/modify image parameters ###

	sub imlib_image_get_width()
		returns int32  { ... };
    trait_mod:<is>(&imlib_image_get_width, :native('Imlib2', v1));

	sub imlib_image_get_height()
		returns int32  { ... };
    trait_mod:<is>(&imlib_image_get_height, :native('Imlib2', v1));

	sub imlib_image_get_filename()
		returns Str  { ... };
    trait_mod:<is>(&imlib_image_get_filename, :native('Imlib2', v1));

	sub imlib_image_set_has_alpha(int8)
		 { ... };
    trait_mod:<is>(&imlib_image_set_has_alpha, :native('Imlib2', v1));

	sub imlib_image_has_alpha()
		returns int8  { ... };
    trait_mod:<is>(&imlib_image_has_alpha, :native('Imlib2', v1));

	sub imlib_image_set_changes_on_disk()
		 { ... };
    trait_mod:<is>(&imlib_image_set_changes_on_disk, :native('Imlib2', v1));

	sub imlib_image_set_border(OpaquePointer)
		 { ... };
    trait_mod:<is>(&imlib_image_set_border, :native('Imlib2', v1));

	sub imlib_image_get_border(OpaquePointer)
		 { ... };
    trait_mod:<is>(&imlib_image_get_border, :native('Imlib2', v1));

	sub imlib_image_set_format(Str)
		 { ... };
    trait_mod:<is>(&imlib_image_set_format, :native('Imlib2', v1));

	sub imlib_image_format()
		returns Str  { ... };
    trait_mod:<is>(&imlib_image_format, :native('Imlib2', v1));

	sub imlib_image_set_irrelevant_format(int8)
		 { ... };
    trait_mod:<is>(&imlib_image_set_irrelevant_format, :native('Imlib2', v1));

	sub p6_imlib_image_query_pixel(
			int32 $x,
			int32 $y,
			CArray[int32] $red,
			CArray[int32] $green,
			CArray[int32] $blue,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&p6_imlib_image_query_pixel, :native('Imlib2', v1));

	sub imlib_image_query_pixel_hsva(
			int32 $x,
			int32 $y,
			CArray[num32] $hue,
			CArray[num32] $saturation,
			CArray[num32] $value,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&imlib_image_query_pixel_hsva, :native('Imlib2', v1));

	sub imlib_image_query_pixel_hlsa(
			int32 $x,
			int32 $y,
			CArray[num32] $hue,
			CArray[num32] $lightness,
			CArray[num32] $saturation,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&imlib_image_query_pixel_hlsa, :native('Imlib2', v1));

	sub imlib_image_query_pixel_cmya(
			int32 $x,
			int32 $y,
			CArray[int32] $cyan,
			CArray[int32] $magenta,
			CArray[int32] $yellow,
			CArray[int32] $alpha)
		 { ... };
    trait_mod:<is>(&imlib_image_query_pixel_cmya, :native('Imlib2', v1));

	sub imlib_image_set_irrelevant_border(int8)
		 { ... };
    trait_mod:<is>(&imlib_image_set_irrelevant_border, :native('Imlib2', v1));

	sub imlib_image_set_irrelevant_alpha(int8)
		 { ... };
    trait_mod:<is>(&imlib_image_set_irrelevant_alpha, :native('Imlib2', v1));

	### rendering functions ###

	sub imlib_blend_image_onto_image(Imlib2, int8, int64, int64, int64, int64, int64, int64, int64, int64)
		 { ... };
    trait_mod:<is>(&imlib_blend_image_onto_image, :native('Imlib2', v1));

	### creation functions ###

	sub imlib_create_image(int32, int32)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_create_image, :native('Imlib2', v1));

	sub imlib_clone_image()
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_clone_image, :native('Imlib2', v1));

	sub imlib_create_cropped_image(int32, int32, int32, int32)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_create_cropped_image, :native('Imlib2', v1));

	sub imlib_create_cropped_scaled_image(int32, int32, int32, int32, int32, int32)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_create_cropped_scaled_image, :native('Imlib2', v1));

	### imlib updates ###

	### image modification ###

	sub imlib_image_flip_horizontal()
		 { ... };
    trait_mod:<is>(&imlib_image_flip_horizontal, :native('Imlib2', v1));

	sub imlib_image_flip_vertical()
		 { ... };
    trait_mod:<is>(&imlib_image_flip_vertical, :native('Imlib2', v1));

	sub imlib_image_flip_diagonal()
		 { ... };
    trait_mod:<is>(&imlib_image_flip_diagonal, :native('Imlib2', v1));

	sub imlib_image_orientate(int32)
		 { ... };
    trait_mod:<is>(&imlib_image_orientate, :native('Imlib2', v1));

	sub imlib_image_blur(int32)
		 { ... };
    trait_mod:<is>(&imlib_image_blur, :native('Imlib2', v1));

	sub imlib_image_sharpen(int32)
		 { ... };
    trait_mod:<is>(&imlib_image_sharpen, :native('Imlib2', v1));

	sub imlib_image_tile()
		 { ... };
    trait_mod:<is>(&imlib_image_tile, :native('Imlib2', v1));

	sub imlib_image_tile_horizontal()
		 { ... };
    trait_mod:<is>(&imlib_image_tile_horizontal, :native('Imlib2', v1));

	sub imlib_image_tile_vertical()
		 { ... };
    trait_mod:<is>(&imlib_image_tile_vertical, :native('Imlib2', v1));

	### fonts and text ###

	sub imlib_load_font(Str)
		returns Imlib2::Font  { ... };
    trait_mod:<is>(&imlib_load_font, :native('Imlib2', v1));

	sub imlib_free_font()
		 { ... };
    trait_mod:<is>(&imlib_free_font, :native('Imlib2', v1));

	sub imlib_text_draw(int32, int32, Str)
		 { ... };
    trait_mod:<is>(&imlib_text_draw, :native('Imlib2', v1));

	sub imlib_text_draw_with_return_metrics(int32 $x, int32 $y, Str $text,
			CArray[int32] $w, CArray[int32] $h, CArray[int32] $ha, CArray[int32] $va)
		 { ... };
    trait_mod:<is>(&imlib_text_draw_with_return_metrics, :native('Imlib2', v1));

	sub imlib_get_text_size(Str $text, CArray[int32] $w, CArray[int32] $h)
		 { ... };
    trait_mod:<is>(&imlib_get_text_size, :native('Imlib2', v1));

	sub imlib_get_text_advance(Str $text, CArray[int32] $ha, CArray[int32] $va)
		 { ... };
    trait_mod:<is>(&imlib_get_text_advance, :native('Imlib2', v1));

	sub imlib_get_text_inset(Str)
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_text_inset, :native('Imlib2', v1));

	sub imlib_text_get_index_and_location(
			Str $text, int32 $x, int32 $y,
			CArray[int32] $cx, CArray[int32] $cy,
			CArray[int32] $cw, CArray[int32] $ch)
		returns int32  { ... };
    trait_mod:<is>(&imlib_text_get_index_and_location, :native('Imlib2', v1));

	sub imlib_text_get_location_at_index(
			Str $text, int32 $x, int32 $y,
			CArray[int32] $cx, CArray[int32] $cy,
			CArray[int32] $cw, CArray[int32] $ch)
		 { ... };
    trait_mod:<is>(&imlib_text_get_location_at_index, :native('Imlib2', v1));

	sub imlib_get_font_ascent()
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_font_ascent, :native('Imlib2', v1));

	sub imlib_get_font_descent()
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_font_descent, :native('Imlib2', v1));

	sub imlib_get_maximum_font_ascent()
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_maximum_font_ascent, :native('Imlib2', v1));

	sub imlib_get_maximum_font_descent()
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_maximum_font_descent, :native('Imlib2', v1));

	sub imlib_add_path_to_font_path(Str)
		 { ... };
    trait_mod:<is>(&imlib_add_path_to_font_path, :native('Imlib2', v1));

	sub imlib_remove_path_from_font_path(Str)
		 { ... };
    trait_mod:<is>(&imlib_remove_path_from_font_path, :native('Imlib2', v1));

	sub imlib_list_font_path(CArray[int32] $number)
		returns CArray[Str]  { ... };
    trait_mod:<is>(&imlib_list_font_path, :native('Imlib2', v1));

	sub imlib_list_fonts(CArray[int32] $number)
		returns CArray[Str]  { ... };
    trait_mod:<is>(&imlib_list_fonts, :native('Imlib2', v1));

	sub imlib_free_font_list(CArray[Str] $list, int32 $number)
		 { ... };
    trait_mod:<is>(&imlib_free_font_list, :native('Imlib2', v1));

	sub imlib_set_font_cache_size(int32)
		 { ... };
    trait_mod:<is>(&imlib_set_font_cache_size, :native('Imlib2', v1));

	sub imlib_get_font_cache_size()
		returns int32  { ... };
    trait_mod:<is>(&imlib_get_font_cache_size, :native('Imlib2', v1));

	sub imlib_flush_font_cache()
		 { ... };
    trait_mod:<is>(&imlib_flush_font_cache, :native('Imlib2', v1));

	### color modifiers ###

	sub imlib_create_color_modifier()
		returns Imlib2::ColorModifier  { ... };
    trait_mod:<is>(&imlib_create_color_modifier, :native('Imlib2', v1));

	sub imlib_free_color_modifier()
		 { ... };
    trait_mod:<is>(&imlib_free_color_modifier, :native('Imlib2', v1));

	sub imlib_modify_color_modifier_brightness(num64)
		 { ... };
    trait_mod:<is>(&imlib_modify_color_modifier_brightness, :native('Imlib2', v1));

	sub imlib_modify_color_modifier_contrast(num64)
		 { ... };
    trait_mod:<is>(&imlib_modify_color_modifier_contrast, :native('Imlib2', v1));

	sub imlib_modify_color_modifier_gamma(num64)
		 { ... };
    trait_mod:<is>(&imlib_modify_color_modifier_gamma, :native('Imlib2', v1));

	sub imlib_set_color_modifier_tables(CArray[int8], CArray[int8], CArray[int8], CArray[int8])
		 { ... };
    trait_mod:<is>(&imlib_set_color_modifier_tables, :native('Imlib2', v1));

	sub imlib_get_color_modifier_tables(CArray[int8], CArray[int8], CArray[int8], CArray[int8])
		 { ... };
    trait_mod:<is>(&imlib_get_color_modifier_tables, :native('Imlib2', v1));

	sub imlib_reset_color_modifier()
		 { ... };
    trait_mod:<is>(&imlib_reset_color_modifier, :native('Imlib2', v1));

	sub imlib_apply_color_modifier()
		 { ... };
    trait_mod:<is>(&imlib_apply_color_modifier, :native('Imlib2', v1));

	sub imlib_apply_color_modifier_to_rectangle(int64, int64, int64, int64)
		 { ... };
    trait_mod:<is>(&imlib_apply_color_modifier_to_rectangle, :native('Imlib2', v1));

	### drawing on images ###

	sub imlib_image_draw_pixel(int32, int32, int8)
		returns Imlib2::Updates  { ... };
    trait_mod:<is>(&imlib_image_draw_pixel, :native('Imlib2', v1));

	sub imlib_image_draw_line(int32, int32, int32, int32, int8)
		returns Imlib2::Updates  { ... };
    trait_mod:<is>(&imlib_image_draw_line, :native('Imlib2', v1));

	sub imlib_image_draw_rectangle(int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_image_draw_rectangle, :native('Imlib2', v1));

	sub imlib_image_fill_rectangle(int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_image_fill_rectangle, :native('Imlib2', v1));

	### polygons ###

	sub imlib_polygon_new()
		returns Imlib2::Polygon  { ... };
    trait_mod:<is>(&imlib_polygon_new, :native('Imlib2', v1));

	sub imlib_image_draw_polygon(Imlib2::Polygon, int8)
		 { ... };
    trait_mod:<is>(&imlib_image_draw_polygon, :native('Imlib2', v1));

	sub imlib_image_fill_polygon(Imlib2::Polygon)
		 { ... };
    trait_mod:<is>(&imlib_image_fill_polygon, :native('Imlib2', v1));

	### ellipses/circumferences ###

	sub imlib_image_draw_ellipse(int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_image_draw_ellipse, :native('Imlib2', v1));

	sub imlib_image_fill_ellipse(int32, int32, int32, int32)
		 { ... };
    trait_mod:<is>(&imlib_image_fill_ellipse, :native('Imlib2', v1));

	### color ranges ###

	sub imlib_create_color_range()
		returns Imlib2::ColorRange  { ... };
    trait_mod:<is>(&imlib_create_color_range, :native('Imlib2', v1));

	sub imlib_free_color_range()
		 { ... };
    trait_mod:<is>(&imlib_free_color_range, :native('Imlib2', v1));

	sub imlib_add_color_to_color_range(int32)
		 { ... };
    trait_mod:<is>(&imlib_add_color_to_color_range, :native('Imlib2', v1));

	sub imlib_image_fill_color_range_rectangle(int32, int32, int32, int32, num64)
		 { ... };
    trait_mod:<is>(&imlib_image_fill_color_range_rectangle, :native('Imlib2', v1));

	sub imlib_image_fill_hsva_color_range_rectangle(int32, int32, int32, int32, num64)
		 { ... };
    trait_mod:<is>(&imlib_image_fill_hsva_color_range_rectangle, :native('Imlib2', v1));

	### saving ###

	sub imlib_save_image(Str)
		 { ... };
    trait_mod:<is>(&imlib_save_image, :native('Imlib2', v1));

	sub imlib_save_image_with_error_return(Str $filename, CArray[int32] $error_return)
		 { ... };
    trait_mod:<is>(&imlib_save_image_with_error_return, :native('Imlib2', v1));

	### rotation/skewing ###

	sub imlib_create_rotated_image(num64)
		returns Imlib2::Image  { ... };
    trait_mod:<is>(&imlib_create_rotated_image, :native('Imlib2', v1));

	### image filters ###

	sub imlib_image_clear()
		 { ... };
    trait_mod:<is>(&imlib_image_clear, :native('Imlib2', v1));

	### auxiliary functions ###

	sub copy_CArray2p6Array(@carray, Int $number_elements) returns Array {
		my @p6array;
		loop (my $i=0; $i < $number_elements; $i++) {
			@p6array.push(@carray[$i]);
		}
		return @p6array;
	}

	sub init_table(@table = ()) {
		my $ctable = CArray[int8].new();
		if @table.elems {
			$ctable[$_] = @table[$_].Int for 0..255;
		} else {
			$ctable[$_] = 0 for 0..255;
		}
		return $ctable;
	}

	### METHODS ###

	method new() {
		return self;
	}

	### context setting/getting ###

	method context_set_dither_mask(Bool $dither_mask) {
		imlib_context_set_dither_mask($dither_mask ?? 1 !! 0);
	}

	method context_get_dither_mask() returns Bool {
		return imlib_context_get_dither_mask().Bool;
	}

	method context_set_anti_alias(Bool $anti_alias) {
		imlib_context_set_anti_alias($anti_alias ?? 1 !! 0);
	}

	method context_get_anti_alias() returns Bool {
		return imlib_context_get_anti_alias().Bool;
	}

	method context_set_mask_alpha_threshold(Int $mask_alpha_threshold where 0..255) {
		imlib_context_set_mask_alpha_threshold($mask_alpha_threshold);
	}

	method context_get_mask_alpha_threshold() returns Int {
		return imlib_context_get_mask_alpha_threshold();
	}

	method context_set_dither(Bool $dither) {
		imlib_context_set_dither($dither ?? 1 !! 0);
	}

	method context_get_dither() returns Bool {
		return imlib_context_get_dither().Bool;
	}

	method context_set_blend(Bool $blend) {
		imlib_context_set_blend($blend ?? 1 !! 0);
	}

	method context_get_blend() returns Bool {
		return imlib_context_get_blend().Bool;
	}

	method context_get_color_modifier() returns Imlib2::ColorModifier {
		return imlib_context_get_color_modifier();
	}

	method context_set_operation(OperationMode $operation) {
		imlib_context_set_operation($operation.value);
	}

	method context_get_operation() returns OperationMode {
		return OperationMode(imlib_context_get_operation());
	}

	method context_get_font() returns Imlib2::Font {
		return imlib_context_get_font();
	}

	method context_set_direction(TextDirection $text