about-dialog.c 24.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
18
19
20

#include "config.h"

Elliot Lee's avatar
Elliot Lee committed
21
22
#include <stdio.h>
#include <stdlib.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
23
#include <string.h>
Elliot Lee's avatar
Elliot Lee committed
24
#include <time.h>
Manish Singh's avatar
Manish Singh committed
25

26
#include <gtk/gtk.h>
Manish Singh's avatar
Manish Singh committed
27
#include <gdk/gdkkeysyms.h>
Manish Singh's avatar
Manish Singh committed
28

29
#include "libgimpmath/gimpmath.h"
30
#include "libgimpbase/gimpbase.h"
31
#include "libgimpwidgets/gimpwidgets.h"
32

33
#include "gui-types.h"
Sven Neumann's avatar
Sven Neumann committed
34

Michael Natterer's avatar
Michael Natterer committed
35
#include "core/gimptoolinfo.h"
36

37
#include "widgets/gimphelp-ids.h"
Michael Natterer's avatar
Michael Natterer committed
38
39
#include "widgets/gimpdnd.h"

40
#include "about-dialog.h"
Michael Natterer's avatar
Michael Natterer committed
41
#include "authors.h"
42

43
#include "gimp-intl.h"
44

45
46
47
48
49
50
51
52
53
static gchar *founders[] =
{
  N_("Version %s brought to you by"),
  "Spencer Kimball & Peter Mattis"
};

static gchar *translators[] =
{
  N_("Translation by"),
54
55
56
  /* Translators: insert your names here, separated by newline */
  /* we'd prefer just the names, please no email adresses.     */
  N_("translator-credits"),
57
58
59
60
};

static gchar *contri_intro[] =
{
61
62
  N_("Contributions by")
};
63

64
65
static gchar **translator_names = NULL;

66
67
68
69
70
71
typedef struct
{
  GtkWidget    *about_dialog;
  GtkWidget    *logo_area;
  GdkPixmap    *logo_pixmap;
  GdkRectangle  pixmaparea;
72

73
74
75
76
77
78
79
80
81
82
  GdkRectangle  textarea;
  gdouble       text_size;
  gdouble       min_text_size;
  PangoLayout  *layout;
  PangoColor    foreground;
  PangoColor    background;

  gint          timer;

  gint          index;
83
  gint          animstep;
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  gboolean      visible;
  gint          textrange[2];
  gint          state;

} GimpAboutInfo;

PangoColor gradient[] =
{
    { 31868, 33153, 32382 },
    { 10000, 10000, 10000 },
    { 65535, 65535, 65535 },
};

static GimpAboutInfo about_info = { 0 };
98

99
100
static gboolean  about_dialog_load_logo   (GtkWidget      *window);
static void      about_dialog_destroy     (GtkObject      *object,
101
                                           gpointer        data);
102
static void      about_dialog_unmap       (GtkWidget      *widget,
103
                                           gpointer        data);
104
static gint      about_dialog_logo_expose (GtkWidget      *widget,
105
106
                                           GdkEventExpose *event,
                                           gpointer        data);
107
static gint      about_dialog_button      (GtkWidget      *widget,
108
109
                                           GdkEventButton *event,
                                           gpointer        data);
Manish Singh's avatar
Manish Singh committed
110
static gint      about_dialog_key         (GtkWidget      *widget,
111
112
                                           GdkEventKey    *event,
                                           gpointer        data);
113
static void      reshuffle_array          (void);
114
static gboolean  about_dialog_timer       (gpointer        data);
Elliot Lee's avatar
Elliot Lee committed
115
116


117
static gboolean     double_speed     = FALSE;
Michael Natterer's avatar
Michael Natterer committed
118

119
static PangoFontDescription *font_desc = NULL;
120
121
122
static gchar      **scroll_text      = authors;
static gint         nscroll_texts    = G_N_ELEMENTS (authors);
static gint         shuffle_array[G_N_ELEMENTS (authors)];
123

Michael Natterer's avatar
Michael Natterer committed
124

