summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlessio Treglia <alessio@debian.org>2011-08-27 10:54:22 +0200
committerAlessio Treglia <alessio@debian.org>2011-08-27 10:54:22 +0200
commit575d802c4f1a81ebce3b7b71be6dd3a51fddf7bd (patch)
treef67206af06039627d241d77bc83009505189b7eb /src
parent77a9b5bea4c6dc6977e51b002d92d268e57208f3 (diff)
parent87ebc2af1f0417b3bc38a233e28ff673eff4fa51 (diff)
Merge commit 'upstream/3.1.5'
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am40
-rw-r--r--src/Makefile.in103
-rw-r--r--src/book-view.c2090
-rw-r--r--src/book-view.h59
-rw-r--r--src/book-view.vala594
-rw-r--r--src/book.c2925
-rw-r--r--src/book.h69
-rw-r--r--src/book.vala571
-rw-r--r--src/colord.vapi17
-rw-r--r--src/config.vapi10
-rw-r--r--src/jpeglib.vapi57
-rw-r--r--src/page-view.c3036
-rw-r--r--src/page-view.h79
-rw-r--r--src/page-view.vala1043
-rw-r--r--src/page.c2559
-rw-r--r--src/page.h126
-rw-r--r--src/page.vala735
-rw-r--r--src/sane.vapi757
-rw-r--r--src/scanner.c7763
-rw-r--r--src/scanner.h132
-rw-r--r--src/scanner.vala1472
-rw-r--r--src/simple-scan.c2006
-rw-r--r--src/simple-scan.vala516
-rw-r--r--src/simple_scan_vala.stamp0
-rw-r--r--src/ui.c5281
-rw-r--r--src/ui.h70
-rw-r--r--src/ui.vala1458
27 files changed, 25582 insertions, 7986 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8a4f587..3fa8558 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,22 +1,31 @@
bin_PROGRAMS = simple-scan
simple_scan_SOURCES = \
- book.c \
- book.h \
- book-view.c \
- book-view.h \
- page.c \
- page.h \
- page-view.c \
- page-view.h \
- simple-scan.c \
- scanner.c \
- scanner.h \
- ui.c \
- ui.h
+ config.vapi \
+ book.vala \
+ book-view.vala \
+ colord.vapi \
+ jpeglib.vapi \
+ page.vala \
+ page-view.vala \
+ sane.vapi \
+ simple-scan.vala \
+ scanner.vala \
+ ui.vala
+
+simple_scan_VALAFLAGS = \
+ --pkg=zlib \
+ --pkg=gudev-1.0 \
+ --pkg=gio-2.0 \
+ --pkg=gtk+-3.0
+
+if HAVE_COLORD
+simple_scan_VALAFLAGS += -D HAVE_COLORD
+endif
simple_scan_CFLAGS = \
$(SIMPLE_SCAN_CFLAGS) \
+ $(COLORD_CFLAGS) \
$(WARN_CFLAGS) \
-DVERSION=\"$(VERSION)\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
@@ -28,9 +37,14 @@ simple_scan_CFLAGS = \
simple_scan_LDADD = \
$(SIMPLE_SCAN_LIBS) \
+ $(COLORD_LIBS) \
-lsane \
-ljpeg \
-lm
+CLEANFILES = \
+ $(patsubst %.vala,%.c,$(filter %.vala, $(SOURCES))) \
+ *_vala.stamp
+
DISTCLEANFILES = \
Makefile.in
diff --git a/src/Makefile.in b/src/Makefile.in
index 946fc6c..33521bc 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -33,13 +33,17 @@ NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
bin_PROGRAMS = simple-scan$(EXEEXT)
+@HAVE_COLORD_TRUE@am__append_1 = -D HAVE_COLORD
subdir = src
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in book-view.c \
+ book.c page-view.c page.c scanner.c simple-scan.c \
+ simple_scan_vala.stamp ui.c
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
@@ -51,10 +55,10 @@ am_simple_scan_OBJECTS = simple_scan-book.$(OBJEXT) \
simple_scan-scanner.$(OBJEXT) simple_scan-ui.$(OBJEXT)
simple_scan_OBJECTS = $(am_simple_scan_OBJECTS)
am__DEPENDENCIES_1 =
-simple_scan_DEPENDENCIES = $(am__DEPENDENCIES_1)
+simple_scan_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
simple_scan_LINK = $(CCLD) $(simple_scan_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
-DEFAULT_INCLUDES = -I.@am__isrc@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
@@ -74,6 +78,10 @@ LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_$(V))
am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
am__v_CCLD_0 = @echo " CCLD " $@;
+VALACOMPILE = $(VALAC) $(AM_VALAFLAGS) $(VALAFLAGS)
+AM_V_VALAC = $(am__v_VALAC_$(V))
+am__v_VALAC_ = $(am__v_VALAC_$(AM_DEFAULT_VERBOSITY))
+am__v_VALAC_0 = @echo " VALAC " $@;
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
@@ -93,6 +101,8 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+COLORD_CFLAGS = @COLORD_CFLAGS@
+COLORD_LIBS = @COLORD_LIBS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -107,11 +117,11 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_COMPILE_SCHEMAS = @GLIB_COMPILE_SCHEMAS@
GMSGFMT = @GMSGFMT@
GREP = @GREP@
+GSETTINGS_DISABLE_SCHEMAS_COMPILE = @GSETTINGS_DISABLE_SCHEMAS_COMPILE@
HELP_DIR = @HELP_DIR@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -151,6 +161,7 @@ SIMPLE_SCAN_CFLAGS = @SIMPLE_SCAN_CFLAGS@
SIMPLE_SCAN_LIBS = @SIMPLE_SCAN_LIBS@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
+VALAC = @VALAC@
VERSION = @VERSION@
WARN_CFLAGS = @WARN_CFLAGS@
XGETTEXT = @XGETTEXT@
@@ -172,6 +183,7 @@ datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
+gsettingsschemadir = @gsettingsschemadir@
host_alias = @host_alias@
htmldir = @htmldir@
includedir = @includedir@
@@ -197,22 +209,23 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
simple_scan_SOURCES = \
- book.c \
- book.h \
- book-view.c \
- book-view.h \
- page.c \
- page.h \
- page-view.c \
- page-view.h \
- simple-scan.c \
- scanner.c \
- scanner.h \
- ui.c \
- ui.h
-
+ config.vapi \
+ book.vala \
+ book-view.vala \
+ colord.vapi \
+ jpeglib.vapi \
+ page.vala \
+ page-view.vala \
+ sane.vapi \
+ simple-scan.vala \
+ scanner.vala \
+ ui.vala
+
+simple_scan_VALAFLAGS = --pkg=zlib --pkg=gudev-1.0 --pkg=gio-2.0 \
+ --pkg=gtk+-3.0 $(am__append_1)
simple_scan_CFLAGS = \
$(SIMPLE_SCAN_CFLAGS) \
+ $(COLORD_CFLAGS) \
$(WARN_CFLAGS) \
-DVERSION=\"$(VERSION)\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
@@ -224,10 +237,15 @@ simple_scan_CFLAGS = \
simple_scan_LDADD = \
$(SIMPLE_SCAN_LIBS) \
+ $(COLORD_LIBS) \
-lsane \
-ljpeg \
-lm
+CLEANFILES = \
+ $(patsubst %.vala,%.c,$(filter %.vala, $(SOURCES))) \
+ *_vala.stamp
+
DISTCLEANFILES = \
Makefile.in
@@ -447,6 +465,44 @@ simple_scan-ui.obj: ui.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ui.c' object='simple_scan-ui.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(simple_scan_CFLAGS) $(CFLAGS) -c -o simple_scan-ui.obj `if test -f 'ui.c'; then $(CYGPATH_W) 'ui.c'; else $(CYGPATH_W) '$(srcdir)/ui.c'; fi`
+$(srcdir)/book.c: $(srcdir)/simple_scan_vala.stamp
+ @if test -f $@; then :; else \
+ rm -f $(srcdir)/simple_scan_vala.stamp; \
+ $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \
+ fi
+$(srcdir)/book-view.c: $(srcdir)/simple_scan_vala.stamp
+ @if test -f $@; then :; else \
+ rm -f $(srcdir)/simple_scan_vala.stamp; \
+ $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \
+ fi
+$(srcdir)/page.c: $(srcdir)/simple_scan_vala.stamp
+ @if test -f $@; then :; else \
+ rm -f $(srcdir)/simple_scan_vala.stamp; \
+ $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \
+ fi
+$(srcdir)/page-view.c: $(srcdir)/simple_scan_vala.stamp
+ @if test -f $@; then :; else \
+ rm -f $(srcdir)/simple_scan_vala.stamp; \
+ $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \
+ fi
+$(srcdir)/simple-scan.c: $(srcdir)/simple_scan_vala.stamp
+ @if test -f $@; then :; else \
+ rm -f $(srcdir)/simple_scan_vala.stamp; \
+ $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \
+ fi
+$(srcdir)/scanner.c: $(srcdir)/simple_scan_vala.stamp
+ @if test -f $@; then :; else \
+ rm -f $(srcdir)/simple_scan_vala.stamp; \
+ $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \
+ fi
+$(srcdir)/ui.c: $(srcdir)/simple_scan_vala.stamp
+ @if test -f $@; then :; else \
+ rm -f $(srcdir)/simple_scan_vala.stamp; \
+ $(am__cd) $(srcdir) && $(MAKE) $(AM_MAKEFLAGS) simple_scan_vala.stamp; \
+ fi
+simple_scan_vala.stamp: $(simple_scan_SOURCES)
+ $(AM_V_VALAC)$(VALAC) $(simple_scan_VALAFLAGS) $(VALAFLAGS) -C $(simple_scan_SOURCES)
+ $(AM_V_at)touch $@
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -554,6 +610,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -563,6 +620,14 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+ -rm -f book-view.c
+ -rm -f book.c
+ -rm -f page-view.c
+ -rm -f page.c
+ -rm -f scanner.c
+ -rm -f simple-scan.c
+ -rm -f simple_scan_vala.stamp
+ -rm -f ui.c
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
diff --git a/src/book-view.c b/src/book-view.c
index ac6e32c..5d2e84d 100644
--- a/src/book-view.c
+++ b/src/book-view.c
@@ -1,806 +1,1554 @@
+/* book-view.c generated by valac 0.13.1, the Vala compiler
+ * generated from book-view.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
* version. See http://www.gnu.org/copyleft/gpl.html the full text of the
* license.
*/
+/* FIXME: When scrolling, copy existing render sideways?*/
+/* FIXME: Only render pages that change and only the part that changed*/
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <cairo.h>
+#include <float.h>
+#include <math.h>
+
+
+#define TYPE_BOOK_VIEW (book_view_get_type ())
+#define BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK_VIEW, BookView))
+#define BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK_VIEW, BookViewClass))
+#define IS_BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK_VIEW))
+#define IS_BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK_VIEW))
+#define BOOK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK_VIEW, BookViewClass))
+
+typedef struct _BookView BookView;
+typedef struct _BookViewClass BookViewClass;
+typedef struct _BookViewPrivate BookViewPrivate;
+
+#define TYPE_BOOK (book_get_type ())
+#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book))
+#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass))
+#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK))
+#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK))
+#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass))
+
+typedef struct _Book Book;
+typedef struct _BookClass BookClass;
+
+#define TYPE_PAGE (page_get_type ())
+#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page))
+#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass))
+#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE))
+#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE))
+#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass))
+
+typedef struct _Page Page;
+typedef struct _PageClass PageClass;
+
+#define TYPE_PAGE_VIEW (page_view_get_type ())
+#define PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE_VIEW, PageView))
+#define PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE_VIEW, PageViewClass))
+#define IS_PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE_VIEW))
+#define IS_PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE_VIEW))
+#define PAGE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE_VIEW, PageViewClass))
+
+typedef struct _PageView PageView;
+typedef struct _PageViewClass PageViewClass;
+#define _book_unref0(var) ((var == NULL) ? NULL : (var = (book_unref (var), NULL)))
+#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
+#define _page_view_unref0(var) ((var == NULL) ? NULL : (var = (page_view_unref (var), NULL)))
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL)))
+
+struct _BookView {
+ GtkVBox parent_instance;
+ BookViewPrivate * priv;
+};
-#include <gdk/gdkkeysyms.h>
+struct _BookViewClass {
+ GtkVBoxClass parent_class;
+};
-#include "book-view.h"
-#include "page-view.h"
+struct _BookViewPrivate {
+ Book* book;
+ GHashTable* page_data;
+ gboolean need_layout;
+ gboolean laying_out;
+ gboolean show_selected_page;
+ PageView* selected_page;
+ GtkWidget* drawing_area;
+ GtkHScrollbar* scroll;
+ GtkAdjustment* adjustment;
+ GdkCursorType cursor;
+};
-// FIXME: When scrolling, copy existing render sideways?
-// FIXME: Only render pages that change and only the part that changed
-enum {
- PROP_0,
- PROP_BOOK
+static gpointer book_view_parent_class = NULL;
+
+GType book_view_get_type (void) G_GNUC_CONST;
+gpointer book_ref (gpointer instance);
+void book_unref (gpointer instance);
+GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_book (GValue* value, gpointer v_object);
+void value_take_book (GValue* value, gpointer v_object);
+gpointer value_get_book (const GValue* value);
+GType book_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;
+gpointer page_view_ref (gpointer instance);
+void page_view_unref (gpointer instance);
+GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_page_view (GValue* value, gpointer v_object);
+void value_take_page_view (GValue* value, gpointer v_object);
+gpointer value_get_page_view (const GValue* value);
+GType page_view_get_type (void) G_GNUC_CONST;
+#define BOOK_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_BOOK_VIEW, BookViewPrivate))
+enum {
+ BOOK_VIEW_DUMMY_PROPERTY
};
+BookView* book_view_new (Book* book);
+BookView* book_view_construct (GType object_type, Book* book);
+guint book_get_n_pages (Book* self);
+Page* book_get_page (Book* self, gint page_number);
+static void book_view_add_cb (BookView* self, Book* book, Page* page);
+void book_view_select_page (BookView* self, Page* page);
+static void _book_view_add_cb_book_page_added (Book* _sender, Page* page, gpointer self);
+static void book_view_remove_cb (BookView* self, Book* book, Page* page);
+static void _book_view_remove_cb_book_page_removed (Book* _sender, Page* page, gpointer self);
+static void book_view_reorder_cb (BookView* self, Book* book);
+static void _book_view_reorder_cb_book_reordered (Book* _sender, gpointer self);
+static void book_view_clear_cb (BookView* self, Book* book);
+static void _book_view_clear_cb_book_cleared (Book* _sender, gpointer self);
+static void _page_unref0_ (gpointer var);
+static void _page_view_unref0_ (gpointer var);
+static gboolean book_view_configure_cb (BookView* self, GtkWidget* widget, GdkEventConfigure* event);
+static gboolean _book_view_configure_cb_gtk_widget_configure_event (GtkWidget* _sender, GdkEventConfigure* event, gpointer self);
+static gboolean book_view_draw_cb (BookView* self, GtkWidget* widget, cairo_t* context);
+static gboolean _book_view_draw_cb_gtk_widget_draw (GtkWidget* _sender, cairo_t* cr, gpointer self);
+static gboolean book_view_motion_cb (BookView* self, GtkWidget* widget, GdkEventMotion* event);
+static gboolean _book_view_motion_cb_gtk_widget_motion_notify_event (GtkWidget* _sender, GdkEventMotion* event, gpointer self);
+static gboolean book_view_key_cb (BookView* self, GtkWidget* widget, GdkEventKey* event);
+static gboolean _book_view_key_cb_gtk_widget_key_press_event (GtkWidget* _sender, GdkEventKey* event, gpointer self);
+static gboolean book_view_button_cb (BookView* self, GtkWidget* widget, GdkEventButton* event);
+static gboolean _book_view_button_cb_gtk_widget_button_press_event (GtkWidget* _sender, GdkEventButton* event, gpointer self);
+static gboolean _book_view_button_cb_gtk_widget_button_release_event (GtkWidget* _sender, GdkEventButton* event, gpointer self);
+static gboolean book_view_focus_cb (BookView* self, GtkWidget* widget, GdkEventFocus* event);
+static gboolean _book_view_focus_cb_gtk_widget_focus_in_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self);
+static gboolean _book_view_focus_cb_gtk_widget_focus_out_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self);
+static void book_view_scroll_cb (BookView* self, GtkAdjustment* adjustment);
+static void _book_view_scroll_cb_gtk_adjustment_value_changed (GtkAdjustment* _sender, gpointer self);
+static PageView* book_view_get_nth_page (BookView* self, gint n);
+static PageView* book_view_get_next_page (BookView* self, PageView* page);
+Page* page_view_get_page (PageView* self);
+static PageView* book_view_get_prev_page (BookView* self, PageView* page);
+static void book_view_page_view_changed_cb (BookView* self, PageView* page);
+void book_view_redraw (BookView* self);
+static void book_view_page_view_size_changed_cb (BookView* self, PageView* page);
+PageView* page_view_new (Page* page);
+PageView* page_view_construct (GType object_type, Page* page);
+static void _book_view_page_view_changed_cb_page_view_changed (PageView* _sender, gpointer self);
+static void _book_view_page_view_size_changed_cb_page_view_size_changed (PageView* _sender, gpointer self);
+static void book_view_set_selected_page (BookView* self, PageView* page);
+void page_view_set_selected (PageView* self, gboolean selected);
+static void book_view_set_x_offset (BookView* self, gint offset);
+static gint book_view_get_x_offset (BookView* self);
+static void book_view_show_page_view (BookView* self, PageView* page);
+gint page_view_get_x_offset (PageView* self);
+gint page_view_get_width (PageView* self);
+static void book_view_select_page_view (BookView* self, PageView* page);
+Page* book_view_get_selected (BookView* self);
+Book* book_view_get_book (BookView* self);
+static void book_view_layout_into (BookView* self, gint width, gint height, gint* book_width, gint* book_height);
+gint page_get_dpi (Page* self);
+gint page_get_width (Page* self);
+gint page_get_height (Page* self);
+void page_view_set_width (PageView* self, gint width);
+void page_view_set_height (PageView* self, gint height);
+gint page_view_get_height (PageView* self);
+void page_view_set_x_offset (PageView* self, gint offset);
+void page_view_set_y_offset (PageView* self, gint offset);
+static void book_view_layout (BookView* self);
+void page_view_render (PageView* self, cairo_t* context);
+gboolean page_view_get_selected (PageView* self);
+gint page_view_get_y_offset (PageView* self);
+static PageView* book_view_get_page_at (BookView* self, gint x, gint y, gint* x_, gint* y_);
+void page_view_button_press (PageView* self, gint x, gint y);
+void page_view_button_release (PageView* self, gint x, gint y);
+static void book_view_set_cursor (BookView* self, GdkCursorType cursor);
+void page_view_motion (PageView* self, gint x, gint y);
+GdkCursorType page_view_get_cursor (PageView* self);
+void book_view_select_next_page (BookView* self);
+void book_view_select_prev_page (BookView* self);
+static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+static void book_view_finalize (GObject* obj);
+
+
+static gpointer _book_ref0 (gpointer self) {
+ return self ? book_ref (self) : NULL;
+}
+
+
+static void _book_view_add_cb_book_page_added (Book* _sender, Page* page, gpointer self) {
+ book_view_add_cb (self, _sender, page);
+}
+
+
+static void _book_view_remove_cb_book_page_removed (Book* _sender, Page* page, gpointer self) {
+ book_view_remove_cb (self, _sender, page);
+}
+
+
+static void _book_view_reorder_cb_book_reordered (Book* _sender, gpointer self) {
+ book_view_reorder_cb (self, _sender);
+}
+
+
+static void _book_view_clear_cb_book_cleared (Book* _sender, gpointer self) {
+ book_view_clear_cb (self, _sender);
+}
+
+
+static void _page_unref0_ (gpointer var) {
+ (var == NULL) ? NULL : (var = (page_unref (var), NULL));
+}
+
+
+static void _page_view_unref0_ (gpointer var) {
+ (var == NULL) ? NULL : (var = (page_view_unref (var), NULL));
+}
+
+
+static gpointer _g_object_ref0 (gpointer self) {
+ return self ? g_object_ref (self) : NULL;
+}
+
+
+static gboolean _book_view_configure_cb_gtk_widget_configure_event (GtkWidget* _sender, GdkEventConfigure* event, gpointer self) {
+ gboolean result;
+ result = book_view_configure_cb (self, _sender, event);
+ return result;
+}
-enum {
- PAGE_SELECTED,
- SHOW_PAGE,
- SHOW_MENU,
- LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0, };
-
-struct BookViewPrivate
-{
- /* Book being rendered */
- Book *book;
- GHashTable *page_data;
-
- /* True if the view needs to be laid out again */
- gboolean need_layout, laying_out, show_selected_page;
-
- /* Currently selected page */
- PageView *selected_page;
-
- /* Widget being rendered to */
- GtkWidget *drawing_area;
-
- /* Horizontal scrollbar */
- GtkWidget *scroll;
- GtkAdjustment *adjustment;
-
- gint cursor;
-};
-G_DEFINE_TYPE (BookView, book_view, GTK_TYPE_VBOX);
+static gboolean _book_view_draw_cb_gtk_widget_draw (GtkWidget* _sender, cairo_t* cr, gpointer self) {
+ gboolean result;
+ result = book_view_draw_cb (self, _sender, cr);
+ return result;
+}
-BookView *
-book_view_new (Book *book)
-{
- return g_object_new (BOOK_VIEW_TYPE, "book", book, NULL);
+static gboolean _book_view_motion_cb_gtk_widget_motion_notify_event (GtkWidget* _sender, GdkEventMotion* event, gpointer self) {
+ gboolean result;
+ result = book_view_motion_cb (self, _sender, event);
+ return result;
}
-static PageView *
-get_nth_page (BookView *view, gint n)
-{
- Page *page = book_get_page (view->priv->book, n);
- return g_hash_table_lookup (view->priv->page_data, page);
+static gboolean _book_view_key_cb_gtk_widget_key_press_event (GtkWidget* _sender, GdkEventKey* event, gpointer self) {
+ gboolean result;
+ result = book_view_key_cb (self, _sender, event);
+ return result;
}
-static PageView *
-get_next_page (BookView *view, PageView *page)
-{
- gint i;
-
- for (i = 0; ; i++) {
- Page *p;
- p = book_get_page (view->priv->book, i);
- if (!p)
- break;
- if (p == page_view_get_page (page)) {
- p = book_get_page (view->priv->book, i + 1);
- if (p)
- return g_hash_table_lookup (view->priv->page_data, p);
- }
- }
-
- return page;
+static gboolean _book_view_button_cb_gtk_widget_button_press_event (GtkWidget* _sender, GdkEventButton* event, gpointer self) {
+ gboolean result;
+ result = book_view_button_cb (self, _sender, event);
+ return result;
}
-static PageView *
-get_prev_page (BookView *view, PageView *page)
-{
- gint i;
- PageView *prev_page = page;
+static gboolean _book_view_button_cb_gtk_widget_button_release_event (GtkWidget* _sender, GdkEventButton* event, gpointer self) {
+ gboolean result;
+ result = book_view_button_cb (self, _sender, event);
+ return result;
+}
- for (i = 0; ; i++) {
- Page *p;
- p = book_get_page (view->priv->book, i);
- if (!p)
- break;
- if (p == page_view_get_page (page))
- return prev_page;
- prev_page = g_hash_table_lookup (view->priv->page_data, p);
- }
- return page;
+static gboolean _book_view_focus_cb_gtk_widget_focus_in_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self) {
+ gboolean result;
+ result = book_view_focus_cb (self, _sender, event);
+ return result;
}
-static void
-page_view_changed_cb (PageView *page, BookView *view)
-{
- book_view_redraw (view);
+static gboolean _book_view_focus_cb_gtk_widget_focus_out_event (GtkWidget* _sender, GdkEventFocus* event, gpointer self) {
+ gboolean result;
+ result = book_view_focus_cb (self, _sender, event);
+ return result;
}
-static void
-page_view_size_changed_cb (PageView *page, BookView *view)
-{
- view->priv->need_layout = TRUE;
- book_view_redraw (view);
+static void _book_view_scroll_cb_gtk_adjustment_value_changed (GtkAdjustment* _sender, gpointer self) {
+ book_view_scroll_cb (self, _sender);
}
-static void
-add_cb (Book *book, Page *page, BookView *view)
-{
- PageView *page_view;
- page_view = page_view_new (page);
- g_signal_connect (page_view, "changed", G_CALLBACK (page_view_changed_cb), view);
- g_signal_connect (page_view, "size-changed", G_CALLBACK (page_view_size_changed_cb), view);
- g_hash_table_insert (view->priv->page_data, page, page_view);
- view->priv->need_layout = TRUE;
- book_view_redraw (view);
+BookView* book_view_construct (GType object_type, Book* book) {
+ BookView * self = NULL;
+ Book* _tmp0_;
+ Page* _tmp4_ = NULL;
+ Page* _tmp5_;
+ GHashTable* _tmp6_ = NULL;
+ GtkDrawingArea* _tmp7_ = NULL;
+ GtkHScrollbar* _tmp8_ = NULL;
+ GtkAdjustment* _tmp9_ = NULL;
+ GtkAdjustment* _tmp10_;
+ g_return_val_if_fail (book != NULL, NULL);
+ self = (BookView*) g_object_new (object_type, NULL);
+ _tmp0_ = _book_ref0 (book);
+ _book_unref0 (self->priv->book);
+ self->priv->book = _tmp0_;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp1_;
+ _tmp1_ = TRUE;
+ while (TRUE) {
+ guint _tmp2_;
+ Page* _tmp3_ = NULL;
+ Page* page;
+ if (!_tmp1_) {
+ i++;
+ }
+ _tmp1_ = FALSE;
+ _tmp2_ = book_get_n_pages (book);
+ if (!(((guint) i) < _tmp2_)) {
+ break;
+ }
+ _tmp3_ = book_get_page (book, i);
+ page = _tmp3_;
+ book_view_add_cb (self, book, page);
+ _page_unref0 (page);
+ }
+ }
+ }
+ _tmp4_ = book_get_page (book, 0);
+ _tmp5_ = _tmp4_;
+ book_view_select_page (self, _tmp5_);
+ _page_unref0 (_tmp5_);
+ g_signal_connect_object (book, "page-added", (GCallback) _book_view_add_cb_book_page_added, self, 0);
+ g_signal_connect_object (book, "page-removed", (GCallback) _book_view_remove_cb_book_page_removed, self, 0);
+ g_signal_connect_object (book, "reordered", (GCallback) _book_view_reorder_cb_book_reordered, self, 0);
+ g_signal_connect_object (book, "cleared", (GCallback) _book_view_clear_cb_book_cleared, self, 0);
+ self->priv->need_layout = TRUE;
+ _tmp6_ = g_hash_table_new_full (g_direct_hash, g_direct_equal, _page_unref0_, _page_view_unref0_);
+ _g_hash_table_unref0 (self->priv->page_data);
+ self->priv->page_data = _tmp6_;
+ self->priv->cursor = GDK_ARROW;
+ _tmp7_ = (GtkDrawingArea*) gtk_drawing_area_new ();
+ _g_object_unref0 (self->priv->drawing_area);
+ self->priv->drawing_area = (GtkWidget*) g_object_ref_sink (_tmp7_);
+ gtk_widget_set_size_request (self->priv->drawing_area, 200, 100);
+ gtk_widget_set_can_focus (self->priv->drawing_area, TRUE);
+ gtk_widget_set_events (self->priv->drawing_area, (gint) (((((GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK) | GDK_BUTTON_RELEASE_MASK) | GDK_FOCUS_CHANGE_MASK) | GDK_STRUCTURE_MASK) | GDK_SCROLL_MASK));
+ gtk_box_pack_start ((GtkBox*) self, self->priv->drawing_area, TRUE, TRUE, (guint) 0);
+ _tmp8_ = (GtkHScrollbar*) gtk_hscrollbar_new (NULL);
+ _g_object_unref0 (self->priv->scroll);
+ self->priv->scroll = g_object_ref_sink (_tmp8_);
+ _tmp9_ = gtk_range_get_adjustment ((GtkRange*) self->priv->scroll);
+ _tmp10_ = _g_object_ref0 (_tmp9_);
+ _g_object_unref0 (self->priv->adjustment);
+ self->priv->adjustment = _tmp10_;
+ gtk_box_pack_start ((GtkBox*) self, (GtkWidget*) self->priv->scroll, FALSE, TRUE, (guint) 0);
+ g_signal_connect_object (self->priv->drawing_area, "configure-event", (GCallback) _book_view_configure_cb_gtk_widget_configure_event, self, 0);
+ g_signal_connect_object (self->priv->drawing_area, "draw", (GCallback) _book_view_draw_cb_gtk_widget_draw, self, 0);
+ g_signal_connect_object (self->priv->drawing_area, "motion-notify-event", (GCallback) _book_view_motion_cb_gtk_widget_motion_notify_event, self, 0);
+ g_signal_connect_object (self->priv->drawing_area, "key-press-event", (GCallback) _book_view_key_cb_gtk_widget_key_press_event, self, 0);
+ g_signal_connect_object (self->priv->drawing_area, "button-press-event", (GCallback) _book_view_button_cb_gtk_widget_button_press_event, self, 0);
+ g_signal_connect_object (self->priv->drawing_area, "button-release-event", (GCallback) _book_view_button_cb_gtk_widget_button_release_event, self, 0);
+ g_signal_connect_object (self->priv->drawing_area, "focus-in-event", (GCallback) _book_view_focus_cb_gtk_widget_focus_in_event, self, G_CONNECT_AFTER);
+ g_signal_connect_object (self->priv->drawing_area, "focus-out-event", (GCallback) _book_view_focus_cb_gtk_widget_focus_out_event, self, G_CONNECT_AFTER);
+ g_signal_connect_object (self->priv->adjustment, "value-changed", (GCallback) _book_view_scroll_cb_gtk_adjustment_value_changed, self, 0);
+ gtk_widget_show (self->priv->drawing_area);
+ return self;
}
-static void
-set_selected_page (BookView *view, PageView *page)
-{
- /* Deselect existing page if changed */
- if (view->priv->selected_page && page != view->priv->selected_page)
- page_view_set_selected (view->priv->selected_page, FALSE);
+BookView* book_view_new (Book* book) {
+ return book_view_construct (TYPE_BOOK_VIEW, book);
+}
- view->priv->selected_page = page;
- if (!view->priv->selected_page)
- return;
- /* Select new page if widget has focus */
- if (!gtk_widget_has_focus (view->priv->drawing_area))
- page_view_set_selected (view->priv->selected_page, FALSE);
- else
- page_view_set_selected (view->priv->selected_page, TRUE);
+static gpointer _page_view_ref0 (gpointer self) {
+ return self ? page_view_ref (self) : NULL;
}
-static void
-set_x_offset (BookView *view, gint offset)
-{
- gtk_adjustment_set_value (view->priv->adjustment, offset);
+static PageView* book_view_get_nth_page (BookView* self, gint n) {
+ PageView* result = NULL;
+ Page* _tmp0_ = NULL;
+ Page* page;
+ gconstpointer _tmp1_ = NULL;
+ PageView* _tmp2_;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = book_get_page (self->priv->book, n);
+ page = _tmp0_;
+ _tmp1_ = g_hash_table_lookup (self->priv->page_data, page);
+ _tmp2_ = _page_view_ref0 ((PageView*) _tmp1_);
+ result = _tmp2_;
+ _page_unref0 (page);
+ return result;
}
-static gint
-get_x_offset (BookView *view)
-{
- return (gint) gtk_adjustment_get_value (view->priv->adjustment);
+static PageView* book_view_get_next_page (BookView* self, PageView* page) {
+ PageView* result = NULL;
+ PageView* _tmp8_;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (page != NULL, NULL);
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp0_;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ Page* _tmp1_ = NULL;
+ Page* p;
+ Page* _tmp2_ = NULL;
+ Page* _tmp3_;
+ gboolean _tmp4_;
+ if (!_tmp0_) {
+ i++;
+ }
+ _tmp0_ = FALSE;
+ _tmp1_ = book_get_page (self->priv->book, i);
+ p = _tmp1_;
+ if (p == NULL) {
+ _page_unref0 (p);
+ break;
+ }
+ _tmp2_ = page_view_get_page (page);
+ _tmp3_ = _tmp2_;
+ _tmp4_ = p == _tmp3_;
+ _page_unref0 (_tmp3_);
+ if (_tmp4_) {
+ Page* _tmp5_ = NULL;
+ _tmp5_ = book_get_page (self->priv->book, i + 1);
+ _page_unref0 (p);
+ p = _tmp5_;
+ if (p != NULL) {
+ gconstpointer _tmp6_ = NULL;
+ PageView* _tmp7_;
+ _tmp6_ = g_hash_table_lookup (self->priv->page_data, p);
+ _tmp7_ = _page_view_ref0 ((PageView*) _tmp6_);
+ result = _tmp7_;
+ _page_unref0 (p);
+ return result;
+ }
+ }
+ _page_unref0 (p);
+ }
+ }
+ }
+ _tmp8_ = _page_view_ref0 (page);
+ result = _tmp8_;
+ return result;
}
-static void
-show_page (BookView *view, PageView *page)
-{
- gint left_edge, right_edge;
- GtkAllocation allocation;
+static PageView* book_view_get_prev_page (BookView* self, PageView* page) {
+ PageView* result = NULL;
+ PageView* _tmp0_;
+ PageView* prev_page;
+ PageView* _tmp8_;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (page != NULL, NULL);
+ _tmp0_ = _page_view_ref0 (page);
+ prev_page = _tmp0_;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp1_;
+ _tmp1_ = TRUE;
+ while (TRUE) {
+ Page* _tmp2_ = NULL;
+ Page* p;
+ Page* _tmp3_ = NULL;
+ Page* _tmp4_;
+ gboolean _tmp5_;
+ gconstpointer _tmp6_ = NULL;
+ PageView* _tmp7_;
+ if (!_tmp1_) {
+ i++;
+ }
+ _tmp1_ = FALSE;
+ _tmp2_ = book_get_page (self->priv->book, i);
+ p = _tmp2_;
+ if (p == NULL) {
+ _page_unref0 (p);
+ break;
+ }
+ _tmp3_ = page_view_get_page (page);
+ _tmp4_ = _tmp3_;
+ _tmp5_ = p == _tmp4_;
+ _page_unref0 (_tmp4_);
+ if (_tmp5_) {
+ result = prev_page;
+ _page_unref0 (p);
+ return result;
+ }
+ _tmp6_ = g_hash_table_lookup (self->priv->page_data, p);
+ _tmp7_ = _page_view_ref0 ((PageView*) _tmp6_);
+ _page_view_unref0 (prev_page);
+ prev_page = _tmp7_;
+ _page_unref0 (p);
+ }
+ }
+ }
+ _tmp8_ = _page_view_ref0 (page);
+ result = _tmp8_;
+ _page_view_unref0 (prev_page);
+ return result;
+}
+
- if (!page || !gtk_widget_get_visible (view->priv->scroll))
- return;
+static void book_view_page_view_changed_cb (BookView* self, PageView* page) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ book_view_redraw (self);
+}
- gtk_widget_get_allocation(view->priv->drawing_area, &allocation);
- left_edge = page_view_get_x_offset (page);
- right_edge = page_view_get_x_offset (page) + page_view_get_width (page);
- if (left_edge - get_x_offset (view) < 0)
- set_x_offset(view, left_edge);
- else if (right_edge - get_x_offset (view) > allocation.width)
- set_x_offset(view, right_edge - allocation.width);
+static void book_view_page_view_size_changed_cb (BookView* self, PageView* page) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ self->priv->need_layout = TRUE;
+ book_view_redraw (self);
}
-static void
-select_page (BookView *view, PageView *page)
-{
- Page *p = NULL;
-
- if (view->priv->selected_page == page)
- return;
+static void _book_view_page_view_changed_cb_page_view_changed (PageView* _sender, gpointer self) {
+ book_view_page_view_changed_cb (self, _sender);
+}
+
- set_selected_page (view, page);
+static void _book_view_page_view_size_changed_cb_page_view_size_changed (PageView* _sender, gpointer self) {
+ book_view_page_view_size_changed_cb (self, _sender);
+}
- if (view->priv->need_layout)
- view->priv->show_selected_page = TRUE;
- else
- show_page (view, page);
- if (page)
- p = page_view_get_page (page);
- g_signal_emit (view, signals[PAGE_SELECTED], 0, p);
+static gpointer _page_ref0 (gpointer self) {
+ return self ? page_ref (self) : NULL;
}
-static void
-remove_cb (Book *book, Page *page, BookView *view)
-{
- PageView *new_selection = view->priv->selected_page;
+static void book_view_add_cb (BookView* self, Book* book, Page* page) {
+ PageView* _tmp0_ = NULL;
+ PageView* page_view;
+ Page* _tmp1_;
+ PageView* _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (book != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = page_view_new (page);
+ page_view = _tmp0_;
+ g_signal_connect_object (page_view, "changed", (GCallback) _book_view_page_view_changed_cb_page_view_changed, self, 0);
+ g_signal_connect_object (page_view, "size-changed", (GCallback) _book_view_page_view_size_changed_cb_page_view_size_changed, self, 0);
+ _tmp1_ = _page_ref0 (page);
+ _tmp2_ = _page_view_ref0 (page_view);
+ g_hash_table_insert (self->priv->page_data, _tmp1_, _tmp2_);
+ self->priv->need_layout = TRUE;
+ book_view_redraw (self);
+ _page_view_unref0 (page_view);
+}
- /* Select previous page or next if removing the selected page */
- if (page == book_view_get_selected (view)) {
- new_selection = get_prev_page (view, view->priv->selected_page);
- if (new_selection == view->priv->selected_page)
- new_selection = get_next_page (view, view->priv->selected_page);
- view->priv->selected_page = NULL;
- }
- g_hash_table_remove (view->priv->page_data, page);
+static void book_view_set_selected_page (BookView* self, PageView* page) {
+ gboolean _tmp0_ = FALSE;
+ PageView* _tmp1_;
+ gboolean _tmp2_;
+ g_return_if_fail (self != NULL);
+ if (self->priv->selected_page != NULL) {
+ _tmp0_ = page != self->priv->selected_page;
+ } else {
+ _tmp0_ = FALSE;
+ }
+ if (_tmp0_) {
+ page_view_set_selected (self->priv->selected_page, FALSE);
+ }
+ _tmp1_ = _page_view_ref0 (page);
+ _page_view_unref0 (self->priv->selected_page);
+ self->priv->selected_page = _tmp1_;
+ if (self->priv->selected_page == NULL) {
+ return;
+ }
+ g_object_get (self->priv->drawing_area, "has-focus", &_tmp2_, NULL);
+ if (!_tmp2_) {
+ page_view_set_selected (self->priv->selected_page, FALSE);
+ } else {
+ page_view_set_selected (self->priv->selected_page, TRUE);
+ }
+}
- select_page (view, new_selection);
- view->priv->need_layout = TRUE;
- book_view_redraw (view);
+static void book_view_set_x_offset (BookView* self, gint offset) {
+ g_return_if_fail (self != NULL);
+ gtk_adjustment_set_value (self->priv->adjustment, (gdouble) offset);
}
-static void
-reorder_cb (Book *book, BookView *view)
-{
- view->priv->need_layout = TRUE;
- book_view_redraw (view);
+static gint book_view_get_x_offset (BookView* self) {
+ gint result = 0;
+ gdouble _tmp0_;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = gtk_adjustment_get_value (self->priv->adjustment);
+ result = (gint) _tmp0_;
+ return result;
}
-static void
-clear_cb (Book *book, BookView *view)
-{
- g_hash_table_remove_all (view->priv->page_data);
- view->priv->selected_page = NULL;
- g_signal_emit (view, signals[PAGE_SELECTED], 0, NULL);
- view->priv->need_layout = TRUE;
- book_view_redraw (view);
+static void book_view_show_page_view (BookView* self, PageView* page) {
+ gboolean _tmp0_ = FALSE;
+ GtkAllocation allocation = {0};
+ GtkAllocation _tmp2_ = {0};
+ gint _tmp3_;
+ gint left_edge;
+ gint _tmp4_;
+ gint _tmp5_;
+ gint right_edge;
+ gint _tmp6_;
+ g_return_if_fail (self != NULL);
+ if (page == NULL) {
+ _tmp0_ = TRUE;
+ } else {
+ gboolean _tmp1_;
+ _tmp1_ = gtk_widget_get_visible ((GtkWidget*) self->priv->scroll);
+ _tmp0_ = !_tmp1_;
+ }
+ if (_tmp0_) {
+ return;
+ }
+ gtk_widget_get_allocation (self->priv->drawing_area, &_tmp2_);
+ allocation = _tmp2_;
+ _tmp3_ = page_view_get_x_offset (page);
+ left_edge = _tmp3_;
+ _tmp4_ = page_view_get_x_offset (page);
+ _tmp5_ = page_view_get_width (page);
+ right_edge = _tmp4_ + _tmp5_;
+ _tmp6_ = book_view_get_x_offset (self);
+ if ((left_edge - _tmp6_) < 0) {
+ book_view_set_x_offset (self, left_edge);
+ } else {
+ gint _tmp7_;
+ _tmp7_ = book_view_get_x_offset (self);
+ if ((right_edge - _tmp7_) > allocation.width) {
+ book_view_set_x_offset (self, right_edge - allocation.width);
+ }
+ }
}
-Book *
-book_view_get_book (BookView *view)
-{
- g_return_val_if_fail (view != NULL, NULL);
+static void book_view_select_page_view (BookView* self, PageView* page) {
+ Page* p;
+ g_return_if_fail (self != NULL);
+ p = NULL;
+ if (self->priv->selected_page == page) {
+ _page_unref0 (p);
+ return;
+ }
+ book_view_set_selected_page (self, page);
+ if (self->priv->need_layout) {
+ self->priv->show_selected_page = TRUE;
+ } else {
+ book_view_show_page_view (self, page);
+ }
+ if (page != NULL) {
+ Page* _tmp0_ = NULL;
+ _tmp0_ = page_view_get_page (page);
+ _page_unref0 (p);
+ p = _tmp0_;
+ }
+ g_signal_emit_by_name (self, "page-selected", p);
+ _page_unref0 (p);
+}
+
- return view->priv->book;
+static void book_view_remove_cb (BookView* self, Book* book, Page* page) {
+ PageView* _tmp0_;
+ PageView* new_selection;
+ Page* _tmp1_ = NULL;
+ Page* _tmp2_;
+ gboolean _tmp3_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (book != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = _page_view_ref0 (self->priv->selected_page);
+ new_selection = _tmp0_;
+ _tmp1_ = book_view_get_selected (self);
+ _tmp2_ = _tmp1_;
+ _tmp3_ = page == _tmp2_;
+ _page_unref0 (_tmp2_);
+ if (_tmp3_) {
+ PageView* _tmp4_ = NULL;
+ _tmp4_ = book_view_get_prev_page (self, self->priv->selected_page);
+ _page_view_unref0 (new_selection);
+ new_selection = _tmp4_;
+ if (new_selection == self->priv->selected_page) {
+ PageView* _tmp5_ = NULL;
+ _tmp5_ = book_view_get_next_page (self, self->priv->selected_page);
+ _page_view_unref0 (new_selection);
+ new_selection = _tmp5_;
+ }
+ _page_view_unref0 (self->priv->selected_page);
+ self->priv->selected_page = NULL;
+ }
+ g_hash_table_remove (self->priv->page_data, page);
+ book_view_select_page_view (self, new_selection);
+ self->priv->need_layout = TRUE;
+ book_view_redraw (self);
+ _page_view_unref0 (new_selection);
}
-static gboolean
-configure_cb (GtkWidget *widget, GdkEventConfigure *event, BookView *view)
-{
- view->priv->need_layout = TRUE;
- return FALSE;
+static void book_view_reorder_cb (BookView* self, Book* book) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (book != NULL);
+ self->priv->need_layout = TRUE;
+ book_view_redraw (self);
}
-static void
-layout_into (BookView *view, gint width, gint height, gint *book_width, gint *book_height)
-{
- gint spacing = 12;
- gint max_width = 0, max_height = 0;
- gdouble aspect, max_aspect;
- gint x_offset = 0;
- gint i, n_pages;
- gint max_dpi = 0;
+static void book_view_clear_cb (BookView* self, Book* book) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (book != NULL);
+ g_hash_table_remove_all (self->priv->page_data);
+ _page_view_unref0 (self->priv->selected_page);
+ self->priv->selected_page = NULL;
+ g_signal_emit_by_name (self, "page-selected", NULL);
+ self->priv->need_layout = TRUE;
+ book_view_redraw (self);
+}
- n_pages = book_get_n_pages (view->priv->book);
- /* Get maximum page resolution */
- for (i = 0; i < n_pages; i++) {
- Page *page = book_get_page (view->priv->book, i);
- if (page_get_dpi (page) > max_dpi)
- max_dpi = page_get_dpi (page);
- }
+Book* book_view_get_book (BookView* self) {
+ Book* result = NULL;
+ Book* _tmp0_;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = _book_ref0 (self->priv->book);
+ result = _tmp0_;
+ return result;
+}
- /* Get area required to fit all pages */
- for (i = 0; i < n_pages; i++) {
- Page *page = book_get_page (view->priv->book, i);
- gint w, h;
- w = page_get_width (page);
- h = page_get_height (page);
+static gboolean book_view_configure_cb (BookView* self, GtkWidget* widget, GdkEventConfigure* event) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ self->priv->need_layout = TRUE;
+ result = FALSE;
+ return result;
+}
- /* Scale to the same DPI */
- w = (double)w * max_dpi / page_get_dpi (page) + 0.5;
- h = (double)h * max_dpi / page_get_dpi (page) + 0.5;
- if (w > max_width)
- max_width = w;
- if (h > max_height)
- max_height = h;
- }
-
- aspect = (double)width / height;
- max_aspect = (double)max_width / max_height;
-
- /* Get total dimensions of all pages */
- *book_width = 0;
- *book_height = 0;
- for (i = 0; i < n_pages; i++) {
- PageView *page = get_nth_page (view, i);
- Page *p = page_view_get_page (page);
- gint h;
-
- /* NOTE: Using double to avoid overflow for large images */
- if (max_aspect > aspect) {
- /* Set width scaled on DPI and maximum width */
- gint w = (double)page_get_width (p) * max_dpi * width / (page_get_dpi (p) * max_width);
- page_view_set_width (page, w);
- }
- else {
- /* Set height scaled on DPI and maximum height */
- gint h = (double)page_get_height (p) * max_dpi * height / (page_get_dpi (p) * max_height);
- page_view_set_height (page, h);
- }
-
- h = page_view_get_height (page);
- if (h > *book_height)
- *book_height = h;
- *book_width += page_view_get_width (page);
- if (i != 0)
- *book_width += spacing;
- }
-
- for (i = 0; i < n_pages; i++) {
- PageView *page = get_nth_page (view, i);
-
- /* Layout pages left to right */
- page_view_set_x_offset (page, x_offset);
- x_offset += page_view_get_width (page) + spacing;
-
- /* Centre page vertically */
- page_view_set_y_offset (page, (height - page_view_get_height (page)) / 2);
- }
-}
-
-
-static void
-layout (BookView *view)
-{
- gint width, height, book_width, book_height;
- gboolean right_aligned = TRUE;
- GtkAllocation allocation, box_allocation;
-
- if (!view->priv->need_layout)
- return;
-
- view->priv->laying_out = TRUE;
-
- gtk_widget_get_allocation(view->priv->drawing_area, &allocation);
- gtk_widget_get_allocation(GTK_WIDGET(view), &box_allocation);
-
- /* If scroll is right aligned then keep that after layout */
- if (gtk_adjustment_get_value (view->priv->adjustment) < gtk_adjustment_get_upper (view->priv->adjustment) - gtk_adjustment_get_page_size (view->priv->adjustment))
- right_aligned = FALSE;
-
- /* Try and fit without scrollbar */
- width = allocation.width;
- height = box_allocation.height - gtk_container_get_border_width (GTK_CONTAINER (view)) * 2;
- layout_into (view, width, height, &book_width, &book_height);
-
- /* Relayout with scrollbar */
- if (book_width > allocation.width) {
- gint max_offset;
-
- /* Re-layout leaving space for scrollbar */
- height = allocation.height;
- layout_into (view, width, height, &book_width, &book_height);
-
- /* Set scrollbar limits */
- gtk_adjustment_set_lower (view->priv->adjustment, 0);
- gtk_adjustment_set_upper (view->priv->adjustment, book_width);
- gtk_adjustment_set_page_size (view->priv->adjustment, allocation.width);
-
- /* Keep right-aligned */
- max_offset = book_width - allocation.width;
- if (right_aligned || get_x_offset (view) > max_offset)
- set_x_offset(view, max_offset);
-
- gtk_widget_show (view->priv->scroll);
- } else {
- gint offset;
- gtk_widget_hide (view->priv->scroll);
- offset = (book_width - allocation.width) / 2;
- gtk_adjustment_set_lower (view->priv->adjustment, offset);
- gtk_adjustment_set_upper (view->priv->adjustment, offset);
- gtk_adjustment_set_page_size (view->priv->adjustment, 0);
- set_x_offset(view, offset);
- }
-
- if (view->priv->show_selected_page)
- show_page (view, view->priv->selected_page);
-
- view->priv->need_layout = FALSE;
- view->priv->show_selected_page = FALSE;
- view->priv->laying_out = FALSE;
-}
-
-
-static gboolean
-expose_cb (GtkWidget *widget, GdkEventExpose *event, BookView *view)
-{
- gint i, n_pages;
- cairo_t *context;
-
- n_pages = book_get_n_pages (view->priv->book);
- if (n_pages == 0)
- return FALSE;
-
- layout (view);
-
- context = gdk_cairo_create (gtk_widget_get_window(widget));
-
- /* Render each page */
- for (i = 0; i < n_pages; i++) {
- PageView *page = get_nth_page (view, i);
- gint left_edge, right_edge;
-
- left_edge = page_view_get_x_offset (page) - get_x_offset (view);
- right_edge = page_view_get_x_offset (page) + page_view_get_width (page) - get_x_offset (view);
-
- /* Page not visible, don't render */
- if (right_edge < event->area.x || left_edge > event->area.x + event->area.width)
- continue;
-
- cairo_save (context);
- cairo_translate (context, -get_x_offset (view), 0);
- page_view_render (page, context);
- cairo_restore (context);
-
- if (page_view_get_selected (page))
- gtk_paint_focus (gtk_widget_get_style (view->priv->drawing_area),
- gtk_widget_get_window (view->priv->drawing_area),
- GTK_STATE_SELECTED,
- &event->area,
- NULL,
- NULL,
- page_view_get_x_offset (page) - get_x_offset (view),
- page_view_get_y_offset (page),
- page_view_get_width (page),
- page_view_get_height (page));
- }
-
- cairo_destroy (context);
-
- return FALSE;
-}
-
-
-static PageView *
-get_page_at (BookView *view, gint x, gint y, gint *x_, gint *y_)
-{
- gint i, n_pages;
-
- n_pages = book_get_n_pages (view->priv->book);
- for (i = 0; i < n_pages; i++) {
- PageView *page;
- gint left, right, top, bottom;
-
- page = get_nth_page (view, i);
- left = page_view_get_x_offset (page);
- right = left + page_view_get_width (page);
- top = page_view_get_y_offset (page);
- bottom = top + page_view_get_height (page);
- if (x >= left && x <= right && y >= top && y <= bottom)
- {
- *x_ = x - left;
- *y_ = y - top;
- return page;
- }
- }
-
- return NULL;
-}
-
-
-static gboolean
-button_cb (GtkWidget *widget, GdkEventButton *event, BookView *view)
-{
- gint x, y;
-
- layout (view);
-
- gtk_widget_grab_focus (view->priv->drawing_area);
-
- if (event->type == GDK_BUTTON_PRESS)
- select_page (view, get_page_at (view, event->x + get_x_offset (view), event->y, &x, &y));
-
- if (!view->priv->selected_page)
- return FALSE;
+static void book_view_layout_into (BookView* self, gint width, gint height, gint* book_width, gint* book_height) {
+ gint _book_width = 0;
+ gint _book_height = 0;
+ gint max_dpi;
+ gint max_width;
+ gint max_height;
+ gdouble aspect;
+ gdouble max_aspect;
+ gint spacing;
+ gint x_offset;
+ g_return_if_fail (self != NULL);
+ max_dpi = 0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp0_;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ guint _tmp1_;
+ Page* _tmp2_ = NULL;
+ Page* page;
+ gint _tmp3_;
+ if (!_tmp0_) {
+ i++;
+ }
+ _tmp0_ = FALSE;
+ _tmp1_ = book_get_n_pages (self->priv->book);
+ if (!(((guint) i) < _tmp1_)) {
+ break;
+ }
+ _tmp2_ = book_get_page (self->priv->book, i);
+ page = _tmp2_;
+ _tmp3_ = page_get_dpi (page);
+ if (_tmp3_ > max_dpi) {
+ gint _tmp4_;
+ _tmp4_ = page_get_dpi (page);
+ max_dpi = _tmp4_;
+ }
+ _page_unref0 (page);
+ }
+ }
+ }
+ max_width = 0;
+ max_height = 0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp5_;
+ _tmp5_ = TRUE;
+ while (TRUE) {
+ guint _tmp6_;
+ Page* _tmp7_ = NULL;
+ Page* page;
+ gint _tmp8_;
+ gint w;
+ gint _tmp9_;
+ gint h;
+ gint _tmp10_;
+ gint _tmp11_;
+ if (!_tmp5_) {
+ i++;
+ }
+ _tmp5_ = FALSE;
+ _tmp6_ = book_get_n_pages (self->priv->book);
+ if (!(((guint) i) < _tmp6_)) {
+ break;
+ }
+ _tmp7_ = book_get_page (self->priv->book, i);
+ page = _tmp7_;
+ _tmp8_ = page_get_width (page);
+ w = _tmp8_;
+ _tmp9_ = page_get_height (page);
+ h = _tmp9_;
+ _tmp10_ = page_get_dpi (page);
+ w = (gint) (((((gdouble) w) * max_dpi) / _tmp10_) + 0.5);
+ _tmp11_ = page_get_dpi (page);
+ h = (gint) (((((gdouble) h) * max_dpi) / _tmp11_) + 0.5);
+ if (w > max_width) {
+ max_width = w;
+ }
+ if (h > max_height) {
+ max_height = h;
+ }
+ _page_unref0 (page);
+ }
+ }
+ }
+ aspect = ((gdouble) width) / height;
+ max_aspect = ((gdouble) max_width) / max_height;
+ spacing = 12;
+ _book_width = 0;
+ _book_height = 0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp12_;
+ _tmp12_ = TRUE;
+ while (TRUE) {
+ guint _tmp13_;
+ PageView* _tmp14_ = NULL;
+ PageView* page;
+ Page* _tmp15_ = NULL;
+ Page* p;
+ gint _tmp20_;
+ gint h;
+ gint _tmp21_;
+ if (!_tmp12_) {
+ i++;
+ }
+ _tmp12_ = FALSE;
+ _tmp13_ = book_get_n_pages (self->priv->book);
+ if (!(((guint) i) < _tmp13_)) {
+ break;
+ }
+ _tmp14_ = book_view_get_nth_page (self, i);
+ page = _tmp14_;
+ _tmp15_ = page_view_get_page (page);
+ p = _tmp15_;
+ if (max_aspect > aspect) {
+ gint _tmp16_;
+ gint _tmp17_;
+ gint w;
+ _tmp16_ = page_get_width (p);
+ _tmp17_ = page_get_dpi (p);
+ w = (gint) (((((gdouble) _tmp16_) * max_dpi) * width) / (_tmp17_ * max_width));
+ page_view_set_width (page, w);
+ } else {
+ gint _tmp18_;
+ gint _tmp19_;
+ gint h;
+ _tmp18_ = page_get_height (p);
+ _tmp19_ = page_get_dpi (p);
+ h = (gint) (((((gdouble) _tmp18_) * max_dpi) * height) / (_tmp19_ * max_height));
+ page_view_set_height (page, h);
+ }
+ _tmp20_ = page_view_get_height (page);
+ h = _tmp20_;
+ if (h > _book_height) {
+ _book_height = h;
+ }
+ _tmp21_ = page_view_get_width (page);
+ _book_width = _book_width + _tmp21_;
+ if (i != 0) {
+ _book_width = _book_width + spacing;
+ }
+ _page_unref0 (p);
+ _page_view_unref0 (page);
+ }
+ }
+ }
+ x_offset = 0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp22_;
+ _tmp22_ = TRUE;
+ while (TRUE) {
+ guint _tmp23_;
+ PageView* _tmp24_ = NULL;
+ PageView* page;
+ gint _tmp25_;
+ gint _tmp26_;
+ if (!_tmp22_) {
+ i++;
+ }
+ _tmp22_ = FALSE;
+ _tmp23_ = book_get_n_pages (self->priv->book);
+ if (!(((guint) i) < _tmp23_)) {
+ break;
+ }
+ _tmp24_ = book_view_get_nth_page (self, i);
+ page = _tmp24_;
+ page_view_set_x_offset (page, x_offset);
+ _tmp25_ = page_view_get_width (page);
+ x_offset = x_offset + (_tmp25_ + spacing);
+ _tmp26_ = page_view_get_height (page);
+ page_view_set_y_offset (page, (height - _tmp26_) / 2);
+ _page_view_unref0 (page);
+ }
+ }
+ }
+ if (book_width) {
+ *book_width = _book_width;
+ }
+ if (book_height) {
+ *book_height = _book_height;
+ }
+}
- /* Modify page */
- if (event->button == 1) {
- if (event->type == GDK_BUTTON_PRESS)
- page_view_button_press (view->priv->selected_page, x, y);
- else if (event->type == GDK_BUTTON_RELEASE)
- page_view_button_release (view->priv->selected_page, x, y);
- else if (event->type == GDK_2BUTTON_PRESS)
- g_signal_emit (view, signals[SHOW_PAGE], 0, book_view_get_selected (view));
- }
-
- /* Show pop-up menu on right click */
- if (event->button == 3)
- g_signal_emit (view, signals[SHOW_MENU], 0);
- return FALSE;
+static void book_view_layout (BookView* self) {
+ GtkAllocation allocation = {0};
+ GtkAllocation _tmp0_ = {0};
+ GtkAllocation box_allocation = {0};
+ GtkAllocation _tmp1_ = {0};
+ gboolean right_aligned;
+ gdouble _tmp2_;
+ gdouble _tmp3_;
+ gdouble _tmp4_;
+ gint width;
+ guint _tmp5_;
+ gint height;
+ gint book_width = 0;
+ gint book_height = 0;
+ gint _tmp6_;
+ gint _tmp7_;
+ g_return_if_fail (self != NULL);
+ if (!self->priv->need_layout) {
+ return;
+ }
+ self->priv->laying_out = TRUE;
+ gtk_widget_get_allocation (self->priv->drawing_area, &_tmp0_);
+ allocation = _tmp0_;
+ gtk_widget_get_allocation ((GtkWidget*) self, &_tmp1_);
+ box_allocation = _tmp1_;
+ right_aligned = TRUE;
+ _tmp2_ = gtk_adjustment_get_value (self->priv->adjustment);
+ _tmp3_ = gtk_adjustment_get_upper (self->priv->adjustment);
+ _tmp4_ = gtk_adjustment_get_page_size (self->priv->adjustment);
+ if (_tmp2_ < (_tmp3_ - _tmp4_)) {
+ right_aligned = FALSE;
+ }
+ width = (gint) allocation.width;
+ _tmp5_ = gtk_container_get_border_width ((GtkContainer*) self);
+ height = (gint) (box_allocation.height - (_tmp5_ * 2));
+ book_view_layout_into (self, width, height, &_tmp6_, &_tmp7_);
+ book_width = _tmp6_;
+ book_height = _tmp7_;
+ if (book_width > allocation.width) {
+ gint _tmp8_;
+ gint _tmp9_;
+ gint max_offset;
+ gboolean _tmp10_ = FALSE;
+ height = allocation.height;
+ book_view_layout_into (self, width, height, &_tmp8_, &_tmp9_);
+ book_width = _tmp8_;
+ book_height = _tmp9_;
+ gtk_adjustment_set_lower (self->priv->adjustment, (gdouble) 0);
+ gtk_adjustment_set_upper (self->priv->adjustment, (gdouble) book_width);
+ gtk_adjustment_set_page_size (self->priv->adjustment, (gdouble) allocation.width);
+ max_offset = book_width - allocation.width;
+ if (right_aligned) {
+ _tmp10_ = TRUE;
+ } else {
+ gint _tmp11_;
+ _tmp11_ = book_view_get_x_offset (self);
+ _tmp10_ = _tmp11_ > max_offset;
+ }
+ if (_tmp10_) {
+ book_view_set_x_offset (self, max_offset);
+ }
+ gtk_widget_show ((GtkWidget*) self->priv->scroll);
+ } else {
+ gint offset;
+ gtk_widget_hide ((GtkWidget*) self->priv->scroll);
+ offset = (book_width - allocation.width) / 2;
+ gtk_adjustment_set_lower (self->priv->adjustment, (gdouble) offset);
+ gtk_adjustment_set_upper (self->priv->adjustment, (gdouble) offset);
+ gtk_adjustment_set_page_size (self->priv->adjustment, (gdouble) 0);
+ book_view_set_x_offset (self, offset);
+ }
+ if (self->priv->show_selected_page) {
+ book_view_show_page_view (self, self->priv->selected_page);
+ }
+ self->priv->need_layout = FALSE;
+ self->priv->show_selected_page = FALSE;
+ self->priv->laying_out = FALSE;
}
-static void
-set_cursor (BookView *view, gint cursor)
-{
- GdkCursor *c;
-
- if (view->priv->cursor == cursor)
- return;
- view->priv->cursor = cursor;
+static gboolean book_view_draw_cb (BookView* self, GtkWidget* widget, cairo_t* context) {
+ gboolean result = FALSE;
+ guint _tmp0_;
+ gdouble left = 0.0;
+ gdouble top = 0.0;
+ gdouble right = 0.0;
+ gdouble bottom = 0.0;
+ gdouble _tmp1_;
+ gdouble _tmp2_;
+ gdouble _tmp3_;
+ gdouble _tmp4_;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (context != NULL, FALSE);
+ _tmp0_ = book_get_n_pages (self->priv->book);
+ if (_tmp0_ == ((guint) 0)) {
+ result = FALSE;
+ return result;
+ }
+ book_view_layout (self);
+ cairo_clip_extents (context, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_);
+ left = _tmp1_;
+ top = _tmp2_;
+ right = _tmp3_;
+ bottom = _tmp4_;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp5_;
+ _tmp5_ = TRUE;
+ while (TRUE) {
+ guint _tmp6_;
+ PageView* _tmp7_ = NULL;
+ PageView* page;
+ gint _tmp8_;
+ gint _tmp9_;
+ gint left_edge;
+ gint _tmp10_;
+ gint _tmp11_;
+ gint _tmp12_;
+ gint right_edge;
+ gboolean _tmp13_ = FALSE;
+ gint _tmp14_;
+ gboolean _tmp15_;
+ if (!_tmp5_) {
+ i++;
+ }
+ _tmp5_ = FALSE;
+ _tmp6_ = book_get_n_pages (self->priv->book);
+ if (!(((guint) i) < _tmp6_)) {
+ break;
+ }
+ _tmp7_ = book_view_get_nth_page (self, i);
+ page = _tmp7_;
+ _tmp8_ = page_view_get_x_offset (page);
+ _tmp9_ = book_view_get_x_offset (self);
+ left_edge = _tmp8_ - _tmp9_;
+ _tmp10_ = page_view_get_x_offset (page);
+ _tmp11_ = page_view_get_width (page);
+ _tmp12_ = book_view_get_x_offset (self);
+ right_edge = (_tmp10_ + _tmp11_) - _tmp12_;
+ if (((gdouble) right_edge) < left) {
+ _tmp13_ = TRUE;
+ } else {
+ _tmp13_ = ((gdouble) left_edge) > right;
+ }
+ if (_tmp13_) {
+ _page_view_unref0 (page);
+ continue;
+ }
+ cairo_save (context);
+ _tmp14_ = book_view_get_x_offset (self);
+ cairo_translate (context, (gdouble) (-_tmp14_), (gdouble) 0);
+ page_view_render (page, context);
+ cairo_restore (context);
+ _tmp15_ = page_view_get_selected (page);
+ if (_tmp15_) {
+ GtkStyle* _tmp16_ = NULL;
+ gint _tmp17_;
+ gint _tmp18_;
+ gint _tmp19_;
+ gint _tmp20_;
+ gint _tmp21_;
+ _tmp16_ = gtk_widget_get_style (self->priv->drawing_area);
+ _tmp17_ = page_view_get_x_offset (page);
+ _tmp18_ = book_view_get_x_offset (self);
+ _tmp19_ = page_view_get_y_offset (page);
+ _tmp20_ = page_view_get_width (page);
+ _tmp21_ = page_view_get_height (page);
+ gtk_paint_focus (_tmp16_, context, GTK_STATE_SELECTED, NULL, NULL, _tmp17_ - _tmp18_, _tmp19_, _tmp20_, _tmp21_);
+ }
+ _page_view_unref0 (page);
+ }
+ }
+ }
+ result = FALSE;
+ return result;
+}
+
- c = gdk_cursor_new (cursor);
- gdk_window_set_cursor (gtk_widget_get_window (view->priv->drawing_area), c);
- gdk_cursor_destroy (c);
+static PageView* book_view_get_page_at (BookView* self, gint x, gint y, gint* x_, gint* y_) {
+ gint _x_ = 0;
+ gint _y_ = 0;
+ PageView* result = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp0_;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ guint _tmp1_;
+ PageView* _tmp2_ = NULL;
+ PageView* page;
+ gint _tmp3_;
+ gint left;
+ gint _tmp4_;
+ gint right;
+ gint _tmp5_;
+ gint top;
+ gint _tmp6_;
+ gint bottom;
+ gboolean _tmp7_ = FALSE;
+ gboolean _tmp8_ = FALSE;
+ gboolean _tmp9_ = FALSE;
+ if (!_tmp0_) {
+ i++;
+ }
+ _tmp0_ = FALSE;
+ _tmp1_ = book_get_n_pages (self->priv->book);
+ if (!(((guint) i) < _tmp1_)) {
+ break;
+ }
+ _tmp2_ = book_view_get_nth_page (self, i);
+ page = _tmp2_;
+ _tmp3_ = page_view_get_x_offset (page);
+ left = _tmp3_;
+ _tmp4_ = page_view_get_width (page);
+ right = left + _tmp4_;
+ _tmp5_ = page_view_get_y_offset (page);
+ top = _tmp5_;
+ _tmp6_ = page_view_get_height (page);
+ bottom = top + _tmp6_;
+ if (x >= left) {
+ _tmp9_ = x <= right;
+ } else {
+ _tmp9_ = FALSE;
+ }
+ if (_tmp9_) {
+ _tmp8_ = y >= top;
+ } else {
+ _tmp8_ = FALSE;
+ }
+ if (_tmp8_) {
+ _tmp7_ = y <= bottom;
+ } else {
+ _tmp7_ = FALSE;
+ }
+ if (_tmp7_) {
+ _x_ = x - left;
+ _y_ = y - top;
+ result = page;
+ if (x_) {
+ *x_ = _x_;
+ }
+ if (y_) {
+ *y_ = _y_;
+ }
+ return result;
+ }
+ _page_view_unref0 (page);
+ }
+ }
+ }
+ result = NULL;
+ if (x_) {
+ *x_ = _x_;
+ }
+ if (y_) {
+ *y_ = _y_;
+ }
+ return result;
}
-static gboolean
-motion_cb (GtkWidget *widget, GdkEventMotion *event, BookView *view)
-{
- gint x, y;
- gint cursor = GDK_ARROW;
-
- /* Dragging */
- if (view->priv->selected_page && (event->state & GDK_BUTTON1_MASK) != 0) {
- x = event->x + get_x_offset (view) - page_view_get_x_offset (view->priv->selected_page);
- y = event->y - page_view_get_y_offset (view->priv->selected_page);
- page_view_motion (view->priv->selected_page, x, y);
- cursor = page_view_get_cursor (view->priv->selected_page);
- }
- else {
- PageView *over_page;
- over_page = get_page_at (view, event->x + get_x_offset (view), event->y, &x, &y);
- if (over_page) {
- page_view_motion (over_page, x, y);
- cursor = page_view_get_cursor (over_page);
- }
- }
+static gboolean book_view_button_cb (BookView* self, GtkWidget* widget, GdkEventButton* event) {
+ gboolean result = FALSE;
+ gint x;
+ gint y;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ book_view_layout (self);
+ gtk_widget_grab_focus (self->priv->drawing_area);
+ x = 0;
+ y = 0;
+ if ((*event).type == GDK_BUTTON_PRESS) {
+ gint _tmp0_;
+ gint _tmp1_;
+ gint _tmp2_;
+ PageView* _tmp3_ = NULL;
+ PageView* _tmp4_;
+ _tmp0_ = book_view_get_x_offset (self);
+ _tmp3_ = book_view_get_page_at (self, (gint) ((*event).x + _tmp0_), (gint) (*event).y, &_tmp1_, &_tmp2_);
+ x = _tmp1_;
+ y = _tmp2_;
+ _tmp4_ = _tmp3_;
+ book_view_select_page_view (self, _tmp4_);
+ _page_view_unref0 (_tmp4_);
+ }
+ if (self->priv->selected_page == NULL) {
+ result = FALSE;
+ return result;
+ }
+ if ((*event).button == ((guint) 1)) {
+ if ((*event).type == GDK_BUTTON_PRESS) {
+ page_view_button_press (self->priv->selected_page, x, y);
+ } else {
+ if ((*event).type == GDK_BUTTON_RELEASE) {
+ page_view_button_release (self->priv->selected_page, x, y);
+ } else {
+ if ((*event).type == GDK_2BUTTON_PRESS) {
+ Page* _tmp5_ = NULL;
+ Page* _tmp6_;
+ _tmp5_ = book_view_get_selected (self);
+ _tmp6_ = _tmp5_;
+ g_signal_emit_by_name (self, "show-page", _tmp6_);
+ _page_unref0 (_tmp6_);
+ }
+ }
+ }
+ }
+ if ((*event).button == ((guint) 3)) {
+ g_signal_emit_by_name (self, "show-menu");
+ }
+ result = FALSE;
+ return result;
+}
- set_cursor (view, cursor);
- return FALSE;
+static void book_view_set_cursor (BookView* self, GdkCursorType cursor) {
+ GdkCursor* c = NULL;
+ GdkCursor* _tmp0_ = NULL;
+ GdkWindow* _tmp1_ = NULL;
+ g_return_if_fail (self != NULL);
+ if (self->priv->cursor == cursor) {
+ _g_object_unref0 (c);
+ return;
+ }
+ self->priv->cursor = cursor;
+ _tmp0_ = gdk_cursor_new (cursor);
+ _g_object_unref0 (c);
+ c = _tmp0_;
+ _tmp1_ = gtk_widget_get_window (self->priv->drawing_area);
+ gdk_window_set_cursor (_tmp1_, c);
+ _g_object_unref0 (c);
}
-static gboolean
-key_cb (GtkWidget *widget, GdkEventKey *event, BookView *view)
-{
- switch (event->keyval) {
- case GDK_Home:
- book_view_select_page (view, book_get_page (view->priv->book, 0));
- return TRUE;
- case GDK_Left:
- select_page (view, get_prev_page (view, view->priv->selected_page));
- return TRUE;
- case GDK_Right:
- select_page (view, get_next_page (view, view->priv->selected_page));
- return TRUE;
- case GDK_End:
- book_view_select_page (view, book_get_page (view->priv->book, book_get_n_pages (view->priv->book) - 1));
- return TRUE;
+static gboolean book_view_motion_cb (BookView* self, GtkWidget* widget, GdkEventMotion* event) {
+ gboolean result = FALSE;
+ GdkCursorType cursor;
+ gboolean _tmp0_ = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ cursor = GDK_ARROW;
+ if (self->priv->selected_page != NULL) {
+ _tmp0_ = ((*event).state & GDK_BUTTON1_MASK) != 0;
+ } else {
+ _tmp0_ = FALSE;
+ }
+ if (_tmp0_) {
+ gint _tmp1_;
+ gint _tmp2_;
+ gint x;
+ gint _tmp3_;
+ gint y;
+ GdkCursorType _tmp4_;
+ _tmp1_ = book_view_get_x_offset (self);
+ _tmp2_ = page_view_get_x_offset (self->priv->selected_page);
+ x = (gint) (((*event).x + _tmp1_) - _tmp2_);
+ _tmp3_ = page_view_get_y_offset (self->priv->selected_page);
+ y = (gint) ((*event).y - _tmp3_);
+ page_view_motion (self->priv->selected_page, x, y);
+ _tmp4_ = page_view_get_cursor (self->priv->selected_page);
+ cursor = _tmp4_;
+ } else {
+ gint x = 0;
+ gint y = 0;
+ gint _tmp5_;
+ gint _tmp6_;
+ gint _tmp7_;
+ PageView* _tmp8_ = NULL;
+ PageView* over_page;
+ _tmp5_ = book_view_get_x_offset (self);
+ _tmp8_ = book_view_get_page_at (self, (gint) ((*event).x + _tmp5_), (gint) (*event).y, &_tmp6_, &_tmp7_);
+ x = _tmp6_;
+ y = _tmp7_;
+ over_page = _tmp8_;
+ if (over_page != NULL) {
+ GdkCursorType _tmp9_;
+ page_view_motion (over_page, x, y);
+ _tmp9_ = page_view_get_cursor (over_page);
+ cursor = _tmp9_;
+ }
+ _page_view_unref0 (over_page);
+ }
+ book_view_set_cursor (self, cursor);
+ result = FALSE;
+ return result;
+}
+
- default:
- return FALSE;
- }
+static gboolean book_view_key_cb (BookView* self, GtkWidget* widget, GdkEventKey* event) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ switch ((*event).keyval) {
+ case 0xff50:
+ {
+ Page* _tmp0_ = NULL;
+ Page* _tmp1_;
+ _tmp0_ = book_get_page (self->priv->book, 0);
+ _tmp1_ = _tmp0_;
+ book_view_select_page (self, _tmp1_);
+ _page_unref0 (_tmp1_);
+ result = TRUE;
+ return result;
+ }
+ case 0xff51:
+ {
+ PageView* _tmp2_ = NULL;
+ PageView* _tmp3_;
+ _tmp2_ = book_view_get_prev_page (self, self->priv->selected_page);
+ _tmp3_ = _tmp2_;
+ book_view_select_page_view (self, _tmp3_);
+ _page_view_unref0 (_tmp3_);
+ result = TRUE;
+ return result;
+ }
+ case 0xff53:
+ {
+ PageView* _tmp4_ = NULL;
+ PageView* _tmp5_;
+ _tmp4_ = book_view_get_next_page (self, self->priv->selected_page);
+ _tmp5_ = _tmp4_;
+ book_view_select_page_view (self, _tmp5_);
+ _page_view_unref0 (_tmp5_);
+ result = TRUE;
+ return result;
+ }
+ case 0xFF57:
+ {
+ guint _tmp6_;
+ Page* _tmp7_ = NULL;
+ Page* _tmp8_;
+ _tmp6_ = book_get_n_pages (self->priv->book);
+ _tmp7_ = book_get_page (self->priv->book, ((gint) _tmp6_) - 1);
+ _tmp8_ = _tmp7_;
+ book_view_select_page (self, _tmp8_);
+ _page_unref0 (_tmp8_);
+ result = TRUE;
+ return result;
+ }
+ default:
+ {
+ result = FALSE;
+ return result;
+ }
+ }
}
-static gboolean
-focus_cb (GtkWidget *widget, GdkEventFocus *event, BookView *view)
-{
- set_selected_page (view, view->priv->selected_page);
- return FALSE;
+static gboolean book_view_focus_cb (BookView* self, GtkWidget* widget, GdkEventFocus* event) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ book_view_set_selected_page (self, self->priv->selected_page);
+ result = FALSE;
+ return result;
}
-static void
-scroll_cb (GtkAdjustment *adjustment, BookView *view)
-{
- if (!view->priv->laying_out)
- book_view_redraw (view);
+static void book_view_scroll_cb (BookView* self, GtkAdjustment* adjustment) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (adjustment != NULL);
+ if (!self->priv->laying_out) {
+ book_view_redraw (self);
+ }
}
-void
-book_view_redraw (BookView *view)
-{
- g_return_if_fail (view != NULL);
- gtk_widget_queue_draw (view->priv->drawing_area);
+void book_view_redraw (BookView* self) {
+ g_return_if_fail (self != NULL);
+ gtk_widget_queue_draw (self->priv->drawing_area);
}
-void
-book_view_select_page (BookView *view, Page *page)
-{
- g_return_if_fail (view != NULL);
+void book_view_select_page (BookView* self, Page* page) {
+ Page* _tmp0_ = NULL;
+ Page* _tmp1_;
+ gboolean _tmp2_;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = book_view_get_selected (self);
+ _tmp1_ = _tmp0_;
+ _tmp2_ = _tmp1_ == page;
+ _page_unref0 (_tmp1_);
+ if (_tmp2_) {
+ return;
+ }
+ if (page != NULL) {
+ gconstpointer _tmp3_ = NULL;
+ _tmp3_ = g_hash_table_lookup (self->priv->page_data, page);
+ book_view_select_page_view (self, (PageView*) _tmp3_);
+ } else {
+ book_view_select_page_view (self, NULL);
+ }
+}
- if (book_view_get_selected (view) == page)
- return;
- if (page)
- select_page (view, g_hash_table_lookup (view->priv->page_data, page));
- else
- select_page (view, NULL);
+void book_view_select_next_page (BookView* self) {
+ PageView* _tmp0_ = NULL;
+ PageView* _tmp1_;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = book_view_get_next_page (self, self->priv->selected_page);
+ _tmp1_ = _tmp0_;
+ book_view_select_page_view (self, _tmp1_);
+ _page_view_unref0 (_tmp1_);
}
-void
-book_view_select_next_page (BookView *view)
-{
- g_return_if_fail (view != NULL);
- select_page (view, get_next_page (view, view->priv->selected_page));
+void book_view_select_prev_page (BookView* self) {
+ PageView* _tmp0_ = NULL;
+ PageView* _tmp1_;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = book_view_get_prev_page (self, self->priv->selected_page);
+ _tmp1_ = _tmp0_;
+ book_view_select_page_view (self, _tmp1_);
+ _page_view_unref0 (_tmp1_);
}
-void
-book_view_select_prev_page (BookView *view)
-{
- g_return_if_fail (view != NULL);
- select_page (view, get_prev_page (view, view->priv->selected_page));
+Page* book_view_get_selected (BookView* self) {
+ Page* result = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ if (self->priv->selected_page != NULL) {
+ Page* _tmp0_ = NULL;
+ _tmp0_ = page_view_get_page (self->priv->selected_page);
+ result = _tmp0_;
+ return result;
+ } else {
+ result = NULL;
+ return result;
+ }
}
-Page *
-book_view_get_selected (BookView *view)
-{
- g_return_val_if_fail (view != NULL, NULL);
+static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__PAGE) (gpointer data1, gpointer arg_1, gpointer data2);
+ register GMarshalFunc_VOID__PAGE callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 2);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__PAGE) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, value_get_page (param_values + 1), data2);
+}
- if (view->priv->selected_page)
- return page_view_get_page (view->priv->selected_page);
- else
- return NULL;
+
+static void book_view_class_init (BookViewClass * klass) {
+ book_view_parent_class = g_type_class_peek_parent (klass);
+ g_type_class_add_private (klass, sizeof (BookViewPrivate));
+ G_OBJECT_CLASS (klass)->finalize = book_view_finalize;
+ g_signal_new ("page_selected", TYPE_BOOK_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE);
+ g_signal_new ("show_page", TYPE_BOOK_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE);
+ g_signal_new ("show_menu", TYPE_BOOK_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
-static void
-book_view_set_property(GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- BookView *self;
- gint i, n_pages;
-
- self = BOOK_VIEW (object);
-
- switch (prop_id) {
- case PROP_BOOK:
- self->priv->book = g_object_ref (g_value_get_object (value));
+static void book_view_instance_init (BookView * self) {
+ self->priv = BOOK_VIEW_GET_PRIVATE (self);
+ self->priv->selected_page = NULL;
+}
+
- /* Load existing pages */
- n_pages = book_get_n_pages (self->priv->book);
- for (i = 0; i < n_pages; i++) {
- Page *page = book_get_page (self->priv->book, i);
- add_cb (self->priv->book, page, self);
- }
+static void book_view_finalize (GObject* obj) {
+ BookView * self;
+ self = BOOK_VIEW (obj);
+ _book_unref0 (self->priv->book);
+ _g_hash_table_unref0 (self->priv->page_data);
+ _page_view_unref0 (self->priv->selected_page);
+ _g_object_unref0 (self->priv->drawing_area);
+ _g_object_unref0 (self->priv->scroll);
+ _g_object_unref0 (self->priv->adjustment);
+ G_OBJECT_CLASS (book_view_parent_class)->finalize (obj);
+}
- book_view_select_page (self, book_get_page (self->priv->book, 0));
- /* Watch for new pages */
- g_signal_connect (self->priv->book, "page-added", G_CALLBACK (add_cb), self);
- g_signal_connect (self->priv->book, "page-removed", G_CALLBACK (remove_cb), self);
- g_signal_connect (self->priv->book, "reordered", G_CALLBACK (reorder_cb), self);
- g_signal_connect (self->priv->book, "cleared", G_CALLBACK (clear_cb), self);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static void
-book_view_get_property(GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- BookView *self;
-
- self = BOOK_VIEW (object);
-
- switch (prop_id) {
- case PROP_BOOK:
- g_value_set_object (value, self->priv->book);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static void
-book_view_finalize (GObject *object)
-{
- BookView *view = BOOK_VIEW (object);
- g_object_unref (view->priv->book);
- view->priv->book = NULL;
- g_hash_table_unref (view->priv->page_data);
- view->priv->page_data = NULL;
- G_OBJECT_CLASS (book_view_parent_class)->finalize (object);
-}
-
-
-static void
-book_view_class_init (BookViewClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = book_view_finalize;
- object_class->set_property = book_view_set_property;
- object_class->get_property = book_view_get_property;
-
- signals[PAGE_SELECTED] =
- g_signal_new ("page-selected",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (BookViewClass, page_selected),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, page_get_type ());
- signals[SHOW_PAGE] =
- g_signal_new ("show-page",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (BookViewClass, show_page),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, page_get_type ());
- signals[SHOW_MENU] =
- g_signal_new ("show-menu",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (BookViewClass, show_page),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_object_class_install_property(object_class,
- PROP_BOOK,
- g_param_spec_object("book",
- "book",
- "Book being shown",
- book_get_type(),
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_type_class_add_private (klass, sizeof (BookViewPrivate));
-}
-
-
-static void
-book_view_init (BookView *view)
-{
- view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, BOOK_VIEW_TYPE, BookViewPrivate);
- view->priv->need_layout = TRUE;
- view->priv->page_data = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) g_object_unref);
- view->priv->cursor = GDK_ARROW;
-
- view->priv->drawing_area = gtk_drawing_area_new ();
- gtk_widget_set_size_request (view->priv->drawing_area, 200, 100);
- gtk_widget_set_can_focus (view->priv->drawing_area, TRUE);
- gtk_widget_set_events (view->priv->drawing_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK);
- gtk_box_pack_start (GTK_BOX (view), view->priv->drawing_area, TRUE, TRUE, 0);
-
- view->priv->scroll = gtk_hscrollbar_new (NULL);
- view->priv->adjustment = gtk_range_get_adjustment (GTK_RANGE (view->priv->scroll));
- gtk_box_pack_start (GTK_BOX (view), view->priv->scroll, FALSE, TRUE, 0);
-
- g_signal_connect (view->priv->drawing_area, "configure-event", G_CALLBACK (configure_cb), view);
- g_signal_connect (view->priv->drawing_area, "expose-event", G_CALLBACK (expose_cb), view);
- g_signal_connect (view->priv->drawing_area, "motion-notify-event", G_CALLBACK (motion_cb), view);
- g_signal_connect (view->priv->drawing_area, "key-press-event", G_CALLBACK (key_cb), view);
- g_signal_connect (view->priv->drawing_area, "button-press-event", G_CALLBACK (button_cb), view);
- g_signal_connect (view->priv->drawing_area, "button-release-event", G_CALLBACK (button_cb), view);
- g_signal_connect_after (view->priv->drawing_area, "focus-in-event", G_CALLBACK (focus_cb), view);
- g_signal_connect_after (view->priv->drawing_area, "focus-out-event", G_CALLBACK (focus_cb), view);
- g_signal_connect (view->priv->adjustment, "value-changed", G_CALLBACK (scroll_cb), view);
-
- gtk_widget_show (view->priv->drawing_area);
+GType book_view_get_type (void) {
+ static volatile gsize book_view_type_id__volatile = 0;
+ if (g_once_init_enter (&book_view_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (BookViewClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) book_view_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (BookView), 0, (GInstanceInitFunc) book_view_instance_init, NULL };
+ GType book_view_type_id;
+ book_view_type_id = g_type_register_static (GTK_TYPE_VBOX, "BookView", &g_define_type_info, 0);
+ g_once_init_leave (&book_view_type_id__volatile, book_view_type_id);
+ }
+ return book_view_type_id__volatile;
}
+
+
+
diff --git a/src/book-view.h b/src/book-view.h
deleted file mode 100644
index 5b5e2a6..0000000
--- a/src/book-view.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2009 Canonical Ltd.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#ifndef _BOOK_VIEW_H_
-#define _BOOK_VIEW_H_
-
-#include <gtk/gtk.h>
-#include <cairo.h>
-#include "book.h"
-
-G_BEGIN_DECLS
-
-#define BOOK_VIEW_TYPE (book_view_get_type ())
-#define BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BOOK_VIEW_TYPE, BookView))
-
-
-typedef struct BookViewPrivate BookViewPrivate;
-
-typedef struct
-{
- GtkVBox parent_instance;
- BookViewPrivate *priv;
-} BookView;
-
-typedef struct
-{
- GtkVBoxClass parent_class;
-
- void (*page_selected) (BookView *view, Page *page);
- void (*show_page) (BookView *view, Page *page);
- void (*show_menu) (BookView *view, Page *page);
-} BookViewClass;
-
-
-GType book_view_get_type (void);
-
-BookView *book_view_new (Book *book);
-
-void book_view_redraw (BookView *view);
-
-Book *book_view_get_book (BookView *view);
-
-void book_view_select_page (BookView *view, Page *page);
-
-void book_view_select_next_page (BookView *view);
-
-void book_view_select_prev_page (BookView *view);
-
-Page *book_view_get_selected (BookView *view);
-
-#endif /* _BOOK_VIEW_H_ */
diff --git a/src/book-view.vala b/src/book-view.vala
new file mode 100644
index 0000000..9dfd361
--- /dev/null
+++ b/src/book-view.vala
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2009-2011 Canonical Ltd.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+// FIXME: When scrolling, copy existing render sideways?
+// FIXME: Only render pages that change and only the part that changed
+
+public class BookView : Gtk.VBox
+{
+ /* Book being rendered */
+ private Book book;
+ private HashTable<Page, PageView> page_data;
+
+ /* True if the view needs to be laid out again */
+ private bool need_layout;
+ private bool laying_out;
+ private bool show_selected_page;
+
+ /* Currently selected page */
+ private PageView? selected_page = null;
+
+ /* Widget being rendered to */
+ private Gtk.Widget drawing_area;
+
+ /* Horizontal scrollbar */
+ private Gtk.HScrollbar scroll;
+ private Gtk.Adjustment adjustment;
+
+ private Gdk.CursorType cursor;
+
+ public signal void page_selected (Page? page);
+ public signal void show_page (Page page);
+ public signal void show_menu ();
+
+ public BookView (Book book)
+ {
+ this.book = book;
+
+ /* Load existing pages */
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ Page page = book.get_page (i);
+ add_cb (book, page);
+ }
+
+ select_page (book.get_page (0));
+
+ /* Watch for new pages */
+ book.page_added.connect (add_cb);
+ book.page_removed.connect (remove_cb);
+ book.reordered.connect (reorder_cb);
+ book.cleared.connect (clear_cb);
+
+ need_layout = true;
+ page_data = new HashTable<Page, PageView> (direct_hash, direct_equal);
+ cursor = Gdk.CursorType.ARROW;
+
+ drawing_area = new Gtk.DrawingArea ();
+ drawing_area.set_size_request (200, 100);
+ drawing_area.set_can_focus (true);
+ drawing_area.set_events (Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.FOCUS_CHANGE_MASK | Gdk.EventMask.STRUCTURE_MASK | Gdk.EventMask.SCROLL_MASK);
+ pack_start (drawing_area, true, true, 0);
+
+ scroll = new Gtk.HScrollbar (null);
+ adjustment = scroll.get_adjustment ();
+ pack_start (scroll, false, true, 0);
+
+ drawing_area.configure_event.connect (configure_cb);
+ drawing_area.draw.connect (draw_cb);
+ drawing_area.motion_notify_event.connect (motion_cb);
+ drawing_area.key_press_event.connect (key_cb);
+ drawing_area.button_press_event.connect (button_cb);
+ drawing_area.button_release_event.connect (button_cb);
+ drawing_area.focus_in_event.connect_after (focus_cb);
+ drawing_area.focus_out_event.connect_after (focus_cb);
+ adjustment.value_changed.connect (scroll_cb);
+
+ drawing_area.show ();
+ }
+
+ private PageView get_nth_page (int n)
+ {
+ Page page = book.get_page (n);
+ return page_data.lookup (page);
+ }
+
+ private PageView get_next_page (PageView page)
+ {
+ for (var i = 0; ; i++)
+ {
+ var p = book.get_page (i);
+ if (p == null)
+ break;
+ if (p == page.get_page ())
+ {
+ p = book.get_page (i + 1);
+ if (p != null)
+ return page_data.lookup (p);
+ }
+ }
+
+ return page;
+ }
+
+ private PageView get_prev_page (PageView page)
+ {
+ var prev_page = page;
+ for (var i = 0; ; i++)
+ {
+ var p = book.get_page (i);
+ if (p == null)
+ break;
+ if (p == page.get_page ())
+ return prev_page;
+ prev_page = page_data.lookup (p);
+ }
+
+ return page;
+ }
+
+ private void page_view_changed_cb (PageView page)
+ {
+ redraw ();
+ }
+
+ private void page_view_size_changed_cb (PageView page)
+ {
+ need_layout = true;
+ redraw ();
+ }
+
+ private void add_cb (Book book, Page page)
+ {
+ var page_view = new PageView (page);
+ page_view.changed.connect (page_view_changed_cb);
+ page_view.size_changed.connect (page_view_size_changed_cb);
+ page_data.insert (page, page_view);
+ need_layout = true;
+ redraw ();
+ }
+
+ private void set_selected_page (PageView? page)
+ {
+ /* Deselect existing page if changed */
+ if (selected_page != null && page != selected_page)
+ selected_page.set_selected (false);
+
+ selected_page = page;
+ if (selected_page == null)
+ return;
+
+ /* Select new page if widget has focus */
+ if (!drawing_area.has_focus)
+ selected_page.set_selected (false);
+ else
+ selected_page.set_selected (true);
+ }
+
+ private void set_x_offset (int offset)
+ {
+ adjustment.set_value (offset);
+ }
+
+ private int get_x_offset ()
+ {
+ return (int) adjustment.get_value ();
+ }
+
+ private void show_page_view (PageView? page)
+ {
+ if (page == null || !scroll.get_visible ())
+ return;
+
+ Gtk.Allocation allocation;
+ drawing_area.get_allocation (out allocation);
+ var left_edge = page.get_x_offset ();
+ var right_edge = page.get_x_offset () + page.get_width ();
+
+ if (left_edge - get_x_offset () < 0)
+ set_x_offset (left_edge);
+ else if (right_edge - get_x_offset () > allocation.width)
+ set_x_offset (right_edge - allocation.width);
+ }
+
+ private void select_page_view (PageView? page)
+ {
+ Page? p = null;
+
+ if (selected_page == page)
+ return;
+
+ set_selected_page (page);
+
+ if (need_layout)
+ show_selected_page = true;
+ else
+ show_page_view (page);
+
+ if (page != null)
+ p = page.get_page ();
+ page_selected (p);
+ }
+
+ private void remove_cb (Book book, Page page)
+ {
+ PageView new_selection = selected_page;
+
+ /* Select previous page or next if removing the selected page */
+ if (page == get_selected ())
+ {
+ new_selection = get_prev_page (selected_page);
+ if (new_selection == selected_page)
+ new_selection = get_next_page (selected_page);
+ selected_page = null;
+ }
+
+ page_data.remove (page);
+
+ select_page_view (new_selection);
+
+ need_layout = true;
+ redraw ();
+ }
+
+ private void reorder_cb (Book book)
+ {
+ need_layout = true;
+ redraw ();
+ }
+
+ private void clear_cb (Book book)
+ {
+ page_data.remove_all ();
+ selected_page = null;
+ page_selected (null);
+ need_layout = true;
+ redraw ();
+ }
+
+ public Book get_book ()
+ {
+ return book;
+ }
+
+ private bool configure_cb (Gtk.Widget widget, Gdk.EventConfigure event)
+ {
+ need_layout = true;
+ return false;
+ }
+
+ private void layout_into (int width, int height, out int book_width, out int book_height)
+ {
+ /* Get maximum page resolution */
+ int max_dpi = 0;
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ var page = book.get_page (i);
+ if (page.get_dpi () > max_dpi)
+ max_dpi = page.get_dpi ();
+ }
+
+ /* Get area required to fit all pages */
+ int max_width = 0, max_height = 0;
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ var page = book.get_page (i);
+ var w = page.get_width ();
+ var h = page.get_height ();
+
+ /* Scale to the same DPI */
+ w = (int) ((double)w * max_dpi / page.get_dpi () + 0.5);
+ h = (int) ((double)h * max_dpi / page.get_dpi () + 0.5);
+
+ if (w > max_width)
+ max_width = w;
+ if (h > max_height)
+ max_height = h;
+ }
+
+ var aspect = (double)width / height;
+ var max_aspect = (double)max_width / max_height;
+
+ /* Get total dimensions of all pages */
+ int spacing = 12;
+ book_width = 0;
+ book_height = 0;
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ var page = get_nth_page (i);
+ var p = page.get_page ();
+
+ /* NOTE: Using double to avoid overflow for large images */
+ if (max_aspect > aspect)
+ {
+ /* Set width scaled on DPI and maximum width */
+ int w = (int) ((double)p.get_width () * max_dpi * width / (p.get_dpi () * max_width));
+ page.set_width (w);
+ }
+ else
+ {
+ /* Set height scaled on DPI and maximum height */
+ int h = (int) ((double)p.get_height () * max_dpi * height / (p.get_dpi () * max_height));
+ page.set_height (h);
+ }
+
+ var h = page.get_height ();
+ if (h > book_height)
+ book_height = h;
+ book_width += page.get_width ();
+ if (i != 0)
+ book_width += spacing;
+ }
+
+ int x_offset = 0;
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ var page = get_nth_page (i);
+
+ /* Layout pages left to right */
+ page.set_x_offset (x_offset);
+ x_offset += page.get_width () + spacing;
+
+ /* Centre page vertically */
+ page.set_y_offset ((height - page.get_height ()) / 2);
+ }
+ }
+
+ private void layout ()
+ {
+ if (!need_layout)
+ return;
+
+ laying_out = true;
+
+ Gtk.Allocation allocation;
+ drawing_area.get_allocation(out allocation);
+ Gtk.Allocation box_allocation;
+ get_allocation(out box_allocation);
+
+ /* If scroll is right aligned then keep that after layout */
+ bool right_aligned = true;
+ if (adjustment.get_value () < adjustment.get_upper () - adjustment.get_page_size ())
+ right_aligned = false;
+
+ /* Try and fit without scrollbar */
+ var width = (int) allocation.width;
+ var height = (int) (box_allocation.height - get_border_width () * 2);
+ int book_width, book_height;
+ layout_into (width, height, out book_width, out book_height);
+
+ /* Relayout with scrollbar */
+ if (book_width > allocation.width)
+ {
+ /* Re-layout leaving space for scrollbar */
+ height = allocation.height;
+ layout_into (width, height, out book_width, out book_height);
+
+ /* Set scrollbar limits */
+ adjustment.set_lower (0);
+ adjustment.set_upper (book_width);
+ adjustment.set_page_size (allocation.width);
+
+ /* Keep right-aligned */
+ var max_offset = book_width - allocation.width;
+ if (right_aligned || get_x_offset () > max_offset)
+ set_x_offset(max_offset);
+
+ scroll.show ();
+ }
+ else
+ {
+ scroll.hide ();
+ var offset = (book_width - allocation.width) / 2;
+ adjustment.set_lower (offset);
+ adjustment.set_upper (offset);
+ adjustment.set_page_size (0);
+ set_x_offset (offset);
+ }
+
+ if (show_selected_page)
+ show_page_view (selected_page);
+
+ need_layout = false;
+ show_selected_page = false;
+ laying_out = false;
+ }
+
+ private bool draw_cb (Gtk.Widget widget, Cairo.Context context)
+ {
+ if (book.get_n_pages () == 0)
+ return false;
+
+ layout ();
+
+ double left, top, right, bottom;
+ context.clip_extents (out left, out top, out right, out bottom);
+
+ /* Render each page */
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ var page = get_nth_page (i);
+ var left_edge = page.get_x_offset () - get_x_offset ();
+ var right_edge = page.get_x_offset () + page.get_width () - get_x_offset ();
+
+ /* Page not visible, don't render */
+ if (right_edge < left || left_edge > right)
+ continue;
+
+ context.save ();
+ context.translate (-get_x_offset (), 0);
+ page.render (context);
+ context.restore ();
+
+ if (page.get_selected ())
+ Gtk.paint_focus (drawing_area.get_style (),
+ context,
+ Gtk.StateType.SELECTED,
+ null,
+ null,
+ page.get_x_offset () - get_x_offset (),
+ page.get_y_offset (),
+ page.get_width (),
+ page.get_height ());
+ }
+
+ return false;
+ }
+
+ private PageView? get_page_at (int x, int y, out int x_, out int y_)
+ {
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ var page = get_nth_page (i);
+ var left = page.get_x_offset ();
+ var right = left + page.get_width ();
+ var top = page.get_y_offset ();
+ var bottom = top + page.get_height ();
+ if (x >= left && x <= right && y >= top && y <= bottom)
+ {
+ x_ = x - left;
+ y_ = y - top;
+ return page;
+ }
+ }
+
+ return null;
+ }
+
+ private bool button_cb (Gtk.Widget widget, Gdk.EventButton event)
+ {
+ layout ();
+
+ drawing_area.grab_focus ();
+
+ int x = 0, y = 0;
+ if (event.type == Gdk.EventType.BUTTON_PRESS)
+ select_page_view (get_page_at ((int) (event.x + get_x_offset ()), (int) event.y, out x, out y));
+
+ if (selected_page == null)
+ return false;
+
+ /* Modify page */
+ if (event.button == 1)
+ {
+ if (event.type == Gdk.EventType.BUTTON_PRESS)
+ selected_page.button_press (x, y);
+ else if (event.type == Gdk.EventType.BUTTON_RELEASE)
+ selected_page.button_release (x, y);
+ else if (event.type == Gdk.EventType.2BUTTON_PRESS)
+ show_page (get_selected ());
+ }
+
+ /* Show pop-up menu on right click */
+ if (event.button == 3)
+ show_menu ();
+
+ return false;
+ }
+
+ private void set_cursor (Gdk.CursorType cursor)
+ {
+ Gdk.Cursor c;
+
+ if (this.cursor == cursor)
+ return;
+ this.cursor = cursor;
+
+ c = new Gdk.Cursor (cursor);
+ drawing_area.get_window ().set_cursor (c);
+ }
+
+ private bool motion_cb (Gtk.Widget widget, Gdk.EventMotion event)
+ {
+ Gdk.CursorType cursor = Gdk.CursorType.ARROW;
+
+ /* Dragging */
+ if (selected_page != null && (event.state & Gdk.ModifierType.BUTTON1_MASK) != 0)
+ {
+ var x = (int) (event.x + get_x_offset () - selected_page.get_x_offset ());
+ var y = (int) (event.y - selected_page.get_y_offset ());
+ selected_page.motion (x, y);
+ cursor = selected_page.get_cursor ();
+ }
+ else
+ {
+ int x, y;
+ var over_page = get_page_at ((int) (event.x + get_x_offset ()), (int) event.y, out x, out y);
+ if (over_page != null)
+ {
+ over_page.motion (x, y);
+ cursor = over_page.get_cursor ();
+ }
+ }
+
+ set_cursor (cursor);
+
+ return false;
+ }
+
+ private bool key_cb (Gtk.Widget widget, Gdk.EventKey event)
+ {
+ switch (event.keyval)
+ {
+ case 0xff50: /* FIXME: GDK_Home */
+ select_page (book.get_page (0));
+ return true;
+ case 0xff51: /* FIXME: GDK_Left */
+ select_page_view (get_prev_page (selected_page));
+ return true;
+ case 0xff53: /* FIXME: GDK_Right */
+ select_page_view (get_next_page (selected_page));
+ return true;
+ case 0xFF57: /* FIXME: GDK_End */
+ select_page (book.get_page ((int) book.get_n_pages () - 1));
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private bool focus_cb (Gtk.Widget widget, Gdk.EventFocus event)
+ {
+ set_selected_page (selected_page);
+ return false;
+ }
+
+ private void scroll_cb (Gtk.Adjustment adjustment)
+ {
+ if (!laying_out)
+ redraw ();
+ }
+
+ public void redraw ()
+ {
+ drawing_area.queue_draw ();
+ }
+
+ public void select_page (Page? page)
+ {
+ if (get_selected () == page)
+ return;
+
+ if (page != null)
+ select_page_view (page_data.lookup (page));
+ else
+ select_page_view (null);
+ }
+
+ public void select_next_page ()
+ {
+ select_page_view (get_next_page (selected_page));
+ }
+
+ public void select_prev_page ()
+ {
+ select_page_view (get_prev_page (selected_page));
+ }
+
+ public Page? get_selected ()
+ {
+ if (selected_page != null)
+ return selected_page.get_page ();
+ else
+ return null;
+ }
+}
diff --git a/src/book.c b/src/book.c
index de40036..154b6d4 100644
--- a/src/book.c
+++ b/src/book.c
@@ -1,7 +1,10 @@
+/* book.c generated by valac 0.13.1, the Vala compiler
+ * generated from book.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,870 +12,2278 @@
* license.
*/
-#include <stdio.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <stdlib.h>
#include <string.h>
+#include <gio/gio.h>
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixdata.h>
+#include <float.h>
#include <math.h>
+#include <gdk/gdk.h>
+#include <cairo-ps.h>
#include <zlib.h>
#include <jpeglib.h>
-#include <gdk/gdk.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <cairo/cairo-pdf.h>
-#include <cairo/cairo-ps.h>
+#include <config.h>
+#include <gobject/gvaluecollector.h>
+
+
+#define TYPE_BOOK (book_get_type ())
+#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book))
+#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass))
+#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK))
+#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK))
+#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass))
+
+typedef struct _Book Book;
+typedef struct _BookClass BookClass;
+typedef struct _BookPrivate BookPrivate;
+
+#define TYPE_PAGE (page_get_type ())
+#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page))
+#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass))
+#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE))
+#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE))
+#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass))
+
+typedef struct _Page Page;
+typedef struct _PageClass PageClass;
+#define __g_list_free__page_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__page_unref0_ (var), NULL)))
+
+#define TYPE_SCAN_DIRECTION (scan_direction_get_type ())
+#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL)))
+
+#define TYPE_PS_WRITER (ps_writer_get_type ())
+#define PS_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PS_WRITER, PsWriter))
+#define PS_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PS_WRITER, PsWriterClass))
+#define IS_PS_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PS_WRITER))
+#define IS_PS_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PS_WRITER))
+#define PS_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PS_WRITER, PsWriterClass))
+
+typedef struct _PsWriter PsWriter;
+typedef struct _PsWriterClass PsWriterClass;
+typedef struct _PsWriterPrivate PsWriterPrivate;
+#define _cairo_surface_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_surface_destroy (var), NULL)))
+#define _ps_writer_unref0(var) ((var == NULL) ? NULL : (var = (ps_writer_unref (var), NULL)))
+
+#define TYPE_PDF_WRITER (pdf_writer_get_type ())
+#define PDF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PDF_WRITER, PDFWriter))
+#define PDF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PDF_WRITER, PDFWriterClass))
+#define IS_PDF_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PDF_WRITER))
+#define IS_PDF_WRITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PDF_WRITER))
+#define PDF_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PDF_WRITER, PDFWriterClass))
+
+typedef struct _PDFWriter PDFWriter;
+typedef struct _PDFWriterClass PDFWriterClass;
+typedef struct _PDFWriterPrivate PDFWriterPrivate;
+#define _pdf_writer_unref0(var) ((var == NULL) ? NULL : (var = (pdf_writer_unref (var), NULL)))
+typedef struct _ParamSpecBook ParamSpecBook;
+#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL)))
+#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
+typedef struct _ParamSpecPDFWriter ParamSpecPDFWriter;
+typedef struct _ParamSpecPsWriter ParamSpecPsWriter;
+
+struct _Book {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ BookPrivate * priv;
+};
+
+struct _BookClass {
+ GTypeClass parent_class;
+ void (*finalize) (Book *self);
+};
+
+struct _BookPrivate {
+ GList* pages;
+ gboolean needs_saving;
+};
+
+typedef enum {
+ SCAN_DIRECTION_TOP_TO_BOTTOM,
+ SCAN_DIRECTION_LEFT_TO_RIGHT,
+ SCAN_DIRECTION_BOTTOM_TO_TOP,
+ SCAN_DIRECTION_RIGHT_TO_LEFT
+} ScanDirection;
+
+struct _PsWriter {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ PsWriterPrivate * priv;
+ cairo_surface_t* surface;
+ GFileOutputStream* stream;
+};
-#include "book.h"
+struct _PsWriterClass {
+ GTypeClass parent_class;
+ void (*finalize) (PsWriter *self);
+};
-enum {
- PROP_0,
- PROP_NEEDS_SAVING
+struct _PDFWriter {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ PDFWriterPrivate * priv;
+ gsize offset;
+ GList* object_offsets;
};
-enum {
- PAGE_ADDED,
- PAGE_REMOVED,
- REORDERED,
- CLEARED,
- LAST_SIGNAL
+struct _PDFWriterClass {
+ GTypeClass parent_class;
+ void (*finalize) (PDFWriter *self);
};
-static guint signals[LAST_SIGNAL] = { 0, };
-struct BookPrivate
-{
- GList *pages;
-
- gboolean needs_saving;
+struct _ParamSpecBook {
+ GParamSpec parent_instance;
};
-G_DEFINE_TYPE (Book, book, G_TYPE_OBJECT);
+struct _PDFWriterPrivate {
+ GFileOutputStream* stream;
+};
+
+struct _ParamSpecPDFWriter {
+ GParamSpec parent_instance;
+};
+
+struct _ParamSpecPsWriter {
+ GParamSpec parent_instance;
+};
+
+
+static gpointer book_parent_class = NULL;
+static gpointer pdf_writer_parent_class = NULL;
+static gpointer ps_writer_parent_class = NULL;
+
+gpointer book_ref (gpointer instance);
+void book_unref (gpointer instance);
+GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_book (GValue* value, gpointer v_object);
+void value_take_book (GValue* value, gpointer v_object);
+gpointer value_get_book (const GValue* value);
+GType book_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 BOOK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_BOOK, BookPrivate))
+enum {
+ BOOK_DUMMY_PROPERTY
+};
+static void _page_unref0_ (gpointer var);
+static void _g_list_free__page_unref0_ (GList* self);
+Book* book_new (void);
+Book* book_construct (GType object_type);
+void book_clear (Book* self);
+static void book_page_changed_cb (Book* self, Page* page);
+void book_set_needs_saving (Book* self, gboolean needs_saving);
+GType scan_direction_get_type (void) G_GNUC_CONST;
+Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction);
+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);
+static void _book_page_changed_cb_page_pixels_changed (Page* _sender, gpointer self);
+static void _book_page_changed_cb_page_crop_changed (Page* _sender, gpointer self);
+void book_move_page (Book* self, Page* page, guint location);
+void book_delete_page (Book* self, Page* page);
+guint book_get_n_pages (Book* self);
+Page* book_get_page (Book* self, gint page_number);
+guint book_get_page_index (Book* self, Page* page);
+static GFile* book_make_indexed_file (Book* self, const gchar* uri, gint i);
+static void book_save_multi_file (Book* self, const gchar* type, GFile* file, GError** error);
+void page_save (Page* self, const gchar* type, GFile* file, GError** error);
+static void book_save_ps_pdf_surface (Book* self, cairo_surface_t* surface, GdkPixbuf* image, gdouble dpi);
+static void book_save_ps (Book* self, GFile* file, GError** error);
+PsWriter* ps_writer_new (GFileOutputStream* stream);
+PsWriter* ps_writer_construct (GType object_type, GFileOutputStream* stream);
+gpointer ps_writer_ref (gpointer instance);
+void ps_writer_unref (gpointer instance);
+GParamSpec* param_spec_ps_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_ps_writer (GValue* value, gpointer v_object);
+void value_take_ps_writer (GValue* value, gpointer v_object);
+gpointer value_get_ps_writer (const GValue* value);
+GType ps_writer_get_type (void) G_GNUC_CONST;
+GdkPixbuf* page_get_image (Page* self, gboolean apply_crop);
+gint page_get_dpi (Page* self);
+static guint8* book_compress_zlib (Book* self, guint8* data, int data_length1, int* result_length1);
+static void book_jpeg_init_cb (struct jpeg_compress_struct* info);
+static gboolean book_jpeg_empty_cb (struct jpeg_compress_struct* info);
+static void book_jpeg_term_cb (struct jpeg_compress_struct* info);
+static guint8* book_compress_jpeg (Book* self, GdkPixbuf* image, gsize* n_written, int* result_length1);
+static void _book_jpeg_init_cb_jpeg_initdestinationfunc (struct jpeg_compress_struct* cinfo);
+static gboolean _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc (struct jpeg_compress_struct* cinfo);
+static void _book_jpeg_term_cb_jpeg_termdestinationfunc (struct jpeg_compress_struct* cinfo);
+static void book_save_pdf (Book* self, GFile* file, GError** error);
+PDFWriter* pdf_writer_new (GFileOutputStream* stream);
+PDFWriter* pdf_writer_construct (GType object_type, GFileOutputStream* stream);
+gpointer pdf_writer_ref (gpointer instance);
+void pdf_writer_unref (gpointer instance);
+GParamSpec* param_spec_pdf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_pdf_writer (GValue* value, gpointer v_object);
+void value_take_pdf_writer (GValue* value, gpointer v_object);
+gpointer value_get_pdf_writer (const GValue* value);
+GType pdf_writer_get_type (void) G_GNUC_CONST;
+void pdf_writer_write_string (PDFWriter* self, const gchar* text);
+guint pdf_writer_start_object (PDFWriter* self);
+gboolean page_is_color (Page* self);
+gint page_get_depth (Page* self);
+static guint8* _vala_array_dup1 (guint8* self, int length);
+static guint8* _vala_array_dup2 (guint8* self, int length);
+void pdf_writer_write (PDFWriter* self, guint8* data, int data_length1);
+void book_save (Book* self, const gchar* type, GFile* file, GError** error);
+gboolean book_get_needs_saving (Book* self);
+static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+static void book_finalize (Book* obj);
+#define PDF_WRITER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PDF_WRITER, PDFWriterPrivate))
+enum {
+ PDF_WRITER_DUMMY_PROPERTY
+};
+static void pdf_writer_finalize (PDFWriter* obj);
+enum {
+ PS_WRITER_DUMMY_PROPERTY
+};
+static cairo_status_t ps_writer_write_cairo_data (PsWriter* self, guint8* data, int data_length1);
+static cairo_status_t _ps_writer_write_cairo_data_cairo_write_func_t (gpointer self, guchar* data, int data_length1);
+static void ps_writer_finalize (PsWriter* obj);
+
+
+static void _page_unref0_ (gpointer var) {
+ (var == NULL) ? NULL : (var = (page_unref (var), NULL));
+}
+
+
+static void _g_list_free__page_unref0_ (GList* self) {
+ g_list_foreach (self, (GFunc) _page_unref0_, NULL);
+ g_list_free (self);
+}
+
+
+Book* book_construct (GType object_type) {
+ Book* self = NULL;
+ self = (Book*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+Book* book_new (void) {
+ return book_construct (TYPE_BOOK);
+}
+
+
+void book_clear (Book* self) {
+ g_return_if_fail (self != NULL);
+ __g_list_free__page_unref0_0 (self->priv->pages);
+ self->priv->pages = NULL;
+ g_signal_emit_by_name (self, "cleared");
+}
+
+
+static void book_page_changed_cb (Book* self, Page* page) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ book_set_needs_saving (self, TRUE);
+}
+
+
+static void _book_page_changed_cb_page_pixels_changed (Page* _sender, gpointer self) {
+ book_page_changed_cb (self, _sender);
+}
+
+
+static void _book_page_changed_cb_page_crop_changed (Page* _sender, gpointer self) {
+ book_page_changed_cb (self, _sender);
+}
+
+
+static gpointer _page_ref0 (gpointer self) {
+ return self ? page_ref (self) : NULL;
+}
+
+
+Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction) {
+ Page* result = NULL;
+ Page* _tmp0_ = NULL;
+ Page* page;
+ Page* _tmp1_;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = page_new (width, height, dpi, scan_direction);
+ page = _tmp0_;
+ g_signal_connect (page, "pixels-changed", (GCallback) _book_page_changed_cb_page_pixels_changed, self);
+ g_signal_connect (page, "crop-changed", (GCallback) _book_page_changed_cb_page_crop_changed, self);
+ _tmp1_ = _page_ref0 (page);
+ self->priv->pages = g_list_append (self->priv->pages, _tmp1_);
+ g_signal_emit_by_name (self, "page-added", page);
+ book_set_needs_saving (self, TRUE);
+ result = page;
+ return result;
+}
+
+
+void book_move_page (Book* self, Page* page, guint location) {
+ Page* _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ self->priv->pages = g_list_remove (self->priv->pages, page);
+ _tmp0_ = _page_ref0 (page);
+ self->priv->pages = g_list_insert (self->priv->pages, _tmp0_, (gint) location);
+ g_signal_emit_by_name (self, "reordered");
+ book_set_needs_saving (self, TRUE);
+}
+
+
+void book_delete_page (Book* self, Page* page) {
+ guint _tmp0_;
+ guint _tmp1_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ g_signal_parse_name ("pixels-changed", TYPE_PAGE, &_tmp0_, NULL, FALSE);
+ g_signal_handlers_disconnect_matched (page, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp0_, 0, NULL, (GCallback) _book_page_changed_cb_page_pixels_changed, self);
+ g_signal_parse_name ("crop-changed", TYPE_PAGE, &_tmp1_, NULL, FALSE);
+ g_signal_handlers_disconnect_matched (page, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp1_, 0, NULL, (GCallback) _book_page_changed_cb_page_crop_changed, self);
+ g_signal_emit_by_name (self, "page-removed", page);
+ self->priv->pages = g_list_remove (self->priv->pages, page);
+ book_set_needs_saving (self, TRUE);
+}
+
+
+guint book_get_n_pages (Book* self) {
+ guint result = 0U;
+ guint _tmp0_;
+ g_return_val_if_fail (self != NULL, 0U);
+ _tmp0_ = g_list_length (self->priv->pages);
+ result = _tmp0_;
+ return result;
+}
+
+
+Page* book_get_page (Book* self, gint page_number) {
+ Page* result = NULL;
+ gconstpointer _tmp1_ = NULL;
+ Page* _tmp2_;
+ g_return_val_if_fail (self != NULL, NULL);
+ if (page_number < 0) {
+ guint _tmp0_;
+ _tmp0_ = g_list_length (self->priv->pages);
+ page_number = ((gint) _tmp0_) + page_number;
+ }
+ _tmp1_ = g_list_nth_data (self->priv->pages, (guint) page_number);
+ _tmp2_ = _page_ref0 ((Page*) _tmp1_);
+ result = _tmp2_;
+ return result;
+}
+
+
+guint book_get_page_index (Book* self, Page* page) {
+ guint result = 0U;
+ gint _tmp0_;
+ g_return_val_if_fail (self != NULL, 0U);
+ g_return_val_if_fail (page != NULL, 0U);
+ _tmp0_ = g_list_index (self->priv->pages, page);
+ result = (guint) _tmp0_;
+ return result;
+}
+
+
+static gint string_last_index_of_char (const gchar* self, gunichar c, gint start_index) {
+ gint result = 0;
+ gchar* _tmp0_ = NULL;
+ gchar* _result_;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = g_utf8_strrchr (((gchar*) self) + start_index, (gssize) (-1), c);
+ _result_ = _tmp0_;
+ if (_result_ != NULL) {
+ result = (gint) (_result_ - ((gchar*) self));
+ return result;
+ } else {
+ result = -1;
+ return result;
+ }
+}
+
+
+static gchar* string_slice (const gchar* self, glong start, glong end) {
+ gchar* result = NULL;
+ gint _tmp0_;
+ glong string_length;
+ gboolean _tmp1_ = FALSE;
+ gboolean _tmp2_ = FALSE;
+ gchar* _tmp3_ = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = strlen (self);
+ string_length = (glong) _tmp0_;
+ if (start < ((glong) 0)) {
+ start = string_length + start;
+ }
+ if (end < ((glong) 0)) {
+ end = string_length + end;
+ }
+ if (start >= ((glong) 0)) {
+ _tmp1_ = start <= string_length;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ g_return_val_if_fail (_tmp1_, NULL);
+ if (end >= ((glong) 0)) {
+ _tmp2_ = end <= string_length;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ g_return_val_if_fail (_tmp2_, NULL);
+ g_return_val_if_fail (start <= end, NULL);
+ _tmp3_ = g_strndup (((gchar*) self) + start, (gsize) (end - start));
+ result = _tmp3_;
+ return result;
+}
+
+
+static GFile* book_make_indexed_file (Book* self, const gchar* uri, gint i) {
+ GFile* result = NULL;
+ gchar* _tmp1_ = NULL;
+ gchar* basename;
+ gchar* _tmp2_;
+ gchar* prefix;
+ gchar* _tmp3_;
+ gchar* suffix;
+ gint _tmp4_;
+ gint extension_index;
+ gchar* _tmp10_ = NULL;
+ gchar* _tmp11_;
+ GFile* _tmp12_ = NULL;
+ GFile* _tmp13_;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (uri != NULL, NULL);
+ if (i == 0) {
+ GFile* _tmp0_ = NULL;
+ _tmp0_ = g_file_new_for_uri (uri);
+ result = _tmp0_;
+ return result;
+ }
+ _tmp1_ = g_path_get_basename (uri);
+ basename = _tmp1_;
+ _tmp2_ = g_strdup (uri);
+ prefix = _tmp2_;
+ _tmp3_ = g_strdup ("");
+ suffix = _tmp3_;
+ _tmp4_ = string_last_index_of_char (basename, (gunichar) '.', 0);
+ extension_index = _tmp4_;
+ if (extension_index >= 0) {
+ gint _tmp5_;
+ gchar* _tmp6_ = NULL;
+ gint _tmp7_;
+ gint _tmp8_;
+ gchar* _tmp9_ = NULL;
+ _tmp5_ = strlen (basename);
+ _tmp6_ = string_slice (basename, (glong) extension_index, (glong) _tmp5_);
+ _g_free0 (suffix);
+ suffix = _tmp6_;
+ _tmp7_ = strlen (uri);
+ _tmp8_ = strlen (suffix);
+ _tmp9_ = string_slice (uri, (glong) 0, (glong) (_tmp7_ - _tmp8_));
+ _g_free0 (prefix);
+ prefix = _tmp9_;
+ }
+ _tmp10_ = g_strdup_printf ("%s-%d%s", prefix, i, suffix);
+ _tmp11_ = _tmp10_;
+ _tmp12_ = g_file_new_for_uri (_tmp11_);
+ _tmp13_ = _tmp12_;
+ _g_free0 (_tmp11_);
+ result = _tmp13_;
+ _g_free0 (suffix);
+ _g_free0 (prefix);
+ _g_free0 (basename);
+ return result;
+}
+
+
+static void book_save_multi_file (Book* self, const gchar* type, GFile* file, GError** error) {
+ gint i;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (type != NULL);
+ g_return_if_fail (file != NULL);
+ i = 0;
+ {
+ GList* page_collection = NULL;
+ GList* page_it = NULL;
+ page_collection = self->priv->pages;
+ for (page_it = page_collection; page_it != NULL; page_it = page_it->next) {
+ Page* _tmp0_;
+ Page* page = NULL;
+ _tmp0_ = _page_ref0 ((Page*) page_it->data);
+ page = _tmp0_;
+ {
+ gchar* _tmp1_ = NULL;
+ gchar* _tmp2_;
+ GFile* _tmp3_ = NULL;
+ GFile* _tmp4_;
+ _tmp1_ = g_file_get_uri (file);
+ _tmp2_ = _tmp1_;
+ _tmp3_ = book_make_indexed_file (self, _tmp2_, i);
+ _tmp4_ = _tmp3_;
+ page_save (page, type, _tmp4_, &_inner_error_);
+ _g_object_unref0 (_tmp4_);
+ _g_free0 (_tmp2_);
+ if (_inner_error_ != NULL) {
+ g_propagate_error (error, _inner_error_);
+ _page_unref0 (page);
+ return;
+ }
+ i++;
+ _page_unref0 (page);
+ }
+ }
+ }
+}
+
+
+static void book_save_ps_pdf_surface (Book* self, cairo_surface_t* surface, GdkPixbuf* image, gdouble dpi) {
+ cairo_t* _tmp0_ = NULL;
+ cairo_t* context;
+ cairo_pattern_t* _tmp1_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (surface != NULL);
+ g_return_if_fail (image != NULL);
+ _tmp0_ = cairo_create (surface);
+ context = _tmp0_;
+ cairo_scale (context, 72.0 / dpi, 72.0 / dpi);
+ gdk_cairo_set_source_pixbuf (context, image, (gdouble) 0, (gdouble) 0);
+ _tmp1_ = cairo_get_source (context);
+ cairo_pattern_set_filter (_tmp1_, CAIRO_FILTER_BEST);
+ cairo_paint (context);
+ _cairo_destroy0 (context);
+}
+
+
+static gpointer _cairo_surface_reference0 (gpointer self) {
+ return self ? cairo_surface_reference (self) : NULL;
+}
+
+
+static void book_save_ps (Book* self, GFile* file, GError** error) {
+ GFileOutputStream* _tmp0_ = NULL;
+ GFileOutputStream* stream;
+ PsWriter* _tmp1_ = NULL;
+ PsWriter* writer;
+ cairo_surface_t* _tmp2_;
+ cairo_surface_t* surface;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != 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_ = ps_writer_new (stream);
+ writer = _tmp1_;
+ _tmp2_ = _cairo_surface_reference0 (writer->surface);
+ surface = _tmp2_;
+ {
+ GList* page_collection = NULL;
+ GList* page_it = NULL;
+ page_collection = self->priv->pages;
+ for (page_it = page_collection; page_it != NULL; page_it = page_it->next) {
+ Page* _tmp3_;
+ Page* page = NULL;
+ _tmp3_ = _page_ref0 ((Page*) page_it->data);
+ page = _tmp3_;
+ {
+ GdkPixbuf* _tmp4_ = NULL;
+ GdkPixbuf* image;
+ gint _tmp5_;
+ gint _tmp6_;
+ gdouble width;
+ gint _tmp7_;
+ gint _tmp8_;
+ gdouble height;
+ gint _tmp9_;
+ _tmp4_ = page_get_image (page, TRUE);
+ image = _tmp4_;
+ _tmp5_ = gdk_pixbuf_get_width (image);
+ _tmp6_ = page_get_dpi (page);
+ width = (_tmp5_ * 72.0) / _tmp6_;
+ _tmp7_ = gdk_pixbuf_get_height (image);
+ _tmp8_ = page_get_dpi (page);
+ height = (_tmp7_ * 72.0) / _tmp8_;
+ cairo_ps_surface_set_size (surface, width, height);
+ _tmp9_ = page_get_dpi (page);
+ book_save_ps_pdf_surface (self, surface, image, (gdouble) _tmp9_);
+ cairo_surface_show_page (surface);
+ _g_object_unref0 (image);
+ _page_unref0 (page);
+ }
+ }
+ }
+ _cairo_surface_destroy0 (surface);
+ _ps_writer_unref0 (writer);
+ _g_object_unref0 (stream);
+}
+
+
+static guint8* book_compress_zlib (Book* self, guint8* data, int data_length1, int* result_length1) {
+ guint8* result = NULL;
+ z_stream stream = {0};
+ guint8* _tmp0_ = NULL;
+ guint8* out_data;
+ gint out_data_length1;
+ gint _out_data_size_;
+ guint n_written;
+ gint _tmp3_;
+ guint8* _tmp4_;
+ g_return_val_if_fail (self != NULL, NULL);
+ deflateInit (&stream, (gint) Z_BEST_COMPRESSION);
+ _tmp0_ = g_new0 (guint8, data_length1);
+ out_data = _tmp0_;
+ out_data_length1 = data_length1;
+ _out_data_size_ = out_data_length1;
+ stream.next_in = data;
+ stream.avail_in = data_length1;
+ stream.next_out = out_data;
+ stream.avail_out = out_data_length1;
+ while (TRUE) {
+ gint _tmp1_;
+ if (!(stream.avail_in > ((guint) 0))) {
+ break;
+ }
+ _tmp1_ = deflate (&stream, (gint) Z_FINISH);
+ if (_tmp1_ == ((gint) Z_STREAM_ERROR)) {
+ break;
+ }
+ }
+ if (stream.avail_in > ((guint) 0)) {
+ guint8* _tmp2_;
+ _tmp2_ = NULL;
+ if (result_length1) {
+ *result_length1 = 0;
+ }
+ result = _tmp2_;
+ out_data = (g_free (out_data), NULL);
+ deflateEnd (&stream);
+ return result;
+ }
+ n_written = data_length1 - stream.avail_out;
+ _tmp3_ = (gint) n_written;
+ out_data = g_renew (guint8, out_data, (gint) n_written);
+ (_tmp3_ > out_data_length1) ? memset (out_data + out_data_length1, 0, sizeof (guint8) * (_tmp3_ - out_data_length1)) : NULL;
+ out_data_length1 = _tmp3_;
+ _out_data_size_ = _tmp3_;
+ _tmp4_ = out_data;
+ if (result_length1) {
+ *result_length1 = out_data_length1;
+ }
+ result = _tmp4_;
+ deflateEnd (&stream);
+ return result;
+}
+
+
+static void book_jpeg_init_cb (struct jpeg_compress_struct* info) {
+}
+
+
+static gboolean book_jpeg_empty_cb (struct jpeg_compress_struct* info) {
+ gboolean result = FALSE;
+ result = TRUE;
+ return result;
+}
+
+
+static void book_jpeg_term_cb (struct jpeg_compress_struct* info) {
+}
+
+
+static void _book_jpeg_init_cb_jpeg_initdestinationfunc (struct jpeg_compress_struct* cinfo) {
+ book_jpeg_init_cb (cinfo);
+}
+
+
+static gboolean _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc (struct jpeg_compress_struct* cinfo) {
+ gboolean result;
+ result = book_jpeg_empty_cb (cinfo);
+ return result;
+}
+
+
+static void _book_jpeg_term_cb_jpeg_termdestinationfunc (struct jpeg_compress_struct* cinfo) {
+ book_jpeg_term_cb (cinfo);
+}
+
+
+static guint8* book_compress_jpeg (Book* self, GdkPixbuf* image, gsize* n_written, int* result_length1) {
+ gsize _n_written = 0UL;
+ guint8* result = NULL;
+ struct jpeg_compress_struct info = {0};
+ struct jpeg_error_mgr jerr = {0};
+ struct jpeg_destination_mgr dest_mgr = {0};
+ struct jpeg_error_mgr* _tmp0_ = NULL;
+ gint _tmp1_;
+ gint _tmp2_;
+ gint max_length;
+ guint8* _tmp3_ = NULL;
+ guint8* data;
+ gint data_length1;
+ gint _data_size_;
+ guint8* _tmp4_ = NULL;
+ guint8* pixels;
+ gint pixels_length1;
+ gint _pixels_size_;
+ guint8* _tmp7_;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (image != NULL, NULL);
+ memset (&info, 0, sizeof (struct jpeg_compress_struct));
+ memset (&jerr, 0, sizeof (struct jpeg_error_mgr));
+ memset (&dest_mgr, 0, sizeof (struct jpeg_destination_mgr));
+ _tmp0_ = jpeg_std_error (&jerr);
+ info.err = _tmp0_;
+ jpeg_create_compress (&info);
+ _tmp1_ = gdk_pixbuf_get_width (image);
+ info.image_width = _tmp1_;
+ _tmp2_ = gdk_pixbuf_get_height (image);
+ info.image_height = _tmp2_;
+ info.input_components = 3;
+ info.in_color_space = JCS_RGB;
+ jpeg_set_defaults (&info);
+ max_length = (info.image_width * info.image_height) * info.input_components;
+ _tmp3_ = g_new0 (guint8, max_length);
+ data = _tmp3_;
+ data_length1 = max_length;
+ _data_size_ = data_length1;
+ dest_mgr.next_output_byte = data;
+ dest_mgr.free_in_buffer = max_length;
+ dest_mgr.init_destination = _book_jpeg_init_cb_jpeg_initdestinationfunc;
+ dest_mgr.empty_output_buffer = _book_jpeg_empty_cb_jpeg_emptyoutputbufferfunc;
+ dest_mgr.term_destination = _book_jpeg_term_cb_jpeg_termdestinationfunc;
+ info.dest = &dest_mgr;
+ jpeg_start_compress (&info, TRUE);
+ _tmp4_ = gdk_pixbuf_get_pixels (image);
+ pixels = _tmp4_;
+ pixels_length1 = -1;
+ _pixels_size_ = pixels_length1;
+ {
+ gint r;
+ r = 0;
+ {
+ gboolean _tmp5_;
+ _tmp5_ = TRUE;
+ while (TRUE) {
+ guint8* row[1] = {0};
+ gint _tmp6_;
+ if (!_tmp5_) {
+ r++;
+ }
+ _tmp5_ = FALSE;
+ if (!(r < info.image_height)) {
+ break;
+ }
+ _tmp6_ = gdk_pixbuf_get_rowstride (image);
+ row[0] = ((guint8*) pixels) + (r * _tmp6_);
+ jpeg_write_scanlines (&info, row, 1);
+ }
+ }
+ }
+ jpeg_finish_compress (&info);
+ _n_written = (gsize) (max_length - dest_mgr.free_in_buffer);
+ _tmp7_ = data;
+ if (result_length1) {
+ *result_length1 = data_length1;
+ }
+ result = _tmp7_;
+ jpeg_destroy_compress (&info);
+ if (n_written) {
+ *n_written = _n_written;
+ }
+ return result;
+}
+
+
+static guint8* _vala_array_dup1 (guint8* self, int length) {
+ return g_memdup (self, length * sizeof (guint8));
+}
+
+
+static guint8* _vala_array_dup2 (guint8* self, int length) {
+ return g_memdup (self, length * sizeof (guint8));
+}
+
+
+static void book_save_pdf (Book* self, GFile* file, GError** error) {
+ GFileOutputStream* _tmp0_ = NULL;
+ GFileOutputStream* stream;
+ PDFWriter* _tmp1_ = NULL;
+ PDFWriter* writer;
+ guint _tmp2_;
+ guint catalog_number;
+ gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ gchar* _tmp5_ = NULL;
+ gchar* _tmp6_;
+ guint _tmp7_;
+ guint pages_number;
+ gchar* _tmp8_ = NULL;
+ gchar* _tmp9_;
+ guint _tmp14_;
+ gchar* _tmp15_ = NULL;
+ gchar* _tmp16_;
+ guint _tmp100_;
+ guint info_number;
+ gchar* _tmp101_ = NULL;
+ gchar* _tmp102_;
+ gchar* _tmp103_ = NULL;
+ gchar* _tmp104_;
+ gsize xref_offset;
+ guint _tmp105_;
+ gchar* _tmp106_ = NULL;
+ gchar* _tmp107_;
+ guint _tmp110_;
+ gchar* _tmp111_ = NULL;
+ gchar* _tmp112_;
+ gchar* _tmp113_ = NULL;
+ gchar* _tmp114_;
+ gchar* _tmp115_ = NULL;
+ gchar* _tmp116_;
+ gchar* _tmp117_ = NULL;
+ gchar* _tmp118_;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != 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_ = pdf_writer_new (stream);
+ writer = _tmp1_;
+ pdf_writer_write_string (writer, "%%PDF-1.3\n");
+ pdf_writer_write_string (writer, "%%\xe2\xe3\xcf\xd3\n");
+ _tmp2_ = pdf_writer_start_object (writer);
+ catalog_number = _tmp2_;
+ _tmp3_ = g_strdup_printf ("%u 0 obj\n", catalog_number);
+ _tmp4_ = _tmp3_;
+ pdf_writer_write_string (writer, _tmp4_);
+ _g_free0 (_tmp4_);
+ pdf_writer_write_string (writer, "<<\n");
+ pdf_writer_write_string (writer, "/Type /Catalog\n");
+ _tmp5_ = g_strdup_printf ("/Pages %u 0 R\n", catalog_number + 1);
+ _tmp6_ = _tmp5_;
+ pdf_writer_write_string (writer, _tmp6_);
+ _g_free0 (_tmp6_);
+ pdf_writer_write_string (writer, ">>\n");
+ pdf_writer_write_string (writer, "endobj\n");
+ pdf_writer_write_string (writer, "\n");
+ _tmp7_ = pdf_writer_start_object (writer);
+ pages_number = _tmp7_;
+ _tmp8_ = g_strdup_printf ("%u 0 obj\n", pages_number);
+ _tmp9_ = _tmp8_;
+ pdf_writer_write_string (writer, _tmp9_);
+ _g_free0 (_tmp9_);
+ pdf_writer_write_string (writer, "<<\n");
+ pdf_writer_write_string (writer, "/Type /Pages\n");
+ pdf_writer_write_string (writer, "/Kids [");
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp10_;
+ _tmp10_ = TRUE;
+ while (TRUE) {
+ guint _tmp11_;
+ gchar* _tmp12_ = NULL;
+ gchar* _tmp13_;
+ if (!_tmp10_) {
+ i++;
+ }
+ _tmp10_ = FALSE;
+ _tmp11_ = book_get_n_pages (self);
+ if (!(((guint) i) < _tmp11_)) {
+ break;
+ }
+ _tmp12_ = g_strdup_printf (" %u 0 R", (pages_number + 1) + (i * 3));
+ _tmp13_ = _tmp12_;
+ pdf_writer_write_string (writer, _tmp13_);
+ _g_free0 (_tmp13_);
+ }
+ }
+ }
+ pdf_writer_write_string (writer, " ]\n");
+ _tmp14_ = book_get_n_pages (self);
+ _tmp15_ = g_strdup_printf ("/Count %u\n", _tmp14_);
+ _tmp16_ = _tmp15_;
+ pdf_writer_write_string (writer, _tmp16_);
+ _g_free0 (_tmp16_);
+ pdf_writer_write_string (writer, ">>\n");
+ pdf_writer_write_string (writer, "endobj\n");
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp17_;
+ _tmp17_ = TRUE;
+ while (TRUE) {
+ guint _tmp18_;
+ Page* _tmp19_ = NULL;
+ Page* page;
+ GdkPixbuf* _tmp20_ = NULL;
+ GdkPixbuf* image;
+ gint _tmp21_;
+ gint width;
+ gint _tmp22_;
+ gint height;
+ guint8* _tmp23_ = NULL;
+ guint8* pixels;
+ gint pixels_length1;
+ gint _pixels_size_;
+ gint _tmp24_;
+ gdouble page_width;
+ gint _tmp25_;
+ gdouble page_height;
+ gint depth;
+ gchar* _tmp26_;
+ gchar* color_space;
+ gchar* filter;
+ gchar* _tmp27_ = NULL;
+ gchar* width_buffer;
+ gint width_buffer_length1;
+ gint _width_buffer_size_;
+ gchar* _tmp28_ = NULL;
+ gchar* height_buffer;
+ gint height_buffer_length1;
+ gint _height_buffer_size_;
+ guint8* data = NULL;
+ gint data_length1 = 0;
+ gint _data_size_ = 0;
+ gboolean _tmp29_;
+ gint _tmp52_;
+ guint8* _tmp53_ = NULL;
+ guint8* compressed_data;
+ gint compressed_data_length1;
+ gint _compressed_data_size_;
+ guint _tmp63_;
+ guint number;
+ gchar* _tmp64_ = NULL;
+ gchar* _tmp65_;
+ gchar* _tmp66_ = NULL;
+ gchar* _tmp67_;
+ gchar* _tmp68_ = NULL;
+ gchar* _tmp69_;
+ const gchar* _tmp70_ = NULL;
+ const gchar* _tmp71_ = NULL;
+ gchar* _tmp72_ = NULL;
+ gchar* _tmp73_;
+ gchar* _tmp74_ = NULL;
+ gchar* _tmp75_;
+ guint _tmp76_;
+ gchar* _tmp77_ = NULL;
+ gchar* _tmp78_;
+ gchar* _tmp79_ = NULL;
+ gchar* _tmp80_;
+ gchar* _tmp81_ = NULL;
+ gchar* _tmp82_;
+ gchar* _tmp83_ = NULL;
+ gchar* _tmp84_;
+ gchar* _tmp85_ = NULL;
+ gchar* _tmp86_;
+ gchar* _tmp87_ = NULL;
+ gchar* _tmp88_;
+ const gchar* _tmp91_ = NULL;
+ const gchar* _tmp92_ = NULL;
+ gchar* _tmp93_ = NULL;
+ gchar* command;
+ guint _tmp94_;
+ gchar* _tmp95_ = NULL;
+ gchar* _tmp96_;
+ gint _tmp97_;
+ gchar* _tmp98_ = NULL;
+ gchar* _tmp99_;
+ if (!_tmp17_) {
+ i++;
+ }
+ _tmp17_ = FALSE;
+ _tmp18_ = book_get_n_pages (self);
+ if (!(((guint) i) < _tmp18_)) {
+ break;
+ }
+ _tmp19_ = book_get_page (self, i);
+ page = _tmp19_;
+ _tmp20_ = page_get_image (page, TRUE);
+ image = _tmp20_;
+ _tmp21_ = gdk_pixbuf_get_width (image);
+ width = _tmp21_;
+ _tmp22_ = gdk_pixbuf_get_height (image);
+ height = _tmp22_;
+ _tmp23_ = gdk_pixbuf_get_pixels (image);
+ pixels = _tmp23_;
+ pixels_length1 = -1;
+ _pixels_size_ = pixels_length1;
+ _tmp24_ = page_get_dpi (page);
+ page_width = (width * 72.0) / _tmp24_;
+ _tmp25_ = page_get_dpi (page);
+ page_height = (height * 72.0) / _tmp25_;
+ depth = 8;
+ _tmp26_ = g_strdup ("DeviceRGB");
+ color_space = _tmp26_;
+ filter = NULL;
+ _tmp27_ = g_new0 (gchar, G_ASCII_DTOSTR_BUF_SIZE);
+ width_buffer = _tmp27_;
+ width_buffer_length1 = G_ASCII_DTOSTR_BUF_SIZE;
+ _width_buffer_size_ = width_buffer_length1;
+ _tmp28_ = g_new0 (gchar, G_ASCII_DTOSTR_BUF_SIZE);
+ height_buffer = _tmp28_;
+ height_buffer_length1 = G_ASCII_DTOSTR_BUF_SIZE;
+ _height_buffer_size_ = height_buffer_length1;
+ _tmp29_ = page_is_color (page);
+ if (_tmp29_) {
+ gchar* _tmp30_;
+ gint data_length;
+ guint8* _tmp31_ = NULL;
+ depth = 8;
+ _tmp30_ = g_strdup ("DeviceRGB");
+ _g_free0 (color_space);
+ color_space = _tmp30_;
+ data_length = ((height * width) * 3) + 1;
+ _tmp31_ = g_new0 (guint8, data_length);
+ data = (g_free (data), NULL);
+ data = _tmp31_;
+ data_length1 = data_length;
+ _data_size_ = data_length1;
+ {
+ gint row;
+ row = 0;
+ {
+ gboolean _tmp32_;
+ _tmp32_ = TRUE;
+ while (TRUE) {
+ gint _tmp33_;
+ gint in_offset;
+ gint out_offset;
+ if (!_tmp32_) {
+ row++;
+ }
+ _tmp32_ = FALSE;
+ if (!(row < height)) {
+ break;
+ }
+ _tmp33_ = gdk_pixbuf_get_rowstride (image);
+ in_offset = row * _tmp33_;
+ out_offset = (row * width) * 3;
+ {
+ gint x;
+ x = 0;
+ {
+ gboolean _tmp34_;
+ _tmp34_ = TRUE;
+ while (TRUE) {
+ gint in_o;
+ gint out_o;
+ if (!_tmp34_) {
+ x++;
+ }
+ _tmp34_ = FALSE;
+ if (!(x < width)) {
+ break;
+ }
+ in_o = in_offset + (x * 3);
+ out_o = out_offset + (x * 3);
+ data[out_o] = pixels[in_o];
+ data[out_o + 1] = pixels[in_o + 1];
+ data[out_o + 2] = pixels[in_o + 2];
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ gint _tmp35_;
+ _tmp35_ = page_get_depth (page);
+ if (_tmp35_ == 2) {
+ gint shift_count;
+ gchar* _tmp36_;
+ gint data_length;
+ guint8* _tmp37_ = NULL;
+ gint offset;
+ shift_count = 6;
+ depth = 2;
+ _tmp36_ = g_strdup ("DeviceGray");
+ _g_free0 (color_space);
+ color_space = _tmp36_;
+ data_length = height * (((width * 2) + 7) / 8);
+ _tmp37_ = g_new0 (guint8, data_length);
+ data = (g_free (data), NULL);
+ data = _tmp37_;
+ data_length1 = data_length;
+ _data_size_ = data_length1;
+ offset = 0;
+ data[offset] = (guint8) 0;
+ {
+ gint row;
+ row = 0;
+ {
+ gboolean _tmp38_;
+ _tmp38_ = TRUE;
+ while (TRUE) {
+ gint _tmp39_;
+ gint in_offset;
+ if (!_tmp38_) {
+ row++;
+ }
+ _tmp38_ = FALSE;
+ if (!(row < height)) {
+ break;
+ }
+ if (shift_count != 6) {
+ offset++;
+ data[offset] = (guint8) 0;
+ shift_count = 6;
+ }
+ _tmp39_ = gdk_pixbuf_get_rowstride (image);
+ in_offset = row * _tmp39_;
+ {
+ gint x;
+ x = 0;
+ {
+ gboolean _tmp40_;
+ _tmp40_ = TRUE;
+ while (TRUE) {
+ guint8 p;
+ if (!_tmp40_) {
+ x++;
+ }
+ _tmp40_ = FALSE;
+ if (!(x < width)) {
+ break;
+ }
+ p = pixels[in_offset + (x * 3)];
+ if (((gint) p) >= 192) {
+ data[offset] |= (guint8) (3 << shift_count);
+ } else {
+ if (((gint) p) >= 128) {
+ data[offset] |= (guint8) (2 << shift_count);
+ } else {
+ if (((gint) p) >= 64) {
+ data[offset] |= (guint8) (1 << shift_count);
+ }
+ }
+ }
+ if (shift_count == 0) {
+ offset++;
+ data[offset] = (guint8) 0;
+ shift_count = 6;
+ } else {
+ shift_count = shift_count - 2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ gint _tmp41_;
+ _tmp41_ = page_get_depth (page);
+ if (_tmp41_ == 1) {
+ gint mask;
+ gchar* _tmp42_;
+ gint data_length;
+ guint8* _tmp43_ = NULL;
+ gint offset;
+ mask = 0x80;
+ depth = 1;
+ _tmp42_ = g_strdup ("DeviceGray");
+ _g_free0 (color_space);
+ color_space = _tmp42_;
+ data_length = height * ((width + 7) / 8);
+ _tmp43_ = g_new0 (guint8, data_length);
+ data = (g_free (data), NULL);
+ data = _tmp43_;
+ data_length1 = data_length;
+ _data_size_ = data_length1;
+ offset = 0;
+ data[offset] = (guint8) 0;
+ {
+ gint row;
+ row = 0;
+ {
+ gboolean _tmp44_;
+ _tmp44_ = TRUE;
+ while (TRUE) {
+ gint _tmp45_;
+ gint in_offset;
+ if (!_tmp44_) {
+ row++;
+ }
+ _tmp44_ = FALSE;
+ if (!(row < height)) {
+ break;
+ }
+ if (mask != 0x80) {
+ offset++;
+ data[offset] = (guint8) 0;
+ mask = 0x80;
+ }
+ _tmp45_ = gdk_pixbuf_get_rowstride (image);
+ in_offset = row * _tmp45_;
+ {
+ gint x;
+ x = 0;
+ {
+ gboolean _tmp46_;
+ _tmp46_ = TRUE;
+ while (TRUE) {
+ if (!_tmp46_) {
+ x++;
+ }
+ _tmp46_ = FALSE;
+ if (!(x < width)) {
+ break;
+ }
+ if (((gint) pixels[in_offset + (x * 3)]) != 0) {
+ data[offset] |= (guint8) mask;
+ }
+ mask = mask >> 1;
+ if (mask == 0) {
+ offset++;
+ data[offset] = (guint8) 0;
+ mask = 0x80;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ gchar* _tmp47_;
+ gint data_length;
+ guint8* _tmp48_ = NULL;
+ depth = 8;
+ _tmp47_ = g_strdup ("DeviceGray");
+ _g_free0 (color_space);
+ color_space = _tmp47_;
+ data_length = (height * width) + 1;
+ _tmp48_ = g_new0 (guint8, data_length);
+ data = (g_free (data), NULL);
+ data = _tmp48_;
+ data_length1 = data_length;
+ _data_size_ = data_length1;
+ {
+ gint row;
+ row = 0;
+ {
+ gboolean _tmp49_;
+ _tmp49_ = TRUE;
+ while (TRUE) {
+ gint _tmp50_;
+ gint in_offset;
+ gint out_offset;
+ if (!_tmp49_) {
+ row++;
+ }
+ _tmp49_ = FALSE;
+ if (!(row < height)) {
+ break;
+ }
+ _tmp50_ = gdk_pixbuf_get_rowstride (image);
+ in_offset = row * _tmp50_;
+ out_offset = row * width;
+ {
+ gint x;
+ x = 0;
+ {
+ gboolean _tmp51_;
+ _tmp51_ = TRUE;
+ while (TRUE) {
+ if (!_tmp51_) {
+ x++;
+ }
+ _tmp51_ = FALSE;
+ if (!(x < width)) {
+ break;
+ }
+ data[out_offset + x] = pixels[in_offset + (x * 3)];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ _tmp53_ = book_compress_zlib (self, data, data_length1, &_tmp52_);
+ compressed_data = _tmp53_;
+ compressed_data_length1 = _tmp52_;
+ _compressed_data_size_ = compressed_data_length1;
+ if (compressed_data != NULL) {
+ if (depth > 1) {
+ gsize jpeg_length = 0UL;
+ gsize _tmp54_;
+ gint _tmp55_;
+ guint8* _tmp56_ = NULL;
+ guint8* jpeg_data;
+ gint jpeg_data_length1;
+ gint _jpeg_data_size_;
+ _tmp56_ = book_compress_jpeg (self, image, &_tmp54_, &_tmp55_);
+ jpeg_length = _tmp54_;
+ jpeg_data = _tmp56_;
+ jpeg_data_length1 = _tmp55_;
+ _jpeg_data_size_ = jpeg_data_length1;
+ if (jpeg_length < ((gsize) compressed_data_length1)) {
+ gchar* _tmp57_;
+ guint8* _tmp58_;
+ guint8* _tmp59_;
+ _tmp57_ = g_strdup ("DCTDecode");
+ _g_free0 (filter);
+ filter = _tmp57_;
+ _tmp59_ = (_tmp58_ = jpeg_data, (_tmp58_ == NULL) ? ((gpointer) _tmp58_) : _vala_array_dup1 (_tmp58_, jpeg_data_length1));
+ data = (g_free (data), NULL);
+ data = _tmp59_;
+ data_length1 = jpeg_data_length1;
+ _data_size_ = data_length1;
+ }
+ jpeg_data = (g_free (jpeg_data), NULL);
+ }
+ if (filter == NULL) {
+ gchar* _tmp60_;
+ guint8* _tmp61_;
+ guint8* _tmp62_;
+ _tmp60_ = g_strdup ("FlateDecode");
+ _g_free0 (filter);
+ filter = _tmp60_;
+ _tmp62_ = (_tmp61_ = compressed_data, (_tmp61_ == NULL) ? ((gpointer) _tmp61_) : _vala_array_dup2 (_tmp61_, compressed_data_length1));
+ data = (g_free (data), NULL);
+ data = _tmp62_;
+ data_length1 = compressed_data_length1;
+ _data_size_ = data_length1;
+ }
+ }
+ pdf_writer_write_string (writer, "\n");
+ _tmp63_ = pdf_writer_start_object (writer);
+ number = _tmp63_;
+ _tmp64_ = g_strdup_printf ("%u 0 obj\n", number);
+ _tmp65_ = _tmp64_;
+ pdf_writer_write_string (writer, _tmp65_);
+ _g_free0 (_tmp65_);
+ pdf_writer_write_string (writer, "<<\n");
+ pdf_writer_write_string (writer, "/Type /Page\n");
+ _tmp66_ = g_strdup_printf ("/Parent %u 0 R\n", pages_number);
+ _tmp67_ = _tmp66_;
+ pdf_writer_write_string (writer, _tmp67_);
+ _g_free0 (_tmp67_);
+ _tmp68_ = g_strdup_printf ("/Resources << /XObject << /Im%d %u 0 R >> >>\n", i, number + 1);
+ _tmp69_ = _tmp68_;
+ pdf_writer_write_string (writer, _tmp69_);
+ _g_free0 (_tmp69_);
+ _tmp70_ = g_ascii_formatd (width_buffer, width_buffer_length1, "%.2f", page_width);
+ _tmp71_ = g_ascii_formatd (height_buffer, height_buffer_length1, "%.2f", page_height);
+ _tmp72_ = g_strdup_printf ("/MediaBox [ 0 0 %s %s ]\n", _tmp70_, _tmp71_);
+ _tmp73_ = _tmp72_;
+ pdf_writer_write_string (writer, _tmp73_);
+ _g_free0 (_tmp73_);
+ _tmp74_ = g_strdup_printf ("/Contents %u 0 R\n", number + 2);
+ _tmp75_ = _tmp74_;
+ pdf_writer_write_string (writer, _tmp75_);
+ _g_free0 (_tmp75_);
+ pdf_writer_write_string (writer, ">>\n");
+ pdf_writer_write_string (writer, "endobj\n");
+ pdf_writer_write_string (writer, "\n");
+ _tmp76_ = pdf_writer_start_object (writer);
+ number = _tmp76_;
+ _tmp77_ = g_strdup_printf ("%u 0 obj\n", number);
+ _tmp78_ = _tmp77_;
+ pdf_writer_write_string (writer, _tmp78_);
+ _g_free0 (_tmp78_);
+ pdf_writer_write_string (writer, "<<\n");
+ pdf_writer_write_string (writer, "/Type /XObject\n");
+ pdf_writer_write_string (writer, "/Subtype /Image\n");
+ _tmp79_ = g_strdup_printf ("/Width %d\n", width);
+ _tmp80_ = _tmp79_;
+ pdf_writer_write_string (writer, _tmp80_);
+ _g_free0 (_tmp80_);
+ _tmp81_ = g_strdup_printf ("/Height %d\n", height);
+ _tmp82_ = _tmp81_;
+ pdf_writer_write_string (writer, _tmp82_);
+ _g_free0 (_tmp82_);
+ _tmp83_ = g_strdup_printf ("/ColorSpace /%s\n", color_space);
+ _tmp84_ = _tmp83_;
+ pdf_writer_write_string (writer, _tmp84_);
+ _g_free0 (_tmp84_);
+ _tmp85_ = g_strdup_printf ("/BitsPerComponent %d\n", depth);
+ _tmp86_ = _tmp85_;
+ pdf_writer_write_string (writer, _tmp86_);
+ _g_free0 (_tmp86_);
+ _tmp87_ = g_strdup_printf ("/Length %d\n", data_length1);
+ _tmp88_ = _tmp87_;
+ pdf_writer_write_string (writer, _tmp88_);
+ _g_free0 (_tmp88_);
+ if (filter != NULL) {
+ gchar* _tmp89_ = NULL;
+ gchar* _tmp90_;
+ _tmp89_ = g_strdup_printf ("/Filter /%s\n", filter);
+ _tmp90_ = _tmp89_;
+ pdf_writer_write_string (writer, _tmp90_);
+ _g_free0 (_tmp90_);
+ }
+ pdf_writer_write_string (writer, ">>\n");
+ pdf_writer_write_string (writer, "stream\n");
+ pdf_writer_write (writer, data, data_length1);
+ pdf_writer_write_string (writer, "\n");
+ pdf_writer_write_string (writer, "endstream\n");
+ pdf_writer_write_string (writer, "endobj\n");
+ _tmp91_ = g_ascii_formatd (width_buffer, width_buffer_length1, "%f", page_width);
+ _tmp92_ = g_ascii_formatd (height_buffer, height_buffer_length1, "%f", page_height);
+ _tmp93_ = g_strdup_printf ("q\n%s 0 0 %s 0 0 cm\n/Im%d Do\nQ", _tmp91_, _tmp92_, i);
+ command = _tmp93_;
+ pdf_writer_write_string (writer, "\n");
+ _tmp94_ = pdf_writer_start_object (writer);
+ number = _tmp94_;
+ _tmp95_ = g_strdup_printf ("%u 0 obj\n", number);
+ _tmp96_ = _tmp95_;
+ pdf_writer_write_string (writer, _tmp96_);
+ _g_free0 (_tmp96_);
+ pdf_writer_write_string (writer, "<<\n");
+ _tmp97_ = strlen (command);
+ _tmp98_ = g_strdup_printf ("/Length %d\n", _tmp97_ + 1);
+ _tmp99_ = _tmp98_;
+ pdf_writer_write_string (writer, _tmp99_);
+ _g_free0 (_tmp99_);
+ pdf_writer_write_string (writer, ">>\n");
+ pdf_writer_write_string (writer, "stream\n");
+ pdf_writer_write_string (writer, command);
+ pdf_writer_write_string (writer, "\n");
+ pdf_writer_write_string (writer, "endstream\n");
+ pdf_writer_write_string (writer, "endobj\n");
+ _g_free0 (command);
+ compressed_data = (g_free (compressed_data), NULL);
+ data = (g_free (data), NULL);
+ height_buffer = (g_free (height_buffer), NULL);
+ width_buffer = (g_free (width_buffer), NULL);
+ _g_free0 (filter);
+ _g_free0 (color_space);
+ _g_object_unref0 (image);
+ _page_unref0 (page);
+ }
+ }
+ }
+ pdf_writer_write_string (writer, "\n");
+ _tmp100_ = pdf_writer_start_object (writer);
+ info_number = _tmp100_;
+ _tmp101_ = g_strdup_printf ("%u 0 obj\n", info_number);
+ _tmp102_ = _tmp101_;
+ pdf_writer_write_string (writer, _tmp102_);
+ _g_free0 (_tmp102_);
+ pdf_writer_write_string (writer, "<<\n");
+ _tmp103_ = g_strdup_printf ("/Creator (Simple Scan %s)\n", VERSION);
+ _tmp104_ = _tmp103_;
+ pdf_writer_write_string (writer, _tmp104_);
+ _g_free0 (_tmp104_);
+ pdf_writer_write_string (writer, ">>\n");
+ pdf_writer_write_string (writer, "endobj\n");
+ xref_offset = writer->offset;
+ pdf_writer_write_string (writer, "xref\n");
+ _tmp105_ = g_list_length (writer->object_offsets);
+ _tmp106_ = g_strdup_printf ("1 %zu\n", (gsize) _tmp105_);
+ _tmp107_ = _tmp106_;
+ pdf_writer_write_string (writer, _tmp107_);
+ _g_free0 (_tmp107_);
+ {
+ GList* offset_collection = NULL;
+ GList* offset_it = NULL;
+ offset_collection = writer->object_offsets;
+ for (offset_it = offset_collection; offset_it != NULL; offset_it = offset_it->next) {
+ guint offset = 0U;
+ offset = GPOINTER_TO_UINT (offset_it->data);
+ {
+ gchar* _tmp108_ = NULL;
+ gchar* _tmp109_;
+ _tmp108_ = g_strdup_printf ("%010zu 0000 n\n", (gsize) offset);
+ _tmp109_ = _tmp108_;
+ pdf_writer_write_string (writer, _tmp109_);
+ _g_free0 (_tmp109_);
+ }
+ }
+ }
+ pdf_writer_write_string (writer, "trailer\n");
+ pdf_writer_write_string (writer, "<<\n");
+ _tmp110_ = g_list_length (writer->object_offsets);
+ _tmp111_ = g_strdup_printf ("/Size %zu\n", (gsize) _tmp110_);
+ _tmp112_ = _tmp111_;
+ pdf_writer_write_string (writer, _tmp112_);
+ _g_free0 (_tmp112_);
+ _tmp113_ = g_strdup_printf ("/Info %u 0 R\n", info_number);
+ _tmp114_ = _tmp113_;
+ pdf_writer_write_string (writer, _tmp114_);
+ _g_free0 (_tmp114_);
+ _tmp115_ = g_strdup_printf ("/Root %u 0 R\n", catalog_number);
+ _tmp116_ = _tmp115_;
+ pdf_writer_write_string (writer, _tmp116_);
+ _g_free0 (_tmp116_);
+ pdf_writer_write_string (writer, ">>\n");
+ pdf_writer_write_string (writer, "startxref\n");
+ _tmp117_ = g_strdup_printf ("%zu\n", xref_offset);
+ _tmp118_ = _tmp117_;
+ pdf_writer_write_string (writer, _tmp118_);
+ _g_free0 (_tmp118_);
+ pdf_writer_write_string (writer, "%%%%EOF\n");
+ _pdf_writer_unref0 (writer);
+ _g_object_unref0 (stream);
+}
+
+
+void book_save (Book* self, const gchar* type, GFile* file, GError** error) {
+ gint _tmp0_;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (type != NULL);
+ g_return_if_fail (file != NULL);
+ _tmp0_ = g_strcmp0 (type, "jpeg");
+ if (_tmp0_ == 0) {
+ book_save_multi_file (self, "jpeg", file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ g_propagate_error (error, _inner_error_);
+ return;
+ }
+ } else {
+ gint _tmp1_;
+ _tmp1_ = g_strcmp0 (type, "png");
+ if (_tmp1_ == 0) {
+ book_save_multi_file (self, "png", file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ g_propagate_error (error, _inner_error_);
+ return;
+ }
+ } else {
+ gint _tmp2_;
+ _tmp2_ = g_strcmp0 (type, "tiff");
+ if (_tmp2_ == 0) {
+ book_save_multi_file (self, "tiff", file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ g_propagate_error (error, _inner_error_);
+ return;
+ }
+ } else {
+ gint _tmp3_;
+ _tmp3_ = g_strcmp0 (type, "ps");
+ if (_tmp3_ == 0) {
+ book_save_ps (self, file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ g_propagate_error (error, _inner_error_);
+ return;
+ }
+ } else {
+ gint _tmp4_;
+ _tmp4_ = g_strcmp0 (type, "pdf");
+ if (_tmp4_ == 0) {
+ book_save_pdf (self, file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ g_propagate_error (error, _inner_error_);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void book_set_needs_saving (Book* self, gboolean needs_saving) {
+ gboolean needed_saving;
+ g_return_if_fail (self != NULL);
+ needed_saving = self->priv->needs_saving;
+ self->priv->needs_saving = needs_saving;
+ if (needed_saving != needs_saving) {
+ g_signal_emit_by_name (self, "needs-saving-changed");
+ }
+}
+
+
+gboolean book_get_needs_saving (Book* self) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ result = self->priv->needs_saving;
+ return result;
+}
+
+
+static void g_cclosure_user_marshal_VOID__PAGE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__PAGE) (gpointer data1, gpointer arg_1, gpointer data2);
+ register GMarshalFunc_VOID__PAGE callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 2);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__PAGE) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, value_get_page (param_values + 1), data2);
+}
+
+
+static void value_book_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_book_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ book_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_book_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = book_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_book_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_book_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ Book* 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 = book_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_book_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ Book** 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 = book_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecBook* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_BOOK), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_book (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_book (GValue* value, gpointer v_object) {
+ Book* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BOOK));
+ 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;
+ book_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ book_unref (old);
+ }
+}
-Book *
-book_new ()
-{
- return g_object_new (BOOK_TYPE, NULL);
+void value_take_book (GValue* value, gpointer v_object) {
+ Book* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BOOK));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BOOK));
+ 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) {
+ book_unref (old);
+ }
}
-void
-book_clear (Book *book)
-{
- GList *iter;
- for (iter = book->priv->pages; iter; iter = iter->next) {
- Page *page = iter->data;
- g_object_unref (page);
- }
- g_list_free (book->priv->pages);
- book->priv->pages = NULL;
- g_signal_emit (book, signals[CLEARED], 0);
+static void book_class_init (BookClass * klass) {
+ book_parent_class = g_type_class_peek_parent (klass);
+ BOOK_CLASS (klass)->finalize = book_finalize;
+ g_type_class_add_private (klass, sizeof (BookPrivate));
+ g_signal_new ("page_added", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE);
+ g_signal_new ("page_removed", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__PAGE, G_TYPE_NONE, 1, TYPE_PAGE);
+ g_signal_new ("reordered", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("cleared", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("needs_saving_changed", TYPE_BOOK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
-static void
-page_changed_cb (Page *page, Book *book)
-{
- book_set_needs_saving (book, TRUE);
+static void book_instance_init (Book * self) {
+ self->priv = BOOK_GET_PRIVATE (self);
+ self->ref_count = 1;
}
-Page *
-book_append_page (Book *book, gint width, gint height, gint dpi, ScanDirection scan_direction)
-{
- Page *page;
+static void book_finalize (Book* obj) {
+ Book * self;
+ self = BOOK (obj);
+ __g_list_free__page_unref0_0 (self->priv->pages);
+}
- page = page_new (width, height, dpi, scan_direction);
- g_signal_connect (page, "pixels-changed", G_CALLBACK (page_changed_cb), book);
- g_signal_connect (page, "crop-changed", G_CALLBACK (page_changed_cb), book);
- book->priv->pages = g_list_append (book->priv->pages, page);
+GType book_get_type (void) {
+ static volatile gsize book_type_id__volatile = 0;
+ if (g_once_init_enter (&book_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_book_init, value_book_free_value, value_book_copy_value, value_book_peek_pointer, "p", value_book_collect_value, "p", value_book_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (BookClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) book_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Book), 0, (GInstanceInitFunc) book_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 book_type_id;
+ book_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Book", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&book_type_id__volatile, book_type_id);
+ }
+ return book_type_id__volatile;
+}
- g_signal_emit (book, signals[PAGE_ADDED], 0, page);
-
- book_set_needs_saving (book, TRUE);
- return page;
+gpointer book_ref (gpointer instance) {
+ Book* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
}
-void
-book_move_page (Book *book, Page *page, gint location)
-{
- book->priv->pages = g_list_remove (book->priv->pages, page);
- book->priv->pages = g_list_insert (book->priv->pages, page, location);
+void book_unref (gpointer instance) {
+ Book* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ BOOK_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
- g_signal_emit (book, signals[REORDERED], 0, page);
- book_set_needs_saving (book, TRUE);
+static gpointer _g_object_ref0 (gpointer self) {
+ return self ? g_object_ref (self) : NULL;
}
-void
-book_delete_page (Book *book, Page *page)
-{
- g_signal_handlers_disconnect_by_func (page, page_changed_cb, book);
+PDFWriter* pdf_writer_construct (GType object_type, GFileOutputStream* stream) {
+ PDFWriter* self = NULL;
+ GFileOutputStream* _tmp0_;
+ g_return_val_if_fail (stream != NULL, NULL);
+ self = (PDFWriter*) g_type_create_instance (object_type);
+ _tmp0_ = _g_object_ref0 (stream);
+ _g_object_unref0 (self->priv->stream);
+ self->priv->stream = _tmp0_;
+ return self;
+}
- g_signal_emit (book, signals[PAGE_REMOVED], 0, page);
- book->priv->pages = g_list_remove (book->priv->pages, page);
- g_object_unref (page);
+PDFWriter* pdf_writer_new (GFileOutputStream* stream) {
+ return pdf_writer_construct (TYPE_PDF_WRITER, stream);
+}
+
- book_set_needs_saving (book, TRUE);
+void pdf_writer_write (PDFWriter* self, guint8* data, int data_length1) {
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ {
+ g_output_stream_write_all ((GOutputStream*) self->priv->stream, data, (gsize) data_length1, NULL, NULL, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch0_g_error;
+ }
+ }
+ goto __finally0;
+ __catch0_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("book.vala:529: Error writing PDF: %s", e->message);
+ _g_error_free0 (e);
+ }
+ __finally0:
+ if (_inner_error_ != NULL) {
+ 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;
+ }
+ self->offset = self->offset + data_length1;
}
-gint
-book_get_n_pages (Book *book)
-{
- return g_list_length (book->priv->pages);
+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;
}
-Page *
-book_get_page (Book *book, gint page_number)
-{
- if (page_number < 0)
- page_number = g_list_length (book->priv->pages) + page_number;
- return g_list_nth_data (book->priv->pages, page_number);
+void pdf_writer_write_string (PDFWriter* self, const gchar* text) {
+ gint _tmp0_;
+ gchar* _tmp1_ = NULL;
+ guint8* _tmp2_;
+ gint _tmp2__length1;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (text != NULL);
+ _tmp1_ = string_to_utf8 (text, &_tmp0_);
+ _tmp2_ = (guint8*) _tmp1_;
+ _tmp2__length1 = _tmp0_;
+ pdf_writer_write (self, _tmp2_, _tmp0_);
+ _tmp2_ = (g_free (_tmp2_), NULL);
}
-gint
-book_get_page_index (Book *book, Page *page)
-{
- return g_list_index (book->priv->pages, page);
+guint pdf_writer_start_object (PDFWriter* self) {
+ guint result = 0U;
+ guint _tmp0_;
+ g_return_val_if_fail (self != NULL, 0U);
+ self->object_offsets = g_list_append (self->object_offsets, GUINT_TO_POINTER ((guint) self->offset));
+ _tmp0_ = g_list_length (self->object_offsets);
+ result = _tmp0_;
+ return result;
}
-static GFile *
-make_indexed_file (const gchar *uri, gint i)
-{
- gchar *basename, *suffix, *indexed_uri;
- GFile *file;
+static void value_pdf_writer_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
- if (i == 0)
- return g_file_new_for_uri (uri);
+static void value_pdf_writer_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ pdf_writer_unref (value->data[0].v_pointer);
+ }
+}
- basename = g_path_get_basename (uri);
- suffix = g_strrstr (basename, ".");
- if (suffix)
- indexed_uri = g_strdup_printf ("%.*s-%d%s", (int) (strlen (uri) - strlen (suffix)), uri, i, suffix);
- else
- indexed_uri = g_strdup_printf ("%s-%d", uri, i);
- g_free (basename);
+static void value_pdf_writer_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = pdf_writer_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
- file = g_file_new_for_uri (indexed_uri);
- g_free (indexed_uri);
- return file;
+static gpointer value_pdf_writer_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
}
-static gboolean
-book_save_multi_file (Book *book, const gchar *type, GFile *file, GError **error)
-{
- GList *iter;
- gboolean result = TRUE;
- gint i;
- gchar *uri;
+static gchar* value_pdf_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ PDFWriter* 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 = pdf_writer_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
- uri = g_file_get_uri (file);
- for (iter = book->priv->pages, i = 0; iter && result; iter = iter->next, i++) {
- Page *page = iter->data;
- GFile *file;
- file = make_indexed_file (uri, i);
- result = page_save (page, type, file, error);
- g_object_unref (file);
- }
- g_free (uri);
-
- return result;
+static gchar* value_pdf_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ PDFWriter** 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 = pdf_writer_ref (value->data[0].v_pointer);
+ }
+ return NULL;
}
-static void
-save_ps_pdf_surface (cairo_surface_t *surface, GdkPixbuf *image, gdouble dpi)
-{
- cairo_t *context;
-
- context = cairo_create (surface);
+GParamSpec* param_spec_pdf_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecPDFWriter* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_PDF_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);
+}
- cairo_scale (context, 72.0 / dpi, 72.0 / dpi);
- gdk_cairo_set_source_pixbuf (context, image, 0, 0);
- cairo_pattern_set_filter (cairo_get_source (context), CAIRO_FILTER_BEST);
- cairo_paint (context);
- cairo_destroy (context);
+gpointer value_get_pdf_writer (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER), NULL);
+ return value->data[0].v_pointer;
}
-static cairo_status_t
-write_cairo_data (GFileOutputStream *stream, unsigned char *data, unsigned int length)
-{
- gboolean result;
- GError *error = NULL;
+void value_set_pdf_writer (GValue* value, gpointer v_object) {
+ PDFWriter* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PDF_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;
+ pdf_writer_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ pdf_writer_unref (old);
+ }
+}
- result = g_output_stream_write_all (G_OUTPUT_STREAM (stream), data, length, NULL, NULL, &error);
-
- if (error) {
- g_warning ("Error writing data: %s", error->message);
- g_error_free (error);
- }
- return result ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR;
+void value_take_pdf_writer (GValue* value, gpointer v_object) {
+ PDFWriter* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PDF_WRITER));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PDF_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) {
+ pdf_writer_unref (old);
+ }
}
-static gboolean
-book_save_ps (Book *book, GFile *file, GError **error)
-{
- GFileOutputStream *stream;
- GList *iter;
- cairo_surface_t *surface;
+static void pdf_writer_class_init (PDFWriterClass * klass) {
+ pdf_writer_parent_class = g_type_class_peek_parent (klass);
+ PDF_WRITER_CLASS (klass)->finalize = pdf_writer_finalize;
+ g_type_class_add_private (klass, sizeof (PDFWriterPrivate));
+}
- stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
- if (!stream)
- return FALSE;
- surface = cairo_ps_surface_create_for_stream ((cairo_write_func_t) write_cairo_data,
- stream, 0, 0);
+static void pdf_writer_instance_init (PDFWriter * self) {
+ self->priv = PDF_WRITER_GET_PRIVATE (self);
+ self->offset = (gsize) 0;
+ self->ref_count = 1;
+}
- for (iter = book->priv->pages; iter; iter = iter->next) {
- Page *page = iter->data;
- double width, height;
- GdkPixbuf *image;
- image = page_get_image (page, TRUE);
+static void pdf_writer_finalize (PDFWriter* obj) {
+ PDFWriter * self;
+ self = PDF_WRITER (obj);
+ _g_list_free0 (self->object_offsets);
+ _g_object_unref0 (self->priv->stream);
+}
- width = gdk_pixbuf_get_width (image) * 72.0 / page_get_dpi (page);
- height = gdk_pixbuf_get_height (image) * 72.0 / page_get_dpi (page);
- cairo_ps_surface_set_size (surface, width, height);
- save_ps_pdf_surface (surface, image, page_get_dpi (page));
- cairo_surface_show_page (surface);
-
- g_object_unref (image);
- }
- cairo_surface_destroy (surface);
+GType pdf_writer_get_type (void) {
+ static volatile gsize pdf_writer_type_id__volatile = 0;
+ if (g_once_init_enter (&pdf_writer_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_pdf_writer_init, value_pdf_writer_free_value, value_pdf_writer_copy_value, value_pdf_writer_peek_pointer, "p", value_pdf_writer_collect_value, "p", value_pdf_writer_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (PDFWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pdf_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PDFWriter), 0, (GInstanceInitFunc) pdf_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 pdf_writer_type_id;
+ pdf_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PDFWriter", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&pdf_writer_type_id__volatile, pdf_writer_type_id);
+ }
+ return pdf_writer_type_id__volatile;
+}
- g_object_unref (stream);
- return TRUE;
+gpointer pdf_writer_ref (gpointer instance) {
+ PDFWriter* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
}
-typedef struct
-{
- int offset;
- int n_objects;
- GList *object_offsets;
- GFileOutputStream *stream;
-} PDFWriter;
+void pdf_writer_unref (gpointer instance) {
+ PDFWriter* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ PDF_WRITER_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
-static PDFWriter *
-pdf_writer_new (GFileOutputStream *stream)
-{
- PDFWriter *writer;
- writer = g_malloc0 (sizeof (PDFWriter));
- writer->stream = g_object_ref (stream);
- return writer;
+static cairo_status_t _ps_writer_write_cairo_data_cairo_write_func_t (gpointer self, guchar* data, int data_length1) {
+ cairo_status_t result;
+ result = ps_writer_write_cairo_data (self, data, data_length1);
+ return result;
}
-static void
-pdf_writer_free (PDFWriter *writer)
-{
- g_object_unref (writer->stream);
- g_list_free (writer->object_offsets);
- g_free (writer);
+PsWriter* ps_writer_construct (GType object_type, GFileOutputStream* stream) {
+ PsWriter* self = NULL;
+ GFileOutputStream* _tmp0_;
+ cairo_surface_t* _tmp1_ = NULL;
+ g_return_val_if_fail (stream != NULL, NULL);
+ self = (PsWriter*) g_type_create_instance (object_type);
+ _tmp0_ = _g_object_ref0 (stream);
+ _g_object_unref0 (self->stream);
+ self->stream = _tmp0_;
+ _tmp1_ = cairo_ps_surface_create_for_stream (_ps_writer_write_cairo_data_cairo_write_func_t, self, (gdouble) 0, (gdouble) 0);
+ _cairo_surface_destroy0 (self->surface);
+ self->surface = _tmp1_;
+ return self;
}
-static void
-pdf_write (PDFWriter *writer, const unsigned char *data, size_t length)
-{
- g_output_stream_write_all (G_OUTPUT_STREAM (writer->stream), data, length, NULL, NULL, NULL);
- writer->offset += length;
+PsWriter* ps_writer_new (GFileOutputStream* stream) {
+ return ps_writer_construct (TYPE_PS_WRITER, stream);
}
-static void
-pdf_printf (PDFWriter *writer, const char *format, ...)
-{
- va_list args;
- gchar *string;
+static cairo_status_t ps_writer_write_cairo_data (PsWriter* self, guint8* data, int data_length1) {
+ cairo_status_t result = 0;
+ GError * _inner_error_ = NULL;
+ g_return_val_if_fail (self != NULL, 0);
+ {
+ g_output_stream_write_all ((GOutputStream*) self->stream, data, (gsize) data_length1, NULL, NULL, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch1_g_error;
+ }
+ }
+ goto __finally1;
+ __catch1_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("book.vala:565: Error writing data: %s", e->message);
+ result = CAIRO_STATUS_WRITE_ERROR;
+ _g_error_free0 (e);
+ return result;
+ }
+ __finally1:
+ if (_inner_error_ != NULL) {
+ 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 0;
+ }
+ result = CAIRO_STATUS_SUCCESS;
+ return result;
+}
- va_start (args, format);
- string = g_strdup_vprintf (format, args);
- va_end (args);
- pdf_write (writer, (unsigned char *)string, strlen (string));
- g_free (string);
+static void value_ps_writer_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
}
-static int
-pdf_start_object (PDFWriter *writer)
-{
- writer->n_objects++;
- writer->object_offsets = g_list_append (writer->object_offsets, GINT_TO_POINTER (writer->offset));
- return writer->n_objects;
+static void value_ps_writer_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ ps_writer_unref (value->data[0].v_pointer);
+ }
}
-static guchar *
-compress_zlib (guchar *data, size_t length, size_t *n_written)
-{
- z_stream stream;
- guchar *out_data;
+static void value_ps_writer_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = ps_writer_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
- out_data = g_malloc (sizeof (guchar) * length);
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- if (deflateInit (&stream, Z_BEST_COMPRESSION) != Z_OK)
- return NULL;
+static gpointer value_ps_writer_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
- stream.next_in = data;
- stream.avail_in = length;
- stream.next_out = out_data;
- stream.avail_out = length;
- while (stream.avail_in > 0) {
- if (deflate (&stream, Z_FINISH) == Z_STREAM_ERROR)
- break;
- }
- deflateEnd (&stream);
+static gchar* value_ps_writer_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ PsWriter* 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 = ps_writer_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
- if (stream.avail_in > 0) {
- g_free (out_data);
- return NULL;
- }
+static gchar* value_ps_writer_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ PsWriter** 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 = ps_writer_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
- *n_written = length - stream.avail_out;
- return out_data;
+GParamSpec* param_spec_ps_writer (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecPsWriter* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_PS_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);
}
-
-
-static void jpeg_init_cb (struct jpeg_compress_struct *info) {}
-static boolean jpeg_empty_cb (struct jpeg_compress_struct *info) { return TRUE; }
-static void jpeg_term_cb (struct jpeg_compress_struct *info) {}
-
-static guchar *
-compress_jpeg (GdkPixbuf *image, size_t *n_written)
-{
- struct jpeg_compress_struct info;
- struct jpeg_error_mgr jerr;
- struct jpeg_destination_mgr dest_mgr;
- int r;
- guchar *pixels;
- guchar *data;
- size_t max_length;
-
- info.err = jpeg_std_error (&jerr);
- jpeg_create_compress (&info);
-
- pixels = gdk_pixbuf_get_pixels (image);
- info.image_width = gdk_pixbuf_get_width (image);
- info.image_height = gdk_pixbuf_get_height (image);
- info.input_components = 3;
- info.in_color_space = JCS_RGB; /* TODO: JCS_GRAYSCALE? */
- jpeg_set_defaults (&info);
-
- max_length = info.image_width * info.image_height * info.input_components;
- data = g_malloc (sizeof (guchar) * max_length);
- dest_mgr.next_output_byte = data;
- dest_mgr.free_in_buffer = max_length;
- dest_mgr.init_destination = jpeg_init_cb;
- dest_mgr.empty_output_buffer = jpeg_empty_cb;
- dest_mgr.term_destination = jpeg_term_cb;
- info.dest = &dest_mgr;
-
- jpeg_start_compress (&info, TRUE);
- for (r = 0; r < info.image_height; r++) {
- JSAMPROW row[1];
- row[0] = pixels + r * gdk_pixbuf_get_rowstride (image);
- jpeg_write_scanlines (&info, row, 1);
- }
- jpeg_finish_compress (&info);
- *n_written = max_length - dest_mgr.free_in_buffer;
-
- jpeg_destroy_compress (&info);
-
- return data;
-}
-
-
-static gboolean
-book_save_pdf (Book *book, GFile *file, GError **error)
-{
- GFileOutputStream *stream;
- PDFWriter *writer;
- int catalog_number, pages_number, info_number;
- int xref_offset;
- int i;
-
- stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error);
- if (!stream)
- return FALSE;
-
- writer = pdf_writer_new (stream);
- g_object_unref (stream);
-
- /* Header */
- pdf_printf (writer, "%%PDF-1.3\n");
-
- /* Comment with binary as recommended so file is treated as binary */
- pdf_printf (writer, "%%\xe2\xe3\xcf\xd3\n");
-
- /* Catalog */
- catalog_number = pdf_start_object (writer);
- pdf_printf (writer, "%d 0 obj\n", catalog_number);
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Type /Catalog\n");
- //FIXMEpdf_printf (writer, "/Metadata %d 0 R\n", catalog_number + 1);
- pdf_printf (writer, "/Pages %d 0 R\n", catalog_number + 1); //+2
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "endobj\n");
-
- /* Metadata */
- /* FIXME pdf_printf (writer, "\n");
- number = pdf_start_object (writer);
- pdf_printf (writer, "%d 0 obj\n", number);
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Type /Metadata\n");
- pdf_printf (writer, "/Subtype /XML\n");
- pdf_printf (writer, "/Length %d\n", ...);
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "stream\n");
- // ...
- pdf_printf (writer, "\n");
- pdf_printf (writer, "endstream\n");
- pdf_printf (writer, "endobj\n");*/
-
- /* Pages */
- pdf_printf (writer, "\n");
- pages_number = pdf_start_object (writer);
- pdf_printf (writer, "%d 0 obj\n", pages_number);
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Type /Pages\n");
- pdf_printf (writer, "/Kids [");
- for (i = 0; i < book_get_n_pages (book); i++) {
- pdf_printf (writer, " %d 0 R", pages_number + 1 + (i*3));
- }
- pdf_printf (writer, " ]\n");
- pdf_printf (writer, "/Count %d\n", book_get_n_pages (book));
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "endobj\n");
-
- for (i = 0; i < book_get_n_pages (book); i++) {
- int number, width, height, depth;
- size_t data_length, compressed_length;
- Page *page;
- GdkPixbuf *image;
- guchar *pixels, *data, *compressed_data;
- gchar *command, width_buffer[G_ASCII_DTOSTR_BUF_SIZE], height_buffer[G_ASCII_DTOSTR_BUF_SIZE];
- const gchar *color_space, *filter = NULL;
- float page_width, page_height;
-
- page = book_get_page (book, i);
- image = page_get_image (page, TRUE);
- width = gdk_pixbuf_get_width (image);
- height = gdk_pixbuf_get_height (image);
- pixels = gdk_pixbuf_get_pixels (image);
- page_width = width * 72. / page_get_dpi (page);
- page_height = height * 72. / page_get_dpi (page);
-
- if (page_is_color (page)) {
- int row;
-
- depth = 8;
- color_space = "DeviceRGB";
- data_length = height * width * 3 + 1;
- data = g_malloc (sizeof (guchar) * data_length);
- for (row = 0; row < height; row++) {
- int x;
- guchar *in_line, *out_line;
-
- in_line = pixels + row * gdk_pixbuf_get_rowstride (image);
- out_line = data + row * width * 3;
- for (x = 0; x < width; x++) {
- guchar *in_p = in_line + x*3;
- guchar *out_p = out_line + x*3;
-
- out_p[0] = in_p[0];
- out_p[1] = in_p[1];
- out_p[2] = in_p[2];
- }
- }
- }
- else if (page_get_depth (page) == 2) {
- int row, shift_count = 6;
- guchar *write_ptr;
-
- depth = 2;
- color_space = "DeviceGray";
- data_length = height * ((width * 2 + 7) / 8);
- data = g_malloc (sizeof (guchar) * data_length);
- write_ptr = data;
- write_ptr[0] = 0;
- for (row = 0; row < height; row++) {
- int x;
- guchar *in_line;
-
- /* Pad to the next line */
- if (shift_count != 6) {
- write_ptr++;
- write_ptr[0] = 0;
- shift_count = 6;
- }
-
- in_line = pixels + row * gdk_pixbuf_get_rowstride (image);
- for (x = 0; x < width; x++) {
- guchar *in_p = in_line + x*3;
- if (in_p[0] >= 192)
- write_ptr[0] |= 3 << shift_count;
- else if (in_p[0] >= 128)
- write_ptr[0] |= 2 << shift_count;
- else if (in_p[0] >= 64)
- write_ptr[0] |= 1 << shift_count;
- if (shift_count == 0) {
- write_ptr++;
- write_ptr[0] = 0;
- shift_count = 6;
- }
- else
- shift_count -= 2;
- }
- }
- }
- else if (page_get_depth (page) == 1) {
- int row, mask = 0x80;
- guchar *write_ptr;
-
- depth = 1;
- color_space = "DeviceGray";
- data_length = height * ((width + 7) / 8);
- data = g_malloc (sizeof (guchar) * data_length);
- write_ptr = data;
- write_ptr[0] = 0;
- for (row = 0; row < height; row++) {
- int x;
- guchar *in_line;
-
- /* Pad to the next line */
- if (mask != 0x80) {
- write_ptr++;
- write_ptr[0] = 0;
- mask = 0x80;
- }
-
- in_line = pixels + row * gdk_pixbuf_get_rowstride (image);
- for (x = 0; x < width; x++) {
- guchar *in_p = in_line + x*3;
- if (in_p[0] != 0)
- write_ptr[0] |= mask;
- mask >>= 1;
- if (mask == 0) {
- write_ptr++;
- write_ptr[0] = 0;
- mask = 0x80;
- }
- }
- }
- }
- else {
- int row;
-
- depth = 8;
- color_space = "DeviceGray";
- data_length = height * width + 1;
- data = g_malloc (sizeof (guchar) * data_length);
- for (row = 0; row < height; row++) {
- int x;
- guchar *in_line, *out_line;
-
- in_line = pixels + row * gdk_pixbuf_get_rowstride (image);
- out_line = data + row * width;
- for (x = 0; x < width; x++) {
- guchar *in_p = in_line + x*3;
- guchar *out_p = out_line + x;
-
- out_p[0] = in_p[0];
- }
- }
- }
-
- /* Compress data */
- compressed_data = compress_zlib (data, data_length, &compressed_length);
- if (compressed_data) {
- /* Try if JPEG compression is better */
- if (depth > 1) {
- guchar *jpeg_data;
- size_t jpeg_length;
-
- jpeg_data = compress_jpeg (image, &jpeg_length);
- if (jpeg_length < compressed_length) {
- filter = "DCTDecode";
- g_free (data);
- g_free (compressed_data);
- data = jpeg_data;
- data_length = jpeg_length;
- }
- }
-
- if (!filter) {
- filter = "FlateDecode";
- g_free (data);
- data = compressed_data;
- data_length = compressed_length;
- }
- }
-
- /* Page */
- pdf_printf (writer, "\n");
- number = pdf_start_object (writer);
- pdf_printf (writer, "%d 0 obj\n", number);
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Type /Page\n");
- pdf_printf (writer, "/Parent %d 0 R\n", pages_number);
- pdf_printf (writer, "/Resources << /XObject << /Im%d %d 0 R >> >>\n", i, number+1);
- pdf_printf (writer, "/MediaBox [ 0 0 %s %s ]\n",
- g_ascii_formatd (width_buffer, sizeof (width_buffer), "%.2f", page_width),
- g_ascii_formatd (height_buffer, sizeof (height_buffer), "%.2f", page_height));
- pdf_printf (writer, "/Contents %d 0 R\n", number+2);
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "endobj\n");
-
- /* Page image */
- pdf_printf (writer, "\n");
- number = pdf_start_object (writer);
- pdf_printf (writer, "%d 0 obj\n", number);
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Type /XObject\n");
- pdf_printf (writer, "/Subtype /Image\n");
- pdf_printf (writer, "/Width %d\n", width);
- pdf_printf (writer, "/Height %d\n", height);
- pdf_printf (writer, "/ColorSpace /%s\n", color_space);
- pdf_printf (writer, "/BitsPerComponent %d\n", depth);
- pdf_printf (writer, "/Length %d\n", data_length);
- if (filter)
- pdf_printf (writer, "/Filter /%s\n", filter);
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "stream\n");
- pdf_write (writer, data, data_length);
- g_free (data);
- pdf_printf (writer, "\n");
- pdf_printf (writer, "endstream\n");
- pdf_printf (writer, "endobj\n");
-
- /* Page contents */
- command = g_strdup_printf ("q\n"
- "%s 0 0 %s 0 0 cm\n"
- "/Im%d Do\n"
- "Q",
- g_ascii_formatd (width_buffer, sizeof (width_buffer), "%f", page_width),
- g_ascii_formatd (height_buffer, sizeof (height_buffer), "%f", page_height),
- i);
- pdf_printf (writer, "\n");
- number = pdf_start_object (writer);
- pdf_printf (writer, "%d 0 obj\n", number);
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Length %d\n", strlen (command) + 1);
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "stream\n");
- pdf_write (writer, (unsigned char *)command, strlen (command));
- pdf_printf (writer, "\n");
- pdf_printf (writer, "endstream\n");
- pdf_printf (writer, "endobj\n");
- g_free (command);
-
- g_object_unref (image);
- }
-
- /* Info */
- pdf_printf (writer, "\n");
- info_number = pdf_start_object (writer);
- pdf_printf (writer, "%d 0 obj\n", info_number);
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Creator (Simple Scan " VERSION ")\n");
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "endobj\n");
-
- /* Cross-reference table */
- xref_offset = writer->offset;
- pdf_printf (writer, "xref\n");
- pdf_printf (writer, "1 %d\n", writer->n_objects);
- GList *link;
- for (link = writer->object_offsets; link != NULL; link = link->next) {
- int offset = GPOINTER_TO_INT (link->data);
- pdf_printf (writer, "%010d 0000 n\n", offset);
- }
-
- /* Trailer */
- pdf_printf (writer, "trailer\n");
- pdf_printf (writer, "<<\n");
- pdf_printf (writer, "/Size %d\n", writer->n_objects);
- pdf_printf (writer, "/Info %d 0 R\n", info_number);
- pdf_printf (writer, "/Root %d 0 R\n", catalog_number);
- //FIXME: pdf_printf (writer, "/ID [<...> <...>]\n");
- pdf_printf (writer, ">>\n");
- pdf_printf (writer, "startxref\n");
- pdf_printf (writer, "%d\n", xref_offset);
- pdf_printf (writer, "%%%%EOF\n");
-
- pdf_writer_free (writer);
-
- return TRUE;
-}
-
-
-gboolean
-book_save (Book *book, const gchar *type, GFile *file, GError **error)
-{
- gboolean result = FALSE;
-
- if (strcmp (type, "jpeg") == 0)
- result = book_save_multi_file (book, "jpeg", file, error);
- else if (strcmp (type, "png") == 0)
- result = book_save_multi_file (book, "png", file, error);
- else if (strcmp (type, "tiff") == 0)
- result = book_save_multi_file (book, "tiff", file, error);
- else if (strcmp (type, "ps") == 0)
- result = book_save_ps (book, file, error);
- else if (strcmp (type, "pdf") == 0)
- result = book_save_pdf (book, file, error);
-
- return result;
-}
-
-
-void
-book_set_needs_saving (Book *book, gboolean needs_saving)
-{
- gboolean needed_saving = book->priv->needs_saving;
- book->priv->needs_saving = needs_saving;
- if (needed_saving != needs_saving)
- g_object_notify (G_OBJECT (book), "needs-saving");
-}
-
-
-gboolean
-book_get_needs_saving (Book *book)
-{
- return book->priv->needs_saving;
-}
-
-
-static void
-book_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- Book *self;
-
- self = BOOK (object);
-
- switch (prop_id) {
- case PROP_NEEDS_SAVING:
- book_set_needs_saving (self, g_value_get_boolean (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static void
-book_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- Book *self;
-
- self = BOOK (object);
-
- switch (prop_id) {
- case PROP_NEEDS_SAVING:
- g_value_set_boolean (value, book_get_needs_saving (self));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-
-static void
-book_finalize (GObject *object)
-{
- Book *book = BOOK (object);
- book_clear (book);
- G_OBJECT_CLASS (book_parent_class)->finalize (object);
-}
-
-
-static void
-book_class_init (BookClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->get_property = book_get_property;
- object_class->set_property = book_set_property;
- object_class->finalize = book_finalize;
-
- g_object_class_install_property (object_class,
- PROP_NEEDS_SAVING,
- g_param_spec_boolean ("needs-saving",
- "needs-saving",
- "TRUE if this book needs saving",
- FALSE,
- G_PARAM_READWRITE));
-
- signals[PAGE_ADDED] =
- g_signal_new ("page-added",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (BookClass, page_added),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, page_get_type ());
- signals[PAGE_REMOVED] =
- g_signal_new ("page-removed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (BookClass, page_removed),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, page_get_type ());
- signals[REORDERED] =
- g_signal_new ("reordered",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (BookClass, reordered),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- signals[CLEARED] =
- g_signal_new ("cleared",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (BookClass, cleared),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (klass, sizeof (BookPrivate));
-}
-
-
-static void
-book_init (Book *book)
-{
- book->priv = G_TYPE_INSTANCE_GET_PRIVATE (book, BOOK_TYPE, BookPrivate);
+
+
+gpointer value_get_ps_writer (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER), NULL);
+ return value->data[0].v_pointer;
}
+
+
+void value_set_ps_writer (GValue* value, gpointer v_object) {
+ PsWriter* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PS_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;
+ ps_writer_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ ps_writer_unref (old);
+ }
+}
+
+
+void value_take_ps_writer (GValue* value, gpointer v_object) {
+ PsWriter* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PS_WRITER));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PS_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) {
+ ps_writer_unref (old);
+ }
+}
+
+
+static void ps_writer_class_init (PsWriterClass * klass) {
+ ps_writer_parent_class = g_type_class_peek_parent (klass);
+ PS_WRITER_CLASS (klass)->finalize = ps_writer_finalize;
+}
+
+
+static void ps_writer_instance_init (PsWriter * self) {
+ self->ref_count = 1;
+}
+
+
+static void ps_writer_finalize (PsWriter* obj) {
+ PsWriter * self;
+ self = PS_WRITER (obj);
+ _cairo_surface_destroy0 (self->surface);
+ _g_object_unref0 (self->stream);
+}
+
+
+GType ps_writer_get_type (void) {
+ static volatile gsize ps_writer_type_id__volatile = 0;
+ if (g_once_init_enter (&ps_writer_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_ps_writer_init, value_ps_writer_free_value, value_ps_writer_copy_value, value_ps_writer_peek_pointer, "p", value_ps_writer_collect_value, "p", value_ps_writer_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (PsWriterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ps_writer_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PsWriter), 0, (GInstanceInitFunc) ps_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 ps_writer_type_id;
+ ps_writer_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PsWriter", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&ps_writer_type_id__volatile, ps_writer_type_id);
+ }
+ return ps_writer_type_id__volatile;
+}
+
+
+gpointer ps_writer_ref (gpointer instance) {
+ PsWriter* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void ps_writer_unref (gpointer instance) {
+ PsWriter* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ PS_WRITER_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+
diff --git a/src/book.h b/src/book.h
deleted file mode 100644
index cf82978..0000000
--- a/src/book.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009 Canonical Ltd.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#ifndef _BOOK_H_
-#define _BOOK_H_
-
-#include <glib-object.h>
-#include <gio/gio.h>
-#include <cairo.h>
-#include "page.h"
-
-G_BEGIN_DECLS
-
-#define BOOK_TYPE (book_get_type ())
-#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BOOK_TYPE, Book))
-
-
-typedef struct BookPrivate BookPrivate;
-
-typedef struct
-{
- GObject parent_instance;
- BookPrivate *priv;
-} Book;
-
-typedef struct
-{
- GObjectClass parent_class;
-
- void (*page_added) (Book *book, Page *page);
- void (*page_removed) (Book *book, Page *page);
- void (*reordered) (Book *book);
- void (*cleared) (Book *book);
-} BookClass;
-
-
-GType book_get_type (void);
-
-Book *book_new (void);
-
-void book_clear (Book *book);
-
-Page *book_append_page (Book *book, gint width, gint height, gint dpi, ScanDirection orientation);
-
-void book_move_page (Book *book, Page *page, gint location);
-
-void book_delete_page (Book *book, Page *page);
-
-gint book_get_n_pages (Book *book);
-
-Page *book_get_page (Book *book, gint page_number);
-
-gint book_get_page_index (Book *book, Page *page);
-
-gboolean book_save (Book *book, const gchar *type, GFile *file, GError **error);
-
-void book_set_needs_saving (Book *book, gboolean needs_saving);
-
-gboolean book_get_needs_saving (Book *book);
-
-#endif /* _BOOK_H_ */
diff --git a/src/book.vala b/src/book.vala
new file mode 100644
index 0000000..1aed281
--- /dev/null
+++ b/src/book.vala
@@ -0,0 +1,571 @@
+/*
+ * Copyright (C) 2009-2011 Canonical Ltd.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+public class Book
+{
+ private List<Page> pages;
+
+ private bool needs_saving;
+
+ public signal void page_added (Page page);
+ public signal void page_removed (Page page);
+ public signal void reordered ();
+ public signal void cleared ();
+ public signal void needs_saving_changed ();
+
+ public Book ()
+ {
+ }
+
+ public void clear ()
+ {
+ pages = null;
+ cleared ();
+ }
+
+ private void page_changed_cb (Page page)
+ {
+ set_needs_saving (true);
+ }
+
+ public Page append_page (int width, int height, int dpi, ScanDirection scan_direction)
+ {
+ var page = new Page (width, height, dpi, scan_direction);
+ page.pixels_changed.connect (page_changed_cb);
+ page.crop_changed.connect (page_changed_cb);
+
+ pages.append (page);
+ page_added (page);
+ set_needs_saving (true);
+
+ return page;
+ }
+
+ public void move_page (Page page, uint location)
+ {
+ pages.remove (page);
+ pages.insert (page, (int) location);
+ reordered ();
+ set_needs_saving (true);
+ }
+
+ public void delete_page (Page page)
+ {
+ page.pixels_changed.disconnect (page_changed_cb);
+ page.crop_changed.disconnect (page_changed_cb);
+ page_removed (page);
+ pages.remove (page);
+ set_needs_saving (true);
+ }
+
+ public uint get_n_pages ()
+ {
+ return pages.length ();
+ }
+
+ public Page get_page (int page_number)
+ {
+ if (page_number < 0)
+ page_number = (int) pages.length () + page_number;
+ return pages.nth_data (page_number);
+ }
+
+ public uint get_page_index (Page page)
+ {
+ return pages.index (page);
+ }
+
+ private File make_indexed_file (string uri, int i)
+ {
+ if (i == 0)
+ return File.new_for_uri (uri);
+
+ /* Insert index before extension */
+ var basename = Path.get_basename (uri);
+ string prefix = uri, suffix = "";
+ var extension_index = basename.last_index_of_char ('.');
+ if (extension_index >= 0)
+ {
+ suffix = basename.slice (extension_index, basename.length);
+ prefix = uri.slice (0, uri.length - suffix.length);
+ }
+
+ return File.new_for_uri ("%s-%d%s".printf (prefix, i, suffix));
+ }
+
+ private void save_multi_file (string type, File file) throws Error
+ {
+ int i = 0;
+ foreach (var page in pages)
+ {
+ page.save (type, make_indexed_file (file.get_uri (), i));
+ i++;
+ }
+ }
+
+ private void save_ps_pdf_surface (Cairo.Surface surface, Gdk.Pixbuf image, double dpi)
+ {
+ var context = new Cairo.Context (surface);
+ context.scale (72.0 / dpi, 72.0 / dpi);
+ Gdk.cairo_set_source_pixbuf (context, image, 0, 0);
+ context.get_source ().set_filter (Cairo.Filter.BEST);
+ context.paint ();
+ }
+
+ private void save_ps (File file) throws Error
+ {
+ var stream = file.replace (null, false, FileCreateFlags.NONE, null);
+ var writer = new PsWriter (stream);
+ var surface = writer.surface;
+
+ foreach (var page in pages)
+ {
+ var image = page.get_image (true);
+ var width = image.get_width () * 72.0 / page.get_dpi ();
+ var height = image.get_height () * 72.0 / page.get_dpi ();
+ surface.set_size (width, height);
+ save_ps_pdf_surface (surface, image, page.get_dpi ());
+ surface.show_page ();
+ }
+ }
+
+ private uint8[]? compress_zlib (uint8[] data)
+ {
+ var stream = ZLib.DeflateStream (ZLib.Level.BEST_COMPRESSION);
+ var out_data = new uint8[data.length];
+
+ stream.next_in = data;
+ stream.next_out = out_data;
+ while (stream.avail_in > 0)
+ {
+ if (stream.deflate (ZLib.Flush.FINISH) == ZLib.Status.STREAM_ERROR)
+ break;
+ }
+
+ if (stream.avail_in > 0)
+ return null;
+
+ var n_written = data.length - stream.avail_out;
+ out_data.resize ((int) n_written);
+
+ return out_data;
+ }
+
+ private static void jpeg_init_cb (JPEG.Compress info) {}
+ private static bool jpeg_empty_cb (JPEG.Compress info) { return true; }
+ private static void jpeg_term_cb (JPEG.Compress info) {}
+
+ private uint8[] compress_jpeg (Gdk.Pixbuf image, out size_t n_written)
+ {
+ var info = JPEG.Compress ();
+ var jerr = JPEG.ErrorManager ();
+ var dest_mgr = JPEG.DestinationManager ();
+
+ info.err = jerr.std_error ();
+ info.create_compress ();
+
+ info.image_width = image.get_width ();
+ info.image_height = image.get_height ();
+ info.input_components = 3;
+ info.in_color_space = JPEG.ColorSpace.RGB; /* TODO: JCS_GRAYSCALE? */
+ info.set_defaults ();
+
+ var max_length = info.image_width * info.image_height * info.input_components;
+ var data = new uint8[max_length];
+ dest_mgr.next_output_byte = data;
+ dest_mgr.free_in_buffer = max_length;
+ dest_mgr.init_destination = jpeg_init_cb;
+ dest_mgr.empty_output_buffer = jpeg_empty_cb;
+ dest_mgr.term_destination = jpeg_term_cb;
+ info.dest = &dest_mgr;
+
+ info.start_compress (true);
+ unowned uint8[] pixels = image.get_pixels ();
+ for (var r = 0; r < info.image_height; r++)
+ {
+ uint8* row[1];
+ row[0] = (uint8*) pixels + r * image.get_rowstride ();
+ info.write_scanlines (row, 1);
+ }
+ info.finish_compress ();
+ n_written = max_length - dest_mgr.free_in_buffer;
+
+ return data;
+ }
+
+ private void save_pdf (File file) throws Error
+ {
+ var stream = file.replace (null, false, FileCreateFlags.NONE, null);
+ var writer = new PDFWriter (stream);
+
+ /* Header */
+ writer.write_string ("%%PDF-1.3\n");
+
+ /* Comment with binary as recommended so file is treated as binary */
+ writer.write_string ("%%\xe2\xe3\xcf\xd3\n");
+
+ /* Catalog */
+ var catalog_number = writer.start_object ();
+ writer.write_string ("%u 0 obj\n".printf (catalog_number));
+ writer.write_string ("<<\n");
+ writer.write_string ("/Type /Catalog\n");
+ //FIXMEwriter.write_string ("/Metadata %u 0 R\n".printf (catalog_number + 1));
+ writer.write_string ("/Pages %u 0 R\n".printf (catalog_number + 1)); //+2
+ writer.write_string (">>\n");
+ writer.write_string ("endobj\n");
+
+ /* Metadata */
+ /* FIXME writer.write_string ("\n");
+ number = writer.start_object ();
+ writer.write_string ("%u 0 obj\n".printf (number));
+ writer.write_string ("<<\n");
+ writer.write_string ("/Type /Metadata\n");
+ writer.write_string ("/Subtype /XML\n");
+ writer.write_string ("/Length %u\n".printf (...));
+ writer.write_string (">>\n");
+ writer.write_string ("stream\n");
+ // ...
+ writer.write_string ("\n");
+ writer.write_string ("endstream\n");
+ writer.write_string ("endobj\n");*/
+
+ /* Pages */
+ writer.write_string ("\n");
+ var pages_number = writer.start_object ();
+ writer.write_string ("%u 0 obj\n".printf (pages_number));
+ writer.write_string ("<<\n");
+ writer.write_string ("/Type /Pages\n");
+ writer.write_string ("/Kids [");
+ for (var i = 0; i < get_n_pages (); i++)
+ writer.write_string (" %u 0 R".printf (pages_number + 1 + (i*3)));
+ writer.write_string (" ]\n");
+ writer.write_string ("/Count %u\n".printf (get_n_pages ()));
+ writer.write_string (">>\n");
+ writer.write_string ("endobj\n");
+
+ for (var i = 0; i < get_n_pages (); i++)
+ {
+ var page = get_page (i);
+ var image = page.get_image (true);
+ var width = image.get_width ();
+ var height = image.get_height ();
+ unowned uint8[] pixels = image.get_pixels ();
+ var page_width = width * 72.0 / page.get_dpi ();
+ var page_height = height * 72.0 / page.get_dpi ();
+
+ int depth = 8;
+ string color_space = "DeviceRGB";
+ string? filter = null;
+ char[] width_buffer = new char[double.DTOSTR_BUF_SIZE];
+ char[] height_buffer = new char[double.DTOSTR_BUF_SIZE];
+ uint8[] data;
+ if (page.is_color ())
+ {
+ depth = 8;
+ color_space = "DeviceRGB";
+ var data_length = height * width * 3 + 1;
+ data = new uint8[data_length];
+ for (var row = 0; row < height; row++)
+ {
+ var in_offset = row * image.get_rowstride ();
+ var out_offset = row * width * 3;
+ for (var x = 0; x < width; x++)
+ {
+ var in_o = in_offset + x*3;
+ var out_o = out_offset + x*3;
+
+ data[out_o] = pixels[in_o];
+ data[out_o+1] = pixels[in_o+1];
+ data[out_o+2] = pixels[in_o+2];
+ }
+ }
+ }
+ else if (page.get_depth () == 2)
+ {
+ int shift_count = 6;
+ depth = 2;
+ color_space = "DeviceGray";
+ var data_length = height * ((width * 2 + 7) / 8);
+ data = new uint8[data_length];
+ var offset = 0;
+ data[offset] = 0;
+ for (var row = 0; row < height; row++)
+ {
+ /* Pad to the next line */
+ if (shift_count != 6)
+ {
+ offset++;
+ data[offset] = 0;
+ shift_count = 6;
+ }
+
+ var in_offset = row * image.get_rowstride ();
+ for (var x = 0; x < width; x++)
+ {
+ var p = pixels[in_offset + x*3];
+ if (p >= 192)
+ data[offset] |= 3 << shift_count;
+ else if (p >= 128)
+ data[offset] |= 2 << shift_count;
+ else if (p >= 64)
+ data[offset] |= 1 << shift_count;
+ if (shift_count == 0)
+ {
+ offset++;
+ data[offset] = 0;
+ shift_count = 6;
+ }
+ else
+ shift_count -= 2;
+ }
+ }
+ }
+ else if (page.get_depth () == 1)
+ {
+ int mask = 0x80;
+
+ depth = 1;
+ color_space = "DeviceGray";
+ var data_length = height * ((width + 7) / 8);
+ data = new uint8[data_length];
+ var offset = 0;
+ data[offset] = 0;
+ for (var row = 0; row < height; row++)
+ {
+ /* Pad to the next line */
+ if (mask != 0x80)
+ {
+ offset++;
+ data[offset] = 0;
+ mask = 0x80;
+ }
+
+ var in_offset = row * image.get_rowstride ();
+ for (var x = 0; x < width; x++)
+ {
+ if (pixels[in_offset+x*3] != 0)
+ data[offset] |= (uint8) mask;
+ mask >>= 1;
+ if (mask == 0)
+ {
+ offset++;
+ data[offset] = 0;
+ mask = 0x80;
+ }
+ }
+ }
+ }
+ else
+ {
+ depth = 8;
+ color_space = "DeviceGray";
+ var data_length = height * width + 1;
+ data = new uint8 [data_length];
+ for (var row = 0; row < height; row++)
+ {
+ var in_offset = row * image.get_rowstride ();
+ var out_offset = row * width;
+ for (var x = 0; x < width; x++)
+ data[out_offset+x] = pixels[in_offset+x*3];
+ }
+ }
+
+ /* Compress data */
+ var compressed_data = compress_zlib (data);
+ if (compressed_data != null)
+ {
+ /* Try if JPEG compression is better */
+ if (depth > 1)
+ {
+ size_t jpeg_length;
+ var jpeg_data = compress_jpeg (image, out jpeg_length);
+ if (jpeg_length < compressed_data.length)
+ {
+ filter = "DCTDecode";
+ data = jpeg_data;
+ }
+ }
+
+ if (filter == null)
+ {
+ filter = "FlateDecode";
+ data = compressed_data;
+ }
+ }
+
+ /* Page */
+ writer.write_string ("\n");
+ var number = writer.start_object ();
+ writer.write_string ("%u 0 obj\n".printf (number));
+ writer.write_string ("<<\n");
+ writer.write_string ("/Type /Page\n");
+ writer.write_string ("/Parent %u 0 R\n".printf (pages_number));
+ writer.write_string ("/Resources << /XObject << /Im%d %u 0 R >> >>\n".printf (i, number+1));
+ writer.write_string ("/MediaBox [ 0 0 %s %s ]\n".printf (page_width.format (width_buffer, "%.2f"), page_height.format (height_buffer, "%.2f")));
+ writer.write_string ("/Contents %u 0 R\n".printf (number+2));
+ writer.write_string (">>\n");
+ writer.write_string ("endobj\n");
+
+ /* Page image */
+ writer.write_string ("\n");
+ number = writer.start_object ();
+ writer.write_string ("%u 0 obj\n".printf (number));
+ writer.write_string ("<<\n");
+ writer.write_string ("/Type /XObject\n");
+ writer.write_string ("/Subtype /Image\n");
+ writer.write_string ("/Width %d\n".printf (width));
+ writer.write_string ("/Height %d\n".printf (height));
+ writer.write_string ("/ColorSpace /%s\n".printf (color_space));
+ writer.write_string ("/BitsPerComponent %d\n".printf (depth));
+ writer.write_string ("/Length %d\n".printf (data.length));
+ if (filter != null)
+ writer.write_string ("/Filter /%s\n".printf (filter));
+ writer.write_string (">>\n");
+ writer.write_string ("stream\n");
+ writer.write (data);
+ writer.write_string ("\n");
+ writer.write_string ("endstream\n");
+ writer.write_string ("endobj\n");
+
+ /* Page contents */
+ var command = "q\n%s 0 0 %s 0 0 cm\n/Im%d Do\nQ".printf (page_width.format (width_buffer, "%f"), page_height.format (height_buffer, "%f"), i);
+ writer.write_string ("\n");
+ number = writer.start_object ();
+ writer.write_string ("%u 0 obj\n".printf (number));
+ writer.write_string ("<<\n");
+ writer.write_string ("/Length %d\n".printf (command.length + 1));
+ writer.write_string (">>\n");
+ writer.write_string ("stream\n");
+ writer.write_string (command);
+ writer.write_string ("\n");
+ writer.write_string ("endstream\n");
+ writer.write_string ("endobj\n");
+ }
+
+ /* Info */
+ writer.write_string ("\n");
+ var info_number = writer.start_object ();
+ writer.write_string ("%u 0 obj\n".printf (info_number));
+ writer.write_string ("<<\n");
+ writer.write_string ("/Creator (Simple Scan %s)\n".printf (Config.VERSION));
+ writer.write_string (">>\n");
+ writer.write_string ("endobj\n");
+
+ /* Cross-reference table */
+ var xref_offset = writer.offset;
+ writer.write_string ("xref\n");
+ writer.write_string ("1 %zu\n".printf (writer.object_offsets.length ()));
+ foreach (var offset in writer.object_offsets)
+ writer.write_string ("%010zu 0000 n\n".printf (offset));
+
+ /* Trailer */
+ writer.write_string ("trailer\n");
+ writer.write_string ("<<\n");
+ writer.write_string ("/Size %zu\n".printf (writer.object_offsets.length ()));
+ writer.write_string ("/Info %u 0 R\n".printf (info_number));
+ writer.write_string ("/Root %u 0 R\n".printf (catalog_number));
+ //FIXME: writer.write_string ("/ID [<...> <...>]\n");
+ writer.write_string (">>\n");
+ writer.write_string ("startxref\n");
+ writer.write_string ("%zu\n".printf (xref_offset));
+ writer.write_string ("%%%%EOF\n");
+ }
+
+ public void save (string type, File file) throws Error
+ {
+ if (strcmp (type, "jpeg") == 0)
+ save_multi_file ("jpeg", file);
+ else if (strcmp (type, "png") == 0)
+ save_multi_file ("png", file);
+ else if (strcmp (type, "tiff") == 0)
+ save_multi_file ("tiff", file);
+ else if (strcmp (type, "ps") == 0)
+ save_ps (file);
+ else if (strcmp (type, "pdf") == 0)
+ save_pdf (file);
+ }
+
+ public void set_needs_saving (bool needs_saving)
+ {
+ var needed_saving = this.needs_saving;
+ this.needs_saving = needs_saving;
+ if (needed_saving != needs_saving)
+ needs_saving_changed ();
+ }
+
+ public bool get_needs_saving ()
+ {
+ return needs_saving;
+ }
+}
+
+private class PDFWriter
+{
+ public size_t offset = 0;
+ public List<uint> object_offsets;
+ private FileOutputStream stream;
+
+ public PDFWriter (FileOutputStream stream)
+ {
+ this.stream = stream;
+ }
+
+ public void write (uint8[] data)
+ {
+ try
+ {
+ stream.write_all (data, null, null);
+ }
+ catch (Error e)
+ {
+ warning ("Error writing PDF: %s", e.message);
+ }
+ offset += data.length;
+ }
+
+ public void write_string (string text)
+ {
+ write ((uint8[]) text.to_utf8 ());
+ }
+
+ public uint start_object ()
+ {
+ object_offsets.append ((uint)offset);
+ return object_offsets.length ();
+ }
+}
+
+public class PsWriter
+{
+ public Cairo.PsSurface surface;
+ public FileOutputStream stream;
+
+ public PsWriter (FileOutputStream stream)
+ {
+ this.stream = stream;
+ surface = new Cairo.PsSurface.for_stream (write_cairo_data, 0, 0);
+ }
+
+ private Cairo.Status write_cairo_data (uint8[] data)
+ {
+ try
+ {
+ stream.write_all (data, null, null);
+ }
+ catch (Error e)
+ {
+ warning ("Error writing data: %s", e.message);
+ return Cairo.Status.WRITE_ERROR;
+ }
+
+ return Cairo.Status.SUCCESS;
+ }
+}
diff --git a/src/colord.vapi b/src/colord.vapi
new file mode 100644
index 0000000..817673f
--- /dev/null
+++ b/src/colord.vapi
@@ -0,0 +1,17 @@
+[CCode (cprefix = "Cd", lower_case_cprefix = "cd_", cheader_filename = "colord.h")]
+namespace Colord {
+ public class Client : GLib.Object {
+ public Client ();
+ public bool connect_sync (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public Device find_device_by_property_sync (string key, string value, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ }
+ public class Device : GLib.Object {
+ public bool connect_sync (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public Profile? get_default_profile ();
+ }
+ public class Profile : GLib.Object {
+ public bool connect_sync (GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public string? filename { get; }
+ }
+ public const string DEVICE_PROPERTY_SERIAL;
+}
diff --git a/src/config.vapi b/src/config.vapi
new file mode 100644
index 0000000..c326020
--- /dev/null
+++ b/src/config.vapi
@@ -0,0 +1,10 @@
+[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
+namespace Config
+{
+ public const string PKGDATADIR;
+ public const string LOCALE_DIR;
+ public const string GETTEXT_PACKAGE;
+ public const string VERSION;
+ public const string UI_DIR;
+ public const string ICON_DIR;
+}
diff --git a/src/jpeglib.vapi b/src/jpeglib.vapi
new file mode 100644
index 0000000..3022b5b
--- /dev/null
+++ b/src/jpeglib.vapi
@@ -0,0 +1,57 @@
+[CCode (cheader_filename = "jpeglib.h", cprefix = "jpeg_")]
+namespace JPEG {
+ [CCode (cprefix = "JCS_")]
+ public enum ColorSpace
+ {
+ UNKNOWN,
+ GRAYSCALE,
+ RGB,
+ YCbCr,
+ CMYK,
+ YCCK
+ }
+
+ public ErrorManager std_error (out ErrorManager err);
+
+ [CCode (cname = "struct jpeg_compress_struct", cprefix = "jpeg_", destroy_function = "jpeg_destroy_compress")]
+ public struct Compress
+ {
+ public DestinationManager* dest;
+ public int image_width;
+ public int image_height;
+ public int input_components;
+ public ColorSpace in_color_space;
+ public ErrorManager* err;
+
+ public void create_compress ();
+ public void set_defaults ();
+ public void start_compress (bool write_all_tables);
+ public void write_scanlines ([CCode (array_length = false)] uint8*[] scanlines, int num_Lines);
+ public void finish_compress ();
+ }
+
+ [CCode (cname = "struct jpeg_error_mgr")]
+ public struct ErrorManager
+ {
+ [CCode (cname = "jpeg_std_error")]
+ public ErrorManager* std_error ();
+ }
+
+ [CCode (has_target = false)]
+ public delegate void InitDestinationFunc (Compress cinfo);
+ [CCode (has_target = false)]
+ public delegate bool EmptyOutputBufferFunc (Compress cinfo);
+ [CCode (has_target = false)]
+ public delegate void TermDestinationFunc (Compress cinfo);
+
+ [CCode (cname = "struct jpeg_destination_mgr")]
+ public struct DestinationManager
+ {
+ [CCode (array_length = false)]
+ public unowned uint8[] next_output_byte;
+ public int free_in_buffer;
+ public InitDestinationFunc init_destination;
+ public EmptyOutputBufferFunc empty_output_buffer;
+ public TermDestinationFunc term_destination;
+ }
+}
diff --git a/src/page-view.c b/src/page-view.c
index eae49e6..5f916e7 100644
--- a/src/page-view.c
+++ b/src/page-view.c
@@ -1,7 +1,10 @@
+/* page-view.c generated by valac 0.13.1, the Vala compiler
+ * generated from page-view.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,1251 +12,2080 @@
* license.
*/
+#include <glib.h>
+#include <glib-object.h>
+#include <gdk-pixbuf/gdk-pixdata.h>
+#include <float.h>
#include <math.h>
+#include <gdk/gdk.h>
+#include <string.h>
+#include <stdlib.h>
+#include <cairo.h>
+#include <gobject/gvaluecollector.h>
+
+
+#define TYPE_CROP_LOCATION (crop_location_get_type ())
+
+#define TYPE_PAGE_VIEW (page_view_get_type ())
+#define PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE_VIEW, PageView))
+#define PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE_VIEW, PageViewClass))
+#define IS_PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE_VIEW))
+#define IS_PAGE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE_VIEW))
+#define PAGE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE_VIEW, PageViewClass))
+
+typedef struct _PageView PageView;
+typedef struct _PageViewClass PageViewClass;
+typedef struct _PageViewPrivate PageViewPrivate;
+
+#define TYPE_PAGE (page_get_type ())
+#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page))
+#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass))
+#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE))
+#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE))
+#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass))
+
+typedef struct _Page Page;
+typedef struct _PageClass PageClass;
+
+#define TYPE_SCAN_DIRECTION (scan_direction_get_type ())
+#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL)))
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+typedef struct _ParamSpecPageView ParamSpecPageView;
+
+typedef enum {
+ CROP_LOCATION_NONE = 0,
+ CROP_LOCATION_MIDDLE,
+ CROP_LOCATION_TOP,
+ CROP_LOCATION_BOTTOM,
+ CROP_LOCATION_LEFT,
+ CROP_LOCATION_RIGHT,
+ CROP_LOCATION_TOP_LEFT,
+ CROP_LOCATION_TOP_RIGHT,
+ CROP_LOCATION_BOTTOM_LEFT,
+ CROP_LOCATION_BOTTOM_RIGHT
+} CropLocation;
+
+struct _PageView {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ PageViewPrivate * priv;
+};
-#include "page-view.h"
+struct _PageViewClass {
+ GTypeClass parent_class;
+ void (*finalize) (PageView *self);
+};
-enum {
- CHANGED,
- SIZE_CHANGED,
- LAST_SIGNAL
+typedef enum {
+ SCAN_DIRECTION_TOP_TO_BOTTOM,
+ SCAN_DIRECTION_LEFT_TO_RIGHT,
+ SCAN_DIRECTION_BOTTOM_TO_TOP,
+ SCAN_DIRECTION_RIGHT_TO_LEFT
+} ScanDirection;
+
+struct _PageViewPrivate {
+ Page* page;
+ GdkPixbuf* image;
+ gboolean selected;
+ gint border_width;
+ gboolean update_image;
+ ScanDirection scan_direction;
+ gint scan_line;
+ gint width;
+ gint height;
+ gint x_offset;
+ gint y_offset;
+ CropLocation crop_location;
+ gdouble selected_crop_px;
+ gdouble selected_crop_py;
+ gint selected_crop_x;
+ gint selected_crop_y;
+ gint selected_crop_w;
+ gint selected_crop_h;
+ GdkCursorType cursor;
+ gint animate_n_segments;
+ gint animate_segment;
+ guint animate_timeout;
};
-static guint signals[LAST_SIGNAL] = { 0, };
-enum {
- PROP_0,
- PROP_PAGE
+struct _ParamSpecPageView {
+ GParamSpec parent_instance;
};
-typedef enum
-{
- CROP_NONE = 0,
- CROP_MIDDLE,
- CROP_TOP,
- CROP_BOTTOM,
- CROP_LEFT,
- CROP_RIGHT,
- CROP_TOP_LEFT,
- CROP_TOP_RIGHT,
- CROP_BOTTOM_LEFT,
- CROP_BOTTOM_RIGHT
-} CropLocation;
-struct PageViewPrivate
-{
- /* Page being rendered */
- Page *page;
-
- /* Image to render at current resolution */
- GdkPixbuf *image;
-
- /* Border around image */
- gboolean selected;
- gint border_width;
-
- /* True if image needs to be regenerated */
- gboolean update_image;
-
- /* Direction of currently scanned image */
- ScanDirection scan_direction;
-
- /* Next scan line to render */
- gint scan_line;
-
- /* Dimensions of image to generate */
- gint width, height;
-
- /* Location to place this page */
- gint x, y;
-
- CropLocation crop_location;
- gdouble selected_crop_px, selected_crop_py;
- gint selected_crop_x, selected_crop_y;
- gint selected_crop_w, selected_crop_h;
-
- /* Cursor over this page */
- gint cursor;
-
- gint animate_n_segments, animate_segment;
- guint animate_timeout;
+static gpointer page_view_parent_class = NULL;
+
+GType crop_location_get_type (void) G_GNUC_CONST;
+gpointer page_view_ref (gpointer instance);
+void page_view_unref (gpointer instance);
+GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_page_view (GValue* value, gpointer v_object);
+void value_take_page_view (GValue* value, gpointer v_object);
+gpointer value_get_page_view (const GValue* value);
+GType page_view_get_type (void) G_GNUC_CONST;
+gpointer page_ref (gpointer instance);
+void page_unref (gpointer instance);
+GParamSpec* param_spec_page (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_page (GValue* value, gpointer v_object);
+void value_take_page (GValue* value, gpointer v_object);
+gpointer value_get_page (const GValue* value);
+GType page_get_type (void) G_GNUC_CONST;
+GType scan_direction_get_type (void) G_GNUC_CONST;
+#define PAGE_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PAGE_VIEW, PageViewPrivate))
+enum {
+ PAGE_VIEW_DUMMY_PROPERTY
};
+PageView* page_view_new (Page* page);
+PageView* page_view_construct (GType object_type, Page* page);
+static void page_view_page_pixels_changed_cb (PageView* self, Page* p);
+static void _page_view_page_pixels_changed_cb_page_pixels_changed (Page* _sender, gpointer self);
+static void page_view_page_size_changed_cb (PageView* self, Page* p);
+static void _page_view_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self);
+static void page_view_page_overlay_changed_cb (PageView* self, Page* p);
+static void _page_view_page_overlay_changed_cb_page_crop_changed (Page* _sender, gpointer self);
+static void _page_view_page_overlay_changed_cb_page_scan_line_changed (Page* _sender, gpointer self);
+static void page_view_scan_direction_changed_cb (PageView* self, Page* p);
+static void _page_view_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self);
+Page* page_view_get_page (PageView* self);
+void page_view_set_selected (PageView* self, gboolean selected);
+gboolean page_view_get_selected (PageView* self);
+void page_view_set_x_offset (PageView* self, gint offset);
+void page_view_set_y_offset (PageView* self, gint offset);
+gint page_view_get_x_offset (PageView* self);
+gint page_view_get_y_offset (PageView* self);
+static guchar page_view_get_sample (PageView* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint sample);
+static void page_view_get_pixel (PageView* self, Page* page, gint x, gint y, guchar* pixel, int pixel_length1);
+ScanDirection page_get_scan_direction (Page* self);
+gint page_get_scan_width (Page* self);
+gint page_get_scan_height (Page* self);
+gint page_get_depth (Page* self);
+gint page_get_n_channels (Page* self);
+guchar* page_get_pixels (Page* self, int* result_length1);
+gint page_get_rowstride (Page* self);
+static void page_view_set_pixel (PageView* self, Page* page, gdouble l, gdouble r, gdouble t, gdouble b, guchar* output, int output_length1, gint offset);
+static void page_view_update_preview (PageView* self, Page* page, GdkPixbuf** output_image, gint output_width, gint output_height, ScanDirection scan_direction, gint old_scan_line, gint scan_line);
+gint page_get_width (Page* self);
+gint page_get_height (Page* self);
+gboolean page_has_data (Page* self);
+static gint page_view_get_preview_width (PageView* self);
+static gint page_view_get_preview_height (PageView* self);
+static void page_view_update_page_view (PageView* self);
+gint page_get_scan_line (Page* self);
+static gint page_view_page_to_screen_x (PageView* self, gint x);
+static gint page_view_page_to_screen_y (PageView* self, gint y);
+static gint page_view_screen_to_page_x (PageView* self, gint x);
+static gint page_view_screen_to_page_y (PageView* self, gint y);
+static CropLocation page_view_get_crop_location (PageView* self, gint x, gint y);
+gboolean page_has_crop (Page* self);
+void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height);
+gchar* page_get_named_crop (Page* self);
+void page_view_button_press (PageView* self, gint x, gint y);
+void page_view_motion (PageView* self, gint x, gint y);
+void page_move_crop (Page* self, gint x, gint y);
+void page_set_custom_crop (Page* self, gint width, gint height);
+void page_view_button_release (PageView* self, gint x, gint y);
+GdkCursorType page_view_get_cursor (PageView* self);
+static gboolean page_view_animation_cb (PageView* self);
+static void page_view_update_animation (PageView* self);
+gboolean page_is_scanning (Page* self);
+static gboolean _page_view_animation_cb_gsource_func (gpointer self);
+void page_view_render (PageView* self, cairo_t* context);
+void page_view_set_width (PageView* self, gint width);
+void page_view_set_height (PageView* self, gint height);
+gint page_view_get_width (PageView* self);
+gint page_view_get_height (PageView* self);
+static void page_view_finalize (PageView* obj);
+
+
+GType crop_location_get_type (void) {
+ static volatile gsize crop_location_type_id__volatile = 0;
+ if (g_once_init_enter (&crop_location_type_id__volatile)) {
+ static const GEnumValue values[] = {{CROP_LOCATION_NONE, "CROP_LOCATION_NONE", "none"}, {CROP_LOCATION_MIDDLE, "CROP_LOCATION_MIDDLE", "middle"}, {CROP_LOCATION_TOP, "CROP_LOCATION_TOP", "top"}, {CROP_LOCATION_BOTTOM, "CROP_LOCATION_BOTTOM", "bottom"}, {CROP_LOCATION_LEFT, "CROP_LOCATION_LEFT", "left"}, {CROP_LOCATION_RIGHT, "CROP_LOCATION_RIGHT", "right"}, {CROP_LOCATION_TOP_LEFT, "CROP_LOCATION_TOP_LEFT", "top-left"}, {CROP_LOCATION_TOP_RIGHT, "CROP_LOCATION_TOP_RIGHT", "top-right"}, {CROP_LOCATION_BOTTOM_LEFT, "CROP_LOCATION_BOTTOM_LEFT", "bottom-left"}, {CROP_LOCATION_BOTTOM_RIGHT, "CROP_LOCATION_BOTTOM_RIGHT", "bottom-right"}, {0, NULL, NULL}};
+ GType crop_location_type_id;
+ crop_location_type_id = g_enum_register_static ("CropLocation", values);
+ g_once_init_leave (&crop_location_type_id__volatile, crop_location_type_id);
+ }
+ return crop_location_type_id__volatile;
+}
+
+
+static gpointer _page_ref0 (gpointer self) {
+ return self ? page_ref (self) : NULL;
+}
+
+
+static void _page_view_page_pixels_changed_cb_page_pixels_changed (Page* _sender, gpointer self) {
+ page_view_page_pixels_changed_cb (self, _sender);
+}
+
+
+static void _page_view_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self) {
+ page_view_page_size_changed_cb (self, _sender);
+}
+
+
+static void _page_view_page_overlay_changed_cb_page_crop_changed (Page* _sender, gpointer self) {
+ page_view_page_overlay_changed_cb (self, _sender);
+}
+
+
+static void _page_view_page_overlay_changed_cb_page_scan_line_changed (Page* _sender, gpointer self) {
+ page_view_page_overlay_changed_cb (self, _sender);
+}
+
+
+static void _page_view_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self) {
+ page_view_scan_direction_changed_cb (self, _sender);
+}
+
+
+PageView* page_view_construct (GType object_type, Page* page) {
+ PageView* self = NULL;
+ Page* _tmp0_;
+ g_return_val_if_fail (page != NULL, NULL);
+ self = (PageView*) g_type_create_instance (object_type);
+ _tmp0_ = _page_ref0 (page);
+ _page_unref0 (self->priv->page);
+ self->priv->page = _tmp0_;
+ g_signal_connect (page, "pixels-changed", (GCallback) _page_view_page_pixels_changed_cb_page_pixels_changed, self);
+ g_signal_connect (page, "size-changed", (GCallback) _page_view_page_size_changed_cb_page_size_changed, self);
+ g_signal_connect (page, "crop-changed", (GCallback) _page_view_page_overlay_changed_cb_page_crop_changed, self);
+ g_signal_connect (page, "scan-line-changed", (GCallback) _page_view_page_overlay_changed_cb_page_scan_line_changed, self);
+ g_signal_connect (page, "scan-direction-changed", (GCallback) _page_view_scan_direction_changed_cb_page_scan_direction_changed, self);
+ return self;
+}
+
+
+PageView* page_view_new (Page* page) {
+ return page_view_construct (TYPE_PAGE_VIEW, page);
+}
+
-G_DEFINE_TYPE (PageView, page_view, G_TYPE_OBJECT);
+Page* page_view_get_page (PageView* self) {
+ Page* result = NULL;
+ Page* _tmp0_;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = _page_ref0 (self->priv->page);
+ result = _tmp0_;
+ return result;
+}
-PageView *
-page_view_new (Page *page)
-{
- return g_object_new (PAGE_VIEW_TYPE, "page", page, NULL);
+void page_view_set_selected (PageView* self, gboolean selected) {
+ gboolean _tmp0_ = FALSE;
+ gboolean _tmp1_ = FALSE;
+ g_return_if_fail (self != NULL);
+ if (self->priv->selected) {
+ _tmp1_ = selected;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ _tmp0_ = TRUE;
+ } else {
+ gboolean _tmp2_ = FALSE;
+ if (!self->priv->selected) {
+ _tmp2_ = !selected;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ _tmp0_ = _tmp2_;
+ }
+ if (_tmp0_) {
+ return;
+ }
+ self->priv->selected = selected;
+ g_signal_emit_by_name (self, "changed");
}
-Page *
-page_view_get_page (PageView *view)
-{
- g_return_val_if_fail (view != NULL, NULL);
- return view->priv->page;
+gboolean page_view_get_selected (PageView* self) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ result = self->priv->selected;
+ return result;
}
-void
-page_view_set_selected (PageView *view, gboolean selected)
-{
- g_return_if_fail (view != NULL);
- if ((view->priv->selected && selected) || (!view->priv->selected && !selected))
- return;
- view->priv->selected = selected;
- g_signal_emit (view, signals[CHANGED], 0);
+void page_view_set_x_offset (PageView* self, gint offset) {
+ g_return_if_fail (self != NULL);
+ self->priv->x_offset = offset;
}
-gboolean
-page_view_get_selected (PageView *view)
-{
- g_return_val_if_fail (view != NULL, FALSE);
- return view->priv->selected;
+void page_view_set_y_offset (PageView* self, gint offset) {
+ g_return_if_fail (self != NULL);
+ self->priv->y_offset = offset;
}
-void
-page_view_set_x_offset (PageView *view, gint offset)
-{
- g_return_if_fail (view != NULL);
- view->priv->x = offset;
+gint page_view_get_x_offset (PageView* self) {
+ gint result = 0;
+ g_return_val_if_fail (self != NULL, 0);
+ result = self->priv->x_offset;
+ return result;
}
-void
-page_view_set_y_offset (PageView *view, gint offset)
-{
- g_return_if_fail (view != NULL);
- view->priv->y = offset;
+gint page_view_get_y_offset (PageView* self) {
+ gint result = 0;
+ g_return_val_if_fail (self != NULL, 0);
+ result = self->priv->y_offset;
+ return result;
}
-gint
-page_view_get_x_offset (PageView *view)
-{
- g_return_val_if_fail (view != NULL, 0);
- return view->priv->x;
+static guchar page_view_get_sample (PageView* self, guchar* pixels, int pixels_length1, gint offset, gint x, gint depth, gint sample) {
+ guchar result = '\0';
+ g_return_val_if_fail (self != NULL, '\0');
+ result = (guchar) 0xFF;
+ return result;
}
-gint
-page_view_get_y_offset (PageView *view)
-{
- g_return_val_if_fail (view != NULL, 0);
- return view->priv->y;
+static void page_view_get_pixel (PageView* self, Page* page, gint x, gint y, guchar* pixel, int pixel_length1) {
+ ScanDirection _tmp0_;
+ gint _tmp5_;
+ gint depth;
+ gint _tmp6_;
+ gint n_channels;
+ gint _tmp7_;
+ guchar* _tmp8_ = NULL;
+ guchar* pixels;
+ gint pixels_length1;
+ gint _pixels_size_;
+ gint _tmp9_;
+ gint offset;
+ gboolean _tmp10_ = FALSE;
+ guchar _tmp16_;
+ guchar _tmp17_;
+ guchar _tmp18_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = page_get_scan_direction (page);
+ switch (_tmp0_) {
+ case SCAN_DIRECTION_TOP_TO_BOTTOM:
+ {
+ break;
+ }
+ case SCAN_DIRECTION_BOTTOM_TO_TOP:
+ {
+ gint _tmp1_;
+ gint _tmp2_;
+ _tmp1_ = page_get_scan_width (page);
+ x = (_tmp1_ - x) - 1;
+ _tmp2_ = page_get_scan_height (page);
+ y = (_tmp2_ - y) - 1;
+ break;
+ }
+ case SCAN_DIRECTION_LEFT_TO_RIGHT:
+ {
+ gint t;
+ gint _tmp3_;
+ t = x;
+ _tmp3_ = page_get_scan_width (page);
+ x = (_tmp3_ - y) - 1;
+ y = t;
+ break;
+ }
+ case SCAN_DIRECTION_RIGHT_TO_LEFT:
+ {
+ gint t;
+ gint _tmp4_;
+ t = x;
+ x = y;
+ _tmp4_ = page_get_scan_height (page);
+ y = (_tmp4_ - t) - 1;
+ break;
+ }
+ default:
+ break;
+ }
+ _tmp5_ = page_get_depth (page);
+ depth = _tmp5_;
+ _tmp6_ = page_get_n_channels (page);
+ n_channels = _tmp6_;
+ _tmp8_ = page_get_pixels (page, &_tmp7_);
+ pixels = _tmp8_;
+ pixels_length1 = _tmp7_;
+ _pixels_size_ = pixels_length1;
+ _tmp9_ = page_get_rowstride (page);
+ offset = _tmp9_ * y;
+ if (depth == 8) {
+ _tmp10_ = n_channels == 3;
+ } else {
+ _tmp10_ = FALSE;
+ }
+ if (_tmp10_) {
+ gint o;
+ o = offset + (x * n_channels);
+ pixel[0] = pixels[o];
+ pixel[1] = pixels[o + 1];
+ pixel[2] = pixels[o + 2];
+ return;
+ } else {
+ gboolean _tmp11_ = FALSE;
+ if (depth == 8) {
+ _tmp11_ = n_channels == 1;
+ } else {
+ _tmp11_ = FALSE;
+ }
+ if (_tmp11_) {
+ pixel[2] = pixels[offset + x];
+ pixel[1] = pixel[2];
+ pixel[0] = pixel[1];
+ return;
+ } else {
+ gboolean _tmp12_ = FALSE;
+ if (depth == 1) {
+ _tmp12_ = n_channels == 1;
+ } else {
+ _tmp12_ = FALSE;
+ }
+ if (_tmp12_) {
+ gint o;
+ gint _tmp13_ = 0;
+ o = offset + (x / 8);
+ if (((gint) (pixels[o] & (0x80 >> (x % 8)))) != 0) {
+ _tmp13_ = 0x00;
+ } else {
+ _tmp13_ = 0xFF;
+ }
+ pixel[2] = (guchar) _tmp13_;
+ pixel[1] = pixel[2];
+ pixel[0] = pixel[1];
+ return;
+ } else {
+ gboolean _tmp14_ = FALSE;
+ if (depth == 2) {
+ _tmp14_ = n_channels == 1;
+ } else {
+ _tmp14_ = FALSE;
+ }
+ if (_tmp14_) {
+ gint _tmp15_[4] = {0};
+ gint block_shift[4];
+ gint o;
+ gint sample;
+ _tmp15_[0] = 6;
+ _tmp15_[1] = 4;
+ _tmp15_[2] = 2;
+ _tmp15_[3] = 0;
+ memcpy (block_shift, _tmp15_, 4 * sizeof (gint));
+ o = offset + (x / 4);
+ sample = (pixels[o] >> block_shift[x % 4]) & 0x3;
+ sample = (sample * 255) / 3;
+ pixel[2] = (guchar) sample;
+ pixel[1] = pixel[2];
+ pixel[0] = pixel[1];
+ return;
+ }
+ }
+ }
+ }
+ _tmp16_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, x * n_channels);
+ pixel[0] = _tmp16_;
+ _tmp17_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, (x * n_channels) + 1);
+ pixel[1] = _tmp17_;
+ _tmp18_ = page_view_get_sample (self, pixels, pixels_length1, offset, x, depth, (x * n_channels) + 2);
+ pixel[2] = _tmp18_;
}
-static guchar
-get_sample (const guchar *line, gint x, gint depth, gint sample)
-{
- // FIXME
- return 0xFF;
+static void page_view_set_pixel (PageView* self, Page* page, gdouble l, gdouble r, gdouble t, gdouble b, guchar* output, int output_length1, gint offset) {
+ gint L;
+ gint R;
+ gint T;
+ gint B;
+ gdouble red;
+ gdouble green;
+ gdouble blue;
+ gboolean _tmp0_ = FALSE;
+ gboolean _tmp1_ = FALSE;
+ gboolean _tmp10_ = FALSE;
+ gboolean _tmp11_ = FALSE;
+ gboolean _tmp12_ = FALSE;
+ gboolean _tmp13_ = FALSE;
+ gdouble scale;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ L = (gint) l;
+ if (((gdouble) L) != l) {
+ L++;
+ }
+ R = (gint) r;
+ T = (gint) t;
+ if (((gdouble) T) != t) {
+ T++;
+ }
+ B = (gint) b;
+ red = 0.0;
+ green = 0.0;
+ blue = 0.0;
+ if ((r - l) <= 1.0) {
+ _tmp1_ = ((gint) r) == ((gint) l);
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ _tmp0_ = TRUE;
+ } else {
+ gboolean _tmp2_ = FALSE;
+ if ((b - t) <= 1.0) {
+ _tmp2_ = ((gint) b) == ((gint) t);
+ } else {
+ _tmp2_ = FALSE;
+ }
+ _tmp0_ = _tmp2_;
+ }
+ if (_tmp0_) {
+ gboolean _tmp3_ = FALSE;
+ gdouble scale;
+ if (((gint) l) == ((gint) r)) {
+ _tmp3_ = TRUE;
+ } else {
+ _tmp3_ = ((gint) t) == ((gint) b);
+ }
+ if (_tmp3_) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, (gint) l, (gint) t, p, 3);
+ output[offset] = p[0];
+ output[offset + 1] = p[1];
+ output[offset + 2] = p[2];
+ return;
+ }
+ if (L > R) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, R, T - 1, p, 3);
+ red = red + ((p[0] * (r - l)) * (T - t));
+ green = green + ((p[1] * (r - l)) * (T - t));
+ blue = blue + ((p[2] * (r - l)) * (T - t));
+ {
+ gint y;
+ y = T;
+ {
+ gboolean _tmp4_;
+ _tmp4_ = TRUE;
+ while (TRUE) {
+ if (!_tmp4_) {
+ y++;
+ }
+ _tmp4_ = FALSE;
+ if (!(y < B)) {
+ break;
+ }
+ page_view_get_pixel (self, page, R, y, p, 3);
+ red = red + (p[0] * (r - l));
+ green = green + (p[1] * (r - l));
+ blue = blue + (p[2] * (r - l));
+ }
+ }
+ }
+ page_view_get_pixel (self, page, R, B, p, 3);
+ red = red + ((p[0] * (r - l)) * (b - B));
+ green = green + ((p[1] * (r - l)) * (b - B));
+ blue = blue + ((p[2] * (r - l)) * (b - B));
+ } else {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, L - 1, B, p, 3);
+ red = red + ((p[0] * (b - t)) * (L - l));
+ green = green + ((p[1] * (b - t)) * (L - l));
+ blue = blue + ((p[2] * (b - t)) * (L - l));
+ {
+ gint x;
+ x = L;
+ {
+ gboolean _tmp5_;
+ _tmp5_ = TRUE;
+ while (TRUE) {
+ if (!_tmp5_) {
+ x++;
+ }
+ _tmp5_ = FALSE;
+ if (!(x < R)) {
+ break;
+ }
+ page_view_get_pixel (self, page, x, B, p, 3);
+ red = red + (p[0] * (b - t));
+ green = green + (p[1] * (b - t));
+ blue = blue + (p[2] * (b - t));
+ }
+ }
+ }
+ page_view_get_pixel (self, page, R, B, p, 3);
+ red = red + ((p[0] * (b - t)) * (r - R));
+ green = green + ((p[1] * (b - t)) * (r - R));
+ blue = blue + ((p[2] * (b - t)) * (r - R));
+ }
+ scale = 1.0 / ((r - l) * (b - t));
+ output[offset] = (guchar) ((red * scale) + 0.5);
+ output[offset + 1] = (guchar) ((green * scale) + 0.5);
+ output[offset + 2] = (guchar) ((blue * scale) + 0.5);
+ return;
+ }
+ {
+ gint x;
+ x = L;
+ {
+ gboolean _tmp6_;
+ _tmp6_ = TRUE;
+ while (TRUE) {
+ if (!_tmp6_) {
+ x++;
+ }
+ _tmp6_ = FALSE;
+ if (!(x < R)) {
+ break;
+ }
+ {
+ gint y;
+ y = T;
+ {
+ gboolean _tmp7_;
+ _tmp7_ = TRUE;
+ while (TRUE) {
+ guchar p[3] = {0};
+ if (!_tmp7_) {
+ y++;
+ }
+ _tmp7_ = FALSE;
+ if (!(y < B)) {
+ break;
+ }
+ page_view_get_pixel (self, page, x, y, p, 3);
+ red = red + p[0];
+ green = green + p[1];
+ blue = blue + p[2];
+ }
+ }
+ }
+ }
+ }
+ }
+ {
+ gint x;
+ x = L;
+ {
+ gboolean _tmp8_;
+ _tmp8_ = TRUE;
+ while (TRUE) {
+ if (!_tmp8_) {
+ x++;
+ }
+ _tmp8_ = FALSE;
+ if (!(x < R)) {
+ break;
+ }
+ if (t != ((gdouble) T)) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, x, T - 1, p, 3);
+ red = red + (p[0] * (T - t));
+ green = green + (p[1] * (T - t));
+ blue = blue + (p[2] * (T - t));
+ }
+ if (b != ((gdouble) B)) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, x, B, p, 3);
+ red = red + (p[0] * (b - B));
+ green = green + (p[1] * (b - B));
+ blue = blue + (p[2] * (b - B));
+ }
+ }
+ }
+ }
+ {
+ gint y;
+ y = T;
+ {
+ gboolean _tmp9_;
+ _tmp9_ = TRUE;
+ while (TRUE) {
+ if (!_tmp9_) {
+ y++;
+ }
+ _tmp9_ = FALSE;
+ if (!(y < B)) {
+ break;
+ }
+ if (l != ((gdouble) L)) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, L - 1, y, p, 3);
+ red = red + (p[0] * (L - l));
+ green = green + (p[1] * (L - l));
+ blue = blue + (p[2] * (L - l));
+ }
+ if (r != ((gdouble) R)) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, R, y, p, 3);
+ red = red + (p[0] * (r - R));
+ green = green + (p[1] * (r - R));
+ blue = blue + (p[2] * (r - R));
+ }
+ }
+ }
+ }
+ if (l != ((gdouble) L)) {
+ _tmp10_ = t != ((gdouble) T);
+ } else {
+ _tmp10_ = FALSE;
+ }
+ if (_tmp10_) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, L - 1, T - 1, p, 3);
+ red = red + ((p[0] * (L - l)) * (T - t));
+ green = green + ((p[1] * (L - l)) * (T - t));
+ blue = blue + ((p[2] * (L - l)) * (T - t));
+ }
+ if (r != ((gdouble) R)) {
+ _tmp11_ = t != ((gdouble) T);
+ } else {
+ _tmp11_ = FALSE;
+ }
+ if (_tmp11_) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, R, T - 1, p, 3);
+ red = red + ((p[0] * (r - R)) * (T - t));
+ green = green + ((p[1] * (r - R)) * (T - t));
+ blue = blue + ((p[2] * (r - R)) * (T - t));
+ }
+ if (r != ((gdouble) R)) {
+ _tmp12_ = b != ((gdouble) B);
+ } else {
+ _tmp12_ = FALSE;
+ }
+ if (_tmp12_) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, R, B, p, 3);
+ red = red + ((p[0] * (r - R)) * (b - B));
+ green = green + ((p[1] * (r - R)) * (b - B));
+ blue = blue + ((p[2] * (r - R)) * (b - B));
+ }
+ if (l != ((gdouble) L)) {
+ _tmp13_ = b != ((gdouble) B);
+ } else {
+ _tmp13_ = FALSE;
+ }
+ if (_tmp13_) {
+ guchar p[3] = {0};
+ page_view_get_pixel (self, page, L - 1, B, p, 3);
+ red = red + ((p[0] * (L - l)) * (b - B));
+ green = green + ((p[1] * (L - l)) * (b - B));
+ blue = blue + ((p[2] * (L - l)) * (b - B));
+ }
+ scale = 1.0 / ((r - l) * (b - t));
+ output[offset] = (guchar) ((red * scale) + 0.5);
+ output[offset + 1] = (guchar) ((green * scale) + 0.5);
+ output[offset + 2] = (guchar) ((blue * scale) + 0.5);
}
-static void
-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, x * n_channels);
- pixel[0] = get_sample (line, x, depth, x * n_channels + 1);
- pixel[0] = get_sample (line, x, depth, x * n_channels + 2);
+static void page_view_update_preview (PageView* self, Page* page, GdkPixbuf** output_image, gint output_width, gint output_height, ScanDirection scan_direction, gint old_scan_line, gint scan_line) {
+ gint _tmp0_;
+ gint input_width;
+ gint _tmp1_;
+ gint input_height;
+ gint L = 0;
+ gint R = 0;
+ gint T = 0;
+ gint B = 0;
+ gboolean _tmp2_ = FALSE;
+ gboolean _tmp3_ = FALSE;
+ guint8* _tmp7_ = NULL;
+ guchar* output;
+ gint output_length1;
+ gint _output_size_;
+ gint _tmp8_;
+ gint output_rowstride;
+ gint _tmp9_;
+ gint output_n_channels;
+ gboolean _tmp10_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = page_get_width (page);
+ input_width = _tmp0_;
+ _tmp1_ = page_get_height (page);
+ input_height = _tmp1_;
+ if ((*output_image) == NULL) {
+ _tmp3_ = TRUE;
+ } else {
+ gint _tmp4_;
+ _tmp4_ = gdk_pixbuf_get_width (*output_image);
+ _tmp3_ = _tmp4_ != output_width;
+ }
+ if (_tmp3_) {
+ _tmp2_ = TRUE;
+ } else {
+ gint _tmp5_;
+ _tmp5_ = gdk_pixbuf_get_height (*output_image);
+ _tmp2_ = _tmp5_ != output_height;
+ }
+ if (_tmp2_) {
+ GdkPixbuf* _tmp6_ = NULL;
+ _tmp6_ = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, output_width, output_height);
+ _g_object_unref0 (*output_image);
+ *output_image = _tmp6_;
+ L = 0;
+ R = output_width - 1;
+ T = 0;
+ B = output_height - 1;
+ } else {
+ switch (scan_direction) {
+ case SCAN_DIRECTION_TOP_TO_BOTTOM:
+ {
+ L = 0;
+ R = output_width - 1;
+ T = (gint) ((((gdouble) old_scan_line) * output_height) / input_height);
+ B = (gint) (((((gdouble) scan_line) * output_height) / input_height) + 0.5);
+ break;
+ }
+ case SCAN_DIRECTION_LEFT_TO_RIGHT:
+ {
+ L = (gint) ((((gdouble) old_scan_line) * output_width) / input_width);
+ R = (gint) (((((gdouble) scan_line) * output_width) / input_width) + 0.5);
+ T = 0;
+ B = output_height - 1;
+ break;
+ }
+ case SCAN_DIRECTION_BOTTOM_TO_TOP:
+ {
+ L = 0;
+ R = output_width - 1;
+ T = (gint) ((((gdouble) (input_height - scan_line)) * output_height) / input_height);
+ B = (gint) (((((gdouble) (input_height - old_scan_line)) * output_height) / input_height) + 0.5);
+ break;
+ }
+ case SCAN_DIRECTION_RIGHT_TO_LEFT:
+ {
+ L = (gint) ((((gdouble) (input_width - scan_line)) * output_width) / input_width);
+ R = (gint) (((((gdouble) (input_width - old_scan_line)) * output_width) / input_width) + 0.5);
+ T = 0;
+ B = output_height - 1;
+ break;
+ }
+ default:
+ {
+ T = 0;
+ B = T;
+ R = B;
+ L = R;
+ break;
+ }
+ }
+ }
+ if (R >= output_width) {
+ R = output_width - 1;
+ }
+ if (B >= output_height) {
+ B = output_height - 1;
+ }
+ g_return_if_fail (L >= 0);
+ g_return_if_fail (R < output_width);
+ g_return_if_fail (T >= 0);
+ g_return_if_fail (B < output_height);
+ g_return_if_fail ((*output_image) != NULL);
+ _tmp7_ = gdk_pixbuf_get_pixels (*output_image);
+ output = _tmp7_;
+ output_length1 = -1;
+ _output_size_ = output_length1;
+ _tmp8_ = gdk_pixbuf_get_rowstride (*output_image);
+ output_rowstride = _tmp8_;
+ _tmp9_ = gdk_pixbuf_get_n_channels (*output_image);
+ output_n_channels = _tmp9_;
+ _tmp10_ = page_has_data (page);
+ if (!_tmp10_) {
+ {
+ gint x;
+ x = L;
+ {
+ gboolean _tmp11_;
+ _tmp11_ = TRUE;
+ while (TRUE) {
+ if (!_tmp11_) {
+ x++;
+ }
+ _tmp11_ = FALSE;
+ if (!(x <= R)) {
+ break;
+ }
+ {
+ gint y;
+ y = T;
+ {
+ gboolean _tmp12_;
+ _tmp12_ = TRUE;
+ while (TRUE) {
+ gint o;
+ if (!_tmp12_) {
+ y++;
+ }
+ _tmp12_ = FALSE;
+ if (!(y <= B)) {
+ break;
+ }
+ o = (output_rowstride * y) + (x * output_n_channels);
+ output[o + 2] = (guchar) 0xFF;
+ output[o + 1] = output[o + 2];
+ output[o] = output[o + 1];
+ }
+ }
+ }
+ }
+ }
+ }
+ return;
+ }
+ {
+ gint x;
+ x = L;
+ {
+ gboolean _tmp13_;
+ _tmp13_ = TRUE;
+ while (TRUE) {
+ gdouble l;
+ gdouble r;
+ if (!_tmp13_) {
+ x++;
+ }
+ _tmp13_ = FALSE;
+ if (!(x <= R)) {
+ break;
+ }
+ l = (((gdouble) x) * input_width) / output_width;
+ r = (((gdouble) (x + 1)) * input_width) / output_width;
+ {
+ gint y;
+ y = T;
+ {
+ gboolean _tmp14_;
+ _tmp14_ = TRUE;
+ while (TRUE) {
+ gdouble t;
+ gdouble b;
+ if (!_tmp14_) {
+ y++;
+ }
+ _tmp14_ = FALSE;
+ if (!(y <= B)) {
+ break;
+ }
+ t = (((gdouble) y) * input_height) / output_height;
+ b = (((gdouble) (y + 1)) * input_height) / output_height;
+ page_view_set_pixel (self, page, l, r, t, b, output, output_length1, (output_rowstride * y) + (x * output_n_channels));
+ }
+ }
+ }
+ }
+ }
+ }
}
-static void
-set_pixel (Page *page,
- double l, double r, double t, double b, guchar *pixel)
-{
- gint x, y;
- gint L, R, T, B;
- guchar p[3];
- double scale, red, green, blue;
-
- /* Decimation:
- *
- * Target pixel is defined by (t,l)-(b,r)
- * It touches 16 pixels in original image
- * It completely covers 4 pixels in original image (T,L)-(B,R)
- * Add covered pixels and add weighted partially covered pixels.
- * Divide by total area.
- *
- * l L R r
- * +-----+-----+-----+-----+
- * | | | | |
- * t | +--+-----+-----+---+ |
- * T +--+--+-----+-----+---+-+
- * | | | | | | |
- * | | | | | | |
- * +--+--+-----+-----+---+-+
- * | | | | | | |
- * | | | | | | |
- * B +--+--+-----+-----+---+-+
- * | | | | | | |
- * b | +--+-----+-----+---+ |
- * +-----+-----+-----+-----+
- *
- *
- * Interpolation:
- *
- * l r
- * +-----+-----+-----+-----+
- * | | | | |
- * | | | | |
- * +-----+-----+-----+-----+
- * t | | +-+--+ | |
- * | | | | | | |
- * +-----+---+-+--+--+-----+
- * b | | +-+--+ | |
- * | | | | |
- * +-----+-----+-----+-----+
- * | | | | |
- * | | | | |
- * +-----+-----+-----+-----+
- *
- * Same again, just no completely covered pixels.
- */
-
- L = l;
- if (L != l)
- L++;
- R = r;
- T = t;
- if (T != t)
- T++;
- B = b;
-
- red = green = blue = 0.0;
-
- /* Target can fit inside one source pixel
- * +-----+
- * | |
- * | +--+| +-----+-----+ +-----+ +-----+ +-----+
- * +-+--++ or | +-++ | or | +-+ | or | +--+| or | +--+
- * | +--+| | +-++ | | +-+ | | | || | | |
- * | | +-----+-----+ +-----+ +-+--++ +--+--+
- * +-----+
- */
- if ((r - l <= 1.0 && (gint)r == (gint)l) || (b - t <= 1.0 && (gint)b == (gint)t)) {
- /* Inside */
- if ((gint)l == (gint)r || (gint)t == (gint)b) {
- get_pixel (page, (gint)l, (gint)t, p);
- pixel[0] = p[0];
- pixel[1] = p[1];
- pixel[2] = p[2];
- return;
- }
-
- /* Stradling horizontal edge */
- if (L > R) {
- get_pixel (page, R, T-1, p);
- red += p[0] * (r-l)*(T-t);
- green += p[1] * (r-l)*(T-t);
- blue += p[2] * (r-l)*(T-t);
- for (y = T; y < B; y++) {
- get_pixel (page, R, y, p);
- red += p[0] * (r-l);
- green += p[1] * (r-l);
- blue += p[2] * (r-l);
- }
- get_pixel (page, R, B, p);
- red += p[0] * (r-l)*(b-B);
- green += p[1] * (r-l)*(b-B);
- blue += p[2] * (r-l)*(b-B);
- }
- /* Stradling vertical edge */
- else {
- get_pixel (page, L - 1, B, p);
- red += p[0] * (b-t)*(L-l);
- green += p[1] * (b-t)*(L-l);
- blue += p[2] * (b-t)*(L-l);
- for (x = L; x < R; x++) {
- get_pixel (page, x, B, p);
- red += p[0] * (b-t);
- green += p[1] * (b-t);
- blue += p[2] * (b-t);
- }
- get_pixel (page, R, B, p);
- red += p[0] * (b-t)*(r-R);
- green += p[1] * (b-t)*(r-R);
- blue += p[2] * (b-t)*(r-R);
- }
-
- scale = 1.0 / ((r - l) * (b - t));
- pixel[0] = (guchar)(red * scale + 0.5);
- pixel[1] = (guchar)(green * scale + 0.5);
- pixel[2] = (guchar)(blue * scale + 0.5);
- return;
- }
-
- /* Add the middle pixels */
- for (x = L; x < R; x++) {
- for (y = T; y < B; y++) {
- get_pixel (page, x, y, p);
- red += p[0];
- green += p[1];
- blue += p[2];
- }
- }
-
- /* Add the weighted top and bottom pixels */
- for (x = L; x < R; x++) {
- if (t != T) {
- get_pixel (page, x, T - 1, p);
- red += p[0] * (T - t);
- green += p[1] * (T - t);
- blue += p[2] * (T - t);
- }
-
- if (b != B) {
- get_pixel (page, x, B, p);
- red += p[0] * (b - B);
- green += p[1] * (b - B);
- blue += p[2] * (b - B);
- }
- }
-
- /* Add the left and right pixels */
- for (y = T; y < B; y++) {
- if (l != L) {
- get_pixel (page, L - 1, y, p);
- red += p[0] * (L - l);
- green += p[1] * (L - l);
- blue += p[2] * (L - l);
- }
-
- if (r != R) {
- get_pixel (page, R, y, p);
- red += p[0] * (r - R);
- green += p[1] * (r - R);
- blue += p[2] * (r - R);
- }
- }
-
- /* Add the corner pixels */
- if (l != L && t != T) {
- get_pixel (page, L - 1, T - 1, p);
- red += p[0] * (L - l)*(T - t);
- green += p[1] * (L - l)*(T - t);
- blue += p[2] * (L - l)*(T - t);
- }
- if (r != R && t != T) {
- get_pixel (page, R, T - 1, p);
- red += p[0] * (r - R)*(T - t);
- green += p[1] * (r - R)*(T - t);
- blue += p[2] * (r - R)*(T - t);
- }
- if (r != R && b != B) {
- get_pixel (page, R, B, p);
- red += p[0] * (r - R)*(b - B);
- green += p[1] * (r - R)*(b - B);
- blue += p[2] * (r - R)*(b - B);
- }
- if (l != L && b != B) {
- get_pixel (page, L - 1, B, p);
- red += p[0] * (L - l)*(b - B);
- green += p[1] * (L - l)*(b - B);
- blue += p[2] * (L - l)*(b - B);
- }
-
- /* Scale pixel values and clamp in range [0, 255] */
- scale = 1.0 / ((r - l) * (b - t));
- pixel[0] = (guchar)(red * scale + 0.5);
- pixel[1] = (guchar)(green * scale + 0.5);
- pixel[2] = (guchar)(blue * scale + 0.5);
+static gint page_view_get_preview_width (PageView* self) {
+ gint result = 0;
+ g_return_val_if_fail (self != NULL, 0);
+ result = self->priv->width - (self->priv->border_width * 2);
+ return result;
}
-static void
-update_preview (Page *page,
- GdkPixbuf **output_image, gint output_width, gint output_height,
- ScanDirection scan_direction, gint old_scan_line, gint scan_line)
-{
- guchar *output;
- gint input_width, input_height;
- gint output_rowstride, output_n_channels;
- gint x, y;
- gint L, R, T, B;
-
- input_width = page_get_width (page);
- input_height = page_get_height (page);
-
- /* Create new image if one does not exist or has changed size */
- if (!*output_image ||
- gdk_pixbuf_get_width (*output_image) != output_width ||
- gdk_pixbuf_get_height (*output_image) != output_height) {
- if (*output_image)
- g_object_unref (*output_image);
- *output_image = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- FALSE,
- 8,
- output_width,
- output_height);
-
- /* Update entire image */
- L = 0;
- R = output_width - 1;
- T = 0;
- B = output_height - 1;
- }
- /* Otherwise only update changed area */
- else {
- switch (scan_direction) {
- case TOP_TO_BOTTOM:
- L = 0;
- R = output_width - 1;
- T = (gint)((double)old_scan_line * output_height / input_height);
- B = (gint)((double)scan_line * output_height / input_height + 0.5);
- break;
- case LEFT_TO_RIGHT:
- L = (gint)((double)old_scan_line * output_width / input_width);
- R = (gint)((double)scan_line * output_width / input_width + 0.5);
- T = 0;
- B = output_height - 1;
- break;
- case BOTTOM_TO_TOP:
- L = 0;
- R = output_width - 1;
- T = (gint)((double)(input_height - scan_line) * output_height / input_height);
- B = (gint)((double)(input_height - old_scan_line) * output_height / input_height + 0.5);
- break;
- case RIGHT_TO_LEFT:
- L = (gint)((double)(input_width - scan_line) * output_width / input_width);
- R = (gint)((double)(input_width - old_scan_line) * output_width / input_width + 0.5);
- T = 0;
- B = output_height - 1;
- break;
- default:
- L = R = B = T = 0;
- break;
- }
- }
-
- /* FIXME: There's an off by one error in there somewhere... */
- if (R >= output_width)
- R = output_width - 1;
- if (B >= output_height)
- B = output_height - 1;
-
- g_return_if_fail (L >= 0);
- g_return_if_fail (R < output_width);
- g_return_if_fail (T >= 0);
- g_return_if_fail (B < output_height);
- g_return_if_fail (*output_image != NULL);
-
- output = gdk_pixbuf_get_pixels (*output_image);
- output_rowstride = gdk_pixbuf_get_rowstride (*output_image);
- output_n_channels = gdk_pixbuf_get_n_channels (*output_image);
-
- if (!page_has_data (page)) {
- for (x = L; x <= R; x++)
- for (y = T; y <= B; y++) {
- guchar *pixel;
- pixel = output + output_rowstride * y + x * output_n_channels;
- pixel[0] = pixel[1] = pixel[2] = 0xFF;
- }
- return;
- }
-
- /* Update changed area */
- for (x = L; x <= R; x++) {
- double l, r;
-
- l = (double)x * input_width / output_width;
- r = (double)(x + 1) * input_width / output_width;
-
- for (y = T; y <= B; y++) {
- double t, b;
-
- t = (double)y * input_height / output_height;
- b = (double)(y + 1) * input_height / output_height;
-
- set_pixel (page,
- l, r, t, b,
- output + output_rowstride * y + x * output_n_channels);
- }
- }
+static gint page_view_get_preview_height (PageView* self) {
+ gint result = 0;
+ g_return_val_if_fail (self != NULL, 0);
+ result = self->priv->height - (self->priv->border_width * 2);
+ return result;
}
-static gint
-get_preview_width (PageView *view)
-{
- return view->priv->width - view->priv->border_width * 2;
+static void page_view_update_page_view (PageView* self) {
+ gint old_scan_line;
+ gint _tmp0_;
+ gint scan_line;
+ ScanDirection _tmp1_;
+ ScanDirection left_steps;
+ gboolean _tmp2_ = FALSE;
+ ScanDirection _tmp3_;
+ gint _tmp4_;
+ gint _tmp5_;
+ ScanDirection _tmp6_;
+ g_return_if_fail (self != NULL);
+ if (!self->priv->update_image) {
+ return;
+ }
+ old_scan_line = self->priv->scan_line;
+ _tmp0_ = page_get_scan_line (self->priv->page);
+ scan_line = _tmp0_;
+ _tmp1_ = page_get_scan_direction (self->priv->page);
+ left_steps = self->priv->scan_direction - _tmp1_;
+ if (left_steps != 0) {
+ _tmp2_ = self->priv->image != NULL;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (_tmp2_) {
+ _g_object_unref0 (self->priv->image);
+ self->priv->image = NULL;
+ }
+ _tmp3_ = page_get_scan_direction (self->priv->page);
+ self->priv->scan_direction = _tmp3_;
+ _tmp4_ = page_view_get_preview_width (self);
+ _tmp5_ = page_view_get_preview_height (self);
+ _tmp6_ = page_get_scan_direction (self->priv->page);
+ page_view_update_preview (self, self->priv->page, &self->priv->image, _tmp4_, _tmp5_, _tmp6_, old_scan_line, scan_line);
+ self->priv->update_image = FALSE;
+ self->priv->scan_line = scan_line;
}
-static gint
-get_preview_height (PageView *view)
-{
- return view->priv->height - view->priv->border_width * 2;
+static gint page_view_page_to_screen_x (PageView* self, gint x) {
+ gint result = 0;
+ gint _tmp0_;
+ gint _tmp1_;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = page_view_get_preview_width (self);
+ _tmp1_ = page_get_width (self->priv->page);
+ result = (gint) (((((gdouble) x) * _tmp0_) / _tmp1_) + 0.5);
+ return result;
}
-static void
-update_page_view (PageView *view)
-{
- gint old_scan_line, scan_line, left_steps;
+static gint page_view_page_to_screen_y (PageView* self, gint y) {
+ gint result = 0;
+ gint _tmp0_;
+ gint _tmp1_;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = page_view_get_preview_height (self);
+ _tmp1_ = page_get_height (self->priv->page);
+ result = (gint) (((((gdouble) y) * _tmp0_) / _tmp1_) + 0.5);
+ return result;
+}
+
- if (!view->priv->update_image)
- return;
+static gint page_view_screen_to_page_x (PageView* self, gint x) {
+ gint result = 0;
+ gint _tmp0_;
+ gint _tmp1_;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = page_get_width (self->priv->page);
+ _tmp1_ = page_view_get_preview_width (self);
+ result = (gint) (((((gdouble) x) * _tmp0_) / _tmp1_) + 0.5);
+ return result;
+}
- old_scan_line = view->priv->scan_line;
- scan_line = page_get_scan_line (view->priv->page);
- /* Delete old image if scan direction changed */
- left_steps = view->priv->scan_direction - page_get_scan_direction (view->priv->page);
- if (left_steps && view->priv->image) {
- g_object_unref (view->priv->image);
- view->priv->image = NULL;
- }
- view->priv->scan_direction = page_get_scan_direction (view->priv->page);
+static gint page_view_screen_to_page_y (PageView* self, gint y) {
+ gint result = 0;
+ gint _tmp0_;
+ gint _tmp1_;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = page_get_height (self->priv->page);
+ _tmp1_ = page_view_get_preview_height (self);
+ result = (gint) (((((gdouble) y) * _tmp0_) / _tmp1_) + 0.5);
+ return result;
+}
- update_preview (view->priv->page,
- &view->priv->image,
- get_preview_width (view),
- get_preview_height (view),
- page_get_scan_direction (view->priv->page), old_scan_line, scan_line);
- view->priv->update_image = FALSE;
- view->priv->scan_line = scan_line;
+static CropLocation page_view_get_crop_location (PageView* self, gint x, gint y) {
+ CropLocation result = 0;
+ gboolean _tmp0_;
+ gint cx = 0;
+ gint cy = 0;
+ gint cw = 0;
+ gint ch = 0;
+ gint _tmp1_;
+ gint _tmp2_;
+ gint _tmp3_;
+ gint _tmp4_;
+ gint _tmp5_;
+ gint dx;
+ gint _tmp6_;
+ gint dy;
+ gint _tmp7_;
+ gint dw;
+ gint _tmp8_;
+ gint dh;
+ gint ix;
+ gint iy;
+ gboolean _tmp9_ = FALSE;
+ gboolean _tmp10_ = FALSE;
+ gboolean _tmp11_ = FALSE;
+ gchar* _tmp12_ = NULL;
+ gchar* name;
+ gint crop_border;
+ gboolean _tmp13_ = FALSE;
+ gboolean _tmp14_ = FALSE;
+ gboolean _tmp15_ = FALSE;
+ gboolean _tmp16_ = FALSE;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = page_has_crop (self->priv->page);
+ if (!_tmp0_) {
+ result = 0;
+ return result;
+ }
+ page_get_crop (self->priv->page, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_);
+ cx = _tmp1_;
+ cy = _tmp2_;
+ cw = _tmp3_;
+ ch = _tmp4_;
+ _tmp5_ = page_view_page_to_screen_x (self, cx);
+ dx = _tmp5_;
+ _tmp6_ = page_view_page_to_screen_y (self, cy);
+ dy = _tmp6_;
+ _tmp7_ = page_view_page_to_screen_x (self, cw);
+ dw = _tmp7_;
+ _tmp8_ = page_view_page_to_screen_y (self, ch);
+ dh = _tmp8_;
+ ix = x - dx;
+ iy = y - dy;
+ if (ix < 0) {
+ _tmp11_ = TRUE;
+ } else {
+ _tmp11_ = ix > dw;
+ }
+ if (_tmp11_) {
+ _tmp10_ = TRUE;
+ } else {
+ _tmp10_ = iy < 0;
+ }
+ if (_tmp10_) {
+ _tmp9_ = TRUE;
+ } else {
+ _tmp9_ = iy > dh;
+ }
+ if (_tmp9_) {
+ result = CROP_LOCATION_NONE;
+ return result;
+ }
+ _tmp12_ = page_get_named_crop (self->priv->page);
+ name = _tmp12_;
+ if (name != NULL) {
+ result = CROP_LOCATION_MIDDLE;
+ _g_free0 (name);
+ return result;
+ }
+ crop_border = 20;
+ if (dw < (crop_border * 3)) {
+ crop_border = dw / 3;
+ }
+ if (dh < (crop_border * 3)) {
+ crop_border = dh / 3;
+ }
+ if (ix < crop_border) {
+ _tmp13_ = iy < crop_border;
+ } else {
+ _tmp13_ = FALSE;
+ }
+ if (_tmp13_) {
+ result = CROP_LOCATION_TOP_LEFT;
+ _g_free0 (name);
+ return result;
+ }
+ if (ix > (dw - crop_border)) {
+ _tmp14_ = iy < crop_border;
+ } else {
+ _tmp14_ = FALSE;
+ }
+ if (_tmp14_) {
+ result = CROP_LOCATION_TOP_RIGHT;
+ _g_free0 (name);
+ return result;
+ }
+ if (ix < crop_border) {
+ _tmp15_ = iy > (dh - crop_border);
+ } else {
+ _tmp15_ = FALSE;
+ }
+ if (_tmp15_) {
+ result = CROP_LOCATION_BOTTOM_LEFT;
+ _g_free0 (name);
+ return result;
+ }
+ if (ix > (dw - crop_border)) {
+ _tmp16_ = iy > (dh - crop_border);
+ } else {
+ _tmp16_ = FALSE;
+ }
+ if (_tmp16_) {
+ result = CROP_LOCATION_BOTTOM_RIGHT;
+ _g_free0 (name);
+ return result;
+ }
+ if (ix < crop_border) {
+ result = CROP_LOCATION_LEFT;
+ _g_free0 (name);
+ return result;
+ }
+ if (ix > (dw - crop_border)) {
+ result = CROP_LOCATION_RIGHT;
+ _g_free0 (name);
+ return result;
+ }
+ if (iy < crop_border) {
+ result = CROP_LOCATION_TOP;
+ _g_free0 (name);
+ return result;
+ }
+ if (iy > (dh - crop_border)) {
+ result = CROP_LOCATION_BOTTOM;
+ _g_free0 (name);
+ return result;
+ }
+ result = CROP_LOCATION_MIDDLE;
+ _g_free0 (name);
+ return result;
}
-static gint
-page_to_screen_x (PageView *view, gint x)
-{
- return (double) x * get_preview_width (view) / page_get_width (view->priv->page) + 0.5;
+void page_view_button_press (PageView* self, gint x, gint y) {
+ CropLocation location = 0;
+ CropLocation _tmp0_;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = page_view_get_crop_location (self, x, y);
+ location = _tmp0_;
+ if (location != CROP_LOCATION_NONE) {
+ gint _tmp1_;
+ gint _tmp2_;
+ gint _tmp3_;
+ gint _tmp4_;
+ self->priv->crop_location = location;
+ self->priv->selected_crop_px = (gdouble) x;
+ self->priv->selected_crop_py = (gdouble) y;
+ page_get_crop (self->priv->page, &_tmp1_, &_tmp2_, &_tmp3_, &_tmp4_);
+ self->priv->selected_crop_x = _tmp1_;
+ self->priv->selected_crop_y = _tmp2_;
+ self->priv->selected_crop_w = _tmp3_;
+ self->priv->selected_crop_h = _tmp4_;
+ }
}
-static gint
-page_to_screen_y (PageView *view, gint y)
-{
- return (double) y * get_preview_height (view) / page_get_height (view->priv->page) + 0.5;
+void page_view_motion (PageView* self, gint x, gint y) {
+ CropLocation _tmp0_;
+ CropLocation location;
+ GdkCursorType cursor = 0;
+ gint _tmp1_;
+ gint pw;
+ gint _tmp2_;
+ gint ph;
+ gint cx = 0;
+ gint cy = 0;
+ gint cw = 0;
+ gint ch = 0;
+ gint _tmp3_;
+ gint _tmp4_;
+ gint _tmp5_;
+ gint _tmp6_;
+ gint _tmp7_;
+ gint dx;
+ gint _tmp8_;
+ gint dy;
+ gint new_x;
+ gint new_y;
+ gint new_w;
+ gint new_h;
+ gint _tmp9_;
+ gint min_size;
+ gboolean _tmp10_ = FALSE;
+ gboolean _tmp11_ = FALSE;
+ gboolean _tmp12_ = FALSE;
+ gboolean _tmp13_ = FALSE;
+ gboolean _tmp14_ = FALSE;
+ gboolean _tmp15_ = FALSE;
+ gboolean _tmp16_ = FALSE;
+ gboolean _tmp17_ = FALSE;
+ gboolean _tmp18_ = FALSE;
+ gboolean _tmp19_ = FALSE;
+ gboolean _tmp20_ = FALSE;
+ gboolean _tmp21_ = FALSE;
+ gboolean _tmp22_ = FALSE;
+ gboolean _tmp23_ = FALSE;
+ gboolean _tmp24_ = FALSE;
+ gboolean _tmp25_ = FALSE;
+ gboolean _tmp26_ = FALSE;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = page_view_get_crop_location (self, x, y);
+ location = _tmp0_;
+ switch (location) {
+ case CROP_LOCATION_MIDDLE:
+ {
+ cursor = GDK_HAND1;
+ break;
+ }
+ case CROP_LOCATION_TOP:
+ {
+ cursor = GDK_TOP_SIDE;
+ break;
+ }
+ case CROP_LOCATION_BOTTOM:
+ {
+ cursor = GDK_BOTTOM_SIDE;
+ break;
+ }
+ case CROP_LOCATION_LEFT:
+ {
+ cursor = GDK_LEFT_SIDE;
+ break;
+ }
+ case CROP_LOCATION_RIGHT:
+ {
+ cursor = GDK_RIGHT_SIDE;
+ break;
+ }
+ case CROP_LOCATION_TOP_LEFT:
+ {
+ cursor = GDK_TOP_LEFT_CORNER;
+ break;
+ }
+ case CROP_LOCATION_TOP_RIGHT:
+ {
+ cursor = GDK_TOP_RIGHT_CORNER;
+ break;
+ }
+ case CROP_LOCATION_BOTTOM_LEFT:
+ {
+ cursor = GDK_BOTTOM_LEFT_CORNER;
+ break;
+ }
+ case CROP_LOCATION_BOTTOM_RIGHT:
+ {
+ cursor = GDK_BOTTOM_RIGHT_CORNER;
+ break;
+ }
+ default:
+ {
+ cursor = GDK_ARROW;
+ break;
+ }
+ }
+ if (self->priv->crop_location == CROP_LOCATION_NONE) {
+ self->priv->cursor = cursor;
+ return;
+ }
+ _tmp1_ = page_get_width (self->priv->page);
+ pw = _tmp1_;
+ _tmp2_ = page_get_height (self->priv->page);
+ ph = _tmp2_;
+ page_get_crop (self->priv->page, &_tmp3_, &_tmp4_, &_tmp5_, &_tmp6_);
+ cx = _tmp3_;
+ cy = _tmp4_;
+ cw = _tmp5_;
+ ch = _tmp6_;
+ _tmp7_ = page_view_screen_to_page_x (self, x - ((gint) self->priv->selected_crop_px));
+ dx = _tmp7_;
+ _tmp8_ = page_view_screen_to_page_y (self, y - ((gint) self->priv->selected_crop_py));
+ dy = _tmp8_;
+ new_x = self->priv->selected_crop_x;
+ new_y = self->priv->selected_crop_y;
+ new_w = self->priv->selected_crop_w;
+ new_h = self->priv->selected_crop_h;
+ _tmp9_ = page_view_screen_to_page_x (self, 15);
+ min_size = _tmp9_;
+ if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
+ _tmp11_ = TRUE;
+ } else {
+ _tmp11_ = self->priv->crop_location == CROP_LOCATION_LEFT;
+ }
+ if (_tmp11_) {
+ _tmp10_ = TRUE;
+ } else {
+ _tmp10_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT;
+ }
+ if (_tmp10_) {
+ if (dx > (new_w - min_size)) {
+ dx = new_w - min_size;
+ }
+ if ((new_x + dx) < 0) {
+ dx = -new_x;
+ }
+ }
+ if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
+ _tmp13_ = TRUE;
+ } else {
+ _tmp13_ = self->priv->crop_location == CROP_LOCATION_TOP;
+ }
+ if (_tmp13_) {
+ _tmp12_ = TRUE;
+ } else {
+ _tmp12_ = self->priv->crop_location == CROP_LOCATION_TOP_RIGHT;
+ }
+ if (_tmp12_) {
+ if (dy > (new_h - min_size)) {
+ dy = new_h - min_size;
+ }
+ if ((new_y + dy) < 0) {
+ dy = -new_y;
+ }
+ }
+ if (self->priv->crop_location == CROP_LOCATION_TOP_RIGHT) {
+ _tmp15_ = TRUE;
+ } else {
+ _tmp15_ = self->priv->crop_location == CROP_LOCATION_RIGHT;
+ }
+ if (_tmp15_) {
+ _tmp14_ = TRUE;
+ } else {
+ _tmp14_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
+ }
+ if (_tmp14_) {
+ if (dx < (min_size - new_w)) {
+ dx = min_size - new_w;
+ }
+ if (((new_x + new_w) + dx) > pw) {
+ dx = (pw - new_x) - new_w;
+ }
+ }
+ if (self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT) {
+ _tmp17_ = TRUE;
+ } else {
+ _tmp17_ = self->priv->crop_location == CROP_LOCATION_BOTTOM;
+ }
+ if (_tmp17_) {
+ _tmp16_ = TRUE;
+ } else {
+ _tmp16_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
+ }
+ if (_tmp16_) {
+ if (dy < (min_size - new_h)) {
+ dy = min_size - new_h;
+ }
+ if (((new_y + new_h) + dy) > ph) {
+ dy = (ph - new_y) - new_h;
+ }
+ }
+ if (self->priv->crop_location == CROP_LOCATION_MIDDLE) {
+ if (((new_x + dx) + new_w) > pw) {
+ dx = (pw - new_x) - new_w;
+ }
+ if ((new_x + dx) < 0) {
+ dx = -new_x;
+ }
+ if (((new_y + dy) + new_h) > ph) {
+ dy = (ph - new_y) - new_h;
+ }
+ if ((new_y + dy) < 0) {
+ dy = -new_y;
+ }
+ }
+ if (self->priv->crop_location == CROP_LOCATION_MIDDLE) {
+ new_x = new_x + dx;
+ new_y = new_y + dy;
+ }
+ if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
+ _tmp19_ = TRUE;
+ } else {
+ _tmp19_ = self->priv->crop_location == CROP_LOCATION_LEFT;
+ }
+ if (_tmp19_) {
+ _tmp18_ = TRUE;
+ } else {
+ _tmp18_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT;
+ }
+ if (_tmp18_) {
+ new_x = new_x + dx;
+ new_w = new_w - dx;
+ }
+ if (self->priv->crop_location == CROP_LOCATION_TOP_LEFT) {
+ _tmp21_ = TRUE;
+ } else {
+ _tmp21_ = self->priv->crop_location == CROP_LOCATION_TOP;
+ }
+ if (_tmp21_) {
+ _tmp20_ = TRUE;
+ } else {
+ _tmp20_ = self->priv->crop_location == CROP_LOCATION_TOP_RIGHT;
+ }
+ if (_tmp20_) {
+ new_y = new_y + dy;
+ new_h = new_h - dy;
+ }
+ if (self->priv->crop_location == CROP_LOCATION_TOP_RIGHT) {
+ _tmp23_ = TRUE;
+ } else {
+ _tmp23_ = self->priv->crop_location == CROP_LOCATION_RIGHT;
+ }
+ if (_tmp23_) {
+ _tmp22_ = TRUE;
+ } else {
+ _tmp22_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
+ }
+ if (_tmp22_) {
+ new_w = new_w + dx;
+ }
+ if (self->priv->crop_location == CROP_LOCATION_BOTTOM_LEFT) {
+ _tmp25_ = TRUE;
+ } else {
+ _tmp25_ = self->priv->crop_location == CROP_LOCATION_BOTTOM;
+ }
+ if (_tmp25_) {
+ _tmp24_ = TRUE;
+ } else {
+ _tmp24_ = self->priv->crop_location == CROP_LOCATION_BOTTOM_RIGHT;
+ }
+ if (_tmp24_) {
+ new_h = new_h + dy;
+ }
+ page_move_crop (self->priv->page, new_x, new_y);
+ if (new_w != cw) {
+ _tmp26_ = TRUE;
+ } else {
+ _tmp26_ = new_h != ch;
+ }
+ if (_tmp26_) {
+ page_set_custom_crop (self->priv->page, new_w, new_h);
+ }
}
-static gint
-screen_to_page_x (PageView *view, gint x)
-{
- return (double) x * page_get_width (view->priv->page) / get_preview_width (view) + 0.5;
+void page_view_button_release (PageView* self, gint x, gint y) {
+ g_return_if_fail (self != NULL);
+ self->priv->crop_location = CROP_LOCATION_NONE;
+ g_signal_emit_by_name (self, "changed");
}
-static gint
-screen_to_page_y (PageView *view, gint y)
-{
- return (double) y * page_get_height (view->priv->page) / get_preview_height (view) + 0.5;
+GdkCursorType page_view_get_cursor (PageView* self) {
+ GdkCursorType result = 0;
+ g_return_val_if_fail (self != NULL, 0);
+ result = self->priv->cursor;
+ return result;
}
-static CropLocation
-get_crop_location (PageView *view, gint x, gint y)
-{
- gint cx, cy, cw, ch;
- gint dx, dy, dw, dh;
- gint ix, iy;
- gint crop_border = 20;
- gchar *name;
-
- if (!page_has_crop (view->priv->page))
- return 0;
-
- page_get_crop (view->priv->page, &cx, &cy, &cw, &ch);
- dx = page_to_screen_x (view, cx);
- dy = page_to_screen_y (view, cy);
- dw = page_to_screen_x (view, cw);
- dh = page_to_screen_y (view, ch);
- ix = x - dx;
- iy = y - dy;
-
- if (ix < 0 || ix > dw || iy < 0 || iy > dh)
- return CROP_NONE;
-
- /* Can't resize named crops */
- name = page_get_named_crop (view->priv->page);
- if (name != NULL) {
- g_free (name);
- return CROP_MIDDLE;
- }
-
- /* Adjust borders so can select */
- if (dw < crop_border * 3)
- crop_border = dw / 3;
- if (dh < crop_border * 3)
- crop_border = dh / 3;
-
- /* Top left */
- if (ix < crop_border && iy < crop_border)
- return CROP_TOP_LEFT;
- /* Top right */
- if (ix > dw - crop_border && iy < crop_border)
- return CROP_TOP_RIGHT;
- /* Bottom left */
- if (ix < crop_border && iy > dh - crop_border)
- return CROP_BOTTOM_LEFT;
- /* Bottom right */
- if (ix > dw - crop_border && iy > dh - crop_border)
- return CROP_BOTTOM_RIGHT;
-
- /* Left */
- if (ix < crop_border)
- return CROP_LEFT;
- /* Right */
- if (ix > dw - crop_border)
- return CROP_RIGHT;
- /* Top */
- if (iy < crop_border)
- return CROP_TOP;
- /* Bottom */
- if (iy > dh - crop_border)
- return CROP_BOTTOM;
-
- /* In the middle */
- return CROP_MIDDLE;
+static gboolean page_view_animation_cb (PageView* self) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ self->priv->animate_segment = (self->priv->animate_segment + 1) % self->priv->animate_n_segments;
+ g_signal_emit_by_name (self, "changed");
+ result = TRUE;
+ return result;
}
-void
-page_view_button_press (PageView *view, gint x, gint y)
-{
- CropLocation location;
-
- g_return_if_fail (view != NULL);
-
- /* See if selecting crop */
- location = get_crop_location (view, x, y);;
- if (location != CROP_NONE) {
- view->priv->crop_location = location;
- view->priv->selected_crop_px = x;
- view->priv->selected_crop_py = y;
- page_get_crop (view->priv->page,
- &view->priv->selected_crop_x,
- &view->priv->selected_crop_y,
- &view->priv->selected_crop_w,
- &view->priv->selected_crop_h);
- }
+static gboolean _page_view_animation_cb_gsource_func (gpointer self) {
+ gboolean result;
+ result = page_view_animation_cb (self);
+ return result;
}
-void
-page_view_motion (PageView *view, gint x, gint y)
-{
- gint pw, ph;
- gint cx, cy, cw, ch, dx, dy;
- gint new_x, new_y, new_w, new_h;
- CropLocation location;
- gint cursor;
- gint min_size;
-
- min_size = screen_to_page_x (view, 15);
-
- g_return_if_fail (view != NULL);
-
- location = get_crop_location (view, x, y);
- switch (location) {
- case CROP_MIDDLE:
- cursor = GDK_HAND1;
- break;
- case CROP_TOP:
- cursor = GDK_TOP_SIDE;
- break;
- case CROP_BOTTOM:
- cursor = GDK_BOTTOM_SIDE;
- break;
- case CROP_LEFT:
- cursor = GDK_LEFT_SIDE;
- break;
- case CROP_RIGHT:
- cursor = GDK_RIGHT_SIDE;
- break;
- case CROP_TOP_LEFT:
- cursor = GDK_TOP_LEFT_CORNER;
- break;
- case CROP_TOP_RIGHT:
- cursor = GDK_TOP_RIGHT_CORNER;
- break;
- case CROP_BOTTOM_LEFT:
- cursor = GDK_BOTTOM_LEFT_CORNER;
- break;
- case CROP_BOTTOM_RIGHT:
- cursor = GDK_BOTTOM_RIGHT_CORNER;
- break;
- default:
- cursor = GDK_ARROW;
- break;
- }
-
- if (view->priv->crop_location == CROP_NONE) {
- view->priv->cursor = cursor;
- return;
- }
-
- /* Move the crop */
- pw = page_get_width (view->priv->page);
- ph = page_get_height (view->priv->page);
- page_get_crop (view->priv->page, &cx, &cy, &cw, &ch);
-
- dx = screen_to_page_x (view, x - view->priv->selected_crop_px);
- dy = screen_to_page_y (view, y - view->priv->selected_crop_py);
-
- new_x = view->priv->selected_crop_x;
- new_y = view->priv->selected_crop_y;
- new_w = view->priv->selected_crop_w;
- new_h = view->priv->selected_crop_h;
-
- /* Limit motion to remain within page and minimum crop size */
- if (view->priv->crop_location == CROP_TOP_LEFT ||
- view->priv->crop_location == CROP_LEFT ||
- view->priv->crop_location == CROP_BOTTOM_LEFT) {
- if (dx > new_w - min_size)
- dx = new_w - min_size;
- if (new_x + dx < 0)
- dx = -new_x;
- }
- if (view->priv->crop_location == CROP_TOP_LEFT ||
- view->priv->crop_location == CROP_TOP ||
- view->priv->crop_location == CROP_TOP_RIGHT) {
- if (dy > new_h - min_size)
- dy = new_h - min_size;
- if (new_y + dy < 0)
- dy = -new_y;
- }
-
- if (view->priv->crop_location == CROP_TOP_RIGHT ||
- view->priv->crop_location == CROP_RIGHT ||
- view->priv->crop_location == CROP_BOTTOM_RIGHT) {
- if (dx < min_size - new_w)
- dx = min_size - new_w;
- if (new_x + new_w + dx > pw)
- dx = pw - new_x - new_w;
- }
- if (view->priv->crop_location == CROP_BOTTOM_LEFT ||
- view->priv->crop_location == CROP_BOTTOM ||
- view->priv->crop_location == CROP_BOTTOM_RIGHT) {
- if (dy < min_size - new_h)
- dy = min_size - new_h;
- if (new_y + new_h + dy > ph)
- dy = ph - new_y - new_h;
- }
- if (view->priv->crop_location == CROP_MIDDLE) {
- if (new_x + dx + new_w > pw)
- dx = pw - new_x - new_w;
- if (new_x + dx < 0)
- dx = -new_x;
- if (new_y + dy + new_h > ph)
- dy = ph - new_y - new_h;
- if (new_y + dy < 0)
- dy = -new_y;
- }
-
- /* Move crop */
- if (view->priv->crop_location == CROP_MIDDLE) {
- new_x += dx;
- new_y += dy;
- }
- if (view->priv->crop_location == CROP_TOP_LEFT ||
- view->priv->crop_location == CROP_LEFT ||
- view->priv->crop_location == CROP_BOTTOM_LEFT)
- {
- new_x += dx;
- new_w -= dx;
- }
- if (view->priv->crop_location == CROP_TOP_LEFT ||
- view->priv->crop_location == CROP_TOP ||
- view->priv->crop_location == CROP_TOP_RIGHT) {
- new_y += dy;
- new_h -= dy;
- }
-
- if (view->priv->crop_location == CROP_TOP_RIGHT ||
- view->priv->crop_location == CROP_RIGHT ||
- view->priv->crop_location == CROP_BOTTOM_RIGHT) {
- new_w += dx;
- }
- if (view->priv->crop_location == CROP_BOTTOM_LEFT ||
- view->priv->crop_location == CROP_BOTTOM ||
- view->priv->crop_location == CROP_BOTTOM_RIGHT) {
- new_h += dy;
- }
-
- page_move_crop (view->priv->page, new_x, new_y);
-
- /* If reshaped crop, must be a custom crop */
- if (new_w != cw || new_h != ch)
- page_set_custom_crop (view->priv->page, new_w, new_h);
+static void page_view_update_animation (PageView* self) {
+ gboolean animate = FALSE;
+ gboolean is_animating = FALSE;
+ gboolean _tmp0_ = FALSE;
+ gboolean _tmp1_;
+ g_return_if_fail (self != NULL);
+ _tmp1_ = page_is_scanning (self->priv->page);
+ if (_tmp1_) {
+ gboolean _tmp2_;
+ _tmp2_ = page_has_data (self->priv->page);
+ _tmp0_ = !_tmp2_;
+ } else {
+ _tmp0_ = FALSE;
+ }
+ animate = _tmp0_;
+ is_animating = self->priv->animate_timeout != ((guint) 0);
+ if (animate == is_animating) {
+ return;
+ }
+ if (animate) {
+ self->priv->animate_segment = 0;
+ if (self->priv->animate_timeout == ((guint) 0)) {
+ guint _tmp3_;
+ _tmp3_ = g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) 150, _page_view_animation_cb_gsource_func, page_view_ref (self), page_view_unref);
+ self->priv->animate_timeout = _tmp3_;
+ }
+ } else {
+ if (self->priv->animate_timeout != ((guint) 0)) {
+ g_source_remove (self->priv->animate_timeout);
+ }
+ self->priv->animate_timeout = (guint) 0;
+ }
}
-void
-page_view_button_release (PageView *view, gint x, gint y)
-{
- g_return_if_fail (view != NULL);
+void page_view_render (PageView* self, cairo_t* context) {
+ gint _tmp0_;
+ gint w;
+ gint _tmp1_;
+ gint h;
+ gboolean _tmp2_ = FALSE;
+ gboolean _tmp3_;
+ gboolean _tmp11_ = FALSE;
+ gboolean _tmp12_;
+ gboolean _tmp20_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (context != NULL);
+ page_view_update_animation (self);
+ page_view_update_page_view (self);
+ _tmp0_ = page_view_get_preview_width (self);
+ w = _tmp0_;
+ _tmp1_ = page_view_get_preview_height (self);
+ h = _tmp1_;
+ cairo_set_line_width (context, (gdouble) 1);
+ cairo_translate (context, (gdouble) self->priv->x_offset, (gdouble) self->priv->y_offset);
+ cairo_set_source_rgb (context, (gdouble) 0, (gdouble) 0, (gdouble) 0);
+ cairo_set_line_width (context, (gdouble) self->priv->border_width);
+ cairo_rectangle (context, ((gdouble) self->priv->border_width) / 2, ((gdouble) self->priv->border_width) / 2, (gdouble) (self->priv->width - self->priv->border_width), (gdouble) (self->priv->height - self->priv->border_width));
+ cairo_stroke (context);
+ cairo_translate (context, (gdouble) self->priv->border_width, (gdouble) self->priv->border_width);
+ gdk_cairo_set_source_pixbuf (context, self->priv->image, (gdouble) 0, (gdouble) 0);
+ cairo_paint (context);
+ _tmp3_ = page_is_scanning (self->priv->page);
+ if (_tmp3_) {
+ gboolean _tmp4_;
+ _tmp4_ = page_has_data (self->priv->page);
+ _tmp2_ = !_tmp4_;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (_tmp2_) {
+ gdouble outer_radius = 0.0;
+ gdouble arc;
+ gdouble _tmp5_;
+ gdouble x;
+ gdouble _tmp6_;
+ gdouble y;
+ gdouble _tmp7_;
+ gdouble inner_radius;
+ gdouble offset;
+ if (w > h) {
+ outer_radius = 0.15 * w;
+ } else {
+ outer_radius = 0.15 * h;
+ }
+ arc = G_PI / self->priv->animate_n_segments;
+ _tmp5_ = sin (arc);
+ x = outer_radius * _tmp5_;
+ _tmp6_ = cos (arc);
+ y = outer_radius * (_tmp6_ - 1.0);
+ _tmp7_ = sqrt ((x * x) + (y * y));
+ inner_radius = 0.6 * _tmp7_;
+ offset = 0.0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp8_;
+ _tmp8_ = TRUE;
+ while (TRUE) {
+ gdouble _tmp9_;
+ gdouble _tmp10_;
+ if (!_tmp8_) {
+ i++;
+ offset = offset + (arc * 2);
+ }
+ _tmp8_ = FALSE;
+ if (!(i < self->priv->animate_n_segments)) {
+ break;
+ }
+ _tmp9_ = sin (offset);
+ x = (w / 2) + (outer_radius * _tmp9_);
+ _tmp10_ = cos (offset);
+ y = (h / 2) - (outer_radius * _tmp10_);
+ cairo_arc (context, x, y, inner_radius, (gdouble) 0, 2 * G_PI);
+ if (i == self->priv->animate_segment) {
+ cairo_set_source_rgb (context, 0.75, 0.75, 0.75);
+ cairo_fill_preserve (context);
+ }
+ cairo_set_source_rgb (context, 0.5, 0.5, 0.5);
+ cairo_stroke (context);
+ }
+ }
+ }
+ }
+ _tmp12_ = page_is_scanning (self->priv->page);
+ if (_tmp12_) {
+ gint _tmp13_;
+ _tmp13_ = page_get_scan_line (self->priv->page);
+ _tmp11_ = _tmp13_ > 0;
+ } else {
+ _tmp11_ = FALSE;
+ }
+ if (_tmp11_) {
+ gint _tmp14_;
+ gint scan_line;
+ gdouble s = 0.0;
+ gdouble x1 = 0.0;
+ gdouble y1 = 0.0;
+ gdouble x2 = 0.0;
+ gdouble y2 = 0.0;
+ ScanDirection _tmp15_;
+ _tmp14_ = page_get_scan_line (self->priv->page);
+ scan_line = _tmp14_;
+ _tmp15_ = page_get_scan_direction (self->priv->page);
+ switch (_tmp15_) {
+ case SCAN_DIRECTION_TOP_TO_BOTTOM:
+ {
+ gint _tmp16_;
+ _tmp16_ = page_view_page_to_screen_y (self, scan_line);
+ s = (gdouble) _tmp16_;
+ x1 = (gdouble) 0;
+ y1 = s + 0.5;
+ x2 = (gdouble) w;
+ y2 = s + 0.5;
+ break;
+ }
+ case SCAN_DIRECTION_BOTTOM_TO_TOP:
+ {
+ gint _tmp17_;
+ _tmp17_ = page_view_page_to_screen_y (self, scan_line);
+ s = (gdouble) _tmp17_;
+ x1 = (gdouble) 0;
+ y1 = (h - s) + 0.5;
+ x2 = (gdouble) w;
+ y2 = (h - s) + 0.5;
+ break;
+ }
+ case SCAN_DIRECTION_LEFT_TO_RIGHT:
+ {
+ gint _tmp18_;
+ _tmp18_ = page_view_page_to_screen_x (self, scan_line);
+ s = (gdouble) _tmp18_;
+ x1 = s + 0.5;
+ y1 = (gdouble) 0;
+ x2 = s + 0.5;
+ y2 = (gdouble) h;
+ break;
+ }
+ case SCAN_DIRECTION_RIGHT_TO_LEFT:
+ {
+ gint _tmp19_;
+ _tmp19_ = page_view_page_to_screen_x (self, scan_line);
+ s = (gdouble) _tmp19_;
+ x1 = (w - s) + 0.5;
+ y1 = (gdouble) 0;
+ x2 = (w - s) + 0.5;
+ y2 = (gdouble) h;
+ break;
+ }
+ default:
+ {
+ y2 = (gdouble) 0;
+ x2 = y2;
+ y1 = x2;
+ x1 = y1;
+ break;
+ }
+ }
+ cairo_move_to (context, x1, y1);
+ cairo_line_to (context, x2, y2);
+ cairo_set_source_rgb (context, 1.0, 0.0, 0.0);
+ cairo_stroke (context);
+ }
+ _tmp20_ = page_has_crop (self->priv->page);
+ if (_tmp20_) {
+ gint x = 0;
+ gint y = 0;
+ gint crop_width = 0;
+ gint crop_height = 0;
+ gint _tmp21_;
+ gint _tmp22_;
+ gint _tmp23_;
+ gint _tmp24_;
+ gint _tmp25_;
+ gint dx;
+ gint _tmp26_;
+ gint dy;
+ gint _tmp27_;
+ gint dw;
+ gint _tmp28_;
+ gint dh;
+ page_get_crop (self->priv->page, &_tmp21_, &_tmp22_, &_tmp23_, &_tmp24_);
+ x = _tmp21_;
+ y = _tmp22_;
+ crop_width = _tmp23_;
+ crop_height = _tmp24_;
+ _tmp25_ = page_view_page_to_screen_x (self, x);
+ dx = _tmp25_;
+ _tmp26_ = page_view_page_to_screen_y (self, y);
+ dy = _tmp26_;
+ _tmp27_ = page_view_page_to_screen_x (self, crop_width);
+ dw = _tmp27_;
+ _tmp28_ = page_view_page_to_screen_y (self, crop_height);
+ dh = _tmp28_;
+ cairo_rectangle (context, (gdouble) 0, (gdouble) 0, (gdouble) w, (gdouble) h);
+ cairo_new_sub_path (context);
+ cairo_rectangle (context, (gdouble) dx, (gdouble) dy, (gdouble) dw, (gdouble) dh);
+ cairo_set_fill_rule (context, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_source_rgba (context, 0.25, 0.25, 0.25, 0.2);
+ cairo_fill (context);
+ cairo_rectangle (context, dx - 1.5, dy - 1.5, (gdouble) (dw + 3), (gdouble) (dh + 3));
+ cairo_set_source_rgb (context, 1.0, 1.0, 1.0);
+ cairo_stroke (context);
+ cairo_rectangle (context, dx - 0.5, dy - 0.5, (gdouble) (dw + 1), (gdouble) (dh + 1));
+ cairo_set_source_rgb (context, 0.0, 0.0, 0.0);
+ cairo_stroke (context);
+ }
+}
+
- /* Complete crop */
- view->priv->crop_location = CROP_NONE;
- g_signal_emit (view, signals[CHANGED], 0);
+void page_view_set_width (PageView* self, gint width) {
+ gint _tmp0_;
+ gint _tmp1_;
+ gint height;
+ gboolean _tmp2_ = FALSE;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = page_get_height (self->priv->page);
+ _tmp1_ = page_get_width (self->priv->page);
+ height = (gint) ((((gdouble) width) * _tmp0_) / _tmp1_);
+ if (self->priv->width == width) {
+ _tmp2_ = self->priv->height == height;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (_tmp2_) {
+ return;
+ }
+ self->priv->width = width;
+ self->priv->height = height;
+ self->priv->update_image = TRUE;
+ g_signal_emit_by_name (self, "size-changed");
+ g_signal_emit_by_name (self, "changed");
}
-gint
-page_view_get_cursor (PageView *view)
-{
- g_return_val_if_fail (view != NULL, 0);
- return view->priv->cursor;
+void page_view_set_height (PageView* self, gint height) {
+ gint _tmp0_;
+ gint _tmp1_;
+ gint width;
+ gboolean _tmp2_ = FALSE;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = page_get_width (self->priv->page);
+ _tmp1_ = page_get_height (self->priv->page);
+ width = (gint) ((((gdouble) height) * _tmp0_) / _tmp1_);
+ if (self->priv->width == width) {
+ _tmp2_ = self->priv->height == height;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (_tmp2_) {
+ return;
+ }
+ self->priv->width = width;
+ self->priv->height = height;
+ self->priv->update_image = TRUE;
+ g_signal_emit_by_name (self, "size-changed");
+ g_signal_emit_by_name (self, "changed");
}
-static gboolean
-animation_cb (PageView *view)
-{
- view->priv->animate_segment = (view->priv->animate_segment + 1) % view->priv->animate_n_segments;
- g_signal_emit (view, signals[CHANGED], 0);
- return TRUE;
+gint page_view_get_width (PageView* self) {
+ gint result = 0;
+ g_return_val_if_fail (self != NULL, 0);
+ result = self->priv->width;
+ return result;
}
-static void
-update_animation (PageView *view)
-{
- gboolean animate, is_animating;
-
- animate = page_is_scanning (view->priv->page) && !page_has_data (view->priv->page);
- is_animating = view->priv->animate_timeout != 0;
- if (animate == is_animating)
- return;
-
- if (animate) {
- view->priv->animate_segment = 0;
- if (view->priv->animate_timeout == 0)
- view->priv->animate_timeout = g_timeout_add (150, (GSourceFunc) animation_cb, view);
- }
- else
- {
- if (view->priv->animate_timeout != 0)
- g_source_remove (view->priv->animate_timeout);
- view->priv->animate_timeout = 0;
- }
+gint page_view_get_height (PageView* self) {
+ gint result = 0;
+ g_return_val_if_fail (self != NULL, 0);
+ result = self->priv->height;
+ return result;
}
-void
-page_view_render (PageView *view, cairo_t *context)
-{
- gint width, height;
-
- g_return_if_fail (view != NULL);
- g_return_if_fail (context != NULL);
-
- update_animation (view);
- update_page_view (view);
-
- width = get_preview_width (view);
- height = get_preview_height (view);
-
- cairo_set_line_width (context, 1);
- cairo_translate (context, view->priv->x, view->priv->y);
-
- /* Draw page border */
- cairo_set_source_rgb (context, 0, 0, 0);
- cairo_set_line_width (context, view->priv->border_width);
- cairo_rectangle (context,
- (double)view->priv->border_width / 2,
- (double)view->priv->border_width / 2,
- view->priv->width - view->priv->border_width,
- view->priv->height - view->priv->border_width);
- cairo_stroke (context);
-
- /* Draw image */
- cairo_translate (context, view->priv->border_width, view->priv->border_width);
- gdk_cairo_set_source_pixbuf (context, view->priv->image, 0, 0);
- cairo_paint (context);
-
- /* Draw throbber */
- if (page_is_scanning (view->priv->page) && !page_has_data (view->priv->page)) {
- gdouble inner_radius, outer_radius, x, y, arc, offset = 0.0;
- gint i;
-
- if (width > height)
- outer_radius = 0.15 * width;
- else
- outer_radius = 0.15 * height;
- arc = M_PI / view->priv->animate_n_segments;
-
- /* Space circles */
- x = outer_radius * sin (arc);
- y = outer_radius * (cos (arc) - 1.0);
- inner_radius = 0.6 * sqrt (x*x + y*y);
-
- for (i = 0; i < view->priv->animate_n_segments; i++, offset += arc * 2) {
- x = width / 2 + outer_radius * sin (offset);
- y = height / 2 - outer_radius * cos (offset);
- cairo_arc (context, x, y, inner_radius, 0, 2 * M_PI);
-
- if (i == view->priv->animate_segment) {
- cairo_set_source_rgb (context, 0.75, 0.75, 0.75);
- cairo_fill_preserve (context);
- }
-
- cairo_set_source_rgb (context, 0.5, 0.5, 0.5);
- cairo_stroke (context);
- }
- }
-
- /* Draw scan line */
- if (page_is_scanning (view->priv->page) && page_get_scan_line (view->priv->page) > 0) {
- gint scan_line;
- double s;
- double x1, y1, x2, y2;
-
- scan_line = page_get_scan_line (view->priv->page);
-
- switch (page_get_scan_direction (view->priv->page)) {
- case TOP_TO_BOTTOM:
- s = page_to_screen_y (view, scan_line);
- x1 = 0; y1 = s + 0.5;
- x2 = width; y2 = s + 0.5;
- break;
- case BOTTOM_TO_TOP:
- s = page_to_screen_y (view, scan_line);
- x1 = 0; y1 = height - s + 0.5;
- x2 = width; y2 = height - s + 0.5;
- break;
- case LEFT_TO_RIGHT:
- s = page_to_screen_x (view, scan_line);
- x1 = s + 0.5; y1 = 0;
- x2 = s + 0.5; y2 = height;
- break;
- case RIGHT_TO_LEFT:
- s = page_to_screen_x (view, scan_line);
- x1 = width - s + 0.5; y1 = 0;
- x2 = width - s + 0.5; y2 = height;
- break;
- default:
- x1 = y1 = x2 = y2 = 0;
- break;
- }
-
- cairo_move_to (context, x1, y1);
- cairo_line_to (context, x2, y2);
- cairo_set_source_rgb (context, 1.0, 0.0, 0.0);
- cairo_stroke (context);
- }
-
- /* Draw crop */
- if (page_has_crop (view->priv->page)) {
- gint x, y, crop_width, crop_height;
- gdouble dx, dy, dw, dh;
-
- page_get_crop (view->priv->page, &x, &y, &crop_width, &crop_height);
-
- dx = page_to_screen_x (view, x);
- dy = page_to_screen_y (view, y);
- dw = page_to_screen_x (view, crop_width);
- dh = page_to_screen_y (view, crop_height);
-
- /* Shade out cropped area */
- cairo_rectangle (context,
- 0, 0,
- width, height);
- cairo_new_sub_path (context);
- cairo_rectangle (context, dx, dy, dw, dh);
- cairo_set_fill_rule (context, CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_source_rgba (context, 0.25, 0.25, 0.25, 0.2);
- cairo_fill (context);
-
- /* Show new edge */
- cairo_rectangle (context, dx - 1.5, dy - 1.5, dw + 3, dh + 3);
- cairo_set_source_rgb (context, 1.0, 1.0, 1.0);
- cairo_stroke (context);
- cairo_rectangle (context, dx - 0.5, dy - 0.5, dw + 1, dh + 1);
- cairo_set_source_rgb (context, 0.0, 0.0, 0.0);
- cairo_stroke (context);
- }
+static void page_view_page_pixels_changed_cb (PageView* self, Page* p) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (p != NULL);
+ self->priv->update_image = TRUE;
+ g_signal_emit_by_name (self, "changed");
}
-void
-page_view_set_width (PageView *view, gint width)
-{
- gint height;
+static void page_view_page_size_changed_cb (PageView* self, Page* p) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (p != NULL);
+ self->priv->update_image = TRUE;
+ g_signal_emit_by_name (self, "size-changed");
+ g_signal_emit_by_name (self, "changed");
+}
- g_return_if_fail (view != NULL);
- // FIXME: Automatically update when get updated image
- height = (double)width * page_get_height (view->priv->page) / page_get_width (view->priv->page);
- if (view->priv->width == width && view->priv->height == height)
- return;
+static void page_view_page_overlay_changed_cb (PageView* self, Page* p) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (p != NULL);
+ g_signal_emit_by_name (self, "changed");
+}
- view->priv->width = width;
- view->priv->height = height;
-
- /* Regenerate image */
- view->priv->update_image = TRUE;
- g_signal_emit (view, signals[SIZE_CHANGED], 0);
- g_signal_emit (view, signals[CHANGED], 0);
+static void page_view_scan_direction_changed_cb (PageView* self, Page* p) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (p != NULL);
+ self->priv->update_image = TRUE;
+ g_signal_emit_by_name (self, "size-changed");
+ g_signal_emit_by_name (self, "changed");
}
-void
-page_view_set_height (PageView *view, gint height)
-{
- gint width;
+static void value_page_view_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
- g_return_if_fail (view != NULL);
- // FIXME: Automatically update when get updated image
- width = (double)height * page_get_width (view->priv->page) / page_get_height (view->priv->page);
- if (view->priv->width == width && view->priv->height == height)
- return;
+static void value_page_view_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ page_view_unref (value->data[0].v_pointer);
+ }
+}
- view->priv->width = width;
- view->priv->height = height;
-
- /* Regenerate image */
- view->priv->update_image = TRUE;
- g_signal_emit (view, signals[SIZE_CHANGED], 0);
- g_signal_emit (view, signals[CHANGED], 0);
+static void value_page_view_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = page_view_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
}
-gint
-page_view_get_width (PageView *view)
-{
- g_return_val_if_fail (view != NULL, 0);
- return view->priv->width;
+static gpointer value_page_view_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
}
-gint
-page_view_get_height (PageView *view)
-{
- g_return_val_if_fail (view != NULL, 0);
- return view->priv->height;
+static gchar* value_page_view_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ PageView* object;
+ object = collect_values[0].v_pointer;
+ if (object->parent_instance.g_class == NULL) {
+ return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
+ return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ }
+ value->data[0].v_pointer = page_view_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
}
-static void
-page_pixels_changed_cb (Page *p, PageView *view)
-{
- /* Regenerate image */
- view->priv->update_image = TRUE;
- g_signal_emit (view, signals[CHANGED], 0);
+static gchar* value_page_view_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ PageView** object_p;
+ object_p = collect_values[0].v_pointer;
+ if (!object_p) {
+ return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+ }
+ if (!value->data[0].v_pointer) {
+ *object_p = NULL;
+ } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
+ *object_p = value->data[0].v_pointer;
+ } else {
+ *object_p = page_view_ref (value->data[0].v_pointer);
+ }
+ return NULL;
}
-static void
-page_size_changed_cb (Page *p, PageView *view)
-{
- /* Regenerate image */
- view->priv->update_image = TRUE;
- g_signal_emit (view, signals[SIZE_CHANGED], 0);
- g_signal_emit (view, signals[CHANGED], 0);
+GParamSpec* param_spec_page_view (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecPageView* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_PAGE_VIEW), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
}
-static void
-page_overlay_changed_cb (Page *p, PageView *view)
-{
- g_signal_emit (view, signals[CHANGED], 0);
+gpointer value_get_page_view (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW), NULL);
+ return value->data[0].v_pointer;
}
-static void
-scan_direction_changed_cb (Page *p, PageView *view)
-{
- /* Regenerate image */
- view->priv->update_image = TRUE;
- g_signal_emit (view, signals[SIZE_CHANGED], 0);
- g_signal_emit (view, signals[CHANGED], 0);
+void value_set_page_view (GValue* value, gpointer v_object) {
+ PageView* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE_VIEW));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ page_view_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ page_view_unref (old);
+ }
}
-static void
-page_view_set_page (PageView *view, Page *page)
-{
- g_return_if_fail (view != NULL);
- g_return_if_fail (view->priv->page == NULL);
+void value_take_page_view (GValue* value, gpointer v_object) {
+ PageView* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_PAGE_VIEW));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_PAGE_VIEW));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ page_view_unref (old);
+ }
+}
+
- view->priv->page = g_object_ref (page);
- g_signal_connect (view->priv->page, "pixels-changed", G_CALLBACK (page_pixels_changed_cb), view);
- g_signal_connect (view->priv->page, "size-changed", G_CALLBACK (page_size_changed_cb), view);
- g_signal_connect (view->priv->page, "crop-changed", G_CALLBACK (page_overlay_changed_cb), view);
- g_signal_connect (view->priv->page, "scan-line-changed", G_CALLBACK (page_overlay_changed_cb), view);
- g_signal_connect (view->priv->page, "scan-direction-changed", G_CALLBACK (scan_direction_changed_cb), view);
+static void page_view_class_init (PageViewClass * klass) {
+ page_view_parent_class = g_type_class_peek_parent (klass);
+ PAGE_VIEW_CLASS (klass)->finalize = page_view_finalize;
+ g_type_class_add_private (klass, sizeof (PageViewPrivate));
+ g_signal_new ("size_changed", TYPE_PAGE_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("changed", TYPE_PAGE_VIEW, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
-static void
-page_view_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- PageView *self;
-
- self = PAGE_VIEW (object);
-
- switch (prop_id) {
- case PROP_PAGE:
- page_view_set_page (self, g_value_get_object (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+static void page_view_instance_init (PageView * self) {
+ self->priv = PAGE_VIEW_GET_PRIVATE (self);
+ self->priv->image = NULL;
+ self->priv->border_width = 1;
+ self->priv->update_image = TRUE;
+ self->priv->cursor = GDK_ARROW;
+ self->priv->animate_n_segments = 7;
+ self->ref_count = 1;
}
-static void
-page_view_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- PageView *self;
-
- self = PAGE_VIEW (object);
-
- switch (prop_id) {
- case PROP_PAGE:
- g_value_set_object (value, self->priv->page);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+static void page_view_finalize (PageView* obj) {
+ PageView * self;
+ self = PAGE_VIEW (obj);
+ _page_unref0 (self->priv->page);
+ _g_object_unref0 (self->priv->image);
}
-static void
-page_view_finalize (GObject *object)
-{
- PageView *view = PAGE_VIEW (object);
- g_object_unref (view->priv->page);
- view->priv->page = NULL;
- if (view->priv->image)
- g_object_unref (view->priv->image);
- view->priv->image = NULL;
- if (view->priv->animate_timeout != 0)
- g_source_remove (view->priv->animate_timeout);
- view->priv->animate_timeout = 0;
- G_OBJECT_CLASS (page_view_parent_class)->finalize (object);
+GType page_view_get_type (void) {
+ static volatile gsize page_view_type_id__volatile = 0;
+ if (g_once_init_enter (&page_view_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_page_view_init, value_page_view_free_value, value_page_view_copy_value, value_page_view_peek_pointer, "p", value_page_view_collect_value, "p", value_page_view_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (PageViewClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) page_view_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (PageView), 0, (GInstanceInitFunc) page_view_instance_init, &g_define_type_value_table };
+ static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
+ GType page_view_type_id;
+ page_view_type_id = g_type_register_fundamental (g_type_fundamental_next (), "PageView", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&page_view_type_id__volatile, page_view_type_id);
+ }
+ return page_view_type_id__volatile;
}
-static void
-page_view_class_init (PageViewClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->get_property = page_view_get_property;
- object_class->set_property = page_view_set_property;
- object_class->finalize = page_view_finalize;
-
- signals[CHANGED] =
- g_signal_new ("changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (PageViewClass, 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 (PageViewClass, size_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (klass, sizeof (PageViewPrivate));
-
- g_object_class_install_property (object_class,
- PROP_PAGE,
- g_param_spec_object ("page",
- "page",
- "Page being rendered",
- PAGE_TYPE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+gpointer page_view_ref (gpointer instance) {
+ PageView* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
}
-static void
-page_view_init (PageView *view)
-{
- view->priv = G_TYPE_INSTANCE_GET_PRIVATE (view, PAGE_VIEW_TYPE, PageViewPrivate);
- view->priv->update_image = TRUE;
- view->priv->cursor = GDK_ARROW;
- view->priv->border_width = 1;
- view->priv->animate_n_segments = 7;
+void page_view_unref (gpointer instance) {
+ PageView* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ PAGE_VIEW_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
}
+
+
+
diff --git a/src/page-view.h b/src/page-view.h
deleted file mode 100644
index dd64197..0000000
--- a/src/page-view.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2009 Canonical Ltd.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#ifndef _PAGE_VIEW_H_
-#define _PAGE_VIEW_H_
-
-#include <glib-object.h>
-#include <gtk/gtk.h>
-#include <cairo.h>
-#include "page.h"
-
-G_BEGIN_DECLS
-
-#define PAGE_VIEW_TYPE (page_view_get_type ())
-#define PAGE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PAGE_VIEW_TYPE, PageView))
-
-
-typedef struct PageViewPrivate PageViewPrivate;
-
-typedef struct
-{
- GObject parent_instance;
- PageViewPrivate *priv;
-} PageView;
-
-typedef struct
-{
- GObjectClass parent_class;
-
- void (*changed) (PageView *view);
- void (*size_changed) (PageView *view);
-} PageViewClass;
-
-
-GType page_view_get_type (void);
-
-PageView *page_view_new (Page *page);
-
-Page *page_view_get_page (PageView *view);
-
-void page_view_set_selected (PageView *view, gboolean selected);
-
-gboolean page_view_get_selected (PageView *view);
-
-void page_view_set_x_offset (PageView *view, gint offset);
-
-void page_view_set_y_offset (PageView *view, gint offset);
-
-gint page_view_get_x_offset (PageView *view);
-
-gint page_view_get_y_offset (PageView *view);
-
-void page_view_set_width (PageView *view, gint width);
-
-void page_view_set_height (PageView *view, gint height);
-
-gint page_view_get_width (PageView *view);
-
-gint page_view_get_height (PageView *view);
-
-void page_view_button_press (PageView *view, gint x, gint y);
-
-void page_view_motion (PageView *view, gint x, gint y);
-
-void page_view_button_release (PageView *view, gint x, gint y);
-
-gint page_view_get_cursor (PageView *view);
-
-void page_view_render (PageView *view, cairo_t *context);
-
-#endif /* _PAGE_VIEW_H_ */
diff --git a/src/page-view.vala b/src/page-view.vala
new file mode 100644
index 0000000..97bcaf0
--- /dev/null
+++ b/src/page-view.vala
@@ -0,0 +1,1043 @@
+/*
+ * Copyright (C) 2009-2011 Canonical Ltd.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+public enum CropLocation
+{
+ NONE = 0,
+ MIDDLE,
+ TOP,
+ BOTTOM,
+ LEFT,
+ RIGHT,
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT
+}
+
+public class PageView
+{
+ /* Page being rendered */
+ private Page page;
+
+ /* Image to render at current resolution */
+ private Gdk.Pixbuf? image = null;
+
+ /* Border around image */
+ private bool selected;
+ private int border_width = 1;
+
+ /* True if image needs to be regenerated */
+ private bool update_image = true;
+
+ /* Direction of currently scanned image */
+ private ScanDirection scan_direction;
+
+ /* Next scan line to render */
+ private int scan_line;
+
+ /* Dimensions of image to generate */
+ private int width;
+ private int height;
+
+ /* Location to place this page */
+ private int x_offset;
+ private int y_offset;
+
+ private CropLocation crop_location;
+ private double selected_crop_px;
+ private double selected_crop_py;
+ private int selected_crop_x;
+ private int selected_crop_y;
+ private int selected_crop_w;
+ private int selected_crop_h;
+
+ /* Cursor over this page */
+ private Gdk.CursorType cursor = Gdk.CursorType.ARROW;
+
+ private int animate_n_segments = 7;
+ private int animate_segment;
+ private uint animate_timeout;
+
+ public signal void size_changed ();
+ public signal void changed ();
+
+ public PageView (Page page)
+ {
+ this.page = page;
+ page.pixels_changed.connect (page_pixels_changed_cb);
+ page.size_changed.connect (page_size_changed_cb);
+ page.crop_changed.connect (page_overlay_changed_cb);
+ page.scan_line_changed.connect (page_overlay_changed_cb);
+ page.scan_direction_changed.connect (scan_direction_changed_cb);
+ }
+
+ public Page get_page ()
+ {
+ return page;
+ }
+
+ public void set_selected (bool selected)
+ {
+ if ((this.selected && selected) || (!this.selected && !selected))
+ return;
+ this.selected = selected;
+ changed ();
+ }
+
+ public bool get_selected ()
+ {
+ return selected;
+ }
+
+ public void set_x_offset (int offset)
+ {
+ x_offset = offset;
+ }
+
+ public void set_y_offset (int offset)
+ {
+ y_offset = offset;
+ }
+
+ public int get_x_offset ()
+ {
+ return x_offset;
+ }
+
+ public int get_y_offset ()
+ {
+ return y_offset;
+ }
+
+ private uchar get_sample (uchar[] pixels, int offset, int x, int depth, int sample)
+ {
+ // FIXME
+ return 0xFF;
+ }
+
+ private void get_pixel (Page page, int x, int y, uchar[] pixel)
+ {
+ switch (page.get_scan_direction ())
+ {
+ case ScanDirection.TOP_TO_BOTTOM:
+ break;
+ case ScanDirection.BOTTOM_TO_TOP:
+ x = page.get_scan_width () - x - 1;
+ y = page.get_scan_height () - y - 1;
+ break;
+ case ScanDirection.LEFT_TO_RIGHT:
+ var t = x;
+ x = page.get_scan_width () - y - 1;
+ y = t;
+ break;
+ case ScanDirection.RIGHT_TO_LEFT:
+ var t = x;
+ x = y;
+ y = page.get_scan_height () - t - 1;
+ break;
+ }
+
+ var depth = page.get_depth ();
+ var n_channels = page.get_n_channels ();
+ unowned uchar[] pixels = page.get_pixels ();
+ var offset = page.get_rowstride () * y;
+
+ /* Optimise for 8 bit images */
+ if (depth == 8 && n_channels == 3)
+ {
+ var o = offset + x * n_channels;
+ pixel[0] = pixels[o];
+ pixel[1] = pixels[o+1];
+ pixel[2] = pixels[o+2];
+ return;
+ }
+ else if (depth == 8 && n_channels == 1)
+ {
+ pixel[0] = pixel[1] = pixel[2] = pixels[offset + x];
+ return;
+ }
+
+ /* Optimise for bitmaps */
+ else if (depth == 1 && n_channels == 1)
+ {
+ var o = offset + (x / 8);
+ pixel[0] = pixel[1] = pixel[2] = (pixels[o] & (0x80 >> (x % 8))) != 0 ? 0x00 : 0xFF;
+ return;
+ }
+
+ /* Optimise for 2 bit images */
+ else if (depth == 2 && n_channels == 1)
+ {
+ int block_shift[4] = { 6, 4, 2, 0 };
+
+ var o = offset + (x / 4);
+ var sample = (pixels[o] >> block_shift[x % 4]) & 0x3;
+ sample = sample * 255 / 3;
+
+ pixel[0] = pixel[1] = pixel[2] = (uchar) sample;
+ return;
+ }
+
+ /* Use slow method */
+ pixel[0] = get_sample (pixels, offset, x, depth, x * n_channels);
+ pixel[1] = get_sample (pixels, offset, x, depth, x * n_channels + 1);
+ pixel[2] = get_sample (pixels, offset, x, depth, x * n_channels + 2);
+ }
+
+ private void set_pixel (Page page, double l, double r, double t, double b, uchar[] output, int offset)
+ {
+ /* Decimation:
+ *
+ * Target pixel is defined by (t,l)-(b,r)
+ * It touches 16 pixels in original image
+ * It completely covers 4 pixels in original image (T,L)-(B,R)
+ * Add covered pixels and add weighted partially covered pixels.
+ * Divide by total area.
+ *
+ * l L R r
+ * +-----+-----+-----+-----+
+ * | | | | |
+ * t | +--+-----+-----+---+ |
+ * T +--+--+-----+-----+---+-+
+ * | | | | | | |
+ * | | | | | | |
+ * +--+--+-----+-----+---+-+
+ * | | | | | | |
+ * | | | | | | |
+ * B +--+--+-----+-----+---+-+
+ * | | | | | | |
+ * b | +--+-----+-----+---+ |
+ * +-----+-----+-----+-----+
+ *
+ *
+ * Interpolation:
+ *
+ * l r
+ * +-----+-----+-----+-----+
+ * | | | | |
+ * | | | | |
+ * +-----+-----+-----+-----+
+ * t | | +-+--+ | |
+ * | | | | | | |
+ * +-----+---+-+--+--+-----+
+ * b | | +-+--+ | |
+ * | | | | |
+ * +-----+-----+-----+-----+
+ * | | | | |
+ * | | | | |
+ * +-----+-----+-----+-----+
+ *
+ * Same again, just no completely covered pixels.
+ */
+
+ var L = (int) l;
+ if (L != l)
+ L++;
+ var R = (int) r;
+ var T = (int) t;
+ if (T != t)
+ T++;
+ var B = (int) b;
+
+ var red = 0.0;
+ var green = 0.0;
+ var blue = 0.0;
+
+ /* Target can fit inside one source pixel
+ * +-----+
+ * | |
+ * | +--+| +-----+-----+ +-----+ +-----+ +-----+
+ * +-+--++ or | +-++ | or | +-+ | or | +--+| or | +--+
+ * | +--+| | +-++ | | +-+ | | | || | | |
+ * | | +-----+-----+ +-----+ +-+--++ +--+--+
+ * +-----+
+ */
+ if ((r - l <= 1.0 && (int)r == (int)l) || (b - t <= 1.0 && (int)b == (int)t))
+ {
+ /* Inside */
+ if ((int)l == (int)r || (int)t == (int)b)
+ {
+ uchar p[3];
+ get_pixel (page, (int)l, (int)t, p);
+ output[offset] = p[0];
+ output[offset+1] = p[1];
+ output[offset+2] = p[2];
+ return;
+ }
+
+ /* Stradling horizontal edge */
+ if (L > R)
+ {
+ uchar p[3];
+ get_pixel (page, R, T-1, p);
+ red += p[0] * (r-l)*(T-t);
+ green += p[1] * (r-l)*(T-t);
+ blue += p[2] * (r-l)*(T-t);
+ for (var y = T; y < B; y++)
+ {
+ get_pixel (page, R, y, p);
+ red += p[0] * (r-l);
+ green += p[1] * (r-l);
+ blue += p[2] * (r-l);
+ }
+ get_pixel (page, R, B, p);
+ red += p[0] * (r-l)*(b-B);
+ green += p[1] * (r-l)*(b-B);
+ blue += p[2] * (r-l)*(b-B);
+ }
+ /* Stradling vertical edge */
+ else
+ {
+ uchar p[3];
+ get_pixel (page, L - 1, B, p);
+ red += p[0] * (b-t)*(L-l);
+ green += p[1] * (b-t)*(L-l);
+ blue += p[2] * (b-t)*(L-l);
+ for (var x = L; x < R; x++) {
+ get_pixel (page, x, B, p);
+ red += p[0] * (b-t);
+ green += p[1] * (b-t);
+ blue += p[2] * (b-t);
+ }
+ get_pixel (page, R, B, p);
+ red += p[0] * (b-t)*(r-R);
+ green += p[1] * (b-t)*(r-R);
+ blue += p[2] * (b-t)*(r-R);
+ }
+
+ var scale = 1.0 / ((r - l) * (b - t));
+ output[offset] = (uchar)(red * scale + 0.5);
+ output[offset+1] = (uchar)(green * scale + 0.5);
+ output[offset+2] = (uchar)(blue * scale + 0.5);
+ return;
+ }
+
+ /* Add the middle pixels */
+ for (var x = L; x < R; x++)
+ {
+ for (var y = T; y < B; y++)
+ {
+ uchar p[3];
+ get_pixel (page, x, y, p);
+ red += p[0];
+ green += p[1];
+ blue += p[2];
+ }
+ }
+
+ /* Add the weighted top and bottom pixels */
+ for (var x = L; x < R; x++)
+ {
+ if (t != T)
+ {
+ uchar p[3];
+ get_pixel (page, x, T - 1, p);
+ red += p[0] * (T - t);
+ green += p[1] * (T - t);
+ blue += p[2] * (T - t);
+ }
+
+ if (b != B)
+ {
+ uchar p[3];
+ get_pixel (page, x, B, p);
+ red += p[0] * (b - B);
+ green += p[1] * (b - B);
+ blue += p[2] * (b - B);
+ }
+ }
+
+ /* Add the left and right pixels */
+ for (var y = T; y < B; y++)
+ {
+ if (l != L)
+ {
+ uchar p[3];
+ get_pixel (page, L - 1, y, p);
+ red += p[0] * (L - l);
+ green += p[1] * (L - l);
+ blue += p[2] * (L - l);
+ }
+
+ if (r != R)
+ {
+ uchar p[3];
+ get_pixel (page, R, y, p);
+ red += p[0] * (r - R);
+ green += p[1] * (r - R);
+ blue += p[2] * (r - R);
+ }
+ }
+
+ /* Add the corner pixels */
+ if (l != L && t != T)
+ {
+ uchar p[3];
+ get_pixel (page, L - 1, T - 1, p);
+ red += p[0] * (L - l)*(T - t);
+ green += p[1] * (L - l)*(T - t);
+ blue += p[2] * (L - l)*(T - t);
+ }
+ if (r != R && t != T)
+ {
+ uchar p[3];
+ get_pixel (page, R, T - 1, p);
+ red += p[0] * (r - R)*(T - t);
+ green += p[1] * (r - R)*(T - t);
+ blue += p[2] * (r - R)*(T - t);
+ }
+ if (r != R && b != B)
+ {
+ uchar p[3];
+ get_pixel (page, R, B, p);
+ red += p[0] * (r - R)*(b - B);
+ green += p[1] * (r - R)*(b - B);
+ blue += p[2] * (r - R)*(b - B);
+ }
+ if (l != L && b != B)
+ {
+ uchar p[3];
+ get_pixel (page, L - 1, B, p);
+ red += p[0] * (L - l)*(b - B);
+ green += p[1] * (L - l)*(b - B);
+ blue += p[2] * (L - l)*(b - B);
+ }
+
+ /* Scale pixel values and clamp in range [0, 255] */
+ var scale = 1.0 / ((r - l) * (b - t));
+ output[offset] = (uchar)(red * scale + 0.5);
+ output[offset+1] = (uchar)(green * scale + 0.5);
+ output[offset+2] = (uchar)(blue * scale + 0.5);
+ }
+
+ private void update_preview (Page page, ref Gdk.Pixbuf? output_image, int output_width, int output_height,
+ ScanDirection scan_direction, int old_scan_line, int scan_line)
+ {
+ var input_width = page.get_width ();
+ var input_height = page.get_height ();
+
+ /* Create new image if one does not exist or has changed size */
+ int L, R, T, B;
+ if (output_image == null ||
+ output_image.get_width () != output_width ||
+ output_image.get_height () != output_height)
+ {
+ output_image = new Gdk.Pixbuf (Gdk.Colorspace.RGB,
+ false,
+ 8,
+ output_width,
+ output_height);
+
+ /* Update entire image */
+ L = 0;
+ R = output_width - 1;
+ T = 0;
+ B = output_height - 1;
+ }
+ /* Otherwise only update changed area */
+ else
+ {
+ switch (scan_direction)
+ {
+ case ScanDirection.TOP_TO_BOTTOM:
+ L = 0;
+ R = output_width - 1;
+ T = (int)((double)old_scan_line * output_height / input_height);
+ B = (int)((double)scan_line * output_height / input_height + 0.5);
+ break;
+ case ScanDirection.LEFT_TO_RIGHT:
+ L = (int)((double)old_scan_line * output_width / input_width);
+ R = (int)((double)scan_line * output_width / input_width + 0.5);
+ T = 0;
+ B = output_height - 1;
+ break;
+ case ScanDirection.BOTTOM_TO_TOP:
+ L = 0;
+ R = output_width - 1;
+ T = (int)((double)(input_height - scan_line) * output_height / input_height);
+ B = (int)((double)(input_height - old_scan_line) * output_height / input_height + 0.5);
+ break;
+ case ScanDirection.RIGHT_TO_LEFT:
+ L = (int)((double)(input_width - scan_line) * output_width / input_width);
+ R = (int)((double)(input_width - old_scan_line) * output_width / input_width + 0.5);
+ T = 0;
+ B = output_height - 1;
+ break;
+ default:
+ L = R = B = T = 0;
+ break;
+ }
+ }
+
+ /* FIXME: There's an off by one error in there somewhere... */
+ if (R >= output_width)
+ R = output_width - 1;
+ if (B >= output_height)
+ B = output_height - 1;
+
+ return_if_fail (L >= 0);
+ return_if_fail (R < output_width);
+ return_if_fail (T >= 0);
+ return_if_fail (B < output_height);
+ return_if_fail (output_image != null);
+
+ unowned uchar[] output = output_image.get_pixels ();
+ var output_rowstride = output_image.get_rowstride ();
+ var output_n_channels = output_image.get_n_channels ();
+
+ if (!page.has_data ())
+ {
+ for (var x = L; x <= R; x++)
+ for (var y = T; y <= B; y++)
+ {
+ var o = output_rowstride * y + x * output_n_channels;
+ output[o] = output[o+1] = output[o+2] = 0xFF;
+ }
+ return;
+ }
+
+ /* Update changed area */
+ for (var x = L; x <= R; x++)
+ {
+ var l = (double)x * input_width / output_width;
+ var r = (double)(x + 1) * input_width / output_width;
+
+ for (var y = T; y <= B; y++)
+ {
+ var t = (double)y * input_height / output_height;
+ var b = (double)(y + 1) * input_height / output_height;
+
+ set_pixel (page,
+ l, r, t, b,
+ output, output_rowstride * y + x * output_n_channels);
+ }
+ }
+ }
+
+ private int get_preview_width ()
+ {
+ return width - border_width * 2;
+ }
+
+ private int get_preview_height ()
+ {
+ return height - border_width * 2;
+ }
+
+ private void update_page_view ()
+ {
+ if (!update_image)
+ return;
+
+ var old_scan_line = scan_line;
+ var scan_line = page.get_scan_line ();
+
+ /* Delete old image if scan direction changed */
+ var left_steps = scan_direction - page.get_scan_direction ();
+ if (left_steps != 0 && image != null)
+ image = null;
+ scan_direction = page.get_scan_direction ();
+
+ update_preview (page,
+ ref image,
+ get_preview_width (),
+ get_preview_height (),
+ page.get_scan_direction (), old_scan_line, scan_line);
+
+ update_image = false;
+ this.scan_line = scan_line;
+ }
+
+ private int page_to_screen_x (int x)
+ {
+ return (int) ((double)x * get_preview_width () / page.get_width () + 0.5);
+ }
+
+ private int page_to_screen_y (int y)
+ {
+ return (int) ((double)y * get_preview_height () / page.get_height () + 0.5);
+ }
+
+ private int screen_to_page_x (int x)
+ {
+ return (int) ((double)x * page.get_width () / get_preview_width () + 0.5);
+ }
+
+ private int screen_to_page_y (int y)
+ {
+ return (int) ((double)y * page.get_height () / get_preview_height () + 0.5);
+ }
+
+ private CropLocation get_crop_location (int x, int y)
+ {
+ if (!page.has_crop ())
+ return 0;
+
+ int cx, cy, cw, ch;
+ page.get_crop (out cx, out cy, out cw, out ch);
+ var dx = page_to_screen_x (cx);
+ var dy = page_to_screen_y (cy);
+ var dw = page_to_screen_x (cw);
+ var dh = page_to_screen_y (ch);
+ var ix = x - dx;
+ var iy = y - dy;
+
+ if (ix < 0 || ix > dw || iy < 0 || iy > dh)
+ return CropLocation.NONE;
+
+ /* Can't resize named crops */
+ var name = page.get_named_crop ();
+ if (name != null)
+ return CropLocation.MIDDLE;
+
+ /* Adjust borders so can select */
+ int crop_border = 20;
+ if (dw < crop_border * 3)
+ crop_border = dw / 3;
+ if (dh < crop_border * 3)
+ crop_border = dh / 3;
+
+ /* Top left */
+ if (ix < crop_border && iy < crop_border)
+ return CropLocation.TOP_LEFT;
+ /* Top right */
+ if (ix > dw - crop_border && iy < crop_border)
+ return CropLocation.TOP_RIGHT;
+ /* Bottom left */
+ if (ix < crop_border && iy > dh - crop_border)
+ return CropLocation.BOTTOM_LEFT;
+ /* Bottom right */
+ if (ix > dw - crop_border && iy > dh - crop_border)
+ return CropLocation.BOTTOM_RIGHT;
+
+ /* Left */
+ if (ix < crop_border)
+ return CropLocation.LEFT;
+ /* Right */
+ if (ix > dw - crop_border)
+ return CropLocation.RIGHT;
+ /* Top */
+ if (iy < crop_border)
+ return CropLocation.TOP;
+ /* Bottom */
+ if (iy > dh - crop_border)
+ return CropLocation.BOTTOM;
+
+ /* In the middle */
+ return CropLocation.MIDDLE;
+ }
+
+ public void button_press (int x, int y)
+ {
+ CropLocation location;
+
+ /* See if selecting crop */
+ location = get_crop_location (x, y);;
+ if (location != CropLocation.NONE)
+ {
+ crop_location = location;
+ selected_crop_px = x;
+ selected_crop_py = y;
+ page.get_crop (out selected_crop_x,
+ out selected_crop_y,
+ out selected_crop_w,
+ out selected_crop_h);
+ }
+ }
+
+ public void motion (int x, int y)
+ {
+ var location = get_crop_location (x, y);
+ Gdk.CursorType cursor;
+ switch (location)
+ {
+ case CropLocation.MIDDLE:
+ cursor = Gdk.CursorType.HAND1;
+ break;
+ case CropLocation.TOP:
+ cursor = Gdk.CursorType.TOP_SIDE;
+ break;
+ case CropLocation.BOTTOM:
+ cursor = Gdk.CursorType.BOTTOM_SIDE;
+ break;
+ case CropLocation.LEFT:
+ cursor = Gdk.CursorType.LEFT_SIDE;
+ break;
+ case CropLocation.RIGHT:
+ cursor = Gdk.CursorType.RIGHT_SIDE;
+ break;
+ case CropLocation.TOP_LEFT:
+ cursor = Gdk.CursorType.TOP_LEFT_CORNER;
+ break;
+ case CropLocation.TOP_RIGHT:
+ cursor = Gdk.CursorType.TOP_RIGHT_CORNER;
+ break;
+ case CropLocation.BOTTOM_LEFT:
+ cursor = Gdk.CursorType.BOTTOM_LEFT_CORNER;
+ break;
+ case CropLocation.BOTTOM_RIGHT:
+ cursor = Gdk.CursorType.BOTTOM_RIGHT_CORNER;
+ break;
+ default:
+ cursor = Gdk.CursorType.ARROW;
+ break;
+ }
+
+ if (crop_location == CropLocation.NONE)
+ {
+ this.cursor = cursor;
+ return;
+ }
+
+ /* Move the crop */
+ var pw = page.get_width ();
+ var ph = page.get_height ();
+ int cx, cy, cw, ch;
+ page.get_crop (out cx, out cy, out cw, out ch);
+
+ var dx = screen_to_page_x (x - (int) selected_crop_px);
+ var dy = screen_to_page_y (y - (int) selected_crop_py);
+
+ var new_x = selected_crop_x;
+ var new_y = selected_crop_y;
+ var new_w = selected_crop_w;
+ var new_h = selected_crop_h;
+
+ /* Limit motion to remain within page and minimum crop size */
+ var min_size = screen_to_page_x (15);
+ if (crop_location == CropLocation.TOP_LEFT ||
+ crop_location == CropLocation.LEFT ||
+ crop_location == CropLocation.BOTTOM_LEFT)
+ {
+ if (dx > new_w - min_size)
+ dx = new_w - min_size;
+ if (new_x + dx < 0)
+ dx = -new_x;
+ }
+ if (crop_location == CropLocation.TOP_LEFT ||
+ crop_location == CropLocation.TOP ||
+ crop_location == CropLocation.TOP_RIGHT)
+ {
+ if (dy > new_h - min_size)
+ dy = new_h - min_size;
+ if (new_y + dy < 0)
+ dy = -new_y;
+ }
+
+ if (crop_location == CropLocation.TOP_RIGHT ||
+ crop_location == CropLocation.RIGHT ||
+ crop_location == CropLocation.BOTTOM_RIGHT)
+ {
+ if (dx < min_size - new_w)
+ dx = min_size - new_w;
+ if (new_x + new_w + dx > pw)
+ dx = pw - new_x - new_w;
+ }
+ if (crop_location == CropLocation.BOTTOM_LEFT ||
+ crop_location == CropLocation.BOTTOM ||
+ crop_location == CropLocation.BOTTOM_RIGHT)
+ {
+ if (dy < min_size - new_h)
+ dy = min_size - new_h;
+ if (new_y + new_h + dy > ph)
+ dy = ph - new_y - new_h;
+ }
+ if (crop_location == CropLocation.MIDDLE)
+ {
+ if (new_x + dx + new_w > pw)
+ dx = pw - new_x - new_w;
+ if (new_x + dx < 0)
+ dx = -new_x;
+ if (new_y + dy + new_h > ph)
+ dy = ph - new_y - new_h;
+ if (new_y + dy < 0)
+ dy = -new_y;
+ }
+
+ /* Move crop */
+ if (crop_location == CropLocation.MIDDLE)
+ {
+ new_x += dx;
+ new_y += dy;
+ }
+ if (crop_location == CropLocation.TOP_LEFT ||
+ crop_location == CropLocation.LEFT ||
+ crop_location == CropLocation.BOTTOM_LEFT)
+ {
+ new_x += dx;
+ new_w -= dx;
+ }
+ if (crop_location == CropLocation.TOP_LEFT ||
+ crop_location == CropLocation.TOP ||
+ crop_location == CropLocation.TOP_RIGHT)
+ {
+ new_y += dy;
+ new_h -= dy;
+ }
+
+ if (crop_location == CropLocation.TOP_RIGHT ||
+ crop_location == CropLocation.RIGHT ||
+ crop_location == CropLocation.BOTTOM_RIGHT)
+ new_w += dx;
+ if (crop_location == CropLocation.BOTTOM_LEFT ||
+ crop_location == CropLocation.BOTTOM ||
+ crop_location == CropLocation.BOTTOM_RIGHT)
+ new_h += dy;
+
+ page.move_crop (new_x, new_y);
+
+ /* If reshaped crop, must be a custom crop */
+ if (new_w != cw || new_h != ch)
+ page.set_custom_crop (new_w, new_h);
+ }
+
+ public void button_release (int x, int y)
+ {
+ /* Complete crop */
+ crop_location = CropLocation.NONE;
+ changed ();
+ }
+
+ public Gdk.CursorType get_cursor ()
+ {
+ return cursor;
+ }
+
+ private bool animation_cb ()
+ {
+ animate_segment = (animate_segment + 1) % animate_n_segments;
+ changed ();
+ return true;
+ }
+
+ private void update_animation ()
+ {
+ bool animate, is_animating;
+
+ animate = page.is_scanning () && !page.has_data ();
+ is_animating = animate_timeout != 0;
+ if (animate == is_animating)
+ return;
+
+ if (animate)
+ {
+ animate_segment = 0;
+ if (animate_timeout == 0)
+ animate_timeout = Timeout.add (150, animation_cb);
+ }
+ else
+ {
+ if (animate_timeout != 0)
+ Source.remove (animate_timeout);
+ animate_timeout = 0;
+ }
+ }
+
+ public void render (Cairo.Context context)
+ {
+ update_animation ();
+ update_page_view ();
+
+ var w = get_preview_width ();
+ var h = get_preview_height ();
+
+ context.set_line_width (1);
+ context.translate (x_offset, y_offset);
+
+ /* Draw page border */
+ context.set_source_rgb (0, 0, 0);
+ context.set_line_width (border_width);
+ context.rectangle ((double)border_width / 2,
+ (double)border_width / 2,
+ width - border_width,
+ height - border_width);
+ context.stroke ();
+
+ /* Draw image */
+ context.translate (border_width, border_width);
+ Gdk.cairo_set_source_pixbuf (context, image, 0, 0);
+ context.paint ();
+
+ /* Draw throbber */
+ if (page.is_scanning () && !page.has_data ())
+ {
+ double outer_radius;
+ if (w > h)
+ outer_radius = 0.15 * w;
+ else
+ outer_radius = 0.15 * h;
+ var arc = Math.PI / animate_n_segments;
+
+ /* Space circles */
+ var x = outer_radius * Math.sin (arc);
+ var y = outer_radius * (Math.cos (arc) - 1.0);
+ var inner_radius = 0.6 * Math.sqrt (x*x + y*y);
+
+ double offset = 0.0;
+ for (var i = 0; i < animate_n_segments; i++, offset += arc * 2)
+ {
+ x = w / 2 + outer_radius * Math.sin (offset);
+ y = h / 2 - outer_radius * Math.cos (offset);
+ context.arc (x, y, inner_radius, 0, 2 * Math.PI);
+
+ if (i == animate_segment)
+ {
+ context.set_source_rgb (0.75, 0.75, 0.75);
+ context.fill_preserve ();
+ }
+
+ context.set_source_rgb (0.5, 0.5, 0.5);
+ context.stroke ();
+ }
+ }
+
+ /* Draw scan line */
+ if (page.is_scanning () && page.get_scan_line () > 0)
+ {
+ var scan_line = page.get_scan_line ();
+
+ double s;
+ double x1, y1, x2, y2;
+ switch (page.get_scan_direction ())
+ {
+ case ScanDirection.TOP_TO_BOTTOM:
+ s = page_to_screen_y (scan_line);
+ x1 = 0; y1 = s + 0.5;
+ x2 = w; y2 = s + 0.5;
+ break;
+ case ScanDirection.BOTTOM_TO_TOP:
+ s = page_to_screen_y (scan_line);
+ x1 = 0; y1 = h - s + 0.5;
+ x2 = w; y2 = h - s + 0.5;
+ break;
+ case ScanDirection.LEFT_TO_RIGHT:
+ s = page_to_screen_x (scan_line);
+ x1 = s + 0.5; y1 = 0;
+ x2 = s + 0.5; y2 = h;
+ break;
+ case ScanDirection.RIGHT_TO_LEFT:
+ s = page_to_screen_x (scan_line);
+ x1 = w - s + 0.5; y1 = 0;
+ x2 = w - s + 0.5; y2 = h;
+ break;
+ default:
+ x1 = y1 = x2 = y2 = 0;
+ break;
+ }
+
+ context.move_to (x1, y1);
+ context.line_to (x2, y2);
+ context.set_source_rgb (1.0, 0.0, 0.0);
+ context.stroke ();
+ }
+
+ /* Draw crop */
+ if (page.has_crop ())
+ {
+ int x, y, crop_width, crop_height;
+ page.get_crop (out x, out y, out crop_width, out crop_height);
+
+ var dx = page_to_screen_x (x);
+ var dy = page_to_screen_y (y);
+ var dw = page_to_screen_x (crop_width);
+ var dh = page_to_screen_y (crop_height);
+
+ /* Shade out cropped area */
+ context.rectangle (0, 0, w, h);
+ context.new_sub_path ();
+ context.rectangle (dx, dy, dw, dh);
+ context.set_fill_rule (Cairo.FillRule.EVEN_ODD);
+ context.set_source_rgba (0.25, 0.25, 0.25, 0.2);
+ context.fill ();
+
+ /* Show new edge */
+ context.rectangle (dx - 1.5, dy - 1.5, dw + 3, dh + 3);
+ context.set_source_rgb (1.0, 1.0, 1.0);
+ context.stroke ();
+ context.rectangle (dx - 0.5, dy - 0.5, dw + 1, dh + 1);
+ context.set_source_rgb (0.0, 0.0, 0.0);
+ context.stroke ();
+ }
+ }
+
+ public void set_width (int width)
+ {
+ // FIXME: Automatically update when get updated image
+ var height = (int) ((double)width * page.get_height () / page.get_width ());
+ if (this.width == width && this.height == height)
+ return;
+
+ this.width = width;
+ this.height = height;
+
+ /* Regenerate image */
+ update_image = true;
+
+ size_changed ();
+ changed ();
+ }
+
+ public void set_height (int height)
+ {
+ // FIXME: Automatically update when get updated image
+ var width = (int) ((double)height * page.get_width () / page.get_height ());
+ if (this.width == width && this.height == height)
+ return;
+
+ this.width = width;
+ this.height = height;
+
+ /* Regenerate image */
+ update_image = true;
+
+ size_changed ();
+ changed ();
+ }
+
+ public int get_width ()
+ {
+ return width;
+ }
+
+ public int get_height ()
+ {
+ return height;
+ }
+
+ private void page_pixels_changed_cb (Page p)
+ {
+ /* Regenerate image */
+ update_image = true;
+ changed ();
+ }
+
+ private void page_size_changed_cb (Page p)
+ {
+ /* Regenerate image */
+ update_image = true;
+ size_changed ();
+ changed ();
+ }
+
+ private void page_overlay_changed_cb (Page p)
+ {
+ changed ();
+ }
+
+ private void scan_direction_changed_cb (Page p)
+ {
+ /* Regenerate image */
+ update_image = true;
+ size_changed ();
+ changed ();
+ }
+}
diff --git a/src/page.c b/src/page.c
index ec21088..581c577 100644
--- a/src/page.c
+++ b/src/page.c
@@ -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);
}
+
+
+
diff --git a/src/page.h b/src/page.h
deleted file mode 100644
index 993029f..0000000
--- a/src/page.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2009 Canonical Ltd.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#ifndef _PAGE_H_
-#define _PAGE_H_
-
-#include <glib-object.h>
-#include <gio/gio.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include "scanner.h"
-
-G_BEGIN_DECLS
-
-#define PAGE_TYPE (page_get_type ())
-#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PAGE_TYPE, Page))
-
-typedef enum
-{
- TOP_TO_BOTTOM,
- LEFT_TO_RIGHT,
- BOTTOM_TO_TOP,
- RIGHT_TO_LEFT
-} ScanDirection;
-
-
-typedef struct PagePrivate PagePrivate;
-
-typedef struct
-{
- GObject parent_instance;
- PagePrivate *priv;
-} Page;
-
-typedef struct
-{
- GObjectClass parent_class;
-
- void (*pixels_changed) (Page *page);
- void (*size_changed) (Page *page);
- void (*scan_line_changed) (Page *page);
- void (*scan_direction_changed) (Page *page);
- void (*crop_changed) (Page *page);
-} PageClass;
-
-
-GType page_get_type (void);
-
-Page *page_new (gint width, gint height, gint dpi, ScanDirection scan_direction);
-
-void page_set_page_info (Page *page, ScanPageInfo *info);
-
-gint page_get_dpi (Page *page);
-
-gint page_get_width (Page *page);
-
-gint page_get_height (Page *page);
-
-gint page_get_depth (Page *page);
-
-gint page_get_n_channels (Page *page);
-
-gint page_get_rowstride (Page *page);
-
-const guchar *page_get_pixels (Page *page);
-
-guchar *page_get_pixel (Page *page, gint x, gint y);
-
-gboolean page_is_landscape (Page *page);
-
-gint page_get_scan_width (Page *page);
-
-gint page_get_scan_height (Page *page);
-
-void page_set_color_profile (Page *page, const gchar *color_profile);
-
-const gchar *page_get_color_profile (Page *page);
-
-void page_start (Page *page);
-
-gboolean page_is_scanning (Page *page);
-
-gboolean page_has_data (Page *page);
-
-gboolean page_is_color (Page *page);
-
-gint page_get_scan_line (Page *page);
-
-void page_parse_scan_line (Page *page, ScanLine *line);
-
-void page_finish (Page *page);
-
-ScanDirection page_get_scan_direction (Page *page);
-
-void page_rotate_left (Page *page);
-
-void page_rotate_right (Page *page);
-
-void page_set_no_crop (Page *page);
-
-void page_set_custom_crop (Page *page, gint width, gint height);
-
-void page_set_named_crop (Page *page, const gchar *name);
-
-void page_move_crop (Page *page, gint x, gint y);
-
-void page_rotate_crop (Page *page);
-
-gboolean page_has_crop (Page *page);
-
-void page_get_crop (Page *page, gint *x, gint *y, gint *width, gint *height);
-
-gchar *page_get_named_crop (Page *page);
-
-GdkPixbuf *page_get_image (Page *page, gboolean apply_crop);
-
-gboolean page_save (Page *page, const gchar *type, GFile *file, GError **error);
-
-#endif /* _PAGE_H_ */
diff --git a/src/page.vala b/src/page.vala
new file mode 100644
index 0000000..ef7ddb6
--- /dev/null
+++ b/src/page.vala
@@ -0,0 +1,735 @@
+/*
+ * Copyright (C) 2009-2011 Canonical Ltd.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+public enum ScanDirection
+{
+ TOP_TO_BOTTOM,
+ LEFT_TO_RIGHT,
+ BOTTOM_TO_TOP,
+ RIGHT_TO_LEFT
+}
+
+public class Page
+{
+ /* Resolution of page */
+ private int dpi;
+
+ /* Number of rows in this page or -1 if currently unknown */
+ private int expected_rows;
+
+ /* Bit depth */
+ private int depth;
+
+ /* Color profile */
+ private string? color_profile;
+
+ /* Scanned image data */
+ private int width;
+ private int n_rows;
+ private int rowstride;
+ private int n_channels;
+ private uchar[] pixels;
+
+ /* Page is getting data */
+ private bool scanning;
+
+ /* true if have some page data */
+ private bool has_data_;
+
+ /* Expected next scan row */
+ private int scan_line;
+
+ /* Rotation of scanned data */
+ private ScanDirection scan_direction = ScanDirection.TOP_TO_BOTTOM;
+
+ /* Crop */
+ private bool has_crop_;
+ private string? crop_name;
+ private int crop_x;
+ private int crop_y;
+ private int crop_width;
+ private int crop_height;
+
+ public signal void pixels_changed ();
+ public signal void size_changed ();
+ public signal void scan_line_changed ();
+ public signal void scan_direction_changed ();
+ public signal void crop_changed ();
+
+ public Page (int width, int height, int dpi, ScanDirection scan_direction)
+ {
+ if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP)
+ {
+ this.width = width;
+ n_rows = height;
+ }
+ else
+ {
+ this.width = height;
+ n_rows = width;
+ }
+ this.dpi = dpi;
+ this.scan_direction = scan_direction;
+ }
+
+ public void set_page_info (ScanPageInfo info)
+ {
+ expected_rows = info.height;
+ dpi = (int) info.dpi;
+
+ /* Create a white page */
+ width = info.width;
+ n_rows = info.height;
+ /* Variable height, try 50% of the width for now */
+ if (n_rows < 0)
+ n_rows = width / 2;
+ depth = info.depth;
+ n_channels = info.n_channels;
+ rowstride = (width * depth * n_channels + 7) / 8;
+ pixels.resize (n_rows * rowstride);
+ return_if_fail (pixels != null);
+
+ /* Fill with white */
+ if (depth == 1)
+ Memory.set (pixels, 0x00, n_rows * rowstride);
+ else
+ Memory.set (pixels, 0xFF, n_rows * rowstride);
+
+ size_changed ();
+ pixels_changed ();
+ }
+
+ public void start ()
+ {
+ scanning = true;
+ scan_line_changed ();
+ }
+
+ public bool is_scanning ()
+ {
+ return scanning;
+ }
+
+ public bool has_data ()
+ {
+ return has_data_;
+ }
+
+ public bool is_color ()
+ {
+ return n_channels > 1;
+ }
+
+ public int get_scan_line ()
+ {
+ return scan_line;
+ }
+
+ private void parse_line (ScanLine line, int n, out bool size_changed)
+ {
+ int line_number;
+
+ line_number = line.number + n;
+
+ /* Extend image if necessary */
+ size_changed = false;
+ while (line_number >= get_scan_height ())
+ {
+ int rows;
+
+ /* Extend image */
+ rows = n_rows;
+ n_rows = rows + width / 2;
+ debug ("Extending image from %d lines to %d lines", rows, n_rows);
+ pixels.resize (n_rows * rowstride);
+
+ size_changed = true;
+ }
+
+ /* Copy in new row */
+ var offset = line_number * rowstride;
+ var line_offset = n * line.data_length;
+ for (var i = 0; i < line.data_length; i++)
+ pixels[offset+i] = line.data[line_offset+i];
+
+ scan_line = line_number;
+ }
+
+ public void parse_scan_line (ScanLine line)
+ {
+ bool size_has_changed = false;
+ for (var i = 0; i < line.n_lines; i++)
+ parse_line (line, i, out size_has_changed);
+
+ has_data_ = true;
+
+ if (size_has_changed)
+ size_changed ();
+ scan_line_changed ();
+ pixels_changed ();
+ }
+
+ public void finish ()
+ {
+ bool size_has_changed = false;
+
+ /* Trim page */
+ if (expected_rows < 0 &&
+ scan_line != get_scan_height ())
+ {
+ int rows;
+
+ rows = n_rows;
+ n_rows = scan_line;
+ pixels.resize (n_rows * rowstride);
+ debug ("Trimming page from %d lines to %d lines", rows, n_rows);
+
+ size_has_changed = true;
+ }
+ scanning = false;
+
+ if (size_has_changed)
+ size_changed ();
+ scan_line_changed ();
+ }
+
+ public ScanDirection get_scan_direction ()
+ {
+ return scan_direction;
+ }
+
+ private void set_scan_direction (ScanDirection direction)
+ {
+ int left_steps, t;
+ bool size_has_changed = false;
+ int width, height;
+
+ if (scan_direction == direction)
+ return;
+
+ /* Work out how many times it has been rotated to the left */
+ left_steps = direction - scan_direction;
+ if (left_steps < 0)
+ left_steps += 4;
+ if (left_steps != 2)
+ size_has_changed = true;
+
+ width = get_width ();
+ height = get_height ();
+
+ /* Rotate crop */
+ if (has_crop_)
+ {
+ switch (left_steps)
+ {
+ /* 90 degrees counter-clockwise */
+ case 1:
+ t = crop_x;
+ crop_x = crop_y;
+ crop_y = width - (t + crop_width);
+ t = crop_width;
+ crop_width = crop_height;
+ crop_height = t;
+ break;
+ /* 180 degrees */
+ case 2:
+ crop_x = width - (crop_x + crop_width);
+ crop_y = width - (crop_y + crop_height);
+ break;
+ /* 90 degrees clockwise */
+ case 3:
+ t = crop_y;
+ crop_y = crop_x;
+ crop_x = height - (t + crop_height);
+ t = crop_width;
+ crop_width = crop_height;
+ crop_height = t;
+ break;
+ }
+ }
+
+ scan_direction = direction;
+ if (size_has_changed)
+ size_changed ();
+ scan_direction_changed ();
+ if (has_crop_)
+ crop_changed ();
+ }
+
+ public void rotate_left ()
+ {
+ var direction = scan_direction;
+ switch (direction)
+ {
+ case ScanDirection.TOP_TO_BOTTOM:
+ direction = ScanDirection.LEFT_TO_RIGHT;
+ break;
+ case ScanDirection.LEFT_TO_RIGHT:
+ direction = ScanDirection.BOTTOM_TO_TOP;
+ break;
+ case ScanDirection.BOTTOM_TO_TOP:
+ direction = ScanDirection.RIGHT_TO_LEFT;
+ break;
+ case ScanDirection.RIGHT_TO_LEFT:
+ direction = ScanDirection.TOP_TO_BOTTOM;
+ break;
+ }
+ set_scan_direction (direction);
+ }
+
+ public void rotate_right ()
+ {
+ var direction = scan_direction;
+ switch (direction)
+ {
+ case ScanDirection.TOP_TO_BOTTOM:
+ direction = ScanDirection.RIGHT_TO_LEFT;
+ break;
+ case ScanDirection.LEFT_TO_RIGHT:
+ direction = ScanDirection.TOP_TO_BOTTOM;
+ break;
+ case ScanDirection.BOTTOM_TO_TOP:
+ direction = ScanDirection.LEFT_TO_RIGHT;
+ break;
+ case ScanDirection.RIGHT_TO_LEFT:
+ direction = ScanDirection.BOTTOM_TO_TOP;
+ break;
+ }
+ set_scan_direction (direction);
+ }
+
+ public int get_dpi ()
+ {
+ return dpi;
+ }
+
+ public bool is_landscape ()
+ {
+ return get_width () > get_height ();
+ }
+
+ public int get_width ()
+ {
+ if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP)
+ return width;
+ else
+ return n_rows;
+ }
+
+ public int get_height ()
+ {
+ if (scan_direction == ScanDirection.TOP_TO_BOTTOM || scan_direction == ScanDirection.BOTTOM_TO_TOP)
+ return n_rows;
+ else
+ return width;
+ }
+
+ public int get_depth ()
+ {
+ return depth;
+ }
+
+ public int get_n_channels ()
+ {
+ return n_channels;
+ }
+
+ public int get_rowstride ()
+ {
+ return rowstride;
+ }
+
+ public int get_scan_width ()
+ {
+ return width;
+ }
+
+ public int get_scan_height ()
+ {
+ return n_rows;
+ }
+
+ public void set_color_profile (string? color_profile)
+ {
+ this.color_profile = color_profile;
+ }
+
+ public string get_color_profile ()
+ {
+ return color_profile;
+ }
+
+ public void set_no_crop ()
+ {
+ if (!has_crop_)
+ return;
+ has_crop_ = false;
+ crop_changed ();
+ }
+
+ public void set_custom_crop (int width, int height)
+ {
+ //int pw, ph;
+
+ return_if_fail (width >= 1);
+ return_if_fail (height >= 1);
+
+ if (crop_name == null && has_crop_ && crop_width == width && crop_height == height)
+ return;
+ crop_name = null;
+ has_crop_ = true;
+
+ crop_width = width;
+ crop_height = height;
+
+ /*pw = get_width ();
+ ph = get_height ();
+ if (crop_width < pw)
+ crop_x = (pw - crop_width) / 2;
+ else
+ crop_x = 0;
+ if (crop_height < ph)
+ crop_y = (ph - crop_height) / 2;
+ else
+ crop_y = 0;*/
+
+ crop_changed ();
+ }
+
+ public void set_named_crop (string name)
+ {
+ double width, height;
+ switch (name)
+ {
+ case "A4":
+ width = 8.3;
+ height = 11.7;
+ break;
+ case "A5":
+ width = 5.8;
+ height = 8.3;
+ break;
+ case "A6":
+ width = 4.1;
+ height = 5.8;
+ break;
+ case "letter":
+ width = 8.5;
+ height = 11;
+ break;
+ case "legal":
+ width = 8.5;
+ height = 14;
+ break;
+ case "4x6":
+ width = 4;
+ height = 6;
+ break;
+ default:
+ warning ("Unknown paper size '%s'", name);
+ return;
+ }
+
+ crop_name = name;
+ has_crop_ = true;
+
+ var pw = get_width ();
+ var ph = get_height ();
+
+ /* Rotate to match original aspect */
+ if (pw > ph)
+ {
+ double t;
+ t = width;
+ width = height;
+ height = t;
+ }
+
+ /* Custom crop, make slightly smaller than original */
+ crop_width = (int) (width * dpi + 0.5);
+ crop_height = (int) (height * dpi + 0.5);
+
+ if (crop_width < pw)
+ crop_x = (pw - crop_width) / 2;
+ else
+ crop_x = 0;
+ if (crop_height < ph)
+ crop_y = (ph - crop_height) / 2;
+ else
+ crop_y = 0;
+ crop_changed ();
+ }
+
+ public void move_crop (int x, int y)
+ {
+ return_if_fail (x >= 0);
+ return_if_fail (y >= 0);
+ return_if_fail (x < get_width ());
+ return_if_fail (y < get_height ());
+
+ crop_x = x;
+ crop_y = y;
+ crop_changed ();
+ }
+
+ public void rotate_crop ()
+ {
+ int t;
+
+ if (!has_crop_)
+ return;
+
+ t = crop_width;
+ crop_width = crop_height;
+ crop_height = t;
+
+ /* Clip custom crops */
+ if (crop_name == null)
+ {
+ int w, h;
+
+ w = get_width ();
+ h = get_height ();
+
+ if (crop_x + crop_width > w)
+ crop_x = w - crop_width;
+ if (crop_x < 0)
+ {
+ crop_x = 0;
+ crop_width = w;
+ }
+ if (crop_y + crop_height > h)
+ crop_y = h - crop_height;
+ if (crop_y < 0)
+ {
+ crop_y = 0;
+ crop_height = h;
+ }
+ }
+
+ crop_changed ();
+ }
+
+ public bool has_crop ()
+ {
+ return has_crop_;
+ }
+
+ public void get_crop (out int x, out int y, out int width, out int height)
+ {
+ x = crop_x;
+ y = crop_y;
+ width = crop_width;
+ height = crop_height;
+ }
+
+ public string get_named_crop ()
+ {
+ return crop_name;
+ }
+
+ public unowned uchar[] get_pixels ()
+ {
+ return pixels;
+ }
+
+ // FIXME: Copied from page-view, should be shared code
+ private uchar get_sample (uchar[] pixels, int offset, int x, int depth, int n_channels, int channel)
+ {
+ // FIXME
+ return 0xFF;
+ }
+
+ // FIXME: Copied from page-view, should be shared code
+ private void get_pixel (int x, int y, uchar[] pixel, int offset)
+ {
+ switch (get_scan_direction ())
+ {
+ case ScanDirection.TOP_TO_BOTTOM:
+ break;
+ case ScanDirection.BOTTOM_TO_TOP:
+ x = get_scan_width () - x - 1;
+ y = get_scan_height () - y - 1;
+ break;
+ case ScanDirection.LEFT_TO_RIGHT:
+ var t = x;
+ x = get_scan_width () - y - 1;
+ y = t;
+ break;
+ case ScanDirection.RIGHT_TO_LEFT:
+ var t = x;
+ x = y;
+ y = get_scan_height () - t - 1;
+ break;
+ }
+
+ var depth = get_depth ();
+ var n_channels = get_n_channels ();
+ var line_offset = get_rowstride () * y;
+
+ /* Optimise for 8 bit images */
+ if (depth == 8 && n_channels == 3)
+ {
+ var o = line_offset + x * n_channels;
+ pixel[offset+0] = pixels[o];
+ pixel[offset+1] = pixels[o+1];
+ pixel[offset+2] = pixels[o+2];
+ return;
+ }
+ else if (depth == 8 && n_channels == 1)
+ {
+ var p = pixels[line_offset + x];
+ pixel[offset+0] = pixel[offset+1] = pixel[offset+2] = p;
+ return;
+ }
+
+ /* Optimise for bitmaps */
+ else if (depth == 1 && n_channels == 1)
+ {
+ var p = pixels[line_offset + (x / 8)];
+ pixel[offset+0] = pixel[offset+1] = pixel[offset+2] = (p & (0x80 >> (x % 8))) != 0 ? 0x00 : 0xFF;
+ return;
+ }
+
+ /* Optimise for 2 bit images */
+ else if (depth == 2 && n_channels == 1)
+ {
+ int block_shift[4] = { 6, 4, 2, 0 };
+
+ var p = pixels[line_offset + (x / 4)];
+ var sample = (p >> block_shift[x % 4]) & 0x3;
+ sample = sample * 255 / 3;
+
+ pixel[offset+0] = pixel[offset+1] = pixel[offset+2] = (uchar) sample;
+ return;
+ }
+
+ /* Use slow method */
+ pixel[offset+0] = get_sample (pixels, line_offset, x, depth, n_channels, 0);
+ pixel[offset+1] = get_sample (pixels, line_offset, x, depth, n_channels, 1);
+ pixel[offset+2] = get_sample (pixels, line_offset, x, depth, n_channels, 2);
+ }
+
+ public Gdk.Pixbuf get_image (bool apply_crop)
+ {
+ int l, r, t, b;
+ if (apply_crop && has_crop_)
+ {
+ l = crop_x;
+ r = l + crop_width;
+ t = crop_y;
+ b = t + crop_height;
+
+ if (l < 0)
+ l = 0;
+ if (r > get_width ())
+ r = get_width ();
+ if (t < 0)
+ t = 0;
+ if (b > get_height ())
+ b = get_height ();
+ }
+ else
+ {
+ l = 0;
+ r = get_width ();
+ t = 0;
+ b = get_height ();
+ }
+
+ var image = new Gdk.Pixbuf (Gdk.Colorspace.RGB, false, 8, r - l, b - t);
+ unowned uint8[] image_pixels = image.get_pixels ();
+ for (var y = t; y < b; y++)
+ {
+ var offset = image.get_rowstride () * (y - t);
+ for (var x = l; x < r; x++)
+ get_pixel (x, y, image_pixels, offset + (x - l) * 3);
+ }
+
+ return image;
+ }
+
+ private string? get_icc_data_encoded (string icc_profile_filename)
+ {
+ /* Get binary data */
+ string contents;
+ try
+ {
+ FileUtils.get_contents (icc_profile_filename, out contents);
+ }
+ catch (Error e)
+ {
+ warning ("failed to get icc profile data: %s", e.message);
+ return null;
+ }
+
+ /* Encode into base64 */
+ return Base64.encode ((uchar[]) contents.to_utf8 ());
+ }
+
+ public void save (string type, File file) throws Error
+ {
+ var stream = file.replace (null, false, FileCreateFlags.NONE, null);
+ var writer = new PixbufWriter (stream);
+ var image = get_image (true);
+
+ string? icc_profile_data = null;
+ if (color_profile != null)
+ icc_profile_data = get_icc_data_encoded (color_profile);
+
+ if (strcmp (type, "jpeg") == 0)
+ {
+ /* ICC profile is awaiting review in gtk2+ bugzilla */
+ string[] keys = { "quality", /* "icc-profile", */ null };
+ string[] values = { "90", /* icc_profile_data, */ null };
+ writer.save (image, "jpeg", keys, values);
+ }
+ else if (strcmp (type, "png") == 0)
+ {
+ string[] keys = { "icc-profile", null };
+ string[] values = { icc_profile_data, null };
+ if (icc_profile_data == null)
+ keys[0] = null;
+ writer.save (image, "png", keys, values);
+ }
+ else if (strcmp (type, "tiff") == 0)
+ {
+ string[] keys = { "compression", "icc-profile", null };
+ string[] values = { "8" /* Deflate compression */, icc_profile_data, null };
+ if (icc_profile_data == null)
+ keys[1] = null;
+ writer.save (image, "tiff", keys, values);
+ }
+ else
+ ; // FIXME: Throw Error
+ }
+}
+
+public class PixbufWriter
+{
+ public FileOutputStream stream;
+
+ public PixbufWriter (FileOutputStream stream)
+ {
+ this.stream = stream;
+ }
+
+ public void save (Gdk.Pixbuf image, string type, string[] option_keys, string[] option_values) throws Error
+ {
+ image.save_to_callbackv (write_pixbuf_data, type, option_keys, option_values);
+ }
+
+ private bool write_pixbuf_data (uint8[] buf) throws Error
+ {
+ stream.write_all (buf, null, null);
+ return true;
+ }
+}
diff --git a/src/sane.vapi b/src/sane.vapi
new file mode 100644
index 0000000..ae69940
--- /dev/null
+++ b/src/sane.vapi
@@ -0,0 +1,757 @@
+[CCode (cprefix = "SANE_", lower_case_cprefix = "sane_", cheader_filename = "sane/sane.h")]
+namespace Sane {
+ [SimpleType]
+ [BooleanType]
+ public struct Bool
+ {
+ }
+
+ [SimpleType]
+ [IntegerType]
+ public struct Int
+ {
+ }
+
+ [SimpleType]
+ [IntegerType]
+ public struct Fixed
+ {
+ }
+
+ [SimpleType]
+ [IntegerType]
+ public struct Word
+ {
+ }
+
+ [CCode (ref_function = "", unref_function = "")]
+ public class Device
+ {
+ public string name;
+ public string vendor;
+ public string model;
+ public string type;
+ }
+
+ public enum Status
+ {
+ GOOD,
+ UNSUPPORTED,
+ CANCELLED,
+ DEVICE_BUSY,
+ INVAL,
+ EOF,
+ JAMMED,
+ NO_DOCS,
+ COVER_OPEN,
+ IO_ERROR,
+ NO_MEM,
+ ACCESS_DENIED
+ }
+
+ public static string status_to_string (Status status)
+ {
+ switch (status)
+ {
+ case Status.GOOD:
+ return "SANE_STATUS_GOOD";
+ case Status.UNSUPPORTED:
+ return "SANE_STATUS_UNSUPPORTED";
+ case Status.CANCELLED:
+ return "SANE_STATUS_CANCELLED";
+ case Status.DEVICE_BUSY:
+ return "SANE_STATUS_DEVICE_BUSY";
+ case Status.INVAL:
+ return "SANE_STATUS_INVAL";
+ case Status.EOF:
+ return "SANE_STATUS_EOF";
+ case Status.JAMMED:
+ return "SANE_STATUS_JAMMED";
+ case Status.NO_DOCS:
+ return "SANE_STATUS_NO_DOCS";
+ case Status.COVER_OPEN:
+ return "SANE_STATUS_COVER_OPEN";
+ case Status.IO_ERROR:
+ return "SANE_STATUS_IO_ERROR";
+ case Status.NO_MEM:
+ return "SANE_STATUS_NO_MEM";
+ case Status.ACCESS_DENIED:
+ return "SANE_STATUS_ACCESS_DENIED";
+ default:
+ return "SANE_STATUS(%d)".printf (status);
+ }
+ }
+
+ public enum Action
+ {
+ GET_VALUE,
+ SET_VALUE,
+ SET_AUTO
+ }
+
+ public enum Frame
+ {
+ GRAY,
+ RGB,
+ RED,
+ GREEN,
+ BLUE
+ }
+
+ public static string frame_to_string (Frame frame)
+ {
+ switch (frame)
+ {
+ case Frame.GRAY:
+ return "SANE_FRAME_GRAY";
+ case Frame.RGB:
+ return "SANE_FRAME_RGB";
+ case Frame.RED:
+ return "SANE_FRAME_RED";
+ case Frame.GREEN:
+ return "SANE_FRAME_GREEN";
+ case Frame.BLUE:
+ return "SANE_FRAME_BLUE";
+ default:
+ return "SANE_FRAME(%d)".printf (frame);
+ }
+ }
+
+ public struct Parameters
+ {
+ Frame format;
+ bool last_frame;
+ int bytes_per_line;
+ int pixels_per_line;
+ int lines;
+ int depth;
+ }
+
+ [CCode (cname = "SANE_MAX_USERNAME_LEN")]
+ public int MAX_USERNAME_LEN;
+
+ [CCode (cname = "SANE_MAX_USERNAME_LEN")]
+ public int MAX_PASSWORD_LEN;
+
+ [CCode (cname = "SANE_Value_Type", cprefix = "SANE_TYPE_")]
+ public enum ValueType
+ {
+ BOOL,
+ INT,
+ FIXED,
+ STRING,
+ BUTTON,
+ GROUP
+ }
+
+ public enum Unit
+ {
+ NONE,
+ PIXEL,
+ BIT,
+ MM,
+ DPI,
+ PERCENT,
+ MICROSECOND
+ }
+
+ [CCode (cname = "const SANE_Constraint_Type", cprefix = "SANE_CONSTRAINT_")]
+ public enum ConstraintType
+ {
+ NONE,
+ RANGE,
+ WORD_LIST,
+ STRING_LIST
+ }
+
+ public class Range
+ {
+ public Word min;
+ public Word max;
+ public Word quant;
+ }
+
+ [CCode (cprefix = "SANE_CAP_")]
+ public enum Capability
+ {
+ SOFT_SELECT,
+ HARD_SELECT,
+ SOFT_DETECT,
+ EMULATED,
+ AUTOMATIC,
+ INACTIVE,
+ ADVANCED
+ }
+
+ [CCode (cname = "const SANE_Option_Descriptor", ref_function = "", unref_function = "")]
+ public class OptionDescriptor
+ {
+ public string name;
+ public string title;
+ public string desc;
+ public ValueType type;
+ public Unit unit;
+ public Int size;
+ public Int cap;
+
+ public ConstraintType constraint_type;
+ public struct _Constraint
+ {
+ [CCode (array_length = false, null_terminated = true)]
+ public string[] string_list;
+ public Word[] word_list;
+ public Range range;
+ }
+ public _Constraint constraint;
+ }
+
+ [CCode (type = "Int", cprefix = "SANE_INFO_")]
+ public enum Info
+ {
+ INEXACT,
+ RELOAD_OPTIONS,
+ RELOAD_PARAMS
+ }
+
+ [SimpleType]
+ public struct Handle
+ {
+ }
+
+ [CCode (has_target = false)]
+ public delegate void AuthCallback (string resource, [CCode (array_length = false)] char[] username, [CCode (array_length = false)] char[] password);
+
+ [CCode (cname = "SANE_VERSION_MAJOR")]
+ public int VERSION_MAJOR (Int code);
+ [CCode (cname = "SANE_VERSION_MINOR")]
+ public int VERSION_MINOR (Int code);
+ [CCode (cname = "SANE_VERSION_BUILD")]
+ public int VERSION_BUILD (Int code);
+
+ [CCode (cname = "SANE_FIX")]
+ public Fixed FIX (double d);
+ [CCode (cname = "SANE_UNFIX")]
+ public double UNFIX (Fixed w);
+
+ [CCode (cname = "SANE_I18N")]
+ public unowned string I18N (string value);
+
+ public Status init (out Int version_code, AuthCallback callback);
+ public void exit ();
+ public Status get_devices ([CCode (array_length = false, null_terminated = true)] out unowned Device[] device_list, bool local_only);
+ public unowned string strstatus (Status status);
+ public Status open (string devicename, out Handle handle);
+ public void close (Handle handle);
+ public unowned OptionDescriptor? get_option_descriptor (Handle handle, Int option);
+ public Status control_option (Handle handle, Int option, Action action, void *value, out Info? info = null);
+ public Status get_parameters (Handle handle, out Parameters params);
+ public Status start (Handle handle);
+ public Status read (Handle handle, uint8* data, Int max_length, out Int length);
+ public void cancel (Handle handle);
+ public Status set_io_mode (Handle handle, bool non_blocking);
+ public Status get_select_fd (Handle handle, out int fd);
+
+ [CCode (cname = "SANE_NAME_STANDARD", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_STANDARD;
+ [CCode (cname = "SANE_NAME_GEOMETRY", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_GEOMETRY;
+ [CCode (cname = "SANE_NAME_ENHANCEMENT", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_ENHANCEMENT;
+ [CCode (cname = "SANE_NAME_ADVANCED", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_ADVANCED;
+ [CCode (cname = "SANE_NAME_SENSORS", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SENSORS;
+ [CCode (cname = "SANE_NAME_PREVIEW", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_PREVIEW;
+ [CCode (cname = "SANE_NAME_GRAY_PREVIEW", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_GRAY_PREVIEW;
+ [CCode (cname = "SANE_NAME_BIT_DEPTH", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_BIT_DEPTH;
+ [CCode (cname = "SANE_NAME_SCAN_MODE", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_MODE;
+ [CCode (cname = "SANE_NAME_SCAN_SPEED", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_SPEED;
+ [CCode (cname = "SANE_NAME_SCAN_SOURCE", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_SOURCE;
+ [CCode (cname = "SANE_NAME_BACKTRACK", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_BACKTRACK;
+ [CCode (cname = "SANE_NAME_SCAN_TL_X", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_TL_X;
+ [CCode (cname = "SANE_NAME_SCAN_TL_Y", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_TL_Y;
+ [CCode (cname = "SANE_NAME_SCAN_BR_X", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_BR_X;
+ [CCode (cname = "SANE_NAME_SCAN_BR_Y", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_BR_Y;
+ [CCode (cname = "SANE_NAME_SCAN_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_RESOLUTION;
+ [CCode (cname = "SANE_NAME_SCAN_X_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_X_RESOLUTION;
+ [CCode (cname = "SANE_NAME_SCAN_Y_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_Y_RESOLUTION;
+ [CCode (cname = "SANE_NAME_PAGE_WIDTH", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_PAGE_WIDTH;
+ [CCode (cname = "SANE_NAME_PAGE_HEIGHT", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_PAGE_HEIGHT;
+ [CCode (cname = "SANE_NAME_CUSTOM_GAMMA", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CUSTOM_GAMMA;
+ [CCode (cname = "SANE_NAME_GAMMA_VECTOR", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_GAMMA_VECTOR;
+ [CCode (cname = "SANE_NAME_GAMMA_VECTOR_R", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_GAMMA_VECTOR_R;
+ [CCode (cname = "SANE_NAME_GAMMA_VECTOR_G", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_GAMMA_VECTOR_G;
+ [CCode (cname = "SANE_NAME_GAMMA_VECTOR_B", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_GAMMA_VECTOR_B;
+ [CCode (cname = "SANE_NAME_BRIGHTNESS", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_BRIGHTNESS;
+ [CCode (cname = "SANE_NAME_CONTRAST", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CONTRAST;
+ [CCode (cname = "SANE_NAME_GRAIN_SIZE", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_GRAIN_SIZE;
+ [CCode (cname = "SANE_NAME_HALFTONE", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HALFTONE;
+ [CCode (cname = "SANE_NAME_BLACK_LEVEL", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_BLACK_LEVEL;
+ [CCode (cname = "SANE_NAME_WHITE_LEVEL", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_WHITE_LEVEL;
+ [CCode (cname = "SANE_NAME_WHITE_LEVEL_R", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_WHITE_LEVEL_R;
+ [CCode (cname = "SANE_NAME_WHITE_LEVEL_G", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_WHITE_LEVEL_G;
+ [CCode (cname = "SANE_NAME_WHITE_LEVEL_B", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_WHITE_LEVEL_B;
+ [CCode (cname = "SANE_NAME_SHADOW", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SHADOW;
+ [CCode (cname = "SANE_NAME_SHADOW_R", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SHADOW_R;
+ [CCode (cname = "SANE_NAME_SHADOW_G", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SHADOW_G;
+ [CCode (cname = "SANE_NAME_SHADOW_B", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SHADOW_B;
+ [CCode (cname = "SANE_NAME_HIGHLIGHT", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HIGHLIGHT;
+ [CCode (cname = "SANE_NAME_HIGHLIGHT_R", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HIGHLIGHT_R;
+ [CCode (cname = "SANE_NAME_HIGHLIGHT_G", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HIGHLIGHT_G;
+ [CCode (cname = "SANE_NAME_HIGHLIGHT_B", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HIGHLIGHT_B;
+ [CCode (cname = "SANE_NAME_HUE", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HUE;
+ [CCode (cname = "SANE_NAME_SATURATION", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SATURATION;
+ [CCode (cname = "SANE_NAME_FILE", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_FILE;
+ [CCode (cname = "SANE_NAME_HALFTONE_DIMENSION", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HALFTONE_DIMENSION;
+ [CCode (cname = "SANE_NAME_HALFTONE_PATTERN", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_HALFTONE_PATTERN;
+ [CCode (cname = "SANE_NAME_RESOLUTION_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_RESOLUTION_BIND;
+ [CCode (cname = "SANE_NAME_NEGATIVE", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_NEGATIVE;
+ [CCode (cname = "SANE_NAME_QUALITY_CAL", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_QUALITY_CAL;
+ [CCode (cname = "SANE_NAME_DOR", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_DOR;
+ [CCode (cname = "SANE_NAME_RGB_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_RGB_BIND;
+ [CCode (cname = "SANE_NAME_THRESHOLD", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_THRESHOLD;
+ [CCode (cname = "SANE_NAME_ANALOG_GAMMA", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_ANALOG_GAMMA;
+ [CCode (cname = "SANE_NAME_ANALOG_GAMMA_R", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_ANALOG_GAMMA_R;
+ [CCode (cname = "SANE_NAME_ANALOG_GAMMA_G", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_ANALOG_GAMMA_G;
+ [CCode (cname = "SANE_NAME_ANALOG_GAMMA_B", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_ANALOG_GAMMA_B;
+ [CCode (cname = "SANE_NAME_ANALOG_GAMMA_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_ANALOG_GAMMA_BIND;
+ [CCode (cname = "SANE_NAME_WARMUP", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_WARMUP;
+ [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CAL_EXPOS_TIME;
+ [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CAL_EXPOS_TIME_R;
+ [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CAL_EXPOS_TIME_G;
+ [CCode (cname = "SANE_NAME_CAL_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CAL_EXPOS_TIME_B;
+ [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_EXPOS_TIME;
+ [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_EXPOS_TIME_R;
+ [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_EXPOS_TIME_G;
+ [CCode (cname = "SANE_NAME_SCAN_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_EXPOS_TIME_B;
+ [CCode (cname = "SANE_NAME_SELECT_EXPOSURE_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SELECT_EXPOSURE_TIME;
+ [CCode (cname = "SANE_NAME_CAL_LAMP_DEN", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CAL_LAMP_DEN;
+ [CCode (cname = "SANE_NAME_SCAN_LAMP_DEN", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN_LAMP_DEN;
+ [CCode (cname = "SANE_NAME_SELECT_LAMP_DENSITY", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SELECT_LAMP_DENSITY;
+ [CCode (cname = "SANE_NAME_LAMP_OFF_AT_EXIT", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_LAMP_OFF_AT_EXIT;
+ [CCode (cname = "SANE_NAME_SCAN", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_SCAN;
+ [CCode (cname = "SANE_NAME_EMAIL", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_EMAIL;
+ [CCode (cname = "SANE_NAME_FAX", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_FAX;
+ [CCode (cname = "SANE_NAME_COPY", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_COPY;
+ [CCode (cname = "SANE_NAME_PDF", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_PDF;
+ [CCode (cname = "SANE_NAME_CANCEL", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_CANCEL;
+ [CCode (cname = "SANE_NAME_PAGE_LOADED", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_PAGE_LOADED;
+ [CCode (cname = "SANE_NAME_COVER_OPEN", cheader_filename = "sane/saneopts.h")]
+ public static string NAME_COVER_OPEN;
+ [CCode (cname = "SANE_TITLE_NUM_OPTIONS", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_NUM_OPTIONS;
+ [CCode (cname = "SANE_TITLE_STANDARD", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_STANDARD;
+ [CCode (cname = "SANE_TITLE_GEOMETRY", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_GEOMETRY;
+ [CCode (cname = "SANE_TITLE_ENHANCEMENT", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_ENHANCEMENT;
+ [CCode (cname = "SANE_TITLE_ADVANCED", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_ADVANCED;
+ [CCode (cname = "SANE_TITLE_SENSORS", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SENSORS;
+ [CCode (cname = "SANE_TITLE_PREVIEW", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_PREVIEW;
+ [CCode (cname = "SANE_TITLE_GRAY_PREVIEW", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_GRAY_PREVIEW;
+ [CCode (cname = "SANE_TITLE_BIT_DEPTH", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_BIT_DEPTH;
+ [CCode (cname = "SANE_TITLE_SCAN_MODE", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_MODE;
+ [CCode (cname = "SANE_TITLE_SCAN_SPEED", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_SPEED;
+ [CCode (cname = "SANE_TITLE_SCAN_SOURCE", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_SOURCE;
+ [CCode (cname = "SANE_TITLE_BACKTRACK", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_BACKTRACK;
+ [CCode (cname = "SANE_TITLE_SCAN_TL_X", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_TL_X;
+ [CCode (cname = "SANE_TITLE_SCAN_TL_Y", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_TL_Y;
+ [CCode (cname = "SANE_TITLE_SCAN_BR_X", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_BR_X;
+ [CCode (cname = "SANE_TITLE_SCAN_BR_Y", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_BR_Y;
+ [CCode (cname = "SANE_TITLE_SCAN_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_RESOLUTION;
+ [CCode (cname = "SANE_TITLE_SCAN_X_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_X_RESOLUTION;
+ [CCode (cname = "SANE_TITLE_SCAN_Y_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_Y_RESOLUTION;
+ [CCode (cname = "SANE_TITLE_PAGE_WIDTH", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_PAGE_WIDTH;
+ [CCode (cname = "SANE_TITLE_PAGE_HEIGHT", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_PAGE_HEIGHT;
+ [CCode (cname = "SANE_TITLE_CUSTOM_GAMMA", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CUSTOM_GAMMA;
+ [CCode (cname = "SANE_TITLE_GAMMA_VECTOR", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_GAMMA_VECTOR;
+ [CCode (cname = "SANE_TITLE_GAMMA_VECTOR_R", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_GAMMA_VECTOR_R;
+ [CCode (cname = "SANE_TITLE_GAMMA_VECTOR_G", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_GAMMA_VECTOR_G;
+ [CCode (cname = "SANE_TITLE_GAMMA_VECTOR_B", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_GAMMA_VECTOR_B;
+ [CCode (cname = "SANE_TITLE_BRIGHTNESS", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_BRIGHTNESS;
+ [CCode (cname = "SANE_TITLE_CONTRAST", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CONTRAST;
+ [CCode (cname = "SANE_TITLE_GRAIN_SIZE", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_GRAIN_SIZE;
+ [CCode (cname = "SANE_TITLE_HALFTONE", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HALFTONE;
+ [CCode (cname = "SANE_TITLE_BLACK_LEVEL", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_BLACK_LEVEL;
+ [CCode (cname = "SANE_TITLE_WHITE_LEVEL", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_WHITE_LEVEL;
+ [CCode (cname = "SANE_TITLE_WHITE_LEVEL_R", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_WHITE_LEVEL_R;
+ [CCode (cname = "SANE_TITLE_WHITE_LEVEL_G", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_WHITE_LEVEL_G;
+ [CCode (cname = "SANE_TITLE_WHITE_LEVEL_B", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_WHITE_LEVEL_B;
+ [CCode (cname = "SANE_TITLE_SHADOW", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SHADOW;
+ [CCode (cname = "SANE_TITLE_SHADOW_R", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SHADOW_R;
+ [CCode (cname = "SANE_TITLE_SHADOW_G", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SHADOW_G;
+ [CCode (cname = "SANE_TITLE_SHADOW_B", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SHADOW_B;
+ [CCode (cname = "SANE_TITLE_HIGHLIGHT", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HIGHLIGHT;
+ [CCode (cname = "SANE_TITLE_HIGHLIGHT_R", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HIGHLIGHT_R;
+ [CCode (cname = "SANE_TITLE_HIGHLIGHT_G", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HIGHLIGHT_G;
+ [CCode (cname = "SANE_TITLE_HIGHLIGHT_B", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HIGHLIGHT_B;
+ [CCode (cname = "SANE_TITLE_HUE", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HUE;
+ [CCode (cname = "SANE_TITLE_SATURATION", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SATURATION;
+ [CCode (cname = "SANE_TITLE_FILE", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_FILE;
+ [CCode (cname = "SANE_TITLE_HALFTONE_DIMENSION", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HALFTONE_DIMENSION;
+ [CCode (cname = "SANE_TITLE_HALFTONE_PATTERN", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_HALFTONE_PATTERN;
+ [CCode (cname = "SANE_TITLE_RESOLUTION_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_RESOLUTION_BIND;
+ [CCode (cname = "SANE_TITLE_NEGATIVE", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_NEGATIVE;
+ [CCode (cname = "SANE_TITLE_QUALITY_CAL", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_QUALITY_CAL;
+ [CCode (cname = "SANE_TITLE_DOR", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_DOR;
+ [CCode (cname = "SANE_TITLE_RGB_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_RGB_BIND;
+ [CCode (cname = "SANE_TITLE_THRESHOLD", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_THRESHOLD;
+ [CCode (cname = "SANE_TITLE_ANALOG_GAMMA", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_ANALOG_GAMMA;
+ [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_R", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_ANALOG_GAMMA_R;
+ [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_G", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_ANALOG_GAMMA_G;
+ [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_B", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_ANALOG_GAMMA_B;
+ [CCode (cname = "SANE_TITLE_ANALOG_GAMMA_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_ANALOG_GAMMA_BIND;
+ [CCode (cname = "SANE_TITLE_WARMUP", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_WARMUP;
+ [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CAL_EXPOS_TIME;
+ [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CAL_EXPOS_TIME_R;
+ [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CAL_EXPOS_TIME_G;
+ [CCode (cname = "SANE_TITLE_CAL_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CAL_EXPOS_TIME_B;
+ [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_EXPOS_TIME;
+ [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_EXPOS_TIME_R;
+ [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_EXPOS_TIME_G;
+ [CCode (cname = "SANE_TITLE_SCAN_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_EXPOS_TIME_B;
+ [CCode (cname = "SANE_TITLE_SELECT_EXPOSURE_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SELECT_EXPOSURE_TIME;
+ [CCode (cname = "SANE_TITLE_CAL_LAMP_DEN", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CAL_LAMP_DEN;
+ [CCode (cname = "SANE_TITLE_SCAN_LAMP_DEN", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN_LAMP_DEN;
+ [CCode (cname = "SANE_TITLE_SELECT_LAMP_DENSITY", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SELECT_LAMP_DENSITY;
+ [CCode (cname = "SANE_TITLE_LAMP_OFF_AT_EXIT", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_LAMP_OFF_AT_EXIT;
+ [CCode (cname = "SANE_TITLE_SCAN", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_SCAN;
+ [CCode (cname = "SANE_TITLE_EMAIL", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_EMAIL;
+ [CCode (cname = "SANE_TITLE_FAX", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_FAX;
+ [CCode (cname = "SANE_TITLE_COPY", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_COPY;
+ [CCode (cname = "SANE_TITLE_PDF", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_PDF;
+ [CCode (cname = "SANE_TITLE_CANCEL", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_CANCEL;
+ [CCode (cname = "SANE_TITLE_PAGE_LOADED", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_PAGE_LOADED;
+ [CCode (cname = "SANE_TITLE_COVER_OPEN", cheader_filename = "sane/saneopts.h")]
+ public static string TITLE_COVER_OPEN;
+ [CCode (cname = "SANE_DESC_NUM_OPTIONS", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_NUM_OPTIONS;
+ [CCode (cname = "SANE_DESC_STANDARD", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_STANDARD;
+ [CCode (cname = "SANE_DESC_GEOMETRY", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_GEOMETRY;
+ [CCode (cname = "SANE_DESC_ENHANCEMENT", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_ENHANCEMENT;
+ [CCode (cname = "SANE_DESC_ADVANCED", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_ADVANCED;
+ [CCode (cname = "SANE_DESC_SENSORS", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SENSORS;
+ [CCode (cname = "SANE_DESC_PREVIEW", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_PREVIEW;
+ [CCode (cname = "SANE_DESC_GRAY_PREVIEW", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_GRAY_PREVIEW;
+ [CCode (cname = "SANE_DESC_BIT_DEPTH", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_BIT_DEPTH;
+ [CCode (cname = "SANE_DESC_SCAN_MODE", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_MODE;
+ [CCode (cname = "SANE_DESC_SCAN_SPEED", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_SPEED;
+ [CCode (cname = "SANE_DESC_SCAN_SOURCE", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_SOURCE;
+ [CCode (cname = "SANE_DESC_BACKTRACK", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_BACKTRACK;
+ [CCode (cname = "SANE_DESC_SCAN_TL_X", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_TL_X;
+ [CCode (cname = "SANE_DESC_SCAN_TL_Y", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_TL_Y;
+ [CCode (cname = "SANE_DESC_SCAN_BR_X", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_BR_X;
+ [CCode (cname = "SANE_DESC_SCAN_BR_Y", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_BR_Y;
+ [CCode (cname = "SANE_DESC_SCAN_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_RESOLUTION;
+ [CCode (cname = "SANE_DESC_SCAN_X_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_X_RESOLUTION;
+ [CCode (cname = "SANE_DESC_SCAN_Y_RESOLUTION", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_Y_RESOLUTION;
+ [CCode (cname = "SANE_DESC_PAGE_WIDTH", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_PAGE_WIDTH;
+ [CCode (cname = "SANE_DESC_PAGE_HEIGHT", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_PAGE_HEIGHT;
+ [CCode (cname = "SANE_DESC_CUSTOM_GAMMA", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CUSTOM_GAMMA;
+ [CCode (cname = "SANE_DESC_GAMMA_VECTOR", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_GAMMA_VECTOR;
+ [CCode (cname = "SANE_DESC_GAMMA_VECTOR_R", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_GAMMA_VECTOR_R;
+ [CCode (cname = "SANE_DESC_GAMMA_VECTOR_G", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_GAMMA_VECTOR_G;
+ [CCode (cname = "SANE_DESC_GAMMA_VECTOR_B", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_GAMMA_VECTOR_B;
+ [CCode (cname = "SANE_DESC_BRIGHTNESS", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_BRIGHTNESS;
+ [CCode (cname = "SANE_DESC_CONTRAST", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CONTRAST;
+ [CCode (cname = "SANE_DESC_GRAIN_SIZE", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_GRAIN_SIZE;
+ [CCode (cname = "SANE_DESC_HALFTONE", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HALFTONE;
+ [CCode (cname = "SANE_DESC_BLACK_LEVEL", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_BLACK_LEVEL;
+ [CCode (cname = "SANE_DESC_WHITE_LEVEL", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_WHITE_LEVEL;
+ [CCode (cname = "SANE_DESC_WHITE_LEVEL_R", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_WHITE_LEVEL_R;
+ [CCode (cname = "SANE_DESC_WHITE_LEVEL_G", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_WHITE_LEVEL_G;
+ [CCode (cname = "SANE_DESC_WHITE_LEVEL_B", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_WHITE_LEVEL_B;
+ [CCode (cname = "SANE_DESC_SHADOW", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SHADOW;
+ [CCode (cname = "SANE_DESC_SHADOW_R", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SHADOW_R;
+ [CCode (cname = "SANE_DESC_SHADOW_G", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SHADOW_G;
+ [CCode (cname = "SANE_DESC_SHADOW_B", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SHADOW_B;
+ [CCode (cname = "SANE_DESC_HIGHLIGHT", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HIGHLIGHT;
+ [CCode (cname = "SANE_DESC_HIGHLIGHT_R", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HIGHLIGHT_R;
+ [CCode (cname = "SANE_DESC_HIGHLIGHT_G", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HIGHLIGHT_G;
+ [CCode (cname = "SANE_DESC_HIGHLIGHT_B", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HIGHLIGHT_B;
+ [CCode (cname = "SANE_DESC_HUE", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HUE;
+ [CCode (cname = "SANE_DESC_SATURATION", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SATURATION;
+ [CCode (cname = "SANE_DESC_FILE", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_FILE;
+ [CCode (cname = "SANE_DESC_HALFTONE_DIMENSION", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HALFTONE_DIMENSION;
+ [CCode (cname = "SANE_DESC_HALFTONE_PATTERN", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_HALFTONE_PATTERN;
+ [CCode (cname = "SANE_DESC_RESOLUTION_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_RESOLUTION_BIND;
+ [CCode (cname = "SANE_DESC_NEGATIVE", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_NEGATIVE;
+ [CCode (cname = "SANE_DESC_QUALITY_CAL", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_QUALITY_CAL;
+ [CCode (cname = "SANE_DESC_DOR", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_DOR;
+ [CCode (cname = "SANE_DESC_RGB_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_RGB_BIND;
+ [CCode (cname = "SANE_DESC_THRESHOLD", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_THRESHOLD;
+ [CCode (cname = "SANE_DESC_ANALOG_GAMMA", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_ANALOG_GAMMA;
+ [CCode (cname = "SANE_DESC_ANALOG_GAMMA_R", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_ANALOG_GAMMA_R;
+ [CCode (cname = "SANE_DESC_ANALOG_GAMMA_G", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_ANALOG_GAMMA_G;
+ [CCode (cname = "SANE_DESC_ANALOG_GAMMA_B", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_ANALOG_GAMMA_B;
+ [CCode (cname = "SANE_DESC_ANALOG_GAMMA_BIND", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_ANALOG_GAMMA_BIND;
+ [CCode (cname = "SANE_DESC_WARMUP", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_WARMUP;
+ [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CAL_EXPOS_TIME;
+ [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CAL_EXPOS_TIME_R;
+ [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CAL_EXPOS_TIME_G;
+ [CCode (cname = "SANE_DESC_CAL_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CAL_EXPOS_TIME_B;
+ [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_EXPOS_TIME;
+ [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME_R", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_EXPOS_TIME_R;
+ [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME_G", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_EXPOS_TIME_G;
+ [CCode (cname = "SANE_DESC_SCAN_EXPOS_TIME_B", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_EXPOS_TIME_B;
+ [CCode (cname = "SANE_DESC_SELECT_EXPOSURE_TIME", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SELECT_EXPOSURE_TIME;
+ [CCode (cname = "SANE_DESC_CAL_LAMP_DEN", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CAL_LAMP_DEN;
+ [CCode (cname = "SANE_DESC_SCAN_LAMP_DEN", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN_LAMP_DEN;
+ [CCode (cname = "SANE_DESC_SELECT_LAMP_DENSITY", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SELECT_LAMP_DENSITY;
+ [CCode (cname = "SANE_DESC_LAMP_OFF_AT_EXIT", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_LAMP_OFF_AT_EXIT;
+ [CCode (cname = "SANE_DESC_SCAN", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_SCAN;
+ [CCode (cname = "SANE_DESC_EMAIL", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_EMAIL;
+ [CCode (cname = "SANE_DESC_FAX", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_FAX;
+ [CCode (cname = "SANE_DESC_COPY", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_COPY;
+ [CCode (cname = "SANE_DESC_PDF", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_PDF;
+ [CCode (cname = "SANE_DESC_CANCEL", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_CANCEL;
+ [CCode (cname = "SANE_DESC_PAGE_LOADED", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_PAGE_LOADED;
+ [CCode (cname = "SANE_DESC_COVER_OPEN", cheader_filename = "sane/saneopts.h")]
+ public static string DESC_COVER_OPEN;
+ [CCode (cname = "SANE_VALUE_SCAN_MODE_COLOR", cheader_filename = "sane/saneopts.h")]
+ public static string VALUE_SCAN_MODE_COLOR;
+ [CCode (cname = "SANE_VALUE_SCAN_MODE_COLOR_LINEART", cheader_filename = "sane/saneopts.h")]
+ public static string VALUE_SCAN_MODE_COLOR_LINEART;
+ [CCode (cname = "SANE_VALUE_SCAN_MODE_COLOR_HALFTONE", cheader_filename = "sane/saneopts.h")]
+ public static string VALUE_SCAN_MODE_COLOR_HALFTONE;
+ [CCode (cname = "SANE_VALUE_SCAN_MODE_GRAY", cheader_filename = "sane/saneopts.h")]
+ public static string VALUE_SCAN_MODE_GRAY;
+ [CCode (cname = "SANE_VALUE_SCAN_MODE_HALFTONE", cheader_filename = "sane/saneopts.h")]
+ public static string VALUE_SCAN_MODE_HALFTONE;
+ [CCode (cname = "SANE_VALUE_SCAN_MODE_LINEART", cheader_filename = "sane/saneopts.h")]
+ public static string VALUE_SCAN_MODE_LINEART;
+}
+
diff --git a/src/scanner.c b/src/scanner.c
index ff8a994..e7e83cc 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -1,1714 +1,6089 @@
+/* scanner.c generated by valac 0.13.1, the Vala compiler
+ * generated from scanner.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
* version. See http://www.gnu.org/copyleft/gpl.html the full text of the
* license.
*/
+/* TODO: Could indicate the start of the next page immediately after the last page is received (i.e. before the sane_cancel()) */
+#include <glib.h>
+#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
+#include <float.h>
#include <math.h>
#include <sane/sane.h>
+#include <glib/gi18n-lib.h>
#include <sane/saneopts.h>
-#include <glib/gi18n.h>
+#include <gobject/gvaluecollector.h>
+
+
+#define TYPE_SCAN_DEVICE (scan_device_get_type ())
+#define SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_DEVICE, ScanDevice))
+#define SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_DEVICE, ScanDeviceClass))
+#define IS_SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_DEVICE))
+#define IS_SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_DEVICE))
+#define SCAN_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_DEVICE, ScanDeviceClass))
+
+typedef struct _ScanDevice ScanDevice;
+typedef struct _ScanDeviceClass ScanDeviceClass;
+typedef struct _ScanDevicePrivate ScanDevicePrivate;
+#define _g_free0(var) (var = (g_free (var), NULL))
+typedef struct _ParamSpecScanDevice ParamSpecScanDevice;
+
+#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;
+typedef struct _ParamSpecScanPageInfo ParamSpecScanPageInfo;
+
+#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;
+typedef struct _ParamSpecScanLine ParamSpecScanLine;
+
+#define TYPE_SCAN_MODE (scan_mode_get_type ())
+
+#define TYPE_SCAN_TYPE (scan_type_get_type ())
+
+#define TYPE_SCAN_OPTIONS (scan_options_get_type ())
+#define SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_OPTIONS, ScanOptions))
+#define SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_OPTIONS, ScanOptionsClass))
+#define IS_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_OPTIONS))
+#define IS_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_OPTIONS))
+#define SCAN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_OPTIONS, ScanOptionsClass))
+
+typedef struct _ScanOptions ScanOptions;
+typedef struct _ScanOptionsClass ScanOptionsClass;
+typedef struct _ScanOptionsPrivate ScanOptionsPrivate;
+typedef struct _ParamSpecScanOptions ParamSpecScanOptions;
+
+#define TYPE_SCAN_JOB (scan_job_get_type ())
+#define SCAN_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_JOB, ScanJob))
+#define SCAN_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_JOB, ScanJobClass))
+#define IS_SCAN_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_JOB))
+#define IS_SCAN_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_JOB))
+#define SCAN_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_JOB, ScanJobClass))
+
+typedef struct _ScanJob ScanJob;
+typedef struct _ScanJobClass ScanJobClass;
+typedef struct _ScanJobPrivate ScanJobPrivate;
+typedef struct _ParamSpecScanJob ParamSpecScanJob;
+
+#define TYPE_REQUEST (request_get_type ())
+#define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST, Request))
+#define REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST, RequestClass))
+#define IS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST))
+#define IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST))
+#define REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST, RequestClass))
+
+typedef struct _Request Request;
+typedef struct _RequestClass RequestClass;
+typedef struct _RequestPrivate RequestPrivate;
+typedef struct _ParamSpecRequest ParamSpecRequest;
+
+#define TYPE_REQUEST_REDETECT (request_redetect_get_type ())
+#define REQUEST_REDETECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_REDETECT, RequestRedetect))
+#define REQUEST_REDETECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_REDETECT, RequestRedetectClass))
+#define IS_REQUEST_REDETECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_REDETECT))
+#define IS_REQUEST_REDETECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_REDETECT))
+#define REQUEST_REDETECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_REDETECT, RequestRedetectClass))
+
+typedef struct _RequestRedetect RequestRedetect;
+typedef struct _RequestRedetectClass RequestRedetectClass;
+typedef struct _RequestRedetectPrivate RequestRedetectPrivate;
+
+#define TYPE_REQUEST_CANCEL (request_cancel_get_type ())
+#define REQUEST_CANCEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_CANCEL, RequestCancel))
+#define REQUEST_CANCEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_CANCEL, RequestCancelClass))
+#define IS_REQUEST_CANCEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_CANCEL))
+#define IS_REQUEST_CANCEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_CANCEL))
+#define REQUEST_CANCEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_CANCEL, RequestCancelClass))
+
+typedef struct _RequestCancel RequestCancel;
+typedef struct _RequestCancelClass RequestCancelClass;
+typedef struct _RequestCancelPrivate RequestCancelPrivate;
+
+#define TYPE_REQUEST_START_SCAN (request_start_scan_get_type ())
+#define REQUEST_START_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_START_SCAN, RequestStartScan))
+#define REQUEST_START_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_START_SCAN, RequestStartScanClass))
+#define IS_REQUEST_START_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_START_SCAN))
+#define IS_REQUEST_START_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_START_SCAN))
+#define REQUEST_START_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_START_SCAN, RequestStartScanClass))
+
+typedef struct _RequestStartScan RequestStartScan;
+typedef struct _RequestStartScanClass RequestStartScanClass;
+typedef struct _RequestStartScanPrivate RequestStartScanPrivate;
+#define _scan_job_unref0(var) ((var == NULL) ? NULL : (var = (scan_job_unref (var), NULL)))
+
+#define TYPE_REQUEST_QUIT (request_quit_get_type ())
+#define REQUEST_QUIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_REQUEST_QUIT, RequestQuit))
+#define REQUEST_QUIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_REQUEST_QUIT, RequestQuitClass))
+#define IS_REQUEST_QUIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_REQUEST_QUIT))
+#define IS_REQUEST_QUIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_REQUEST_QUIT))
+#define REQUEST_QUIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_REQUEST_QUIT, RequestQuitClass))
+
+typedef struct _RequestQuit RequestQuit;
+typedef struct _RequestQuitClass RequestQuitClass;
+typedef struct _RequestQuitPrivate RequestQuitPrivate;
+
+#define TYPE_CREDENTIALS (credentials_get_type ())
+#define CREDENTIALS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CREDENTIALS, Credentials))
+#define CREDENTIALS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_CREDENTIALS, CredentialsClass))
+#define IS_CREDENTIALS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CREDENTIALS))
+#define IS_CREDENTIALS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_CREDENTIALS))
+#define CREDENTIALS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CREDENTIALS, CredentialsClass))
+
+typedef struct _Credentials Credentials;
+typedef struct _CredentialsClass CredentialsClass;
+typedef struct _CredentialsPrivate CredentialsPrivate;
+typedef struct _ParamSpecCredentials ParamSpecCredentials;
+
+#define TYPE_SCAN_STATE (scan_state_get_type ())
+
+#define TYPE_NOTIFY (notify_get_type ())
+#define NOTIFY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY, Notify))
+#define NOTIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY, NotifyClass))
+#define IS_NOTIFY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY))
+#define IS_NOTIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY))
+#define NOTIFY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY, NotifyClass))
+
+typedef struct _Notify Notify;
+typedef struct _NotifyClass NotifyClass;
+typedef struct _NotifyPrivate NotifyPrivate;
+
+#define TYPE_SCANNER (scanner_get_type ())
+#define SCANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCANNER, Scanner))
+#define SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCANNER, ScannerClass))
+#define IS_SCANNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCANNER))
+#define IS_SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCANNER))
+#define SCANNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCANNER, ScannerClass))
+
+typedef struct _Scanner Scanner;
+typedef struct _ScannerClass ScannerClass;
+typedef struct _ParamSpecNotify ParamSpecNotify;
+
+#define TYPE_NOTIFY_SCANNING_CHANGED (notify_scanning_changed_get_type ())
+#define NOTIFY_SCANNING_CHANGED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_SCANNING_CHANGED, NotifyScanningChanged))
+#define NOTIFY_SCANNING_CHANGED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_SCANNING_CHANGED, NotifyScanningChangedClass))
+#define IS_NOTIFY_SCANNING_CHANGED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_SCANNING_CHANGED))
+#define IS_NOTIFY_SCANNING_CHANGED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_SCANNING_CHANGED))
+#define NOTIFY_SCANNING_CHANGED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_SCANNING_CHANGED, NotifyScanningChangedClass))
+
+typedef struct _NotifyScanningChanged NotifyScanningChanged;
+typedef struct _NotifyScanningChangedClass NotifyScanningChangedClass;
+typedef struct _NotifyScanningChangedPrivate NotifyScanningChangedPrivate;
+
+#define TYPE_NOTIFY_UPDATE_DEVICES (notify_update_devices_get_type ())
+#define NOTIFY_UPDATE_DEVICES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevices))
+#define NOTIFY_UPDATE_DEVICES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevicesClass))
+#define IS_NOTIFY_UPDATE_DEVICES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_UPDATE_DEVICES))
+#define IS_NOTIFY_UPDATE_DEVICES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_UPDATE_DEVICES))
+#define NOTIFY_UPDATE_DEVICES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevicesClass))
+
+typedef struct _NotifyUpdateDevices NotifyUpdateDevices;
+typedef struct _NotifyUpdateDevicesClass NotifyUpdateDevicesClass;
+typedef struct _NotifyUpdateDevicesPrivate NotifyUpdateDevicesPrivate;
+#define __g_list_free__scan_device_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__scan_device_unref0_ (var), NULL)))
+
+#define TYPE_NOTIFY_REQUEST_AUTHORIZATION (notify_request_authorization_get_type ())
+#define NOTIFY_REQUEST_AUTHORIZATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorization))
+#define NOTIFY_REQUEST_AUTHORIZATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorizationClass))
+#define IS_NOTIFY_REQUEST_AUTHORIZATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_REQUEST_AUTHORIZATION))
+#define IS_NOTIFY_REQUEST_AUTHORIZATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_REQUEST_AUTHORIZATION))
+#define NOTIFY_REQUEST_AUTHORIZATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorizationClass))
+
+typedef struct _NotifyRequestAuthorization NotifyRequestAuthorization;
+typedef struct _NotifyRequestAuthorizationClass NotifyRequestAuthorizationClass;
+typedef struct _NotifyRequestAuthorizationPrivate NotifyRequestAuthorizationPrivate;
+
+#define TYPE_NOTIFY_SCAN_FAILED (notify_scan_failed_get_type ())
+#define NOTIFY_SCAN_FAILED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailed))
+#define NOTIFY_SCAN_FAILED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailedClass))
+#define IS_NOTIFY_SCAN_FAILED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_SCAN_FAILED))
+#define IS_NOTIFY_SCAN_FAILED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_SCAN_FAILED))
+#define NOTIFY_SCAN_FAILED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailedClass))
+
+typedef struct _NotifyScanFailed NotifyScanFailed;
+typedef struct _NotifyScanFailedClass NotifyScanFailedClass;
+typedef struct _NotifyScanFailedPrivate NotifyScanFailedPrivate;
+
+#define TYPE_NOTIFY_DOCUMENT_DONE (notify_document_done_get_type ())
+#define NOTIFY_DOCUMENT_DONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_DOCUMENT_DONE, NotifyDocumentDone))
+#define NOTIFY_DOCUMENT_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_DOCUMENT_DONE, NotifyDocumentDoneClass))
+#define IS_NOTIFY_DOCUMENT_DONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_DOCUMENT_DONE))
+#define IS_NOTIFY_DOCUMENT_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_DOCUMENT_DONE))
+#define NOTIFY_DOCUMENT_DONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_DOCUMENT_DONE, NotifyDocumentDoneClass))
+
+typedef struct _NotifyDocumentDone NotifyDocumentDone;
+typedef struct _NotifyDocumentDoneClass NotifyDocumentDoneClass;
+typedef struct _NotifyDocumentDonePrivate NotifyDocumentDonePrivate;
+
+#define TYPE_NOTIFY_EXPECT_PAGE (notify_expect_page_get_type ())
+#define NOTIFY_EXPECT_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_EXPECT_PAGE, NotifyExpectPage))
+#define NOTIFY_EXPECT_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_EXPECT_PAGE, NotifyExpectPageClass))
+#define IS_NOTIFY_EXPECT_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_EXPECT_PAGE))
+#define IS_NOTIFY_EXPECT_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_EXPECT_PAGE))
+#define NOTIFY_EXPECT_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_EXPECT_PAGE, NotifyExpectPageClass))
+
+typedef struct _NotifyExpectPage NotifyExpectPage;
+typedef struct _NotifyExpectPageClass NotifyExpectPageClass;
+typedef struct _NotifyExpectPagePrivate NotifyExpectPagePrivate;
+
+#define TYPE_NOTIFY_GOT_PAGE_INFO (notify_got_page_info_get_type ())
+#define NOTIFY_GOT_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfo))
+#define NOTIFY_GOT_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfoClass))
+#define IS_NOTIFY_GOT_PAGE_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_GOT_PAGE_INFO))
+#define IS_NOTIFY_GOT_PAGE_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_GOT_PAGE_INFO))
+#define NOTIFY_GOT_PAGE_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfoClass))
+
+typedef struct _NotifyGotPageInfo NotifyGotPageInfo;
+typedef struct _NotifyGotPageInfoClass NotifyGotPageInfoClass;
+typedef struct _NotifyGotPageInfoPrivate NotifyGotPageInfoPrivate;
+#define _scan_page_info_unref0(var) ((var == NULL) ? NULL : (var = (scan_page_info_unref (var), NULL)))
+
+#define TYPE_NOTIFY_PAGE_DONE (notify_page_done_get_type ())
+#define NOTIFY_PAGE_DONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_PAGE_DONE, NotifyPageDone))
+#define NOTIFY_PAGE_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_PAGE_DONE, NotifyPageDoneClass))
+#define IS_NOTIFY_PAGE_DONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_PAGE_DONE))
+#define IS_NOTIFY_PAGE_DONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_PAGE_DONE))
+#define NOTIFY_PAGE_DONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_PAGE_DONE, NotifyPageDoneClass))
+
+typedef struct _NotifyPageDone NotifyPageDone;
+typedef struct _NotifyPageDoneClass NotifyPageDoneClass;
+typedef struct _NotifyPageDonePrivate NotifyPageDonePrivate;
+
+#define TYPE_NOTIFY_GOT_LINE (notify_got_line_get_type ())
+#define NOTIFY_GOT_LINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_NOTIFY_GOT_LINE, NotifyGotLine))
+#define NOTIFY_GOT_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_NOTIFY_GOT_LINE, NotifyGotLineClass))
+#define IS_NOTIFY_GOT_LINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_NOTIFY_GOT_LINE))
+#define IS_NOTIFY_GOT_LINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_NOTIFY_GOT_LINE))
+#define NOTIFY_GOT_LINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_NOTIFY_GOT_LINE, NotifyGotLineClass))
+
+typedef struct _NotifyGotLine NotifyGotLine;
+typedef struct _NotifyGotLineClass NotifyGotLineClass;
+typedef struct _NotifyGotLinePrivate NotifyGotLinePrivate;
+#define _scan_line_unref0(var) ((var == NULL) ? NULL : (var = (scan_line_unref (var), NULL)))
+typedef struct _ScannerPrivate ScannerPrivate;
+#define _g_async_queue_unref0(var) ((var == NULL) ? NULL : (var = (g_async_queue_unref (var), NULL)))
+#define __g_list_free__scan_job_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__scan_job_unref0_ (var), NULL)))
+#define _scanner_unref0(var) ((var == NULL) ? NULL : (var = (scanner_unref (var), NULL)))
+#define _notify_unref0(var) ((var == NULL) ? NULL : (var = (notify_unref (var), NULL)))
+#define _g_regex_unref0(var) ((var == NULL) ? NULL : (var = (g_regex_unref (var), NULL)))
+#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
+#define _scan_device_unref0(var) ((var == NULL) ? NULL : (var = (scan_device_unref (var), NULL)))
+#define _credentials_unref0(var) ((var == NULL) ? NULL : (var = (credentials_unref (var), NULL)))
+#define _request_unref0(var) ((var == NULL) ? NULL : (var = (request_unref (var), NULL)))
+typedef struct _ParamSpecScanner ParamSpecScanner;
+
+struct _ScanDevice {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanDevicePrivate * priv;
+ gchar* name;
+ gchar* label;
+};
-#include "scanner.h"
+struct _ScanDeviceClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanDevice *self);
+};
-/* TODO: Could indicate the start of the next page immediately after the last page is received (i.e. before the sane_cancel()) */
+struct _ParamSpecScanDevice {
+ GParamSpec parent_instance;
+};
+
+struct _ScanPageInfo {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanPageInfoPrivate * priv;
+ gint width;
+ gint height;
+ gint depth;
+ gint n_channels;
+ gdouble dpi;
+ gchar* device;
+};
+
+struct _ScanPageInfoClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanPageInfo *self);
+};
+
+struct _ParamSpecScanPageInfo {
+ GParamSpec parent_instance;
+};
+
+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);
+};
+
+struct _ParamSpecScanLine {
+ GParamSpec parent_instance;
+};
+
+typedef enum {
+ SCAN_MODE_DEFAULT,
+ SCAN_MODE_COLOR,
+ SCAN_MODE_GRAY,
+ SCAN_MODE_LINEART
+} ScanMode;
+
+typedef enum {
+ SCAN_TYPE_SINGLE,
+ SCAN_TYPE_ADF_FRONT,
+ SCAN_TYPE_ADF_BACK,
+ SCAN_TYPE_ADF_BOTH
+} ScanType;
+
+struct _ScanOptions {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanOptionsPrivate * priv;
+ gint dpi;
+ ScanMode scan_mode;
+ gint depth;
+ ScanType type;
+ gint paper_width;
+ gint paper_height;
+};
+
+struct _ScanOptionsClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanOptions *self);
+};
+
+struct _ParamSpecScanOptions {
+ GParamSpec parent_instance;
+};
+
+struct _ScanJob {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanJobPrivate * priv;
+ gchar* device;
+ gdouble dpi;
+ ScanMode scan_mode;
+ gint depth;
+ ScanType type;
+ gint page_width;
+ gint page_height;
+};
+
+struct _ScanJobClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanJob *self);
+};
+
+struct _ParamSpecScanJob {
+ GParamSpec parent_instance;
+};
+
+struct _Request {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ RequestPrivate * priv;
+};
+
+struct _RequestClass {
+ GTypeClass parent_class;
+ void (*finalize) (Request *self);
+};
-enum {
- UPDATE_DEVICES,
- AUTHORIZE,
- EXPECT_PAGE,
- GOT_PAGE_INFO,
- GOT_LINE,
- SCAN_FAILED,
- PAGE_DONE,
- DOCUMENT_DONE,
- SCANNING_CHANGED,
- LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0, };
-
-typedef struct
-{
- Scanner *instance;
- guint sig;
- gpointer data;
-} SignalInfo;
-
-typedef struct
-{
- gchar *device;
- gdouble dpi;
- ScanMode scan_mode;
- gint depth;
- gboolean type;
- gint page_width, page_height;
-} ScanJob;
-
-typedef struct
-{
- enum
- {
- REQUEST_CANCEL,
- REQUEST_REDETECT,
- REQUEST_START_SCAN,
- REQUEST_QUIT
- } type;
- ScanJob *job;
-} ScanRequest;
-
-typedef struct
-{
- gchar *username, *password;
-} Credentials;
-
-typedef enum
-{
- STATE_IDLE = 0,
- STATE_REDETECT,
- STATE_OPEN,
- STATE_GET_OPTION,
- STATE_START,
- STATE_GET_PARAMETERS,
- STATE_READ
+struct _ParamSpecRequest {
+ GParamSpec parent_instance;
+};
+
+struct _RequestRedetect {
+ Request parent_instance;
+ RequestRedetectPrivate * priv;
+};
+
+struct _RequestRedetectClass {
+ RequestClass parent_class;
+};
+
+struct _RequestCancel {
+ Request parent_instance;
+ RequestCancelPrivate * priv;
+};
+
+struct _RequestCancelClass {
+ RequestClass parent_class;
+};
+
+struct _RequestStartScan {
+ Request parent_instance;
+ RequestStartScanPrivate * priv;
+ ScanJob* job;
+};
+
+struct _RequestStartScanClass {
+ RequestClass parent_class;
+};
+
+struct _RequestQuit {
+ Request parent_instance;
+ RequestQuitPrivate * priv;
+};
+
+struct _RequestQuitClass {
+ RequestClass parent_class;
+};
+
+struct _Credentials {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ CredentialsPrivate * priv;
+ gchar* username;
+ gchar* password;
+};
+
+struct _CredentialsClass {
+ GTypeClass parent_class;
+ void (*finalize) (Credentials *self);
+};
+
+struct _ParamSpecCredentials {
+ GParamSpec parent_instance;
+};
+
+typedef enum {
+ SCAN_STATE_IDLE = 0,
+ SCAN_STATE_REDETECT,
+ SCAN_STATE_OPEN,
+ SCAN_STATE_GET_OPTION,
+ SCAN_STATE_START,
+ SCAN_STATE_GET_PARAMETERS,
+ SCAN_STATE_READ
} ScanState;
-struct ScannerPrivate
-{
- GAsyncQueue *scan_queue, *authorize_queue;
- GThread *thread;
-
- gchar *default_device;
-
- ScanState state;
- gboolean redetect;
-
- GList *job_queue;
-
- /* Handle to SANE device */
- SANE_Handle handle;
- gchar *current_device;
-
- SANE_Parameters parameters;
-
- /* Last option read */
- SANE_Int option_index;
-
- /* Option index for scan area */
- SANE_Int br_x_option_index, br_y_option_index;
-
- /* Buffer for received line */
- SANE_Byte *buffer;
- SANE_Int buffer_size, n_used;
-
- SANE_Int bytes_remaining, line_count, pass_number, page_number, notified_page;
-
- gboolean scanning;
-};
-
-G_DEFINE_TYPE (Scanner, scanner, G_TYPE_OBJECT);
-
-
-/* Table of scanner objects for each thread (required for authorization callback) */
-static GHashTable *scanners;
-
-
-static gboolean
-send_signal (SignalInfo *info)
-{
- g_signal_emit (info->instance, signals[info->sig], 0, info->data);
-
- switch (info->sig) {
- case UPDATE_DEVICES:
- {
- GList *iter, *devices = info->data;
- for (iter = devices; iter; iter = iter->next) {
- ScanDevice *device = iter->data;
- g_free (device->name);
- g_free (device->label);
- g_free (device);
- }
- g_list_free (devices);
- }
- break;
- case AUTHORIZE:
- {
- gchar *resource = info->data;
- g_free (resource);
- }
- break;
- case GOT_PAGE_INFO:
- {
- ScanPageInfo *page_info = info->data;
- g_free (page_info);
- }
- break;
- case GOT_LINE:
- {
- ScanLine *line = info->data;
- g_free(line->data);
- g_free(line);
- }
- break;
- case SCAN_FAILED:
- {
- GError *error = info->data;
- g_error_free (error);
- }
- break;
- default:
- case EXPECT_PAGE:
- case PAGE_DONE:
- case DOCUMENT_DONE:
- case LAST_SIGNAL:
- g_assert (info->data == NULL);
- break;
- }
- g_free (info);
-
- return FALSE;
-}
-
-
-/* Emit signals in main loop */
-static void
-emit_signal (Scanner *scanner, guint sig, gpointer data)
-{
- SignalInfo *info;
-
- info = g_malloc(sizeof(SignalInfo));
- info->instance = scanner;
- info->sig = sig;
- info->data = data;
- g_idle_add ((GSourceFunc) send_signal, info);
-}
-
-
-static void
-set_scanning (Scanner *scanner, gboolean is_scanning)
-{
- if ((scanner->priv->scanning && !is_scanning) || (!scanner->priv->scanning && is_scanning)) {
- scanner->priv->scanning = is_scanning;
- emit_signal (scanner, SCANNING_CHANGED, NULL);
- }
-}
-
-
-static gint
-get_device_weight (const gchar *device)
-{
- /* NOTE: This is using trends in the naming of SANE devices, SANE should be able to provide this information better */
-
- /* Use webcams as a last resort */
- if (g_str_has_prefix (device, "vfl:"))
- return 2;
-
- /* Use locally connected devices first */
- if (strstr (device, "usb"))
- return 0;
-
- return 1;
-}
-
-
-static gint
-compare_devices (ScanDevice *device1, ScanDevice *device2)
-{
- gint weight1, weight2;
-
- /* TODO: Should do some fuzzy matching on the last selected device and set that to the default */
-
- weight1 = get_device_weight (device1->name);
- weight2 = get_device_weight (device2->name);
- if (weight1 != weight2)
- return weight1 - weight2;
-
- return strcmp (device1->label, device2->label);
-}
-
-
-static const char *
-get_status_string (SANE_Status status)
-{
- struct {
- SANE_Status status;
- const char *name;
- } status_names[] = {
- { SANE_STATUS_GOOD, "SANE_STATUS_GOOD"},
- { SANE_STATUS_UNSUPPORTED, "SANE_STATUS_UNSUPPORTED"},
- { SANE_STATUS_CANCELLED, "SANE_STATUS_CANCELLED"},
- { SANE_STATUS_DEVICE_BUSY, "SANE_STATUS_DEVICE_BUSY"},
- { SANE_STATUS_INVAL, "SANE_STATUS_INVAL"},
- { SANE_STATUS_EOF, "SANE_STATUS_EOF"},
- { SANE_STATUS_JAMMED, "SANE_STATUS_JAMMED"},
- { SANE_STATUS_NO_DOCS, "SANE_STATUS_NO_DOCS"},
- { SANE_STATUS_COVER_OPEN, "SANE_STATUS_COVER_OPEN"},
- { SANE_STATUS_IO_ERROR, "SANE_STATUS_IO_ERROR"},
- { SANE_STATUS_NO_MEM, "SANE_STATUS_NO_MEM"},
- { SANE_STATUS_ACCESS_DENIED, "SANE_STATUS_ACCESS_DENIED"},
- { -1, NULL}
- };
- static char *unknown_string = NULL;
- int i;
-
- for (i = 0; status_names[i].name != NULL && status_names[i].status != status; i++);
-
- if (status_names[i].name == NULL) {
- g_free (unknown_string);
- unknown_string = g_strdup_printf ("SANE_STATUS(%d)", status);
- return unknown_string; /* Note result is undefined on second call to this function */
- }
-
- return status_names[i].name;
-}
-
-
-static const char *
-get_action_string (SANE_Action action)
-{
- struct {
- SANE_Action action;
- const char *name;
- } action_names[] = {
- { SANE_ACTION_GET_VALUE, "SANE_ACTION_GET_VALUE" },
- { SANE_ACTION_SET_VALUE, "SANE_ACTION_SET_VALUE" },
- { SANE_ACTION_SET_AUTO, "SANE_ACTION_SET_AUTO" },
- { -1, NULL}
- };
- static char *unknown_string = NULL;
- int i;
-
- for (i = 0; action_names[i].name != NULL && action_names[i].action != action; i++);
-
- if (action_names[i].name == NULL) {
- g_free (unknown_string);
- unknown_string = g_strdup_printf ("SANE_ACTION(%d)", action);
- return unknown_string; /* Note result is undefined on second call to this function */
- }
-
- return action_names[i].name;
-}
-
-
-static const char *
-get_frame_string (SANE_Frame frame)
-{
- struct {
- SANE_Frame frame;
- const char *name;
- } frame_names[] = {
- { SANE_FRAME_GRAY, "SANE_FRAME_GRAY" },
- { SANE_FRAME_RGB, "SANE_FRAME_RGB" },
- { SANE_FRAME_RED, "SANE_FRAME_RED" },
- { SANE_FRAME_GREEN, "SANE_FRAME_GREEN" },
- { SANE_FRAME_BLUE, "SANE_FRAME_BLUE" },
- { -1, NULL}
- };
- static char *unknown_string = NULL;
- int i;
-
- for (i = 0; frame_names[i].name != NULL && frame_names[i].frame != frame; i++);
-
- if (frame_names[i].name == NULL) {
- g_free (unknown_string);
- unknown_string = g_strdup_printf ("SANE_FRAME(%d)", frame);
- return unknown_string; /* Note result is undefined on second call to this function */
- }
-
- return frame_names[i].name;
-}
-
-
-static void
-do_redetect (Scanner *scanner)
-{
- const SANE_Device **device_list, **device_iter;
- SANE_Status status;
- GList *devices = NULL;
-
- status = sane_get_devices (&device_list, SANE_FALSE);
- g_debug ("sane_get_devices () -> %s", get_status_string (status));
- if (status != SANE_STATUS_GOOD) {
- g_warning ("Unable to get SANE devices: %s", sane_strstatus(status));
- scanner->priv->state = STATE_IDLE;
- return;
- }
-
- for (device_iter = device_list; *device_iter; device_iter++) {
- const SANE_Device *device = *device_iter;
- ScanDevice *scan_device;
- gchar *c, *label;
-
- g_debug ("Device: name=\"%s\" vendor=\"%s\" model=\"%s\" type=\"%s\"",
- device->name, device->vendor, device->model, device->type);
-
- scan_device = g_malloc0 (sizeof (ScanDevice));
-
- scan_device->name = g_strdup (device->name);
-
- /* Abbreviate HP as it is a long string and does not match what is on the physical scanner */
- if (strcmp (device->vendor, "Hewlett-Packard") == 0)
- label = g_strdup_printf ("HP %s", device->model);
- else
- label = g_strdup_printf ("%s %s", device->vendor, device->model);
-
- /* Replace underscored in name */
- for (c = label; *c; c++)
- if (*c == '_')
- *c = ' ';
-
- scan_device->label = label;
-
- devices = g_list_append (devices, scan_device);
- }
-
- /* Sort devices by priority */
- devices = g_list_sort (devices, (GCompareFunc) compare_devices);
-
- scanner->priv->redetect = FALSE;
- scanner->priv->state = STATE_IDLE;
-
- g_free (scanner->priv->default_device);
- if (devices) {
- ScanDevice *device = g_list_nth_data (devices, 0);
- scanner->priv->default_device = g_strdup (device->name);
- }
- else
- scanner->priv->default_device = NULL;
-
- emit_signal (scanner, UPDATE_DEVICES, devices);
-}
-
-
-static gboolean
-control_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int index, SANE_Action action, void *value)
-{
- SANE_Status status;
- gchar *old_value;
-
- switch (option->type) {
- case SANE_TYPE_BOOL:
- old_value = g_strdup_printf (*((SANE_Bool *) value) ? "SANE_TRUE" : "SANE_FALSE");
- break;
- case SANE_TYPE_INT:
- old_value = g_strdup_printf ("%d", *((SANE_Int *) value));
- break;
- case SANE_TYPE_FIXED:
- old_value = g_strdup_printf ("%f", SANE_UNFIX (*((SANE_Fixed *) value)));
- break;
- case SANE_TYPE_STRING:
- old_value = g_strdup_printf ("\"%s\"", (char *) value);
- break;
- default:
- old_value = g_strdup ("?");
- break;
- }
-
- status = sane_control_option (handle, index, action, value, NULL);
- switch (option->type) {
- case SANE_TYPE_BOOL:
- g_debug ("sane_control_option (%d, %s, %s) -> (%s, %s)",
- index, get_action_string (action),
- *((SANE_Bool *) value) ? "SANE_TRUE" : "SANE_FALSE",
- get_status_string (status),
- old_value);
- break;
- case SANE_TYPE_INT:
- g_debug ("sane_control_option (%d, %s, %d) -> (%s, %s)",
- index, get_action_string (action),
- *((SANE_Int *) value),
- get_status_string (status),
- old_value);
- break;
- case SANE_TYPE_FIXED:
- g_debug ("sane_control_option (%d, %s, %f) -> (%s, %s)",
- index, get_action_string (action),
- SANE_UNFIX (*((SANE_Fixed *) value)),
- get_status_string (status),
- old_value);
- break;
- case SANE_TYPE_STRING:
- g_debug ("sane_control_option (%d, %s, \"%s\") -> (%s, %s)",
- index, get_action_string (action),
- (char *) value,
- get_status_string (status),
- old_value);
- break;
- default:
- break;
- }
- g_free (old_value);
-
- if (status != SANE_STATUS_GOOD)
- g_warning ("Error setting option %s: %s", option->name, sane_strstatus(status));
-
- return status == SANE_STATUS_GOOD;
-}
-
-
-static gboolean
-set_default_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index)
-{
- SANE_Status status;
-
- /* Check if supports automatic option */
- if ((option->cap & SANE_CAP_AUTOMATIC) == 0)
- return FALSE;
-
- status = sane_control_option (handle, option_index, SANE_ACTION_SET_AUTO, NULL, NULL);
- g_debug ("sane_control_option (%d, SANE_ACTION_SET_AUTO) -> %s",
- option_index, get_status_string (status));
- if (status != SANE_STATUS_GOOD)
- g_warning ("Error setting default option %s: %s", option->name, sane_strstatus(status));
-
- return status == SANE_STATUS_GOOD;
-}
-
-
-static void
-set_bool_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, SANE_Bool value, SANE_Bool *result)
-{
- SANE_Bool v = value;
- g_return_if_fail (option->type == SANE_TYPE_BOOL);
- control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, &v);
- if (result)
- *result = v;
-}
-
-
-static void
-set_int_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, SANE_Int value, SANE_Int *result)
-{
- SANE_Int v = value;
-
- g_return_if_fail (option->type == SANE_TYPE_INT);
-
- if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
- if (option->constraint.range->quant)
- v *= option->constraint.range->quant;
- if (v < option->constraint.range->min)
- v = option->constraint.range->min;
- if (v > option->constraint.range->max)
- v = option->constraint.range->max;
- }
- else if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) {
- int i;
- SANE_Int distance = INT_MAX, nearest = 0;
-
- /* Find nearest value to requested */
- for (i = 0; i < option->constraint.word_list[0]; i++) {
- SANE_Int x = option->constraint.word_list[i+1];
- if (abs (x - v) < distance) {
- distance = abs (x - v);
- nearest = x;
- }
- }
- v = nearest;
- }
-
- control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, &v);
- if (result)
- *result = v;
-}
-
-
-static void
-set_fixed_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, gdouble value, gdouble *result)
-{
- gdouble v = value;
- SANE_Fixed v_fixed;
-
- g_return_if_fail (option->type == SANE_TYPE_FIXED);
-
- if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
- double min = SANE_UNFIX (option->constraint.range->min);
- double max = SANE_UNFIX (option->constraint.range->max);
-
- if (v < min)
- v = min;
- if (v > max)
- v = max;
- }
- else if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) {
- int i;
- double distance = DBL_MAX, nearest = 0.0;
-
- /* Find nearest value to requested */
- for (i = 0; i < option->constraint.word_list[0]; i++) {
- double x = SANE_UNFIX (option->constraint.word_list[i+1]);
- if (fabs (x - v) < distance) {
- distance = fabs (x - v);
- nearest = x;
- }
- }
- v = nearest;
- }
-
- v_fixed = SANE_FIX (v);
- control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, &v_fixed);
- if (result)
- *result = SANE_UNFIX (v_fixed);
-}
-
-
-static gboolean
-set_string_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, const char *value, char **result)
-{
- char *string;
- gsize value_size, size;
- gboolean error;
-
- g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE);
-
- value_size = strlen (value) + 1;
- size = option->size > value_size ? option->size : value_size;
- string = g_malloc(sizeof(char) * size);
- strcpy (string, value);
- error = control_option (handle, option, option_index, SANE_ACTION_SET_VALUE, string);
- if (result)
- *result = string;
- else
- g_free (string);
-
- return error;
-}
-
-
-static gboolean
-set_constrained_string_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int option_index, const char *values[], char **result)
-{
- gint i, j;
-
- g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE);
- g_return_val_if_fail (option->constraint_type == SANE_CONSTRAINT_STRING_LIST, FALSE);
-
- for (i = 0; values[i] != NULL; i++) {
- for (j = 0; option->constraint.string_list[j]; j++) {
- if (strcmp (values[i], option->constraint.string_list[j]) == 0)
- break;
- }
-
- if (option->constraint.string_list[j] != NULL)
- return set_string_option (handle, option, option_index, values[i], result);
- }
-
- return FALSE;
-}
-
-
-static void
-log_option (SANE_Int index, const SANE_Option_Descriptor *option)
-{
- GString *string;
- SANE_Word i;
- SANE_Int cap;
-
- string = g_string_new ("");
-
- g_string_append_printf (string, "Option %d:", index);
-
- if (option->name)
- g_string_append_printf (string, " name='%s'", option->name);
-
- if (option->title)
- g_string_append_printf (string, " title='%s'", option->title);
-
- switch (option->type) {
- case SANE_TYPE_BOOL:
- g_string_append (string, " type=bool");
- break;
- case SANE_TYPE_INT:
- g_string_append (string, " type=int");
- break;
- case SANE_TYPE_FIXED:
- g_string_append (string, " type=fixed");
- break;
- case SANE_TYPE_STRING:
- g_string_append (string, " type=string");
- break;
- case SANE_TYPE_BUTTON:
- g_string_append (string, " type=button");
- break;
- case SANE_TYPE_GROUP:
- g_string_append (string, " type=group");
- break;
- default:
- g_string_append_printf (string, " type=%d", option->type);
- break;
- }
-
- g_string_append_printf (string, " size=%d", option->size);
-
- switch (option->unit) {
- case SANE_UNIT_NONE:
- break;
- case SANE_UNIT_PIXEL:
- g_string_append (string, " unit=pixels");
- break;
- case SANE_UNIT_BIT:
- g_string_append (string, " unit=bits");
- break;
- case SANE_UNIT_MM:
- g_string_append (string, " unit=mm");
- break;
- case SANE_UNIT_DPI:
- g_string_append (string, " unit=dpi");
- break;
- case SANE_UNIT_PERCENT:
- g_string_append (string, " unit=percent");
- break;
- case SANE_UNIT_MICROSECOND:
- g_string_append (string, " unit=microseconds");
- break;
- default:
- g_string_append_printf (string, " unit=%d", option->unit);
- break;
- }
-
- switch (option->constraint_type) {
- case SANE_CONSTRAINT_RANGE:
- if (option->type == SANE_TYPE_FIXED)
- g_string_append_printf (string, " min=%f, max=%f, quant=%d",
- SANE_UNFIX (option->constraint.range->min), SANE_UNFIX (option->constraint.range->max),
- option->constraint.range->quant);
- else
- g_string_append_printf (string, " min=%d, max=%d, quant=%d",
- option->constraint.range->min, option->constraint.range->max,
- option->constraint.range->quant);
- break;
- case SANE_CONSTRAINT_WORD_LIST:
- g_string_append (string, " values=[");
- for (i = 0; i < option->constraint.word_list[0]; i++) {
- if (i != 0)
- g_string_append (string, ", ");
- if (option->type == SANE_TYPE_INT)
- g_string_append_printf (string, "%d", option->constraint.word_list[i+1]);
- else
- g_string_append_printf (string, "%f", SANE_UNFIX (option->constraint.word_list[i+1]));
- }
- g_string_append (string, "]");
- break;
- case SANE_CONSTRAINT_STRING_LIST:
- g_string_append (string, " values=[");
- for (i = 0; option->constraint.string_list[i]; i++) {
- if (i != 0)
- g_string_append (string, ", ");
- g_string_append_printf (string, "\"%s\"", option->constraint.string_list[i]);
- }
- g_string_append (string, "]");
- break;
- default:
- break;
- }
-
- cap = option->cap;
- if (cap) {
- struct {
- SANE_Int cap;
- const char *name;
- } caps[] = {
- { SANE_CAP_SOFT_SELECT, "soft-select"},
- { SANE_CAP_HARD_SELECT, "hard-select"},
- { SANE_CAP_SOFT_DETECT, "soft-detect"},
- { SANE_CAP_EMULATED, "emulated"},
- { SANE_CAP_AUTOMATIC, "automatic"},
- { SANE_CAP_INACTIVE, "inactive"},
- { SANE_CAP_ADVANCED, "advanced"},
- { 0, NULL}
- };
- int i, n = 0;
-
- g_string_append (string, " cap=");
- for (i = 0; caps[i].cap > 0; i++) {
- if (cap & caps[i].cap) {
- cap &= ~caps[i].cap;
- if (n != 0)
- g_string_append (string, ",");
- g_string_append (string, caps[i].name);
- n++;
- }
- }
- /* Unknown capabilities */
- if (cap) {
- if (n != 0)
- g_string_append (string, ",");
- g_string_append_printf (string, "%x", cap);
- }
- }
-
- g_debug ("%s", string->str);
- g_string_free (string, TRUE);
-
- if (option->desc)
- g_debug (" Description: %s", option->desc);
-}
-
-
-static void
-authorization_cb (SANE_String_Const resource, SANE_Char username[SANE_MAX_USERNAME_LEN], SANE_Char password[SANE_MAX_PASSWORD_LEN])
-{
- Scanner *scanner;
- Credentials *credentials;
-
- scanner = g_hash_table_lookup (scanners, g_thread_self ());
-
- emit_signal (scanner, AUTHORIZE, g_strdup (resource));
-
- credentials = g_async_queue_pop (scanner->priv->authorize_queue);
- strncpy (username, credentials->username, SANE_MAX_USERNAME_LEN);
- strncpy (password, credentials->password, SANE_MAX_PASSWORD_LEN);
- g_free (credentials);
-}
-
-
-void
-scanner_authorize (Scanner *scanner, const gchar *username, const gchar *password)
-{
- Credentials *credentials;
-
- credentials = g_malloc (sizeof (Credentials));
- credentials->username = g_strdup (username);
- credentials->password = g_strdup (password);
- g_async_queue_push (scanner->priv->authorize_queue, credentials);
-}
-
-
-static void
-close_device (Scanner *scanner)
-{
- GList *iter;
-
- if (scanner->priv->handle) {
- sane_cancel (scanner->priv->handle);
- g_debug ("sane_cancel ()");
-
- sane_close (scanner->priv->handle);
- g_debug ("sane_close ()");
- scanner->priv->handle = NULL;
- }
-
- g_free (scanner->priv->buffer);
- scanner->priv->buffer = NULL;
-
- for (iter = scanner->priv->job_queue; iter; iter = iter->next) {
- ScanJob *job = (ScanJob *) iter->data;
- g_free (job->device);
- g_free (job);
- }
- g_list_free (scanner->priv->job_queue);
- scanner->priv->job_queue = NULL;
-
- set_scanning (scanner, FALSE);
-}
-
-static void
-fail_scan (Scanner *scanner, gint error_code, const gchar *error_string)
-{
- close_device (scanner);
- scanner->priv->state = STATE_IDLE;
- emit_signal (scanner, SCAN_FAILED, g_error_new (SCANNER_TYPE, error_code, "%s", error_string));
-}
-
-
-static gboolean
-handle_requests (Scanner *scanner)
-{
- gint request_count = 0;
-
- /* Redetect when idle */
- if (scanner->priv->state == STATE_IDLE && scanner->priv->redetect)
- scanner->priv->state = STATE_REDETECT;
-
- /* Process all requests */
- while (TRUE) {
- ScanRequest *request = NULL;
-
- if ((scanner->priv->state == STATE_IDLE && request_count == 0) ||
- g_async_queue_length (scanner->priv->scan_queue) > 0)
- request = g_async_queue_pop (scanner->priv->scan_queue);
- else
- return TRUE;
-
- g_debug ("Processing request");
- request_count++;
-
- switch (request->type) {
- case REQUEST_REDETECT:
- break;
-
- case REQUEST_START_SCAN:
- scanner->priv->job_queue = g_list_append (scanner->priv->job_queue, request->job);
- break;
-
- case REQUEST_CANCEL:
- fail_scan (scanner, SANE_STATUS_CANCELLED, "Scan cancelled - do not report this error");
- break;
-
- case REQUEST_QUIT:
- close_device (scanner);
- g_free (request);
- return FALSE;
- }
-
- g_free (request);
- }
-
- return TRUE;
-}
-
-
-static void
-do_open (Scanner *scanner)
-{
- SANE_Status status;
- ScanJob *job;
-
- job = (ScanJob *) scanner->priv->job_queue->data;
-
- scanner->priv->line_count = 0;
- scanner->priv->pass_number = 0;
- scanner->priv->page_number = 0;
- scanner->priv->notified_page = -1;
- scanner->priv->option_index = 0;
- scanner->priv->br_x_option_index = 0;
- scanner->priv->br_y_option_index = 0;
-
- if (!job->device && scanner->priv->default_device)
- job->device = g_strdup (scanner->priv->default_device);
-
- if (!job->device) {
- g_warning ("No scan device available");
- fail_scan (scanner, 0,
- /* Error displayed when no scanners to scan with */
- _("No scanners available. Please connect a scanner."));
- return;
- }
-
- /* See if we can use the already open device */
- if (scanner->priv->handle) {
- if (strcmp (scanner->priv->current_device, job->device) == 0) {
- scanner->priv->state = STATE_GET_OPTION;
- return;
- }
-
- sane_close (scanner->priv->handle);
- g_debug ("sane_close ()");
- scanner->priv->handle = NULL;
- }
-
- g_free (scanner->priv->current_device);
- scanner->priv->current_device = NULL;
-
- status = sane_open (job->device, &scanner->priv->handle);
- g_debug ("sane_open (\"%s\") -> %s", job->device, get_status_string (status));
-
- if (status != SANE_STATUS_GOOD) {
- g_warning ("Unable to get open device: %s", sane_strstatus (status));
- scanner->priv->handle = NULL;
- fail_scan (scanner, status,
- /* Error displayed when cannot connect to scanner */
- _("Unable to connect to scanner"));
- return;
- }
-
- scanner->priv->current_device = g_strdup (job->device);
- scanner->priv->state = STATE_GET_OPTION;
-}
-
-
-static void
-do_get_option (Scanner *scanner)
-{
- const SANE_Option_Descriptor *option;
- SANE_Int option_index;
- ScanJob *job;
-
- job = (ScanJob *) scanner->priv->job_queue->data;
-
- option = sane_get_option_descriptor (scanner->priv->handle, scanner->priv->option_index);
- g_debug ("sane_get_option_descriptor (%d)", scanner->priv->option_index);
- option_index = scanner->priv->option_index;
- scanner->priv->option_index++;
-
- if (!option) {
- /* Always use maximum scan area - some scanners default to using partial areas. This should be patched in sane-backends */
- if (scanner->priv->br_x_option_index) {
- option = sane_get_option_descriptor (scanner->priv->handle, scanner->priv->br_x_option_index);
- g_debug ("sane_get_option_descriptor (%d)", scanner->priv->br_x_option_index);
- if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
- if (option->type == SANE_TYPE_FIXED)
- set_fixed_option (scanner->priv->handle, option, scanner->priv->br_x_option_index, SANE_UNFIX (option->constraint.range->max), NULL);
- else
- set_int_option (scanner->priv->handle, option, scanner->priv->br_x_option_index, option->constraint.range->max, NULL);
- }
- }
- if (scanner->priv->br_y_option_index) {
- option = sane_get_option_descriptor (scanner->priv->handle, scanner->priv->br_y_option_index);
- g_debug ("sane_get_option_descriptor (%d)", scanner->priv->br_y_option_index);
- if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
- if (option->type == SANE_TYPE_FIXED)
- set_fixed_option (scanner->priv->handle, option, scanner->priv->br_y_option_index, SANE_UNFIX (option->constraint.range->max), NULL);
- else
- set_int_option (scanner->priv->handle, option, scanner->priv->br_y_option_index, option->constraint.range->max, NULL);
- }
- }
-
- scanner->priv->state = STATE_START;
- return;
- }
-
- log_option (option_index, option);
-
- /* Ignore groups */
- if (option->type == SANE_TYPE_GROUP)
- return;
-
- /* Option disabled */
- if (option->cap & SANE_CAP_INACTIVE)
- return;
-
- /* Some options are unnammed (e.g. Option 0) */
- if (option->name == NULL)
- return;
-
- if (strcmp (option->name, SANE_NAME_SCAN_RESOLUTION) == 0) {
- if (option->type == SANE_TYPE_FIXED) {
- set_fixed_option (scanner->priv->handle, option, option_index, job->dpi, &job->dpi);
- }
- else {
- SANE_Int dpi;
- set_int_option (scanner->priv->handle, option, option_index, job->dpi, &dpi);
- job->dpi = dpi;
- }
- }
- else if (strcmp (option->name, SANE_NAME_SCAN_SOURCE) == 0) {
- const char *flatbed_sources[] =
- {
- "Auto",
- SANE_I18N ("Auto"),
- "Flatbed",
- SANE_I18N ("Flatbed"),
- "FlatBed",
- "Normal",
- SANE_I18N ("Normal"),
- NULL
- };
-
- const char *adf_sources[] =
- {
- "Automatic Document Feeder",
- SANE_I18N ("Automatic Document Feeder"),
- "ADF",
- "Automatic Document Feeder(left aligned)", /* Seen in the proprietary brother3 driver */
- "Automatic Document Feeder(centrally aligned)", /* Seen in the proprietary brother3 driver */
- NULL
- };
-
- const char *adf_front_sources[] =
- {
- "ADF Front",
- SANE_I18N ("ADF Front"),
- NULL
- };
-
- const char *adf_back_sources[] =
- {
- "ADF Back",
- SANE_I18N ("ADF Back"),
- NULL
- };
-
- const char *adf_duplex_sources[] =
- {
- "ADF Duplex",
- SANE_I18N ("ADF Duplex"),
- NULL
- };
-
- switch (job->type) {
- case SCAN_SINGLE:
- if (!set_default_option (scanner->priv->handle, option, option_index))
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, flatbed_sources, NULL))
- g_warning ("Unable to set single page source, please file a bug");
- break;
- case SCAN_ADF_FRONT:
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_front_sources, NULL))
- if (!!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_sources, NULL))
- g_warning ("Unable to set front ADF source, please file a bug");
- break;
- case SCAN_ADF_BACK:
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_back_sources, NULL))
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_sources, NULL))
- g_warning ("Unable to set back ADF source, please file a bug");
- break;
- case SCAN_ADF_BOTH:
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_duplex_sources, NULL))
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, adf_sources, NULL))
- g_warning ("Unable to set duplex ADF source, please file a bug");
- break;
- }
- }
- else if (strcmp (option->name, "duplex") == 0) {
- if (option->type == SANE_TYPE_BOOL)
- set_bool_option (scanner->priv->handle, option, option_index, job->type == SCAN_ADF_BOTH, NULL);
- }
- else if (strcmp (option->name, "batch-scan") == 0) {
- if (option->type == SANE_TYPE_BOOL)
- set_bool_option (scanner->priv->handle, option, option_index, job->type != SCAN_SINGLE, NULL);
- }
- else if (strcmp (option->name, SANE_NAME_BIT_DEPTH) == 0) {
- if (job->depth > 0)
- set_int_option (scanner->priv->handle, option, option_index, job->depth, NULL);
- }
- else if (strcmp (option->name, SANE_NAME_SCAN_MODE) == 0) {
- /* The names of scan modes often used in drivers, as taken from the sane-backends source */
- const char *color_scan_modes[] =
- {
- SANE_VALUE_SCAN_MODE_COLOR,
- "Color",
- "24bit Color", /* Seen in the proprietary brother3 driver */
- NULL
- };
- const char *gray_scan_modes[] =
- {
- SANE_VALUE_SCAN_MODE_GRAY,
- "Gray",
- "Grayscale",
- SANE_I18N ("Grayscale"),
- "True Gray", /* Seen in the proprietary brother3 driver */
- NULL
- };
- const char *lineart_scan_modes[] =
- {
- SANE_VALUE_SCAN_MODE_LINEART,
- "Lineart",
- "LineArt",
- SANE_I18N ("LineArt"),
- "Black & White",
- SANE_I18N ("Black & White"),
- "Binary",
- SANE_I18N ("Binary"),
- "Thresholded",
- SANE_VALUE_SCAN_MODE_GRAY,
- "Gray",
- "Grayscale",
- SANE_I18N ("Grayscale"),
- "True Gray", /* Seen in the proprietary brother3 driver */
- NULL
- };
-
- switch (job->scan_mode) {
- case SCAN_MODE_COLOR:
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, color_scan_modes, NULL))
- g_warning ("Unable to set Color mode, please file a bug");
- break;
- case SCAN_MODE_GRAY:
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, gray_scan_modes, NULL))
- g_warning ("Unable to set Gray mode, please file a bug");
- break;
- case SCAN_MODE_LINEART:
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, lineart_scan_modes, NULL))
- g_warning ("Unable to set Lineart mode, please file a bug");
- break;
- default:
- break;
- }
- }
- /* Disable compression, we will compress after scanning */
- else if (strcmp (option->name, "compression") == 0) {
- const char *disable_compression_names[] =
- {
- SANE_I18N ("None"),
- SANE_I18N ("none"),
- "None",
- "none",
- NULL
- };
-
- if (!set_constrained_string_option (scanner->priv->handle, option, option_index, disable_compression_names, NULL))
- g_warning ("Unable to disable compression, please file a bug");
- }
- else if (strcmp (option->name, SANE_NAME_SCAN_BR_X) == 0)
- scanner->priv->br_x_option_index = option_index;
- else if (strcmp (option->name, SANE_NAME_SCAN_BR_Y) == 0)
- scanner->priv->br_y_option_index = option_index;
- else if (strcmp (option->name, SANE_NAME_PAGE_WIDTH) == 0) {
- if (job->page_width > 0.0) {
- if (option->type == SANE_TYPE_FIXED)
- set_fixed_option (scanner->priv->handle, option, option_index, job->page_width / 10.0, NULL);
- else
- set_int_option (scanner->priv->handle, option, option_index, job->page_width / 10, NULL);
- }
- }
- else if (strcmp (option->name, SANE_NAME_PAGE_HEIGHT) == 0) {
- if (job->page_height > 0.0) {
- if (option->type == SANE_TYPE_FIXED)
- set_fixed_option (scanner->priv->handle, option, option_index, job->page_height / 10.0, NULL);
- else
- set_int_option (scanner->priv->handle, option, option_index, job->page_height / 10, NULL);
- }
- }
-
- /* Test scanner options (hoping will not effect other scanners...) */
- if (strcmp (scanner->priv->current_device, "test") == 0) {
- if (strcmp (option->name, "hand-scanner") == 0) {
- set_bool_option (scanner->priv->handle, option, option_index, FALSE, NULL);
- }
- else if (strcmp (option->name, "three-pass") == 0) {
- set_bool_option (scanner->priv->handle, option, option_index, FALSE, NULL);
- }
- else if (strcmp (option->name, "test-picture") == 0) {
- set_string_option (scanner->priv->handle, option, option_index, "Color pattern", NULL);
- }
- else if (strcmp (option->name, "read-delay") == 0) {
- set_bool_option (scanner->priv->handle, option, option_index, TRUE, NULL);
- }
- else if (strcmp (option->name, "read-delay-duration") == 0) {
- set_int_option (scanner->priv->handle, option, option_index, 200000, NULL);
- }
- }
-}
-
-
-static void
-do_complete_document (Scanner *scanner)
-{
- ScanJob *job;
-
- job = (ScanJob *) scanner->priv->job_queue->data;
- g_free (job->device);
- g_free (job);
- scanner->priv->job_queue = g_list_remove_link (scanner->priv->job_queue, scanner->priv->job_queue);
-
- scanner->priv->state = STATE_IDLE;
-
- /* Continue onto the next job */
- if (scanner->priv->job_queue) {
- scanner->priv->state = STATE_OPEN;
- return;
- }
-
- /* Trigger timeout to close */
- // TODO
-
- emit_signal (scanner, DOCUMENT_DONE, NULL);
- set_scanning (scanner, FALSE);
-}
-
-
-static void
-do_start (Scanner *scanner)
-{
- SANE_Status status;
-
- emit_signal (scanner, EXPECT_PAGE, NULL);
-
- status = sane_start (scanner->priv->handle);
- g_debug ("sane_start (page=%d, pass=%d) -> %s", scanner->priv->page_number, scanner->priv->pass_number, get_status_string (status));
- if (status == SANE_STATUS_GOOD) {
- scanner->priv->state = STATE_GET_PARAMETERS;
- }
- else if (status == SANE_STATUS_NO_DOCS) {
- do_complete_document (scanner);
- }
- else {
- g_warning ("Unable to start device: %s", sane_strstatus (status));
- fail_scan (scanner, status,
- /* Error display when unable to start scan */
- _("Unable to start scan"));
- }
-}
-
-
-static void
-do_get_parameters (Scanner *scanner)
-{
- SANE_Status status;
- ScanPageInfo *info;
- ScanJob *job;
-
- status = sane_get_parameters (scanner->priv->handle, &scanner->priv->parameters);
- g_debug ("sane_get_parameters () -> %s", get_status_string (status));
- if (status != SANE_STATUS_GOOD) {
- g_warning ("Unable to get device parameters: %s", sane_strstatus (status));
- fail_scan (scanner, status,
- /* Error displayed when communication with scanner broken */
- _("Error communicating with scanner"));
- return;
- }
-
- job = (ScanJob *) scanner->priv->job_queue->data;
-
- g_debug ("Parameters: format=%s last_frame=%s bytes_per_line=%d pixels_per_line=%d lines=%d depth=%d",
- get_frame_string (scanner->priv->parameters.format),
- scanner->priv->parameters.last_frame ? "SANE_TRUE" : "SANE_FALSE",
- scanner->priv->parameters.bytes_per_line,
- scanner->priv->parameters.pixels_per_line,
- scanner->priv->parameters.lines,
- scanner->priv->parameters.depth);
-
- info = g_malloc(sizeof(ScanPageInfo));
- info->width = scanner->priv->parameters.pixels_per_line;
- info->height = scanner->priv->parameters.lines;
- info->depth = scanner->priv->parameters.depth;
- /* Reduce bit depth if requested lower than received */
- // FIXME: This a hack and only works on 8 bit gray to 2 bit gray
- if (scanner->priv->parameters.depth == 8 && scanner->priv->parameters.format == SANE_FRAME_GRAY && job->depth == 2 && job->scan_mode == SCAN_MODE_GRAY)
- info->depth = job->depth;
- info->n_channels = scanner->priv->parameters.format == SANE_FRAME_GRAY ? 1 : 3;
- info->dpi = job->dpi; // FIXME: This is the requested DPI, not the actual DPI
- info->device = g_strdup (scanner->priv->current_device);
-
- if (scanner->priv->page_number != scanner->priv->notified_page) {
- emit_signal (scanner, GOT_PAGE_INFO, info);
- scanner->priv->notified_page = scanner->priv->page_number;
- }
-
- /* Prepare for read */
- scanner->priv->buffer_size = scanner->priv->parameters.bytes_per_line + 1; /* Use +1 so buffer is not resized if driver returns one line per read */
- scanner->priv->buffer = g_malloc (sizeof(SANE_Byte) * scanner->priv->buffer_size);
- scanner->priv->n_used = 0;
- scanner->priv->line_count = 0;
- scanner->priv->pass_number = 0;
- scanner->priv->state = STATE_READ;
-}
-
-
-static void
-do_complete_page (Scanner *scanner)
-{
- ScanJob *job;
-
- emit_signal (scanner, PAGE_DONE, NULL);
-
- job = (ScanJob *) scanner->priv->job_queue->data;
-
- /* If multi-pass then scan another page */
- if (!scanner->priv->parameters.last_frame) {
- scanner->priv->pass_number++;
- scanner->priv->state = STATE_START;
- return;
- }
-
- /* Go back for another page */
- if (job->type != SCAN_SINGLE) {
- scanner->priv->page_number++;
- scanner->priv->pass_number = 0;
- emit_signal (scanner, PAGE_DONE, NULL);
- scanner->priv->state = STATE_START;
- return;
- }
-
- sane_cancel (scanner->priv->handle);
- g_debug ("sane_cancel ()");
-
- do_complete_document (scanner);
-}
-
-
-static void
-do_read (Scanner *scanner)
-{
- ScanJob *job;
- SANE_Status status;
- SANE_Int n_to_read, n_read;
- gboolean full_read = FALSE;
-
- job = (ScanJob *) scanner->priv->job_queue->data;
-
- /* Read as many bytes as we expect */
- n_to_read = scanner->priv->buffer_size - scanner->priv->n_used;
-
- status = sane_read (scanner->priv->handle,
- scanner->priv->buffer + scanner->priv->n_used,
- n_to_read, &n_read);
- g_debug ("sane_read (%d) -> (%s, %d)", n_to_read, get_status_string (status), n_read);
-
- /* Completed read */
- if (status == SANE_STATUS_EOF) {
- if (scanner->priv->parameters.lines > 0 && scanner->priv->line_count != scanner->priv->parameters.lines)
- g_warning ("Scan completed with %d lines, expected %d lines", scanner->priv->parameters.lines, scanner->priv->parameters.lines);
- if (scanner->priv->n_used > 0)
- g_warning ("Scan complete with %d bytes of unused data", scanner->priv->n_used);
- do_complete_page (scanner);
- return;
- }
-
- /* Communication error */
- if (status != SANE_STATUS_GOOD) {
- g_warning ("Unable to read frame from device: %s", sane_strstatus (status));
- fail_scan (scanner, status,
- /* Error displayed when communication with scanner broken */
- _("Error communicating with scanner"));
- return;
- }
-
- if (scanner->priv->n_used == 0 && n_read == scanner->priv->buffer_size)
- full_read = TRUE;
- scanner->priv->n_used += n_read;
-
- /* Feed out lines */
- if (scanner->priv->n_used >= scanner->priv->parameters.bytes_per_line) {
- ScanLine *line;
- int i, n_remaining;
-
- line = g_malloc(sizeof(ScanLine));
- switch (scanner->priv->parameters.format) {
- case SANE_FRAME_GRAY:
- line->channel = 0;
- break;
- case SANE_FRAME_RGB:
- line->channel = -1;
- break;
- case SANE_FRAME_RED:
- line->channel = 0;
- break;
- case SANE_FRAME_GREEN:
- line->channel = 1;
- break;
- case SANE_FRAME_BLUE:
- line->channel = 2;
- break;
- }
- line->width = scanner->priv->parameters.pixels_per_line;
- line->depth = scanner->priv->parameters.depth;
- line->data = scanner->priv->buffer;
- line->data_length = scanner->priv->parameters.bytes_per_line;
- line->number = scanner->priv->line_count;
- line->n_lines = scanner->priv->n_used / line->data_length;
-
- scanner->priv->buffer = NULL;
- scanner->priv->line_count += line->n_lines;
-
- /* Increase buffer size if did full read */
- if (full_read)
- scanner->priv->buffer_size += scanner->priv->parameters.bytes_per_line;
-
- scanner->priv->buffer = g_malloc(sizeof(SANE_Byte) * scanner->priv->buffer_size);
- n_remaining = scanner->priv->n_used - (line->n_lines * line->data_length);
- scanner->priv->n_used = 0;
- for (i = 0; i < n_remaining; i++) {
- scanner->priv->buffer[i] = line->data[i + (line->n_lines * line->data_length)];
- scanner->priv->n_used++;
- }
-
- /* Reduce bit depth if requested lower than received */
- // FIXME: This a hack and only works on 8 bit gray to 2 bit gray
- if (scanner->priv->parameters.depth == 8 && scanner->priv->parameters.format == SANE_FRAME_GRAY &&
- job->depth == 2 && job->scan_mode == SCAN_MODE_GRAY) {
- gint block_shift = 6;
- guchar block = 0;
- guchar *write_ptr = line->data;
-
- for (i = 0; i < line->n_lines; i++) {
- guchar *in_line = line->data + i * line->data_length;
- gint x;
-
- for (x = 0; x < line->width; x++) {
- guchar *p = in_line + x;
- guchar sample;
-
- if (p[0] >= 192)
- sample = 3;
- else if (p[0] >= 128)
- sample = 2;
- else if (p[0] >= 64)
- sample = 1;
- else
- sample = 0;
-
- block |= sample << block_shift;
- if (block_shift == 0) {
- *write_ptr = block;
- write_ptr++;
- block = 0;
- block_shift = 6;
- }
- else {
- block_shift -= 2;
- }
- }
-
- /* Finish each line on a byte boundary */
- if (block_shift != 6) {
- *write_ptr = block;
- write_ptr++;
- block = 0;
- block_shift = 6;
- }
- }
-
- line->data_length = (line->width * 2 + 7) / 8;
- }
-
- emit_signal (scanner, GOT_LINE, line);
- }
-}
-
-
-static gpointer
-scan_thread (Scanner *scanner)
-{
- SANE_Status status;
- SANE_Int version_code;
-
- g_hash_table_insert (scanners, g_thread_self (), scanner);
-
- scanner->priv->state = STATE_IDLE;
-
- status = sane_init (&version_code, authorization_cb);
- g_debug ("sane_init () -> %s", get_status_string (status));
- if (status != SANE_STATUS_GOOD) {
- g_warning ("Unable to initialize SANE backend: %s", sane_strstatus(status));
- return FALSE;
- }
- g_debug ("SANE version %d.%d.%d",
- SANE_VERSION_MAJOR(version_code),
- SANE_VERSION_MINOR(version_code),
- SANE_VERSION_BUILD(version_code));
-
- /* Scan for devices on first start */
- scanner_redetect (scanner);
-
- while (handle_requests (scanner)) {
- switch (scanner->priv->state) {
- case STATE_IDLE:
- if (scanner->priv->job_queue) {
- set_scanning (scanner, TRUE);
- scanner->priv->state = STATE_OPEN;
- }
- break;
- case STATE_REDETECT:
- do_redetect (scanner);
- break;
- case STATE_OPEN:
- do_open (scanner);
- break;
- case STATE_GET_OPTION:
- do_get_option (scanner);
- break;
- case STATE_START:
- do_start (scanner);
- break;
- case STATE_GET_PARAMETERS:
- do_get_parameters (scanner);
- break;
- case STATE_READ:
- do_read (scanner);
- break;
- }
- }
-
- return NULL;
-}
-
-
-Scanner *
-scanner_new ()
-{
- return g_object_new (SCANNER_TYPE, NULL);
-}
-
-
-void
-scanner_start (Scanner *scanner)
-{
- GError *error = NULL;
- scanner->priv->thread = g_thread_create ((GThreadFunc) scan_thread, scanner, TRUE, &error);
- if (error) {
- g_critical ("Unable to create thread: %s", error->message);
- g_error_free (error);
- }
-}
-
-
-void
-scanner_redetect (Scanner *scanner)
-{
- ScanRequest *request;
-
- if (scanner->priv->redetect)
- return;
- scanner->priv->redetect = TRUE;
-
- g_debug ("Requesting redetection of scan devices");
-
- request = g_malloc0 (sizeof (ScanRequest));
- request->type = REQUEST_REDETECT;
- g_async_queue_push (scanner->priv->scan_queue, request);
-}
-
-
-gboolean
-scanner_is_scanning (Scanner *scanner)
-{
- return scanner->priv->scanning;
-}
-
-
-void
-scanner_scan (Scanner *scanner, const char *device, ScanOptions *options)
-{
- ScanRequest *request;
- const gchar *type_string;
-
- switch (options->type) {
- case SCAN_SINGLE:
- type_string = "SCAN_SINGLE";
- break;
- case SCAN_ADF_FRONT:
- type_string = "SCAN_ADF_FRONT";
- break;
- case SCAN_ADF_BACK:
- type_string = "SCAN_ADF_BACK";
- break;
- case SCAN_ADF_BOTH:
- type_string = "SCAN_ADF_BOTH";
- break;
- default:
- g_assert (FALSE);
- return;
- }
-
- g_debug ("scanner_scan (\"%s\", %d, %s)", device ? device : "(null)", options->dpi, type_string);
- request = g_malloc0 (sizeof (ScanRequest));
- request->type = REQUEST_START_SCAN;
- request->job = g_malloc0 (sizeof (ScanJob));
- request->job->device = g_strdup (device);
- request->job->dpi = options->dpi;
- request->job->scan_mode = options->scan_mode;
- request->job->depth = options->depth;
- request->job->type = options->type;
- request->job->page_width = options->paper_width;
- request->job->page_height = options->paper_height;
- g_async_queue_push (scanner->priv->scan_queue, request);
-}
-
-
-void
-scanner_cancel (Scanner *scanner)
-{
- ScanRequest *request;
-
- request = g_malloc0 (sizeof (ScanRequest));
- request->type = REQUEST_CANCEL;
- g_async_queue_push (scanner->priv->scan_queue, request);
-}
-
-
-void scanner_free (Scanner *scanner)
-{
- ScanRequest *request;
-
- g_debug ("Stopping scan thread");
-
- request = g_malloc0 (sizeof (ScanRequest));
- request->type = REQUEST_QUIT;
- g_async_queue_push (scanner->priv->scan_queue, request);
-
- if (scanner->priv->thread)
- g_thread_join (scanner->priv->thread);
-
- g_async_queue_unref (scanner->priv->scan_queue);
- g_object_unref (scanner);
-
- sane_exit ();
- g_debug ("sane_exit ()");
-}
-
-
-static void
-scanner_class_init (ScannerClass *klass)
-{
- signals[AUTHORIZE] =
- g_signal_new ("authorize",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, authorize),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
- signals[UPDATE_DEVICES] =
- g_signal_new ("update-devices",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, update_devices),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
- signals[EXPECT_PAGE] =
- g_signal_new ("expect-page",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, expect_page),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- signals[GOT_PAGE_INFO] =
- g_signal_new ("got-page-info",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, got_page_info),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
- signals[GOT_LINE] =
- g_signal_new ("got-line",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, got_line),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
- signals[SCAN_FAILED] =
- g_signal_new ("scan-failed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, scan_failed),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
- signals[PAGE_DONE] =
- g_signal_new ("page-done",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, page_done),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- signals[DOCUMENT_DONE] =
- g_signal_new ("document-done",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, document_done),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- signals[SCANNING_CHANGED] =
- g_signal_new ("scanning-changed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ScannerClass, scanning_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (klass, sizeof (ScannerPrivate));
-
- scanners = g_hash_table_new (g_direct_hash, g_direct_equal);
-}
-
-
-static void
-scanner_init (Scanner *scanner)
-{
- scanner->priv = G_TYPE_INSTANCE_GET_PRIVATE (scanner, SCANNER_TYPE, ScannerPrivate);
- scanner->priv->scan_queue = g_async_queue_new ();
- scanner->priv->authorize_queue = g_async_queue_new ();
+struct _Notify {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ NotifyPrivate * priv;
+};
+
+struct _NotifyClass {
+ GTypeClass parent_class;
+ void (*finalize) (Notify *self);
+ void (*run) (Notify* self, Scanner* scanner);
+};
+
+struct _ParamSpecNotify {
+ GParamSpec parent_instance;
+};
+
+struct _NotifyScanningChanged {
+ Notify parent_instance;
+ NotifyScanningChangedPrivate * priv;
+};
+
+struct _NotifyScanningChangedClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyUpdateDevices {
+ Notify parent_instance;
+ NotifyUpdateDevicesPrivate * priv;
+};
+
+struct _NotifyUpdateDevicesClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyUpdateDevicesPrivate {
+ GList* devices;
+};
+
+struct _NotifyRequestAuthorization {
+ Notify parent_instance;
+ NotifyRequestAuthorizationPrivate * priv;
+};
+
+struct _NotifyRequestAuthorizationClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyRequestAuthorizationPrivate {
+ gchar* resource;
+};
+
+struct _NotifyScanFailed {
+ Notify parent_instance;
+ NotifyScanFailedPrivate * priv;
+};
+
+struct _NotifyScanFailedClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyScanFailedPrivate {
+ gint error_code;
+ gchar* error_string;
+};
+
+struct _NotifyDocumentDone {
+ Notify parent_instance;
+ NotifyDocumentDonePrivate * priv;
+};
+
+struct _NotifyDocumentDoneClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyExpectPage {
+ Notify parent_instance;
+ NotifyExpectPagePrivate * priv;
+};
+
+struct _NotifyExpectPageClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyGotPageInfo {
+ Notify parent_instance;
+ NotifyGotPageInfoPrivate * priv;
+};
+
+struct _NotifyGotPageInfoClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyGotPageInfoPrivate {
+ ScanPageInfo* info;
+};
+
+struct _NotifyPageDone {
+ Notify parent_instance;
+ NotifyPageDonePrivate * priv;
+};
+
+struct _NotifyPageDoneClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyGotLine {
+ Notify parent_instance;
+ NotifyGotLinePrivate * priv;
+};
+
+struct _NotifyGotLineClass {
+ NotifyClass parent_class;
+};
+
+struct _NotifyGotLinePrivate {
+ ScanLine* line;
+};
+
+struct _Scanner {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScannerPrivate * priv;
+};
+
+struct _ScannerClass {
+ GTypeClass parent_class;
+ void (*finalize) (Scanner *self);
+};
+
+struct _ScannerPrivate {
+ GThread* thread;
+ GAsyncQueue* request_queue;
+ GAsyncQueue* notify_queue;
+ GAsyncQueue* authorize_queue;
+ gchar* default_device;
+ ScanState state;
+ gboolean need_redetect;
+ GList* job_queue;
+ SANE_Handle handle;
+ gboolean have_handle;
+ gchar* current_device;
+ SANE_Parameters parameters;
+ SANE_Int option_index;
+ SANE_Int br_x_option_index;
+ SANE_Int br_y_option_index;
+ guchar* buffer;
+ gint buffer_length1;
+ gint _buffer_size_;
+ gint n_used;
+ gint line_count;
+ gint pass_number;
+ gint page_number;
+ gint notified_page;
+ gboolean scanning;
+};
+
+struct _ParamSpecScanner {
+ GParamSpec parent_instance;
+};
+
+
+static gpointer scan_device_parent_class = NULL;
+static gpointer scan_page_info_parent_class = NULL;
+static gpointer scan_line_parent_class = NULL;
+static gpointer scan_options_parent_class = NULL;
+static gpointer scan_job_parent_class = NULL;
+static gpointer request_parent_class = NULL;
+static gpointer request_redetect_parent_class = NULL;
+static gpointer request_cancel_parent_class = NULL;
+static gpointer request_start_scan_parent_class = NULL;
+static gpointer request_quit_parent_class = NULL;
+static gpointer credentials_parent_class = NULL;
+static gpointer notify_parent_class = NULL;
+static gpointer notify_scanning_changed_parent_class = NULL;
+static gpointer notify_update_devices_parent_class = NULL;
+static gpointer notify_request_authorization_parent_class = NULL;
+static gpointer notify_scan_failed_parent_class = NULL;
+static gpointer notify_document_done_parent_class = NULL;
+static gpointer notify_expect_page_parent_class = NULL;
+static gpointer notify_got_page_info_parent_class = NULL;
+static gpointer notify_page_done_parent_class = NULL;
+static gpointer notify_got_line_parent_class = NULL;
+static gpointer scanner_parent_class = NULL;
+static Scanner* scanner_scanner_object;
+static Scanner* scanner_scanner_object = NULL;
+
+gpointer scan_device_ref (gpointer instance);
+void scan_device_unref (gpointer instance);
+GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scan_device (GValue* value, gpointer v_object);
+void value_take_scan_device (GValue* value, gpointer v_object);
+gpointer value_get_scan_device (const GValue* value);
+GType scan_device_get_type (void) G_GNUC_CONST;
+enum {
+ SCAN_DEVICE_DUMMY_PROPERTY
+};
+ScanDevice* scan_device_new (void);
+ScanDevice* scan_device_construct (GType object_type);
+static void scan_device_finalize (ScanDevice* obj);
+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;
+enum {
+ SCAN_PAGE_INFO_DUMMY_PROPERTY
+};
+ScanPageInfo* scan_page_info_new (void);
+ScanPageInfo* scan_page_info_construct (GType object_type);
+static void scan_page_info_finalize (ScanPageInfo* obj);
+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;
+enum {
+ SCAN_LINE_DUMMY_PROPERTY
+};
+ScanLine* scan_line_new (void);
+ScanLine* scan_line_construct (GType object_type);
+static void scan_line_finalize (ScanLine* obj);
+GType scan_mode_get_type (void) G_GNUC_CONST;
+GType scan_type_get_type (void) G_GNUC_CONST;
+gpointer scan_options_ref (gpointer instance);
+void scan_options_unref (gpointer instance);
+GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scan_options (GValue* value, gpointer v_object);
+void value_take_scan_options (GValue* value, gpointer v_object);
+gpointer value_get_scan_options (const GValue* value);
+GType scan_options_get_type (void) G_GNUC_CONST;
+enum {
+ SCAN_OPTIONS_DUMMY_PROPERTY
+};
+ScanOptions* scan_options_new (void);
+ScanOptions* scan_options_construct (GType object_type);
+static void scan_options_finalize (ScanOptions* obj);
+gpointer scan_job_ref (gpointer instance);
+void scan_job_unref (gpointer instance);
+GParamSpec* param_spec_scan_job (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scan_job (GValue* value, gpointer v_object);
+void value_take_scan_job (GValue* value, gpointer v_object);
+gpointer value_get_scan_job (const GValue* value);
+GType scan_job_get_type (void) G_GNUC_CONST;
+enum {
+ SCAN_JOB_DUMMY_PROPERTY
+};
+ScanJob* scan_job_new (void);
+ScanJob* scan_job_construct (GType object_type);
+static void scan_job_finalize (ScanJob* obj);
+gpointer request_ref (gpointer instance);
+void request_unref (gpointer instance);
+GParamSpec* param_spec_request (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_request (GValue* value, gpointer v_object);
+void value_take_request (GValue* value, gpointer v_object);
+gpointer value_get_request (const GValue* value);
+GType request_get_type (void) G_GNUC_CONST;
+enum {
+ REQUEST_DUMMY_PROPERTY
+};
+Request* request_new (void);
+Request* request_construct (GType object_type);
+static void request_finalize (Request* obj);
+GType request_redetect_get_type (void) G_GNUC_CONST;
+enum {
+ REQUEST_REDETECT_DUMMY_PROPERTY
+};
+RequestRedetect* request_redetect_new (void);
+RequestRedetect* request_redetect_construct (GType object_type);
+GType request_cancel_get_type (void) G_GNUC_CONST;
+enum {
+ REQUEST_CANCEL_DUMMY_PROPERTY
+};
+RequestCancel* request_cancel_new (void);
+RequestCancel* request_cancel_construct (GType object_type);
+GType request_start_scan_get_type (void) G_GNUC_CONST;
+enum {
+ REQUEST_START_SCAN_DUMMY_PROPERTY
+};
+RequestStartScan* request_start_scan_new (void);
+RequestStartScan* request_start_scan_construct (GType object_type);
+static void request_start_scan_finalize (Request* obj);
+GType request_quit_get_type (void) G_GNUC_CONST;
+enum {
+ REQUEST_QUIT_DUMMY_PROPERTY
+};
+RequestQuit* request_quit_new (void);
+RequestQuit* request_quit_construct (GType object_type);
+gpointer credentials_ref (gpointer instance);
+void credentials_unref (gpointer instance);
+GParamSpec* param_spec_credentials (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_credentials (GValue* value, gpointer v_object);
+void value_take_credentials (GValue* value, gpointer v_object);
+gpointer value_get_credentials (const GValue* value);
+GType credentials_get_type (void) G_GNUC_CONST;
+enum {
+ CREDENTIALS_DUMMY_PROPERTY
+};
+Credentials* credentials_new (void);
+Credentials* credentials_construct (GType object_type);
+static void credentials_finalize (Credentials* obj);
+GType scan_state_get_type (void) G_GNUC_CONST;
+gpointer notify_ref (gpointer instance);
+void notify_unref (gpointer instance);
+GParamSpec* param_spec_notify (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_notify (GValue* value, gpointer v_object);
+void value_take_notify (GValue* value, gpointer v_object);
+gpointer value_get_notify (const GValue* value);
+GType notify_get_type (void) G_GNUC_CONST;
+gpointer scanner_ref (gpointer instance);
+void scanner_unref (gpointer instance);
+GParamSpec* param_spec_scanner (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scanner (GValue* value, gpointer v_object);
+void value_take_scanner (GValue* value, gpointer v_object);
+gpointer value_get_scanner (const GValue* value);
+GType scanner_get_type (void) G_GNUC_CONST;
+enum {
+ NOTIFY_DUMMY_PROPERTY
+};
+void notify_run (Notify* self, Scanner* scanner);
+static void notify_real_run (Notify* self, Scanner* scanner);
+Notify* notify_new (void);
+Notify* notify_construct (GType object_type);
+static void notify_finalize (Notify* obj);
+GType notify_scanning_changed_get_type (void) G_GNUC_CONST;
+enum {
+ NOTIFY_SCANNING_CHANGED_DUMMY_PROPERTY
+};
+static void notify_scanning_changed_real_run (Notify* base, Scanner* scanner);
+NotifyScanningChanged* notify_scanning_changed_new (void);
+NotifyScanningChanged* notify_scanning_changed_construct (GType object_type);
+GType notify_update_devices_get_type (void) G_GNUC_CONST;
+#define NOTIFY_UPDATE_DEVICES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_UPDATE_DEVICES, NotifyUpdateDevicesPrivate))
+enum {
+ NOTIFY_UPDATE_DEVICES_DUMMY_PROPERTY
+};
+static void _scan_device_unref0_ (gpointer var);
+static void _g_list_free__scan_device_unref0_ (GList* self);
+NotifyUpdateDevices* notify_update_devices_new (GList* devices);
+NotifyUpdateDevices* notify_update_devices_construct (GType object_type, GList* devices);
+static void notify_update_devices_real_run (Notify* base, Scanner* scanner);
+static void notify_update_devices_finalize (Notify* obj);
+GType notify_request_authorization_get_type (void) G_GNUC_CONST;
+#define NOTIFY_REQUEST_AUTHORIZATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_REQUEST_AUTHORIZATION, NotifyRequestAuthorizationPrivate))
+enum {
+ NOTIFY_REQUEST_AUTHORIZATION_DUMMY_PROPERTY
+};
+NotifyRequestAuthorization* notify_request_authorization_new (const gchar* resource);
+NotifyRequestAuthorization* notify_request_authorization_construct (GType object_type, const gchar* resource);
+static void notify_request_authorization_real_run (Notify* base, Scanner* scanner);
+static void notify_request_authorization_finalize (Notify* obj);
+GType notify_scan_failed_get_type (void) G_GNUC_CONST;
+#define NOTIFY_SCAN_FAILED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_SCAN_FAILED, NotifyScanFailedPrivate))
+enum {
+ NOTIFY_SCAN_FAILED_DUMMY_PROPERTY
+};
+NotifyScanFailed* notify_scan_failed_new (gint error_code, const gchar* error_string);
+NotifyScanFailed* notify_scan_failed_construct (GType object_type, gint error_code, const gchar* error_string);
+static void notify_scan_failed_real_run (Notify* base, Scanner* scanner);
+static void notify_scan_failed_finalize (Notify* obj);
+GType notify_document_done_get_type (void) G_GNUC_CONST;
+enum {
+ NOTIFY_DOCUMENT_DONE_DUMMY_PROPERTY
+};
+static void notify_document_done_real_run (Notify* base, Scanner* scanner);
+NotifyDocumentDone* notify_document_done_new (void);
+NotifyDocumentDone* notify_document_done_construct (GType object_type);
+GType notify_expect_page_get_type (void) G_GNUC_CONST;
+enum {
+ NOTIFY_EXPECT_PAGE_DUMMY_PROPERTY
+};
+static void notify_expect_page_real_run (Notify* base, Scanner* scanner);
+NotifyExpectPage* notify_expect_page_new (void);
+NotifyExpectPage* notify_expect_page_construct (GType object_type);
+GType notify_got_page_info_get_type (void) G_GNUC_CONST;
+#define NOTIFY_GOT_PAGE_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_GOT_PAGE_INFO, NotifyGotPageInfoPrivate))
+enum {
+ NOTIFY_GOT_PAGE_INFO_DUMMY_PROPERTY
+};
+NotifyGotPageInfo* notify_got_page_info_new (ScanPageInfo* info);
+NotifyGotPageInfo* notify_got_page_info_construct (GType object_type, ScanPageInfo* info);
+static void notify_got_page_info_real_run (Notify* base, Scanner* scanner);
+static void notify_got_page_info_finalize (Notify* obj);
+GType notify_page_done_get_type (void) G_GNUC_CONST;
+enum {
+ NOTIFY_PAGE_DONE_DUMMY_PROPERTY
+};
+static void notify_page_done_real_run (Notify* base, Scanner* scanner);
+NotifyPageDone* notify_page_done_new (void);
+NotifyPageDone* notify_page_done_construct (GType object_type);
+GType notify_got_line_get_type (void) G_GNUC_CONST;
+#define NOTIFY_GOT_LINE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_NOTIFY_GOT_LINE, NotifyGotLinePrivate))
+enum {
+ NOTIFY_GOT_LINE_DUMMY_PROPERTY
+};
+NotifyGotLine* notify_got_line_new (ScanLine* line);
+NotifyGotLine* notify_got_line_construct (GType object_type, ScanLine* line);
+static void notify_got_line_real_run (Notify* base, Scanner* scanner);
+static void notify_got_line_finalize (Notify* obj);
+#define SCANNER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_SCANNER, ScannerPrivate))
+enum {
+ SCANNER_DUMMY_PROPERTY
+};
+static void _scan_job_unref0_ (gpointer var);
+static void _g_list_free__scan_job_unref0_ (GList* self);
+static Scanner* scanner_new (void);
+static Scanner* scanner_construct (GType object_type);
+Scanner* scanner_get_instance (void);
+static gboolean scanner_notify_idle_cb (Scanner* self);
+static void scanner_notify (Scanner* self, Notify* notification);
+static gboolean _scanner_notify_idle_cb_gsource_func (gpointer self);
+static void scanner_set_scanning (Scanner* self, gboolean is_scanning);
+static gint scanner_get_device_weight (const gchar* device);
+static gint scanner_compare_devices (ScanDevice* device1, ScanDevice* device2);
+static void scanner_do_redetect (Scanner* self);
+static gint _scanner_compare_devices_gcompare_func (gconstpointer a, gconstpointer b);
+static gboolean scanner_set_default_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index);
+static void scanner_set_bool_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gboolean value, gboolean* _result_);
+static void scanner_set_int_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gint value, gint* _result_);
+static void scanner_set_fixed_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gdouble value, gdouble* _result_);
+static gboolean scanner_set_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, const gchar* value, gchar** _result_);
+static gboolean scanner_set_constrained_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gchar** values, int values_length1, gchar** _result_);
+static void scanner_log_option (Scanner* self, SANE_Int index, const SANE_Option_Descriptor* option);
+static void scanner_authorization_cb (const gchar* resource, gchar* username, int username_length1, gchar* password, int password_length1);
+void scanner_authorize (Scanner* self, const gchar* username, const gchar* password);
+static void scanner_close_device (Scanner* self);
+static void scanner_fail_scan (Scanner* self, gint error_code, const gchar* error_string);
+static gboolean scanner_handle_requests (Scanner* self);
+static void scanner_do_open (Scanner* self);
+static void scanner_do_get_option (Scanner* self);
+static void scanner_do_complete_document (Scanner* self);
+static void scanner_do_start (Scanner* self);
+static void scanner_do_get_parameters (Scanner* self);
+static void scanner_do_complete_page (Scanner* self);
+static void scanner_do_read (Scanner* self);
+static void* scanner_scan_thread (Scanner* self);
+static void _scanner_authorization_cb_sane_authcallback (const gchar* resource, gchar* username, gchar* password);
+void scanner_redetect (Scanner* self);
+void scanner_start (Scanner* self);
+static gpointer _scanner_scan_thread_gthread_func (gpointer self);
+gboolean scanner_is_scanning (Scanner* self);
+static gchar* scanner_get_scan_mode_string (Scanner* self, ScanMode mode);
+static gchar* scanner_get_scan_type_string (Scanner* self, ScanType type);
+void scanner_scan (Scanner* self, const gchar* device, ScanOptions* options);
+void scanner_cancel (Scanner* self);
+void scanner_free (Scanner* self);
+static void g_cclosure_user_marshal_VOID__SCAN_PAGE_INFO (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+static void g_cclosure_user_marshal_VOID__SCAN_LINE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+static void g_cclosure_user_marshal_VOID__INT_STRING (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+static void scanner_finalize (Scanner* 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);
+
+
+ScanDevice* scan_device_construct (GType object_type) {
+ ScanDevice* self = NULL;
+ self = (ScanDevice*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+ScanDevice* scan_device_new (void) {
+ return scan_device_construct (TYPE_SCAN_DEVICE);
+}
+
+
+static void value_scan_device_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_scan_device_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ scan_device_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_scan_device_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = scan_device_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_scan_device_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_scan_device_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ ScanDevice* 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 = scan_device_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_scan_device_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ ScanDevice** 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 = scan_device_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecScanDevice* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_DEVICE), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_scan_device (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_DEVICE), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_scan_device (GValue* value, gpointer v_object) {
+ ScanDevice* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_DEVICE));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_DEVICE));
+ 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;
+ scan_device_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ scan_device_unref (old);
+ }
+}
+
+
+void value_take_scan_device (GValue* value, gpointer v_object) {
+ ScanDevice* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_DEVICE));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_DEVICE));
+ 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) {
+ scan_device_unref (old);
+ }
+}
+
+
+static void scan_device_class_init (ScanDeviceClass * klass) {
+ scan_device_parent_class = g_type_class_peek_parent (klass);
+ SCAN_DEVICE_CLASS (klass)->finalize = scan_device_finalize;
+}
+
+
+static void scan_device_instance_init (ScanDevice * self) {
+ self->ref_count = 1;
+}
+
+
+static void scan_device_finalize (ScanDevice* obj) {
+ ScanDevice * self;
+ self = SCAN_DEVICE (obj);
+ _g_free0 (self->name);
+ _g_free0 (self->label);
+}
+
+
+GType scan_device_get_type (void) {
+ static volatile gsize scan_device_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_device_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_scan_device_init, value_scan_device_free_value, value_scan_device_copy_value, value_scan_device_peek_pointer, "p", value_scan_device_collect_value, "p", value_scan_device_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (ScanDeviceClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_device_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanDevice), 0, (GInstanceInitFunc) scan_device_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 scan_device_type_id;
+ scan_device_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanDevice", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&scan_device_type_id__volatile, scan_device_type_id);
+ }
+ return scan_device_type_id__volatile;
+}
+
+
+gpointer scan_device_ref (gpointer instance) {
+ ScanDevice* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void scan_device_unref (gpointer instance) {
+ ScanDevice* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ SCAN_DEVICE_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+ScanPageInfo* scan_page_info_construct (GType object_type) {
+ ScanPageInfo* self = NULL;
+ self = (ScanPageInfo*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+ScanPageInfo* scan_page_info_new (void) {
+ return scan_page_info_construct (TYPE_SCAN_PAGE_INFO);
+}
+
+
+static void value_scan_page_info_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_scan_page_info_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ scan_page_info_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_scan_page_info_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = scan_page_info_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_scan_page_info_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_scan_page_info_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ ScanPageInfo* 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 = scan_page_info_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_scan_page_info_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ ScanPageInfo** 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 = scan_page_info_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_scan_page_info (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecScanPageInfo* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_PAGE_INFO), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_scan_page_info (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_PAGE_INFO), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_scan_page_info (GValue* value, gpointer v_object) {
+ ScanPageInfo* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_PAGE_INFO));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_PAGE_INFO));
+ 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;
+ scan_page_info_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ scan_page_info_unref (old);
+ }
+}
+
+
+void value_take_scan_page_info (GValue* value, gpointer v_object) {
+ ScanPageInfo* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_PAGE_INFO));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_PAGE_INFO));
+ 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) {
+ scan_page_info_unref (old);
+ }
+}
+
+
+static void scan_page_info_class_init (ScanPageInfoClass * klass) {
+ scan_page_info_parent_class = g_type_class_peek_parent (klass);
+ SCAN_PAGE_INFO_CLASS (klass)->finalize = scan_page_info_finalize;
+}
+
+
+static void scan_page_info_instance_init (ScanPageInfo * self) {
+ self->ref_count = 1;
+}
+
+
+static void scan_page_info_finalize (ScanPageInfo* obj) {
+ ScanPageInfo * self;
+ self = SCAN_PAGE_INFO (obj);
+ _g_free0 (self->device);
+}
+
+
+GType scan_page_info_get_type (void) {
+ static volatile gsize scan_page_info_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_page_info_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_scan_page_info_init, value_scan_page_info_free_value, value_scan_page_info_copy_value, value_scan_page_info_peek_pointer, "p", value_scan_page_info_collect_value, "p", value_scan_page_info_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (ScanPageInfoClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_page_info_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanPageInfo), 0, (GInstanceInitFunc) scan_page_info_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 scan_page_info_type_id;
+ scan_page_info_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanPageInfo", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&scan_page_info_type_id__volatile, scan_page_info_type_id);
+ }
+ return scan_page_info_type_id__volatile;
+}
+
+
+gpointer scan_page_info_ref (gpointer instance) {
+ ScanPageInfo* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void scan_page_info_unref (gpointer instance) {
+ ScanPageInfo* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ SCAN_PAGE_INFO_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+ScanLine* scan_line_construct (GType object_type) {
+ ScanLine* self = NULL;
+ self = (ScanLine*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+ScanLine* scan_line_new (void) {
+ return scan_line_construct (TYPE_SCAN_LINE);
+}
+
+
+static void value_scan_line_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_scan_line_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ scan_line_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_scan_line_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = scan_line_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_scan_line_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_scan_line_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ ScanLine* 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 = scan_line_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
}
+
+
+static gchar* value_scan_line_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ ScanLine** 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 = scan_line_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_scan_line (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecScanLine* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_LINE), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_scan_line (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_LINE), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_scan_line (GValue* value, gpointer v_object) {
+ ScanLine* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_LINE));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_LINE));
+ 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;
+ scan_line_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ scan_line_unref (old);
+ }
+}
+
+
+void value_take_scan_line (GValue* value, gpointer v_object) {
+ ScanLine* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_LINE));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_LINE));
+ 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) {
+ scan_line_unref (old);
+ }
+}
+
+
+static void scan_line_class_init (ScanLineClass * klass) {
+ scan_line_parent_class = g_type_class_peek_parent (klass);
+ SCAN_LINE_CLASS (klass)->finalize = scan_line_finalize;
+}
+
+
+static void scan_line_instance_init (ScanLine * self) {
+ self->ref_count = 1;
+}
+
+
+static void scan_line_finalize (ScanLine* obj) {
+ ScanLine * self;
+ self = SCAN_LINE (obj);
+ self->data = (g_free (self->data), NULL);
+}
+
+
+GType scan_line_get_type (void) {
+ static volatile gsize scan_line_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_line_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_scan_line_init, value_scan_line_free_value, value_scan_line_copy_value, value_scan_line_peek_pointer, "p", value_scan_line_collect_value, "p", value_scan_line_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (ScanLineClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_line_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanLine), 0, (GInstanceInitFunc) scan_line_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 scan_line_type_id;
+ scan_line_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanLine", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&scan_line_type_id__volatile, scan_line_type_id);
+ }
+ return scan_line_type_id__volatile;
+}
+
+
+gpointer scan_line_ref (gpointer instance) {
+ ScanLine* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void scan_line_unref (gpointer instance) {
+ ScanLine* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ SCAN_LINE_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+GType scan_mode_get_type (void) {
+ static volatile gsize scan_mode_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_mode_type_id__volatile)) {
+ static const GEnumValue values[] = {{SCAN_MODE_DEFAULT, "SCAN_MODE_DEFAULT", "default"}, {SCAN_MODE_COLOR, "SCAN_MODE_COLOR", "color"}, {SCAN_MODE_GRAY, "SCAN_MODE_GRAY", "gray"}, {SCAN_MODE_LINEART, "SCAN_MODE_LINEART", "lineart"}, {0, NULL, NULL}};
+ GType scan_mode_type_id;
+ scan_mode_type_id = g_enum_register_static ("ScanMode", values);
+ g_once_init_leave (&scan_mode_type_id__volatile, scan_mode_type_id);
+ }
+ return scan_mode_type_id__volatile;
+}
+
+
+GType scan_type_get_type (void) {
+ static volatile gsize scan_type_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_type_type_id__volatile)) {
+ static const GEnumValue values[] = {{SCAN_TYPE_SINGLE, "SCAN_TYPE_SINGLE", "single"}, {SCAN_TYPE_ADF_FRONT, "SCAN_TYPE_ADF_FRONT", "adf-front"}, {SCAN_TYPE_ADF_BACK, "SCAN_TYPE_ADF_BACK", "adf-back"}, {SCAN_TYPE_ADF_BOTH, "SCAN_TYPE_ADF_BOTH", "adf-both"}, {0, NULL, NULL}};
+ GType scan_type_type_id;
+ scan_type_type_id = g_enum_register_static ("ScanType", values);
+ g_once_init_leave (&scan_type_type_id__volatile, scan_type_type_id);
+ }
+ return scan_type_type_id__volatile;
+}
+
+
+ScanOptions* scan_options_construct (GType object_type) {
+ ScanOptions* self = NULL;
+ self = (ScanOptions*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+ScanOptions* scan_options_new (void) {
+ return scan_options_construct (TYPE_SCAN_OPTIONS);
+}
+
+
+static void value_scan_options_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_scan_options_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ scan_options_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_scan_options_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = scan_options_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_scan_options_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_scan_options_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ ScanOptions* 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 = scan_options_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_scan_options_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ ScanOptions** 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 = scan_options_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecScanOptions* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_OPTIONS), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_scan_options (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_OPTIONS), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_scan_options (GValue* value, gpointer v_object) {
+ ScanOptions* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_OPTIONS));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_OPTIONS));
+ 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;
+ scan_options_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ scan_options_unref (old);
+ }
+}
+
+
+void value_take_scan_options (GValue* value, gpointer v_object) {
+ ScanOptions* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_OPTIONS));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_OPTIONS));
+ 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) {
+ scan_options_unref (old);
+ }
+}
+
+
+static void scan_options_class_init (ScanOptionsClass * klass) {
+ scan_options_parent_class = g_type_class_peek_parent (klass);
+ SCAN_OPTIONS_CLASS (klass)->finalize = scan_options_finalize;
+}
+
+
+static void scan_options_instance_init (ScanOptions * self) {
+ self->ref_count = 1;
+}
+
+
+static void scan_options_finalize (ScanOptions* obj) {
+ ScanOptions * self;
+ self = SCAN_OPTIONS (obj);
+}
+
+
+GType scan_options_get_type (void) {
+ static volatile gsize scan_options_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_options_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_scan_options_init, value_scan_options_free_value, value_scan_options_copy_value, value_scan_options_peek_pointer, "p", value_scan_options_collect_value, "p", value_scan_options_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (ScanOptionsClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_options_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanOptions), 0, (GInstanceInitFunc) scan_options_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 scan_options_type_id;
+ scan_options_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanOptions", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&scan_options_type_id__volatile, scan_options_type_id);
+ }
+ return scan_options_type_id__volatile;
+}
+
+
+gpointer scan_options_ref (gpointer instance) {
+ ScanOptions* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void scan_options_unref (gpointer instance) {
+ ScanOptions* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ SCAN_OPTIONS_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+ScanJob* scan_job_construct (GType object_type) {
+ ScanJob* self = NULL;
+ self = (ScanJob*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+ScanJob* scan_job_new (void) {
+ return scan_job_construct (TYPE_SCAN_JOB);
+}
+
+
+static void value_scan_job_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_scan_job_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ scan_job_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_scan_job_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = scan_job_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_scan_job_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_scan_job_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ ScanJob* 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 = scan_job_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_scan_job_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ ScanJob** 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 = scan_job_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_scan_job (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecScanJob* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCAN_JOB), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_scan_job (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_JOB), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_scan_job (GValue* value, gpointer v_object) {
+ ScanJob* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_JOB));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_JOB));
+ 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;
+ scan_job_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ scan_job_unref (old);
+ }
+}
+
+
+void value_take_scan_job (GValue* value, gpointer v_object) {
+ ScanJob* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCAN_JOB));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCAN_JOB));
+ 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) {
+ scan_job_unref (old);
+ }
+}
+
+
+static void scan_job_class_init (ScanJobClass * klass) {
+ scan_job_parent_class = g_type_class_peek_parent (klass);
+ SCAN_JOB_CLASS (klass)->finalize = scan_job_finalize;
+}
+
+
+static void scan_job_instance_init (ScanJob * self) {
+ self->ref_count = 1;
+}
+
+
+static void scan_job_finalize (ScanJob* obj) {
+ ScanJob * self;
+ self = SCAN_JOB (obj);
+ _g_free0 (self->device);
+}
+
+
+GType scan_job_get_type (void) {
+ static volatile gsize scan_job_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_job_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_scan_job_init, value_scan_job_free_value, value_scan_job_copy_value, value_scan_job_peek_pointer, "p", value_scan_job_collect_value, "p", value_scan_job_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (ScanJobClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scan_job_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScanJob), 0, (GInstanceInitFunc) scan_job_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 scan_job_type_id;
+ scan_job_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScanJob", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&scan_job_type_id__volatile, scan_job_type_id);
+ }
+ return scan_job_type_id__volatile;
+}
+
+
+gpointer scan_job_ref (gpointer instance) {
+ ScanJob* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void scan_job_unref (gpointer instance) {
+ ScanJob* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ SCAN_JOB_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+Request* request_construct (GType object_type) {
+ Request* self = NULL;
+ self = (Request*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+Request* request_new (void) {
+ return request_construct (TYPE_REQUEST);
+}
+
+
+static void value_request_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_request_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ request_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_request_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = request_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_request_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_request_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ Request* 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 = request_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_request_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ Request** 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 = request_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_request (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecRequest* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_REQUEST), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_request (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_REQUEST), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_request (GValue* value, gpointer v_object) {
+ Request* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_REQUEST));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_REQUEST));
+ 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;
+ request_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ request_unref (old);
+ }
+}
+
+
+void value_take_request (GValue* value, gpointer v_object) {
+ Request* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_REQUEST));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_REQUEST));
+ 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) {
+ request_unref (old);
+ }
+}
+
+
+static void request_class_init (RequestClass * klass) {
+ request_parent_class = g_type_class_peek_parent (klass);
+ REQUEST_CLASS (klass)->finalize = request_finalize;
+}
+
+
+static void request_instance_init (Request * self) {
+ self->ref_count = 1;
+}
+
+
+static void request_finalize (Request* obj) {
+ Request * self;
+ self = REQUEST (obj);
+}
+
+
+GType request_get_type (void) {
+ static volatile gsize request_type_id__volatile = 0;
+ if (g_once_init_enter (&request_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_request_init, value_request_free_value, value_request_copy_value, value_request_peek_pointer, "p", value_request_collect_value, "p", value_request_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (RequestClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Request), 0, (GInstanceInitFunc) request_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 request_type_id;
+ request_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Request", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&request_type_id__volatile, request_type_id);
+ }
+ return request_type_id__volatile;
+}
+
+
+gpointer request_ref (gpointer instance) {
+ Request* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void request_unref (gpointer instance) {
+ Request* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ REQUEST_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+RequestRedetect* request_redetect_construct (GType object_type) {
+ RequestRedetect* self = NULL;
+ self = (RequestRedetect*) request_construct (object_type);
+ return self;
+}
+
+
+RequestRedetect* request_redetect_new (void) {
+ return request_redetect_construct (TYPE_REQUEST_REDETECT);
+}
+
+
+static void request_redetect_class_init (RequestRedetectClass * klass) {
+ request_redetect_parent_class = g_type_class_peek_parent (klass);
+}
+
+
+static void request_redetect_instance_init (RequestRedetect * self) {
+}
+
+
+GType request_redetect_get_type (void) {
+ static volatile gsize request_redetect_type_id__volatile = 0;
+ if (g_once_init_enter (&request_redetect_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (RequestRedetectClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_redetect_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestRedetect), 0, (GInstanceInitFunc) request_redetect_instance_init, NULL };
+ GType request_redetect_type_id;
+ request_redetect_type_id = g_type_register_static (TYPE_REQUEST, "RequestRedetect", &g_define_type_info, 0);
+ g_once_init_leave (&request_redetect_type_id__volatile, request_redetect_type_id);
+ }
+ return request_redetect_type_id__volatile;
+}
+
+
+RequestCancel* request_cancel_construct (GType object_type) {
+ RequestCancel* self = NULL;
+ self = (RequestCancel*) request_construct (object_type);
+ return self;
+}
+
+
+RequestCancel* request_cancel_new (void) {
+ return request_cancel_construct (TYPE_REQUEST_CANCEL);
+}
+
+
+static void request_cancel_class_init (RequestCancelClass * klass) {
+ request_cancel_parent_class = g_type_class_peek_parent (klass);
+}
+
+
+static void request_cancel_instance_init (RequestCancel * self) {
+}
+
+
+GType request_cancel_get_type (void) {
+ static volatile gsize request_cancel_type_id__volatile = 0;
+ if (g_once_init_enter (&request_cancel_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (RequestCancelClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_cancel_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestCancel), 0, (GInstanceInitFunc) request_cancel_instance_init, NULL };
+ GType request_cancel_type_id;
+ request_cancel_type_id = g_type_register_static (TYPE_REQUEST, "RequestCancel", &g_define_type_info, 0);
+ g_once_init_leave (&request_cancel_type_id__volatile, request_cancel_type_id);
+ }
+ return request_cancel_type_id__volatile;
+}
+
+
+RequestStartScan* request_start_scan_construct (GType object_type) {
+ RequestStartScan* self = NULL;
+ self = (RequestStartScan*) request_construct (object_type);
+ return self;
+}
+
+
+RequestStartScan* request_start_scan_new (void) {
+ return request_start_scan_construct (TYPE_REQUEST_START_SCAN);
+}
+
+
+static void request_start_scan_class_init (RequestStartScanClass * klass) {
+ request_start_scan_parent_class = g_type_class_peek_parent (klass);
+ REQUEST_CLASS (klass)->finalize = request_start_scan_finalize;
+}
+
+
+static void request_start_scan_instance_init (RequestStartScan * self) {
+}
+
+
+static void request_start_scan_finalize (Request* obj) {
+ RequestStartScan * self;
+ self = REQUEST_START_SCAN (obj);
+ _scan_job_unref0 (self->job);
+ REQUEST_CLASS (request_start_scan_parent_class)->finalize (obj);
+}
+
+
+GType request_start_scan_get_type (void) {
+ static volatile gsize request_start_scan_type_id__volatile = 0;
+ if (g_once_init_enter (&request_start_scan_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (RequestStartScanClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_start_scan_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestStartScan), 0, (GInstanceInitFunc) request_start_scan_instance_init, NULL };
+ GType request_start_scan_type_id;
+ request_start_scan_type_id = g_type_register_static (TYPE_REQUEST, "RequestStartScan", &g_define_type_info, 0);
+ g_once_init_leave (&request_start_scan_type_id__volatile, request_start_scan_type_id);
+ }
+ return request_start_scan_type_id__volatile;
+}
+
+
+RequestQuit* request_quit_construct (GType object_type) {
+ RequestQuit* self = NULL;
+ self = (RequestQuit*) request_construct (object_type);
+ return self;
+}
+
+
+RequestQuit* request_quit_new (void) {
+ return request_quit_construct (TYPE_REQUEST_QUIT);
+}
+
+
+static void request_quit_class_init (RequestQuitClass * klass) {
+ request_quit_parent_class = g_type_class_peek_parent (klass);
+}
+
+
+static void request_quit_instance_init (RequestQuit * self) {
+}
+
+
+GType request_quit_get_type (void) {
+ static volatile gsize request_quit_type_id__volatile = 0;
+ if (g_once_init_enter (&request_quit_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (RequestQuitClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) request_quit_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RequestQuit), 0, (GInstanceInitFunc) request_quit_instance_init, NULL };
+ GType request_quit_type_id;
+ request_quit_type_id = g_type_register_static (TYPE_REQUEST, "RequestQuit", &g_define_type_info, 0);
+ g_once_init_leave (&request_quit_type_id__volatile, request_quit_type_id);
+ }
+ return request_quit_type_id__volatile;
+}
+
+
+Credentials* credentials_construct (GType object_type) {
+ Credentials* self = NULL;
+ self = (Credentials*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+Credentials* credentials_new (void) {
+ return credentials_construct (TYPE_CREDENTIALS);
+}
+
+
+static void value_credentials_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_credentials_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ credentials_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_credentials_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = credentials_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_credentials_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_credentials_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ Credentials* 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 = credentials_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_credentials_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ Credentials** 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 = credentials_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_credentials (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecCredentials* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_CREDENTIALS), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_credentials (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CREDENTIALS), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_credentials (GValue* value, gpointer v_object) {
+ Credentials* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CREDENTIALS));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_CREDENTIALS));
+ 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;
+ credentials_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ credentials_unref (old);
+ }
+}
+
+
+void value_take_credentials (GValue* value, gpointer v_object) {
+ Credentials* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_CREDENTIALS));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_CREDENTIALS));
+ 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) {
+ credentials_unref (old);
+ }
+}
+
+
+static void credentials_class_init (CredentialsClass * klass) {
+ credentials_parent_class = g_type_class_peek_parent (klass);
+ CREDENTIALS_CLASS (klass)->finalize = credentials_finalize;
+}
+
+
+static void credentials_instance_init (Credentials * self) {
+ self->ref_count = 1;
+}
+
+
+static void credentials_finalize (Credentials* obj) {
+ Credentials * self;
+ self = CREDENTIALS (obj);
+ _g_free0 (self->username);
+ _g_free0 (self->password);
+}
+
+
+GType credentials_get_type (void) {
+ static volatile gsize credentials_type_id__volatile = 0;
+ if (g_once_init_enter (&credentials_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_credentials_init, value_credentials_free_value, value_credentials_copy_value, value_credentials_peek_pointer, "p", value_credentials_collect_value, "p", value_credentials_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (CredentialsClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) credentials_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Credentials), 0, (GInstanceInitFunc) credentials_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 credentials_type_id;
+ credentials_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Credentials", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&credentials_type_id__volatile, credentials_type_id);
+ }
+ return credentials_type_id__volatile;
+}
+
+
+gpointer credentials_ref (gpointer instance) {
+ Credentials* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void credentials_unref (gpointer instance) {
+ Credentials* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ CREDENTIALS_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+GType scan_state_get_type (void) {
+ static volatile gsize scan_state_type_id__volatile = 0;
+ if (g_once_init_enter (&scan_state_type_id__volatile)) {
+ static const GEnumValue values[] = {{SCAN_STATE_IDLE, "SCAN_STATE_IDLE", "idle"}, {SCAN_STATE_REDETECT, "SCAN_STATE_REDETECT", "redetect"}, {SCAN_STATE_OPEN, "SCAN_STATE_OPEN", "open"}, {SCAN_STATE_GET_OPTION, "SCAN_STATE_GET_OPTION", "get-option"}, {SCAN_STATE_START, "SCAN_STATE_START", "start"}, {SCAN_STATE_GET_PARAMETERS, "SCAN_STATE_GET_PARAMETERS", "get-parameters"}, {SCAN_STATE_READ, "SCAN_STATE_READ", "read"}, {0, NULL, NULL}};
+ GType scan_state_type_id;
+ scan_state_type_id = g_enum_register_static ("ScanState", values);
+ g_once_init_leave (&scan_state_type_id__volatile, scan_state_type_id);
+ }
+ return scan_state_type_id__volatile;
+}
+
+
+static void notify_real_run (Notify* self, Scanner* scanner) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+}
+
+
+void notify_run (Notify* self, Scanner* scanner) {
+ NOTIFY_GET_CLASS (self)->run (self, scanner);
+}
+
+
+Notify* notify_construct (GType object_type) {
+ Notify* self = NULL;
+ self = (Notify*) g_type_create_instance (object_type);
+ return self;
+}
+
+
+Notify* notify_new (void) {
+ return notify_construct (TYPE_NOTIFY);
+}
+
+
+static void value_notify_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_notify_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ notify_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_notify_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = notify_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_notify_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_notify_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ Notify* 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 = notify_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_notify_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ Notify** 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 = notify_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_notify (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecNotify* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_NOTIFY), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_notify (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_NOTIFY), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_notify (GValue* value, gpointer v_object) {
+ Notify* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_NOTIFY));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_NOTIFY));
+ 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;
+ notify_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ notify_unref (old);
+ }
+}
+
+
+void value_take_notify (GValue* value, gpointer v_object) {
+ Notify* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_NOTIFY));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_NOTIFY));
+ 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) {
+ notify_unref (old);
+ }
+}
+
+
+static void notify_class_init (NotifyClass * klass) {
+ notify_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->finalize = notify_finalize;
+ NOTIFY_CLASS (klass)->run = notify_real_run;
+}
+
+
+static void notify_instance_init (Notify * self) {
+ self->ref_count = 1;
+}
+
+
+static void notify_finalize (Notify* obj) {
+ Notify * self;
+ self = NOTIFY (obj);
+}
+
+
+GType notify_get_type (void) {
+ static volatile gsize notify_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_notify_init, value_notify_free_value, value_notify_copy_value, value_notify_peek_pointer, "p", value_notify_collect_value, "p", value_notify_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Notify), 0, (GInstanceInitFunc) notify_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 notify_type_id;
+ notify_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Notify", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&notify_type_id__volatile, notify_type_id);
+ }
+ return notify_type_id__volatile;
+}
+
+
+gpointer notify_ref (gpointer instance) {
+ Notify* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void notify_unref (gpointer instance) {
+ Notify* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ NOTIFY_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+static void notify_scanning_changed_real_run (Notify* base, Scanner* scanner) {
+ NotifyScanningChanged * self;
+ self = (NotifyScanningChanged*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "scanning-changed");
+}
+
+
+NotifyScanningChanged* notify_scanning_changed_construct (GType object_type) {
+ NotifyScanningChanged* self = NULL;
+ self = (NotifyScanningChanged*) notify_construct (object_type);
+ return self;
+}
+
+
+NotifyScanningChanged* notify_scanning_changed_new (void) {
+ return notify_scanning_changed_construct (TYPE_NOTIFY_SCANNING_CHANGED);
+}
+
+
+static void notify_scanning_changed_class_init (NotifyScanningChangedClass * klass) {
+ notify_scanning_changed_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->run = notify_scanning_changed_real_run;
+}
+
+
+static void notify_scanning_changed_instance_init (NotifyScanningChanged * self) {
+}
+
+
+GType notify_scanning_changed_get_type (void) {
+ static volatile gsize notify_scanning_changed_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_scanning_changed_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyScanningChangedClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_scanning_changed_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyScanningChanged), 0, (GInstanceInitFunc) notify_scanning_changed_instance_init, NULL };
+ GType notify_scanning_changed_type_id;
+ notify_scanning_changed_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyScanningChanged", &g_define_type_info, 0);
+ g_once_init_leave (&notify_scanning_changed_type_id__volatile, notify_scanning_changed_type_id);
+ }
+ return notify_scanning_changed_type_id__volatile;
+}
+
+
+static void _scan_device_unref0_ (gpointer var) {
+ (var == NULL) ? NULL : (var = (scan_device_unref (var), NULL));
+}
+
+
+static void _g_list_free__scan_device_unref0_ (GList* self) {
+ g_list_foreach (self, (GFunc) _scan_device_unref0_, NULL);
+ g_list_free (self);
+}
+
+
+NotifyUpdateDevices* notify_update_devices_construct (GType object_type, GList* devices) {
+ NotifyUpdateDevices* self = NULL;
+ GList* _tmp0_;
+ self = (NotifyUpdateDevices*) notify_construct (object_type);
+ _tmp0_ = devices;
+ devices = NULL;
+ __g_list_free__scan_device_unref0_0 (self->priv->devices);
+ self->priv->devices = _tmp0_;
+ __g_list_free__scan_device_unref0_0 (devices);
+ return self;
+}
+
+
+NotifyUpdateDevices* notify_update_devices_new (GList* devices) {
+ return notify_update_devices_construct (TYPE_NOTIFY_UPDATE_DEVICES, devices);
+}
+
+
+static void notify_update_devices_real_run (Notify* base, Scanner* scanner) {
+ NotifyUpdateDevices * self;
+ self = (NotifyUpdateDevices*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "update-devices", self->priv->devices);
+}
+
+
+static void notify_update_devices_class_init (NotifyUpdateDevicesClass * klass) {
+ notify_update_devices_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->finalize = notify_update_devices_finalize;
+ g_type_class_add_private (klass, sizeof (NotifyUpdateDevicesPrivate));
+ NOTIFY_CLASS (klass)->run = notify_update_devices_real_run;
+}
+
+
+static void notify_update_devices_instance_init (NotifyUpdateDevices * self) {
+ self->priv = NOTIFY_UPDATE_DEVICES_GET_PRIVATE (self);
+}
+
+
+static void notify_update_devices_finalize (Notify* obj) {
+ NotifyUpdateDevices * self;
+ self = NOTIFY_UPDATE_DEVICES (obj);
+ __g_list_free__scan_device_unref0_0 (self->priv->devices);
+ NOTIFY_CLASS (notify_update_devices_parent_class)->finalize (obj);
+}
+
+
+GType notify_update_devices_get_type (void) {
+ static volatile gsize notify_update_devices_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_update_devices_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyUpdateDevicesClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_update_devices_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyUpdateDevices), 0, (GInstanceInitFunc) notify_update_devices_instance_init, NULL };
+ GType notify_update_devices_type_id;
+ notify_update_devices_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyUpdateDevices", &g_define_type_info, 0);
+ g_once_init_leave (&notify_update_devices_type_id__volatile, notify_update_devices_type_id);
+ }
+ return notify_update_devices_type_id__volatile;
+}
+
+
+NotifyRequestAuthorization* notify_request_authorization_construct (GType object_type, const gchar* resource) {
+ NotifyRequestAuthorization* self = NULL;
+ gchar* _tmp0_;
+ g_return_val_if_fail (resource != NULL, NULL);
+ self = (NotifyRequestAuthorization*) notify_construct (object_type);
+ _tmp0_ = g_strdup (resource);
+ _g_free0 (self->priv->resource);
+ self->priv->resource = _tmp0_;
+ return self;
+}
+
+
+NotifyRequestAuthorization* notify_request_authorization_new (const gchar* resource) {
+ return notify_request_authorization_construct (TYPE_NOTIFY_REQUEST_AUTHORIZATION, resource);
+}
+
+
+static void notify_request_authorization_real_run (Notify* base, Scanner* scanner) {
+ NotifyRequestAuthorization * self;
+ self = (NotifyRequestAuthorization*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "request-authorization", self->priv->resource);
+}
+
+
+static void notify_request_authorization_class_init (NotifyRequestAuthorizationClass * klass) {
+ notify_request_authorization_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->finalize = notify_request_authorization_finalize;
+ g_type_class_add_private (klass, sizeof (NotifyRequestAuthorizationPrivate));
+ NOTIFY_CLASS (klass)->run = notify_request_authorization_real_run;
+}
+
+
+static void notify_request_authorization_instance_init (NotifyRequestAuthorization * self) {
+ self->priv = NOTIFY_REQUEST_AUTHORIZATION_GET_PRIVATE (self);
+}
+
+
+static void notify_request_authorization_finalize (Notify* obj) {
+ NotifyRequestAuthorization * self;
+ self = NOTIFY_REQUEST_AUTHORIZATION (obj);
+ _g_free0 (self->priv->resource);
+ NOTIFY_CLASS (notify_request_authorization_parent_class)->finalize (obj);
+}
+
+
+GType notify_request_authorization_get_type (void) {
+ static volatile gsize notify_request_authorization_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_request_authorization_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyRequestAuthorizationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_request_authorization_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyRequestAuthorization), 0, (GInstanceInitFunc) notify_request_authorization_instance_init, NULL };
+ GType notify_request_authorization_type_id;
+ notify_request_authorization_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyRequestAuthorization", &g_define_type_info, 0);
+ g_once_init_leave (&notify_request_authorization_type_id__volatile, notify_request_authorization_type_id);
+ }
+ return notify_request_authorization_type_id__volatile;
+}
+
+
+NotifyScanFailed* notify_scan_failed_construct (GType object_type, gint error_code, const gchar* error_string) {
+ NotifyScanFailed* self = NULL;
+ gchar* _tmp0_;
+ g_return_val_if_fail (error_string != NULL, NULL);
+ self = (NotifyScanFailed*) notify_construct (object_type);
+ self->priv->error_code = error_code;
+ _tmp0_ = g_strdup (error_string);
+ _g_free0 (self->priv->error_string);
+ self->priv->error_string = _tmp0_;
+ return self;
+}
+
+
+NotifyScanFailed* notify_scan_failed_new (gint error_code, const gchar* error_string) {
+ return notify_scan_failed_construct (TYPE_NOTIFY_SCAN_FAILED, error_code, error_string);
+}
+
+
+static void notify_scan_failed_real_run (Notify* base, Scanner* scanner) {
+ NotifyScanFailed * self;
+ self = (NotifyScanFailed*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "scan-failed", self->priv->error_code, self->priv->error_string);
+}
+
+
+static void notify_scan_failed_class_init (NotifyScanFailedClass * klass) {
+ notify_scan_failed_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->finalize = notify_scan_failed_finalize;
+ g_type_class_add_private (klass, sizeof (NotifyScanFailedPrivate));
+ NOTIFY_CLASS (klass)->run = notify_scan_failed_real_run;
+}
+
+
+static void notify_scan_failed_instance_init (NotifyScanFailed * self) {
+ self->priv = NOTIFY_SCAN_FAILED_GET_PRIVATE (self);
+}
+
+
+static void notify_scan_failed_finalize (Notify* obj) {
+ NotifyScanFailed * self;
+ self = NOTIFY_SCAN_FAILED (obj);
+ _g_free0 (self->priv->error_string);
+ NOTIFY_CLASS (notify_scan_failed_parent_class)->finalize (obj);
+}
+
+
+GType notify_scan_failed_get_type (void) {
+ static volatile gsize notify_scan_failed_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_scan_failed_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyScanFailedClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_scan_failed_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyScanFailed), 0, (GInstanceInitFunc) notify_scan_failed_instance_init, NULL };
+ GType notify_scan_failed_type_id;
+ notify_scan_failed_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyScanFailed", &g_define_type_info, 0);
+ g_once_init_leave (&notify_scan_failed_type_id__volatile, notify_scan_failed_type_id);
+ }
+ return notify_scan_failed_type_id__volatile;
+}
+
+
+static void notify_document_done_real_run (Notify* base, Scanner* scanner) {
+ NotifyDocumentDone * self;
+ self = (NotifyDocumentDone*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "document-done");
+}
+
+
+NotifyDocumentDone* notify_document_done_construct (GType object_type) {
+ NotifyDocumentDone* self = NULL;
+ self = (NotifyDocumentDone*) notify_construct (object_type);
+ return self;
+}
+
+
+NotifyDocumentDone* notify_document_done_new (void) {
+ return notify_document_done_construct (TYPE_NOTIFY_DOCUMENT_DONE);
+}
+
+
+static void notify_document_done_class_init (NotifyDocumentDoneClass * klass) {
+ notify_document_done_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->run = notify_document_done_real_run;
+}
+
+
+static void notify_document_done_instance_init (NotifyDocumentDone * self) {
+}
+
+
+GType notify_document_done_get_type (void) {
+ static volatile gsize notify_document_done_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_document_done_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyDocumentDoneClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_document_done_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyDocumentDone), 0, (GInstanceInitFunc) notify_document_done_instance_init, NULL };
+ GType notify_document_done_type_id;
+ notify_document_done_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyDocumentDone", &g_define_type_info, 0);
+ g_once_init_leave (&notify_document_done_type_id__volatile, notify_document_done_type_id);
+ }
+ return notify_document_done_type_id__volatile;
+}
+
+
+static void notify_expect_page_real_run (Notify* base, Scanner* scanner) {
+ NotifyExpectPage * self;
+ self = (NotifyExpectPage*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "expect-page");
+}
+
+
+NotifyExpectPage* notify_expect_page_construct (GType object_type) {
+ NotifyExpectPage* self = NULL;
+ self = (NotifyExpectPage*) notify_construct (object_type);
+ return self;
+}
+
+
+NotifyExpectPage* notify_expect_page_new (void) {
+ return notify_expect_page_construct (TYPE_NOTIFY_EXPECT_PAGE);
+}
+
+
+static void notify_expect_page_class_init (NotifyExpectPageClass * klass) {
+ notify_expect_page_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->run = notify_expect_page_real_run;
+}
+
+
+static void notify_expect_page_instance_init (NotifyExpectPage * self) {
+}
+
+
+GType notify_expect_page_get_type (void) {
+ static volatile gsize notify_expect_page_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_expect_page_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyExpectPageClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_expect_page_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyExpectPage), 0, (GInstanceInitFunc) notify_expect_page_instance_init, NULL };
+ GType notify_expect_page_type_id;
+ notify_expect_page_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyExpectPage", &g_define_type_info, 0);
+ g_once_init_leave (&notify_expect_page_type_id__volatile, notify_expect_page_type_id);
+ }
+ return notify_expect_page_type_id__volatile;
+}
+
+
+static gpointer _scan_page_info_ref0 (gpointer self) {
+ return self ? scan_page_info_ref (self) : NULL;
+}
+
+
+NotifyGotPageInfo* notify_got_page_info_construct (GType object_type, ScanPageInfo* info) {
+ NotifyGotPageInfo* self = NULL;
+ ScanPageInfo* _tmp0_;
+ g_return_val_if_fail (info != NULL, NULL);
+ self = (NotifyGotPageInfo*) notify_construct (object_type);
+ _tmp0_ = _scan_page_info_ref0 (info);
+ _scan_page_info_unref0 (self->priv->info);
+ self->priv->info = _tmp0_;
+ return self;
+}
+
+
+NotifyGotPageInfo* notify_got_page_info_new (ScanPageInfo* info) {
+ return notify_got_page_info_construct (TYPE_NOTIFY_GOT_PAGE_INFO, info);
+}
+
+
+static void notify_got_page_info_real_run (Notify* base, Scanner* scanner) {
+ NotifyGotPageInfo * self;
+ self = (NotifyGotPageInfo*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "got-page-info", self->priv->info);
+}
+
+
+static void notify_got_page_info_class_init (NotifyGotPageInfoClass * klass) {
+ notify_got_page_info_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->finalize = notify_got_page_info_finalize;
+ g_type_class_add_private (klass, sizeof (NotifyGotPageInfoPrivate));
+ NOTIFY_CLASS (klass)->run = notify_got_page_info_real_run;
+}
+
+
+static void notify_got_page_info_instance_init (NotifyGotPageInfo * self) {
+ self->priv = NOTIFY_GOT_PAGE_INFO_GET_PRIVATE (self);
+}
+
+
+static void notify_got_page_info_finalize (Notify* obj) {
+ NotifyGotPageInfo * self;
+ self = NOTIFY_GOT_PAGE_INFO (obj);
+ _scan_page_info_unref0 (self->priv->info);
+ NOTIFY_CLASS (notify_got_page_info_parent_class)->finalize (obj);
+}
+
+
+GType notify_got_page_info_get_type (void) {
+ static volatile gsize notify_got_page_info_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_got_page_info_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyGotPageInfoClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_got_page_info_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyGotPageInfo), 0, (GInstanceInitFunc) notify_got_page_info_instance_init, NULL };
+ GType notify_got_page_info_type_id;
+ notify_got_page_info_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyGotPageInfo", &g_define_type_info, 0);
+ g_once_init_leave (&notify_got_page_info_type_id__volatile, notify_got_page_info_type_id);
+ }
+ return notify_got_page_info_type_id__volatile;
+}
+
+
+static void notify_page_done_real_run (Notify* base, Scanner* scanner) {
+ NotifyPageDone * self;
+ self = (NotifyPageDone*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "page-done");
+}
+
+
+NotifyPageDone* notify_page_done_construct (GType object_type) {
+ NotifyPageDone* self = NULL;
+ self = (NotifyPageDone*) notify_construct (object_type);
+ return self;
+}
+
+
+NotifyPageDone* notify_page_done_new (void) {
+ return notify_page_done_construct (TYPE_NOTIFY_PAGE_DONE);
+}
+
+
+static void notify_page_done_class_init (NotifyPageDoneClass * klass) {
+ notify_page_done_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->run = notify_page_done_real_run;
+}
+
+
+static void notify_page_done_instance_init (NotifyPageDone * self) {
+}
+
+
+GType notify_page_done_get_type (void) {
+ static volatile gsize notify_page_done_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_page_done_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyPageDoneClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_page_done_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyPageDone), 0, (GInstanceInitFunc) notify_page_done_instance_init, NULL };
+ GType notify_page_done_type_id;
+ notify_page_done_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyPageDone", &g_define_type_info, 0);
+ g_once_init_leave (&notify_page_done_type_id__volatile, notify_page_done_type_id);
+ }
+ return notify_page_done_type_id__volatile;
+}
+
+
+static gpointer _scan_line_ref0 (gpointer self) {
+ return self ? scan_line_ref (self) : NULL;
+}
+
+
+NotifyGotLine* notify_got_line_construct (GType object_type, ScanLine* line) {
+ NotifyGotLine* self = NULL;
+ ScanLine* _tmp0_;
+ g_return_val_if_fail (line != NULL, NULL);
+ self = (NotifyGotLine*) notify_construct (object_type);
+ _tmp0_ = _scan_line_ref0 (line);
+ _scan_line_unref0 (self->priv->line);
+ self->priv->line = _tmp0_;
+ return self;
+}
+
+
+NotifyGotLine* notify_got_line_new (ScanLine* line) {
+ return notify_got_line_construct (TYPE_NOTIFY_GOT_LINE, line);
+}
+
+
+static void notify_got_line_real_run (Notify* base, Scanner* scanner) {
+ NotifyGotLine * self;
+ self = (NotifyGotLine*) base;
+ g_return_if_fail (scanner != NULL);
+ g_signal_emit_by_name (scanner, "got-line", self->priv->line);
+}
+
+
+static void notify_got_line_class_init (NotifyGotLineClass * klass) {
+ notify_got_line_parent_class = g_type_class_peek_parent (klass);
+ NOTIFY_CLASS (klass)->finalize = notify_got_line_finalize;
+ g_type_class_add_private (klass, sizeof (NotifyGotLinePrivate));
+ NOTIFY_CLASS (klass)->run = notify_got_line_real_run;
+}
+
+
+static void notify_got_line_instance_init (NotifyGotLine * self) {
+ self->priv = NOTIFY_GOT_LINE_GET_PRIVATE (self);
+}
+
+
+static void notify_got_line_finalize (Notify* obj) {
+ NotifyGotLine * self;
+ self = NOTIFY_GOT_LINE (obj);
+ _scan_line_unref0 (self->priv->line);
+ NOTIFY_CLASS (notify_got_line_parent_class)->finalize (obj);
+}
+
+
+GType notify_got_line_get_type (void) {
+ static volatile gsize notify_got_line_type_id__volatile = 0;
+ if (g_once_init_enter (&notify_got_line_type_id__volatile)) {
+ static const GTypeInfo g_define_type_info = { sizeof (NotifyGotLineClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) notify_got_line_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (NotifyGotLine), 0, (GInstanceInitFunc) notify_got_line_instance_init, NULL };
+ GType notify_got_line_type_id;
+ notify_got_line_type_id = g_type_register_static (TYPE_NOTIFY, "NotifyGotLine", &g_define_type_info, 0);
+ g_once_init_leave (&notify_got_line_type_id__volatile, notify_got_line_type_id);
+ }
+ return notify_got_line_type_id__volatile;
+}
+
+
+static void _scan_job_unref0_ (gpointer var) {
+ (var == NULL) ? NULL : (var = (scan_job_unref (var), NULL));
+}
+
+
+static void _g_list_free__scan_job_unref0_ (GList* self) {
+ g_list_foreach (self, (GFunc) _scan_job_unref0_, NULL);
+ g_list_free (self);
+}
+
+
+static Scanner* scanner_construct (GType object_type) {
+ Scanner* self = NULL;
+ GAsyncQueue* _tmp0_ = NULL;
+ GAsyncQueue* _tmp1_ = NULL;
+ GAsyncQueue* _tmp2_ = NULL;
+ self = (Scanner*) g_type_create_instance (object_type);
+ _tmp0_ = g_async_queue_new ();
+ _g_async_queue_unref0 (self->priv->request_queue);
+ self->priv->request_queue = _tmp0_;
+ _tmp1_ = g_async_queue_new ();
+ _g_async_queue_unref0 (self->priv->notify_queue);
+ self->priv->notify_queue = _tmp1_;
+ _tmp2_ = g_async_queue_new ();
+ _g_async_queue_unref0 (self->priv->authorize_queue);
+ self->priv->authorize_queue = _tmp2_;
+ return self;
+}
+
+
+static Scanner* scanner_new (void) {
+ return scanner_construct (TYPE_SCANNER);
+}
+
+
+static gpointer _scanner_ref0 (gpointer self) {
+ return self ? scanner_ref (self) : NULL;
+}
+
+
+Scanner* scanner_get_instance (void) {
+ Scanner* result = NULL;
+ Scanner* _tmp1_;
+ if (scanner_scanner_object == NULL) {
+ Scanner* _tmp0_ = NULL;
+ _tmp0_ = scanner_new ();
+ _scanner_unref0 (scanner_scanner_object);
+ scanner_scanner_object = _tmp0_;
+ }
+ _tmp1_ = _scanner_ref0 (scanner_scanner_object);
+ result = _tmp1_;
+ return result;
+}
+
+
+static gboolean scanner_notify_idle_cb (Scanner* self) {
+ gboolean result = FALSE;
+ gpointer _tmp0_ = NULL;
+ Notify* notification;
+ g_return_val_if_fail (self != NULL, FALSE);
+ _tmp0_ = g_async_queue_pop (self->priv->notify_queue);
+ notification = (Notify*) _tmp0_;
+ notify_run (notification, self);
+ result = FALSE;
+ _notify_unref0 (notification);
+ return result;
+}
+
+
+static gpointer _notify_ref0 (gpointer self) {
+ return self ? notify_ref (self) : NULL;
+}
+
+
+static gboolean _scanner_notify_idle_cb_gsource_func (gpointer self) {
+ gboolean result;
+ result = scanner_notify_idle_cb (self);
+ return result;
+}
+
+
+static void scanner_notify (Scanner* self, Notify* notification) {
+ Notify* _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (notification != NULL);
+ _tmp0_ = _notify_ref0 (notification);
+ g_async_queue_push (self->priv->notify_queue, _tmp0_);
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, _scanner_notify_idle_cb_gsource_func, scanner_ref (self), scanner_unref);
+}
+
+
+static void scanner_set_scanning (Scanner* self, gboolean is_scanning) {
+ gboolean _tmp0_ = FALSE;
+ gboolean _tmp1_ = FALSE;
+ g_return_if_fail (self != NULL);
+ if (self->priv->scanning) {
+ _tmp1_ = !is_scanning;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ _tmp0_ = TRUE;
+ } else {
+ gboolean _tmp2_ = FALSE;
+ if (!self->priv->scanning) {
+ _tmp2_ = is_scanning;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ _tmp0_ = _tmp2_;
+ }
+ if (_tmp0_) {
+ NotifyScanningChanged* _tmp3_ = NULL;
+ NotifyScanningChanged* _tmp4_;
+ self->priv->scanning = is_scanning;
+ g_signal_emit_by_name (self, "scanning-changed");
+ _tmp3_ = notify_scanning_changed_new ();
+ _tmp4_ = _tmp3_;
+ scanner_notify (self, (Notify*) _tmp4_);
+ _notify_unref0 (_tmp4_);
+ }
+}
+
+
+static gboolean string_contains (const gchar* self, const gchar* needle) {
+ gboolean result = FALSE;
+ gchar* _tmp0_ = NULL;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (needle != NULL, FALSE);
+ _tmp0_ = strstr ((gchar*) self, (gchar*) needle);
+ result = _tmp0_ != NULL;
+ return result;
+}
+
+
+static gint scanner_get_device_weight (const gchar* device) {
+ gint result = 0;
+ gboolean _tmp0_;
+ gboolean _tmp1_;
+ g_return_val_if_fail (device != NULL, 0);
+ _tmp0_ = g_str_has_prefix (device, "vfl:");
+ if (_tmp0_) {
+ result = 2;
+ return result;
+ }
+ _tmp1_ = string_contains (device, "usb");
+ if (_tmp1_) {
+ result = 0;
+ return result;
+ }
+ result = 1;
+ return result;
+}
+
+
+static gint scanner_compare_devices (ScanDevice* device1, ScanDevice* device2) {
+ gint result = 0;
+ gint _tmp0_;
+ gint weight1;
+ gint _tmp1_;
+ gint weight2;
+ gint _tmp2_;
+ g_return_val_if_fail (device1 != NULL, 0);
+ g_return_val_if_fail (device2 != NULL, 0);
+ _tmp0_ = scanner_get_device_weight (device1->name);
+ weight1 = _tmp0_;
+ _tmp1_ = scanner_get_device_weight (device2->name);
+ weight2 = _tmp1_;
+ if (weight1 != weight2) {
+ result = weight1 - weight2;
+ return result;
+ }
+ _tmp2_ = g_strcmp0 (device1->label, device2->label);
+ result = _tmp2_;
+ return result;
+}
+
+
+static gchar* sane_status_to_string (SANE_Status status) {
+ gchar* result = NULL;
+ switch (status) {
+ case SANE_STATUS_GOOD:
+ {
+ gchar* _tmp0_;
+ _tmp0_ = g_strdup ("SANE_STATUS_GOOD");
+ result = _tmp0_;
+ return result;
+ }
+ case SANE_STATUS_UNSUPPORTED:
+ {
+ gchar* _tmp1_;
+ _tmp1_ = g_strdup ("SANE_STATUS_UNSUPPORTED");
+ result = _tmp1_;
+ return result;
+ }
+ case SANE_STATUS_CANCELLED:
+ {
+ gchar* _tmp2_;
+ _tmp2_ = g_strdup ("SANE_STATUS_CANCELLED");
+ result = _tmp2_;
+ return result;
+ }
+ case SANE_STATUS_DEVICE_BUSY:
+ {
+ gchar* _tmp3_;
+ _tmp3_ = g_strdup ("SANE_STATUS_DEVICE_BUSY");
+ result = _tmp3_;
+ return result;
+ }
+ case SANE_STATUS_INVAL:
+ {
+ gchar* _tmp4_;
+ _tmp4_ = g_strdup ("SANE_STATUS_INVAL");
+ result = _tmp4_;
+ return result;
+ }
+ case SANE_STATUS_EOF:
+ {
+ gchar* _tmp5_;
+ _tmp5_ = g_strdup ("SANE_STATUS_EOF");
+ result = _tmp5_;
+ return result;
+ }
+ case SANE_STATUS_JAMMED:
+ {
+ gchar* _tmp6_;
+ _tmp6_ = g_strdup ("SANE_STATUS_JAMMED");
+ result = _tmp6_;
+ return result;
+ }
+ case SANE_STATUS_NO_DOCS:
+ {
+ gchar* _tmp7_;
+ _tmp7_ = g_strdup ("SANE_STATUS_NO_DOCS");
+ result = _tmp7_;
+ return result;
+ }
+ case SANE_STATUS_COVER_OPEN:
+ {
+ gchar* _tmp8_;
+ _tmp8_ = g_strdup ("SANE_STATUS_COVER_OPEN");
+ result = _tmp8_;
+ return result;
+ }
+ case SANE_STATUS_IO_ERROR:
+ {
+ gchar* _tmp9_;
+ _tmp9_ = g_strdup ("SANE_STATUS_IO_ERROR");
+ result = _tmp9_;
+ return result;
+ }
+ case SANE_STATUS_NO_MEM:
+ {
+ gchar* _tmp10_;
+ _tmp10_ = g_strdup ("SANE_STATUS_NO_MEM");
+ result = _tmp10_;
+ return result;
+ }
+ case SANE_STATUS_ACCESS_DENIED:
+ {
+ gchar* _tmp11_;
+ _tmp11_ = g_strdup ("SANE_STATUS_ACCESS_DENIED");
+ result = _tmp11_;
+ return result;
+ }
+ default:
+ {
+ gchar* _tmp12_ = NULL;
+ _tmp12_ = g_strdup_printf ("SANE_STATUS(%d)", (gint) status);
+ result = _tmp12_;
+ return result;
+ }
+ }
+}
+
+
+static gchar* string_replace (const gchar* self, const gchar* old, const gchar* replacement) {
+ gchar* result = NULL;
+ GError * _inner_error_ = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (old != NULL, NULL);
+ g_return_val_if_fail (replacement != NULL, NULL);
+ {
+ gchar* _tmp0_ = NULL;
+ gchar* _tmp1_;
+ GRegex* _tmp2_ = NULL;
+ GRegex* _tmp3_;
+ GRegex* regex;
+ gchar* _tmp4_ = NULL;
+ gchar* _tmp5_;
+ _tmp0_ = g_regex_escape_string (old, -1);
+ _tmp1_ = _tmp0_;
+ _tmp2_ = g_regex_new (_tmp1_, 0, 0, &_inner_error_);
+ _tmp3_ = _tmp2_;
+ _g_free0 (_tmp1_);
+ regex = _tmp3_;
+ if (_inner_error_ != NULL) {
+ if (_inner_error_->domain == G_REGEX_ERROR) {
+ goto __catch8_g_regex_error;
+ }
+ g_critical ("file %s: line %d: unexpected 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;
+ }
+ _tmp4_ = g_regex_replace_literal (regex, self, (gssize) (-1), 0, replacement, 0, &_inner_error_);
+ _tmp5_ = _tmp4_;
+ if (_inner_error_ != NULL) {
+ _g_regex_unref0 (regex);
+ if (_inner_error_->domain == G_REGEX_ERROR) {
+ goto __catch8_g_regex_error;
+ }
+ _g_regex_unref0 (regex);
+ g_critical ("file %s: line %d: unexpected 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;
+ }
+ result = _tmp5_;
+ _g_regex_unref0 (regex);
+ return result;
+ }
+ goto __finally8;
+ __catch8_g_regex_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_assert_not_reached ();
+ _g_error_free0 (e);
+ }
+ __finally8:
+ if (_inner_error_ != NULL) {
+ 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;
+ }
+}
+
+
+static gpointer _scan_device_ref0 (gpointer self) {
+ return self ? scan_device_ref (self) : NULL;
+}
+
+
+static gint _scanner_compare_devices_gcompare_func (gconstpointer a, gconstpointer b) {
+ gint result;
+ result = scanner_compare_devices (a, b);
+ return result;
+}
+
+
+static void scanner_do_redetect (Scanner* self) {
+ SANE_Device** device_list;
+ gint device_list_length1;
+ gint _device_list_size_;
+ SANE_Device** _tmp0_ = NULL;
+ SANE_Status _tmp1_;
+ SANE_Status status;
+ gchar* _tmp2_ = NULL;
+ gchar* _tmp3_;
+ GList* devices;
+ GList* _tmp17_;
+ NotifyUpdateDevices* _tmp18_ = NULL;
+ NotifyUpdateDevices* _tmp19_;
+ g_return_if_fail (self != NULL);
+ device_list = NULL;
+ device_list_length1 = 0;
+ _device_list_size_ = device_list_length1;
+ _tmp1_ = sane_get_devices (&_tmp0_, FALSE);
+ device_list = _tmp0_;
+ device_list_length1 = -1;
+ _device_list_size_ = device_list_length1;
+ status = _tmp1_;
+ _tmp2_ = sane_status_to_string (status);
+ _tmp3_ = _tmp2_;
+ g_debug ("scanner.vala:318: sane_get_devices () -> %s", _tmp3_);
+ _g_free0 (_tmp3_);
+ if (status != SANE_STATUS_GOOD) {
+ const gchar* _tmp4_ = NULL;
+ _tmp4_ = sane_strstatus (status);
+ g_warning ("scanner.vala:321: Unable to get SANE devices: %s", _tmp4_);
+ self->priv->need_redetect = FALSE;
+ self->priv->state = SCAN_STATE_IDLE;
+ return;
+ }
+ devices = NULL;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp5_;
+ _tmp5_ = TRUE;
+ while (TRUE) {
+ ScanDevice* _tmp6_ = NULL;
+ ScanDevice* scan_device;
+ gchar* _tmp7_;
+ gchar* _tmp8_;
+ gchar* vendor;
+ gchar* _tmp10_ = NULL;
+ gchar* _tmp11_ = NULL;
+ gchar* _tmp12_;
+ ScanDevice* _tmp13_;
+ if (!_tmp5_) {
+ i++;
+ }
+ _tmp5_ = FALSE;
+ if (!(device_list[i] != NULL)) {
+ break;
+ }
+ g_debug ("scanner.vala:330: Device: name=\"%s\" vendor=\"%s\" model=\"%s\" type=" \
+"\"%s\"", device_list[i]->name, device_list[i]->vendor, device_list[i]->model, device_list[i]->type);
+ _tmp6_ = scan_device_new ();
+ scan_device = _tmp6_;
+ _tmp7_ = g_strdup (device_list[i]->name);
+ _g_free0 (scan_device->name);
+ scan_device->name = _tmp7_;
+ _tmp8_ = g_strdup (device_list[i]->vendor);
+ vendor = _tmp8_;
+ if (g_strcmp0 (vendor, "Hewlett-Packard") == 0) {
+ gchar* _tmp9_;
+ _tmp9_ = g_strdup ("HP");
+ _g_free0 (vendor);
+ vendor = _tmp9_;
+ }
+ _tmp10_ = g_strdup_printf ("%s %s", vendor, device_list[i]->model);
+ _g_free0 (scan_device->label);
+ scan_device->label = _tmp10_;
+ _tmp11_ = string_replace (scan_device->label, "_", " ");
+ _tmp12_ = _tmp11_;
+ _g_free0 (_tmp12_);
+ _tmp13_ = _scan_device_ref0 (scan_device);
+ devices = g_list_append (devices, _tmp13_);
+ _g_free0 (vendor);
+ _scan_device_unref0 (scan_device);
+ }
+ }
+ }
+ devices = g_list_sort (devices, _scanner_compare_devices_gcompare_func);
+ self->priv->need_redetect = FALSE;
+ self->priv->state = SCAN_STATE_IDLE;
+ if (devices != NULL) {
+ gconstpointer _tmp14_ = NULL;
+ ScanDevice* _tmp15_;
+ ScanDevice* device;
+ gchar* _tmp16_;
+ _tmp14_ = g_list_nth_data (devices, (guint) 0);
+ _tmp15_ = _scan_device_ref0 ((ScanDevice*) _tmp14_);
+ device = _tmp15_;
+ _tmp16_ = g_strdup (device->name);
+ _g_free0 (self->priv->default_device);
+ self->priv->default_device = _tmp16_;
+ _scan_device_unref0 (device);
+ } else {
+ _g_free0 (self->priv->default_device);
+ self->priv->default_device = NULL;
+ }
+ _tmp17_ = devices;
+ devices = NULL;
+ _tmp18_ = notify_update_devices_new (_tmp17_);
+ _tmp19_ = _tmp18_;
+ scanner_notify (self, (Notify*) _tmp19_);
+ _notify_unref0 (_tmp19_);
+ __g_list_free__scan_device_unref0_0 (devices);
+}
+
+
+static gboolean scanner_set_default_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index) {
+ gboolean result = FALSE;
+ SANE_Status _tmp0_;
+ SANE_Status status;
+ gchar* _tmp1_ = NULL;
+ gchar* _tmp2_;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (option != NULL, FALSE);
+ if (((gint) (option->cap & SANE_CAP_AUTOMATIC)) == 0) {
+ result = FALSE;
+ return result;
+ }
+ _tmp0_ = sane_control_option (handle, option_index, SANE_ACTION_SET_AUTO, NULL, NULL);
+ status = _tmp0_;
+ _tmp1_ = sane_status_to_string (status);
+ _tmp2_ = _tmp1_;
+ g_debug ("scanner.vala:372: sane_control_option (%d, SANE_ACTION_SET_AUTO) -> %s", (gint) option_index, _tmp2_);
+ _g_free0 (_tmp2_);
+ if (status != SANE_STATUS_GOOD) {
+ const gchar* _tmp3_ = NULL;
+ _tmp3_ = sane_strstatus (status);
+ g_warning ("scanner.vala:374: Error setting default option %s: %s", option->name, _tmp3_);
+ }
+ result = status == SANE_STATUS_GOOD;
+ return result;
+}
+
+
+static void scanner_set_bool_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gboolean value, gboolean* _result_) {
+ gboolean _result = FALSE;
+ SANE_Bool v;
+ SANE_Status _tmp0_;
+ SANE_Status status;
+ const gchar* _tmp1_ = NULL;
+ const gchar* _tmp2_ = NULL;
+ gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (option != NULL);
+ g_return_if_fail (option->type == SANE_TYPE_BOOL);
+ v = (SANE_Bool) value;
+ _tmp0_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, &v, NULL);
+ status = _tmp0_;
+ _result = (gboolean) v;
+ if (value) {
+ _tmp1_ = "SANE_TRUE";
+ } else {
+ _tmp1_ = "SANE_FALSE";
+ }
+ if (_result) {
+ _tmp2_ = "SANE_TRUE";
+ } else {
+ _tmp2_ = "SANE_FALSE";
+ }
+ _tmp3_ = sane_status_to_string (status);
+ _tmp4_ = _tmp3_;
+ g_debug ("scanner.vala:386: sane_control_option (%d, SANE_ACTION_SET_VALUE, %s) " \
+"-> (%s, %s)", (gint) option_index, _tmp1_, _tmp4_, _tmp2_);
+ _g_free0 (_tmp4_);
+ if (_result_) {
+ *_result_ = _result;
+ }
+}
+
+
+static void scanner_set_int_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gint value, gint* _result_) {
+ gint _result = 0;
+ SANE_Int v;
+ SANE_Status _tmp2_;
+ SANE_Status status;
+ gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (option != NULL);
+ g_return_if_fail (option->type == SANE_TYPE_INT);
+ v = (SANE_Int) value;
+ if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
+ if (((gint) option->constraint.range->quant) != 0) {
+ v = v * option->constraint.range->quant;
+ }
+ if (v < ((SANE_Int) option->constraint.range->min)) {
+ v = (SANE_Int) option->constraint.range->min;
+ }
+ if (v > ((SANE_Int) option->constraint.range->max)) {
+ v = (SANE_Int) option->constraint.range->max;
+ }
+ } else {
+ if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) {
+ gint distance;
+ gint nearest;
+ distance = G_MAXINT;
+ nearest = 0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp0_;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ gint x;
+ gint _tmp1_;
+ gint d;
+ if (!_tmp0_) {
+ i++;
+ }
+ _tmp0_ = FALSE;
+ if (!(i < ((gint) option->constraint.word_list[0]))) {
+ break;
+ }
+ x = (gint) option->constraint.word_list[i + 1];
+ _tmp1_ = abs (x - v);
+ d = _tmp1_;
+ if (d < distance) {
+ distance = d;
+ nearest = x;
+ }
+ }
+ }
+ }
+ v = (SANE_Int) nearest;
+ }
+ }
+ _tmp2_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, &v, NULL);
+ status = _tmp2_;
+ _tmp3_ = sane_status_to_string (status);
+ _tmp4_ = _tmp3_;
+ g_debug ("scanner.vala:422: sane_control_option (%d, SANE_ACTION_SET_VALUE, %d) " \
+"-> (%s, %d)", (gint) option_index, value, _tmp4_, (gint) v);
+ _g_free0 (_tmp4_);
+ _result = (gint) v;
+ if (_result_) {
+ *_result_ = _result;
+ }
+}
+
+
+static void scanner_set_fixed_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gdouble value, gdouble* _result_) {
+ gdouble _result = 0.0;
+ gdouble v;
+ SANE_Fixed v_fixed;
+ SANE_Fixed _tmp6_;
+ SANE_Status _tmp7_;
+ SANE_Status status;
+ gchar* _tmp8_ = NULL;
+ gchar* _tmp9_;
+ gdouble _tmp10_;
+ gdouble _tmp11_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (option != NULL);
+ v = value;
+ g_return_if_fail (option->type == SANE_TYPE_FIXED);
+ if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
+ gdouble _tmp0_;
+ gdouble min;
+ gdouble _tmp1_;
+ gdouble max;
+ _tmp0_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->min);
+ min = _tmp0_;
+ _tmp1_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max);
+ max = _tmp1_;
+ if (v < min) {
+ v = min;
+ }
+ if (v > max) {
+ v = max;
+ }
+ } else {
+ if (option->constraint_type == SANE_CONSTRAINT_WORD_LIST) {
+ gdouble distance;
+ gdouble nearest;
+ distance = DBL_MAX;
+ nearest = 0.0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp2_;
+ _tmp2_ = TRUE;
+ while (TRUE) {
+ gdouble _tmp3_;
+ gdouble x;
+ gdouble _tmp4_;
+ if (!_tmp2_) {
+ i++;
+ }
+ _tmp2_ = FALSE;
+ if (!(i < ((gint) option->constraint.word_list[0]))) {
+ break;
+ }
+ _tmp3_ = SANE_UNFIX ((SANE_Fixed) option->constraint.word_list[i + 1]);
+ x = _tmp3_;
+ _tmp4_ = fabs (x - v);
+ if (_tmp4_ < distance) {
+ gdouble _tmp5_;
+ _tmp5_ = fabs (x - v);
+ distance = _tmp5_;
+ nearest = x;
+ }
+ }
+ }
+ }
+ v = nearest;
+ }
+ }
+ _tmp6_ = SANE_FIX (v);
+ v_fixed = _tmp6_;
+ _tmp7_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, &v_fixed, NULL);
+ status = _tmp7_;
+ _tmp8_ = sane_status_to_string (status);
+ _tmp9_ = _tmp8_;
+ _tmp10_ = SANE_UNFIX (v_fixed);
+ g_debug ("scanner.vala:462: sane_control_option (%d, SANE_ACTION_SET_VALUE, %f) " \
+"-> (%s, %f)", (gint) option_index, value, _tmp9_, _tmp10_);
+ _g_free0 (_tmp9_);
+ _tmp11_ = SANE_UNFIX (v_fixed);
+ _result = _tmp11_;
+ if (_result_) {
+ *_result_ = _result;
+ }
+}
+
+
+static gchar string_get (const gchar* self, glong index) {
+ gchar result = '\0';
+ g_return_val_if_fail (self != NULL, '\0');
+ result = ((gchar*) self)[index];
+ return result;
+}
+
+
+static gboolean scanner_set_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, const gchar* value, gchar** _result_) {
+ gchar* _result = NULL;
+ gboolean result = FALSE;
+ gchar* _tmp0_ = NULL;
+ gchar* s;
+ gint s_length1;
+ gint _s_size_;
+ gint i;
+ SANE_Status _tmp5_;
+ SANE_Status status;
+ gchar* _tmp6_;
+ gchar* _tmp7_ = NULL;
+ gchar* _tmp8_;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (option != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE);
+ _tmp0_ = g_new0 (gchar, option->size);
+ s = _tmp0_;
+ s_length1 = option->size;
+ _s_size_ = s_length1;
+ i = 0;
+ {
+ gboolean _tmp1_;
+ _tmp1_ = TRUE;
+ while (TRUE) {
+ gboolean _tmp2_ = FALSE;
+ gchar _tmp4_;
+ if (!_tmp1_) {
+ i++;
+ }
+ _tmp1_ = FALSE;
+ if (i < (option->size - 1)) {
+ gchar _tmp3_;
+ _tmp3_ = string_get (value, (glong) i);
+ _tmp2_ = _tmp3_ != '\0';
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (!_tmp2_) {
+ break;
+ }
+ _tmp4_ = string_get (value, (glong) i);
+ s[i] = _tmp4_;
+ }
+ }
+ s[i] = '\0';
+ _tmp5_ = sane_control_option (handle, option_index, SANE_ACTION_SET_VALUE, s, NULL);
+ status = _tmp5_;
+ _tmp6_ = g_strdup ((const gchar*) s);
+ _g_free0 (_result);
+ _result = _tmp6_;
+ _tmp7_ = sane_status_to_string (status);
+ _tmp8_ = _tmp7_;
+ g_debug ("scanner.vala:478: sane_control_option (%d, SANE_ACTION_SET_VALUE, \"%s" \
+"\") -> (%s, \"%s\")", (gint) option_index, value, _tmp8_, _result);
+ _g_free0 (_tmp8_);
+ result = status == SANE_STATUS_GOOD;
+ s = (g_free (s), NULL);
+ if (_result_) {
+ *_result_ = _result;
+ } else {
+ _g_free0 (_result);
+ }
+ return result;
+}
+
+
+static gboolean scanner_set_constrained_string_option (Scanner* self, SANE_Handle handle, const SANE_Option_Descriptor* option, SANE_Int option_index, gchar** values, int values_length1, gchar** _result_) {
+ gchar* _result = NULL;
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (option != NULL, FALSE);
+ g_return_val_if_fail (option->type == SANE_TYPE_STRING, FALSE);
+ g_return_val_if_fail (option->constraint_type == SANE_CONSTRAINT_STRING_LIST, FALSE);
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp0_;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ gint j;
+ if (!_tmp0_) {
+ i++;
+ }
+ _tmp0_ = FALSE;
+ if (!(values[i] != NULL)) {
+ break;
+ }
+ j = 0;
+ {
+ gboolean _tmp1_;
+ _tmp1_ = TRUE;
+ while (TRUE) {
+ if (!_tmp1_) {
+ j++;
+ }
+ _tmp1_ = FALSE;
+ if (!(option->constraint.string_list[j] != NULL)) {
+ break;
+ }
+ if (g_strcmp0 (values[i], option->constraint.string_list[j]) == 0) {
+ break;
+ }
+ }
+ }
+ if (option->constraint.string_list[j] != NULL) {
+ gchar* _tmp2_ = NULL;
+ gboolean _tmp3_;
+ _tmp3_ = scanner_set_string_option (self, handle, option, option_index, values[i], &_tmp2_);
+ _g_free0 (_result);
+ _result = _tmp2_;
+ result = _tmp3_;
+ if (_result_) {
+ *_result_ = _result;
+ } else {
+ _g_free0 (_result);
+ }
+ return result;
+ }
+ }
+ }
+ }
+ result = FALSE;
+ if (_result_) {
+ *_result_ = _result;
+ } else {
+ _g_free0 (_result);
+ }
+ return result;
+}
+
+
+static void scanner_log_option (Scanner* self, SANE_Int index, const SANE_Option_Descriptor* option) {
+ gchar* _tmp0_ = NULL;
+ gchar* s;
+ gchar* _tmp16_ = NULL;
+ gchar* _tmp17_;
+ gchar* _tmp18_;
+ SANE_Int cap;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (option != NULL);
+ _tmp0_ = g_strdup_printf ("Option %d:", (gint) index);
+ s = _tmp0_;
+ if (g_strcmp0 (option->name, "") != 0) {
+ gchar* _tmp1_ = NULL;
+ gchar* _tmp2_;
+ gchar* _tmp3_;
+ _tmp1_ = g_strdup_printf (" name='%s'", option->name);
+ _tmp2_ = _tmp1_;
+ _tmp3_ = g_strconcat (s, _tmp2_, NULL);
+ _g_free0 (s);
+ s = _tmp3_;
+ _g_free0 (_tmp2_);
+ }
+ if (g_strcmp0 (option->title, "") != 0) {
+ gchar* _tmp4_ = NULL;
+ gchar* _tmp5_;
+ gchar* _tmp6_;
+ _tmp4_ = g_strdup_printf (" title='%s'", option->title);
+ _tmp5_ = _tmp4_;
+ _tmp6_ = g_strconcat (s, _tmp5_, NULL);
+ _g_free0 (s);
+ s = _tmp6_;
+ _g_free0 (_tmp5_);
+ }
+ switch (option->type) {
+ case SANE_TYPE_BOOL:
+ {
+ gchar* _tmp7_;
+ _tmp7_ = g_strconcat (s, " type=bool", NULL);
+ _g_free0 (s);
+ s = _tmp7_;
+ break;
+ }
+ case SANE_TYPE_INT:
+ {
+ gchar* _tmp8_;
+ _tmp8_ = g_strconcat (s, " type=int", NULL);
+ _g_free0 (s);
+ s = _tmp8_;
+ break;
+ }
+ case SANE_TYPE_FIXED:
+ {
+ gchar* _tmp9_;
+ _tmp9_ = g_strconcat (s, " type=fixed", NULL);
+ _g_free0 (s);
+ s = _tmp9_;
+ break;
+ }
+ case SANE_TYPE_STRING:
+ {
+ gchar* _tmp10_;
+ _tmp10_ = g_strconcat (s, " type=string", NULL);
+ _g_free0 (s);
+ s = _tmp10_;
+ break;
+ }
+ case SANE_TYPE_BUTTON:
+ {
+ gchar* _tmp11_;
+ _tmp11_ = g_strconcat (s, " type=button", NULL);
+ _g_free0 (s);
+ s = _tmp11_;
+ break;
+ }
+ case SANE_TYPE_GROUP:
+ {
+ gchar* _tmp12_;
+ _tmp12_ = g_strconcat (s, " type=group", NULL);
+ _g_free0 (s);
+ s = _tmp12_;
+ break;
+ }
+ default:
+ {
+ gchar* _tmp13_ = NULL;
+ gchar* _tmp14_;
+ gchar* _tmp15_;
+ _tmp13_ = g_strdup_printf (" type=%d", (gint) option->type);
+ _tmp14_ = _tmp13_;
+ _tmp15_ = g_strconcat (s, _tmp14_, NULL);
+ _g_free0 (s);
+ s = _tmp15_;
+ _g_free0 (_tmp14_);
+ break;
+ }
+ }
+ _tmp16_ = g_strdup_printf (" size=%d", (gint) option->size);
+ _tmp17_ = _tmp16_;
+ _tmp18_ = g_strconcat (s, _tmp17_, NULL);
+ _g_free0 (s);
+ s = _tmp18_;
+ _g_free0 (_tmp17_);
+ switch (option->unit) {
+ case SANE_UNIT_NONE:
+ {
+ break;
+ }
+ case SANE_UNIT_PIXEL:
+ {
+ gchar* _tmp19_;
+ _tmp19_ = g_strconcat (s, " unit=pixels", NULL);
+ _g_free0 (s);
+ s = _tmp19_;
+ break;
+ }
+ case SANE_UNIT_BIT:
+ {
+ gchar* _tmp20_;
+ _tmp20_ = g_strconcat (s, " unit=bits", NULL);
+ _g_free0 (s);
+ s = _tmp20_;
+ break;
+ }
+ case SANE_UNIT_MM:
+ {
+ gchar* _tmp21_;
+ _tmp21_ = g_strconcat (s, " unit=mm", NULL);
+ _g_free0 (s);
+ s = _tmp21_;
+ break;
+ }
+ case SANE_UNIT_DPI:
+ {
+ gchar* _tmp22_;
+ _tmp22_ = g_strconcat (s, " unit=dpi", NULL);
+ _g_free0 (s);
+ s = _tmp22_;
+ break;
+ }
+ case SANE_UNIT_PERCENT:
+ {
+ gchar* _tmp23_;
+ _tmp23_ = g_strconcat (s, " unit=percent", NULL);
+ _g_free0 (s);
+ s = _tmp23_;
+ break;
+ }
+ case SANE_UNIT_MICROSECOND:
+ {
+ gchar* _tmp24_;
+ _tmp24_ = g_strconcat (s, " unit=microseconds", NULL);
+ _g_free0 (s);
+ s = _tmp24_;
+ break;
+ }
+ default:
+ {
+ gchar* _tmp25_ = NULL;
+ gchar* _tmp26_;
+ gchar* _tmp27_;
+ _tmp25_ = g_strdup_printf (" unit=%d", (gint) option->unit);
+ _tmp26_ = _tmp25_;
+ _tmp27_ = g_strconcat (s, _tmp26_, NULL);
+ _g_free0 (s);
+ s = _tmp27_;
+ _g_free0 (_tmp26_);
+ break;
+ }
+ }
+ switch (option->constraint_type) {
+ case SANE_CONSTRAINT_RANGE:
+ {
+ if (option->type == SANE_TYPE_FIXED) {
+ gdouble _tmp28_;
+ gdouble _tmp29_;
+ gchar* _tmp30_ = NULL;
+ gchar* _tmp31_;
+ gchar* _tmp32_;
+ _tmp28_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->min);
+ _tmp29_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max);
+ _tmp30_ = g_strdup_printf (" min=%f, max=%f, quant=%d", _tmp28_, _tmp29_, (gint) option->constraint.range->quant);
+ _tmp31_ = _tmp30_;
+ _tmp32_ = g_strconcat (s, _tmp31_, NULL);
+ _g_free0 (s);
+ s = _tmp32_;
+ _g_free0 (_tmp31_);
+ } else {
+ gchar* _tmp33_ = NULL;
+ gchar* _tmp34_;
+ gchar* _tmp35_;
+ _tmp33_ = g_strdup_printf (" min=%d, max=%d, quant=%d", (gint) option->constraint.range->min, (gint) option->constraint.range->max, (gint) option->constraint.range->quant);
+ _tmp34_ = _tmp33_;
+ _tmp35_ = g_strconcat (s, _tmp34_, NULL);
+ _g_free0 (s);
+ s = _tmp35_;
+ _g_free0 (_tmp34_);
+ }
+ break;
+ }
+ case SANE_CONSTRAINT_WORD_LIST:
+ {
+ gchar* _tmp36_;
+ gchar* _tmp46_;
+ _tmp36_ = g_strconcat (s, " values=[", NULL);
+ _g_free0 (s);
+ s = _tmp36_;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp37_;
+ _tmp37_ = TRUE;
+ while (TRUE) {
+ if (!_tmp37_) {
+ i++;
+ }
+ _tmp37_ = FALSE;
+ if (!(i < ((gint) option->constraint.word_list[0]))) {
+ break;
+ }
+ if (i != 0) {
+ gchar* _tmp38_;
+ _tmp38_ = g_strconcat (s, ", ", NULL);
+ _g_free0 (s);
+ s = _tmp38_;
+ }
+ if (option->type == SANE_TYPE_INT) {
+ gchar* _tmp39_ = NULL;
+ gchar* _tmp40_;
+ gchar* _tmp41_;
+ _tmp39_ = g_strdup_printf ("%d", (gint) option->constraint.word_list[i + 1]);
+ _tmp40_ = _tmp39_;
+ _tmp41_ = g_strconcat (s, _tmp40_, NULL);
+ _g_free0 (s);
+ s = _tmp41_;
+ _g_free0 (_tmp40_);
+ } else {
+ gdouble _tmp42_;
+ gchar* _tmp43_ = NULL;
+ gchar* _tmp44_;
+ gchar* _tmp45_;
+ _tmp42_ = SANE_UNFIX ((SANE_Fixed) option->constraint.word_list[i + 1]);
+ _tmp43_ = g_strdup_printf ("%f", _tmp42_);
+ _tmp44_ = _tmp43_;
+ _tmp45_ = g_strconcat (s, _tmp44_, NULL);
+ _g_free0 (s);
+ s = _tmp45_;
+ _g_free0 (_tmp44_);
+ }
+ }
+ }
+ }
+ _tmp46_ = g_strconcat (s, "]", NULL);
+ _g_free0 (s);
+ s = _tmp46_;
+ break;
+ }
+ case SANE_CONSTRAINT_STRING_LIST:
+ {
+ gchar* _tmp47_;
+ gchar* _tmp53_;
+ _tmp47_ = g_strconcat (s, " values=[", NULL);
+ _g_free0 (s);
+ s = _tmp47_;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp48_;
+ _tmp48_ = TRUE;
+ while (TRUE) {
+ gchar* _tmp50_ = NULL;
+ gchar* _tmp51_;
+ gchar* _tmp52_;
+ if (!_tmp48_) {
+ i++;
+ }
+ _tmp48_ = FALSE;
+ if (!(option->constraint.string_list[i] != NULL)) {
+ break;
+ }
+ if (i != 0) {
+ gchar* _tmp49_;
+ _tmp49_ = g_strconcat (s, ", ", NULL);
+ _g_free0 (s);
+ s = _tmp49_;
+ }
+ _tmp50_ = g_strdup_printf ("\"%s\"", option->constraint.string_list[i]);
+ _tmp51_ = _tmp50_;
+ _tmp52_ = g_strconcat (s, _tmp51_, NULL);
+ _g_free0 (s);
+ s = _tmp52_;
+ _g_free0 (_tmp51_);
+ }
+ }
+ }
+ _tmp53_ = g_strconcat (s, "]", NULL);
+ _g_free0 (s);
+ s = _tmp53_;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ cap = option->cap;
+ if (((gint) cap) != 0) {
+ gchar* _tmp54_;
+ _tmp54_ = g_strconcat (s, " cap=", NULL);
+ _g_free0 (s);
+ s = _tmp54_;
+ if (((gint) (cap & SANE_CAP_SOFT_SELECT)) != 0) {
+ gchar* _tmp56_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp55_;
+ _tmp55_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp55_;
+ }
+ _tmp56_ = g_strconcat (s, "soft-select", NULL);
+ _g_free0 (s);
+ s = _tmp56_;
+ cap = cap & (~SANE_CAP_SOFT_SELECT);
+ }
+ if (((gint) (cap & SANE_CAP_HARD_SELECT)) != 0) {
+ gchar* _tmp58_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp57_;
+ _tmp57_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp57_;
+ }
+ _tmp58_ = g_strconcat (s, "hard-select", NULL);
+ _g_free0 (s);
+ s = _tmp58_;
+ cap = cap & (~SANE_CAP_HARD_SELECT);
+ }
+ if (((gint) (cap & SANE_CAP_SOFT_DETECT)) != 0) {
+ gchar* _tmp60_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp59_;
+ _tmp59_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp59_;
+ }
+ _tmp60_ = g_strconcat (s, "soft-detect", NULL);
+ _g_free0 (s);
+ s = _tmp60_;
+ cap = cap & (~SANE_CAP_SOFT_DETECT);
+ }
+ if (((gint) (cap & SANE_CAP_EMULATED)) != 0) {
+ gchar* _tmp62_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp61_;
+ _tmp61_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp61_;
+ }
+ _tmp62_ = g_strconcat (s, "emulated", NULL);
+ _g_free0 (s);
+ s = _tmp62_;
+ cap = cap & (~SANE_CAP_EMULATED);
+ }
+ if (((gint) (cap & SANE_CAP_AUTOMATIC)) != 0) {
+ gchar* _tmp64_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp63_;
+ _tmp63_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp63_;
+ }
+ _tmp64_ = g_strconcat (s, "automatic", NULL);
+ _g_free0 (s);
+ s = _tmp64_;
+ cap = cap & (~SANE_CAP_AUTOMATIC);
+ }
+ if (((gint) (cap & SANE_CAP_INACTIVE)) != 0) {
+ gchar* _tmp66_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp65_;
+ _tmp65_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp65_;
+ }
+ _tmp66_ = g_strconcat (s, "inactive", NULL);
+ _g_free0 (s);
+ s = _tmp66_;
+ cap = cap & (~SANE_CAP_INACTIVE);
+ }
+ if (((gint) (cap & SANE_CAP_ADVANCED)) != 0) {
+ gchar* _tmp68_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp67_;
+ _tmp67_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp67_;
+ }
+ _tmp68_ = g_strconcat (s, "advanced", NULL);
+ _g_free0 (s);
+ s = _tmp68_;
+ cap = cap & (~SANE_CAP_ADVANCED);
+ }
+ if (((gint) cap) != 0) {
+ gchar* _tmp70_ = NULL;
+ gchar* _tmp71_;
+ gchar* _tmp72_;
+ if (g_strcmp0 (s, "") != 0) {
+ gchar* _tmp69_;
+ _tmp69_ = g_strconcat (s, ",", NULL);
+ _g_free0 (s);
+ s = _tmp69_;
+ }
+ _tmp70_ = g_strdup_printf ("%x", (guint) cap);
+ _tmp71_ = _tmp70_;
+ _tmp72_ = g_strconcat (s, _tmp71_, NULL);
+ _g_free0 (s);
+ s = _tmp72_;
+ _g_free0 (_tmp71_);
+ }
+ }
+ g_debug ("scanner.vala:665: %s", s);
+ if (option->desc != NULL) {
+ g_debug ("scanner.vala:668: Description: %s", option->desc);
+ }
+ _g_free0 (s);
+}
+
+
+static void scanner_authorization_cb (const gchar* resource, gchar* username, int username_length1, gchar* password, int password_length1) {
+ NotifyRequestAuthorization* _tmp0_ = NULL;
+ NotifyRequestAuthorization* _tmp1_;
+ gpointer _tmp2_ = NULL;
+ Credentials* credentials;
+ g_return_if_fail (resource != NULL);
+ _tmp0_ = notify_request_authorization_new (resource);
+ _tmp1_ = _tmp0_;
+ scanner_notify (scanner_scanner_object, (Notify*) _tmp1_);
+ _notify_unref0 (_tmp1_);
+ _tmp2_ = g_async_queue_pop (scanner_scanner_object->priv->authorize_queue);
+ credentials = (Credentials*) _tmp2_;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp3_;
+ _tmp3_ = TRUE;
+ while (TRUE) {
+ gboolean _tmp4_ = FALSE;
+ gchar _tmp5_;
+ gchar _tmp6_;
+ if (!_tmp3_) {
+ i++;
+ }
+ _tmp3_ = FALSE;
+ _tmp5_ = string_get (credentials->username, (glong) i);
+ if (_tmp5_ != '\0') {
+ _tmp4_ = i < SANE_MAX_USERNAME_LEN;
+ } else {
+ _tmp4_ = FALSE;
+ }
+ if (!_tmp4_) {
+ break;
+ }
+ _tmp6_ = string_get (credentials->username, (glong) i);
+ username[i] = _tmp6_;
+ }
+ }
+ }
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp7_;
+ _tmp7_ = TRUE;
+ while (TRUE) {
+ gboolean _tmp8_ = FALSE;
+ gchar _tmp9_;
+ gchar _tmp10_;
+ if (!_tmp7_) {
+ i++;
+ }
+ _tmp7_ = FALSE;
+ _tmp9_ = string_get (credentials->password, (glong) i);
+ if (_tmp9_ != '\0') {
+ _tmp8_ = i < SANE_MAX_USERNAME_LEN;
+ } else {
+ _tmp8_ = FALSE;
+ }
+ if (!_tmp8_) {
+ break;
+ }
+ _tmp10_ = string_get (credentials->password, (glong) i);
+ password[i] = _tmp10_;
+ }
+ }
+ }
+ _credentials_unref0 (credentials);
+}
+
+
+static gpointer _credentials_ref0 (gpointer self) {
+ return self ? credentials_ref (self) : NULL;
+}
+
+
+void scanner_authorize (Scanner* self, const gchar* username, const gchar* password) {
+ Credentials* _tmp0_ = NULL;
+ Credentials* credentials;
+ gchar* _tmp1_;
+ gchar* _tmp2_;
+ Credentials* _tmp3_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (username != NULL);
+ g_return_if_fail (password != NULL);
+ _tmp0_ = credentials_new ();
+ credentials = _tmp0_;
+ _tmp1_ = g_strdup (username);
+ _g_free0 (credentials->username);
+ credentials->username = _tmp1_;
+ _tmp2_ = g_strdup (password);
+ _g_free0 (credentials->password);
+ credentials->password = _tmp2_;
+ _tmp3_ = _credentials_ref0 (credentials);
+ g_async_queue_push (self->priv->authorize_queue, _tmp3_);
+ _credentials_unref0 (credentials);
+}
+
+
+static void scanner_close_device (Scanner* self) {
+ g_return_if_fail (self != NULL);
+ if (self->priv->have_handle) {
+ sane_cancel (self->priv->handle);
+ g_debug ("scanner.vala:695: sane_cancel ()");
+ sane_close (self->priv->handle);
+ g_debug ("scanner.vala:698: sane_close ()");
+ self->priv->have_handle = FALSE;
+ }
+ self->priv->buffer = (g_free (self->priv->buffer), NULL);
+ self->priv->buffer = NULL;
+ self->priv->buffer_length1 = 0;
+ self->priv->_buffer_size_ = self->priv->buffer_length1;
+ __g_list_free__scan_job_unref0_0 (self->priv->job_queue);
+ self->priv->job_queue = NULL;
+ scanner_set_scanning (self, FALSE);
+}
+
+
+static void scanner_fail_scan (Scanner* self, gint error_code, const gchar* error_string) {
+ NotifyScanFailed* _tmp0_ = NULL;
+ NotifyScanFailed* _tmp1_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (error_string != NULL);
+ scanner_close_device (self);
+ self->priv->state = SCAN_STATE_IDLE;
+ _tmp0_ = notify_scan_failed_new (error_code, error_string);
+ _tmp1_ = _tmp0_;
+ scanner_notify (self, (Notify*) _tmp1_);
+ _notify_unref0 (_tmp1_);
+}
+
+
+static gpointer _request_ref0 (gpointer self) {
+ return self ? request_ref (self) : NULL;
+}
+
+
+static gpointer _scan_job_ref0 (gpointer self) {
+ return self ? scan_job_ref (self) : NULL;
+}
+
+
+static gboolean scanner_handle_requests (Scanner* self) {
+ gboolean result = FALSE;
+ gboolean _tmp0_ = FALSE;
+ gint request_count;
+ g_return_val_if_fail (self != NULL, FALSE);
+ if (self->priv->state == SCAN_STATE_IDLE) {
+ _tmp0_ = self->priv->need_redetect;
+ } else {
+ _tmp0_ = FALSE;
+ }
+ if (_tmp0_) {
+ self->priv->state = SCAN_STATE_REDETECT;
+ }
+ request_count = 0;
+ while (TRUE) {
+ Request* request = NULL;
+ gboolean _tmp1_ = FALSE;
+ gboolean _tmp2_ = FALSE;
+ if (self->priv->state == SCAN_STATE_IDLE) {
+ _tmp2_ = request_count == 0;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ if (_tmp2_) {
+ _tmp1_ = TRUE;
+ } else {
+ gint _tmp3_;
+ _tmp3_ = g_async_queue_length (self->priv->request_queue);
+ _tmp1_ = _tmp3_ > 0;
+ }
+ if (_tmp1_) {
+ gpointer _tmp4_ = NULL;
+ _tmp4_ = g_async_queue_pop (self->priv->request_queue);
+ _request_unref0 (request);
+ request = (Request*) _tmp4_;
+ } else {
+ result = TRUE;
+ _request_unref0 (request);
+ return result;
+ }
+ g_debug ("scanner.vala:732: Processing request");
+ request_count++;
+ if (IS_REQUEST_START_SCAN (request)) {
+ RequestStartScan* _tmp5_;
+ RequestStartScan* r;
+ ScanJob* _tmp6_;
+ _tmp5_ = _request_ref0 (REQUEST_START_SCAN (request));
+ r = _tmp5_;
+ _tmp6_ = _scan_job_ref0 (r->job);
+ self->priv->job_queue = g_list_append (self->priv->job_queue, _tmp6_);
+ _request_unref0 (r);
+ } else {
+ if (IS_REQUEST_CANCEL (request)) {
+ scanner_fail_scan (self, (gint) SANE_STATUS_CANCELLED, "Scan cancelled - do not report this error");
+ } else {
+ if (IS_REQUEST_QUIT (request)) {
+ scanner_close_device (self);
+ result = FALSE;
+ _request_unref0 (request);
+ return result;
+ }
+ }
+ }
+ _request_unref0 (request);
+ }
+}
+
+
+static void scanner_do_open (Scanner* self) {
+ ScanJob* _tmp0_;
+ ScanJob* job;
+ gboolean _tmp1_ = FALSE;
+ SANE_Handle _tmp4_;
+ SANE_Status _tmp5_;
+ SANE_Status status;
+ gchar* _tmp6_ = NULL;
+ gchar* _tmp7_;
+ gchar* _tmp10_;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data));
+ job = _tmp0_;
+ self->priv->line_count = 0;
+ self->priv->pass_number = 0;
+ self->priv->page_number = 0;
+ self->priv->notified_page = -1;
+ self->priv->option_index = (SANE_Int) 0;
+ self->priv->br_x_option_index = (SANE_Int) 0;
+ self->priv->br_y_option_index = (SANE_Int) 0;
+ if (job->device == NULL) {
+ _tmp1_ = self->priv->default_device != NULL;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ gchar* _tmp2_;
+ _tmp2_ = g_strdup (self->priv->default_device);
+ _g_free0 (job->device);
+ job->device = _tmp2_;
+ }
+ if (job->device == NULL) {
+ const gchar* _tmp3_ = NULL;
+ g_warning ("scanner.vala:769: No scan device available");
+ _tmp3_ = _ ("No scanners available. Please connect a scanner.");
+ scanner_fail_scan (self, 0, _tmp3_);
+ _scan_job_unref0 (job);
+ return;
+ }
+ if (self->priv->have_handle) {
+ if (g_strcmp0 (self->priv->current_device, job->device) == 0) {
+ self->priv->state = SCAN_STATE_GET_OPTION;
+ _scan_job_unref0 (job);
+ return;
+ }
+ sane_close (self->priv->handle);
+ g_debug ("scanner.vala:786: sane_close ()");
+ self->priv->have_handle = FALSE;
+ }
+ _g_free0 (self->priv->current_device);
+ self->priv->current_device = NULL;
+ self->priv->have_handle = FALSE;
+ _tmp5_ = sane_open (job->device, &_tmp4_);
+ self->priv->handle = _tmp4_;
+ status = _tmp5_;
+ _tmp6_ = sane_status_to_string (status);
+ _tmp7_ = _tmp6_;
+ g_debug ("scanner.vala:794: sane_open (\"%s\") -> %s", job->device, _tmp7_);
+ _g_free0 (_tmp7_);
+ if (status != SANE_STATUS_GOOD) {
+ const gchar* _tmp8_ = NULL;
+ const gchar* _tmp9_ = NULL;
+ _tmp8_ = sane_strstatus (status);
+ g_warning ("scanner.vala:798: Unable to get open device: %s", _tmp8_);
+ _tmp9_ = _ ("Unable to connect to scanner");
+ scanner_fail_scan (self, (gint) status, _tmp9_);
+ _scan_job_unref0 (job);
+ return;
+ }
+ self->priv->have_handle = TRUE;
+ _tmp10_ = g_strdup (job->device);
+ _g_free0 (self->priv->current_device);
+ self->priv->current_device = _tmp10_;
+ self->priv->state = SCAN_STATE_GET_OPTION;
+ _scan_job_unref0 (job);
+}
+
+
+static void scanner_do_get_option (Scanner* self) {
+ ScanJob* _tmp0_;
+ ScanJob* job;
+ const SANE_Option_Descriptor* _tmp1_ = NULL;
+ const SANE_Option_Descriptor* option;
+ SANE_Int index;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data));
+ job = _tmp0_;
+ _tmp1_ = sane_get_option_descriptor (self->priv->handle, self->priv->option_index);
+ option = _tmp1_;
+ g_debug ("scanner.vala:815: sane_get_option_descriptor (%d)", (gint) self->priv->option_index);
+ index = self->priv->option_index;
+ self->priv->option_index++;
+ if (option == NULL) {
+ if (((gint) self->priv->br_x_option_index) != 0) {
+ const SANE_Option_Descriptor* _tmp2_ = NULL;
+ _tmp2_ = sane_get_option_descriptor (self->priv->handle, self->priv->br_x_option_index);
+ option = _tmp2_;
+ g_debug ("scanner.vala:825: sane_get_option_descriptor (%d)", (gint) self->priv->br_x_option_index);
+ if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
+ if (option->type == SANE_TYPE_FIXED) {
+ gdouble _tmp3_;
+ _tmp3_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max);
+ scanner_set_fixed_option (self, self->priv->handle, option, self->priv->br_x_option_index, _tmp3_, NULL);
+ } else {
+ scanner_set_int_option (self, self->priv->handle, option, self->priv->br_x_option_index, (gint) option->constraint.range->max, NULL);
+ }
+ }
+ }
+ if (((gint) self->priv->br_y_option_index) != 0) {
+ const SANE_Option_Descriptor* _tmp4_ = NULL;
+ _tmp4_ = sane_get_option_descriptor (self->priv->handle, self->priv->br_y_option_index);
+ option = _tmp4_;
+ g_debug ("scanner.vala:837: sane_get_option_descriptor (%d)", (gint) self->priv->br_y_option_index);
+ if (option->constraint_type == SANE_CONSTRAINT_RANGE) {
+ if (option->type == SANE_TYPE_FIXED) {
+ gdouble _tmp5_;
+ _tmp5_ = SANE_UNFIX ((SANE_Fixed) option->constraint.range->max);
+ scanner_set_fixed_option (self, self->priv->handle, option, self->priv->br_y_option_index, _tmp5_, NULL);
+ } else {
+ scanner_set_int_option (self, self->priv->handle, option, self->priv->br_y_option_index, (gint) option->constraint.range->max, NULL);
+ }
+ }
+ }
+ self->priv->state = SCAN_STATE_START;
+ _scan_job_unref0 (job);
+ return;
+ }
+ scanner_log_option (self, index, option);
+ if (option->type == SANE_TYPE_GROUP) {
+ _scan_job_unref0 (job);
+ return;
+ }
+ if (((gint) (option->cap & SANE_CAP_INACTIVE)) != 0) {
+ _scan_job_unref0 (job);
+ return;
+ }
+ if (option->name == NULL) {
+ _scan_job_unref0 (job);
+ return;
+ }
+ if (g_strcmp0 (option->name, SANE_NAME_SCAN_RESOLUTION) == 0) {
+ if (option->type == SANE_TYPE_FIXED) {
+ gdouble _tmp6_;
+ scanner_set_fixed_option (self, self->priv->handle, option, index, job->dpi, &_tmp6_);
+ job->dpi = _tmp6_;
+ } else {
+ gint dpi = 0;
+ gint _tmp7_;
+ scanner_set_int_option (self, self->priv->handle, option, index, (gint) job->dpi, &_tmp7_);
+ dpi = _tmp7_;
+ job->dpi = (gdouble) dpi;
+ }
+ } else {
+ if (g_strcmp0 (option->name, SANE_NAME_SCAN_SOURCE) == 0) {
+ gchar* _tmp8_;
+ const gchar* _tmp9_ = NULL;
+ gchar* _tmp10_;
+ gchar* _tmp11_;
+ const gchar* _tmp12_ = NULL;
+ gchar* _tmp13_;
+ gchar* _tmp14_;
+ gchar* _tmp15_;
+ const gchar* _tmp16_ = NULL;
+ gchar* _tmp17_;
+ gchar** _tmp18_ = NULL;
+ gchar** flatbed_sources;
+ gint flatbed_sources_length1;
+ gint _flatbed_sources_size_;
+ gchar* _tmp19_;
+ const gchar* _tmp20_ = NULL;
+ gchar* _tmp21_;
+ gchar* _tmp22_;
+ gchar* _tmp23_;
+ gchar* _tmp24_;
+ gchar** _tmp25_ = NULL;
+ gchar** adf_sources;
+ gint adf_sources_length1;
+ gint _adf_sources_size_;
+ gchar* _tmp26_;
+ const gchar* _tmp27_ = NULL;
+ gchar* _tmp28_;
+ gchar** _tmp29_ = NULL;
+ gchar** adf_front_sources;
+ gint adf_front_sources_length1;
+ gint _adf_front_sources_size_;
+ gchar* _tmp30_;
+ const gchar* _tmp31_ = NULL;
+ gchar* _tmp32_;
+ gchar** _tmp33_ = NULL;
+ gchar** adf_back_sources;
+ gint adf_back_sources_length1;
+ gint _adf_back_sources_size_;
+ gchar* _tmp34_;
+ const gchar* _tmp35_ = NULL;
+ gchar* _tmp36_;
+ gchar** _tmp37_ = NULL;
+ gchar** adf_duplex_sources;
+ gint adf_duplex_sources_length1;
+ gint _adf_duplex_sources_size_;
+ _tmp8_ = g_strdup ("Auto");
+ _tmp9_ = SANE_I18N ("Auto");
+ _tmp10_ = g_strdup (_tmp9_);
+ _tmp11_ = g_strdup ("Flatbed");
+ _tmp12_ = SANE_I18N ("Flatbed");
+ _tmp13_ = g_strdup (_tmp12_);
+ _tmp14_ = g_strdup ("FlatBed");
+ _tmp15_ = g_strdup ("Normal");
+ _tmp16_ = SANE_I18N ("Normal");
+ _tmp17_ = g_strdup (_tmp16_);
+ _tmp18_ = g_new0 (gchar*, 7 + 1);
+ _tmp18_[0] = _tmp8_;
+ _tmp18_[1] = _tmp10_;
+ _tmp18_[2] = _tmp11_;
+ _tmp18_[3] = _tmp13_;
+ _tmp18_[4] = _tmp14_;
+ _tmp18_[5] = _tmp15_;
+ _tmp18_[6] = _tmp17_;
+ flatbed_sources = _tmp18_;
+ flatbed_sources_length1 = 7;
+ _flatbed_sources_size_ = flatbed_sources_length1;
+ _tmp19_ = g_strdup ("Automatic Document Feeder");
+ _tmp20_ = SANE_I18N ("Automatic Document Feeder");
+ _tmp21_ = g_strdup (_tmp20_);
+ _tmp22_ = g_strdup ("ADF");
+ _tmp23_ = g_strdup ("Automatic Document Feeder(left aligned)");
+ _tmp24_ = g_strdup ("Automatic Document Feeder(centrally aligned)");
+ _tmp25_ = g_new0 (gchar*, 5 + 1);
+ _tmp25_[0] = _tmp19_;
+ _tmp25_[1] = _tmp21_;
+ _tmp25_[2] = _tmp22_;
+ _tmp25_[3] = _tmp23_;
+ _tmp25_[4] = _tmp24_;
+ adf_sources = _tmp25_;
+ adf_sources_length1 = 5;
+ _adf_sources_size_ = adf_sources_length1;
+ _tmp26_ = g_strdup ("ADF Front");
+ _tmp27_ = SANE_I18N ("ADF Front");
+ _tmp28_ = g_strdup (_tmp27_);
+ _tmp29_ = g_new0 (gchar*, 2 + 1);
+ _tmp29_[0] = _tmp26_;
+ _tmp29_[1] = _tmp28_;
+ adf_front_sources = _tmp29_;
+ adf_front_sources_length1 = 2;
+ _adf_front_sources_size_ = adf_front_sources_length1;
+ _tmp30_ = g_strdup ("ADF Back");
+ _tmp31_ = SANE_I18N ("ADF Back");
+ _tmp32_ = g_strdup (_tmp31_);
+ _tmp33_ = g_new0 (gchar*, 2 + 1);
+ _tmp33_[0] = _tmp30_;
+ _tmp33_[1] = _tmp32_;
+ adf_back_sources = _tmp33_;
+ adf_back_sources_length1 = 2;
+ _adf_back_sources_size_ = adf_back_sources_length1;
+ _tmp34_ = g_strdup ("ADF Duplex");
+ _tmp35_ = SANE_I18N ("ADF Duplex");
+ _tmp36_ = g_strdup (_tmp35_);
+ _tmp37_ = g_new0 (gchar*, 2 + 1);
+ _tmp37_[0] = _tmp34_;
+ _tmp37_[1] = _tmp36_;
+ adf_duplex_sources = _tmp37_;
+ adf_duplex_sources_length1 = 2;
+ _adf_duplex_sources_size_ = adf_duplex_sources_length1;
+ switch (job->type) {
+ case SCAN_TYPE_SINGLE:
+ {
+ gboolean _tmp38_;
+ _tmp38_ = scanner_set_default_option (self, self->priv->handle, option, index);
+ if (!_tmp38_) {
+ gboolean _tmp39_;
+ _tmp39_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, flatbed_sources, flatbed_sources_length1, NULL);
+ if (!_tmp39_) {
+ g_warning ("scanner.vala:921: Unable to set single page source, please file a bug");
+ }
+ }
+ break;
+ }
+ case SCAN_TYPE_ADF_FRONT:
+ {
+ gboolean _tmp40_;
+ _tmp40_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_front_sources, adf_front_sources_length1, NULL);
+ if (!_tmp40_) {
+ gboolean _tmp41_;
+ _tmp41_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_sources, adf_sources_length1, NULL);
+ if (!(!_tmp41_)) {
+ g_warning ("scanner.vala:926: Unable to set front ADF source, please file a bug");
+ }
+ }
+ break;
+ }
+ case SCAN_TYPE_ADF_BACK:
+ {
+ gboolean _tmp42_;
+ _tmp42_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_back_sources, adf_back_sources_length1, NULL);
+ if (!_tmp42_) {
+ gboolean _tmp43_;
+ _tmp43_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_sources, adf_sources_length1, NULL);
+ if (!_tmp43_) {
+ g_warning ("scanner.vala:931: Unable to set back ADF source, please file a bug");
+ }
+ }
+ break;
+ }
+ case SCAN_TYPE_ADF_BOTH:
+ {
+ gboolean _tmp44_;
+ _tmp44_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_duplex_sources, adf_duplex_sources_length1, NULL);
+ if (!_tmp44_) {
+ gboolean _tmp45_;
+ _tmp45_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, adf_sources, adf_sources_length1, NULL);
+ if (!_tmp45_) {
+ g_warning ("scanner.vala:936: Unable to set duplex ADF source, please file a bug");
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ adf_duplex_sources = (_vala_array_free (adf_duplex_sources, adf_duplex_sources_length1, (GDestroyNotify) g_free), NULL);
+ adf_back_sources = (_vala_array_free (adf_back_sources, adf_back_sources_length1, (GDestroyNotify) g_free), NULL);
+ adf_front_sources = (_vala_array_free (adf_front_sources, adf_front_sources_length1, (GDestroyNotify) g_free), NULL);
+ adf_sources = (_vala_array_free (adf_sources, adf_sources_length1, (GDestroyNotify) g_free), NULL);
+ flatbed_sources = (_vala_array_free (flatbed_sources, flatbed_sources_length1, (GDestroyNotify) g_free), NULL);
+ } else {
+ if (g_strcmp0 (option->name, "duplex") == 0) {
+ if (option->type == SANE_TYPE_BOOL) {
+ scanner_set_bool_option (self, self->priv->handle, option, index, job->type == SCAN_TYPE_ADF_BOTH, NULL);
+ }
+ } else {
+ if (g_strcmp0 (option->name, "batch-scan") == 0) {
+ if (option->type == SANE_TYPE_BOOL) {
+ scanner_set_bool_option (self, self->priv->handle, option, index, job->type != SCAN_TYPE_SINGLE, NULL);
+ }
+ } else {
+ if (g_strcmp0 (option->name, SANE_NAME_BIT_DEPTH) == 0) {
+ if (job->depth > 0) {
+ scanner_set_int_option (self, self->priv->handle, option, index, job->depth, NULL);
+ }
+ } else {
+ if (g_strcmp0 (option->name, SANE_NAME_SCAN_MODE) == 0) {
+ gchar* _tmp46_;
+ gchar* _tmp47_;
+ gchar* _tmp48_;
+ gchar** _tmp49_ = NULL;
+ gchar** color_scan_modes;
+ gint color_scan_modes_length1;
+ gint _color_scan_modes_size_;
+ gchar* _tmp50_;
+ gchar* _tmp51_;
+ gchar* _tmp52_;
+ const gchar* _tmp53_ = NULL;
+ gchar* _tmp54_;
+ gchar* _tmp55_;
+ gchar** _tmp56_ = NULL;
+ gchar** gray_scan_modes;
+ gint gray_scan_modes_length1;
+ gint _gray_scan_modes_size_;
+ gchar* _tmp57_;
+ gchar* _tmp58_;
+ gchar* _tmp59_;
+ const gchar* _tmp60_ = NULL;
+ gchar* _tmp61_;
+ gchar* _tmp62_;
+ const gchar* _tmp63_ = NULL;
+ gchar* _tmp64_;
+ gchar* _tmp65_;
+ const gchar* _tmp66_ = NULL;
+ gchar* _tmp67_;
+ gchar* _tmp68_;
+ gchar* _tmp69_;
+ gchar* _tmp70_;
+ gchar* _tmp71_;
+ const gchar* _tmp72_ = NULL;
+ gchar* _tmp73_;
+ gchar* _tmp74_;
+ gchar** _tmp75_ = NULL;
+ gchar** lineart_scan_modes;
+ gint lineart_scan_modes_length1;
+ gint _lineart_scan_modes_size_;
+ _tmp46_ = g_strdup (SANE_VALUE_SCAN_MODE_COLOR);
+ _tmp47_ = g_strdup ("Color");
+ _tmp48_ = g_strdup ("24bit Color");
+ _tmp49_ = g_new0 (gchar*, 3 + 1);
+ _tmp49_[0] = _tmp46_;
+ _tmp49_[1] = _tmp47_;
+ _tmp49_[2] = _tmp48_;
+ color_scan_modes = _tmp49_;
+ color_scan_modes_length1 = 3;
+ _color_scan_modes_size_ = color_scan_modes_length1;
+ _tmp50_ = g_strdup (SANE_VALUE_SCAN_MODE_GRAY);
+ _tmp51_ = g_strdup ("Gray");
+ _tmp52_ = g_strdup ("Grayscale");
+ _tmp53_ = SANE_I18N ("Grayscale");
+ _tmp54_ = g_strdup (_tmp53_);
+ _tmp55_ = g_strdup ("True Gray");
+ _tmp56_ = g_new0 (gchar*, 5 + 1);
+ _tmp56_[0] = _tmp50_;
+ _tmp56_[1] = _tmp51_;
+ _tmp56_[2] = _tmp52_;
+ _tmp56_[3] = _tmp54_;
+ _tmp56_[4] = _tmp55_;
+ gray_scan_modes = _tmp56_;
+ gray_scan_modes_length1 = 5;
+ _gray_scan_modes_size_ = gray_scan_modes_length1;
+ _tmp57_ = g_strdup (SANE_VALUE_SCAN_MODE_LINEART);
+ _tmp58_ = g_strdup ("Lineart");
+ _tmp59_ = g_strdup ("LineArt");
+ _tmp60_ = SANE_I18N ("LineArt");
+ _tmp61_ = g_strdup (_tmp60_);
+ _tmp62_ = g_strdup ("Black & White");
+ _tmp63_ = SANE_I18N ("Black & White");
+ _tmp64_ = g_strdup (_tmp63_);
+ _tmp65_ = g_strdup ("Binary");
+ _tmp66_ = SANE_I18N ("Binary");
+ _tmp67_ = g_strdup (_tmp66_);
+ _tmp68_ = g_strdup ("Thresholded");
+ _tmp69_ = g_strdup (SANE_VALUE_SCAN_MODE_GRAY);
+ _tmp70_ = g_strdup ("Gray");
+ _tmp71_ = g_strdup ("Grayscale");
+ _tmp72_ = SANE_I18N ("Grayscale");
+ _tmp73_ = g_strdup (_tmp72_);
+ _tmp74_ = g_strdup ("True Gray");
+ _tmp75_ = g_new0 (gchar*, 14 + 1);
+ _tmp75_[0] = _tmp57_;
+ _tmp75_[1] = _tmp58_;
+ _tmp75_[2] = _tmp59_;
+ _tmp75_[3] = _tmp61_;
+ _tmp75_[4] = _tmp62_;
+ _tmp75_[5] = _tmp64_;
+ _tmp75_[6] = _tmp65_;
+ _tmp75_[7] = _tmp67_;
+ _tmp75_[8] = _tmp68_;
+ _tmp75_[9] = _tmp69_;
+ _tmp75_[10] = _tmp70_;
+ _tmp75_[11] = _tmp71_;
+ _tmp75_[12] = _tmp73_;
+ _tmp75_[13] = _tmp74_;
+ lineart_scan_modes = _tmp75_;
+ lineart_scan_modes_length1 = 14;
+ _lineart_scan_modes_size_ = lineart_scan_modes_length1;
+ switch (job->scan_mode) {
+ case SCAN_MODE_COLOR:
+ {
+ gboolean _tmp76_;
+ _tmp76_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, color_scan_modes, color_scan_modes_length1, NULL);
+ if (!_tmp76_) {
+ g_warning ("scanner.vala:994: Unable to set Color mode, please file a bug");
+ }
+ break;
+ }
+ case SCAN_MODE_GRAY:
+ {
+ gboolean _tmp77_;
+ _tmp77_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, gray_scan_modes, gray_scan_modes_length1, NULL);
+ if (!_tmp77_) {
+ g_warning ("scanner.vala:998: Unable to set Gray mode, please file a bug");
+ }
+ break;
+ }
+ case SCAN_MODE_LINEART:
+ {
+ gboolean _tmp78_;
+ _tmp78_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, lineart_scan_modes, lineart_scan_modes_length1, NULL);
+ if (!_tmp78_) {
+ g_warning ("scanner.vala:1002: Unable to set Lineart mode, please file a bug");
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ lineart_scan_modes = (_vala_array_free (lineart_scan_modes, lineart_scan_modes_length1, (GDestroyNotify) g_free), NULL);
+ gray_scan_modes = (_vala_array_free (gray_scan_modes, gray_scan_modes_length1, (GDestroyNotify) g_free), NULL);
+ color_scan_modes = (_vala_array_free (color_scan_modes, color_scan_modes_length1, (GDestroyNotify) g_free), NULL);
+ } else {
+ if (g_strcmp0 (option->name, "compression") == 0) {
+ const gchar* _tmp79_ = NULL;
+ gchar* _tmp80_;
+ const gchar* _tmp81_ = NULL;
+ gchar* _tmp82_;
+ gchar* _tmp83_;
+ gchar* _tmp84_;
+ gchar** _tmp85_ = NULL;
+ gchar** disable_compression_names;
+ gint disable_compression_names_length1;
+ gint _disable_compression_names_size_;
+ gboolean _tmp86_;
+ _tmp79_ = SANE_I18N ("None");
+ _tmp80_ = g_strdup (_tmp79_);
+ _tmp81_ = SANE_I18N ("none");
+ _tmp82_ = g_strdup (_tmp81_);
+ _tmp83_ = g_strdup ("None");
+ _tmp84_ = g_strdup ("none");
+ _tmp85_ = g_new0 (gchar*, 4 + 1);
+ _tmp85_[0] = _tmp80_;
+ _tmp85_[1] = _tmp82_;
+ _tmp85_[2] = _tmp83_;
+ _tmp85_[3] = _tmp84_;
+ disable_compression_names = _tmp85_;
+ disable_compression_names_length1 = 4;
+ _disable_compression_names_size_ = disable_compression_names_length1;
+ _tmp86_ = scanner_set_constrained_string_option (self, self->priv->handle, option, index, disable_compression_names, disable_compression_names_length1, NULL);
+ if (!_tmp86_) {
+ g_warning ("scanner.vala:1020: Unable to disable compression, please file a bug");
+ }
+ disable_compression_names = (_vala_array_free (disable_compression_names, disable_compression_names_length1, (GDestroyNotify) g_free), NULL);
+ } else {
+ if (g_strcmp0 (option->name, SANE_NAME_SCAN_BR_X) == 0) {
+ self->priv->br_x_option_index = index;
+ } else {
+ if (g_strcmp0 (option->name, SANE_NAME_SCAN_BR_Y) == 0) {
+ self->priv->br_y_option_index = index;
+ } else {
+ if (g_strcmp0 (option->name, SANE_NAME_PAGE_WIDTH) == 0) {
+ if (((gdouble) job->page_width) > 0.0) {
+ if (option->type == SANE_TYPE_FIXED) {
+ scanner_set_fixed_option (self, self->priv->handle, option, index, job->page_width / 10.0, NULL);
+ } else {
+ scanner_set_int_option (self, self->priv->handle, option, index, job->page_width / 10, NULL);
+ }
+ }
+ } else {
+ if (g_strcmp0 (option->name, SANE_NAME_PAGE_HEIGHT) == 0) {
+ if (((gdouble) job->page_height) > 0.0) {
+ if (option->type == SANE_TYPE_FIXED) {
+ scanner_set_fixed_option (self, self->priv->handle, option, index, job->page_height / 10.0, NULL);
+ } else {
+ scanner_set_int_option (self, self->priv->handle, option, index, job->page_height / 10, NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (g_strcmp0 (self->priv->current_device, "test") == 0) {
+ if (g_strcmp0 (option->name, "hand-scanner") == 0) {
+ scanner_set_bool_option (self, self->priv->handle, option, index, FALSE, NULL);
+ } else {
+ if (g_strcmp0 (option->name, "three-pass") == 0) {
+ scanner_set_bool_option (self, self->priv->handle, option, index, FALSE, NULL);
+ } else {
+ if (g_strcmp0 (option->name, "test-picture") == 0) {
+ scanner_set_string_option (self, self->priv->handle, option, index, "Color pattern", NULL);
+ } else {
+ if (g_strcmp0 (option->name, "read-delay") == 0) {
+ scanner_set_bool_option (self, self->priv->handle, option, index, TRUE, NULL);
+ } else {
+ if (g_strcmp0 (option->name, "read-delay-duration") == 0) {
+ scanner_set_int_option (self, self->priv->handle, option, index, 200000, NULL);
+ }
+ }
+ }
+ }
+ }
+ }
+ _scan_job_unref0 (job);
+}
+
+
+static void scanner_do_complete_document (Scanner* self) {
+ NotifyDocumentDone* _tmp0_ = NULL;
+ NotifyDocumentDone* _tmp1_;
+ g_return_if_fail (self != NULL);
+ self->priv->job_queue = g_list_remove_link (self->priv->job_queue, self->priv->job_queue);
+ self->priv->state = SCAN_STATE_IDLE;
+ if (self->priv->job_queue != NULL) {
+ self->priv->state = SCAN_STATE_OPEN;
+ return;
+ }
+ _tmp0_ = notify_document_done_new ();
+ _tmp1_ = _tmp0_;
+ scanner_notify (self, (Notify*) _tmp1_);
+ _notify_unref0 (_tmp1_);
+ scanner_set_scanning (self, FALSE);
+}
+
+
+static void scanner_do_start (Scanner* self) {
+ SANE_Status status = 0;
+ NotifyExpectPage* _tmp0_ = NULL;
+ NotifyExpectPage* _tmp1_;
+ SANE_Status _tmp2_;
+ gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = notify_expect_page_new ();
+ _tmp1_ = _tmp0_;
+ scanner_notify (self, (Notify*) _tmp1_);
+ _notify_unref0 (_tmp1_);
+ _tmp2_ = sane_start (self->priv->handle);
+ status = _tmp2_;
+ _tmp3_ = sane_status_to_string (status);
+ _tmp4_ = _tmp3_;
+ g_debug ("scanner.vala:1090: sane_start (page=%d, pass=%d) -> %s", self->priv->page_number, self->priv->pass_number, _tmp4_);
+ _g_free0 (_tmp4_);
+ if (status == SANE_STATUS_GOOD) {
+ self->priv->state = SCAN_STATE_GET_PARAMETERS;
+ } else {
+ if (status == SANE_STATUS_NO_DOCS) {
+ scanner_do_complete_document (self);
+ } else {
+ const gchar* _tmp5_ = NULL;
+ const gchar* _tmp6_ = NULL;
+ _tmp5_ = sane_strstatus (status);
+ g_warning ("scanner.vala:1097: Unable to start device: %s", _tmp5_);
+ _tmp6_ = _ ("Unable to start scan");
+ scanner_fail_scan (self, (gint) status, _tmp6_);
+ }
+ }
+}
+
+
+static gchar* sane_frame_to_string (SANE_Frame frame) {
+ gchar* result = NULL;
+ switch (frame) {
+ case SANE_FRAME_GRAY:
+ {
+ gchar* _tmp0_;
+ _tmp0_ = g_strdup ("SANE_FRAME_GRAY");
+ result = _tmp0_;
+ return result;
+ }
+ case SANE_FRAME_RGB:
+ {
+ gchar* _tmp1_;
+ _tmp1_ = g_strdup ("SANE_FRAME_RGB");
+ result = _tmp1_;
+ return result;
+ }
+ case SANE_FRAME_RED:
+ {
+ gchar* _tmp2_;
+ _tmp2_ = g_strdup ("SANE_FRAME_RED");
+ result = _tmp2_;
+ return result;
+ }
+ case SANE_FRAME_GREEN:
+ {
+ gchar* _tmp3_;
+ _tmp3_ = g_strdup ("SANE_FRAME_GREEN");
+ result = _tmp3_;
+ return result;
+ }
+ case SANE_FRAME_BLUE:
+ {
+ gchar* _tmp4_;
+ _tmp4_ = g_strdup ("SANE_FRAME_BLUE");
+ result = _tmp4_;
+ return result;
+ }
+ default:
+ {
+ gchar* _tmp5_ = NULL;
+ _tmp5_ = g_strdup_printf ("SANE_FRAME(%d)", (gint) frame);
+ result = _tmp5_;
+ return result;
+ }
+ }
+}
+
+
+static void scanner_do_get_parameters (Scanner* self) {
+ SANE_Parameters _tmp0_ = {0};
+ SANE_Status _tmp1_;
+ SANE_Status status;
+ gchar* _tmp2_ = NULL;
+ gchar* _tmp3_;
+ ScanJob* _tmp6_;
+ ScanJob* job;
+ const gchar* _tmp7_ = NULL;
+ gchar* _tmp8_ = NULL;
+ gchar* _tmp9_;
+ ScanPageInfo* _tmp10_ = NULL;
+ ScanPageInfo* info;
+ gboolean _tmp11_ = FALSE;
+ gboolean _tmp12_ = FALSE;
+ gboolean _tmp13_ = FALSE;
+ gint _tmp14_ = 0;
+ gchar* _tmp15_;
+ gint buffer_size;
+ guchar* _tmp18_ = NULL;
+ g_return_if_fail (self != NULL);
+ _tmp1_ = sane_get_parameters (self->priv->handle, &_tmp0_);
+ self->priv->parameters = _tmp0_;
+ status = _tmp1_;
+ _tmp2_ = sane_status_to_string (status);
+ _tmp3_ = _tmp2_;
+ g_debug ("scanner.vala:1107: sane_get_parameters () -> %s", _tmp3_);
+ _g_free0 (_tmp3_);
+ if (status != SANE_STATUS_GOOD) {
+ const gchar* _tmp4_ = NULL;
+ const gchar* _tmp5_ = NULL;
+ _tmp4_ = sane_strstatus (status);
+ g_warning ("scanner.vala:1110: Unable to get device parameters: %s", _tmp4_);
+ _tmp5_ = _ ("Error communicating with scanner");
+ scanner_fail_scan (self, (gint) status, _tmp5_);
+ return;
+ }
+ _tmp6_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data));
+ job = _tmp6_;
+ if (self->priv->parameters.last_frame) {
+ _tmp7_ = "SANE_TRUE";
+ } else {
+ _tmp7_ = "SANE_FALSE";
+ }
+ _tmp8_ = sane_frame_to_string (self->priv->parameters.format);
+ _tmp9_ = _tmp8_;
+ g_debug ("scanner.vala:1119: Parameters: format=%s last_frame=%s bytes_per_line=" \
+"%d pixels_per_line=%d lines=%d depth=%d", _tmp9_, _tmp7_, self->priv->parameters.bytes_per_line, self->priv->parameters.pixels_per_line, self->priv->parameters.lines, self->priv->parameters.depth);
+ _g_free0 (_tmp9_);
+ _tmp10_ = scan_page_info_new ();
+ info = _tmp10_;
+ info->width = self->priv->parameters.pixels_per_line;
+ info->height = self->priv->parameters.lines;
+ info->depth = self->priv->parameters.depth;
+ if (self->priv->parameters.depth == 8) {
+ _tmp13_ = self->priv->parameters.format == SANE_FRAME_GRAY;
+ } else {
+ _tmp13_ = FALSE;
+ }
+ if (_tmp13_) {
+ _tmp12_ = job->depth == 2;
+ } else {
+ _tmp12_ = FALSE;
+ }
+ if (_tmp12_) {
+ _tmp11_ = job->scan_mode == SCAN_MODE_GRAY;
+ } else {
+ _tmp11_ = FALSE;
+ }
+ if (_tmp11_) {
+ info->depth = job->depth;
+ }
+ if (self->priv->parameters.format == SANE_FRAME_GRAY) {
+ _tmp14_ = 1;
+ } else {
+ _tmp14_ = 3;
+ }
+ info->n_channels = _tmp14_;
+ info->dpi = job->dpi;
+ _tmp15_ = g_strdup (self->priv->current_device);
+ _g_free0 (info->device);
+ info->device = _tmp15_;
+ if (self->priv->page_number != self->priv->notified_page) {
+ NotifyGotPageInfo* _tmp16_ = NULL;
+ NotifyGotPageInfo* _tmp17_;
+ _tmp16_ = notify_got_page_info_new (info);
+ _tmp17_ = _tmp16_;
+ scanner_notify (self, (Notify*) _tmp17_);
+ _notify_unref0 (_tmp17_);
+ self->priv->notified_page = self->priv->page_number;
+ }
+ buffer_size = self->priv->parameters.bytes_per_line + 1;
+ _tmp18_ = g_new0 (guchar, buffer_size);
+ self->priv->buffer = (g_free (self->priv->buffer), NULL);
+ self->priv->buffer = _tmp18_;
+ self->priv->buffer_length1 = buffer_size;
+ self->priv->_buffer_size_ = self->priv->buffer_length1;
+ self->priv->n_used = 0;
+ self->priv->line_count = 0;
+ self->priv->pass_number = 0;
+ self->priv->state = SCAN_STATE_READ;
+ _scan_page_info_unref0 (info);
+ _scan_job_unref0 (job);
+}
+
+
+static void scanner_do_complete_page (Scanner* self) {
+ NotifyPageDone* _tmp0_ = NULL;
+ NotifyPageDone* _tmp1_;
+ ScanJob* _tmp2_;
+ ScanJob* job;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = notify_page_done_new ();
+ _tmp1_ = _tmp0_;
+ scanner_notify (self, (Notify*) _tmp1_);
+ _notify_unref0 (_tmp1_);
+ _tmp2_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data));
+ job = _tmp2_;
+ if (!self->priv->parameters.last_frame) {
+ self->priv->pass_number++;
+ self->priv->state = SCAN_STATE_START;
+ _scan_job_unref0 (job);
+ return;
+ }
+ if (job->type != SCAN_TYPE_SINGLE) {
+ NotifyPageDone* _tmp3_ = NULL;
+ NotifyPageDone* _tmp4_;
+ self->priv->page_number++;
+ self->priv->pass_number = 0;
+ _tmp3_ = notify_page_done_new ();
+ _tmp4_ = _tmp3_;
+ scanner_notify (self, (Notify*) _tmp4_);
+ _notify_unref0 (_tmp4_);
+ self->priv->state = SCAN_STATE_START;
+ _scan_job_unref0 (job);
+ return;
+ }
+ sane_cancel (self->priv->handle);
+ g_debug ("scanner.vala:1179: sane_cancel ()");
+ scanner_do_complete_document (self);
+ _scan_job_unref0 (job);
+}
+
+
+static void scanner_do_read (Scanner* self) {
+ ScanJob* _tmp0_;
+ ScanJob* job;
+ gint n_to_read;
+ SANE_Int n_read;
+ guchar* b;
+ SANE_Int _tmp1_;
+ SANE_Status _tmp2_;
+ SANE_Status status;
+ gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ gboolean full_read;
+ gboolean _tmp8_ = FALSE;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = _scan_job_ref0 (SCAN_JOB ((ScanJob*) self->priv->job_queue->data));
+ job = _tmp0_;
+ n_to_read = self->priv->buffer_length1 - self->priv->n_used;
+ b = (guchar*) self->priv->buffer;
+ _tmp2_ = sane_read (self->priv->handle, (guint8*) (b + self->priv->n_used), (SANE_Int) n_to_read, &_tmp1_);
+ n_read = _tmp1_;
+ status = _tmp2_;
+ _tmp3_ = sane_status_to_string (status);
+ _tmp4_ = _tmp3_;
+ g_debug ("scanner.vala:1194: sane_read (%d) -> (%s, %d)", n_to_read, _tmp4_, (gint) n_read);
+ _g_free0 (_tmp4_);
+ if (status == SANE_STATUS_EOF) {
+ gboolean _tmp5_ = FALSE;
+ if (self->priv->parameters.lines > 0) {
+ _tmp5_ = self->priv->line_count != self->priv->parameters.lines;
+ } else {
+ _tmp5_ = FALSE;
+ }
+ if (_tmp5_) {
+ g_warning ("scanner.vala:1200: Scan completed with %d lines, expected %d lines", self->priv->parameters.lines, self->priv->parameters.lines);
+ }
+ if (self->priv->n_used > 0) {
+ g_warning ("scanner.vala:1202: Scan complete with %d bytes of unused data", self->priv->n_used);
+ }
+ scanner_do_complete_page (self);
+ _scan_job_unref0 (job);
+ return;
+ }
+ if (status != SANE_STATUS_GOOD) {
+ const gchar* _tmp6_ = NULL;
+ const gchar* _tmp7_ = NULL;
+ _tmp6_ = sane_strstatus (status);
+ g_warning ("scanner.vala:1210: Unable to read frame from device: %s", _tmp6_);
+ _tmp7_ = _ ("Error communicating with scanner");
+ scanner_fail_scan (self, (gint) status, _tmp7_);
+ _scan_job_unref0 (job);
+ return;
+ }
+ full_read = FALSE;
+ if (self->priv->n_used == 0) {
+ _tmp8_ = ((gint) n_read) == self->priv->buffer_length1;
+ } else {
+ _tmp8_ = FALSE;
+ }
+ if (_tmp8_) {
+ full_read = TRUE;
+ }
+ self->priv->n_used = self->priv->n_used + n_read;
+ if (self->priv->n_used >= self->priv->parameters.bytes_per_line) {
+ ScanLine* _tmp9_ = NULL;
+ ScanLine* line;
+ guchar* _tmp10_;
+ gint _tmp11_;
+ gint buffer_size;
+ guchar* _tmp12_ = NULL;
+ gint n_remaining;
+ gboolean _tmp14_ = FALSE;
+ gboolean _tmp15_ = FALSE;
+ gboolean _tmp16_ = FALSE;
+ NotifyGotLine* _tmp19_ = NULL;
+ NotifyGotLine* _tmp20_;
+ _tmp9_ = scan_line_new ();
+ line = _tmp9_;
+ switch (self->priv->parameters.format) {
+ case SANE_FRAME_GRAY:
+ {
+ line->channel = 0;
+ break;
+ }
+ case SANE_FRAME_RGB:
+ {
+ line->channel = -1;
+ break;
+ }
+ case SANE_FRAME_RED:
+ {
+ line->channel = 0;
+ break;
+ }
+ case SANE_FRAME_GREEN:
+ {
+ line->channel = 1;
+ break;
+ }
+ case SANE_FRAME_BLUE:
+ {
+ line->channel = 2;
+ break;
+ }
+ default:
+ break;
+ }
+ line->width = self->priv->parameters.pixels_per_line;
+ line->depth = self->priv->parameters.depth;
+ _tmp10_ = self->priv->buffer;
+ _tmp11_ = self->priv->buffer_length1;
+ self->priv->buffer = NULL;
+ line->data = (g_free (line->data), NULL);
+ line->data = _tmp10_;
+ line->data_length1 = _tmp11_;
+ line->data_length = self->priv->parameters.bytes_per_line;
+ line->number = self->priv->line_count;
+ line->n_lines = self->priv->n_used / line->data_length;
+ self->priv->line_count = self->priv->line_count + line->n_lines;
+ buffer_size = self->priv->buffer_length1;
+ if (full_read) {
+ buffer_size = buffer_size + self->priv->parameters.bytes_per_line;
+ }
+ _tmp12_ = g_new0 (guchar, buffer_size);
+ self->priv->buffer = (g_free (self->priv->buffer), NULL);
+ self->priv->buffer = _tmp12_;
+ self->priv->buffer_length1 = buffer_size;
+ self->priv->_buffer_size_ = self->priv->buffer_length1;
+ n_remaining = self->priv->n_used - (line->n_lines * line->data_length);
+ self->priv->n_used = 0;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp13_;
+ _tmp13_ = TRUE;
+ while (TRUE) {
+ if (!_tmp13_) {
+ i++;
+ }
+ _tmp13_ = FALSE;
+ if (!(i < n_remaining)) {
+ break;
+ }
+ self->priv->buffer[i] = line->data[i + (line->n_lines * line->data_length)];
+ self->priv->n_used++;
+ }
+ }
+ }
+ if (self->priv->parameters.depth == 8) {
+ _tmp16_ = self->priv->parameters.format == SANE_FRAME_GRAY;
+ } else {
+ _tmp16_ = FALSE;
+ }
+ if (_tmp16_) {
+ _tmp15_ = job->depth == 2;
+ } else {
+ _tmp15_ = FALSE;
+ }
+ if (_tmp15_) {
+ _tmp14_ = job->scan_mode == SCAN_MODE_GRAY;
+ } else {
+ _tmp14_ = FALSE;
+ }
+ if (_tmp14_) {
+ guchar block;
+ gint write_offset;
+ gint block_shift;
+ block = (guchar) 0;
+ write_offset = 0;
+ block_shift = 6;
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp17_;
+ _tmp17_ = TRUE;
+ while (TRUE) {
+ gint offset;
+ if (!_tmp17_) {
+ i++;
+ }
+ _tmp17_ = FALSE;
+ if (!(i < line->n_lines)) {
+ break;
+ }
+ offset = i * line->data_length;
+ {
+ gint x;
+ x = 0;
+ {
+ gboolean _tmp18_;
+ _tmp18_ = TRUE;
+ while (TRUE) {
+ guchar p;
+ guchar sample = '\0';
+ if (!_tmp18_) {
+ x++;
+ }
+ _tmp18_ = FALSE;
+ if (!(x < line->width)) {
+ break;
+ }
+ p = line->data[offset + x];
+ if (((gint) p) >= 192) {
+ sample = (guchar) 3;
+ } else {
+ if (((gint) p) >= 128) {
+ sample = (guchar) 2;
+ } else {
+ if (((gint) p) >= 64) {
+ sample = (guchar) 1;
+ } else {
+ sample = (guchar) 0;
+ }
+ }
+ }
+ block = block | (sample << block_shift);
+ if (block_shift == 0) {
+ line->data[write_offset] = block;
+ write_offset++;
+ block = (guchar) 0;
+ block_shift = 6;
+ } else {
+ block_shift = block_shift - 2;
+ }
+ }
+ }
+ }
+ if (block_shift != 6) {
+ line->data[write_offset] = block;
+ write_offset++;
+ block = (guchar) 0;
+ block_shift = 6;
+ }
+ }
+ }
+ }
+ line->data_length = ((line->width * 2) + 7) / 8;
+ }
+ _tmp19_ = notify_got_line_new (line);
+ _tmp20_ = _tmp19_;
+ scanner_notify (self, (Notify*) _tmp20_);
+ _notify_unref0 (_tmp20_);
+ _scan_line_unref0 (line);
+ }
+ _scan_job_unref0 (job);
+}
+
+
+static void _scanner_authorization_cb_sane_authcallback (const gchar* resource, gchar* username, gchar* password) {
+ scanner_authorization_cb (resource, username, -1, password, -1);
+}
+
+
+static void* scanner_scan_thread (Scanner* self) {
+ void* result = NULL;
+ SANE_Int version_code;
+ SANE_Int _tmp0_;
+ SANE_Status _tmp1_;
+ SANE_Status status;
+ gchar* _tmp2_ = NULL;
+ gchar* _tmp3_;
+ gint _tmp5_;
+ gint _tmp6_;
+ gint _tmp7_;
+ g_return_val_if_fail (self != NULL, NULL);
+ self->priv->state = SCAN_STATE_IDLE;
+ _tmp1_ = sane_init (&_tmp0_, _scanner_authorization_cb_sane_authcallback);
+ version_code = _tmp0_;
+ status = _tmp1_;
+ _tmp2_ = sane_status_to_string (status);
+ _tmp3_ = _tmp2_;
+ g_debug ("scanner.vala:1327: sane_init () -> %s", _tmp3_);
+ _g_free0 (_tmp3_);
+ if (status != SANE_STATUS_GOOD) {
+ const gchar* _tmp4_ = NULL;
+ _tmp4_ = sane_strstatus (status);
+ g_warning ("scanner.vala:1330: Unable to initialize SANE backend: %s", _tmp4_);
+ result = NULL;
+ return result;
+ }
+ _tmp5_ = SANE_VERSION_MAJOR (version_code);
+ _tmp6_ = SANE_VERSION_MINOR (version_code);
+ _tmp7_ = SANE_VERSION_BUILD (version_code);
+ g_debug ("scanner.vala:1333: SANE version %d.%d.%d", _tmp5_, _tmp6_, _tmp7_);
+ scanner_redetect (self);
+ while (TRUE) {
+ gboolean _tmp8_;
+ _tmp8_ = scanner_handle_requests (self);
+ if (!_tmp8_) {
+ break;
+ }
+ switch (self->priv->state) {
+ case SCAN_STATE_IDLE:
+ {
+ if (self->priv->job_queue != NULL) {
+ scanner_set_scanning (self, TRUE);
+ self->priv->state = SCAN_STATE_OPEN;
+ }
+ break;
+ }
+ case SCAN_STATE_REDETECT:
+ {
+ scanner_do_redetect (self);
+ break;
+ }
+ case SCAN_STATE_OPEN:
+ {
+ scanner_do_open (self);
+ break;
+ }
+ case SCAN_STATE_GET_OPTION:
+ {
+ scanner_do_get_option (self);
+ break;
+ }
+ case SCAN_STATE_START:
+ {
+ scanner_do_start (self);
+ break;
+ }
+ case SCAN_STATE_GET_PARAMETERS:
+ {
+ scanner_do_get_parameters (self);
+ break;
+ }
+ case SCAN_STATE_READ:
+ {
+ scanner_do_read (self);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ result = NULL;
+ return result;
+}
+
+
+static gpointer _scanner_scan_thread_gthread_func (gpointer self) {
+ gpointer result;
+ result = scanner_scan_thread (self);
+ return result;
+}
+
+
+void scanner_start (Scanner* self) {
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ {
+ GThread* _tmp0_ = NULL;
+ GThread* _tmp1_;
+ _tmp0_ = g_thread_create (_scanner_scan_thread_gthread_func, self, TRUE, &_inner_error_);
+ _tmp1_ = _tmp0_;
+ if (_inner_error_ != NULL) {
+ goto __catch9_g_error;
+ }
+ self->priv->thread = _tmp1_;
+ }
+ goto __finally9;
+ __catch9_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_critical ("scanner.vala:1384: Unable to create thread: %s", e->message);
+ _g_error_free0 (e);
+ }
+ __finally9:
+ if (_inner_error_ != NULL) {
+ 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;
+ }
+}
+
+
+void scanner_redetect (Scanner* self) {
+ RequestRedetect* _tmp0_ = NULL;
+ g_return_if_fail (self != NULL);
+ if (self->priv->need_redetect) {
+ return;
+ }
+ self->priv->need_redetect = TRUE;
+ g_debug ("scanner.vala:1394: Requesting redetection of scan devices");
+ _tmp0_ = request_redetect_new ();
+ g_async_queue_push (self->priv->request_queue, (Request*) _tmp0_);
+}
+
+
+gboolean scanner_is_scanning (Scanner* self) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ result = self->priv->scanning;
+ return result;
+}
+
+
+static gchar* scanner_get_scan_mode_string (Scanner* self, ScanMode mode) {
+ gchar* result = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ switch (mode) {
+ case SCAN_MODE_DEFAULT:
+ {
+ gchar* _tmp0_;
+ _tmp0_ = g_strdup ("ScanMode.DEFAULT");
+ result = _tmp0_;
+ return result;
+ }
+ case SCAN_MODE_COLOR:
+ {
+ gchar* _tmp1_;
+ _tmp1_ = g_strdup ("ScanMode.COLOR");
+ result = _tmp1_;
+ return result;
+ }
+ case SCAN_MODE_GRAY:
+ {
+ gchar* _tmp2_;
+ _tmp2_ = g_strdup ("ScanMode.GRAY");
+ result = _tmp2_;
+ return result;
+ }
+ case SCAN_MODE_LINEART:
+ {
+ gchar* _tmp3_;
+ _tmp3_ = g_strdup ("ScanMode.LINEART");
+ result = _tmp3_;
+ return result;
+ }
+ default:
+ {
+ gchar* _tmp4_ = NULL;
+ _tmp4_ = g_strdup_printf ("%d", (gint) mode);
+ result = _tmp4_;
+ return result;
+ }
+ }
+}
+
+
+static gchar* scanner_get_scan_type_string (Scanner* self, ScanType type) {
+ gchar* result = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ switch (type) {
+ case SCAN_TYPE_SINGLE:
+ {
+ gchar* _tmp0_;
+ _tmp0_ = g_strdup ("ScanType.SINGLE");
+ result = _tmp0_;
+ return result;
+ }
+ case SCAN_TYPE_ADF_FRONT:
+ {
+ gchar* _tmp1_;
+ _tmp1_ = g_strdup ("ScanType.ADF_FRONT");
+ result = _tmp1_;
+ return result;
+ }
+ case SCAN_TYPE_ADF_BACK:
+ {
+ gchar* _tmp2_;
+ _tmp2_ = g_strdup ("ScanType.ADF_BACK");
+ result = _tmp2_;
+ return result;
+ }
+ case SCAN_TYPE_ADF_BOTH:
+ {
+ gchar* _tmp3_;
+ _tmp3_ = g_strdup ("ScanType.ADF_BOTH");
+ result = _tmp3_;
+ return result;
+ }
+ default:
+ {
+ gchar* _tmp4_ = NULL;
+ _tmp4_ = g_strdup_printf ("%d", (gint) type);
+ result = _tmp4_;
+ return result;
+ }
+ }
+}
+
+
+void scanner_scan (Scanner* self, const gchar* device, ScanOptions* options) {
+ const gchar* _tmp0_ = NULL;
+ gchar* _tmp1_ = NULL;
+ gchar* _tmp2_;
+ gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ RequestStartScan* _tmp5_ = NULL;
+ RequestStartScan* request;
+ ScanJob* _tmp6_ = NULL;
+ gchar* _tmp7_;
+ Request* _tmp8_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (options != NULL);
+ if (device != NULL) {
+ _tmp0_ = device;
+ } else {
+ _tmp0_ = "(null)";
+ }
+ _tmp1_ = scanner_get_scan_mode_string (self, options->scan_mode);
+ _tmp2_ = _tmp1_;
+ _tmp3_ = scanner_get_scan_type_string (self, options->type);
+ _tmp4_ = _tmp3_;
+ g_debug ("scanner.vala:1440: Scanner.scan (\"%s\", dpi=%d, scan_mode=%s, depth=%" \
+"d, type=%s, paper_width=%d, paper_height=%d)", _tmp0_, options->dpi, _tmp2_, options->depth, _tmp4_, options->paper_width, options->paper_height);
+ _g_free0 (_tmp4_);
+ _g_free0 (_tmp2_);
+ _tmp5_ = request_start_scan_new ();
+ request = _tmp5_;
+ _tmp6_ = scan_job_new ();
+ _scan_job_unref0 (request->job);
+ request->job = _tmp6_;
+ _tmp7_ = g_strdup (device);
+ _g_free0 (request->job->device);
+ request->job->device = _tmp7_;
+ request->job->dpi = (gdouble) options->dpi;
+ request->job->scan_mode = options->scan_mode;
+ request->job->depth = options->depth;
+ request->job->type = options->type;
+ request->job->page_width = options->paper_width;
+ request->job->page_height = options->paper_height;
+ _tmp8_ = _request_ref0 ((Request*) request);
+ g_async_queue_push (self->priv->request_queue, _tmp8_);
+ _request_unref0 (request);
+}
+
+
+void scanner_cancel (Scanner* self) {
+ RequestCancel* _tmp0_ = NULL;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = request_cancel_new ();
+ g_async_queue_push (self->priv->request_queue, (Request*) _tmp0_);
+}
+
+
+void scanner_free (Scanner* self) {
+ RequestQuit* _tmp0_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_debug ("scanner.vala:1462: Stopping scan thread");
+ _tmp0_ = request_quit_new ();
+ g_async_queue_push (self->priv->request_queue, (Request*) _tmp0_);
+ if (self->priv->thread != NULL) {
+ g_thread_join (self->priv->thread);
+ }
+ sane_exit ();
+ g_debug ("scanner.vala:1470: sane_exit ()");
+}
+
+
+static void g_cclosure_user_marshal_VOID__SCAN_PAGE_INFO (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__SCAN_PAGE_INFO) (gpointer data1, gpointer arg_1, gpointer data2);
+ register GMarshalFunc_VOID__SCAN_PAGE_INFO callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 2);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__SCAN_PAGE_INFO) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, value_get_scan_page_info (param_values + 1), data2);
+}
+
+
+static void g_cclosure_user_marshal_VOID__SCAN_LINE (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__SCAN_LINE) (gpointer data1, gpointer arg_1, gpointer data2);
+ register GMarshalFunc_VOID__SCAN_LINE callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 2);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__SCAN_LINE) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, value_get_scan_line (param_values + 1), data2);
+}
+
+
+static void g_cclosure_user_marshal_VOID__INT_STRING (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__INT_STRING) (gpointer data1, gint arg_1, const char* arg_2, gpointer data2);
+ register GMarshalFunc_VOID__INT_STRING callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 3);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__INT_STRING) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, g_value_get_int (param_values + 1), g_value_get_string (param_values + 2), data2);
+}
+
+
+static void value_scanner_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_scanner_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ scanner_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_scanner_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = scanner_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_scanner_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_scanner_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ Scanner* 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 = scanner_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_scanner_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ Scanner** 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 = scanner_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_scanner (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecScanner* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_SCANNER), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_scanner (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCANNER), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_scanner (GValue* value, gpointer v_object) {
+ Scanner* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCANNER));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCANNER));
+ 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;
+ scanner_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ scanner_unref (old);
+ }
+}
+
+
+void value_take_scanner (GValue* value, gpointer v_object) {
+ Scanner* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SCANNER));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SCANNER));
+ 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) {
+ scanner_unref (old);
+ }
+}
+
+
+static void scanner_class_init (ScannerClass * klass) {
+ scanner_parent_class = g_type_class_peek_parent (klass);
+ SCANNER_CLASS (klass)->finalize = scanner_finalize;
+ g_type_class_add_private (klass, sizeof (ScannerPrivate));
+ g_signal_new ("update_devices", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
+ g_signal_new ("request_authorization", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+ g_signal_new ("expect_page", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("got_page_info", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__SCAN_PAGE_INFO, G_TYPE_NONE, 1, TYPE_SCAN_PAGE_INFO);
+ g_signal_new ("got_line", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__SCAN_LINE, G_TYPE_NONE, 1, TYPE_SCAN_LINE);
+ g_signal_new ("scan_failed", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__INT_STRING, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING);
+ g_signal_new ("page_done", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("document_done", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("scanning_changed", TYPE_SCANNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+
+static void scanner_instance_init (Scanner * self) {
+ self->priv = SCANNER_GET_PRIVATE (self);
+ self->ref_count = 1;
+}
+
+
+static void scanner_finalize (Scanner* obj) {
+ Scanner * self;
+ self = SCANNER (obj);
+ _g_async_queue_unref0 (self->priv->request_queue);
+ _g_async_queue_unref0 (self->priv->notify_queue);
+ _g_async_queue_unref0 (self->priv->authorize_queue);
+ _g_free0 (self->priv->default_device);
+ __g_list_free__scan_job_unref0_0 (self->priv->job_queue);
+ _g_free0 (self->priv->current_device);
+ self->priv->buffer = (g_free (self->priv->buffer), NULL);
+}
+
+
+GType scanner_get_type (void) {
+ static volatile gsize scanner_type_id__volatile = 0;
+ if (g_once_init_enter (&scanner_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_scanner_init, value_scanner_free_value, value_scanner_copy_value, value_scanner_peek_pointer, "p", value_scanner_collect_value, "p", value_scanner_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (ScannerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scanner_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Scanner), 0, (GInstanceInitFunc) scanner_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 scanner_type_id;
+ scanner_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Scanner", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&scanner_type_id__volatile, scanner_type_id);
+ }
+ return scanner_type_id__volatile;
+}
+
+
+gpointer scanner_ref (gpointer instance) {
+ Scanner* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void scanner_unref (gpointer instance) {
+ Scanner* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ SCANNER_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+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]);
+ }
+ }
+ }
+}
+
+
+static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {
+ _vala_array_destroy (array, array_length, destroy_func);
+ g_free (array);
+}
+
+
+
diff --git a/src/scanner.h b/src/scanner.h
deleted file mode 100644
index 72a4ffd..0000000
--- a/src/scanner.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2009 Canonical Ltd.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#ifndef _SCANNER_H_
-#define _SCANNER_H_
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define SCANNER_TYPE (scanner_get_type ())
-#define SCANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SCANNER_TYPE, Scanner))
-
-
-typedef struct
-{
- gchar *name, *label;
-} ScanDevice;
-
-typedef struct
-{
- /* Width, height in pixels */
- gint width, height;
-
- /* Bit depth */
- gint depth;
-
- /* Number of colour channels */
- gint n_channels;
-
- /* Resolution */
- gdouble dpi;
-
- /* The device this page came from */
- gchar *device;
-} ScanPageInfo;
-
-typedef struct
-{
- /* Line number */
- gint number;
-
- /* Number of lines in this packet */
- gint n_lines;
-
- /* Width in pixels and format */
- gint width, depth;
-
- /* Channel for this line or -1 for all channels */
- gint channel;
-
- /* Raw line data */
- guchar *data;
- gsize data_length;
-} ScanLine;
-
-typedef enum
-{
- SCAN_MODE_DEFAULT,
- SCAN_MODE_COLOR,
- SCAN_MODE_GRAY,
- SCAN_MODE_LINEART
-} ScanMode;
-
-typedef enum
-{
- SCAN_SINGLE,
- SCAN_ADF_FRONT,
- SCAN_ADF_BACK,
- SCAN_ADF_BOTH
-} ScanType;
-
-typedef struct
-{
- gint dpi;
- ScanMode scan_mode;
- gint depth;
- ScanType type;
- gint paper_width, paper_height;
-} ScanOptions;
-
-typedef struct ScannerPrivate ScannerPrivate;
-
-typedef struct
-{
- GObject parent_instance;
- ScannerPrivate *priv;
-} Scanner;
-
-typedef struct
-{
- GObjectClass parent_class;
-
- void (*update_devices) (Scanner *scanner, GList *devices);
- void (*authorize) (Scanner *scanner, const gchar *resource);
- void (*expect_page) (Scanner *scanner);
- void (*got_page_info) (Scanner *scanner, ScanPageInfo *info);
- void (*got_line) (Scanner *scanner, ScanLine *line);
- void (*scan_failed) (Scanner *scanner, GError *error);
- void (*page_done) (Scanner *scanner);
- void (*document_done) (Scanner *scanner);
- void (*scanning_changed) (Scanner *scanner);
-} ScannerClass;
-
-
-GType scanner_get_type (void);
-
-Scanner *scanner_new (void);
-
-void scanner_start (Scanner *scanner);
-
-void scanner_authorize (Scanner *scanner, const gchar *username, const gchar *password);
-
-void scanner_redetect (Scanner *scanner);
-
-gboolean scanner_is_scanning (Scanner *scanner);
-
-void scanner_scan (Scanner *scanner, const char *device, ScanOptions *options);
-
-void scanner_cancel (Scanner *scanner);
-
-void scanner_free (Scanner *scanner);
-
-#endif /* _SCANNER_H_ */
diff --git a/src/scanner.vala b/src/scanner.vala
new file mode 100644
index 0000000..02aa69d
--- /dev/null
+++ b/src/scanner.vala
@@ -0,0 +1,1472 @@
+/*
+ * Copyright (C) 2009-2011 Canonical Ltd.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+/* TODO: Could indicate the start of the next page immediately after the last page is received (i.e. before the sane_cancel()) */
+
+public class ScanDevice
+{
+ public string name;
+ public string label;
+}
+
+public class ScanPageInfo
+{
+ /* Width, height in pixels */
+ public int width;
+ public int height;
+
+ /* Bit depth */
+ public int depth;
+
+ /* Number of colour channels */
+ public int n_channels;
+
+ /* Resolution */
+ public double dpi;
+
+ /* The device this page came from */
+ public string device;
+}
+
+public class ScanLine
+{
+ /* Line number */
+ public int number;
+
+ /* Number of lines in this packet */
+ public int n_lines;
+
+ /* Width in pixels and format */
+ public int width;
+ public int depth;
+
+ /* Channel for this line or -1 for all channels */
+ public int channel;
+
+ /* Raw line data */
+ public uchar[] data;
+ public int data_length;
+}
+
+public enum ScanMode
+{
+ DEFAULT,
+ COLOR,
+ GRAY,
+ LINEART
+}
+
+public enum ScanType
+{
+ SINGLE,
+ ADF_FRONT,
+ ADF_BACK,
+ ADF_BOTH
+}
+
+public class ScanOptions
+{
+ public int dpi;
+ public ScanMode scan_mode;
+ public int depth;
+ public ScanType type;
+ public int paper_width;
+ public int paper_height;
+}
+
+private class ScanJob
+{
+ public string device;
+ public double dpi;
+ public ScanMode scan_mode;
+ public int depth;
+ public ScanType type;
+ public int page_width;
+ public int page_height;
+}
+
+private class Request {}
+
+private class RequestRedetect : Request {}
+
+private class RequestCancel : Request {}
+
+private class RequestStartScan : Request
+{
+ public ScanJob job;
+}
+
+private class RequestQuit : Request {}
+
+private class Credentials
+{
+ public string username;
+ public string password;
+}
+
+private enum ScanState
+{
+ IDLE = 0,
+ REDETECT,
+ OPEN,
+ GET_OPTION,
+ START,
+ GET_PARAMETERS,
+ READ
+}
+
+private class Notify
+{
+ public virtual void run (Scanner scanner) {}
+}
+
+private class NotifyScanningChanged : Notify
+{
+ public override void run (Scanner scanner) { scanner.scanning_changed (); }
+}
+
+private class NotifyUpdateDevices : Notify
+{
+ public NotifyUpdateDevices (owned List<ScanDevice> devices) { this.devices = (owned) devices; }
+ private List<ScanDevice> devices;
+ public override void run (Scanner scanner) { scanner.update_devices (devices); }
+}
+
+private class NotifyRequestAuthorization : Notify
+{
+ public NotifyRequestAuthorization (string resource) { this.resource = resource; }
+ private string resource;
+ public override void run (Scanner scanner) { scanner.request_authorization (resource); }
+}
+
+private class NotifyScanFailed : Notify
+{
+ public NotifyScanFailed (int error_code, string error_string) { this.error_code = error_code; this.error_string = error_string; }
+ private int error_code;
+ private string error_string;
+ public override void run (Scanner scanner) { scanner.scan_failed (error_code, error_string); }
+}
+
+private class NotifyDocumentDone : Notify
+{
+ public override void run (Scanner scanner) { scanner.document_done (); }
+}
+
+private class NotifyExpectPage : Notify
+{
+ public override void run (Scanner scanner) { scanner.expect_page (); }
+}
+
+private class NotifyGotPageInfo : Notify
+{
+ public NotifyGotPageInfo (ScanPageInfo info) { this.info = info; }
+ private ScanPageInfo info;
+ public override void run (Scanner scanner) { scanner.got_page_info (info); }
+}
+
+private class NotifyPageDone : Notify
+{
+ public override void run (Scanner scanner) { scanner.page_done (); }
+}
+
+private class NotifyGotLine : Notify
+{
+ public NotifyGotLine (ScanLine line) { this.line = line; }
+ private ScanLine line;
+ public override void run (Scanner scanner)
+ {
+ scanner.got_line (line);
+ }
+}
+
+public class Scanner
+{
+ /* Singleton object */
+ private static Scanner scanner_object = null;
+
+ /* Thread communicating with SANE */
+ private unowned Thread<void*> thread;
+
+ /* Queue of requests from main thread */
+ private AsyncQueue<Request> request_queue;
+
+ /* Queue of events to notify in main queue */
+ private AsyncQueue<Notify> notify_queue;
+
+ /* Queue of responses to authorization requests */
+ private AsyncQueue<Credentials> authorize_queue;
+
+ private string? default_device;
+
+ private ScanState state;
+ private bool need_redetect;
+
+ private List<ScanJob> job_queue;
+
+ /* Handle to SANE device */
+ private Sane.Handle handle;
+ private bool have_handle;
+ private string? current_device;
+
+ private Sane.Parameters parameters;
+
+ /* Last option read */
+ private Sane.Int option_index;
+
+ /* Option index for scan area */
+ private Sane.Int br_x_option_index;
+ private Sane.Int br_y_option_index;
+
+ /* Buffer for received line */
+ private uchar[] buffer;
+ private int n_used;
+
+ //private int bytes_remaining;
+ private int line_count;
+ private int pass_number;
+ private int page_number;
+ private int notified_page;
+
+ private bool scanning;
+
+ public signal void update_devices (List<ScanDevice> devices);
+ public signal void request_authorization (string resource);
+ public signal void expect_page ();
+ public signal void got_page_info (ScanPageInfo info);
+ public signal void got_line (ScanLine line);
+ public signal void scan_failed (int error_code, string error_string);
+ public signal void page_done ();
+ public signal void document_done ();
+ public signal void scanning_changed ();
+
+ private Scanner ()
+ {
+ request_queue = new AsyncQueue<Request> ();
+ notify_queue = new AsyncQueue<Notify> ();
+ authorize_queue = new AsyncQueue<Credentials> ();
+ }
+
+ public static Scanner get_instance ()
+ {
+ if (scanner_object == null)
+ scanner_object = new Scanner ();
+ return scanner_object;
+ }
+
+ private bool notify_idle_cb ()
+ {
+ var notification = notify_queue.pop ();
+ notification.run (this);
+ return false;
+ }
+
+ private void notify (Notify notification)
+ {
+ notify_queue.push (notification);
+ Idle.add (notify_idle_cb);
+ }
+
+ private void set_scanning (bool is_scanning)
+ {
+ if ((scanning && !is_scanning) || (!scanning && is_scanning))
+ {
+ scanning = is_scanning;
+ scanning_changed ();
+ notify (new NotifyScanningChanged ());
+ }
+ }
+
+ private static int get_device_weight (string device)
+ {
+ /* NOTE: This is using trends in the naming of SANE devices, SANE should be able to provide this information better */
+
+ /* Use webcams as a last resort */
+ if (device.has_prefix ("vfl:"))
+ return 2;
+
+ /* Use locally connected devices first */
+ if (device.contains ("usb"))
+ return 0;
+
+ return 1;
+ }
+
+ private static int compare_devices (ScanDevice device1, ScanDevice device2)
+ {
+ /* TODO: Should do some fuzzy matching on the last selected device and set that to the default */
+
+ var weight1 = get_device_weight (device1.name);
+ var weight2 = get_device_weight (device2.name);
+ if (weight1 != weight2)
+ return weight1 - weight2;
+
+ return strcmp (device1.label, device2.label);
+ }
+
+ private void do_redetect ()
+ {
+ unowned Sane.Device[] device_list = null;
+ var status = Sane.get_devices (out device_list, false);
+ debug ("sane_get_devices () -> %s", Sane.status_to_string (status));
+ if (status != Sane.Status.GOOD)
+ {
+ warning ("Unable to get SANE devices: %s", Sane.strstatus(status));
+ need_redetect = false;
+ state = ScanState.IDLE;
+ return;
+ }
+
+ List<ScanDevice> devices = null;
+ for (var i = 0; device_list[i] != null; i++)
+ {
+ debug ("Device: name=\"%s\" vendor=\"%s\" model=\"%s\" type=\"%s\"",
+ device_list[i].name, device_list[i].vendor, device_list[i].model, device_list[i].type);
+
+ var scan_device = new ScanDevice ();
+ scan_device.name = device_list[i].name;
+
+ /* Abbreviate HP as it is a long string and does not match what is on the physical scanner */
+ var vendor = device_list[i].vendor;
+ if (vendor == "Hewlett-Packard")
+ vendor = "HP";
+
+ scan_device.label = "%s %s".printf (vendor, device_list[i].model);
+ /* Replace underscores in name */
+ scan_device.label.replace ("_", " ");
+
+ devices.append (scan_device);
+ }
+
+ /* Sort devices by priority */
+ devices.sort (compare_devices);
+
+ need_redetect = false;
+ state = ScanState.IDLE;
+
+ if (devices != null)
+ {
+ var device = devices.nth_data (0);
+ default_device = device.name;
+ }
+ else
+ default_device = null;
+
+ notify (new NotifyUpdateDevices ((owned) devices));
+ }
+
+ private bool set_default_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index)
+ {
+ /* Check if supports automatic option */
+ if ((option.cap & Sane.Capability.AUTOMATIC) == 0)
+ return false;
+
+ var status = Sane.control_option (handle, option_index, Sane.Action.SET_AUTO, null, null);
+ debug ("sane_control_option (%d, SANE_ACTION_SET_AUTO) -> %s", option_index, Sane.status_to_string (status));
+ if (status != Sane.Status.GOOD)
+ warning ("Error setting default option %s: %s", option.name, Sane.strstatus(status));
+
+ return status == Sane.Status.GOOD;
+ }
+
+ private void set_bool_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, bool value, out bool result)
+ {
+ return_if_fail (option.type == Sane.ValueType.BOOL);
+
+ Sane.Bool v = (Sane.Bool) value;
+ var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v, null);
+ result = (bool) v;
+ debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %s) -> (%s, %s)", option_index, value ? "SANE_TRUE" : "SANE_FALSE", Sane.status_to_string (status), result ? "SANE_TRUE" : "SANE_FALSE");
+ }
+
+ private void set_int_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, int value, out int result)
+ {
+ return_if_fail (option.type == Sane.ValueType.INT);
+
+ Sane.Int v = (Sane.Int) value;
+ if (option.constraint_type == Sane.ConstraintType.RANGE)
+ {
+ if (option.constraint.range.quant != 0)
+ v *= option.constraint.range.quant;
+ if (v < option.constraint.range.min)
+ v = option.constraint.range.min;
+ if (v > option.constraint.range.max)
+ v = option.constraint.range.max;
+ }
+ else if (option.constraint_type == Sane.ConstraintType.WORD_LIST)
+ {
+ int distance = int.MAX, nearest = 0;
+
+ /* Find nearest value to requested */
+ for (var i = 0; i < option.constraint.word_list[0]; i++)
+ {
+ var x = (int) option.constraint.word_list[i+1];
+ var d = (x - v).abs ();
+ if (d < distance)
+ {
+ distance = d;
+ nearest = x;
+ }
+ }
+ v = (Sane.Int) nearest;
+ }
+
+ var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v, null);
+ debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %d) -> (%s, %d)", option_index, value, Sane.status_to_string (status), v);
+ result = v;
+ }
+
+ private void set_fixed_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, double value, out double result)
+ {
+ double v = value;
+ Sane.Fixed v_fixed;
+
+ return_if_fail (option.type == Sane.ValueType.FIXED);
+
+ if (option.constraint_type == Sane.ConstraintType.RANGE)
+ {
+ double min = Sane.UNFIX (option.constraint.range.min);
+ double max = Sane.UNFIX (option.constraint.range.max);
+
+ if (v < min)
+ v = min;
+ if (v > max)
+ v = max;
+ }
+ else if (option.constraint_type == Sane.ConstraintType.WORD_LIST)
+ {
+ double distance = double.MAX, nearest = 0.0;
+
+ /* Find nearest value to requested */
+ for (var i = 0; i < option.constraint.word_list[0]; i++)
+ {
+ double x = Sane.UNFIX (option.constraint.word_list[i+1]);
+ if (Math.fabs (x - v) < distance)
+ {
+ distance = Math.fabs (x - v);
+ nearest = x;
+ }
+ }
+ v = nearest;
+ }
+
+ v_fixed = Sane.FIX (v);
+ var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, &v_fixed, null);
+ debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, %f) -> (%s, %f)", option_index, value, Sane.status_to_string (status), Sane.UNFIX (v_fixed));
+
+ result = Sane.UNFIX (v_fixed);
+ }
+
+ private bool set_string_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, string value, out string result)
+ {
+ return_val_if_fail (option.type == Sane.ValueType.STRING, false);
+
+ var s = new char[option.size];
+ var i = 0;
+ for (; i < (option.size - 1) && value[i] != '\0'; i++)
+ s[i] = value[i];
+ s[i] = '\0';
+ var status = Sane.control_option (handle, option_index, Sane.Action.SET_VALUE, s, null);
+ result = (string) s;
+ debug ("sane_control_option (%d, SANE_ACTION_SET_VALUE, \"%s\") -> (%s, \"%s\")", option_index, value, Sane.status_to_string (status), result);
+
+ return status == Sane.Status.GOOD;
+ }
+
+ private bool set_constrained_string_option (Sane.Handle handle, Sane.OptionDescriptor option, Sane.Int option_index, string[] values, out string result)
+ {
+ return_val_if_fail (option.type == Sane.ValueType.STRING, false);
+ return_val_if_fail (option.constraint_type == Sane.ConstraintType.STRING_LIST, false);
+
+ for (var i = 0; values[i] != null; i++)
+ {
+ var j = 0;
+ for (; option.constraint.string_list[j] != null; j++)
+ {
+ if (values[i] == option.constraint.string_list[j])
+ break;
+ }
+
+ if (option.constraint.string_list[j] != null)
+ return set_string_option (handle, option, option_index, values[i], out result);
+ }
+
+ return false;
+ }
+
+ private void log_option (Sane.Int index, Sane.OptionDescriptor option)
+ {
+ var s = "Option %d:".printf (index);
+
+ if (option.name != "")
+ s += " name='%s'".printf (option.name);
+
+ if (option.title != "")
+ s += " title='%s'".printf (option.title);
+
+ switch (option.type)
+ {
+ case Sane.ValueType.BOOL:
+ s += " type=bool";
+ break;
+ case Sane.ValueType.INT:
+ s += " type=int";
+ break;
+ case Sane.ValueType.FIXED:
+ s += " type=fixed";
+ break;
+ case Sane.ValueType.STRING:
+ s += " type=string";
+ break;
+ case Sane.ValueType.BUTTON:
+ s += " type=button";
+ break;
+ case Sane.ValueType.GROUP:
+ s += " type=group";
+ break;
+ default:
+ s += " type=%d".printf (option.type);
+ break;
+ }
+
+ s += " size=%d".printf (option.size);
+
+ switch (option.unit)
+ {
+ case Sane.Unit.NONE:
+ break;
+ case Sane.Unit.PIXEL:
+ s += " unit=pixels";
+ break;
+ case Sane.Unit.BIT:
+ s += " unit=bits";
+ break;
+ case Sane.Unit.MM:
+ s += " unit=mm";
+ break;
+ case Sane.Unit.DPI:
+ s += " unit=dpi";
+ break;
+ case Sane.Unit.PERCENT:
+ s += " unit=percent";
+ break;
+ case Sane.Unit.MICROSECOND:
+ s += " unit=microseconds";
+ break;
+ default:
+ s += " unit=%d".printf (option.unit);
+ break;
+ }
+
+ switch (option.constraint_type)
+ {
+ case Sane.ConstraintType.RANGE:
+ if (option.type == Sane.ValueType.FIXED)
+ s += " min=%f, max=%f, quant=%d".printf (Sane.UNFIX (option.constraint.range.min), Sane.UNFIX (option.constraint.range.max), option.constraint.range.quant);
+ else
+ s += " min=%d, max=%d, quant=%d".printf (option.constraint.range.min, option.constraint.range.max, option.constraint.range.quant);
+ break;
+ case Sane.ConstraintType.WORD_LIST:
+ s += " values=[";
+ for (var i = 0; i < option.constraint.word_list[0]; i++)
+ {
+ if (i != 0)
+ s += ", ";
+ if (option.type == Sane.ValueType.INT)
+ s += "%d".printf (option.constraint.word_list[i+1]);
+ else
+ s += "%f".printf (Sane.UNFIX (option.constraint.word_list[i+1]));
+ }
+ s += "]";
+ break;
+ case Sane.ConstraintType.STRING_LIST:
+ s += " values=[";
+ for (var i = 0; option.constraint.string_list[i] != null; i++)
+ {
+ if (i != 0)
+ s += ", ";
+ s += "\"%s\"".printf (option.constraint.string_list[i]);
+ }
+ s += "]";
+ break;
+ default:
+ break;
+ }
+
+ var cap = option.cap;
+ if (cap != 0)
+ {
+ s += " cap=";
+ if ((cap & Sane.Capability.SOFT_SELECT) != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "soft-select";
+ cap &= ~Sane.Capability.SOFT_SELECT;
+ }
+ if ((cap & Sane.Capability.HARD_SELECT) != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "hard-select";
+ cap &= ~Sane.Capability.HARD_SELECT;
+ }
+ if ((cap & Sane.Capability.SOFT_DETECT) != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "soft-detect";
+ cap &= ~Sane.Capability.SOFT_DETECT;
+ }
+ if ((cap & Sane.Capability.EMULATED) != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "emulated";
+ cap &= ~Sane.Capability.EMULATED;
+ }
+ if ((cap & Sane.Capability.AUTOMATIC) != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "automatic";
+ cap &= ~Sane.Capability.AUTOMATIC;
+ }
+ if ((cap & Sane.Capability.INACTIVE) != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "inactive";
+ cap &= ~Sane.Capability.INACTIVE;
+ }
+ if ((cap & Sane.Capability.ADVANCED) != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "advanced";
+ cap &= ~Sane.Capability.ADVANCED;
+ }
+ /* Unknown capabilities */
+ if (cap != 0)
+ {
+ if (s != "")
+ s += ",";
+ s += "%x".printf (cap);
+ }
+ }
+
+ debug ("%s", s);
+
+ if (option.desc != null)
+ debug (" Description: %s", option.desc);
+ }
+
+ private static void authorization_cb (string resource, char[] username, char[] password)
+ {
+ scanner_object.notify (new NotifyRequestAuthorization (resource));
+
+ var credentials = scanner_object.authorize_queue.pop ();
+ for (var i = 0; credentials.username[i] != '\0' && i < Sane.MAX_USERNAME_LEN; i++)
+ username[i] = credentials.username[i];
+ for (var i = 0; credentials.password[i] != '\0' && i < Sane.MAX_PASSWORD_LEN; i++)
+ password[i] = credentials.password[i];
+ }
+
+ public void authorize (string username, string password)
+ {
+ var credentials = new Credentials ();
+ credentials.username = username;
+ credentials.password = password;
+ authorize_queue.push (credentials);
+ }
+
+ private void close_device ()
+ {
+ if (have_handle)
+ {
+ Sane.cancel (handle);
+ debug ("sane_cancel ()");
+
+ Sane.close (handle);
+ debug ("sane_close ()");
+ have_handle = false;
+ }
+
+ buffer = null;
+ job_queue = null;
+
+ set_scanning (false);
+ }
+
+ private void fail_scan (int error_code, string error_string)
+ {
+ close_device ();
+ state = ScanState.IDLE;
+ notify (new NotifyScanFailed (error_code, error_string));
+ }
+
+ private bool handle_requests ()
+ {
+ /* Redetect when idle */
+ if (state == ScanState.IDLE && need_redetect)
+ state = ScanState.REDETECT;
+
+ /* Process all requests */
+ int request_count = 0;
+ while (true)
+ {
+ Request request;
+ if ((state == ScanState.IDLE && request_count == 0) ||
+ request_queue.length () > 0)
+ request = request_queue.pop ();
+ else
+ return true;
+
+ debug ("Processing request");
+ request_count++;
+
+ if (request is RequestStartScan)
+ {
+ var r = (RequestStartScan) request;
+ job_queue.append (r.job);
+ }
+ else if (request is RequestCancel)
+ {
+ fail_scan (Sane.Status.CANCELLED, "Scan cancelled - do not report this error");
+ }
+ else if (request is RequestQuit)
+ {
+ close_device ();
+ return false;
+ }
+ }
+ }
+
+ private void do_open ()
+ {
+ var job = (ScanJob) job_queue.data;
+
+ line_count = 0;
+ pass_number = 0;
+ page_number = 0;
+ notified_page = -1;
+ option_index = 0;
+ br_x_option_index = 0;
+ br_y_option_index = 0;
+
+ if (job.device == null && default_device != null)
+ job.device = default_device;
+
+ if (job.device == null)
+ {
+ warning ("No scan device available");
+ fail_scan (0,
+ /* Error displayed when no scanners to scan with */
+ _("No scanners available. Please connect a scanner."));
+ return;
+ }
+
+ /* See if we can use the already open device */
+ if (have_handle)
+ {
+ if (current_device == job.device)
+ {
+ state = ScanState.GET_OPTION;
+ return;
+ }
+
+ Sane.close (handle);
+ debug ("sane_close ()");
+ have_handle = false;
+ }
+
+ current_device = null;
+
+ have_handle = false;
+ var status = Sane.open (job.device, out handle);
+ debug ("sane_open (\"%s\") -> %s", job.device, Sane.status_to_string (status));
+
+ if (status != Sane.Status.GOOD)
+ {
+ warning ("Unable to get open device: %s", Sane.strstatus (status));
+ fail_scan (status,
+ /* Error displayed when cannot connect to scanner */
+ _("Unable to connect to scanner"));
+ return;
+ }
+ have_handle = true;
+
+ current_device = job.device;
+ state = ScanState.GET_OPTION;
+ }
+
+ private void do_get_option ()
+ {
+ var job = (ScanJob) job_queue.data;
+
+ var option = Sane.get_option_descriptor (handle, option_index);
+ debug ("sane_get_option_descriptor (%d)", option_index);
+ var index = option_index;
+ option_index++;
+
+ if (option == null)
+ {
+ /* Always use maximum scan area - some scanners default to using partial areas. This should be patched in sane-backends */
+ if (br_x_option_index != 0)
+ {
+ option = Sane.get_option_descriptor (handle, br_x_option_index);
+ debug ("sane_get_option_descriptor (%d)", br_x_option_index);
+ if (option.constraint_type == Sane.ConstraintType.RANGE)
+ {
+ if (option.type == Sane.ValueType.FIXED)
+ set_fixed_option (handle, option, br_x_option_index, Sane.UNFIX (option.constraint.range.max), null);
+ else
+ set_int_option (handle, option, br_x_option_index, option.constraint.range.max, null);
+ }
+ }
+ if (br_y_option_index != 0)
+ {
+ option = Sane.get_option_descriptor (handle, br_y_option_index);
+ debug ("sane_get_option_descriptor (%d)", br_y_option_index);
+ if (option.constraint_type == Sane.ConstraintType.RANGE)
+ {
+ if (option.type == Sane.ValueType.FIXED)
+ set_fixed_option (handle, option, br_y_option_index, Sane.UNFIX (option.constraint.range.max), null);
+ else
+ set_int_option (handle, option, br_y_option_index, option.constraint.range.max, null);
+ }
+ }
+
+ state = ScanState.START;
+ return;
+ }
+
+ log_option (index, option);
+
+ /* Ignore groups */
+ if (option.type == Sane.ValueType.GROUP)
+ return;
+
+ /* Option disabled */
+ if ((option.cap & Sane.Capability.INACTIVE) != 0)
+ return;
+
+ /* Some options are unnammed (e.g. Option 0) */
+ if (option.name == null)
+ return;
+
+ if (option.name == Sane.NAME_SCAN_RESOLUTION)
+ {
+ if (option.type == Sane.ValueType.FIXED)
+ set_fixed_option (handle, option, index, job.dpi, out job.dpi);
+ else
+ {
+ int dpi;
+ set_int_option (handle, option, index, (int) job.dpi, out dpi);
+ job.dpi = dpi;
+ }
+ }
+ else if (option.name == Sane.NAME_SCAN_SOURCE)
+ {
+ string[] flatbed_sources =
+ {
+ "Auto",
+ Sane.I18N ("Auto"),
+ "Flatbed",
+ Sane.I18N ("Flatbed"),
+ "FlatBed",
+ "Normal",
+ Sane.I18N ("Normal")
+ };
+
+ string[] adf_sources =
+ {
+ "Automatic Document Feeder",
+ Sane.I18N ("Automatic Document Feeder"),
+ "ADF",
+ "Automatic Document Feeder(left aligned)", /* Seen in the proprietary brother3 driver */
+ "Automatic Document Feeder(centrally aligned)" /* Seen in the proprietary brother3 driver */
+ };
+
+ string[] adf_front_sources =
+ {
+ "ADF Front",
+ Sane.I18N ("ADF Front")
+ };
+
+ string[] adf_back_sources =
+ {
+ "ADF Back",
+ Sane.I18N ("ADF Back")
+ };
+
+ string[] adf_duplex_sources =
+ {
+ "ADF Duplex",
+ Sane.I18N ("ADF Duplex")
+ };
+
+ switch (job.type)
+ {
+ case ScanType.SINGLE:
+ if (!set_default_option (handle, option, index))
+ if (!set_constrained_string_option (handle, option, index, flatbed_sources, null))
+ warning ("Unable to set single page source, please file a bug");
+ break;
+ case ScanType.ADF_FRONT:
+ if (!set_constrained_string_option (handle, option, index, adf_front_sources, null))
+ if (!!set_constrained_string_option (handle, option, index, adf_sources, null))
+ warning ("Unable to set front ADF source, please file a bug");
+ break;
+ case ScanType.ADF_BACK:
+ if (!set_constrained_string_option (handle, option, index, adf_back_sources, null))
+ if (!set_constrained_string_option (handle, option, index, adf_sources, null))
+ warning ("Unable to set back ADF source, please file a bug");
+ break;
+ case ScanType.ADF_BOTH:
+ if (!set_constrained_string_option (handle, option, index, adf_duplex_sources, null))
+ if (!set_constrained_string_option (handle, option, index, adf_sources, null))
+ warning ("Unable to set duplex ADF source, please file a bug");
+ break;
+ }
+ }
+ else if (option.name == "duplex")
+ {
+ if (option.type == Sane.ValueType.BOOL)
+ set_bool_option (handle, option, index, job.type == ScanType.ADF_BOTH, null);
+ }
+ else if (option.name == "batch-scan")
+ {
+ if (option.type == Sane.ValueType.BOOL)
+ set_bool_option (handle, option, index, job.type != ScanType.SINGLE, null);
+ }
+ else if (option.name == Sane.NAME_BIT_DEPTH)
+ {
+ if (job.depth > 0)
+ set_int_option (handle, option, index, job.depth, null);
+ }
+ else if (option.name == Sane.NAME_SCAN_MODE)
+ {
+ /* The names of scan modes often used in drivers, as taken from the sane-backends source */
+ string[] color_scan_modes =
+ {
+ Sane.VALUE_SCAN_MODE_COLOR,
+ "Color",
+ "24bit Color" /* Seen in the proprietary brother3 driver */
+ };
+ string[] gray_scan_modes =
+ {
+ Sane.VALUE_SCAN_MODE_GRAY,
+ "Gray",
+ "Grayscale",
+ Sane.I18N ("Grayscale"),
+ "True Gray" /* Seen in the proprietary brother3 driver */
+ };
+ string[] lineart_scan_modes =
+ {
+ Sane.VALUE_SCAN_MODE_LINEART,
+ "Lineart",
+ "LineArt",
+ Sane.I18N ("LineArt"),
+ "Black & White",
+ Sane.I18N ("Black & White"),
+ "Binary",
+ Sane.I18N ("Binary"),
+ "Thresholded",
+ Sane.VALUE_SCAN_MODE_GRAY,
+ "Gray",
+ "Grayscale",
+ Sane.I18N ("Grayscale"),
+ "True Gray" /* Seen in the proprietary brother3 driver */
+ };
+
+ switch (job.scan_mode)
+ {
+ case ScanMode.COLOR:
+ if (!set_constrained_string_option (handle, option, index, color_scan_modes, null))
+ warning ("Unable to set Color mode, please file a bug");
+ break;
+ case ScanMode.GRAY:
+ if (!set_constrained_string_option (handle, option, index, gray_scan_modes, null))
+ warning ("Unable to set Gray mode, please file a bug");
+ break;
+ case ScanMode.LINEART:
+ if (!set_constrained_string_option (handle, option, index, lineart_scan_modes, null))
+ warning ("Unable to set Lineart mode, please file a bug");
+ break;
+ default:
+ break;
+ }
+ }
+ /* Disable compression, we will compress after scanning */
+ else if (option.name == "compression")
+ {
+ string[] disable_compression_names =
+ {
+ Sane.I18N ("None"),
+ Sane.I18N ("none"),
+ "None",
+ "none"
+ };
+
+ if (!set_constrained_string_option (handle, option, index, disable_compression_names, null))
+ warning ("Unable to disable compression, please file a bug");
+ }
+ else if (option.name == Sane.NAME_SCAN_BR_X)
+ br_x_option_index = index;
+ else if (option.name == Sane.NAME_SCAN_BR_Y)
+ br_y_option_index = index;
+ else if (option.name == Sane.NAME_PAGE_WIDTH)
+ {
+ if (job.page_width > 0.0)
+ {
+ if (option.type == Sane.ValueType.FIXED)
+ set_fixed_option (handle, option, index, job.page_width / 10.0, null);
+ else
+ set_int_option (handle, option, index, job.page_width / 10, null);
+ }
+ }
+ else if (option.name == Sane.NAME_PAGE_HEIGHT)
+ {
+ if (job.page_height > 0.0)
+ {
+ if (option.type == Sane.ValueType.FIXED)
+ set_fixed_option (handle, option, index, job.page_height / 10.0, null);
+ else
+ set_int_option (handle, option, index, job.page_height / 10, null);
+ }
+ }
+
+ /* Test scanner options (hoping will not effect other scanners...) */
+ if (current_device == "test")
+ {
+ if (option.name == "hand-scanner")
+ set_bool_option (handle, option, index, false, null);
+ else if (option.name == "three-pass")
+ set_bool_option (handle, option, index, false, null);
+ else if (option.name == "test-picture")
+ set_string_option (handle, option, index, "Color pattern", null);
+ else if (option.name == "read-delay")
+ set_bool_option (handle, option, index, true, null);
+ else if (option.name == "read-delay-duration")
+ set_int_option (handle, option, index, 200000, null);
+ }
+ }
+
+ private void do_complete_document ()
+ {
+ job_queue.remove_link (job_queue);
+
+ state = ScanState.IDLE;
+
+ /* Continue onto the next job */
+ if (job_queue != null)
+ {
+ state = ScanState.OPEN;
+ return;
+ }
+
+ /* Trigger timeout to close */
+ // TODO
+
+ notify (new NotifyDocumentDone ());
+ set_scanning (false);
+ }
+
+ private void do_start ()
+ {
+ Sane.Status status;
+
+ notify (new NotifyExpectPage ());
+
+ status = Sane.start (handle);
+ debug ("sane_start (page=%d, pass=%d) -> %s", page_number, pass_number, Sane.status_to_string (status));
+ if (status == Sane.Status.GOOD)
+ state = ScanState.GET_PARAMETERS;
+ else if (status == Sane.Status.NO_DOCS)
+ do_complete_document ();
+ else
+ {
+ warning ("Unable to start device: %s", Sane.strstatus (status));
+ fail_scan (status,
+ /* Error display when unable to start scan */
+ _("Unable to start scan"));
+ }
+ }
+
+ private void do_get_parameters ()
+ {
+ var status = Sane.get_parameters (handle, out parameters);
+ debug ("sane_get_parameters () -> %s", Sane.status_to_string (status));
+ if (status != Sane.Status.GOOD)
+ {
+ warning ("Unable to get device parameters: %s", Sane.strstatus (status));
+ fail_scan (status,
+ /* Error displayed when communication with scanner broken */
+ _("Error communicating with scanner"));
+ return;
+ }
+
+ var job = (ScanJob) job_queue.data;
+
+ debug ("Parameters: format=%s last_frame=%s bytes_per_line=%d pixels_per_line=%d lines=%d depth=%d",
+ Sane.frame_to_string (parameters.format),
+ parameters.last_frame ? "SANE_TRUE" : "SANE_FALSE",
+ parameters.bytes_per_line,
+ parameters.pixels_per_line,
+ parameters.lines,
+ parameters.depth);
+
+ var info = new ScanPageInfo ();
+ info.width = parameters.pixels_per_line;
+ info.height = parameters.lines;
+ info.depth = parameters.depth;
+ /* Reduce bit depth if requested lower than received */
+ // FIXME: This a hack and only works on 8 bit gray to 2 bit gray
+ if (parameters.depth == 8 && parameters.format == Sane.Frame.GRAY && job.depth == 2 && job.scan_mode == ScanMode.GRAY)
+ info.depth = job.depth;
+ info.n_channels = parameters.format == Sane.Frame.GRAY ? 1 : 3;
+ info.dpi = job.dpi; // FIXME: This is the requested DPI, not the actual DPI
+ info.device = current_device;
+
+ if (page_number != notified_page)
+ {
+ notify (new NotifyGotPageInfo (info));
+ notified_page = page_number;
+ }
+
+ /* Prepare for read */
+ var buffer_size = parameters.bytes_per_line + 1; /* Use +1 so buffer is not resized if driver returns one line per read */
+ buffer = new uchar[buffer_size];
+ n_used = 0;
+ line_count = 0;
+ pass_number = 0;
+ state = ScanState.READ;
+ }
+
+ private void do_complete_page ()
+ {
+ notify (new NotifyPageDone ());
+
+ var job = (ScanJob) job_queue.data;
+
+ /* If multi-pass then scan another page */
+ if (!parameters.last_frame)
+ {
+ pass_number++;
+ state = ScanState.START;
+ return;
+ }
+
+ /* Go back for another page */
+ if (job.type != ScanType.SINGLE)
+ {
+ page_number++;
+ pass_number = 0;
+ notify (new NotifyPageDone ());
+ state = ScanState.START;
+ return;
+ }
+
+ Sane.cancel (handle);
+ debug ("sane_cancel ()");
+
+ do_complete_document ();
+ }
+
+ private void do_read ()
+ {
+ var job = (ScanJob) job_queue.data;
+
+ /* Read as many bytes as we expect */
+ var n_to_read = buffer.length - n_used;
+
+ Sane.Int n_read;
+ var b = (uchar *) buffer;
+ var status = Sane.read (handle, (uint8[]) (b + n_used), (Sane.Int) n_to_read, out n_read);
+ debug ("sane_read (%d) -> (%s, %d)", n_to_read, Sane.status_to_string (status), n_read);
+
+ /* Completed read */
+ if (status == Sane.Status.EOF)
+ {
+ if (parameters.lines > 0 && line_count != parameters.lines)
+ warning ("Scan completed with %d lines, expected %d lines", parameters.lines, parameters.lines);
+ if (n_used > 0)
+ warning ("Scan complete with %d bytes of unused data", n_used);
+ do_complete_page ();
+ return;
+ }
+
+ /* Communication error */
+ if (status != Sane.Status.GOOD)
+ {
+ warning ("Unable to read frame from device: %s", Sane.strstatus (status));
+ fail_scan (status,
+ /* Error displayed when communication with scanner broken */
+ _("Error communicating with scanner"));
+ return;
+ }
+
+ bool full_read = false;
+ if (n_used == 0 && n_read == buffer.length)
+ full_read = true;
+ n_used += n_read;
+
+ /* Feed out lines */
+ if (n_used >= parameters.bytes_per_line)
+ {
+ var line = new ScanLine ();
+ switch (parameters.format)
+ {
+ case Sane.Frame.GRAY:
+ line.channel = 0;
+ break;
+ case Sane.Frame.RGB:
+ line.channel = -1;
+ break;
+ case Sane.Frame.RED:
+ line.channel = 0;
+ break;
+ case Sane.Frame.GREEN:
+ line.channel = 1;
+ break;
+ case Sane.Frame.BLUE:
+ line.channel = 2;
+ break;
+ }
+ line.width = parameters.pixels_per_line;
+ line.depth = parameters.depth;
+ line.data = (owned) buffer;
+ line.data_length = parameters.bytes_per_line;
+ line.number = line_count;
+ line.n_lines = n_used / line.data_length;
+
+ line_count += line.n_lines;
+
+ /* Increase buffer size if did full read */
+ var buffer_size = buffer.length;
+ if (full_read)
+ buffer_size += parameters.bytes_per_line;
+
+ buffer = new uchar[buffer_size];
+ var n_remaining = n_used - (line.n_lines * line.data_length);
+ n_used = 0;
+ for (var i = 0; i < n_remaining; i++)
+ {
+ buffer[i] = line.data[i + (line.n_lines * line.data_length)];
+ n_used++;
+ }
+
+ /* Reduce bit depth if requested lower than received */
+ // FIXME: This a hack and only works on 8 bit gray to 2 bit gray
+ if (parameters.depth == 8 && parameters.format == Sane.Frame.GRAY &&
+ job.depth == 2 && job.scan_mode == ScanMode.GRAY)
+ {
+ uchar block = 0;
+ var write_offset = 0;
+ var block_shift = 6;
+ for (var i = 0; i < line.n_lines; i++)
+ {
+ var offset = i * line.data_length;
+ for (var x = 0; x < line.width; x++)
+ {
+ var p = line.data[offset + x];
+
+ uchar sample;
+ if (p >= 192)
+ sample = 3;
+ else if (p >= 128)
+ sample = 2;
+ else if (p >= 64)
+ sample = 1;
+ else
+ sample = 0;
+
+ block |= sample << block_shift;
+ if (block_shift == 0)
+ {
+ line.data[write_offset] = block;
+ write_offset++;
+ block = 0;
+ block_shift = 6;
+ }
+ else
+ block_shift -= 2;
+ }
+
+ /* Finish each line on a byte boundary */
+ if (block_shift != 6)
+ {
+ line.data[write_offset] = block;
+ write_offset++;
+ block = 0;
+ block_shift = 6;
+ }
+ }
+
+ line.data_length = (line.width * 2 + 7) / 8;
+ }
+
+ notify (new NotifyGotLine (line));
+ }
+ }
+
+ private void* scan_thread ()
+ {
+ state = ScanState.IDLE;
+
+ Sane.Int version_code;
+ var status = Sane.init (out version_code, authorization_cb);
+ debug ("sane_init () -> %s", Sane.status_to_string (status));
+ if (status != Sane.Status.GOOD)
+ {
+ warning ("Unable to initialize SANE backend: %s", Sane.strstatus(status));
+ return null;
+ }
+ debug ("SANE version %d.%d.%d",
+ Sane.VERSION_MAJOR(version_code),
+ Sane.VERSION_MINOR(version_code),
+ Sane.VERSION_BUILD(version_code));
+
+ /* Scan for devices on first start */
+ redetect ();
+
+ while (handle_requests ())
+ {
+ switch (state)
+ {
+ case ScanState.IDLE:
+ if (job_queue != null)
+ {
+ set_scanning (true);
+ state = ScanState.OPEN;
+ }
+ break;
+ case ScanState.REDETECT:
+ do_redetect ();
+ break;
+ case ScanState.OPEN:
+ do_open ();
+ break;
+ case ScanState.GET_OPTION:
+ do_get_option ();
+ break;
+ case ScanState.START:
+ do_start ();
+ break;
+ case ScanState.GET_PARAMETERS:
+ do_get_parameters ();
+ break;
+ case ScanState.READ:
+ do_read ();
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ public void start ()
+ {
+ try
+ {
+ thread = Thread.create<void*> (scan_thread, true);
+ }
+ catch (Error e)
+ {
+ critical ("Unable to create thread: %s", e.message);
+ }
+ }
+
+ public void redetect ()
+ {
+ if (need_redetect)
+ return;
+ need_redetect = true;
+
+ debug ("Requesting redetection of scan devices");
+
+ request_queue.push (new RequestRedetect ());
+ }
+
+ public bool is_scanning ()
+ {
+ return scanning;
+ }
+
+ private string get_scan_mode_string (ScanMode mode)
+ {
+ switch (mode)
+ {
+ case ScanMode.DEFAULT:
+ return "ScanMode.DEFAULT";
+ case ScanMode.COLOR:
+ return "ScanMode.COLOR";
+ case ScanMode.GRAY:
+ return "ScanMode.GRAY";
+ case ScanMode.LINEART:
+ return "ScanMode.LINEART";
+ default:
+ return "%d".printf (mode);
+ }
+ }
+
+ private string get_scan_type_string (ScanType type)
+ {
+ switch (type)
+ {
+ case ScanType.SINGLE:
+ return "ScanType.SINGLE";
+ case ScanType.ADF_FRONT:
+ return "ScanType.ADF_FRONT";
+ case ScanType.ADF_BACK:
+ return "ScanType.ADF_BACK";
+ case ScanType.ADF_BOTH:
+ return "ScanType.ADF_BOTH";
+ default:
+ return "%d".printf (type);
+ }
+ }
+
+ public void scan (string? device, ScanOptions options)
+ {
+ debug ("Scanner.scan (\"%s\", dpi=%d, scan_mode=%s, depth=%d, type=%s, paper_width=%d, paper_height=%d)",
+ device != null ? device : "(null)", options.dpi, get_scan_mode_string (options.scan_mode), options.depth,
+ get_scan_type_string (options.type), options.paper_width, options.paper_height);
+ var request = new RequestStartScan ();
+ request.job = new ScanJob ();
+ request.job.device = device;
+ request.job.dpi = options.dpi;
+ request.job.scan_mode = options.scan_mode;
+ request.job.depth = options.depth;
+ request.job.type = options.type;
+ request.job.page_width = options.paper_width;
+ request.job.page_height = options.paper_height;
+ request_queue.push (request);
+ }
+
+ public void cancel ()
+ {
+ request_queue.push (new RequestCancel ());
+ }
+
+ public void free ()
+ {
+ debug ("Stopping scan thread");
+
+ request_queue.push (new RequestQuit ());
+
+ if (thread != null)
+ thread.join ();
+
+ Sane.exit ();
+ debug ("sane_exit ()");
+ }
+}
diff --git a/src/simple-scan.c b/src/simple-scan.c
index bb7e036..1f1f599 100644
--- a/src/simple-scan.c
+++ b/src/simple-scan.c
@@ -1,7 +1,10 @@
+/* simple-scan.c generated by valac 0.13.1, the Vala compiler
+ * generated from simple-scan.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,608 +12,1507 @@
* license.
*/
-#include <stdlib.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <gudev/gudev.h>
#include <stdio.h>
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
+#include <stdlib.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <sane/sane.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
#include <unistd.h>
-#include <gudev/gudev.h>
-#include <dbus/dbus-glib.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <locale.h>
+#include <config.h>
+#include <gobject/gvaluecollector.h>
+
+
+#define TYPE_APPLICATION (application_get_type ())
+#define APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_APPLICATION, Application))
+#define APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_APPLICATION, ApplicationClass))
+#define IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_APPLICATION))
+#define IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_APPLICATION))
+#define APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_APPLICATION, ApplicationClass))
+
+typedef struct _Application Application;
+typedef struct _ApplicationClass ApplicationClass;
+typedef struct _ApplicationPrivate ApplicationPrivate;
+
+#define TYPE_SCAN_DEVICE (scan_device_get_type ())
+#define SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_DEVICE, ScanDevice))
+#define SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_DEVICE, ScanDeviceClass))
+#define IS_SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_DEVICE))
+#define IS_SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_DEVICE))
+#define SCAN_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_DEVICE, ScanDeviceClass))
+
+typedef struct _ScanDevice ScanDevice;
+typedef struct _ScanDeviceClass ScanDeviceClass;
+
+#define TYPE_SIMPLE_SCAN (simple_scan_get_type ())
+#define SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SIMPLE_SCAN, SimpleScan))
+#define SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SIMPLE_SCAN, SimpleScanClass))
+#define IS_SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SIMPLE_SCAN))
+#define IS_SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SIMPLE_SCAN))
+#define SIMPLE_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SIMPLE_SCAN, SimpleScanClass))
+
+typedef struct _SimpleScan SimpleScan;
+typedef struct _SimpleScanClass SimpleScanClass;
+
+#define TYPE_SCANNER (scanner_get_type ())
+#define SCANNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCANNER, Scanner))
+#define SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCANNER, ScannerClass))
+#define IS_SCANNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCANNER))
+#define IS_SCANNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCANNER))
+#define SCANNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCANNER, ScannerClass))
+
+typedef struct _Scanner Scanner;
+typedef struct _ScannerClass ScannerClass;
+
+#define TYPE_BOOK (book_get_type ())
+#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book))
+#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass))
+#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK))
+#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK))
+#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass))
+
+typedef struct _Book Book;
+typedef struct _BookClass BookClass;
+#define _scan_device_unref0(var) ((var == NULL) ? NULL : (var = (scan_device_unref (var), NULL)))
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _simple_scan_unref0(var) ((var == NULL) ? NULL : (var = (simple_scan_unref (var), NULL)))
+#define _scanner_unref0(var) ((var == NULL) ? NULL : (var = (scanner_unref (var), NULL)))
+#define _book_unref0(var) ((var == NULL) ? NULL : (var = (book_unref (var), NULL)))
+
+#define TYPE_SCAN_OPTIONS (scan_options_get_type ())
+#define SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_OPTIONS, ScanOptions))
+#define SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_OPTIONS, ScanOptionsClass))
+#define IS_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_OPTIONS))
+#define IS_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_OPTIONS))
+#define SCAN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_OPTIONS, ScanOptionsClass))
+
+typedef struct _ScanOptions ScanOptions;
+typedef struct _ScanOptionsClass ScanOptionsClass;
+
+#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;
+
+#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 _ScanDevicePrivate ScanDevicePrivate;
+#define __g_list_free__scan_device_unref0_0(var) ((var == NULL) ? NULL : (var = (_g_list_free__scan_device_unref0_ (var), NULL)))
+#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+
+#define TYPE_PAGE (page_get_type ())
+#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page))
+#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass))
+#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE))
+#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE))
+#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass))
+
+typedef struct _Page Page;
+typedef struct _PageClass PageClass;
+
+#define TYPE_SCAN_DIRECTION (scan_direction_get_type ())
+#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL)))
+typedef struct _ScanPageInfoPrivate ScanPageInfoPrivate;
+typedef struct _ScanOptionsPrivate ScanOptionsPrivate;
+
+#define TYPE_SCAN_MODE (scan_mode_get_type ())
+
+#define TYPE_SCAN_TYPE (scan_type_get_type ())
+#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
+#define _g_option_context_free0(var) ((var == NULL) ? NULL : (var = (g_option_context_free (var), NULL)))
+#define _g_timer_destroy0(var) ((var == NULL) ? NULL : (var = (g_timer_destroy (var), NULL)))
+#define _fclose0(var) ((var == NULL) ? NULL : (var = (fclose (var), NULL)))
+#define _application_unref0(var) ((var == NULL) ? NULL : (var = (application_unref (var), NULL)))
+typedef struct _ParamSpecApplication ParamSpecApplication;
+
+struct _Application {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ApplicationPrivate * priv;
+};
+
+struct _ApplicationClass {
+ GTypeClass parent_class;
+ void (*finalize) (Application *self);
+};
+
+struct _ApplicationPrivate {
+ ScanDevice* default_device;
+ gboolean have_devices;
+ GUdevClient* udev_client;
+ SimpleScan* ui;
+ Scanner* scanner;
+ Book* book;
+};
+
+struct _ScanDevice {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanDevicePrivate * priv;
+ gchar* name;
+ gchar* label;
+};
+
+struct _ScanDeviceClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanDevice *self);
+};
+
+typedef enum {
+ SCAN_DIRECTION_TOP_TO_BOTTOM,
+ SCAN_DIRECTION_LEFT_TO_RIGHT,
+ SCAN_DIRECTION_BOTTOM_TO_TOP,
+ SCAN_DIRECTION_RIGHT_TO_LEFT
+} ScanDirection;
+
+struct _ScanPageInfo {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanPageInfoPrivate * priv;
+ gint width;
+ gint height;
+ gint depth;
+ gint n_channels;
+ gdouble dpi;
+ gchar* device;
+};
+
+struct _ScanPageInfoClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanPageInfo *self);
+};
+
+typedef enum {
+ SCAN_MODE_DEFAULT,
+ SCAN_MODE_COLOR,
+ SCAN_MODE_GRAY,
+ SCAN_MODE_LINEART
+} ScanMode;
+
+typedef enum {
+ SCAN_TYPE_SINGLE,
+ SCAN_TYPE_ADF_FRONT,
+ SCAN_TYPE_ADF_BACK,
+ SCAN_TYPE_ADF_BOTH
+} ScanType;
+
+struct _ScanOptions {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanOptionsPrivate * priv;
+ gint dpi;
+ ScanMode scan_mode;
+ gint depth;
+ ScanType type;
+ gint paper_width;
+ gint paper_height;
+};
+
+struct _ScanOptionsClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanOptions *self);
+};
+
+struct _ParamSpecApplication {
+ GParamSpec parent_instance;
+};
+
+
+static gpointer application_parent_class = NULL;
+static gboolean application_show_version;
+static gboolean application_show_version = FALSE;
+static gboolean application_debug_enabled;
+static gboolean application_debug_enabled = FALSE;
+static GTimer* application_log_timer;
+static GTimer* application_log_timer = NULL;
+static FILE* application_log_file;
+static FILE* application_log_file = NULL;
+
+gpointer application_ref (gpointer instance);
+void application_unref (gpointer instance);
+GParamSpec* param_spec_application (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_application (GValue* value, gpointer v_object);
+void value_take_application (GValue* value, gpointer v_object);
+gpointer value_get_application (const GValue* value);
+GType application_get_type (void) G_GNUC_CONST;
+gpointer scan_device_ref (gpointer instance);
+void scan_device_unref (gpointer instance);
+GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scan_device (GValue* value, gpointer v_object);
+void value_take_scan_device (GValue* value, gpointer v_object);
+gpointer value_get_scan_device (const GValue* value);
+GType scan_device_get_type (void) G_GNUC_CONST;
+gpointer simple_scan_ref (gpointer instance);
+void simple_scan_unref (gpointer instance);
+GParamSpec* param_spec_simple_scan (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_simple_scan (GValue* value, gpointer v_object);
+void value_take_simple_scan (GValue* value, gpointer v_object);
+gpointer value_get_simple_scan (const GValue* value);
+GType simple_scan_get_type (void) G_GNUC_CONST;
+gpointer scanner_ref (gpointer instance);
+void scanner_unref (gpointer instance);
+GParamSpec* param_spec_scanner (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scanner (GValue* value, gpointer v_object);
+void value_take_scanner (GValue* value, gpointer v_object);
+gpointer value_get_scanner (const GValue* value);
+GType scanner_get_type (void) G_GNUC_CONST;
+gpointer book_ref (gpointer instance);
+void book_unref (gpointer instance);
+GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_book (GValue* value, gpointer v_object);
+void value_take_book (GValue* value, gpointer v_object);
+gpointer value_get_book (const GValue* value);
+GType book_get_type (void) G_GNUC_CONST;
+#define APPLICATION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_APPLICATION, ApplicationPrivate))
+enum {
+ APPLICATION_DUMMY_PROPERTY
+};
+Application* application_new (ScanDevice* device);
+Application* application_construct (GType object_type, ScanDevice* device);
+SimpleScan* simple_scan_new (void);
+SimpleScan* simple_scan_construct (GType object_type);
+Book* simple_scan_get_book (SimpleScan* self);
+gpointer scan_options_ref (gpointer instance);
+void scan_options_unref (gpointer instance);
+GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scan_options (GValue* value, gpointer v_object);
+void value_take_scan_options (GValue* value, gpointer v_object);
+gpointer value_get_scan_options (const GValue* value);
+GType scan_options_get_type (void) G_GNUC_CONST;
+static void application_scan_cb (Application* self, SimpleScan* ui, const gchar* device, ScanOptions* options);
+static void _application_scan_cb_simple_scan_start_scan (SimpleScan* _sender, const gchar* device, ScanOptions* options, gpointer self);
+static void application_cancel_cb (Application* self, SimpleScan* ui);
+static void _application_cancel_cb_simple_scan_stop_scan (SimpleScan* _sender, gpointer self);
+static void application_email_cb (Application* self, SimpleScan* ui, const gchar* profile);
+static void _application_email_cb_simple_scan_email (SimpleScan* _sender, const gchar* profile, gpointer self);
+static void application_quit_cb (Application* self, SimpleScan* ui);
+static void _application_quit_cb_simple_scan_quit (SimpleScan* _sender, gpointer self);
+Scanner* scanner_get_instance (void);
+static void application_update_scan_devices_cb (Application* self, Scanner* scanner, GList* devices);
+static void _application_update_scan_devices_cb_scanner_update_devices (Scanner* _sender, GList* devices, gpointer self);
+static void application_authorize_cb (Application* self, Scanner* scanner, const gchar* resource);
+static void _application_authorize_cb_scanner_request_authorization (Scanner* _sender, const gchar* resource, gpointer self);
+static void application_scanner_new_page_cb (Application* self, Scanner* scanner);
+static void _application_scanner_new_page_cb_scanner_expect_page (Scanner* _sender, gpointer self);
+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;
+static void application_scanner_page_info_cb (Application* self, Scanner* scanner, ScanPageInfo* info);
+static void _application_scanner_page_info_cb_scanner_got_page_info (Scanner* _sender, ScanPageInfo* info, gpointer 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 application_scanner_line_cb (Application* self, Scanner* scanner, ScanLine* line);
+static void _application_scanner_line_cb_scanner_got_line (Scanner* _sender, ScanLine* line, gpointer self);
+static void application_scanner_page_done_cb (Application* self, Scanner* scanner);
+static void _application_scanner_page_done_cb_scanner_page_done (Scanner* _sender, gpointer self);
+static void application_scanner_document_done_cb (Application* self, Scanner* scanner);
+static void _application_scanner_document_done_cb_scanner_document_done (Scanner* _sender, gpointer self);
+static void application_scanner_failed_cb (Application* self, Scanner* scanner, gint error_code, const gchar* error_string);
+static void _application_scanner_failed_cb_scanner_scan_failed (Scanner* _sender, gint error_code, const gchar* error_string, gpointer self);
+static void application_scanner_scanning_changed_cb (Application* self, Scanner* scanner);
+static void _application_scanner_scanning_changed_cb_scanner_scanning_changed (Scanner* _sender, gpointer self);
+static void application_on_uevent (Application* self, GUdevClient* client, const gchar* action, GUdevDevice* device);
+static void _application_on_uevent_g_udev_client_uevent (GUdevClient* _sender, const gchar* action, GUdevDevice* device, gpointer self);
+void simple_scan_set_scan_devices (SimpleScan* self, GList* devices);
+void simple_scan_set_selected_device (SimpleScan* self, const gchar* device);
+static void _scan_device_unref0_ (gpointer var);
+static void _g_list_free__scan_device_unref0_ (GList* self);
+void application_start (Application* self);
+void simple_scan_start (SimpleScan* self);
+void scanner_start (Scanner* self);
+void simple_scan_authorize (SimpleScan* self, const gchar* resource, gchar** username, gchar** password);
+void scanner_authorize (Scanner* self, const gchar* username, const gchar* password);
+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;
+static Page* application_append_page (Application* self);
+Page* book_get_page (Book* self, gint page_number);
+gboolean page_has_data (Page* self);
+void simple_scan_set_selected_page (SimpleScan* self, Page* page);
+void page_start (Page* self);
+GType scan_direction_get_type (void) G_GNUC_CONST;
+ScanDirection page_get_scan_direction (Page* self);
+gint page_get_width (Page* self);
+gint page_get_height (Page* self);
+gint page_get_dpi (Page* self);
+gboolean page_has_crop (Page* self);
+gchar* page_get_named_crop (Page* self);
+void page_get_crop (Page* self, gint* x, gint* y, gint* width, gint* height);
+Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction);
+void page_set_named_crop (Page* self, const gchar* name);
+void page_set_custom_crop (Page* self, gint width, gint height);
+void page_move_crop (Page* self, gint x, gint y);
+static gchar* application_get_profile_for_device (Application* self, const gchar* device_name);
+void page_set_page_info (Page* self, ScanPageInfo* info);
+void page_set_color_profile (Page* self, const gchar* color_profile);
+guint book_get_n_pages (Book* self);
+void page_parse_scan_line (Page* self, ScanLine* line);
+void page_finish (Page* self);
+static void application_remove_empty_page (Application* self);
+void book_delete_page (Book* self, Page* page);
+void simple_scan_show_error (SimpleScan* self, const gchar* error_title, const gchar* error_text, gboolean change_scanner_hint);
+void simple_scan_set_scanning (SimpleScan* self, gboolean scanning);
+gboolean scanner_is_scanning (Scanner* self);
+GType scan_mode_get_type (void) G_GNUC_CONST;
+GType scan_type_get_type (void) G_GNUC_CONST;
+void simple_scan_set_default_file_name (SimpleScan* self, const gchar* default_file_name);
+void scanner_scan (Scanner* self, const gchar* device, ScanOptions* options);
+void scanner_cancel (Scanner* self);
+static gchar* application_get_temporary_filename (Application* self, const gchar* prefix, const gchar* extension);
+void book_save (Book* self, const gchar* type, GFile* file, GError** error);
+void page_save (Page* self, const gchar* type, GFile* file, GError** error);
+void scanner_free (Scanner* self);
+static void application_log_cb (const gchar* log_domain, GLogLevelFlags log_level, const gchar* message);
+void scanner_redetect (Scanner* self);
+gint application_main (gchar** args, int args_length1);
+ScanDevice* scan_device_new (void);
+ScanDevice* scan_device_construct (GType object_type);
+static void _application_log_cb_glog_func (const gchar* log_domain, GLogLevelFlags log_levels, const gchar* message, gpointer self);
+static void application_finalize (Application* 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);
+
+const GOptionEntry APPLICATION_options[3] = {{"version", 'v', 0, G_OPTION_ARG_NONE, &application_show_version, "Show release version", NULL}, {"debug", 'd', 0, G_OPTION_ARG_NONE, &application_debug_enabled, "Print debugging messages", NULL}, {NULL}};
+
+static gpointer _scan_device_ref0 (gpointer self) {
+ return self ? scan_device_ref (self) : NULL;
+}
+
+
+static void _application_scan_cb_simple_scan_start_scan (SimpleScan* _sender, const gchar* device, ScanOptions* options, gpointer self) {
+ application_scan_cb (self, _sender, device, options);
+}
+
+
+static void _application_cancel_cb_simple_scan_stop_scan (SimpleScan* _sender, gpointer self) {
+ application_cancel_cb (self, _sender);
+}
+
+
+static void _application_email_cb_simple_scan_email (SimpleScan* _sender, const gchar* profile, gpointer self) {
+ application_email_cb (self, _sender, profile);
+}
+
+
+static void _application_quit_cb_simple_scan_quit (SimpleScan* _sender, gpointer self) {
+ application_quit_cb (self, _sender);
+}
+
+
+static void _application_update_scan_devices_cb_scanner_update_devices (Scanner* _sender, GList* devices, gpointer self) {
+ application_update_scan_devices_cb (self, _sender, devices);
+}
+
+
+static void _application_authorize_cb_scanner_request_authorization (Scanner* _sender, const gchar* resource, gpointer self) {
+ application_authorize_cb (self, _sender, resource);
+}
+
+
+static void _application_scanner_new_page_cb_scanner_expect_page (Scanner* _sender, gpointer self) {
+ application_scanner_new_page_cb (self, _sender);
+}
+
+
+static void _application_scanner_page_info_cb_scanner_got_page_info (Scanner* _sender, ScanPageInfo* info, gpointer self) {
+ application_scanner_page_info_cb (self, _sender, info);
+}
+
+
+static void _application_scanner_line_cb_scanner_got_line (Scanner* _sender, ScanLine* line, gpointer self) {
+ application_scanner_line_cb (self, _sender, line);
+}
+
+
+static void _application_scanner_page_done_cb_scanner_page_done (Scanner* _sender, gpointer self) {
+ application_scanner_page_done_cb (self, _sender);
+}
+
+
+static void _application_scanner_document_done_cb_scanner_document_done (Scanner* _sender, gpointer self) {
+ application_scanner_document_done_cb (self, _sender);
+}
+
+
+static void _application_scanner_failed_cb_scanner_scan_failed (Scanner* _sender, gint error_code, const gchar* error_string, gpointer self) {
+ application_scanner_failed_cb (self, _sender, error_code, error_string);
+}
+
+
+static void _application_scanner_scanning_changed_cb_scanner_scanning_changed (Scanner* _sender, gpointer self) {
+ application_scanner_scanning_changed_cb (self, _sender);
+}
+
+
+static void _application_on_uevent_g_udev_client_uevent (GUdevClient* _sender, const gchar* action, GUdevDevice* device, gpointer self) {
+ application_on_uevent (self, _sender, action, device);
+}
+
-#include <sane/sane.h> // For SANE_STATUS_CANCELLED
+static void _scan_device_unref0_ (gpointer var) {
+ (var == NULL) ? NULL : (var = (scan_device_unref (var), NULL));
+}
-#include "ui.h"
-#include "scanner.h"
-#include "book.h"
-
-
-static ScanDevice *default_device = NULL;
-
-static gboolean have_devices = FALSE;
-
-static GUdevClient *udev_client;
-static SimpleScan *ui;
+static void _g_list_free__scan_device_unref0_ (GList* self) {
+ g_list_foreach (self, (GFunc) _scan_device_unref0_, NULL);
+ g_list_free (self);
+}
-static Scanner *scanner;
-static Book *book;
+Application* application_construct (GType object_type, ScanDevice* device) {
+ Application* self = NULL;
+ ScanDevice* _tmp0_;
+ SimpleScan* _tmp1_ = NULL;
+ Book* _tmp2_ = NULL;
+ Scanner* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ gchar** _tmp5_ = NULL;
+ gchar** subsystems;
+ gint subsystems_length1;
+ gint _subsystems_size_;
+ GUdevClient* _tmp6_ = NULL;
+ self = (Application*) g_type_create_instance (object_type);
+ _tmp0_ = _scan_device_ref0 (device);
+ _scan_device_unref0 (self->priv->default_device);
+ self->priv->default_device = _tmp0_;
+ _tmp1_ = simple_scan_new ();
+ _simple_scan_unref0 (self->priv->ui);
+ self->priv->ui = _tmp1_;
+ _tmp2_ = simple_scan_get_book (self->priv->ui);
+ _book_unref0 (self->priv->book);
+ self->priv->book = _tmp2_;
+ g_signal_connect (self->priv->ui, "start-scan", (GCallback) _application_scan_cb_simple_scan_start_scan, self);
+ g_signal_connect (self->priv->ui, "stop-scan", (GCallback) _application_cancel_cb_simple_scan_stop_scan, self);
+ g_signal_connect (self->priv->ui, "email", (GCallback) _application_email_cb_simple_scan_email, self);
+ g_signal_connect (self->priv->ui, "quit", (GCallback) _application_quit_cb_simple_scan_quit, self);
+ _tmp3_ = scanner_get_instance ();
+ _scanner_unref0 (self->priv->scanner);
+ self->priv->scanner = _tmp3_;
+ g_signal_connect (self->priv->scanner, "update-devices", (GCallback) _application_update_scan_devices_cb_scanner_update_devices, self);
+ g_signal_connect (self->priv->scanner, "request-authorization", (GCallback) _application_authorize_cb_scanner_request_authorization, self);
+ g_signal_connect (self->priv->scanner, "expect-page", (GCallback) _application_scanner_new_page_cb_scanner_expect_page, self);
+ g_signal_connect (self->priv->scanner, "got-page-info", (GCallback) _application_scanner_page_info_cb_scanner_got_page_info, self);
+ g_signal_connect (self->priv->scanner, "got-line", (GCallback) _application_scanner_line_cb_scanner_got_line, self);
+ g_signal_connect (self->priv->scanner, "page-done", (GCallback) _application_scanner_page_done_cb_scanner_page_done, self);
+ g_signal_connect (self->priv->scanner, "document-done", (GCallback) _application_scanner_document_done_cb_scanner_document_done, self);
+ g_signal_connect (self->priv->scanner, "scan-failed", (GCallback) _application_scanner_failed_cb_scanner_scan_failed, self);
+ g_signal_connect (self->priv->scanner, "scanning-changed", (GCallback) _application_scanner_scanning_changed_cb_scanner_scanning_changed, self);
+ _tmp4_ = g_strdup ("usb");
+ _tmp5_ = g_new0 (gchar*, 2 + 1);
+ _tmp5_[0] = _tmp4_;
+ _tmp5_[1] = NULL;
+ subsystems = _tmp5_;
+ subsystems_length1 = 2;
+ _subsystems_size_ = subsystems_length1;
+ _tmp6_ = g_udev_client_new (subsystems);
+ _g_object_unref0 (self->priv->udev_client);
+ self->priv->udev_client = _tmp6_;
+ g_signal_connect (self->priv->udev_client, "uevent", (GCallback) _application_on_uevent_g_udev_client_uevent, self);
+ if (self->priv->default_device != NULL) {
+ GList* device_list;
+ ScanDevice* _tmp7_;
+ device_list = NULL;
+ _tmp7_ = _scan_device_ref0 (self->priv->default_device);
+ device_list = g_list_append (device_list, _tmp7_);
+ simple_scan_set_scan_devices (self->priv->ui, device_list);
+ simple_scan_set_selected_device (self->priv->ui, self->priv->default_device->name);
+ __g_list_free__scan_device_unref0_0 (device_list);
+ }
+ subsystems = (_vala_array_free (subsystems, subsystems_length1, (GDestroyNotify) g_free), NULL);
+ return self;
+}
-static GTimer *log_timer;
-static FILE *log_file;
+Application* application_new (ScanDevice* device) {
+ return application_construct (TYPE_APPLICATION, device);
+}
-static gboolean debug = FALSE;
+void application_start (Application* self) {
+ g_return_if_fail (self != NULL);
+ simple_scan_start (self->priv->ui);
+ scanner_start (self->priv->scanner);
+}
-static void
-update_scan_devices_cb (Scanner *scanner, GList *devices)
-{
- GList *devices_copy;
-
- devices_copy = g_list_copy (devices);
-
- /* If the default device is not detected add it to the list */
- if (default_device) {
- GList *i;
-
- for (i = devices_copy; i; i = i->next) {
- ScanDevice *device = i->data;
- if (strcmp (device->name, default_device->name) == 0)
- break;
- }
-
- if (!i)
- devices_copy = g_list_prepend (devices_copy, default_device);
- }
-
- have_devices = devices_copy != NULL;
- ui_set_scan_devices (ui, devices_copy);
-
- g_list_free (devices_copy);
-}
-
-
-static void
-authorize_cb (Scanner *scanner, const gchar *resource)
-{
- gchar *username = NULL, *password = NULL;
- ui_authorize (ui, resource, &username, &password);
- scanner_authorize (scanner, username, password);
- g_free (username);
- g_free (password);
-}
-
-
-static Page *
-append_page ()
-{
- Page *page;
- ScanDirection scan_direction = TOP_TO_BOTTOM;
- gboolean do_crop = FALSE;
- gchar *named_crop = NULL;
- gint width = 100, height = 100, dpi = 100, cx, cy, cw, ch;
-
- /* Use current page if not used */
- page = book_get_page (book, -1);
- if (page && !page_has_data (page)) {
- ui_set_selected_page (ui, page);
- page_start (page);
- return page;
- }
-
- /* Copy info from previous page */
- if (page) {
- scan_direction = page_get_scan_direction (page);
- width = page_get_width (page);
- height = page_get_height (page);
- dpi = page_get_dpi (page);
-
- do_crop = page_has_crop (page);
- if (do_crop) {
- named_crop = page_get_named_crop (page);
- page_get_crop (page, &cx, &cy, &cw, &ch);
- }
- }
-
- page = book_append_page (book, width, height, dpi, scan_direction);
- if (do_crop) {
- if (named_crop) {
- page_set_named_crop (page, named_crop);
- g_free (named_crop);
- }
- else
- page_set_custom_crop (page, cw, ch);
- page_move_crop (page, cx, cy);
- }
- ui_set_selected_page (ui, page);
- page_start (page);
-
- return page;
-}
-
-
-static void
-scanner_new_page_cb (Scanner *scanner)
-{
- append_page ();
-}
-
-
-static gchar *
-get_profile_for_device (const gchar *current_device)
-{
- gboolean ret;
- DBusGConnection *connection;
- DBusGProxy *proxy;
- GError *error = NULL;
- GType custom_g_type_string_string;
- GPtrArray *profile_data_array = NULL;
- gchar *device_id = NULL;
- gchar *icc_profile = NULL;
-
- /* Connect to the color manager on the session bus */
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
- proxy = dbus_g_proxy_new_for_name (connection,
- "org.gnome.ColorManager",
- "/org/gnome/ColorManager",
- "org.gnome.ColorManager");
-
- /* Get color profile */
- device_id = g_strdup_printf ("sane:%s", current_device);
- custom_g_type_string_string = dbus_g_type_get_collection ("GPtrArray",
- dbus_g_type_get_struct("GValueArray",
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_INVALID));
- ret = dbus_g_proxy_call (proxy, "GetProfilesForDevice", &error,
- G_TYPE_STRING, device_id,
- G_TYPE_STRING, "",
- G_TYPE_INVALID,
- custom_g_type_string_string, &profile_data_array,
- G_TYPE_INVALID);
- g_object_unref (proxy);
- g_free (device_id);
- if (!ret) {
- g_debug ("The request failed: %s", error->message);
- g_error_free (error);
- return NULL;
- }
-
- if (profile_data_array->len > 0) {
- GValueArray *gva;
- GValue *gv = NULL;
-
- /* Just use the preferred profile filename */
- gva = (GValueArray *) g_ptr_array_index (profile_data_array, 0);
- gv = g_value_array_get_nth (gva, 1);
- icc_profile = g_value_dup_string (gv);
- g_value_unset (gv);
- }
- else
- g_debug ("There are no ICC profiles for the device sane:%s", current_device);
- g_ptr_array_free (profile_data_array, TRUE);
-
- return icc_profile;
-}
-
-
-static void
-scanner_page_info_cb (Scanner *scanner, ScanPageInfo *info)
-{
- Page *page;
-
- g_debug ("Page is %d pixels wide, %d pixels high, %d bits per pixel",
- info->width, info->height, info->depth);
- /* Add a new page */
- page = append_page ();
- page_set_page_info (page, info);
+static void application_update_scan_devices_cb (Application* self, Scanner* scanner, GList* devices) {
+ GList* _tmp0_ = NULL;
+ GList* devices_copy;
+ guint _tmp1_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ _tmp0_ = g_list_copy (devices);
+ devices_copy = _tmp0_;
+ if (self->priv->default_device != NULL) {
+ gboolean default_in_list;
+ default_in_list = FALSE;
+ {
+ GList* device_collection = NULL;
+ GList* device_it = NULL;
+ device_collection = devices_copy;
+ for (device_it = device_collection; device_it != NULL; device_it = device_it->next) {
+ ScanDevice* device = NULL;
+ device = (ScanDevice*) device_it->data;
+ {
+ if (g_strcmp0 (device->name, self->priv->default_device->name) == 0) {
+ default_in_list = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (!default_in_list) {
+ devices_copy = g_list_prepend (devices_copy, self->priv->default_device);
+ }
+ }
+ _tmp1_ = g_list_length (devices_copy);
+ self->priv->have_devices = _tmp1_ > ((guint) 0);
+ simple_scan_set_scan_devices (self->priv->ui, devices_copy);
+ _g_list_free0 (devices_copy);
+}
+
- /* Get ICC color profile */
- /* FIXME: The ICC profile could change */
- /* FIXME: Don't do a D-bus call for each page, cache color profiles */
- page_set_color_profile (page, get_profile_for_device (info->device));
+static void application_authorize_cb (Application* self, Scanner* scanner, const gchar* resource) {
+ gchar* username = NULL;
+ gchar* password = NULL;
+ gchar* _tmp0_ = NULL;
+ gchar* _tmp1_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (resource != NULL);
+ simple_scan_authorize (self->priv->ui, resource, &_tmp0_, &_tmp1_);
+ _g_free0 (username);
+ username = _tmp0_;
+ _g_free0 (password);
+ password = _tmp1_;
+ scanner_authorize (scanner, username, password);
+ _g_free0 (password);
+ _g_free0 (username);
}
-static void
-scanner_line_cb (Scanner *scanner, ScanLine *line)
-{
- Page *page;
+static Page* application_append_page (Application* self) {
+ Page* result = NULL;
+ Page* _tmp0_ = NULL;
+ Page* page;
+ gboolean _tmp1_ = FALSE;
+ ScanDirection scan_direction;
+ gboolean do_crop;
+ gchar* named_crop;
+ gint width;
+ gint height;
+ gint dpi;
+ gint cx;
+ gint cy;
+ gint cw;
+ gint ch;
+ Page* _tmp13_ = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = book_get_page (self->priv->book, -1);
+ page = _tmp0_;
+ if (page != NULL) {
+ gboolean _tmp2_;
+ _tmp2_ = page_has_data (page);
+ _tmp1_ = !_tmp2_;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ if (_tmp1_) {
+ simple_scan_set_selected_page (self->priv->ui, page);
+ page_start (page);
+ result = page;
+ return result;
+ }
+ scan_direction = SCAN_DIRECTION_TOP_TO_BOTTOM;
+ do_crop = FALSE;
+ named_crop = NULL;
+ width = 100;
+ height = 100;
+ dpi = 100;
+ cx = 0;
+ cy = 0;
+ cw = 0;
+ ch = 0;
+ if (page != NULL) {
+ ScanDirection _tmp3_;
+ gint _tmp4_;
+ gint _tmp5_;
+ gint _tmp6_;
+ gboolean _tmp7_;
+ _tmp3_ = page_get_scan_direction (page);
+ scan_direction = _tmp3_;
+ _tmp4_ = page_get_width (page);
+ width = _tmp4_;
+ _tmp5_ = page_get_height (page);
+ height = _tmp5_;
+ _tmp6_ = page_get_dpi (page);
+ dpi = _tmp6_;
+ _tmp7_ = page_has_crop (page);
+ do_crop = _tmp7_;
+ if (do_crop) {
+ gchar* _tmp8_ = NULL;
+ gint _tmp9_;
+ gint _tmp10_;
+ gint _tmp11_;
+ gint _tmp12_;
+ _tmp8_ = page_get_named_crop (page);
+ _g_free0 (named_crop);
+ named_crop = _tmp8_;
+ page_get_crop (page, &_tmp9_, &_tmp10_, &_tmp11_, &_tmp12_);
+ cx = _tmp9_;
+ cy = _tmp10_;
+ cw = _tmp11_;
+ ch = _tmp12_;
+ }
+ }
+ _tmp13_ = book_append_page (self->priv->book, width, height, dpi, scan_direction);
+ _page_unref0 (page);
+ page = _tmp13_;
+ if (do_crop) {
+ if (named_crop != NULL) {
+ page_set_named_crop (page, named_crop);
+ } else {
+ page_set_custom_crop (page, cw, ch);
+ }
+ page_move_crop (page, cx, cy);
+ }
+ simple_scan_set_selected_page (self->priv->ui, page);
+ page_start (page);
+ result = page;
+ _g_free0 (named_crop);
+ return result;
+}
+
- page = book_get_page (book, book_get_n_pages (book) - 1);
- page_parse_scan_line (page, line);
+static void application_scanner_new_page_cb (Application* self, Scanner* scanner) {
+ Page* _tmp0_ = NULL;
+ Page* _tmp1_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ _tmp0_ = application_append_page (self);
+ _tmp1_ = _tmp0_;
+ _page_unref0 (_tmp1_);
}
-static void
-scanner_page_done_cb (Scanner *scanner)
-{
- Page *page;
- page = book_get_page (book, book_get_n_pages (book) - 1);
- page_finish (page);
+static gchar* application_get_profile_for_device (Application* self, const gchar* device_name) {
+ gchar* result = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (device_name != NULL, NULL);
+ result = NULL;
+ return result;
}
-static void
-remove_empty_page ()
-{
- Page *page;
+static void application_scanner_page_info_cb (Application* self, Scanner* scanner, ScanPageInfo* info) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ gchar* _tmp1_ = NULL;
+ gchar* _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (info != NULL);
+ g_debug ("simple-scan.vala:233: Page is %d pixels wide, %d pixels high, %d bits " \
+"per pixel", info->width, info->height, info->depth);
+ _tmp0_ = application_append_page (self);
+ page = _tmp0_;
+ page_set_page_info (page, info);
+ _tmp1_ = application_get_profile_for_device (self, info->device);
+ _tmp2_ = _tmp1_;
+ page_set_color_profile (page, _tmp2_);
+ _g_free0 (_tmp2_);
+ _page_unref0 (page);
+}
- page = book_get_page (book, book_get_n_pages (book) - 1);
- /* Remove a failed page */
- if (page_has_data (page))
- page_finish (page);
- else
- book_delete_page (book, page);
+static void application_scanner_line_cb (Application* self, Scanner* scanner, ScanLine* line) {
+ guint _tmp0_;
+ Page* _tmp1_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (line != NULL);
+ _tmp0_ = book_get_n_pages (self->priv->book);
+ _tmp1_ = book_get_page (self->priv->book, ((gint) _tmp0_) - 1);
+ page = _tmp1_;
+ page_parse_scan_line (page, line);
+ _page_unref0 (page);
}
-static void
-scanner_document_done_cb (Scanner *scanner)
-{
- remove_empty_page ();
+static void application_scanner_page_done_cb (Application* self, Scanner* scanner) {
+ guint _tmp0_;
+ Page* _tmp1_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ _tmp0_ = book_get_n_pages (self->priv->book);
+ _tmp1_ = book_get_page (self->priv->book, ((gint) _tmp0_) - 1);
+ page = _tmp1_;
+ page_finish (page);
+ _page_unref0 (page);
}
-static void
-scanner_failed_cb (Scanner *scanner, GError *error)
-{
- remove_empty_page ();
- if (!g_error_matches (error, SCANNER_TYPE, SANE_STATUS_CANCELLED)) {
- ui_show_error (ui,
- /* Title of error dialog when scan failed */
- _("Failed to scan"),
- error->message,
- have_devices);
- }
+static void application_remove_empty_page (Application* self) {
+ guint _tmp0_;
+ Page* _tmp1_ = NULL;
+ Page* page;
+ gboolean _tmp2_;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = book_get_n_pages (self->priv->book);
+ _tmp1_ = book_get_page (self->priv->book, ((gint) _tmp0_) - 1);
+ page = _tmp1_;
+ _tmp2_ = page_has_data (page);
+ if (_tmp2_) {
+ page_finish (page);
+ } else {
+ book_delete_page (self->priv->book, page);
+ }
+ _page_unref0 (page);
}
-static void
-scanner_scanning_changed_cb (Scanner *scanner)
-{
- ui_set_scanning (ui, scanner_is_scanning (scanner));
+static void application_scanner_document_done_cb (Application* self, Scanner* scanner) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ application_remove_empty_page (self);
}
-static void
-scan_cb (SimpleScan *ui, const gchar *device, ScanOptions *options)
-{
- /* Default filename to use when saving document (and extension will be added, e.g. .jpg) */
- const gchar *filename_prefix = _("Scanned Document");
- const gchar *extension;
- gchar *filename;
+static void application_scanner_failed_cb (Application* self, Scanner* scanner, gint error_code, const gchar* error_string) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ g_return_if_fail (error_string != NULL);
+ application_remove_empty_page (self);
+ if (error_code != ((gint) SANE_STATUS_CANCELLED)) {
+ const gchar* _tmp0_ = NULL;
+ _tmp0_ = _ ("Failed to scan");
+ simple_scan_show_error (self->priv->ui, _tmp0_, error_string, self->priv->have_devices);
+ }
+}
- if (options->scan_mode == SCAN_MODE_COLOR)
- extension = "jpg";
- else
- extension = "pdf";
- g_debug ("Requesting scan at %d dpi from device '%s'", options->dpi, device);
+static void application_scanner_scanning_changed_cb (Application* self, Scanner* scanner) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (scanner != NULL);
+ _tmp0_ = scanner_is_scanning (scanner);
+ simple_scan_set_scanning (self->priv->ui, _tmp0_);
+}
- if (!scanner_is_scanning (scanner))
- append_page ();
- filename = g_strdup_printf ("%s.%s", filename_prefix, extension);
- ui_set_default_file_name (ui, filename);
- g_free (filename);
- scanner_scan (scanner, device, options);
+static void application_scan_cb (Application* self, SimpleScan* ui, const gchar* device, ScanOptions* options) {
+ gboolean _tmp0_;
+ const gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ gchar* filename_prefix;
+ gchar* extension = NULL;
+ gchar* _tmp7_ = NULL;
+ gchar* filename;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (ui != NULL);
+ g_return_if_fail (options != NULL);
+ g_debug ("simple-scan.vala:293: Requesting scan at %d dpi from device '%s'", options->dpi, device);
+ _tmp0_ = scanner_is_scanning (self->priv->scanner);
+ if (!_tmp0_) {
+ Page* _tmp1_ = NULL;
+ Page* _tmp2_;
+ _tmp1_ = application_append_page (self);
+ _tmp2_ = _tmp1_;
+ _page_unref0 (_tmp2_);
+ }
+ _tmp3_ = _ ("Scanned Document");
+ _tmp4_ = g_strdup (_tmp3_);
+ filename_prefix = _tmp4_;
+ if (options->scan_mode == SCAN_MODE_COLOR) {
+ gchar* _tmp5_;
+ _tmp5_ = g_strdup ("jpg");
+ _g_free0 (extension);
+ extension = _tmp5_;
+ } else {
+ gchar* _tmp6_;
+ _tmp6_ = g_strdup ("pdf");
+ _g_free0 (extension);
+ extension = _tmp6_;
+ }
+ _tmp7_ = g_strdup_printf ("%s.%s", filename_prefix, extension);
+ filename = _tmp7_;
+ simple_scan_set_default_file_name (ui, filename);
+ scanner_scan (self->priv->scanner, device, options);
+ _g_free0 (filename);
+ _g_free0 (extension);
+ _g_free0 (filename_prefix);
}
-static void
-cancel_cb (SimpleScan *ui)
-{
- scanner_cancel (scanner);
+static void application_cancel_cb (Application* self, SimpleScan* ui) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (ui != NULL);
+ scanner_cancel (self->priv->scanner);
}
-static gchar *
-get_temporary_filename (const gchar *prefix, const gchar *extension)
-{
- gint fd;
- gchar *filename, *path;
- GError *error = NULL;
+static gchar* application_get_temporary_filename (Application* self, const gchar* prefix, const gchar* extension) {
+ gchar* result = NULL;
+ gchar* _tmp0_ = NULL;
+ gchar* filename;
+ gchar* path = NULL;
+ GError * _inner_error_ = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (prefix != NULL, NULL);
+ g_return_val_if_fail (extension != NULL, NULL);
+ _tmp0_ = g_strdup_printf ("%sXXXXXX.%s", prefix, extension);
+ filename = _tmp0_;
+ {
+ gchar* _tmp1_ = NULL;
+ gint _tmp2_;
+ gint fd;
+ _tmp2_ = g_file_open_tmp (filename, &_tmp1_, &_inner_error_);
+ _g_free0 (path);
+ path = _tmp1_;
+ fd = _tmp2_;
+ if (_inner_error_ != NULL) {
+ goto __catch3_g_error;
+ }
+ close (fd);
+ }
+ goto __finally3;
+ __catch3_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("simple-scan.vala:329: Error saving email attachment: %s", e->message);
+ result = NULL;
+ _g_error_free0 (e);
+ _g_free0 (path);
+ _g_free0 (filename);
+ return result;
+ }
+ __finally3:
+ if (_inner_error_ != NULL) {
+ _g_free0 (path);
+ _g_free0 (filename);
+ 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;
+ }
+ result = path;
+ _g_free0 (filename);
+ return result;
+}
+
- /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and
- * use the filename but it appears to work in practise */
+static void application_email_cb (Application* self, SimpleScan* ui, const gchar* profile) {
+ gboolean saved;
+ gchar* _tmp0_;
+ gchar* command_line;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (ui != NULL);
+ g_return_if_fail (profile != NULL);
+ saved = FALSE;
+ _tmp0_ = g_strdup ("xdg-email");
+ command_line = _tmp0_;
+ if (g_strcmp0 (profile, "text") == 0) {
+ gchar* _tmp1_ = NULL;
+ gchar* path;
+ _tmp1_ = application_get_temporary_filename (self, "scan", "pdf");
+ path = _tmp1_;
+ if (path != NULL) {
+ GFile* _tmp2_ = NULL;
+ GFile* file;
+ gchar* _tmp3_ = NULL;
+ gchar* _tmp4_;
+ gchar* _tmp5_;
+ _tmp2_ = g_file_new_for_path (path);
+ file = _tmp2_;
+ {
+ book_save (self->priv->book, "pdf", file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch4_g_error;
+ }
+ }
+ goto __finally4;
+ __catch4_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("simple-scan.vala:355: Unable to save email file: %s", e->message);
+ _g_error_free0 (e);
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ _g_free0 (command_line);
+ return;
+ }
+ __finally4:
+ if (_inner_error_ != NULL) {
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ _g_free0 (command_line);
+ 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;
+ }
+ _tmp3_ = g_strdup_printf (" --attach %s", path);
+ _tmp4_ = _tmp3_;
+ _tmp5_ = g_strconcat (command_line, _tmp4_, NULL);
+ _g_free0 (command_line);
+ command_line = _tmp5_;
+ _g_free0 (_tmp4_);
+ _g_object_unref0 (file);
+ }
+ _g_free0 (path);
+ } else {
+ {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp6_;
+ _tmp6_ = TRUE;
+ while (TRUE) {
+ guint _tmp7_;
+ gchar* _tmp8_ = NULL;
+ gchar* path;
+ GFile* _tmp9_ = NULL;
+ GFile* file;
+ gchar* _tmp12_ = NULL;
+ gchar* _tmp13_;
+ gchar* _tmp14_;
+ if (!_tmp6_) {
+ i++;
+ }
+ _tmp6_ = FALSE;
+ _tmp7_ = book_get_n_pages (self->priv->book);
+ if (!(((guint) i) < _tmp7_)) {
+ break;
+ }
+ _tmp8_ = application_get_temporary_filename (self, "scan", "jpg");
+ path = _tmp8_;
+ if (path == NULL) {
+ saved = FALSE;
+ _g_free0 (path);
+ break;
+ }
+ _tmp9_ = g_file_new_for_path (path);
+ file = _tmp9_;
+ {
+ Page* _tmp10_ = NULL;
+ Page* _tmp11_;
+ _tmp10_ = book_get_page (self->priv->book, i);
+ _tmp11_ = _tmp10_;
+ page_save (_tmp11_, "jpeg", file, &_inner_error_);
+ _page_unref0 (_tmp11_);
+ if (_inner_error_ != NULL) {
+ goto __catch5_g_error;
+ }
+ }
+ goto __finally5;
+ __catch5_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("simple-scan.vala:379: Unable to save email file: %s", e->message);
+ _g_error_free0 (e);
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ _g_free0 (command_line);
+ return;
+ }
+ __finally5:
+ if (_inner_error_ != NULL) {
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ _g_free0 (command_line);
+ 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;
+ }
+ _tmp12_ = g_strdup_printf (" --attach %s", path);
+ _tmp13_ = _tmp12_;
+ _tmp14_ = g_strconcat (command_line, _tmp13_, NULL);
+ _g_free0 (command_line);
+ command_line = _tmp14_;
+ _g_free0 (_tmp13_);
+ if (!saved) {
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ break;
+ }
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ }
+ }
+ }
+ }
+ g_debug ("simple-scan.vala:389: Launching email client: %s", command_line);
+ {
+ g_spawn_command_line_async (command_line, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch6_g_error;
+ }
+ }
+ goto __finally6;
+ __catch6_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("simple-scan.vala:396: Unable to start email: %s", e->message);
+ _g_error_free0 (e);
+ }
+ __finally6:
+ if (_inner_error_ != NULL) {
+ _g_free0 (command_line);
+ 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;
+ }
+ _g_free0 (command_line);
+}
- filename = g_strdup_printf ("%sXXXXXX.%s", prefix, extension);
- fd = g_file_open_tmp (filename, &path, &error);
- g_free (filename);
- if (fd < 0) {
- g_warning ("Error saving email attachment: %s", error->message);
- g_clear_error (&error);
- return NULL;
- }
- close (fd);
- return path;
+static void application_quit_cb (Application* self, SimpleScan* ui) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (ui != NULL);
+ _book_unref0 (self->priv->book);
+ self->priv->book = NULL;
+ ui = NULL;
+ _g_object_unref0 (self->priv->udev_client);
+ self->priv->udev_client = NULL;
+ scanner_free (self->priv->scanner);
+ gtk_main_quit ();
}
-static void
-email_cb (SimpleScan *ui, const gchar *profile)
-{
- gboolean saved = FALSE;
- GError *error = NULL;
- GString *command_line;
-
- command_line = g_string_new ("xdg-email");
-
- /* Save text files as PDFs */
- if (strcmp (profile, "text") == 0) {
- gchar *path;
-
- /* Open a temporary file */
- path = get_temporary_filename ("scan", "pdf");
- if (path) {
- GFile *file;
-
- file = g_file_new_for_path (path);
- saved = book_save (book, "pdf", file, &error);
- g_string_append_printf (command_line, " --attach %s", path);
- g_free (path);
- g_object_unref (file);
- }
- }
- else {
- gint i;
-
- for (i = 0; i < book_get_n_pages (book); i++) {
- gchar *path;
- GFile *file;
-
- path = get_temporary_filename ("scan", "jpg");
- if (!path) {
- saved = FALSE;
- break;
- }
-
- file = g_file_new_for_path (path);
- saved = page_save (book_get_page (book, i), "jpeg", file, &error);
- g_string_append_printf (command_line, " --attach %s", path);
- g_free (path);
- g_object_unref (file);
-
- if (!saved)
- break;
- }
- }
-
- if (saved) {
- g_debug ("Launchind email client: %s", command_line->str);
- g_spawn_command_line_async (command_line->str, &error);
-
- if (error) {
- g_warning ("Unable to start email: %s", error->message);
- g_clear_error (&error);
- }
- }
- else {
- g_warning ("Unable to save email file: %s", error->message);
- g_clear_error (&error);
- }
-
- g_string_free (command_line, TRUE);
-}
-
-
-static void
-quit_cb (SimpleScan *ui)
-{
- g_object_unref (book);
- g_object_unref (ui);
- g_object_unref (udev_client);
- scanner_free (scanner);
- gtk_main_quit ();
-}
-
-
-static void
-version()
-{
- /* NOTE: Is not translated so can be easily parsed */
- fprintf(stderr, "%1$s %2$s\n", SIMPLE_SCAN_BINARY, VERSION);
-}
-
-
-static void
-usage(int show_gtk)
-{
- fprintf(stderr,
- /* Description on how to use simple-scan displayed on command-line */
- _("Usage:\n"
- " %s [DEVICE...] - Scanning utility"), SIMPLE_SCAN_BINARY);
-
- fprintf(stderr,
- "\n\n");
-
- fprintf(stderr,
- /* Description on how to use simple-scan displayed on command-line */
- _("Help Options:\n"
- " -d, --debug Print debugging messages\n"
- " -v, --version Show release version\n"
- " -h, --help Show help options\n"
- " --help-all Show all help options\n"
- " --help-gtk Show GTK+ options"));
- fprintf(stderr,
- "\n\n");
-
- if (show_gtk) {
- fprintf(stderr,
- /* Description on simple-scan command-line GTK+ options displayed on command-line */
- _("GTK+ Options:\n"
- " --class=CLASS Program class as used by the window manager\n"
- " --name=NAME Program name as used by the window manager\n"
- " --screen=SCREEN X screen to use\n"
- " --sync Make X calls synchronous\n"
- " --gtk-module=MODULES Load additional GTK+ modules\n"
- " --g-fatal-warnings Make all warnings fatal"));
- fprintf(stderr,
- "\n\n");
- }
-}
-
-
-static void
-log_cb (const gchar *log_domain, GLogLevelFlags log_level,
- const gchar *message, gpointer data)
-{
- /* Log everything to a file */
- if (log_file) {
- const gchar *prefix;
-
- switch (log_level & G_LOG_LEVEL_MASK) {
- case G_LOG_LEVEL_ERROR:
- prefix = "ERROR:";
- break;
- case G_LOG_LEVEL_CRITICAL:
- prefix = "CRITICAL:";
- break;
- case G_LOG_LEVEL_WARNING:
- prefix = "WARNING:";
- break;
- case G_LOG_LEVEL_MESSAGE:
- prefix = "MESSAGE:";
- break;
- case G_LOG_LEVEL_INFO:
- prefix = "INFO:";
- break;
- case G_LOG_LEVEL_DEBUG:
- prefix = "DEBUG:";
- break;
- default:
- prefix = "LOG:";
- break;
- }
-
- fprintf (log_file, "[%+.2fs] %s %s\n", g_timer_elapsed (log_timer, NULL), prefix, message);
- }
-
- /* Only show debug if requested */
- if (log_level & G_LOG_LEVEL_DEBUG) {
- if (debug)
- g_log_default_handler (log_domain, log_level, message, data);
- }
- else
- g_log_default_handler (log_domain, log_level, message, data);
-}
-
-
-static void
-get_options (int argc, char **argv)
-{
- int i;
-
- for (i = 1; i < argc; i++) {
- char *arg = argv[i];
-
- if (strcmp (arg, "-d") == 0 ||
- strcmp (arg, "--debug") == 0) {
- debug = TRUE;
- }
- else if (strcmp (arg, "-v") == 0 ||
- strcmp (arg, "--version") == 0) {
- version ();
- exit (0);
- }
- else if (strcmp (arg, "-h") == 0 ||
- strcmp (arg, "--help") == 0) {
- usage (FALSE);
- exit (0);
- }
- else if (strcmp (arg, "--help-all") == 0 ||
- strcmp (arg, "--help-gtk") == 0) {
- usage (TRUE);
- exit (0);
- }
- else {
- if (default_device) {
- fprintf (stderr, "Unknown argument: '%s'\n", arg);
- exit (1);
- }
- default_device = g_malloc0 (sizeof (ScanDevice));
- default_device->name = g_strdup (arg);
- default_device->label = g_strdup (arg);
- }
- }
-}
-
-
-static void
-on_uevent (GUdevClient *client, const gchar *action, GUdevDevice *device)
-{
- scanner_redetect (scanner);
-}
-
-
-int
-main (int argc, char **argv)
-{
- const char *udev_subsystems[] = { "usb", NULL };
- gchar *path;
-
- g_thread_init (NULL);
-
- /* Log to a file */
- log_timer = g_timer_new ();
- path = g_build_filename (g_get_user_cache_dir (), "simple-scan", NULL);
- g_mkdir_with_parents (path, 0700);
- g_free (path);
- path = g_build_filename (g_get_user_cache_dir (), "simple-scan", "simple-scan.log", NULL);
- log_file = fopen (path, "w");
- g_free (path);
- g_log_set_default_handler (log_cb, NULL);
-
- bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- textdomain (GETTEXT_PACKAGE);
-
- gtk_init (&argc, &argv);
-
- get_options (argc, argv);
-
- g_debug ("Starting Simple Scan %s, PID=%i", VERSION, getpid ());
-
- ui = ui_new ();
- book = ui_get_book (ui);
- g_signal_connect (ui, "start-scan", G_CALLBACK (scan_cb), NULL);
- g_signal_connect (ui, "stop-scan", G_CALLBACK (cancel_cb), NULL);
- g_signal_connect (ui, "email", G_CALLBACK (email_cb), NULL);
- g_signal_connect (ui, "quit", G_CALLBACK (quit_cb), NULL);
-
- scanner = scanner_new ();
- g_signal_connect (G_OBJECT (scanner), "update-devices", G_CALLBACK (update_scan_devices_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "authorize", G_CALLBACK (authorize_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "expect-page", G_CALLBACK (scanner_new_page_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "got-page-info", G_CALLBACK (scanner_page_info_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "got-line", G_CALLBACK (scanner_line_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "page-done", G_CALLBACK (scanner_page_done_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "document-done", G_CALLBACK (scanner_document_done_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "scan-failed", G_CALLBACK (scanner_failed_cb), NULL);
- g_signal_connect (G_OBJECT (scanner), "scanning-changed", G_CALLBACK (scanner_scanning_changed_cb), NULL);
-
- udev_client = g_udev_client_new (udev_subsystems);
- g_signal_connect (udev_client, "uevent", G_CALLBACK (on_uevent), NULL);
-
- if (default_device) {
- GList device_list;
-
- device_list.data = default_device;
- device_list.next = NULL;
- device_list.prev = NULL;
- ui_set_scan_devices (ui, &device_list);
- ui_set_selected_device (ui, default_device->name);
- }
-
- ui_start (ui);
- scanner_start (scanner);
-
- gtk_main ();
-
- return 0;
+static void application_log_cb (const gchar* log_domain, GLogLevelFlags log_level, const gchar* message) {
+ g_return_if_fail (message != NULL);
+ if (application_log_file != NULL) {
+ gchar* prefix = NULL;
+ gdouble _tmp7_;
+ switch (log_level & G_LOG_LEVEL_MASK) {
+ case G_LOG_LEVEL_ERROR:
+ {
+ gchar* _tmp0_;
+ _tmp0_ = g_strdup ("ERROR:");
+ _g_free0 (prefix);
+ prefix = _tmp0_;
+ break;
+ }
+ case G_LOG_LEVEL_CRITICAL:
+ {
+ gchar* _tmp1_;
+ _tmp1_ = g_strdup ("CRITICAL:");
+ _g_free0 (prefix);
+ prefix = _tmp1_;
+ break;
+ }
+ case G_LOG_LEVEL_WARNING:
+ {
+ gchar* _tmp2_;
+ _tmp2_ = g_strdup ("WARNING:");
+ _g_free0 (prefix);
+ prefix = _tmp2_;
+ break;
+ }
+ case G_LOG_LEVEL_MESSAGE:
+ {
+ gchar* _tmp3_;
+ _tmp3_ = g_strdup ("MESSAGE:");
+ _g_free0 (prefix);
+ prefix = _tmp3_;
+ break;
+ }
+ case G_LOG_LEVEL_INFO:
+ {
+ gchar* _tmp4_;
+ _tmp4_ = g_strdup ("INFO:");
+ _g_free0 (prefix);
+ prefix = _tmp4_;
+ break;
+ }
+ case G_LOG_LEVEL_DEBUG:
+ {
+ gchar* _tmp5_;
+ _tmp5_ = g_strdup ("DEBUG:");
+ _g_free0 (prefix);
+ prefix = _tmp5_;
+ break;
+ }
+ default:
+ {
+ gchar* _tmp6_;
+ _tmp6_ = g_strdup ("LOG:");
+ _g_free0 (prefix);
+ prefix = _tmp6_;
+ break;
+ }
+ }
+ _tmp7_ = g_timer_elapsed (application_log_timer, NULL);
+ fprintf (application_log_file, "[%+.2fs] %s %s\n", _tmp7_, prefix, message);
+ _g_free0 (prefix);
+ }
+ if ((log_level & G_LOG_LEVEL_DEBUG) != 0) {
+ if (application_debug_enabled) {
+ g_log_default_handler (log_domain, log_level, message, NULL);
+ }
+ } else {
+ g_log_default_handler (log_domain, log_level, message, NULL);
+ }
}
+
+
+static void application_on_uevent (Application* self, GUdevClient* client, const gchar* action, GUdevDevice* device) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (client != NULL);
+ g_return_if_fail (action != NULL);
+ g_return_if_fail (device != NULL);
+ scanner_redetect (self->priv->scanner);
+}
+
+
+static void _application_log_cb_glog_func (const gchar* log_domain, GLogLevelFlags log_levels, const gchar* message, gpointer self) {
+ application_log_cb (log_domain, log_levels, message);
+}
+
+
+gint application_main (gchar** args, int args_length1) {
+ gint result = 0;
+ const gchar* _tmp0_ = NULL;
+ GOptionContext* _tmp1_ = NULL;
+ GOptionContext* c;
+ GOptionGroup* _tmp2_ = NULL;
+ ScanDevice* device;
+ GTimer* _tmp7_ = NULL;
+ const gchar* _tmp8_ = NULL;
+ gchar* _tmp9_ = NULL;
+ gchar* path;
+ const gchar* _tmp10_ = NULL;
+ gchar* _tmp11_ = NULL;
+ FILE* _tmp12_ = NULL;
+ pid_t _tmp13_;
+ Application* _tmp14_ = NULL;
+ Application* app;
+ GError * _inner_error_ = NULL;
+ setlocale (LC_ALL, "");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+ gtk_init (&args_length1, &args);
+ _tmp0_ = _ ("[DEVICE...] - Scanning utility");
+ _tmp1_ = g_option_context_new (_tmp0_);
+ c = _tmp1_;
+ g_option_context_add_main_entries (c, APPLICATION_options, GETTEXT_PACKAGE);
+ _tmp2_ = gtk_get_option_group (TRUE);
+ g_option_context_add_group (c, _tmp2_);
+ {
+ g_option_context_parse (c, &args_length1, &args, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch7_g_error;
+ }
+ }
+ goto __finally7;
+ __catch7_g_error:
+ {
+ GError* e = NULL;
+ const gchar* _tmp3_ = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ fprintf (stderr, "%s\n", e->message);
+ _tmp3_ = _ ("Run '%s --help' to see a full list of available command line options.");
+ fprintf (stderr, _tmp3_, args[0]);
+ fprintf (stderr, "\n");
+ result = EXIT_FAILURE;
+ _g_error_free0 (e);
+ _g_option_context_free0 (c);
+ return result;
+ }
+ __finally7:
+ if (_inner_error_ != NULL) {
+ _g_option_context_free0 (c);
+ 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 0;
+ }
+ if (application_show_version) {
+ fprintf (stderr, "simple-scan %s\n", VERSION);
+ result = EXIT_SUCCESS;
+ _g_option_context_free0 (c);
+ return result;
+ }
+ device = NULL;
+ if (args_length1 > 1) {
+ ScanDevice* _tmp4_ = NULL;
+ gchar* _tmp5_;
+ gchar* _tmp6_;
+ _tmp4_ = scan_device_new ();
+ _scan_device_unref0 (device);
+ device = _tmp4_;
+ _tmp5_ = g_strdup (args[1]);
+ _g_free0 (device->name);
+ device->name = _tmp5_;
+ _tmp6_ = g_strdup (args[1]);
+ _g_free0 (device->label);
+ device->label = _tmp6_;
+ }
+ _tmp7_ = g_timer_new ();
+ _g_timer_destroy0 (application_log_timer);
+ application_log_timer = _tmp7_;
+ _tmp8_ = g_get_user_cache_dir ();
+ _tmp9_ = g_build_filename (_tmp8_, "simple-scan", NULL, NULL);
+ path = _tmp9_;
+ g_mkdir_with_parents (path, 0700);
+ _tmp10_ = g_get_user_cache_dir ();
+ _tmp11_ = g_build_filename (_tmp10_, "simple-scan", "simple-scan.log", NULL, NULL);
+ _g_free0 (path);
+ path = _tmp11_;
+ _tmp12_ = fopen (path, "w");
+ _fclose0 (application_log_file);
+ application_log_file = _tmp12_;
+ g_log_set_default_handler (_application_log_cb_glog_func, NULL);
+ _tmp13_ = getpid ();
+ g_debug ("simple-scan.vala:507: Starting Simple Scan %s, PID=%i", VERSION, (gint) _tmp13_);
+ _tmp14_ = application_new (device);
+ app = _tmp14_;
+ application_start (app);
+ gtk_main ();
+ result = EXIT_SUCCESS;
+ _application_unref0 (app);
+ _g_free0 (path);
+ _scan_device_unref0 (device);
+ _g_option_context_free0 (c);
+ return result;
+}
+
+
+int main (int argc, char ** argv) {
+ g_type_init ();
+ return application_main (argv, argc);
+}
+
+
+static void value_application_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
+}
+
+
+static void value_application_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ application_unref (value->data[0].v_pointer);
+ }
+}
+
+
+static void value_application_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = application_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+
+static gpointer value_application_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
+}
+
+
+static gchar* value_application_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ Application* 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 = application_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+
+static gchar* value_application_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ Application** 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 = application_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_application (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecApplication* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_APPLICATION), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_application (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_APPLICATION), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_application (GValue* value, gpointer v_object) {
+ Application* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_APPLICATION));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_APPLICATION));
+ 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;
+ application_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ application_unref (old);
+ }
+}
+
+
+void value_take_application (GValue* value, gpointer v_object) {
+ Application* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_APPLICATION));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_APPLICATION));
+ 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) {
+ application_unref (old);
+ }
+}
+
+
+static void application_class_init (ApplicationClass * klass) {
+ application_parent_class = g_type_class_peek_parent (klass);
+ APPLICATION_CLASS (klass)->finalize = application_finalize;
+ g_type_class_add_private (klass, sizeof (ApplicationPrivate));
+}
+
+
+static void application_instance_init (Application * self) {
+ self->priv = APPLICATION_GET_PRIVATE (self);
+ self->priv->default_device = NULL;
+ self->priv->have_devices = FALSE;
+ self->ref_count = 1;
+}
+
+
+static void application_finalize (Application* obj) {
+ Application * self;
+ self = APPLICATION (obj);
+ _scan_device_unref0 (self->priv->default_device);
+ _g_object_unref0 (self->priv->udev_client);
+ _simple_scan_unref0 (self->priv->ui);
+ _scanner_unref0 (self->priv->scanner);
+ _book_unref0 (self->priv->book);
+}
+
+
+GType application_get_type (void) {
+ static volatile gsize application_type_id__volatile = 0;
+ if (g_once_init_enter (&application_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_application_init, value_application_free_value, value_application_copy_value, value_application_peek_pointer, "p", value_application_collect_value, "p", value_application_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (ApplicationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) application_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Application), 0, (GInstanceInitFunc) application_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 application_type_id;
+ application_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Application", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&application_type_id__volatile, application_type_id);
+ }
+ return application_type_id__volatile;
+}
+
+
+gpointer application_ref (gpointer instance) {
+ Application* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void application_unref (gpointer instance) {
+ Application* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ APPLICATION_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+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]);
+ }
+ }
+ }
+}
+
+
+static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {
+ _vala_array_destroy (array, array_length, destroy_func);
+ g_free (array);
+}
+
+
+
diff --git a/src/simple-scan.vala b/src/simple-scan.vala
new file mode 100644
index 0000000..0ced7ad
--- /dev/null
+++ b/src/simple-scan.vala
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2009-2011 Canonical Ltd.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+public class Application
+{
+ static bool show_version;
+ static bool debug_enabled;
+ public static const OptionEntry[] options =
+ {
+ { "version", 'v', 0, OptionArg.NONE, ref show_version,
+ /* Help string for command line --version flag */
+ N_("Show release version"), null},
+ { "debug", 'd', 0, OptionArg.NONE, ref debug_enabled,
+ /* Help string for command line --debug flag */
+ N_("Print debugging messages"), null},
+ { null }
+ };
+ private static Timer log_timer;
+ private static FileStream? log_file;
+
+ private ScanDevice? default_device = null;
+ private bool have_devices = false;
+ private GUdev.Client udev_client;
+ private SimpleScan ui;
+ private Scanner scanner;
+ private Book book;
+
+ public Application (ScanDevice? device = null)
+ {
+ default_device = device;
+
+ ui = new SimpleScan ();
+ book = ui.get_book ();
+ ui.start_scan.connect (scan_cb);
+ ui.stop_scan.connect (cancel_cb);
+ ui.email.connect (email_cb);
+ ui.quit.connect (quit_cb);
+
+ scanner = Scanner.get_instance ();
+ scanner.update_devices.connect (update_scan_devices_cb);
+ scanner.request_authorization.connect (authorize_cb);
+ scanner.expect_page.connect (scanner_new_page_cb);
+ scanner.got_page_info.connect (scanner_page_info_cb);
+ scanner.got_line.connect (scanner_line_cb);
+ scanner.page_done.connect (scanner_page_done_cb);
+ scanner.document_done.connect (scanner_document_done_cb);
+ scanner.scan_failed.connect (scanner_failed_cb);
+ scanner.scanning_changed.connect (scanner_scanning_changed_cb);
+
+ string[]? subsystems = { "usb", null };
+ udev_client = new GUdev.Client (subsystems);
+ udev_client.uevent.connect (on_uevent);
+
+ if (default_device != null)
+ {
+ List<ScanDevice> device_list = null;
+
+ device_list.append (default_device);
+ ui.set_scan_devices (device_list);
+ ui.set_selected_device (default_device.name);
+ }
+ }
+
+ public void start ()
+ {
+ ui.start ();
+ scanner.start ();
+ }
+
+ private void update_scan_devices_cb (Scanner scanner, List<ScanDevice> devices)
+ {
+ var devices_copy = devices.copy ();
+
+ /* If the default device is not detected add it to the list */
+ if (default_device != null)
+ {
+ var default_in_list = false;
+ foreach (var device in devices_copy)
+ {
+ if (device.name == default_device.name)
+ {
+ default_in_list = true;
+ break;
+ }
+ }
+
+ if (!default_in_list)
+ devices_copy.prepend (default_device);
+ }
+
+ have_devices = devices_copy.length () > 0;
+ ui.set_scan_devices (devices_copy);
+ }
+
+ private void authorize_cb (Scanner scanner, string resource)
+ {
+ string username, password;
+ ui.authorize (resource, out username, out password);
+ scanner.authorize (username, password);
+ }
+
+ private Page append_page ()
+ {
+ /* Use current page if not used */
+ var page = book.get_page (-1);
+ if (page != null && !page.has_data ())
+ {
+ ui.set_selected_page (page);
+ page.start ();
+ return page;
+ }
+
+ /* Copy info from previous page */
+ var scan_direction = ScanDirection.TOP_TO_BOTTOM;
+ bool do_crop = false;
+ string named_crop = null;
+ var width = 100, height = 100, dpi = 100, cx = 0, cy = 0, cw = 0, ch = 0;
+ if (page != null)
+ {
+ scan_direction = page.get_scan_direction ();
+ width = page.get_width ();
+ height = page.get_height ();
+ dpi = page.get_dpi ();
+
+ do_crop = page.has_crop ();
+ if (do_crop)
+ {
+ named_crop = page.get_named_crop ();
+ page.get_crop (out cx, out cy, out cw, out ch);
+ }
+ }
+
+ page = book.append_page (width, height, dpi, scan_direction);
+ if (do_crop)
+ {
+ if (named_crop != null)
+ {
+ page.set_named_crop (named_crop);
+ }
+ else
+ page.set_custom_crop (cw, ch);
+ page.move_crop (cx, cy);
+ }
+ ui.set_selected_page (page);
+ page.start ();
+
+ return page;
+ }
+
+ private void scanner_new_page_cb (Scanner scanner)
+ {
+ append_page ();
+ }
+
+ private string? get_profile_for_device (string device_name)
+ {
+#if HAVE_COLORD
+ var device_id = "sane:%s".printf (device_name);
+ debug ("Getting color profile for device %s", device_name);
+
+ var client = new Colord.Client ();
+ try
+ {
+ client.connect_sync ();
+ }
+ catch (Error e)
+ {
+ debug ("Failed to connect to colord: %s", e.message);
+ return null;
+ }
+
+ Colord.Device device;
+ try
+ {
+ device = client.find_device_by_property_sync (Colord.DEVICE_PROPERTY_SERIAL, device_id);
+ }
+ catch (Error e)
+ {
+ debug ("Unable to find colord device %s: %s", device_name, e.message);
+ return null;
+ }
+
+ try
+ {
+ device.connect_sync ();
+ }
+ catch (Error e)
+ {
+ debug ("Failed to get properties from the device %s: %s", device_name, e.message);
+ return null;
+ }
+
+ var profile = device.get_default_profile ();
+ if (profile == null)
+ {
+ debug ("No default color profile for device: %s", device_name);
+ return null;
+ }
+
+ try
+ {
+ profile.connect_sync ();
+ }
+ catch (Error e)
+ {
+ debug ("Failed to get properties from the profile %s: %s", device_name, e.message);
+ return null;
+ }
+
+ if (profile.filename == null)
+ {
+ debug ("No icc color profile for the device %s", device_name);
+ return null;
+ }
+
+ debug ("Using color profile %s for device %s", profile.filename, device_name);
+ return profile.filename;
+#else
+ return null;
+#endif
+ }
+
+ private void scanner_page_info_cb (Scanner scanner, ScanPageInfo info)
+ {
+ debug ("Page is %d pixels wide, %d pixels high, %d bits per pixel",
+ info.width, info.height, info.depth);
+
+ /* Add a new page */
+ var page = append_page ();
+ page.set_page_info (info);
+
+ /* Get ICC color profile */
+ /* FIXME: The ICC profile could change */
+ /* FIXME: Don't do a D-bus call for each page, cache color profiles */
+ page.set_color_profile (get_profile_for_device (info.device));
+ }
+
+ private void scanner_line_cb (Scanner scanner, ScanLine line)
+ {
+ var page = book.get_page ((int) book.get_n_pages () - 1);
+ page.parse_scan_line (line);
+ }
+
+ private void scanner_page_done_cb (Scanner scanner)
+ {
+ var page = book.get_page ((int) book.get_n_pages () - 1);
+ page.finish ();
+ }
+
+ private void remove_empty_page ()
+ {
+ var page = book.get_page ((int) book.get_n_pages () - 1);
+
+ /* Remove a failed page */
+ if (page.has_data ())
+ page.finish ();
+ else
+ book.delete_page (page);
+ }
+
+ private void scanner_document_done_cb (Scanner scanner)
+ {
+ remove_empty_page ();
+ }
+
+ private void scanner_failed_cb (Scanner scanner, int error_code, string error_string)
+ {
+ remove_empty_page ();
+ if (error_code != Sane.Status.CANCELLED)
+ {
+ ui.show_error (/* Title of error dialog when scan failed */
+ _("Failed to scan"),
+ error_string,
+ have_devices);
+ }
+ }
+
+ private void scanner_scanning_changed_cb (Scanner scanner)
+ {
+ ui.set_scanning (scanner.is_scanning ());
+ }
+
+ private void scan_cb (SimpleScan ui, string? device, ScanOptions options)
+ {
+ debug ("Requesting scan at %d dpi from device '%s'", options.dpi, device);
+
+ if (!scanner.is_scanning ())
+ append_page ();
+
+ /* Default filename to use when saving document (and extension will be added, e.g. .jpg) */
+ string filename_prefix = _("Scanned Document");
+ string extension;
+ if (options.scan_mode == ScanMode.COLOR)
+ extension = "jpg";
+ else
+ extension = "pdf";
+ var filename = "%s.%s".printf (filename_prefix, extension);
+ ui.set_default_file_name (filename);
+ scanner.scan (device, options);
+ }
+
+ private void cancel_cb (SimpleScan ui)
+ {
+ scanner.cancel ();
+ }
+
+ private string? get_temporary_filename (string prefix, string extension)
+ {
+ /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and
+ * use the filename but it appears to work in practise */
+
+ var filename = "%sXXXXXX.%s".printf (prefix, extension);
+ string path;
+ try
+ {
+ var fd = FileUtils.open_tmp (filename, out path);
+ Posix.close (fd);
+ }
+ catch (Error e)
+ {
+ warning ("Error saving email attachment: %s", e.message);
+ return null;
+ }
+
+ return path;
+ }
+
+ private void email_cb (SimpleScan ui, string profile)
+ {
+ var saved = false;
+ var command_line = "xdg-email";
+
+ /* Save text files as PDFs */
+ if (profile == "text")
+ {
+ /* Open a temporary file */
+ var path = get_temporary_filename ("scan", "pdf");
+ if (path != null)
+ {
+ var file = File.new_for_path (path);
+ try
+ {
+ book.save ("pdf", file);
+ }
+ catch (Error e)
+ {
+ warning ("Unable to save email file: %s", e.message);
+ return;
+ }
+ command_line += " --attach %s".printf (path);
+ }
+ }
+ else
+ {
+ for (var i = 0; i < book.get_n_pages (); i++)
+ {
+ var path = get_temporary_filename ("scan", "jpg");
+ if (path == null)
+ {
+ saved = false;
+ break;
+ }
+
+ var file = File.new_for_path (path);
+ try
+ {
+ book.get_page (i).save ("jpeg", file);
+ }
+ catch (Error e)
+ {
+ warning ("Unable to save email file: %s", e.message);
+ return;
+ }
+ command_line += " --attach %s".printf (path);
+
+ if (!saved)
+ break;
+ }
+ }
+
+ debug ("Launching email client: %s", command_line);
+ try
+ {
+ Process.spawn_command_line_async (command_line);
+ }
+ catch (Error e)
+ {
+ warning ("Unable to start email: %s", e.message);
+ }
+ }
+
+ private void quit_cb (SimpleScan ui)
+ {
+ book = null;
+ ui = null;
+ udev_client = null;
+ scanner.free ();
+ Gtk.main_quit ();
+ }
+
+ private static void log_cb (string? log_domain, LogLevelFlags log_level, string message)
+ {
+ /* Log everything to a file */
+ if (log_file != null)
+ {
+ string prefix;
+
+ switch (log_level & LogLevelFlags.LEVEL_MASK)
+ {
+ case LogLevelFlags.LEVEL_ERROR:
+ prefix = "ERROR:";
+ break;
+ case LogLevelFlags.LEVEL_CRITICAL:
+ prefix = "CRITICAL:";
+ break;
+ case LogLevelFlags.LEVEL_WARNING:
+ prefix = "WARNING:";
+ break;
+ case LogLevelFlags.LEVEL_MESSAGE:
+ prefix = "MESSAGE:";
+ break;
+ case LogLevelFlags.LEVEL_INFO:
+ prefix = "INFO:";
+ break;
+ case LogLevelFlags.LEVEL_DEBUG:
+ prefix = "DEBUG:";
+ break;
+ default:
+ prefix = "LOG:";
+ break;
+ }
+
+ log_file.printf ("[%+.2fs] %s %s\n", log_timer.elapsed (), prefix, message);
+ }
+
+ /* Only show debug if requested */
+ if ((log_level & LogLevelFlags.LEVEL_DEBUG) != 0)
+ {
+ if (debug_enabled)
+ Log.default_handler (log_domain, log_level, message);
+ }
+ else
+ Log.default_handler (log_domain, log_level, message);
+ }
+
+ private void on_uevent (GUdev.Client client, string action, GUdev.Device device)
+ {
+ scanner.redetect ();
+ }
+
+ public static int main (string[] args)
+ {
+ Intl.setlocale (LocaleCategory.ALL, "");
+ Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALE_DIR);
+ Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");
+ Intl.textdomain (Config.GETTEXT_PACKAGE);
+
+ Gtk.init (ref args);
+
+ var c = new OptionContext (/* Arguments and description for --help text */
+ _("[DEVICE...] - Scanning utility"));
+ c.add_main_entries (options, Config.GETTEXT_PACKAGE);
+ c.add_group (Gtk.get_option_group (true));
+ try
+ {
+ c.parse (ref args);
+ }
+ catch (Error e)
+ {
+ stderr.printf ("%s\n", e.message);
+ stderr.printf (/* Text printed out when an unknown command-line argument provided */
+ _("Run '%s --help' to see a full list of available command line options."), args[0]);
+ stderr.printf ("\n");
+ return Posix.EXIT_FAILURE;
+ }
+ if (show_version)
+ {
+ /* Note, not translated so can be easily parsed */
+ stderr.printf ("simple-scan %s\n", Config.VERSION);
+ return Posix.EXIT_SUCCESS;
+ }
+
+ ScanDevice? device = null;
+ if (args.length > 1)
+ {
+ device = new ScanDevice ();
+ device.name = args[1];
+ device.label = args[1];
+ }
+
+ /* Log to a file */
+ log_timer = new Timer ();
+ var path = Path.build_filename (Environment.get_user_cache_dir (), "simple-scan", null);
+ DirUtils.create_with_parents (path, 0700);
+ path = Path.build_filename (Environment.get_user_cache_dir (), "simple-scan", "simple-scan.log", null);
+ log_file = FileStream.open (path, "w");
+ Log.set_default_handler (log_cb);
+
+ debug ("Starting Simple Scan %s, PID=%i", Config.VERSION, Posix.getpid ());
+
+ Application app = new Application (device);
+ app.start ();
+
+ Gtk.main ();
+
+ return Posix.EXIT_SUCCESS;
+ }
+}
diff --git a/src/simple_scan_vala.stamp b/src/simple_scan_vala.stamp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/simple_scan_vala.stamp
diff --git a/src/ui.c b/src/ui.c
index a62123c..121d780 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -1,7 +1,10 @@
+/* ui.c generated by valac 0.13.1, the Vala compiler
+ * generated from ui.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,1917 +12,3443 @@
* license.
*/
+#include <glib.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <gconf/gconf-client.h>
+#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
+#include <unistd.h>
+#include <cairo.h>
+#include <float.h>
#include <math.h>
-#include <unistd.h> // TEMP: Needed for close() in get_temporary_filename()
-
-#include "ui.h"
-#include "book-view.h"
-
-
-#define DEFAULT_TEXT_DPI 150
-#define DEFAULT_PHOTO_DPI 300
-
-
-enum {
- START_SCAN,
- STOP_SCAN,
- EMAIL,
- QUIT,
- LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0, };
-
-
-struct SimpleScanPrivate
-{
- GConfClient *client;
-
- GtkBuilder *builder;
-
- GtkWidget *window, *main_vbox;
- GtkWidget *info_bar, *info_bar_image, *info_bar_label;
- GtkWidget *info_bar_close_button, *info_bar_change_scanner_button;
- GtkWidget *page_move_left_menuitem, *page_move_right_menuitem;
- GtkWidget *page_delete_menuitem, *crop_rotate_menuitem;
- GtkWidget *save_menuitem, *save_as_menuitem, *save_toolbutton;
- GtkWidget *stop_menuitem, *stop_toolbutton;
-
- GtkWidget *text_toolbar_menuitem, *text_menu_menuitem;
- GtkWidget *photo_toolbar_menuitem, *photo_menu_menuitem;
-
- GtkWidget *authorize_dialog;
- GtkWidget *authorize_label;
- GtkWidget *username_entry, *password_entry;
-
- GtkWidget *preferences_dialog;
- GtkWidget *device_combo, *text_dpi_combo, *photo_dpi_combo, *page_side_combo, *paper_size_combo;
- GtkTreeModel *device_model, *text_dpi_model, *photo_dpi_model, *page_side_model, *paper_size_model;
- gboolean setting_devices, user_selected_device;
-
- gboolean have_error;
- gchar *error_title, *error_text;
- gboolean error_change_scanner_hint;
-
- Book *book;
- gchar *book_uri;
-
- BookView *book_view;
- gboolean updating_page_menu;
- gint default_page_width, default_page_height, default_page_dpi;
- ScanDirection default_page_scan_direction;
-
- gchar *document_hint;
-
- gchar *default_file_name;
- gboolean scanning;
-
- gint window_width, window_height;
- gboolean window_is_maximized;
+#include <gdk-pixbuf/gdk-pixdata.h>
+#include <gdk/gdk.h>
+#include <config.h>
+#include <gobject/gvaluecollector.h>
+
+
+#define TYPE_SIMPLE_SCAN (simple_scan_get_type ())
+#define SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SIMPLE_SCAN, SimpleScan))
+#define SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SIMPLE_SCAN, SimpleScanClass))
+#define IS_SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SIMPLE_SCAN))
+#define IS_SIMPLE_SCAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SIMPLE_SCAN))
+#define SIMPLE_SCAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SIMPLE_SCAN, SimpleScanClass))
+
+typedef struct _SimpleScan SimpleScan;
+typedef struct _SimpleScanClass SimpleScanClass;
+typedef struct _SimpleScanPrivate SimpleScanPrivate;
+
+#define TYPE_BOOK (book_get_type ())
+#define BOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK, Book))
+#define BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK, BookClass))
+#define IS_BOOK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK))
+#define IS_BOOK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK))
+#define BOOK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK, BookClass))
+
+typedef struct _Book Book;
+typedef struct _BookClass BookClass;
+
+#define TYPE_BOOK_VIEW (book_view_get_type ())
+#define BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BOOK_VIEW, BookView))
+#define BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BOOK_VIEW, BookViewClass))
+#define IS_BOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BOOK_VIEW))
+#define IS_BOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BOOK_VIEW))
+#define BOOK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BOOK_VIEW, BookViewClass))
+
+typedef struct _BookView BookView;
+typedef struct _BookViewClass BookViewClass;
+
+#define TYPE_SCAN_DIRECTION (scan_direction_get_type ())
+#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
+#define _g_free0(var) (var = (g_free (var), NULL))
+#define _book_unref0(var) ((var == NULL) ? NULL : (var = (book_unref (var), NULL)))
+
+#define TYPE_PAGE (page_get_type ())
+#define PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PAGE, Page))
+#define PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PAGE, PageClass))
+#define IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PAGE))
+#define IS_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PAGE))
+#define PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PAGE, PageClass))
+
+typedef struct _Page Page;
+typedef struct _PageClass PageClass;
+
+#define TYPE_SCAN_DEVICE (scan_device_get_type ())
+#define SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_DEVICE, ScanDevice))
+#define SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_DEVICE, ScanDeviceClass))
+#define IS_SCAN_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_DEVICE))
+#define IS_SCAN_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_DEVICE))
+#define SCAN_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_DEVICE, ScanDeviceClass))
+
+typedef struct _ScanDevice ScanDevice;
+typedef struct _ScanDeviceClass ScanDeviceClass;
+typedef struct _ScanDevicePrivate ScanDevicePrivate;
+#define _scan_device_unref0(var) ((var == NULL) ? NULL : (var = (scan_device_unref (var), NULL)))
+#define _page_unref0(var) ((var == NULL) ? NULL : (var = (page_unref (var), NULL)))
+#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
+
+#define TYPE_SCAN_TYPE (scan_type_get_type ())
+
+#define TYPE_SCAN_OPTIONS (scan_options_get_type ())
+#define SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_SCAN_OPTIONS, ScanOptions))
+#define SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_SCAN_OPTIONS, ScanOptionsClass))
+#define IS_SCAN_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_SCAN_OPTIONS))
+#define IS_SCAN_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_SCAN_OPTIONS))
+#define SCAN_OPTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_SCAN_OPTIONS, ScanOptionsClass))
+
+typedef struct _ScanOptions ScanOptions;
+typedef struct _ScanOptionsClass ScanOptionsClass;
+
+#define TYPE_SCAN_MODE (scan_mode_get_type ())
+typedef struct _ScanOptionsPrivate ScanOptionsPrivate;
+#define _scan_options_unref0(var) ((var == NULL) ? NULL : (var = (scan_options_unref (var), NULL)))
+#define _cairo_destroy0(var) ((var == NULL) ? NULL : (var = (cairo_destroy (var), NULL)))
+typedef struct _ParamSpecSimpleScan ParamSpecSimpleScan;
+
+struct _SimpleScan {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ SimpleScanPrivate * priv;
};
-G_DEFINE_TYPE (SimpleScan, ui, G_TYPE_OBJECT);
-
-static struct
-{
- const gchar *key;
- ScanDirection scan_direction;
-} scan_direction_keys[] =
-{
- { "top-to-bottom", TOP_TO_BOTTOM },
- { "bottom-to-top", BOTTOM_TO_TOP },
- { "left-to-right", LEFT_TO_RIGHT },
- { "right-to-left", RIGHT_TO_LEFT },
- { NULL, 0 }
+struct _SimpleScanClass {
+ GTypeClass parent_class;
+ void (*finalize) (SimpleScan *self);
};
+typedef enum {
+ SCAN_DIRECTION_TOP_TO_BOTTOM,
+ SCAN_DIRECTION_LEFT_TO_RIGHT,
+ SCAN_DIRECTION_BOTTOM_TO_TOP,
+ SCAN_DIRECTION_RIGHT_TO_LEFT
+} ScanDirection;
+
+struct _SimpleScanPrivate {
+ GSettings* settings;
+ GtkBuilder* builder;
+ GtkWindow* window;
+ GtkVBox* main_vbox;
+ GtkInfoBar* info_bar;
+ GtkImage* info_bar_image;
+ GtkLabel* info_bar_label;
+ GtkButton* info_bar_close_button;
+ GtkButton* info_bar_change_scanner_button;
+ GtkMenuItem* page_move_left_menuitem;
+ GtkMenuItem* page_move_right_menuitem;
+ GtkMenuItem* page_delete_menuitem;
+ GtkMenuItem* crop_rotate_menuitem;
+ GtkMenuItem* save_menuitem;
+ GtkMenuItem* save_as_menuitem;
+ GtkToolButton* save_toolbutton;
+ GtkMenuItem* stop_menuitem;
+ GtkToolButton* stop_toolbutton;
+ GtkRadioMenuItem* text_toolbar_menuitem;
+ GtkRadioMenuItem* text_menu_menuitem;
+ GtkRadioMenuItem* photo_toolbar_menuitem;
+ GtkRadioMenuItem* photo_menu_menuitem;
+ GtkDialog* authorize_dialog;
+ GtkLabel* authorize_label;
+ GtkEntry* username_entry;
+ GtkEntry* password_entry;
+ GtkDialog* preferences_dialog;
+ GtkComboBox* device_combo;
+ GtkComboBox* text_dpi_combo;
+ GtkComboBox* photo_dpi_combo;
+ GtkComboBox* page_side_combo;
+ GtkComboBox* paper_size_combo;
+ GtkListStore* device_model;
+ GtkListStore* text_dpi_model;
+ GtkListStore* photo_dpi_model;
+ GtkListStore* page_side_model;
+ GtkListStore* paper_size_model;
+ gboolean setting_devices;
+ gboolean user_selected_device;
+ GtkFileChooserDialog* save_dialog;
+ gboolean have_error;
+ gchar* error_title;
+ gchar* error_text;
+ gboolean error_change_scanner_hint;
+ Book* book;
+ gchar* book_uri;
+ BookView* book_view;
+ gboolean updating_page_menu;
+ gint default_page_width;
+ gint default_page_height;
+ gint default_page_dpi;
+ ScanDirection default_page_scan_direction;
+ gchar* document_hint;
+ gchar* default_file_name;
+ gboolean scanning;
+ gint window_width;
+ gint window_height;
+ gboolean window_is_maximized;
+};
-static gboolean
-find_scan_device (SimpleScan *ui, const char *device, GtkTreeIter *iter)
-{
- gboolean have_iter = FALSE;
-
- if (gtk_tree_model_get_iter_first (ui->priv->device_model, iter)) {
- do {
- gchar *d;
- gtk_tree_model_get (ui->priv->device_model, iter, 0, &d, -1);
- if (strcmp (d, device) == 0)
- have_iter = TRUE;
- g_free (d);
- } while (!have_iter && gtk_tree_model_iter_next (ui->priv->device_model, iter));
- }
-
- return have_iter;
-}
-
-
-static void
-show_error_dialog (SimpleScan *ui, const char *error_title, const char *error_text)
-{
- GtkWidget *dialog;
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (ui->priv->window),
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_NONE,
- "%s", error_title);
- gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CLOSE, 0);
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error_text);
- gtk_widget_destroy (dialog);
-}
-
-
-void
-ui_set_default_file_name (SimpleScan *ui, const gchar *default_file_name)
-{
- g_free (ui->priv->default_file_name);
- ui->priv->default_file_name = g_strdup (default_file_name);
-}
-
-
-void
-ui_authorize (SimpleScan *ui, const gchar *resource, gchar **username, gchar **password)
-{
- GString *description;
-
- description = g_string_new ("");
- g_string_printf (description,
- /* Label in authorization dialog. '%s' is replaced with the name of the resource requesting authorization */
- _("Username and password required to access '%s'"),
- resource);
-
- gtk_entry_set_text (GTK_ENTRY (ui->priv->username_entry), *username ? *username : "");
- gtk_entry_set_text (GTK_ENTRY (ui->priv->password_entry), "");
- gtk_label_set_text (GTK_LABEL (ui->priv->authorize_label), description->str);
- g_string_free (description, TRUE);
-
- gtk_widget_show (ui->priv->authorize_dialog);
- gtk_dialog_run (GTK_DIALOG (ui->priv->authorize_dialog));
- gtk_widget_hide (ui->priv->authorize_dialog);
-
- *username = g_strdup (gtk_entry_get_text (GTK_ENTRY (ui->priv->username_entry)));
- *password = g_strdup (gtk_entry_get_text (GTK_ENTRY (ui->priv->password_entry)));
-}
-
-
-void device_combo_changed_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-device_combo_changed_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (ui->priv->setting_devices)
- return;
- ui->priv->user_selected_device = TRUE;
-}
-
-
-static void
-update_info_bar (SimpleScan *ui)
-{
- GtkMessageType type;
- const gchar *title, *text, *image_id;
- gchar *message;
- gboolean show_close_button = FALSE;
- gboolean show_change_scanner_button = FALSE;
-
- if (ui->priv->have_error) {
- type = GTK_MESSAGE_ERROR;
- image_id = GTK_STOCK_DIALOG_ERROR;
- title = ui->priv->error_title;
- text = ui->priv->error_text;
- show_close_button = TRUE;
- show_change_scanner_button = ui->priv->error_change_scanner_hint;
- }
- else if (gtk_tree_model_iter_n_children (ui->priv->device_model, NULL) == 0) {
- type = GTK_MESSAGE_WARNING;
- image_id = GTK_STOCK_DIALOG_WARNING;
- /* Warning displayed when no scanners are detected */
- title = _("No scanners detected");
- /* Hint to user on why there are no scanners detected */
- text = _("Please check your scanner is connected and powered on");
- }
- else {
- gtk_widget_hide (ui->priv->info_bar);
- return;
- }
-
- gtk_info_bar_set_message_type (GTK_INFO_BAR (ui->priv->info_bar), type);
- gtk_image_set_from_stock (GTK_IMAGE (ui->priv->info_bar_image), image_id, GTK_ICON_SIZE_DIALOG);
- message = g_strdup_printf ("<big><b>%s</b></big>\n\n%s", title, text);
- gtk_label_set_markup (GTK_LABEL (ui->priv->info_bar_label), message);
- g_free (message);
- gtk_widget_set_visible (ui->priv->info_bar_close_button, show_close_button);
- gtk_widget_set_visible (ui->priv->info_bar_change_scanner_button, show_change_scanner_button);
- gtk_widget_show (ui->priv->info_bar);
-}
-
-
-void
-ui_set_scan_devices (SimpleScan *ui, GList *devices)
-{
- GList *d;
- gboolean have_selection = FALSE;
- gint index;
- GtkTreeIter iter;
-
- ui->priv->setting_devices = TRUE;
-
- /* If the user hasn't chosen a scanner choose the best available one */
- if (ui->priv->user_selected_device)
- have_selection = gtk_combo_box_get_active (GTK_COMBO_BOX (ui->priv->device_combo)) >= 0;
-
- /* Add new devices */
- index = 0;
- for (d = devices; d; d = d->next) {
- ScanDevice *device = (ScanDevice *) d->data;
- gint n_delete = -1;
-
- /* Find if already exists */
- if (gtk_tree_model_iter_nth_child (ui->priv->device_model, &iter, NULL, index)) {
- gint i = 0;
- do {
- gchar *name;
- gboolean matched;
-
- gtk_tree_model_get (ui->priv->device_model, &iter, 0, &name, -1);
- matched = strcmp (name, device->name) == 0;
- g_free (name);
-
- if (matched) {
- n_delete = i;
- break;
- }
- i++;
- } while (gtk_tree_model_iter_next (ui->priv->device_model, &iter));
- }
-
- /* If exists, remove elements up to this one */
- if (n_delete >= 0) {
- gint i;
-
- /* Update label */
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->device_model), &iter, 1, device->label, -1);
-
- for (i = 0; i < n_delete; i++) {
- gtk_tree_model_iter_nth_child (ui->priv->device_model, &iter, NULL, index);
- gtk_list_store_remove (GTK_LIST_STORE (ui->priv->device_model), &iter);
- }
- }
- else {
- gtk_list_store_insert (GTK_LIST_STORE (ui->priv->device_model), &iter, index);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->device_model), &iter, 0, device->name, 1, device->label, -1);
- }
- index++;
- }
-
- /* Remove any remaining devices */
- while (gtk_tree_model_iter_nth_child (ui->priv->device_model, &iter, NULL, index))
- gtk_list_store_remove (GTK_LIST_STORE (ui->priv->device_model), &iter);
-
- /* Select the first available device */
- if (!have_selection && devices != NULL)
- gtk_combo_box_set_active (GTK_COMBO_BOX (ui->priv->device_combo), 0);
-
- ui->priv->setting_devices = FALSE;
-
- update_info_bar (ui);
-}
-
-
-static gchar *
-get_selected_device (SimpleScan *ui)
-{
- GtkTreeIter iter;
-
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->device_combo), &iter)) {
- gchar *device;
- gtk_tree_model_get (ui->priv->device_model, &iter, 0, &device, -1);
- return device;
- }
-
- return NULL;
-}
-
-
-void
-ui_set_selected_device (SimpleScan *ui, const gchar *device)
-{
- GtkTreeIter iter;
-
- if (!find_scan_device (ui, device, &iter))
- return;
-
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->device_combo), &iter);
- ui->priv->user_selected_device = TRUE;
-}
-
-
-static void
-add_default_page (SimpleScan *ui)
-{
- Page *page;
-
- page = book_append_page (ui->priv->book,
- ui->priv->default_page_width,
- ui->priv->default_page_height,
- ui->priv->default_page_dpi,
- ui->priv->default_page_scan_direction);
- book_view_select_page (ui->priv->book_view, page);
-}
-
-
-static void
-on_file_type_changed (GtkTreeSelection *selection, GtkWidget *dialog)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- gchar *path, *filename, *extension, *new_filename;
-
- if (!gtk_tree_selection_get_selected (selection, &model, &iter))
- return;
-
- gtk_tree_model_get (model, &iter, 1, &extension, -1);
- path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
- filename = g_path_get_basename (path);
-
- /* Replace extension */
- if (g_strrstr (filename, "."))
- new_filename = g_strdup_printf ("%.*s%s", (int)(g_strrstr (filename, ".") - filename), filename, extension);
- else
- new_filename = g_strdup_printf ("%s%s", filename, extension);
- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), new_filename);
-
- g_free (path);
- g_free (filename);
- g_free (new_filename);
- g_free (extension);
-}
-
-
-static gchar *
-choose_file_location (SimpleScan *ui)
-{
- GtkWidget *dialog;
- gint response;
- GtkFileFilter *filter;
- GtkWidget *expander, *file_type_view;
- GtkListStore *file_type_store;
- GtkTreeIter iter;
- GtkTreeViewColumn *column;
- const gchar *extension;
- gchar *directory, *uri = NULL;
- gint i;
-
- struct
- {
- gchar *label, *extension;
- } file_types[] =
- {
- /* Save dialog: Label for saving in PDF format */
- { _("PDF (multi-page document)"), ".pdf" },
- /* Save dialog: Label for saving in JPEG format */
- { _("JPEG (compressed)"), ".jpg" },
- /* Save dialog: Label for saving in PNG format */
- { _("PNG (lossless)"), ".png" },
- { NULL, NULL }
- };
-
- /* Get directory to save to */
- directory = gconf_client_get_string (ui->priv->client, GCONF_DIR "/save_directory", NULL);
- if (!directory || directory[0] == '\0') {
- g_free (directory);
- directory = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
- }
-
- dialog = gtk_file_chooser_dialog_new (/* Save dialog: Dialog title */
- _("Save As..."),
- GTK_WINDOW (ui->priv->window),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
- gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE);
- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), directory);
- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), ui->priv->default_file_name);
- g_free (directory);
-
- /* Filter to only show images by default */
- filter = gtk_file_filter_new ();
- gtk_file_filter_set_name (filter,
- /* Save dialog: Filter name to show only image files */
- _("Image Files"));
- gtk_file_filter_add_pixbuf_formats (filter);
- gtk_file_filter_add_mime_type (filter, "application/pdf");
- gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
- filter = gtk_file_filter_new ();
- gtk_file_filter_set_name (filter,
- /* Save dialog: Filter name to show all files */
- _("All Files"));
- gtk_file_filter_add_pattern (filter, "*");
- gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
-
- expander = gtk_expander_new_with_mnemonic (/* */
- _("Select File _Type"));
- gtk_expander_set_spacing (GTK_EXPANDER (expander), 5);
- gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), expander);
-
- extension = strstr (ui->priv->default_file_name, ".");
- if (!extension)
- extension = "";
-
- file_type_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
- for (i = 0; file_types[i].label; i++) {
- gtk_list_store_append (file_type_store, &iter);
- gtk_list_store_set (file_type_store, &iter, 0, file_types[i].label, 1, file_types[i].extension, -1);
- }
-
- file_type_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file_type_store));
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (file_type_view), FALSE);
- gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (file_type_view), TRUE);
- column = gtk_tree_view_column_new_with_attributes ("",
- gtk_cell_renderer_text_new (),
- "text", 0, NULL);
- gtk_tree_view_append_column (GTK_TREE_VIEW (file_type_view), column);
- gtk_container_add (GTK_CONTAINER (expander), file_type_view);
-
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (file_type_store), &iter)) {
- do {
- gchar *e;
- gtk_tree_model_get (GTK_TREE_MODEL (file_type_store), &iter, 1, &e, -1);
- if (strcmp (extension, e) == 0)
- gtk_tree_selection_select_iter (gtk_tree_view_get_selection (GTK_TREE_VIEW (file_type_view)), &iter);
- g_free (e);
- } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (file_type_store), &iter));
- }
- g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (file_type_view)),
- "changed",
- G_CALLBACK (on_file_type_changed),
- dialog);
-
- gtk_widget_show_all (expander);
-
- response = gtk_dialog_run (GTK_DIALOG (dialog));
-
- if (response == GTK_RESPONSE_ACCEPT)
- uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
-
- gconf_client_set_string (ui->priv->client, GCONF_DIR "/save_directory",
- gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)),
- NULL);
-
- gtk_widget_destroy (dialog);
-
- return uri;
-}
-
-
-static gboolean
-save_document (SimpleScan *ui, gboolean force_choose_location)
-{
- gboolean result;
- gchar *uri, *uri_lower;
- GError *error = NULL;
- GFile *file;
-
- if (ui->priv->book_uri && !force_choose_location)
- uri = g_strdup (ui->priv->book_uri);
- else
- uri = choose_file_location (ui);
- if (!uri)
- return FALSE;
-
- file = g_file_new_for_uri (uri);
-
- g_debug ("Saving to '%s'", uri);
-
- uri_lower = g_utf8_strdown (uri, -1);
- if (g_str_has_suffix (uri_lower, ".pdf"))
- result = book_save (ui->priv->book, "pdf", file, &error);
- else if (g_str_has_suffix (uri_lower, ".ps"))
- result = book_save (ui->priv->book, "ps", file, &error);
- else if (g_str_has_suffix (uri_lower, ".png"))
- result = book_save (ui->priv->book, "png", file, &error);
- else if (g_str_has_suffix (uri_lower, ".tif") || g_str_has_suffix (uri_lower, ".tiff"))
- result = book_save (ui->priv->book, "tiff", file, &error);
- else
- result = book_save (ui->priv->book, "jpeg", file, &error);
-
- g_free (uri_lower);
-
- if (result) {
- g_free (ui->priv->book_uri);
- ui->priv->book_uri = uri;
- book_set_needs_saving (ui->priv->book, FALSE);
- }
- else {
- g_free (uri);
-
- g_warning ("Error saving file: %s", error->message);
- ui_show_error (ui,
- /* Title of error dialog when save failed */
- _("Failed to save file"),
- error->message,
- FALSE);
- g_clear_error (&error);
- }
-
- g_object_unref (file);
-
- return result;
-}
-
-
-static gboolean
-prompt_to_save (SimpleScan *ui, const gchar *title, const gchar *discard_label)
-{
- GtkWidget *dialog;
- gint response;
-
- if (!book_get_needs_saving (ui->priv->book))
- return TRUE;
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (ui->priv->window),
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_NONE,
- "%s", title);
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s",
- /* Text in dialog warning when a document is about to be lost*/
- _("If you don't save, changes will be permanently lost."));
- gtk_dialog_add_button (GTK_DIALOG (dialog), discard_label, GTK_RESPONSE_NO);
- gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
- gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_SAVE, GTK_RESPONSE_YES);
-
- response = gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-
- switch (response) {
- case GTK_RESPONSE_YES:
- if (save_document (ui, FALSE))
- return TRUE;
- else
- return FALSE;
- case GTK_RESPONSE_CANCEL:
- return FALSE;
- case GTK_RESPONSE_NO:
- default:
- return TRUE;
- }
-}
-
-
-static void
-clear_document (SimpleScan *ui)
-{
- book_clear (ui->priv->book);
- add_default_page (ui);
- g_free (ui->priv->book_uri);
- ui->priv->book_uri = NULL;
- book_set_needs_saving (ui->priv->book, FALSE);
- gtk_widget_set_sensitive (ui->priv->save_as_menuitem, FALSE);
-}
-
-
-void new_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-new_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (!prompt_to_save (ui,
- /* Text in dialog warning when a document is about to be lost */
- _("Save current document?"),
- /* Button in dialog to create new document and discard unsaved document */
- _("Discard Changes")))
- return;
-
- clear_document (ui);
-}
-
-
-static void
-set_document_hint (SimpleScan *ui, const gchar *document_hint)
-{
- g_free (ui->priv->document_hint);
- ui->priv->document_hint = g_strdup (document_hint);
-
- if (strcmp (document_hint, "text") == 0) {
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->text_toolbar_menuitem), TRUE);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->text_menu_menuitem), TRUE);
- }
- else if (strcmp (document_hint, "photo") == 0) {
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->photo_toolbar_menuitem), TRUE);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (ui->priv->photo_menu_menuitem), TRUE);
- }
-}
-
-
-void text_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-text_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_document_hint (ui, "text");
-}
-
-
-void photo_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-photo_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_document_hint (ui, "photo");
-}
-
-
-static void
-set_page_side (SimpleScan *ui, const gchar *document_hint)
-{
- GtkTreeIter iter;
-
- if (gtk_tree_model_get_iter_first (ui->priv->page_side_model, &iter)) {
- do {
- gchar *d;
- gboolean have_match;
-
- gtk_tree_model_get (ui->priv->page_side_model, &iter, 0, &d, -1);
- have_match = strcmp (d, document_hint) == 0;
- g_free (d);
-
- if (have_match) {
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->page_side_combo), &iter);
- return;
- }
- } while (gtk_tree_model_iter_next (ui->priv->page_side_model, &iter));
- }
-}
-
-
-static void
-set_paper_size (SimpleScan *ui, gint width, gint height)
-{
- GtkTreeIter iter;
- gboolean have_iter;
-
- for (have_iter = gtk_tree_model_get_iter_first (ui->priv->paper_size_model, &iter);
- have_iter;
- have_iter = gtk_tree_model_iter_next (ui->priv->paper_size_model, &iter)) {
- gint w, h;
-
- gtk_tree_model_get (ui->priv->paper_size_model, &iter, 0, &w, 1, &h, -1);
- if (w == width && h == height)
- break;
- }
-
- if (!have_iter)
- have_iter = gtk_tree_model_get_iter_first (ui->priv->paper_size_model, &iter);
- if (have_iter)
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->paper_size_combo), &iter);
-}
-
-
-static gint
-get_text_dpi (SimpleScan *ui)
-{
- GtkTreeIter iter;
- gint dpi = DEFAULT_TEXT_DPI;
-
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->text_dpi_combo), &iter))
- gtk_tree_model_get (ui->priv->text_dpi_model, &iter, 0, &dpi, -1);
-
- return dpi;
-}
-
-
-static gint
-get_photo_dpi (SimpleScan *ui)
-{
- GtkTreeIter iter;
- gint dpi = DEFAULT_PHOTO_DPI;
-
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->photo_dpi_combo), &iter))
- gtk_tree_model_get (ui->priv->photo_dpi_model, &iter, 0, &dpi, -1);
-
- return dpi;
-}
-
-
-static gchar *
-get_page_side (SimpleScan *ui)
-{
- GtkTreeIter iter;
- gchar *mode = NULL;
-
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->page_side_combo), &iter))
- gtk_tree_model_get (ui->priv->page_side_model, &iter, 0, &mode, -1);
-
- return mode;
-}
-
-
-static gboolean
-get_paper_size (SimpleScan *ui, gint *width, gint *height)
-{
- GtkTreeIter iter;
-
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (ui->priv->paper_size_combo), &iter)) {
- gtk_tree_model_get (ui->priv->paper_size_model, &iter, 0, width, 1, height, -1);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-static ScanOptions *
-get_scan_options (SimpleScan *ui)
-{
- struct {
- const gchar *name;
- ScanMode mode;
- gint depth;
- } profiles[] =
- {
- { "text", SCAN_MODE_GRAY, 2 },
- { "photo", SCAN_MODE_COLOR, 8 },
- { NULL, SCAN_MODE_COLOR, 8 }
- };
- gint i;
- ScanOptions *options;
-
- /* Find this profile */
- // FIXME: Move this into scan-profile.c
- for (i = 0; profiles[i].name && strcmp (profiles[i].name, ui->priv->document_hint) != 0; i++);
-
- options = g_malloc0 (sizeof (ScanOptions));
- options->scan_mode = profiles[i].mode;
- options->depth = profiles[i].depth;
- if (options->scan_mode == SCAN_MODE_COLOR)
- options->dpi = get_photo_dpi (ui);
- else
- options->dpi = get_text_dpi (ui);
- get_paper_size (ui, &options->paper_width, &options->paper_height);
-
- return options;
-}
-
-
-void scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- gchar *device;
- ScanOptions *options;
-
- device = get_selected_device (ui);
-
- options = get_scan_options (ui);
- options->type = SCAN_SINGLE;
- g_signal_emit (G_OBJECT (ui), signals[START_SCAN], 0, device, options);
- g_free (device);
- g_free (options);
-}
-
-
-void stop_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-stop_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- g_signal_emit (G_OBJECT (ui), signals[STOP_SCAN], 0);
-}
-
-
-void continuous_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-continuous_scan_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (ui->priv->scanning) {
- g_signal_emit (G_OBJECT (ui), signals[STOP_SCAN], 0);
- } else {
- gchar *device, *side;
- ScanOptions *options;
-
- device = get_selected_device (ui);
- options = get_scan_options (ui);
- side = get_page_side (ui);
- if (strcmp (side, "front") == 0)
- options->type = SCAN_ADF_FRONT;
- else if (strcmp (side, "back") == 0)
- options->type = SCAN_ADF_BACK;
- else
- options->type = SCAN_ADF_BOTH;
-
- g_signal_emit (G_OBJECT (ui), signals[START_SCAN], 0, device, options);
- g_free (device);
- g_free (side);
- g_free (options);
- }
-}
-
-
-void preferences_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-preferences_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- gtk_window_present (GTK_WINDOW (ui->priv->preferences_dialog));
-}
-
-
-gboolean preferences_dialog_delete_event_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-gboolean
-preferences_dialog_delete_event_cb (GtkWidget *widget, SimpleScan *ui)
-{
- return TRUE;
-}
-
-
-void preferences_dialog_response_cb (GtkWidget *widget, gint response_id, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-preferences_dialog_response_cb (GtkWidget *widget, gint response_id, SimpleScan *ui)
-{
- gtk_widget_hide (ui->priv->preferences_dialog);
-}
-
-
-static void
-update_page_menu (SimpleScan *ui)
-{
- Book *book;
- gint index;
-
- book = book_view_get_book (ui->priv->book_view);
- index = book_get_page_index (book, book_view_get_selected (ui->priv->book_view));
- gtk_widget_set_sensitive (ui->priv->page_move_left_menuitem, index > 0);
- gtk_widget_set_sensitive (ui->priv->page_move_right_menuitem, index < book_get_n_pages (book) - 1);
-}
-
-
-static void
-page_selected_cb (BookView *view, Page *page, SimpleScan *ui)
-{
- char *name = NULL;
-
- if (page == NULL)
- return;
-
- ui->priv->updating_page_menu = TRUE;
-
- update_page_menu (ui);
-
- if (page_has_crop (page)) {
- char *crop_name;
-
- // FIXME: Make more generic, move into page-size.c and reuse
- crop_name = page_get_named_crop (page);
- if (crop_name) {
- if (strcmp (crop_name, "A4") == 0)
- name = "a4_menuitem";
- else if (strcmp (crop_name, "A5") == 0)
- name = "a5_menuitem";
- else if (strcmp (crop_name, "A6") == 0)
- name = "a6_menuitem";
- else if (strcmp (crop_name, "letter") == 0)
- name = "letter_menuitem";
- else if (strcmp (crop_name, "legal") == 0)
- name = "legal_menuitem";
- else if (strcmp (crop_name, "4x6") == 0)
- name = "4x6_menuitem";
- g_free (crop_name);
- }
- else
- name = "custom_crop_menuitem";
- }
- else
- name = "no_crop_menuitem";
-
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (ui->priv->builder, name)), TRUE);
- gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (gtk_builder_get_object (ui->priv->builder, "crop_toolbutton")), page_has_crop (page));
-
- ui->priv->updating_page_menu = FALSE;
-}
-
-
-// FIXME: Duplicated from simple-scan.c
-static gchar *
-get_temporary_filename (const gchar *prefix, const gchar *extension)
-{
- gint fd;
- gchar *filename, *path;
- GError *error = NULL;
-
- /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and
- * use the filename but it appears to work in practise */
-
- filename = g_strdup_printf ("%s-XXXXXX.%s", prefix, extension);
- fd = g_file_open_tmp (filename, &path, &error);
- g_free (filename);
- if (fd < 0) {
- g_warning ("Error saving page for viewing: %s", error->message);
- g_clear_error (&error);
- return NULL;
- }
- close (fd);
-
- return path;
-}
-
-
-static void
-show_page_cb (BookView *view, Page *page, SimpleScan *ui)
-{
- gchar *path;
- GFile *file;
- GdkScreen *screen;
- GError *error = NULL;
-
- path = get_temporary_filename ("scanned-page", "tiff");
- if (!path)
- return;
- file = g_file_new_for_path (path);
- g_free (path);
-
- screen = gtk_widget_get_screen (GTK_WIDGET (ui->priv->window));
-
- if (page_save (page, "tiff", file, &error)) {
- gchar *uri = g_file_get_uri (file);
- gtk_show_uri (screen, uri, gtk_get_current_event_time (), &error);
- g_free (uri);
- }
-
- g_object_unref (file);
-
- if (error) {
- show_error_dialog (ui,
- /* Error message display when unable to preview image */
- _("Unable to open image preview application"),
- error->message);
- g_clear_error (&error);
- }
-}
-
-
-static void
-show_page_menu_cb (BookView *view, SimpleScan *ui)
-{
- gtk_menu_popup (GTK_MENU (gtk_builder_get_object (ui->priv->builder, "page_menu")), NULL, NULL, NULL, NULL,
- 3, gtk_get_current_event_time());
-}
-
-
-void rotate_left_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-rotate_left_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- Page *page;
-
- if (ui->priv->updating_page_menu)
- return;
- page = book_view_get_selected (ui->priv->book_view);
- page_rotate_left (page);
-}
-
-
-void rotate_right_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-rotate_right_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- Page *page;
-
- if (ui->priv->updating_page_menu)
- return;
- page = book_view_get_selected (ui->priv->book_view);
- page_rotate_right (page);
-}
-
-
-static void
-set_crop (SimpleScan *ui, const gchar *crop_name)
-{
- Page *page;
-
- gtk_widget_set_sensitive (ui->priv->crop_rotate_menuitem, crop_name != NULL);
-
- if (ui->priv->updating_page_menu)
- return;
-
- page = book_view_get_selected (ui->priv->book_view);
- if (!page)
- return;
-
- if (!crop_name) {
- page_set_no_crop (page);
- return;
- }
-
- if (strcmp (crop_name, "custom") == 0) {
- gint width, height, crop_width, crop_height;
-
- width = page_get_width (page);
- height = page_get_height (page);
-
- crop_width = (int) (width * 0.8 + 0.5);
- crop_height = (int) (height * 0.8 + 0.5);
- page_set_custom_crop (page, crop_width, crop_height);
- page_move_crop (page, (width - crop_width) / 2, (height - crop_height) / 2);
-
- return;
- }
-
- page_set_named_crop (page, crop_name);
-}
-
-
-void no_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-no_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, NULL);
-}
-
-
-void custom_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-custom_crop_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, "custom");
-}
-
-void crop_toolbutton_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-crop_toolbutton_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (ui->priv->updating_page_menu)
- return;
-
- if (gtk_toggle_tool_button_get_active (GTK_TOGGLE_TOOL_BUTTON (widget)))
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (ui->priv->builder, "custom_crop_menuitem")), TRUE);
- else
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_builder_get_object (ui->priv->builder, "no_crop_menuitem")), TRUE);
-}
-
-
-void four_by_six_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-four_by_six_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, "4x6");
-}
-
-
-void legal_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-legal_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, "legal");
-}
-
-
-void letter_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-letter_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, "letter");
-}
-
-
-void a6_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-a6_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, "A6");
-}
-
-
-void a5_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-a5_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, "A5");
-}
+struct _ScanDevice {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanDevicePrivate * priv;
+ gchar* name;
+ gchar* label;
+};
-
-void a4_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-a4_menuitem_toggled_cb (GtkWidget *widget, SimpleScan *ui)
-{
- if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
- set_crop (ui, "A4");
-}
+struct _ScanDeviceClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanDevice *self);
+};
+typedef enum {
+ SCAN_TYPE_SINGLE,
+ SCAN_TYPE_ADF_FRONT,
+ SCAN_TYPE_ADF_BACK,
+ SCAN_TYPE_ADF_BOTH
+} ScanType;
+
+typedef enum {
+ SCAN_MODE_DEFAULT,
+ SCAN_MODE_COLOR,
+ SCAN_MODE_GRAY,
+ SCAN_MODE_LINEART
+} ScanMode;
+
+struct _ScanOptions {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ ScanOptionsPrivate * priv;
+ gint dpi;
+ ScanMode scan_mode;
+ gint depth;
+ ScanType type;
+ gint paper_width;
+ gint paper_height;
+};
-void crop_rotate_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-crop_rotate_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui)
-{
- Page *page;
-
- page = book_view_get_selected (ui->priv->book_view);
- if (!page)
- return;
-
- page_rotate_crop (page);
-}
+struct _ScanOptionsClass {
+ GTypeClass parent_class;
+ void (*finalize) (ScanOptions *self);
+};
+struct _ParamSpecSimpleScan {
+ GParamSpec parent_instance;
+};
-void page_move_left_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-page_move_left_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui)
-{
- Book *book = book_view_get_book (ui->priv->book_view);
- Page *page = book_view_get_selected (ui->priv->book_view);
- gint index;
- index = book_get_page_index (book, page);
- if (index > 0)
- book_move_page (book, page, index - 1);
+static gpointer simple_scan_parent_class = NULL;
+
+gpointer simple_scan_ref (gpointer instance);
+void simple_scan_unref (gpointer instance);
+GParamSpec* param_spec_simple_scan (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_simple_scan (GValue* value, gpointer v_object);
+void value_take_simple_scan (GValue* value, gpointer v_object);
+gpointer value_get_simple_scan (const GValue* value);
+GType simple_scan_get_type (void) G_GNUC_CONST;
+gpointer book_ref (gpointer instance);
+void book_unref (gpointer instance);
+GParamSpec* param_spec_book (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_book (GValue* value, gpointer v_object);
+void value_take_book (GValue* value, gpointer v_object);
+gpointer value_get_book (const GValue* value);
+GType book_get_type (void) G_GNUC_CONST;
+GType book_view_get_type (void) G_GNUC_CONST;
+GType scan_direction_get_type (void) G_GNUC_CONST;
+#define SIMPLE_SCAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_SIMPLE_SCAN, SimpleScanPrivate))
+enum {
+ SIMPLE_SCAN_DUMMY_PROPERTY
+};
+#define SIMPLE_SCAN_DEFAULT_TEXT_DPI 150
+#define SIMPLE_SCAN_DEFAULT_PHOTO_DPI 300
+SimpleScan* simple_scan_new (void);
+SimpleScan* simple_scan_construct (GType object_type);
+Book* book_new (void);
+Book* book_construct (GType object_type);
+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;
+static void simple_scan_page_removed_cb (SimpleScan* self, Book* book, Page* page);
+static void _simple_scan_page_removed_cb_book_page_removed (Book* _sender, Page* page, gpointer self);
+static void simple_scan_page_added_cb (SimpleScan* self, Book* book, Page* page);
+static void _simple_scan_page_added_cb_book_page_added (Book* _sender, Page* page, gpointer self);
+static void simple_scan_load (SimpleScan* self);
+static gboolean simple_scan_find_scan_device (SimpleScan* self, const gchar* device, GtkTreeIter* iter);
+static void simple_scan_show_error_dialog (SimpleScan* self, const gchar* error_title, const gchar* error_text);
+void simple_scan_set_default_file_name (SimpleScan* self, const gchar* default_file_name);
+void simple_scan_authorize (SimpleScan* self, const gchar* resource, gchar** username, gchar** password);
+void G_MODULE_EXPORT device_combo_changed_cb (GtkWidget* widget, SimpleScan* self);
+static void simple_scan_update_info_bar (SimpleScan* self);
+gpointer scan_device_ref (gpointer instance);
+void scan_device_unref (gpointer instance);
+GParamSpec* param_spec_scan_device (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scan_device (GValue* value, gpointer v_object);
+void value_take_scan_device (GValue* value, gpointer v_object);
+gpointer value_get_scan_device (const GValue* value);
+GType scan_device_get_type (void) G_GNUC_CONST;
+void simple_scan_set_scan_devices (SimpleScan* self, GList* devices);
+static gchar* simple_scan_get_selected_device (SimpleScan* self);
+void simple_scan_set_selected_device (SimpleScan* self, const gchar* device);
+static void simple_scan_add_default_page (SimpleScan* self);
+Page* book_append_page (Book* self, gint width, gint height, gint dpi, ScanDirection scan_direction);
+void book_view_select_page (BookView* self, Page* page);
+static void simple_scan_on_file_type_changed (SimpleScan* self, GtkTreeSelection* selection);
+static gchar* simple_scan_choose_file_location (SimpleScan* self);
+static void _simple_scan_on_file_type_changed_gtk_tree_selection_changed (GtkTreeSelection* _sender, gpointer self);
+static gboolean simple_scan_save_document (SimpleScan* self, gboolean force_choose_location);
+void book_save (Book* self, const gchar* type, GFile* file, GError** error);
+void simple_scan_show_error (SimpleScan* self, const gchar* error_title, const gchar* error_text, gboolean change_scanner_hint);
+void book_set_needs_saving (Book* self, gboolean needs_saving);
+static gboolean simple_scan_prompt_to_save (SimpleScan* self, const gchar* title, const gchar* discard_label);
+gboolean book_get_needs_saving (Book* self);
+static void simple_scan_clear_document (SimpleScan* self);
+void book_clear (Book* self);
+void G_MODULE_EXPORT new_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+static void simple_scan_set_document_hint (SimpleScan* self, const gchar* document_hint);
+void G_MODULE_EXPORT text_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT photo_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+GType scan_type_get_type (void) G_GNUC_CONST;
+static void simple_scan_set_page_side (SimpleScan* self, ScanType page_side);
+static void simple_scan_set_paper_size (SimpleScan* self, gint width, gint height);
+static gint simple_scan_get_text_dpi (SimpleScan* self);
+static gint simple_scan_get_photo_dpi (SimpleScan* self);
+static ScanType simple_scan_get_page_side (SimpleScan* self);
+static gboolean simple_scan_get_paper_size (SimpleScan* self, gint* width, gint* height);
+gpointer scan_options_ref (gpointer instance);
+void scan_options_unref (gpointer instance);
+GParamSpec* param_spec_scan_options (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags);
+void value_set_scan_options (GValue* value, gpointer v_object);
+void value_take_scan_options (GValue* value, gpointer v_object);
+gpointer value_get_scan_options (const GValue* value);
+GType scan_options_get_type (void) G_GNUC_CONST;
+static ScanOptions* simple_scan_get_scan_options (SimpleScan* self);
+ScanOptions* scan_options_new (void);
+ScanOptions* scan_options_construct (GType object_type);
+GType scan_mode_get_type (void) G_GNUC_CONST;
+void G_MODULE_EXPORT scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT stop_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT continuous_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT preferences_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+gboolean G_MODULE_EXPORT preferences_dialog_delete_event_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT preferences_dialog_response_cb (GtkWidget* widget, gint response_id, SimpleScan* self);
+static void simple_scan_update_page_menu (SimpleScan* self);
+Page* book_view_get_selected (BookView* self);
+guint book_get_page_index (Book* self, Page* page);
+guint book_get_n_pages (Book* self);
+static void simple_scan_page_selected_cb (SimpleScan* self, BookView* view, Page* page);
+gboolean page_has_crop (Page* self);
+gchar* page_get_named_crop (Page* self);
+static gchar* simple_scan_get_temporary_filename (SimpleScan* self, const gchar* prefix, const gchar* extension);
+static void simple_scan_show_page_cb (SimpleScan* self, BookView* view, Page* page);
+void page_save (Page* self, const gchar* type, GFile* file, GError** error);
+static void simple_scan_show_page_menu_cb (SimpleScan* self, BookView* view);
+void G_MODULE_EXPORT rotate_left_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+void page_rotate_left (Page* self);
+void G_MODULE_EXPORT rotate_right_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+void page_rotate_right (Page* self);
+static void simple_scan_set_crop (SimpleScan* self, const gchar* crop_name);
+void page_set_no_crop (Page* self);
+gint page_get_width (Page* self);
+gint page_get_height (Page* self);
+void page_set_custom_crop (Page* self, gint width, gint height);
+void page_move_crop (Page* self, gint x, gint y);
+void page_set_named_crop (Page* self, const gchar* name);
+void G_MODULE_EXPORT no_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT custom_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT crop_toolbutton_toggled_cb (GtkToggleToolButton* widget, SimpleScan* self);
+void G_MODULE_EXPORT four_by_six_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT legal_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT letter_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT a6_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT a5_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT a4_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self);
+void G_MODULE_EXPORT crop_rotate_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self);
+void page_rotate_crop (Page* self);
+void G_MODULE_EXPORT page_move_left_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self);
+void book_move_page (Book* self, Page* page, guint location);
+void G_MODULE_EXPORT page_move_right_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT page_delete_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self);
+Book* book_view_get_book (BookView* self);
+void book_delete_page (Book* self, Page* page);
+void G_MODULE_EXPORT save_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT save_as_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+static void simple_scan_draw_page (SimpleScan* self, GtkPrintOperation* operation, GtkPrintContext* print_context, gint page_number);
+Page* book_get_page (Book* self, gint page_number);
+gboolean page_is_landscape (Page* self);
+gint page_get_dpi (Page* self);
+GdkPixbuf* page_get_image (Page* self, gboolean apply_crop);
+void G_MODULE_EXPORT email_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT print_button_clicked_cb (GtkWidget* widget, SimpleScan* self);
+static void _simple_scan_draw_page_gtk_print_operation_draw_page (GtkPrintOperation* _sender, GtkPrintContext* context, gint page_nr, gpointer self);
+void G_MODULE_EXPORT help_contents_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self);
+void G_MODULE_EXPORT about_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self);
+static gboolean simple_scan_on_quit (SimpleScan* self);
+void G_MODULE_EXPORT quit_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self);
+gboolean G_MODULE_EXPORT simple_scan_window_configure_event_cb (GtkWidget* widget, GdkEventConfigure* event, SimpleScan* self);
+static void simple_scan_info_bar_response_cb (SimpleScan* self, GtkInfoBar* widget, gint response_id);
+gboolean G_MODULE_EXPORT simple_scan_window_window_state_event_cb (GtkWidget* widget, GdkEventWindowState* event, SimpleScan* self);
+gboolean G_MODULE_EXPORT window_delete_event_cb (GtkWidget* widget, GdkEvent* event, SimpleScan* self);
+static void simple_scan_page_size_changed_cb (SimpleScan* self, Page* page);
+static void simple_scan_page_scan_direction_changed_cb (SimpleScan* self, Page* page);
+ScanDirection page_get_scan_direction (Page* self);
+static void _simple_scan_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self);
+static void _simple_scan_page_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self);
+static void simple_scan_set_dpi_combo (SimpleScan* self, GtkComboBox* combo, gint default_dpi, gint current_dpi);
+static void simple_scan_needs_saving_cb (SimpleScan* self, Book* book);
+static void _simple_scan_info_bar_response_cb_gtk_info_bar_response (GtkInfoBar* _sender, gint response_id, gpointer self);
+BookView* book_view_new (Book* book);
+BookView* book_view_construct (GType object_type, Book* book);
+static void _simple_scan_page_selected_cb_book_view_page_selected (BookView* _sender, Page* page, gpointer self);
+static void _simple_scan_show_page_cb_book_view_show_page (BookView* _sender, Page* page, gpointer self);
+static void _simple_scan_show_page_menu_cb_book_view_show_menu (BookView* _sender, gpointer self);
+static void _simple_scan_needs_saving_cb_book_needs_saving_changed (Book* _sender, gpointer self);
+Book* simple_scan_get_book (SimpleScan* self);
+void simple_scan_set_selected_page (SimpleScan* self, Page* page);
+Page* simple_scan_get_selected_page (SimpleScan* self);
+void simple_scan_set_scanning (SimpleScan* self, gboolean scanning);
+void simple_scan_start (SimpleScan* self);
+static void g_cclosure_user_marshal_VOID__STRING_SCAN_OPTIONS (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data);
+static void simple_scan_finalize (SimpleScan* 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);
+
+
+static void _simple_scan_page_removed_cb_book_page_removed (Book* _sender, Page* page, gpointer self) {
+ simple_scan_page_removed_cb (self, _sender, page);
+}
+
+
+static void _simple_scan_page_added_cb_book_page_added (Book* _sender, Page* page, gpointer self) {
+ simple_scan_page_added_cb (self, _sender, page);
+}
+
+
+SimpleScan* simple_scan_construct (GType object_type) {
+ SimpleScan* self = NULL;
+ Book* _tmp0_ = NULL;
+ GSettings* _tmp1_ = NULL;
+ self = (SimpleScan*) g_type_create_instance (object_type);
+ _tmp0_ = book_new ();
+ _book_unref0 (self->priv->book);
+ self->priv->book = _tmp0_;
+ g_signal_connect (self->priv->book, "page-removed", (GCallback) _simple_scan_page_removed_cb_book_page_removed, self);
+ g_signal_connect (self->priv->book, "page-added", (GCallback) _simple_scan_page_added_cb_book_page_added, self);
+ _tmp1_ = g_settings_new ("org.gnome.SimpleScan");
+ _g_object_unref0 (self->priv->settings);
+ self->priv->settings = _tmp1_;
+ simple_scan_load (self);
+ return self;
+}
+
+
+SimpleScan* simple_scan_new (void) {
+ return simple_scan_construct (TYPE_SIMPLE_SCAN);
+}
+
+
+static gboolean simple_scan_find_scan_device (SimpleScan* self, const gchar* device, GtkTreeIter* iter) {
+ GtkTreeIter _iter = {0};
+ gboolean result = FALSE;
+ gboolean have_iter;
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (device != NULL, FALSE);
+ have_iter = FALSE;
+ _tmp1_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->device_model, &_tmp0_);
+ _iter = _tmp0_;
+ if (_tmp1_) {
+ {
+ gboolean _tmp2_;
+ _tmp2_ = TRUE;
+ while (TRUE) {
+ gchar* d = NULL;
+ if (!_tmp2_) {
+ gboolean _tmp3_ = FALSE;
+ if (!have_iter) {
+ gboolean _tmp4_;
+ _tmp4_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->device_model, &_iter);
+ _tmp3_ = _tmp4_;
+ } else {
+ _tmp3_ = FALSE;
+ }
+ if (!_tmp3_) {
+ break;
+ }
+ }
+ _tmp2_ = FALSE;
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->device_model, &_iter, 0, &d, -1, -1);
+ if (g_strcmp0 (d, device) == 0) {
+ have_iter = TRUE;
+ }
+ _g_free0 (d);
+ }
+ }
+ }
+ result = have_iter;
+ if (iter) {
+ *iter = _iter;
+ }
+ return result;
+}
+
+
+static void simple_scan_show_error_dialog (SimpleScan* self, const gchar* error_title, const gchar* error_text) {
+ GtkMessageDialog* _tmp0_ = NULL;
+ GtkMessageDialog* dialog;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (error_title != NULL);
+ g_return_if_fail (error_text != NULL);
+ _tmp0_ = (GtkMessageDialog*) gtk_message_dialog_new (self->priv->window, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, "%s", error_title);
+ dialog = g_object_ref_sink (_tmp0_);
+ gtk_dialog_add_button ((GtkDialog*) dialog, GTK_STOCK_CLOSE, 0);
+ gtk_message_dialog_format_secondary_text (dialog, "%s", error_text, NULL);
+ gtk_widget_destroy ((GtkWidget*) dialog);
+ _g_object_unref0 (dialog);
+}
+
+
+void simple_scan_set_default_file_name (SimpleScan* self, const gchar* default_file_name) {
+ gchar* _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (default_file_name != NULL);
+ _tmp0_ = g_strdup (default_file_name);
+ _g_free0 (self->priv->default_file_name);
+ self->priv->default_file_name = _tmp0_;
+}
+
+
+void simple_scan_authorize (SimpleScan* self, const gchar* resource, gchar** username, gchar** password) {
+ gchar* _username = NULL;
+ gchar* _password = NULL;
+ const gchar* _tmp0_ = NULL;
+ gchar* _tmp1_ = NULL;
+ gchar* description;
+ const gchar* _tmp2_ = NULL;
+ gchar* _tmp3_;
+ const gchar* _tmp4_ = NULL;
+ gchar* _tmp5_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (resource != NULL);
+ _tmp0_ = _ ("Username and password required to access '%s'");
+ _tmp1_ = g_strdup_printf (_tmp0_, resource);
+ description = _tmp1_;
+ gtk_entry_set_text (self->priv->username_entry, "");
+ gtk_entry_set_text (self->priv->password_entry, "");
+ gtk_label_set_text (self->priv->authorize_label, description);
+ gtk_widget_show ((GtkWidget*) self->priv->authorize_dialog);
+ gtk_dialog_run (self->priv->authorize_dialog);
+ gtk_widget_hide ((GtkWidget*) self->priv->authorize_dialog);
+ _tmp2_ = gtk_entry_get_text (self->priv->username_entry);
+ _tmp3_ = g_strdup (_tmp2_);
+ _g_free0 (_username);
+ _username = _tmp3_;
+ _tmp4_ = gtk_entry_get_text (self->priv->password_entry);
+ _tmp5_ = g_strdup (_tmp4_);
+ _g_free0 (_password);
+ _password = _tmp5_;
+ _g_free0 (description);
+ if (username) {
+ *username = _username;
+ } else {
+ _g_free0 (_username);
+ }
+ if (password) {
+ *password = _password;
+ } else {
+ _g_free0 (_password);
+ }
+}
+
+
+void G_MODULE_EXPORT device_combo_changed_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ if (self->priv->setting_devices) {
+ return;
+ }
+ self->priv->user_selected_device = TRUE;
+}
+
+
+static void simple_scan_update_info_bar (SimpleScan* self) {
+ GtkMessageType type = 0;
+ gchar* title = NULL;
+ gchar* text = NULL;
+ gchar* image_id = NULL;
+ gboolean show_close_button;
+ gboolean show_change_scanner_button;
+ gchar* _tmp9_ = NULL;
+ gchar* message;
+ g_return_if_fail (self != NULL);
+ show_close_button = FALSE;
+ show_change_scanner_button = FALSE;
+ if (self->priv->have_error) {
+ gchar* _tmp0_;
+ gchar* _tmp1_;
+ gchar* _tmp2_;
+ type = GTK_MESSAGE_ERROR;
+ _tmp0_ = g_strdup (GTK_STOCK_DIALOG_ERROR);
+ _g_free0 (image_id);
+ image_id = _tmp0_;
+ _tmp1_ = g_strdup (self->priv->error_title);
+ _g_free0 (title);
+ title = _tmp1_;
+ _tmp2_ = g_strdup (self->priv->error_text);
+ _g_free0 (text);
+ text = _tmp2_;
+ show_close_button = TRUE;
+ show_change_scanner_button = self->priv->error_change_scanner_hint;
+ } else {
+ gint _tmp3_;
+ _tmp3_ = gtk_tree_model_iter_n_children ((GtkTreeModel*) self->priv->device_model, NULL);
+ if (_tmp3_ == 0) {
+ gchar* _tmp4_;
+ const gchar* _tmp5_ = NULL;
+ gchar* _tmp6_;
+ const gchar* _tmp7_ = NULL;
+ gchar* _tmp8_;
+ type = GTK_MESSAGE_WARNING;
+ _tmp4_ = g_strdup (GTK_STOCK_DIALOG_WARNING);
+ _g_free0 (image_id);
+ image_id = _tmp4_;
+ _tmp5_ = _ ("No scanners detected");
+ _tmp6_ = g_strdup (_tmp5_);
+ _g_free0 (title);
+ title = _tmp6_;
+ _tmp7_ = _ ("Please check your scanner is connected and powered on");
+ _tmp8_ = g_strdup (_tmp7_);
+ _g_free0 (text);
+ text = _tmp8_;
+ } else {
+ gtk_widget_hide ((GtkWidget*) self->priv->info_bar);
+ _g_free0 (image_id);
+ _g_free0 (text);
+ _g_free0 (title);
+ return;
+ }
+ }
+ gtk_info_bar_set_message_type (self->priv->info_bar, type);
+ gtk_image_set_from_stock (self->priv->info_bar_image, image_id, GTK_ICON_SIZE_DIALOG);
+ _tmp9_ = g_strdup_printf ("<big><b>%s</b></big>\n\n%s", title, text);
+ message = _tmp9_;
+ gtk_label_set_markup (self->priv->info_bar_label, message);
+ gtk_widget_set_visible ((GtkWidget*) self->priv->info_bar_close_button, show_close_button);
+ gtk_widget_set_visible ((GtkWidget*) self->priv->info_bar_change_scanner_button, show_change_scanner_button);
+ gtk_widget_show ((GtkWidget*) self->priv->info_bar);
+ _g_free0 (message);
+ _g_free0 (image_id);
+ _g_free0 (text);
+ _g_free0 (title);
+}
+
+
+static gpointer _scan_device_ref0 (gpointer self) {
+ return self ? scan_device_ref (self) : NULL;
+}
+
+
+void simple_scan_set_scan_devices (SimpleScan* self, GList* devices) {
+ gboolean have_selection;
+ gint index = 0;
+ GtkTreeIter iter = {0};
+ gboolean _tmp11_ = FALSE;
+ g_return_if_fail (self != NULL);
+ have_selection = FALSE;
+ self->priv->setting_devices = TRUE;
+ if (self->priv->user_selected_device) {
+ gint _tmp0_;
+ _tmp0_ = gtk_combo_box_get_active (self->priv->device_combo);
+ have_selection = _tmp0_ >= 0;
+ }
+ index = 0;
+ {
+ GList* device_collection = NULL;
+ GList* device_it = NULL;
+ device_collection = devices;
+ for (device_it = device_collection; device_it != NULL; device_it = device_it->next) {
+ ScanDevice* _tmp1_;
+ ScanDevice* device = NULL;
+ _tmp1_ = _scan_device_ref0 ((ScanDevice*) device_it->data);
+ device = _tmp1_;
+ {
+ gint n_delete;
+ GtkTreeIter _tmp2_ = {0};
+ gboolean _tmp3_;
+ n_delete = -1;
+ _tmp3_ = gtk_tree_model_iter_nth_child ((GtkTreeModel*) self->priv->device_model, &_tmp2_, NULL, index);
+ iter = _tmp2_;
+ if (_tmp3_) {
+ gint i;
+ i = 0;
+ {
+ gboolean _tmp4_;
+ _tmp4_ = TRUE;
+ while (TRUE) {
+ gchar* name = NULL;
+ gboolean matched = FALSE;
+ if (!_tmp4_) {
+ gboolean _tmp5_;
+ _tmp5_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->device_model, &iter);
+ if (!_tmp5_) {
+ break;
+ }
+ }
+ _tmp4_ = FALSE;
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->device_model, &iter, 0, &name, -1, -1);
+ matched = g_strcmp0 (name, device->name) == 0;
+ if (matched) {
+ n_delete = i;
+ _g_free0 (name);
+ break;
+ }
+ i++;
+ _g_free0 (name);
+ }
+ }
+ }
+ if (n_delete >= 0) {
+ gint i = 0;
+ gtk_list_store_set (self->priv->device_model, &iter, 1, device->label, -1, -1);
+ {
+ gboolean _tmp6_;
+ i = 0;
+ _tmp6_ = TRUE;
+ while (TRUE) {
+ GtkTreeIter _tmp7_ = {0};
+ if (!_tmp6_) {
+ i++;
+ }
+ _tmp6_ = FALSE;
+ if (!(i < n_delete)) {
+ break;
+ }
+ gtk_tree_model_iter_nth_child ((GtkTreeModel*) self->priv->device_model, &_tmp7_, NULL, index);
+ iter = _tmp7_;
+ gtk_list_store_remove (self->priv->device_model, &iter);
+ }
+ }
+ } else {
+ GtkTreeIter _tmp8_ = {0};
+ gtk_list_store_insert (self->priv->device_model, &_tmp8_, index);
+ iter = _tmp8_;
+ gtk_list_store_set (self->priv->device_model, &iter, 0, device->name, 1, device->label, -1, -1);
+ }
+ index++;
+ _scan_device_unref0 (device);
+ }
+ }
+ }
+ while (TRUE) {
+ GtkTreeIter _tmp9_ = {0};
+ gboolean _tmp10_;
+ _tmp10_ = gtk_tree_model_iter_nth_child ((GtkTreeModel*) self->priv->device_model, &_tmp9_, NULL, index);
+ iter = _tmp9_;
+ if (!_tmp10_) {
+ break;
+ }
+ gtk_list_store_remove (self->priv->device_model, &iter);
+ }
+ if (!have_selection) {
+ _tmp11_ = devices != NULL;
+ } else {
+ _tmp11_ = FALSE;
+ }
+ if (_tmp11_) {
+ gtk_combo_box_set_active (self->priv->device_combo, 0);
+ }
+ self->priv->setting_devices = FALSE;
+ simple_scan_update_info_bar (self);
+}
+
+
+static gchar* simple_scan_get_selected_device (SimpleScan* self) {
+ gchar* result = NULL;
+ GtkTreeIter iter = {0};
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp1_ = gtk_combo_box_get_active_iter (self->priv->device_combo, &_tmp0_);
+ iter = _tmp0_;
+ if (_tmp1_) {
+ gchar* device = NULL;
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->device_model, &iter, 0, &device, -1, -1);
+ result = device;
+ return result;
+ }
+ result = NULL;
+ return result;
+}
+
+
+void simple_scan_set_selected_device (SimpleScan* self, const gchar* device) {
+ GtkTreeIter iter = {0};
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (device != NULL);
+ _tmp1_ = simple_scan_find_scan_device (self, device, &_tmp0_);
+ iter = _tmp0_;
+ if (!_tmp1_) {
+ return;
+ }
+ gtk_combo_box_set_active_iter (self->priv->device_combo, &iter);
+ self->priv->user_selected_device = TRUE;
+}
+
+
+static void simple_scan_add_default_page (SimpleScan* self) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = book_append_page (self->priv->book, self->priv->default_page_width, self->priv->default_page_height, self->priv->default_page_dpi, self->priv->default_page_scan_direction);
+ page = _tmp0_;
+ book_view_select_page (self->priv->book_view, page);
+ _page_unref0 (page);
+}
+
+
+static gpointer _g_object_ref0 (gpointer self) {
+ return self ? g_object_ref (self) : NULL;
+}
+
+
+static gint string_last_index_of_char (const gchar* self, gunichar c, gint start_index) {
+ gint result = 0;
+ gchar* _tmp0_ = NULL;
+ gchar* _result_;
+ g_return_val_if_fail (self != NULL, 0);
+ _tmp0_ = g_utf8_strrchr (((gchar*) self) + start_index, (gssize) (-1), c);
+ _result_ = _tmp0_;
+ if (_result_ != NULL) {
+ result = (gint) (_result_ - ((gchar*) self));
+ return result;
+ } else {
+ result = -1;
+ return result;
+ }
+}
+
+
+static gchar* string_slice (const gchar* self, glong start, glong end) {
+ gchar* result = NULL;
+ gint _tmp0_;
+ glong string_length;
+ gboolean _tmp1_ = FALSE;
+ gboolean _tmp2_ = FALSE;
+ gchar* _tmp3_ = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = strlen (self);
+ string_length = (glong) _tmp0_;
+ if (start < ((glong) 0)) {
+ start = string_length + start;
+ }
+ if (end < ((glong) 0)) {
+ end = string_length + end;
+ }
+ if (start >= ((glong) 0)) {
+ _tmp1_ = start <= string_length;
+ } else {
+ _tmp1_ = FALSE;
+ }
+ g_return_val_if_fail (_tmp1_, NULL);
+ if (end >= ((glong) 0)) {
+ _tmp2_ = end <= string_length;
+ } else {
+ _tmp2_ = FALSE;
+ }
+ g_return_val_if_fail (_tmp2_, NULL);
+ g_return_val_if_fail (start <= end, NULL);
+ _tmp3_ = g_strndup (((gchar*) self) + start, (gsize) (end - start));
+ result = _tmp3_;
+ return result;
+}
+
+
+static void simple_scan_on_file_type_changed (SimpleScan* self, GtkTreeSelection* selection) {
+ GtkTreeModel* model = NULL;
+ GtkTreeIter iter = {0};
+ GtkTreeModel* _tmp0_ = NULL;
+ GtkTreeIter _tmp1_ = {0};
+ gboolean _tmp2_;
+ GtkTreeModel* _tmp3_;
+ gchar* extension = NULL;
+ gchar* _tmp4_ = NULL;
+ gchar* path;
+ gchar* _tmp5_ = NULL;
+ gchar* filename;
+ gint _tmp6_;
+ gint extension_index;
+ gchar* _tmp8_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (selection != NULL);
+ _tmp2_ = gtk_tree_selection_get_selected (selection, &_tmp0_, &_tmp1_);
+ _g_object_unref0 (model);
+ _tmp3_ = _g_object_ref0 (_tmp0_);
+ model = _tmp3_;
+ iter = _tmp1_;
+ if (!_tmp2_) {
+ _g_object_unref0 (model);
+ return;
+ }
+ gtk_tree_model_get (model, &iter, 1, &extension, -1, -1);
+ _tmp4_ = gtk_file_chooser_get_filename ((GtkFileChooser*) self->priv->save_dialog);
+ path = _tmp4_;
+ _tmp5_ = g_path_get_basename (path);
+ filename = _tmp5_;
+ _tmp6_ = string_last_index_of_char (filename, (gunichar) '.', 0);
+ extension_index = _tmp6_;
+ if (extension_index >= 0) {
+ gchar* _tmp7_ = NULL;
+ _tmp7_ = string_slice (filename, (glong) 0, (glong) extension_index);
+ _g_free0 (filename);
+ filename = _tmp7_;
+ }
+ _tmp8_ = g_strconcat (filename, extension, NULL);
+ _g_free0 (filename);
+ filename = _tmp8_;
+ gtk_file_chooser_set_current_name ((GtkFileChooser*) self->priv->save_dialog, filename);
+ _g_free0 (filename);
+ _g_free0 (path);
+ _g_free0 (extension);
+ _g_object_unref0 (model);
+}
+
+
+static void _simple_scan_on_file_type_changed_gtk_tree_selection_changed (GtkTreeSelection* _sender, gpointer self) {
+ simple_scan_on_file_type_changed (self, _sender);
+}
+
+
+static gchar* simple_scan_choose_file_location (SimpleScan* self) {
+ gchar* result = NULL;
+ gchar* directory;
+ gchar* _tmp0_ = NULL;
+ gboolean _tmp1_ = FALSE;
+ const gchar* _tmp4_ = NULL;
+ GtkFileChooserDialog* _tmp5_ = NULL;
+ GtkFileFilter* _tmp6_ = NULL;
+ GtkFileFilter* filter;
+ const gchar* _tmp7_ = NULL;
+ GtkFileFilter* _tmp8_ = NULL;
+ const gchar* _tmp9_ = NULL;
+ const gchar* _tmp10_ = NULL;
+ GtkExpander* _tmp11_ = NULL;
+ GtkExpander* expander;
+ gchar* _tmp12_;
+ gchar* extension;
+ gint _tmp13_;
+ gint index;
+ GtkListStore* _tmp15_ = NULL;
+ GtkListStore* file_type_store;
+ GtkTreeIter iter = {0};
+ GtkTreeIter _tmp16_ = {0};
+ const gchar* _tmp17_ = NULL;
+ GtkTreeIter _tmp18_ = {0};
+ const gchar* _tmp19_ = NULL;
+ GtkTreeIter _tmp20_ = {0};
+ const gchar* _tmp21_ = NULL;
+ GtkTreeView* _tmp22_ = NULL;
+ GtkTreeView* file_type_view;
+ GtkCellRendererText* _tmp23_ = NULL;
+ GtkCellRendererText* _tmp24_;
+ GtkTreeViewColumn* _tmp25_ = NULL;
+ GtkTreeViewColumn* _tmp26_;
+ GtkTreeViewColumn* column;
+ GtkTreeIter _tmp27_ = {0};
+ gboolean _tmp28_;
+ GtkTreeSelection* _tmp32_ = NULL;
+ gint _tmp33_;
+ gint response;
+ gchar* uri;
+ gchar* _tmp35_ = NULL;
+ gchar* _tmp36_;
+ g_return_val_if_fail (self != NULL, NULL);
+ directory = NULL;
+ _tmp0_ = g_settings_get_string (self->priv->settings, "save-directory");
+ _g_free0 (directory);
+ directory = _tmp0_;
+ if (directory == NULL) {
+ _tmp1_ = TRUE;
+ } else {
+ _tmp1_ = g_strcmp0 (directory, "") == 0;
+ }
+ if (_tmp1_) {
+ const gchar* _tmp2_ = NULL;
+ gchar* _tmp3_;
+ _tmp2_ = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
+ _tmp3_ = g_strdup (_tmp2_);
+ _g_free0 (directory);
+ directory = _tmp3_;
+ }
+ _tmp4_ = _ ("Save As...");
+ _tmp5_ = (GtkFileChooserDialog*) gtk_file_chooser_dialog_new (_tmp4_, self->priv->window, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL, NULL);
+ _g_object_unref0 (self->priv->save_dialog);
+ self->priv->save_dialog = g_object_ref_sink (_tmp5_);
+ gtk_file_chooser_set_do_overwrite_confirmation ((GtkFileChooser*) self->priv->save_dialog, TRUE);
+ gtk_file_chooser_set_local_only ((GtkFileChooser*) self->priv->save_dialog, FALSE);
+ gtk_file_chooser_set_current_folder ((GtkFileChooser*) self->priv->save_dialog, directory);
+ gtk_file_chooser_set_current_name ((GtkFileChooser*) self->priv->save_dialog, self->priv->default_file_name);
+ _tmp6_ = gtk_file_filter_new ();
+ filter = g_object_ref_sink (_tmp6_);
+ _tmp7_ = _ ("Image Files");
+ gtk_buildable_set_name ((GtkBuildable*) filter, _tmp7_);
+ gtk_file_filter_add_pixbuf_formats (filter);
+ gtk_file_filter_add_mime_type (filter, "application/pdf");
+ gtk_file_chooser_add_filter ((GtkFileChooser*) self->priv->save_dialog, filter);
+ _tmp8_ = gtk_file_filter_new ();
+ _g_object_unref0 (filter);
+ filter = g_object_ref_sink (_tmp8_);
+ _tmp9_ = _ ("All Files");
+ gtk_buildable_set_name ((GtkBuildable*) filter, _tmp9_);
+ gtk_file_filter_add_pattern (filter, "*");
+ gtk_file_chooser_add_filter ((GtkFileChooser*) self->priv->save_dialog, filter);
+ _tmp10_ = _ ("Select File _Type");
+ _tmp11_ = (GtkExpander*) gtk_expander_new_with_mnemonic (_tmp10_);
+ expander = g_object_ref_sink (_tmp11_);
+ gtk_expander_set_spacing (expander, 5);
+ gtk_file_chooser_set_extra_widget ((GtkFileChooser*) self->priv->save_dialog, (GtkWidget*) expander);
+ _tmp12_ = g_strdup ("");
+ extension = _tmp12_;
+ _tmp13_ = string_last_index_of_char (self->priv->default_file_name, (gunichar) '.', 0);
+ index = _tmp13_;
+ if (index >= 0) {
+ gchar* _tmp14_ = NULL;
+ _tmp14_ = string_slice (self->priv->default_file_name, (glong) 0, (glong) index);
+ _g_free0 (extension);
+ extension = _tmp14_;
+ }
+ _tmp15_ = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ file_type_store = _tmp15_;
+ gtk_list_store_append (file_type_store, &_tmp16_);
+ iter = _tmp16_;
+ _tmp17_ = _ ("PDF (multi-page document)");
+ gtk_list_store_set (file_type_store, &iter, 0, _tmp17_, 1, ".pdf", -1, -1);
+ gtk_list_store_append (file_type_store, &_tmp18_);
+ iter = _tmp18_;
+ _tmp19_ = _ ("JPEG (compressed)");
+ gtk_list_store_set (file_type_store, &iter, 0, _tmp19_, 1, ".jpg", -1, -1);
+ gtk_list_store_append (file_type_store, &_tmp20_);
+ iter = _tmp20_;
+ _tmp21_ = _ ("PNG (lossless)");
+ gtk_list_store_set (file_type_store, &iter, 0, _tmp21_, 1, ".png", -1, -1);
+ _tmp22_ = (GtkTreeView*) gtk_tree_view_new_with_model ((GtkTreeModel*) file_type_store);
+ file_type_view = g_object_ref_sink (_tmp22_);
+ gtk_tree_view_set_headers_visible (file_type_view, FALSE);
+ gtk_tree_view_set_rules_hint (file_type_view, TRUE);
+ _tmp23_ = (GtkCellRendererText*) gtk_cell_renderer_text_new ();
+ _tmp24_ = g_object_ref_sink (_tmp23_);
+ _tmp25_ = gtk_tree_view_column_new_with_attributes ("", (GtkCellRenderer*) _tmp24_, "text", 0, NULL, NULL);
+ _tmp26_ = g_object_ref_sink (_tmp25_);
+ _g_object_unref0 (_tmp24_);
+ column = _tmp26_;
+ gtk_tree_view_append_column (file_type_view, column);
+ gtk_container_add ((GtkContainer*) expander, (GtkWidget*) file_type_view);
+ _tmp28_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) file_type_store, &_tmp27_);
+ iter = _tmp27_;
+ if (_tmp28_) {
+ {
+ gboolean _tmp29_;
+ _tmp29_ = TRUE;
+ while (TRUE) {
+ gchar* e = NULL;
+ if (!_tmp29_) {
+ gboolean _tmp30_;
+ _tmp30_ = gtk_tree_model_iter_next ((GtkTreeModel*) file_type_store, &iter);
+ if (!_tmp30_) {
+ break;
+ }
+ }
+ _tmp29_ = FALSE;
+ gtk_tree_model_get ((GtkTreeModel*) file_type_store, &iter, 1, &e, -1, -1);
+ if (g_strcmp0 (extension, e) == 0) {
+ GtkTreeSelection* _tmp31_ = NULL;
+ _tmp31_ = gtk_tree_view_get_selection (file_type_view);
+ gtk_tree_selection_select_iter (_tmp31_, &iter);
+ }
+ _g_free0 (e);
+ }
+ }
+ }
+ _tmp32_ = gtk_tree_view_get_selection (file_type_view);
+ g_signal_connect (_tmp32_, "changed", (GCallback) _simple_scan_on_file_type_changed_gtk_tree_selection_changed, self);
+ gtk_widget_show_all ((GtkWidget*) expander);
+ _tmp33_ = gtk_dialog_run ((GtkDialog*) self->priv->save_dialog);
+ response = _tmp33_;
+ uri = NULL;
+ if (response == ((gint) GTK_RESPONSE_ACCEPT)) {
+ gchar* _tmp34_ = NULL;
+ _tmp34_ = gtk_file_chooser_get_uri ((GtkFileChooser*) self->priv->save_dialog);
+ _g_free0 (uri);
+ uri = _tmp34_;
+ }
+ _tmp35_ = gtk_file_chooser_get_current_folder ((GtkFileChooser*) self->priv->save_dialog);
+ _tmp36_ = _tmp35_;
+ g_settings_set_string (self->priv->settings, "save-directory", _tmp36_);
+ _g_free0 (_tmp36_);
+ gtk_widget_destroy ((GtkWidget*) self->priv->save_dialog);
+ _g_object_unref0 (self->priv->save_dialog);
+ self->priv->save_dialog = NULL;
+ result = uri;
+ _g_object_unref0 (column);
+ _g_object_unref0 (file_type_view);
+ _g_object_unref0 (file_type_store);
+ _g_free0 (extension);
+ _g_object_unref0 (expander);
+ _g_object_unref0 (filter);
+ _g_free0 (directory);
+ return result;
+}
+
+
+static gboolean simple_scan_save_document (SimpleScan* self, gboolean force_choose_location) {
+ gboolean result = FALSE;
+ gchar* uri = NULL;
+ gboolean _tmp0_ = FALSE;
+ GFile* _tmp3_ = NULL;
+ GFile* file;
+ gchar* _tmp4_ = NULL;
+ gchar* uri_lower;
+ gchar* _tmp5_;
+ gchar* format;
+ gboolean _tmp6_;
+ gchar* _tmp17_;
+ GError * _inner_error_ = NULL;
+ g_return_val_if_fail (self != NULL, FALSE);
+ if (self->priv->book_uri != NULL) {
+ _tmp0_ = !force_choose_location;
+ } else {
+ _tmp0_ = FALSE;
+ }
+ if (_tmp0_) {
+ gchar* _tmp1_;
+ _tmp1_ = g_strdup (self->priv->book_uri);
+ _g_free0 (uri);
+ uri = _tmp1_;
+ } else {
+ gchar* _tmp2_ = NULL;
+ _tmp2_ = simple_scan_choose_file_location (self);
+ _g_free0 (uri);
+ uri = _tmp2_;
+ }
+ if (uri == NULL) {
+ result = FALSE;
+ _g_free0 (uri);
+ return result;
+ }
+ _tmp3_ = g_file_new_for_uri (uri);
+ file = _tmp3_;
+ g_debug ("ui.vala:445: Saving to '%s'", uri);
+ _tmp4_ = g_utf8_strdown (uri, (gssize) (-1));
+ uri_lower = _tmp4_;
+ _tmp5_ = g_strdup ("jpeg");
+ format = _tmp5_;
+ _tmp6_ = g_str_has_suffix (uri_lower, ".pdf");
+ if (_tmp6_) {
+ gchar* _tmp7_;
+ _tmp7_ = g_strdup ("pdf");
+ _g_free0 (format);
+ format = _tmp7_;
+ } else {
+ gboolean _tmp8_;
+ _tmp8_ = g_str_has_suffix (uri_lower, ".ps");
+ if (_tmp8_) {
+ gchar* _tmp9_;
+ _tmp9_ = g_strdup ("ps");
+ _g_free0 (format);
+ format = _tmp9_;
+ } else {
+ gboolean _tmp10_;
+ _tmp10_ = g_str_has_suffix (uri_lower, ".png");
+ if (_tmp10_) {
+ gchar* _tmp11_;
+ _tmp11_ = g_strdup ("png");
+ _g_free0 (format);
+ format = _tmp11_;
+ } else {
+ gboolean _tmp12_ = FALSE;
+ gboolean _tmp13_;
+ _tmp13_ = g_str_has_suffix (uri_lower, ".tif");
+ if (_tmp13_) {
+ _tmp12_ = TRUE;
+ } else {
+ gboolean _tmp14_;
+ _tmp14_ = g_str_has_suffix (uri_lower, ".tiff");
+ _tmp12_ = _tmp14_;
+ }
+ if (_tmp12_) {
+ gchar* _tmp15_;
+ _tmp15_ = g_strdup ("tiff");
+ _g_free0 (format);
+ format = _tmp15_;
+ }
+ }
+ }
+ }
+ {
+ book_save (self->priv->book, format, file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch10_g_error;
+ }
+ }
+ goto __finally10;
+ __catch10_g_error:
+ {
+ GError* e = NULL;
+ const gchar* _tmp16_ = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("ui.vala:464: Error saving file: %s", e->message);
+ _tmp16_ = _ ("Failed to save file");
+ simple_scan_show_error (self, _tmp16_, e->message, FALSE);
+ result = FALSE;
+ _g_error_free0 (e);
+ _g_free0 (format);
+ _g_free0 (uri_lower);
+ _g_object_unref0 (file);
+ _g_free0 (uri);
+ return result;
+ }
+ __finally10:
+ if (_inner_error_ != NULL) {
+ _g_free0 (format);
+ _g_free0 (uri_lower);
+ _g_object_unref0 (file);
+ _g_free0 (uri);
+ 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 FALSE;
+ }
+ _tmp17_ = g_strdup (uri);
+ _g_free0 (self->priv->book_uri);
+ self->priv->book_uri = _tmp17_;
+ book_set_needs_saving (self->priv->book, FALSE);
+ result = TRUE;
+ _g_free0 (format);
+ _g_free0 (uri_lower);
+ _g_object_unref0 (file);
+ _g_free0 (uri);
+ return result;
+}
+
+
+static gboolean simple_scan_prompt_to_save (SimpleScan* self, const gchar* title, const gchar* discard_label) {
+ gboolean result = FALSE;
+ gboolean _tmp0_;
+ GtkMessageDialog* _tmp1_ = NULL;
+ GtkMessageDialog* dialog;
+ const gchar* _tmp2_ = NULL;
+ gint _tmp3_;
+ gint response;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (title != NULL, FALSE);
+ g_return_val_if_fail (discard_label != NULL, FALSE);
+ _tmp0_ = book_get_needs_saving (self->priv->book);
+ if (!_tmp0_) {
+ result = TRUE;
+ return result;
+ }
+ _tmp1_ = (GtkMessageDialog*) gtk_message_dialog_new (self->priv->window, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, "%s", title);
+ dialog = g_object_ref_sink (_tmp1_);
+ _tmp2_ = _ ("If you don't save, changes will be permanently lost.");
+ gtk_message_dialog_format_secondary_text (dialog, "%s", _tmp2_, NULL);
+ gtk_dialog_add_button ((GtkDialog*) dialog, discard_label, (gint) GTK_RESPONSE_NO);
+ gtk_dialog_add_button ((GtkDialog*) dialog, GTK_STOCK_CANCEL, (gint) GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_button ((GtkDialog*) dialog, GTK_STOCK_SAVE, (gint) GTK_RESPONSE_YES);
+ _tmp3_ = gtk_dialog_run ((GtkDialog*) dialog);
+ response = _tmp3_;
+ gtk_widget_destroy ((GtkWidget*) dialog);
+ switch (response) {
+ case GTK_RESPONSE_YES:
+ {
+ gboolean _tmp4_;
+ _tmp4_ = simple_scan_save_document (self, FALSE);
+ if (_tmp4_) {
+ result = TRUE;
+ _g_object_unref0 (dialog);
+ return result;
+ } else {
+ result = FALSE;
+ _g_object_unref0 (dialog);
+ return result;
+ }
+ }
+ case GTK_RESPONSE_CANCEL:
+ {
+ result = FALSE;
+ _g_object_unref0 (dialog);
+ return result;
+ }
+ default:
+ case GTK_RESPONSE_NO:
+ {
+ result = TRUE;
+ _g_object_unref0 (dialog);
+ return result;
+ }
+ }
+ _g_object_unref0 (dialog);
+}
+
+
+static void simple_scan_clear_document (SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ book_clear (self->priv->book);
+ simple_scan_add_default_page (self);
+ _g_free0 (self->priv->book_uri);
+ self->priv->book_uri = NULL;
+ book_set_needs_saving (self->priv->book, FALSE);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_as_menuitem, FALSE);
+}
+
+
+void G_MODULE_EXPORT new_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ const gchar* _tmp0_ = NULL;
+ const gchar* _tmp1_ = NULL;
+ gboolean _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = _ ("Save current document?");
+ _tmp1_ = _ ("Discard Changes");
+ _tmp2_ = simple_scan_prompt_to_save (self, _tmp0_, _tmp1_);
+ if (!_tmp2_) {
+ return;
+ }
+ simple_scan_clear_document (self);
+}
+
+
+static void simple_scan_set_document_hint (SimpleScan* self, const gchar* document_hint) {
+ gchar* _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (document_hint != NULL);
+ _tmp0_ = g_strdup (document_hint);
+ _g_free0 (self->priv->document_hint);
+ self->priv->document_hint = _tmp0_;
+ if (g_strcmp0 (document_hint, "text") == 0) {
+ gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->text_toolbar_menuitem, TRUE);
+ gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->text_menu_menuitem, TRUE);
+ } else {
+ if (g_strcmp0 (document_hint, "photo") == 0) {
+ gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->photo_toolbar_menuitem, TRUE);
+ gtk_check_menu_item_set_active ((GtkCheckMenuItem*) self->priv->photo_menu_menuitem, TRUE);
+ }
+ }
+}
+
+
+void G_MODULE_EXPORT text_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_document_hint (self, "text");
+ }
+}
+
+
+void G_MODULE_EXPORT photo_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_document_hint (self, "photo");
+ }
+}
+
+
+static void simple_scan_set_page_side (SimpleScan* self, ScanType page_side) {
+ GtkTreeIter iter = {0};
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_if_fail (self != NULL);
+ _tmp1_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->page_side_model, &_tmp0_);
+ iter = _tmp0_;
+ if (_tmp1_) {
+ {
+ gboolean _tmp2_;
+ _tmp2_ = TRUE;
+ while (TRUE) {
+ gint s = 0;
+ if (!_tmp2_) {
+ gboolean _tmp3_;
+ _tmp3_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->page_side_model, &iter);
+ if (!_tmp3_) {
+ break;
+ }
+ }
+ _tmp2_ = FALSE;
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->page_side_model, &iter, 0, &s, -1, -1);
+ if (s == ((gint) page_side)) {
+ gtk_combo_box_set_active_iter (self->priv->page_side_combo, &iter);
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+static void simple_scan_set_paper_size (SimpleScan* self, gint width, gint height) {
+ GtkTreeIter iter = {0};
+ gboolean have_iter = FALSE;
+ g_return_if_fail (self != NULL);
+ {
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ gboolean _tmp2_;
+ _tmp1_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->paper_size_model, &_tmp0_);
+ iter = _tmp0_;
+ have_iter = _tmp1_;
+ _tmp2_ = TRUE;
+ while (TRUE) {
+ gint w = 0;
+ gint h = 0;
+ gboolean _tmp4_ = FALSE;
+ if (!_tmp2_) {
+ gboolean _tmp3_;
+ _tmp3_ = gtk_tree_model_iter_next ((GtkTreeModel*) self->priv->paper_size_model, &iter);
+ have_iter = _tmp3_;
+ }
+ _tmp2_ = FALSE;
+ if (!have_iter) {
+ break;
+ }
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->paper_size_model, &iter, 0, &w, 1, &h, -1, -1);
+ if (w == width) {
+ _tmp4_ = h == height;
+ } else {
+ _tmp4_ = FALSE;
+ }
+ if (_tmp4_) {
+ break;
+ }
+ }
+ }
+ if (!have_iter) {
+ GtkTreeIter _tmp5_ = {0};
+ gboolean _tmp6_;
+ _tmp6_ = gtk_tree_model_get_iter_first ((GtkTreeModel*) self->priv->paper_size_model, &_tmp5_);
+ iter = _tmp5_;
+ have_iter = _tmp6_;
+ }
+ if (have_iter) {
+ gtk_combo_box_set_active_iter (self->priv->paper_size_combo, &iter);
+ }
+}
+
+
+static gint simple_scan_get_text_dpi (SimpleScan* self) {
+ gint result = 0;
+ GtkTreeIter iter = {0};
+ gint dpi;
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_val_if_fail (self != NULL, 0);
+ dpi = SIMPLE_SCAN_DEFAULT_TEXT_DPI;
+ _tmp1_ = gtk_combo_box_get_active_iter (self->priv->text_dpi_combo, &_tmp0_);
+ iter = _tmp0_;
+ if (_tmp1_) {
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->text_dpi_model, &iter, 0, &dpi, -1, -1);
+ }
+ result = dpi;
+ return result;
+}
+
+
+static gint simple_scan_get_photo_dpi (SimpleScan* self) {
+ gint result = 0;
+ GtkTreeIter iter = {0};
+ gint dpi;
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_val_if_fail (self != NULL, 0);
+ dpi = SIMPLE_SCAN_DEFAULT_PHOTO_DPI;
+ _tmp1_ = gtk_combo_box_get_active_iter (self->priv->photo_dpi_combo, &_tmp0_);
+ iter = _tmp0_;
+ if (_tmp1_) {
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->photo_dpi_model, &iter, 0, &dpi, -1, -1);
+ }
+ result = dpi;
+ return result;
+}
+
+
+static ScanType simple_scan_get_page_side (SimpleScan* self) {
+ ScanType result = 0;
+ GtkTreeIter iter = {0};
+ gint page_side;
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_val_if_fail (self != NULL, 0);
+ page_side = (gint) SCAN_TYPE_ADF_BOTH;
+ _tmp1_ = gtk_combo_box_get_active_iter (self->priv->page_side_combo, &_tmp0_);
+ iter = _tmp0_;
+ if (_tmp1_) {
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->page_side_model, &iter, 0, &page_side, -1, -1);
+ }
+ result = (ScanType) page_side;
+ return result;
+}
+
+
+static gboolean simple_scan_get_paper_size (SimpleScan* self, gint* width, gint* height) {
+ gint _width = 0;
+ gint _height = 0;
+ gboolean result = FALSE;
+ GtkTreeIter iter = {0};
+ GtkTreeIter _tmp0_ = {0};
+ gboolean _tmp1_;
+ g_return_val_if_fail (self != NULL, FALSE);
+ _tmp1_ = gtk_combo_box_get_active_iter (self->priv->paper_size_combo, &_tmp0_);
+ iter = _tmp0_;
+ if (_tmp1_) {
+ gtk_tree_model_get ((GtkTreeModel*) self->priv->paper_size_model, &iter, 0, &_width, 1, &_height, -1, -1);
+ result = TRUE;
+ if (width) {
+ *width = _width;
+ }
+ if (height) {
+ *height = _height;
+ }
+ return result;
+ }
+ result = FALSE;
+ if (width) {
+ *width = _width;
+ }
+ if (height) {
+ *height = _height;
+ }
+ return result;
+}
+
+
+static ScanOptions* simple_scan_get_scan_options (SimpleScan* self) {
+ ScanOptions* result = NULL;
+ ScanOptions* _tmp0_ = NULL;
+ ScanOptions* options;
+ gint _tmp3_;
+ gint _tmp4_;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = scan_options_new ();
+ options = _tmp0_;
+ if (g_strcmp0 (self->priv->document_hint, "text") == 0) {
+ gint _tmp1_;
+ options->scan_mode = SCAN_MODE_GRAY;
+ _tmp1_ = simple_scan_get_text_dpi (self);
+ options->dpi = _tmp1_;
+ options->depth = 2;
+ } else {
+ gint _tmp2_;
+ options->scan_mode = SCAN_MODE_COLOR;
+ _tmp2_ = simple_scan_get_photo_dpi (self);
+ options->dpi = _tmp2_;
+ options->depth = 8;
+ }
+ simple_scan_get_paper_size (self, &_tmp3_, &_tmp4_);
+ options->paper_width = _tmp3_;
+ options->paper_height = _tmp4_;
+ result = options;
+ return result;
+}
+
+
+void G_MODULE_EXPORT scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ ScanOptions* _tmp0_ = NULL;
+ ScanOptions* options;
+ gchar* _tmp1_ = NULL;
+ gchar* _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = simple_scan_get_scan_options (self);
+ options = _tmp0_;
+ options->type = SCAN_TYPE_SINGLE;
+ _tmp1_ = simple_scan_get_selected_device (self);
+ _tmp2_ = _tmp1_;
+ g_signal_emit_by_name (self, "start-scan", _tmp2_, options);
+ _g_free0 (_tmp2_);
+ _scan_options_unref0 (options);
+}
+
+
+void G_MODULE_EXPORT stop_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ g_signal_emit_by_name (self, "stop-scan");
+}
+
+
+void G_MODULE_EXPORT continuous_scan_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ if (self->priv->scanning) {
+ g_signal_emit_by_name (self, "stop-scan");
+ } else {
+ ScanOptions* _tmp0_ = NULL;
+ ScanOptions* options;
+ ScanType _tmp1_;
+ gchar* _tmp2_ = NULL;
+ gchar* _tmp3_;
+ _tmp0_ = simple_scan_get_scan_options (self);
+ options = _tmp0_;
+ _tmp1_ = simple_scan_get_page_side (self);
+ options->type = _tmp1_;
+ _tmp2_ = simple_scan_get_selected_device (self);
+ _tmp3_ = _tmp2_;
+ g_signal_emit_by_name (self, "start-scan", _tmp3_, options);
+ _g_free0 (_tmp3_);
+ _scan_options_unref0 (options);
+ }
+}
+
+
+void G_MODULE_EXPORT preferences_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ gtk_window_present ((GtkWindow*) self->priv->preferences_dialog);
+}
+
+
+gboolean G_MODULE_EXPORT preferences_dialog_delete_event_cb (GtkWidget* widget, SimpleScan* self) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ result = TRUE;
+ return result;
+}
+
+
+void G_MODULE_EXPORT preferences_dialog_response_cb (GtkWidget* widget, gint response_id, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ gtk_widget_hide ((GtkWidget*) self->priv->preferences_dialog);
+}
+
+
+static void simple_scan_update_page_menu (SimpleScan* self) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ page = _tmp0_;
+ if (page == NULL) {
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_left_menuitem, FALSE);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_right_menuitem, FALSE);
+ } else {
+ guint _tmp1_;
+ guint index;
+ guint _tmp2_;
+ _tmp1_ = book_get_page_index (self->priv->book, page);
+ index = _tmp1_;
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_left_menuitem, index > ((guint) 0));
+ _tmp2_ = book_get_n_pages (self->priv->book);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_move_right_menuitem, index < (_tmp2_ - 1));
+ }
+ _page_unref0 (page);
+}
+
+
+static void simple_scan_page_selected_cb (SimpleScan* self, BookView* view, Page* page) {
+ gchar* name;
+ gboolean _tmp0_;
+ GObject* _tmp10_ = NULL;
+ GtkRadioMenuItem* _tmp11_;
+ GtkRadioMenuItem* menuitem;
+ GObject* _tmp12_ = NULL;
+ GtkToggleToolButton* _tmp13_;
+ GtkToggleToolButton* toolbutton;
+ gboolean _tmp14_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (view != NULL);
+ if (page == NULL) {
+ return;
+ }
+ self->priv->updating_page_menu = TRUE;
+ simple_scan_update_page_menu (self);
+ name = NULL;
+ _tmp0_ = page_has_crop (page);
+ if (_tmp0_) {
+ gchar* _tmp1_ = NULL;
+ gchar* crop_name;
+ _tmp1_ = page_get_named_crop (page);
+ crop_name = _tmp1_;
+ if (crop_name != NULL) {
+ if (g_strcmp0 (crop_name, "A4") == 0) {
+ gchar* _tmp2_;
+ _tmp2_ = g_strdup ("a4_menuitem");
+ _g_free0 (name);
+ name = _tmp2_;
+ } else {
+ if (g_strcmp0 (crop_name, "A5") == 0) {
+ gchar* _tmp3_;
+ _tmp3_ = g_strdup ("a5_menuitem");
+ _g_free0 (name);
+ name = _tmp3_;
+ } else {
+ if (g_strcmp0 (crop_name, "A6") == 0) {
+ gchar* _tmp4_;
+ _tmp4_ = g_strdup ("a6_menuitem");
+ _g_free0 (name);
+ name = _tmp4_;
+ } else {
+ if (g_strcmp0 (crop_name, "letter") == 0) {
+ gchar* _tmp5_;
+ _tmp5_ = g_strdup ("letter_menuitem");
+ _g_free0 (name);
+ name = _tmp5_;
+ } else {
+ if (g_strcmp0 (crop_name, "legal") == 0) {
+ gchar* _tmp6_;
+ _tmp6_ = g_strdup ("legal_menuitem");
+ _g_free0 (name);
+ name = _tmp6_;
+ } else {
+ if (g_strcmp0 (crop_name, "4x6") == 0) {
+ gchar* _tmp7_;
+ _tmp7_ = g_strdup ("4x6_menuitem");
+ _g_free0 (name);
+ name = _tmp7_;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ gchar* _tmp8_;
+ _tmp8_ = g_strdup ("custom_crop_menuitem");
+ _g_free0 (name);
+ name = _tmp8_;
+ }
+ _g_free0 (crop_name);
+ } else {
+ gchar* _tmp9_;
+ _tmp9_ = g_strdup ("no_crop_menuitem");
+ _g_free0 (name);
+ name = _tmp9_;
+ }
+ _tmp10_ = gtk_builder_get_object (self->priv->builder, name);
+ _tmp11_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp10_));
+ menuitem = _tmp11_;
+ gtk_check_menu_item_set_active ((GtkCheckMenuItem*) menuitem, TRUE);
+ _tmp12_ = gtk_builder_get_object (self->priv->builder, "crop_toolbutton");
+ _tmp13_ = _g_object_ref0 (GTK_TOGGLE_TOOL_BUTTON (_tmp12_));
+ toolbutton = _tmp13_;
+ _tmp14_ = page_has_crop (page);
+ gtk_toggle_tool_button_set_active (toolbutton, _tmp14_);
+ self->priv->updating_page_menu = FALSE;
+ _g_object_unref0 (toolbutton);
+ _g_object_unref0 (menuitem);
+ _g_free0 (name);
+}
+
+
+static gchar* simple_scan_get_temporary_filename (SimpleScan* self, const gchar* prefix, const gchar* extension) {
+ gchar* result = NULL;
+ gchar* _tmp0_ = NULL;
+ gchar* filename;
+ gchar* path = NULL;
+ GError * _inner_error_ = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (prefix != NULL, NULL);
+ g_return_val_if_fail (extension != NULL, NULL);
+ _tmp0_ = g_strdup_printf ("%sXXXXXX.%s", prefix, extension);
+ filename = _tmp0_;
+ {
+ gchar* _tmp1_ = NULL;
+ gint _tmp2_;
+ gint fd;
+ _tmp2_ = g_file_open_tmp (filename, &_tmp1_, &_inner_error_);
+ _g_free0 (path);
+ path = _tmp1_;
+ fd = _tmp2_;
+ if (_inner_error_ != NULL) {
+ goto __catch11_g_error;
+ }
+ close (fd);
+ }
+ goto __finally11;
+ __catch11_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("ui.vala:788: Error saving email attachment: %s", e->message);
+ result = NULL;
+ _g_error_free0 (e);
+ _g_free0 (path);
+ _g_free0 (filename);
+ return result;
+ }
+ __finally11:
+ if (_inner_error_ != NULL) {
+ _g_free0 (path);
+ _g_free0 (filename);
+ 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;
+ }
+ result = path;
+ _g_free0 (filename);
+ return result;
+}
+
+
+static void simple_scan_show_page_cb (SimpleScan* self, BookView* view, Page* page) {
+ gchar* _tmp0_ = NULL;
+ gchar* path;
+ GFile* _tmp1_ = NULL;
+ GFile* file;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = simple_scan_get_temporary_filename (self, "scanned-page", "tiff");
+ path = _tmp0_;
+ if (path == NULL) {
+ _g_free0 (path);
+ return;
+ }
+ _tmp1_ = g_file_new_for_path (path);
+ file = _tmp1_;
+ {
+ page_save (page, "tiff", file, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch12_g_error;
+ }
+ }
+ goto __finally12;
+ __catch12_g_error:
+ {
+ GError* e = NULL;
+ const gchar* _tmp2_ = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ _tmp2_ = _ ("Unable to save image for preview");
+ simple_scan_show_error_dialog (self, _tmp2_, e->message);
+ _g_error_free0 (e);
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ return;
+ }
+ __finally12:
+ if (_inner_error_ != NULL) {
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ 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;
+ }
+ {
+ GdkScreen* _tmp3_ = NULL;
+ gchar* _tmp4_ = NULL;
+ gchar* _tmp5_;
+ guint32 _tmp6_;
+ _tmp3_ = gtk_window_get_screen (self->priv->window);
+ _tmp4_ = g_file_get_uri (file);
+ _tmp5_ = _tmp4_;
+ _tmp6_ = gtk_get_current_event_time ();
+ gtk_show_uri (_tmp3_, _tmp5_, _tmp6_, &_inner_error_);
+ _g_free0 (_tmp5_);
+ if (_inner_error_ != NULL) {
+ goto __catch13_g_error;
+ }
+ }
+ goto __finally13;
+ __catch13_g_error:
+ {
+ GError* e = NULL;
+ const gchar* _tmp7_ = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ _tmp7_ = _ ("Unable to open image preview application");
+ simple_scan_show_error_dialog (self, _tmp7_, e->message);
+ _g_error_free0 (e);
+ }
+ __finally13:
+ if (_inner_error_ != NULL) {
+ _g_object_unref0 (file);
+ _g_free0 (path);
+ 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;
+ }
+ _g_object_unref0 (file);
+ _g_free0 (path);
+}
+
+
+static void simple_scan_show_page_menu_cb (SimpleScan* self, BookView* view) {
+ GObject* _tmp0_ = NULL;
+ GtkMenu* _tmp1_;
+ GtkMenu* menu;
+ guint32 _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (view != NULL);
+ _tmp0_ = gtk_builder_get_object (self->priv->builder, "page_menu");
+ _tmp1_ = _g_object_ref0 (GTK_MENU (_tmp0_));
+ menu = _tmp1_;
+ _tmp2_ = gtk_get_current_event_time ();
+ gtk_menu_popup (menu, NULL, NULL, NULL, NULL, (guint) 3, _tmp2_);
+ _g_object_unref0 (menu);
+}
+
+
+void G_MODULE_EXPORT rotate_left_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ if (self->priv->updating_page_menu) {
+ return;
+ }
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ page = _tmp0_;
+ if (page != NULL) {
+ page_rotate_left (page);
+ }
+ _page_unref0 (page);
+}
+
+
+void G_MODULE_EXPORT rotate_right_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ if (self->priv->updating_page_menu) {
+ return;
+ }
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ page = _tmp0_;
+ if (page != NULL) {
+ page_rotate_right (page);
+ }
+ _page_unref0 (page);
+}
+
+
+static void simple_scan_set_crop (SimpleScan* self, const gchar* crop_name) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->crop_rotate_menuitem, crop_name != NULL);
+ if (self->priv->updating_page_menu) {
+ return;
+ }
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ page = _tmp0_;
+ if (page == NULL) {
+ _page_unref0 (page);
+ return;
+ }
+ if (crop_name == NULL) {
+ page_set_no_crop (page);
+ _page_unref0 (page);
+ return;
+ } else {
+ if (g_strcmp0 (crop_name, "custom") == 0) {
+ gint _tmp1_;
+ gint width;
+ gint _tmp2_;
+ gint height;
+ gint crop_width;
+ gint crop_height;
+ _tmp1_ = page_get_width (page);
+ width = _tmp1_;
+ _tmp2_ = page_get_height (page);
+ height = _tmp2_;
+ crop_width = (gint) ((width * 0.8) + 0.5);
+ crop_height = (gint) ((height * 0.8) + 0.5);
+ page_set_custom_crop (page, crop_width, crop_height);
+ page_move_crop (page, (width - crop_width) / 2, (height - crop_height) / 2);
+ } else {
+ page_set_named_crop (page, crop_name);
+ }
+ }
+ _page_unref0 (page);
+}
+
+
+void G_MODULE_EXPORT no_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, NULL);
+ }
+}
+
+
+void G_MODULE_EXPORT custom_crop_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, "custom");
+ }
+}
+
+
+void G_MODULE_EXPORT crop_toolbutton_toggled_cb (GtkToggleToolButton* widget, SimpleScan* self) {
+ GtkRadioMenuItem* menuitem = NULL;
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ if (self->priv->updating_page_menu) {
+ return;
+ }
+ _tmp0_ = gtk_toggle_tool_button_get_active (widget);
+ if (_tmp0_) {
+ GObject* _tmp1_ = NULL;
+ GtkRadioMenuItem* _tmp2_;
+ _tmp1_ = gtk_builder_get_object (self->priv->builder, "custom_crop_menuitem");
+ _tmp2_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp1_));
+ _g_object_unref0 (menuitem);
+ menuitem = _tmp2_;
+ } else {
+ GObject* _tmp3_ = NULL;
+ GtkRadioMenuItem* _tmp4_;
+ _tmp3_ = gtk_builder_get_object (self->priv->builder, "no_crop_menuitem");
+ _tmp4_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp3_));
+ _g_object_unref0 (menuitem);
+ menuitem = _tmp4_;
+ }
+ gtk_check_menu_item_set_active ((GtkCheckMenuItem*) menuitem, TRUE);
+ _g_object_unref0 (menuitem);
+}
+
+
+void G_MODULE_EXPORT four_by_six_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, "4x6");
+ }
+}
+
+
+void G_MODULE_EXPORT legal_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, "legal");
+ }
+}
+
+
+void G_MODULE_EXPORT letter_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, "letter");
+ }
+}
+
+
+void G_MODULE_EXPORT a6_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, "A6");
+ }
+}
+
+
+void G_MODULE_EXPORT a5_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, "A5");
+ }
+}
+
+
+void G_MODULE_EXPORT a4_menuitem_toggled_cb (GtkCheckMenuItem* widget, SimpleScan* self) {
+ gboolean _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_check_menu_item_get_active (widget);
+ if (_tmp0_) {
+ simple_scan_set_crop (self, "A4");
+ }
+}
+
+
+void G_MODULE_EXPORT crop_rotate_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ page = _tmp0_;
+ if (page == NULL) {
+ _page_unref0 (page);
+ return;
+ }
+ page_rotate_crop (page);
+ _page_unref0 (page);
+}
+
+
+void G_MODULE_EXPORT page_move_left_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ guint _tmp1_;
+ guint index;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ page = _tmp0_;
+ _tmp1_ = book_get_page_index (self->priv->book, page);
+ index = _tmp1_;
+ if (index > ((guint) 0)) {
+ book_move_page (self->priv->book, page, index - 1);
+ }
+ simple_scan_update_page_menu (self);
+ _page_unref0 (page);
+}
+
+
+void G_MODULE_EXPORT page_move_right_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) {
+ Page* _tmp0_ = NULL;
+ Page* page;
+ guint _tmp1_;
+ guint index;
+ guint _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ page = _tmp0_;
+ _tmp1_ = book_get_page_index (self->priv->book, page);
+ index = _tmp1_;
+ _tmp2_ = book_get_n_pages (self->priv->book);
+ if (index < (_tmp2_ - 1)) {
+ guint _tmp3_;
+ _tmp3_ = book_get_page_index (self->priv->book, page);
+ book_move_page (self->priv->book, page, _tmp3_ + 1);
+ }
+ simple_scan_update_page_menu (self);
+ _page_unref0 (page);
+}
+
+
+void G_MODULE_EXPORT page_delete_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) {
+ Book* _tmp0_ = NULL;
+ Book* _tmp1_;
+ Page* _tmp2_ = NULL;
+ Page* _tmp3_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = book_view_get_book (self->priv->book_view);
+ _tmp1_ = _tmp0_;
+ _tmp2_ = book_view_get_selected (self->priv->book_view);
+ _tmp3_ = _tmp2_;
+ book_delete_page (_tmp1_, _tmp3_);
+ _page_unref0 (_tmp3_);
+ _book_unref0 (_tmp1_);
+}
+
+
+void G_MODULE_EXPORT save_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ simple_scan_save_document (self, FALSE);
+}
+
+
+void G_MODULE_EXPORT save_as_file_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ simple_scan_save_document (self, TRUE);
+}
+
+
+static gpointer _cairo_reference0 (gpointer self) {
+ return self ? cairo_reference (self) : NULL;
+}
+
+
+static void simple_scan_draw_page (SimpleScan* self, GtkPrintOperation* operation, GtkPrintContext* print_context, gint page_number) {
+ cairo_t* _tmp0_ = NULL;
+ cairo_t* _tmp1_;
+ cairo_t* context;
+ Page* _tmp2_ = NULL;
+ Page* page;
+ gboolean is_landscape;
+ gdouble _tmp3_;
+ gdouble _tmp4_;
+ gboolean _tmp5_;
+ gdouble _tmp7_;
+ gint _tmp8_;
+ gdouble _tmp9_;
+ gint _tmp10_;
+ GdkPixbuf* _tmp11_ = NULL;
+ GdkPixbuf* image;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (operation != NULL);
+ g_return_if_fail (print_context != NULL);
+ _tmp0_ = gtk_print_context_get_cairo_context (print_context);
+ _tmp1_ = _cairo_reference0 (_tmp0_);
+ context = _tmp1_;
+ _tmp2_ = book_get_page (self->priv->book, page_number);
+ page = _tmp2_;
+ is_landscape = FALSE;
+ _tmp3_ = gtk_print_context_get_width (print_context);
+ _tmp4_ = gtk_print_context_get_height (print_context);
+ if (_tmp3_ > _tmp4_) {
+ is_landscape = TRUE;
+ }
+ _tmp5_ = page_is_landscape (page);
+ if (_tmp5_ != is_landscape) {
+ gdouble _tmp6_;
+ _tmp6_ = gtk_print_context_get_width (print_context);
+ cairo_translate (context, _tmp6_, (gdouble) 0);
+ cairo_rotate (context, G_PI_2);
+ }
+ _tmp7_ = gtk_print_context_get_dpi_x (print_context);
+ _tmp8_ = page_get_dpi (page);
+ _tmp9_ = gtk_print_context_get_dpi_y (print_context);
+ _tmp10_ = page_get_dpi (page);
+ cairo_scale (context, _tmp7_ / _tmp8_, _tmp9_ / _tmp10_);
+ _tmp11_ = page_get_image (page, TRUE);
+ image = _tmp11_;
+ gdk_cairo_set_source_pixbuf (context, image, (gdouble) 0, (gdouble) 0);
+ cairo_paint (context);
+ _g_object_unref0 (image);
+ _page_unref0 (page);
+ _cairo_destroy0 (context);
+}
+
+
+void G_MODULE_EXPORT email_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ g_signal_emit_by_name (self, "email", self->priv->document_hint);
+}
+
+
+static void _simple_scan_draw_page_gtk_print_operation_draw_page (GtkPrintOperation* _sender, GtkPrintContext* context, gint page_nr, gpointer self) {
+ simple_scan_draw_page (self, _sender, context, page_nr);
+}
+
+
+void G_MODULE_EXPORT print_button_clicked_cb (GtkWidget* widget, SimpleScan* self) {
+ GtkPrintOperation* _tmp0_ = NULL;
+ GtkPrintOperation* print;
+ guint _tmp1_;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = gtk_print_operation_new ();
+ print = _tmp0_;
+ _tmp1_ = book_get_n_pages (self->priv->book);
+ gtk_print_operation_set_n_pages (print, (gint) _tmp1_);
+ g_signal_connect (print, "draw-page", (GCallback) _simple_scan_draw_page_gtk_print_operation_draw_page, self);
+ {
+ gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, self->priv->window, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch14_g_error;
+ }
+ }
+ goto __finally14;
+ __catch14_g_error:
+ {
+ GError* e = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_warning ("ui.vala:1044: Error printing: %s", e->message);
+ _g_error_free0 (e);
+ }
+ __finally14:
+ if (_inner_error_ != NULL) {
+ _g_object_unref0 (print);
+ 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;
+ }
+ _g_object_unref0 (print);
+}
+
+
+void G_MODULE_EXPORT help_contents_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) {
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ {
+ GdkScreen* _tmp0_ = NULL;
+ guint32 _tmp1_;
+ _tmp0_ = gtk_window_get_screen (self->priv->window);
+ _tmp1_ = gtk_get_current_event_time ();
+ gtk_show_uri (_tmp0_, "ghelp:simple-scan", _tmp1_, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch15_g_error;
+ }
+ }
+ goto __finally15;
+ __catch15_g_error:
+ {
+ GError* e = NULL;
+ const gchar* _tmp2_ = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ _tmp2_ = _ ("Unable to open help file");
+ simple_scan_show_error_dialog (self, _tmp2_, e->message);
+ _g_error_free0 (e);
+ }
+ __finally15:
+ if (_inner_error_ != NULL) {
+ 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;
+ }
+}
+
+
+void G_MODULE_EXPORT about_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) {
+ gchar* _tmp0_;
+ gchar** _tmp1_ = NULL;
+ gchar** authors;
+ gint authors_length1;
+ gint _authors_size_;
+ const gchar* _tmp2_ = NULL;
+ gchar* _tmp3_;
+ gchar* license;
+ const gchar* _tmp4_ = NULL;
+ gchar* _tmp5_;
+ gchar* title;
+ const gchar* _tmp6_ = NULL;
+ gchar* _tmp7_;
+ gchar* description;
+ const gchar* _tmp8_ = NULL;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ _tmp0_ = g_strdup ("Robert Ancell <robert.ancell@canonical.com>");
+ _tmp1_ = g_new0 (gchar*, 1 + 1);
+ _tmp1_[0] = _tmp0_;
+ authors = _tmp1_;
+ authors_length1 = 1;
+ _authors_size_ = authors_length1;
+ _tmp2_ = _ ("This program is free software: you can redistribute it and/or modify\n" \
+"it under the terms of the GNU General Public License as published by\n" \
+"the Free Software Foundation, either version 3 of the License, or\n" \
+"(at your option) any later version.\n" \
+"\n" \
+"This program is distributed in the hope that it will be useful,\n" \
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" \
+"GNU General Public License for more details.\n" \
+"\n" \
+"You should have received a copy of the GNU General Public License\n" \
+"along with this program. If not, see <http://www.gnu.org/licenses/>.");
+ _tmp3_ = g_strdup (_tmp2_);
+ license = _tmp3_;
+ _tmp4_ = _ ("About Simple Scan");
+ _tmp5_ = g_strdup (_tmp4_);
+ title = _tmp5_;
+ _tmp6_ = _ ("Simple document scanning tool");
+ _tmp7_ = g_strdup (_tmp6_);
+ description = _tmp7_;
+ _tmp8_ = _ ("translator-credits");
+ gtk_show_about_dialog (self->priv->window, "title", title, "program-name", "Simple Scan", "version", VERSION, "comments", description, "logo-icon-name", "scanner", "authors", authors, "translator-credits", _tmp8_, "website", "https://launchpad.net/simple-scan", "copyright", "Copyright © 2009-2011 Canonical Ltd.", "license", license, "wrap-license", TRUE, NULL, NULL);
+ _g_free0 (description);
+ _g_free0 (title);
+ _g_free0 (license);
+ authors = (_vala_array_free (authors, authors_length1, (GDestroyNotify) g_free), NULL);
+}
+
+
+static gboolean simple_scan_on_quit (SimpleScan* self) {
+ gboolean result = FALSE;
+ const gchar* _tmp0_ = NULL;
+ const gchar* _tmp1_ = NULL;
+ gboolean _tmp2_;
+ gchar* _tmp3_ = NULL;
+ gchar* device;
+ gint paper_width;
+ gint paper_height;
+ gint _tmp4_;
+ gint _tmp5_;
+ gint _tmp6_;
+ gint _tmp7_;
+ ScanType _tmp8_;
+ g_return_val_if_fail (self != NULL, FALSE);
+ _tmp0_ = _ ("Save document before quitting?");
+ _tmp1_ = _ ("Quit without Saving");
+ _tmp2_ = simple_scan_prompt_to_save (self, _tmp0_, _tmp1_);
+ if (!_tmp2_) {
+ result = FALSE;
+ return result;
+ }
+ _tmp3_ = simple_scan_get_selected_device (self);
+ device = _tmp3_;
+ paper_width = 0;
+ paper_height = 0;
+ simple_scan_get_paper_size (self, &_tmp4_, &_tmp5_);
+ paper_width = _tmp4_;
+ paper_height = _tmp5_;
+ if (device != NULL) {
+ g_settings_set_string (self->priv->settings, "selected-device", device);
+ }
+ g_settings_set_string (self->priv->settings, "document-type", self->priv->document_hint);
+ _tmp6_ = simple_scan_get_text_dpi (self);
+ g_settings_set_int (self->priv->settings, "text-dpi", _tmp6_);
+ _tmp7_ = simple_scan_get_photo_dpi (self);
+ g_settings_set_int (self->priv->settings, "photo-dpi", _tmp7_);
+ _tmp8_ = simple_scan_get_page_side (self);
+ g_settings_set_enum (self->priv->settings, "page-side", (gint) _tmp8_);
+ g_settings_set_int (self->priv->settings, "paper-width", paper_width);
+ g_settings_set_int (self->priv->settings, "paper-height", paper_height);
+ g_settings_set_int (self->priv->settings, "window-width", self->priv->window_width);
+ g_settings_set_int (self->priv->settings, "window-height", self->priv->window_height);
+ g_settings_set_boolean (self->priv->settings, "window-is-maximized", self->priv->window_is_maximized);
+ g_settings_set_enum (self->priv->settings, "scan-direction", (gint) self->priv->default_page_scan_direction);
+ g_settings_set_int (self->priv->settings, "page-width", self->priv->default_page_width);
+ g_settings_set_int (self->priv->settings, "page-height", self->priv->default_page_height);
+ g_settings_set_int (self->priv->settings, "page-dpi", self->priv->default_page_dpi);
+ g_signal_emit_by_name (self, "quit");
+ result = TRUE;
+ _g_free0 (device);
+ return result;
+}
+
+
+void G_MODULE_EXPORT quit_menuitem_activate_cb (GtkWidget* widget, SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ simple_scan_on_quit (self);
+}
+
+
+gboolean G_MODULE_EXPORT simple_scan_window_configure_event_cb (GtkWidget* widget, GdkEventConfigure* event, SimpleScan* self) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ if (!self->priv->window_is_maximized) {
+ self->priv->window_width = (*event).width;
+ self->priv->window_height = (*event).height;
+ }
+ result = FALSE;
+ return result;
+}
+
+
+static void simple_scan_info_bar_response_cb (SimpleScan* self, GtkInfoBar* widget, gint response_id) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (widget != NULL);
+ if (response_id == 1) {
+ gtk_widget_grab_focus ((GtkWidget*) self->priv->device_combo);
+ gtk_window_present ((GtkWindow*) self->priv->preferences_dialog);
+ } else {
+ self->priv->have_error = FALSE;
+ _g_free0 (self->priv->error_title);
+ self->priv->error_title = NULL;
+ _g_free0 (self->priv->error_text);
+ self->priv->error_text = NULL;
+ simple_scan_update_info_bar (self);
+ }
+}
+
+
+gboolean G_MODULE_EXPORT simple_scan_window_window_state_event_cb (GtkWidget* widget, GdkEventWindowState* event, SimpleScan* self) {
+ gboolean result = FALSE;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ if (((*event).changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0) {
+ self->priv->window_is_maximized = ((*event).new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
+ }
+ result = FALSE;
+ return result;
+}
+
+
+gboolean G_MODULE_EXPORT window_delete_event_cb (GtkWidget* widget, GdkEvent* event, SimpleScan* self) {
+ gboolean result = FALSE;
+ gboolean _tmp0_;
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ _tmp0_ = simple_scan_on_quit (self);
+ result = !_tmp0_;
+ return result;
+}
+
+
+static void simple_scan_page_size_changed_cb (SimpleScan* self, Page* page) {
+ gint _tmp0_;
+ gint _tmp1_;
+ gint _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = page_get_width (page);
+ self->priv->default_page_width = _tmp0_;
+ _tmp1_ = page_get_height (page);
+ self->priv->default_page_height = _tmp1_;
+ _tmp2_ = page_get_dpi (page);
+ self->priv->default_page_dpi = _tmp2_;
+}
+
+
+static void simple_scan_page_scan_direction_changed_cb (SimpleScan* self, Page* page) {
+ ScanDirection _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = page_get_scan_direction (page);
+ self->priv->default_page_scan_direction = _tmp0_;
+}
+
+
+static void _simple_scan_page_size_changed_cb_page_size_changed (Page* _sender, gpointer self) {
+ simple_scan_page_size_changed_cb (self, _sender);
+}
+
+
+static void _simple_scan_page_scan_direction_changed_cb_page_scan_direction_changed (Page* _sender, gpointer self) {
+ simple_scan_page_scan_direction_changed_cb (self, _sender);
+}
+
+
+static void simple_scan_page_added_cb (SimpleScan* self, Book* book, Page* page) {
+ gint _tmp0_;
+ gint _tmp1_;
+ gint _tmp2_;
+ ScanDirection _tmp3_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (book != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = page_get_width (page);
+ self->priv->default_page_width = _tmp0_;
+ _tmp1_ = page_get_height (page);
+ self->priv->default_page_height = _tmp1_;
+ _tmp2_ = page_get_dpi (page);
+ self->priv->default_page_dpi = _tmp2_;
+ _tmp3_ = page_get_scan_direction (page);
+ self->priv->default_page_scan_direction = _tmp3_;
+ g_signal_connect (page, "size-changed", (GCallback) _simple_scan_page_size_changed_cb_page_size_changed, self);
+ g_signal_connect (page, "scan-direction-changed", (GCallback) _simple_scan_page_scan_direction_changed_cb_page_scan_direction_changed, self);
+ simple_scan_update_page_menu (self);
+}
+
+
+static void simple_scan_page_removed_cb (SimpleScan* self, Book* book, Page* page) {
+ guint _tmp0_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (book != NULL);
+ g_return_if_fail (page != NULL);
+ _tmp0_ = book_get_n_pages (book);
+ if (_tmp0_ == ((guint) 1)) {
+ simple_scan_add_default_page (self);
+ }
+ simple_scan_update_page_menu (self);
+}
+
+
+static void simple_scan_set_dpi_combo (SimpleScan* self, GtkComboBox* combo, gint default_dpi, gint current_dpi) {
+ GtkCellRendererText* _tmp0_ = NULL;
+ GtkCellRendererText* renderer;
+ GtkTreeModel* _tmp1_ = NULL;
+ GtkListStore* _tmp2_;
+ GtkListStore* model;
+ gint* _tmp3_ = NULL;
+ gint* scan_resolutions;
+ gint scan_resolutions_length1;
+ gint _scan_resolutions_size_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (combo != NULL);
+ _tmp0_ = (GtkCellRendererText*) gtk_cell_renderer_text_new ();
+ renderer = g_object_ref_sink (_tmp0_);
+ gtk_cell_layout_pack_start ((GtkCellLayout*) combo, (GtkCellRenderer*) renderer, TRUE);
+ gtk_cell_layout_add_attribute ((GtkCellLayout*) combo, (GtkCellRenderer*) renderer, "text", 1);
+ _tmp1_ = gtk_combo_box_get_model (combo);
+ _tmp2_ = _g_object_ref0 (GTK_LIST_STORE (_tmp1_));
+ model = _tmp2_;
+ _tmp3_ = g_new0 (gint, 6);
+ _tmp3_[0] = 75;
+ _tmp3_[1] = 150;
+ _tmp3_[2] = 300;
+ _tmp3_[3] = 600;
+ _tmp3_[4] = 1200;
+ _tmp3_[5] = 2400;
+ scan_resolutions = _tmp3_;
+ scan_resolutions_length1 = 6;
+ _scan_resolutions_size_ = scan_resolutions_length1;
+ {
+ gint* dpi_collection = NULL;
+ gint dpi_collection_length1 = 0;
+ gint _dpi_collection_size_ = 0;
+ gint dpi_it;
+ dpi_collection = scan_resolutions;
+ dpi_collection_length1 = scan_resolutions_length1;
+ for (dpi_it = 0; dpi_it < scan_resolutions_length1; dpi_it = dpi_it + 1) {
+ gint dpi = 0;
+ dpi = dpi_collection[dpi_it];
+ {
+ gchar* label = NULL;
+ GtkTreeIter iter = {0};
+ GtkTreeIter _tmp12_ = {0};
+ if (dpi == default_dpi) {
+ const gchar* _tmp4_ = NULL;
+ gchar* _tmp5_ = NULL;
+ _tmp4_ = _ ("%d dpi (default)");
+ _tmp5_ = g_strdup_printf (_tmp4_, dpi);
+ _g_free0 (label);
+ label = _tmp5_;
+ } else {
+ if (dpi == 75) {
+ const gchar* _tmp6_ = NULL;
+ gchar* _tmp7_ = NULL;
+ _tmp6_ = _ ("%d dpi (draft)");
+ _tmp7_ = g_strdup_printf (_tmp6_, dpi);
+ _g_free0 (label);
+ label = _tmp7_;
+ } else {
+ if (dpi == 1200) {
+ const gchar* _tmp8_ = NULL;
+ gchar* _tmp9_ = NULL;
+ _tmp8_ = _ ("%d dpi (high resolution)");
+ _tmp9_ = g_strdup_printf (_tmp8_, dpi);
+ _g_free0 (label);
+ label = _tmp9_;
+ } else {
+ const gchar* _tmp10_ = NULL;
+ gchar* _tmp11_ = NULL;
+ _tmp10_ = _ ("%d dpi");
+ _tmp11_ = g_strdup_printf (_tmp10_, dpi);
+ _g_free0 (label);
+ label = _tmp11_;
+ }
+ }
+ }
+ gtk_list_store_append (model, &_tmp12_);
+ iter = _tmp12_;
+ gtk_list_store_set (model, &iter, 0, dpi, 1, label, -1, -1);
+ if (dpi == current_dpi) {
+ gtk_combo_box_set_active_iter (combo, &iter);
+ }
+ _g_free0 (label);
+ }
+ }
+ }
+ scan_resolutions = (g_free (scan_resolutions), NULL);
+ _g_object_unref0 (model);
+ _g_object_unref0 (renderer);
+}
+
+
+static void simple_scan_needs_saving_cb (SimpleScan* self, Book* book) {
+ gboolean _tmp0_;
+ gboolean _tmp1_;
+ gboolean _tmp2_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (book != NULL);
+ _tmp0_ = book_get_needs_saving (book);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_menuitem, _tmp0_);
+ _tmp1_ = book_get_needs_saving (book);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_toolbutton, _tmp1_);
+ _tmp2_ = book_get_needs_saving (book);
+ if (_tmp2_) {
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->save_as_menuitem, TRUE);
+ }
+}
+
+
+static void _simple_scan_info_bar_response_cb_gtk_info_bar_response (GtkInfoBar* _sender, gint response_id, gpointer self) {
+ simple_scan_info_bar_response_cb (self, _sender, response_id);
+}
+
+
+static void _simple_scan_page_selected_cb_book_view_page_selected (BookView* _sender, Page* page, gpointer self) {
+ simple_scan_page_selected_cb (self, _sender, page);
+}
+
+
+static void _simple_scan_show_page_cb_book_view_show_page (BookView* _sender, Page* page, gpointer self) {
+ simple_scan_show_page_cb (self, _sender, page);
+}
+
+
+static void _simple_scan_show_page_menu_cb_book_view_show_menu (BookView* _sender, gpointer self) {
+ simple_scan_show_page_menu_cb (self, _sender);
+}
+
+
+static void _simple_scan_needs_saving_cb_book_needs_saving_changed (Book* _sender, gpointer self) {
+ simple_scan_needs_saving_cb (self, _sender);
+}
+
+
+static void simple_scan_load (SimpleScan* self) {
+ GtkIconTheme* _tmp0_ = NULL;
+ GtkBuilder* _tmp1_ = NULL;
+ gchar* _tmp2_ = NULL;
+ gchar* filename;
+ GObject* _tmp5_ = NULL;
+ GtkWindow* _tmp6_;
+ GObject* _tmp7_ = NULL;
+ GtkVBox* _tmp8_;
+ GObject* _tmp9_ = NULL;
+ GtkMenuItem* _tmp10_;
+ GObject* _tmp11_ = NULL;
+ GtkMenuItem* _tmp12_;
+ GObject* _tmp13_ = NULL;
+ GtkMenuItem* _tmp14_;
+ GObject* _tmp15_ = NULL;
+ GtkMenuItem* _tmp16_;
+ GObject* _tmp17_ = NULL;
+ GtkMenuItem* _tmp18_;
+ GObject* _tmp19_ = NULL;
+ GtkMenuItem* _tmp20_;
+ GObject* _tmp21_ = NULL;
+ GtkToolButton* _tmp22_;
+ GObject* _tmp23_ = NULL;
+ GtkMenuItem* _tmp24_;
+ GObject* _tmp25_ = NULL;
+ GtkToolButton* _tmp26_;
+ GObject* _tmp27_ = NULL;
+ GtkRadioMenuItem* _tmp28_;
+ GObject* _tmp29_ = NULL;
+ GtkRadioMenuItem* _tmp30_;
+ GObject* _tmp31_ = NULL;
+ GtkRadioMenuItem* _tmp32_;
+ GObject* _tmp33_ = NULL;
+ GtkRadioMenuItem* _tmp34_;
+ GObject* _tmp35_ = NULL;
+ GtkDialog* _tmp36_;
+ GObject* _tmp37_ = NULL;
+ GtkLabel* _tmp38_;
+ GObject* _tmp39_ = NULL;
+ GtkEntry* _tmp40_;
+ GObject* _tmp41_ = NULL;
+ GtkEntry* _tmp42_;
+ GObject* _tmp43_ = NULL;
+ GtkDialog* _tmp44_;
+ GObject* _tmp45_ = NULL;
+ GtkComboBox* _tmp46_;
+ GtkTreeModel* _tmp47_ = NULL;
+ GtkListStore* _tmp48_;
+ GObject* _tmp49_ = NULL;
+ GtkComboBox* _tmp50_;
+ GtkTreeModel* _tmp51_ = NULL;
+ GtkListStore* _tmp52_;
+ GObject* _tmp53_ = NULL;
+ GtkComboBox* _tmp54_;
+ GtkTreeModel* _tmp55_ = NULL;
+ GtkListStore* _tmp56_;
+ GObject* _tmp57_ = NULL;
+ GtkComboBox* _tmp58_;
+ GtkTreeModel* _tmp59_ = NULL;
+ GtkListStore* _tmp60_;
+ GObject* _tmp61_ = NULL;
+ GtkComboBox* _tmp62_;
+ GtkTreeModel* _tmp63_ = NULL;
+ GtkListStore* _tmp64_;
+ GtkInfoBar* _tmp65_ = NULL;
+ GtkHBox* _tmp66_ = NULL;
+ GtkHBox* hbox;
+ GtkWidget* _tmp67_ = NULL;
+ GtkContainer* _tmp68_;
+ GtkContainer* content_area;
+ GtkImage* _tmp69_ = NULL;
+ GtkLabel* _tmp70_ = NULL;
+ GtkWidget* _tmp71_ = NULL;
+ GtkButton* _tmp72_;
+ const gchar* _tmp73_ = NULL;
+ GtkWidget* _tmp74_ = NULL;
+ GtkButton* _tmp75_;
+ GtkTreeIter iter = {0};
+ GtkTreeIter _tmp76_ = {0};
+ const gchar* _tmp77_ = NULL;
+ GtkTreeIter _tmp78_ = {0};
+ GtkTreeIter _tmp79_ = {0};
+ GtkTreeIter _tmp80_ = {0};
+ GtkTreeIter _tmp81_ = {0};
+ GtkTreeIter _tmp82_ = {0};
+ GtkTreeIter _tmp83_ = {0};
+ gint _tmp84_;
+ gint dpi;
+ gint _tmp85_;
+ GtkCellRendererText* _tmp86_ = NULL;
+ GtkCellRendererText* renderer;
+ GtkCellRendererText* _tmp87_ = NULL;
+ gint _tmp88_;
+ GtkCellRendererText* _tmp89_ = NULL;
+ gint _tmp90_;
+ gint paper_width;
+ gint _tmp91_;
+ gint paper_height;
+ gchar* _tmp92_ = NULL;
+ gchar* device;
+ gchar* _tmp95_ = NULL;
+ gchar* document_type;
+ BookView* _tmp96_ = NULL;
+ gint _tmp97_;
+ gint _tmp98_;
+ gint _tmp99_;
+ gint _tmp100_;
+ gint _tmp101_;
+ gint _tmp102_;
+ gboolean _tmp103_;
+ guint _tmp104_;
+ GError * _inner_error_ = NULL;
+ g_return_if_fail (self != NULL);
+ _tmp0_ = gtk_icon_theme_get_default ();
+ gtk_icon_theme_append_search_path (_tmp0_, ICON_DIR);
+ gtk_window_set_default_icon_name ("scanner");
+ _tmp1_ = gtk_builder_new ();
+ _g_object_unref0 (self->priv->builder);
+ self->priv->builder = _tmp1_;
+ _tmp2_ = g_build_filename (UI_DIR, "simple-scan.ui", NULL, NULL);
+ filename = _tmp2_;
+ {
+ gtk_builder_add_from_file (self->priv->builder, filename, &_inner_error_);
+ if (_inner_error_ != NULL) {
+ goto __catch16_g_error;
+ }
+ }
+ goto __finally16;
+ __catch16_g_error:
+ {
+ GError* e = NULL;
+ const gchar* _tmp3_ = NULL;
+ const gchar* _tmp4_ = NULL;
+ e = _inner_error_;
+ _inner_error_ = NULL;
+ g_critical ("ui.vala:1261: Unable to load UI %s: %s\n", filename, e->message);
+ _tmp3_ = _ ("Files missing");
+ _tmp4_ = _ ("Please check your installation");
+ simple_scan_show_error_dialog (self, _tmp3_, _tmp4_);
+ exit (EXIT_FAILURE);
+ _g_error_free0 (e);
+ }
+ __finally16:
+ if (_inner_error_ != NULL) {
+ _g_free0 (filename);
+ 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;
+ }
+ gtk_builder_connect_signals (self->priv->builder, self);
+ _tmp5_ = gtk_builder_get_object (self->priv->builder, "simple_scan_window");
+ _tmp6_ = _g_object_ref0 (GTK_WINDOW (_tmp5_));
+ _g_object_unref0 (self->priv->window);
+ self->priv->window = _tmp6_;
+ _tmp7_ = gtk_builder_get_object (self->priv->builder, "main_vbox");
+ _tmp8_ = _g_object_ref0 (GTK_VBOX (_tmp7_));
+ _g_object_unref0 (self->priv->main_vbox);
+ self->priv->main_vbox = _tmp8_;
+ _tmp9_ = gtk_builder_get_object (self->priv->builder, "page_move_left_menuitem");
+ _tmp10_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp9_));
+ _g_object_unref0 (self->priv->page_move_left_menuitem);
+ self->priv->page_move_left_menuitem = _tmp10_;
+ _tmp11_ = gtk_builder_get_object (self->priv->builder, "page_move_right_menuitem");
+ _tmp12_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp11_));
+ _g_object_unref0 (self->priv->page_move_right_menuitem);
+ self->priv->page_move_right_menuitem = _tmp12_;
+ _tmp13_ = gtk_builder_get_object (self->priv->builder, "page_delete_menuitem");
+ _tmp14_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp13_));
+ _g_object_unref0 (self->priv->page_delete_menuitem);
+ self->priv->page_delete_menuitem = _tmp14_;
+ _tmp15_ = gtk_builder_get_object (self->priv->builder, "crop_rotate_menuitem");
+ _tmp16_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp15_));
+ _g_object_unref0 (self->priv->crop_rotate_menuitem);
+ self->priv->crop_rotate_menuitem = _tmp16_;
+ _tmp17_ = gtk_builder_get_object (self->priv->builder, "save_menuitem");
+ _tmp18_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp17_));
+ _g_object_unref0 (self->priv->save_menuitem);
+ self->priv->save_menuitem = _tmp18_;
+ _tmp19_ = gtk_builder_get_object (self->priv->builder, "save_as_menuitem");
+ _tmp20_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp19_));
+ _g_object_unref0 (self->priv->save_as_menuitem);
+ self->priv->save_as_menuitem = _tmp20_;
+ _tmp21_ = gtk_builder_get_object (self->priv->builder, "save_toolbutton");
+ _tmp22_ = _g_object_ref0 (GTK_TOOL_BUTTON (_tmp21_));
+ _g_object_unref0 (self->priv->save_toolbutton);
+ self->priv->save_toolbutton = _tmp22_;
+ _tmp23_ = gtk_builder_get_object (self->priv->builder, "stop_scan_menuitem");
+ _tmp24_ = _g_object_ref0 (GTK_MENU_ITEM (_tmp23_));
+ _g_object_unref0 (self->priv->stop_menuitem);
+ self->priv->stop_menuitem = _tmp24_;
+ _tmp25_ = gtk_builder_get_object (self->priv->builder, "stop_toolbutton");
+ _tmp26_ = _g_object_ref0 (GTK_TOOL_BUTTON (_tmp25_));
+ _g_object_unref0 (self->priv->stop_toolbutton);
+ self->priv->stop_toolbutton = _tmp26_;
+ _tmp27_ = gtk_builder_get_object (self->priv->builder, "text_toolbutton_menuitem");
+ _tmp28_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp27_));
+ _g_object_unref0 (self->priv->text_toolbar_menuitem);
+ self->priv->text_toolbar_menuitem = _tmp28_;
+ _tmp29_ = gtk_builder_get_object (self->priv->builder, "text_menuitem");
+ _tmp30_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp29_));
+ _g_object_unref0 (self->priv->text_menu_menuitem);
+ self->priv->text_menu_menuitem = _tmp30_;
+ _tmp31_ = gtk_builder_get_object (self->priv->builder, "photo_toolbutton_menuitem");
+ _tmp32_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp31_));
+ _g_object_unref0 (self->priv->photo_toolbar_menuitem);
+ self->priv->photo_toolbar_menuitem = _tmp32_;
+ _tmp33_ = gtk_builder_get_object (self->priv->builder, "photo_menuitem");
+ _tmp34_ = _g_object_ref0 (GTK_RADIO_MENU_ITEM (_tmp33_));
+ _g_object_unref0 (self->priv->photo_menu_menuitem);
+ self->priv->photo_menu_menuitem = _tmp34_;
+ _tmp35_ = gtk_builder_get_object (self->priv->builder, "authorize_dialog");
+ _tmp36_ = _g_object_ref0 (GTK_DIALOG (_tmp35_));
+ _g_object_unref0 (self->priv->authorize_dialog);
+ self->priv->authorize_dialog = _tmp36_;
+ _tmp37_ = gtk_builder_get_object (self->priv->builder, "authorize_label");
+ _tmp38_ = _g_object_ref0 (GTK_LABEL (_tmp37_));
+ _g_object_unref0 (self->priv->authorize_label);
+ self->priv->authorize_label = _tmp38_;
+ _tmp39_ = gtk_builder_get_object (self->priv->builder, "username_entry");
+ _tmp40_ = _g_object_ref0 (GTK_ENTRY (_tmp39_));
+ _g_object_unref0 (self->priv->username_entry);
+ self->priv->username_entry = _tmp40_;
+ _tmp41_ = gtk_builder_get_object (self->priv->builder, "password_entry");
+ _tmp42_ = _g_object_ref0 (GTK_ENTRY (_tmp41_));
+ _g_object_unref0 (self->priv->password_entry);
+ self->priv->password_entry = _tmp42_;
+ _tmp43_ = gtk_builder_get_object (self->priv->builder, "preferences_dialog");
+ _tmp44_ = _g_object_ref0 (GTK_DIALOG (_tmp43_));
+ _g_object_unref0 (self->priv->preferences_dialog);
+ self->priv->preferences_dialog = _tmp44_;
+ _tmp45_ = gtk_builder_get_object (self->priv->builder, "device_combo");
+ _tmp46_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp45_));
+ _g_object_unref0 (self->priv->device_combo);
+ self->priv->device_combo = _tmp46_;
+ _tmp47_ = gtk_combo_box_get_model (self->priv->device_combo);
+ _tmp48_ = _g_object_ref0 (GTK_LIST_STORE (_tmp47_));
+ _g_object_unref0 (self->priv->device_model);
+ self->priv->device_model = _tmp48_;
+ _tmp49_ = gtk_builder_get_object (self->priv->builder, "text_dpi_combo");
+ _tmp50_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp49_));
+ _g_object_unref0 (self->priv->text_dpi_combo);
+ self->priv->text_dpi_combo = _tmp50_;
+ _tmp51_ = gtk_combo_box_get_model (self->priv->text_dpi_combo);
+ _tmp52_ = _g_object_ref0 (GTK_LIST_STORE (_tmp51_));
+ _g_object_unref0 (self->priv->text_dpi_model);
+ self->priv->text_dpi_model = _tmp52_;
+ _tmp53_ = gtk_builder_get_object (self->priv->builder, "photo_dpi_combo");
+ _tmp54_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp53_));
+ _g_object_unref0 (self->priv->photo_dpi_combo);
+ self->priv->photo_dpi_combo = _tmp54_;
+ _tmp55_ = gtk_combo_box_get_model (self->priv->photo_dpi_combo);
+ _tmp56_ = _g_object_ref0 (GTK_LIST_STORE (_tmp55_));
+ _g_object_unref0 (self->priv->photo_dpi_model);
+ self->priv->photo_dpi_model = _tmp56_;
+ _tmp57_ = gtk_builder_get_object (self->priv->builder, "page_side_combo");
+ _tmp58_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp57_));
+ _g_object_unref0 (self->priv->page_side_combo);
+ self->priv->page_side_combo = _tmp58_;
+ _tmp59_ = gtk_combo_box_get_model (self->priv->page_side_combo);
+ _tmp60_ = _g_object_ref0 (GTK_LIST_STORE (_tmp59_));
+ _g_object_unref0 (self->priv->page_side_model);
+ self->priv->page_side_model = _tmp60_;
+ _tmp61_ = gtk_builder_get_object (self->priv->builder, "paper_size_combo");
+ _tmp62_ = _g_object_ref0 (GTK_COMBO_BOX (_tmp61_));
+ _g_object_unref0 (self->priv->paper_size_combo);
+ self->priv->paper_size_combo = _tmp62_;
+ _tmp63_ = gtk_combo_box_get_model (self->priv->paper_size_combo);
+ _tmp64_ = _g_object_ref0 (GTK_LIST_STORE (_tmp63_));
+ _g_object_unref0 (self->priv->paper_size_model);
+ self->priv->paper_size_model = _tmp64_;
+ _tmp65_ = (GtkInfoBar*) gtk_info_bar_new ();
+ _g_object_unref0 (self->priv->info_bar);
+ self->priv->info_bar = g_object_ref_sink (_tmp65_);
+ g_signal_connect (self->priv->info_bar, "response", (GCallback) _simple_scan_info_bar_response_cb_gtk_info_bar_response, self);
+ gtk_box_pack_start ((GtkBox*) self->priv->main_vbox, (GtkWidget*) self->priv->info_bar, FALSE, TRUE, (guint) 0);
+ _tmp66_ = (GtkHBox*) gtk_hbox_new (FALSE, 12);
+ hbox = g_object_ref_sink (_tmp66_);
+ _tmp67_ = gtk_info_bar_get_content_area (self->priv->info_bar);
+ _tmp68_ = _g_object_ref0 (GTK_CONTAINER (_tmp67_));
+ content_area = _tmp68_;
+ gtk_container_add (content_area, (GtkWidget*) hbox);
+ gtk_widget_show ((GtkWidget*) hbox);
+ _tmp69_ = (GtkImage*) gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
+ _g_object_unref0 (self->priv->info_bar_image);
+ self->priv->info_bar_image = g_object_ref_sink (_tmp69_);
+ gtk_box_pack_start ((GtkBox*) hbox, (GtkWidget*) self->priv->info_bar_image, FALSE, TRUE, (guint) 0);
+ gtk_widget_show ((GtkWidget*) self->priv->info_bar_image);
+ _tmp70_ = (GtkLabel*) gtk_label_new (NULL);
+ _g_object_unref0 (self->priv->info_bar_label);
+ self->priv->info_bar_label = g_object_ref_sink (_tmp70_);
+ gtk_misc_set_alignment ((GtkMisc*) self->priv->info_bar_label, 0.0f, 0.5f);
+ gtk_box_pack_start ((GtkBox*) hbox, (GtkWidget*) self->priv->info_bar_label, TRUE, TRUE, (guint) 0);
+ gtk_widget_show ((GtkWidget*) self->priv->info_bar_label);
+ _tmp71_ = gtk_info_bar_add_button (self->priv->info_bar, GTK_STOCK_CLOSE, (gint) GTK_RESPONSE_CLOSE);
+ _tmp72_ = _g_object_ref0 (GTK_BUTTON (_tmp71_));
+ _g_object_unref0 (self->priv->info_bar_close_button);
+ self->priv->info_bar_close_button = _tmp72_;
+ _tmp73_ = _ ("Change _Scanner");
+ _tmp74_ = gtk_info_bar_add_button (self->priv->info_bar, _tmp73_, 1);
+ _tmp75_ = _g_object_ref0 (GTK_BUTTON (_tmp74_));
+ _g_object_unref0 (self->priv->info_bar_change_scanner_button);
+ self->priv->info_bar_change_scanner_button = _tmp75_;
+ gtk_list_store_append (self->priv->paper_size_model, &_tmp76_);
+ iter = _tmp76_;
+ _tmp77_ = _ ("Automatic");
+ gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 0, 1, 0, 2, _tmp77_, -1, -1);
+ gtk_list_store_append (self->priv->paper_size_model, &_tmp78_);
+ iter = _tmp78_;
+ gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 1050, 1, 1480, 2, "A6", -1, -1);
+ gtk_list_store_append (self->priv->paper_size_model, &_tmp79_);
+ iter = _tmp79_;
+ gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 1480, 1, 2100, 2, "A5", -1, -1);
+ gtk_list_store_append (self->priv->paper_size_model, &_tmp80_);
+ iter = _tmp80_;
+ gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 2100, 1, 2970, 2, "A4", -1, -1);
+ gtk_list_store_append (self->priv->paper_size_model, &_tmp81_);
+ iter = _tmp81_;
+ gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 2159, 1, 2794, 2, "Letter", -1, -1);
+ gtk_list_store_append (self->priv->paper_size_model, &_tmp82_);
+ iter = _tmp82_;
+ gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 2159, 1, 3556, 2, "Legal", -1, -1);
+ gtk_list_store_append (self->priv->paper_size_model, &_tmp83_);
+ iter = _tmp83_;
+ gtk_list_store_set (self->priv->paper_size_model, &iter, 0, 1016, 1, 1524, 2, "4×6", -1, -1);
+ _tmp84_ = g_settings_get_int (self->priv->settings, "text-dpi");
+ dpi = _tmp84_;
+ if (dpi <= 0) {
+ dpi = SIMPLE_SCAN_DEFAULT_TEXT_DPI;
+ }
+ simple_scan_set_dpi_combo (self, self->priv->text_dpi_combo, SIMPLE_SCAN_DEFAULT_TEXT_DPI, dpi);
+ _tmp85_ = g_settings_get_int (self->priv->settings, "photo-dpi");
+ dpi = _tmp85_;
+ if (dpi <= 0) {
+ dpi = SIMPLE_SCAN_DEFAULT_PHOTO_DPI;
+ }
+ simple_scan_set_dpi_combo (self, self->priv->photo_dpi_combo, SIMPLE_SCAN_DEFAULT_PHOTO_DPI, dpi);
+ _tmp86_ = (GtkCellRendererText*) gtk_cell_renderer_text_new ();
+ renderer = g_object_ref_sink (_tmp86_);
+ gtk_cell_layout_pack_start ((GtkCellLayout*) self->priv->device_combo, (GtkCellRenderer*) renderer, TRUE);
+ gtk_cell_layout_add_attribute ((GtkCellLayout*) self->priv->device_combo, (GtkCellRenderer*) renderer, "text", 1);
+ _tmp87_ = (GtkCellRendererText*) gtk_cell_renderer_text_new ();
+ _g_object_unref0 (renderer);
+ renderer = g_object_ref_sink (_tmp87_);
+ gtk_cell_layout_pack_start ((GtkCellLayout*) self->priv->page_side_combo, (GtkCellRenderer*) renderer, TRUE);
+ gtk_cell_layout_add_attribute ((GtkCellLayout*) self->priv->page_side_combo, (GtkCellRenderer*) renderer, "text", 1);
+ _tmp88_ = g_settings_get_enum (self->priv->settings, "page-side");
+ simple_scan_set_page_side (self, (ScanType) _tmp88_);
+ _tmp89_ = (GtkCellRendererText*) gtk_cell_renderer_text_new ();
+ _g_object_unref0 (renderer);
+ renderer = g_object_ref_sink (_tmp89_);
+ gtk_cell_layout_pack_start ((GtkCellLayout*) self->priv->paper_size_combo, (GtkCellRenderer*) renderer, TRUE);
+ gtk_cell_layout_add_attribute ((GtkCellLayout*) self->priv->paper_size_combo, (GtkCellRenderer*) renderer, "text", 2);
+ _tmp90_ = g_settings_get_int (self->priv->settings, "paper-width");
+ paper_width = _tmp90_;
+ _tmp91_ = g_settings_get_int (self->priv->settings, "paper-height");
+ paper_height = _tmp91_;
+ simple_scan_set_paper_size (self, paper_width, paper_height);
+ _tmp92_ = g_settings_get_string (self->priv->settings, "selected-device");
+ device = _tmp92_;
+ if (device != NULL) {
+ GtkTreeIter _tmp93_ = {0};
+ gboolean _tmp94_;
+ _tmp94_ = simple_scan_find_scan_device (self, device, &_tmp93_);
+ iter = _tmp93_;
+ if (_tmp94_) {
+ gtk_combo_box_set_active_iter (self->priv->device_combo, &iter);
+ }
+ }
+ _tmp95_ = g_settings_get_string (self->priv->settings, "document-type");
+ document_type = _tmp95_;
+ if (document_type != NULL) {
+ simple_scan_set_document_hint (self, document_type);
+ }
+ _tmp96_ = book_view_new (self->priv->book);
+ _g_object_unref0 (self->priv->book_view);
+ self->priv->book_view = g_object_ref_sink (_tmp96_);
+ gtk_container_set_border_width ((GtkContainer*) self->priv->book_view, (guint) 18);
+ gtk_box_pack_end ((GtkBox*) self->priv->main_vbox, (GtkWidget*) self->priv->book_view, TRUE, TRUE, (guint) 0);
+ g_signal_connect (self->priv->book_view, "page-selected", (GCallback) _simple_scan_page_selected_cb_book_view_page_selected, self);
+ g_signal_connect (self->priv->book_view, "show-page", (GCallback) _simple_scan_show_page_cb_book_view_show_page, self);
+ g_signal_connect (self->priv->book_view, "show-menu", (GCallback) _simple_scan_show_page_menu_cb_book_view_show_menu, self);
+ gtk_widget_show ((GtkWidget*) self->priv->book_view);
+ _tmp97_ = g_settings_get_enum (self->priv->settings, "scan-direction");
+ self->priv->default_page_scan_direction = (ScanDirection) _tmp97_;
+ _tmp98_ = g_settings_get_int (self->priv->settings, "page-width");
+ self->priv->default_page_width = _tmp98_;
+ if (self->priv->default_page_width <= 0) {
+ self->priv->default_page_width = 595;
+ }
+ _tmp99_ = g_settings_get_int (self->priv->settings, "page-height");
+ self->priv->default_page_height = _tmp99_;
+ if (self->priv->default_page_height <= 0) {
+ self->priv->default_page_height = 842;
+ }
+ _tmp100_ = g_settings_get_int (self->priv->settings, "page-dpi");
+ self->priv->default_page_dpi = _tmp100_;
+ if (self->priv->default_page_dpi <= 0) {
+ self->priv->default_page_dpi = 72;
+ }
+ _tmp101_ = g_settings_get_int (self->priv->settings, "window-width");
+ self->priv->window_width = _tmp101_;
+ if (self->priv->window_width <= 0) {
+ self->priv->window_width = 600;
+ }
+ _tmp102_ = g_settings_get_int (self->priv->settings, "window-height");
+ self->priv->window_height = _tmp102_;
+ if (self->priv->window_height <= 0) {
+ self->priv->window_height = 400;
+ }
+ g_debug ("ui.vala:1407: Restoring window to %dx%d pixels", self->priv->window_width, self->priv->window_height);
+ gtk_window_set_default_size (self->priv->window, self->priv->window_width, self->priv->window_height);
+ _tmp103_ = g_settings_get_boolean (self->priv->settings, "window-is-maximized");
+ self->priv->window_is_maximized = _tmp103_;
+ if (self->priv->window_is_maximized) {
+ g_debug ("ui.vala:1412: Restoring window to maximized");
+ gtk_window_maximize (self->priv->window);
+ }
+ _tmp104_ = book_get_n_pages (self->priv->book);
+ if (_tmp104_ == ((guint) 0)) {
+ simple_scan_add_default_page (self);
+ }
+ book_set_needs_saving (self->priv->book, FALSE);
+ g_signal_connect (self->priv->book, "needs-saving-changed", (GCallback) _simple_scan_needs_saving_cb_book_needs_saving_changed, self);
+ _g_free0 (document_type);
+ _g_free0 (device);
+ _g_object_unref0 (renderer);
+ _g_object_unref0 (content_area);
+ _g_object_unref0 (hbox);
+ _g_free0 (filename);
+}
+
+
+static gpointer _book_ref0 (gpointer self) {
+ return self ? book_ref (self) : NULL;
+}
+
+
+Book* simple_scan_get_book (SimpleScan* self) {
+ Book* result = NULL;
+ Book* _tmp0_;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = _book_ref0 (self->priv->book);
+ result = _tmp0_;
+ return result;
+}
+
+
+void simple_scan_set_selected_page (SimpleScan* self, Page* page) {
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (page != NULL);
+ book_view_select_page (self->priv->book_view, page);
+}
+
+
+Page* simple_scan_get_selected_page (SimpleScan* self) {
+ Page* result = NULL;
+ Page* _tmp0_ = NULL;
+ g_return_val_if_fail (self != NULL, NULL);
+ _tmp0_ = book_view_get_selected (self->priv->book_view);
+ result = _tmp0_;
+ return result;
+}
+
+
+void simple_scan_set_scanning (SimpleScan* self, gboolean scanning) {
+ g_return_if_fail (self != NULL);
+ self->priv->scanning = scanning;
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->page_delete_menuitem, !scanning);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->stop_menuitem, scanning);
+ gtk_widget_set_sensitive ((GtkWidget*) self->priv->stop_toolbutton, scanning);
+}
+
+
+void simple_scan_show_error (SimpleScan* self, const gchar* error_title, const gchar* error_text, gboolean change_scanner_hint) {
+ gchar* _tmp0_;
+ gchar* _tmp1_;
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (error_title != NULL);
+ g_return_if_fail (error_text != NULL);
+ self->priv->have_error = TRUE;
+ _tmp0_ = g_strdup (error_title);
+ _g_free0 (self->priv->error_title);
+ self->priv->error_title = _tmp0_;
+ _tmp1_ = g_strdup (error_text);
+ _g_free0 (self->priv->error_text);
+ self->priv->error_text = _tmp1_;
+ self->priv->error_change_scanner_hint = change_scanner_hint;
+ simple_scan_update_info_bar (self);
+}
+
- update_page_menu (ui);
+void simple_scan_start (SimpleScan* self) {
+ g_return_if_fail (self != NULL);
+ gtk_widget_show ((GtkWidget*) self->priv->window);
}
-void page_move_right_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-page_move_right_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui)
-{
- Book *book = book_view_get_book (ui->priv->book_view);
- Page *page = book_view_get_selected (ui->priv->book_view);
- gint index;
-
- index = book_get_page_index (book, page);
- if (index < book_get_n_pages (book) - 1)
- book_move_page (book, page, book_get_page_index (book, page) + 1);
-
- update_page_menu (ui);
+static void g_cclosure_user_marshal_VOID__STRING_SCAN_OPTIONS (GClosure * closure, GValue * return_value, guint n_param_values, const GValue * param_values, gpointer invocation_hint, gpointer marshal_data) {
+ typedef void (*GMarshalFunc_VOID__STRING_SCAN_OPTIONS) (gpointer data1, const char* arg_1, gpointer arg_2, gpointer data2);
+ register GMarshalFunc_VOID__STRING_SCAN_OPTIONS callback;
+ register GCClosure * cc;
+ register gpointer data1;
+ register gpointer data2;
+ cc = (GCClosure *) closure;
+ g_return_if_fail (n_param_values == 3);
+ if (G_CCLOSURE_SWAP_DATA (closure)) {
+ data1 = closure->data;
+ data2 = param_values->data[0].v_pointer;
+ } else {
+ data1 = param_values->data[0].v_pointer;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__STRING_SCAN_OPTIONS) (marshal_data ? marshal_data : cc->callback);
+ callback (data1, g_value_get_string (param_values + 1), value_get_scan_options (param_values + 2), data2);
}
-void page_delete_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-page_delete_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui)
-{
- book_delete_page (book_view_get_book (ui->priv->book_view),
- book_view_get_selected (ui->priv->book_view));
+static void value_simple_scan_init (GValue* value) {
+ value->data[0].v_pointer = NULL;
}
-void save_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-save_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- save_document (ui, FALSE);
+static void value_simple_scan_free_value (GValue* value) {
+ if (value->data[0].v_pointer) {
+ simple_scan_unref (value->data[0].v_pointer);
+ }
}
-void save_as_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-save_as_file_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- save_document (ui, TRUE);
+static void value_simple_scan_copy_value (const GValue* src_value, GValue* dest_value) {
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = simple_scan_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
}
-static void
-draw_page (GtkPrintOperation *operation,
- GtkPrintContext *print_context,
- gint page_number,
- SimpleScan *ui)
-{
- cairo_t *context;
- Page *page;
- GdkPixbuf *image;
- gboolean is_landscape = FALSE;
-
- context = gtk_print_context_get_cairo_context (print_context);
-
- page = book_get_page (ui->priv->book, page_number);
-
- /* Rotate to same aspect */
- if (gtk_print_context_get_width (print_context) > gtk_print_context_get_height (print_context))
- is_landscape = TRUE;
- if (page_is_landscape (page) != is_landscape) {
- cairo_translate (context, gtk_print_context_get_width (print_context), 0);
- cairo_rotate (context, M_PI_2);
- }
-
- cairo_scale (context,
- gtk_print_context_get_dpi_x (print_context) / page_get_dpi (page),
- gtk_print_context_get_dpi_y (print_context) / page_get_dpi (page));
-
- image = page_get_image (page, TRUE);
- gdk_cairo_set_source_pixbuf (context, image, 0, 0);
- cairo_paint (context);
-
- g_object_unref (image);
-}
-
-
-void email_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-email_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- g_signal_emit (G_OBJECT (ui), signals[EMAIL], 0, ui->priv->document_hint);
-}
-
-
-void print_button_clicked_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-print_button_clicked_cb (GtkWidget *widget, SimpleScan *ui)
-{
- GtkPrintOperation *print;
- GtkPrintOperationResult result;
- GError *error = NULL;
-
- print = gtk_print_operation_new ();
- gtk_print_operation_set_n_pages (print, book_get_n_pages (ui->priv->book));
- g_signal_connect (print, "draw-page", G_CALLBACK (draw_page), ui);
-
- result = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
- GTK_WINDOW (ui->priv->window), &error);
-
- g_object_unref (print);
-}
-
-
-void help_contents_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-help_contents_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui)
-{
- GdkScreen *screen;
- GError *error = NULL;
-
- screen = gtk_widget_get_screen (GTK_WIDGET (ui->priv->window));
- gtk_show_uri (screen, "ghelp:simple-scan", gtk_get_current_event_time (), &error);
-
- if (error)
- {
- show_error_dialog (ui,
- /* Error message displayed when unable to launch help browser */
- _("Unable to open help file"),
- error->message);
- g_clear_error (&error);
- }
-}
-
-
-void about_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-about_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui)
-{
- const gchar *authors[] = { "Robert Ancell <robert.ancell@canonical.com>", NULL };
-
- /* The license this software is under (GPL3+) */
- const char *license = _("This program is free software: you can redistribute it and/or modify\n"
- "it under the terms of the GNU General Public License as published by\n"
- "the Free Software Foundation, either version 3 of the License, or\n"
- "(at your option) any later version.\n"
- "\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program. If not, see <http://www.gnu.org/licenses/>.");
-
- /* Title of about dialog */
- const char *title = _("About Simple Scan");
-
- /* Description of program */
- const char *description = _("Simple document scanning tool");
-
- gtk_show_about_dialog (GTK_WINDOW (ui->priv->window),
- "title", title,
- "program-name", "Simple Scan",
- "version", VERSION,
- "comments", description,
- "logo-icon-name", "scanner",
- "authors", authors,
- "translator-credits", _("translator-credits"),
- "website", "https://launchpad.net/simple-scan",
- "copyright", "Copyright © 2009 Canonical Ltd.",
- "license", license,
- "wrap-license", TRUE,
- NULL);
-}
-
-
-static gboolean
-quit (SimpleScan *ui)
-{
- char *device;
- gint paper_width = 0, paper_height = 0;
- gint i;
-
- if (!prompt_to_save (ui,
- /* Text in dialog warning when a document is about to be lost */
- _("Save document before quitting?"),
- /* Button in dialog to quit and discard unsaved document */
- _("Quit without Saving")))
- return FALSE;
-
- device = get_selected_device (ui);
- if (device) {
- gconf_client_set_string(ui->priv->client, GCONF_DIR "/selected_device", device, NULL);
- g_free (device);
- }
-
- gconf_client_set_string (ui->priv->client, GCONF_DIR "/document_type", ui->priv->document_hint, NULL);
- gconf_client_set_int (ui->priv->client, GCONF_DIR "/text_dpi", get_text_dpi (ui), NULL);
- gconf_client_set_int (ui->priv->client, GCONF_DIR "/photo_dpi", get_photo_dpi (ui), NULL);
- gconf_client_set_string (ui->priv->client, GCONF_DIR "/page_side", get_page_side (ui), NULL);
- get_paper_size (ui, &paper_width, &paper_height);
- gconf_client_set_int (ui->priv->client, GCONF_DIR "/paper_width", paper_width, NULL);
- gconf_client_set_int (ui->priv->client, GCONF_DIR "/paper_height", paper_height, NULL);
-
- gconf_client_set_int(ui->priv->client, GCONF_DIR "/window_width", ui->priv->window_width, NULL);
- gconf_client_set_int(ui->priv->client, GCONF_DIR "/window_height", ui->priv->window_height, NULL);
- gconf_client_set_bool(ui->priv->client, GCONF_DIR "/window_is_maximized", ui->priv->window_is_maximized, NULL);
-
- for (i = 0; scan_direction_keys[i].key != NULL && scan_direction_keys[i].scan_direction != ui->priv->default_page_scan_direction; i++);
- if (scan_direction_keys[i].key != NULL)
- gconf_client_set_string(ui->priv->client, GCONF_DIR "/scan_direction", scan_direction_keys[i].key, NULL);
- gconf_client_set_int (ui->priv->client, GCONF_DIR "/page_width", ui->priv->default_page_width, NULL);
- gconf_client_set_int (ui->priv->client, GCONF_DIR "/page_height", ui->priv->default_page_height, NULL);
- gconf_client_set_int (ui->priv->client, GCONF_DIR "/page_dpi", ui->priv->default_page_dpi, NULL);
-
- g_signal_emit (G_OBJECT (ui), signals[QUIT], 0);
-
- return TRUE;
-}
-
-
-void quit_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui);
-G_MODULE_EXPORT
-void
-quit_menuitem_activate_cb (GtkWidget *widget, SimpleScan *ui)
-{
- quit (ui);
-}
-
-
-gboolean simple_scan_window_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, SimpleScan *ui);
-G_MODULE_EXPORT
-gboolean
-simple_scan_window_configure_event_cb (GtkWidget *widget, GdkEventConfigure *event, SimpleScan *ui)
-{
- if (!ui->priv->window_is_maximized) {
- ui->priv->window_width = event->width;
- ui->priv->window_height = event->height;
- }
-
- return FALSE;
-}
-
-
-static void
-info_bar_response_cb (GtkWidget *widget, gint response_id, SimpleScan *ui)
-{
- if (response_id == 1) {
- gtk_widget_grab_focus (ui->priv->device_combo);
- gtk_window_present (GTK_WINDOW (ui->priv->preferences_dialog));
- }
- else {
- ui->priv->have_error = FALSE;
- g_free (ui->priv->error_title);
- ui->priv->error_title = NULL;
- g_free (ui->priv->error_text);
- ui->priv->error_text = NULL;
- update_info_bar (ui);
- }
-}
-
-
-gboolean simple_scan_window_window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event, SimpleScan *ui);
-G_MODULE_EXPORT
-gboolean
-simple_scan_window_window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event, SimpleScan *ui)
-{
- if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
- ui->priv->window_is_maximized = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
- return FALSE;
-}
-
-
-gboolean window_delete_event_cb (GtkWidget *widget, GdkEvent *event, SimpleScan *ui);
-G_MODULE_EXPORT
-gboolean
-window_delete_event_cb (GtkWidget *widget, GdkEvent *event, SimpleScan *ui)
-{
- return !quit (ui);
-}
-
-
-static void
-page_size_changed_cb (Page *page, SimpleScan *ui)
-{
- ui->priv->default_page_width = page_get_width (page);
- ui->priv->default_page_height = page_get_height (page);
- ui->priv->default_page_dpi = page_get_dpi (page);
+static gpointer value_simple_scan_peek_pointer (const GValue* value) {
+ return value->data[0].v_pointer;
}
-static void
-page_scan_direction_changed_cb (Page *page, SimpleScan *ui)
-{
- ui->priv->default_page_scan_direction = page_get_scan_direction (page);
+static gchar* value_simple_scan_collect_value (GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ if (collect_values[0].v_pointer) {
+ SimpleScan* 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 = simple_scan_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
}
-static void
-page_added_cb (Book *book, Page *page, SimpleScan *ui)
-{
- ui->priv->default_page_width = page_get_width (page);
- ui->priv->default_page_height = page_get_height (page);
- ui->priv->default_page_dpi = page_get_dpi (page);
- ui->priv->default_page_scan_direction = page_get_scan_direction (page);
- g_signal_connect (page, "size-changed", G_CALLBACK (page_size_changed_cb), ui);
- g_signal_connect (page, "scan-direction-changed", G_CALLBACK (page_scan_direction_changed_cb), ui);
-
- update_page_menu (ui);
+static gchar* value_simple_scan_lcopy_value (const GValue* value, guint n_collect_values, GTypeCValue* collect_values, guint collect_flags) {
+ SimpleScan** 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 = simple_scan_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+
+GParamSpec* param_spec_simple_scan (const gchar* name, const gchar* nick, const gchar* blurb, GType object_type, GParamFlags flags) {
+ ParamSpecSimpleScan* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_SIMPLE_SCAN), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+
+gpointer value_get_simple_scan (const GValue* value) {
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SIMPLE_SCAN), NULL);
+ return value->data[0].v_pointer;
+}
+
+
+void value_set_simple_scan (GValue* value, gpointer v_object) {
+ SimpleScan* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SIMPLE_SCAN));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SIMPLE_SCAN));
+ 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;
+ simple_scan_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ simple_scan_unref (old);
+ }
+}
+
+
+void value_take_simple_scan (GValue* value, gpointer v_object) {
+ SimpleScan* old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_SIMPLE_SCAN));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_SIMPLE_SCAN));
+ 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) {
+ simple_scan_unref (old);
+ }
+}
+
+
+static void simple_scan_class_init (SimpleScanClass * klass) {
+ simple_scan_parent_class = g_type_class_peek_parent (klass);
+ SIMPLE_SCAN_CLASS (klass)->finalize = simple_scan_finalize;
+ g_type_class_add_private (klass, sizeof (SimpleScanPrivate));
+ g_signal_new ("start_scan", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_user_marshal_VOID__STRING_SCAN_OPTIONS, G_TYPE_NONE, 2, G_TYPE_STRING, TYPE_SCAN_OPTIONS);
+ g_signal_new ("stop_scan", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+ g_signal_new ("email", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
+ g_signal_new ("quit", TYPE_SIMPLE_SCAN, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+
+static void simple_scan_instance_init (SimpleScan * self) {
+ gchar* _tmp0_;
+ const gchar* _tmp1_ = NULL;
+ gchar* _tmp2_;
+ self->priv = SIMPLE_SCAN_GET_PRIVATE (self);
+ self->priv->book_uri = NULL;
+ _tmp0_ = g_strdup ("photo");
+ self->priv->document_hint = _tmp0_;
+ _tmp1_ = _ ("Scanned Document.pdf");
+ _tmp2_ = g_strdup (_tmp1_);
+ self->priv->default_file_name = _tmp2_;
+ self->priv->scanning = FALSE;
+ self->ref_count = 1;
+}
+
+
+static void simple_scan_finalize (SimpleScan* obj) {
+ SimpleScan * self;
+ self = SIMPLE_SCAN (obj);
+ _g_object_unref0 (self->priv->settings);
+ _g_object_unref0 (self->priv->builder);
+ _g_object_unref0 (self->priv->window);
+ _g_object_unref0 (self->priv->main_vbox);
+ _g_object_unref0 (self->priv->info_bar);
+ _g_object_unref0 (self->priv->info_bar_image);
+ _g_object_unref0 (self->priv->info_bar_label);
+ _g_object_unref0 (self->priv->info_bar_close_button);
+ _g_object_unref0 (self->priv->info_bar_change_scanner_button);
+ _g_object_unref0 (self->priv->page_move_left_menuitem);
+ _g_object_unref0 (self->priv->page_move_right_menuitem);
+ _g_object_unref0 (self->priv->page_delete_menuitem);
+ _g_object_unref0 (self->priv->crop_rotate_menuitem);
+ _g_object_unref0 (self->priv->save_menuitem);
+ _g_object_unref0 (self->priv->save_as_menuitem);
+ _g_object_unref0 (self->priv->save_toolbutton);
+ _g_object_unref0 (self->priv->stop_menuitem);
+ _g_object_unref0 (self->priv->stop_toolbutton);
+ _g_object_unref0 (self->priv->text_toolbar_menuitem);
+ _g_object_unref0 (self->priv->text_menu_menuitem);
+ _g_object_unref0 (self->priv->photo_toolbar_menuitem);
+ _g_object_unref0 (self->priv->photo_menu_menuitem);
+ _g_object_unref0 (self->priv->authorize_dialog);
+ _g_object_unref0 (self->priv->authorize_label);
+ _g_object_unref0 (self->priv->username_entry);
+ _g_object_unref0 (self->priv->password_entry);
+ _g_object_unref0 (self->priv->preferences_dialog);
+ _g_object_unref0 (self->priv->device_combo);
+ _g_object_unref0 (self->priv->text_dpi_combo);
+ _g_object_unref0 (self->priv->photo_dpi_combo);
+ _g_object_unref0 (self->priv->page_side_combo);
+ _g_object_unref0 (self->priv->paper_size_combo);
+ _g_object_unref0 (self->priv->device_model);
+ _g_object_unref0 (self->priv->text_dpi_model);
+ _g_object_unref0 (self->priv->photo_dpi_model);
+ _g_object_unref0 (self->priv->page_side_model);
+ _g_object_unref0 (self->priv->paper_size_model);
+ _g_object_unref0 (self->priv->save_dialog);
+ _g_free0 (self->priv->error_title);
+ _g_free0 (self->priv->error_text);
+ _book_unref0 (self->priv->book);
+ _g_free0 (self->priv->book_uri);
+ _g_object_unref0 (self->priv->book_view);
+ _g_free0 (self->priv->document_hint);
+ _g_free0 (self->priv->default_file_name);
+}
+
+
+GType simple_scan_get_type (void) {
+ static volatile gsize simple_scan_type_id__volatile = 0;
+ if (g_once_init_enter (&simple_scan_type_id__volatile)) {
+ static const GTypeValueTable g_define_type_value_table = { value_simple_scan_init, value_simple_scan_free_value, value_simple_scan_copy_value, value_simple_scan_peek_pointer, "p", value_simple_scan_collect_value, "p", value_simple_scan_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (SimpleScanClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) simple_scan_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (SimpleScan), 0, (GInstanceInitFunc) simple_scan_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 simple_scan_type_id;
+ simple_scan_type_id = g_type_register_fundamental (g_type_fundamental_next (), "SimpleScan", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ g_once_init_leave (&simple_scan_type_id__volatile, simple_scan_type_id);
+ }
+ return simple_scan_type_id__volatile;
+}
+
+
+gpointer simple_scan_ref (gpointer instance) {
+ SimpleScan* self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+
+void simple_scan_unref (gpointer instance) {
+ SimpleScan* self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ SIMPLE_SCAN_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+
+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]);
+ }
+ }
+ }
+}
+
+
+static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {
+ _vala_array_destroy (array, array_length, destroy_func);
+ g_free (array);
}
-static void
-page_removed_cb (Book *book, Page *page, SimpleScan *ui)
-{
- /* If this is the last page add a new blank one */
- if (book_get_n_pages (ui->priv->book) == 1)
- add_default_page (ui);
- update_page_menu (ui);
-}
-
-
-static void
-set_dpi_combo (GtkWidget *combo, gint default_dpi, gint current_dpi)
-{
- struct
- {
- gint dpi;
- const gchar *label;
- } scan_resolutions[] =
- {
- /* Preferences dialog: Label for minimum resolution in resolution list */
- { 75, _("%d dpi (draft)") },
- /* Preferences dialog: Label for resolution value in resolution list (dpi = dots per inch) */
- { 150, _("%d dpi") },
- { 300, _("%d dpi") },
- { 600, _("%d dpi") },
- /* Preferences dialog: Label for maximum resolution in resolution list */
- { 1200, _("%d dpi (high resolution)") },
- { 2400, _("%d dpi") },
- { -1, NULL }
- };
- GtkCellRenderer *renderer;
- GtkTreeModel *model;
- gint i;
-
- renderer = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "text", 1);
-
- model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo));
- for (i = 0; scan_resolutions[i].dpi > 0; i++)
- {
- GtkTreeIter iter;
- gchar *label;
- gint dpi;
-
- dpi = scan_resolutions[i].dpi;
-
- if (dpi == default_dpi)
- label = g_strdup_printf (/* Preferences dialog: Label for default resolution in resolution list */
- _("%d dpi (default)"), dpi);
- else
- label = g_strdup_printf (scan_resolutions[i].label, dpi);
-
- gtk_list_store_append (GTK_LIST_STORE (model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, dpi, 1, label, -1);
-
- if (dpi == current_dpi)
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &iter);
-
- g_free (label);
- }
-}
-
-
-static void
-needs_saving_cb (Book *book, GParamSpec *param, SimpleScan *ui)
-{
- gtk_widget_set_sensitive (ui->priv->save_menuitem, book_get_needs_saving (book));
- gtk_widget_set_sensitive (ui->priv->save_toolbutton, book_get_needs_saving (book));
- if (book_get_needs_saving (book))
- gtk_widget_set_sensitive (ui->priv->save_as_menuitem, TRUE);
-}
-
-
-static void
-ui_load (SimpleScan *ui)
-{
- GtkBuilder *builder;
- GError *error = NULL;
- GtkWidget *hbox;
- GtkCellRenderer *renderer;
- gchar *device, *document_type, *scan_direction, *page_side;
- gint dpi, paper_width, paper_height;
-
- gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), ICON_DIR);
-
- gtk_window_set_default_icon_name ("scanner");
-
- builder = ui->priv->builder = gtk_builder_new ();
- gtk_builder_add_from_file (builder, UI_DIR "simple-scan.ui", &error);
- if (error) {
- g_critical ("Unable to load UI: %s\n", error->message);
- show_error_dialog (ui,
- /* Title of dialog when cannot load required files */
- _("Files missing"),
- /* Description in dialog when cannot load required files */
- _("Please check your installation"));
- exit (1);
- }
- gtk_builder_connect_signals (builder, ui);
-
- ui->priv->window = GTK_WIDGET (gtk_builder_get_object (builder, "simple_scan_window"));
- ui->priv->main_vbox = GTK_WIDGET (gtk_builder_get_object (builder, "main_vbox"));
- ui->priv->page_move_left_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "page_move_left_menuitem"));
- ui->priv->page_move_right_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "page_move_right_menuitem"));
- ui->priv->page_delete_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "page_delete_menuitem"));
- ui->priv->crop_rotate_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "crop_rotate_menuitem"));
- ui->priv->save_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "save_menuitem"));
- ui->priv->save_as_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "save_as_menuitem"));
- ui->priv->save_toolbutton = GTK_WIDGET (gtk_builder_get_object (builder, "save_toolbutton"));
- ui->priv->stop_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "stop_scan_menuitem"));
- ui->priv->stop_toolbutton = GTK_WIDGET (gtk_builder_get_object (builder, "stop_toolbutton"));
-
- ui->priv->text_toolbar_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "text_toolbutton_menuitem"));
- ui->priv->text_menu_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "text_menuitem"));
- ui->priv->photo_toolbar_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "photo_toolbutton_menuitem"));
- ui->priv->photo_menu_menuitem = GTK_WIDGET (gtk_builder_get_object (builder, "photo_menuitem"));
-
- ui->priv->authorize_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "authorize_dialog"));
- ui->priv->authorize_label = GTK_WIDGET (gtk_builder_get_object (builder, "authorize_label"));
- ui->priv->username_entry = GTK_WIDGET (gtk_builder_get_object (builder, "username_entry"));
- ui->priv->password_entry = GTK_WIDGET (gtk_builder_get_object (builder, "password_entry"));
-
- ui->priv->preferences_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "preferences_dialog"));
- ui->priv->device_combo = GTK_WIDGET (gtk_builder_get_object (builder, "device_combo"));
- ui->priv->device_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->device_combo));
- ui->priv->text_dpi_combo = GTK_WIDGET (gtk_builder_get_object (builder, "text_dpi_combo"));
- ui->priv->text_dpi_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->text_dpi_combo));
- ui->priv->photo_dpi_combo = GTK_WIDGET (gtk_builder_get_object (builder, "photo_dpi_combo"));
- ui->priv->photo_dpi_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->photo_dpi_combo));
- ui->priv->page_side_combo = GTK_WIDGET (gtk_builder_get_object (builder, "page_side_combo"));
- ui->priv->page_side_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->page_side_combo));
- ui->priv->paper_size_combo = GTK_WIDGET (gtk_builder_get_object (builder, "paper_size_combo"));
- ui->priv->paper_size_model = gtk_combo_box_get_model (GTK_COMBO_BOX (ui->priv->paper_size_combo));
-
- /* Add InfoBar (not supported in Glade) */
- ui->priv->info_bar = gtk_info_bar_new ();
- g_signal_connect (ui->priv->info_bar, "response", G_CALLBACK (info_bar_response_cb), ui);
- gtk_box_pack_start (GTK_BOX(ui->priv->main_vbox), ui->priv->info_bar, FALSE, TRUE, 0);
- hbox = gtk_hbox_new (FALSE, 12);
- gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (ui->priv->info_bar))), hbox);
- gtk_widget_show (hbox);
-
- ui->priv->info_bar_image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG);
- gtk_box_pack_start (GTK_BOX(hbox), ui->priv->info_bar_image, FALSE, TRUE, 0);
- gtk_widget_show (ui->priv->info_bar_image);
-
- ui->priv->info_bar_label = gtk_label_new (NULL);
- gtk_misc_set_alignment (GTK_MISC (ui->priv->info_bar_label), 0.0, 0.5);
- gtk_box_pack_start (GTK_BOX(hbox), ui->priv->info_bar_label, TRUE, TRUE, 0);
- gtk_widget_show (ui->priv->info_bar_label);
-
- ui->priv->info_bar_close_button = gtk_info_bar_add_button (GTK_INFO_BAR (ui->priv->info_bar), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
- ui->priv->info_bar_change_scanner_button = gtk_info_bar_add_button (GTK_INFO_BAR (ui->priv->info_bar),
- /* Button in error infobar to open preferences dialog and change scanner */
- _("Change _Scanner"), 1);
-
- GtkTreeIter iter;
- gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 0, 1, 0, 2,
- /* Combo box value for automatic paper size */
- _("Automatic"), -1);
- gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 1050, 1, 1480, 2, "A6", -1);
- gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 1480, 1, 2100, 2, "A5", -1);
- gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 2100, 1, 2970, 2, "A4", -1);
- gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 2159, 1, 2794, 2, "Letter", -1);
- gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 2159, 1, 3556, 2, "Legal", -1);
- gtk_list_store_append (GTK_LIST_STORE (ui->priv->paper_size_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (ui->priv->paper_size_model), &iter, 0, 1016, 1, 1524, 2, "4×6", -1);
-
- dpi = gconf_client_get_int (ui->priv->client, GCONF_DIR "/text_dpi", NULL);
- if (dpi <= 0)
- dpi = DEFAULT_TEXT_DPI;
- set_dpi_combo (ui->priv->text_dpi_combo, DEFAULT_TEXT_DPI, dpi);
- dpi = gconf_client_get_int (ui->priv->client, GCONF_DIR "/photo_dpi", NULL);
- if (dpi <= 0)
- dpi = DEFAULT_PHOTO_DPI;
- set_dpi_combo (ui->priv->photo_dpi_combo, DEFAULT_PHOTO_DPI, dpi);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->priv->device_combo), renderer, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (ui->priv->device_combo), renderer, "text", 1);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->priv->page_side_combo), renderer, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (ui->priv->page_side_combo), renderer, "text", 1);
- page_side = gconf_client_get_string (ui->priv->client, GCONF_DIR "/page_side", NULL);
- if (page_side) {
- set_page_side (ui, page_side);
- g_free (page_side);
- }
-
- renderer = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->priv->paper_size_combo), renderer, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (ui->priv->paper_size_combo), renderer, "text", 2);
- paper_width = gconf_client_get_int (ui->priv->client, GCONF_DIR "/paper_width", NULL);
- paper_height = gconf_client_get_int (ui->priv->client, GCONF_DIR "/paper_height", NULL);
- set_paper_size (ui, paper_width, paper_height);
-
- device = gconf_client_get_string (ui->priv->client, GCONF_DIR "/selected_device", NULL);
- if (device) {
- GtkTreeIter iter;
- if (find_scan_device (ui, device, &iter))
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (ui->priv->device_combo), &iter);
- g_free (device);
- }
-
- document_type = gconf_client_get_string (ui->priv->client, GCONF_DIR "/document_type", NULL);
- if (document_type) {
- set_document_hint (ui, document_type);
- g_free (document_type);
- }
-
- ui->priv->book_view = book_view_new (ui->priv->book);
- gtk_container_set_border_width (GTK_CONTAINER (ui->priv->book_view), 18);
- gtk_box_pack_end (GTK_BOX (ui->priv->main_vbox), GTK_WIDGET (ui->priv->book_view), TRUE, TRUE, 0);
- g_signal_connect (ui->priv->book_view, "page-selected", G_CALLBACK (page_selected_cb), ui);
- g_signal_connect (ui->priv->book_view, "show-page", G_CALLBACK (show_page_cb), ui);
- g_signal_connect (ui->priv->book_view, "show-menu", G_CALLBACK (show_page_menu_cb), ui);
- gtk_widget_show (GTK_WIDGET (ui->priv->book_view));
-
- /* Find default page details */
- scan_direction = gconf_client_get_string(ui->priv->client, GCONF_DIR "/scan_direction", NULL);
- ui->priv->default_page_scan_direction = TOP_TO_BOTTOM;
- if (scan_direction) {
- gint i;
- for (i = 0; scan_direction_keys[i].key != NULL && strcmp (scan_direction_keys[i].key, scan_direction) != 0; i++);
- if (scan_direction_keys[i].key != NULL)
- ui->priv->default_page_scan_direction = scan_direction_keys[i].scan_direction;
- g_free (scan_direction);
- }
- ui->priv->default_page_width = gconf_client_get_int (ui->priv->client, GCONF_DIR "/page_width", NULL);
- if (ui->priv->default_page_width <= 0)
- ui->priv->default_page_width = 595;
- ui->priv->default_page_height = gconf_client_get_int (ui->priv->client, GCONF_DIR "/page_height", NULL);
- if (ui->priv->default_page_height <= 0)
- ui->priv->default_page_height = 842;
- ui->priv->default_page_dpi = gconf_client_get_int (ui->priv->client, GCONF_DIR "/page_dpi", NULL);
- if (ui->priv->default_page_dpi <= 0)
- ui->priv->default_page_dpi = 72;
-
- /* Restore window size */
- ui->priv->window_width = gconf_client_get_int (ui->priv->client, GCONF_DIR "/window_width", NULL);
- if (ui->priv->window_width <= 0)
- ui->priv->window_width = 600;
- ui->priv->window_height = gconf_client_get_int (ui->priv->client, GCONF_DIR "/window_height", NULL);
- if (ui->priv->window_height <= 0)
- ui->priv->window_height = 400;
- g_debug ("Restoring window to %dx%d pixels", ui->priv->window_width, ui->priv->window_height);
- gtk_window_set_default_size (GTK_WINDOW (ui->priv->window), ui->priv->window_width, ui->priv->window_height);
- ui->priv->window_is_maximized = gconf_client_get_bool (ui->priv->client, GCONF_DIR "/window_is_maximized", NULL);
- if (ui->priv->window_is_maximized) {
- g_debug ("Restoring window to maximized");
- gtk_window_maximize (GTK_WINDOW (ui->priv->window));
- }
-
- if (book_get_n_pages (ui->priv->book) == 0)
- add_default_page (ui);
- book_set_needs_saving (ui->priv->book, FALSE);
- g_signal_connect (ui->priv->book, "notify::needs-saving", G_CALLBACK (needs_saving_cb), ui);
-}
-
-
-SimpleScan *
-ui_new ()
-{
- return g_object_new (SIMPLE_SCAN_TYPE, NULL);
-}
-
-
-Book *
-ui_get_book (SimpleScan *ui)
-{
- return g_object_ref (ui->priv->book);
-}
-
-
-void
-ui_set_selected_page (SimpleScan *ui, Page *page)
-{
- book_view_select_page (ui->priv->book_view, page);
-}
-
-
-Page *
-ui_get_selected_page (SimpleScan *ui)
-{
- return book_view_get_selected (ui->priv->book_view);
-}
-
-
-void
-ui_set_scanning (SimpleScan *ui, gboolean scanning)
-{
- ui->priv->scanning = scanning;
- gtk_widget_set_sensitive (ui->priv->page_delete_menuitem, !scanning);
- gtk_widget_set_sensitive (ui->priv->stop_menuitem, scanning);
- gtk_widget_set_sensitive (ui->priv->stop_toolbutton, scanning);
-}
-
-
-void
-ui_show_error (SimpleScan *ui, const gchar *error_title, const gchar *error_text, gboolean change_scanner_hint)
-{
- ui->priv->have_error = TRUE;
- g_free (ui->priv->error_title);
- ui->priv->error_title = g_strdup (error_title);
- g_free (ui->priv->error_text);
- ui->priv->error_text = g_strdup (error_text);
- ui->priv->error_change_scanner_hint = change_scanner_hint;
- update_info_bar (ui);
-}
-
-
-void
-ui_start (SimpleScan *ui)
-{
- gtk_widget_show (ui->priv->window);
-}
-
-
-/* Generated with glib-genmarshal */
-static void
-g_cclosure_user_marshal_VOID__STRING_POINTER (GClosure *closure,
- GValue *return_value G_GNUC_UNUSED,
- guint n_param_values,
- const GValue *param_values,
- gpointer invocation_hint G_GNUC_UNUSED,
- gpointer marshal_data)
-{
- typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1,
- gconstpointer arg_1,
- gconstpointer arg_2,
- gpointer data2);
- register GMarshalFunc_VOID__STRING_POINTER callback;
- register GCClosure *cc = (GCClosure*) closure;
- register gpointer data1, data2;
-
- g_return_if_fail (n_param_values == 3);
-
- if (G_CCLOSURE_SWAP_DATA (closure))
- {
- data1 = closure->data;
- data2 = g_value_peek_pointer (param_values + 0);
- }
- else
- {
- data1 = g_value_peek_pointer (param_values + 0);
- data2 = closure->data;
- }
- callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback);
-
- callback (data1,
- g_value_get_string (param_values + 1),
- g_value_get_pointer (param_values + 2),
- data2);
-}
-
-
-static void
-ui_finalize (GObject *object)
-{
- SimpleScan *ui = SIMPLE_SCAN (object);
-
- g_object_unref (ui->priv->client);
- ui->priv->client = NULL;
- g_object_unref (ui->priv->builder);
- ui->priv->builder = NULL;
- g_object_unref (ui->priv->book);
- ui->priv->book = NULL;
- gtk_widget_destroy (GTK_WIDGET (ui->priv->book_view));
- ui->priv->book_view = NULL;
-
- G_OBJECT_CLASS (ui_parent_class)->finalize (object);
-}
-
-
-static void
-ui_class_init (SimpleScanClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->finalize = ui_finalize;
-
- signals[START_SCAN] =
- g_signal_new ("start-scan",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (SimpleScanClass, start_scan),
- NULL, NULL,
- g_cclosure_user_marshal_VOID__STRING_POINTER,
- G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER);
- signals[STOP_SCAN] =
- g_signal_new ("stop-scan",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (SimpleScanClass, stop_scan),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- signals[EMAIL] =
- g_signal_new ("email",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (SimpleScanClass, email),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
- signals[QUIT] =
- g_signal_new ("quit",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (SimpleScanClass, quit),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (klass, sizeof (SimpleScanPrivate));
-}
-
-
-static void
-ui_init (SimpleScan *ui)
-{
- ui->priv = G_TYPE_INSTANCE_GET_PRIVATE (ui, SIMPLE_SCAN_TYPE, SimpleScanPrivate);
-
- ui->priv->book = book_new ();
- g_signal_connect (ui->priv->book, "page-removed", G_CALLBACK (page_removed_cb), ui);
- g_signal_connect (ui->priv->book, "page-added", G_CALLBACK (page_added_cb), ui);
-
- ui->priv->client = gconf_client_get_default();
- gconf_client_add_dir(ui->priv->client, GCONF_DIR, GCONF_CLIENT_PRELOAD_NONE, NULL);
-
- ui->priv->document_hint = g_strdup ("photo");
- ui->priv->default_file_name = g_strdup (_("Scanned Document.pdf"));
- ui->priv->scanning = FALSE;
- ui_load (ui);
-}
diff --git a/src/ui.h b/src/ui.h
deleted file mode 100644
index d43c187..0000000
--- a/src/ui.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2009 Canonical Ltd.
- * Author: Robert Ancell <robert.ancell@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later
- * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
- * license.
- */
-
-#ifndef _UI_H_
-#define _UI_H_
-
-#include <glib-object.h>
-#include "book.h"
-#include "scanner.h"
-
-G_BEGIN_DECLS
-
-#define SIMPLE_SCAN_TYPE (ui_get_type ())
-#define SIMPLE_SCAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SIMPLE_SCAN_TYPE, SimpleScan))
-
-
-typedef struct SimpleScanPrivate SimpleScanPrivate;
-
-typedef struct
-{
- GObject parent_instance;
- SimpleScanPrivate *priv;
-} SimpleScan;
-
-typedef struct
-{
- GObjectClass parent_class;
-
- void (*start_scan) (SimpleScan *ui, ScanOptions *options);
- void (*stop_scan) (SimpleScan *ui);
- void (*email) (SimpleScan *ui, const gchar *profile);
- void (*quit) (SimpleScan *ui);
-} SimpleScanClass;
-
-
-GType ui_get_type (void);
-
-SimpleScan *ui_new (void);
-
-Book *ui_get_book (SimpleScan *ui);
-
-void ui_set_selected_page (SimpleScan *ui, Page *page);
-
-Page *ui_get_selected_page (SimpleScan *ui);
-
-void ui_set_default_file_name (SimpleScan *ui, const gchar *default_file_name);
-
-void ui_authorize (SimpleScan *ui, const gchar *resource, gchar **username, gchar **password);
-
-void ui_set_scan_devices (SimpleScan *ui, GList *devices);
-
-gchar *ui_get_selected_device (SimpleScan *ui);
-
-void ui_set_selected_device (SimpleScan *ui, const gchar *device);
-
-void ui_set_scanning (SimpleScan *ui, gboolean scanning);
-
-void ui_show_error (SimpleScan *ui, const gchar *error_title, const gchar *error_text, gboolean change_scanner_hint);
-
-void ui_start (SimpleScan *ui);
-
-#endif /* _UI_H_ */
diff --git a/src/ui.vala b/src/ui.vala
new file mode 100644
index 0000000..4287d13
--- /dev/null
+++ b/src/ui.vala
@@ -0,0 +1,1458 @@
+/*
+ * Copyright (C) 2009-2011 Canonical Ltd.
+ * Author: Robert Ancell <robert.ancell@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+public class SimpleScan
+{
+ private const int DEFAULT_TEXT_DPI = 150;
+ private const int DEFAULT_PHOTO_DPI = 300;
+
+ private Settings settings;
+
+ private Gtk.Builder builder;
+
+ private Gtk.Window window;
+ private Gtk.VBox main_vbox;
+ private Gtk.InfoBar info_bar;
+ private Gtk.Image info_bar_image;
+ private Gtk.Label info_bar_label;
+ private Gtk.Button info_bar_close_button;
+ private Gtk.Button info_bar_change_scanner_button;
+ private Gtk.MenuItem page_move_left_menuitem;
+ private Gtk.MenuItem page_move_right_menuitem;
+ private Gtk.MenuItem page_delete_menuitem;
+ private Gtk.MenuItem crop_rotate_menuitem;
+ private Gtk.MenuItem save_menuitem;
+ private Gtk.MenuItem save_as_menuitem;
+ private Gtk.ToolButton save_toolbutton;
+ private Gtk.MenuItem stop_menuitem;
+ private Gtk.ToolButton stop_toolbutton;
+
+ private Gtk.RadioMenuItem text_toolbar_menuitem;
+ private Gtk.RadioMenuItem text_menu_menuitem;
+ private Gtk.RadioMenuItem photo_toolbar_menuitem;
+ private Gtk.RadioMenuItem photo_menu_menuitem;
+
+ private Gtk.Dialog authorize_dialog;
+ private Gtk.Label authorize_label;
+ private Gtk.Entry username_entry;
+ private Gtk.Entry password_entry;
+
+ private Gtk.Dialog preferences_dialog;
+ private Gtk.ComboBox device_combo;
+ private Gtk.ComboBox text_dpi_combo;
+ private Gtk.ComboBox photo_dpi_combo;
+ private Gtk.ComboBox page_side_combo;
+ private Gtk.ComboBox paper_size_combo;
+ private Gtk.ListStore device_model;
+ private Gtk.ListStore text_dpi_model;
+ private Gtk.ListStore photo_dpi_model;
+ private Gtk.ListStore page_side_model;
+ private Gtk.ListStore paper_size_model;
+ private bool setting_devices;
+ private bool user_selected_device;
+
+ private Gtk.FileChooserDialog? save_dialog;
+
+ private bool have_error;
+ private string error_title;
+ private string error_text;
+ private bool error_change_scanner_hint;
+
+ private Book book;
+ private string? book_uri = null;
+
+ private BookView book_view;
+ private bool updating_page_menu;
+ private int default_page_width;
+ private int default_page_height;
+ private int default_page_dpi;
+ private ScanDirection default_page_scan_direction;
+
+ private string document_hint = "photo";
+
+ private string default_file_name = _("Scanned Document.pdf");
+ private bool scanning = false;
+
+ private int window_width;
+ private int window_height;
+ private bool window_is_maximized;
+
+ public signal void start_scan (string? device, ScanOptions options);
+ public signal void stop_scan ();
+ public signal void email (string profile);
+ public signal void quit ();
+
+ public SimpleScan ()
+ {
+ book = new Book ();
+ book.page_removed.connect (page_removed_cb);
+ book.page_added.connect (page_added_cb);
+
+ settings = new Settings ("org.gnome.SimpleScan");
+
+ load ();
+ }
+
+ private bool find_scan_device (string device, out Gtk.TreeIter iter)
+ {
+ bool have_iter = false;
+
+ if (device_model.get_iter_first (out iter))
+ {
+ do
+ {
+ string d;
+ device_model.get (iter, 0, out d, -1);
+ if (d == device)
+ have_iter = true;
+ } while (!have_iter && device_model.iter_next (ref iter));
+ }
+
+ return have_iter;
+ }
+
+ private void show_error_dialog (string error_title, string error_text)
+ {
+ var dialog = new Gtk.MessageDialog (window,
+ Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.WARNING,
+ Gtk.ButtonsType.NONE,
+ "%s", error_title);
+ dialog.add_button (Gtk.Stock.CLOSE, 0);
+ dialog.format_secondary_text ("%s", error_text);
+ dialog.destroy ();
+ }
+
+ public void set_default_file_name (string default_file_name)
+ {
+ this.default_file_name = default_file_name;
+ }
+
+ public void authorize (string resource, out string username, out string password)
+ {
+ /* Label in authorization dialog. '%s' is replaced with the name of the resource requesting authorization */
+ var description = _("Username and password required to access '%s'").printf (resource);
+
+ username_entry.set_text ("");
+ password_entry.set_text ("");
+ authorize_label.set_text (description);
+
+ authorize_dialog.show ();
+ authorize_dialog.run ();
+ authorize_dialog.hide ();
+
+ username = username_entry.get_text ();
+ password = password_entry.get_text ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT device_combo_changed_cb", instance_pos = -1)]
+ public void device_combo_changed_cb (Gtk.Widget widget)
+ {
+ if (setting_devices)
+ return;
+ user_selected_device = true;
+ }
+
+ private void update_info_bar ()
+ {
+ Gtk.MessageType type;
+ string title, text, image_id;
+ bool show_close_button = false;
+ bool show_change_scanner_button = false;
+
+ if (have_error)
+ {
+ type = Gtk.MessageType.ERROR;
+ image_id = Gtk.Stock.DIALOG_ERROR;
+ title = error_title;
+ text = error_text;
+ show_close_button = true;
+ show_change_scanner_button = error_change_scanner_hint;
+ }
+ else if (device_model.iter_n_children (null) == 0)
+ {
+ type = Gtk.MessageType.WARNING;
+ image_id = Gtk.Stock.DIALOG_WARNING;
+ /* Warning displayed when no scanners are detected */
+ title = _("No scanners detected");
+ /* Hint to user on why there are no scanners detected */
+ text = _("Please check your scanner is connected and powered on");
+ }
+ else
+ {
+ info_bar.hide ();
+ return;
+ }
+
+ info_bar.set_message_type (type);
+ info_bar_image.set_from_stock (image_id, Gtk.IconSize.DIALOG);
+ var message = "<big><b>%s</b></big>\n\n%s".printf (title, text);
+ info_bar_label.set_markup (message);
+ info_bar_close_button.set_visible (show_close_button);
+ info_bar_change_scanner_button.set_visible (show_change_scanner_button);
+ info_bar.show ();
+ }
+
+ public void set_scan_devices (List<ScanDevice> devices)
+ {
+ bool have_selection = false;
+ int index;
+ Gtk.TreeIter iter;
+
+ setting_devices = true;
+
+ /* If the user hasn't chosen a scanner choose the best available one */
+ if (user_selected_device)
+ have_selection = device_combo.get_active () >= 0;
+
+ /* Add new devices */
+ index = 0;
+ foreach (var device in devices)
+ {
+ int n_delete = -1;
+
+ /* Find if already exists */
+ if (device_model.iter_nth_child (out iter, null, index))
+ {
+ int i = 0;
+ do
+ {
+ string name;
+ bool matched;
+
+ device_model.get (iter, 0, out name, -1);
+ matched = name == device.name;
+
+ if (matched)
+ {
+ n_delete = i;
+ break;
+ }
+ i++;
+ } while (device_model.iter_next (ref iter));
+ }
+
+ /* If exists, remove elements up to this one */
+ if (n_delete >= 0)
+ {
+ int i;
+
+ /* Update label */
+ device_model.set (iter, 1, device.label, -1);
+
+ for (i = 0; i < n_delete; i++)
+ {
+ device_model.iter_nth_child (out iter, null, index);
+ device_model.remove (iter);
+ }
+ }
+ else
+ {
+ device_model.insert (out iter, index);
+ device_model.set (iter, 0, device.name, 1, device.label, -1);
+ }
+ index++;
+ }
+
+ /* Remove any remaining devices */
+ while (device_model.iter_nth_child (out iter, null, index))
+ device_model.remove (iter);
+
+ /* Select the first available device */
+ if (!have_selection && devices != null)
+ device_combo.set_active (0);
+
+ setting_devices = false;
+
+ update_info_bar ();
+ }
+
+ private string? get_selected_device ()
+ {
+ Gtk.TreeIter iter;
+
+ if (device_combo.get_active_iter (out iter))
+ {
+ string device;
+ device_model.get (iter, 0, out device, -1);
+ return device;
+ }
+
+ return null;
+ }
+
+ public void set_selected_device (string device)
+ {
+ Gtk.TreeIter iter;
+ if (!find_scan_device (device, out iter))
+ return;
+
+ device_combo.set_active_iter (iter);
+ user_selected_device = true;
+ }
+
+ private void add_default_page ()
+ {
+ var page = book.append_page (default_page_width,
+ default_page_height,
+ default_page_dpi,
+ default_page_scan_direction);
+ book_view.select_page (page);
+ }
+
+ private void on_file_type_changed (Gtk.TreeSelection selection)
+ {
+ Gtk.TreeModel model;
+ Gtk.TreeIter iter;
+ if (!selection.get_selected (out model, out iter))
+ return;
+
+ string extension;
+ model.get (iter, 1, out extension, -1);
+ var path = save_dialog.get_filename ();
+ var filename = Path.get_basename (path);
+
+ /* Replace extension */
+ var extension_index = filename.last_index_of_char ('.');
+ if (extension_index >= 0)
+ filename = filename.slice (0, extension_index);
+ filename = filename + extension;
+ save_dialog.set_current_name (filename);
+ }
+
+ private string choose_file_location ()
+ {
+ /* Get directory to save to */
+ string? directory = null;
+ directory = settings.get_string ("save-directory");
+
+ if (directory == null || directory == "")
+ directory = Environment.get_user_special_dir (UserDirectory.DOCUMENTS);
+
+ save_dialog = new Gtk.FileChooserDialog (/* Save dialog: Dialog title */
+ _("Save As..."),
+ window,
+ Gtk.FileChooserAction.SAVE,
+ Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT,
+ null);
+ save_dialog.set_do_overwrite_confirmation (true);
+ save_dialog.set_local_only (false);
+ save_dialog.set_current_folder (directory);
+ save_dialog.set_current_name (default_file_name);
+
+ /* Filter to only show images by default */
+ var filter = new Gtk.FileFilter ();
+ filter.set_name (/* Save dialog: Filter name to show only image files */
+ _("Image Files"));
+ filter.add_pixbuf_formats ();
+ filter.add_mime_type ("application/pdf");
+ save_dialog.add_filter (filter);
+ filter = new Gtk.FileFilter ();
+ filter.set_name (/* Save dialog: Filter name to show all files */
+ _("All Files"));
+ filter.add_pattern ("*");
+ save_dialog.add_filter (filter);
+
+ var expander = new Gtk.Expander.with_mnemonic (/* */
+ _("Select File _Type"));
+ expander.set_spacing (5);
+ save_dialog.set_extra_widget (expander);
+
+ string extension = "";
+ var index = default_file_name.last_index_of_char ('.');
+ if (index >= 0)
+ extension = default_file_name.slice (0, index);
+
+ var file_type_store = new Gtk.ListStore (2, typeof (string), typeof (string));
+ Gtk.TreeIter iter;
+ file_type_store.append (out iter);
+ file_type_store.set (iter,
+ /* Save dialog: Label for saving in PDF format */
+ 0, _("PDF (multi-page document)"),
+ 1, ".pdf",
+ -1);
+ file_type_store.append (out iter);
+ file_type_store.set (iter,
+ /* Save dialog: Label for saving in JPEG format */
+ 0, _("JPEG (compressed)"),
+ 1, ".jpg",
+ -1);
+ file_type_store.append (out iter);
+ file_type_store.set (iter,
+ /* Save dialog: Label for saving in PNG format */
+ 0, _("PNG (lossless)"),
+ 1, ".png",
+ -1);
+
+ var file_type_view = new Gtk.TreeView.with_model (file_type_store);
+ file_type_view.set_headers_visible (false);
+ file_type_view.set_rules_hint (true);
+ var column = new Gtk.TreeViewColumn.with_attributes ("",
+ new Gtk.CellRendererText (),
+ "text", 0, null);
+ file_type_view.append_column (column);
+ expander.add (file_type_view);
+
+ if (file_type_store.get_iter_first (out iter))
+ {
+ do
+ {
+ string e;
+ file_type_store.get (iter, 1, out e, -1);
+ if (extension == e)
+ file_type_view.get_selection ().select_iter (iter);
+ } while (file_type_store.iter_next (ref iter));
+ }
+ file_type_view.get_selection ().changed.connect (on_file_type_changed);
+
+ expander.show_all ();
+
+ var response = save_dialog.run ();
+
+ string? uri = null;
+ if (response == Gtk.ResponseType.ACCEPT)
+ uri = save_dialog.get_uri ();
+
+ settings.set_string ("save-directory", save_dialog.get_current_folder ());
+
+ save_dialog.destroy ();
+ save_dialog = null;
+
+ return uri;
+ }
+
+ private bool save_document (bool force_choose_location)
+ {
+ string? uri;
+ if (book_uri != null && !force_choose_location)
+ uri = book_uri;
+ else
+ uri = choose_file_location ();
+ if (uri == null)
+ return false;
+
+ var file = File.new_for_uri (uri);
+
+ debug ("Saving to '%s'", uri);
+
+ var uri_lower = uri.down ();
+ string format = "jpeg";
+ if (uri_lower.has_suffix (".pdf"))
+ format = "pdf";
+ else if (uri_lower.has_suffix (".ps"))
+ format = "ps";
+ else if (uri_lower.has_suffix (".png"))
+ format = "png";
+ else if (uri_lower.has_suffix (".tif") || uri_lower.has_suffix (".tiff"))
+ format = "tiff";
+
+ try
+ {
+ book.save (format, file);
+ }
+ catch (Error e)
+ {
+ warning ("Error saving file: %s", e.message);
+ show_error (/* Title of error dialog when save failed */
+ _("Failed to save file"),
+ e.message,
+ false);
+ return false;
+ }
+
+ book_uri = uri;
+ book.set_needs_saving (false);
+ return true;
+ }
+
+ private bool prompt_to_save (string title, string discard_label)
+ {
+ if (!book.get_needs_saving ())
+ return true;
+
+ var dialog = new Gtk.MessageDialog (window,
+ Gtk.DialogFlags.MODAL,
+ Gtk.MessageType.WARNING,
+ Gtk.ButtonsType.NONE,
+ "%s", title);
+ dialog.format_secondary_text ("%s",
+ /* Text in dialog warning when a document is about to be lost*/
+ _("If you don't save, changes will be permanently lost."));
+ dialog.add_button (discard_label, Gtk.ResponseType.NO);
+ dialog.add_button (Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL);
+ dialog.add_button (Gtk.Stock.SAVE, Gtk.ResponseType.YES);
+
+ var response = dialog.run ();
+ dialog.destroy ();
+
+ switch (response)
+ {
+ case Gtk.ResponseType.YES:
+ if (save_document (false))
+ return true;
+ else
+ return false;
+ case Gtk.ResponseType.CANCEL:
+ return false;
+ case Gtk.ResponseType.NO:
+ default:
+ return true;
+ }
+ }
+
+ private void clear_document ()
+ {
+ book.clear ();
+ add_default_page ();
+ book_uri = null;
+ book.set_needs_saving (false);
+ save_as_menuitem.set_sensitive (false);
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT new_button_clicked_cb", instance_pos = -1)]
+ public void new_button_clicked_cb (Gtk.Widget widget)
+ {
+ if (!prompt_to_save (/* Text in dialog warning when a document is about to be lost */
+ _("Save current document?"),
+ /* Button in dialog to create new document and discard unsaved document */
+ _("Discard Changes")))
+ return;
+
+ clear_document ();
+ }
+
+ private void set_document_hint (string document_hint)
+ {
+ this.document_hint = document_hint;
+
+ if (document_hint == "text")
+ {
+ text_toolbar_menuitem.set_active (true);
+ text_menu_menuitem.set_active (true);
+ }
+ else if (document_hint == "photo")
+ {
+ photo_toolbar_menuitem.set_active (true);
+ photo_menu_menuitem.set_active (true);
+ }
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT text_menuitem_toggled_cb", instance_pos = -1)]
+ public void text_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_document_hint ("text");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT photo_menuitem_toggled_cb", instance_pos = -1)]
+ public void photo_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_document_hint ("photo");
+ }
+
+ private void set_page_side (ScanType page_side)
+ {
+ Gtk.TreeIter iter;
+
+ if (page_side_model.get_iter_first (out iter))
+ {
+ do
+ {
+ int s;
+ page_side_model.get (iter, 0, out s, -1);
+ if (s == page_side)
+ {
+ page_side_combo.set_active_iter (iter);
+ return;
+ }
+ } while (page_side_model.iter_next (ref iter));
+ }
+ }
+
+ private void set_paper_size (int width, int height)
+ {
+ Gtk.TreeIter iter;
+ bool have_iter;
+
+ for (have_iter = paper_size_model.get_iter_first (out iter);
+ have_iter;
+ have_iter = paper_size_model.iter_next (ref iter))
+ {
+ int w, h;
+ paper_size_model.get (iter, 0, out w, 1, out h, -1);
+ if (w == width && h == height)
+ break;
+ }
+
+ if (!have_iter)
+ have_iter = paper_size_model.get_iter_first (out iter);
+ if (have_iter)
+ paper_size_combo.set_active_iter (iter);
+ }
+
+ private int get_text_dpi ()
+ {
+ Gtk.TreeIter iter;
+ int dpi = DEFAULT_TEXT_DPI;
+
+ if (text_dpi_combo.get_active_iter (out iter))
+ text_dpi_model.get (iter, 0, out dpi, -1);
+
+ return dpi;
+ }
+
+ private int get_photo_dpi ()
+ {
+ Gtk.TreeIter iter;
+ int dpi = DEFAULT_PHOTO_DPI;
+
+ if (photo_dpi_combo.get_active_iter (out iter))
+ photo_dpi_model.get (iter, 0, out dpi, -1);
+
+ return dpi;
+ }
+
+ private ScanType get_page_side ()
+ {
+ Gtk.TreeIter iter;
+ int page_side = ScanType.ADF_BOTH;
+
+ if (page_side_combo.get_active_iter (out iter))
+ page_side_model.get (iter, 0, out page_side, -1);
+
+ return (ScanType) page_side;
+ }
+
+ private bool get_paper_size (out int width, out int height)
+ {
+ Gtk.TreeIter iter;
+
+ if (paper_size_combo.get_active_iter (out iter))
+ {
+ paper_size_model.get (iter, 0, ref width, 1, ref height, -1);
+ return true;
+ }
+
+ return false;
+ }
+
+ private ScanOptions get_scan_options ()
+ {
+ var options = new ScanOptions ();
+ if (document_hint == "text")
+ {
+ options.scan_mode = ScanMode.GRAY;
+ options.dpi = get_text_dpi ();
+ options.depth = 2;
+ }
+ else
+ {
+ options.scan_mode = ScanMode.COLOR;
+ options.dpi = get_photo_dpi ();
+ options.depth = 8;
+ }
+ get_paper_size (out options.paper_width, out options.paper_height);
+
+ return options;
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT scan_button_clicked_cb", instance_pos = -1)]
+ public void scan_button_clicked_cb (Gtk.Widget widget)
+ {
+ var options = get_scan_options ();
+ options.type = ScanType.SINGLE;
+ start_scan (get_selected_device (), options);
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT stop_scan_button_clicked_cb", instance_pos = -1)]
+ public void stop_scan_button_clicked_cb (Gtk.Widget widget)
+ {
+ stop_scan ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT continuous_scan_button_clicked_cb", instance_pos = -1)]
+ public void continuous_scan_button_clicked_cb (Gtk.Widget widget)
+ {
+ if (scanning)
+ stop_scan ();
+ else
+ {
+ var options = get_scan_options ();
+ options.type = get_page_side ();
+ start_scan (get_selected_device (), options);
+ }
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT preferences_button_clicked_cb", instance_pos = -1)]
+ public void preferences_button_clicked_cb (Gtk.Widget widget)
+ {
+ preferences_dialog.present ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT preferences_dialog_delete_event_cb", instance_pos = -1)]
+ public bool preferences_dialog_delete_event_cb (Gtk.Widget widget)
+ {
+ return true;
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT preferences_dialog_response_cb", instance_pos = -1)]
+ public void preferences_dialog_response_cb (Gtk.Widget widget, int response_id)
+ {
+ preferences_dialog.hide ();
+ }
+
+ private void update_page_menu ()
+ {
+ var page = book_view.get_selected ();
+ if (page == null)
+ {
+ page_move_left_menuitem.set_sensitive (false);
+ page_move_right_menuitem.set_sensitive (false);
+ }
+ else
+ {
+ var index = book.get_page_index (page);
+ page_move_left_menuitem.set_sensitive (index > 0);
+ page_move_right_menuitem.set_sensitive (index < book.get_n_pages () - 1);
+ }
+ }
+
+ private void page_selected_cb (BookView view, Page? page)
+ {
+ if (page == null)
+ return;
+
+ updating_page_menu = true;
+
+ update_page_menu ();
+
+ string? name = null;
+ if (page.has_crop ())
+ {
+ // FIXME: Make more generic, move into page-size.c and reuse
+ var crop_name = page.get_named_crop ();
+ if (crop_name != null)
+ {
+ if (crop_name == "A4")
+ name = "a4_menuitem";
+ else if (crop_name == "A5")
+ name = "a5_menuitem";
+ else if (crop_name == "A6")
+ name = "a6_menuitem";
+ else if (crop_name == "letter")
+ name = "letter_menuitem";
+ else if (crop_name == "legal")
+ name = "legal_menuitem";
+ else if (crop_name == "4x6")
+ name = "4x6_menuitem";
+ }
+ else
+ name = "custom_crop_menuitem";
+ }
+ else
+ name = "no_crop_menuitem";
+
+ var menuitem = (Gtk.RadioMenuItem) builder.get_object (name);
+ menuitem.set_active (true);
+ var toolbutton = (Gtk.ToggleToolButton) builder.get_object ("crop_toolbutton");
+ toolbutton.set_active (page.has_crop ());
+
+ updating_page_menu = false;
+ }
+
+ // FIXME: Duplicated from simple-scan.vala
+ private string? get_temporary_filename (string prefix, string extension)
+ {
+ /* NOTE: I'm not sure if this is a 100% safe strategy to use g_file_open_tmp(), close and
+ * use the filename but it appears to work in practise */
+
+ var filename = "%sXXXXXX.%s".printf (prefix, extension);
+ string path;
+ try
+ {
+ var fd = FileUtils.open_tmp (filename, out path);
+ Posix.close (fd);
+ }
+ catch (Error e)
+ {
+ warning ("Error saving email attachment: %s", e.message);
+ return null;
+ }
+
+ return path;
+ }
+
+ private void show_page_cb (BookView view, Page page)
+ {
+ var path = get_temporary_filename ("scanned-page", "tiff");
+ if (path == null)
+ return;
+ var file = File.new_for_path (path);
+
+ try
+ {
+ page.save ("tiff", file);
+ }
+ catch (Error e)
+ {
+ show_error_dialog (/* Error message display when unable to save image for preview */
+ _("Unable to save image for preview"),
+ e.message);
+ return;
+ }
+
+ try
+ {
+ Gtk.show_uri (window.get_screen (), file.get_uri (), Gtk.get_current_event_time ());
+ }
+ catch (Error e)
+ {
+ show_error_dialog (/* Error message display when unable to preview image */
+ _("Unable to open image preview application"),
+ e.message);
+ }
+ }
+
+ private void show_page_menu_cb (BookView view)
+ {
+ var menu = (Gtk.Menu) builder.get_object ("page_menu");
+ menu.popup (null, null, null, 3, Gtk.get_current_event_time());
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT rotate_left_button_clicked_cb", instance_pos = -1)]
+ public void rotate_left_button_clicked_cb (Gtk.Widget widget)
+ {
+ if (updating_page_menu)
+ return;
+ var page = book_view.get_selected ();
+ if (page != null)
+ page.rotate_left ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT rotate_right_button_clicked_cb", instance_pos = -1)]
+ public void rotate_right_button_clicked_cb (Gtk.Widget widget)
+ {
+ if (updating_page_menu)
+ return;
+ var page = book_view.get_selected ();
+ if (page != null)
+ page.rotate_right ();
+ }
+
+ private void set_crop (string? crop_name)
+ {
+ crop_rotate_menuitem.set_sensitive (crop_name != null);
+
+ if (updating_page_menu)
+ return;
+
+ var page = book_view.get_selected ();
+ if (page == null)
+ return;
+
+ if (crop_name == null)
+ {
+ page.set_no_crop ();
+ return;
+ }
+ else if (crop_name == "custom")
+ {
+ var width = page.get_width ();
+ var height = page.get_height ();
+ var crop_width = (int) (width * 0.8 + 0.5);
+ var crop_height = (int) (height * 0.8 + 0.5);
+ page.set_custom_crop (crop_width, crop_height);
+ page.move_crop ((width - crop_width) / 2, (height - crop_height) / 2);
+ }
+ else
+ page.set_named_crop (crop_name);
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT no_crop_menuitem_toggled_cb", instance_pos = -1)]
+ public void no_crop_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop (null);
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT custom_crop_menuitem_toggled_cb", instance_pos = -1)]
+ public void custom_crop_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop ("custom");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT crop_toolbutton_toggled_cb", instance_pos = -1)]
+ public void crop_toolbutton_toggled_cb (Gtk.ToggleToolButton widget)
+ {
+ if (updating_page_menu)
+ return;
+
+ Gtk.RadioMenuItem menuitem;
+ if (widget.get_active ())
+ menuitem = (Gtk.RadioMenuItem) builder.get_object ("custom_crop_menuitem");
+ else
+ menuitem = (Gtk.RadioMenuItem) builder.get_object ("no_crop_menuitem");
+ menuitem.set_active (true);
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT four_by_six_menuitem_toggled_cb", instance_pos = -1)]
+ public void four_by_six_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop ("4x6");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT legal_menuitem_toggled_cb", instance_pos = -1)]
+ public void legal_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop ("legal");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT letter_menuitem_toggled_cb", instance_pos = -1)]
+ public void letter_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop ("letter");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT a6_menuitem_toggled_cb", instance_pos = -1)]
+ public void a6_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop ("A6");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT a5_menuitem_toggled_cb", instance_pos = -1)]
+ public void a5_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop ("A5");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT a4_menuitem_toggled_cb", instance_pos = -1)]
+ public void a4_menuitem_toggled_cb (Gtk.CheckMenuItem widget)
+ {
+ if (widget.get_active ())
+ set_crop ("A4");
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT crop_rotate_menuitem_activate_cb", instance_pos = -1)]
+ public void crop_rotate_menuitem_activate_cb (Gtk.Widget widget)
+ {
+ var page = book_view.get_selected ();
+ if (page == null)
+ return;
+ page.rotate_crop ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT page_move_left_menuitem_activate_cb", instance_pos = -1)]
+ public void page_move_left_menuitem_activate_cb (Gtk.Widget widget)
+ {
+ var page = book_view.get_selected ();
+ var index = book.get_page_index (page);
+ if (index > 0)
+ book.move_page (page, index - 1);
+
+ update_page_menu ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT page_move_right_menuitem_activate_cb", instance_pos = -1)]
+ public void page_move_right_menuitem_activate_cb (Gtk.Widget widget)
+ {
+ var page = book_view.get_selected ();
+ var index = book.get_page_index (page);
+ if (index < book.get_n_pages () - 1)
+ book.move_page (page, book.get_page_index (page) + 1);
+
+ update_page_menu ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT page_delete_menuitem_activate_cb", instance_pos = -1)]
+ public void page_delete_menuitem_activate_cb (Gtk.Widget widget)
+ {
+ book_view.get_book ().delete_page (book_view.get_selected ());
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT save_file_button_clicked_cb", instance_pos = -1)]
+ public void save_file_button_clicked_cb (Gtk.Widget widget)
+ {
+ save_document (false);
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT save_as_file_button_clicked_cb", instance_pos = -1)]
+ public void save_as_file_button_clicked_cb (Gtk.Widget widget)
+ {
+ save_document (true);
+ }
+
+ private void draw_page (Gtk.PrintOperation operation,
+ Gtk.PrintContext print_context,
+ int page_number)
+ {
+ var context = print_context.get_cairo_context ();
+ var page = book.get_page (page_number);
+
+ /* Rotate to same aspect */
+ bool is_landscape = false;
+ if (print_context.get_width () > print_context.get_height ())
+ is_landscape = true;
+ if (page.is_landscape () != is_landscape)
+ {
+ context.translate (print_context.get_width (), 0);
+ context.rotate (Math.PI_2);
+ }
+
+ context.scale (print_context.get_dpi_x () / page.get_dpi (),
+ print_context.get_dpi_y () / page.get_dpi ());
+
+ var image = page.get_image (true);
+ Gdk.cairo_set_source_pixbuf (context, image, 0, 0);
+ context.paint ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT email_button_clicked_cb", instance_pos = -1)]
+ public void email_button_clicked_cb (Gtk.Widget widget)
+ {
+ email (document_hint);
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT print_button_clicked_cb", instance_pos = -1)]
+ public void print_button_clicked_cb (Gtk.Widget widget)
+ {
+ var print = new Gtk.PrintOperation ();
+ print.set_n_pages ((int) book.get_n_pages ());
+ print.draw_page.connect (draw_page);
+
+ try
+ {
+ print.run (Gtk.PrintOperationAction.PRINT_DIALOG, window);
+ }
+ catch (Error e)
+ {
+ warning ("Error printing: %s", e.message);
+ }
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT help_contents_menuitem_activate_cb", instance_pos = -1)]
+ public void help_contents_menuitem_activate_cb (Gtk.Widget widget)
+ {
+ try
+ {
+ Gtk.show_uri (window.get_screen (), "ghelp:simple-scan", Gtk.get_current_event_time ());
+ }
+ catch (Error e)
+ {
+ show_error_dialog (/* Error message displayed when unable to launch help browser */
+ _("Unable to open help file"),
+ e.message);
+ }
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT about_menuitem_activate_cb", instance_pos = -1)]
+ public void about_menuitem_activate_cb (Gtk.Widget widget)
+ {
+ string[] authors = { "Robert Ancell <robert.ancell@canonical.com>" };
+
+ /* The license this software is under (GPL3+) */
+ string license = _("This program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nYou should have received a copy of the GNU General Public License\nalong with this program. If not, see <http://www.gnu.org/licenses/>.");
+
+ /* Title of about dialog */
+ string title = _("About Simple Scan");
+
+ /* Description of program */
+ string description = _("Simple document scanning tool");
+
+ Gtk.show_about_dialog (window,
+ "title", title,
+ "program-name", "Simple Scan",
+ "version", Config.VERSION,
+ "comments", description,
+ "logo-icon-name", "scanner",
+ "authors", authors,
+ "translator-credits", _("translator-credits"),
+ "website", "https://launchpad.net/simple-scan",
+ "copyright", "Copyright © 2009-2011 Canonical Ltd.",
+ "license", license,
+ "wrap-license", true,
+ null);
+ }
+
+ private bool on_quit ()
+ {
+ if (!prompt_to_save (/* Text in dialog warning when a document is about to be lost */
+ _("Save document before quitting?"),
+ /* Button in dialog to quit and discard unsaved document */
+ _("Quit without Saving")))
+ return false;
+
+ var device = get_selected_device ();
+ int paper_width = 0, paper_height = 0;
+ get_paper_size (out paper_width, out paper_height);
+
+ if (device != null)
+ settings.set_string ("selected-device", device);
+ settings.set_string ("document-type", document_hint);
+ settings.set_int ("text-dpi", get_text_dpi ());
+ settings.set_int ("photo-dpi", get_photo_dpi ());
+ settings.set_enum ("page-side", get_page_side ());
+ settings.set_int ("paper-width", paper_width);
+ settings.set_int ("paper-height", paper_height);
+ settings.set_int ("window-width", window_width);
+ settings.set_int ("window-height", window_height);
+ settings.set_boolean ("window-is-maximized", window_is_maximized);
+ settings.set_enum ("scan-direction", default_page_scan_direction);
+ settings.set_int ("page-width", default_page_width);
+ settings.set_int ("page-height", default_page_height);
+ settings.set_int ("page-dpi", default_page_dpi);
+
+ quit ();
+
+ return true;
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT quit_menuitem_activate_cb", instance_pos = -1)]
+ public void quit_menuitem_activate_cb (Gtk.Widget widget)
+ {
+ on_quit ();
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT simple_scan_window_configure_event_cb", instance_pos = -1)]
+ public bool simple_scan_window_configure_event_cb (Gtk.Widget widget, Gdk.EventConfigure event)
+ {
+ if (!window_is_maximized)
+ {
+ window_width = event.width;
+ window_height = event.height;
+ }
+
+ return false;
+ }
+
+ private void info_bar_response_cb (Gtk.InfoBar widget, int response_id)
+ {
+ if (response_id == 1)
+ {
+ device_combo.grab_focus ();
+ preferences_dialog.present ();
+ }
+ else
+ {
+ have_error = false;
+ error_title = null;
+ error_text = null;
+ update_info_bar ();
+ }
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT simple_scan_window_window_state_event_cb", instance_pos = -1)]
+ public bool simple_scan_window_window_state_event_cb (Gtk.Widget widget, Gdk.EventWindowState event)
+ {
+ if ((event.changed_mask & Gdk.WindowState.MAXIMIZED) != 0)
+ window_is_maximized = (event.new_window_state & Gdk.WindowState.MAXIMIZED) != 0;
+ return false;
+ }
+
+ [CCode (cname = "G_MODULE_EXPORT window_delete_event_cb", instance_pos = -1)]
+ public bool window_delete_event_cb (Gtk.Widget widget, Gdk.Event event)
+ {
+ return !on_quit ();
+ }
+
+ private void page_size_changed_cb (Page page)
+ {
+ default_page_width = page.get_width ();
+ default_page_height = page.get_height ();
+ default_page_dpi = page.get_dpi ();
+ }
+
+ private void page_scan_direction_changed_cb (Page page)
+ {
+ default_page_scan_direction = page.get_scan_direction ();
+ }
+
+ private void page_added_cb (Book book, Page page)
+ {
+ default_page_width = page.get_width ();
+ default_page_height = page.get_height ();
+ default_page_dpi = page.get_dpi ();
+ default_page_scan_direction = page.get_scan_direction ();
+ page.size_changed.connect (page_size_changed_cb);
+ page.scan_direction_changed.connect (page_scan_direction_changed_cb);
+
+ update_page_menu ();
+ }
+
+ private void page_removed_cb (Book book, Page page)
+ {
+ /* If this is the last page add a new blank one */
+ if (book.get_n_pages () == 1)
+ add_default_page ();
+
+ update_page_menu ();
+ }
+
+ private void set_dpi_combo (Gtk.ComboBox combo, int default_dpi, int current_dpi)
+ {
+ var renderer = new Gtk.CellRendererText ();
+ combo.pack_start (renderer, true);
+ combo.add_attribute (renderer, "text", 1);
+
+ var model = (Gtk.ListStore) combo.get_model ();
+ int[] scan_resolutions = {75, 150, 300, 600, 1200, 2400};
+ foreach (var dpi in scan_resolutions)
+ {
+ string label;
+ if (dpi == default_dpi)
+ /* Preferences dialog: Label for default resolution in resolution list */
+ label = _("%d dpi (default)").printf (dpi);
+ else if (dpi == 75)
+ /* Preferences dialog: Label for minimum resolution in resolution list */
+ label = _("%d dpi (draft)").printf (dpi);
+ else if (dpi == 1200)
+ /* Preferences dialog: Label for maximum resolution in resolution list */
+ label = _("%d dpi (high resolution)").printf (dpi);
+ else
+ /* Preferences dialog: Label for resolution value in resolution list (dpi = dots per inch) */
+ label = _("%d dpi").printf (dpi);
+
+ Gtk.TreeIter iter;
+ model.append (out iter);
+ model.set (iter, 0, dpi, 1, label, -1);
+
+ if (dpi == current_dpi)
+ combo.set_active_iter (iter);
+ }
+ }
+
+ private void needs_saving_cb (Book book)
+ {
+ save_menuitem.set_sensitive (book.get_needs_saving ());
+ save_toolbutton.set_sensitive (book.get_needs_saving ());
+ if (book.get_needs_saving ())
+ save_as_menuitem.set_sensitive (true);
+ }
+
+ private void load ()
+ {
+ Gtk.IconTheme.get_default ().append_search_path (Config.ICON_DIR);
+
+ Gtk.Window.set_default_icon_name ("scanner");
+
+ builder = new Gtk.Builder ();
+ var filename = Path.build_filename (Config.UI_DIR, "simple-scan.ui", null);
+ try
+ {
+ builder.add_from_file (filename);
+ }
+ catch (Error e)
+ {
+ critical ("Unable to load UI %s: %s\n", filename, e.message);
+ show_error_dialog (/* Title of dialog when cannot load required files */
+ _("Files missing"),
+ /* Description in dialog when cannot load required files */
+ _("Please check your installation"));
+ Posix.exit (Posix.EXIT_FAILURE);
+ }
+ builder.connect_signals (this);
+
+ window = (Gtk.Window) builder.get_object ("simple_scan_window");
+ main_vbox = (Gtk.VBox) builder.get_object ("main_vbox");
+ page_move_left_menuitem = (Gtk.MenuItem) builder.get_object ("page_move_left_menuitem");
+ page_move_right_menuitem = (Gtk.MenuItem) builder.get_object ("page_move_right_menuitem");
+ page_delete_menuitem = (Gtk.MenuItem) builder.get_object ("page_delete_menuitem");
+ crop_rotate_menuitem = (Gtk.MenuItem) builder.get_object ("crop_rotate_menuitem");
+ save_menuitem = (Gtk.MenuItem) builder.get_object ("save_menuitem");
+ save_as_menuitem = (Gtk.MenuItem) builder.get_object ("save_as_menuitem");
+ save_toolbutton = (Gtk.ToolButton) builder.get_object ("save_toolbutton");
+ stop_menuitem = (Gtk.MenuItem) builder.get_object ("stop_scan_menuitem");
+ stop_toolbutton = (Gtk.ToolButton) builder.get_object ("stop_toolbutton");
+
+ text_toolbar_menuitem = (Gtk.RadioMenuItem) builder.get_object ("text_toolbutton_menuitem");
+ text_menu_menuitem = (Gtk.RadioMenuItem) builder.get_object ("text_menuitem");
+ photo_toolbar_menuitem = (Gtk.RadioMenuItem) builder.get_object ("photo_toolbutton_menuitem");
+ photo_menu_menuitem = (Gtk.RadioMenuItem) builder.get_object ("photo_menuitem");
+
+ authorize_dialog = (Gtk.Dialog) builder.get_object ("authorize_dialog");
+ authorize_label = (Gtk.Label) builder.get_object ("authorize_label");
+ username_entry = (Gtk.Entry) builder.get_object ("username_entry");
+ password_entry = (Gtk.Entry) builder.get_object ("password_entry");
+
+ preferences_dialog = (Gtk.Dialog) builder.get_object ("preferences_dialog");
+ device_combo = (Gtk.ComboBox) builder.get_object ("device_combo");
+ device_model = (Gtk.ListStore) device_combo.get_model ();
+ text_dpi_combo = (Gtk.ComboBox) builder.get_object ("text_dpi_combo");
+ text_dpi_model = (Gtk.ListStore) text_dpi_combo.get_model ();
+ photo_dpi_combo = (Gtk.ComboBox) builder.get_object ("photo_dpi_combo");
+ photo_dpi_model = (Gtk.ListStore) photo_dpi_combo.get_model ();
+ page_side_combo = (Gtk.ComboBox) builder.get_object ("page_side_combo");
+ page_side_model = (Gtk.ListStore) page_side_combo.get_model ();
+ paper_size_combo = (Gtk.ComboBox) builder.get_object ("paper_size_combo");
+ paper_size_model = (Gtk.ListStore) paper_size_combo.get_model ();
+
+ /* Add InfoBar (not supported in Glade) */
+ info_bar = new Gtk.InfoBar ();
+ info_bar.response.connect (info_bar_response_cb);
+ main_vbox.pack_start (info_bar, false, true, 0);
+ var hbox = new Gtk.HBox (false, 12);
+ var content_area = (Gtk.Container) info_bar.get_content_area ();
+ content_area.add (hbox);
+ hbox.show ();
+
+ info_bar_image = new Gtk.Image.from_stock (Gtk.Stock.DIALOG_WARNING, Gtk.IconSize.DIALOG);
+ hbox.pack_start (info_bar_image, false, true, 0);
+ info_bar_image.show ();
+
+ info_bar_label = new Gtk.Label (null);
+ info_bar_label.set_alignment (0.0f, 0.5f);
+ hbox.pack_start (info_bar_label, true, true, 0);
+ info_bar_label.show ();
+
+ info_bar_close_button = (Gtk.Button) info_bar.add_button (Gtk.Stock.CLOSE, Gtk.ResponseType.CLOSE);
+ info_bar_change_scanner_button = (Gtk.Button) info_bar.add_button (/* Button in error infobar to open preferences dialog and change scanner */
+ _("Change _Scanner"), 1);
+
+ Gtk.TreeIter iter;
+ paper_size_model.append (out iter);
+ paper_size_model.set (iter, 0, 0, 1, 0, 2,
+ /* Combo box value for automatic paper size */
+ _("Automatic"), -1);
+ paper_size_model.append (out iter);
+ paper_size_model.set (iter, 0, 1050, 1, 1480, 2, "A6", -1);
+ paper_size_model.append (out iter);
+ paper_size_model.set (iter, 0, 1480, 1, 2100, 2, "A5", -1);
+ paper_size_model.append (out iter);
+ paper_size_model.set (iter, 0, 2100, 1, 2970, 2, "A4", -1);
+ paper_size_model.append (out iter);
+ paper_size_model.set (iter, 0, 2159, 1, 2794, 2, "Letter", -1);
+ paper_size_model.append (out iter);
+ paper_size_model.set (iter, 0, 2159, 1, 3556, 2, "Legal", -1);
+ paper_size_model.append (out iter);
+ paper_size_model.set (iter, 0, 1016, 1, 1524, 2, "4×6", -1);
+
+ var dpi = settings.get_int ("text-dpi");
+ if (dpi <= 0)
+ dpi = DEFAULT_TEXT_DPI;
+ set_dpi_combo (text_dpi_combo, DEFAULT_TEXT_DPI, dpi);
+ dpi = settings.get_int ("photo-dpi");
+ if (dpi <= 0)
+ dpi = DEFAULT_PHOTO_DPI;
+ set_dpi_combo (photo_dpi_combo, DEFAULT_PHOTO_DPI, dpi);
+
+ var renderer = new Gtk.CellRendererText ();
+ device_combo.pack_start (renderer, true);
+ device_combo.add_attribute (renderer, "text", 1);
+
+ renderer = new Gtk.CellRendererText ();
+ page_side_combo.pack_start (renderer, true);
+ page_side_combo.add_attribute (renderer, "text", 1);
+ set_page_side ((ScanType) settings.get_enum ("page-side"));
+
+ renderer = new Gtk.CellRendererText ();
+ paper_size_combo.pack_start (renderer, true);
+ paper_size_combo.add_attribute (renderer, "text", 2);
+ var paper_width = settings.get_int ("paper-width");
+ var paper_height = settings.get_int ("paper-height");
+ set_paper_size (paper_width, paper_height);
+
+ var device = settings.get_string ("selected-device");
+ if (device != null)
+ {
+ if (find_scan_device (device, out iter))
+ device_combo.set_active_iter (iter);
+ }
+
+ var document_type = settings.get_string ("document-type");
+ if (document_type != null)
+ set_document_hint (document_type);
+
+ book_view = new BookView (book);
+ book_view.set_border_width (18);
+ main_vbox.pack_end (book_view, true, true, 0);
+ book_view.page_selected.connect (page_selected_cb);
+ book_view.show_page.connect (show_page_cb);
+ book_view.show_menu.connect (show_page_menu_cb);
+ book_view.show ();
+
+ /* Find default page details */
+ default_page_scan_direction = (ScanDirection) settings.get_enum ("scan-direction");
+ default_page_width = settings.get_int ("page-width");
+ if (default_page_width <= 0)
+ default_page_width = 595;
+ default_page_height = settings.get_int ("page-height");
+ if (default_page_height <= 0)
+ default_page_height = 842;
+ default_page_dpi = settings.get_int ("page-dpi");
+ if (default_page_dpi <= 0)
+ default_page_dpi = 72;
+
+ /* Restore window size */
+ window_width = settings.get_int ("window-width");
+ if (window_width <= 0)
+ window_width = 600;
+ window_height = settings.get_int ("window-height");
+ if (window_height <= 0)
+ window_height = 400;
+ debug ("Restoring window to %dx%d pixels", window_width, window_height);
+ window.set_default_size (window_width, window_height);
+ window_is_maximized = settings.get_boolean ("window-is-maximized");
+ if (window_is_maximized)
+ {
+ debug ("Restoring window to maximized");
+ window.maximize ();
+ }
+
+ if (book.get_n_pages () == 0)
+ add_default_page ();
+ book.set_needs_saving (false);
+ book.needs_saving_changed.connect (needs_saving_cb);
+ }
+
+ public Book get_book ()
+ {
+ return book;
+ }
+
+ public void set_selected_page (Page page)
+ {
+ book_view.select_page (page);
+ }
+
+ public Page get_selected_page ()
+ {
+ return book_view.get_selected ();
+ }
+
+ public void set_scanning (bool scanning)
+ {
+ this.scanning = scanning;
+ page_delete_menuitem.set_sensitive (!scanning);
+ stop_menuitem.set_sensitive (scanning);
+ stop_toolbutton.set_sensitive (scanning);
+ }
+
+ public void show_error (string error_title, string error_text, bool change_scanner_hint)
+ {
+ have_error = true;
+ this.error_title = error_title;
+ this.error_text = error_text;
+ error_change_scanner_hint = change_scanner_hint;
+ update_info_bar ();
+ }
+
+ public void start ()
+ {
+ window.show ();
+ }
+}