gnome-scan r814 - in trunk: . modules/gsane



Author: bersace
Date: Sun Feb  1 18:15:32 2009
New Revision: 814
URL: http://svn.gnome.org/viewvc/gnome-scan?rev=814&view=rev

Log:
Support pixel defined scan area

Modified:
   trunk/ChangeLog
   trunk/modules/gsane/gsane-option-area.c

Modified: trunk/modules/gsane/gsane-option-area.c
==============================================================================
--- trunk/modules/gsane/gsane-option-area.c	(original)
+++ trunk/modules/gsane/gsane-option-area.c	Sun Feb  1 18:15:32 2009
@@ -37,6 +37,10 @@
 	GnomeScanOption* origin;
 	GnomeScanOption* paper_size;
 	GnomeScanOption* page_orientation;
+	GnomeScanUnit unit;
+	gdouble	fake_resolution;
+	gdouble width;
+	gdouble height;
 };
 
 G_DEFINE_TYPE(GSaneOptionArea, gsane_option_area, GSANE_TYPE_OPTION_HANDLER)
@@ -45,10 +49,19 @@
 gsane_option_area_install_origin(GSaneOptionArea *self)
 {
 	GSaneOptionHandler* handler = (GSaneOptionHandler*) self;
-	/* TODO: convert from non MM unit */
+	gdouble x, y;
+
+	x = gsane_option_handler_get_double(handler, self->priv->tl_x_desc, self->priv->tl_x_index, NULL);
+	y = gsane_option_handler_get_double(handler, self->priv->tl_y_desc, self->priv->tl_y_index, NULL);
+
+	if (self->priv->fake_resolution) {
+		x = gnome_scan_convert_to_mm(x, self->priv->unit, self->priv->fake_resolution);
+		y = gnome_scan_convert_to_mm(y, self->priv->unit, self->priv->fake_resolution);
+	}
+
 	GnomeScanPoint point = {
-		.x = gsane_option_handler_get_double(handler, self->priv->tl_x_desc, self->priv->tl_x_index, NULL),
-		.y = gsane_option_handler_get_double(handler, self->priv->tl_y_desc, self->priv->tl_y_index, NULL)
+		.x = x,
+		.y = y,
 	};
 
 	self->priv->origin = GNOME_SCAN_OPTION(gnome_scan_option_pointer_new("origin", _("Origin"), _("Coordinate of the top left corner of the paper."), GNOME_SCAN_OPTION_GROUP_FORMAT, GETTEXT_PACKAGE,
@@ -84,9 +97,17 @@
 		br_y = origin->y + gtk_paper_size_get_width(ps, GTK_UNIT_MM);
 	}
 
-	g_debug("Scan (%.2f ; %.2f) (%.2f ; %.2f)", tl_x, tl_y, br_x, br_y);
+	g_debug("Scan (%.2f ; %.2f) (%.2f ; %.2f) mm", tl_x, tl_y, br_x, br_y);
+	if (self->priv->fake_resolution) {
+		tl_x = gnome_scan_convert_from_mm(tl_x, self->priv->unit, self->priv->fake_resolution);
+		tl_y = gnome_scan_convert_from_mm(tl_y, self->priv->unit, self->priv->fake_resolution);
+		br_x = gnome_scan_convert_from_mm(br_x, self->priv->unit, self->priv->fake_resolution);
+		br_y = gnome_scan_convert_from_mm(br_y, self->priv->unit, self->priv->fake_resolution);
+		g_debug("=> actual scan (%.2f ; %.2f) (%.2f ; %.2f) %s",
+			tl_x, tl_y, br_x, br_y,
+			gnome_scan_unit_to_string(self->priv->unit));
+	}
 
-	/* TODO: convert to non MM unit */
 	gsane_option_handler_set_double(handler, self->priv->tl_x_desc, self->priv->tl_x_index, tl_x, NULL);
 	gsane_option_handler_set_double(handler, self->priv->tl_y_desc, self->priv->tl_y_index, tl_y, NULL);
 	gsane_option_handler_set_double(handler, self->priv->br_x_desc, self->priv->br_x_index, br_x, NULL);
@@ -100,31 +121,38 @@
 }
 
 static GSList*
-gsane_option_area_add_paper_size(GSaneOptionArea* self, GSList* values, const gchar* paper_name, gdouble width, gdouble height, GtkUnit unit)
+gsane_option_area_add_paper_size(GSaneOptionArea* self, GSList* values, const gchar* paper_name, gdouble width, gdouble height)
 {
 	GtkPaperSize* ps;
-	GnomeScanEnumValue evalue;
-	GValue* value;
 
 	ps = gtk_paper_size_new(paper_name);
 
-	if (gtk_paper_size_get_width(ps, unit) > width
-	    || gtk_paper_size_get_height(ps, unit) > height) {
-		g_message("%s can't scan %s document, too wide for hardware extent.",
-			  gnome_scan_scanner_get_name(GSANE_OPTION_HANDLER(self)->scanner),
+	if (gtk_paper_size_get_width(ps, GTK_UNIT_MM) > width
+	    || gtk_paper_size_get_height(ps, GTK_UNIT_MM) > height) {
+		g_message("Can't scan %s document, too wide for hardware extent.",
 			  gtk_paper_size_get_display_name(ps));
 		gtk_paper_size_free(ps);
 		return values;
 	}
 
-	value = g_new0(GValue, 1);
-	g_value_init(value, GTK_TYPE_PAPER_SIZE);
-	g_value_set_boxed(value, ps);
-	gnome_scan_enum_value_init(&evalue, value, gtk_paper_size_get_display_name(ps), NULL);
-	values = g_slist_append(values, gnome_scan_enum_value_dup(&evalue));
-	gnome_scan_enum_value_destroy(&evalue);
-	g_value_reset(value);
-	g_free(value);
+	return g_slist_append(values, ps);
+}
+
+/* List common paper sizes. This will be extendable through
+   Preselection */
+static GSList*
+gsane_option_area_list_paper_sizes(GSaneOptionArea *self)
+{
+	GSList *values = NULL;
+
+	/* ISO format */
+	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_A4, self->priv->width, self->priv->height);
+	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_A5, self->priv->width, self->priv->height);
+
+	/* US bullshit non standard paper sizes */
+	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_LETTER, self->priv->width, self->priv->height);
+	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_LEGAL, self->priv->width, self->priv->height);
+	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_EXECUTIVE, self->priv->width, self->priv->height);
 
 	return values;
 }