125
GtkWidget *
126
about_dialog_create (void)
Elliot Lee's avatar
Elliot Lee committed
127
{
128
  GdkModifierType mask;
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  if (! about_info.about_dialog)
    {
      GtkWidget *widget;

      about_info.textarea.x = 0;
      about_info.textarea.y = 265;
      about_info.textarea.width = 300;
      about_info.textarea.height = 60;

      about_info.foreground.red   = 65535;
      about_info.foreground.green = 65535;
      about_info.foreground.blue  = 65535;
      about_info.background.red   = 31868;
      about_info.background.green = 33153;
      about_info.background.blue  = 32382;

      about_info.visible = FALSE;
      about_info.state = 0;
148
      about_info.animstep = -1;
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

      widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      about_info.about_dialog = widget;

      gtk_window_set_type_hint (GTK_WINDOW (widget),
                                GDK_WINDOW_TYPE_HINT_DIALOG);
      gtk_window_set_wmclass (GTK_WINDOW (widget), "about_dialog", "Gimp");
      gtk_window_set_title (GTK_WINDOW (widget), _("About The GIMP"));
      gtk_window_set_position (GTK_WINDOW (widget), GTK_WIN_POS_CENTER);

      /* The window must not be resizeable, since otherwise
       * the copying of nonexisting parts of the image pixmap
       * would result in an endless loop due to the X-Server
       * generating expose events on the pixmap. */

      gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);

      g_signal_connect (widget, "destroy",
                        G_CALLBACK (about_dialog_destroy),
                        NULL);
      g_signal_connect (widget, "unmap",
                        G_CALLBACK (about_dialog_unmap),
                        NULL);
      g_signal_connect (widget, "button_press_event",
                        G_CALLBACK (about_dialog_button),
                        NULL);
      g_signal_connect (widget, "key_press_event",
                        G_CALLBACK (about_dialog_key),
                        NULL);
      
      gtk_widget_set_events (widget, GDK_BUTTON_PRESS_MASK);

      if (! about_dialog_load_logo (widget))
        {
	  gtk_widget_destroy (widget);
	  about_info.about_dialog = NULL;
185
	  return NULL;
Elliot Lee's avatar
Elliot Lee committed
186
187
	}

188
189
      widget = gtk_drawing_area_new ();
      about_info.logo_area = widget;
Elliot Lee's avatar
Elliot Lee committed
190

191
192
193
194
195
196
197
      gtk_widget_set_size_request (widget,
                                   about_info.pixmaparea.width,
                                   about_info.pixmaparea.height);
      gtk_widget_set_events (widget, GDK_EXPOSURE_MASK);
      gtk_container_add (GTK_CONTAINER (about_info.about_dialog),
                         widget);
      gtk_widget_show (widget);
Elliot Lee's avatar
Elliot Lee committed
198

199
      g_signal_connect (widget, "expose_event",
200
201
202
			G_CALLBACK (about_dialog_logo_expose),
			NULL);

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
      gtk_widget_realize (widget);
      gdk_window_set_background (widget->window,
                                 &(widget->style)->black);

      about_info.layout = gtk_widget_create_pango_layout (about_info.logo_area, NULL);
      g_object_weak_ref (G_OBJECT (about_info.logo_area), 
                         (GWeakNotify) g_object_unref, about_info.layout);

      font_desc = pango_font_description_from_string ("Bitstream Vera Sans,"
                                                      "Trebuchet MS,"
                                                      "Helvetica,"
                                                      "Sans,"
                                                      "Bold 13");

      pango_layout_set_font_description (about_info.layout, font_desc);
      pango_layout_set_justify (about_info.layout, PANGO_ALIGN_CENTER);

Elliot Lee's avatar
Elliot Lee committed
220
221
    }

222
223
224
225
  /* for future enhancements */
  gdk_window_get_pointer (NULL, NULL, NULL, &mask);

  if (! GTK_WIDGET_VISIBLE (about_info.about_dialog))
Elliot Lee's avatar
Elliot Lee committed
226
    {
227
      if (! double_speed)
Elliot Lee's avatar
Elliot Lee committed
228
	{
229
230
          about_info.state = 0;
          about_info.index = 0;
231

232
          reshuffle_array ();
233
          pango_layout_set_text (about_info.layout, "", -1);
Elliot Lee's avatar
Elliot Lee committed
234
235
	}
    }
236

237
  gtk_window_present (GTK_WINDOW (about_info.about_dialog));
238

239
  return about_info.about_dialog;
Elliot Lee's avatar
Elliot Lee committed
240
241
}

