]> Pileus Git - ~andy/gtk/blob - gtk/gtkpreview.c
removed deprecated functions: gtk_clist_set_border,
[~andy/gtk] / gtk / gtkpreview.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include <math.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/param.h>
24 #include "gdk/gdkx.h"
25 #include "gdk/gdkrgb.h"
26 #include "gtkpreview.h"
27 #include "gtksignal.h"
28
29
30 #define PREVIEW_CLASS(w)      GTK_PREVIEW_CLASS (GTK_OBJECT (w)->klass)
31
32
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 void   gtk_preview_size_allocate (GtkWidget        *widget,
38                                          GtkAllocation    *allocation);
39 static gint   gtk_preview_expose        (GtkWidget        *widget,
40                                          GdkEventExpose   *event);
41 static void   gtk_preview_make_buffer   (GtkPreview       *preview);
42 static void   gtk_fill_lookup_array     (guchar           *array);
43
44 static GtkWidgetClass *parent_class = NULL;
45 static GtkPreviewClass *preview_class = NULL;
46 static gint install_cmap = FALSE;
47
48
49 guint
50 gtk_preview_get_type (void)
51 {
52   static guint preview_type = 0;
53
54   if (!preview_type)
55     {
56       static const GtkTypeInfo preview_info =
57       {
58         "GtkPreview",
59         sizeof (GtkPreview),
60         sizeof (GtkPreviewClass),
61         (GtkClassInitFunc) gtk_preview_class_init,
62         (GtkObjectInitFunc) gtk_preview_init,
63         /* reserved_1 */ NULL,
64         /* reserved_2 */ NULL,
65         (GtkClassInitFunc) NULL,
66       };
67
68       preview_type = gtk_type_unique (gtk_widget_get_type (), &preview_info);
69     }
70
71   return preview_type;
72 }
73
74 static void
75 gtk_preview_class_init (GtkPreviewClass *klass)
76 {
77   GtkObjectClass *object_class;
78   GtkWidgetClass *widget_class;
79
80   object_class = (GtkObjectClass*) klass;
81   widget_class = (GtkWidgetClass*) klass;
82
83   parent_class = gtk_type_class (gtk_widget_get_type ());
84   preview_class = klass;
85
86   object_class->finalize = gtk_preview_finalize;
87
88   widget_class->realize = gtk_preview_realize;
89   widget_class->size_allocate = gtk_preview_size_allocate;
90   widget_class->expose_event = gtk_preview_expose;
91
92   klass->info.visual = NULL;
93   klass->info.cmap = NULL;
94
95   klass->info.lookup = NULL;
96
97   klass->info.gamma = 1.0;
98
99   gdk_rgb_init ();
100   klass->info.cmap = gdk_rgb_get_cmap ();
101   klass->info.visual = gdk_rgb_get_visual ();
102 }
103
104 void
105 gtk_preview_reset (void)
106 {
107   /* unimplemented */
108 }
109
110 static void
111 gtk_preview_init (GtkPreview *preview)
112 {
113   preview->buffer = NULL;
114   preview->buffer_width = 0;
115   preview->buffer_height = 0;
116   preview->expand = FALSE;
117 }
118
119 void
120 gtk_preview_uninit (void)
121 {
122
123   /* unimplemented */
124 }
125
126 GtkWidget*
127 gtk_preview_new (GtkPreviewType type)
128 {
129   GtkPreview *preview;
130
131   preview = gtk_type_new (gtk_preview_get_type ());
132   preview->type = type;
133
134   if (type == GTK_PREVIEW_COLOR)
135     preview->bpp = 3;
136   else
137     preview->bpp = 1;
138
139   preview->dither = GDK_RGB_DITHER_NORMAL;
140
141   return GTK_WIDGET (preview);
142 }
143
144 void
145 gtk_preview_size (GtkPreview *preview,
146                   gint        width,
147                   gint        height)
148 {
149   g_return_if_fail (preview != NULL);
150   g_return_if_fail (GTK_IS_PREVIEW (preview));
151
152   if ((width != GTK_WIDGET (preview)->requisition.width) ||
153       (height != GTK_WIDGET (preview)->requisition.height))
154     {
155       GTK_WIDGET (preview)->requisition.width = width;
156       GTK_WIDGET (preview)->requisition.height = height;
157
158       if (preview->buffer)
159         g_free (preview->buffer);
160       preview->buffer = NULL;
161     }
162 }
163
164 void
165 gtk_preview_put (GtkPreview   *preview,
166                  GdkWindow    *window,
167                  GdkGC        *gc,
168                  gint          srcx,
169                  gint          srcy,
170                  gint          destx,
171                  gint          desty,
172                  gint          width,
173                  gint          height)
174 {
175   GtkWidget *widget;
176   GdkRectangle r1, r2, r3;
177   guchar *src;
178   guint bpp;
179   guint rowstride;
180
181   g_return_if_fail (preview != NULL);
182   g_return_if_fail (GTK_IS_PREVIEW (preview));
183   g_return_if_fail (window != NULL);
184
185   if (!preview->buffer)
186     return;
187
188   widget = GTK_WIDGET (preview);
189
190   r1.x = 0;
191   r1.y = 0;
192   r1.width = preview->buffer_width;
193   r1.height = preview->buffer_height;
194
195   r2.x = srcx;
196   r2.y = srcy;
197   r2.width = width;
198   r2.height = height;
199
200   if (!gdk_rectangle_intersect (&r1, &r2, &r3))
201     return;
202
203   bpp = preview->bpp;
204   rowstride = preview->rowstride;
205
206   src = preview->buffer + r3.y * rowstride + r3.x * bpp;
207
208   if (preview->type == GTK_PREVIEW_COLOR)
209     gdk_draw_rgb_image (window,
210                         gc,
211                         destx + (r3.x - srcx),
212                         desty + (r3.y - srcy),
213                         r3.width,
214                         r3.height,
215                         preview->dither,
216                         src,
217                         rowstride);
218   else
219     gdk_draw_gray_image (window,
220                          gc,
221                          destx + (r3.x - srcx),
222                          desty + (r3.y - srcy),
223                          r3.width,
224                          r3.height,
225                          preview->dither,
226                          src,
227                          rowstride);
228                         
229 }
230
231 void
232 gtk_preview_draw_row (GtkPreview *preview,
233                       guchar     *data,
234                       gint        x,
235                       gint        y,
236                       gint        w)
237 {
238   guint bpp;
239   guint rowstride;
240
241   g_return_if_fail (preview != NULL);
242   g_return_if_fail (GTK_IS_PREVIEW (preview));
243   g_return_if_fail (data != NULL);
244   g_return_if_fail (preview_class->info.visual != NULL);
245   
246   bpp = (preview->type == GTK_PREVIEW_COLOR ? 3 : 1);
247   rowstride = (preview->buffer_width * bpp + 3) & -4;
248
249   if ((w <= 0) || (y < 0))
250     return;
251
252   g_return_if_fail (data != NULL);
253
254   gtk_preview_make_buffer (preview);
255
256   if (x + w > preview->buffer_width)
257     return;
258
259   if (y + 1 > preview->buffer_height)
260     return;
261
262   if (preview_class->info.gamma == 1.0)
263     memcpy (preview->buffer + y * rowstride + x * bpp, data, w * bpp);
264   else
265     {
266       guint i, size;
267       guchar *src, *dst;
268       guchar *lookup;
269
270       if (preview_class->info.lookup != NULL)
271         lookup = preview_class->info.lookup;
272       else
273         {
274           preview_class->info.lookup = g_new (guchar, 256);
275           gtk_fill_lookup_array (preview_class->info.lookup);
276           lookup = preview_class->info.lookup;
277         }
278       size = w * bpp;
279       src = data;
280       dst = preview->buffer + y * rowstride + x * bpp;
281       for (i = 0; i < size; i++)
282         *dst++ = lookup[*src++];
283     }
284 }
285
286 void
287 gtk_preview_set_expand (GtkPreview *preview,
288                         gint        expand)
289 {
290   g_return_if_fail (preview != NULL);
291   g_return_if_fail (GTK_IS_PREVIEW (preview));
292
293   preview->expand = (expand != FALSE);
294 }
295
296 void
297 gtk_preview_set_gamma (double _gamma)
298 {
299   if (!preview_class)
300     preview_class = gtk_type_class (gtk_preview_get_type ());
301
302   if (preview_class->info.gamma != _gamma)
303     {
304       preview_class->info.gamma = _gamma;
305       if (preview_class->info.lookup != NULL)
306         {
307           g_free (preview_class->info.lookup);
308           preview_class->info.lookup = NULL;
309         }
310     }
311 }
312
313 void
314 gtk_preview_set_color_cube (guint nred_shades,
315                             guint ngreen_shades,
316                             guint nblue_shades,
317                             guint ngray_shades)
318 {
319   /* unimplemented */
320 }
321
322 void
323 gtk_preview_set_install_cmap (gint _install_cmap)
324 {
325   /* effectively unimplemented */
326   install_cmap = _install_cmap;
327 }
328
329 void
330 gtk_preview_set_reserved (gint nreserved)
331 {
332
333   /* unimplemented */
334 }
335
336 void
337 gtk_preview_set_dither (GtkPreview      *preview,
338                         GdkRgbDither     dither)
339 {
340   preview->dither = dither;
341 }
342
343 GdkVisual*
344 gtk_preview_get_visual (void)
345 {
346   if (!preview_class)
347     preview_class = gtk_type_class (gtk_preview_get_type ());
348
349   return preview_class->info.visual;
350 }
351
352 GdkColormap*
353 gtk_preview_get_cmap (void)
354 {
355   if (!preview_class)
356     preview_class = gtk_type_class (gtk_preview_get_type ());
357
358   return preview_class->info.cmap;
359 }
360
361 GtkPreviewInfo*
362 gtk_preview_get_info (void)
363 {
364   if (!preview_class)
365     preview_class = gtk_type_class (gtk_preview_get_type ());
366
367   return &preview_class->info;
368 }
369
370
371 static void
372 gtk_preview_finalize (GtkObject *object)
373 {
374   GtkPreview *preview;
375
376   g_return_if_fail (object != NULL);
377   g_return_if_fail (GTK_IS_PREVIEW (object));
378
379   preview = GTK_PREVIEW (object);
380   if (preview->buffer)
381     g_free (preview->buffer);
382   preview->type = (GtkPreviewType) -1;
383
384   (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
385 }
386
387 static void
388 gtk_preview_realize (GtkWidget *widget)
389 {
390   GtkPreview *preview;
391   GdkWindowAttr attributes;
392   gint attributes_mask;
393
394   g_return_if_fail (widget != NULL);
395   g_return_if_fail (GTK_IS_PREVIEW (widget));
396
397   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
398   preview = GTK_PREVIEW (widget);
399
400   attributes.window_type = GDK_WINDOW_CHILD;
401
402   if (preview->expand)
403     {
404       attributes.width = widget->allocation.width;
405       attributes.height = widget->allocation.height;
406     }
407   else
408     {
409       attributes.width = MIN (widget->requisition.width, widget->allocation.width);
410       attributes.height = MIN (widget->requisition.height, widget->allocation.height);
411     }
412
413   attributes.x = widget->allocation.x + (widget->allocation.width - attributes.width) / 2;
414   attributes.y = widget->allocation.y + (widget->allocation.height - attributes.height) / 2;;
415
416   attributes.wclass = GDK_INPUT_OUTPUT;
417   attributes.visual = preview_class->info.visual;
418   attributes.colormap = preview_class->info.cmap;
419   attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
420   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
421
422   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
423   gdk_window_set_user_data (widget->window, widget);
424
425   widget->style = gtk_style_attach (widget->style, widget->window);
426   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
427 }
428
429 static void   
430 gtk_preview_size_allocate (GtkWidget        *widget,
431                            GtkAllocation    *allocation)
432 {
433   GtkPreview *preview;
434   gint width, height;
435
436   g_return_if_fail (widget != NULL);
437   g_return_if_fail (GTK_IS_PREVIEW (widget));
438
439   preview = GTK_PREVIEW (widget);
440   widget->allocation = *allocation;
441
442   if (GTK_WIDGET_REALIZED (widget))
443     {
444       if (preview->expand)
445         {
446           width = widget->allocation.width;
447           height = widget->allocation.height;
448         }
449       else
450         {
451           width = MIN (widget->allocation.width, widget->requisition.width);
452           height = MIN (widget->allocation.height, widget->requisition.height);
453         }
454
455       gdk_window_move_resize (widget->window,
456                               widget->allocation.x + (widget->allocation.width - width) / 2,
457                               widget->allocation.y + (widget->allocation.height - height) / 2,
458                               width, height);
459     }
460 }
461
462 static gint
463 gtk_preview_expose (GtkWidget      *widget,
464                     GdkEventExpose *event)
465 {
466   GtkPreview *preview;
467   gint width, height;
468
469   g_return_val_if_fail (widget != NULL, FALSE);
470   g_return_val_if_fail (GTK_IS_PREVIEW (widget), FALSE);
471   g_return_val_if_fail (event != NULL, FALSE);
472
473   if (GTK_WIDGET_DRAWABLE (widget))
474     {
475       preview = GTK_PREVIEW (widget);
476       
477       gdk_window_get_size (widget->window, &width, &height);
478
479       gtk_preview_put (GTK_PREVIEW (widget),
480                        widget->window, widget->style->black_gc,
481                        event->area.x - (width - preview->buffer_width)/2,
482                        event->area.y - (height - preview->buffer_height)/2,
483                        event->area.x, event->area.y,
484                        event->area.width, event->area.height);
485     }
486   
487   return FALSE;
488 }
489
490 static void
491 gtk_preview_make_buffer (GtkPreview *preview)
492 {
493   GtkWidget *widget;
494   gint width;
495   gint height;
496
497   g_return_if_fail (preview != NULL);
498   g_return_if_fail (GTK_IS_PREVIEW (preview));
499
500   widget = GTK_WIDGET (preview);
501
502   if (preview->expand &&
503       (widget->allocation.width != 0) &&
504       (widget->allocation.height != 0))
505     {
506       width = widget->allocation.width;
507       height = widget->allocation.height;
508     }
509   else
510     {
511       width = widget->requisition.width;
512       height = widget->requisition.height;
513     }
514
515   if (!preview->buffer ||
516       (preview->buffer_width != width) ||
517       (preview->buffer_height != height))
518     {
519       if (preview->buffer)
520         g_free (preview->buffer);
521
522       preview->buffer_width = width;
523       preview->buffer_height = height;
524
525       preview->rowstride = (preview->buffer_width * preview->bpp + 3) & -4;
526       preview->buffer = g_new0 (guchar,
527                                 preview->buffer_height *
528                                 preview->rowstride);
529     }
530 }
531
532 /* This will be useful for implementing gamma. */
533 static void
534 gtk_fill_lookup_array (guchar *array)
535 {
536   double one_over_gamma;
537   double ind;
538   int val;
539   int i;
540
541   one_over_gamma = 1.0 / preview_class->info.gamma;
542
543   for (i = 0; i < 256; i++)
544     {
545       ind = (double) i / 255.0;
546       val = (int) (255 * pow (ind, one_over_gamma));
547       array[i] = val;
548     }
549 }