@@ -133,73 +161,77 @@
 gsane_option_area_install_paper_size(GSaneOptionArea* self)
 {
 	GSaneOptionHandler* handler = (GSaneOptionHandler*)self;
-	GtkPaperSize* ps;
-	GnomeScanEnumValue evalue;
-	GValue* value;
-	GSList *values = NULL, *it;
-	gdouble width, height;
-	GnomeScanUnit unit = gsane_option_unit(self->priv->tl_x_desc);
+	GSList *ps_list = NULL, *it;
+	gdouble tlx, tly, brx, bry, width, height;
 
-	/* get width and height */
-	switch (self->priv->tl_x_desc->type) {
-	case SANE_TYPE_INT:
-		width = self->priv->br_x_desc->constraint.range->max;
-		height = self->priv->br_y_desc->constraint.range->max;
-		break;
-	case SANE_TYPE_FIXED:
-		width = SANE_UNFIX(self->priv->br_x_desc->constraint.range->max);
-		height = SANE_UNFIX(self->priv->br_y_desc->constraint.range->max);
-		break;
-	default:
-		g_warning("Unsupported coordinate type.");
-		return;
-		break;
+	tlx = gsane_option_handler_get_double(handler, self->priv->tl_x_desc, self->priv->tl_x_index, NULL);
+	tly = gsane_option_handler_get_double(handler, self->priv->tl_y_desc, self->priv->tl_y_index, NULL);
+	brx = gsane_option_handler_get_double(handler, self->priv->br_x_desc, self->priv->br_x_index, NULL);
+	bry = gsane_option_handler_get_double(handler, self->priv->br_y_desc, self->priv->br_y_index, NULL);
+	width = brx - tlx;
+	height = bry - tly;
+
+	/* We don't list paper size when using fake resolution because
+	   we can't reliabily check whether fit the scan area. Also,
+	   this will lead the ROI not to fit the actual paper on the
+	   preview. Last but not least, pixel device are often webcam
+	   and such device that really don't care paper sizes.
+	*/
+	if (self->priv->fake_resolution) {
+		width = gnome_scan_convert_to_mm(width, self->priv->unit, self->priv->fake_resolution);	
+		height = gnome_scan_convert_to_mm(height, self->priv->unit, self->priv->fake_resolution);
 	}
+	else
+		ps_list = gsane_option_area_list_paper_sizes(self);
 
-	g_debug("%s extent is %.2fx%.2f %s",
-		gnome_scan_scanner_get_name(handler->scanner),
-		width, height, gnome_scan_unit_to_string(unit));
+	/* define special paper sizes */
 
-	/* define max paper size */
-	value = g_new0(GValue, 1);
-	g_value_init(value, GTK_TYPE_PAPER_SIZE);
-	ps = gtk_paper_size_new_custom("max", _("Maximum"), width, height, unit);
-	g_value_set_boxed(value, ps);
-	gnome_scan_enum_value_init(&evalue, value, gtk_paper_size_get_display_name(ps), NULL);
-	values = g_slist_append(values, gnome_scan_enum_value_dup(&evalue));
-	gnome_scan_enum_value_destroy(&evalue);
-
-	/* A4 */
-	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_A4, width, height, unit);
-	/* A5 */
-	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_A5, width, height, unit);
-	/* US bullshit */
-	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_LETTER, width, height, unit);
-	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_LEGAL, width, height, unit);
-	values = gsane_option_area_add_paper_size(self, values, GTK_PAPER_NAME_EXECUTIVE, width, height, unit);
+	
+	ps_list = g_slist_prepend(ps_list,
+				  /* Translator: manual selection display label */
+				  gtk_paper_size_new_custom("manual", _("Manual"),
+							    width, height,
+							    GTK_UNIT_MM));
+
+	ps_list = g_slist_prepend(ps_list,
+				  /* Translator: maximum paper size display label */
+				  gtk_paper_size_new_custom("max", _("Maximum"),
+							    self->priv->width, self->priv->height,
+							    GTK_UNIT_MM));
 
