/* image.c generated by valac 0.56.19, the Vala compiler
 * generated from image.vala, do not modify */

/*
* Copyright (c) 2009-2013 Yorba Foundation
*
* This program 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 program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/

#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gdk/gdk.h>
#include <cairo-gobject.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "io.elementary.photos.h"
#include <float.h>
#include <math.h>

#define MIN_SCALED_WIDTH 10
#define MIN_SCALED_HEIGHT 10
#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

#define _pixel_transformation_unref0(var) ((var == NULL) ? NULL : (var = (pixel_transformation_unref (var), NULL)))
#define _pixel_transformer_unref0(var) ((var == NULL) ? NULL : (var = (pixel_transformer_unref (var), NULL)))
#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL)))
#define _cairo_surface_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_surface_destroy (var), NULL)))
#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);

VALA_EXTERN void parse_color (const gchar* spec,
                  GdkRGBA* result);
VALA_EXTERN void fetch_color (const gchar* spec,
                  GdkRGBA* result);
VALA_EXTERN void set_source_color_from_string (cairo_t* ctx,
                                   const gchar* spec);
VALA_EXTERN GdkPixbuf* scale_pixbuf (GdkPixbuf* pixbuf,
                         gint scale,
                         GdkInterpType interp,
                         gboolean scale_up);
VALA_EXTERN GdkPixbuf* resize_pixbuf (GdkPixbuf* pixbuf,
                          Dimensions* resized,
                          GdkInterpType interp);
VALA_EXTERN guchar shift_color_byte (gint b,
                         gint shift);
VALA_EXTERN gboolean coord_in_rectangle (gint x,
                             gint y,
                             GdkRectangle* rect);
VALA_EXTERN void fix_cairo_pixbuf (GdkPixbuf* pixbuf);
VALA_EXTERN void compute_arb_rotated_size (gdouble src_width,
                               gdouble src_height,
                               gdouble angle,
                               gdouble* dest_width,
                               gdouble* dest_height);
VALA_EXTERN gdouble degrees_to_radians (gdouble theta);
VALA_EXTERN GdkPixbuf* rotate_arb (GdkPixbuf* source_pixbuf,
                       gdouble angle);
VALA_EXTERN void rotate_point_arb (GdkPoint* source_point,
                       gint img_w,
                       gint img_h,
                       gdouble angle,
                       gboolean invert,
                       GdkPoint* result);
VALA_EXTERN void derotate_point_arb (GdkPoint* source_point,
                         gint img_w,
                         gint img_h,
                         gdouble angle,
                         GdkPoint* result);
VALA_EXTERN void clamp_inside_rotated_image (Box* src,
                                 gint img_w,
                                 gint img_h,
                                 gdouble angle_deg,
                                 gboolean preserve_geom,
                                 Box* result);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

void
parse_color (const gchar* spec,
             GdkRGBA* result)
{
	GdkRGBA _tmp0_ = {0};
	g_return_if_fail (spec != NULL);
	fetch_color (spec, &_tmp0_);
	*result = _tmp0_;
	return;
}

void
fetch_color (const gchar* spec,
             GdkRGBA* result)
{
	GdkRGBA rgba = {0};
	g_return_if_fail (spec != NULL);
	memset (&rgba, 0, sizeof (GdkRGBA));
	if (!gdk_rgba_parse (&rgba, spec)) {
		g_error ("image.vala:27: Can't parse color %s", spec);
	}
	*result = rgba;
	return;
}

void
set_source_color_from_string (cairo_t* ctx,
                              const gchar* spec)
{
	GdkRGBA rgba = {0};
	GdkRGBA _tmp0_ = {0};
	GdkRGBA _tmp1_;
	GdkRGBA _tmp2_;
	GdkRGBA _tmp3_;
	GdkRGBA _tmp4_;
	g_return_if_fail (ctx != NULL);
	g_return_if_fail (spec != NULL);
	fetch_color (spec, &_tmp0_);
	rgba = _tmp0_;
	_tmp1_ = rgba;
	_tmp2_ = rgba;
	_tmp3_ = rgba;
	_tmp4_ = rgba;
	cairo_set_source_rgba (ctx, _tmp1_.red, _tmp2_.green, _tmp3_.blue, _tmp4_.alpha);
}

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

GdkPixbuf*
scale_pixbuf (GdkPixbuf* pixbuf,
              gint scale,
              GdkInterpType interp,
              gboolean scale_up)
{
	Dimensions original = {0};
	Dimensions _tmp0_ = {0};
	Dimensions scaled = {0};
	Dimensions _tmp1_ = {0};
	gboolean _tmp2_ = FALSE;
	Dimensions _tmp3_;
	Dimensions _tmp4_;
	Dimensions _tmp8_ = {0};
	Dimensions _tmp9_;
	Dimensions _tmp10_;
	GdkPixbuf* _tmp11_;
	GdkPixbuf* result;
	g_return_val_if_fail (pixbuf != NULL, NULL);
	dimensions_for_pixbuf (pixbuf, &_tmp0_);
	original = _tmp0_;
	dimensions_get_scaled (&original, scale, scale_up, &_tmp1_);
	scaled = _tmp1_;
	_tmp3_ = original;
	_tmp4_ = scaled;
	if (_tmp3_.width == _tmp4_.width) {
		Dimensions _tmp5_;
		Dimensions _tmp6_;
		_tmp5_ = original;
		_tmp6_ = scaled;
		_tmp2_ = _tmp5_.height == _tmp6_.height;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		GdkPixbuf* _tmp7_;
		_tmp7_ = _g_object_ref0 (pixbuf);
		result = _tmp7_;
		return result;
	}
	dimensions_with_min (&scaled, MIN_SCALED_WIDTH, MIN_SCALED_HEIGHT, &_tmp8_);
	scaled = _tmp8_;
	_tmp9_ = scaled;
	_tmp10_ = scaled;
	_tmp11_ = gdk_pixbuf_scale_simple (pixbuf, _tmp9_.width, _tmp10_.height, interp);
	result = _tmp11_;
	return result;
}

GdkPixbuf*
resize_pixbuf (GdkPixbuf* pixbuf,
               Dimensions* resized,
               GdkInterpType interp)
{
	Dimensions original = {0};
	Dimensions _tmp0_ = {0};
	gboolean _tmp1_ = FALSE;
	Dimensions _tmp2_;
	Dimensions _tmp3_;
	Dimensions _tmp7_ = {0};
	Dimensions _tmp8_;
	Dimensions _tmp9_;
	GdkPixbuf* _tmp10_;
	GdkPixbuf* result;
	g_return_val_if_fail (pixbuf != NULL, NULL);
	g_return_val_if_fail (resized != NULL, NULL);
	dimensions_for_pixbuf (pixbuf, &_tmp0_);
	original = _tmp0_;
	_tmp2_ = original;
	_tmp3_ = *resized;
	if (_tmp2_.width == _tmp3_.width) {
		Dimensions _tmp4_;
		Dimensions _tmp5_;
		_tmp4_ = original;
		_tmp5_ = *resized;
		_tmp1_ = _tmp4_.height == _tmp5_.height;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		GdkPixbuf* _tmp6_;
		_tmp6_ = _g_object_ref0 (pixbuf);
		result = _tmp6_;
		return result;
	}
	dimensions_with_min (resized, MIN_SCALED_WIDTH, MIN_SCALED_HEIGHT, &_tmp7_);
	*resized = _tmp7_;
	_tmp8_ = *resized;
	_tmp9_ = *resized;
	_tmp10_ = gdk_pixbuf_scale_simple (pixbuf, _tmp8_.width, _tmp9_.height, interp);
	result = _tmp10_;
	return result;
}

inline guchar
shift_color_byte (gint b,
                  gint shift)
{
	guchar result;
	result = (guchar) CLAMP (b + shift, 0, 255);
	return result;
}

void
shift_colors (GdkPixbuf* pixbuf,
              gint red,
              gint green,
              gint blue,
              gint alpha)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	gint width = 0;
	gint height = 0;
	gint rowstride = 0;
	gint channels = 0;
	guchar* pixels = NULL;
	guint8* _tmp4_;
	g_return_if_fail (pixbuf != NULL);
	if (red >= -255) {
		_tmp0_ = red <= 255;
	} else {
		_tmp0_ = FALSE;
	}
	_vala_assert (_tmp0_, "red >= -255 && red <= 255");
	if (green >= -255) {
		_tmp1_ = green <= 255;
	} else {
		_tmp1_ = FALSE;
	}
	_vala_assert (_tmp1_, "green >= -255 && green <= 255");
	if (blue >= -255) {
		_tmp2_ = blue <= 255;
	} else {
		_tmp2_ = FALSE;
	}
	_vala_assert (_tmp2_, "blue >= -255 && blue <= 255");
	if (alpha >= -255) {
		_tmp3_ = alpha <= 255;
	} else {
		_tmp3_ = FALSE;
	}
	_vala_assert (_tmp3_, "alpha >= -255 && alpha <= 255");
	width = gdk_pixbuf_get_width (pixbuf);
	height = gdk_pixbuf_get_height (pixbuf);
	rowstride = gdk_pixbuf_get_rowstride (pixbuf);
	channels = gdk_pixbuf_get_n_channels (pixbuf);
	_tmp4_ = gdk_pixbuf_get_pixels (pixbuf);
	pixels = _tmp4_;
	_vala_assert (channels >= 3, "channels >= 3");
	_vala_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB, "pixbuf.get_colorspace () == Gdk.Colorspace.RGB");
	_vala_assert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8, "pixbuf.get_bits_per_sample () == 8");
	{
		gint y = 0;
		y = 0;
		{
			gboolean _tmp5_ = FALSE;
			_tmp5_ = TRUE;
			while (TRUE) {
				gint y_offset = 0;
				if (!_tmp5_) {
					gint _tmp6_;
					_tmp6_ = y;
					y = _tmp6_ + 1;
				}
				_tmp5_ = FALSE;
				if (!(y < height)) {
					break;
				}
				y_offset = y * rowstride;
				{
					gint x = 0;
					x = 0;
					{
						gboolean _tmp7_ = FALSE;
						_tmp7_ = TRUE;
						while (TRUE) {
							gint offset = 0;
							gboolean _tmp18_ = FALSE;
							if (!_tmp7_) {
								gint _tmp8_;
								_tmp8_ = x;
								x = _tmp8_ + 1;
							}
							_tmp7_ = FALSE;
							if (!(x < width)) {
								break;
							}
							offset = y_offset + (x * channels);
							if (red != 0) {
								guchar* _tmp9_;
								guchar* _tmp10_;
								guchar _tmp11_;
								_tmp9_ = pixels;
								_tmp10_ = pixels;
								_tmp11_ = _tmp10_[offset];
								_tmp9_[offset] = shift_color_byte ((gint) _tmp11_, red);
							}
							if (green != 0) {
								guchar* _tmp12_;
								guchar* _tmp13_;
								guchar _tmp14_;
								_tmp12_ = pixels;
								_tmp13_ = pixels;
								_tmp14_ = _tmp13_[offset + 1];
								_tmp12_[offset + 1] = shift_color_byte ((gint) _tmp14_, green);
							}
							if (blue != 0) {
								guchar* _tmp15_;
								guchar* _tmp16_;
								guchar _tmp17_;
								_tmp15_ = pixels;
								_tmp16_ = pixels;
								_tmp17_ = _tmp16_[offset + 2];
								_tmp15_[offset + 2] = shift_color_byte ((gint) _tmp17_, blue);
							}
							if (alpha != 0) {
								_tmp18_ = channels >= 4;
							} else {
								_tmp18_ = FALSE;
							}
							if (_tmp18_) {
								guchar* _tmp19_;
								guchar* _tmp20_;
								guchar _tmp21_;
								_tmp19_ = pixels;
								_tmp20_ = pixels;
								_tmp21_ = _tmp20_[offset + 3];
								_tmp19_[offset + 3] = shift_color_byte ((gint) _tmp21_, alpha);
							}
						}
					}
				}
			}
		}
	}
}

void
dim_pixbuf (GdkPixbuf* pixbuf)
{
	PixelTransformer* transformer = NULL;
	PixelTransformer* _tmp0_;
	SaturationTransformation* sat = NULL;
	SaturationTransformation* _tmp1_;
	g_return_if_fail (pixbuf != NULL);
	_tmp0_ = pixel_transformer_new ();
	transformer = _tmp0_;
	_tmp1_ = saturation_transformation_new (SATURATION_TRANSFORMATION_MIN_PARAMETER);
	sat = _tmp1_;
	pixel_transformer_attach_transformation (transformer, (PixelTransformation*) sat);
	pixel_transformer_transform_pixbuf (transformer, pixbuf, NULL);
	shift_colors (pixbuf, 0, 0, 0, -100);
	_pixel_transformation_unref0 (sat);
	_pixel_transformer_unref0 (transformer);
}

gboolean
coord_in_rectangle (gint x,
                    gint y,
                    GdkRectangle* rect)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	GdkRectangle _tmp3_;
	gboolean result;
	g_return_val_if_fail (rect != NULL, FALSE);
	_tmp3_ = *rect;
	if (x >= _tmp3_.x) {
		GdkRectangle _tmp4_;
		GdkRectangle _tmp5_;
		_tmp4_ = *rect;
		_tmp5_ = *rect;
		_tmp2_ = x < (_tmp4_.x + _tmp5_.width);
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		GdkRectangle _tmp6_;
		_tmp6_ = *rect;
		_tmp1_ = y >= _tmp6_.y;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		GdkRectangle _tmp7_;
		GdkRectangle _tmp8_;
		_tmp7_ = *rect;
		_tmp8_ = *rect;
		_tmp0_ = y <= (_tmp7_.y + _tmp8_.height);
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

gboolean
rectangles_equal (GdkRectangle* a,
                  GdkRectangle* b)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp2_ = FALSE;
	GdkRectangle _tmp3_;
	GdkRectangle _tmp4_;
	gboolean result;
	g_return_val_if_fail (a != NULL, FALSE);
	g_return_val_if_fail (b != NULL, FALSE);
	_tmp3_ = *a;
	_tmp4_ = *b;
	if (_tmp3_.x == _tmp4_.x) {
		GdkRectangle _tmp5_;
		GdkRectangle _tmp6_;
		_tmp5_ = *a;
		_tmp6_ = *b;
		_tmp2_ = _tmp5_.y == _tmp6_.y;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		GdkRectangle _tmp7_;
		GdkRectangle _tmp8_;
		_tmp7_ = *a;
		_tmp8_ = *b;
		_tmp1_ = _tmp7_.width == _tmp8_.width;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		GdkRectangle _tmp9_;
		GdkRectangle _tmp10_;
		_tmp9_ = *a;
		_tmp10_ = *b;
		_tmp0_ = _tmp9_.height == _tmp10_.height;
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

gchar*
rectangle_to_string (GdkRectangle* rect)
{
	GdkRectangle _tmp0_;
	GdkRectangle _tmp1_;
	GdkRectangle _tmp2_;
	GdkRectangle _tmp3_;
	gchar* _tmp4_;
	gchar* result;
	g_return_val_if_fail (rect != NULL, NULL);
	_tmp0_ = *rect;
	_tmp1_ = *rect;
	_tmp2_ = *rect;
	_tmp3_ = *rect;
	_tmp4_ = g_strdup_printf ("%d,%d %dx%d", _tmp0_.x, _tmp1_.y, _tmp2_.width, _tmp3_.height);
	result = _tmp4_;
	return result;
}

void
clamp_rectangle (GdkRectangle* original,
                 Dimensions* max,
                 GdkRectangle* result)
{
	GdkRectangle rect = {0};
	GdkRectangle _tmp0_;
	Dimensions _tmp1_;
	GdkRectangle _tmp2_;
	Dimensions _tmp3_;
	GdkRectangle _tmp4_;
	Dimensions _tmp5_;
	GdkRectangle _tmp6_;
	Dimensions _tmp7_;
	g_return_if_fail (original != NULL);
	g_return_if_fail (max != NULL);
	memset (&rect, 0, sizeof (GdkRectangle));
	_tmp0_ = *original;
	_tmp1_ = *max;
	rect.x = CLAMP (_tmp0_.x, 0, _tmp1_.width);
	_tmp2_ = *original;
	_tmp3_ = *max;
	rect.y = CLAMP (_tmp2_.y, 0, _tmp3_.height);
	_tmp4_ = *original;
	_tmp5_ = *max;
	rect.width = CLAMP (_tmp4_.width, 0, _tmp5_.width);
	_tmp6_ = *original;
	_tmp7_ = *max;
	rect.height = CLAMP (_tmp6_.height, 0, _tmp7_.height);
	*result = rect;
	return;
}

void
scale_point (GdkPoint* p,
             gdouble factor,
             GdkPoint* result)
{
	GdkPoint _result_ = {0};
	GdkPoint _tmp0_ = {0};
	GdkPoint _tmp1_;
	GdkPoint _tmp2_;
	g_return_if_fail (p != NULL);
	_tmp0_.x = 0;
	_result_ = _tmp0_;
	_tmp1_ = *p;
	_result_.x = (gint) ((factor * _tmp1_.x) + 0.5);
	_tmp2_ = *p;
	_result_.y = (gint) ((factor * _tmp2_.y) + 0.5);
	*result = _result_;
	return;
}

void
add_points (GdkPoint* p1,
            GdkPoint* p2,
            GdkPoint* result)
{
	GdkPoint _result_ = {0};
	GdkPoint _tmp0_ = {0};
	GdkPoint _tmp1_;
	GdkPoint _tmp2_;
	GdkPoint _tmp3_;
	GdkPoint _tmp4_;
	g_return_if_fail (p1 != NULL);
	g_return_if_fail (p2 != NULL);
	_tmp0_.x = 0;
	_result_ = _tmp0_;
	_tmp1_ = *p1;
	_tmp2_ = *p2;
	_result_.x = _tmp1_.x + _tmp2_.x;
	_tmp3_ = *p1;
	_tmp4_ = *p2;
	_result_.y = _tmp3_.y + _tmp4_.y;
	*result = _result_;
	return;
}

void
subtract_points (GdkPoint* p1,
                 GdkPoint* p2,
                 GdkPoint* result)
{
	GdkPoint _result_ = {0};
	GdkPoint _tmp0_ = {0};
	GdkPoint _tmp1_;
	GdkPoint _tmp2_;
	GdkPoint _tmp3_;
	GdkPoint _tmp4_;
	g_return_if_fail (p1 != NULL);
	g_return_if_fail (p2 != NULL);
	_tmp0_.x = 0;
	_result_ = _tmp0_;
	_tmp1_ = *p1;
	_tmp2_ = *p2;
	_result_.x = _tmp1_.x - _tmp2_.x;
	_tmp3_ = *p1;
	_tmp4_ = *p2;
	_result_.y = _tmp3_.y - _tmp4_.y;
	*result = _result_;
	return;
}

void
fix_cairo_pixbuf (GdkPixbuf* pixbuf)
{
	guchar* gdk_pixels = NULL;
	void* _tmp0_;
	void* _tmp1_;
	g_return_if_fail (pixbuf != NULL);
	_tmp0_ = gdk_pixbuf_get_pixels (pixbuf);
	_tmp1_ = _tmp0_;
	gdk_pixels = _tmp1_;
	{
		gint j = 0;
		j = 0;
		{
			gboolean _tmp2_ = FALSE;
			_tmp2_ = TRUE;
			while (TRUE) {
				gint _tmp4_;
				gint _tmp5_;
				guchar* p = NULL;
				guchar* _tmp6_;
				guchar* end = NULL;
				guchar* _tmp7_;
				gint _tmp8_;
				gint _tmp9_;
				guchar* _tmp19_;
				gint _tmp20_;
				gint _tmp21_;
				if (!_tmp2_) {
					gint _tmp3_;
					j = j + 1;
					_tmp3_ = j;
				}
				_tmp2_ = FALSE;
				_tmp4_ = gdk_pixbuf_get_height (pixbuf);
				_tmp5_ = _tmp4_;
				if (!(j < _tmp5_)) {
					break;
				}
				_tmp6_ = gdk_pixels;
				p = _tmp6_;
				_tmp7_ = p;
				_tmp8_ = gdk_pixbuf_get_width (pixbuf);
				_tmp9_ = _tmp8_;
				end = _tmp7_ + (4 * _tmp9_);
				while (TRUE) {
					guchar* _tmp10_;
					guchar* _tmp11_;
					guchar tmp = '\0';
					guchar* _tmp12_;
					guchar _tmp13_;
					guchar* _tmp14_;
					guchar* _tmp15_;
					guchar _tmp16_;
					guchar* _tmp17_;
					guchar* _tmp18_;
					_tmp10_ = p;
					_tmp11_ = end;
					if (!(_tmp10_ < _tmp11_)) {
						break;
					}
					_tmp12_ = p;
					_tmp13_ = _tmp12_[0];
					tmp = _tmp13_;
					_tmp14_ = p;
					_tmp15_ = p;
					_tmp16_ = _tmp15_[2];
					_tmp14_[0] = _tmp16_;
					_tmp17_ = p;
					_tmp17_[2] = tmp;
					_tmp18_ = p;
					p = _tmp18_ + 4;
				}
				_tmp19_ = gdk_pixels;
				_tmp20_ = gdk_pixbuf_get_rowstride (pixbuf);
				_tmp21_ = _tmp20_;
				gdk_pixels = _tmp19_ + _tmp21_;
			}
		}
	}
}

/**
 * Finds the size of the smallest axially-aligned rectangle that could contain
 * a rectangle src_width by src_height, rotated by angle.
 *
 * @param src_width The width of the incoming rectangle.
 * @param src_height The height of the incoming rectangle.
 * @param angle The amount to rotate by, given in degrees.
 * @param dest_width The width of the computed rectangle.
 * @param dest_height The height of the computed rectangle.
 */
