revised curve plus new gamma widget



It's me again.  As per Pete's suggestion, I revised the gtk_curve
widget so it's really just a curve (no other buttons or anything).
Then I wrote a gtk_gamma_curve widget that adds back all the
user-interface junk that used to be in gtk_curve.  In addition,
gtk_gamma_curve also has a button to set the curve as a
gamma-correction value (hence the name gtk_gamma_curve).  Finally, I
"designed" some cheesy 16x16 pixmaps to make the buttons smaller.

There is a slight problem with the pixmaps: i wanted to make the
background transparent, but when doing so, the _entire_ pixmap became
transparent.  I couldn't figure out what's going wrong, so if anybody
has a suggestion, I'm all ears (just search for "why does this not
work" in the patch below and you'll see what I mean...).

Comments welcome.

	--david

diff -urN gimp-0.99.10/gtk+/gtk/Makefile.in gimp-0.99.10-davidm/gtk+/gtk/Makefile.in
--- gimp-0.99.10/gtk+/gtk/Makefile.in	Fri Jun  6 22:26:45 1997
+++ gimp-0.99.10-davidm/gtk+/gtk/Makefile.in	Sun Jun  8 17:35:43 1997
@@ -72,6 +72,7 @@
 	gtkcolorsel.c		\
 	gtkcontainer.c		\
 	gtkcurve.c		\
+	gtkgamma.c		\
 	gtkdata.c		\
 	gtkdialog.c		\
 	gtkdrawingarea.c	\
@@ -146,6 +147,7 @@
 	gtkcolorsel.h		\
 	gtkcontainer.h		\
 	gtkcurve.h		\
+	gtkgamma.h		\
 	gtkdata.h		\
 	gtkdialog.h		\
 	gtkdrawingarea.h	\
diff -urN gimp-0.99.10/gtk+/gtk/gtk.h gimp-0.99.10-davidm/gtk+/gtk/gtk.h
--- gimp-0.99.10/gtk+/gtk/gtk.h	Sun Apr 27 14:48:24 1997
+++ gimp-0.99.10-davidm/gtk+/gtk/gtk.h	Sun Jun  8 17:39:35 1997
@@ -33,6 +33,7 @@
 #include <gtk/gtkcolorsel.h>
 #include <gtk/gtkcontainer.h>
 #include <gtk/gtkcurve.h>
+#include <gtk/gtkgamma.h>
 #include <gtk/gtkdata.h>
 #include <gtk/gtkdialog.h>
 #include <gtk/gtkdrawingarea.h>
diff -urN gimp-0.99.10/gtk+/gtk/gtkcurve.c gimp-0.99.10-davidm/gtk+/gtk/gtkcurve.c
--- gimp-0.99.10/gtk+/gtk/gtkcurve.c	Tue Jun  3 17:40:30 1997
+++ gimp-0.99.10-davidm/gtk+/gtk/gtkcurve.c	Sun Jun  8 21:10:20 1997
@@ -15,8 +15,8 @@
  * License along with this library; if not, write to the Free
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <stdio.h>	/* XXX fix me */
 #include <string.h>
+#include <math.h>
 
 #include "gtkcurve.h"
 #include "gtkdrawingarea.h"
@@ -37,7 +37,8 @@
 			 GDK_BUTTON_RELEASE_MASK |	\
 			 GDK_BUTTON1_MOTION_MASK)
 
-static GtkContainerClass *parent_class = NULL;
+static GtkDrawingAreaClass *parent_class = NULL;
+static gint curve_type_changed_signal = 0;
 
 
 /* forward declarations: */
@@ -45,6 +46,7 @@
 static void gtk_curve_init (GtkCurve *curve);
 static void gtk_curve_destroy (GtkObject *object);
 
+
 guint
 gtk_curve_get_type (void)
 {
@@ -62,7 +64,7 @@
 	(GtkArgFunc) NULL,
       };
 
-      curve_type = gtk_type_unique (gtk_vbox_get_type (), &curve_info);
+      curve_type = gtk_type_unique (gtk_drawing_area_get_type (), &curve_info);
     }
   return curve_type;
 }
@@ -72,9 +74,16 @@
 {
   GtkObjectClass *object_class;
 
-  parent_class = gtk_type_class (gtk_vbox_get_type ());
+  parent_class = gtk_type_class (gtk_drawing_area_get_type ());
 
   object_class = (GtkObjectClass *) class;
+
+  curve_type_changed_signal =
+    gtk_signal_new ("curve_type_changed", GTK_RUN_FIRST, object_class->type,
+		    GTK_SIGNAL_OFFSET (GtkCurveClass, curve_type_changed),
+		    gtk_signal_default_marshaller, GTK_ARG_NONE, 0);
+  gtk_object_class_add_signals (object_class, &curve_type_changed_signal, 1);
+
   object_class->destroy = gtk_curve_destroy;
 }
 
@@ -82,7 +91,6 @@
 gtk_curve_init (GtkCurve *curve)
 {
   curve->cursor_type = GDK_TOP_LEFT_ARROW;
-  curve->graph = NULL;
   curve->pixmap = NULL;
   curve->curve_type = GTK_CURVE_TYPE_SPLINE;
   curve->height = 0;
@@ -163,157 +171,6 @@
     ((a*a*a - a)*y2[k_lo] + (b*b*b - b)*y2[k_hi]) * (h*h)/6.0;
 }
 