242
static gboolean
Elliot Lee's avatar
Elliot Lee committed
243
244
about_dialog_load_logo (GtkWidget *window)
{
245
246
247
248
249
250
  gchar       *filename;
  GdkPixbuf   *pixbuf;
  GdkGC       *gc;
  gint         width;
  PangoLayout *layout;
  PangoFontDescription *desc;
251

252
  if (about_info.logo_pixmap)
Elliot Lee's avatar
Elliot Lee committed
253
254
    return TRUE;

255
  filename = g_build_filename (gimp_data_directory (), "images",
256
                               "gimp_logo.png", NULL);
Elliot Lee's avatar
Elliot Lee committed
257

258
259
  pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
  g_free (filename);
Elliot Lee's avatar
Elliot Lee committed
260

261
262
  if (! pixbuf)
    return FALSE;
Elliot Lee's avatar
Elliot Lee committed
263

264
265
266
267
  about_info.pixmaparea.x = 0;
  about_info.pixmaparea.y = 0;
  about_info.pixmaparea.width = gdk_pixbuf_get_width (pixbuf);
  about_info.pixmaparea.height = gdk_pixbuf_get_height (pixbuf);
Elliot Lee's avatar
Elliot Lee committed
268

269
  gtk_widget_realize (window);
Elliot Lee's avatar
Elliot Lee committed
270

271
272
273
  about_info.logo_pixmap = gdk_pixmap_new (window->window,
                                about_info.pixmaparea.width,
                                about_info.pixmaparea.height,
274
                                gtk_widget_get_visual (window)->depth);
Elliot Lee's avatar
Elliot Lee committed
275

276
277
278
279
280
281
282
283
284
285
  layout = gtk_widget_create_pango_layout (window, NULL);
  desc = pango_font_description_from_string ("Bitstream Vera Sans,"
                                             "Trebuchet MS,"
                                             "Helvetica,"
                                             "Sans,"
                                             "Bold 9");
  pango_layout_set_font_description (layout, desc);
  pango_layout_set_justify (layout, PANGO_ALIGN_CENTER);
  pango_layout_set_text (layout, GIMP_VERSION, -1);
  
286
  gc = gdk_gc_new (about_info.logo_pixmap);
Elliot Lee's avatar
Elliot Lee committed
287

288
289
290
291
292
  gdk_draw_pixbuf (GDK_DRAWABLE (about_info.logo_pixmap),
                   gc, pixbuf,
                   0, 0, 0, 0,
                   about_info.pixmaparea.width,
                   about_info.pixmaparea.height,
293
                   GDK_RGB_DITHER_NORMAL, 0, 0);
Elliot Lee's avatar
Elliot Lee committed
294

295
296
297
298
299
  pango_layout_get_pixel_size (layout, &width, NULL);

  gdk_draw_layout (GDK_DRAWABLE (about_info.logo_pixmap),
                   gc, 224 - width, 204, layout);

300
301
  g_object_unref (gc);
  g_object_unref (pixbuf);
302
  g_object_unref (layout);
Elliot Lee's avatar
Elliot Lee committed
303
304
305
306
307

  return TRUE;
}

static void
308
309
about_dialog_destroy (GtkObject *object,
		      gpointer   data)