void
compute_arb_rotated_size (gdouble src_width,
                          gdouble src_height,
                          gdouble angle,
                          gdouble* dest_width,
                          gdouble* dest_height)
{
	gdouble _vala_dest_width = 0.0;
	gdouble _vala_dest_height = 0.0;
	angle = fabs (degrees_to_radians (angle));
	_vala_assert (angle <= G_PI_2, "angle <= Math.PI_2");
	_vala_dest_width = (src_width * cos (angle)) + (src_height * sin (angle));
	_vala_dest_height = (src_height * cos (angle)) + (src_width * sin (angle));
	if (dest_width) {
		*dest_width = _vala_dest_width;
	}
	if (dest_height) {
		*dest_height = _vala_dest_height;
	}
}

/**
 * Rotates a pixbuf to an arbitrary angle, given in degrees, and returns the rotated pixbuf.
 *
 * @param source_pixbuf The source image that needs to be angled.
 * @param angle The angle the source image should be rotated by.
 */
GdkPixbuf*
rotate_arb (GdkPixbuf* source_pixbuf,
            gdouble angle)
{
	gdouble x_tmp = 0.0;
	gdouble y_tmp = 0.0;
	gint _tmp1_;
	gint _tmp2_;
	gint _tmp3_;
	gint _tmp4_;
	gdouble _tmp5_ = 0.0;
	gdouble _tmp6_ = 0.0;
	GdkPixbuf* dest_pixbuf = NULL;
	GdkPixbuf* _tmp7_;
	cairo_format_t _tmp8_ = 0;
	gboolean _tmp9_;
	gboolean _tmp10_;
	cairo_surface_t* surface = NULL;
	GdkPixbuf* _tmp11_;
	void* _tmp12_;
	void* _tmp13_;
	GdkPixbuf* _tmp14_;
	gint _tmp15_;
	gint _tmp16_;
	GdkPixbuf* _tmp17_;
	gint _tmp18_;
	gint _tmp19_;
	GdkPixbuf* _tmp20_;
	gint _tmp21_;
	gint _tmp22_;
	cairo_surface_t* _tmp23_;
	cairo_t* context = NULL;
	cairo_surface_t* _tmp24_;
	cairo_t* _tmp25_;
	cairo_t* _tmp26_;
	cairo_t* _tmp27_;
	GdkPixbuf* _tmp28_;
	gint _tmp29_;
	gint _tmp30_;
	GdkPixbuf* _tmp31_;
	gint _tmp32_;
	gint _tmp33_;
	cairo_t* _tmp34_;
	cairo_t* _tmp35_;
	GdkPixbuf* _tmp36_;
	gint _tmp37_;
	gint _tmp38_;
	GdkPixbuf* _tmp39_;
	gint _tmp40_;
	gint _tmp41_;
	cairo_t* _tmp42_;
	cairo_t* _tmp43_;
	gint _tmp44_;
	gint _tmp45_;
	gint _tmp46_;
	gint _tmp47_;
	cairo_t* _tmp48_;
	cairo_t* _tmp49_;
	cairo_pattern_t* _tmp50_;
	cairo_t* _tmp51_;
	GdkPixbuf* _tmp52_;
	GdkPixbuf* result;
	g_return_val_if_fail (source_pixbuf != NULL, NULL);
	if (angle == 0.0) {
		GdkPixbuf* _tmp0_;
		_tmp0_ = _g_object_ref0 (source_pixbuf);
		result = _tmp0_;
		return result;
	}
	_tmp1_ = gdk_pixbuf_get_width (source_pixbuf);
	_tmp2_ = _tmp1_;
	_tmp3_ = gdk_pixbuf_get_height (source_pixbuf);
	_tmp4_ = _tmp3_;
	compute_arb_rotated_size ((gdouble) _tmp2_, (gdouble) _tmp4_, angle, &_tmp5_, &_tmp6_);
	x_tmp = _tmp5_;
	y_tmp = _tmp6_;
	_tmp7_ = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, (gint) round (x_tmp), (gint) round (y_tmp));
	dest_pixbuf = _tmp7_;
	_tmp9_ = gdk_pixbuf_get_has_alpha (source_pixbuf);
	_tmp10_ = _tmp9_;
	if (_tmp10_) {
		_tmp8_ = CAIRO_FORMAT_ARGB32;
	} else {
		_tmp8_ = CAIRO_FORMAT_RGB24;
	}
	_tmp11_ = dest_pixbuf;
	_tmp12_ = gdk_pixbuf_get_pixels (_tmp11_);
	_tmp13_ = _tmp12_;
	_tmp14_ = dest_pixbuf;
	_tmp15_ = gdk_pixbuf_get_width (_tmp14_);
	_tmp16_ = _tmp15_;
	_tmp17_ = dest_pixbuf;
	_tmp18_ = gdk_pixbuf_get_height (_tmp17_);
	_tmp19_ = _tmp18_;
	_tmp20_ = dest_pixbuf;
	_tmp21_ = gdk_pixbuf_get_rowstride (_tmp20_);
	_tmp22_ = _tmp21_;
	_tmp23_ = cairo_image_surface_create_for_data ((guchar*) _tmp13_, _tmp8_, _tmp16_, _tmp19_, _tmp22_);
	surface = _tmp23_;
	_tmp24_ = surface;
	_tmp25_ = cairo_create (_tmp24_);
	context = _tmp25_;
	_tmp26_ = context;
	cairo_set_source_rgb (_tmp26_, (gdouble) 0, (gdouble) 0, (gdouble) 0);
	_tmp27_ = context;
	_tmp28_ = dest_pixbuf;
	_tmp29_ = gdk_pixbuf_get_width (_tmp28_);
	_tmp30_ = _tmp29_;
	_tmp31_ = dest_pixbuf;
	_tmp32_ = gdk_pixbuf_get_height (_tmp31_);
	_tmp33_ = _tmp32_;
	cairo_rectangle (_tmp27_, (gdouble) 0, (gdouble) 0, (gdouble) _tmp30_, (gdouble) _tmp33_);
	_tmp34_ = context;
	cairo_fill (_tmp34_);
	_tmp35_ = context;
	_tmp36_ = dest_pixbuf;
	_tmp37_ = gdk_pixbuf_get_width (_tmp36_);
	_tmp38_ = _tmp37_;
	_tmp39_ = dest_pixbuf;
	_tmp40_ = gdk_pixbuf_get_height (_tmp39_);
	_tmp41_ = _tmp40_;
	cairo_translate (_tmp35_, (gdouble) (_tmp38_ / 2), (gdouble) (_tmp41_ / 2));
	_tmp42_ = context;
	cairo_rotate (_tmp42_, degrees_to_radians (angle));
	_tmp43_ = context;
	_tmp44_ = gdk_pixbuf_get_width (source_pixbuf);
	_tmp45_ = _tmp44_;
	_tmp46_ = gdk_pixbuf_get_height (source_pixbuf);
	_tmp47_ = _tmp46_;
	cairo_translate (_tmp43_, (gdouble) ((-_tmp45_) / 2), (gdouble) ((-_tmp47_) / 2));
	_tmp48_ = context;
	gdk_cairo_set_source_pixbuf (_tmp48_, source_pixbuf, (gdouble) 0, (gdouble) 0);
	_tmp49_ = context;
	_tmp50_ = cairo_get_source (_tmp49_);
	cairo_pattern_set_filter (_tmp50_, CAIRO_FILTER_BEST);
	_tmp51_ = context;
	cairo_paint (_tmp51_);
	_tmp52_ = dest_pixbuf;
	fix_cairo_pixbuf (_tmp52_);
	result = dest_pixbuf;
	_cairo_destroy0 (context);
	_cairo_surface_destroy0 (surface);
	return result;
}

