2004-01-07 Simon Budig <simon@gimp.org> * app/gui/about-dialog.c: Changed the string that is intended to be translated to the translators names, to be the same as in Gnome. Sorry for the string change.
878 lines
24 KiB
C
878 lines
24 KiB
C
/* 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.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
#include "libgimpmath/gimpmath.h"
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
#include "gui-types.h"
|
|
|
|
#include "core/gimptoolinfo.h"
|
|
|
|
#include "widgets/gimphelp-ids.h"
|
|
#include "widgets/gimpdnd.h"
|
|
|
|
#include "about-dialog.h"
|
|
#include "authors.h"
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
static gchar *founders[] =
|
|
{
|
|
N_("Version %s brought to you by"),
|
|
"Spencer Kimball & Peter Mattis"
|
|
};
|
|
|
|
static gchar *translators[] =
|
|
{
|
|
N_("Translation by"),
|
|
/* Translators: insert your names here, separated by newline */
|
|
/* we'd prefer just the names, please no email adresses. */
|
|
N_("translator-credits"),
|
|
};
|
|
|
|
static gchar *contri_intro[] =
|
|
{
|
|
N_("Contributions by")
|
|
};
|
|
|
|
static gchar **translator_names = NULL;
|
|
|
|
typedef struct
|
|
{
|
|
GtkWidget *about_dialog;
|
|
GtkWidget *logo_area;
|
|
GdkPixmap *logo_pixmap;
|
|
GdkRectangle pixmaparea;
|
|
|
|
GdkRectangle textarea;
|
|
gdouble text_size;
|
|
gdouble min_text_size;
|
|
PangoLayout *layout;
|
|
PangoColor foreground;
|
|
PangoColor background;
|
|
|
|
gint timer;
|
|
|
|
gint index;
|
|
gint animstep;
|
|
gboolean visible;
|
|
gint textrange[2];
|
|
gint state;
|
|
|
|
} GimpAboutInfo;
|
|
|
|
PangoColor gradient[] =
|
|
{
|
|
{ 31868, 33153, 32382 },
|
|
{ 10000, 10000, 10000 },
|
|
{ 65535, 65535, 65535 },
|
|
};
|
|
|
|
static GimpAboutInfo about_info = { 0 };
|
|
|
|
static gboolean about_dialog_load_logo (GtkWidget *window);
|
|
static void about_dialog_destroy (GtkObject *object,
|
|
gpointer data);
|
|
static void about_dialog_unmap (GtkWidget *widget,
|
|
gpointer data);
|
|
static gint about_dialog_logo_expose (GtkWidget *widget,
|
|
GdkEventExpose *event,
|
|
gpointer data);
|
|
static gint about_dialog_button (GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
gpointer data);
|
|
static gint about_dialog_key (GtkWidget *widget,
|
|
GdkEventKey *event,
|
|
gpointer data);
|
|
static void reshuffle_array (void);
|
|
static gboolean about_dialog_timer (gpointer data);
|
|
|
|
|
|
static gboolean double_speed = FALSE;
|
|
|
|
static PangoFontDescription *font_desc = NULL;
|
|
static gchar **scroll_text = authors;
|
|
static gint nscroll_texts = G_N_ELEMENTS (authors);
|
|
static gint shuffle_array[G_N_ELEMENTS (authors)];
|
|
|
|
|
|
GtkWidget *
|
|
about_dialog_create (void)
|
|
{
|
|
GdkModifierType mask;
|
|
|
|
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;
|
|
about_info.animstep = -1;
|
|
|
|
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;
|
|
return NULL;
|
|
}
|
|
|
|
widget = gtk_drawing_area_new ();
|
|
about_info.logo_area = widget;
|
|
|
|
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);
|
|
|
|
g_signal_connect (widget, "expose_event",
|
|
G_CALLBACK (about_dialog_logo_expose),
|
|
NULL);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
/* for future enhancements */
|
|
gdk_window_get_pointer (NULL, NULL, NULL, &mask);
|
|
|
|
if (! GTK_WIDGET_VISIBLE (about_info.about_dialog))
|
|
{
|
|
if (! double_speed)
|
|
{
|
|
about_info.state = 0;
|
|
about_info.index = 0;
|
|
|
|
reshuffle_array ();
|
|
pango_layout_set_text (about_info.layout, "", -1);
|
|
}
|
|
}
|
|
|
|
gtk_window_present (GTK_WINDOW (about_info.about_dialog));
|
|
|
|
return about_info.about_dialog;
|
|
}
|
|
|
|
static gboolean
|
|
about_dialog_load_logo (GtkWidget *window)
|
|
{
|
|
gchar *filename;
|
|
GdkPixbuf *pixbuf;
|
|
GdkGC *gc;
|
|
gint width;
|
|
PangoLayout *layout;
|
|
PangoFontDescription *desc;
|
|
|
|
if (about_info.logo_pixmap)
|
|
return TRUE;
|
|
|
|
filename = g_build_filename (gimp_data_directory (), "images",
|
|
"gimp_logo.png", NULL);
|
|
|
|
pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
|
|
g_free (filename);
|
|
|
|
if (! pixbuf)
|
|
return FALSE;
|
|
|
|
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);
|
|
|
|
gtk_widget_realize (window);
|
|
|
|
about_info.logo_pixmap = gdk_pixmap_new (window->window,
|
|
about_info.pixmaparea.width,
|
|
about_info.pixmaparea.height,
|
|
gtk_widget_get_visual (window)->depth);
|
|
|
|
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);
|
|
|
|
gc = gdk_gc_new (about_info.logo_pixmap);
|
|
|
|
gdk_draw_pixbuf (GDK_DRAWABLE (about_info.logo_pixmap),
|
|
gc, pixbuf,
|
|
0, 0, 0, 0,
|
|
about_info.pixmaparea.width,
|
|
about_info.pixmaparea.height,
|
|
GDK_RGB_DITHER_NORMAL, 0, 0);
|
|
|
|
pango_layout_get_pixel_size (layout, &width, NULL);
|
|
|
|
gdk_draw_layout (GDK_DRAWABLE (about_info.logo_pixmap),
|
|
gc, 224 - width, 204, layout);
|
|
|
|
g_object_unref (gc);
|
|
g_object_unref (pixbuf);
|
|
g_object_unref (layout);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
about_dialog_destroy (GtkObject *object,
|
|
gpointer data)
|
|
{
|
|
about_info.about_dialog = NULL;
|
|
about_dialog_unmap (NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
about_dialog_unmap (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
if (about_info.timer)
|
|
{
|
|
g_source_remove (about_info.timer);
|
|
about_info.timer = 0;
|
|
}
|
|
}
|
|
|
|
static gint
|
|
about_dialog_logo_expose (GtkWidget *widget,
|
|
GdkEventExpose *event,
|
|
gpointer data)
|
|
{
|
|
gint width, height;
|
|
|
|
if (!about_info.timer)
|
|
{
|
|
/* 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);
|
|
}
|
|
|
|
/* 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)
|
|
{
|
|
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);
|
|
|
|
}
|
|
|
|
gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gint
|
|
about_dialog_button (GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
gpointer data)
|
|
{
|
|
gtk_widget_hide (about_info.about_dialog);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gint
|
|
about_dialog_key (GtkWidget *widget,
|
|
GdkEventKey *event,
|
|
gpointer data)
|
|
{
|
|
/* placeholder */
|
|
switch (event->keyval)
|
|
{
|
|
case GDK_a:
|
|
case GDK_A:
|
|
case GDK_b:
|
|
case GDK_B:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gchar *
|
|
insert_spacers (const gchar *string)
|
|
{
|
|
gchar *normalized, *ptr;
|
|
gunichar unichr;
|
|
GString *str;
|
|
|
|
str = g_string_new (NULL);
|
|
|
|
normalized = g_utf8_normalize (string, -1, G_NORMALIZE_DEFAULT_COMPOSE);
|
|
ptr = normalized;
|
|
|
|
while ((unichr = g_utf8_get_char (ptr)))
|
|
{
|
|
g_string_append_unichar (str, unichr);
|
|
g_string_append_unichar (str, 0x200b); /* ZERO WIDTH SPACE */
|
|
ptr = g_utf8_next_char (ptr);
|
|
}
|
|
|
|
g_free (normalized);
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
static void
|
|
mix_colors (PangoColor *start, PangoColor *end,
|
|
PangoColor *target,
|
|
gdouble pos)
|
|
{
|
|
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;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
case 3: /* letterwise Fade in */
|
|
ptr = text;
|
|
|
|
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 = 0;
|
|
else if (letter_count > border + 15)
|
|
pos = 1;
|
|
else
|
|
pos = ((gdouble) (letter_count - border)) / 15;
|
|
|
|
mix_colors (&(about_info.foreground),
|
|
&(about_info.background),
|
|
&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 < 1.0)
|
|
about_info.textrange[1] = cluster_end;
|
|
|
|
letter_count++;
|
|
cluster_start = cluster_end;
|
|
}
|
|
|
|
break;
|
|
|
|
case 4: /* letterwise Fade in, triangular */
|
|
ptr = text;
|
|
|
|
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;
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
static gboolean
|
|
about_dialog_timer (gpointer data)
|
|
{
|
|
gboolean return_val;
|
|
gint width, height;
|
|
gdouble size;
|
|
gchar *text;
|
|
return_val = TRUE;
|
|
|
|
if (about_info.animstep == 0)
|
|
{
|
|
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;
|
|
|
|
/* skip the translators section when the translator
|
|
* did not provide a translation with his name
|
|
*/
|
|
if (gettext (translators[1]) == translators[1])
|
|
about_info.state = 3;
|
|
else
|
|
about_info.state = 1;
|
|
}
|
|
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++;
|
|
}
|
|
}
|
|
|
|
if (about_info.state == 1)
|
|
{
|
|
about_info.visible = TRUE;
|
|
if (about_info.index >= G_N_ELEMENTS (translators) - 1)
|
|
{
|
|
about_info.index = 0;
|
|
about_info.state++;
|
|
}
|
|
else
|
|
{
|
|
text = insert_spacers (gettext (translators[about_info.index]));
|
|
about_info.index++;
|
|
}
|
|
}
|
|
|
|
if (about_info.state == 2)
|
|
{
|
|
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)
|
|
{
|
|
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]]);
|
|
}
|
|
|
|
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);
|
|
|
|
pango_font_description_set_size (font_desc, size * PANGO_SCALE);
|
|
pango_layout_set_font_description (about_info.layout, font_desc);
|
|
|
|
pango_layout_get_pixel_size (about_info.layout, &width, &height);
|
|
|
|
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);
|
|
|
|
pango_layout_get_pixel_size (about_info.layout, &width, &height);
|
|
}
|
|
}
|
|
|
|
about_info.animstep++;
|
|
|
|
if (about_info.animstep < 16)
|
|
{
|
|
decorate_text (about_info.layout, 4, ((float) about_info.animstep) / 15.0);
|
|
}
|
|
else if (about_info.animstep == 16)
|
|
{
|
|
about_info.timer = g_timeout_add (800, about_dialog_timer, NULL);
|
|
return_val = FALSE;
|
|
}
|
|
else if (about_info.animstep == 17)
|
|
{
|
|
about_info.timer = g_timeout_add (30, about_dialog_timer, NULL);
|
|
return_val = FALSE;
|
|
}
|
|
else if (about_info.animstep < 33)
|
|
{
|
|
decorate_text (about_info.layout, 1, 1.0 - ((float) (about_info.animstep-17)) / 15.0);
|
|
}
|
|
else if (about_info.animstep == 33)
|
|
{
|
|
about_info.timer = g_timeout_add (300, about_dialog_timer, NULL);
|
|
return_val = FALSE;
|
|
about_info.visible = FALSE;
|
|
}
|
|
else
|
|
{
|
|
about_info.animstep = 0;
|
|
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);
|
|
|
|
return return_val;
|
|
}
|