about-dialog.c 29 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
  GdkBitmap    *shape_bitmap;
  GdkGC        *trans_gc;
  GdkGC        *opaque_gc;

77
78
79
80
81
82
83
84
  GdkRectangle  textarea;
  gdouble       text_size;
  gdouble       min_text_size;
  PangoLayout  *layout;

  gint          timer;

  gint          index;
85
  gint          animstep;
86
87
88
89
90
91
92
93
  gboolean      visible;
  gint          textrange[2];
  gint          state;

} GimpAboutInfo;

PangoColor gradient[] =
{
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  { 50372, 50372, 50115 },
  { 65535, 65535, 65535 },
  { 10000, 10000, 10000 },
};

PangoColor foreground = { 10000, 10000, 10000 };
PangoColor background = { 50372, 50372, 50115 };

/* backup values */

PangoColor grad1ent[] =
{
  { 0xff * 257, 0xba * 257, 0x00 * 257 },
  { 37522, 51914, 57568 },
108
109
};

110
111
112
PangoColor foregr0und = { 37522, 51914, 57568 };
PangoColor backgr0und = { 0, 0, 0 };

113
static GimpAboutInfo about_info = { 0 };
114
static gboolean pp = FALSE;
115

116
117
static gboolean  about_dialog_load_logo   (GtkWidget      *window);
static void      about_dialog_destroy     (GtkObject      *object,
118
                                           gpointer        data);
119
static void      about_dialog_unmap       (GtkWidget      *widget,
120
                                           gpointer        data);
121
static gint      about_dialog_logo_expose (GtkWidget      *widget,
122
123
                                           GdkEventExpose *event,
                                           gpointer        data);
124
static gint      about_dialog_button      (GtkWidget      *widget,
125
126
                                           GdkEventButton *event,
                                           gpointer        data);
Manish Singh's avatar
Manish Singh committed
127
static gint      about_dialog_key         (GtkWidget      *widget,
128
129
                                           GdkEventKey    *event,
                                           gpointer        data);
130
static void      reshuffle_array          (void);
131
static gboolean  about_dialog_timer       (gpointer        data);
Elliot Lee's avatar
Elliot Lee committed
132
133


134
static gboolean     double_speed     = FALSE;
Michael Natterer's avatar
Michael Natterer committed
135

136
static PangoFontDescription *font_desc = NULL;
137
138
139
static gchar      **scroll_text      = authors;
static gint         nscroll_texts    = G_N_ELEMENTS (authors);
static gint         shuffle_array[G_N_ELEMENTS (authors)];
140

Michael Natterer's avatar
Michael Natterer committed
141