+	GSList *enum_values = NULL;
+	GnomeScanEnumValue evalue;
+	GValue *value = g_new0(GValue,1);
 	gchar *papersizes = NULL, *old;
-	const gchar* label;
-	for(it = values; it; it = it->next) {
-		label = ((GnomeScanEnumValue*)(it->data))->label;
+	g_value_init(value, GTK_TYPE_PAPER_SIZE);
+	for(it = ps_list; it; it = it->next) {
+		g_value_set_boxed(value, it->data);
+		gnome_scan_enum_value_init(&evalue, value, gtk_paper_size_get_display_name(it->data), NULL);
+		enum_values = g_slist_append(enum_values, gnome_scan_enum_value_dup(&evalue));
+
+		/* Assemble debugging list  */
 		if (papersizes) {
 			old = papersizes;
-			papersizes = g_strdup_printf("%s, \"%s\"", papersizes, label);
+			papersizes = g_strdup_printf("%s, \"%s\"", papersizes, evalue.label);
 			g_free(old);
 		}
 		else
-			papersizes = g_strdup_printf("\"%s\"", label);
-	}
+			papersizes = g_strdup_printf("\"%s\"", evalue.label);
 
+		gnome_scan_enum_value_destroy(&evalue);
+	}
 	g_value_reset(value);
 	g_free(value);
 
+
 	self->priv->paper_size = GNOME_SCAN_OPTION(gnome_scan_option_enum_new("paper-size", _("Paper-Size"), _("Paper-Size"), GNOME_SCAN_OPTION_GROUP_FORMAT, GETTEXT_PACKAGE,
-									      values->data, values, GNOME_SCAN_OPTION_HINT_PRIMARY));
+									      enum_values->data, enum_values, GNOME_SCAN_OPTION_HINT_PRIMARY));
 	gnome_scan_node_install_option(GNOME_SCAN_NODE(handler->scanner), self->priv->paper_size);
 	g_signal_connect_swapped(self->priv->paper_size, "notify::value", G_CALLBACK(gsane_option_area_option_changed), self);
 
