/* page-view.c generated by valac 0.13.1, the Vala compiler
 * generated from page-view.vala, do not modify */

/*
 * Copyright (C) 2009-2011 Canonical Ltd.
 * Author: Robert Ancell <robert.ancell@canonical.com>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
 * license.
 */

#include <glib.h>
#include <glib-object.h>
#include <gdk-pixbuf/gdk-pixdata.h>
#include <float.h>
#include <math.h>
#include <gdk/gdk.h>
#include <string.h>
#include <stdlib.h>
#include <cairo.h>
#include <gobject/gvaluecollector.h>


#define TYPE_CROP_LOCATION (crop_location_get_type ())

#define TYPE_PAGE_VIEW (page_view_get_type ())
#define PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE_VIEW, PageView))
#define PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE_VIEW, PageViewClass))
#define IS_PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE_VIEW))
#define IS_PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE_VIEW))
#define PAGE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE_VIEW, PageViewClass))

typedef struct _PageView PageView;
typedef struct _PageViewClass PageViewClass;
typedef struct _PageViewPrivate PageViewPrivate;

#define TYPE_PAGE (page_get_type ())
#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page))
#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass))
#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE))
#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE))
#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass))

typedef struct _Page Page;
typedef struct _PageClass PageClass;

#define TYPE_SCAN_DIRECTION (scan_direction_get_type ())
#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
typedef struct _ParamSpecPageView ParamSpecPageView;

typedef enum  {
	CROP_LOCATION_NONE = 0,
	CROP_LOCATION_MIDDLE,
	CROP_LOCATION_TOP,
	CROP_LOCATION_BOTTOM,
	CROP_LOCATION_LEFT,
	CROP_LOCATION_RIGHT,
	CROP_LOCATION_TOP_LEFT,
	CROP_LOCATION_TOP_RIGHT,
	CROP_LOCATION_BOTTOM_LEFT,
	CROP_LOCATION_BOTTOM_RIGHT
} CropLocation;

struct _PageView {
	GTypeInstance parent_instance;
	volatile int ref_count;
	PageViewPrivate * priv;
};

struct _PageViewClass {
	GTypeClass parent_class;
	void (*finalize) (PageView *self);
};

typedef enum  {
	SCAN_DIRECTION_TOP_TO_BOTTOM,
	SCAN_DIRECTION_LEFT_TO_RIGHT,
	SCAN_DIRECTION_BOTTOM_TO_TOP,
	SCAN_DIRECTION_RIGHT_TO_LEFT
} ScanDirection;

struct _PageViewPrivate {
	Page* page;
	GdkPixbuf* image;
	gboolean selected;
	gint border_width;
	gboolean update_image;
	ScanDirection scan_direction;
	gint scan_line;
	gint width;
	gint height;
	gint x_offset;
	gint y_offset;
	CropLocation crop_location;
	gdouble selected_crop_px;
	gdouble selected_crop_py;
	gint selected_crop_x;
	gint selected_crop_y;
	gint selected_crop_w;
	gint selected_crop_h;
	GdkCursorType cursor;
	gint animate_n_segments;
	gint animate_segment;
	guint animate_timeout;
};

struct _ParamSpecPageView {
	GParamSpec parent_instance;
};


static gpointer page_view_parent_class = NULL;

GType crop_location_get_type (void) G_GNUC_CONST;
gpointer page_view_ref (gpointer instance);
void page_view_unref (gpointer instance);
GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_page_view (GValue* value, gpointer v_object);
void value_take_page_view (GValue* value, gpointer v_object);
gpointer value_get_page_view (const GValue* value);
GType page_view_get_type (void) G_GNUC_CONST;
gpointer page_ref (gpointer instance);
void page_unref (gpointer instance);
GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
void value_set_page (GValue* value, gpointer v_object);
void value_take_page (GValue* value, gpointer v_object);
gpointer value_get_page (const GValue* value);
GType page_get_type (void) G_GNUC_CONST;
GType scan_direction_get_type (void) G_GNUC_CONST;
#define PAGE_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PAGE_VIEW, PageViewPrivate))
enum  {
	PAGE_VIEW_DUMMY_PROPERTY
};
PageView* page_view_new (Page* page);
PageView* page_view_construct (GType object_type, Page* page);
static void page_view_page_pixels_changed_cb (PageView* self, Page* p);
static void _page_view_page_pixels_changed_cb_page_pixels_changed (Page* _sender, gpointer self);
static void page_view_page_size_changed_cb (PageView* self, Page* p);
static void _page_view_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self);
static void page_view_page_overlay_changed_cb (PageView* self, Page* p);
static void _page_view_page_overlay_changed_cb_page_crop_changed (Page* _sender, gpointer self);
static void _page_view_page_overlay_changed_cb_page_scan_line_changed (Page* _sender, gpointer self);
static void page_view_scan_direction_changed_cb (PageView* self, Page* p);
static void _page_view_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self);
Page* page_view_get_page (PageView* self);
void page_view_set_selected (PageView* self, gboolean selected);
gboolean page_view_get_selected (PageView* self);
void page_view_set_x_offset (PageView* self, gint offset);
void page_view_set_y_offset (PageView* self, gint offset);
gint page_view_get_x_offset (PageView* self);
gint page_view_get_y_offset (PageView* self);
static guchar page_view_get_sample (PageView* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint sample);
static void page_view_get_pixel (PageView* self, Page* page, gint x, gint y, guchar* pixel, int pixel_length1);
ScanDirection page_get_scan_direction (Page* self);
gint page_get_scan_width (Page* self);
gint page_get_scan_height (Page* self);
gint page_get_depth (Page* self);
gint page_get_n_channels (Page* self);
guchar* page_get_pixels (Page* self, int* result_length1);
gint page_get_rowstride (Page* self);
static void page_view_set_pixel (PageView* self, Page* page, gdouble l, gdouble r, gdouble t, gdouble b, guchar* output, int output_length1, gint offset);
static void page_view_update_preview (PageView* self, Page* page, GdkPixbuf** output_image, gint output_width, gint output_height, ScanDirection scan_direction, gint old_scan_line, gint scan_line);
gint page_get_width (Page* self);
gint page_get_height (Page* self);
gboolean page_has_data (Page* self);
static gint page_view_get_preview_width (PageView* self);
static gint page_view_get_preview_height (PageView* self);
static void page_view_update_page_view (PageView* self);
gint page_get_scan_line (Page* self);
static gint page_view_page_to_screen_x (PageView* self, gint x);
static gint page_view_page_to_screen_y (PageView* self, gint y);
static gint page_view_screen_to_page_x (PageView* self, gint x);
static gint page_view_screen_to_page_y (PageView* self, gint y);
static CropLocation page_view_get_crop_location (PageView* self, gint x, gint y);
gboolean page_has_crop (Page* self);
void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height);
gchar* page_get_named_crop (Page* self);
void page_view_button_press (PageView* self, gint x, gint y);
void page_view_motion (PageView* self, gint x, gint y);
void page_move_crop (Page* self, gint x, gint y);
void page_set_custom_crop (Page* self, gint width, gint height);
void page_view_button_release (PageView* self, gint x, gint y);
GdkCursorType page_view_get_cursor (PageView* self);
static gboolean page_view_animation_cb (PageView* self);
static void page_view_update_animation (PageView* self);
gboolean page_is_scanning (Page* self);
static gboolean _page_view_animation_cb_gsource_func (gpointer self);
void page_view_render (PageView* self, cairo_t* context);
void page_view_set_width (PageView* self, gint width);
void page_view_set_height (PageView* self, gint height);
gint page_view_get_width (PageView* self);
gint page_view_get_height (PageView* self);
static void page_view_finalize (PageView* obj);