Elliot Lee's avatar
Elliot Lee committed
310
{
311
  about_info.about_dialog = NULL;
312
  about_dialog_unmap (NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
313
314
315
}

static void
316
about_dialog_unmap (GtkWidget *widget,
317
                    gpointer   data)
Elliot Lee's avatar
Elliot Lee committed
318
{
319
  if (about_info.timer)
Elliot Lee's avatar
Elliot Lee committed
320
    {
321
322
      g_source_remove (about_info.timer);
      about_info.timer = 0;
Elliot Lee's avatar
Elliot Lee committed
323
324
325
    }
}

326
static gint
Elliot Lee's avatar
Elliot Lee committed
327
about_dialog_logo_expose (GtkWidget      *widget,
328
329
			  GdkEventExpose *event,
			  gpointer        data)
Elliot Lee's avatar
Elliot Lee committed
330
{
331
332
333
  gint width, height;

  if (!about_info.timer)
334
335
336
337
338
339
340
341
342
    {
      /* No timeout, we were unmapped earlier */
      about_info.state = 0;
      about_info.index = 0;
      about_info.animstep = -1;
      about_info.visible = FALSE;
      reshuffle_array ();
      about_info.timer = g_timeout_add (30, about_dialog_timer, NULL);
    }
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

  /* only operate on the region covered by the pixmap */
  if (! gdk_rectangle_intersect (&(about_info.pixmaparea),
                                 &(event->area),
                                 &(event->area)))
    return FALSE;

  gdk_gc_set_clip_rectangle (widget->style->black_gc, &(event->area));

  gdk_draw_drawable (widget->window,
                     widget->style->white_gc,
                     about_info.logo_pixmap,
                     event->area.x, event->area.y,
                     event->area.x, event->area.y,
                     event->area.width, event->area.height);

  if (about_info.visible == TRUE)
Elliot Lee's avatar
Elliot Lee committed
360
    {
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
      gint layout_x, layout_y;

      pango_layout_get_pixel_size (about_info.layout, &width, &height);

      layout_x = about_info.textarea.x +
                        (about_info.textarea.width - width) / 2;
      layout_y = about_info.textarea.y +
                        (about_info.textarea.height - height) / 2;
      
      if (about_info.textrange[1] > 0)
        {
          GdkRegion *covered_region = NULL;
          GdkRegion *rect_region;

          covered_region = gdk_pango_layout_get_clip_region
                              (about_info.layout,
                               layout_x, layout_y,
                               about_info.textrange, 1);

          rect_region = gdk_region_rectangle (&(event->area));

          gdk_region_intersect (covered_region, rect_region);
          gdk_region_destroy (rect_region);

          gdk_gc_set_clip_region (about_info.logo_area->style->text_gc[GTK_STATE_NORMAL],
                                  covered_region);
          gdk_region_destroy (covered_region);
        }

      gdk_draw_layout (widget->window,
                       widget->style->text_gc[GTK_STATE_NORMAL],
                       layout_x, layout_y,
                       about_info.layout);

Elliot Lee's avatar
Elliot Lee committed
395
396
    }

397
398
  gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);

Elliot Lee's avatar
Elliot Lee committed
399
400
401
  return FALSE;
}

402
static gint
Elliot Lee's avatar
Elliot Lee committed
403
about_dialog_button (GtkWidget      *widget,
404
405
		     GdkEventButton *event,
		     gpointer        data)
Elliot Lee's avatar
Elliot Lee committed
406
{
407
  gtk_widget_hide (about_info.about_dialog);
Elliot Lee's avatar
Elliot Lee committed
408
409
410
411

  return FALSE;
}

Manish Singh's avatar
Manish Singh committed
412
413
414
415
416
static gint
about_dialog_key (GtkWidget      *widget,
		  GdkEventKey    *event,
		  gpointer        data)
{
417
  /* placeholder */
Manish Singh's avatar
Manish Singh committed
418
419
420
421
  switch (event->keyval)
    {
    case GDK_a:
    case GDK_A:
422
423
    case GDK_b:
    case GDK_B:
Manish Singh's avatar
Manish Singh committed
424
    default:
425
        break;
Manish Singh's avatar
Manish Singh committed
426
    }
427
428
429
430
431
432
433
434
435
436
437
438
  
  return FALSE;
}

static gchar *
insert_spacers (const gchar *string)
{
  gchar *normalized, *ptr;
  gunichar unichr;
  GString *str;

  str = g_string_new (NULL);
Manish Singh's avatar
Manish Singh committed
439

440
441
442
443
  normalized = g_utf8_normalize (string, -1, G_NORMALIZE_DEFAULT_COMPOSE);
  ptr = normalized;

  while ((unichr = g_utf8_get_char (ptr)))
Manish Singh's avatar
Manish Singh committed
444
    {
445
446
447
448
      g_string_append_unichar (str, unichr);
      g_string_append_unichar (str, 0x200b);  /* ZERO WIDTH SPACE */
      ptr = g_utf8_next_char (ptr);
    }
449

450
  g_free (normalized);
451

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
  return g_string_free (str, FALSE);
}

