]> Pileus Git - ~andy/gtk/commitdiff
Minor fixes that were needed for the Gimp/GdkRgb integration.
authorRaph Levien <raph@src.gnome.org>
Thu, 20 Aug 1998 06:52:52 +0000 (06:52 +0000)
committerRaph Levien <raph@src.gnome.org>
Thu, 20 Aug 1998 06:52:52 +0000 (06:52 +0000)
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/gdkrgb.c
gtk/gtkpreview.c
gtk/gtkpreview.h

index 39c307eeee89e656569022a9ddf4cb7178132669..0691ca573b4e32f81ebcfb3f13b78be14e7dfca3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+1998-08-19  Raph Levien  <raph@gimp.org>
+
+       * gdk/gdkrgb.c: fixed some bugs in the 565_d mode, and added a
+       4bpp static_color mode (for vga displays). Also fixed a '64' value
+       in the dither matrix, which was causing one pixel out of 16k to be
+       dithered wrong.
+
+       * gtk/gtkpreview.{c,h}: Changed it to work with GdkRgb, gutting
+       most of the contents. This is an API change - any apps that relied
+       on the internal structure of GtkPreview will need some change -
+       most notably in the use of reserved colors. The Gimp needed
+       changes in this regard.
+
 Wed Aug 19 00:11:14 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkmain.c (gtk_init): allow argument parsing in gtk without
index 39c307eeee89e656569022a9ddf4cb7178132669..0691ca573b4e32f81ebcfb3f13b78be14e7dfca3 100644 (file)
@@ -1,3 +1,16 @@
+1998-08-19  Raph Levien  <raph@gimp.org>
+
+       * gdk/gdkrgb.c: fixed some bugs in the 565_d mode, and added a
+       4bpp static_color mode (for vga displays). Also fixed a '64' value
+       in the dither matrix, which was causing one pixel out of 16k to be
+       dithered wrong.
+
+       * gtk/gtkpreview.{c,h}: Changed it to work with GdkRgb, gutting
+       most of the contents. This is an API change - any apps that relied
+       on the internal structure of GtkPreview will need some change -
+       most notably in the use of reserved colors. The Gimp needed
+       changes in this regard.
+
 Wed Aug 19 00:11:14 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkmain.c (gtk_init): allow argument parsing in gtk without
index 39c307eeee89e656569022a9ddf4cb7178132669..0691ca573b4e32f81ebcfb3f13b78be14e7dfca3 100644 (file)
@@ -1,3 +1,16 @@
+1998-08-19  Raph Levien  <raph@gimp.org>
+
+       * gdk/gdkrgb.c: fixed some bugs in the 565_d mode, and added a
+       4bpp static_color mode (for vga displays). Also fixed a '64' value
+       in the dither matrix, which was causing one pixel out of 16k to be
+       dithered wrong.
+
+       * gtk/gtkpreview.{c,h}: Changed it to work with GdkRgb, gutting
+       most of the contents. This is an API change - any apps that relied
+       on the internal structure of GtkPreview will need some change -
+       most notably in the use of reserved colors. The Gimp needed
+       changes in this regard.
+
 Wed Aug 19 00:11:14 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkmain.c (gtk_init): allow argument parsing in gtk without
index 39c307eeee89e656569022a9ddf4cb7178132669..0691ca573b4e32f81ebcfb3f13b78be14e7dfca3 100644 (file)
@@ -1,3 +1,16 @@
+1998-08-19  Raph Levien  <raph@gimp.org>
+
+       * gdk/gdkrgb.c: fixed some bugs in the 565_d mode, and added a
+       4bpp static_color mode (for vga displays). Also fixed a '64' value
+       in the dither matrix, which was causing one pixel out of 16k to be
+       dithered wrong.
+
+       * gtk/gtkpreview.{c,h}: Changed it to work with GdkRgb, gutting
+       most of the contents. This is an API change - any apps that relied
+       on the internal structure of GtkPreview will need some change -
+       most notably in the use of reserved colors. The Gimp needed
+       changes in this regard.
+
 Wed Aug 19 00:11:14 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkmain.c (gtk_init): allow argument parsing in gtk without
index 39c307eeee89e656569022a9ddf4cb7178132669..0691ca573b4e32f81ebcfb3f13b78be14e7dfca3 100644 (file)
@@ -1,3 +1,16 @@
+1998-08-19  Raph Levien  <raph@gimp.org>
+
+       * gdk/gdkrgb.c: fixed some bugs in the 565_d mode, and added a
+       4bpp static_color mode (for vga displays). Also fixed a '64' value
+       in the dither matrix, which was causing one pixel out of 16k to be
+       dithered wrong.
+
+       * gtk/gtkpreview.{c,h}: Changed it to work with GdkRgb, gutting
+       most of the contents. This is an API change - any apps that relied
+       on the internal structure of GtkPreview will need some change -
+       most notably in the use of reserved colors. The Gimp needed
+       changes in this regard.
+
 Wed Aug 19 00:11:14 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkmain.c (gtk_init): allow argument parsing in gtk without
index 39c307eeee89e656569022a9ddf4cb7178132669..0691ca573b4e32f81ebcfb3f13b78be14e7dfca3 100644 (file)
@@ -1,3 +1,16 @@
+1998-08-19  Raph Levien  <raph@gimp.org>
+
+       * gdk/gdkrgb.c: fixed some bugs in the 565_d mode, and added a
+       4bpp static_color mode (for vga displays). Also fixed a '64' value
+       in the dither matrix, which was causing one pixel out of 16k to be
+       dithered wrong.
+
+       * gtk/gtkpreview.{c,h}: Changed it to work with GdkRgb, gutting
+       most of the contents. This is an API change - any apps that relied
+       on the internal structure of GtkPreview will need some change -
+       most notably in the use of reserved colors. The Gimp needed
+       changes in this regard.
+
 Wed Aug 19 00:11:14 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkmain.c (gtk_init): allow argument parsing in gtk without
index 39c307eeee89e656569022a9ddf4cb7178132669..0691ca573b4e32f81ebcfb3f13b78be14e7dfca3 100644 (file)
@@ -1,3 +1,16 @@
+1998-08-19  Raph Levien  <raph@gimp.org>
+
+       * gdk/gdkrgb.c: fixed some bugs in the 565_d mode, and added a
+       4bpp static_color mode (for vga displays). Also fixed a '64' value
+       in the dither matrix, which was causing one pixel out of 16k to be
+       dithered wrong.
+
+       * gtk/gtkpreview.{c,h}: Changed it to work with GdkRgb, gutting
+       most of the contents. This is an API change - any apps that relied
+       on the internal structure of GtkPreview will need some change -
+       most notably in the use of reserved colors. The Gimp needed
+       changes in this regard.
+
 Wed Aug 19 00:11:14 1998  Tim Janik  <timj@gtk.org>
 
        * gtk/gtkmain.c (gtk_init): allow argument parsing in gtk without
index 644e6060fe3b887c5ce638b75a43ade275bb988a..f884b8af4fdf0481764ef01027968bfd205d3670 100644 (file)
@@ -18,9 +18,9 @@
  */
 
 /* For more information on GdkRgb, see http://www.levien.com/gdkrgb/
-   
+
    Raph Levien <raph@acm.org>
-*/
+   */
 
 #include <math.h>
 #include <stdio.h>
@@ -64,39 +64,39 @@ struct _GdkRgbInfo
 {
   GdkVisual *visual;
   GdkColormap *cmap;
-  
+
   gulong *color_pixels;
   gulong *gray_pixels;
   gulong *reserved_pixels;
-  
+
   guint nred_shades;
   guint ngreen_shades;
   guint nblue_shades;
   guint ngray_shades;
   guint nreserved;
-  
+
   guint bpp;
   gint cmap_alloced;
   gdouble gamma;
-  
+
   /* Generally, the stage buffer is used to convert 32bit RGB, gray,
      and indexed images into 24 bit packed RGB. */
   guchar *stage_buf;
-  
+
   GdkRgbCmap *gray_cmap;
-  
+
   gboolean dith_default;
-  
+
   /* Convert functions */
   GdkRgbConvFunc conv;
   GdkRgbConvFunc conv_d;
-  
+
   GdkRgbConvFunc conv_32;
   GdkRgbConvFunc conv_32_d;
-  
+
   GdkRgbConvFunc conv_gray;
   GdkRgbConvFunc conv_gray_d;
-  
+
   GdkRgbConvFunc conv_indexed;
   GdkRgbConvFunc conv_indexed_d;
 };
@@ -123,9 +123,9 @@ gdk_rgb_cmap_fail (const char *msg, GdkColormap *cmap, gulong *pixels)
   gulong free_pixels[256];
   gint n_free;
   gint i;
-  
+
 #ifdef VERBOSE
-  g_message ("%s", msg);
+  g_print ("%s", msg);
 #endif
   n_free = 0;
   for (i = 0; i < 256; i++)
@@ -141,7 +141,7 @@ gdk_rgb_make_colorcube (gulong *pixels, gint nr, gint ng, gint nb)
 {
   guchar rt[16], gt[16], bt[16];
   gint i;
-  
+
   colorcube = g_new (guchar, 4096);
   for (i = 0; i < 16; i++)
     {
@@ -149,12 +149,12 @@ gdk_rgb_make_colorcube (gulong *pixels, gint nr, gint ng, gint nb)
       gt[i] = nb * ((i * 17 * (ng - 1) + 128) >> 8);
       bt[i] = ((i * 17 * (nb - 1) + 128) >> 8);
     }
-  
+
   for (i = 0; i < 4096; i++)
     {
       colorcube[i] = pixels[rt[i >> 8] + gt[(i >> 4) & 0x0f] + bt[i & 0x0f]];
 #ifdef VERBOSE
-      g_message ("%03x %02x %x %x %x", i, colorcube[i], rt[i >> 8], gt[(i >> 4) & 0x0f], bt[i & 0x0f]);
+      g_print ("%03x %02x %x %x %x\n", i, colorcube[i], rt[i >> 8], gt[(i >> 4) & 0x0f], bt[i & 0x0f]);
 #endif
     }
 }
