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 Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <sys/types.h>
22 #include <sys/param.h>
23 #include <netinet/in.h>
25 #include "gtkpreview.h"
26 #include "gtksignal.h"
29 #define IMAGE_SIZE 256
30 #define PREVIEW_CLASS(w) GTK_PREVIEW_CLASS (GTK_OBJECT (w)->klass)
31 #define COLOR_COMPOSE(r,g,b) (lookup_red[r] | lookup_green[g] | lookup_blue[b])
34 typedef struct _GtkPreviewProp GtkPreviewProp;
35 typedef void (*GtkTransferFunc) (guchar *dest, guchar *src, gint count);
37 struct _GtkPreviewProp
41 guint16 ngreen_shades;
47 static void gtk_preview_class_init (GtkPreviewClass *klass);
48 static void gtk_preview_init (GtkPreview *preview);
49 static void gtk_preview_destroy (GtkObject *object);
50 static void gtk_preview_realize (GtkWidget *widget);
51 static void gtk_preview_unrealize (GtkWidget *widget);
52 static gint gtk_preview_expose (GtkWidget *widget,
53 GdkEventExpose *event);
54 static void gtk_preview_make_buffer (GtkPreview *preview);
55 static void gtk_preview_get_visuals (GtkPreviewClass *klass);
56 static void gtk_preview_get_cmaps (GtkPreviewClass *klass);
57 static void gtk_preview_dither_init (GtkPreviewClass *klass);
58 static void gtk_fill_lookup_array (gulong *array,
62 static void gtk_trim_cmap (GtkPreviewClass *klass);
63 static void gtk_create_8_bit (GtkPreviewClass *klass);
65 static void gtk_color_8 (guchar *src,
70 static void gtk_color_16 (guchar *src,
73 static void gtk_color_24 (guchar *src,
76 static void gtk_grayscale_8 (guchar *src,
81 static void gtk_grayscale_16 (guchar *src,
84 static void gtk_grayscale_24 (guchar *src,
88 static gint gtk_get_preview_prop (guint *nred,
92 static void gtk_set_preview_prop (guint nred,
97 /* transfer functions:
98 * destination byte order/source bpp/destination bpp
100 static void gtk_lsbmsb_1_1 (guchar *dest,
103 static void gtk_lsb_2_2 (guchar *dest,
106 static void gtk_msb_2_2 (guchar *dest,
109 static void gtk_lsb_3_3 (guchar *dest,
112 static void gtk_msb_3_3 (guchar *dest,
115 static void gtk_lsb_3_4 (guchar *dest,
118 static void gtk_msb_3_4 (guchar *dest,
123 static GtkWidgetClass *parent_class = NULL;
124 static GtkPreviewClass *preview_class = NULL;
125 static GtkPreviewInfo *preview_info = NULL;
126 static gint install_cmap = FALSE;
130 gtk_preview_get_type ()
132 static guint preview_type = 0;
136 GtkTypeInfo preview_info =
140 sizeof (GtkPreviewClass),
141 (GtkClassInitFunc) gtk_preview_class_init,
142 (GtkObjectInitFunc) gtk_preview_init,
143 (GtkArgSetFunc) NULL,
144 (GtkArgGetFunc) NULL,
147 preview_type = gtk_type_unique (gtk_widget_get_type (), &preview_info);
154 gtk_preview_class_init (GtkPreviewClass *klass)
156 GtkObjectClass *object_class;
157 GtkWidgetClass *widget_class;
159 object_class = (GtkObjectClass*) klass;
160 widget_class = (GtkWidgetClass*) klass;
162 parent_class = gtk_type_class (gtk_widget_get_type ());
163 preview_class = klass;
165 object_class->destroy = gtk_preview_destroy;
167 widget_class->realize = gtk_preview_realize;
168 widget_class->unrealize = gtk_preview_unrealize;
169 widget_class->expose_event = gtk_preview_expose;
172 klass->info = *preview_info;
175 klass->info.visual = NULL;
176 klass->info.cmap = NULL;
178 klass->info.color_pixels = NULL;
179 klass->info.gray_pixels = NULL;
180 klass->info.reserved_pixels = NULL;
182 klass->info.lookup_red = NULL;
183 klass->info.lookup_green = NULL;
184 klass->info.lookup_blue = NULL;
186 klass->info.dither_red = NULL;
187 klass->info.dither_green = NULL;
188 klass->info.dither_blue = NULL;
189 klass->info.dither_gray = NULL;
190 klass->info.dither_matrix = NULL;
192 klass->info.nred_shades = 6;
193 klass->info.ngreen_shades = 6;
194 klass->info.nblue_shades = 4;
195 klass->info.ngray_shades = 24;
196 klass->info.nreserved = 0;
199 klass->info.cmap_alloced = FALSE;
200 klass->info.gamma = 1.0;
205 gtk_preview_get_visuals (klass);
206 gtk_preview_get_cmaps (klass);
207 gtk_preview_dither_init (klass);
211 gtk_preview_init (GtkPreview *preview)
213 GTK_WIDGET_SET_FLAGS (preview, GTK_BASIC);
215 preview->buffer = NULL;
216 preview->buffer_width = 0;
217 preview->buffer_height = 0;
218 preview->expand = FALSE;
222 gtk_preview_uninit ()
224 GtkPreviewProp *prop;
227 if (preview_class && !install_cmap &&
228 (preview_class->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
229 (preview_class->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
231 property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
233 if (gdk_property_get (NULL, property, property,
234 0, sizeof (GtkPreviewProp), FALSE,
235 NULL, NULL, NULL, (guchar**) &prop))
237 prop->ref_count = ntohs (prop->ref_count) - 1;
238 if (prop->ref_count == 0)
240 gdk_property_delete (NULL, property);
244 prop->ref_count = htons (prop->ref_count);
245 gdk_property_change (NULL, property, property, 16,
246 GDK_PROP_MODE_REPLACE,
254 gtk_preview_new (GtkPreviewType type)
258 preview = gtk_type_new (gtk_preview_get_type ());
259 preview->type = type;
261 return GTK_WIDGET (preview);
265 gtk_preview_size (GtkPreview *preview,
269 g_return_if_fail (preview != NULL);
270 g_return_if_fail (GTK_IS_PREVIEW (preview));
272 if ((width != GTK_WIDGET (preview)->requisition.width) ||
273 (height != GTK_WIDGET (preview)->requisition.height))
275 GTK_WIDGET (preview)->requisition.width = width;
276 GTK_WIDGET (preview)->requisition.height = height;
279 g_free (preview->buffer);
280 preview->buffer = NULL;
285 gtk_preview_put (GtkPreview *preview,
297 GdkRectangle r1, r2, r3;
298 GtkTransferFunc transfer_func;
303 guint dest_rowstride;
308 g_return_if_fail (preview != NULL);
309 g_return_if_fail (GTK_IS_PREVIEW (preview));
310 g_return_if_fail (window != NULL);
312 if (!preview->buffer)
315 widget = GTK_WIDGET (preview);
319 r1.width = preview->buffer_width;
320 r1.height = preview->buffer_height;
327 if (!gdk_rectangle_intersect (&r1, &r2, &r3))
330 x2 = r3.x + r3.width;
331 y2 = r3.y + r3.height;
333 if (!preview_class->image)
334 preview_class->image = gdk_image_new (GDK_IMAGE_FASTEST,
335 preview_class->info.visual,
336 IMAGE_SIZE, IMAGE_SIZE);
337 image = preview_class->image;
338 src_bpp = preview_class->info.bpp;
340 image_mem = image->mem;
341 dest_bpp = image->bpp;
342 dest_rowstride = image->bpl;
344 transfer_func = NULL;
352 transfer_func = gtk_lsbmsb_1_1;
360 if (image->byte_order == GDK_MSB_FIRST)
361 transfer_func = gtk_msb_2_2;
363 transfer_func = gtk_lsb_2_2;
373 if (image->byte_order == GDK_MSB_FIRST)
374 transfer_func = gtk_msb_3_3;
376 transfer_func = gtk_lsb_3_3;
384 if (image->byte_order == GDK_MSB_FIRST)
385 transfer_func = gtk_msb_3_4;
387 transfer_func = gtk_lsb_3_4;
395 g_warning ("unsupported byte order/src bpp/dest bpp combination: %s:%d:%d",
396 (image->byte_order == GDK_MSB_FIRST) ? "msb" : "lsb", src_bpp, dest_bpp);
400 for (y = r3.y; y < y2; y += IMAGE_SIZE)
402 for (x = r3.x; x < x2; x += IMAGE_SIZE)
412 for (i = y; i < ye; i++)
414 src = preview->buffer + (((gulong) (i - r1.y) * (gulong) preview->buffer_width) +
415 (x - r1.x)) * (gulong) src_bpp;
416 dest = image_mem + ((gulong) (i - y) * dest_rowstride);
419 (* transfer_func) (dest, src, xe - x);
422 gdk_draw_image (window, gc,
431 gtk_preview_put_row (GtkPreview *preview,
438 g_return_if_fail (preview != NULL);
439 g_return_if_fail (GTK_IS_PREVIEW (preview));
440 g_return_if_fail (src != NULL);
441 g_return_if_fail (dest != NULL);
443 switch (preview->type)
445 case GTK_PREVIEW_COLOR:
446 switch (preview_class->info.visual->depth)
449 gtk_color_8 (src, dest, x, y, w);
453 gtk_color_16 (src, dest, w);
457 gtk_color_24 (src, dest, w);
461 case GTK_PREVIEW_GRAYSCALE:
462 switch (preview_class->info.visual->depth)
465 gtk_grayscale_8 (src, dest, x, y, w);
469 gtk_grayscale_16 (src, dest, w);
473 gtk_grayscale_24 (src, dest, w);
481 gtk_preview_draw_row (GtkPreview *preview,
489 g_return_if_fail (preview != NULL);
490 g_return_if_fail (GTK_IS_PREVIEW (preview));
491 g_return_if_fail (data != NULL);
493 if ((w <= 0) || (y < 0))
496 g_return_if_fail (data != NULL);
498 gtk_preview_make_buffer (preview);
500 if (y >= preview->buffer_height)
503 switch (preview->type)
505 case GTK_PREVIEW_COLOR:
506 switch (preview_class->info.visual->depth)
509 dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
510 gtk_color_8 (data, dest, x, y, w);
514 dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
515 gtk_color_16 (data, dest, w);
519 dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
520 gtk_color_24 (data, dest, w);
524 case GTK_PREVIEW_GRAYSCALE:
525 switch (preview_class->info.visual->depth)
528 dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x);
529 gtk_grayscale_8 (data, dest, x, y, w);
533 dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 2;
534 gtk_grayscale_16 (data, dest, w);
538 dest = preview->buffer + ((gulong) y * (gulong) preview->buffer_width + (gulong) x) * 3;
539 gtk_grayscale_24 (data, dest, w);
547 gtk_preview_set_expand (GtkPreview *preview,
550 g_return_if_fail (preview != NULL);
551 g_return_if_fail (GTK_IS_PREVIEW (preview));
553 preview->expand = (expand != FALSE);
557 gtk_preview_set_gamma (double _gamma)
559 g_return_if_fail (preview_class == NULL);
563 preview_info = g_new0 (GtkPreviewInfo, 1);
564 preview_info->nred_shades = 6;
565 preview_info->ngreen_shades = 6;
566 preview_info->nblue_shades = 4;
567 preview_info->ngray_shades = 24;
570 preview_info->gamma = _gamma;
574 gtk_preview_set_color_cube (guint nred_shades,
579 g_return_if_fail (preview_class == NULL);
583 preview_info = g_new0 (GtkPreviewInfo, 1);
584 preview_info->gamma = 1.0;
587 preview_info->nred_shades = nred_shades;
588 preview_info->ngreen_shades = ngreen_shades;
589 preview_info->nblue_shades = nblue_shades;
590 preview_info->ngray_shades = ngray_shades;
594 gtk_preview_set_install_cmap (gint _install_cmap)
596 /* g_return_if_fail (preview_class == NULL); */
598 install_cmap = _install_cmap;
602 gtk_preview_set_reserved (gint nreserved)
605 preview_info = g_new0 (GtkPreviewInfo, 1);
607 preview_info->nreserved = nreserved;
611 gtk_preview_get_visual ()
614 preview_class = gtk_type_class (gtk_preview_get_type ());
616 return preview_class->info.visual;
620 gtk_preview_get_cmap ()
623 preview_class = gtk_type_class (gtk_preview_get_type ());
625 return preview_class->info.cmap;
629 gtk_preview_get_info ()
632 preview_class = gtk_type_class (gtk_preview_get_type ());
634 return &preview_class->info;
639 gtk_preview_destroy (GtkObject *object)
643 g_return_if_fail (object != NULL);
644 g_return_if_fail (GTK_IS_PREVIEW (object));
646 preview = GTK_PREVIEW (object);
648 g_free (preview->buffer);
649 preview->type = (GtkPreviewType) -1;
651 if (GTK_OBJECT_CLASS (parent_class)->destroy)
652 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
656 gtk_preview_realize (GtkWidget *widget)
659 GdkWindowAttr attributes;
660 gint attributes_mask;
662 g_return_if_fail (widget != NULL);
663 g_return_if_fail (GTK_IS_PREVIEW (widget));
665 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
666 preview = GTK_PREVIEW (widget);
668 attributes.window_type = GDK_WINDOW_CHILD;
669 attributes.x = widget->allocation.x;
670 attributes.y = widget->allocation.y;
671 attributes.width = widget->allocation.width;
672 attributes.height = widget->allocation.height;
673 attributes.wclass = GDK_INPUT_OUTPUT;
674 attributes.visual = gtk_widget_get_visual (widget);
675 attributes.colormap = gtk_widget_get_colormap (widget);
676 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
677 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
679 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
680 gdk_window_set_user_data (widget->window, widget);
682 widget->style = gtk_style_attach (widget->style, widget->window);
683 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
687 gtk_preview_unrealize (GtkWidget *widget)
691 g_return_if_fail (widget != NULL);
692 g_return_if_fail (GTK_IS_PREVIEW (widget));
694 preview = GTK_PREVIEW (widget);
696 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
697 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
701 gtk_preview_expose (GtkWidget *widget,
702 GdkEventExpose *event)
706 g_return_val_if_fail (widget != NULL, FALSE);
707 g_return_val_if_fail (GTK_IS_PREVIEW (widget), FALSE);
708 g_return_val_if_fail (event != NULL, FALSE);
710 if (GTK_WIDGET_DRAWABLE (widget))
712 preview = GTK_PREVIEW (widget);
714 gtk_preview_put (GTK_PREVIEW (widget),
715 widget->window, widget->style->black_gc,
716 (widget->allocation.width - preview->buffer_width) / 2,
717 (widget->allocation.height - preview->buffer_height) / 2,
718 event->area.x, event->area.y,
719 event->area.width, event->area.height);
726 gtk_preview_make_buffer (GtkPreview *preview)
732 g_return_if_fail (preview != NULL);
733 g_return_if_fail (GTK_IS_PREVIEW (preview));
735 widget = GTK_WIDGET (preview);
737 if (preview->expand &&
738 (widget->allocation.width != 0) &&
739 (widget->allocation.height != 0))
741 width = widget->allocation.width;
742 height = widget->allocation.height;
746 width = widget->requisition.width;
747 height = widget->requisition.height;
750 if (!preview->buffer ||
751 (preview->buffer_width != width) ||
752 (preview->buffer_height != height))
755 g_free (preview->buffer);
757 preview->buffer_width = width;
758 preview->buffer_height = height;
760 preview->buffer = g_new0 (guchar,
761 preview->buffer_width *
762 preview->buffer_height *
763 preview_class->info.bpp);
768 gtk_preview_get_visuals (GtkPreviewClass *klass)
770 static GdkVisualType types[] =
772 GDK_VISUAL_TRUE_COLOR,
773 GDK_VISUAL_DIRECT_COLOR,
774 GDK_VISUAL_TRUE_COLOR,
775 GDK_VISUAL_DIRECT_COLOR,
776 GDK_VISUAL_TRUE_COLOR,
777 GDK_VISUAL_DIRECT_COLOR,
778 GDK_VISUAL_TRUE_COLOR,
779 GDK_VISUAL_DIRECT_COLOR,
780 GDK_VISUAL_PSEUDO_COLOR
782 static gint depths[] = { 24, 24, 32, 32, 16, 16, 15, 15, 8 };
783 static gint nvisual_types = sizeof (types) / sizeof (types[0]);
787 g_return_if_fail (klass != NULL);
789 if (!klass->info.visual)
790 for (i = 0; i < nvisual_types; i++)
791 if ((klass->info.visual = gdk_visual_get_best_with_both (depths[i], types[i])))
793 if ((klass->info.visual->type == GDK_VISUAL_TRUE_COLOR) ||
794 (klass->info.visual->type == GDK_VISUAL_DIRECT_COLOR))
796 klass->info.lookup_red = g_new (gulong, 256);
797 klass->info.lookup_green = g_new (gulong, 256);
798 klass->info.lookup_blue = g_new (gulong, 256);
800 gtk_fill_lookup_array (klass->info.lookup_red,
801 klass->info.visual->depth,
802 klass->info.visual->red_shift,
803 8 - klass->info.visual->red_prec);
804 gtk_fill_lookup_array (klass->info.lookup_green,
805 klass->info.visual->depth,
806 klass->info.visual->green_shift,
807 8 - klass->info.visual->green_prec);
808 gtk_fill_lookup_array (klass->info.lookup_blue,
809 klass->info.visual->depth,
810 klass->info.visual->blue_shift,
811 8 - klass->info.visual->blue_prec);
816 if (!klass->info.visual)
818 g_warning ("unable to find a suitable visual for color image display.\n");
822 switch (klass->info.visual->depth)
839 gtk_preview_get_cmaps (GtkPreviewClass *klass)
841 g_return_if_fail (klass != NULL);
842 g_return_if_fail (klass->info.visual != NULL);
844 if ((klass->info.visual->type != GDK_VISUAL_TRUE_COLOR) &&
845 (klass->info.visual->type != GDK_VISUAL_DIRECT_COLOR))
849 klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
850 klass->info.cmap_alloced = install_cmap;
852 gtk_trim_cmap (klass);
853 gtk_create_8_bit (klass);
863 klass->info.cmap = gdk_colormap_get_system ();
866 if (gtk_get_preview_prop (&nred, &ngreen, &nblue, &ngray))
870 klass->info.nred_shades = nred;
871 klass->info.ngreen_shades = ngreen;
872 klass->info.nblue_shades = nblue;
873 klass->info.ngray_shades = ngray;
875 if (klass->info.nreserved)
877 klass->info.reserved_pixels = g_new (gulong, klass->info.nreserved);
878 if (!gdk_colors_alloc (klass->info.cmap, 0, NULL, 0,
879 klass->info.reserved_pixels,
880 klass->info.nreserved))
882 g_free (klass->info.reserved_pixels);
883 klass->info.reserved_pixels = NULL;
889 gtk_trim_cmap (klass);
892 gtk_create_8_bit (klass);
895 gtk_set_preview_prop (klass->info.nred_shades,
896 klass->info.ngreen_shades,
897 klass->info.nblue_shades,
898 klass->info.ngray_shades);
903 if (klass->info.visual == gdk_visual_get_system ())
904 klass->info.cmap = gdk_colormap_get_system ();
906 klass->info.cmap = gdk_colormap_new (klass->info.visual, FALSE);
907 klass->info.cmap_alloced = TRUE;
909 klass->info.nred_shades = 0;
910 klass->info.ngreen_shades = 0;
911 klass->info.nblue_shades = 0;
912 klass->info.ngray_shades = 0;
917 gtk_preview_dither_init (GtkPreviewClass *klass)
920 unsigned char low_shade, high_shade;
921 unsigned short index;
922 long red_mult, green_mult;
923 double red_matrix_width;
924 double green_matrix_width;
925 double blue_matrix_width;
926 double gray_matrix_width;
927 double red_colors_per_shade;
928 double green_colors_per_shade;
929 double blue_colors_per_shade;
930 double gray_colors_per_shade;
932 gint shades_r, shades_g, shades_b, shades_gray;
933 GtkDitherInfo *red_ordered_dither;
934 GtkDitherInfo *green_ordered_dither;
935 GtkDitherInfo *blue_ordered_dither;
936 GtkDitherInfo *gray_ordered_dither;
937 guchar ***dither_matrix;
940 { 0, 32, 8, 40, 2, 34, 10, 42 },
941 { 48, 16, 56, 24, 50, 18, 58, 26 },
942 { 12, 44, 4, 36, 14, 46, 6, 38 },
943 { 60, 28, 52, 20, 62, 30, 54, 22 },
944 { 3, 35, 11, 43, 1, 33, 9, 41 },
945 { 51, 19, 59, 27, 49, 17, 57, 25 },
946 { 15, 47, 7, 39, 13, 45, 5, 37 },
947 { 63, 31, 55, 23, 61, 29, 53, 21 }
950 if (klass->info.visual->type != GDK_VISUAL_PSEUDO_COLOR)
953 shades_r = klass->info.nred_shades;
954 shades_g = klass->info.ngreen_shades;
955 shades_b = klass->info.nblue_shades;
956 shades_gray = klass->info.ngray_shades;
958 red_mult = shades_g * shades_b;
959 green_mult = shades_b;
961 red_colors_per_shade = 255.0 / (shades_r - 1);
962 red_matrix_width = red_colors_per_shade / 64;
964 green_colors_per_shade = 255.0 / (shades_g - 1);
965 green_matrix_width = green_colors_per_shade / 64;
967 blue_colors_per_shade = 255.0 / (shades_b - 1);
968 blue_matrix_width = blue_colors_per_shade / 64;
970 gray_colors_per_shade = 255.0 / (shades_gray - 1);
971 gray_matrix_width = gray_colors_per_shade / 64;
973 /* alloc the ordered dither arrays for accelerated dithering */
975 klass->info.dither_red = g_new (GtkDitherInfo, 256);
976 klass->info.dither_green = g_new (GtkDitherInfo, 256);
977 klass->info.dither_blue = g_new (GtkDitherInfo, 256);
978 klass->info.dither_gray = g_new (GtkDitherInfo, 256);
980 red_ordered_dither = klass->info.dither_red;
981 green_ordered_dither = klass->info.dither_green;
982 blue_ordered_dither = klass->info.dither_blue;
983 gray_ordered_dither = klass->info.dither_gray;
985 dither_matrix = g_new (guchar**, 8);
986 for (i = 0; i < 8; i++)
988 dither_matrix[i] = g_new (guchar*, 8);
989 for (j = 0; j < 8; j++)
990 dither_matrix[i][j] = g_new (guchar, 65);
993 klass->info.dither_matrix = dither_matrix;
995 /* setup the ordered_dither_matrices */
997 for (i = 0; i < 8; i++)
998 for (j = 0; j < 8; j++)
999 for (k = 0; k <= 64; k++)
1000 dither_matrix[i][j][k] = (DM[i][j] < k) ? 1 : 0;
1002 /* setup arrays containing three bytes of information for red, green, & blue */
1003 /* the arrays contain :
1004 * 1st byte: low end shade value
1005 * 2nd byte: high end shade value
1006 * 3rd & 4th bytes: ordered dither matrix index
1009 gray_pixels = klass->info.gray_pixels;
1011 for (i = 0; i < 256; i++)
1014 /* setup the red information */
1016 low_shade = (unsigned char) (i / red_colors_per_shade);
1017 if (low_shade == (shades_r - 1))
1019 high_shade = low_shade + 1;
1021 index = (unsigned short)
1022 (((double) i - low_shade * red_colors_per_shade) /
1025 low_shade *= red_mult;
1026 high_shade *= red_mult;
1028 red_ordered_dither[i].s[1] = index;
1029 red_ordered_dither[i].c[0] = low_shade;
1030 red_ordered_dither[i].c[1] = high_shade;
1034 /* setup the green information */
1036 low_shade = (unsigned char) (i / green_colors_per_shade);
1037 if (low_shade == (shades_g - 1))
1039 high_shade = low_shade + 1;
1041 index = (unsigned short)
1042 (((double) i - low_shade * green_colors_per_shade) /
1043 green_matrix_width);
1045 low_shade *= green_mult;
1046 high_shade *= green_mult;
1048 green_ordered_dither[i].s[1] = index;
1049 green_ordered_dither[i].c[0] = low_shade;
1050 green_ordered_dither[i].c[1] = high_shade;
1054 /* setup the blue information */
1056 low_shade = (unsigned char) (i / blue_colors_per_shade);
1057 if (low_shade == (shades_b - 1))
1059 high_shade = low_shade + 1;
1061 index = (unsigned short)
1062 (((double) i - low_shade * blue_colors_per_shade) /
1065 blue_ordered_dither[i].s[1] = index;
1066 blue_ordered_dither[i].c[0] = low_shade;
1067 blue_ordered_dither[i].c[1] = high_shade;
1071 /* setup the gray information */
1073 low_shade = (unsigned char) (i / gray_colors_per_shade);
1074 if (low_shade == (shades_gray - 1))
1076 high_shade = low_shade + 1;
1078 index = (unsigned short)
1079 (((double) i - low_shade * gray_colors_per_shade) /
1082 gray_ordered_dither[i].s[1] = index;
1083 gray_ordered_dither[i].c[0] = gray_pixels[low_shade];
1084 gray_ordered_dither[i].c[1] = gray_pixels[high_shade];
1090 gtk_fill_lookup_array (gulong *array,
1095 double one_over_gamma;
1100 if (preview_class->info.gamma != 0.0)
1101 one_over_gamma = 1.0 / preview_class->info.gamma;
1103 one_over_gamma = 1.0;
1105 for (i = 0; i < 256; i++)
1107 if (one_over_gamma == 1.0)
1108 array[i] = ((i >> prec) << shift);
1111 ind = (double) i / 255.0;
1112 val = (int) (255 * pow (ind, one_over_gamma));
1113 array[i] = ((val >> prec) << shift);
1119 gtk_trim_cmap (GtkPreviewClass *klass)
1131 nred = klass->info.nred_shades;
1132 ngreen = klass->info.ngreen_shades;
1133 nblue = klass->info.nblue_shades;
1134 ngray = klass->info.ngray_shades;
1135 nreserved = klass->info.nreserved;
1140 total = nred * ngreen * nblue + ngray + nreserved;
1144 if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
1148 success = gdk_colors_alloc (klass->info.cmap, 0, NULL, 0, pixels, total);
1153 klass->info.reserved_pixels = g_new (gulong, nreserved);
1154 memcpy (klass->info.reserved_pixels, pixels, sizeof (gulong) * nreserved);
1155 gdk_colors_free (klass->info.cmap, &pixels[nreserved],
1156 total - nreserved, 0);
1160 gdk_colors_free (klass->info.cmap, pixels, total, 0);
1168 if ((nblue >= nred) && (nblue >= ngreen))
1170 else if ((nred >= ngreen) && (nred >= nblue))
1174 tmp = log (ngray) / log (2);
1177 ngreen = ngreen - 1;
1184 if ((nred < 2) || (ngreen < 2) || (nblue < 2) || (ngray < 2))
1186 g_print ("Unable to allocate sufficient colormap entries.\n");
1187 g_print ("Try exiting other color intensive applications.\n");
1191 /* If any of the shade values has changed, issue a warning */
1192 if ((nred != klass->info.nred_shades) ||
1193 (ngreen != klass->info.ngreen_shades) ||
1194 (nblue != klass->info.nblue_shades) ||
1195 (ngray != klass->info.ngray_shades))
1197 g_print ("Not enough colors to satisfy requested color cube.\n");
1198 g_print ("Reduced color cube shades from\n");
1199 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",
1200 klass->info.nred_shades, klass->info.ngreen_shades,
1201 klass->info.nblue_shades, klass->info.ngray_shades,
1202 nred, ngreen, nblue, ngray);
1205 klass->info.nred_shades = nred;
1206 klass->info.ngreen_shades = ngreen;
1207 klass->info.nblue_shades = nblue;
1208 klass->info.ngray_shades = ngray;
1212 gtk_create_8_bit (GtkPreviewClass *klass)
1214 unsigned int r, g, b;
1215 unsigned int rv, gv, bv;
1216 unsigned int dr, dg, db, dgray;
1219 double one_over_gamma;
1222 if (!klass->info.color_pixels)
1223 klass->info.color_pixels = g_new (gulong, 256);
1225 if (!klass->info.gray_pixels)
1226 klass->info.gray_pixels = g_new (gulong, 256);
1228 if (klass->info.gamma != 0.0)
1229 one_over_gamma = 1.0 / klass->info.gamma;
1231 one_over_gamma = 1.0;
1233 dr = klass->info.nred_shades - 1;
1234 dg = klass->info.ngreen_shades - 1;
1235 db = klass->info.nblue_shades - 1;
1236 dgray = klass->info.ngray_shades - 1;
1238 pixels = klass->info.color_pixels;
1240 for (r = 0, i = 0; r <= dr; r++)
1241 for (g = 0; g <= dg; g++)
1242 for (b = 0; b <= db; b++, i++)
1244 rv = (unsigned int) ((r * klass->info.visual->colormap_size) / dr);
1245 gv = (unsigned int) ((g * klass->info.visual->colormap_size) / dg);
1246 bv = (unsigned int) ((b * klass->info.visual->colormap_size) / db);
1247 color.red = ((int) (255 * pow ((double) rv / 256.0, one_over_gamma))) * 257;
1248 color.green = ((int) (255 * pow ((double) gv / 256.0, one_over_gamma))) * 257;
1249 color.blue = ((int) (255 * pow ((double) bv / 256.0, one_over_gamma))) * 257;
1251 if (!gdk_color_alloc (klass->info.cmap, &color))
1253 g_error ("could not initialize 8-bit combined colormap");
1257 pixels[i] = color.pixel;
1260 pixels = klass->info.gray_pixels;
1262 for (i = 0; i < (int) klass->info.ngray_shades; i++)
1264 color.red = (i * klass->info.visual->colormap_size) / dgray;
1265 color.red = ((int) (255 * pow ((double) color.red / 256.0, one_over_gamma))) * 257;
1266 color.green = color.red;
1267 color.blue = color.red;
1269 if (!gdk_color_alloc (klass->info.cmap, &color))
1271 g_error ("could not initialize 8-bit combined colormap");
1275 pixels[i] = color.pixel;
1281 gtk_color_8 (guchar *src,
1288 GtkDitherInfo *dither_red;
1289 GtkDitherInfo *dither_green;
1290 GtkDitherInfo *dither_blue;
1291 GtkDitherInfo r, g, b;
1292 guchar **dither_matrix;
1295 colors = preview_class->info.color_pixels;
1296 dither_red = preview_class->info.dither_red;
1297 dither_green = preview_class->info.dither_green;
1298 dither_blue = preview_class->info.dither_blue;
1299 dither_matrix = preview_class->info.dither_matrix[y & 0x7];
1303 r = dither_red[src[0]];
1304 g = dither_green[src[1]];
1305 b = dither_blue[src[2]];
1308 matrix = dither_matrix[x++ & 0x7];
1309 *dest++ = colors[(r.c[matrix[r.s[1]]] +
1310 g.c[matrix[g.s[1]]] +
1311 b.c[matrix[b.s[1]]])];
1316 gtk_color_16 (guchar *src,
1321 gulong *lookup_green;
1322 gulong *lookup_blue;
1325 lookup_red = preview_class->info.lookup_red;
1326 lookup_green = preview_class->info.lookup_green;
1327 lookup_blue = preview_class->info.lookup_blue;
1331 val = COLOR_COMPOSE (src[0], src[1], src[2]);
1340 gtk_color_24 (guchar *src,
1345 gulong *lookup_green;
1346 gulong *lookup_blue;
1349 lookup_red = preview_class->info.lookup_red;
1350 lookup_green = preview_class->info.lookup_green;
1351 lookup_blue = preview_class->info.lookup_blue;
1355 val = COLOR_COMPOSE (src[0], src[1], src[2]);
1358 dest[2] = val >> 16;
1365 gtk_grayscale_8 (guchar *src,
1371 GtkDitherInfo *dither_gray;
1373 guchar **dither_matrix;
1376 dither_gray = preview_class->info.dither_gray;
1377 dither_matrix = preview_class->info.dither_matrix[y & 0x7];
1381 gray = dither_gray[*src++];
1382 matrix = dither_matrix[x++ & 0x7];
1383 *dest++ = gray.c[matrix[gray.s[1]]];
1388 gtk_grayscale_16 (guchar *src,
1393 gulong *lookup_green;
1394 gulong *lookup_blue;
1397 lookup_red = preview_class->info.lookup_red;
1398 lookup_green = preview_class->info.lookup_green;
1399 lookup_blue = preview_class->info.lookup_blue;
1403 val = COLOR_COMPOSE (*src, *src, *src);
1412 gtk_grayscale_24 (guchar *src,
1417 gulong *lookup_green;
1418 gulong *lookup_blue;
1421 lookup_red = preview_class->info.lookup_red;
1422 lookup_green = preview_class->info.lookup_green;
1423 lookup_blue = preview_class->info.lookup_blue;
1427 val = COLOR_COMPOSE (*src, *src, *src);
1430 dest[2] = val >> 16;
1438 gtk_get_preview_prop (guint *nred,
1443 GtkPreviewProp *prop;
1446 property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
1448 if (gdk_property_get (NULL, property, property,
1449 0, sizeof (GtkPreviewProp), FALSE,
1450 NULL, NULL, NULL, (guchar**) &prop))
1452 *nred = ntohs (prop->nred_shades);
1453 *ngreen = ntohs (prop->ngreen_shades);
1454 *nblue = ntohs (prop->nblue_shades);
1455 *ngray = ntohs (prop->ngray_shades);
1457 prop->ref_count = htons (ntohs (prop->ref_count) + 1);
1458 gdk_property_change (NULL, property, property, 16,
1459 GDK_PROP_MODE_REPLACE,
1469 gtk_set_preview_prop (guint nred,
1474 GtkPreviewProp prop;
1477 property = gdk_atom_intern ("GTK_PREVIEW_INFO", FALSE);
1479 prop.ref_count = htons (1);
1480 prop.nred_shades = htons (nred);
1481 prop.ngreen_shades = htons (ngreen);
1482 prop.nblue_shades = htons (nblue);
1483 prop.ngray_shades = htons (ngray);
1485 gdk_property_change (NULL, property, property, 16,
1486 GDK_PROP_MODE_REPLACE,
1487 (guchar*) &prop, 5);
1492 gtk_lsbmsb_1_1 (guchar *dest,
1496 memcpy (dest, src, count);
1500 gtk_lsb_2_2 (guchar *dest,
1504 memcpy (dest, src, count * 2);
1508 gtk_msb_2_2 (guchar *dest,
1522 gtk_lsb_3_3 (guchar *dest,
1526 memcpy (dest, src, count * 3);
1530 gtk_msb_3_3 (guchar *dest,
1545 gtk_lsb_3_4 (guchar *dest,
1560 gtk_msb_3_4 (guchar *dest,