/**
 * Rotates a point around the upper left corner of an image to an arbitrary angle,
 * given in degrees, and returns the rotated point, translated such that it, along with its attendant
 * image, are in positive x, positive y.
 *
 * Note: May be subject to slight inaccuracy as Gdk points' coordinates may only be in whole pixels,
 * so the fractional component is lost.
 *
 * @param source_point The point to be rotated and scaled.
 * @param img_w The width of the source image (unrotated).
 * @param img_h The height of the source image (unrotated).
 * @param angle The angle the source image is to be rotated by to straighten it.
 */
void
rotate_point_arb (GdkPoint* source_point,
                  gint img_w,
                  gint img_h,
                  gdouble angle,
                  gboolean invert,
                  GdkPoint* result)
{
	gdouble dest_width = 0.0;
	gdouble dest_height = 0.0;
	gdouble _tmp1_ = 0.0;
	gdouble _tmp2_ = 0.0;
	cairo_matrix_t matrix = {0};
	gdouble dest_x = 0.0;
	GdkPoint _tmp3_;
	gdouble dest_y = 0.0;
	GdkPoint _tmp4_;
	GdkPoint _tmp5_ = {0};
	g_return_if_fail (source_point != NULL);
	if (angle == 0.0) {
		GdkPoint _tmp0_;
		_tmp0_ = *source_point;
		*result = _tmp0_;
		return;
	}
	compute_arb_rotated_size ((gdouble) img_w, (gdouble) img_h, angle, &_tmp1_, &_tmp2_);
	dest_width = _tmp1_;
	dest_height = _tmp2_;
	cairo_matrix_init_identity (&matrix);
	cairo_matrix_translate (&matrix, dest_width / 2, dest_height / 2);
	cairo_matrix_rotate (&matrix, degrees_to_radians (angle));
	cairo_matrix_translate (&matrix, (gdouble) ((-img_w) / 2), (gdouble) ((-img_h) / 2));
	if (invert) {
		_vala_assert (cairo_matrix_invert (&matrix) == CAIRO_STATUS_SUCCESS, "matrix.invert () == Cairo.Status.SUCCESS");
	}
	_tmp3_ = *source_point;
	dest_x = (gdouble) _tmp3_.x;
	_tmp4_ = *source_point;
	dest_y = (gdouble) _tmp4_.y;
	cairo_matrix_transform_point (&matrix, &dest_x, &dest_y);
	_tmp5_.x = (gint) dest_x;
	_tmp5_.y = (gint) dest_y;
	*result = _tmp5_;
	return;
}

