Index: plugins/plot_xy/gog-xy.c
===================================================================
RCS file: /cvs/gnome/goffice/plugins/plot_xy/gog-xy.c,v
retrieving revision 1.87
diff -p -u -5 -r1.87 gog-xy.c
--- plugins/plot_xy/gog-xy.c	17 Apr 2006 04:28:26 -0000	1.87
+++ plugins/plot_xy/gog-xy.c	26 May 2006 19:30:55 -0000
@@ -38,10 +38,11 @@
 #include <goffice/app/module-plugin-defs.h>
 
 #include <glib/gi18n-lib.h>
 #include <gsf/gsf-impl-utils.h>
 #include <math.h>
+#include <string.h>
 
 typedef struct {
 	GogPlotClass	base;
 	
 	void (*adjust_bounds) (Gog2DPlot *model, double *x_min, double *x_max, double *y_min, double *y_max);
@@ -242,11 +243,12 @@ GSF_DYNAMIC_CLASS (Gog2DPlot, gog_2d_plo
 
 enum {
 	GOG_XY_PROP_0,
 	GOG_XY_PROP_DEFAULT_STYLE_HAS_MARKERS,
 	GOG_XY_PROP_DEFAULT_STYLE_HAS_LINES,
-	GOG_XY_PROP_USE_SPLINES
+	GOG_XY_PROP_USE_SPLINES,
+	GOG_XY_PROP_INTERPOLATION,
 };
 
 static GogObjectClass *xy_parent_klass;
 
 #define GOG_XY_PLOT_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GOG_XY_PLOT_TYPE, GogXYPlotClass))
@@ -267,16 +269,49 @@ gog_xy_set_property (GObject *obj, guint
 	GogXYPlot *xy = GOG_XY_PLOT (obj);
 	switch (param_id) {
 	case GOG_XY_PROP_DEFAULT_STYLE_HAS_MARKERS:
 		xy->default_style_has_markers = g_value_get_boolean (value);
 		break;
-	case GOG_XY_PROP_DEFAULT_STYLE_HAS_LINES:
-		xy->default_style_has_lines = g_value_get_boolean (value);
+	case GOG_XY_PROP_DEFAULT_STYLE_HAS_LINES: {
+		gboolean b = g_value_get_boolean (value);
+		if (!b)
+			xy->interpolation = GOG_XY_INTERPOLATION_NONE;
+		else if (xy->interpolation == GOG_XY_INTERPOLATION_NONE)
+			xy->interpolation = GOG_XY_INTERPOLATION_LINEAR;
 		break;
+	}
 	case GOG_XY_PROP_USE_SPLINES:
-		xy->use_splines = g_value_get_boolean (value);
+		if (g_value_get_boolean (value))
+			xy->interpolation = GOG_XY_INTERPOLATION_SPLINE;
 		break;
+	case GOG_XY_PROP_INTERPOLATION: {
+		char const *s = g_value_get_string (value);
+		if (!strcmp (s, "none"))
+			xy->interpolation = GOG_XY_INTERPOLATION_NONE;
+		else if (!strcmp (s, "linear"))
+			xy->interpolation = GOG_XY_INTERPOLATION_LINEAR;
+		else if (!strcmp (s, "spline"))
+			xy->interpolation = GOG_XY_INTERPOLATION_SPLINE;
+		else if (!strncmp (s, "step", 4)) {
+			xy->interpolation = GOG_XY_INTERPOLATION_STEP;
+			s += 5;
+			if (!strcmp (s, "start"))
+				xy->interp_subtype = GOG_XY_STEP_START;
+			else if (!strcmp (s, "end"))
+				xy->interp_subtype = GOG_XY_STEP_END;
+			else if (!strcmp (s, "center-x"))
+				xy->interp_subtype = GOG_XY_STEP_CENTER_X;
+			else if (!strcmp (s, "center-y"))
+				xy->interp_subtype = GOG_XY_STEP_CENTER_Y;
+			else
+				g_warning ("Invalid value \"%s\" for subtype of a stepped plot", s);
+			break;
+		}
+		else
+			g_warning ("Invalid value \"%s\" for property \"interpolation\" of a scatter plot", s);
+		break;
+	}
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
 		 break;
 	}
 }
 static void
@@ -287,15 +322,49 @@ gog_xy_get_property (GObject *obj, guint
 	switch (param_id) {
 	case GOG_XY_PROP_DEFAULT_STYLE_HAS_MARKERS:
 		g_value_set_boolean (value, xy->default_style_has_markers);
 		break;
 	case GOG_XY_PROP_DEFAULT_STYLE_HAS_LINES:
-		g_value_set_boolean (value, xy->default_style_has_lines);
+		g_value_set_boolean (value, xy->interpolation != GOG_XY_INTERPOLATION_NONE);
 		break;
 	case GOG_XY_PROP_USE_SPLINES:
-		g_value_set_boolean (value, xy->use_splines);
+		g_value_set_boolean (value, xy->interpolation == GOG_XY_INTERPOLATION_SPLINE);
 		break;
+	case GOG_XY_PROP_INTERPOLATION: {
+		switch (xy->interpolation) {
+		case GOG_XY_INTERPOLATION_NONE:
+			g_value_set_string (value, "none");
+			break;
+		case GOG_XY_INTERPOLATION_LINEAR:
+			g_value_set_string (value, "linear");
+			break;
+		case GOG_XY_INTERPOLATION_SPLINE:
+			g_value_set_string (value, "spline");
+			break;
+		case GOG_XY_INTERPOLATION_STEP: {
+			switch (xy->interp_subtype) {
+			case GOG_XY_STEP_START:
+				g_value_set_string (value, "step-start");
+				break;
+			case GOG_XY_STEP_END:
+				g_value_set_string (value, "step-end");
+				break;
+			case GOG_XY_STEP_CENTER_X:
+				g_value_set_string (value, "step-center-x");
+				break;
+			case GOG_XY_STEP_CENTER_Y:
+				g_value_set_string (value, "step-center-y");
+				break;
+			default:
+				g_assert_not_reached ();
+				break;
+			}
+			break;
+		}
+		}
+		break;
+	}
 	default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, param_id, pspec);
 		 break;
 	}
 }
 
@@ -320,11 +389,14 @@ gog_xy_plot_class_init (GogPlotClass *pl
 			TRUE, G_PARAM_READWRITE | GOG_PARAM_PERSISTENT));
 	g_object_class_install_property (gobject_klass, GOG_XY_PROP_USE_SPLINES,
 		g_param_spec_boolean ("use-splines", NULL,
 			"Should the plot use splines instead of linear interpolation",
 			FALSE, G_PARAM_READWRITE | GOG_PARAM_PERSISTENT));
