diff options
| author | Alessio Treglia <alessio@debian.org> | 2011-08-27 10:54:22 +0200 | 
|---|---|---|
| committer | Alessio Treglia <alessio@debian.org> | 2011-08-27 10:54:22 +0200 | 
| commit | 575d802c4f1a81ebce3b7b71be6dd3a51fddf7bd (patch) | |
| tree | f67206af06039627d241d77bc83009505189b7eb /src/page.c | |
| parent | 77a9b5bea4c6dc6977e51b002d92d268e57208f3 (diff) | |
| parent | 87ebc2af1f0417b3bc38a233e28ff673eff4fa51 (diff) | |
Merge commit 'upstream/3.1.5'
Diffstat (limited to 'src/page.c')
| -rw-r--r-- | src/page.c | 2559 | 
1 files changed, 1792 insertions, 767 deletions
| @@ -1,7 +1,10 @@ +/* page.c generated by valac 0.13.1, the Vala compiler + * generated from page.vala, do not modify */ +  /* - * Copyright (C) 2009 Canonical Ltd. + * 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 @@ -9,902 +12,1924 @@   * license.   */ +#include <glib.h> +#include <glib-object.h> +#include <stdlib.h>  #include <string.h> -#include "page.h" - -enum { -    PIXELS_CHANGED, -    SIZE_CHANGED, -    SCAN_LINE_CHANGED, -    SCAN_DIRECTION_CHANGED, -    CROP_CHANGED, -    LAST_SIGNAL +#include <float.h> +#include <math.h> +#include <gdk-pixbuf/gdk-pixdata.h> +#include <glib/gstdio.h> +#include <gio/gio.h> +#include <gobject/gvaluecollector.h> + + +#define TYPE_SCAN_DIRECTION (scan_direction_get_type ()) + +#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; +typedef struct _PagePrivate PagePrivate; +#define _g_free0(var) (var = (g_free (var), NULL)) + +#define TYPE_SCAN_PAGE_INFO (scan_page_info_get_type ()) +#define SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfo)) +#define SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) +#define IS_SCAN_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_PAGE_INFO)) +#define IS_SCAN_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_PAGE_INFO)) +#define SCAN_PAGE_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_PAGE_INFO, ScanPageInfoClass)) + +typedef struct _ScanPageInfo ScanPageInfo; +typedef struct _ScanPageInfoClass ScanPageInfoClass; +typedef struct _ScanPageInfoPrivate ScanPageInfoPrivate; + +#define TYPE_SCAN_LINE (scan_line_get_type ()) +#define SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_LINE, ScanLine)) +#define SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_LINE, ScanLineClass)) +#define IS_SCAN_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_LINE)) +#define IS_SCAN_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_LINE)) +#define SCAN_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_LINE, ScanLineClass)) + +typedef struct _ScanLine ScanLine; +typedef struct _ScanLineClass ScanLineClass; +typedef struct _ScanLinePrivate ScanLinePrivate; +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL))) + +#define TYPE_PIXBUF_WRITER (pixbuf_writer_get_type ()) +#define PIXBUF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PIXBUF_WRITER, PixbufWriter)) +#define PIXBUF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PIXBUF_WRITER, PixbufWriterClass)) +#define IS_PIXBUF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PIXBUF_WRITER)) +#define IS_PIXBUF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PIXBUF_WRITER)) +#define PIXBUF_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PIXBUF_WRITER, PixbufWriterClass)) + +typedef struct _PixbufWriter PixbufWriter; +typedef struct _PixbufWriterClass PixbufWriterClass; +#define _pixbuf_writer_unref0(var) ((var == NULL) ? NULL : (var = (pixbuf_writer_unref (var), NULL))) +typedef struct _ParamSpecPage ParamSpecPage; +typedef struct _PixbufWriterPrivate PixbufWriterPrivate; +typedef struct _ParamSpecPixbufWriter ParamSpecPixbufWriter; + +typedef enum  { +	SCAN_DIRECTION_TOP_TO_BOTTOM, +	SCAN_DIRECTION_LEFT_TO_RIGHT, +	SCAN_DIRECTION_BOTTOM_TO_TOP, +	SCAN_DIRECTION_RIGHT_TO_LEFT +} ScanDirection; + +struct _Page { +	GTypeInstance parent_instance; +	volatile int ref_count; +	PagePrivate * priv;  }; -static guint signals[LAST_SIGNAL] = { 0, }; -struct PagePrivate -{ -    /* Resolution of page */ -    gint dpi; +struct _PageClass { +	GTypeClass parent_class; +	void (*finalize) (Page *self); +}; -    /* Number of rows in this page or -1 if currently unknown */ -    gint expected_rows; +struct _PagePrivate { +	gint dpi; +	gint expected_rows; +	gint depth; +	gchar* color_profile; +	gint width; +	gint n_rows; +	gint rowstride; +	gint n_channels; +	guchar* pixels; +	gint pixels_length1; +	gint _pixels_size_; +	gboolean scanning; +	gboolean has_data_; +	gint scan_line; +	ScanDirection scan_direction; +	gboolean has_crop_; +	gchar* crop_name; +	gint crop_x; +	gint crop_y; +	gint crop_width; +	gint crop_height; +}; -    /* Bit depth */ -    gint depth; +struct _ScanPageInfo { +	GTypeInstance parent_instance; +	volatile int ref_count; +	ScanPageInfoPrivate * priv; +	gint width; +	gint height; +	gint depth; +	gint n_channels; +	gdouble dpi; +	gchar* device; +}; -    /* Color profile */ -    gchar *color_profile; +struct _ScanPageInfoClass { +	GTypeClass parent_class; +	void (*finalize) (ScanPageInfo *self); +}; + +struct _ScanLine { +	GTypeInstance parent_instance; +	volatile int ref_count; +	ScanLinePrivate * priv; +	gint number; +	gint n_lines; +	gint width; +	gint depth; +	gint channel; +	guchar* data; +	gint data_length1; +	gint data_length; +}; + +struct _ScanLineClass { +	GTypeClass parent_class; +	void (*finalize) (ScanLine *self); +}; -    /* Scanned image data */ -    gint width, n_rows, rowstride, n_channels; -    guchar *pixels; +struct _ParamSpecPage { +	GParamSpec parent_instance; +}; -    /* Page is getting data */ -    gboolean scanning; +struct _PixbufWriter { +	GTypeInstance parent_instance; +	volatile int ref_count; +	PixbufWriterPrivate * priv; +	GFileOutputStream* stream; +}; -    /* TRUE if have some page data */ -    gboolean has_data; +struct _PixbufWriterClass { +	GTypeClass parent_class; +	void (*finalize) (PixbufWriter *self); +}; -    /* Expected next scan row */ -    gint scan_line; +struct _ParamSpecPixbufWriter { +	GParamSpec parent_instance; +}; -    /* Rotation of scanned data */ -    ScanDirection scan_direction; -    /* Crop */ -    gboolean has_crop; -    gchar *crop_name; -    gint crop_x, crop_y, crop_width, crop_height; +static gpointer page_parent_class = NULL; +static gpointer pixbuf_writer_parent_class = NULL; + +GType scan_direction_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; +#define PAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PAGE, PagePrivate)) +enum  { +	PAGE_DUMMY_PROPERTY +}; +Page* page_new (gint width, gint height, gint dpi, ScanDirection scan_direction); +Page* page_construct (GType object_type, gint width, gint height, gint dpi, ScanDirection scan_direction); +gpointer scan_page_info_ref (gpointer instance); +void scan_page_info_unref (gpointer instance); +GParamSpec* param_spec_scan_page_info (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_page_info (GValue* value, gpointer v_object); +void value_take_scan_page_info (GValue* value, gpointer v_object); +gpointer value_get_scan_page_info (const GValue* value); +GType scan_page_info_get_type (void) G_GNUC_CONST; +void page_set_page_info (Page* self, ScanPageInfo* info); +void page_start (Page* self); +gboolean page_is_scanning (Page* self); +gboolean page_has_data (Page* self); +gboolean page_is_color (Page* self); +gint page_get_scan_line (Page* self); +gpointer scan_line_ref (gpointer instance); +void scan_line_unref (gpointer instance); +GParamSpec* param_spec_scan_line (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_scan_line (GValue* value, gpointer v_object); +void value_take_scan_line (GValue* value, gpointer v_object); +gpointer value_get_scan_line (const GValue* value); +GType scan_line_get_type (void) G_GNUC_CONST; +static void page_parse_line (Page* self, ScanLine* line, gint n, gboolean* size_changed); +gint page_get_scan_height (Page* self); +void page_parse_scan_line (Page* self, ScanLine* line); +void page_finish (Page* self); +ScanDirection page_get_scan_direction (Page* self); +static void page_set_scan_direction (Page* self, ScanDirection direction); +gint page_get_width (Page* self); +gint page_get_height (Page* self); +void page_rotate_left (Page* self); +void page_rotate_right (Page* self); +gint page_get_dpi (Page* self); +gboolean page_is_landscape (Page* self); +gint page_get_depth (Page* self); +gint page_get_n_channels (Page* self); +gint page_get_rowstride (Page* self); +gint page_get_scan_width (Page* self); +void page_set_color_profile (Page* self, const gchar* color_profile); +gchar* page_get_color_profile (Page* self); +void page_set_no_crop (Page* self); +void page_set_custom_crop (Page* self, gint width, gint height); +void page_set_named_crop (Page* self, const gchar* name); +void page_move_crop (Page* self, gint x, gint y); +void page_rotate_crop (Page* self); +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); +guchar* page_get_pixels (Page* self, int* result_length1); +static guchar page_get_sample (Page* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint n_channels, gint channel); +static void page_get_pixel (Page* self, gint x, gint y, guchar* pixel, int pixel_length1, gint offset); +GdkPixbuf* page_get_image (Page* self, gboolean apply_crop); +static gchar* page_get_icc_data_encoded (Page* self, const gchar* icc_profile_filename); +void page_save (Page* self, const gchar* type, GFile* file, GError** error); +PixbufWriter* pixbuf_writer_new (GFileOutputStream* stream); +PixbufWriter* pixbuf_writer_construct (GType object_type, GFileOutputStream* stream); +gpointer pixbuf_writer_ref (gpointer instance); +void pixbuf_writer_unref (gpointer instance); +GParamSpec* param_spec_pixbuf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags); +void value_set_pixbuf_writer (GValue* value, gpointer v_object); +void value_take_pixbuf_writer (GValue* value, gpointer v_object); +gpointer value_get_pixbuf_writer (const GValue* value); +GType pixbuf_writer_get_type (void) G_GNUC_CONST; +void pixbuf_writer_save (PixbufWriter* self, GdkPixbuf* image, const gchar* type, gchar** option_keys, int option_keys_length1, gchar** option_values, int option_values_length1, GError** error); +static void page_finalize (Page* obj); +enum  { +	PIXBUF_WRITER_DUMMY_PROPERTY  }; +static gboolean pixbuf_writer_write_pixbuf_data (PixbufWriter* self, guint8* buf, int buf_length1, GError** error); +static gboolean _pixbuf_writer_write_pixbuf_data_gdk_pixbuf_save_func (guint8* buf, gsize buf_length1, GError** error, gpointer self); +static void pixbuf_writer_finalize (PixbufWriter* obj); +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); + + +GType scan_direction_get_type (void) { +	static volatile gsize scan_direction_type_id__volatile = 0; +	if (g_once_init_enter (&scan_direction_type_id__volatile)) { +		static const GEnumValue values[] = {{SCAN_DIRECTION_TOP_TO_BOTTOM, "SCAN_DIRECTION_TOP_TO_BOTTOM", "top-to-bottom"}, {SCAN_DIRECTION_LEFT_TO_RIGHT, "SCAN_DIRECTION_LEFT_TO_RIGHT", "left-to-right"}, {SCAN_DIRECTION_BOTTOM_TO_TOP, "SCAN_DIRECTION_BOTTOM_TO_TOP", "bottom-to-top"}, {SCAN_DIRECTION_RIGHT_TO_LEFT, "SCAN_DIRECTION_RIGHT_TO_LEFT", "right-to-left"}, {0, NULL, NULL}}; +		GType scan_direction_type_id; +		scan_direction_type_id = g_enum_register_static ("ScanDirection", values); +		g_once_init_leave (&scan_direction_type_id__volatile, scan_direction_type_id); +	} +	return scan_direction_type_id__volatile; +} + + +Page* page_construct (GType object_type, gint width, gint height, gint dpi, ScanDirection scan_direction) { +	Page* self = NULL; +	gboolean _tmp0_ = FALSE; +	self = (Page*) g_type_create_instance (object_type); +	if (scan_direction == SCAN_DIRECTION_TOP_TO_BOTTOM) { +		_tmp0_ = TRUE; +	} else { +		_tmp0_ = scan_direction == SCAN_DIRECTION_BOTTOM_TO_TOP; +	} +	if (_tmp0_) { +		self->priv->width = width; +		self->priv->n_rows = height; +	} else { +		self->priv->width = height; +		self->priv->n_rows = width; +	} +	self->priv->dpi = dpi; +	self->priv->scan_direction = scan_direction; +	return self; +} + + +Page* page_new (gint width, gint height, gint dpi, ScanDirection scan_direction) { +	return page_construct (TYPE_PAGE, width, height, dpi, scan_direction); +} + + +void page_set_page_info (Page* self, ScanPageInfo* info) { +	gint _tmp0_; +	g_return_if_fail (self != NULL); +	g_return_if_fail (info != NULL); +	self->priv->expected_rows = info->height; +	self->priv->dpi = (gint) info->dpi; +	self->priv->width = info->width; +	self->priv->n_rows = info->height; +	if (self->priv->n_rows < 0) { +		self->priv->n_rows = self->priv->width / 2; +	} +	self->priv->depth = info->depth; +	self->priv->n_channels = info->n_channels; +	self->priv->rowstride = (((self->priv->width * self->priv->depth) * self->priv->n_channels) + 7) / 8; +	_tmp0_ = self->priv->n_rows * self->priv->rowstride; +	self->priv->pixels = g_renew (guchar, self->priv->pixels, self->priv->n_rows * self->priv->rowstride); +	(_tmp0_ > self->priv->pixels_length1) ? memset (self->priv->pixels + self->priv->pixels_length1, 0, sizeof (guchar) * (_tmp0_ - self->priv->pixels_length1)) : NULL; +	self->priv->pixels_length1 = _tmp0_; +	self->priv->_pixels_size_ = _tmp0_; +	g_return_if_fail (self->priv->pixels != NULL); +	if (self->priv->depth == 1) { +		memset (self->priv->pixels, 0x00, (gsize) (self->priv->n_rows * self->priv->rowstride)); +	} else { +		memset (self->priv->pixels, 0xFF, (gsize) (self->priv->n_rows * self->priv->rowstride)); +	} +	g_signal_emit_by_name (self, "size-changed"); +	g_signal_emit_by_name (self, "pixels-changed"); +} + + +void page_start (Page* self) { +	g_return_if_fail (self != NULL); +	self->priv->scanning = TRUE; +	g_signal_emit_by_name (self, "scan-line-changed"); +} + + +gboolean page_is_scanning (Page* self) { +	gboolean result = FALSE; +	g_return_val_if_fail (self != NULL, FALSE); +	result = self->priv->scanning; +	return result; +} + + +gboolean page_has_data (Page* self) { +	gboolean result = FALSE; +	g_return_val_if_fail (self != NULL, FALSE); +	result = self->priv->has_data_; +	return result; +} + + +gboolean page_is_color (Page* self) { +	gboolean result = FALSE; +	g_return_val_if_fail (self != NULL, FALSE); +	result = self->priv->n_channels > 1; +	return result; +} + + +gint page_get_scan_line (Page* self) { +	gint result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->scan_line; +	return result; +} + + +static void page_parse_line (Page* self, ScanLine* line, gint n, gboolean* size_changed) { +	gboolean _size_changed = FALSE; +	gint line_number = 0; +	gint offset; +	gint line_offset; +	g_return_if_fail (self != NULL); +	g_return_if_fail (line != NULL); +	line_number = line->number + n; +	_size_changed = FALSE; +	while (TRUE) { +		gint _tmp0_; +		gint rows = 0; +		gint _tmp1_; +		_tmp0_ = page_get_scan_height (self); +		if (!(line_number >= _tmp0_)) { +			break; +		} +		rows = self->priv->n_rows; +		self->priv->n_rows = rows + (self->priv->width / 2); +		g_debug ("page.vala:151: Extending image from %d lines to %d lines", rows, self->priv->n_rows); +		_tmp1_ = self->priv->n_rows * self->priv->rowstride; +		self->priv->pixels = g_renew (guchar, self->priv->pixels, self->priv->n_rows * self->priv->rowstride); +		(_tmp1_ > self->priv->pixels_length1) ? memset (self->priv->pixels + self->priv->pixels_length1, 0, sizeof (guchar) * (_tmp1_ - self->priv->pixels_length1)) : NULL; +		self->priv->pixels_length1 = _tmp1_; +		self->priv->_pixels_size_ = _tmp1_; +		_size_changed = TRUE; +	} +	offset = line_number * self->priv->rowstride; +	line_offset = n * line->data_length; +	{ +		gint i; +		i = 0; +		{ +			gboolean _tmp2_; +			_tmp2_ = TRUE; +			while (TRUE) { +				if (!_tmp2_) { +					i++; +				} +				_tmp2_ = FALSE; +				if (!(i < line->data_length)) { +					break; +				} +				self->priv->pixels[offset + i] = line->data[line_offset + i]; +			} +		} +	} +	self->priv->scan_line = line_number; +	if (size_changed) { +		*size_changed = _size_changed; +	} +} + + +void page_parse_scan_line (Page* self, ScanLine* line) { +	gboolean size_has_changed; +	g_return_if_fail (self != NULL); +	g_return_if_fail (line != NULL); +	size_has_changed = FALSE; +	{ +		gint i; +		i = 0; +		{ +			gboolean _tmp0_; +			_tmp0_ = TRUE; +			while (TRUE) { +				gboolean _tmp1_; +				if (!_tmp0_) { +					i++; +				} +				_tmp0_ = FALSE; +				if (!(i < line->n_lines)) { +					break; +				} +				page_parse_line (self, line, i, &_tmp1_); +				size_has_changed = _tmp1_; +			} +		} +	} +	self->priv->has_data_ = TRUE; +	if (size_has_changed) { +		g_signal_emit_by_name (self, "size-changed"); +	} +	g_signal_emit_by_name (self, "scan-line-changed"); +	g_signal_emit_by_name (self, "pixels-changed"); +} + + +void page_finish (Page* self) { +	gboolean size_has_changed; +	gboolean _tmp0_ = FALSE; +	g_return_if_fail (self != NULL); +	size_has_changed = FALSE; +	if (self->priv->expected_rows < 0) { +		gint _tmp1_; +		_tmp1_ = page_get_scan_height (self); +		_tmp0_ = self->priv->scan_line != _tmp1_; +	} else { +		_tmp0_ = FALSE; +	} +	if (_tmp0_) { +		gint rows = 0; +		gint _tmp2_; +		rows = self->priv->n_rows; +		self->priv->n_rows = self->priv->scan_line; +		_tmp2_ = self->priv->n_rows * self->priv->rowstride; +		self->priv->pixels = g_renew (guchar, self->priv->pixels, self->priv->n_rows * self->priv->rowstride); +		(_tmp2_ > self->priv->pixels_length1) ? memset (self->priv->pixels + self->priv->pixels_length1, 0, sizeof (guchar) * (_tmp2_ - self->priv->pixels_length1)) : NULL; +		self->priv->pixels_length1 = _tmp2_; +		self->priv->_pixels_size_ = _tmp2_; +		g_debug ("page.vala:193: Trimming page from %d lines to %d lines", rows, self->priv->n_rows); +		size_has_changed = TRUE; +	} +	self->priv->scanning = FALSE; +	if (size_has_changed) { +		g_signal_emit_by_name (self, "size-changed"); +	} +	g_signal_emit_by_name (self, "scan-line-changed"); +} + + +ScanDirection page_get_scan_direction (Page* self) { +	ScanDirection result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->scan_direction; +	return result; +} + + +static void page_set_scan_direction (Page* self, ScanDirection direction) { +	gint left_steps = 0; +	gint t = 0; +	gboolean size_has_changed; +	gint width = 0; +	gint height = 0; +	gint _tmp0_; +	gint _tmp1_; +	g_return_if_fail (self != NULL); +	size_has_changed = FALSE; +	if (self->priv->scan_direction == direction) { +		return; +	} +	left_steps = (gint) (direction - self->priv->scan_direction); +	if (left_steps < 0) { +		left_steps = left_steps + 4; +	} +	if (left_steps != 2) { +		size_has_changed = TRUE; +	} +	_tmp0_ = page_get_width (self); +	width = _tmp0_; +	_tmp1_ = page_get_height (self); +	height = _tmp1_; +	if (self->priv->has_crop_) { +		switch (left_steps) { +			case 1: +			{ +				t = self->priv->crop_x; +				self->priv->crop_x = self->priv->crop_y; +				self->priv->crop_y = width - (t + self->priv->crop_width); +				t = self->priv->crop_width; +				self->priv->crop_width = self->priv->crop_height; +				self->priv->crop_height = t; +				break; +			} +			case 2: +			{ +				self->priv->crop_x = width - (self->priv->crop_x + self->priv->crop_width); +				self->priv->crop_y = width - (self->priv->crop_y + self->priv->crop_height); +				break; +			} +			case 3: +			{ +				t = self->priv->crop_y; +				self->priv->crop_y = self->priv->crop_x; +				self->priv->crop_x = height - (t + self->priv->crop_height); +				t = self->priv->crop_width; +				self->priv->crop_width = self->priv->crop_height; +				self->priv->crop_height = t; +				break; +			} +			default: +			break; +		} +	} +	self->priv->scan_direction = direction; +	if (size_has_changed) { +		g_signal_emit_by_name (self, "size-changed"); +	} +	g_signal_emit_by_name (self, "scan-direction-changed"); +	if (self->priv->has_crop_) { +		g_signal_emit_by_name (self, "crop-changed"); +	} +} + + +void page_rotate_left (Page* self) { +	ScanDirection direction; +	g_return_if_fail (self != NULL); +	direction = self->priv->scan_direction; +	switch (direction) { +		case SCAN_DIRECTION_TOP_TO_BOTTOM: +		{ +			direction = SCAN_DIRECTION_LEFT_TO_RIGHT; +			break; +		} +		case SCAN_DIRECTION_LEFT_TO_RIGHT: +		{ +			direction = SCAN_DIRECTION_BOTTOM_TO_TOP; +			break; +		} +		case SCAN_DIRECTION_BOTTOM_TO_TOP: +		{ +			direction = SCAN_DIRECTION_RIGHT_TO_LEFT; +			break; +		} +		case SCAN_DIRECTION_RIGHT_TO_LEFT: +		{ +			direction = SCAN_DIRECTION_TOP_TO_BOTTOM; +			break; +		} +		default: +		break; +	} +	page_set_scan_direction (self, direction); +} + + +void page_rotate_right (Page* self) { +	ScanDirection direction; +	g_return_if_fail (self != NULL); +	direction = self->priv->scan_direction; +	switch (direction) { +		case SCAN_DIRECTION_TOP_TO_BOTTOM: +		{ +			direction = SCAN_DIRECTION_RIGHT_TO_LEFT; +			break; +		} +		case SCAN_DIRECTION_LEFT_TO_RIGHT: +		{ +			direction = SCAN_DIRECTION_TOP_TO_BOTTOM; +			break; +		} +		case SCAN_DIRECTION_BOTTOM_TO_TOP: +		{ +			direction = SCAN_DIRECTION_LEFT_TO_RIGHT; +			break; +		} +		case SCAN_DIRECTION_RIGHT_TO_LEFT: +		{ +			direction = SCAN_DIRECTION_BOTTOM_TO_TOP; +			break; +		} +		default: +		break; +	} +	page_set_scan_direction (self, direction); +} + + +gint page_get_dpi (Page* self) { +	gint result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->dpi; +	return result; +} + + +gboolean page_is_landscape (Page* self) { +	gboolean result = FALSE; +	gint _tmp0_; +	gint _tmp1_; +	g_return_val_if_fail (self != NULL, FALSE); +	_tmp0_ = page_get_width (self); +	_tmp1_ = page_get_height (self); +	result = _tmp0_ > _tmp1_; +	return result; +} + + +gint page_get_width (Page* self) { +	gint result = 0; +	gboolean _tmp0_ = FALSE; +	g_return_val_if_fail (self != NULL, 0); +	if (self->priv->scan_direction == SCAN_DIRECTION_TOP_TO_BOTTOM) { +		_tmp0_ = TRUE; +	} else { +		_tmp0_ = self->priv->scan_direction == SCAN_DIRECTION_BOTTOM_TO_TOP; +	} +	if (_tmp0_) { +		result = self->priv->width; +		return result; +	} else { +		result = self->priv->n_rows; +		return result; +	} +} + + +gint page_get_height (Page* self) { +	gint result = 0; +	gboolean _tmp0_ = FALSE; +	g_return_val_if_fail (self != NULL, 0); +	if (self->priv->scan_direction == SCAN_DIRECTION_TOP_TO_BOTTOM) { +		_tmp0_ = TRUE; +	} else { +		_tmp0_ = self->priv->scan_direction == SCAN_DIRECTION_BOTTOM_TO_TOP; +	} +	if (_tmp0_) { +		result = self->priv->n_rows; +		return result; +	} else { +		result = self->priv->width; +		return result; +	} +} + + +gint page_get_depth (Page* self) { +	gint result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->depth; +	return result; +} + + +gint page_get_n_channels (Page* self) { +	gint result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->n_channels; +	return result; +} + + +gint page_get_rowstride (Page* self) { +	gint result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->rowstride; +	return result; +} -G_DEFINE_TYPE (Page, page, G_TYPE_OBJECT); +gint page_get_scan_width (Page* self) { +	gint result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->width; +	return result; +} -Page * -page_new (gint width, gint height, gint dpi, ScanDirection scan_direction) -{ -    Page *page; -   -    page = g_object_new (PAGE_TYPE, NULL); -    if (scan_direction == TOP_TO_BOTTOM || scan_direction == BOTTOM_TO_TOP) { -        page->priv->width = width; -        page->priv->n_rows = height; -    } -    else { -        page->priv->width = height; -        page->priv->n_rows = width; -    } -    page->priv->dpi = dpi; -    page->priv->scan_direction = scan_direction; -    return page; +gint page_get_scan_height (Page* self) { +	gint result = 0; +	g_return_val_if_fail (self != NULL, 0); +	result = self->priv->n_rows; +	return result;  } -void -page_set_page_info (Page *page, ScanPageInfo *info) -{ -    g_return_if_fail (page != NULL); +void page_set_color_profile (Page* self, const gchar* color_profile) { +	gchar* _tmp0_; +	g_return_if_fail (self != NULL); +	_tmp0_ = g_strdup (color_profile); +	_g_free0 (self->priv->color_profile); +	self->priv->color_profile = _tmp0_; +} -    page->priv->expected_rows = info->height; -    page->priv->dpi = info->dpi; -    /* Create a white page */ -    page->priv->width = info->width; -    page->priv->n_rows = info->height; -    /* Variable height, try 50% of the width for now */ -    if (page->priv->n_rows < 0) -        page->priv->n_rows = page->priv->width / 2; -    page->priv->depth = info->depth; -    page->priv->n_channels = info->n_channels; -    page->priv->rowstride = (page->priv->width * page->priv->depth * page->priv->n_channels + 7) / 8; -    page->priv->pixels = g_realloc (page->priv->pixels, page->priv->n_rows * page->priv->rowstride); -    g_return_if_fail (page->priv->pixels != NULL); +gchar* page_get_color_profile (Page* self) { +	gchar* result = NULL; +	gchar* _tmp0_; +	g_return_val_if_fail (self != NULL, NULL); +	_tmp0_ = g_strdup (self->priv->color_profile); +	result = _tmp0_; +	return result; +} -    /* Fill with white */ -    if (page->priv->depth == 1) -        memset (page->priv->pixels, 0x00, page->priv->n_rows * page->priv->rowstride); -    else -        memset (page->priv->pixels, 0xFF, page->priv->n_rows * page->priv->rowstride); -    g_signal_emit (page, signals[SIZE_CHANGED], 0); -    g_signal_emit (page, signals[PIXELS_CHANGED], 0); +void page_set_no_crop (Page* self) { +	g_return_if_fail (self != NULL); +	if (!self->priv->has_crop_) { +		return; +	} +	self->priv->has_crop_ = FALSE; +	g_signal_emit_by_name (self, "crop-changed");  } -void -page_start (Page *page) -{ -    g_return_if_fail (page != NULL); +void page_set_custom_crop (Page* self, gint width, gint height) { +	gboolean _tmp0_ = FALSE; +	gboolean _tmp1_ = FALSE; +	gboolean _tmp2_ = FALSE; +	g_return_if_fail (self != NULL); +	g_return_if_fail (width >= 1); +	g_return_if_fail (height >= 1); +	if (self->priv->crop_name == NULL) { +		_tmp2_ = self->priv->has_crop_; +	} else { +		_tmp2_ = FALSE; +	} +	if (_tmp2_) { +		_tmp1_ = self->priv->crop_width == width; +	} else { +		_tmp1_ = FALSE; +	} +	if (_tmp1_) { +		_tmp0_ = self->priv->crop_height == height; +	} else { +		_tmp0_ = FALSE; +	} +	if (_tmp0_) { +		return; +	} +	_g_free0 (self->priv->crop_name); +	self->priv->crop_name = NULL; +	self->priv->has_crop_ = TRUE; +	self->priv->crop_width = width; +	self->priv->crop_height = height; +	g_signal_emit_by_name (self, "crop-changed"); +} + -    page->priv->scanning = TRUE; -    g_signal_emit (page, signals[SCAN_LINE_CHANGED], 0); +void page_set_named_crop (Page* self, const gchar* name) { +	gdouble width = 0.0; +	gdouble height = 0.0; +	const gchar* _tmp0_; +	GQuark _tmp1_; +	static GQuark _tmp1__label0 = 0; +	static GQuark _tmp1__label1 = 0; +	static GQuark _tmp1__label2 = 0; +	static GQuark _tmp1__label3 = 0; +	static GQuark _tmp1__label4 = 0; +	static GQuark _tmp1__label5 = 0; +	gchar* _tmp2_; +	gint _tmp3_; +	gint pw; +	gint _tmp4_; +	gint ph; +	g_return_if_fail (self != NULL); +	g_return_if_fail (name != NULL); +	_tmp0_ = name; +	_tmp1_ = (NULL == _tmp0_) ? 0 : g_quark_from_string (_tmp0_); +	if (_tmp1_ == ((0 != _tmp1__label0) ? _tmp1__label0 : (_tmp1__label0 = g_quark_from_static_string ("A4")))) { +		switch (0) { +			default: +			{ +				width = 8.3; +				height = 11.7; +				break; +			} +		} +	} else if (_tmp1_ == ((0 != _tmp1__label1) ? _tmp1__label1 : (_tmp1__label1 = g_quark_from_static_string ("A5")))) { +		switch (0) { +			default: +			{ +				width = 5.8; +				height = 8.3; +				break; +			} +		} +	} else if (_tmp1_ == ((0 != _tmp1__label2) ? _tmp1__label2 : (_tmp1__label2 = g_quark_from_static_string ("A6")))) { +		switch (0) { +			default: +			{ +				width = 4.1; +				height = 5.8; +				break; +			} +		} +	} else if (_tmp1_ == ((0 != _tmp1__label3) ? _tmp1__label3 : (_tmp1__label3 = g_quark_from_static_string ("letter")))) { +		switch (0) { +			default: +			{ +				width = 8.5; +				height = (gdouble) 11; +				break; +			} +		} +	} else if (_tmp1_ == ((0 != _tmp1__label4) ? _tmp1__label4 : (_tmp1__label4 = g_quark_from_static_string ("legal")))) { +		switch (0) { +			default: +			{ +				width = 8.5; +				height = (gdouble) 14; +				break; +			} +		} +	} else if (_tmp1_ == ((0 != _tmp1__label5) ? _tmp1__label5 : (_tmp1__label5 = g_quark_from_static_string ("4x6")))) { +		switch (0) { +			default: +			{ +				width = (gdouble) 4; +				height = (gdouble) 6; +				break; +			} +		} +	} else { +		switch (0) { +			default: +			{ +				g_warning ("page.vala:437: Unknown paper size '%s'", name); +				return; +			} +		} +	} +	_tmp2_ = g_strdup (name); +	_g_free0 (self->priv->crop_name); +	self->priv->crop_name = _tmp2_; +	self->priv->has_crop_ = TRUE; +	_tmp3_ = page_get_width (self); +	pw = _tmp3_; +	_tmp4_ = page_get_height (self); +	ph = _tmp4_; +	if (pw > ph) { +		gdouble t = 0.0; +		t = width; +		width = height; +		height = t; +	} +	self->priv->crop_width = (gint) ((width * self->priv->dpi) + 0.5); +	self->priv->crop_height = (gint) ((height * self->priv->dpi) + 0.5); +	if (self->priv->crop_width < pw) { +		self->priv->crop_x = (pw - self->priv->crop_width) / 2; +	} else { +		self->priv->crop_x = 0; +	} +	if (self->priv->crop_height < ph) { +		self->priv->crop_y = (ph - self->priv->crop_height) / 2; +	} else { +		self->priv->crop_y = 0; +	} +	g_signal_emit_by_name (self, "crop-changed");  } -gboolean -page_is_scanning (Page *page) -{ -    g_return_val_if_fail (page != NULL, FALSE); -   -    return page->priv->scanning; +void page_move_crop (Page* self, gint x, gint y) { +	gint _tmp0_; +	gint _tmp1_; +	g_return_if_fail (self != NULL); +	g_return_if_fail (x >= 0); +	g_return_if_fail (y >= 0); +	_tmp0_ = page_get_width (self); +	g_return_if_fail (x < _tmp0_); +	_tmp1_ = page_get_height (self); +	g_return_if_fail (y < _tmp1_); +	self->priv->crop_x = x; +	self->priv->crop_y = y; +	g_signal_emit_by_name (self, "crop-changed");  } -gboolean -page_has_data (Page *page) -{ -    g_return_val_if_fail (page != NULL, FALSE); -    return page->priv->has_data; +void page_rotate_crop (Page* self) { +	gint t = 0; +	g_return_if_fail (self != NULL); +	if (!self->priv->has_crop_) { +		return; +	} +	t = self->priv->crop_width; +	self->priv->crop_width = self->priv->crop_height; +	self->priv->crop_height = t; +	if (self->priv->crop_name == NULL) { +		gint w = 0; +		gint h = 0; +		gint _tmp0_; +		gint _tmp1_; +		_tmp0_ = page_get_width (self); +		w = _tmp0_; +		_tmp1_ = page_get_height (self); +		h = _tmp1_; +		if ((self->priv->crop_x + self->priv->crop_width) > w) { +			self->priv->crop_x = w - self->priv->crop_width; +		} +		if (self->priv->crop_x < 0) { +			self->priv->crop_x = 0; +			self->priv->crop_width = w; +		} +		if ((self->priv->crop_y + self->priv->crop_height) > h) { +			self->priv->crop_y = h - self->priv->crop_height; +		} +		if (self->priv->crop_y < 0) { +			self->priv->crop_y = 0; +			self->priv->crop_height = h; +		} +	} +	g_signal_emit_by_name (self, "crop-changed");  } -gboolean -page_is_color (Page *page) -{ -    g_return_val_if_fail (page != NULL, FALSE); -    return page->priv->n_channels > 1; +gboolean page_has_crop (Page* self) { +	gboolean result = FALSE; +	g_return_val_if_fail (self != NULL, FALSE); +	result = self->priv->has_crop_; +	return result;  } -gint -page_get_scan_line (Page *page) -{ -    g_return_val_if_fail (page != NULL, -1); -    return page->priv->scan_line; +void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height) { +	gint _x = 0; +	gint _y = 0; +	gint _width = 0; +	gint _height = 0; +	g_return_if_fail (self != NULL); +	_x = self->priv->crop_x; +	_y = self->priv->crop_y; +	_width = self->priv->crop_width; +	_height = self->priv->crop_height; +	if (x) { +		*x = _x; +	} +	if (y) { +		*y = _y; +	} +	if (width) { +		*width = _width; +	} +	if (height) { +		*height = _height; +	}  } -static void -parse_line (Page *page, ScanLine *line, gint n, gboolean *size_changed) -{ -    gint line_number; +gchar* page_get_named_crop (Page* self) { +	gchar* result = NULL; +	gchar* _tmp0_; +	g_return_val_if_fail (self != NULL, NULL); +	_tmp0_ = g_strdup (self->priv->crop_name); +	result = _tmp0_; +	return result; +} + + +guchar* page_get_pixels (Page* self, int* result_length1) { +	guchar* result = NULL; +	guchar* _tmp0_; +	g_return_val_if_fail (self != NULL, NULL); +	_tmp0_ = self->priv->pixels; +	if (result_length1) { +		*result_length1 = self->priv->pixels_length1; +	} +	result = _tmp0_; +	return result; +} + + +static guchar page_get_sample (Page* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint n_channels, gint channel) { +	guchar result = '\0'; +	g_return_val_if_fail (self != NULL, '\0'); +	result = (guchar) 0xFF; +	return result; +} + + +static void page_get_pixel (Page* self, gint x, gint y, guchar* pixel, int pixel_length1, gint offset) { +	ScanDirection _tmp0_; +	gint _tmp5_; +	gint depth; +	gint _tmp6_; +	gint n_channels; +	gint _tmp7_; +	gint line_offset; +	gboolean _tmp8_ = FALSE; +	guchar _tmp14_; +	guchar _tmp15_; +	guchar _tmp16_; +	g_return_if_fail (self != NULL); +	_tmp0_ = page_get_scan_direction (self); +	switch (_tmp0_) { +		case SCAN_DIRECTION_TOP_TO_BOTTOM: +		{ +			break; +		} +		case SCAN_DIRECTION_BOTTOM_TO_TOP: +		{ +			gint _tmp1_; +			gint _tmp2_; +			_tmp1_ = page_get_scan_width (self); +			x = (_tmp1_ - x) - 1; +			_tmp2_ = page_get_scan_height (self); +			y = (_tmp2_ - y) - 1; +			break; +		} +		case SCAN_DIRECTION_LEFT_TO_RIGHT: +		{ +			gint t; +			gint _tmp3_; +			t = x; +			_tmp3_ = page_get_scan_width (self); +			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 (self); +			y = (_tmp4_ - t) - 1; +			break; +		} +		default: +		break; +	} +	_tmp5_ = page_get_depth (self); +	depth = _tmp5_; +	_tmp6_ = page_get_n_channels (self); +	n_channels = _tmp6_; +	_tmp7_ = page_get_rowstride (self); +	line_offset = _tmp7_ * y; +	if (depth == 8) { +		_tmp8_ = n_channels == 3; +	} else { +		_tmp8_ = FALSE; +	} +	if (_tmp8_) { +		gint o; +		o = line_offset + (x * n_channels); +		pixel[offset + 0] = self->priv->pixels[o]; +		pixel[offset + 1] = self->priv->pixels[o + 1]; +		pixel[offset + 2] = self->priv->pixels[o + 2]; +		return; +	} else { +		gboolean _tmp9_ = FALSE; +		if (depth == 8) { +			_tmp9_ = n_channels == 1; +		} else { +			_tmp9_ = FALSE; +		} +		if (_tmp9_) { +			guchar p; +			p = self->priv->pixels[line_offset + x]; +			pixel[offset + 2] = p; +			pixel[offset + 1] = pixel[offset + 2]; +			pixel[offset + 0] = pixel[offset + 1]; +			return; +		} else { +			gboolean _tmp10_ = FALSE; +			if (depth == 1) { +				_tmp10_ = n_channels == 1; +			} else { +				_tmp10_ = FALSE; +			} +			if (_tmp10_) { +				guchar p; +				gint _tmp11_ = 0; +				p = self->priv->pixels[line_offset + (x / 8)]; +				if (((gint) (p & (0x80 >> (x % 8)))) != 0) { +					_tmp11_ = 0x00; +				} else { +					_tmp11_ = 0xFF; +				} +				pixel[offset + 2] = (guchar) _tmp11_; +				pixel[offset + 1] = pixel[offset + 2]; +				pixel[offset + 0] = pixel[offset + 1]; +				return; +			} else { +				gboolean _tmp12_ = FALSE; +				if (depth == 2) { +					_tmp12_ = n_channels == 1; +				} else { +					_tmp12_ = FALSE; +				} +				if (_tmp12_) { +					gint _tmp13_[4] = {0}; +					gint block_shift[4]; +					guchar p; +					gint sample; +					_tmp13_[0] = 6; +					_tmp13_[1] = 4; +					_tmp13_[2] = 2; +					_tmp13_[3] = 0; +					memcpy (block_shift, _tmp13_, 4 * sizeof (gint)); +					p = self->priv->pixels[line_offset + (x / 4)]; +					sample = (p >> block_shift[x % 4]) & 0x3; +					sample = (sample * 255) / 3; +					pixel[offset + 2] = (guchar) sample; +					pixel[offset + 1] = pixel[offset + 2]; +					pixel[offset + 0] = pixel[offset + 1]; +					return; +				} +			} +		} +	} +	_tmp14_ = page_get_sample (self, self->priv->pixels, self->priv->pixels_length1, line_offset, x, depth, n_channels, 0); +	pixel[offset + 0] = _tmp14_; +	_tmp15_ = page_get_sample (self, self->priv->pixels, self->priv->pixels_length1, line_offset, x, depth, n_channels, 1); +	pixel[offset + 1] = _tmp15_; +	_tmp16_ = page_get_sample (self, self->priv->pixels, self->priv->pixels_length1, line_offset, x, depth, n_channels, 2); +	pixel[offset + 2] = _tmp16_; +} + + +GdkPixbuf* page_get_image (Page* self, gboolean apply_crop) { +	GdkPixbuf* result = NULL; +	gint l = 0; +	gint r = 0; +	gint t = 0; +	gint b = 0; +	gboolean _tmp0_ = FALSE; +	GdkPixbuf* _tmp7_ = NULL; +	GdkPixbuf* image; +	guint8* _tmp8_ = NULL; +	guint8* image_pixels; +	gint image_pixels_length1; +	gint _image_pixels_size_; +	g_return_val_if_fail (self != NULL, NULL); +	if (apply_crop) { +		_tmp0_ = self->priv->has_crop_; +	} else { +		_tmp0_ = FALSE; +	} +	if (_tmp0_) { +		gint _tmp1_; +		gint _tmp3_; +		l = self->priv->crop_x; +		r = l + self->priv->crop_width; +		t = self->priv->crop_y; +		b = t + self->priv->crop_height; +		if (l < 0) { +			l = 0; +		} +		_tmp1_ = page_get_width (self); +		if (r > _tmp1_) { +			gint _tmp2_; +			_tmp2_ = page_get_width (self); +			r = _tmp2_; +		} +		if (t < 0) { +			t = 0; +		} +		_tmp3_ = page_get_height (self); +		if (b > _tmp3_) { +			gint _tmp4_; +			_tmp4_ = page_get_height (self); +			b = _tmp4_; +		} +	} else { +		gint _tmp5_; +		gint _tmp6_; +		l = 0; +		_tmp5_ = page_get_width (self); +		r = _tmp5_; +		t = 0; +		_tmp6_ = page_get_height (self); +		b = _tmp6_; +	} +	_tmp7_ = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, r - l, b - t); +	image = _tmp7_; +	_tmp8_ = gdk_pixbuf_get_pixels (image); +	image_pixels = _tmp8_; +	image_pixels_length1 = -1; +	_image_pixels_size_ = image_pixels_length1; +	{ +		gint y; +		y = t; +		{ +			gboolean _tmp9_; +			_tmp9_ = TRUE; +			while (TRUE) { +				gint _tmp10_; +				gint offset; +				if (!_tmp9_) { +					y++; +				} +				_tmp9_ = FALSE; +				if (!(y < b)) { +					break; +				} +				_tmp10_ = gdk_pixbuf_get_rowstride (image); +				offset = _tmp10_ * (y - t); +				{ +					gint x; +					x = l; +					{ +						gboolean _tmp11_; +						_tmp11_ = TRUE; +						while (TRUE) { +							if (!_tmp11_) { +								x++; +							} +							_tmp11_ = FALSE; +							if (!(x < r)) { +								break; +							} +							page_get_pixel (self, x, y, image_pixels, image_pixels_length1, offset + ((x - l) * 3)); +						} +					} +				} +			} +		} +	} +	result = image; +	return result; +} + + +static gchar* string_to_utf8 (const gchar* self, int* result_length1) { +	gchar* result = NULL; +	gint _tmp0_; +	gchar* _tmp1_ = NULL; +	gchar* _result_; +	gint _result__length1; +	gint __result__size_; +	gint _tmp2_; +	gchar* _tmp3_; +	g_return_val_if_fail (self != NULL, NULL); +	_tmp0_ = strlen (self); +	_tmp1_ = g_new0 (gchar, _tmp0_ + 1); +	_result_ = _tmp1_; +	_result__length1 = _tmp0_ + 1; +	__result__size_ = _result__length1; +	_result__length1--; +	_tmp2_ = strlen (self); +	memcpy (_result_, self, (gsize) _tmp2_); +	_tmp3_ = _result_; +	if (result_length1) { +		*result_length1 = _result__length1; +	} +	result = _tmp3_; +	return result; +} + + +static gchar* page_get_icc_data_encoded (Page* self, const gchar* icc_profile_filename) { +	gchar* result = NULL; +	gchar* contents = NULL; +	gint _tmp1_; +	gchar* _tmp2_ = NULL; +	guchar* _tmp3_; +	gint _tmp3__length1; +	gchar* _tmp4_ = NULL; +	gchar* _tmp5_; +	GError * _inner_error_ = NULL; +	g_return_val_if_fail (self != NULL, NULL); +	g_return_val_if_fail (icc_profile_filename != NULL, NULL); +	{ +		gchar* _tmp0_ = NULL; +		g_file_get_contents (icc_profile_filename, &_tmp0_, NULL, &_inner_error_); +		_g_free0 (contents); +		contents = _tmp0_; +		if (_inner_error_ != NULL) { +			goto __catch2_g_error; +		} +	} +	goto __finally2; +	__catch2_g_error: +	{ +		GError* e = NULL; +		e = _inner_error_; +		_inner_error_ = NULL; +		g_warning ("page.vala:670: failed to get icc profile data: %s", e->message); +		result = NULL; +		_g_error_free0 (e); +		_g_free0 (contents); +		return result; +	} +	__finally2: +	if (_inner_error_ != NULL) { +		_g_free0 (contents); +		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); +		g_clear_error (&_inner_error_); +		return NULL; +	} +	_tmp2_ = string_to_utf8 (contents, &_tmp1_); +	_tmp3_ = (guchar*) _tmp2_; +	_tmp3__length1 = _tmp1_; +	_tmp4_ = g_base64_encode (_tmp3_, _tmp1_); +	_tmp5_ = _tmp4_; +	_tmp3_ = (g_free (_tmp3_), NULL); +	result = _tmp5_; +	_g_free0 (contents); +	return result; +} -    line_number = line->number + n; -    /* Extend image if necessary */ -    while (line_number >= page_get_scan_height (page)) { -        gint rows; +void page_save (Page* self, const gchar* type, GFile* file, GError** error) { +	GFileOutputStream* _tmp0_ = NULL; +	GFileOutputStream* stream; +	PixbufWriter* _tmp1_ = NULL; +	PixbufWriter* writer; +	GdkPixbuf* _tmp2_ = NULL; +	GdkPixbuf* image; +	gchar* icc_profile_data; +	gint _tmp4_; +	GError * _inner_error_ = NULL; +	g_return_if_fail (self != NULL); +	g_return_if_fail (type != NULL); +	g_return_if_fail (file != NULL); +	_tmp0_ = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &_inner_error_); +	stream = _tmp0_; +	if (_inner_error_ != NULL) { +		g_propagate_error (error, _inner_error_); +		return; +	} +	_tmp1_ = pixbuf_writer_new (stream); +	writer = _tmp1_; +	_tmp2_ = page_get_image (self, TRUE); +	image = _tmp2_; +	icc_profile_data = NULL; +	if (self->priv->color_profile != NULL) { +		gchar* _tmp3_ = NULL; +		_tmp3_ = page_get_icc_data_encoded (self, self->priv->color_profile); +		_g_free0 (icc_profile_data); +		icc_profile_data = _tmp3_; +	} +	_tmp4_ = g_strcmp0 (type, "jpeg"); +	if (_tmp4_ == 0) { +		gchar* _tmp5_; +		gchar** _tmp6_ = NULL; +		gchar** keys; +		gint keys_length1; +		gint _keys_size_; +		gchar* _tmp7_; +		gchar** _tmp8_ = NULL; +		gchar** values; +		gint values_length1; +		gint _values_size_; +		_tmp5_ = g_strdup ("quality"); +		_tmp6_ = g_new0 (gchar*, 2 + 1); +		_tmp6_[0] = _tmp5_; +		_tmp6_[1] = NULL; +		keys = _tmp6_; +		keys_length1 = 2; +		_keys_size_ = keys_length1; +		_tmp7_ = g_strdup ("90"); +		_tmp8_ = g_new0 (gchar*, 2 + 1); +		_tmp8_[0] = _tmp7_; +		_tmp8_[1] = NULL; +		values = _tmp8_; +		values_length1 = 2; +		_values_size_ = values_length1; +		pixbuf_writer_save (writer, image, "jpeg", keys, keys_length1, values, values_length1, &_inner_error_); +		if (_inner_error_ != NULL) { +			g_propagate_error (error, _inner_error_); +			values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); +			keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); +			_g_free0 (icc_profile_data); +			_g_object_unref0 (image); +			_pixbuf_writer_unref0 (writer); +			_g_object_unref0 (stream); +			return; +		} +		values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); +		keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); +	} else { +		gint _tmp9_; +		_tmp9_ = g_strcmp0 (type, "png"); +		if (_tmp9_ == 0) { +			gchar* _tmp10_; +			gchar** _tmp11_ = NULL; +			gchar** keys; +			gint keys_length1; +			gint _keys_size_; +			gchar* _tmp12_; +			gchar** _tmp13_ = NULL; +			gchar** values; +			gint values_length1; +			gint _values_size_; +			_tmp10_ = g_strdup ("icc-profile"); +			_tmp11_ = g_new0 (gchar*, 2 + 1); +			_tmp11_[0] = _tmp10_; +			_tmp11_[1] = NULL; +			keys = _tmp11_; +			keys_length1 = 2; +			_keys_size_ = keys_length1; +			_tmp12_ = g_strdup (icc_profile_data); +			_tmp13_ = g_new0 (gchar*, 2 + 1); +			_tmp13_[0] = _tmp12_; +			_tmp13_[1] = NULL; +			values = _tmp13_; +			values_length1 = 2; +			_values_size_ = values_length1; +			if (icc_profile_data == NULL) { +				gchar* _tmp14_; +				_tmp14_ = NULL; +				_g_free0 (keys[0]); +				keys[0] = _tmp14_; +			} +			pixbuf_writer_save (writer, image, "png", keys, keys_length1, values, values_length1, &_inner_error_); +			if (_inner_error_ != NULL) { +				g_propagate_error (error, _inner_error_); +				values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); +				keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); +				_g_free0 (icc_profile_data); +				_g_object_unref0 (image); +				_pixbuf_writer_unref0 (writer); +				_g_object_unref0 (stream); +				return; +			} +			values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); +			keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); +		} else { +			gint _tmp15_; +			_tmp15_ = g_strcmp0 (type, "tiff"); +			if (_tmp15_ == 0) { +				gchar* _tmp16_; +				gchar* _tmp17_; +				gchar** _tmp18_ = NULL; +				gchar** keys; +				gint keys_length1; +				gint _keys_size_; +				gchar* _tmp19_; +				gchar* _tmp20_; +				gchar** _tmp21_ = NULL; +				gchar** values; +				gint values_length1; +				gint _values_size_; +				_tmp16_ = g_strdup ("compression"); +				_tmp17_ = g_strdup ("icc-profile"); +				_tmp18_ = g_new0 (gchar*, 3 + 1); +				_tmp18_[0] = _tmp16_; +				_tmp18_[1] = _tmp17_; +				_tmp18_[2] = NULL; +				keys = _tmp18_; +				keys_length1 = 3; +				_keys_size_ = keys_length1; +				_tmp19_ = g_strdup ("8"); +				_tmp20_ = g_strdup (icc_profile_data); +				_tmp21_ = g_new0 (gchar*, 3 + 1); +				_tmp21_[0] = _tmp19_; +				_tmp21_[1] = _tmp20_; +				_tmp21_[2] = NULL; +				values = _tmp21_; +				values_length1 = 3; +				_values_size_ = values_length1; +				if (icc_profile_data == NULL) { +					gchar* _tmp22_; +					_tmp22_ = NULL; +					_g_free0 (keys[1]); +					keys[1] = _tmp22_; +				} +				pixbuf_writer_save (writer, image, "tiff", keys, keys_length1, values, values_length1, &_inner_error_); +				if (_inner_error_ != NULL) { +					g_propagate_error (error, _inner_error_); +					values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); +					keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); +					_g_free0 (icc_profile_data); +					_g_object_unref0 (image); +					_pixbuf_writer_unref0 (writer); +					_g_object_unref0 (stream); +					return; +				} +				values = (_vala_array_free (values, values_length1, (GDestroyNotify) g_free), NULL); +				keys = (_vala_array_free (keys, keys_length1, (GDestroyNotify) g_free), NULL); +			} else { +			} +		} +	} +	_g_free0 (icc_profile_data); +	_g_object_unref0 (image); +	_pixbuf_writer_unref0 (writer); +	_g_object_unref0 (stream); +} -        /* Extend image */ -        rows = page->priv->n_rows; -        page->priv->n_rows = rows + page->priv->width / 2; -        g_debug("Extending image from %d lines to %d lines", rows, page->priv->n_rows); -        page->priv->pixels = g_realloc (page->priv->pixels, page->priv->n_rows * page->priv->rowstride); -        *size_changed = TRUE; -    } +static void value_page_init (GValue* value) { +	value->data[0].v_pointer = NULL; +} -    /* Copy in new row */ -    memcpy (page->priv->pixels + line_number * page->priv->rowstride, line->data + n * line->data_length, line->data_length); -    page->priv->scan_line = line_number; +static void value_page_free_value (GValue* value) { +	if (value->data[0].v_pointer) { +		page_unref (value->data[0].v_pointer); +	}  } -void -page_parse_scan_line (Page *page, ScanLine *line) -{ -    gint i; -    gboolean size_changed = FALSE; +static void value_page_copy_value (const GValue* src_value, GValue* dest_value) { +	if (src_value->data[0].v_pointer) { +		dest_value->data[0].v_pointer = page_ref (src_value->data[0].v_pointer); +	} else { +		dest_value->data[0].v_pointer = NULL; +	} +} -    g_return_if_fail (page != NULL); -    for (i = 0; i < line->n_lines; i++) -        parse_line (page, line, i, &size_changed); +static gpointer value_page_peek_pointer (const GValue* value) { +	return value->data[0].v_pointer; +} -    page->priv->has_data = TRUE; -    if (size_changed) -        g_signal_emit (page, signals[SIZE_CHANGED], 0); -    g_signal_emit (page, signals[SCAN_LINE_CHANGED], 0); -    g_signal_emit (page, signals[PIXELS_CHANGED], 0); +static gchar* value_page_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { +	if (collect_values[0].v_pointer) { +		Page* 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_ref (object); +	} else { +		value->data[0].v_pointer = NULL; +	} +	return NULL;  } -void -page_finish (Page *page) -{ -    gboolean size_changed = FALSE; +static gchar* value_page_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { +	Page** 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_ref (value->data[0].v_pointer); +	} +	return NULL; +} -    g_return_if_fail (page != NULL); -    /* Trim page */ -    if (page->priv->expected_rows < 0 && -        page->priv->scan_line != page_get_scan_height (page)) { -        gint rows; +GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { +	ParamSpecPage* spec; +	g_return_val_if_fail (g_type_is_a (object_type, TYPE_PAGE), 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); +} + -        rows = page->priv->n_rows; -        page->priv->n_rows = page->priv->scan_line; -        page->priv->pixels = g_realloc (page->priv->pixels, page->priv->n_rows * page->priv->rowstride); -        g_debug("Trimming page from %d lines to %d lines", rows, page->priv->n_rows); +gpointer value_get_page (const GValue* value) { +	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE), NULL); +	return value->data[0].v_pointer; +} -        size_changed = TRUE; -    } -    page->priv->scanning = FALSE; -    if (size_changed) -        g_signal_emit (page, signals[SIZE_CHANGED], 0); -    g_signal_emit (page, signals[SCAN_LINE_CHANGED], 0); +void value_set_page (GValue* value, gpointer v_object) { +	Page* old; +	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE)); +	old = value->data[0].v_pointer; +	if (v_object) { +		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE)); +		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_ref (value->data[0].v_pointer); +	} else { +		value->data[0].v_pointer = NULL; +	} +	if (old) { +		page_unref (old); +	}  } -ScanDirection -page_get_scan_direction (Page *page) -{ -    g_return_val_if_fail (page != NULL, TOP_TO_BOTTOM); +void value_take_page (GValue* value, gpointer v_object) { +	Page* old; +	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE)); +	old = value->data[0].v_pointer; +	if (v_object) { +		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE)); +		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_unref (old); +	} +} + -    return page->priv->scan_direction; +static void page_class_init (PageClass * klass) { +	page_parent_class = g_type_class_peek_parent (klass); +	PAGE_CLASS (klass)->finalize = page_finalize; +	g_type_class_add_private (klass, sizeof (PagePrivate)); +	g_signal_new ("pixels_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +	g_signal_new ("size_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +	g_signal_new ("scan_line_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +	g_signal_new ("scan_direction_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); +	g_signal_new ("crop_changed", TYPE_PAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);  } -static void -page_set_scan_direction (Page *page, ScanDirection scan_direction) -{ -    gint left_steps, t; -    gboolean size_changed = FALSE; -    gint width, height; +static void page_instance_init (Page * self) { +	self->priv = PAGE_GET_PRIVATE (self); +	self->priv->scan_direction = SCAN_DIRECTION_TOP_TO_BOTTOM; +	self->ref_count = 1; +} -    g_return_if_fail (page != NULL); -    if (page->priv->scan_direction == scan_direction) -        return; +static void page_finalize (Page* obj) { +	Page * self; +	self = PAGE (obj); +	_g_free0 (self->priv->color_profile); +	self->priv->pixels = (g_free (self->priv->pixels), NULL); +	_g_free0 (self->priv->crop_name); +} -    /* Work out how many times it has been rotated to the left */ -    left_steps = scan_direction - page->priv->scan_direction; -    if (left_steps < 0) -        left_steps += 4; -    if (left_steps != 2) -        size_changed = TRUE; -   -    width = page_get_width (page); -    height = page_get_height (page); -    /* Rotate crop */ -    if (page->priv->has_crop) { -        switch (left_steps) { -        /* 90 degrees counter-clockwise */ -        case 1: -            t = page->priv->crop_x; -            page->priv->crop_x = page->priv->crop_y; -            page->priv->crop_y = width - (t + page->priv->crop_width); -            t = page->priv->crop_width; -            page->priv->crop_width = page->priv->crop_height; -            page->priv->crop_height = t; -            break; -        /* 180 degrees */ -        case 2: -            page->priv->crop_x = width - (page->priv->crop_x + page->priv->crop_width); -            page->priv->crop_y = width - (page->priv->crop_y + page->priv->crop_height); -            break; -        /* 90 degrees clockwise */ -        case 3: -            t = page->priv->crop_y; -            page->priv->crop_y = page->priv->crop_x; -            page->priv->crop_x = height - (t + page->priv->crop_height); -            t = page->priv->crop_width; -            page->priv->crop_width = page->priv->crop_height; -            page->priv->crop_height = t; -            break; -        } -    } +GType page_get_type (void) { +	static volatile gsize page_type_id__volatile = 0; +	if (g_once_init_enter (&page_type_id__volatile)) { +		static const GTypeValueTable g_define_type_value_table = { value_page_init, value_page_free_value, value_page_copy_value, value_page_peek_pointer, "p", value_page_collect_value, "p", value_page_lcopy_value }; +		static const GTypeInfo g_define_type_info = { sizeof (PageClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) page_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Page), 0, (GInstanceInitFunc) page_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_type_id; +		page_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Page", &g_define_type_info, &g_define_type_fundamental_info, 0); +		g_once_init_leave (&page_type_id__volatile, page_type_id); +	} +	return page_type_id__volatile; +} + -    page->priv->scan_direction = scan_direction; -    if (size_changed) -        g_signal_emit (page, signals[SIZE_CHANGED], 0); -    g_signal_emit (page, signals[SCAN_DIRECTION_CHANGED], 0); -    if (page->priv->has_crop) -        g_signal_emit (page, signals[CROP_CHANGED], 0); +gpointer page_ref (gpointer instance) { +	Page* self; +	self = instance; +	g_atomic_int_inc (&self->ref_count); +	return instance;  } -void -page_rotate_left (Page *page) -{ -    ScanDirection scan_direction; +void page_unref (gpointer instance) { +	Page* self; +	self = instance; +	if (g_atomic_int_dec_and_test (&self->ref_count)) { +		PAGE_GET_CLASS (self)->finalize (self); +		g_type_free_instance ((GTypeInstance *) self); +	} +} -    g_return_if_fail (page != NULL); -    scan_direction = page_get_scan_direction (page); -    if (scan_direction == RIGHT_TO_LEFT) -        scan_direction = TOP_TO_BOTTOM; -    else -        scan_direction++; -    page_set_scan_direction (page, scan_direction); +static gpointer _g_object_ref0 (gpointer self) { +	return self ? g_object_ref (self) : NULL;  } -void -page_rotate_right (Page *page) -{ -    ScanDirection scan_direction; +PixbufWriter* pixbuf_writer_construct (GType object_type, GFileOutputStream* stream) { +	PixbufWriter* self = NULL; +	GFileOutputStream* _tmp0_; +	g_return_val_if_fail (stream != NULL, NULL); +	self = (PixbufWriter*) g_type_create_instance (object_type); +	_tmp0_ = _g_object_ref0 (stream); +	_g_object_unref0 (self->stream); +	self->stream = _tmp0_; +	return self; +} + -    scan_direction = page_get_scan_direction (page); -    if (scan_direction == TOP_TO_BOTTOM) -        scan_direction = RIGHT_TO_LEFT; -    else -        scan_direction--; -    page_set_scan_direction (page, scan_direction); +PixbufWriter* pixbuf_writer_new (GFileOutputStream* stream) { +	return pixbuf_writer_construct (TYPE_PIXBUF_WRITER, stream);  } -gint -page_get_dpi (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); +static gboolean _pixbuf_writer_write_pixbuf_data_gdk_pixbuf_save_func (guint8* buf, gsize buf_length1, GError** error, gpointer self) { +	gboolean result; +	result = pixbuf_writer_write_pixbuf_data (self, buf, buf_length1, error); +	return result; +} -    return page->priv->dpi; + +void pixbuf_writer_save (PixbufWriter* self, GdkPixbuf* image, const gchar* type, gchar** option_keys, int option_keys_length1, gchar** option_values, int option_values_length1, GError** error) { +	GError * _inner_error_ = NULL; +	g_return_if_fail (self != NULL); +	g_return_if_fail (image != NULL); +	g_return_if_fail (type != NULL); +	gdk_pixbuf_save_to_callbackv (image, _pixbuf_writer_write_pixbuf_data_gdk_pixbuf_save_func, self, type, option_keys, option_values, &_inner_error_); +	if (_inner_error_ != NULL) { +		g_propagate_error (error, _inner_error_); +		return; +	}  } -gboolean -page_is_landscape (Page *page) -{ -   return page_get_width (page) > page_get_height (page); +static gboolean pixbuf_writer_write_pixbuf_data (PixbufWriter* self, guint8* buf, int buf_length1, GError** error) { +	gboolean result = FALSE; +	GError * _inner_error_ = NULL; +	g_return_val_if_fail (self != NULL, FALSE); +	g_output_stream_write_all ((GOutputStream*) self->stream, buf, (gsize) buf_length1, NULL, NULL, &_inner_error_); +	if (_inner_error_ != NULL) { +		g_propagate_error (error, _inner_error_); +		return FALSE; +	} +	result = TRUE; +	return result;  } -gint -page_get_width (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); +static void value_pixbuf_writer_init (GValue* value) { +	value->data[0].v_pointer = NULL; +} + -    if (page->priv->scan_direction == TOP_TO_BOTTOM || page->priv->scan_direction == BOTTOM_TO_TOP) -        return page->priv->width; -    else -        return page->priv->n_rows; +static void value_pixbuf_writer_free_value (GValue* value) { +	if (value->data[0].v_pointer) { +		pixbuf_writer_unref (value->data[0].v_pointer); +	}  } -gint -page_get_height (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); +static void value_pixbuf_writer_copy_value (const GValue* src_value, GValue* dest_value) { +	if (src_value->data[0].v_pointer) { +		dest_value->data[0].v_pointer = pixbuf_writer_ref (src_value->data[0].v_pointer); +	} else { +		dest_value->data[0].v_pointer = NULL; +	} +} + -    if (page->priv->scan_direction == TOP_TO_BOTTOM || page->priv->scan_direction == BOTTOM_TO_TOP) -        return page->priv->n_rows; -    else -        return page->priv->width; +static gpointer value_pixbuf_writer_peek_pointer (const GValue* value) { +	return value->data[0].v_pointer;  } -gint -page_get_depth (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); -    return page->priv->depth; +static gchar* value_pixbuf_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { +	if (collect_values[0].v_pointer) { +		PixbufWriter* 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 = pixbuf_writer_ref (object); +	} else { +		value->data[0].v_pointer = NULL; +	} +	return NULL;  } -gint page_get_n_channels (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); -    return page->priv->n_channels; +static gchar* value_pixbuf_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) { +	PixbufWriter** 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 = pixbuf_writer_ref (value->data[0].v_pointer); +	} +	return NULL;  } -gint page_get_rowstride (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); -    return page->priv->rowstride; +GParamSpec* param_spec_pixbuf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) { +	ParamSpecPixbufWriter* spec; +	g_return_val_if_fail (g_type_is_a (object_type, TYPE_PIXBUF_WRITER), 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);  } -gint -page_get_scan_width (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); +gpointer value_get_pixbuf_writer (const GValue* value) { +	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PIXBUF_WRITER), NULL); +	return value->data[0].v_pointer; +} + -    return page->priv->width; +void value_set_pixbuf_writer (GValue* value, gpointer v_object) { +	PixbufWriter* old; +	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PIXBUF_WRITER)); +	old = value->data[0].v_pointer; +	if (v_object) { +		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PIXBUF_WRITER)); +		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; +		pixbuf_writer_ref (value->data[0].v_pointer); +	} else { +		value->data[0].v_pointer = NULL; +	} +	if (old) { +		pixbuf_writer_unref (old); +	}  } -gint -page_get_scan_height (Page *page) -{ -    g_return_val_if_fail (page != NULL, 0); +void value_take_pixbuf_writer (GValue* value, gpointer v_object) { +	PixbufWriter* old; +	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PIXBUF_WRITER)); +	old = value->data[0].v_pointer; +	if (v_object) { +		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PIXBUF_WRITER)); +		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) { +		pixbuf_writer_unref (old); +	} +} + -    return page->priv->n_rows; +static void pixbuf_writer_class_init (PixbufWriterClass * klass) { +	pixbuf_writer_parent_class = g_type_class_peek_parent (klass); +	PIXBUF_WRITER_CLASS (klass)->finalize = pixbuf_writer_finalize;  } -void page_set_color_profile (Page *page, const gchar *color_profile) -{ -     g_free (page->priv->color_profile); -     page->priv->color_profile = g_strdup (color_profile); +static void pixbuf_writer_instance_init (PixbufWriter * self) { +	self->ref_count = 1;  } -const gchar *page_get_color_profile (Page *page) -{ -     return page->priv->color_profile; +static void pixbuf_writer_finalize (PixbufWriter* obj) { +	PixbufWriter * self; +	self = PIXBUF_WRITER (obj); +	_g_object_unref0 (self->stream);  } -void -page_set_no_crop (Page *page) -{ -    g_return_if_fail (page != NULL); +GType pixbuf_writer_get_type (void) { +	static volatile gsize pixbuf_writer_type_id__volatile = 0; +	if (g_once_init_enter (&pixbuf_writer_type_id__volatile)) { +		static const GTypeValueTable g_define_type_value_table = { value_pixbuf_writer_init, value_pixbuf_writer_free_value, value_pixbuf_writer_copy_value, value_pixbuf_writer_peek_pointer, "p", value_pixbuf_writer_collect_value, "p", value_pixbuf_writer_lcopy_value }; +		static const GTypeInfo g_define_type_info = { sizeof (PixbufWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pixbuf_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PixbufWriter), 0, (GInstanceInitFunc) pixbuf_writer_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 pixbuf_writer_type_id; +		pixbuf_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PixbufWriter", &g_define_type_info, &g_define_type_fundamental_info, 0); +		g_once_init_leave (&pixbuf_writer_type_id__volatile, pixbuf_writer_type_id); +	} +	return pixbuf_writer_type_id__volatile; +} + -    if (!page->priv->has_crop) -        return; -    page->priv->has_crop = FALSE; -    g_signal_emit (page, signals[CROP_CHANGED], 0); +gpointer pixbuf_writer_ref (gpointer instance) { +	PixbufWriter* self; +	self = instance; +	g_atomic_int_inc (&self->ref_count); +	return instance;  } -void -page_set_custom_crop (Page *page, gint width, gint height) -{ -    //gint pw, ph; +void pixbuf_writer_unref (gpointer instance) { +	PixbufWriter* self; +	self = instance; +	if (g_atomic_int_dec_and_test (&self->ref_count)) { +		PIXBUF_WRITER_GET_CLASS (self)->finalize (self); +		g_type_free_instance ((GTypeInstance *) self); +	} +} + -    g_return_if_fail (page != NULL); -    g_return_if_fail (width >= 1); -    g_return_if_fail (height >= 1); -     -    if (!page->priv->crop_name && -        page->priv->has_crop && -        page->priv->crop_width == width && -        page->priv->crop_height == height) -        return; -    g_free (page->priv->crop_name); -    page->priv->crop_name = NULL; -    page->priv->has_crop = TRUE; +static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { +	if ((array != NULL) && (destroy_func != NULL)) { +		int i; +		for (i = 0; i < array_length; i = i + 1) { +			if (((gpointer*) array)[i] != NULL) { +				destroy_func (((gpointer*) array)[i]); +			} +		} +	} +} -    page->priv->crop_width = width; -    page->priv->crop_height = height; -    /*pw = page_get_width (page); -    ph = page_get_height (page); -    if (page->priv->crop_width < pw) -        page->priv->crop_x = (pw - page->priv->crop_width) / 2; -    else -        page->priv->crop_x = 0; -    if (page->priv->crop_height < ph) -        page->priv->crop_y = (ph - page->priv->crop_height) / 2; -    else -        page->priv->crop_y = 0;*/ -     -    g_signal_emit (page, signals[CROP_CHANGED], 0); -} - - -void -page_set_named_crop (Page *page, const gchar *name) -{ -    struct { -        const gchar *name; -        /* Width and height in inches */ -        gdouble width, height; -    } named_crops[] = -    { -        {"A4", 8.3, 11.7}, -        {"A5", 5.8, 8.3}, -        {"A6", 4.1, 5.8}, -        {"letter", 8.5, 11}, -        {"legal", 8.5, 14}, -        {"4x6", 4, 6}, -        {NULL, 0, 0} -    }; -    gint i; -    gint pw, ph; -    double width, height; - -    g_return_if_fail (page != NULL); -     -    for (i = 0; named_crops[i].name && strcmp (name, named_crops[i].name) != 0; i++); -    width = named_crops[i].width; -    height = named_crops[i].height; - -    if (!named_crops[i].name) { -        g_warning ("Unknown paper size '%s'", name); -        return; -    } - -    g_free (page->priv->crop_name); -    page->priv->crop_name = g_strdup (name); -    page->priv->has_crop = TRUE; -     -    pw = page_get_width (page); -    ph = page_get_height (page); -    -    /* Rotate to match original aspect */ -    if (pw > ph) { -        double t; -        t = width; -        width = height; -        height = t; -    } - -    /* Custom crop, make slightly smaller than original */ -    page->priv->crop_width = (int) (width * page->priv->dpi + 0.5); -    page->priv->crop_height = (int) (height * page->priv->dpi + 0.5); -         -    if (page->priv->crop_width < pw) -        page->priv->crop_x = (pw - page->priv->crop_width) / 2; -    else -        page->priv->crop_x = 0; -    if (page->priv->crop_height < ph) -        page->priv->crop_y = (ph - page->priv->crop_height) / 2; -    else -        page->priv->crop_y = 0; -    g_signal_emit (page, signals[CROP_CHANGED], 0); -} - - -void -page_move_crop (Page *page, gint x, gint y) -{ -    g_return_if_fail (x >= 0); -    g_return_if_fail (y >= 0); -    g_return_if_fail (x < page_get_width (page)); -    g_return_if_fail (y < page_get_height (page)); - -    page->priv->crop_x = x; -    page->priv->crop_y = y; -    g_signal_emit (page, signals[CROP_CHANGED], 0);     -} - - -void -page_rotate_crop (Page *page) -{ -    gint t; -     -    g_return_if_fail (page != NULL); -   -    if (!page->priv->has_crop) -        return; - -    t = page->priv->crop_width; -    page->priv->crop_width = page->priv->crop_height; -    page->priv->crop_height = t; -   -    /* Clip custom crops */ -    if (!page->priv->crop_name) { -        gint w, h; - -        w = page_get_width (page); -        h = page_get_height (page); -         -        if (page->priv->crop_x + page->priv->crop_width > w) -            page->priv->crop_x = w - page->priv->crop_width; -        if (page->priv->crop_x < 0) { -            page->priv->crop_x = 0; -            page->priv->crop_width = w; -        } -        if (page->priv->crop_y + page->priv->crop_height > h) -            page->priv->crop_y = h - page->priv->crop_height; -        if (page->priv->crop_y < 0) { -            page->priv->crop_y = 0; -            page->priv->crop_height = h; -        } -    } - -    g_signal_emit (page, signals[CROP_CHANGED], 0); -} - - -gboolean -page_has_crop (Page *page) -{ -    g_return_val_if_fail (page != NULL, FALSE); -    return page->priv->has_crop; -} - - -void -page_get_crop (Page *page, gint *x, gint *y, gint *width, gint *height) -{ -    g_return_if_fail (page != NULL); - -    if (x) -        *x = page->priv->crop_x; -    if (y) -        *y = page->priv->crop_y; -    if (width) -        *width = page->priv->crop_width; -    if (height) -        *height = page->priv->crop_height; -} - - -gchar * -page_get_named_crop (Page *page) -{ -    g_return_val_if_fail (page != NULL, NULL); - -    if (page->priv->crop_name) -        return g_strdup (page->priv->crop_name); -    else -        return NULL; -} - - -const guchar * -page_get_pixels (Page *page) -{ -    g_return_val_if_fail (page != NULL, NULL); -    return page->priv->pixels; -} - - -// FIXME: Copied from page-view, should be shared code -static guchar -get_sample (const guchar *line, gint x, gint depth, gint n_channels, gint channel) -{ -    // FIXME -    return 0xFF; -} - - -// FIXME: Copied from page-view, should be shared code -static void -get_pixel (Page *page, gint x, gint y, guchar *pixel) -{ -    gint t, depth, n_channels; -    const guchar *p, *line; - -    switch (page_get_scan_direction (page)) -    { -    case TOP_TO_BOTTOM: -        break; -    case BOTTOM_TO_TOP: -        x = page_get_scan_width (page) - x - 1; -        y = page_get_scan_height (page) - y - 1; -        break; -    case LEFT_TO_RIGHT: -        t = x; -        x = page_get_scan_width (page) - y - 1; -        y = t; -        break; -    case RIGHT_TO_LEFT: -        t = x; -        x = y; -        y = page_get_scan_height (page) - t - 1; -        break; -    } - -    depth = page_get_depth (page); -    n_channels = page_get_n_channels (page); -    line = page_get_pixels (page) + page_get_rowstride (page) * y; - -    /* Optimise for 8 bit images */ -    if (depth == 8 && n_channels == 3) { -        p = line + x * n_channels; -        pixel[0] = p[0]; -        pixel[1] = p[1]; -        pixel[2] = p[2]; -        return; -    } -    else if (depth == 8 && n_channels == 1) { -        p = line + x; -        pixel[0] = pixel[1] = pixel[2] = p[0]; -        return; -    } - -    /* Optimise for bitmaps */ -    else if (depth == 1 && n_channels == 1) { -        p = line + (x / 8); -        pixel[0] = pixel[1] = pixel[2] = p[0] & (0x80 >> (x % 8)) ? 0x00 : 0xFF; -        return; -    } - -    /* Optimise for 2 bit images */ -    else if (depth == 2 && n_channels == 1) { -        gint sample; -        gint block_shift[4] = { 6, 4, 2, 0 }; - -        p = line + (x / 4); -        sample = (p[0] >> block_shift[x % 4]) & 0x3; -        sample = sample * 255 / 3; - -        pixel[0] = pixel[1] = pixel[2] = sample; -        return; -    } - -    /* Use slow method */ -    pixel[0] = get_sample (line, x, depth, n_channels, 0); -    pixel[0] = get_sample (line, x, depth, n_channels, 1); -    pixel[0] = get_sample (line, x, depth, n_channels, 2); -} - - -GdkPixbuf * -page_get_image (Page *page, gboolean apply_crop) -{ -    GdkPixbuf *image; -    gint x, y, l, r, t, b; - -    if (apply_crop && page->priv->has_crop) { -        l = page->priv->crop_x; -        r = l + page->priv->crop_width; -        t = page->priv->crop_y; -        b = t + page->priv->crop_height; -       -        if (l < 0) -            l = 0; -        if (r > page_get_width (page)) -            r = page_get_width (page); -        if (t < 0) -            t = 0; -        if (b > page_get_height (page)) -            b = page_get_height (page); -    } -    else { -        l = 0; -        r = page_get_width (page); -        t = 0; -        b = page_get_height (page); -    } - -    image = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, r - l, b - t); - -    for (y = t; y < b; y++) { -        guchar *line = gdk_pixbuf_get_pixels (image) + gdk_pixbuf_get_rowstride (image) * (y - t); -        for (x = l; x < r; x++) { -            guchar *pixel; - -            pixel = line + (x - l) * 3; -            get_pixel (page, x, y, pixel); -        } -    } - -    return image; -} - - -static gboolean -write_pixbuf_data (const gchar *buf, gsize count, GError **error, GFileOutputStream *stream) -{ -    return g_output_stream_write_all (G_OUTPUT_STREAM (stream), buf, count, NULL, NULL, error); -} - - -static gchar * -get_icc_data_encoded (const gchar *icc_profile_filename) -{ -    gchar *contents = NULL; -    gchar *contents_encode = NULL; -    gsize length; -    gboolean ret; -    GError *error = NULL; - -    /* Get binary data */ -    ret = g_file_get_contents (icc_profile_filename, &contents, &length, &error); -    if (!ret) { -        g_warning ("failed to get icc profile data: %s", error->message); -        g_error_free (error); -    } -    else { -        /* Encode into base64 */ -        contents_encode = g_base64_encode ((const guchar *) contents, length); -    } -   -    g_free (contents); -    return contents_encode; -} - - -gboolean -page_save (Page *page, const gchar *type, GFile *file, GError **error) -{ -    GFileOutputStream *stream; -    GdkPixbuf *image; -    gboolean result = FALSE; -    gchar *icc_profile_data = NULL; - -    stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error); -    if (!stream) -        return FALSE; - -    image = page_get_image (page, TRUE); - -    if (page->priv->color_profile != NULL) -        icc_profile_data = get_icc_data_encoded (page->priv->color_profile); - -    if (strcmp (type, "jpeg") == 0) { -        /* ICC profile is awaiting review in gtk2+ bugzilla */ -        gchar *keys[] = { "quality", /* "icc-profile", */ NULL }; -        gchar *values[] = { "90", /* icc_profile_data, */ NULL }; -        result = gdk_pixbuf_save_to_callbackv (image, -                                               (GdkPixbufSaveFunc) write_pixbuf_data, stream, -                                               "jpeg", keys, values, error); -    } -    else if (strcmp (type, "png") == 0) { -        gchar *keys[] = { "icc-profile", NULL }; -        gchar *values[] = { icc_profile_data, NULL }; -        if (icc_profile_data == NULL) -            keys[0] = NULL; -        result = gdk_pixbuf_save_to_callbackv (image, -                                               (GdkPixbufSaveFunc) write_pixbuf_data, stream, -                                               "png", keys, values, error); -    } -    else if (strcmp (type, "tiff") == 0) { -        gchar *keys[] = { "compression", "icc-profile", NULL }; -        gchar *values[] = { "8" /* Deflate compression */, icc_profile_data, NULL }; -        if (icc_profile_data == NULL) -            keys[1] = NULL; -        result = gdk_pixbuf_save_to_callbackv (image, -                                               (GdkPixbufSaveFunc) write_pixbuf_data, stream, -                                               "tiff", keys, values, error); -    } -    else -        result = FALSE; // FIXME: Set GError - -    g_free (icc_profile_data); -    g_object_unref (image); -    g_object_unref (stream); - -    return result; -} - - -static void -page_finalize (GObject *object) -{ -    Page *page = PAGE (object); -    g_free (page->priv->pixels); -    G_OBJECT_CLASS (page_parent_class)->finalize (object); -} - - -static void -page_class_init (PageClass *klass) -{ -    GObjectClass *object_class = G_OBJECT_CLASS (klass); - -    object_class->finalize = page_finalize; - -    signals[PIXELS_CHANGED] = -        g_signal_new ("pixels-changed", -                      G_TYPE_FROM_CLASS (klass), -                      G_SIGNAL_RUN_LAST, -                      G_STRUCT_OFFSET (PageClass, pixels_changed), -                      NULL, NULL, -                      g_cclosure_marshal_VOID__VOID, -                      G_TYPE_NONE, 0); -    signals[SIZE_CHANGED] = -        g_signal_new ("size-changed", -                      G_TYPE_FROM_CLASS (klass), -                      G_SIGNAL_RUN_LAST, -                      G_STRUCT_OFFSET (PageClass, size_changed), -                      NULL, NULL, -                      g_cclosure_marshal_VOID__VOID, -                      G_TYPE_NONE, 0); -    signals[SCAN_LINE_CHANGED] = -        g_signal_new ("scan-line-changed", -                      G_TYPE_FROM_CLASS (klass), -                      G_SIGNAL_RUN_LAST, -                      G_STRUCT_OFFSET (PageClass, scan_line_changed), -                      NULL, NULL, -                      g_cclosure_marshal_VOID__VOID, -                      G_TYPE_NONE, 0); -    signals[SCAN_DIRECTION_CHANGED] = -        g_signal_new ("scan-direction-changed", -                      G_TYPE_FROM_CLASS (klass), -                      G_SIGNAL_RUN_LAST, -                      G_STRUCT_OFFSET (PageClass, scan_direction_changed), -                      NULL, NULL, -                      g_cclosure_marshal_VOID__VOID, -                      G_TYPE_NONE, 0); -    signals[CROP_CHANGED] = -        g_signal_new ("crop-changed", -                      G_TYPE_FROM_CLASS (klass), -                      G_SIGNAL_RUN_LAST, -                      G_STRUCT_OFFSET (PageClass, crop_changed), -                      NULL, NULL, -                      g_cclosure_marshal_VOID__VOID, -                      G_TYPE_NONE, 0); - -    g_type_class_add_private (klass, sizeof (PagePrivate)); -} - - -static void -page_init (Page *page) -{ -    page->priv = G_TYPE_INSTANCE_GET_PRIVATE (page, PAGE_TYPE, PagePrivate); -    page->priv->scan_direction = TOP_TO_BOTTOM; +static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { +	_vala_array_destroy (array, array_length, destroy_func); +	g_free (array);  } + + + | 