GType crop_location_get_type (void) {
	static volatile gsize crop_location_type_id__volatile = 0;
	if (g_once_init_enter (&crop_location_type_id__volatile)) {
		static const GEnumValue values[] = {{CROP_LOCATION_NONE, "CROP_LOCATION_NONE", "none"}, {CROP_LOCATION_MIDDLE, "CROP_LOCATION_MIDDLE", "middle"}, {CROP_LOCATION_TOP, "CROP_LOCATION_TOP", "top"}, {CROP_LOCATION_BOTTOM, "CROP_LOCATION_BOTTOM", "bottom"}, {CROP_LOCATION_LEFT, "CROP_LOCATION_LEFT", "left"}, {CROP_LOCATION_RIGHT, "CROP_LOCATION_RIGHT", "right"}, {CROP_LOCATION_TOP_LEFT, "CROP_LOCATION_TOP_LEFT", "top-left"}, {CROP_LOCATION_TOP_RIGHT, "CROP_LOCATION_TOP_RIGHT", "top-right"}, {CROP_LOCATION_BOTTOM_LEFT, "CROP_LOCATION_BOTTOM_LEFT", "bottom-left"}, {CROP_LOCATION_BOTTOM_RIGHT, "CROP_LOCATION_BOTTOM_RIGHT", "bottom-right"}, {0, NULL, NULL}};
		GType crop_location_type_id;
		crop_location_type_id = g_enum_register_static ("CropLocation", values);
		g_once_init_leave (&crop_location_type_id__volatile, crop_location_type_id);
	}
	return crop_location_type_id__volatile;
}


static gpointer _page_ref0 (gpointer self) {
	return self ? page_ref (self) : NULL;
}


static void _page_view_page_pixels_changed_cb_page_pixels_changed (Page* _sender, gpointer self) {
	page_view_page_pixels_changed_cb (self, _sender);
}


static void _page_view_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self) {
	page_view_page_size_changed_cb (self, _sender);
}


static void _page_view_page_overlay_changed_cb_page_crop_changed (Page* _sender, gpointer self) {
	page_view_page_overlay_changed_cb (self, _sender);
}


static void _page_view_page_overlay_changed_cb_page_scan_line_changed (Page* _sender, gpointer self) {
	page_view_page_overlay_changed_cb (self, _sender);
}


static void _page_view_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self) {
	page_view_scan_direction_changed_cb (self, _sender);
}


PageView* page_view_construct (GType object_type, Page* page) {
	PageView* self = NULL;
	Page* _tmp0_;
	g_return_val_if_fail (page != NULL, NULL);
	self = (PageView*) g_type_create_instance (object_type);
	_tmp0_ = _page_ref0 (page);
	_page_unref0 (self->priv->page);
	self->priv->page = _tmp0_;
	g_signal_connect (page, "pixels-changed", (GCallback) _page_view_page_pixels_changed_cb_page_pixels_changed, self);
	g_signal_connect (page, "size-changed", (GCallback) _page_view_page_size_changed_cb_page_size_changed, self);
	g_signal_connect (page, "crop-changed", (GCallback) _page_view_page_overlay_changed_cb_page_crop_changed, self);
	g_signal_connect (page, "scan-line-changed", (GCallback) _page_view_page_overlay_changed_cb_page_scan_line_changed, self);
	g_signal_connect (page, "scan-direction-changed", (GCallback) _page_view_scan_direction_changed_cb_page_scan_direction_changed, self);
	return self;
}


PageView* page_view_new (Page* page) {
	return page_view_construct (TYPE_PAGE_VIEW, page);
}


Page* page_view_get_page (PageView* self) {
	Page* result = NULL;
	Page* _tmp0_;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = _page_ref0 (self->priv->page);
	result = _tmp0_;
	return result;
}


void page_view_set_selected (PageView* self, gboolean selected) {
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	g_return_if_fail (self != NULL);
	if (self->priv->selected) {
		_tmp1_ = selected;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		gboolean _tmp2_ = FALSE;
		if (!self->priv->selected) {
			_tmp2_ = !selected;
		} else {
			_tmp2_ = FALSE;
		}
		_tmp0_ = _tmp2_;
	}
	if (_tmp0_) {
		return;
	}
	self->priv->selected = selected;
	g_signal_emit_by_name (self, "changed");
}


gboolean page_view_get_selected (PageView* self) {
	gboolean result = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->selected;
	return result;
}


void page_view_set_x_offset (PageView* self, gint offset) {
	g_return_if_fail (self != NULL);
	self->priv->x_offset = offset;
}


void page_view_set_y_offset (PageView* self, gint offset) {
	g_return_if_fail (self != NULL);
	self->priv->y_offset = offset;
}


gint page_view_get_x_offset (PageView* self) {
	gint result = 0;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->x_offset;
	return result;
}


gint page_view_get_y_offset (PageView* self) {
	gint result = 0;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->y_offset;
	return result;
}


static guchar page_view_get_sample (PageView* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint sample) {
	guchar result = '\0';
	g_return_val_if_fail (self != NULL, '\0');
	result = (guchar) 0xFF;
	return result;
}


static void page_view_get_pixel (PageView* self, Page* page, gint x, gint y, guchar* pixel, int pixel_length1) {
	ScanDirection _tmp0_;
	gint _tmp5_;
	gint depth;
	gint _tmp6_;
	gint n_channels;
	gint _tmp7_;
	guchar* _tmp8_ = NULL;
	guchar* pixels;
	gint pixels_length1;
	gint _pixels_size_;
	gint _tmp9_;
	gint offset;
	gboolean _tmp10_ = FALSE;
	guchar _tmp16_;
	guchar _tmp17_;
	guchar _tmp18_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (page != NULL);
	_tmp0_ = page_get_scan_direction (page);
	switch (_tmp0_) {
		case SCAN_DIRECTION_TOP_TO_BOTTOM:
		{
			break;
		}
		case SCAN_DIRECTION_BOTTOM_TO_TOP:
		{
			gint _tmp1_;
			gint _tmp2_;
			_tmp1_ = page_get_scan_width (page);
			x = (_tmp1_ - x) - 1;
			_tmp2_ = page_get_scan_height (page);
			y = (_tmp2_ - y) - 1;
			break;
		}
		case SCAN_DIRECTION_LEFT_TO_RIGHT:
		{
			gint t;
			gint _tmp3_;
			t = x;
			_tmp3_ = page_get_scan_width (page);
			x = (_tmp3_ - y) - 1;
			y = t;
			break;
		}
		case SCAN_DIRECTION_RIGHT_TO_LEFT:
		{
			gint t;
			gint _tmp4_;
			t = x;
			x = y;
			_tmp4_ = page_get_scan_height (page);
			y = (_tmp4_ - t) - 1;
			break;
		}
		default:
		break;
	}
	_tmp5_ = page_get_depth (page);
	depth = _tmp5_;
	_tmp6_ = page_get_n_channels (page);
	n_channels = _tmp6_;
	_tmp8_ = page_get_pixels (page, &_tmp7_);
	pixels = _tmp8_;
	pixels_length1 = _tmp7_;
	_pixels_size_ = pixels_length1;
	_tmp9_ = page_get_rowstride (page);
	offset = _tmp9_ * y;
	if (depth == 8) {
		_tmp10_ = n_channels == 3;
	} else {
		_tmp10_ = FALSE;
	}
	if (_tmp10_) {
		gint o;
		o = offset + (x * n_channels);
		pixel[0] = pixels[o];
		pixel[1] = pixels[o + 1];
		pixel[2] = pixels[o + 2];
		return;
	} else {
		gboolean _tmp11_ = FALSE;
		if (depth == 8) {
			_tmp11_ = n_channels == 1;
		} else {
			_tmp11_ = FALSE;
		}
		if (_tmp11_) {
			pixel[2] = pixels[offset + x];
			pixel[1] = pixel[2];
			pixel[0] = pixel[1];
			return;
		} else {
			gboolean _tmp12_ = FALSE;
			if (depth == 1) {
				_tmp12_ = n_channels == 1;
			} else {
				_tmp12_ = FALSE;
			}
			if (_tmp12_) {
				gint o;
				gint _tmp13_ = 0;
				o = offset + (x / 8);
				if (((gint) (pixels[o] & (0x80 >> (x % 8)))) != 0) {
					_tmp13_ = 0x00;
				} else {
					_tmp13_ = 0xFF;
				}
				pixel[2] = (guchar) _tmp13_;
				pixel[1] = pixel[2];
				pixel[0] = pixel[1];
				return;
			} else {
				gboolean _tmp14_ = FALSE;
				if (depth == 2) {
					_tmp14_ = n_channels == 1;
				} else {
					_tmp14_ = FALSE;
				}
				if (_tmp14_) {
					gint _tmp15_[4] = {0};
					gint block_shift[4];
					gint o;
					gint sample;
					_tmp15_[0] = 6;
					_tmp15_[1] = 4;
					_tmp15_[2] = 2;
					_tmp15_[3] = 0;
					memcpy (block_shift, _tmp15_, 4 * sizeof (gint));
					o = offset + (x / 4);
					sample = (pixels[o] >> block_shift[x % 4]) & 0x3;
					sample = (sample * 255) / 3;
					pixel[2] = (guchar) sample;
					pixel[1] = pixel[2];
					pixel[0] = pixel[1];
					return;
				}
			}
		}
	}
	_tmp16_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, x * n_channels);
	pixel[0] = _tmp16_;
	_tmp17_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, (x * n_channels) + 1);
	pixel[1] = _tmp17_;
	_tmp18_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, (x * n_channels) + 2);
	pixel[2] = _tmp18_;
}