142
GtkWidget *
143
about_dialog_create (void)
Elliot Lee's avatar
Elliot Lee committed
144
{
145
146
147
  if (! about_info.about_dialog)
    {
      GtkWidget *widget;
148
      GdkGCValues shape_gcv;
149
150

      about_info.textarea.x = 0;
151
152
153
      about_info.textarea.y = 220;
      about_info.textarea.width = 299;
      about_info.textarea.height = 49;
154
155
156

      about_info.visible = FALSE;
      about_info.state = 0;
157
      about_info.animstep = -1;
158
159
160
161
162

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

      gtk_window_set_type_hint (GTK_WINDOW (widget),
163
                                GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
      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;
194
	  return NULL;
Elliot Lee's avatar
Elliot Lee committed
195
196
	}

197
198
      widget = gtk_drawing_area_new ();
      about_info.logo_area = widget;
Elliot Lee's avatar
Elliot Lee committed
199

200
201
202
203
204
205
206
      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
207

208
      g_signal_connect (widget, "expose_event",
209
210
211
			G_CALLBACK (about_dialog_logo_expose),
			NULL);

212
213
214
215
      gtk_widget_realize (widget);
      gdk_window_set_background (widget->window,
                                 &(widget->style)->black);

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
      /* setup shape bitmap */

      about_info.shape_bitmap = gdk_pixmap_new (widget->window,
                                                about_info.pixmaparea.width,
                                                about_info.pixmaparea.height,
                                                1);
      about_info.trans_gc = gdk_gc_new (about_info.shape_bitmap);

      about_info.opaque_gc = gdk_gc_new (about_info.shape_bitmap);
      gdk_gc_get_values (about_info.opaque_gc, &shape_gcv);
      gdk_gc_set_foreground (about_info.opaque_gc, &shape_gcv.background);

      gdk_draw_rectangle (about_info.shape_bitmap,
                          about_info.trans_gc,
                          TRUE,
                          0, 0,
                          about_info.pixmaparea.width,
                          about_info.pixmaparea.height);

      gdk_draw_line (about_info.shape_bitmap,
                     about_info.opaque_gc,
                     0, 0,
                     about_info.pixmaparea.width, 0);

      gtk_widget_shape_combine_mask (about_info.about_dialog,
                                     about_info.shape_bitmap,
                                     0, 0);
      about_info.layout = gtk_widget_create_pango_layout (about_info.logo_area,
                                                          NULL);
245
246
247
      g_object_weak_ref (G_OBJECT (about_info.logo_area), 
                         (GWeakNotify) g_object_unref, about_info.layout);

248
      font_desc = pango_font_description_from_string ("Sans, 11");
249
250
251
252

      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
253
254
    }

255
  if (! GTK_WIDGET_VISIBLE (about_info.about_dialog))
Elliot Lee's avatar
Elliot Lee committed
256
    {
257
      if (! double_speed)
Elliot Lee's avatar
Elliot Lee committed
258
	{
259
260
          about_info.state = 0;
          about_info.index = 0;
261

262
          reshuffle_array ();
263
          pango_layout_set_text (about_info.layout, "", -1);
Elliot Lee's avatar
Elliot Lee committed
264
265
	}
    }
266

267
  gtk_window_present (GTK_WINDOW (about_info.about_dialog));
268

269
  return about_info.about_dialog;
Elliot Lee's avatar
Elliot Lee committed
270
271
}

272
static gboolean
Elliot Lee's avatar
Elliot Lee committed
273
274
about_dialog_load_logo (GtkWidget *window)
{
275
276
277
278
279
280
  gchar       *filename;
  GdkPixbuf   *pixbuf;
  GdkGC       *gc;
  gint         width;
  PangoLayout *layout;
  PangoFontDescription *desc;
281

282
  if (about_info.logo_pixmap)
Elliot Lee's avatar
Elliot Lee committed
283
284
    return TRUE;

285
  filename = g_build_filename (gimp_data_directory (), "images",
286
                               "gimp_logo.png", NULL);
Elliot Lee's avatar
Elliot Lee committed
287

288
289
  pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
  g_free (filename);
Elliot Lee's avatar
Elliot Lee committed
290

291
292
  if (! pixbuf)
    return FALSE;
Elliot Lee's avatar
Elliot Lee committed
293

294
295
296
297
  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
298

299
  gtk_widget_realize (window);
Elliot Lee's avatar
Elliot Lee committed
300

301
302
303
  about_info.logo_pixmap = gdk_pixmap_new (window->window,
                                about_info.pixmaparea.width,
                                about_info.pixmaparea.height,
304
                                gtk_widget_get_visual (window)->depth);
Elliot Lee's avatar
Elliot Lee committed
305

306
  layout = gtk_widget_create_pango_layout (window, NULL);
307
  desc = pango_font_description_from_string ("Sans, Italic 9");
308
309
310
311
  pango_layout_set_font_description (layout, desc);
  pango_layout_set_justify (layout, PANGO_ALIGN_CENTER);
  pango_layout_set_text (layout, GIMP_VERSION, -1);
  
312
  gc = gdk_gc_new (about_info.logo_pixmap);
Elliot Lee's avatar
Elliot Lee committed
313

314
315
316
317
318
  gdk_draw_pixbuf (GDK_DRAWABLE (about_info.logo_pixmap),
                   gc, pixbuf,
                   0, 0, 0, 0,
                   about_info.pixmaparea.width,
                   about_info.pixmaparea.height,
319
                   GDK_RGB_DITHER_NORMAL, 0, 0);
Elliot Lee's avatar
Elliot Lee committed
320

321
322
323
  pango_layout_get_pixel_size (layout, &width, NULL);

  gdk_draw_layout (GDK_DRAWABLE (about_info.logo_pixmap),
324
325
326
                   gc, 222, 137, layout);

  about_info.pixmaparea.height /= 2;
327

328
329
  g_object_unref (gc);
  g_object_unref (pixbuf);
330
  g_object_unref (layout);
Elliot Lee's avatar
Elliot Lee committed
331
332
333
334
335

  return TRUE;
}

