* 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.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
*/
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "config.h"
+
#include <math.h>
#include <string.h>
#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
-#include <netinet/in.h>
-#include "gdk/gdkx.h"
+#endif
+#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;
+enum {
+ ARG_0,
+ ARG_EXPAND
};
static void gtk_preview_class_init (GtkPreviewClass *klass);
static void gtk_preview_init (GtkPreview *preview);
+static void gtk_preview_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_preview_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
static void gtk_preview_finalize (GtkObject *object);
static void gtk_preview_realize (GtkWidget *widget);
-static void gtk_preview_unrealize (GtkWidget *widget);
+static void gtk_preview_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
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;
-guint
-gtk_preview_get_type ()
+GtkType
+gtk_preview_get_type (void)
{
- static guint preview_type = 0;
+ static GtkType preview_type = 0;
if (!preview_type)
{
- GtkTypeInfo preview_info =
+ static const GtkTypeInfo preview_info =
{
"GtkPreview",
sizeof (GtkPreview),
sizeof (GtkPreviewClass),
(GtkClassInitFunc) gtk_preview_class_init,
(GtkObjectInitFunc) gtk_preview_init,
- (GtkArgSetFunc) NULL,
- (GtkArgGetFunc) NULL,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
};
- preview_type = gtk_type_unique (gtk_widget_get_type (), &preview_info);
+ preview_type = gtk_type_unique (GTK_TYPE_WIDGET, &preview_info);
}
return preview_type;
object_class = (GtkObjectClass*) klass;
widget_class = (GtkWidgetClass*) klass;
- parent_class = gtk_type_class (gtk_widget_get_type ());
+ parent_class = gtk_type_class (GTK_TYPE_WIDGET);
preview_class = klass;
+ object_class->set_arg = gtk_preview_set_arg;
+ object_class->get_arg = gtk_preview_get_arg;
object_class->finalize = gtk_preview_finalize;
widget_class->realize = gtk_preview_realize;
- widget_class->unrealize = gtk_preview_unrealize;
+ widget_class->size_allocate = gtk_preview_size_allocate;
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.lookup = NULL;
+
+ klass->info.gamma = 1.0;
+
+ gdk_rgb_init ();
+ klass->info.cmap = gdk_rgb_get_cmap ();
+ klass->info.visual = gdk_rgb_get_visual ();
+
+ gtk_object_add_arg_type ("GtkPreview::expand",
+ GTK_TYPE_BOOL,
+ GTK_ARG_READWRITE,
+ ARG_EXPAND);
+}
+
+static void
+gtk_preview_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkPreview *preview = GTK_PREVIEW (object);
+
+ switch (arg_id)
{
- 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;
+ case ARG_EXPAND:
+ gtk_preview_set_expand (preview, GTK_VALUE_BOOL (*arg));
+ break;
}
+}
- klass->image = NULL;
+static void
+gtk_preview_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkPreview *preview;
+
+ preview = GTK_PREVIEW (object);
+
+ switch (arg_id)
+ {
+ case ARG_EXPAND:
+ GTK_VALUE_BOOL (*arg) = preview->expand;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
- gtk_preview_get_visuals (klass);
- gtk_preview_get_cmaps (klass);
- gtk_preview_dither_init (klass);
+void
+gtk_preview_reset (void)
+{
+ /* unimplemented */
}
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;
}
void
-gtk_preview_uninit ()
+gtk_preview_uninit (void)
{
- 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);
- }
- }
- }
+ /* unimplemented */
}
GtkWidget*
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);
}
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));
widget = GTK_WIDGET (preview);
- r1.x = srcx;
- r1.y = srcy;
+ r1.x = 0;
+ r1.y = 0;
r1.width = preview->buffer_width;
r1.height = preview->buffer_height;
- r2.x = destx;
- r2.y = desty;
+ r2.x = srcx;
+ r2.y = srcy;
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;
- }
+ 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
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;
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++];
}
}
void
gtk_preview_set_expand (GtkPreview *preview,
- gint expand)
+ gboolean expand)
{
g_return_if_fail (preview != NULL);
g_return_if_fail (GTK_IS_PREVIEW (preview));
- preview->expand = (expand != FALSE);
+ expand = expand != FALSE;
+
+ if (preview->expand != expand)
+ {
+ preview->expand = expand;
+ gtk_widget_queue_resize (GTK_WIDGET (preview));
+ }
}
void
gtk_preview_set_gamma (double _gamma)
{
- g_return_if_fail (preview_class == NULL);
+ if (!preview_class)
+ preview_class = gtk_type_class (gtk_preview_get_type ());
- if (!preview_info)
+ 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
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;
+ /* unimplemented */
}
void
gtk_preview_set_install_cmap (gint _install_cmap)
{
- /* g_return_if_fail (preview_class == NULL); */
-
+ /* 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*
-gtk_preview_get_visual ()
+gtk_preview_get_visual (void)
{
if (!preview_class)
preview_class = gtk_type_class (gtk_preview_get_type ());
}
GdkColormap*
-gtk_preview_get_cmap ()
+gtk_preview_get_cmap (void)
{
if (!preview_class)
preview_class = gtk_type_class (gtk_preview_get_type ());
}
GtkPreviewInfo*
-gtk_preview_get_info ()
+gtk_preview_get_info (void)
{
if (!preview_class)
preview_class = gtk_type_class (gtk_preview_get_type ());
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;
+
+ if (preview->expand)
+ {
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ }
+ else
+ {
+ attributes.width = MIN (widget->requisition.width, widget->allocation.width);
+ attributes.height = MIN (widget->requisition.height, widget->allocation.height);
+ }
+
+ attributes.x = widget->allocation.x + (widget->allocation.width - attributes.width) / 2;
+ attributes.y = widget->allocation.y + (widget->allocation.height - attributes.height) / 2;;
+
attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.visual = preview_class->info.visual;
+ attributes.colormap = preview_class->info.cmap;
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;
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}
-static void
-gtk_preview_unrealize (GtkWidget *widget)
+static void
+gtk_preview_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
{
GtkPreview *preview;
+ gint width, height;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_PREVIEW (widget));
preview = GTK_PREVIEW (widget);
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ {
+ if (preview->expand)
+ {
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+ }
+ else
+ {
+ width = MIN (widget->allocation.width, widget->requisition.width);
+ height = MIN (widget->allocation.height, widget->requisition.height);
+ }
- if (GTK_WIDGET_CLASS (parent_class)->unrealize)
- (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+ gdk_window_move_resize (widget->window,
+ widget->allocation.x + (widget->allocation.width - width) / 2,
+ widget->allocation.y + (widget->allocation.height - height) / 2,
+ width, height);
+ }
}
static gint
GdkEventExpose *event)
{
GtkPreview *preview;
+ gint width, height;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_PREVIEW (widget), FALSE);
if (GTK_WIDGET_DRAWABLE (widget))
{
preview = GTK_PREVIEW (widget);
+
+ gdk_window_get_size (widget->window, &width, &height);
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 - (width - preview->buffer_width)/2,
+ event->area.y - (height - preview->buffer_height)/2,
event->area.x, event->area.y,
event->area.width, event->area.height);
}
-
+
return FALSE;
}
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
- };
- 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];
- }
+ preview->rowstride);
}
}
+/* This is used 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 (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;
+ ind = (double) i / 255.0;
+ val = (int) (255 * pow (ind, one_over_gamma));
+ array[i] = val;
}
}