static void page_view_set_pixel (PageView* self, Page* page, gdouble l, gdouble r, gdouble t, gdouble b, guchar* output, int output_length1, gint offset) {
	gint L;
	gint R;
	gint T;
	gint B;
	gdouble red;
	gdouble green;
	gdouble blue;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp10_ = FALSE;
	gboolean _tmp11_ = FALSE;
	gboolean _tmp12_ = FALSE;
	gboolean _tmp13_ = FALSE;
	gdouble scale;
	g_return_if_fail (self != NULL);
	g_return_if_fail (page != NULL);
	L = (gint) l;
	if (((gdouble) L) != l) {
		L++;
	}
	R = (gint) r;
	T = (gint) t;
	if (((gdouble) T) != t) {
		T++;
	}
	B = (gint) b;
	red = 0.0;
	green = 0.0;
	blue = 0.0;
	if ((r - l) <= 1.0) {
		_tmp1_ = ((gint) r) == ((gint) l);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		gboolean _tmp2_ = FALSE;
		if ((b - t) <= 1.0) {
			_tmp2_ = ((gint) b) == ((gint) t);
		} else {
			_tmp2_ = FALSE;
		}
		_tmp0_ = _tmp2_;
	}
	if (_tmp0_) {
		gboolean _tmp3_ = FALSE;
		gdouble scale;
		if (((gint) l) == ((gint) r)) {
			_tmp3_ = TRUE;
		} else {
			_tmp3_ = ((gint) t) == ((gint) b);
		}
		if (_tmp3_) {
			guchar p[3] = {0};
			page_view_get_pixel (self, page, (gint) l, (gint) t, p, 3);
			output[offset] = p[0];
			output[offset + 1] = p[1];
			output[offset + 2] = p[2];
			return;
		}
		if (L > R) {
			guchar p[3] = {0};
			page_view_get_pixel (self, page, R, T - 1, p, 3);
			red = red + ((p[0] * (r - l)) * (T - t));
			green = green + ((p[1] * (r - l)) * (T - t));
			blue = blue + ((p[2] * (r - l)) * (T - t));
			{
				gint y;
				y = T;
				{
					gboolean _tmp4_;
					_tmp4_ = TRUE;
					while (TRUE) {
						if (!_tmp4_) {
							y++;
						}
						_tmp4_ = FALSE;
						if (!(y < B)) {
							break;
						}
						page_view_get_pixel (self, page, R, y, p, 3);
						red = red + (p[0] * (r - l));
						green = green + (p[1] * (r - l));
						blue = blue + (p[2] * (r - l));
					}
				}
			}
			page_view_get_pixel (self, page, R, B, p, 3);
			red = red + ((p[0] * (r - l)) * (b - B));
			green = green + ((p[1] * (r - l)) * (b - B));
			blue = blue + ((p[2] * (r - l)) * (b - B));
		} else {
			guchar p[3] = {0};
			page_view_get_pixel (self, page, L - 1, B, p, 3);
			red = red + ((p[0] * (b - t)) * (L - l));
			green = green + ((p[1] * (b - t)) * (L - l));
			blue = blue + ((p[2] * (b - t)) * (L - l));
			{
				gint x;
				x = L;
				{
					gboolean _tmp5_;
					_tmp5_ = TRUE;
					while (TRUE) {
						if (!_tmp5_) {
							x++;
						}
						_tmp5_ = FALSE;
						if (!(x < R)) {
							break;
						}
						page_view_get_pixel (self, page, x, B, p, 3);
						red = red + (p[0] * (b - t));
						green = green + (p[1] * (b - t));
						blue = blue + (p[2] * (b - t));
					}
				}
			}
			page_view_get_pixel (self, page, R, B, p, 3);
			red = red + ((p[0] * (b - t)) * (r - R));
			green = green + ((p[1] * (b - t)) * (r - R));
			blue = blue + ((p[2] * (b - t)) * (r - R));
		}
		scale = 1.0 / ((r - l) * (b - t));
		output[offset] = (guchar) ((red * scale) + 0.5);
		output[offset + 1] = (guchar) ((green * scale) + 0.5);
		output[offset + 2] = (guchar) ((blue * scale) + 0.5);
		return;
	}
	{
		gint x;
		x = L;
		{
			gboolean _tmp6_;
			_tmp6_ = TRUE;
			while (TRUE) {
				if (!_tmp6_) {
					x++;
				}
				_tmp6_ = FALSE;
				if (!(x < R)) {
					break;
				}
				{
					gint y;
					y = T;
					{
						gboolean _tmp7_;
						_tmp7_ = TRUE;
						while (TRUE) {
							guchar p[3] = {0};
							if (!_tmp7_) {
								y++;
							}
							_tmp7_ = FALSE;
							if (!(y < B)) {
								break;
							}
							page_view_get_pixel (self, page, x, y, p, 3);
							red = red + p[0];
							green = green + p[1];
							blue = blue + p[2];
						}
					}
				}
			}
		}
	}
	{
		gint x;
		x = L;
		{
			gboolean _tmp8_;
			_tmp8_ = TRUE;
			while (TRUE) {
				if (!_tmp8_) {
					x++;
				}
				_tmp8_ = FALSE;
				if (!(x < R)) {
					break;
				}
				if (t != ((gdouble) T)) {
					guchar p[3] = {0};
					page_view_get_pixel (self, page, x, T - 1, p, 3);
					red = red + (p[0] * (T - t));
					green = green + (p[1] * (T - t));
					blue = blue + (p[2] * (T - t));
				}
				if (b != ((gdouble) B)) {
					guchar p[3] = {0};
					page_view_get_pixel (self, page, x, B, p, 3);
					red = red + (p[0] * (b - B));
					green = green + (p[1] * (b - B));
					blue = blue + (p[2] * (b - B));
				}
			}
		}
	}
	{
		gint y;
		y = T;
		{
			gboolean _tmp9_;
			_tmp9_ = TRUE;
			while (TRUE) {
				if (!_tmp9_) {
					y++;
				}
				_tmp9_ = FALSE;
				if (!(y < B)) {
					break;
				}
				if (l != ((gdouble) L)) {
					guchar p[3] = {0};
					page_view_get_pixel (self, page, L - 1, y, p, 3);
					red = red + (p[0] * (L - l));
					green = green + (p[1] * (L - l));
					blue = blue + (p[2] * (L - l));
				}
				if (r != ((gdouble) R)) {
					guchar p[3] = {0};
					page_view_get_pixel (self, page, R, y, p, 3);
					red = red + (p[0] * (r - R));
					green = green + (p[1] * (r - R));
					blue = blue + (p[2] * (r - R));
				}
			}
		}
	}
	if (l != ((gdouble) L)) {
		_tmp10_ = t != ((gdouble) T);
	} else {
		_tmp10_ = FALSE;
	}
	if (_tmp10_) {
		guchar p[3] = {0};
		page_view_get_pixel (self, page, L - 1, T - 1, p, 3);
		red = red + ((p[0] * (L - l)) * (T - t));
		green = green + ((p[1] * (L - l)) * (T - t));
		blue = blue + ((p[2] * (L - l)) * (T - t));
	}
	if (r != ((gdouble) R)) {
		_tmp11_ = t != ((gdouble) T);
	} else {
		_tmp11_ = FALSE;
	}
	if (_tmp11_) {
		guchar p[3] = {0};
		page_view_get_pixel (self, page, R, T - 1, p, 3);
		red = red + ((p[0] * (r - R)) * (T - t));
		green = green + ((p[1] * (r - R)) * (T - t));
		blue = blue + ((p[2] * (r - R)) * (T - t));
	}
	if (r != ((gdouble) R)) {
		_tmp12_ = b != ((gdouble) B);
	} else {
		_tmp12_ = FALSE;
	}
	if (_tmp12_) {
		guchar p[3] = {0};
		page_view_get_pixel (self, page, R, B, p, 3);
		red = red + ((p[0] * (r - R)) * (b - B));
		green = green + ((p[1] * (r - R)) * (b - B));
		blue = blue + ((p[2] * (r - R)) * (b - B));
	}
	if (l != ((gdouble) L)) {
		_tmp13_ = b != ((gdouble) B);
	} else {
		_tmp13_ = FALSE;
	}
	if (_tmp13_) {
		guchar p[3] = {0};
		page_view_get_pixel (self, page, L - 1, B, p, 3);
		red = red + ((p[0] * (L - l)) * (b - B));
		green = green + ((p[1] * (L - l)) * (b - B));
		blue = blue + ((p[2] * (L - l)) * (b - B));
	}
	scale = 1.0 / ((r - l) * (b - t));
	output[offset] = (guchar) ((red * scale) + 0.5);
	output[offset + 1] = (guchar) ((green * scale) + 0.5);
	output[offset + 2] = (guchar) ((blue * scale) + 0.5);
}