-	g_debug("\toption    : paper-size = \"%s\", enum = {%s}", ((GnomeScanEnumValue*)(values->data))->label, papersizes);
+	g_debug("\toption    : paper-size = \"%s\", enum = {%s}", ((GnomeScanEnumValue*)(enum_values->data))->label, papersizes);
+	g_slist_foreach(ps_list, (GFunc) gtk_paper_size_free, NULL);
+	g_slist_free(ps_list);
 	g_free(papersizes);
 }
 
@@ -245,6 +277,39 @@
 	g_signal_connect_swapped(self->priv->page_orientation, "notify::value", G_CALLBACK(gsane_option_area_option_changed), self);
 }
 
+static gboolean
+gsane_option_area_get_extent(GSaneOptionArea *self, gdouble *width, gdouble *height)
+{
+	gdouble min, max;
+
+	/* TODO: handle enum ? Didn't found a backend using enum
+	   constraint */
+	switch (self->priv->tl_x_desc->type) {
+	case SANE_TYPE_INT:
+		min = self->priv->br_x_desc->constraint.range->min;
+		max = self->priv->br_x_desc->constraint.range->max;
+		*width = max - min;
+		min = self->priv->br_y_desc->constraint.range->min;
+		max = self->priv->br_y_desc->constraint.range->max;
+		*height = max - min;
+		break;
+	case SANE_TYPE_FIXED:
+		min = SANE_UNFIX(self->priv->br_x_desc->constraint.range->min);
+		max = SANE_UNFIX(self->priv->br_x_desc->constraint.range->max);
+		*width = max - min;
+		min = SANE_UNFIX(self->priv->br_y_desc->constraint.range->min);
+		max = SANE_UNFIX(self->priv->br_y_desc->constraint.range->max);
+		*height = max - min;
+		break;
+	default:
+		g_warning("Unsupported coordinate unit.");
+		return FALSE;
+		break;
+	}
+
+	return TRUE;
+}
+
 static void
 gsane_option_handler_handle_matched(GSaneOptionHandler *handler, const SANE_Option_Descriptor* desc, SANE_Int n, const gchar*group)
 {
@@ -255,7 +320,32 @@
 	if (self->priv->count < 4)
 		return;
 
-	/* we have matched all SANE option, actually install high level options */
+	/* Here we have matched all SANE option we wanted */
+
+	if (!gsane_option_area_get_extent(self, &self->priv->width, &self->priv->height))
+		return;
+
+	self->priv->unit = gsane_option_unit(self->priv->tl_x_desc);
+	if (self->priv->unit == GNOME_SCAN_UNIT_PIXEL) {
+		/* Pixel defined area prevent us to get the actual
+		   scanner extent. We assume the scanner can scan a US
+		   Legal-width paper. We compute a fake resolution
+		   based on this assumption. */
+		self->priv->fake_resolution = self->priv->width / (216. / 25.4);
+
+		self->priv->width = gnome_scan_convert_to_mm(self->priv->width,
+							     self->priv->unit,
+							     self->priv->fake_resolution);
+		self->priv->height = gnome_scan_convert_to_mm(self->priv->height,
+							      self->priv->unit,
+							      self->priv->fake_resolution);
+	}
+
+	g_debug("%s extent is %.2fx%.2f %s",
+		gnome_scan_scanner_get_name(handler->scanner),
+		self->priv->width, self->priv->height, gnome_scan_unit_to_string(self->priv->unit));
+
+	/* Actually install high level options */
 	gsane_option_area_install_origin(self);
 	gsane_option_area_install_paper_size(self);
 	gsane_option_area_install_page_orientation(self);
@@ -303,6 +393,5 @@
 {
 	self->priv = GSANE_OPTION_AREA_GET_PRIVATE(self);
 	self->priv->count = 0;
+	self->priv->fake_resolution = 0.;
 }
-
-



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]