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