static void page_view_update_preview (PageView* self, Page* page, GdkPixbuf** output_image, gint output_width, gint output_height, ScanDirection scan_direction, gint old_scan_line, gint scan_line) {
	gint _tmp0_;
	gint input_width;
	gint _tmp1_;
	gint input_height;
	gint L = 0;
	gint R = 0;
	gint T = 0;
	gint B = 0;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_ = FALSE;
	guint8* _tmp7_ = NULL;
	guchar* output;
	gint output_length1;
	gint _output_size_;
	gint _tmp8_;
	gint output_rowstride;
	gint _tmp9_;
	gint output_n_channels;
	gboolean _tmp10_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (page != NULL);
	_tmp0_ = page_get_width (page);
	input_width = _tmp0_;
	_tmp1_ = page_get_height (page);
	input_height = _tmp1_;
	if ((*output_image) == NULL) {
		_tmp3_ = TRUE;
	} else {
		gint _tmp4_;
		_tmp4_ = gdk_pixbuf_get_width (*output_image);
		_tmp3_ = _tmp4_ != output_width;
	}
	if (_tmp3_) {
		_tmp2_ = TRUE;
	} else {
		gint _tmp5_;
		_tmp5_ = gdk_pixbuf_get_height (*output_image);
		_tmp2_ = _tmp5_ != output_height;
	}
	if (_tmp2_) {
		GdkPixbuf* _tmp6_ = NULL;
		_tmp6_ = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, output_width, output_height);
		_g_object_unref0 (*output_image);
		*output_image = _tmp6_;
		L = 0;
		R = output_width - 1;
		T = 0;
		B = output_height - 1;
	} else {
		switch (scan_direction) {
			case SCAN_DIRECTION_TOP_TO_BOTTOM:
			{
				L = 0;
				R = output_width - 1;
				T = (gint) ((((gdouble) old_scan_line) * output_height) / input_height);
				B = (gint) (((((gdouble) scan_line) * output_height) / input_height) + 0.5);
				break;
			}
			case SCAN_DIRECTION_LEFT_TO_RIGHT:
			{
				L = (gint) ((((gdouble) old_scan_line) * output_width) / input_width);
				R = (gint) (((((gdouble) scan_line) * output_width) / input_width) + 0.5);
				T = 0;
				B = output_height - 1;
				break;
			}
			case SCAN_DIRECTION_BOTTOM_TO_TOP:
			{
				L = 0;
				R = output_width - 1;
				T = (gint) ((((gdouble) (input_height - scan_line)) * output_height) / input_height);
				B = (gint) (((((gdouble) (input_height - old_scan_line)) * output_height) / input_height) + 0.5);
				break;
			}
			case SCAN_DIRECTION_RIGHT_TO_LEFT:
			{
				L = (gint) ((((gdouble) (input_width - scan_line)) * output_width) / input_width);
				R = (gint) (((((gdouble) (input_width - old_scan_line)) * output_width) / input_width) + 0.5);
				T = 0;
				B = output_height - 1;
				break;
			}
			default:
			{
				T = 0;
				B = T;
				R = B;
				L = R;
				break;
			}
		}
	}
	if (R >= output_width) {
		R = output_width - 1;
	}
	if (B >= output_height) {
		B = output_height - 1;
	}
	g_return_if_fail (L >= 0);
	g_return_if_fail (R < output_width);
	g_return_if_fail (T >= 0);
	g_return_if_fail (B < output_height);
	g_return_if_fail ((*output_image) != NULL);
	_tmp7_ = gdk_pixbuf_get_pixels (*output_image);
	output = _tmp7_;
	output_length1 = -1;
	_output_size_ = output_length1;
	_tmp8_ = gdk_pixbuf_get_rowstride (*output_image);
	output_rowstride = _tmp8_;
	_tmp9_ = gdk_pixbuf_get_n_channels (*output_image);
	output_n_channels = _tmp9_;
	_tmp10_ = page_has_data (page);
	if (!_tmp10_) {
		{
			gint x;
			x = L;
			{
				gboolean _tmp11_;
				_tmp11_ = TRUE;
				while (TRUE) {
					if (!_tmp11_) {
						x++;
					}
					_tmp11_ = FALSE;
					if (!(x <= R)) {
						break;
					}
					{
						gint y;
						y = T;
						{
							gboolean _tmp12_;
							_tmp12_ = TRUE;
							while (TRUE) {
								gint o;
								if (!_tmp12_) {
									y++;
								}
								_tmp12_ = FALSE;
								if (!(y <= B)) {
									break;
								}
								o = (output_rowstride * y) + (x * output_n_channels);
								output[o + 2] = (guchar) 0xFF;
								output[o + 1] = output[o + 2];
								output[o] = output[o + 1];
							}
						}
					}
				}
			}
		}
		return;
	}
	{
		gint x;
		x = L;
		{
			gboolean _tmp13_;
			_tmp13_ = TRUE;
			while (TRUE) {
				gdouble l;
				gdouble r;
				if (!_tmp13_) {
					x++;
				}
				_tmp13_ = FALSE;
				if (!(x <= R)) {
					break;
				}
				l = (((gdouble) x) * input_width) / output_width;
				r = (((gdouble) (x + 1)) * input_width) / output_width;
				{
					gint y;
					y = T;
					{
						gboolean _tmp14_;
						_tmp14_ = TRUE;
						while (TRUE) {
							gdouble t;
							gdouble b;
							if (!_tmp14_) {
								y++;
							}
							_tmp14_ = FALSE;
							if (!(y <= B)) {
								break;
							}
							t = (((gdouble) y) * input_height) / output_height;
							b = (((gdouble) (y + 1)) * input_height) / output_height;
							page_view_set_pixel (self, page, l, r, t, b, output, output_length1, (output_rowstride * y) + (x * output_n_channels));
						}
					}
				}
			}
		}
	}
}


static gint page_view_get_preview_width (PageView* self) {
	gint result = 0;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->width - (self->priv->border_width * 2);
	return result;
}


static gint page_view_get_preview_height (PageView* self) {
	gint result = 0;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->height - (self->priv->border_width * 2);
	return result;
}


