1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include <sys/types.h>
23 #include <sys/param.h>
25 #include "gdk/gdkrgb.h"
26 #include "gtkpreview.h"
27 #include "gtksignal.h"
30 #define PREVIEW_CLASS(w) GTK_PREVIEW_CLASS (GTK_OBJECT (w)->klass)
33 static void gtk_preview_class_init (GtkPreviewClass *klass);
34 static void gtk_preview_init (GtkPreview *preview);
35 static void gtk_preview_finalize (GtkObject *object);
36 static void gtk_preview_realize (GtkWidget *widget);
37 static gint gtk_preview_expose (GtkWidget *widget,
38 GdkEventExpose *event);
39 static void gtk_preview_make_buffer (GtkPreview *preview);
40 static void gtk_fill_lookup_array (guchar *array);
42 static GtkWidgetClass *parent_class = NULL;
43 static GtkPreviewClass *preview_class = NULL;
44 static gint install_cmap = FALSE;
48 gtk_preview_get_type (void)
50 static guint preview_type = 0;
54 GtkTypeInfo preview_info =
58 sizeof (GtkPreviewClass),
59 (GtkClassInitFunc) gtk_preview_class_init,
60 (GtkObjectInitFunc) gtk_preview_init,
61 /* reserved_1 */ NULL,
62 /* reserved_2 */ NULL,
63 (GtkClassInitFunc) NULL,
66 preview_type = gtk_type_unique (gtk_widget_get_type (), &preview_info);
73 gtk_preview_class_init (GtkPreviewClass *klass)
75 GtkObjectClass *object_class;
76 GtkWidgetClass *widget_class;
78 object_class = (GtkObjectClass*) klass;
79 widget_class = (GtkWidgetClass*) klass;
81 parent_class = gtk_type_class (gtk_widget_get_type ());
82 preview_class = klass;
84 object_class->finalize = gtk_preview_finalize;
86 widget_class->realize = gtk_preview_realize;
87 widget_class->expose_event = gtk_preview_expose;
89 klass->info.visual = NULL;
90 klass->info.cmap = NULL;
92 klass->info.lookup = NULL;
94 klass->info.gamma = 1.0;
97 klass->info.cmap = gdk_rgb_get_cmap ();
98 klass->info.visual = gdk_rgb_get_visual ();
102 gtk_preview_reset (void)
108 gtk_preview_init (GtkPreview *preview)
110 preview->buffer = NULL;
111 preview->buffer_width = 0;
112 preview->buffer_height = 0;
113 preview->expand = FALSE;
117 gtk_preview_uninit (void)
124 gtk_preview_new (GtkPreviewType type)
128 preview = gtk_type_new (gtk_preview_get_type ());
129 preview->type = type;
131 if (type == GTK_PREVIEW_COLOR)
136 preview->dither = GDK_RGB_DITHER_NORMAL;
138 return GTK_WIDGET (preview);
142 gtk_preview_size (GtkPreview *preview,
146 g_return_if_fail (preview != NULL);
147 g_return_if_fail (GTK_IS_PREVIEW (preview));
149 if ((width != GTK_WIDGET (preview)->requisition.width) ||
150 (height != GTK_WIDGET (preview)->requisition.height))
152 GTK_WIDGET (preview)->requisition.width = width;
153 GTK_WIDGET (preview)->requisition.height = height;
156 g_free (preview->buffer);
157 preview->buffer = NULL;
162 gtk_preview_put (GtkPreview *preview,
173 GdkRectangle r1, r2, r3;
178 g_return_if_fail (preview != NULL);
179 g_return_if_fail (GTK_IS_PREVIEW (preview));
180 g_return_if_fail (window != NULL);
182 if (!preview->buffer)
185 widget = GTK_WIDGET (preview);
189 r1.width = preview->buffer_width;
190 r1.height = preview->buffer_height;
197 if (!gdk_rectangle_intersect (&r1, &r2, &r3))
201 rowstride = preview->rowstride;
203 src = preview->buffer + r3.y * rowstride + r3.x * bpp;
205 if (preview->type == GTK_PREVIEW_COLOR)
206 gdk_draw_rgb_image (window,
208 destx + (r3.x - srcx),
209 desty + (r3.y - srcy),
216 gdk_draw_gray_image (window,
218 destx + (r3.x - srcx),
219 desty + (r3.y - srcy),
229 gtk_preview_put_row (GtkPreview *preview,
236 g_warning ("gtk_preview_put_row not implemented (deprecated)\n");
240 gtk_preview_draw_row (GtkPreview *preview,
249 g_return_if_fail (preview != NULL);
250 g_return_if_fail (GTK_IS_PREVIEW (preview));
251 g_return_if_fail (data != NULL);
252 g_return_if_fail (preview_class->info.visual != NULL);
254 bpp = (preview->type == GTK_PREVIEW_COLOR ? 3 : 1);
255 rowstride = (preview->buffer_width * bpp + 3) & -4;
257 if ((w <= 0) || (y < 0))
260 g_return_if_fail (data != NULL);
262 gtk_preview_make_buffer (preview);
264 if (x + w > preview->buffer_width)
267 if (y + 1 > preview->buffer_height)
270 if (preview_class->info.gamma == 1.0)
271 memcpy (preview->buffer + y * rowstride + x * bpp, data, w * bpp);
278 if (preview_class->info.lookup != NULL)
279 lookup = preview_class->info.lookup;
282 preview_class->info.lookup = g_new (guchar, 256);
283 gtk_fill_lookup_array (preview_class->info.lookup);
284 lookup = preview_class->info.lookup;
288 dst = preview->buffer + y * rowstride + x * bpp;
289 for (i = 0; i < size; i++)
290 *dst++ = lookup[*src++];
295 gtk_preview_set_expand (GtkPreview *preview,
298 g_return_if_fail (preview != NULL);
299 g_return_if_fail (GTK_IS_PREVIEW (preview));
301 preview->expand = (expand != FALSE);
305 gtk_preview_set_gamma (double _gamma)
308 preview_class = gtk_type_class (gtk_preview_get_type ());
310 if (preview_class->info.gamma != _gamma)
312 preview_class->info.gamma = _gamma;
313 if (preview_class->info.lookup != NULL)
315 g_free (preview_class->info.lookup);
316 preview_class->info.lookup = NULL;
322 gtk_preview_set_color_cube (guint nred_shades,
331 gtk_preview_set_install_cmap (gint _install_cmap)
333 /* effectively unimplemented */
334 install_cmap = _install_cmap;
338 gtk_preview_set_reserved (gint nreserved)
345 gtk_preview_set_dither (GtkPreview *preview,
348 preview->dither = dither;
352 gtk_preview_get_visual (void)
355 preview_class = gtk_type_class (gtk_preview_get_type ());
357 return preview_class->info.visual;
361 gtk_preview_get_cmap (void)
364 preview_class = gtk_type_class (gtk_preview_get_type ());
366 return preview_class->info.cmap;
370 gtk_preview_get_info (void)
373 preview_class = gtk_type_class (gtk_preview_get_type ());
375 return &preview_class->info;
380 gtk_preview_finalize (GtkObject *object)
384 g_return_if_fail (object != NULL);
385 g_return_if_fail (GTK_IS_PREVIEW (object));
387 preview = GTK_PREVIEW (object);
389 g_free (preview->buffer);
390 preview->type = (GtkPreviewType) -1;
392 (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
396 gtk_preview_realize (GtkWidget *widget)
399 GdkWindowAttr attributes;
400 gint attributes_mask;
402 g_return_if_fail (widget != NULL);
403 g_return_if_fail (GTK_IS_PREVIEW (widget));
405 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
406 preview = GTK_PREVIEW (widget);
408 attributes.window_type = GDK_WINDOW_CHILD;
409 attributes.x = widget->allocation.x;
410 attributes.y = widget->allocation.y;
411 attributes.width = widget->allocation.width;
412 attributes.height = widget->allocation.height;
413 attributes.wclass = GDK_INPUT_OUTPUT;
414 attributes.visual = preview_class->info.visual;
415 attributes.colormap = preview_class->info.cmap;
416 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
417 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
419 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
420 gdk_window_set_user_data (widget->window, widget);
422 widget->style = gtk_style_attach (widget->style, widget->window);
423 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
424 gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
428 gtk_preview_expose (GtkWidget *widget,
429 GdkEventExpose *event)
433 g_return_val_if_fail (widget != NULL, FALSE);
434 g_return_val_if_fail (GTK_IS_PREVIEW (widget), FALSE);
435 g_return_val_if_fail (event != NULL, FALSE);
437 if (GTK_WIDGET_DRAWABLE (widget))
439 preview = GTK_PREVIEW (widget);
441 gtk_preview_put (GTK_PREVIEW (widget),
442 widget->window, widget->style->black_gc,
444 (widget->allocation.width - preview->buffer_width)/2,
446 (widget->allocation.height - preview->buffer_height)/2,
447 event->area.x, event->area.y,
448 event->area.width, event->area.height);
455 gtk_preview_make_buffer (GtkPreview *preview)
461 g_return_if_fail (preview != NULL);
462 g_return_if_fail (GTK_IS_PREVIEW (preview));
464 widget = GTK_WIDGET (preview);
466 if (preview->expand &&
467 (widget->allocation.width != 0) &&
468 (widget->allocation.height != 0))
470 width = widget->allocation.width;
471 height = widget->allocation.height;
475 width = widget->requisition.width;
476 height = widget->requisition.height;
479 if (!preview->buffer ||
480 (preview->buffer_width != width) ||
481 (preview->buffer_height != height))
484 g_free (preview->buffer);
486 preview->buffer_width = width;
487 preview->buffer_height = height;
489 preview->rowstride = (preview->buffer_width * preview->bpp + 3) & -4;
490 preview->buffer = g_new0 (guchar,
491 preview->buffer_height *
496 /* This will be useful for implementing gamma. */
498 gtk_fill_lookup_array (guchar *array)
500 double one_over_gamma;
505 one_over_gamma = 1.0 / preview_class->info.gamma;
507 for (i = 0; i < 256; i++)
509 ind = (double) i / 255.0;
510 val = (int) (255 * pow (ind, one_over_gamma));