static void
mix_gradient (PangoColor *gradient, guint ncolors,
              PangoColor *target, gdouble pos)
{
  gint index;

  g_return_if_fail (gradient != NULL);
  g_return_if_fail (ncolors > 1);
  g_return_if_fail (target != NULL);
  g_return_if_fail (pos >= 0.0  &&  pos <= 1.0);

  if (pos == 1.0)
    {
      target->red   = gradient[ncolors-1].red;
      target->green = gradient[ncolors-1].green;
      target->blue  = gradient[ncolors-1].blue;
      return;
Manish Singh's avatar
Manish Singh committed
472
    }
473
474
475
476
477
478
479
  
  index = (int) floor (pos * (ncolors-1));
  pos = pos * (ncolors - 1) - index;

  target->red   = gradient[index].red   * (1.0 - pos) + gradient[index+1].red   * pos;
  target->green = gradient[index].green * (1.0 - pos) + gradient[index+1].green * pos;
  target->blue  = gradient[index].blue  * (1.0 - pos) + gradient[index+1].blue  * pos;
480

Manish Singh's avatar
Manish Singh committed
481
482
}

483
static void
484
485
486
mix_colors (PangoColor *start, PangoColor *end,
            PangoColor *target,
            gdouble pos)
487
{
488
489
490
491
492
493
494
495
496
  g_return_if_fail (start != NULL);
  g_return_if_fail (end != NULL);
  g_return_if_fail (target != NULL);
  g_return_if_fail (pos >= 0.0  &&  pos <= 1.0);

  target->red   = start->red   * (1.0 - pos) + end->red   * pos;
  target->green = start->green * (1.0 - pos) + end->green * pos;
  target->blue  = start->blue  * (1.0 - pos) + end->blue  * pos;
}
497

498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
static void
reshuffle_array (void)
{
  GRand *gr = g_rand_new ();
  gint i;

  for (i = 0; i < nscroll_texts; i++) 
    {
      shuffle_array[i] = i;
    }

  for (i = 0; i < nscroll_texts; i++) 
    {
      gint j;

      j = g_rand_int_range (gr, 0, nscroll_texts);
      if (i != j) 
        {
          gint t;

          t = shuffle_array[j];
          shuffle_array[j] = shuffle_array[i];
          shuffle_array[i] = t;
        }
    }

  g_rand_free (gr);
}