-void
-gtk_curve_set_vector (GtkCurve *c, int veclen, gfloat vector[])
-{
-  gfloat rx, dx, ry;
-  gint i, height;
-
-  c->curve_type = GTK_CURVE_TYPE_FREE;
-
-  if (c->point)
-    height = c->graph->allocation.height - RADIUS * 2;
-  else
-    {
-      height = (c->max_y - c->min_y);
-      if (height > gdk_screen_height () / 4)
-	height = gdk_screen_height () / 4;
-
-      c->height = height;
-      c->num_points = veclen;
-      c->point = g_malloc (c->num_points * sizeof (c->point[0]));
-    }
-  rx = 0;
-  dx = (veclen - 1.0) / (c->num_points - 1.0);
-
-  for (i = 0; i < c->num_points; ++i, rx += dx)
-    {
-      ry = vector[(int) (rx + 0.5)];
-      if (ry > c->max_y) ry = c->max_y;
-      if (ry < c->min_y) ry = c->min_y;
-      c->point[i].x = RADIUS + i;
-      c->point[i].y =
-	RADIUS + height - project (ry, c->min_y, c->max_y, height);
-    }
-}
-
-void
-gtk_curve_get_vector (GtkCurve *c, int veclen, gfloat vector[])
-{
-  gfloat rx, ry, dx, dy, min_x, delta_x, *mem, *xv, *yv, *y2v, prev;
-  gint dst, i, x, next, num_active_ctlpoints = 0, first_active = -1;
-
-  min_x = c->min_x;
-
-  if (c->curve_type != GTK_CURVE_TYPE_FREE)
-    {
-      /* count active points: */
-      prev = min_x - 1.0;
-      for (i = num_active_ctlpoints = 0; i < c->num_ctlpoints; ++i)
-	if (c->ctlpoint[i][0] > prev)
-	  {
-	    if (first_active < 0)
-	      first_active = i;
-	    prev = c->ctlpoint[i][0];
-	    ++num_active_ctlpoints;
-	  }
-
-      /* handle degenerate case: */
-      if (num_active_ctlpoints < 2)
-	{
-	  if (num_active_ctlpoints > 0)
-	    ry = c->ctlpoint[first_active][1];
-	  else
-	    ry = c->min_y;
-	  if (ry < c->min_y) ry = c->min_y;
-	  if (ry > c->max_y) ry = c->max_y;
-	  for (x = 0; x < veclen; ++x)
-	    vector[x] = ry;
-	  return;
-	}
-    }
-
-  switch (c->curve_type)
-    {
-    case GTK_CURVE_TYPE_SPLINE:
-      mem = g_malloc (3 * num_active_ctlpoints * sizeof (gfloat));
-      xv  = mem;
-      yv  = mem + num_active_ctlpoints;
-      y2v = mem + 2*num_active_ctlpoints;
-
-      prev = min_x - 1.0;
-      for (i = dst = 0; i < c->num_ctlpoints; ++i)
-	if (c->ctlpoint[i][0] > prev)
-	  {
-	    prev    = c->ctlpoint[i][0];
-	    xv[dst] = c->ctlpoint[i][0];
-	    yv[dst] = c->ctlpoint[i][1];
-	    ++dst;
-	  }
-
-      spline_solve (num_active_ctlpoints, xv, yv, y2v);
-
-      rx = min_x;
-      dx = (c->max_x - min_x) / (veclen - 1);
-      for (x = 0; x < veclen; ++x, rx += dx)
-	{
-	  ry = spline_eval (num_active_ctlpoints, xv, yv, y2v, rx);
-	  if (ry < c->min_y) ry = c->min_y;
-	  if (ry > c->max_y) ry = c->max_y;
-	  vector[x] = ry;
-	}
-
-      g_free (mem);
-      break;
-
-    case GTK_CURVE_TYPE_LINEAR:
-      dx = (c->max_x - min_x) / (veclen - 1);
-      rx = min_x;
-      ry = c->min_y;
-      dy = 0.0;
-      i  = first_active;
-      for (x = 0; x < veclen; ++x, rx += dx)
-	{
-	  if (rx >= c->ctlpoint[i][0])
-	    {
-	      if (rx > c->ctlpoint[i][0])
-		ry = c->min_y;
-	      dy = 0.0;
-	      next = i + 1;
-	      while (next < c->num_ctlpoints
-		     && c->ctlpoint[next][0] <= c->ctlpoint[i][0])
-		++next;
-	      if (next < c->num_ctlpoints)
-		{
-		  delta_x = c->ctlpoint[next][0] - c->ctlpoint[i][0];
-		  dy = ((c->ctlpoint[next][1] - c->ctlpoint[i][1])
-			/ delta_x);
-		  dy *= dx;
-		  ry = c->ctlpoint[i][1];
-		  i = next;
-		}
-	    }
-	  vector[x] = ry;
-	  ry += dy;
-	}
-      break;
-
-    case GTK_CURVE_TYPE_FREE:
-      if (c->point)
-	{
-	  rx = 0.0;
-	  dx = c->num_points / (double) veclen;
-	  for (x = 0; x < veclen; ++x, rx += dx)
-	    vector[x] = unproject (RADIUS + c->height - c->point[(int) rx].y,
-				   c->min_y, c->max_y,
-				   c->height);
-	}
-      else
-	memset (vector, 0, veclen * sizeof (vector[0]));
-      break;
-    }
-}
-
 static void
 gtk_curve_interpolate (GtkCurve *c, gint width, gint height)
 {
@@ -345,9 +202,10 @@
 gtk_curve_draw (GtkCurve *c, gint width, gint height)
 {
   GtkStateType state;
+  GtkStyle *style;
   gint i;
 
-  if (!c->pixmap || !c->graph)
+  if (!c->pixmap)
     return;
 
   if (c->height != height || c->num_points != width)
@@ -357,23 +215,24 @@
   if (!GTK_WIDGET_IS_SENSITIVE (GTK_WIDGET (c)))
     state = GTK_STATE_INSENSITIVE;
 
+  style = GTK_WIDGET (c)->style;
+
   /* clear the pixmap: */
-  gdk_draw_rectangle (c->pixmap, c->graph->style->bg_gc[state],
-		      TRUE, 0, 0, width + RADIUS * 2, height + RADIUS * 2);
+  gdk_draw_rectangle (c->pixmap, style->bg_gc[state], TRUE,
+		      0, 0, width + RADIUS * 2, height + RADIUS * 2);
 
   /* draw the grid lines: (XXX make more meaningful) */
   for (i = 0; i < 5; i++)
     {
-      gdk_draw_line (c->pixmap, c->graph->style->dark_gc[state],
+      gdk_draw_line (c->pixmap, style->dark_gc[state],
 		     RADIUS, i * (height / 4.0) + RADIUS,
 		     width + RADIUS, i * (height / 4.0) + RADIUS);
-      gdk_draw_line (c->pixmap, c->graph->style->dark_gc[state],
+      gdk_draw_line (c->pixmap, style->dark_gc[state],
 		     i * (width / 4.0) + RADIUS, RADIUS,
 		     i * (width / 4.0) + RADIUS, height + RADIUS);
     }
 
-  gdk_draw_points (c->pixmap, c->graph->style->fg_gc[state],
-		   c->point, c->num_points);
+  gdk_draw_points (c->pixmap, style->fg_gc[state], c->point, c->num_points);
   if (c->curve_type != GTK_CURVE_TYPE_FREE)
     for (i = 0; i < c->num_ctlpoints; ++i)
       {
@@ -389,10 +248,10 @@
 		   height);
 
 	/* draw a bullet: */
-	gdk_draw_arc (c->pixmap, c->graph->style->fg_gc[state], TRUE, x, y,
+	gdk_draw_arc (c->pixmap, style->fg_gc[state], TRUE, x, y,
 		      RADIUS * 2, RADIUS*2, 0, 360*64);
       }
-  gdk_draw_pixmap (c->graph->window, c->graph->style->fg_gc[state], c->pixmap,
+  gdk_draw_pixmap (GTK_WIDGET (c)->window, style->fg_gc[state], c->pixmap,
 		   0, 0, 0, 0, width + RADIUS * 2, height + RADIUS * 2);
 }
 
@@ -403,6 +262,7 @@
   gint i, src, dst, leftbound, rightbound;
   GdkEventButton *bevent;
   GdkEventMotion *mevent;
+  GtkWidget *w;
   gint tx, ty;
   gint cx, x, y, width, height;
   gint closest_point = 0;
@@ -410,11 +270,12 @@
   guint distance;
   gint x1, x2, y1, y2;
 
-  width = c->graph->allocation.width - RADIUS * 2;
-  height = c->graph->allocation.height - RADIUS * 2;
+  w = GTK_WIDGET (c);
+  width = w->allocation.width - RADIUS * 2;
+  height = w->allocation.height - RADIUS * 2;
 
   /*  get the pointer position  */
-  gdk_window_get_pointer (c->graph->window, &tx, &ty, NULL);
+  gdk_window_get_pointer (w->window, &tx, &ty, NULL);
   x = BOUNDS ((tx - RADIUS), 0, width);
   y = BOUNDS ((ty - RADIUS), 0, height);
 
@@ -440,9 +301,9 @@
       /* fall through */
     case GDK_EXPOSE:
       if (!c->pixmap)
-	c->pixmap = gdk_pixmap_new (c->graph->window,
-				    c->graph->allocation.width,
-				    c->graph->allocation.height, -1);
+	c->pixmap = gdk_pixmap_new (w->window,
+				    w->allocation.width,
+				    w->allocation.height, -1);
       gtk_curve_draw (c, width, height);
       break;
 
@@ -625,7 +486,7 @@
 	  c->cursor_type = new_type;
 
 	  cursor = gdk_cursor_new (c->cursor_type);
-	  gdk_window_set_cursor (c->graph->window, cursor);
+	  gdk_window_set_cursor (w->window, cursor);
 	  gdk_cursor_destroy (cursor);
 	}
       break;
@@ -636,29 +497,18 @@
   return FALSE;
 }
 
-static void
-gtk_curve_button_callback (GtkWidget *widget, gpointer data)
+void
+gtk_curve_set_curve_type (GtkCurve *c, GtkCurveType new_type)
 {
-  GtkCurveType new_type;
-  GtkCurve *c = data;
   gfloat rx, dx;
   gint x, i;
 
-  new_type = c->curve_type;
-
-  if (widget == c->linear_button)
-    new_type = GTK_CURVE_TYPE_LINEAR;
-  else if (widget == c->spline_button)
-    new_type = GTK_CURVE_TYPE_SPLINE;
-  else if (widget == c->free_button)
-    new_type = GTK_CURVE_TYPE_FREE;
-
   if (new_type != c->curve_type)
     {
       gint width, height;
 
-      width  = c->graph->allocation.width - RADIUS * 2;
-      height = c->graph->allocation.height - RADIUS * 2;
+      width  = GTK_WIDGET(c)->allocation.width - RADIUS * 2;
+      height = GTK_WIDGET(c)->allocation.height - RADIUS * 2;
 
       if (new_type == GTK_CURVE_TYPE_FREE)
 	{
@@ -692,20 +542,12 @@
 	  c->curve_type = new_type;
 	  gtk_curve_interpolate (c, width, height);
 	}
+      gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
       gtk_curve_draw (c, width, height);
     }
 }
 
 static void
-gtk_curve_reset_callback (GtkWidget *widget, gpointer data)
-{
-  GtkCurve *curve = GTK_CURVE (data);
-
-  curve->curve_type = GTK_CURVE_TYPE_SPLINE;
-  gtk_curve_reset (curve);
-}
-
-static void
 gtk_curve_size_graph (GtkCurve *curve)
 {
   gint width, height;
@@ -724,12 +566,12 @@
   else
     height = width / aspect;
 
-  gtk_drawing_area_size (GTK_DRAWING_AREA (curve->graph),
+  gtk_drawing_area_size (GTK_DRAWING_AREA (curve),
 			 width + RADIUS * 2, height + RADIUS * 2);
 }
 
-void
-gtk_curve_reset (GtkCurve *curve)
+static void
+gtk_curve_reset_vector (GtkCurve *curve)
 {
   if (curve->ctlpoint)
     g_free (curve->ctlpoint);
@@ -745,8 +587,8 @@
     {
       gint width, height;
 
-      width = curve->graph->allocation.width - RADIUS * 2;
-      height = curve->graph->allocation.height - RADIUS * 2;
+      width = GTK_WIDGET (curve)->allocation.width - RADIUS * 2;
+      height = GTK_WIDGET (curve)->allocation.height - RADIUS * 2;
 
       if (curve->curve_type == GTK_CURVE_TYPE_FREE)
 	{
@@ -761,6 +603,52 @@
 }
 
 void
+gtk_curve_reset (GtkCurve *c)
+{
+  GtkCurveType old_type;
+
+  old_type = c->curve_type;
+  c->curve_type = GTK_CURVE_TYPE_SPLINE;
+  gtk_curve_reset_vector (c);
+
+  if (old_type != GTK_CURVE_TYPE_SPLINE)
+    gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
+}
+
+void
+gtk_curve_set_gamma (GtkCurve *c, gfloat gamma)
+{
+  gfloat x, one_over_gamma, height, one_over_width;
+  GtkCurveType old_type;
+  gint i;
+
+  if (c->num_points < 2)
+    return;
+
+  old_type = c->curve_type;
+  c->curve_type = GTK_CURVE_TYPE_FREE;
+
+  if (gamma <= 0)
+    one_over_gamma = 1.0;
+  else
+    one_over_gamma = 1.0 / gamma;
+  one_over_width = 1.0 / (c->num_points - 1);
+  height = c->height;
+  for (i = 0; i < c->num_points; ++i)
+    {
+      x = (gfloat) i / (c->num_points - 1);
+      c->point[i].x = RADIUS + i;
+      c->point[i].y =
+	RADIUS + (height * (1.0 - pow (x, one_over_gamma)) + 0.5);
+    }
+
+  if (old_type != GTK_CURVE_TYPE_FREE)
+    gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
+
+  gtk_curve_draw (c, c->num_points, c->height);
+}
+
+void
 gtk_curve_set_range (GtkCurve *curve,
 		     gfloat min_x, gfloat max_x, gfloat min_y, gfloat max_y)
 {
@@ -770,13 +658,169 @@
   curve->max_y = max_y;
 
   gtk_curve_size_graph (curve);
-  gtk_curve_reset (curve);
+  gtk_curve_reset_vector (curve);
+}
+
+void
+gtk_curve_set_vector (GtkCurve *c, int veclen, gfloat vector[])
+{
+  GtkCurveType old_type;
+  gfloat rx, dx, ry;
+  gint i, height;
+
+  old_type = c->curve_type;
+  c->curve_type = GTK_CURVE_TYPE_FREE;
+
+  if (c->point)
+    height = GTK_WIDGET (c)->allocation.height - RADIUS * 2;
+  else
+    {
+      height = (c->max_y - c->min_y);
+      if (height > gdk_screen_height () / 4)
+	height = gdk_screen_height () / 4;
+
+      c->height = height;
+      c->num_points = veclen;
+      c->point = g_malloc (c->num_points * sizeof (c->point[0]));
+    }
+  rx = 0;
+  dx = (veclen - 1.0) / (c->num_points - 1.0);
+
+  for (i = 0; i < c->num_points; ++i, rx += dx)
+    {
+      ry = vector[(int) (rx + 0.5)];
+      if (ry > c->max_y) ry = c->max_y;
+      if (ry < c->min_y) ry = c->min_y;
+      c->point[i].x = RADIUS + i;
+      c->point[i].y =
+	RADIUS + height - project (ry, c->min_y, c->max_y, height);
+    }
+  if (old_type != GTK_CURVE_TYPE_FREE)
+    gtk_signal_emit (GTK_OBJECT (c), curve_type_changed_signal);
+
+  gtk_curve_draw (c, c->num_points, height);
+}
+
+void
+gtk_curve_get_vector (GtkCurve *c, int veclen, gfloat vector[])
+{
+  gfloat rx, ry, dx, dy, min_x, delta_x, *mem, *xv, *yv, *y2v, prev;
+  gint dst, i, x, next, num_active_ctlpoints = 0, first_active = -1;
+
+  min_x = c->min_x;
+
+  if (c->curve_type != GTK_CURVE_TYPE_FREE)
+    {
+      /* count active points: */
+      prev = min_x - 1.0;
+      for (i = num_active_ctlpoints = 0; i < c->num_ctlpoints; ++i)
+	if (c->ctlpoint[i][0] > prev)
+	  {
+	    if (first_active < 0)
+	      first_active = i;
+	    prev = c->ctlpoint[i][0];
+	    ++num_active_ctlpoints;
+	  }
+
+      /* handle degenerate case: */
+      if (num_active_ctlpoints < 2)
+	{
+	  if (num_active_ctlpoints > 0)
+	    ry = c->ctlpoint[first_active][1];
+	  else
+	    ry = c->min_y;
+	  if (ry < c->min_y) ry = c->min_y;
+	  if (ry > c->max_y) ry = c->max_y;
+	  for (x = 0; x < veclen; ++x)
+	    vector[x] = ry;
+	  return;
+	}
+    }
+
+  switch (c->curve_type)
+    {
+    case GTK_CURVE_TYPE_SPLINE:
+      mem = g_malloc (3 * num_active_ctlpoints * sizeof (gfloat));
+      xv  = mem;
+      yv  = mem + num_active_ctlpoints;
+      y2v = mem + 2*num_active_ctlpoints;
+
+      prev = min_x - 1.0;
+      for (i = dst = 0; i < c->num_ctlpoints; ++i)
+	if (c->ctlpoint[i][0] > prev)
+	  {
+	    prev    = c->ctlpoint[i][0];
+	    xv[dst] = c->ctlpoint[i][0];
+	    yv[dst] = c->ctlpoint[i][1];
+	    ++dst;
+	  }
+
+      spline_solve (num_active_ctlpoints, xv, yv, y2v);
+
+      rx = min_x;
+      dx = (c->max_x - min_x) / (veclen - 1);
+      for (x = 0; x < veclen; ++x, rx += dx)
+	{
+	  ry = spline_eval (num_active_ctlpoints, xv, yv, y2v, rx);
+	  if (ry < c->min_y) ry = c->min_y;
+	  if (ry > c->max_y) ry = c->max_y;
+	  vector[x] = ry;
+	}
+
+      g_free (mem);
+      break;
+
+    case GTK_CURVE_TYPE_LINEAR:
+      dx = (c->max_x - min_x) / (veclen - 1);
+      rx = min_x;
+      ry = c->min_y;
+      dy = 0.0;
+      i  = first_active;
+      for (x = 0; x < veclen; ++x, rx += dx)
+	{
+	  if (rx >= c->ctlpoint[i][0])
+	    {
+	      if (rx > c->ctlpoint[i][0])
+		ry = c->min_y;
+	      dy = 0.0;
+	      next = i + 1;
+	      while (next < c->num_ctlpoints
+		     && c->ctlpoint[next][0] <= c->ctlpoint[i][0])
+		++next;
+	      if (next < c->num_ctlpoints)
+		{
+		  delta_x = c->ctlpoint[next][0] - c->ctlpoint[i][0];
+		  dy = ((c->ctlpoint[next][1] - c->ctlpoint[i][1])
+			/ delta_x);
+		  dy *= dx;
+		  ry = c->ctlpoint[i][1];
+		  i = next;
+		}
+	    }
+	  vector[x] = ry;
+	  ry += dy;
+	}
+      break;
+
+    case GTK_CURVE_TYPE_FREE:
+      if (c->point)
+	{
+	  rx = 0.0;
+	  dx = c->num_points / (double) veclen;
+	  for (x = 0; x < veclen; ++x, rx += dx)
+	    vector[x] = unproject (RADIUS + c->height - c->point[(int) rx].y,
+				   c->min_y, c->max_y,
+				   c->height);
+	}
+      else
+	memset (vector, 0, veclen * sizeof (vector[0]));
+      break;
+    }
 }
 
 GtkWidget*
 gtk_curve_new (void)
 {
-  GtkWidget *table, *vbox, *button;
   GtkCurve *curve;
   gint old_mask;
 
@@ -786,51 +830,12 @@
   curve->min_y = 0.0;
   curve->max_y = 1.0;
 
-  table = gtk_table_new (1, 2, FALSE);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 3);
-  gtk_container_add (GTK_CONTAINER (curve), table);
-
-  curve->graph = gtk_drawing_area_new ();
-  old_mask = gtk_widget_get_events (curve->graph);
-  gtk_widget_set_events (curve->graph, old_mask | GRAPH_MASK);
-  gtk_table_attach_defaults (GTK_TABLE (table), curve->graph, 0, 1, 0, 1);
-
-  gtk_signal_connect (GTK_OBJECT (curve->graph), "event",
+  old_mask = gtk_widget_get_events (GTK_WIDGET (curve));
+  gtk_widget_set_events (GTK_WIDGET (curve), old_mask | GRAPH_MASK);
+  gtk_signal_connect (GTK_OBJECT (curve), "event",
 		      (GtkSignalFunc) gtk_curve_graph_events, curve);
-
-  vbox = gtk_vbox_new (/* homogeneous */ FALSE, /* spacing */ 3);
-  gtk_table_attach (GTK_TABLE (table), vbox, 1, 2, 0, 1, 0, 0, 0, 0);
-
-  curve->linear_button = gtk_button_new_with_label ("linear");
-  gtk_container_add (GTK_CONTAINER (vbox), curve->linear_button);
-  gtk_signal_connect (GTK_OBJECT (curve->linear_button), "clicked",
-		      (GtkSignalFunc) gtk_curve_button_callback, curve);
-
-  curve->spline_button = gtk_button_new_with_label ("spline");
-  gtk_container_add (GTK_CONTAINER (vbox), curve->spline_button);
-  gtk_signal_connect (GTK_OBJECT (curve->spline_button), "clicked",
-		      (GtkSignalFunc) gtk_curve_button_callback, curve);
-
-  curve->free_button = gtk_button_new_with_label ("free");
-  gtk_container_add (GTK_CONTAINER (vbox), curve->free_button);
-  gtk_signal_connect (GTK_OBJECT (curve->free_button), "clicked",
-		      (GtkSignalFunc) gtk_curve_button_callback, curve);
-
-  button = gtk_button_new_with_label ("reset");
-  gtk_container_add (GTK_CONTAINER (vbox), button);
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_curve_reset_callback, curve);
-
   gtk_curve_size_graph (curve);
 
-  gtk_widget_show (button);
-  gtk_widget_show (curve->free_button);
-  gtk_widget_show (curve->spline_button);
-  gtk_widget_show (curve->linear_button);
-  gtk_widget_show (vbox);
-  gtk_widget_show (curve->graph);
-  gtk_widget_show (table);
-
   return GTK_WIDGET (curve);
 }
 
@@ -851,5 +856,5 @@
     g_free (curve->ctlpoint);
 
   if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 }
diff -urN gimp-0.99.10/gtk+/gtk/gtkcurve.h gimp-0.99.10-davidm/gtk+/gtk/gtkcurve.h
--- gimp-0.99.10/gtk+/gtk/gtkcurve.h	Tue Jun  3 17:38:45 1997
+++ gimp-0.99.10-davidm/gtk+/gtk/gtkcurve.h	Sun Jun  8 20:47:43 1997
@@ -20,7 +20,7 @@
 
 
 #include <gdk/gdk.h>
-#include <gtk/gtkvbox.h>
+#include <gtk/gtkdrawingarea.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -44,11 +44,7 @@
 
 struct _GtkCurve
   {
-    GtkVBox vbox;
-    GtkWidget *graph;		/* drawing-area */
-    GtkWidget *linear_button;
-    GtkWidget *spline_button;
-    GtkWidget *free_button;
+    GtkDrawingArea graph;
 
     gint cursor_type;
     gfloat min_x;
@@ -72,13 +68,16 @@
 
 struct _GtkCurveClass
   {
-    GtkVBoxClass parent_class;
+    GtkDrawingAreaClass parent_class;
+
+    void (* curve_type_changed) (GtkCurve *curve);
   };
 
 
 guint		gtk_curve_get_type	(void);
 GtkWidget*	gtk_curve_new		(void);
 void		gtk_curve_reset		(GtkCurve *curve);
+void		gtk_curve_set_gamma	(GtkCurve *curve, gfloat gamma);
 void		gtk_curve_set_range	(GtkCurve *curve,
 					 gfloat min_x, gfloat max_x,
 					 gfloat min_y, gfloat max_y);
@@ -86,6 +85,8 @@
 					 int veclen, gfloat vector[]);
 void		gtk_curve_set_vector	(GtkCurve *curve,
 					 int veclen, gfloat vector[]);
+void		gtk_curve_set_curve_type (GtkCurve *curve, GtkCurveType type);
+					  
 
 #ifdef __cplusplus
 }
diff -urN gimp-0.99.10/gtk+/gtk/gtkgamma.c gimp-0.99.10-davidm/gtk+/gtk/gtkgamma.c
--- gimp-0.99.10/gtk+/gtk/gtkgamma.c	Wed Dec 31 17:00:00 1969
+++ gimp-0.99.10-davidm/gtk+/gtk/gtkgamma.c	Sun Jun  8 20:47:14 1997
@@ -0,0 +1,464 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1997 David Mosberger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "gtkgamma.h"
+#include "gtkcurve.h"
+#include "gtkdialog.h"
+#include "gtkdrawingarea.h"
+#include "gtkentry.h"
+#include "gtkhbox.h"
+#include "gtklabel.h"
+#include "gtkmain.h"
+#include "gtkpixmap.h"
+#include "gtkradiobutton.h"
+#include "gtksignal.h"
+#include "gtktable.h"
+#include "gtkvbox.h"
+#include "gtkwindow.h"
+
+static GtkVBoxClass *parent_class = NULL;
+
+
+/* forward declarations: */
+static void gtk_gamma_curve_class_init (GtkGammaCurveClass *class);
+static void gtk_gamma_curve_init (GtkGammaCurve *curve);
+static void gtk_gamma_curve_destroy (GtkObject *object);
+
+enum
+  {
+    LINEAR = 0,
+    SPLINE,
+    FREE,
+    GAMMA,
+    RESET,
+    NUM_XPMS
+  };
+
+static char *xpm[][27] =
+  {
+    /* spline: */
+    {
+      /* width height ncolors chars_per_pixel */
+      "16 16 4 1",
+      /* colors */
+      "` c #000000",
+      "a c #BC2D2D",
+      "b c #FF0000",
+      "c c #D3D3D3",
+      /* pixels */
+      "cccccccccccccc``",
+      "cccccccccbbbbbb`",
+      "cccccccbbccccccc",
+      "ccccc`accccccccc",
+      "cccc```ccccccccc",
+      "cccca`cccccccccc",
+      "ccccbccccccccccc",
+      "cccbcccccccccccc",
+      "cccbcccccccccccc",
+      "ccbccccccccccccc",
+      "ccbccccccccccccc",
+      "cbcccccccccccccc",
+      "cbcccccccccccccc",
+      "cbcccccccccccccc",
+      "`acccccccccccccc",
+      "``cccccccccccccc"
+    },
+    /* linear: */
+    {
+      /* width height ncolors chars_per_pixel */
+      "16 16 5 1",
+      /* colors */
+      ".", /* transparent */
+      "B c #000000",
+      "' c #7F7F7F",
+      "+ c #824141",
+      "r c #FF0000",
+      /* pixels */
+      "..............BB",
+      "..............+B",
+      "..............r.",
+      ".............r..",
+      ".............r..",
+      "....'B'.....r...",
+      "....BBB.....r...",
+      "....+B+....r....",
+      "....r.r....r....",
+      "...r...r..r.....",
+      "...r...r..r.....",
+      "..r.....rB+.....",
+      "..r.....BBB.....",
+      ".r......'B'.....",
+      "B+..............",
+      "BB.............."
+    },
+    /* free: */
+    {
+      /* width height ncolors chars_per_pixel */
+      "16 16 2 1",
+      /* colors */
+      "` c #FF0000",
+      "a c #D3D3D3",
+      /* pixels */
+      "aaaaaaaaaaaaaaaa",
+      "aaaaaaaaaaaaaaaa",
+      "aaaaaa`aaaaaaaaa",
+      "aaaaaa`aaaaaaaaa",
+      "aaaaaaa`aaaaaaaa",
+      "aaaaaaa`aaaaaaaa",
+      "aaaaaaa`aaaaaaaa",
+      "aaaaaaaa`aaaaaaa",
+      "aaaaaaaa`aaaaaaa",
+      "aaaaaaaa`aaaaaaa",
+      "aaaaa`aaa`a`````",
+      "aaaa`aaaa`aaaaaa",
+      "aaa`aaaaa`aaaaaa",
+      "aa`aaaaaaa`aaaaa",
+      "a`aaaaaaaa`aaaaa",
+      "`aaaaaaaaaaaaaaa"
+    },
+    /* gamma: */
+    {
+      /* width height ncolors chars_per_pixel */
+      "16 16 10 1",
+      /* colors */
+      "` c #000000",
+      "a c #757575",
+      "b c #2F2F2F",
+      "c c #171717",
+      "d c #A4A4A4",
+      "e c #8C8C8C",
+      "f c #5E5E5E",
+      "g c #464646",
+      "h c #D3D3D3",
+      "i c #BBBBBB",
+      /* pixels */
+      "hhhhhhhhhhhhhhhh",
+      "hhhhhhhhhhhhhhhh",
+      "hhhhhhhhhhhhhhhh",
+      "hhhh`fhhe`ehhhhh",
+      "hhhhgcihacdhhhhh",
+      "hhhhhaehgghhhhhh",
+      "hhhhhh`h`ehhhhhh",
+      "hhhhhhghghhhhhhh",
+      "hhhhhhgcehhhhhhh",
+      "hhhhhhd`hhhhhhhh",
+      "hhhhhhafhhhhhhhh",
+      "hhhhhhb`hhhhhhhh",
+      "hhhhhh``hhhhhhhh",
+      "hhhhhh`bhhhhhhhh",
+      "hhhhhhhhhhhhhhhh",
+      "hhhhhhhhhhhhhhhh"
+    },
+    /* reset: */
+    {
+      /* width height ncolors chars_per_pixel */
+      "16 16 4 1",
+      /* colors */
+      "` c #000000",
+      "a c #824141",
+      "b c #FF0000",
+      "c c #D3D3D3",
+      /* pixels */
+      "cccccccccccccc``",
+      "cccccccccccccca`",
+      "cccccccccccccbcc",
+      "ccccccccccccbccc",
+      "cccccccccccbcccc",
+      "ccccccccccbccccc",
+      "cccccccccbcccccc",
+      "ccccccccbccccccc",
+      "cccccccbcccccccc",
+      "ccccccbccccccccc",
+      "cccccbcccccccccc",
+      "ccccbccccccccccc",
+      "cccbcccccccccccc",
+      "ccbccccccccccccc",
+      "`acccccccccccccc",
+      "``cccccccccccccc"
+    }
+  };
+
+guint
+gtk_gamma_curve_get_type (void)
+{
+  static guint gamma_curve_type = 0;
+
+  if (!gamma_curve_type)
+    {
+      GtkTypeInfo gamma_curve_info =
+      {
+	"GtkGammaCurve",
+	sizeof (GtkGammaCurve),
+	sizeof (GtkGammaCurveClass),
+	(GtkClassInitFunc) gtk_gamma_curve_class_init,
+	(GtkObjectInitFunc) gtk_gamma_curve_init,
+	(GtkArgFunc) NULL,
+      };
+
+      gamma_curve_type =
+	gtk_type_unique (gtk_vbox_get_type (), &gamma_curve_info);
+    }
+  return gamma_curve_type;
+}
+
+static void
+gtk_gamma_curve_class_init (GtkGammaCurveClass *class)
+{
+  GtkObjectClass *object_class;
+
+  parent_class = gtk_type_class (gtk_vbox_get_type ());
+
+  object_class = (GtkObjectClass *) class;
+  object_class->destroy = gtk_gamma_curve_destroy;
+}
+
+static void
+gtk_gamma_curve_init (GtkGammaCurve *curve)
+{
+  curve->gamma = 1.0;
+}
+
+static void
+button_realize_callback (GtkWidget *w)
+{
+  GtkWidget *pixmap;
+  GdkBitmap *mask;
+  GdkPixmap *pm;
+  int i;
+
+  i = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
+  pm = gdk_pixmap_create_from_xpm_d (w->window, &mask,
+				     &w->style->bg[GTK_STATE_NORMAL], xpm[i]);
+
+  pixmap = gtk_pixmap_new (pm, 0 /*mask*/); /* why does this not work??? */
+  gtk_container_add (GTK_CONTAINER (w), pixmap);
+  gtk_widget_show (pixmap);
+
+  gdk_pixmap_destroy (pm);
+  gdk_pixmap_destroy (mask);	/* a bitmap is really just a special pixmap */
+}
+
+static void
+button_toggled_callback (GtkWidget *w, gpointer data)
+{
+  GtkGammaCurve *c = data;
+  GtkCurveType type;
+  int active, i;
+
+  if (!GTK_TOGGLE_BUTTON (w)->active)
+    return;
+
+  active = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
+
+  for (i = 0; i < 3; ++i)
+    if ((i != active) && GTK_TOGGLE_BUTTON (c->button[i])->active)
+      break;
+
+  if (i < 3)
+    gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (c->button[i]), FALSE);
+
+  switch (active)
+    {
+    case 0:  type = GTK_CURVE_TYPE_SPLINE; break;
+    case 1:  type = GTK_CURVE_TYPE_LINEAR; break;
+    default: type = GTK_CURVE_TYPE_FREE; break;
+    }
+  gtk_curve_set_curve_type (GTK_CURVE (c->curve), type);
+}
+
+static void
+gamma_cancel_callback (GtkWidget *w, gpointer data)
+{
+  GtkGammaCurve *c = data;
+
+  gtk_widget_destroy (c->gamma_dialog);
+  c->gamma_dialog = 0;
+}
+
+static void
+gamma_ok_callback (GtkWidget *w, gpointer data)
+{
+  GtkGammaCurve *c = data;
+  gchar *start, *end;
+  gfloat v;
+
+  start = gtk_entry_get_text (GTK_ENTRY (c->gamma_text));
+  if (start)
+    {
+      v = strtod (start, &end);
+      if (end > start && v > 0.0)
+	c->gamma = v;
+    }
+  gtk_curve_set_gamma (GTK_CURVE (c->curve), c->gamma);
+  gamma_cancel_callback (w, data);
+}
+
+static void
+button_clicked_callback (GtkWidget *w, gpointer data)
+{
+  GtkGammaCurve *c = data;
+  int active;
+
+  active = (long) gtk_object_get_data (GTK_OBJECT (w), "_GtkGammaCurveIndex");
+  if (active == 3)
+    /* set gamma */
+    if (c->gamma_dialog)
+      return;
+    else
+      {
+	GtkWidget *vbox, *hbox, *label, *button;
+	gchar buf[64];
+
+	c->gamma_dialog = gtk_dialog_new ();
+	gtk_window_set_title (GTK_WINDOW (c->gamma_dialog), "Gamma");
+	vbox = GTK_DIALOG (c->gamma_dialog)->vbox;
+
+	hbox = gtk_hbox_new (/* homogeneous */ FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 2);
+	gtk_widget_show (hbox);
+
+	label = gtk_label_new ("Gamma value");
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
+	gtk_widget_show (label);
+
+	sprintf (buf, "%g", c->gamma);
+	c->gamma_text = gtk_entry_new ();
+	gtk_entry_set_text (GTK_ENTRY (c->gamma_text), buf);
+	gtk_box_pack_start (GTK_BOX (hbox), c->gamma_text, TRUE, TRUE, 2);
+	gtk_widget_show (c->gamma_text);
+
+	/* fill in action area: */
+	hbox = GTK_DIALOG (c->gamma_dialog)->action_area;
+
+	button = gtk_button_new_with_label ("OK");
+	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+	gtk_signal_connect (GTK_OBJECT (button), "clicked",
+			    (GtkSignalFunc) gamma_ok_callback, c);
+	gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+	gtk_widget_grab_default (button);
+	gtk_widget_show (button);
+
+	button = gtk_button_new_with_label ("Cancel");
+	gtk_signal_connect (GTK_OBJECT (button), "clicked",
+			    (GtkSignalFunc) gamma_cancel_callback, c);
+	gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
+	gtk_widget_show (button);
+
+	gtk_widget_show (c->gamma_dialog);
+      }
+  else
+    /* reset */
+    gtk_curve_reset (GTK_CURVE (c->curve));
+}
+
+static void
+curve_type_changed_callback (GtkWidget *w, gpointer data)
+{
+  GtkGammaCurve *c = data;
+  GtkCurveType new_type;
+  int active;
+
+  new_type = GTK_CURVE (w)->curve_type;
+  switch (new_type)
+    {
+    case GTK_CURVE_TYPE_SPLINE: active = 0; break;
+    case GTK_CURVE_TYPE_LINEAR: active = 1; break;
+    default:		        active = 2; break;
+    }
+  if (!GTK_TOGGLE_BUTTON (c->button[active])->active)
+    gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (c->button[active]), TRUE);
+}
+
+GtkWidget*
+gtk_gamma_curve_new (void)
+{
+  GtkGammaCurve *c;
+  GtkWidget *vbox;
+  int i;
+
+  c = gtk_type_new (gtk_gamma_curve_get_type ());
+
+  c->table = gtk_table_new (1, 2, FALSE);
+  gtk_table_set_col_spacings (GTK_TABLE (c->table), 3);
+  gtk_container_add (GTK_CONTAINER (c), c->table);
+
+  c->curve = gtk_curve_new ();
+  gtk_signal_connect (GTK_OBJECT (c->curve), "curve_type_changed",
+		      (GtkSignalFunc) curve_type_changed_callback, c);
+  gtk_table_attach_defaults (GTK_TABLE (c->table), c->curve, 0, 1, 0, 1);
+
+  vbox = gtk_vbox_new (/* homogeneous */ FALSE, /* spacing */ 3);
+  gtk_table_attach (GTK_TABLE (c->table), vbox, 1, 2, 0, 1, 0, 0, 0, 0);
+
+  /* toggle buttons: */
+  for (i = 0; i < 3; ++i)
+    {
+      c->button[i] = gtk_toggle_button_new ();
+      gtk_object_set_data (GTK_OBJECT (c->button[i]), "_GtkGammaCurveIndex",
+			   (gpointer) (long) i);
+      gtk_container_add (GTK_CONTAINER (vbox), c->button[i]);
+      gtk_signal_connect (GTK_OBJECT (c->button[i]), "realize",
+			  (GtkSignalFunc) button_realize_callback, 0);
+      gtk_signal_connect (GTK_OBJECT (c->button[i]), "toggled",
+			  (GtkSignalFunc) button_toggled_callback, c);
+      gtk_widget_show (c->button[i]);
+    }
+
+  /* push buttons: */
+  for (i = 3; i < 5; ++i)
+    {
+      c->button[i] = gtk_button_new ();
+      gtk_object_set_data (GTK_OBJECT (c->button[i]), "_GtkGammaCurveIndex",
+			   (gpointer) (long) i);
+      gtk_container_add (GTK_CONTAINER (vbox), c->button[i]);
+      gtk_signal_connect (GTK_OBJECT (c->button[i]), "realize",
+			  (GtkSignalFunc) button_realize_callback, 0);
+      gtk_signal_connect (GTK_OBJECT (c->button[i]), "clicked",
+			  (GtkSignalFunc) button_clicked_callback, c);
+      gtk_widget_show (c->button[i]);
+    }
+
+  gtk_widget_show (vbox);
+  gtk_widget_show (c->table);
+  gtk_widget_show (c->curve);
+
+  return GTK_WIDGET (c);
+}
+
+static void
+gtk_gamma_curve_destroy (GtkObject *object)
+{
+  GtkGammaCurve *c;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_GAMMA_CURVE (object));
+
+  c = GTK_GAMMA_CURVE (object);
+
+  if (c->gamma_dialog)
+    {
+      gtk_widget_destroy (c->gamma_dialog);
+      c->gamma_dialog = 0;
+    }
+
+  if (GTK_OBJECT_CLASS (parent_class)->destroy)
+    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
diff -urN gimp-0.99.10/gtk+/gtk/gtkgamma.h gimp-0.99.10-davidm/gtk+/gtk/gtkgamma.h
--- gimp-0.99.10/gtk+/gtk/gtkgamma.h	Wed Dec 31 17:00:00 1969
+++ gimp-0.99.10-davidm/gtk+/gtk/gtkgamma.h	Sun Jun  8 20:35:11 1997
@@ -0,0 +1,67 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1997 David Mosberger
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_GAMMA_CURVE_H__
+#define __GTK_GAMMA_CURVE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkvbox.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_GAMMA_CURVE(obj) \
+   GTK_CHECK_CAST (obj, gtk_gamma_curve_get_type (), GtkGammaCurve)
+#define GTK_GAMMA_CURVE_CLASS(klass) \
+   GTK_CHECK_CLASS_CAST (klass, gtk_gamma_curve_get_type, GtkGammaCurveClass)
+#define GTK_IS_GAMMA_CURVE(obj) \
+   GTK_CHECK_TYPE (obj, gtk_gamma_curve_get_type ())
+
+typedef struct _GtkGammaCurve		GtkGammaCurve;
+typedef struct _GtkGammaCurveClass	GtkGammaCurveClass;
+
+struct _GtkGammaCurve
+  {
+    GtkVBox vbox;
+
+    GtkWidget *table;
+    GtkWidget *curve;
+    GtkWidget *button[5];	/* spline, linear, free, gamma, reset */
+
+    gfloat gamma;
+    GtkWidget *gamma_dialog;
+    GtkWidget *gamma_text;
+  };
+
+struct _GtkGammaCurveClass
+  {
+    GtkVBoxClass parent_class;
+  };
+
+
+guint		gtk_gamma_curve_get_type	(void);
+GtkWidget*	gtk_gamma_curve_new		(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_GAMMA_CURVE_H__ */
diff -urN gimp-0.99.10/gtk+/gtk/testgtk.c gimp-0.99.10-davidm/gtk+/gtk/testgtk.c
--- gimp-0.99.10/gtk+/gtk/testgtk.c	Fri Jun  6 00:01:44 1997
+++ gimp-0.99.10-davidm/gtk+/gtk/testgtk.c	Sun Jun  8 21:19:14 1997
@@ -1816,37 +1816,33 @@
 
 
 void
-create_curve ()
+create_gamma_curve ()
 {
-  static GtkWidget *window = NULL;
+  static GtkWidget *window = NULL, *curve;
   static int count = 0;
-  GtkWidget *curve;
+  gfloat vec[256];
+  gint max;
+  gint i;
 
   if (!window)
     {
-      gint max;
-
       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
       gtk_window_set_title (GTK_WINDOW (window), "test");
       gtk_container_border_width (GTK_CONTAINER (window), 10);
 
-      max = 127 + (count % 2)*128;
-
-      curve = gtk_curve_new ();
-      gtk_curve_set_range (GTK_CURVE (curve), 0, max, 0, max);
+      curve = gtk_gamma_curve_new ();
       gtk_container_add (GTK_CONTAINER (window), curve);
       gtk_widget_show (curve);
-
-      {
-	gfloat vec[256];
-	gint i;
-
-	for (i = 0; i < max; ++i)
-	  vec[i] = (max / sqrt (max)) * sqrt (i);
-	gtk_curve_set_vector (GTK_CURVE (curve), max, vec);
-      }
     }
 
+  max = 127 + (count % 2)*128;
+  gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
+		       0, max, 0, max);
+  for (i = 0; i < max; ++i)
+    vec[i] = (127 / sqrt (max)) * sqrt (i);
+  gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
+			max, vec);
+
   if (!GTK_WIDGET_VISIBLE (window))
     gtk_widget_show (window);
   else if (count % 4 == 3)