static void page_view_update_page_view (PageView* self) {
	gint old_scan_line;
	gint _tmp0_;
	gint scan_line;
	ScanDirection _tmp1_;
	ScanDirection left_steps;
	gboolean _tmp2_ = FALSE;
	ScanDirection _tmp3_;
	gint _tmp4_;
	gint _tmp5_;
	ScanDirection _tmp6_;
	g_return_if_fail (self != NULL);
	if (!self->priv->update_image) {
		return;
	}
	old_scan_line = self->priv->scan_line;
	_tmp0_ = page_get_scan_line (self->priv->page);
	scan_line = _tmp0_;
	_tmp1_ = page_get_scan_direction (self->priv->page);
	left_steps = self->priv->scan_direction - _tmp1_;
	if (left_steps != 0) {
		_tmp2_ = self->priv->image != NULL;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		_g_object_unref0 (self->priv->image);
		self->priv->image = NULL;
	}
	_tmp3_ = page_get_scan_direction (self->priv->page);
	self->priv->scan_direction = _tmp3_;
	_tmp4_ = page_view_get_preview_width (self);
	_tmp5_ = page_view_get_preview_height (self);
	_tmp6_ = page_get_scan_direction (self->priv->page);
	page_view_update_preview (self, self->priv->page, &self->priv->image, _tmp4_, _tmp5_, _tmp6_, old_scan_line, scan_line);
	self->priv->update_image = FALSE;
	self->priv->scan_line = scan_line;
}


static gint page_view_page_to_screen_x (PageView* self, gint x) {
	gint result = 0;
	gint _tmp0_;
	gint _tmp1_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = page_view_get_preview_width (self);
	_tmp1_ = page_get_width (self->priv->page);
	result = (gint) (((((gdouble) x) * _tmp0_) / _tmp1_) + 0.5);
	return result;
}


static gint page_view_page_to_screen_y (PageView* self, gint y) {
	gint result = 0;
	gint _tmp0_;
	gint _tmp1_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = page_view_get_preview_height (self);
	_tmp1_ = page_get_height (self->priv->page);
	result = (gint) (((((gdouble) y) * _tmp0_) / _tmp1_) + 0.5);
	return result;
}


static gint page_view_screen_to_page_x (PageView* self, gint x) {
	gint result = 0;
	gint _tmp0_;
	gint _tmp1_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = page_get_width (self->priv->page);
	_tmp1_ = page_view_get_preview_width (self);
	result = (gint) (((((gdouble) x) * _tmp0_) / _tmp1_) + 0.5);
	return result;
}


static gint page_view_screen_to_page_y (PageView* self, gint y) {
	gint result = 0;
	gint _tmp0_;
	gint _tmp1_;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = page_get_height (self->priv->page);
	_tmp1_ = page_view_get_preview_height (self);
	result = (gint) (((((gdouble) y) * _tmp0_) / _tmp1_) + 0.5);
	return result;
}


static CropLocation page_view_get_crop_location (PageView* self, gint x, gint y) {
	CropLocation result = 0;
	gboolean _tmp0_;
	gint cx = 0;
	gint cy = 0;
	gint cw = 0;
	gint ch = 0;
	gint _tmp1_;
	gint _tmp2_;
	gint _tmp3_;
	gint _tmp4_;
	gint _tmp5_;
	gint dx;
	gint _tmp6_;
	gint dy;
	gint _tmp7_;
	gint dw;
	gint _tmp8_;
	gint dh;
	gint ix;
	gint iy;
	gboolean _tmp9_ = FALSE;
	gboolean _tmp10_ = FALSE;
	gboolean _tmp11_ = FALSE;
	gchar* _tmp12_ = NULL;
	gchar* name;
	gint crop_border;
	gboolean _tmp13_ = FALSE;
	gboolean _tmp14_ = FALSE;
	gboolean _tmp15_ = FALSE;
	gboolean _tmp16_ = FALSE;
	g_return_val_if_fail (self != NULL, 0);
	_tmp0_ = page_has_crop (self->priv->page);
	if (!_tmp0_) {
		result = 0;
		return result;
	}
	page_get_crop (self->priv->page, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_);
	cx = _tmp1_;
	cy = _tmp2_;
	cw = _tmp3_;
	ch = _tmp4_;
	_tmp5_ = page_view_page_to_screen_x (self, cx);
	dx = _tmp5_;
	_tmp6_ = page_view_page_to_screen_y (self, cy);
	dy = _tmp6_;
	_tmp7_ = page_view_page_to_screen_x (self, cw);
	dw = _tmp7_;
	_tmp8_ = page_view_page_to_screen_y (self, ch);
	dh = _tmp8_;
	ix = x - dx;
	iy = y - dy;
	if (ix < 0) {
		_tmp11_ = TRUE;
	} else {
		_tmp11_ = ix > dw;
	}
	if (_tmp11_) {
		_tmp10_ = TRUE;
	} else {
		_tmp10_ = iy < 0;
	}
	if (_tmp10_) {
		_tmp9_ = TRUE;
	} else {
		_tmp9_ = iy > dh;
	}
	if (_tmp9_) {
		result = CROP_LOCATION_NONE;
		return result;
	}
	_tmp12_ = page_get_named_crop (self->priv->page);
	name = _tmp12_;
	if (name != NULL) {
		result = CROP_LOCATION_MIDDLE;
		_g_free0 (name);
		return result;
	}
	crop_border = 20;
	if (dw < (crop_border * 3)) {
		crop_border = dw / 3;
	}
	if (dh < (crop_border * 3)) {
		crop_border = dh / 3;
	}
	if (ix < crop_border) {
		_tmp13_ = iy < crop_border;
	} else {
		_tmp13_ = FALSE;
	}
	if (_tmp13_) {
		result = CROP_LOCATION_TOP_LEFT;
		_g_free0 (name);
		return result;
	}
	if (ix > (dw - crop_border)) {
		_tmp14_ = iy < crop_border;
	} else {
		_tmp14_ = FALSE;
	}
	if (_tmp14_) {
		result = CROP_LOCATION_TOP_RIGHT;
		_g_free0 (name);
		return result;
	}
	if (ix < crop_border) {
		_tmp15_ = iy > (dh - crop_border);
	} else {
		_tmp15_ = FALSE;
	}
	if (_tmp15_) {
		result = CROP_LOCATION_BOTTOM_LEFT;
		_g_free0 (name);
		return result;
	}
	if (ix > (dw - crop_border)) {
		_tmp16_ = iy > (dh - crop_border);
	} else {
		_tmp16_ = FALSE;
	}
	if (_tmp16_) {
		result = CROP_LOCATION_BOTTOM_RIGHT;
		_g_free0 (name);
		return result;
	}
	if (ix < crop_border) {
		result = CROP_LOCATION_LEFT;
		_g_free0 (name);
		return result;
	}
	if (ix > (dw - crop_border)) {
		result = CROP_LOCATION_RIGHT;
		_g_free0 (name);
		return result;
	}
	if (iy < crop_border) {
		result = CROP_LOCATION_TOP;
		_g_free0 (name);
		return result;
	}
	if (iy > (dh - crop_border)) {
		result = CROP_LOCATION_BOTTOM;
		_g_free0 (name);
		return result;
	}
	result = CROP_LOCATION_MIDDLE;
	_g_free0 (name);
	return result;
}


void page_view_button_press (PageView* self, gint x, gint y) {
	CropLocation location = 0;
	CropLocation _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = page_view_get_crop_location (self, x, y);
	location = _tmp0_;
	if (location != CROP_LOCATION_NONE) {
		gint _tmp1_;
		gint _tmp2_;
		gint _tmp3_;
		gint _tmp4_;
		self->priv->crop_location = location;
		self->priv->selected_crop_px = (gdouble) x;
		self->priv->selected_crop_py = (gdouble) y;
		page_get_crop (self->priv->page, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_);
		self->priv->selected_crop_x = _tmp1_;
		self->priv->selected_crop_y = _tmp2_;
		self->priv->selected_crop_w = _tmp3_;
		self->priv->selected_crop_h = _tmp4_;
	}
}