static void
336
337
about_dialog_destroy (GtkObject *object,
		      gpointer   data)
Elliot Lee's avatar
Elliot Lee committed
338
{
339
  about_info.about_dialog = NULL;
340
  about_dialog_unmap (NULL, NULL);
Elliot Lee's avatar
Elliot Lee committed
341
342
343
}

static void
344
about_dialog_unmap (GtkWidget *widget,
345
                    gpointer   data)
Elliot Lee's avatar
Elliot Lee committed
346
{
347
  if (about_info.timer)
Elliot Lee's avatar
Elliot Lee committed
348
    {
349
350
      g_source_remove (about_info.timer);
      about_info.timer = 0;
Elliot Lee's avatar
Elliot Lee committed
351
    }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

  if (about_info.about_dialog)
    {
      gdk_draw_rectangle (about_info.shape_bitmap,
                          about_info.trans_gc,
                          TRUE,
                          0, 0,
                          about_info.pixmaparea.width,
                          about_info.pixmaparea.height);

      gdk_draw_line (about_info.shape_bitmap,
                     about_info.opaque_gc,
                     0, 0,
                     about_info.pixmaparea.width, 0);

      gtk_widget_shape_combine_mask (about_info.about_dialog,
                                     about_info.shape_bitmap,
                                     0, 0);
    }
Elliot Lee's avatar
Elliot Lee committed
371
372
}

373
static gint
Elliot Lee's avatar
Elliot Lee committed
374
about_dialog_logo_expose (GtkWidget      *widget,
375
376
			  GdkEventExpose *event,
			  gpointer        data)
Elliot Lee's avatar
Elliot Lee committed
377
{
378
379
380
  gint width, height;

  if (!about_info.timer)
381
    {
382
383
      GdkModifierType mask;

384
385
      /* No timeout, we were unmapped earlier */
      about_info.state = 0;
386
      about_info.index = 1;
387
388
389
      about_info.animstep = -1;
      about_info.visible = FALSE;
      reshuffle_array ();
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
      gdk_draw_rectangle (about_info.shape_bitmap,
                          about_info.trans_gc,
                          TRUE,
                          0, 0,
                          about_info.pixmaparea.width,
                          about_info.pixmaparea.height);

      gdk_draw_line (about_info.shape_bitmap,
                     about_info.opaque_gc,
                     0, 0,
                     about_info.pixmaparea.width, 0);

      gtk_widget_shape_combine_mask (about_info.about_dialog,
                                     about_info.shape_bitmap,
                                     0, 0);
405
      about_info.timer = g_timeout_add (30, about_dialog_timer, NULL);
406
407
408
409
410
411
412
413
414
415
416

      gdk_window_get_pointer (NULL, NULL, NULL, &mask);

      /* weird magic to determine the way the logo should be shown */
      mask &= ~GDK_BUTTON3_MASK;
      pp = (mask &= (GDK_SHIFT_MASK | GDK_CONTROL_MASK) & 
                    (GDK_CONTROL_MASK | GDK_MOD1_MASK) &
                    (GDK_MOD1_MASK | ~GDK_SHIFT_MASK),
      height = mask ? (about_info.pixmaparea.height > 0) &&
                      (about_info.pixmaparea.width > 0): 0);

417
    }
418
419
420
421
422
423
424
425
426
427
428
429

  /* 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,
430
431
                     event->area.x, event->area.y +
                     (pp ? about_info.pixmaparea.height : 0),
432
433
434
                     event->area.x, event->area.y,
                     event->area.width, event->area.height);

Simon Budig's avatar
Simon Budig committed
435
  if (pp && about_info.state == 0 &&
436
437
438
439
440
441
442
443
444
445
446
      (about_info.index < about_info.pixmaparea.height / 12 ||
       about_info.index < g_random_int () %
                          (about_info.pixmaparea.height / 8 + 13)))
    {
      gdk_draw_rectangle (widget->window,
                          widget->style->black_gc,
                          TRUE,
                          0, 0, about_info.pixmaparea.width, 158);
                          
    }

447
  if (about_info.visible == TRUE)
Elliot Lee's avatar
Elliot Lee committed
448
    {
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
      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
464
465
466
                                    (about_info.layout,
                                     layout_x, layout_y,
                                     about_info.textrange, 1);
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

          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
483
484
    }

485
486
  gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);

Elliot Lee's avatar
Elliot Lee committed
487
488
489
  return FALSE;
}

490
static gint
Elliot Lee's avatar
Elliot Lee committed
491
about_dialog_button (GtkWidget      *widget,
492
493
		     GdkEventButton *event,
		     gpointer        data)
Elliot Lee's avatar
Elliot Lee committed
494
{
495
  gtk_widget_hide (about_info.about_dialog);
Elliot Lee's avatar
Elliot Lee committed
496
497
498
499

  return FALSE;
}

Manish Singh's avatar
Manish Singh committed
500
501
502
503
504
static gint
about_dialog_key (GtkWidget      *widget,
		  GdkEventKey    *event,
		  gpointer        data)
{
505
  /* placeholder */
Manish Singh's avatar
Manish Singh committed
506
507
508
509
  switch (event->keyval)
    {
    case GDK_a:
    case GDK_A:
510
511
    case GDK_b:
    case GDK_B:
Manish Singh's avatar
Manish Singh committed
512
    default:
513
        break;
Manish Singh's avatar
Manish Singh committed
514
    }
515
516
517
518
519
520
521
522
523
524
525
526
  
  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
527

528
529
530
531
  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
532
    {
533
534
535
536
      g_string_append_unichar (str, unichr);
      g_string_append_unichar (str, 0x200b);  /* ZERO WIDTH SPACE */
      ptr = g_utf8_next_char (ptr);
    }
537

538
  g_free (normalized);
539

540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
  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
560
    }