@@ -165,7 +165,7 @@ gdk_rgb_make_colorcube_d (gulong *pixels, gint nr, gint ng, gint nb)
 {
   gint r, g, b;
   gint i;
-  
+
   colorcube_d = g_new (guchar, 512);
   for (i = 0; i < 512; i++)
     {
@@ -193,53 +193,53 @@ gdk_rgb_try_colormap (gint nr, gint ng, gint nb)
   gint colors_needed;
   gint idx;
   gint best[256];
-  
+
   if (nr * ng * nb < gdk_rgb_min_colors)
     return FALSE;
-  
+
   if (image_info->cmap_alloced)
     cmap = image_info->cmap;
   else
     cmap = gdk_colormap_get_system ();
-  
+
   colors_needed = nr * ng * nb;
   for (i = 0; i < 256; i++)
     {
       best[i] = 192;
       pixels[i] = 256;
     }
-  
+
 #ifndef GAMMA
   if (!gdk_rgb_install_cmap)
-    /* find color cube colors that are already present */
-    for (i = 0; i < MIN (256, cmap->size); i++)
-      {
-       r = cmap->colors[i].red >> 8;
-       g = cmap->colors[i].green >> 8;
-       b = cmap->colors[i].blue >> 8;
-       ri = (r * (nr - 1) + 128) >> 8;
-       gi = (g * (ng - 1) + 128) >> 8;
-       bi = (b * (nb - 1) + 128) >> 8;
-       r0 = ri * 255 / (nr - 1);
-       g0 = gi * 255 / (ng - 1);
-       b0 = bi * 255 / (nb - 1);
-       idx = ((ri * nr) + gi) * nb + bi;
-       d2 = (r - r0) * (r - r0) + (g - g0) * (g - g0) + (b - b0) * (b - b0);
-       if (d2 < best[idx]) {
-         if (pixels[idx] < 256)
-           gdk_colors_free (cmap, pixels + idx, 1, 0);
-         else
-           colors_needed--;
-         color = cmap->colors[i];
-         if (!gdk_color_alloc (cmap, &color))
-           return gdk_rgb_cmap_fail ("error allocating system color",
-                                     cmap, pixels);
-         pixels[idx] = color.pixel; /* which is almost certainly i */
-         best[idx] = d2;
-       }
+  /* find color cube colors that are already present */
+  for (i = 0; i < MIN (256, cmap->size); i++)
+    {
+      r = cmap->colors[i].red >> 8;
+      g = cmap->colors[i].green >> 8;
+      b = cmap->colors[i].blue >> 8;
+      ri = (r * (nr - 1) + 128) >> 8;
+      gi = (g * (ng - 1) + 128) >> 8;
+      bi = (b * (nb - 1) + 128) >> 8;
+      r0 = ri * 255 / (nr - 1);
+      g0 = gi * 255 / (ng - 1);
+      b0 = bi * 255 / (nb - 1);
+      idx = ((ri * nr) + gi) * nb + bi;
+      d2 = (r - r0) * (r - r0) + (g - g0) * (g - g0) + (b - b0) * (b - b0);
+      if (d2 < best[idx]) {
+       if (pixels[idx] < 256)
+         gdk_colors_free (cmap, pixels + idx, 1, 0);
+       else
+         colors_needed--;
+       color = cmap->colors[i];
+       if (!gdk_color_alloc (cmap, &color))
+         return gdk_rgb_cmap_fail ("error allocating system color\n",
+                                   cmap, pixels);
+       pixels[idx] = color.pixel; /* which is almost certainly i */
+       best[idx] = d2;
       }
+    }
 #endif
-  
+
   if (colors_needed)
     {
       if (!gdk_colors_alloc (cmap, 0, NULL, 0, junk, colors_needed))
@@ -247,14 +247,14 @@ gdk_rgb_try_colormap (gint nr, gint ng, gint nb)
          char tmp_str[80];
          
          sprintf (tmp_str,
-                  "%d %d %d colormap failed (in gdk_colors_alloc)",
+                  "%d %d %d colormap failed (in gdk_colors_alloc)\n",
                   nr, ng, nb);
          return gdk_rgb_cmap_fail (tmp_str, cmap, pixels);
        }
-      
+
       gdk_colors_free (cmap, junk, colors_needed, 0);
     }
-  
+
   for (r = 0, i = 0; r < nr; r++)
     for (g = 0; g < ng; g++)
       for (b = 0; b < nb; b++, i++)
@@ -264,18 +264,19 @@ gdk_rgb_try_colormap (gint nr, gint ng, gint nb)
              color.red = r * 65535 / (nr - 1);
              color.green = g * 65535 / (ng - 1);
              color.blue = b * 65535 / (nb - 1);
-             
+
 #ifdef GAMMA
              color.red = 65535 * pow (color.red / 65535.0, 0.5);
              color.green = 65535 * pow (color.green / 65535.0, 0.5);
              color.blue = 65535 * pow (color.blue / 65535.0, 0.5);
 #endif
-             
+
+             /* This should be a raw XAllocColor call */
              if (!gdk_color_alloc (cmap, &color))
                {
                  char tmp_str[80];
-                 
-                 sprintf (tmp_str, "%d %d %d colormap failed",
+
+                 sprintf (tmp_str, "%d %d %d colormap failed\n",
                           nr, ng, nb);
                  return gdk_rgb_cmap_fail (tmp_str,
                                            cmap, pixels);
@@ -283,10 +284,10 @@ gdk_rgb_try_colormap (gint nr, gint ng, gint nb)
              pixels[i] = color.pixel;
            }
 #ifdef VERBOSE
-         g_message ("%d: %lx", i, pixels[i]);
+         g_print ("%d: %lx\n", i, pixels[i]);
 #endif
        }
-  
+
   image_info->nred_shades = nr;
   image_info->ngreen_shades = ng;
   image_info->nblue_shades = nb;
@@ -300,7 +301,7 @@ static gboolean
 gdk_rgb_do_colormaps (void)
 {
   const gint sizes[][3] = {
-    /*   { 6, 7, 6 }, */
+    /*    { 6, 7, 6 }, */
     { 6, 6, 6 }, 
     { 6, 6, 5 }, 
     { 6, 6, 4 }, 
@@ -313,13 +314,38 @@ gdk_rgb_do_colormaps (void)
   };
   const gint n_sizes = sizeof(sizes) / (3 * sizeof(gint));
   gint i;
-  
+
   for (i = 0; i < n_sizes; i++)
     if (gdk_rgb_try_colormap (sizes[i][0], sizes[i][1], sizes[i][2]))
       return TRUE;
   return FALSE;
 }
 
+/* Make a 2 x 2 x 2 colorcube */
+static void
+gdk_rgb_colorcube_222 (void)
+{
+  int i;
+  GdkColor color;
+  GdkColormap *cmap;
+
+  if (image_info->cmap_alloced)
+    cmap = image_info->cmap;
+  else
+    cmap = gdk_colormap_get_system ();
+
+  colorcube_d = g_new (guchar, 512);
+
+  for (i = 0; i < 8; i++)
+    {
+      color.red = ((i & 4) >> 2) * 65535;
+      color.green = ((i & 2) >> 1) * 65535;
+      color.blue = (i & 1) * 65535;
+      gdk_color_alloc (cmap, &color);
+      colorcube_d[((i & 4) << 4) | ((i & 2) << 2) | (i & 1)] = color.pixel;
+    }
+}
+
 void
 gdk_rgb_set_verbose (gboolean verbose)
 {
@@ -339,16 +365,16 @@ gdk_rgb_set_min_colors (gint min_colors)
 }
 
 /* Return a "score" based on the following criteria (in hex):
-   
+
    x000 is the quality - 1 is 1bpp, 2 is 4bpp,
-   4 is 8bpp,
-   7 is 15bpp truecolor, 8 is 16bpp truecolor,
-   9 is 24bpp truecolor.
+                         4 is 8bpp,
+                        7 is 15bpp truecolor, 8 is 16bpp truecolor,
+                        9 is 24bpp truecolor.
    0x00 is the speed - 1 is the normal case,
-   2 means faster than normal
+                       2 means faster than normal
    00x0 gets a point for being the system visual
    000x gets a point for being pseudocolor
-   
+
    A caveat: in the 8bpp modes, being the system visual seems to be
    quite important. Thus, all of the 8bpp modes should be ranked at
    the same speed.
@@ -366,8 +392,8 @@ gdk_rgb_score_visual (GdkVisual *visual)
     "true color",
     "direct color",
   };
-  
-  
+
+
   quality = 0;
   speed = 1;
   sys = 0;
@@ -386,10 +412,15 @@ gdk_rgb_score_visual (GdkVisual *visual)
       else if (visual->depth == 8)
        quality = 4;
     }
-  else if (visual->type == GDK_VISUAL_PSEUDO_COLOR)
+  else if (visual->type == GDK_VISUAL_PSEUDO_COLOR ||
+          visual->type == GDK_VISUAL_STATIC_COLOR)
     {
       if (visual->depth == 8)
        quality = 4;
+      else if (visual->depth == 4)
+       quality = 2;
+      else if (visual->depth == 1)
+       quality = 1;
     }
   else if (visual->type == GDK_VISUAL_STATIC_GRAY
 #ifdef ENABLE_GRAYSCALE
@@ -404,25 +435,25 @@ gdk_rgb_score_visual (GdkVisual *visual)
       else if (visual->depth == 1)
        quality = 1;
     }
-  
+
   if (quality == 0)
     return 0;
-  
+
   sys = (visual == gdk_visual_get_system ());
-  
+
   pseudo = (visual->type == GDK_VISUAL_PSEUDO_COLOR);
-  
+
   if (gdk_rgb_verbose)
-    g_message ("Visual 0x%x, type = %s, depth = %d, %x:%x:%x%s; score=%x",
-              (gint)(((GdkVisualPrivate *)visual)->xvisual->visualid),
-              visual_names[visual->type],
-              visual->depth,
-              visual->red_mask,
-              visual->green_mask,
-              visual->blue_mask,
-              sys ? " (system)" : "",
-              (quality << 12) | (speed << 8) | (sys << 4) | pseudo);
-  
+    g_print ("Visual 0x%x, type = %s, depth = %d, %x:%x:%x%s; score=%x\n",
+            (gint)(((GdkVisualPrivate *)visual)->xvisual->visualid),
+            visual_names[visual->type],
+            visual->depth,
+            visual->red_mask,
+            visual->green_mask,
+            visual->blue_mask,
+            sys ? " (system)" : "",
+            (quality << 12) | (speed << 8) | (sys << 4) | pseudo);
+
   return (quality << 12) | (speed << 8) | (sys << 4) | pseudo;
 }
 
@@ -432,9 +463,9 @@ gdk_rgb_choose_visual (void)
   GList *visuals;
   guint32 score, best_score;
   GdkVisual *visual, *best_visual;
-  
+
   visuals = gdk_list_visuals ();
-  
+
   best_visual = visuals->data;
   best_score = gdk_rgb_score_visual (best_visual);
   visuals = visuals->next;
@@ -449,7 +480,7 @@ gdk_rgb_choose_visual (void)
        }
       visuals = visuals->next;
     }
-  
+
   image_info->visual = best_visual;
 }
 
@@ -463,7 +494,7 @@ gdk_rgb_set_gray_cmap (GdkColormap *cmap)
   gint status;
   gulong pixels[256];
   gint r, g, b, gray;
-  
+
   for (i = 0; i < 256; i++)
     {
       color.pixel = i;
@@ -473,16 +504,16 @@ gdk_rgb_set_gray_cmap (GdkColormap *cmap)
       status = gdk_color_alloc (cmap, &color);
       pixels[i] = color.pixel;
 #ifdef VERBOSE
-      g_message ("allocating pixel %d, %x %x %x, result %d",
-                color.pixel, color.red, color.green, color.blue, status);
+      g_print ("allocating pixel %d, %x %x %x, result %d\n",
+              color.pixel, color.red, color.green, color.blue, status);
 #endif
     }
-  
+
   /* Now, we make fake colorcubes - we ultimately just use the pseudocolor
      methods. */
-  
+
   colorcube = g_new (guchar, 4096);
-  
+
   for (i = 0; i < 4096; i++)
     {
       r = (i >> 4) & 0xf0;
@@ -501,7 +532,7 @@ gdk_rgb_init (void)
 {
   gint i;
   gint byte_order[1] = { 1 };
-  
+
   /* check endian sanity */
 #ifdef WORDS_BIGENDIAN
   if (((char *)byte_order)[0] == 1)
@@ -510,33 +541,37 @@ gdk_rgb_init (void)
   if (((char *)byte_order)[0] != 1)
     g_error ("gdk_rgb_init: WORDS_BIGENDIAN is not defined, but this is a little endian machine.\n\n");
 #endif
-  
+
   if (image_info == NULL)
     {
       image_info = g_new0 (GdkRgbInfo, 1);
-      
+
       image_info->visual = NULL;
       image_info->cmap = NULL;
-      
+
       image_info->color_pixels = NULL;
       image_info->gray_pixels = NULL;
       image_info->reserved_pixels = NULL;
-      
+
       image_info->nred_shades = 6;
       image_info->ngreen_shades = 6;
       image_info->nblue_shades = 4;
       image_info->ngray_shades = 24;
       image_info->nreserved = 0;
-      
+
       image_info->bpp = 0;
       image_info->cmap_alloced = FALSE;
       image_info->gamma = 1.0;
-      
+
       image_info->stage_buf = NULL;
-      
+
       gdk_rgb_choose_visual ();
-      
-      if (image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR)
+
+      if (image_info->visual->depth == 4)
+       {
+         gdk_rgb_colorcube_222 ();
+       }
+      else if (image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR)
        {
          if (gdk_rgb_install_cmap ||
              image_info->visual != gdk_visual_get_system ())
@@ -551,13 +586,13 @@ gdk_rgb_init (void)
              gdk_rgb_do_colormaps ();
            }
          if (gdk_rgb_verbose)
-           g_message ("color cube: %d x %d x %d",
-                      image_info->nred_shades,
-                      image_info->ngreen_shades,
-                      image_info->nblue_shades);
-         
+           g_print ("color cube: %d x %d x %d\n",
+                    image_info->nred_shades,
+                    image_info->ngreen_shades,
+                    image_info->nblue_shades);
+
          if (!image_info->cmap_alloced)
-           image_info->cmap = gdk_colormap_get_system ();
+             image_info->cmap = gdk_colormap_get_system ();
        }
 #ifdef ENABLE_GRAYSCALE
       else if (image_info->visual->type == GDK_VISUAL_GRAYSCALE)
@@ -565,7 +600,7 @@ gdk_rgb_init (void)
          image_info->cmap = gdk_colormap_new (image_info->visual, FALSE);
          gdk_rgb_set_gray_cmap (image_info->cmap);
          image_info->cmap_alloced = TRUE;
-       }
+       }
 #endif
       else
        {
@@ -579,16 +614,16 @@ gdk_rgb_init (void)
              image_info->cmap_alloced = TRUE;
            }
        }
-      
+
       for (i = 0; i < N_IMAGES; i++)
        static_image[i] = gdk_image_new (GDK_IMAGE_FASTEST,
                                         image_info->visual,
                                         IMAGE_WIDTH, IMAGE_HEIGHT);
-      
+
       image_info->bpp = static_image[0]->bpp;
-      
+
       gdk_rgb_select_conv (static_image[0]);
-      
+
     }
 }
 