@@ -2122,7 +2118,7 @@
       { "progress bar", create_progress_bar },
       { "preview color", create_color_preview },
       { "preview gray", create_gray_preview },
-      { "curve", create_curve },
+      { "gamma curve", create_gamma_curve },
       { "test timeout", create_timeout_test },
       { "test idle", create_idle_test },
       { "test", create_test },
diff -urN gimp-0.99.10/gtk+/gtk/testgtkrc gimp-0.99.10-davidm/gtk+/gtk/testgtkrc
--- gimp-0.99.10/gtk+/gtk/testgtkrc	Fri Jun  6 00:01:43 1997
+++ gimp-0.99.10-davidm/gtk+/gtk/testgtkrc	Sun Jun  8 18:39:43 1997
@@ -49,6 +49,11 @@
   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
 }
 
+style "curve"
+{
+  fg[NORMAL] = { 58000, 0, 0 }			# red
+}
+
 # pixmap_path "~/.pixmaps"
 widget_class "GtkWindow" style "window"
 widget_class "GtkDialog" style "window"
@@ -60,3 +65,4 @@
 widget_class "*Ruler" style "ruler"
 widget_class "*GtkText" style "text"
 widget "main window.*GtkButton*" style "main_button"
+widget "*GtkCurve" style "curve"
diff -urN gimp-0.99.10/gtk+/gtk/testgtkrc gimp-0.99.10-davidm/gtk+/gtk/testgtkrc
--- gimp-0.99.10/gtk+/gtk/testgtkrc	Fri Jun  6 00:01:43 1997
+++ gimp-0.99.10-davidm/gtk+/gtk/testgtkrc	Sun Jun  8 18:39:43 1997
@@ -49,6 +49,11 @@
   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
 }
 
+style "curve"
+{
+  fg[NORMAL] = { 58000, 0, 0 }			# red
+}
+
 # pixmap_path "~/.pixmaps"
 widget_class "GtkWindow" style "window"
 widget_class "GtkDialog" style "window"
@@ -60,3 +65,4 @@
 widget_class "*Ruler" style "ruler"
 widget_class "*GtkText" style "text"
 widget "main window.*GtkButton*" style "main_button"
+widget "*GtkCurve" style "curve"



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