561
562
563
564
565
566
567
  
  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;
568

Manish Singh's avatar
Manish Singh committed
569
570
}

571
static void
572
573
574
mix_colors (PangoColor *start, PangoColor *end,
            PangoColor *target,
            gdouble pos)
575
{
576
577
578
579
580
581
582
583
584
  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;
}
585

586
587
588
589
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
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);
}

615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
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;

631
632
  mix_colors (&(pp ? backgr0und : background),
              &(pp ? foregr0und : foreground),
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
              &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;
678

679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
    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;
707

708
709
    case 3: /* letterwise Fade in */
      ptr = text;
710

711
712
713
714
715
716
      letter_count = 0;
      cluster_start = 0;
      while ((unichr = g_utf8_get_char (ptr)))
        {
          gint border;
          gdouble pos;
717

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

720
721
722
723
724
725
          if (letter_count < border)
            pos = 0;
          else if (letter_count > border + 15)
            pos = 1;
          else
            pos = ((gdouble) (letter_count - border)) / 15;
726

727
728
          mix_colors (&(pp ? foregr0und : foreground),
                      &(pp ? backgr0und : background),
729
                      &mix, pos);
730

731
          ptr = g_utf8_next_char (ptr);
732

733
          cluster_end = ptr - text;
734

735
736
737
738
          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);
739

740
741
          if (pos < 1.0)
            about_info.textrange[1] = cluster_end;
742

743
744
745
          letter_count++;
          cluster_start = cluster_end;
        }
746

747
      break;
748

749
750
    case 4: /* letterwise Fade in, triangular */
      ptr = text;
751

752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
      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;

768
769
770
          mix_gradient (pp ? grad1ent : gradient,
                        pp ? G_N_ELEMENTS (grad1ent) : G_N_ELEMENTS (gradient),
                        &mix, pos);
771
772
773
774
775
776
777
778
779
780
781
782

          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;
783

784
785
786
787
788
789
790
791
792
793
794
795
          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);
796

797
798
}