527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
static void
decorate_text (PangoLayout *layout, gint anim_type, gdouble time)
{
  gint letter_count = 0;
  gint text_length = 0;
  gint text_bytelen = 0;
  gint cluster_start, cluster_end;
  const gchar *text;
  const gchar *ptr;
  gunichar unichr;
  PangoAttrList *attrlist = NULL;
  PangoAttribute *attr;
  PangoRectangle irect = {0, 0, 0, 0};
  PangoRectangle lrect = {0, 0, 0, 0};
  PangoColor mix;

  mix_colors (&(about_info.background),
              &(about_info.foreground),
              &mix, time);

  text = pango_layout_get_text (layout);
  text_length = g_utf8_strlen (text, -1);
  text_bytelen = strlen (text);

  attrlist = pango_attr_list_new ();

  about_info.textrange[0] = 0;
  about_info.textrange[1] = text_bytelen;

  switch (anim_type)
  {
    case 0: /* Fade in */
      attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
      attr->start_index = 0;
      attr->end_index = text_bytelen;
      pango_attr_list_insert (attrlist, attr);
      break;

    case 1: /* Fade in, spread */
      attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
      attr->start_index = 0;
      attr->end_index = text_bytelen;
      pango_attr_list_change (attrlist, attr);

      ptr = text;

      cluster_start = 0;
      while ((unichr = g_utf8_get_char (ptr)))
        {
          ptr = g_utf8_next_char (ptr);
          cluster_end = (ptr - text);

          if (unichr == 0x200b)
            {
              lrect.width = (1.0 - time) * 15.0 * PANGO_SCALE + 0.5;
              attr = pango_attr_shape_new (&irect, &lrect);
              attr->start_index = cluster_start;
              attr->end_index = cluster_end;
              pango_attr_list_change (attrlist, attr);
            }
          cluster_start = cluster_end;
        }
      break;
590

591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
    case 2: /* Fade in, sinewave */
      attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
      attr->start_index = 0;
      attr->end_index = text_bytelen;
      pango_attr_list_change (attrlist, attr);

      ptr = text;

      cluster_start = 0;
      while ((unichr = g_utf8_get_char (ptr)))
        {
          if (unichr == 0x200b)
            {
              cluster_end = ptr - text;
              attr = pango_attr_rise_new ((1.0 -time) * 18000 *
                                          sin (4.0 * time +
                                               (float) letter_count * 0.7));
              attr->start_index = cluster_start;
              attr->end_index = cluster_end;
              pango_attr_list_change (attrlist, attr);

              letter_count++;
              cluster_start = cluster_end;
            }

          ptr = g_utf8_next_char (ptr);
        }
      break;
619

620
621
    case 3: /* letterwise Fade in */
      ptr = text;
622

623
624
625
626
627
628
      letter_count = 0;
      cluster_start = 0;
      while ((unichr = g_utf8_get_char (ptr)))
        {
          gint border;
          gdouble pos;
629

630
          border = (text_length + 15) * time - 15;
631

632
633
634
635
636
637
          if (letter_count < border)
            pos = 0;
          else if (letter_count > border + 15)
            pos = 1;
          else
            pos = ((gdouble) (letter_count - border)) / 15;
638

639
640
641
          mix_colors (&(about_info.foreground),
                      &(about_info.background),
                      &mix, pos);
642

643
          ptr = g_utf8_next_char (ptr);
644

645
          cluster_end = ptr - text;
646

647
648
649
650
          attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
          attr->start_index = cluster_start;
          attr->end_index = cluster_end;
          pango_attr_list_change (attrlist, attr);
651

652
653
          if (pos < 1.0)
            about_info.textrange[1] = cluster_end;
654

655
656
657
          letter_count++;
          cluster_start = cluster_end;
        }
658

659
      break;
660

661
662
    case 4: /* letterwise Fade in, triangular */
      ptr = text;
663

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
      letter_count = 0;
      cluster_start = 0;
      while ((unichr = g_utf8_get_char (ptr)))
        {
          gint border;
          gdouble pos;

          border = (text_length + 15) * time - 15;

          if (letter_count < border)
            pos = 1.0;
          else if (letter_count > border + 15)
            pos = 0.0;
          else
            pos = 1.0 - ((gdouble) (letter_count - border)) / 15;

          mix_gradient (gradient, G_N_ELEMENTS (gradient), &mix, pos);

          ptr = g_utf8_next_char (ptr);

          cluster_end = ptr - text;

          attr = pango_attr_foreground_new (mix.red, mix.green, mix.blue);
          attr->start_index = cluster_start;
          attr->end_index = cluster_end;
          pango_attr_list_change (attrlist, attr);

          if (pos > 0.0)
            about_info.textrange[1] = cluster_end;
693

694
695
696
697
698
699
700
701
702
703
704
705
          letter_count++;
          cluster_start = cluster_end;
        }
      break;

    default:
      g_printerr ("Unknown animation type %d\n", anim_type);
  }

  
  pango_layout_set_attributes (layout, attrlist);
  pango_attr_list_unref (attrlist);
706

707
708
}