@@ -597,36 +632,41 @@ gulong
 gdk_rgb_xpixel_from_rgb (guint32 rgb)
 {
   gulong pixel;
-  
+
   if (image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR)
     pixel = colorcube[((rgb & 0xf00000) >> 12) |
                     ((rgb & 0xf000) >> 8) |
                     ((rgb & 0xf0) >> 4)];
+  else if (image_info->visual->depth == 4 &&
+          image_info->visual->type == GDK_VISUAL_STATIC_COLOR)
+    {
+      pixel = colorcube_d[((rgb & 0x800000) >> 17) |
+                        ((rgb & 0x8000) >> 12) |
+                        ((rgb & 0x80) >> 7)];
+    }
   else
     {
 #ifdef VERBOSE
-      g_message ("shift, prec: r %d %d g %d %d b %d %d",
-                image_info->visual->red_shift,
-                image_info->visual->red_prec,
-                image_info->visual->green_shift,
-                image_info->visual->green_prec,
-                image_info->visual->blue_shift,
-                image_info->visual->blue_prec);
+      g_print ("shift, prec: r %d %d g %d %d b %d %d\n",
+              image_info->visual->red_shift,
+              image_info->visual->red_prec,
+              image_info->visual->green_shift,
+              image_info->visual->green_prec,
+              image_info->visual->blue_shift,
+              image_info->visual->blue_prec);
 #endif
-      
+
       pixel = (((((rgb & 0xff0000) >> 16) >>
                 (8 - image_info->visual->red_prec)) <<
                image_info->visual->red_shift) +
-              ((((rgb & 0xff00) >> 8)  >>
+              ((((rgb & 0xff00) >> 8)  >>
                 (8 - image_info->visual->green_prec)) <<
                image_info->visual->green_shift) +
               (((rgb & 0xff) >>
                 (8 - image_info->visual->blue_prec)) <<
                image_info->visual->blue_shift));
-      
-      ;
     }
-  
+
   return pixel;
 }
 
@@ -634,7 +674,7 @@ void
 gdk_rgb_gc_set_foreground (GdkGC *gc, guint32 rgb)
 {
   GdkColor color;
-  
+
   color.pixel = gdk_rgb_xpixel_from_rgb (rgb);
   gdk_gc_set_foreground (gc, &color);
 }
@@ -643,7 +683,7 @@ void
 gdk_rgb_gc_set_background (GdkGC *gc, guint32 rgb)
 {
   GdkColor color;
-  
+
   color.pixel = gdk_rgb_xpixel_from_rgb (rgb);
   gdk_gc_set_background (gc, &color);
 }
@@ -664,7 +704,7 @@ gdk_rgb_convert_8 (GdkImage *image,
   guchar *obuf, *obptr;
   guchar *bptr, *bp2;
   gint r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0;
@@ -672,7 +712,7 @@ gdk_rgb_convert_8 (GdkImage *image,
     {
       bp2 = bptr;
       obptr = obuf;
-      if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+      if (((unsigned long)obuf | (unsigned long) bp2) & 3)
        {
          for (x = 0; x < width; x++)
            {
@@ -692,7 +732,7 @@ gdk_rgb_convert_8 (GdkImage *image,
              guint32 r1b0g0r0;
              guint32 g2r2b1g1;
              guint32 b3g3r3b2;
-             
+
              r1b0g0r0 = ((guint32 *)bp2)[0];
              g2r2b1g1 = ((guint32 *)bp2)[1];
              b3g3r3b2 = ((guint32 *)bp2)[2];
@@ -739,7 +779,7 @@ gdk_rgb_convert_8 (GdkImage *image,
   guchar *obuf, *obptr;
   guchar *bptr, *bp2;
   gint r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0;
@@ -877,7 +917,7 @@ static guchar DM[128][128] =
   { 46, 2, 56, 11, 41, 1, 49, 6, 27, 47, 2, 48, 5, 32, 37, 3, 13, 19, 32, 1, 55, 28, 60, 17, 43, 59, 32, 20, 49, 16, 55, 23, 14, 46, 2, 36, 6, 30, 20, 49, 12, 47, 35, 14, 21, 60, 29, 14, 35, 24, 46, 1, 56, 29, 53, 8, 33, 23, 56, 1, 35, 46, 20, 39, 26, 4, 53, 28, 17, 38, 60, 34, 48, 9, 55, 15, 46, 7, 41, 31, 60, 24, 16, 36, 1, 59, 19, 52, 35, 6, 55, 11, 59, 33, 7, 57, 4, 29, 48, 1, 19, 26, 37, 30, 18, 63, 37, 6, 59, 1, 40, 24, 56, 33, 46, 22, 35, 7, 24, 53, 39, 5, 26, 45, 55, 18, 62, 7 },
   { 20, 60, 29, 34, 20, 62, 33, 52, 10, 36, 13, 60, 41, 21, 50, 27, 56, 49, 8, 51, 21, 45, 11, 48, 8, 23, 53, 3, 29, 44, 5, 52, 9, 32, 50, 17, 43, 56, 3, 38, 24, 10, 62, 25, 51, 9, 33, 49, 61, 7, 30, 62, 22, 19, 2, 42, 63, 5, 49, 18, 60, 15, 52, 7, 43, 56, 23, 50, 5, 50, 2, 20, 41, 30, 1, 52, 22, 61, 14, 26, 3, 43, 53, 7, 47, 28, 11, 14, 23, 58, 33, 25, 47, 13, 50, 17, 40, 54, 34, 60, 41, 6, 59, 14, 50, 7, 25, 55, 20, 42, 51, 8, 27, 4, 16, 60, 28, 50, 44, 3, 22, 49, 63, 12, 33, 1, 43, 31 },
   { 36, 5, 46, 8, 44, 24, 13, 39, 25, 57, 31, 18, 8, 52, 10, 45, 6, 30, 36, 24, 63, 4, 33, 26, 57, 40, 15, 56, 37, 12, 40, 25, 37, 58, 11, 63, 21, 45, 16, 60, 31, 53, 18, 33, 3, 45, 23, 0, 20, 54, 40, 15, 50, 38, 60, 16, 25, 42, 29, 38, 7, 41, 25, 62, 18, 33, 8, 35, 42, 16, 32, 56, 12, 39, 59, 19, 34, 9, 49, 38, 57, 12, 21, 50, 14, 40, 61, 44, 50, 9, 49, 19, 3, 29, 35, 62, 12, 24, 7, 18, 52, 32, 10, 46, 21, 41, 32, 11, 36, 29, 14, 34, 60, 38, 54, 11, 41, 14, 19, 57, 32, 16, 7, 41, 51, 25, 14, 57 },
-  { 53, 18, 26, 50, 15, 58, 4, 63, 17, 43, 7, 40, 61, 35, 15, 41, 23, 60, 16, 38, 14, 42, 19, 50, 0, 31, 10, 46, 27, 63, 18, 60, 0, 20, 29, 39, 8, 26, 37, 5, 42, 0, 44, 39, 57, 17, 58, 41, 28, 37, 4, 32, 9, 44, 12, 31, 54, 10, 59, 14, 27, 53, 12, 36, 0, 47, 13, 64, 21, 58, 10, 24, 50, 27, 4, 26, 44, 53, 31, 0, 18, 42, 29, 33, 57, 4, 32, 26, 0, 38, 16, 61, 41, 53, 20, 0, 42, 44, 49, 27, 10, 56, 39, 0, 57, 15, 53, 49, 3, 61, 22, 47, 17, 5, 49, 26, 2, 63, 39, 10, 47, 27, 37, 23, 4, 59, 38, 10 },
+  { 53, 18, 26, 50, 15, 58, 4, 63, 17, 43, 7, 40, 61, 35, 15, 41, 23, 60, 16, 38, 14, 42, 19, 50, 0, 31, 10, 46, 27, 63, 18, 60, 0, 20, 29, 39, 8, 26, 37, 5, 42, 0, 44, 39, 57, 17, 58, 41, 28, 37, 4, 32, 9, 44, 12, 31, 54, 10, 59, 14, 27, 53, 12, 36, 0, 47, 13, 63, 21, 58, 10, 24, 50, 27, 4, 26, 44, 53, 31, 0, 18, 42, 29, 33, 57, 4, 32, 26, 0, 38, 16, 61, 41, 53, 20, 0, 42, 44, 49, 27, 10, 56, 39, 0, 57, 15, 53, 49, 3, 61, 22, 47, 17, 5, 49, 26, 2, 63, 39, 10, 47, 27, 37, 23, 4, 59, 38, 10 },
   { 23, 39, 61, 3, 37, 28, 48, 31, 0, 34, 51, 23, 2, 26, 58, 0, 53, 11, 46, 1, 57, 29, 52, 14, 37, 61, 21, 35, 2, 49, 7, 34, 47, 55, 4, 33, 54, 13, 58, 52, 19, 50, 22, 7, 13, 29, 36, 11, 51, 17, 60, 25, 55, 4, 34, 51, 0, 35, 20, 48, 32, 3, 51, 30, 59, 28, 40, 3, 46, 29, 54, 43, 7, 62, 47, 11, 39, 4, 23, 46, 55, 8, 63, 5, 25, 37, 18, 46, 21, 56, 31, 5, 36, 8, 45, 58, 26, 15, 2, 36, 47, 21, 29, 44, 25, 34, 3, 27, 43, 10, 52, 0, 45, 30, 24, 36, 43, 18, 34, 59, 0, 52, 61, 15, 44, 19, 30, 49 },
   { 0, 27, 12, 43, 54, 9, 22, 53, 21, 46, 15, 55, 29, 47, 20, 33, 39, 28, 59, 35, 9, 44, 5, 24, 47, 7, 52, 17, 56, 22, 30, 42, 14, 26, 45, 18, 49, 1, 24, 34, 11, 27, 55, 32, 61, 47, 2, 56, 6, 44, 13, 47, 36, 27, 58, 22, 16, 47, 40, 4, 57, 38, 21, 45, 16, 9, 56, 26, 11, 38, 0, 22, 36, 17, 33, 57, 16, 30, 62, 15, 35, 40, 20, 45, 59, 10, 54, 8, 63, 13, 52, 27, 22, 57, 28, 12, 32, 51, 55, 22, 63, 4, 16, 54, 12, 62, 45, 19, 58, 13, 32, 40, 20, 56, 7, 57, 9, 54, 6, 29, 42, 21, 8, 55, 35, 47, 6, 41 },
   { 56, 33, 58, 32, 19, 35, 42, 6, 59, 11, 38, 5, 49, 12, 62, 7, 52, 17, 5, 25, 54, 20, 61, 31, 54, 27, 41, 11, 44, 5, 59, 12, 36, 51, 10, 61, 28, 41, 48, 9, 43, 63, 5, 40, 20, 8, 49, 26, 34, 21, 58, 1, 18, 45, 7, 39, 61, 26, 8, 50, 23, 10, 63, 5, 55, 37, 19, 49, 52, 15, 59, 47, 13, 54, 1, 25, 42, 58, 10, 48, 3, 27, 50, 1, 17, 48, 34, 41, 16, 40, 2, 45, 10, 39, 17, 61, 5, 38, 19, 9, 41, 31, 60, 38, 5, 23, 36, 8, 30, 55, 24, 63, 12, 48, 14, 51, 31, 20, 45, 25, 12, 50, 32, 2, 28, 11, 62, 14 },
@@ -910,13 +950,13 @@ static guchar DM[128][128] =
 #define DM_HEIGHT 8
 static guchar DM[8][8] =
 {
-  { 0, 32, 8,  40, 2,  34, 10, 42 },
+  { 0,  32, 8,  40, 2,  34, 10, 42 },
   { 48, 16, 56, 24, 50, 18, 58, 26 },
-  { 12, 44, 4, 36, 14, 46, 6,  38 },
+  { 12, 44, 4,  36, 14, 46, 6,  38 },
   { 60, 28, 52, 20, 62, 30, 54, 22 },
-  { 3, 35, 11, 43, 1,  33, 9,  41 },
+  { 3,  35, 11, 43, 1,  33, 9,  41 },
   { 51, 19, 59, 27, 49, 17, 57, 25 },
-  { 15, 47, 7, 39, 13, 45, 5,  37 },
+  { 15, 47, 7,  39, 13, 45, 5,  37 },
   { 63, 31, 55, 23, 61, 29, 53, 21 }
 };
 #endif
@@ -928,7 +968,7 @@ gdk_rgb_preprocess_dm_565 (void)
 {
   int i;
   guint32 dith;
-  
+
   if (DM_565 == NULL)
     {
       DM_565 = g_new (guint32, DM_WIDTH * DM_HEIGHT);
@@ -937,7 +977,7 @@ gdk_rgb_preprocess_dm_565 (void)
          dith = DM[0][i] >> 3;
          DM_565[i] = (dith << 20) | dith | (((7 - dith) >> 1) << 10);
 #ifdef VERBOSE
-         g_message ("%i %x %x", i, dith, DM_565[i]);
+         g_print ("%i %x %x\n", i, dith, DM_565[i]);
 #endif
        }
     }
@@ -956,7 +996,7 @@ gdk_rgb_convert_8_d666 (GdkImage *image,
   gint r, g, b;
   guchar *dmp;
   gint dith;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0;
@@ -997,7 +1037,7 @@ gdk_rgb_convert_8_d (GdkImage *image,
   guchar *dmp;
   gint dith;
   gint rs, gs, bs;
-  
+
   bptr = buf;
   bpl = image->bpl;
   rs = image_info->nred_shades - 1;
@@ -1038,7 +1078,7 @@ gdk_rgb_convert_8_indexed (GdkImage *image,
   guchar *bptr, *bp2;
   guchar c;
   guchar *lut;
-  
+
   lut = cmap->lut;
   bptr = buf;
   bpl = image->bpl;
@@ -1069,7 +1109,7 @@ gdk_rgb_convert_gray8 (GdkImage *image,
   guchar *obuf, *obptr;
   guchar *bptr, *bp2;
   gint r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0;
@@ -1100,7 +1140,7 @@ gdk_rgb_convert_gray8_gray (GdkImage *image,
   gint bpl;
   guchar *obuf;
   guchar *bptr;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0;
@@ -1121,7 +1161,7 @@ gdk_rgb_convert_gray8_gray (GdkImage *image,
    This assumes native byte ordering - what should really be done is to
    check whether static_image->byte_order is consistent with the _ENDIAN
    config flag, and if not, use a different function.
-   
+
    This one is even faster than the one below - its inner loop loads 3
    words (i.e. 4 24-bit pixels), does a lot of shifting and masking,
    then writes 2 words. */
@@ -1136,7 +1176,7 @@ gdk_rgb_convert_565 (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   guchar r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
@@ -1144,7 +1184,7 @@ gdk_rgb_convert_565 (GdkImage *image,
     {
       bp2 = bptr;
       obptr = obuf;
-      if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+      if (((unsigned long)obuf | (unsigned long) bp2) & 3)
        {
          for (x = 0; x < width; x++)
            {
@@ -1164,7 +1204,7 @@ gdk_rgb_convert_565 (GdkImage *image,
              guint32 r1b0g0r0;
              guint32 g2r2b1g1;
              guint32 b3g3r3b2;
-             
+
              r1b0g0r0 = ((guint32 *)bp2)[0];
              g2r2b1g1 = ((guint32 *)bp2)[1];
              b3g3r3b2 = ((guint32 *)bp2)[2];
@@ -1205,19 +1245,19 @@ gdk_rgb_convert_565 (GdkImage *image,
    This assumes native byte ordering - what should really be done is to
    check whether static_image->byte_order is consistent with the _ENDIAN
    config flag, and if not, use a different function.
-   
+
    This routine is faster than the one included with Gtk 1.0 for a number
    of reasons:
-   
+
    1. Shifting instead of lookup tables (less memory traffic).
-   
+
    2. Much less register pressure, especially because shifts are
    in the code.
-   
+
    3. A memcpy is avoided (i.e. the transfer function).
-   
+
    4. On big-endian architectures, byte swapping is avoided.
-   
+
    That said, it wouldn't be hard to make it even faster - just make an
    inner loop that reads 3 words (i.e. 4 24-bit pixels), does a lot of
    shifting and masking, then writes 2 words.
@@ -1233,7 +1273,7 @@ gdk_rgb_convert_565 (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   guchar r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
@@ -1267,7 +1307,7 @@ gdk_rgb_convert_565_gray (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   guchar g;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
@@ -1275,7 +1315,7 @@ gdk_rgb_convert_565_gray (GdkImage *image,
     {
       bp2 = bptr;
       obptr = obuf;
-      if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+      if (((unsigned long)obuf | (unsigned long) bp2) & 3)
        {
          for (x = 0; x < width; x++)
            {
@@ -1291,7 +1331,7 @@ gdk_rgb_convert_565_gray (GdkImage *image,
          for (x = 0; x < width - 3; x += 4)
            {
              guint32 g3g2g1g0;
-             
+
              g3g2g1g0 = ((guint32 *)bp2)[0];
              ((guint32 *)obptr)[0] =
                ((g3g2g1g0 & 0xf8) << 8) |
@@ -1335,7 +1375,7 @@ gdk_rgb_convert_565_gray (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   guchar g;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
@@ -1366,7 +1406,7 @@ gdk_rgb_convert_565_br (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   guchar r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
@@ -1380,7 +1420,7 @@ gdk_rgb_convert_565_br (GdkImage *image,
          b = *bp2++;
          /* final word is:
             g4 g3 g2 b7 b6 b5 b4 b3  r7 r6 r5 r4 r3 g7 g6 g5
-         */
+          */
          ((unsigned short *)obuf)[x] = (r & 0xf8) |
            ((g & 0xe0) >> 5) |
            ((g & 0x1c) << 11) |
@@ -1396,16 +1436,16 @@ gdk_rgb_convert_565_br (GdkImage *image,
 #ifdef HAIRY_CONVERT_565
 static void
 gdk_rgb_convert_565_d (GdkImage *image,
-                      gint x0, gint y0, gint width, gint height,
-                      guchar *buf, int rowstride,
-                      gint x_align, gint y_align, GdkRgbCmap *cmap)
+                    gint x0, gint y0, gint width, gint height,
+                    guchar *buf, int rowstride,
+                    gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   /* Now this is what I'd call some highly tuned code! */
   int x, y;
   guchar *obuf, *obptr;
   gint bpl;
   guchar *bptr, *bp2;
-  
+
   width += x_align;
   height += y_align;
   
@@ -1417,7 +1457,7 @@ gdk_rgb_convert_565_d (GdkImage *image,
       guint32 *dmp = DM_565 + ((y & (DM_HEIGHT - 1)) << DM_WIDTH_SHIFT);
       bp2 = bptr;
       obptr = obuf;
-      if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+      if (((unsigned long)obuf | (unsigned long) bp2) & 3)
        {
          for (x = x_align; x < width; x++)
            {
@@ -1428,8 +1468,8 @@ gdk_rgb_convert_565_d (GdkImage *image,
              rgb += 0x10040100
                - ((rgb & 0x1e0001e0) >> 5)
                - ((rgb & 0x00070000) >> 6);
-             
-             ((unsigned short *)obuf)[0] =
+
+             ((unsigned short *)obptr)[0] =
                ((rgb & 0x0f800000) >> 12) |
                ((rgb & 0x0003f000) >> 7) |
                ((rgb & 0x000000f8) >> 3);
@@ -1444,7 +1484,7 @@ gdk_rgb_convert_565_d (GdkImage *image,
              guint32 g2r2b1g1;
              guint32 b3g3r3b2;
              guint32 rgb02, rgb13;
-             
+
              r1b0g0r0 = ((guint32 *)bp2)[0];
              g2r2b1g1 = ((guint32 *)bp2)[1];
              b3g3r3b2 = ((guint32 *)bp2)[2];
@@ -1506,8 +1546,8 @@ gdk_rgb_convert_565_d (GdkImage *image,
              rgb += 0x10040100
                - ((rgb & 0x1e0001e0) >> 5)
                - ((rgb & 0x00070000) >> 6);
-             
-             ((unsigned short *)obuf)[0] =
+
+             ((unsigned short *)obptr)[0] =
                ((rgb & 0x0f800000) >> 12) |
                ((rgb & 0x0003f000) >> 7) |
                ((rgb & 0x000000f8) >> 3);
@@ -1521,43 +1561,43 @@ gdk_rgb_convert_565_d (GdkImage *image,
 #else
 static void
 gdk_rgb_convert_565_d (GdkImage *image,
-                      gint x0, gint y0, gint width, gint height,
-                      guchar *buf, int rowstride,
-                      gint x_align, gint y_align, GdkRgbCmap *cmap)
+                       gint x0, gint y0, gint width, gint height,
+                       guchar *buf, int rowstride,
+                       gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   int x, y;
   guchar *obuf;
   gint bpl;
   guchar *bptr;
-  
+
   width += x_align;
   height += y_align;
   
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + (x0 - x_align) * 2;
-  
+
   for (y = y_align; y < height; y++)
     {
       guint32 *dmp = DM_565 + ((y & (DM_HEIGHT - 1)) << DM_WIDTH_SHIFT);
       guchar *bp2 = bptr;
-      
+
       for (x = x_align; x < width; x++)
-       {
-         gint32 rgb = *bp2++ << 20;
-         rgb += *bp2++ << 10;
-         rgb += *bp2++;
+        {
+          gint32 rgb = *bp2++ << 20;
+          rgb += *bp2++ << 10;
+          rgb += *bp2++;
          rgb += dmp[x & (DM_WIDTH - 1)];
-         rgb += 0x10040100
-           - ((rgb & 0x1e0001e0) >> 5)
-           - ((rgb & 0x00070000) >> 6);
-         
-         ((unsigned short *)obuf)[x] =
-           ((rgb & 0x0f800000) >> 12) |
-           ((rgb & 0x0003f000) >> 7) |
-           ((rgb & 0x000000f8) >> 3);
-       }
-      
+          rgb += 0x10040100
+            - ((rgb & 0x1e0001e0) >> 5)
+            - ((rgb & 0x00070000) >> 6);
+
+          ((unsigned short *)obuf)[x] =
+            ((rgb & 0x0f800000) >> 12) |
+            ((rgb & 0x0003f000) >> 7) |
+            ((rgb & 0x000000f8) >> 3);
+        }
+
       bptr += rowstride;
       obuf += bpl;
     }
@@ -1575,7 +1615,7 @@ gdk_rgb_convert_555 (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   guchar r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
@@ -1607,7 +1647,7 @@ gdk_rgb_convert_555_br (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   guchar r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 2;
@@ -1621,7 +1661,7 @@ gdk_rgb_convert_555_br (GdkImage *image,
          b = *bp2++;
          /* final word is:
             g5 g4 g3 b7 b6 b5 b4 b3  0 r7 r6 r5 r4 r3 g7 g6
-         */
+          */
          ((unsigned short *)obuf)[x] = ((r & 0xf8) >> 1) |
            ((g & 0xc0) >> 6) |
            ((g & 0x18) << 10) |
@@ -1642,7 +1682,7 @@ gdk_rgb_convert_888_msb (GdkImage *image,
   guchar *obuf;
   gint bpl;
   guchar *bptr;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 3;
@@ -1671,7 +1711,7 @@ gdk_rgb_convert_888_lsb (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   int r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 3;
@@ -1679,7 +1719,7 @@ gdk_rgb_convert_888_lsb (GdkImage *image,
     {
       bp2 = bptr;
       obptr = obuf;
-      if (width < 8 || (((unsigned long)obuf | (unsigned long) bp2) & 3))
+      if (((unsigned long)obuf | (unsigned long) bp2) & 3)
        {
          for (x = 0; x < width; x++)
            {
@@ -1699,7 +1739,7 @@ gdk_rgb_convert_888_lsb (GdkImage *image,
              guint32 r1b0g0r0;
              guint32 g2r2b1g1;
              guint32 b3g3r3b2;
-             
+
              r1b0g0r0 = ((guint32 *)bp2)[0];
              g2r2b1g1 = ((guint32 *)bp2)[1];
              b3g3r3b2 = ((guint32 *)bp2)[2];
@@ -1745,7 +1785,7 @@ gdk_rgb_convert_888_lsb (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   int r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 3;
@@ -1781,7 +1821,7 @@ gdk_rgb_convert_0888 (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   int r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 4;
@@ -1812,7 +1852,7 @@ gdk_rgb_convert_0888_br (GdkImage *image,
   gint bpl;
   guchar *bptr, *bp2;
   int r, g, b;
-  
+
   bptr = buf;
   bpl = image->bpl;
   obuf = ((guchar *)image->mem) + y0 * bpl + x0 * 4;
@@ -1852,7 +1892,7 @@ gdk_rgb_convert_truecolor_lsb (GdkImage *image,
   gint bpp;
   guint32 pixel;
   gint i;
-  
+
   r_right = 8 - image_info->visual->red_prec;
   r_left = image_info->visual->red_shift;
   g_right = 8 - image_info->visual->green_prec;
@@ -1908,7 +1948,7 @@ gdk_rgb_convert_truecolor_lsb_d (GdkImage *image,
   gint dith;
   gint r1, g1, b1;
   guchar *dmp;
-  
+
   r_right = 8 - image_info->visual->red_prec;
   r_left = image_info->visual->red_shift;
   r_prec = image_info->visual->red_prec;
@@ -1969,7 +2009,7 @@ gdk_rgb_convert_truecolor_msb (GdkImage *image,
   gint bpp;
   guint32 pixel;
   gint shift, shift_init;
-  
+
   r_right = 8 - image_info->visual->red_prec;
   r_left = image_info->visual->red_shift;
   g_right = 8 - image_info->visual->green_prec;
@@ -2025,7 +2065,7 @@ gdk_rgb_convert_truecolor_msb_d (GdkImage *image,
   gint dith;
   gint r1, g1, b1;
   guchar *dmp;
-  
+
   r_right = 8 - image_info->visual->red_prec;
   r_left = image_info->visual->red_shift;
   r_prec = image_info->visual->red_prec;
@@ -2068,6 +2108,70 @@ gdk_rgb_convert_truecolor_msb_d (GdkImage *image,
     }
 }
 
+#define IMAGE_8BPP
+static void
+gdk_rgb_convert_4 (GdkImage *image,
+                  gint x0, gint y0, gint width, gint height,
+                  guchar *buf, int rowstride,
+                  gint x_align, gint y_align,
+                  GdkRgbCmap *cmap)
+{
+  int x, y;
+  gint bpl;
+  guchar *obuf, *obptr;
+  guchar *bptr, *bp2;
+  gint r, g, b;
+  guchar *dmp;
+  gint dith;
+  guchar pix0, pix1;
+
+  bptr = buf;
+  bpl = image->bpl;
+  obuf = ((guchar *)image->mem) + y0 * bpl + x0;
+  for (y = 0; y < height; y++)
+    {
+      dmp = DM[(y_align + y) & (DM_HEIGHT - 1)];
+      bp2 = bptr;
+      obptr = obuf;
+#ifdef IMAGE_8BPP
+      for (x = 0; x < width; x += 1)
+       {
+         r = *bp2++;
+         g = *bp2++;
+         b = *bp2++;
+         dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
+         obptr[0] = colorcube_d[(((r + dith) & 0x100) >> 2) |
+                               (((g + 258 - dith) & 0x100) >> 5) |
+                               (((b + dith) & 0x100) >> 8)];
+         obptr++;
+       }
+#else
+      for (x = 0; x < width; x += 2)
+       {
+         r = *bp2++;
+         g = *bp2++;
+         b = *bp2++;
+         dith = (dmp[(x_align + x) & (DM_WIDTH - 1)] << 2) | 3;
+         pix0 = colorcube_d[(((r + dith) & 0x100) >> 2) |
+                           (((g + dith) & 0x100) >> 5) |
+                           (((b + dith) & 0x100) >> 8)];
+         r = *bp2++;
+         g = *bp2++;
+         b = *bp2++;
+         dith = (dmp[(x_align + x + 1) & (DM_WIDTH - 1)] << 2) | 3;
+         pix1 = colorcube_d[(((r + dith) & 0x100) >> 2) |
+                           (((g + dith) & 0x100) >> 5) |
+                           (((b + dith) & 0x100) >> 8)];
+         obptr[0] = (pix0 << 4) | pix1;
+         obptr++;
+       }
+#endif
+      bptr += rowstride;
+      obuf += bpl;
+    }
+}
+
+
 /* Returns a pointer to the stage buffer. */
 static guchar *
 gdk_rgb_ensure_stage (void)
@@ -2084,7 +2188,7 @@ gdk_rgb_32_to_stage (guchar *buf, gint rowstride, gint width, gint height)
   gint x, y;
   guchar *pi_start, *po_start;
   guchar *pi, *po;
-  
+
   pi_start = buf;
   po_start = gdk_rgb_ensure_stage ();
   for (y = 0; y < height; y++)
@@ -2112,7 +2216,7 @@ gdk_rgb_convert_32_generic (GdkImage *image,
                            gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   gdk_rgb_32_to_stage (buf, rowstride, width, height);
-  
+
   (*image_info->conv) (image, x0, y0, width, height,
                       image_info->stage_buf, STAGE_ROWSTRIDE,
                       x_align, y_align, cmap);
@@ -2127,7 +2231,7 @@ gdk_rgb_convert_32_generic_d (GdkImage *image,
                              gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   gdk_rgb_32_to_stage (buf, rowstride, width, height);
-  
+
   (*image_info->conv_d) (image, x0, y0, width, height,
                         image_info->stage_buf, STAGE_ROWSTRIDE,
                         x_align, y_align, cmap);
@@ -2141,7 +2245,7 @@ gdk_rgb_gray_to_stage (guchar *buf, gint rowstride, gint width, gint height)
   guchar *pi_start, *po_start;
   guchar *pi, *po;
   guchar gray;
-  
+
   pi_start = buf;
   po_start = gdk_rgb_ensure_stage ();
   for (y = 0; y < height; y++)
@@ -2169,7 +2273,7 @@ gdk_rgb_convert_gray_generic (GdkImage *image,
                              gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   gdk_rgb_gray_to_stage (buf, rowstride, width, height);
-  
+
   (*image_info->conv) (image, x0, y0, width, height,
                       image_info->stage_buf, STAGE_ROWSTRIDE,
                       x_align, y_align, cmap);
@@ -2182,7 +2286,7 @@ gdk_rgb_convert_gray_generic_d (GdkImage *image,
                                gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   gdk_rgb_gray_to_stage (buf, rowstride, width, height);
-  
+
   (*image_info->conv_d) (image, x0, y0, width, height,
                         image_info->stage_buf, STAGE_ROWSTRIDE,
                         x_align, y_align, cmap);
@@ -2203,9 +2307,9 @@ gdk_rgb_convert_gray_cmap (GdkImage *image,
 #if 0
 static void
 gdk_rgb_convert_gray_cmap_d (GdkImage *image,
-                            gint x0, gint y0, gint width, gint height,
-                            guchar *buf, gint rowstride,
-                            gint x_align, gint y_align, GdkRgbCmap *cmap)
+                               gint x0, gint y0, gint width, gint height,
+                               guchar *buf, gint rowstride,
+                               gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   (*image_info->conv_indexed_d) (image, x0, y0, width, height,
                                 buf, rowstride,
@@ -2222,7 +2326,7 @@ gdk_rgb_indexed_to_stage (guchar *buf, gint rowstride, gint width, gint height,
   guchar *pi_start, *po_start;
   guchar *pi, *po;
   gint rgb;
-  
+
   pi_start = buf;
   po_start = gdk_rgb_ensure_stage ();
   for (y = 0; y < height; y++)
@@ -2250,7 +2354,7 @@ gdk_rgb_convert_indexed_generic (GdkImage *image,
                                 gint x_align, gint y_align, GdkRgbCmap *cmap)
 {
   gdk_rgb_indexed_to_stage (buf, rowstride, width, height, cmap);
-  
+
   (*image_info->conv) (image, x0, y0, width, height,
                       image_info->stage_buf, STAGE_ROWSTRIDE,
                       x_align, y_align, cmap);
@@ -2264,7 +2368,7 @@ gdk_rgb_convert_indexed_generic_d (GdkImage *image,
                                   GdkRgbCmap *cmap)
 {
   gdk_rgb_indexed_to_stage (buf, rowstride, width, height, cmap);
-  
+
   (*image_info->conv_d) (image, x0, y0, width, height,
                         image_info->stage_buf, STAGE_ROWSTRIDE,
                         x_align, y_align, cmap);
@@ -2283,40 +2387,40 @@ gdk_rgb_select_conv (GdkImage *image)
   GdkRgbConvFunc conv_32, conv_32_d;
   GdkRgbConvFunc conv_gray, conv_gray_d;
   GdkRgbConvFunc conv_indexed, conv_indexed_d;
-  
+
   depth = image_info->visual->depth;
   bpp = image->bpp;
-  
+
   byte_order = image->byte_order;
-  
+
 #ifdef WORDS_BIGENDIAN
   byterev = (byte_order == GDK_LSB_FIRST);
 #else
   byterev = (byte_order == GDK_MSB_FIRST);
 #endif
-  
+
   vtype = image_info->visual->type;
   if (vtype == GDK_VISUAL_DIRECT_COLOR)
     vtype = GDK_VISUAL_TRUE_COLOR;
-  
+
   red_mask = image_info->visual->red_mask;
   green_mask = image_info->visual->green_mask;
   blue_mask = image_info->visual->blue_mask;
-  
+
   conv = NULL;
   conv_d = NULL;
-  
+
   conv_32 = gdk_rgb_convert_32_generic;
   conv_32_d = gdk_rgb_convert_32_generic_d;
-  
+
   conv_gray = gdk_rgb_convert_gray_generic;
   conv_gray_d = gdk_rgb_convert_gray_generic_d;
-  
+
   conv_indexed = gdk_rgb_convert_indexed_generic;
   conv_indexed_d = gdk_rgb_convert_indexed_generic_d;
-  
+
   image_info->dith_default = FALSE;
-  
+
   if (bpp == 2 && depth == 16 && !byterev &&
       red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f)
     {
@@ -2327,19 +2431,19 @@ gdk_rgb_select_conv (GdkImage *image)
     }
   else if (bpp == 2 && depth == 16 &&
           vtype == GDK_VISUAL_TRUE_COLOR && byterev &&
-          red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f)
+      red_mask == 0xf800 && green_mask == 0x7e0 && blue_mask == 0x1f)
     conv = gdk_rgb_convert_565_br;
-  
+
   else if (bpp == 2 && depth == 15 &&
           vtype == GDK_VISUAL_TRUE_COLOR && !byterev &&
-          red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
+      red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
     conv = gdk_rgb_convert_555;
-  
+
   else if (bpp == 2 && depth == 15 &&
           vtype == GDK_VISUAL_TRUE_COLOR && byterev &&
-          red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
+      red_mask == 0x7c00 && green_mask == 0x3e0 && blue_mask == 0x1f)
     conv = gdk_rgb_convert_555_br;
-  
+
   /* I'm not 100% sure about the 24bpp tests */
   else if (bpp == 3 && depth == 24 &&
           vtype == GDK_VISUAL_TRUE_COLOR && byte_order == GDK_LSB_FIRST &&
@@ -2357,7 +2461,7 @@ gdk_rgb_select_conv (GdkImage *image)
           vtype == GDK_VISUAL_TRUE_COLOR && byterev &&
           red_mask == 0xff0000 && green_mask == 0xff00 && blue_mask == 0xff)
     conv = gdk_rgb_convert_0888_br;
-  
+
   else if (vtype == GDK_VISUAL_TRUE_COLOR && byte_order == GDK_LSB_FIRST)
     {
       conv = gdk_rgb_convert_truecolor_lsb;
@@ -2397,19 +2501,23 @@ gdk_rgb_select_conv (GdkImage *image)
       conv = gdk_rgb_convert_gray8;
       conv_gray = gdk_rgb_convert_gray8_gray;
     }
-  
+  else if (depth == 4)
+    {
+      conv = gdk_rgb_convert_4;
+    }
+
   if (conv_d == NULL)
     conv_d = conv;
-  
+
   image_info->conv = conv;
   image_info->conv_d = conv_d;
-  
+
   image_info->conv_32 = conv_32;
   image_info->conv_32_d = conv_32_d;
-  
+
   image_info->conv_gray = conv_gray;
   image_info->conv_gray_d = conv_gray_d;
-  
+
   image_info->conv_indexed = conv_indexed;
   image_info->conv_indexed_d = conv_indexed_d;
 }
@@ -2441,7 +2549,7 @@ gdk_rgb_alloc_scratch_image (void)
       gdk_flush ();
 #endif
 #ifdef VERBOSE
-      g_message ("flush, %d puts since last flush", sincelast);
+      g_print ("flush, %d puts since last flush\n", sincelast);
       sincelast = 0;
 #endif
       static_image_idx = 0;
@@ -2458,8 +2566,8 @@ gdk_rgb_alloc_scratch (gint width, gint height, gint *x0, gint *y0)
 {
   GdkImage *image;
   gint idx;
-  
-  
+
+
   if (width >= (IMAGE_WIDTH >> 1))
     {
       if (height >= (IMAGE_HEIGHT >> 1))
@@ -2519,7 +2627,7 @@ gdk_rgb_alloc_scratch (gint width, gint height, gint *x0, gint *y0)
     }
   image = static_image[idx];
 #ifdef VERBOSE
-  g_message ("index %d, x %d, y %d (%d x %d)", idx, *x0, *y0, width, height);
+  g_print ("index %d, x %d, y %d (%d x %d)\n", idx, *x0, *y0, width, height);
   sincelast++;
 #endif
   return image;
@@ -2543,7 +2651,7 @@ gdk_draw_rgb_image_core (GdkDrawable *drawable,
   GdkImage *image;
   gint width1, height1;
   guchar *buf_ptr;
-  
+
   for (y0 = 0; y0 < height; y0 += IMAGE_HEIGHT)
     {
       height1 = MIN (height - y0, IMAGE_HEIGHT);
@@ -2551,12 +2659,12 @@ gdk_draw_rgb_image_core (GdkDrawable *drawable,
        {
          width1 = MIN (width - x0, IMAGE_WIDTH);
          buf_ptr = buf + y0 * rowstride + x0 * pixstride;
-         
+
          image = gdk_rgb_alloc_scratch (width1, height1, &xs0, &ys0);
-         
+
          conv (image, xs0, ys0, width1, height1, buf_ptr, rowstride,
                x + x0, y + y0, cmap);
-         
+
 #ifndef DONT_ACTUALLY_DRAW
          gdk_draw_image (drawable, gc,
                          image, xs0, ys0, x + x0, y + y0, width1, height1);
@@ -2613,9 +2721,9 @@ gdk_rgb_make_gray_cmap (GdkRgbInfo *info)
 {
   guint32 rgb[256];
   gint i;
-  
+
   for (i = 0; i < 256; i++)
-    rgb[i] = (i << 16) | (i << 8) | i;
+    rgb[i] = (i << 16)  | (i << 8) | i;
   info->gray_cmap = gdk_rgb_cmap_new (rgb, 256);
 }
 
@@ -2653,7 +2761,7 @@ gdk_rgb_cmap_new (guint32 *colors, gint n_colors)
   GdkRgbCmap *cmap;
   int i, j;
   guint32 rgb;
-  
+
   g_return_val_if_fail (n_colors >= 0, NULL);
   g_return_val_if_fail (n_colors <= 256, NULL);
   cmap = g_new (GdkRgbCmap, 1);
@@ -2665,10 +2773,10 @@ gdk_rgb_cmap_new (guint32 *colors, gint n_colors)
       {
        rgb = colors[i];
        j = ((rgb & 0xf00000) >> 12) |
-         ((rgb & 0xf000) >> 8) |
-         ((rgb & 0xf0) >> 4);
+                  ((rgb & 0xf000) >> 8) |
+                  ((rgb & 0xf0) >> 4);
 #ifdef VERBOSE
-       g_message ("%d %x %x %d", i, j, colorcube[j]);
+       g_print ("%d %x %x %d\n", i, j, colorcube[j]);
 #endif
        cmap->lut[i] = colorcube[j];
       }
index 9dc9b2973c35cc11f4c6d9c7abab2ad1259e5585..6490fca6da24e6a14d3919d2482a7ab14c34cdfc 100644 (file)
 #include <sys/types.h>
 #include <sys/param.h>
 #include "gdk/gdkx.h"
+#include "gdk/gdkrgb.h"
 #include "gtkpreview.h"
 #include "gtksignal.h"
 
 
-#define IMAGE_SIZE            256
 #define PREVIEW_CLASS(w)      GTK_PREVIEW_CLASS (GTK_OBJECT (w)->klass)
-#define COLOR_COMPOSE(r,g,b)  (lookup_red[r] | lookup_green[g] | lookup_blue[b])
-
-
-typedef struct _GtkPreviewProp  GtkPreviewProp;
-typedef void (*GtkTransferFunc) (guchar *dest, guchar *src, gint count);
-
-struct _GtkPreviewProp
-{
-  guint16 ref_count;
-  guint16 nred_shades;
-  guint16 ngreen_shades;
-  guint16 nblue_shades;
-  guint16 ngray_shades;
-};
 
 
 static void   gtk_preview_class_init    (GtkPreviewClass  *klass);
@@ -51,77 +37,10 @@ static void   gtk_preview_realize       (GtkWidget        *widget);
 static gint   gtk_preview_expose        (GtkWidget        *widget,
                                         GdkEventExpose   *event);
 static void   gtk_preview_make_buffer   (GtkPreview       *preview);
-static void   gtk_preview_get_visuals   (GtkPreviewClass  *klass);
-static void   gtk_preview_get_cmaps     (GtkPreviewClass  *klass);
-static void   gtk_preview_dither_init   (GtkPreviewClass  *klass);
-static void   gtk_fill_lookup_array     (gulong           *array,
-                                        int               depth,
-                                        int               shift,
-                                        int               prec);
-static void   gtk_trim_cmap             (GtkPreviewClass  *klass);
-static void   gtk_create_8_bit          (GtkPreviewClass  *klass);
-
-static void   gtk_color_8               (guchar           *src,
-                                        guchar           *data,
-                                        gint              x,
-                                        gint              y,
-                                        gulong            width);
-static void   gtk_color_16              (guchar           *src,
-                                        guchar           *data,
-                                        gulong            width);
-static void   gtk_color_24              (guchar           *src,
-                                        guchar           *data,
-                                        gulong            width);
-static void   gtk_grayscale_8           (guchar           *src,
-                                        guchar           *data,
-                                        gint              x,
-                                        gint              y,
-                                        gulong            width);
-static void   gtk_grayscale_16          (guchar           *src,
-                                        guchar           *data,
-                                        gulong            width);
-static void   gtk_grayscale_24          (guchar           *src,
-                                        guchar           *data,
-                                        gulong            width);
-
-static gint   gtk_get_preview_prop      (guint            *nred,
-                                        guint            *nblue,
-                                        guint            *ngreen,
-                                        guint            *ngray);
-static void   gtk_set_preview_prop      (guint             nred,
-                                        guint             ngreen,
-                                        guint             nblue,
-                                        guint             ngray);
-
-/* transfer functions:
- *  destination byte order/source bpp/destination bpp
- */
-static void   gtk_lsbmsb_1_1            (guchar           *dest,
-                                        guchar           *src,
-                                        gint              count);
-static void   gtk_lsb_2_2               (guchar           *dest,
-                                        guchar           *src,
-                                        gint              count);
-static void   gtk_msb_2_2               (guchar           *dest,
-                                        guchar           *src,
-                                        gint              count);
-static void   gtk_lsb_3_3               (guchar           *dest,
-                                        guchar           *src,
-                                        gint              count);
-static void   gtk_msb_3_3               (guchar           *dest,
-                                        guchar           *src,
-                                        gint              count);
-static void   gtk_lsb_3_4               (guchar           *dest,
-                                        guchar           *src,
-                                        gint              count);
-static void   gtk_msb_3_4               (guchar           *dest,
-                                        guchar           *src,
-                                        gint              count);
-
+static void   gtk_fill_lookup_array     (guchar           *array);
 
 static GtkWidgetClass *parent_class = NULL;
 static GtkPreviewClass *preview_class = NULL;
-static GtkPreviewInfo *preview_info = NULL;
 static gint install_cmap = FALSE;
 
 
@@ -167,113 +86,22 @@ gtk_preview_class_init (GtkPreviewClass *klass)
   widget_class->realize = gtk_preview_realize;
   widget_class->expose_event = gtk_preview_expose;
 
-  if (preview_info)
-    klass->info = *preview_info;
-  else
-    {
-      klass->info.visual = NULL;
-      klass->info.cmap = NULL;
-
-      klass->info.color_pixels = NULL;
-      klass->info.gray_pixels = NULL;
-      klass->info.reserved_pixels = NULL;
-
-      klass->info.lookup_red = NULL;
-      klass->info.lookup_green = NULL;
-      klass->info.lookup_blue = NULL;
-
-      klass->info.dither_red = NULL;
-      klass->info.dither_green = NULL;
-      klass->info.dither_blue = NULL;
-      klass->info.dither_gray = NULL;
-      klass->info.dither_matrix = NULL;
-
-      klass->info.nred_shades = 6;
-      klass->info.ngreen_shades = 6;
-      klass->info.nblue_shades = 4;
-      klass->info.ngray_shades = 24;
-      klass->info.nreserved = 0;
-
-      klass->info.bpp = 0;
-      klass->info.cmap_alloced = FALSE;
-      klass->info.gamma = 1.0;
-    }
+  klass->info.visual = NULL;
+  klass->info.cmap = NULL;
 
-  klass->image = NULL;
+  klass->info.lookup = NULL;
 
-  gtk_preview_get_visuals (klass);
-  gtk_preview_get_cmaps (klass);
-  gtk_preview_dither_init (klass);
+  klass->info.gamma = 1.0;
+
+  gdk_rgb_init ();
+  klass->info.cmap = gdk_rgb_get_cmap ();
+  klass->info.visual = gdk_rgb_get_visual ();
 }
 
 void
 gtk_preview_reset (void)
 {
-  GtkPreviewInfo *info;
-
-  if (!preview_class || !preview_info)
-    return;
-  
-  info = &preview_class->info;
-
-  gtk_preview_uninit();
-
-  if (info->color_pixels)
-    {
-      gdk_colors_free (info->cmap,
-                      info->color_pixels,
-                      info->nred_shades *
-                        info->ngreen_shades *
-                        info->nblue_shades, 
-                      0);
-
-      gdk_colors_free (info->cmap,
-                      info->gray_pixels,
-                      info->ngray_shades, 0);
-      
-      g_free (info->color_pixels);
-      g_free (info->gray_pixels);
-    }
-
-  if (info->reserved_pixels)
-    {
-      gdk_colors_free (info->cmap,
-                      info->reserved_pixels,
-                      info->nreserved, 0);
-      g_free (info->reserved_pixels);
-    }
-
-  if (info->cmap && info->cmap_alloced)
-    gdk_colormap_unref (info->cmap);
-
-  if (info->lookup_red)
-    {
-      g_free (info->lookup_red);
-      g_free (info->lookup_green);
-      g_free (info->lookup_blue);
-    }
-
-  if (info->dither_matrix)
-    {
-      int i, j;
-
-      for (i= 0 ; i < 8 ; i++)
-       {
-         for (j = 0; j < 8 ; j++)
-           g_free (info->dither_matrix[i][j]);
-         g_free (info->dither_matrix[i]);
-       }
-      g_free (info->dither_matrix);
-      g_free (info->dither_red);
-      g_free (info->dither_green);
-      g_free (info->dither_blue);
-    }
-
-  preview_class->info = *preview_info;
-
-  gtk_preview_get_visuals (preview_class);
-  gtk_preview_get_cmaps (preview_class);
-  gtk_preview_dither_init (preview_class);
+  /* unimplemented */
 }
 
 static void
@@ -290,34 +118,8 @@ gtk_preview_init (GtkPreview *preview)
 void
 gtk_preview_uninit (void)
 {
-  GtkPreviewProp *prop;
-  GdkAtom property;
-
-  /* FIXME: need to grab the server here to prevent a race condition */
-
-  if (preview_class && !install_cmap && preview_class->info.visual &&
-      (preview_class->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
-      (preview_class->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
-    {
-      property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
 
-      if (gdk_property_get (NULL, property, property,
-                           0, sizeof (GtkPreviewProp), FALSE,
-                           NULL, NULL, NULL, (guchar**) &prop))
-       {
-         prop->ref_count = prop->ref_count - 1;
-         if (prop->ref_count == 0)
-           {
-             gdk_property_delete (NULL, property);
-           }
-         else
-           {
-             gdk_property_change (NULL, property, property, 16,
-                                  GDK_PROP_MODE_REPLACE,
-                                  (guchar*) prop, 5);
-           }
-       }
-    }
+  /* unimplemented */
 }
 
 GtkWidget*
@@ -328,6 +130,13 @@ gtk_preview_new (GtkPreviewType type)
   preview = gtk_type_new (gtk_preview_get_type ());
   preview->type = type;
 
+  if (type == GTK_PREVIEW_COLOR)
+    preview->bpp = 3;
+  else
+    preview->bpp = 1;
+
+  preview->dither = GDK_RGB_DITHER_NORMAL;
+
   return GTK_WIDGET (preview);
 }
 
@@ -363,17 +172,10 @@ gtk_preview_put (GtkPreview   *preview,
                 gint          height)
 {
   GtkWidget *widget;
-  GdkImage *image;
   GdkRectangle r1, r2, r3;
-  GtkTransferFunc transfer_func;
-  guchar *image_mem;
-  guchar *src, *dest;
-  gint x, xe, x2;
-  gint y, ye, y2;
-  guint dest_rowstride;
-  guint src_bpp;
-  guint dest_bpp;
-  gint i;
+  guchar *src;
+  guint bpp;
+  guint rowstride;
 
   g_return_if_fail (preview != NULL);
   g_return_if_fail (GTK_IS_PREVIEW (preview));
@@ -397,106 +199,32 @@ gtk_preview_put (GtkPreview   *preview,
   if (!gdk_rectangle_intersect (&r1, &r2, &r3))
     return;
 
-  x2 = r3.x + r3.width;
-  y2 = r3.y + r3.height;
-
-  if (!preview_class->image)
-    preview_class->image = gdk_image_new (GDK_IMAGE_FASTEST,
-                                         preview_class->info.visual,
-                                         IMAGE_SIZE, IMAGE_SIZE);
-  image = preview_class->image;
-  src_bpp = preview_class->info.bpp;
-
-  image_mem = image->mem;
-  dest_bpp = image->bpp;
-  dest_rowstride = image->bpl;
-
-  transfer_func = NULL;
-
-  switch (dest_bpp)
-    {
-    case 1:
-      switch (src_bpp)
-       {
-       case 1:
-         transfer_func = gtk_lsbmsb_1_1;
-         break;
-       }
-      break;
-    case 2:
-      switch (src_bpp)
-       {
-       case 2:
-         if (image->byte_order == GDK_MSB_FIRST)
-           transfer_func = gtk_msb_2_2;
-         else
-           transfer_func = gtk_lsb_2_2;
-         break;
-       case 3:
-         break;
-       }
-      break;
-    case 3:
-      switch (src_bpp)
-       {
-       case 3:
-         if (image->byte_order == GDK_MSB_FIRST)
-           transfer_func = gtk_msb_3_3;
-         else
-           transfer_func = gtk_lsb_3_3;
-         break;
-       }
-      break;
-    case 4:
-      switch (src_bpp)
-       {
-       case 3:
-         if (image->byte_order == GDK_MSB_FIRST)
-           transfer_func = gtk_msb_3_4;
-         else
-           transfer_func = gtk_lsb_3_4;
-         break;
-       }
-      break;
-    }
-
-  if (!transfer_func)
-    {
-      g_warning ("unsupported byte order/src bpp/dest bpp combination: %s:%d:%d",
-                (image->byte_order == GDK_MSB_FIRST) ? "msb" : "lsb", src_bpp, dest_bpp);
-      return;
-    }
-
-  for (y = r3.y; y < y2; y += IMAGE_SIZE)
-    {
-      for (x = r3.x; x < x2; x += IMAGE_SIZE)
-       {
-         xe = x + IMAGE_SIZE;
-         if (xe > x2)
-           xe = x2;
-
-         ye = y + IMAGE_SIZE;
-         if (ye > y2)
-           ye = y2;
-
-         for (i = y; i < ye; i++)
-           {
-             src = preview->buffer + (((gulong) (i - r1.y) * (gulong) preview->buffer_width) +
-                                      (x - r1.x)) * (gulong) src_bpp;
-             dest = image_mem + ((gulong) (i - y) * dest_rowstride);
-
-             if (xe > x)
-               (* transfer_func) (dest, src, xe - x);
-           }
-
-         gdk_draw_image (window, gc,
-                         image, 0, 0,
-                         destx + (r3.x - srcx) + (x - r3.x),
-                         desty + (r3.y - srcy) + (y - r3.y),
-                         xe - x, ye - y);
-         gdk_flush ();
-       }
-    }
+  bpp = preview->bpp;
+  rowstride = preview->rowstride;
+
+  src = preview->buffer + r3.y * rowstride + r3.x * bpp;
+
+  if (preview->type == GTK_PREVIEW_COLOR)
+    gdk_draw_rgb_image (window,
+                       gc,
+                       destx + (r3.x - srcx),
+                       desty + (r3.y - srcy),
+                       r3.width,
+                       r3.height,
+                       preview->dither,
+                       src,
+                       rowstride);
+  else
+    gdk_draw_gray_image (window,
+                        gc,
+                        destx + (r3.x - srcx),
+                        desty + (r3.y - srcy),
+                        r3.width,
+                        r3.height,
+                        preview->dither,
+                        src,
+                        rowstride);
+                       
 }
 
 void
@@ -507,46 +235,7 @@ gtk_preview_put_row (GtkPreview *preview,
                     gint        y,
                     gint        w)
 {
-  g_return_if_fail (preview != NULL);
-  g_return_if_fail (GTK_IS_PREVIEW (preview));
-  g_return_if_fail (src != NULL);
-  g_return_if_fail (dest != NULL);
-
-  switch (preview->type)
-    {
-    case GTK_PREVIEW_COLOR:
-      switch (preview_class->info.visual->depth)
-       {
-       case 8:
-         gtk_color_8 (src, dest, x, y, w);
-         break;
-       case 15:
-       case 16:
-         gtk_color_16 (src, dest, w);
-         break;
-       case 24:
-       case 32:
-         gtk_color_24 (src, dest, w);
-         break;
-       }
-      break;
-    case GTK_PREVIEW_GRAYSCALE:
-      switch (preview_class->info.visual->depth)
-       {
-       case 8:
-         gtk_grayscale_8 (src, dest, x, y, w);
-         break;
-       case 15:
-       case 16:
-         gtk_grayscale_16 (src, dest, w);
-         break;
-       case 24:
-       case 32:
-         gtk_grayscale_24 (src, dest, w);
-         break;
-       }
-      break;
-    }
+  g_warning ("gtk_preview_put_row not implemented (deprecated)\n");
 }
 
 void
@@ -556,13 +245,17 @@ gtk_preview_draw_row (GtkPreview *preview,
                      gint        y,
                      gint        w)
 {
-  guchar *dest;
+  guint bpp;
+  guint rowstride;
 
   g_return_if_fail (preview != NULL);
   g_return_if_fail (GTK_IS_PREVIEW (preview));
   g_return_if_fail (data != NULL);
   g_return_if_fail (preview_class->info.visual != NULL);
   
+  bpp = (preview->type == GTK_PREVIEW_COLOR ? 3 : 1);
+  rowstride = (preview->buffer_width * bpp + 3) & -4;
+
   if ((w <= 0) || (y < 0))
     return;
 
@@ -570,49 +263,33 @@ gtk_preview_draw_row (GtkPreview *preview,
 
   gtk_preview_make_buffer (preview);
 
-  if (y >= preview->buffer_height)
+  if (x + w > preview->buffer_width)
+    return;
+
+  if (y + 1 > preview->buffer_height)
     return;
 
-  switch (preview->type)
+  if (preview_class->info.gamma == 1.0)
+    memcpy (preview->buffer + y * rowstride + x * bpp, data, w * bpp);
+  else
     {
-    case GTK_PREVIEW_COLOR:
-      switch (preview_class->info.visual->depth)
-       {
-       case 8:
-         dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
-         gtk_color_8 (data, dest, x, y, w);
-         break;
-       case 15:
-       case 16:
-         dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
-         gtk_color_16 (data, dest, w);
-         break;
-       case 24:
-       case 32:
-         dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
-         gtk_color_24 (data, dest, w);
-         break;
-       }
-      break;
-    case GTK_PREVIEW_GRAYSCALE:
-      switch (preview_class->info.visual->depth)
+      guint i, size;
+      guchar *src, *dst;
+      guchar *lookup;
+
+      if (preview_class->info.lookup != NULL)
+       lookup = preview_class->info.lookup;
+      else
        {
-       case 8:
-         dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
-         gtk_grayscale_8 (data, dest, x, y, w);
-         break;
-       case 15:
-       case 16:
-         dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
-         gtk_grayscale_16 (data, dest, w);
-         break;
-       case 24:
-       case 32:
-         dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
-         gtk_grayscale_24 (data, dest, w);
-         break;
+         preview_class->info.lookup = g_new (guchar, 256);
+         gtk_fill_lookup_array (preview_class->info.lookup);
+         lookup = preview_class->info.lookup;
        }
-      break;
+      size = w * bpp;
+      src = data;
+      dst = preview->buffer + y * rowstride + x * bpp;
+      for (i = 0; i < size; i++)
+       *dst++ = lookup[*src++];
     }
 }
 
@@ -629,16 +306,18 @@ gtk_preview_set_expand (GtkPreview *preview,
 void
 gtk_preview_set_gamma (double _gamma)
 {
-  if (!preview_info)
+  if (!preview_class)
+    preview_class = gtk_type_class (gtk_preview_get_type ());
+
+  if (preview_class->info.gamma != _gamma)
     {
-      preview_info = g_new0 (GtkPreviewInfo, 1);
-      preview_info->nred_shades = 6;
-      preview_info->ngreen_shades = 6;
-      preview_info->nblue_shades = 4;
-      preview_info->ngray_shades = 24;
+      preview_class->info.gamma = _gamma;
+      if (preview_class->info.lookup != NULL)
+       {
+         g_free (preview_class->info.lookup);
+         preview_class->info.lookup = NULL;
+       }
     }
-
-  preview_info->gamma = _gamma;
 }
 
 void
@@ -647,31 +326,28 @@ gtk_preview_set_color_cube (guint nred_shades,
                            guint nblue_shades,
                            guint ngray_shades)
 {
-  if (!preview_info)
-    {
-      preview_info = g_new0 (GtkPreviewInfo, 1);
-      preview_info->gamma = 1.0;
-    }
-
-  preview_info->nred_shades = nred_shades;
-  preview_info->ngreen_shades = ngreen_shades;
-  preview_info->nblue_shades = nblue_shades;
-  preview_info->ngray_shades = ngray_shades;
+  /* unimplemented */
 }
 
 void
 gtk_preview_set_install_cmap (gint _install_cmap)
 {
+  /* effectively unimplemented */
   install_cmap = _install_cmap;
 }
 
 void
 gtk_preview_set_reserved (gint nreserved)
 {
-  if (!preview_info)
-    preview_info = g_new0 (GtkPreviewInfo, 1);
 
-  preview_info->nreserved = nreserved;
+  /* unimplemented */
+}
+
+void
+gtk_preview_set_dither (GtkPreview      *preview,
+                       GdkRgbDither     dither)
+{
+  preview->dither = dither;
 }
 
 GdkVisual*
@@ -811,837 +487,28 @@ gtk_preview_make_buffer (GtkPreview *preview)
       preview->buffer_width = width;
       preview->buffer_height = height;
 
+      preview->rowstride = (preview->buffer_width * preview->bpp + 3) & -4;
       preview->buffer = g_new0 (guchar,
-                               preview->buffer_width *
                                preview->buffer_height *
-                               preview_class->info.bpp);
-    }
-}
-
-static void
-gtk_preview_get_visuals (GtkPreviewClass *klass)
-{
-  static GdkVisualType types[] =
-  {
-    GDK_VISUAL_TRUE_COLOR,
-    GDK_VISUAL_DIRECT_COLOR,
-    GDK_VISUAL_TRUE_COLOR,
-    GDK_VISUAL_DIRECT_COLOR,
-    GDK_VISUAL_TRUE_COLOR,
-    GDK_VISUAL_DIRECT_COLOR,
-    GDK_VISUAL_TRUE_COLOR,
-    GDK_VISUAL_DIRECT_COLOR,
-    GDK_VISUAL_PSEUDO_COLOR,
-    GDK_VISUAL_STATIC_COLOR,
-    GDK_VISUAL_STATIC_GRAY
-  };
-  static gint depths[] = { 24, 24, 32, 32, 16, 16, 15, 15, 8, 4, 1 };
-  static gint nvisual_types = sizeof (types) / sizeof (types[0]);
-
-  int i;
-
-  g_return_if_fail (klass != NULL);
-
-  if (!klass->info.visual)
-    for (i = 0; i < nvisual_types; i++)
-      if ((klass->info.visual = gdk_visual_get_best_with_both (depths[i], types[i])))
-       {
-         if ((klass->info.visual->type == GDK_VISUAL_TRUE_COLOR) ||
-             (klass->info.visual->type == GDK_VISUAL_DIRECT_COLOR))
-           {
-             klass->info.lookup_red = g_new (gulong, 256);
-             klass->info.lookup_green = g_new (gulong, 256);
-             klass->info.lookup_blue = g_new (gulong, 256);
-
-             gtk_fill_lookup_array (klass->info.lookup_red,
-                                    klass->info.visual->depth,
-                                    klass->info.visual->red_shift,
-                                    8 - klass->info.visual->red_prec);
-             gtk_fill_lookup_array (klass->info.lookup_green,
-                                    klass->info.visual->depth,
-                                    klass->info.visual->green_shift,
-                                    8 - klass->info.visual->green_prec);
-             gtk_fill_lookup_array (klass->info.lookup_blue,
-                                    klass->info.visual->depth,
-                                    klass->info.visual->blue_shift,
-                                    8 - klass->info.visual->blue_prec);
-           }
-         break;
-       }
-
-  if (!klass->info.visual)
-    {
-      g_warning ("unable to find a suitable visual for color image display.\n");
-      return;
-    }
-
-  /* If we are _not_ running with an installed cmap, we must run
-   * with the system visual. Otherwise, we let GDK pick the visual,
-   * and it makes some effort to pick a non-default visual, which
-   * will hopefully provide minimum color flashing.
-   */
-  if ((klass->info.visual->depth == gdk_visual_get_system()->depth) &&
-      (klass->info.visual->type == gdk_visual_get_system()->type) &&
-      !install_cmap)
-    {
-      klass->info.visual = gdk_visual_get_system();
-    }
-    
-  switch (klass->info.visual->depth)
-    {
-    case 1:
-    case 4:
-    case 8:
-      klass->info.bpp = 1;
-      break;
-    case 15:
-    case 16:
-      klass->info.bpp = 2;
-      break;
-    case 24:
-    case 32:
-      klass->info.bpp = 3;
-      break;
-    }
-}
-
-static void
-gtk_preview_get_cmaps (GtkPreviewClass *klass)
-{
-  g_return_if_fail (klass != NULL);
-  g_return_if_fail (klass->info.visual != NULL);
-
-  if ((klass->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
-      (klass->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
-    {
-      if (install_cmap)
-       {
-         klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
-         klass->info.cmap_alloced = install_cmap;
-
-         gtk_trim_cmap (klass);
-         gtk_create_8_bit (klass);
-       }
-      else
-       {
-         guint nred;
-         guint ngreen;
-         guint nblue;
-         guint ngray;
-         gint set_prop;
-
-         klass->info.cmap = gdk_colormap_get_system ();
-
-         set_prop = TRUE;
-         if (gtk_get_preview_prop (&nred, &ngreen, &nblue, &ngray))
-           {
-             set_prop = FALSE;
-
-             klass->info.nred_shades = nred;
-             klass->info.ngreen_shades = ngreen;
-             klass->info.nblue_shades = nblue;
-             klass->info.ngray_shades = ngray;
-
-             if (klass->info.nreserved)
-               {
-                 klass->info.reserved_pixels = g_new (gulong, klass->info.nreserved);
-                 if (!gdk_colors_alloc (klass->info.cmap, 0, NULL, 0,
-                                        klass->info.reserved_pixels,
-                                        klass->info.nreserved))
-                   {
-                     g_free (klass->info.reserved_pixels);
-                     klass->info.reserved_pixels = NULL;
-                   }
-               }
-           }
-         else
-           {
-             gtk_trim_cmap (klass);
-           }
-
-         gtk_create_8_bit (klass);
-
-         if (set_prop)
-           gtk_set_preview_prop (klass->info.nred_shades,
-                                 klass->info.ngreen_shades,
-                                 klass->info.nblue_shades,
-                                 klass->info.ngray_shades);
-       }
-    }
-  else
-    {
-      if (klass->info.visual == gdk_visual_get_system ())
-       klass->info.cmap = gdk_colormap_get_system ();
-      else
-       {
-         klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
-         klass->info.cmap_alloced = TRUE;
-       }
-
-      klass->info.nred_shades = 0;
-      klass->info.ngreen_shades = 0;
-      klass->info.nblue_shades = 0;
-      klass->info.ngray_shades = 0;
-    }
-}
-
-static void
-gtk_preview_dither_init (GtkPreviewClass *klass)
-{
-  int i, j, k;
-  unsigned char low_shade, high_shade;
-  unsigned short index;
-  long red_mult, green_mult;
-  double red_matrix_width;
-  double green_matrix_width;
-  double blue_matrix_width;
-  double gray_matrix_width;
-  double red_colors_per_shade;
-  double green_colors_per_shade;
-  double blue_colors_per_shade;
-  double gray_colors_per_shade;
-  gulong *gray_pixels;
-  gint shades_r, shades_g, shades_b, shades_gray;
-  GtkDitherInfo *red_ordered_dither;
-  GtkDitherInfo *green_ordered_dither;
-  GtkDitherInfo *blue_ordered_dither;
-  GtkDitherInfo *gray_ordered_dither;
-  guchar ***dither_matrix;
-  guchar DM[8][8] =
-  {
-    { 0,  32, 8,  40, 2,  34, 10, 42 },
-    { 48, 16, 56, 24, 50, 18, 58, 26 },
-    { 12, 44, 4,  36, 14, 46, 6,  38 },
-    { 60, 28, 52, 20, 62, 30, 54, 22 },
-    { 3,  35, 11, 43, 1,  33, 9,  41 },
-    { 51, 19, 59, 27, 49, 17, 57, 25 },
-    { 15, 47, 7,  39, 13, 45, 5,  37 },
-    { 63, 31, 55, 23, 61, 29, 53, 21 }
-  };
-
-  if (!klass->info.visual || klass->info.visual->type != GDK_VISUAL_PSEUDO_COLOR)
-    return;
-
-  shades_r = klass->info.nred_shades;
-  shades_g = klass->info.ngreen_shades;
-  shades_b = klass->info.nblue_shades;
-  shades_gray = klass->info.ngray_shades;
-
-  red_mult = shades_g * shades_b;
-  green_mult = shades_b;
-
-  red_colors_per_shade = 255.0 / (shades_r - 1);
-  red_matrix_width = red_colors_per_shade / 64;
-
-  green_colors_per_shade = 255.0 / (shades_g - 1);
-  green_matrix_width = green_colors_per_shade / 64;
-
-  blue_colors_per_shade = 255.0 / (shades_b - 1);
-  blue_matrix_width = blue_colors_per_shade / 64;
-
-  gray_colors_per_shade = 255.0 / (shades_gray - 1);
-  gray_matrix_width = gray_colors_per_shade / 64;
-
-  /*  alloc the ordered dither arrays for accelerated dithering  */
-
-  klass->info.dither_red = g_new (GtkDitherInfo, 256);
-  klass->info.dither_green = g_new (GtkDitherInfo, 256);
-  klass->info.dither_blue = g_new (GtkDitherInfo, 256);
-  klass->info.dither_gray = g_new (GtkDitherInfo, 256);
-
-  red_ordered_dither = klass->info.dither_red;
-  green_ordered_dither = klass->info.dither_green;
-  blue_ordered_dither = klass->info.dither_blue;
-  gray_ordered_dither = klass->info.dither_gray;
-
-  dither_matrix = g_new (guchar**, 8);
-  for (i = 0; i < 8; i++)
-    {
-      dither_matrix[i] = g_new (guchar*, 8);
-      for (j = 0; j < 8; j++)
-       dither_matrix[i][j] = g_new (guchar, 65);
-    }
-
-  klass->info.dither_matrix = dither_matrix;
-
-  /*  setup the ordered_dither_matrices  */
-
-  for (i = 0; i < 8; i++)
-    for (j = 0; j < 8; j++)
-      for (k = 0; k <= 64; k++)
-       dither_matrix[i][j][k] = (DM[i][j] < k) ? 1 : 0;
-
-  /*  setup arrays containing three bytes of information for red, green, & blue  */
-  /*  the arrays contain :
-   *    1st byte:    low end shade value
-   *    2nd byte:    high end shade value
-   *    3rd & 4th bytes:    ordered dither matrix index
-   */
-
-  gray_pixels = klass->info.gray_pixels;
-
-  for (i = 0; i < 256; i++)
-    {
-
-      /*  setup the red information  */
-      {
-       low_shade = (unsigned char) (i / red_colors_per_shade);
-       if (low_shade == (shades_r - 1))
-         low_shade--;
-       high_shade = low_shade + 1;
-
-       index = (unsigned short)
-         (((double) i - low_shade * red_colors_per_shade) /
-          red_matrix_width);
-
-       low_shade *= red_mult;
-       high_shade *= red_mult;
-
-       red_ordered_dither[i].s[1] = index;
-       red_ordered_dither[i].c[0] = low_shade;
-       red_ordered_dither[i].c[1] = high_shade;
-      }
-
-
-      /*  setup the green information  */
-      {
-       low_shade = (unsigned char) (i / green_colors_per_shade);
-       if (low_shade == (shades_g - 1))
-         low_shade--;
-       high_shade = low_shade + 1;
-
-       index = (unsigned short)
-         (((double) i - low_shade * green_colors_per_shade) /
-          green_matrix_width);
-
-       low_shade *= green_mult;
-       high_shade *= green_mult;
-
-       green_ordered_dither[i].s[1] = index;
-       green_ordered_dither[i].c[0] = low_shade;
-       green_ordered_dither[i].c[1] = high_shade;
-      }
-
-
-      /*  setup the blue information  */
-      {
-       low_shade = (unsigned char) (i / blue_colors_per_shade);
-       if (low_shade == (shades_b - 1))
-         low_shade--;
-       high_shade = low_shade + 1;
-
-       index = (unsigned short)
-         (((double) i - low_shade * blue_colors_per_shade) /
-          blue_matrix_width);
-
-       blue_ordered_dither[i].s[1] = index;
-       blue_ordered_dither[i].c[0] = low_shade;
-       blue_ordered_dither[i].c[1] = high_shade;
-      }
-
-
-      /*  setup the gray information */
-      {
-       low_shade = (unsigned char) (i / gray_colors_per_shade);
-       if (low_shade == (shades_gray - 1))
-         low_shade--;
-       high_shade = low_shade + 1;
-
-       index = (unsigned short)
-         (((double) i - low_shade * gray_colors_per_shade) /
-          gray_matrix_width);
-
-       gray_ordered_dither[i].s[1] = index;
-       gray_ordered_dither[i].c[0] = gray_pixels[low_shade];
-       gray_ordered_dither[i].c[1] = gray_pixels[high_shade];
-      }
+                               preview->rowstride);
     }
 }
 
+/* This will be useful for implementing gamma. */
 static void
-gtk_fill_lookup_array (gulong *array,
-                      int     depth,
-                      int     shift,
-                      int     prec)
+gtk_fill_lookup_array (guchar *array)
 {
   double one_over_gamma;
   double ind;
   int val;
   int i;
 
-  if (preview_class->info.gamma != 0.0)
-    one_over_gamma = 1.0 / preview_class->info.gamma;
-  else
-    one_over_gamma = 1.0;
+  one_over_gamma = 1.0 / preview_class->info.gamma;
 
   for (i = 0; i < 256; i++)
     {
-      if (one_over_gamma == 1.0)
-        array[i] = ((i >> prec) << shift);
-      else
-        {
-          ind = (double) i / 255.0;
-          val = (int) (255 * pow (ind, one_over_gamma));
-          array[i] = ((val >> prec) << shift);
-        }
-    }
-}
-
-static void
-gtk_trim_cmap (GtkPreviewClass *klass)
-{
-  gulong pixels[256];
-  guint nred;
-  guint ngreen;
-  guint nblue;
-  guint ngray;
-  guint nreserved;
-  guint total;
-  guint tmp;
-  gint success;
-
-  nred = klass->info.nred_shades;
-  ngreen = klass->info.ngreen_shades;
-  nblue = klass->info.nblue_shades;
-  ngray = klass->info.ngray_shades;
-  nreserved = klass->info.nreserved;
-
-  success = FALSE;
-  while (!success)
-    {
-      total = nred * ngreen * nblue + ngray + nreserved;
-
-      if (total <= 256)
-       {
-         if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
-           success = TRUE;
-         else
-           {
-             success = gdk_colors_alloc (klass->info.cmap, 0, NULL, 0, pixels, total);
-             if (success)
-               {
-                 if (nreserved > 0)
-                   {
-                     klass->info.reserved_pixels = g_new (gulong, nreserved);
-                     memcpy (klass->info.reserved_pixels, pixels, sizeof (gulong) * nreserved);
-                     gdk_colors_free (klass->info.cmap, &pixels[nreserved],
-                                      total - nreserved, 0);
-                   }
-                 else
-                   {
-                     gdk_colors_free (klass->info.cmap, pixels, total, 0);
-                   }
-               }
-           }
-       }
-
-      if (!success)
-       {
-         if ((nblue >= nred) && (nblue >= ngreen))
-           nblue = nblue - 1;
-         else if ((nred >= ngreen) && (nred >= nblue))
-           nred = nred - 1;
-         else
-           {
-             tmp = log ((gdouble)ngray) / log (2.0);
-
-             if (ngreen >= tmp)
-               ngreen = ngreen - 1;
-             else
-               ngray -= 1;
-           }
-       }
-    }
-  
-  if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
-    {
-      g_message ("Unable to allocate sufficient colormap entries.");
-      g_message ("Try exiting other color intensive applications.");
-      return;
-    }
-  
-  /*  If any of the shade values has changed, issue a warning  */
-  if ((nred != klass->info.nred_shades) ||
-      (ngreen != klass->info.ngreen_shades) ||
-      (nblue != klass->info.nblue_shades) ||
-      (ngray != klass->info.ngray_shades))
-    {
-      g_message ("Not enough colors to satisfy requested color cube.");
-      g_message ("Reduced color cube shades from");
-      g_message ("[%d of Red, %d of Green, %d of Blue, %d of Gray] ==> [%d of Red, %d of Green, %d of Blue, %d of Gray]\n",
-                klass->info.nred_shades, klass->info.ngreen_shades,
-                klass->info.nblue_shades, klass->info.ngray_shades,
-                nred, ngreen, nblue, ngray);
-    }
-  
-  klass->info.nred_shades = nred;
-  klass->info.ngreen_shades = ngreen;
-  klass->info.nblue_shades = nblue;
-  klass->info.ngray_shades = ngray;
-}
-
-static void
-gtk_create_8_bit (GtkPreviewClass *klass)
-{
-  unsigned int r, g, b;
-  unsigned int rv, gv, bv;
-  unsigned int dr, dg, db, dgray;
-  GdkColor color;
-  gulong *pixels;
-  double one_over_gamma;
-  int i;
-
-  if (!klass->info.color_pixels)
-    klass->info.color_pixels = g_new (gulong, 256);
-
-  if (!klass->info.gray_pixels)
-    klass->info.gray_pixels = g_new (gulong, 256);
-
-  if (klass->info.gamma != 0.0)
-    one_over_gamma = 1.0 / klass->info.gamma;
-  else
-    one_over_gamma = 1.0;
-
-  dr = klass->info.nred_shades - 1;
-  dg = klass->info.ngreen_shades - 1;
-  db = klass->info.nblue_shades - 1;
-  dgray = klass->info.ngray_shades - 1;
-
-  pixels = klass->info.color_pixels;
-
-  for (r = 0, i = 0; r <= dr; r++)
-    for (g = 0; g <= dg; g++)
-      for (b = 0; b <= db; b++, i++)
-        {
-          rv = (unsigned int) ((r * klass->info.visual->colormap_size) / dr);
-          gv = (unsigned int) ((g * klass->info.visual->colormap_size) / dg);
-          bv = (unsigned int) ((b * klass->info.visual->colormap_size) / db);
-          color.red = ((int) (255 * pow ((double) rv / 256.0, one_over_gamma))) * 257;
-          color.green = ((int) (255 * pow ((double) gv / 256.0, one_over_gamma))) * 257;
-          color.blue = ((int) (255 * pow ((double) bv / 256.0, one_over_gamma))) * 257;
-
-         if (!gdk_color_alloc (klass->info.cmap, &color))
-           {
-             g_error ("could not initialize 8-bit combined colormap");
-             return;
-           }
-
-         pixels[i] = color.pixel;
-        }
-
-
-  pixels = klass->info.gray_pixels;
-
-  for (i = 0; i < (int) klass->info.ngray_shades; i++)
-    {
-      color.red = (i * klass->info.visual->colormap_size) / dgray;
-      color.red = ((int) (255 * pow ((double) color.red / 256.0, one_over_gamma))) * 257;
-      color.green = color.red;
-      color.blue = color.red;
-
-      if (!gdk_color_alloc (klass->info.cmap, &color))
-       {
-         g_error ("could not initialize 8-bit combined colormap");
-         return;
-       }
-
-      pixels[i] = color.pixel;
-    }
-}
-
-
-static void
-gtk_color_8 (guchar *src,
-            guchar *dest,
-            gint    x,
-            gint    y,
-            gulong  width)
-{
-  gulong *colors;
-  GtkDitherInfo *dither_red;
-  GtkDitherInfo *dither_green;
-  GtkDitherInfo *dither_blue;
-  GtkDitherInfo r, g, b;
-  guchar **dither_matrix;
-  guchar *matrix;
-
-  colors = preview_class->info.color_pixels;
-  dither_red = preview_class->info.dither_red;
-  dither_green = preview_class->info.dither_green;
-  dither_blue = preview_class->info.dither_blue;
-  dither_matrix = preview_class->info.dither_matrix[y & 0x7];
-
-  while (width--)
-    {
-      r = dither_red[src[0]];
-      g = dither_green[src[1]];
-      b = dither_blue[src[2]];
-      src += 3;
-
-      matrix = dither_matrix[x++ & 0x7];
-      *dest++ = colors[(r.c[matrix[r.s[1]]] +
-                       g.c[matrix[g.s[1]]] +
-                       b.c[matrix[b.s[1]]])];
-    }
-}
-
-static void
-gtk_color_16 (guchar *src,
-             guchar *dest,
-             gulong  width)
-{
-  gulong *lookup_red;
-  gulong *lookup_green;
-  gulong *lookup_blue;
-  gulong val;
-
-  lookup_red = preview_class->info.lookup_red;
-  lookup_green = preview_class->info.lookup_green;
-  lookup_blue = preview_class->info.lookup_blue;
-
-  while (width--)
-    {
-      val = COLOR_COMPOSE (src[0], src[1], src[2]);
-      dest[0] = val;
-      dest[1] = val >> 8;
-      dest += 2;
-      src += 3;
-    }
-}
-
-static void
-gtk_color_24 (guchar *src,
-             guchar *dest,
-             gulong  width)
-{
-  gulong *lookup_red;
-  gulong *lookup_green;
-  gulong *lookup_blue;
-  gulong val;
-
-  lookup_red = preview_class->info.lookup_red;
-  lookup_green = preview_class->info.lookup_green;
-  lookup_blue = preview_class->info.lookup_blue;
-
-  while (width--)
-    {
-      val = COLOR_COMPOSE (src[0], src[1], src[2]);
-      dest[0] = val;
-      dest[1] = val >> 8;
-      dest[2] = val >> 16;
-      dest += 3;
-      src += 3;
-    }
-}
-
-static void
-gtk_grayscale_8 (guchar *src,
-                guchar *dest,
-                gint    x,
-                gint    y,
-                gulong  width)
-{
-  GtkDitherInfo *dither_gray;
-  GtkDitherInfo gray;
-  guchar **dither_matrix;
-  guchar *matrix;
-
-  dither_gray = preview_class->info.dither_gray;
-  dither_matrix = preview_class->info.dither_matrix[y & 0x7];
-
-  while (width--)
-    {
-      gray = dither_gray[*src++];
-      matrix = dither_matrix[x++ & 0x7];
-      *dest++ = gray.c[matrix[gray.s[1]]];
-    }
-}
-
-static void
-gtk_grayscale_16 (guchar *src,
-                 guchar *dest,
-                 gulong  width)
-{
-  gulong *lookup_red;
-  gulong *lookup_green;
-  gulong *lookup_blue;
-  gulong val;
-
-  lookup_red = preview_class->info.lookup_red;
-  lookup_green = preview_class->info.lookup_green;
-  lookup_blue = preview_class->info.lookup_blue;
-
-  while (width--)
-    {
-      val = COLOR_COMPOSE (*src, *src, *src);
-      dest[0] = val;
-      dest[1] = val >> 8;
-      dest += 2;
-      src += 1;
-    }
-}
-
-static void
-gtk_grayscale_24 (guchar  *src,
-                 guchar  *dest,
-                 gulong   width)
-{
-  gulong *lookup_red;
-  gulong *lookup_green;
-  gulong *lookup_blue;
-  gulong val;
-
-  lookup_red = preview_class->info.lookup_red;
-  lookup_green = preview_class->info.lookup_green;
-  lookup_blue = preview_class->info.lookup_blue;
-
-  while (width--)
-    {
-      val = COLOR_COMPOSE (*src, *src, *src);
-      dest[0] = val;
-      dest[1] = val >> 8;
-      dest[2] = val >> 16;
-      dest += 3;
-      src += 1;
-    }
-}
-
-
-static gint
-gtk_get_preview_prop (guint *nred,
-                     guint *ngreen,
-                     guint *nblue,
-                     guint *ngray)
-{
-  GtkPreviewProp *prop;
-  GdkAtom property;
-
-  /* FIXME: need to grab the server here to prevent a race condition */
-
-  property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
-
-  if (gdk_property_get (NULL, property, property,
-                       0, sizeof (GtkPreviewProp), FALSE,
-                       NULL, NULL, NULL, (guchar**) &prop))
-    {
-      *nred = prop->nred_shades;
-      *ngreen = prop->ngreen_shades;
-      *nblue = prop->nblue_shades;
-      *ngray = prop->ngray_shades;
-
-      prop->ref_count = prop->ref_count + 1;
-      gdk_property_change (NULL, property, property, 16,
-                          GDK_PROP_MODE_REPLACE,
-                          (guchar*) prop, 5);
-
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-gtk_set_preview_prop (guint nred,
-                     guint ngreen,
-                     guint nblue,
-                     guint ngray)
-{
-  GtkPreviewProp prop;
-  GdkAtom property;
-
-  property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
-
-  prop.ref_count = 1;
-  prop.nred_shades = nred;
-  prop.ngreen_shades = ngreen;
-  prop.nblue_shades = nblue;
-  prop.ngray_shades = ngray;
-
-  gdk_property_change (NULL, property, property, 16,
-                      GDK_PROP_MODE_REPLACE,
-                      (guchar*) &prop, 5);
-}
-
-
-static void
-gtk_lsbmsb_1_1 (guchar *dest,
-               guchar *src,
-               gint    count)
-{
-  memcpy (dest, src, count);
-}
-
-static void
-gtk_lsb_2_2 (guchar *dest,
-            guchar *src,
-            gint    count)
-{
-  memcpy (dest, src, count * 2);
-}
-
-static void
-gtk_msb_2_2 (guchar *dest,
-            guchar *src,
-            gint    count)
-{
-  while (count--)
-    {
-      dest[0] = src[1];
-      dest[1] = src[0];
-      dest += 2;
-      src += 2;
-    }
-}
-
-static void
-gtk_lsb_3_3 (guchar *dest,
-            guchar *src,
-            gint    count)
-{
-  memcpy (dest, src, count * 3);
-}
-
-static void
-gtk_msb_3_3 (guchar *dest,
-            guchar *src,
-            gint    count)
-{
-  while (count--)
-    {
-      dest[0] = src[2];
-      dest[1] = src[1];
-      dest[2] = src[0];
-      dest += 3;
-      src += 3;
-    }
-}
-
-static void
-gtk_lsb_3_4 (guchar *dest,
-            guchar *src,
-            gint    count)
-{
-  while (count--)
-    {
-      dest[0] = src[0];
-      dest[1] = src[1];
-      dest[2] = src[2];
-      dest += 4;
-      src += 3;
-    }
-}
-
-static void
-gtk_msb_3_4 (guchar *dest,
-            guchar *src,
-            gint    count)
-{
-  while (count--)
-    {
-      dest[1] = src[2];
-      dest[2] = src[1];
-      dest[3] = src[0];
-      dest += 4;
-      src += 3;
+      ind = (double) i / 255.0;
+      val = (int) (255 * pow (ind, one_over_gamma));
+      array[i] = val;
     }
 }
index 71da9b4f16cccea898e63b898802425e17dd72b4..252569b30e4303360d5eb80a972f1c2e7578cc7e 100644 (file)
@@ -46,6 +46,11 @@ struct _GtkPreview
   guint16 buffer_width;
   guint16 buffer_height;
 
+  guint16 bpp;
+  guint16 rowstride;
+
+  GdkRgbDither dither;
+
   guint type : 1;
   guint expand : 1;
 };
@@ -55,28 +60,8 @@ struct _GtkPreviewInfo
   GdkVisual *visual;
   GdkColormap *cmap;
 
-  gulong *color_pixels;
-  gulong *gray_pixels;
-  gulong *reserved_pixels;
-
-  gulong *lookup_red;
-  gulong *lookup_green;
-  gulong *lookup_blue;
-
-  GtkDitherInfo *dither_red;
-  GtkDitherInfo *dither_green;
-  GtkDitherInfo *dither_blue;
-  GtkDitherInfo *dither_gray;
-  guchar ***dither_matrix;
-
-  guint nred_shades;
-  guint ngreen_shades;
-  guint nblue_shades;
-  guint ngray_shades;
-  guint nreserved;
+  guchar *lookup;
 
-  guint bpp;
-  gint cmap_alloced;
   gdouble gamma;
 };
 
@@ -92,7 +77,6 @@ struct _GtkPreviewClass
 
   GtkPreviewInfo info;
 
-  GdkImage *image;
 };
 
 
@@ -111,6 +95,7 @@ void            gtk_preview_put                (GtkPreview      *preview,
                                                gint             desty,
                                                gint             width,
                                                gint             height);
+/* gtk_preview_put_row is broken */
 void            gtk_preview_put_row            (GtkPreview      *preview,
                                                guchar          *src,
                                                guchar          *dest,
@@ -132,6 +117,8 @@ void            gtk_preview_set_color_cube     (guint            nred_shades,
                                                guint            ngray_shades);
 void            gtk_preview_set_install_cmap   (gint             install_cmap);
 void            gtk_preview_set_reserved       (gint             nreserved);
+void            gtk_preview_set_dither         (GtkPreview      *preview,
+                                               GdkRgbDither     dither);
 GdkVisual*      gtk_preview_get_visual         (void);
 GdkColormap*    gtk_preview_get_cmap           (void);
 GtkPreviewInfo* gtk_preview_get_info           (void);