void page_view_motion (PageView* self, gint x, gint y) {
	CropLocation _tmp0_;
	CropLocation location;
	GdkCursorType cursor = 0;
	gint _tmp1_;
	gint pw;
	gint _tmp2_;
	gint ph;
	gint cx = 0;
	gint cy = 0;
	gint cw = 0;
	gint ch = 0;
	gint _tmp3_;
	gint _tmp4_;
	gint _tmp5_;
	gint _tmp6_;
	gint _tmp7_;
	gint dx;
	gint _tmp8_;
	gint dy;
	gint new_x;
	gint new_y;
	gint new_w;
	gint new_h;
	gint _tmp9_;
	gint min_size;
	gboolean _tmp10_ = FALSE;
	gboolean _tmp11_ = FALSE;
	gboolean _tmp12_ = FALSE;
	gboolean _tmp13_ = FALSE;
	gboolean _tmp14_ = FALSE;
	gboolean _tmp15_ = FALSE;
	gboolean _tmp16_ = FALSE;
	gboolean _tmp17_ = FALSE;
	gboolean _tmp18_ = FALSE;
	gboolean _tmp19_ = FALSE;
	gboolean _tmp20_ = FALSE;
	gboolean _tmp21_ = FALSE;
	gboolean _tmp22_ = FALSE;
	gboolean _tmp23_ = FALSE;
	gboolean _tmp24_ = FALSE;
	gboolean _tmp25_ = FALSE;
	gboolean _tmp26_ = FALSE;
	g_return_if_fail (self != NULL);
	_tmp0_ = page_view_get_crop_location (self, x, y);
	location = _tmp0_;
	switch (location) {
		case CROP_LOCATION_MIDDLE:
		{
			cursor = GDK_HAND1;
			break;
		}
		case CROP_LOCATION_TOP:
		{
			cursor = GDK_TOP_SIDE;
			break;
		}
		case CROP_LOCATION_BOTTOM:
		{
			cursor = GDK_BOTTOM_SIDE;
			break;
		}
		case CROP_LOCATION_LEFT:
		{
			cursor = GDK_LEFT_SIDE;
			break;
		}
		case CROP_LOCATION_RIGHT:
		{
			cursor = GDK_RIGHT_SIDE;
			break;
		}
		case CROP_LOCATION_TOP_LEFT:
		{
			cursor = GDK_TOP_LEFT_CORNER;
			break;
		}
		case CROP_LOCATION_TOP_RIGHT:
		{
			cursor = GDK_TOP_RIGHT_CORNER;
			break;
		}
		case CROP_LOCATION_BOTTOM_LEFT:
		{
			cursor = GDK_BOTTOM_LEFT_CORNER;
			break;
		}
		case CROP_LOCATION_BOTTOM_RIGHT:
		{
			cursor = GDK_BOTTOM_RIGHT_CORNER;
			break;
		}
		default:
		{
			cursor = GDK_ARROW;
			break;
		}
	}
	if (self->priv->crop_location == CROP_LOCATION_NONE) {
		self->priv->cursor = cursor;
		return;
	}
	_tmp1_ = page_get_width (self->priv->page);
	pw = _tmp1_;
	_tmp2_ = page_get_height (self->priv->page);
	ph = _tmp2_;
	page_get_crop (self->priv->page, &_tmp3_, &_tmp4_, &_tmp5_, &_tmp6_);
	cx = _tmp3_;
	cy = _tmp4_;
	cw = _tmp5_;
	ch = _tmp6_;
	_tmp7_ = page_view_screen_to_page_x (self, x - ((gint) self->priv->selected_crop_px));
	dx = _tmp7_;
	_tmp8_ = page_view_screen_to_page_y (self, y - ((gint) self->priv->selected_crop_py));
	dy = _tmp8_;
	new_x = self->priv->selected_crop_x;
	new_y = self->priv->selected_crop_y;
	new_w = self->priv->selected_crop_w;
	new_h = self->priv->selected_crop_h;
	_tmp9_ = page_view_screen_to_page_x (self, 15);
	min_size = _tmp9_;
	if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
		_tmp11_ = TRUE;
	} else {
		_tmp11_ = self->priv->crop_location == CROP_LOCATION_LEFT;
	}
	if (_tmp11_) {
		_tmp10_ = TRUE;
	} else {
		_tmp10_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT;
	}
	if (_tmp10_) {
		if (dx > (new_w - min_size)) {
			dx = new_w - min_size;
		}
		if ((new_x + dx) < 0) {
			dx = -new_x;
		}
	}
	if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
		_tmp13_ = TRUE;
	} else {
		_tmp13_ = self->priv->crop_location == CROP_LOCATION_TOP;
	}
	if (_tmp13_) {
		_tmp12_ = TRUE;
	} else {
		_tmp12_ = self->priv->crop_location == CROP_LOCATION_TOP_RIGHT;
	}
	if (_tmp12_) {
		if (dy > (new_h - min_size)) {
			dy = new_h - min_size;
		}
		if ((new_y + dy) < 0) {
			dy = -new_y;
		}
	}
	if (self->priv->crop_location == CROP_LOCATION_TOP_RIGHT) {
		_tmp15_ = TRUE;
	} else {
		_tmp15_ = self->priv->crop_location == CROP_LOCATION_RIGHT;
	}
	if (_tmp15_) {
		_tmp14_ = TRUE;
	} else {
		_tmp14_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
	}
	if (_tmp14_) {
		if (dx < (min_size - new_w)) {
			dx = min_size - new_w;
		}
		if (((new_x + new_w) + dx) > pw) {
			dx = (pw - new_x) - new_w;
		}
	}
	if (self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT) {
		_tmp17_ = TRUE;
	} else {
		_tmp17_ = self->priv->crop_location == CROP_LOCATION_BOTTOM;
	}
	if (_tmp17_) {
		_tmp16_ = TRUE;
	} else {
		_tmp16_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
	}
	if (_tmp16_) {
		if (dy < (min_size - new_h)) {
			dy = min_size - new_h;
		}
		if (((new_y + new_h) + dy) > ph) {
			dy = (ph - new_y) - new_h;
		}
	}
	if (self->priv->crop_location == CROP_LOCATION_MIDDLE) {
		if (((new_x + dx) + new_w) > pw) {
			dx = (pw - new_x) - new_w;
		}
		if ((new_x + dx) < 0) {
			dx = -new_x;
		}
		if (((new_y + dy) + new_h) > ph) {
			dy = (ph - new_y) - new_h;
		}
		if ((new_y + dy) < 0) {
			dy = -new_y;
		}
	}
	if (self->priv->crop_location == CROP_LOCATION_MIDDLE) {
		new_x = new_x + dx;
		new_y = new_y + dy;
	}
	if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
		_tmp19_ = TRUE;
	} else {
		_tmp19_ = self->priv->crop_location == CROP_LOCATION_LEFT;
	}
	if (_tmp19_) {
		_tmp18_ = TRUE;
	} else {
		_tmp18_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT;
	}
	if (_tmp18_) {
		new_x = new_x + dx;
		new_w = new_w - dx;
	}
	if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
		_tmp21_ = TRUE;
	} else {
		_tmp21_ = self->priv->crop_location == CROP_LOCATION_TOP;
	}
	if (_tmp21_) {
		_tmp20_ = TRUE;
	} else {
		_tmp20_ = self->priv->crop_location == CROP_LOCATION_TOP_RIGHT;
	}
	if (_tmp20_) {
		new_y = new_y + dy;
		new_h = new_h - dy;
	}
	if (self->priv->crop_location == CROP_LOCATION_TOP_RIGHT) {
		_tmp23_ = TRUE;
	} else {
		_tmp23_ = self->priv->crop_location == CROP_LOCATION_RIGHT;
	}
	if (_tmp23_) {
		_tmp22_ = TRUE;
	} else {
		_tmp22_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
	}
	if (_tmp22_) {
		new_w = new_w + dx;
	}
	if (self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT) {
		_tmp25_ = TRUE;
	} else {
		_tmp25_ = self->priv->crop_location == CROP_LOCATION_BOTTOM;
	}
	if (_tmp25_) {
		_tmp24_ = TRUE;
	} else {
		_tmp24_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
	}
	if (_tmp24_) {
		new_h = new_h + dy;
	}
	page_move_crop (self->priv->page, new_x, new_y);
	if (new_w != cw) {
		_tmp26_ = TRUE;
	} else {
		_tmp26_ = new_h != ch;
	}
	if (_tmp26_) {
		page_set_custom_crop (self->priv->page, new_w, new_h);
	}
}


