1572 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1572 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* GTK - The GIMP Toolkit
 | 
						|
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 | 
						|
 *
 | 
						|
 * This library is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Library General Public
 | 
						|
 * License as published by the Free Software Foundation; either
 | 
						|
 * version 2 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This library is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * Library General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Library General Public
 | 
						|
 * License along with this library; if not, write to the Free
 | 
						|
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
						|
 */
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/param.h>
 | 
						|
#include <netinet/in.h>
 | 
						|
#include "gdk/gdkx.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);
 | 
						|
static void   gtk_preview_init          (GtkPreview       *preview);
 | 
						|
static void   gtk_preview_destroy       (GtkObject        *object);
 | 
						|
static void   gtk_preview_realize       (GtkWidget        *widget);
 | 
						|
static void   gtk_preview_unrealize     (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 GtkWidgetClass *parent_class = NULL;
 | 
						|
static GtkPreviewClass *preview_class = NULL;
 | 
						|
static GtkPreviewInfo *preview_info = NULL;
 | 
						|
static gint install_cmap = FALSE;
 | 
						|
 | 
						|
 | 
						|
guint
 | 
						|
gtk_preview_get_type ()
 | 
						|
{
 | 
						|
  static guint preview_type = 0;
 | 
						|
 | 
						|
  if (!preview_type)
 | 
						|
    {
 | 
						|
      GtkTypeInfo preview_info =
 | 
						|
      {
 | 
						|
        "GtkPreview",
 | 
						|
        sizeof (GtkPreview),
 | 
						|
        sizeof (GtkPreviewClass),
 | 
						|
        (GtkClassInitFunc) gtk_preview_class_init,
 | 
						|
        (GtkObjectInitFunc) gtk_preview_init,
 | 
						|
	(GtkArgFunc) NULL,
 | 
						|
      };
 | 
						|
 | 
						|
      preview_type = gtk_type_unique (gtk_widget_get_type (), &preview_info);
 | 
						|
    }
 | 
						|
 | 
						|
  return preview_type;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_preview_class_init (GtkPreviewClass *klass)
 | 
						|
{
 | 
						|
  GtkObjectClass *object_class;
 | 
						|
  GtkWidgetClass *widget_class;
 | 
						|
 | 
						|
  object_class = (GtkObjectClass*) klass;
 | 
						|
  widget_class = (GtkWidgetClass*) klass;
 | 
						|
 | 
						|
  parent_class = gtk_type_class (gtk_widget_get_type ());
 | 
						|
  preview_class = klass;
 | 
						|
 | 
						|
  object_class->destroy = gtk_preview_destroy;
 | 
						|
 | 
						|
  widget_class->realize = gtk_preview_realize;
 | 
						|
  widget_class->unrealize = gtk_preview_unrealize;
 | 
						|
  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->image = NULL;
 | 
						|
 | 
						|
  gtk_preview_get_visuals (klass);
 | 
						|
  gtk_preview_get_cmaps (klass);
 | 
						|
  gtk_preview_dither_init (klass);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_preview_init (GtkPreview *preview)
 | 
						|
{
 | 
						|
  GTK_WIDGET_SET_FLAGS (preview, GTK_BASIC);
 | 
						|
 | 
						|
  preview->buffer = NULL;
 | 
						|
  preview->buffer_width = 0;
 | 
						|
  preview->buffer_height = 0;
 | 
						|
  preview->expand = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_uninit ()
 | 
						|
{
 | 
						|
  GtkPreviewProp *prop;
 | 
						|
  GdkAtom property;
 | 
						|
 | 
						|
  if (preview_class && !install_cmap &&
 | 
						|
      (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 = ntohs (prop->ref_count) - 1;
 | 
						|
	  if (prop->ref_count == 0)
 | 
						|
	    {
 | 
						|
	      gdk_property_delete (NULL, property);
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      prop->ref_count = htons (prop->ref_count);
 | 
						|
	      gdk_property_change (NULL, property, property, 16,
 | 
						|
				   GDK_PROP_MODE_REPLACE,
 | 
						|
				   (guchar*) prop, 5);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
GtkWidget*
 | 
						|
gtk_preview_new (GtkPreviewType type)
 | 
						|
{
 | 
						|
  GtkPreview *preview;
 | 
						|
 | 
						|
  preview = gtk_type_new (gtk_preview_get_type ());
 | 
						|
  preview->type = type;
 | 
						|
 | 
						|
  return GTK_WIDGET (preview);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_size (GtkPreview *preview,
 | 
						|
		  gint        width,
 | 
						|
		  gint        height)
 | 
						|
{
 | 
						|
  g_return_if_fail (preview != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (preview));
 | 
						|
 | 
						|
  if ((width != GTK_WIDGET (preview)->requisition.width) ||
 | 
						|
      (height != GTK_WIDGET (preview)->requisition.height))
 | 
						|
    {
 | 
						|
      GTK_WIDGET (preview)->requisition.width = width;
 | 
						|
      GTK_WIDGET (preview)->requisition.height = height;
 | 
						|
 | 
						|
      if (preview->buffer)
 | 
						|
	g_free (preview->buffer);
 | 
						|
      preview->buffer = NULL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_put (GtkPreview   *preview,
 | 
						|
		 GdkWindow    *window,
 | 
						|
		 GdkGC        *gc,
 | 
						|
		 gint          srcx,
 | 
						|
		 gint          srcy,
 | 
						|
		 gint          destx,
 | 
						|
		 gint          desty,
 | 
						|
		 gint          width,
 | 
						|
		 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;
 | 
						|
 | 
						|
  g_return_if_fail (preview != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (preview));
 | 
						|
  g_return_if_fail (window != NULL);
 | 
						|
 | 
						|
  if (!preview->buffer)
 | 
						|
    return;
 | 
						|
 | 
						|
  widget = GTK_WIDGET (preview);
 | 
						|
 | 
						|
  r1.x = srcx;
 | 
						|
  r1.y = srcy;
 | 
						|
  r1.width = preview->buffer_width;
 | 
						|
  r1.height = preview->buffer_height;
 | 
						|
 | 
						|
  r2.x = destx;
 | 
						|
  r2.y = desty;
 | 
						|
  r2.width = width;
 | 
						|
  r2.height = height;
 | 
						|
 | 
						|
  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, x, y,
 | 
						|
			  xe - x, ye - y);
 | 
						|
	  gdk_flush ();
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_put_row (GtkPreview *preview,
 | 
						|
		     guchar     *src,
 | 
						|
		     guchar     *dest,
 | 
						|
		     gint        x,
 | 
						|
		     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;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_draw_row (GtkPreview *preview,
 | 
						|
		      guchar     *data,
 | 
						|
		      gint        x,
 | 
						|
		      gint        y,
 | 
						|
		      gint        w)
 | 
						|
{
 | 
						|
  guchar *dest;
 | 
						|
 | 
						|
  g_return_if_fail (preview != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (preview));
 | 
						|
  g_return_if_fail (data != NULL);
 | 
						|
 | 
						|
  if ((w <= 0) || (y < 0))
 | 
						|
    return;
 | 
						|
 | 
						|
  g_return_if_fail (data != NULL);
 | 
						|
 | 
						|
  gtk_preview_make_buffer (preview);
 | 
						|
 | 
						|
  if (y >= preview->buffer_height)
 | 
						|
    return;
 | 
						|
 | 
						|
  switch (preview->type)
 | 
						|
    {
 | 
						|
    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)
 | 
						|
	{
 | 
						|
	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;
 | 
						|
	}
 | 
						|
      break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_set_expand (GtkPreview *preview,
 | 
						|
			gint        expand)
 | 
						|
{
 | 
						|
  g_return_if_fail (preview != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (preview));
 | 
						|
 | 
						|
  preview->expand = (expand != FALSE);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_set_gamma (double _gamma)
 | 
						|
{
 | 
						|
  g_return_if_fail (preview_class == NULL);
 | 
						|
 | 
						|
  if (!preview_info)
 | 
						|
    {
 | 
						|
      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_info->gamma = _gamma;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_set_color_cube (guint nred_shades,
 | 
						|
			    guint ngreen_shades,
 | 
						|
			    guint nblue_shades,
 | 
						|
			    guint ngray_shades)
 | 
						|
{
 | 
						|
  g_return_if_fail (preview_class == NULL);
 | 
						|
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_set_install_cmap (gint _install_cmap)
 | 
						|
{
 | 
						|
  /* g_return_if_fail (preview_class == NULL); */
 | 
						|
 | 
						|
  install_cmap = _install_cmap;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
gtk_preview_set_reserved (gint nreserved)
 | 
						|
{
 | 
						|
  if (!preview_info)
 | 
						|
    preview_info = g_new0 (GtkPreviewInfo, 1);
 | 
						|
 | 
						|
  preview_info->nreserved = nreserved;
 | 
						|
}
 | 
						|
 | 
						|
GdkVisual*
 | 
						|
gtk_preview_get_visual ()
 | 
						|
{
 | 
						|
  if (!preview_class)
 | 
						|
    preview_class = gtk_type_class (gtk_preview_get_type ());
 | 
						|
 | 
						|
  return preview_class->info.visual;
 | 
						|
}
 | 
						|
 | 
						|
GdkColormap*
 | 
						|
gtk_preview_get_cmap ()
 | 
						|
{
 | 
						|
  if (!preview_class)
 | 
						|
    preview_class = gtk_type_class (gtk_preview_get_type ());
 | 
						|
 | 
						|
  return preview_class->info.cmap;
 | 
						|
}
 | 
						|
 | 
						|
GtkPreviewInfo*
 | 
						|
gtk_preview_get_info ()
 | 
						|
{
 | 
						|
  if (!preview_class)
 | 
						|
    preview_class = gtk_type_class (gtk_preview_get_type ());
 | 
						|
 | 
						|
  return &preview_class->info;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
gtk_preview_destroy (GtkObject *object)
 | 
						|
{
 | 
						|
  GtkPreview *preview;
 | 
						|
 | 
						|
  g_return_if_fail (object != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (object));
 | 
						|
 | 
						|
  preview = GTK_PREVIEW (object);
 | 
						|
  if (preview->buffer)
 | 
						|
    g_free (preview->buffer);
 | 
						|
  preview->type = (GtkPreviewType) -1;
 | 
						|
 | 
						|
  if (GTK_OBJECT_CLASS (parent_class)->destroy)
 | 
						|
    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_preview_realize (GtkWidget *widget)
 | 
						|
{
 | 
						|
  GtkPreview *preview;
 | 
						|
  GdkWindowAttr attributes;
 | 
						|
  gint attributes_mask;
 | 
						|
 | 
						|
  g_return_if_fail (widget != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (widget));
 | 
						|
 | 
						|
  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 | 
						|
  preview = GTK_PREVIEW (widget);
 | 
						|
 | 
						|
  attributes.window_type = GDK_WINDOW_CHILD;
 | 
						|
  attributes.x = widget->allocation.x;
 | 
						|
  attributes.y = widget->allocation.y;
 | 
						|
  attributes.width = widget->allocation.width;
 | 
						|
  attributes.height = widget->allocation.height;
 | 
						|
  attributes.wclass = GDK_INPUT_OUTPUT;
 | 
						|
  attributes.visual = gtk_widget_get_visual (widget);
 | 
						|
  attributes.colormap = gtk_widget_get_colormap (widget);
 | 
						|
  attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
 | 
						|
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 | 
						|
 | 
						|
  widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
 | 
						|
  gdk_window_set_user_data (widget->window, widget);
 | 
						|
 | 
						|
  widget->style = gtk_style_attach (widget->style, widget->window);
 | 
						|
  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_preview_unrealize (GtkWidget *widget)
 | 
						|
{
 | 
						|
  GtkPreview *preview;
 | 
						|
 | 
						|
  g_return_if_fail (widget != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (widget));
 | 
						|
 | 
						|
  preview = GTK_PREVIEW (widget);
 | 
						|
 | 
						|
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
 | 
						|
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 | 
						|
}
 | 
						|
 | 
						|
static gint
 | 
						|
gtk_preview_expose (GtkWidget      *widget,
 | 
						|
		    GdkEventExpose *event)
 | 
						|
{
 | 
						|
  GtkPreview *preview;
 | 
						|
 | 
						|
  g_return_val_if_fail (widget != NULL, FALSE);
 | 
						|
  g_return_val_if_fail (GTK_IS_PREVIEW (widget), FALSE);
 | 
						|
  g_return_val_if_fail (event != NULL, FALSE);
 | 
						|
 | 
						|
  if (GTK_WIDGET_DRAWABLE (widget))
 | 
						|
    {
 | 
						|
      preview = GTK_PREVIEW (widget);
 | 
						|
 | 
						|
      gtk_preview_put (GTK_PREVIEW (widget),
 | 
						|
		       widget->window, widget->style->black_gc,
 | 
						|
		       (widget->allocation.width - preview->buffer_width) / 2,
 | 
						|
		       (widget->allocation.height - preview->buffer_height) / 2,
 | 
						|
		       event->area.x, event->area.y,
 | 
						|
		       event->area.width, event->area.height);
 | 
						|
    }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_preview_make_buffer (GtkPreview *preview)
 | 
						|
{
 | 
						|
  GtkWidget *widget;
 | 
						|
  gint width;
 | 
						|
  gint height;
 | 
						|
 | 
						|
  g_return_if_fail (preview != NULL);
 | 
						|
  g_return_if_fail (GTK_IS_PREVIEW (preview));
 | 
						|
 | 
						|
  widget = GTK_WIDGET (preview);
 | 
						|
 | 
						|
  if (preview->expand &&
 | 
						|
      (widget->allocation.width != 0) &&
 | 
						|
      (widget->allocation.height != 0))
 | 
						|
    {
 | 
						|
      width = widget->allocation.width;
 | 
						|
      height = widget->allocation.height;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      width = widget->requisition.width;
 | 
						|
      height = widget->requisition.height;
 | 
						|
    }
 | 
						|
 | 
						|
  if (!preview->buffer ||
 | 
						|
      (preview->buffer_width != width) ||
 | 
						|
      (preview->buffer_height != height))
 | 
						|
    {
 | 
						|
      if (preview->buffer)
 | 
						|
	g_free (preview->buffer);
 | 
						|
 | 
						|
      preview->buffer_width = width;
 | 
						|
      preview->buffer_height = height;
 | 
						|
 | 
						|
      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
 | 
						|
  };
 | 
						|
  static gint depths[] = { 24, 24, 32, 32, 16, 16, 15, 15, 8 };
 | 
						|
  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;
 | 
						|
    }
 | 
						|
 | 
						|
  switch (klass->info.visual->depth)
 | 
						|
    {
 | 
						|
    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->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];
 | 
						|
      }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
gtk_fill_lookup_array (gulong *array,
 | 
						|
		       int     depth,
 | 
						|
		       int     shift,
 | 
						|
		       int     prec)
 | 
						|
{
 | 
						|
  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;
 | 
						|
 | 
						|
  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 (ngray) / log (2);
 | 
						|
 | 
						|
	      if (ngreen >= tmp)
 | 
						|
		ngreen = ngreen - 1;
 | 
						|
	      else
 | 
						|
		ngray -= 1;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
 | 
						|
    {
 | 
						|
      g_print ("Unable to allocate sufficient colormap entries.\n");
 | 
						|
      g_print ("Try exiting other color intensive applications.\n");
 | 
						|
      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_print ("Not enough colors to satisfy requested color cube.\n");
 | 
						|
      g_print ("Reduced color cube shades from\n");
 | 
						|
      g_print ("[%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;
 | 
						|
 | 
						|
  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 = ntohs (prop->nred_shades);
 | 
						|
      *ngreen = ntohs (prop->ngreen_shades);
 | 
						|
      *nblue = ntohs (prop->nblue_shades);
 | 
						|
      *ngray = ntohs (prop->ngray_shades);
 | 
						|
 | 
						|
      prop->ref_count = htons (ntohs (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 = htons (1);
 | 
						|
  prop.nred_shades = htons (nred);
 | 
						|
  prop.ngreen_shades = htons (ngreen);
 | 
						|
  prop.nblue_shades = htons (nblue);
 | 
						|
  prop.ngray_shades = htons (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;
 | 
						|
    }
 | 
						|
}
 |