source: trunk/third/gtk/gtk/gtkpreview.c @ 14482

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