void page_view_button_release (PageView* self, gint x, gint y) {
	g_return_if_fail (self != NULL);
	self->priv->crop_location = CROP_LOCATION_NONE;
	g_signal_emit_by_name (self, "changed");
}


GdkCursorType page_view_get_cursor (PageView* self) {
	GdkCursorType result = 0;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->cursor;
	return result;
}


static gboolean page_view_animation_cb (PageView* self) {
	gboolean result = FALSE;
	g_return_val_if_fail (self != NULL, FALSE);
	self->priv->animate_segment = (self->priv->animate_segment + 1) % self->priv->animate_n_segments;
	g_signal_emit_by_name (self, "changed");
	result = TRUE;
	return result;
}


static gboolean _page_view_animation_cb_gsource_func (gpointer self) {
	gboolean result;
	result = page_view_animation_cb (self);
	return result;
}


static void page_view_update_animation (PageView* self) {
	gboolean animate = FALSE;
	gboolean is_animating = FALSE;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_;
	g_return_if_fail (self != NULL);
	_tmp1_ = page_is_scanning (self->priv->page);
	if (_tmp1_) {
		gboolean _tmp2_;
		_tmp2_ = page_has_data (self->priv->page);
		_tmp0_ = !_tmp2_;
	} else {
		_tmp0_ = FALSE;
	}
	animate = _tmp0_;
	is_animating = self->priv->animate_timeout != ((guint) 0);
	if (animate == is_animating) {
		return;
	}
	if (animate) {
		self->priv->animate_segment = 0;
		if (self->priv->animate_timeout == ((guint) 0)) {
			guint _tmp3_;
			_tmp3_ = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 150, _page_view_animation_cb_gsource_func, page_view_ref (self), page_view_unref);
			self->priv->animate_timeout = _tmp3_;
		}
	} else {
		if (self->priv->animate_timeout != ((guint) 0)) {
			g_source_remove (self->priv->animate_timeout);
		}
		self->priv->animate_timeout = (guint) 0;
	}
}


void page_view_render (PageView* self, cairo_t* context) {
	gint _tmp0_;
	gint w;
	gint _tmp1_;
	gint h;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp3_;
	gboolean _tmp11_ = FALSE;
	gboolean _tmp12_;
	gboolean _tmp20_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (context != NULL);
	page_view_update_animation (self);
	page_view_update_page_view (self);
	_tmp0_ = page_view_get_preview_width (self);
	w = _tmp0_;
	_tmp1_ = page_view_get_preview_height (self);
	h = _tmp1_;
	cairo_set_line_width (context, (gdouble) 1);
	cairo_translate (context, (gdouble) self->priv->x_offset, (gdouble) self->priv->y_offset);
	cairo_set_source_rgb (context, (gdouble) 0, (gdouble) 0, (gdouble) 0);
	cairo_set_line_width (context, (gdouble) self->priv->border_width);
	cairo_rectangle (context, ((gdouble) self->priv->border_width) / 2, ((gdouble) self->priv->border_width) / 2, (gdouble) (self->priv->width - self->priv->border_width), (gdouble) (self->priv->height - self->priv->border_width));
	cairo_stroke (context);
	cairo_translate (context, (gdouble) self->priv->border_width, (gdouble) self->priv->border_width);
	gdk_cairo_set_source_pixbuf (context, self->priv->image, (gdouble) 0, (gdouble) 0);
	cairo_paint (context);
	_tmp3_ = page_is_scanning (self->priv->page);
	if (_tmp3_) {
		gboolean _tmp4_;
		_tmp4_ = page_has_data (self->priv->page);
		_tmp2_ = !_tmp4_;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		gdouble outer_radius = 0.0;
		gdouble arc;
		gdouble _tmp5_;
		gdouble x;
		gdouble _tmp6_;
		gdouble y;
		gdouble _tmp7_;
		gdouble inner_radius;
		gdouble offset;
		if (w > h) {
			outer_radius = 0.15 * w;
		} else {
			outer_radius = 0.15 * h;
		}
		arc = G_PI / self->priv->animate_n_segments;
		_tmp5_ = sin (arc);
		x = outer_radius * _tmp5_;
		_tmp6_ = cos (arc);
		y = outer_radius * (_tmp6_ - 1.0);
		_tmp7_ = sqrt ((x * x) + (y * y));
		inner_radius = 0.6 * _tmp7_;
		offset = 0.0;
		{
			gint i;
			i = 0;
			{
				gboolean _tmp8_;
				_tmp8_ = TRUE;
				while (TRUE) {
					gdouble _tmp9_;
					gdouble _tmp10_;
					if (!_tmp8_) {
						i++;
						offset = offset + (arc * 2);
					}
					_tmp8_ = FALSE;
					if (!(i < self->priv->animate_n_segments)) {
						break;
					}
					_tmp9_ = sin (offset);
					x = (w / 2) + (outer_radius * _tmp9_);
					_tmp10_ = cos (offset);
					y = (h / 2) - (outer_radius * _tmp10_);
					cairo_arc (context, x, y, inner_radius, (gdouble) 0, 2 * G_PI);
					if (i == self->priv->animate_segment) {
						cairo_set_source_rgb (context, 0.75, 0.75, 0.75);
						cairo_fill_preserve (context);
					}
					cairo_set_source_rgb (context, 0.5, 0.5, 0.5);
					cairo_stroke (context);
				}
			}
		}
	}
	_tmp12_ = page_is_scanning (self->priv->page);
	if (_tmp12_) {
		gint _tmp13_;
		_tmp13_ = page_get_scan_line (self->priv->page);
		_tmp11_ = _tmp13_ > 0;
	} else {
		_tmp11_ = FALSE;
	}
	if (_tmp11_) {
		gint _tmp14_;
		gint scan_line;
		gdouble s = 0.0;
		gdouble x1 = 0.0;
		gdouble y1 = 0.0;
		gdouble x2 = 0.0;
		gdouble y2 = 0.0;
		ScanDirection _tmp15_;
		_tmp14_ = page_get_scan_line (self->priv->page);
		scan_line = _tmp14_;
		_tmp15_ = page_get_scan_direction (self->priv->page);
		switch (_tmp15_) {
			case SCAN_DIRECTION_TOP_TO_BOTTOM:
			{
				gint _tmp16_;
				_tmp16_ = page_view_page_to_screen_y (self, scan_line);
				s = (gdouble) _tmp16_;
				x1 = (gdouble) 0;
				y1 = s + 0.5;
				x2 = (gdouble) w;
				y2 = s + 0.5;
				break;
			}
			case SCAN_DIRECTION_BOTTOM_TO_TOP:
			{
				gint _tmp17_;
				_tmp17_ = page_view_page_to_screen_y (self, scan_line);
				s = (gdouble) _tmp17_;
				x1 = (gdouble) 0;
				y1 = (h - s) + 0.5;
				x2 = (gdouble) w;
				y2 = (h - s) + 0.5;
				break;
			}
			case SCAN_DIRECTION_LEFT_TO_RIGHT:
			{
				gint _tmp18_;
				_tmp18_ = page_view_page_to_screen_x (self, scan_line);
				s = (gdouble) _tmp18_;
				x1 = s + 0.5;
				y1 = (gdouble) 0;
				x2 = s + 0.5;
				y2 = (gdouble) h;
				break;
			}
			case SCAN_DIRECTION_RIGHT_TO_LEFT:
			{
				gint _tmp19_;
				_tmp19_ = page_view_page_to_screen_x (self, scan_line);
				s = (gdouble) _tmp19_;
				x1 = (w - s) + 0.5;
				y1 = (gdouble) 0;
				x2 = (w - s) + 0.5;
				y2 = (gdouble) h;
				break;
			}
			default:
			{
				y2 = (gdouble) 0;
				x2 = y2;
				y1 = x2;
				x1 = y1;
				break;
			}
		}
		cairo_move_to (context, x1, y1);
		cairo_line_to (context, x2, y2);
		cairo_set_source_rgb (context, 1.0, 0.0, 0.0);
		cairo_stroke (context);
	}
	_tmp20_ = page_has_crop (self->priv->page);
	if (_tmp20_) {
		gint x = 0;
		gint y = 0;
		gint crop_width = 0;
		gint crop_height = 0;
		gint _tmp21_;
		gint _tmp22_;
		gint _tmp23_;
		gint _tmp24_;
		gint _tmp25_;
		gint dx;
		gint _tmp26_;
		gint dy;
		gint _tmp27_;
		gint dw;
		gint _tmp28_;
		gint dh;
		page_get_crop (self->priv->page, &_tmp21_, &_tmp22_, &_tmp23_, &_tmp24_);
		x = _tmp21_;
		y = _tmp22_;
		crop_width = _tmp23_;
		crop_height = _tmp24_;
		_tmp25_ = page_view_page_to_screen_x (self, x);
		dx = _tmp25_;
		_tmp26_ = page_view_page_to_screen_y (self, y);
		dy = _tmp26_;
		_tmp27_ = page_view_page_to_screen_x (self, crop_width);
		dw = _tmp27_;
		_tmp28_ = page_view_page_to_screen_y (self, crop_height);
		dh = _tmp28_;
		cairo_rectangle (context, (gdouble) 0, (gdouble) 0, (gdouble) w, (gdouble) h);
		cairo_new_sub_path (context);
		cairo_rectangle (context, (gdouble) dx, (gdouble) dy, (gdouble) dw, (gdouble) dh);
		cairo_set_fill_rule (context, CAIRO_FILL_RULE_EVEN_ODD);
		cairo_set_source_rgba (context, 0.25, 0.25, 0.25, 0.2);
		cairo_fill (context);
		cairo_rectangle (context, dx - 1.5, dy - 1.5, (gdouble) (dw + 3), (gdouble) (dh + 3));
		cairo_set_source_rgb (context, 1.0, 1.0, 1.0);
		cairo_stroke (context);
		cairo_rectangle (context, dx - 0.5, dy - 0.5, (gdouble) (dw + 1), (gdouble) (dh + 1));
		cairo_set_source_rgb (context, 0.0, 0.0, 0.0);
		cairo_stroke (context);
	}
}