799
static gboolean
Elliot Lee's avatar
Elliot Lee committed
800
801
about_dialog_timer (gpointer data)
{
802
803
804
805
  gboolean return_val;
  gint width, height;
  gdouble size;
  gchar *text;
Elliot Lee's avatar
Elliot Lee committed
806
807
  return_val = TRUE;

808
  if (about_info.animstep == 0)
Elliot Lee's avatar
Elliot Lee committed
809
    {
810
      size = 11.0;
811
      text = NULL;
812
813
      about_info.visible = TRUE;

814
815
      if (about_info.state == 0)
        {
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
          if (about_info.index > (about_info.pixmaparea.height /
                                  (pp ? 8 : 16)) + 16)
            {
              about_info.index = 0;
              about_info.state ++;
            }
          else
            {
              height = about_info.index * 16;

              if (height < about_info.pixmaparea.height)
                gdk_draw_line (about_info.shape_bitmap,
                               about_info.opaque_gc,
                               0, height,
                               about_info.pixmaparea.width, height);

              height -= 15;
              while (height > 0)
                {
                  if (height < about_info.pixmaparea.height)
                    gdk_draw_line (about_info.shape_bitmap,
                                   about_info.opaque_gc,
                                   0, height,
                                   about_info.pixmaparea.width, height);
                  height -= 15;
                }

              gtk_widget_shape_combine_mask (about_info.about_dialog,
                                             about_info.shape_bitmap,
                                             0, 0);
              about_info.index++;
              about_info.visible = FALSE;
              gtk_widget_queue_draw_area (about_info.logo_area,
                                          0, 0,
                                          about_info.pixmaparea.width,
                                          about_info.pixmaparea.height);
              return TRUE;
            }
        }

      if (about_info.state == 1)
        {
858
859
860
          if (about_info.index >= G_N_ELEMENTS (founders))
            {
              about_info.index = 0;
861
              
862
863
864
865
              /* skip the translators section when the translator
               * did not provide a translation with his name
               */
              if (gettext (translators[1]) == translators[1])
866
                about_info.state = 4;
867
              else
868
                about_info.state = 2;
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
            }
          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++;
            }
        }
886

887
      if (about_info.state == 2)
888
        {
889
          if (about_info.index >= G_N_ELEMENTS (translators) - 1)
890
891
892
893
894
895
896
897
898
899
            {
              about_info.index = 0;
              about_info.state++;
            }
          else
            {
              text = insert_spacers (gettext (translators[about_info.index]));
              about_info.index++;
            }
        }
900

901
      if (about_info.state == 3)
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
        {
          if (!translator_names)
            translator_names = g_strsplit (gettext (translators[1]), "\n", 0);

          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++;
            }
        }
      
918
      if (about_info.state == 4)
919
920
921
922
923
924
925
926
927
928
929
930
931
932
        {
          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++;
            }

        }

933
      if (about_info.state == 5)
934
935
936
937
938
939
940
941
        {
        
          about_info.index += 1;
          if (about_info.index == nscroll_texts)
            about_info.index = 0;
        
          text = insert_spacers (scroll_text[shuffle_array[about_info.index]]);
        }
942

943
944
945
946
947
948
949
      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
950

951
952
      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
953

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

956
957
958
959
960
      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);
961

962
963
964
          pango_layout_get_pixel_size (about_info.layout, &width, &height);
        }
    }
Elliot Lee's avatar
Elliot Lee committed
965

966
  about_info.animstep++;
Elliot Lee's avatar
Elliot Lee committed
967

968
  if (about_info.animstep < 16)
969
    {
970
971
      decorate_text (about_info.layout, 4,
                     ((float) about_info.animstep) / 15.0);
972
    }
973
  else if (about_info.animstep == 16)
974
975
976
    {
      about_info.timer = g_timeout_add (800, about_dialog_timer, NULL);
      return_val = FALSE;
Elliot Lee's avatar
Elliot Lee committed
977
    }
978
  else if (about_info.animstep == 17)
979
980
981
982
    {
      about_info.timer = g_timeout_add (30, about_dialog_timer, NULL);
      return_val = FALSE;
    }
983
  else if (about_info.animstep < 33)
984
    {
985
986
      decorate_text (about_info.layout, 1,
                     1.0 - ((float) (about_info.animstep-17)) / 15.0);
987
    }
988
  else if (about_info.animstep == 33)
989
990
991
992
993
994
995
    {
      about_info.timer = g_timeout_add (300, about_dialog_timer, NULL);
      return_val = FALSE;
      about_info.visible = FALSE;
    }
  else
    {
996
      about_info.animstep = 0;
997
998
999
1000
1001
1002
1003
1004
1005
1006
      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
1007
1008
1009

  return return_val;
}