709
static gboolean
Elliot Lee's avatar
Elliot Lee committed
710
711
about_dialog_timer (gpointer data)
{
712
713
714
715
  gboolean return_val;
  gint width, height;
  gdouble size;
  gchar *text;
Elliot Lee's avatar
Elliot Lee committed
716
717
  return_val = TRUE;

718
  if (about_info.animstep == 0)
Elliot Lee's avatar
Elliot Lee committed
719
    {
720
721
722
723
724
725
726
727
      size = 13.0;
      text = NULL;
      if (about_info.state == 0)
        {
          about_info.visible = TRUE;
          if (about_info.index >= G_N_ELEMENTS (founders))
            {
              about_info.index = 0;
728
              
729
730
731
732
              /* skip the translators section when the translator
               * did not provide a translation with his name
               */
              if (gettext (translators[1]) == translators[1])
733
734
735
                about_info.state = 3;
              else
                about_info.state = 1;
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
            }
          else
            {
              if (about_info.index == 0)
                {
                  gchar *tmp;
                  tmp = g_strdup_printf (gettext (founders[0]), GIMP_VERSION);
                  text = insert_spacers (tmp);
                  g_free (tmp);
                }
              else
                {
                  text = insert_spacers (gettext (founders[about_info.index]));
                }
              about_info.index++;
            }
        }
753

754
755
756
      if (about_info.state == 1)
        {
          about_info.visible = TRUE;
757
          if (about_info.index >= G_N_ELEMENTS (translators) - 1)
758
759
760
761
762
763
764
765
766
767
            {
              about_info.index = 0;
              about_info.state++;
            }
          else
            {
              text = insert_spacers (gettext (translators[about_info.index]));
              about_info.index++;
            }
        }
768

769
      if (about_info.state == 2)
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
        {
          if (!translator_names)
            translator_names = g_strsplit (gettext (translators[1]), "\n", 0);

          about_info.visible = TRUE;
          if (translator_names[about_info.index] == NULL)
            {
              about_info.index = 0;
              about_info.state++;
            }
          else
            {
              text = insert_spacers (translator_names[about_info.index]);
              about_info.index++;
            }
        }
      
      if (about_info.state == 3)
        {
          about_info.visible = TRUE;
          if (about_info.index >= G_N_ELEMENTS (contri_intro))
            {
              about_info.index = 0;
              about_info.state++;
            }
          else
            {
              text = insert_spacers (gettext (contri_intro[about_info.index]));
              about_info.index++;
            }

        }

      if (about_info.state == 4)
804
805
806
807
808
809
810
811
812
        {
          about_info.visible = TRUE;
        
          about_info.index += 1;
          if (about_info.index == nscroll_texts)
            about_info.index = 0;
        
          text = insert_spacers (scroll_text[shuffle_array[about_info.index]]);
        }
813

814
815
816
817
818
819
820
      if (text == NULL)
        {
          g_printerr ("TEXT == NULL\n");
          return TRUE;
        }
      pango_layout_set_text (about_info.layout, text, -1);
      pango_layout_set_attributes (about_info.layout, NULL);
Elliot Lee's avatar
Elliot Lee committed
821

822
823
      pango_font_description_set_size (font_desc, size * PANGO_SCALE);
      pango_layout_set_font_description (about_info.layout, font_desc);
Elliot Lee's avatar
Elliot Lee committed
824

825
      pango_layout_get_pixel_size (about_info.layout, &width, &height);
Elliot Lee's avatar
Elliot Lee committed
826

827
828
829
830
831
      while (width >= about_info.textarea.width && size >= 6.0)
        {
          size -= 0.5;
          pango_font_description_set_size (font_desc, size * PANGO_SCALE);
          pango_layout_set_font_description (about_info.layout, font_desc);
832

833
834
835
          pango_layout_get_pixel_size (about_info.layout, &width, &height);
        }
    }
Elliot Lee's avatar
Elliot Lee committed
836

837
  about_info.animstep++;
Elliot Lee's avatar
Elliot Lee committed
838

839
  if (about_info.animstep < 16)
840
    {
841
      decorate_text (about_info.layout, 4, ((float) about_info.animstep) / 15.0);
842
    }
843
  else if (about_info.animstep == 16)
844
845
846
    {
      about_info.timer = g_timeout_add (800, about_dialog_timer, NULL);
      return_val = FALSE;
Elliot Lee's avatar
Elliot Lee committed
847
    }
848
  else if (about_info.animstep == 17)
849
850
851
852
    {
      about_info.timer = g_timeout_add (30, about_dialog_timer, NULL);
      return_val = FALSE;
    }
853
  else if (about_info.animstep < 33)
854
    {
855
      decorate_text (about_info.layout, 1, 1.0 - ((float) (about_info.animstep-17)) / 15.0);
856
    }
857
  else if (about_info.animstep == 33)
858
859
860
861
862
863
864
    {
      about_info.timer = g_timeout_add (300, about_dialog_timer, NULL);
      return_val = FALSE;
      about_info.visible = FALSE;
    }
  else
    {
865
      about_info.animstep = 0;
866
867
868
869
870
871
872
873
874
875
      about_info.timer = g_timeout_add (30, about_dialog_timer, NULL);
      return_val = FALSE;
      about_info.visible = FALSE;
    }

  gtk_widget_queue_draw_area (about_info.logo_area,
                              about_info.textarea.x,
                              about_info.textarea.y,
                              about_info.textarea.width,
                              about_info.textarea.height);
Elliot Lee's avatar
Elliot Lee committed
876
877
878

  return return_val;
}