void page_view_set_width (PageView* self, gint width) {
	gint _tmp0_;
	gint _tmp1_;
	gint height;
	gboolean _tmp2_ = FALSE;
	g_return_if_fail (self != NULL);
	_tmp0_ = page_get_height (self->priv->page);
	_tmp1_ = page_get_width (self->priv->page);
	height = (gint) ((((gdouble) width) * _tmp0_) / _tmp1_);
	if (self->priv->width == width) {
		_tmp2_ = self->priv->height == height;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		return;
	}
	self->priv->width = width;
	self->priv->height = height;
	self->priv->update_image = TRUE;
	g_signal_emit_by_name (self, "size-changed");
	g_signal_emit_by_name (self, "changed");
}


void page_view_set_height (PageView* self, gint height) {
	gint _tmp0_;
	gint _tmp1_;
	gint width;
	gboolean _tmp2_ = FALSE;
	g_return_if_fail (self != NULL);
	_tmp0_ = page_get_width (self->priv->page);
	_tmp1_ = page_get_height (self->priv->page);
	width = (gint) ((((gdouble) height) * _tmp0_) / _tmp1_);
	if (self->priv->width == width) {
		_tmp2_ = self->priv->height == height;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		return;
	}
	self->priv->width = width;
	self->priv->height = height;
	self->priv->update_image = TRUE;
	g_signal_emit_by_name (self, "size-changed");
	g_signal_emit_by_name (self, "changed");
}


gint page_view_get_width (PageView* self) {
	gint result = 0;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->width;
	return result;
}


gint page_view_get_height (PageView* self) {
	gint result = 0;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->height;
	return result;
}


static void page_view_page_pixels_changed_cb (PageView* self, Page* p) {
	g_return_if_fail (self != NULL);
	g_return_if_fail (p != NULL);
	self->priv->update_image = TRUE;
	g_signal_emit_by_name (self, "changed");
}


static void page_view_page_size_changed_cb (PageView* self, Page* p) {
	g_return_if_fail (self != NULL);
	g_return_if_fail (p != NULL);
	self->priv->update_image = TRUE;
	g_signal_emit_by_name (self, "size-changed");
	g_signal_emit_by_name (self, "changed");
}


static void page_view_page_overlay_changed_cb (PageView* self, Page* p) {
	g_return_if_fail (self != NULL);
	g_return_if_fail (p != NULL);
	g_signal_emit_by_name (self, "changed");
}


static void page_view_scan_direction_changed_cb (PageView* self, Page* p) {
	g_return_if_fail (self != NULL);
	g_return_if_fail (p != NULL);
	self->priv->update_image = TRUE;
	g_signal_emit_by_name (self, "size-changed");
	g_signal_emit_by_name (self, "changed");
}


static void value_page_view_init (GValue* value) {
	value->data[0].v_pointer = NULL;
}


static void value_page_view_free_value (GValue* value) {
	if (value->data[0].v_pointer) {
		page_view_unref (value->data[0].v_pointer);
	}
}


static void value_page_view_copy_value (const GValue* src_value, GValue* dest_value) {
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = page_view_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}


static gpointer value_page_view_peek_pointer (const GValue* value) {
	return value->data[0].v_pointer;
}


static gchar* value_page_view_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
	if (collect_values[0].v_pointer) {
		PageView* object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = page_view_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}


static gchar* value_page_view_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
	PageView** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = page_view_ref (value->data[0].v_pointer);
	}
	return NULL;
}


GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
	ParamSpecPageView* spec;
	g_return_val_if_fail (g_type_is_a (object_type, TYPE_PAGE_VIEW), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}


gpointer value_get_page_view (const GValue* value) {
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW), NULL);
	return value->data[0].v_pointer;
}


void value_set_page_view (GValue* value, gpointer v_object) {
	PageView* old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE_VIEW));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		page_view_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		page_view_unref (old);
	}
}


void value_take_page_view (GValue* value, gpointer v_object) {
	PageView* old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE_VIEW));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		page_view_unref (old);
	}
}


static void page_view_class_init (PageViewClass * klass) {
	page_view_parent_class = g_type_class_peek_parent (klass);
	PAGE_VIEW_CLASS (klass)->finalize = page_view_finalize;
	g_type_class_add_private (klass, sizeof (PageViewPrivate));
	g_signal_new ("size_changed", TYPE_PAGE_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	g_signal_new ("changed", TYPE_PAGE_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}


static void page_view_instance_init (PageView * self) {
	self->priv = PAGE_VIEW_GET_PRIVATE (self);
	self->priv->image = NULL;
	self->priv->border_width = 1;
	self->priv->update_image = TRUE;
	self->priv->cursor = GDK_ARROW;
	self->priv->animate_n_segments = 7;
	self->ref_count = 1;
}


static void page_view_finalize (PageView* obj) {
	PageView * self;
	self = PAGE_VIEW (obj);
	_page_unref0 (self->priv->page);
	_g_object_unref0 (self->priv->image);
}


GType page_view_get_type (void) {
	static volatile gsize page_view_type_id__volatile = 0;
	if (g_once_init_enter (&page_view_type_id__volatile)) {
		static const GTypeValueTable g_define_type_value_table = { value_page_view_init, value_page_view_free_value, value_page_view_copy_value, value_page_view_peek_pointer, "p", value_page_view_collect_value, "p", value_page_view_lcopy_value };
		static const GTypeInfo g_define_type_info = { sizeof (PageViewClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) page_view_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PageView), 0, (GInstanceInitFunc) page_view_instance_init, &g_define_type_value_table };
		static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
		GType page_view_type_id;
		page_view_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PageView", &g_define_type_info, &g_define_type_fundamental_info, 0);
		g_once_init_leave (&page_view_type_id__volatile, page_view_type_id);
	}
	return page_view_type_id__volatile;
}


gpointer page_view_ref (gpointer instance) {
	PageView* self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}


void page_view_unref (gpointer instance) {
	PageView* self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		PAGE_VIEW_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}