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); } + + + |