/**
 * <u>De</u>rotates a point around the upper left corner of an image from an arbitrary angle,
 * given in degrees, and returns the de-rotated point, taking into account any translation necessary
 * to make sure all of the rotated image stays in positive x, positive y.
 *
 * Note: May be subject to slight inaccuracy as Gdk points' coordinates may only be in whole pixels,
 * so the fractional component is lost.
 *
 * @param source_point The point to be de-rotated.
 * @param img_w The width of the source image (unrotated).
 * @param img_h The height of the source image (unrotated).
 * @param angle The angle the source image is to be rotated by to straighten it.
 */
void
derotate_point_arb (GdkPoint* source_point,
                    gint img_w,
                    gint img_h,
                    gdouble angle,
                    GdkPoint* result)
{
	GdkPoint _tmp0_;
	GdkPoint _tmp1_ = {0};
	g_return_if_fail (source_point != NULL);
	_tmp0_ = *source_point;
	rotate_point_arb (&_tmp0_, img_w, img_h, angle, TRUE, &_tmp1_);
	*result = _tmp1_;
	return;
}

void
clamp_inside_rotated_image (Box* src,
                            gint img_w,
                            gint img_h,
                            gdouble angle_deg,
                            gboolean preserve_geom,
                            Box* result)
{
	GdkPoint top_left = {0};
	Box _tmp0_;
	Box _tmp1_;
	GdkPoint _tmp2_ = {0};
	GdkPoint _tmp3_ = {0};
	GdkPoint top_right = {0};
	Box _tmp4_;
	Box _tmp5_;
	GdkPoint _tmp6_ = {0};
	GdkPoint _tmp7_ = {0};
	GdkPoint bottom_left = {0};
	Box _tmp8_;
	Box _tmp9_;
	GdkPoint _tmp10_ = {0};
	GdkPoint _tmp11_ = {0};
	GdkPoint bottom_right = {0};
	Box _tmp12_;
	Box _tmp13_;
	GdkPoint _tmp14_ = {0};
	GdkPoint _tmp15_ = {0};
	gdouble angle = 0.0;
	gint top_offset = 0;
	gint bottom_offset = 0;
	gint left_offset = 0;
	gint right_offset = 0;
	gint top = 0;
	GdkPoint _tmp16_;
	GdkPoint _tmp17_;
	gint bottom = 0;
	GdkPoint _tmp18_;
	GdkPoint _tmp19_;
	gint left = 0;
	GdkPoint _tmp20_;
	GdkPoint _tmp21_;
	gint right = 0;
	GdkPoint _tmp22_;
	GdkPoint _tmp23_;
	Box _tmp24_ = {0};
	g_return_if_fail (src != NULL);
	_tmp0_ = *src;
	_tmp1_ = *src;
	_tmp2_.x = _tmp0_.left;
	_tmp2_.y = _tmp1_.top;
	derotate_point_arb (&_tmp2_, img_w, img_h, angle_deg, &_tmp3_);
	top_left = _tmp3_;
	_tmp4_ = *src;
	_tmp5_ = *src;
	_tmp6_.x = _tmp4_.right;
	_tmp6_.y = _tmp5_.top;
	derotate_point_arb (&_tmp6_, img_w, img_h, angle_deg, &_tmp7_);
	top_right = _tmp7_;
	_tmp8_ = *src;
	_tmp9_ = *src;
	_tmp10_.x = _tmp8_.left;
	_tmp10_.y = _tmp9_.bottom;
	derotate_point_arb (&_tmp10_, img_w, img_h, angle_deg, &_tmp11_);
	bottom_left = _tmp11_;
	_tmp12_ = *src;
	_tmp13_ = *src;
	_tmp14_.x = _tmp12_.right;
	_tmp14_.y = _tmp13_.bottom;
	derotate_point_arb (&_tmp14_, img_w, img_h, angle_deg, &_tmp15_);
	bottom_right = _tmp15_;
	angle = degrees_to_radians (angle_deg);
	top_offset = 0;
	bottom_offset = 0;
	left_offset = 0;
	right_offset = 0;
	_tmp16_ = top_left;
	_tmp17_ = top_right;
	top = MIN (_tmp16_.y, _tmp17_.y);
	if (top < 0) {
		top_offset = (gint) ((0 - top) * cos (angle));
	}
	_tmp18_ = bottom_left;
	_tmp19_ = bottom_right;
	bottom = MAX (_tmp18_.y, _tmp19_.y);
	if (bottom > img_h) {
		bottom_offset = (gint) ((img_h - bottom) * cos (angle));
	}
	_tmp20_ = top_left;
	_tmp21_ = bottom_left;
	left = MIN (_tmp20_.x, _tmp21_.x);
	if (left < 0) {
		left_offset = (gint) ((0 - left) * cos (angle));
	}
	_tmp22_ = top_right;
	_tmp23_ = bottom_right;
	right = MAX (_tmp22_.x, _tmp23_.x);
	if (right > img_w) {
		right_offset = (gint) ((img_w - right) * cos (angle));
	}
	if (preserve_geom) {
		Box _tmp25_ = {0};
		box_get_offset (src, left_offset + right_offset, top_offset + bottom_offset, &_tmp25_);
		_tmp24_ = _tmp25_;
	} else {
		Box _tmp26_;
		Box _tmp27_;
		Box _tmp28_;
		Box _tmp29_;
		_tmp26_ = *src;
		_tmp27_ = *src;
		_tmp28_ = *src;
		_tmp29_ = *src;
		box_init (&_tmp24_, _tmp26_.left + left_offset, _tmp27_.top + top_offset, _tmp28_.right + right_offset, _tmp29_.bottom + bottom_offset);
	}
	*result = _tmp24_;
	return;
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