-
+	g_object_class_install_property (gobject_klass, GOG_XY_PROP_INTERPOLATION,
+		g_param_spec_string  ("interpolation", NULL,
+			_("Interpolation type (none, linear, spline or step) with variant, if any."),
+            "none", G_PARAM_READWRITE | GOG_PARAM_PERSISTENT));
 	gog_klass->type_name	= gog_xy_plot_type_name;
 
 	{
 		static GogSeriesDimDesc dimensions[] = {
 			{ N_("X"), GOG_SERIES_SUGGESTED, FALSE,
@@ -349,11 +421,11 @@ gog_xy_plot_class_init (GogPlotClass *pl
 
 static void
 gog_xy_plot_init (GogXYPlot *xy)
 {
 	xy->default_style_has_markers = TRUE;
-	xy->default_style_has_lines = TRUE;
+	xy->interpolation = GOG_XY_INTERPOLATION_LINEAR;
 }
 
 GSF_DYNAMIC_CLASS (GogXYPlot, gog_xy_plot,
 	gog_xy_plot_class_init, gog_xy_plot_init,
 	GOG_2D_PLOT_TYPE)
@@ -735,20 +807,104 @@ gog_xy_view_render (GogView *view, GogVi
 					go_nan;
 				y_splines[i] = gog_axis_map_finite (y_map, y_vals[i]) ?
 					gog_axis_map_to_view (y_map, y_vals[i]):
 					go_nan;
 			}
-			if (GOG_XY_PLOT (view->model)->use_splines) {
+			switch (GOG_XY_PLOT (view->model)->interpolation) {
+			case GOG_XY_INTERPOLATION_LINEAR: {
+				ArtVpath *path;
+				path = go_line_build_vpath (x_splines, y_splines, n);
+				gog_renderer_draw_path (view->renderer, path);
+				art_free (path);
+				break;
+			}
+			case GOG_XY_INTERPOLATION_SPLINE: {
 				ArtBpath *path;
 				path = go_line_build_bpath (x_splines, y_splines, n);
 				gog_renderer_draw_bezier_path (view->renderer, path);
 				art_free (path);
-			} else {
+				break;
+			}
+			case GOG_XY_INTERPOLATION_STEP: {
+				unsigned i, j;
 				ArtVpath *path;
-				path = go_line_build_vpath (x_splines, y_splines, n);
+				gboolean b = FALSE;
+				i = 0;
+				while ((!go_finite (x_splines[i]) || !go_finite (y_splines[i]))  && n < i)
+					i++;
+				if (n == i)
+					break;
+				path = art_new (ArtVpath,
+					((GOG_XY_PLOT (view->model)->interp_subtype <= GOG_XY_STEP_END)?
+					2 * n + 1: 3 * n + 1));
+				path[0].code = ART_MOVETO;
+				path[0].x = x_splines[i];
+				path[0].y = y_splines[i++];
+				for (j = 1; i < n; i++) {
+					while ((!go_finite (x_splines[i]) ||
+							!go_finite (y_splines[i]))  && i < n) {
+						i++;
+						b = TRUE;
+					}
+					if (n == i)
+						break;
+					if (b) {
+						path[j].code = ART_MOVETO;
+						path[j].x = x_splines[i];
+						path[j++].y = y_splines[i];
+						b = FALSE;
+					} else switch (GOG_XY_PLOT (view->model)->interp_subtype) {
+					case GOG_XY_STEP_START:
+						path[j].code = ART_LINETO;
+						path[j].x = x_splines[i];
+						path[j++].y = y_splines[i-1];
+						path[j].code = ART_LINETO;
+						path[j].x = x_splines[i];
+						path[j++].y = y_splines[i];
+						break;
+					case GOG_XY_STEP_END:
+						path[j].code = ART_LINETO;
+						path[j].x = x_splines[i-1];
+						path[j++].y = y_splines[i];
+						path[j].code = ART_LINETO;
+						path[j].x = x_splines[i];
+						path[j++].y = y_splines[i];
+						break;
+					case GOG_XY_STEP_CENTER_X:
+						path[j].code = ART_LINETO;
+						path[j].x = path[j+1].x = (x_splines[i-1] + x_splines[i]) / 2.;
+						path[j++].y = y_splines[i-1];
+						path[j].code = ART_LINETO;
+						path[j++].y = y_splines[i];
+						path[j].code = ART_LINETO;
+						path[j].x = x_splines[i];
+						path[j++].y = y_splines[i];
+						break;
+					case GOG_XY_STEP_CENTER_Y:
+						path[j].code = ART_LINETO;
+						path[j].x = x_splines[i-1];
+						path[j++].y = (y_splines[i-1] + y_splines[i]) / 2.;
+						path[j].code = ART_LINETO;
+						path[j].y = path[j-1].y;
+						path[j++].x = x_splines[i];
+						path[j].code = ART_LINETO;
+						path[j].x = x_splines[i];
+						path[j++].y = y_splines[i];
+						break;
+					default:
+						g_assert_not_reached ();
+						break;
+					}
+				}
+				path[j].code = ART_END;
 				gog_renderer_draw_path (view->renderer, path);
 				art_free (path);
+				break;
+			}
+			default:
+				g_assert_not_reached ();
+				break;
 			}
 			g_free (x_splines);
 			g_free (y_splines);
 		}
 
@@ -1072,11 +1228,11 @@ gog_xy_series_init_style (GogStyledObjec
 
 	if (!plot->default_style_has_markers &&
 	    style->marker.auto_shape) 
 		go_marker_set_shape (style->marker.mark, GO_MARKER_NONE);
 
-	if (!plot->default_style_has_lines &&
+	if (!plot->interpolation &&
 	    style->line.auto_dash)
 		style->line.dash_type = GO_LINE_NONE;
 }
 
 static void
Index: plugins/plot_xy/gog-xy.h
===================================================================
RCS file: /cvs/gnome/goffice/plugins/plot_xy/gog-xy.h,v
retrieving revision 1.16
diff -p -u -5 -r1.16 gog-xy.h
--- plugins/plot_xy/gog-xy.h	5 Apr 2006 06:46:14 -0000	1.16
+++ plugins/plot_xy/gog-xy.h	26 May 2006 19:30:55 -0000
@@ -25,10 +25,24 @@
 #include <goffice/graph/gog-plot-impl.h>
 #include <goffice/graph/gog-series-impl.h>
 
 G_BEGIN_DECLS
 
+typedef enum {
+	GOG_XY_INTERPOLATION_NONE,
+	GOG_XY_INTERPOLATION_LINEAR,
+	GOG_XY_INTERPOLATION_SPLINE,
+	GOG_XY_INTERPOLATION_STEP,
+} GogXYInterpolation;
+
+enum {
+	GOG_XY_STEP_START,
+	GOG_XY_STEP_END,
+	GOG_XY_STEP_CENTER_X,
+	GOG_XY_STEP_CENTER_Y,
+};
+
 typedef struct {
 	GogPlot	base;
 
 	struct {
 		double minima, maxima;
@@ -37,12 +51,12 @@ typedef struct {
 } Gog2DPlot;
 
 typedef struct {
 	Gog2DPlot	base;
 	gboolean	default_style_has_markers;
-	gboolean	default_style_has_lines;
-	gboolean	use_splines;
+	GogXYInterpolation interpolation;
+	int interp_subtype;
 } GogXYPlot;
 
 typedef struct {
 	Gog2DPlot	base;
 	gboolean size_as_area;
Index: plugins/plot_xy/plot-types.xml.in
===================================================================
RCS file: /cvs/gnome/goffice/plugins/plot_xy/plot-types.xml.in,v
retrieving revision 1.8
diff -p -u -5 -r1.8 plot-types.xml.in
--- plugins/plot_xy/plot-types.xml.in	10 Aug 2005 13:50:33 -0000	1.8
+++ plugins/plot_xy/plot-types.xml.in	26 May 2006 19:30:56 -0000
@@ -5,33 +5,67 @@
 
     <Type _name="XY Points" row="1" col="1"
 	  engine="GogXYPlot" family="XY"
 	  _description="Markers at each point."
 	  sample_image_file="chart_scatter_1_1.png">
-	  <property name="default-style-has-lines">FALSE</property>
+	  <property name="interpolation">none</property>
 	  <property name="guru-hints">backplane</property>
     </Type>
     <!-- really 3_1 -->
     <Type _name="XY" row="2" col="1"
 	  engine="GogXYPlot" family="XY"
 	  _description="Linearly interpolate between multi-dimensional points,with markers at each point."
 	  sample_image_file="chart_scatter_3_1.png">
+	  <property name="interpolation">linear</property>
 	  <property name="guru-hints">backplane</property>
     </Type>
     <Type _name="XY Lines" row="2" col="2"
 	  engine="GogXYPlot" family="XY"
 	  _description="Linearly interpolate between multi-dimensional points."
 	  sample_image_file="chart_scatter_3_2.png">
 	  <property name="default-style-has-markers">FALSE</property>
+	  <property name="interpolation">linear</property>
 	  <property name="guru-hints">backplane</property>
     </Type>
     <Type _name="XY Splines" row="2" col="3"
 	  engine="GogXYPlot" family="XY"
 	  _description="Interpolate between multi-dimensional points with Bezier splines."
 	  sample_image_file="chart_scatter_3_3.png">
 	  <property name="default-style-has-markers">FALSE</property>
-	  <property name="use-splines">TRUE</property>
+	  <property name="interpolation">spline</property>
+	  <property name="guru-hints">backplane</property>
+    </Type>
+    <Type _name="XY Steps Start" row="3" col="1"
+	  engine="GogXYPlot" family="XY"
+	  _description="Stepped curve using the first y value."
+	  sample_image_file="chart_scatter_4_1.png">
+	  <property name="default-style-has-markers">TRUE</property>
+	  <property name="interpolation">step-start</property>
+	  <property name="guru-hints">backplane</property>
+    </Type>
+    <Type _name="XY Steps End" row="3" col="2"
+	  engine="GogXYPlot" family="XY"
+	  _description="Stepped curve using the last y value."
+	  sample_image_file="chart_scatter_4_2.png">
+	  <property name="default-style-has-markers">TRUE</property>
+	  <property name="interpolation">step-end</property>
+	  <property name="guru-hints">backplane</property>
+    </Type>
+    <Type _name="XY Steps Center" row="3" col="3"
+	  engine="GogXYPlot" family="XY"
+	  _description="Stepped curve using the nearest y value."
+	  sample_image_file="chart_scatter_4_3.png">
+	  <property name="default-style-has-markers">TRUE</property>
+	  <property name="interpolation">step-center-x</property>
+	  <property name="guru-hints">backplane</property>
+    </Type>
+    <Type _name="XY Steps Mean" row="3" col="4"
+	  engine="GogXYPlot" family="XY"
+	  _description="Stepped curve using the mean y value."
+	  sample_image_file="chart_scatter_4_4.png">
+	  <property name="default-style-has-markers">TRUE</property>
+	  <property name="interpolation">step-center-y</property>
 	  <property name="guru-hints">backplane</property>
     </Type>
     <Type _name="Bubble" row="1" col="1"
 	  engine="GogBubblePlot" family="Bubble"
 	  _description="Multi-dimensional points with circle at each point."
