41
45
GtkWidget *progress;
44
47
PangoLayout *upper;
45
48
gint upper_x, upper_y;
46
49
PangoLayout *lower;
47
50
gint lower_x, lower_y;
50
59
static GimpSplash *splash = NULL;
53
static void splash_map (void);
54
static gboolean splash_area_expose (GtkWidget *widget,
55
GdkEventExpose *event,
57
static GdkPixbuf * splash_pick_from_dir (const gchar *dirname);
58
static void splash_rectangle_union (GdkRectangle *dest,
59
PangoRectangle *pango_rect,
62
static gboolean splash_average_bottom (GtkWidget *widget,
62
static void splash_map (void);
63
static void splash_position_layouts (GimpSplash *splash,
67
static gboolean splash_area_expose (GtkWidget *widget,
68
GdkEventExpose *event,
70
static void splash_rectangle_union (GdkRectangle *dest,
71
PangoRectangle *pango_rect,
74
static gboolean splash_average_text_area (GimpSplash *splash,
78
static GdkPixbufAnimation * splash_image_load (gboolean be_verbose);
79
static GdkPixbufAnimation * splash_image_pick_from_dir (const gchar *dirname,
83
static void splash_timer_elapsed (const gchar *text1,
67
89
/* public functions */
92
splash_create (gboolean be_verbose)
96
GdkPixbufAnimation *pixbuf;
81
102
g_return_if_fail (splash == NULL);
83
filename = gimp_personal_rc_file ("gimp-splash.png");
84
pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
89
filename = gimp_personal_rc_file ("splashes");
90
pixbuf = splash_pick_from_dir (filename);
96
filename = g_build_filename (gimp_data_directory (),
97
"images", "gimp-splash.png", NULL);
98
pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
104
filename = g_build_filename (gimp_data_directory (), "splashes", NULL);
105
pixbuf = splash_pick_from_dir (filename);
104
pixbuf = splash_image_load (be_verbose);
147
144
gtk_container_add (GTK_CONTAINER (frame), vbox);
148
145
gtk_widget_show (vbox);
150
/* prepare the drawing area */
151
splash->area = gtk_drawing_area_new ();
147
/* If the splash image is static, we use a drawing area and set the
148
* image as back pixmap, otherwise a GtkImage is being used.
150
if (gdk_pixbuf_animation_is_static_image (pixbuf))
152
splash->area = gtk_drawing_area_new ();
156
splash->area = gtk_image_new_from_animation (pixbuf);
152
159
gtk_box_pack_start_defaults (GTK_BOX (vbox), splash->area);
153
160
gtk_widget_show (splash->area);
155
162
gtk_widget_set_size_request (splash->area, splash->width, splash->height);
157
gtk_widget_realize (splash->area);
159
splash_average_bottom (splash->area, pixbuf, &values.foreground);
160
splash->gc = gdk_gc_new_with_values (splash->area->window, &values,
163
splash->pixmap = gdk_pixmap_new (splash->area->window,
164
splash->width, splash->height, -1);
165
gdk_draw_pixbuf (splash->pixmap, splash->gc,
166
pixbuf, 0, 0, 0, 0, splash->width, splash->height,
167
GDK_RGB_DITHER_NORMAL, 0, 0);
168
g_object_unref (pixbuf);
170
g_signal_connect (splash->area, "expose_event",
171
G_CALLBACK (splash_area_expose),
174
164
/* create the pango layouts */
175
165
splash->upper = gtk_widget_create_pango_layout (splash->area, "");
176
166
splash->lower = gtk_widget_create_pango_layout (splash->area, "");
184
174
pango_layout_set_attributes (splash->upper, attrs);
185
175
pango_attr_list_unref (attrs);
177
/* this sets the initial layout positions */
178
splash_position_layouts (splash, "", "", NULL);
180
splash_average_text_area (splash,
181
gdk_pixbuf_animation_get_static_image (pixbuf),
184
gtk_widget_realize (splash->area);
185
splash->gc = gdk_gc_new_with_values (splash->area->window, &values,
188
if (gdk_pixbuf_animation_is_static_image (pixbuf))
190
GdkPixmap *pixmap = gdk_pixmap_new (splash->area->window,
191
splash->width, splash->height, -1);
193
gdk_draw_pixbuf (pixmap, splash->gc,
194
gdk_pixbuf_animation_get_static_image (pixbuf),
195
0, 0, 0, 0, splash->width, splash->height,
196
GDK_RGB_DITHER_NORMAL, 0, 0);
197
gdk_window_set_back_pixmap (splash->area->window, pixmap, FALSE);
198
g_object_unref (pixmap);
201
g_object_unref (pixbuf);
203
g_signal_connect_after (splash->area, "expose-event",
204
G_CALLBACK (splash_area_expose),
187
207
/* add a progress bar */
188
208
splash->progress = gtk_progress_bar_new ();
189
209
gtk_box_pack_end (GTK_BOX (vbox), splash->progress, FALSE, FALSE, 0);
190
210
gtk_widget_show (splash->progress);
192
gtk_widget_show (splash->window);
212
gtk_widget_show_now (splash->window);
194
while (gtk_events_pending ())
195
gtk_main_iteration ();
215
splash->timer = g_timer_new ();
217
243
const gchar *text2,
218
244
gdouble percentage)
220
GdkRectangle expose = { 0, 0, 0, 0 };
222
PangoRectangle logical;
246
GdkRectangle expose = { 0, 0, 0, 0 };
248
g_return_if_fail (percentage >= 0.0 && percentage <= 1.0);
229
width = splash->area->allocation.width;
230
height = splash->area->allocation.height;
234
pango_layout_get_pixel_extents (splash->upper, &ink, NULL);
235
splash_rectangle_union (&expose, &ink, splash->upper_x, splash->upper_y);
237
pango_layout_set_text (splash->upper, text1, -1);
238
pango_layout_get_pixel_extents (splash->upper, &ink, &logical);
240
splash->upper_x = (width - logical.width) / 2;
241
splash->upper_y = height - 2 * (logical.height + 6);
243
splash_rectangle_union (&expose, &ink, splash->upper_x, splash->upper_y);
248
pango_layout_get_pixel_extents (splash->lower, &ink, NULL);
249
splash_rectangle_union (&expose, &ink, splash->lower_x, splash->lower_y);
251
pango_layout_set_text (splash->lower, text2, -1);
252
pango_layout_get_pixel_extents (splash->lower, &ink, &logical);
254
splash->lower_x = (width - logical.width) / 2;
255
splash->lower_y = height - (logical.height + 6);
257
splash_rectangle_union (&expose, &ink, splash->lower_x, splash->lower_y);
254
splash_timer_elapsed (text1, text2, percentage);
257
splash_position_layouts (splash, text1, text2, &expose);
260
259
if (expose.width > 0 && expose.height > 0)
261
260
gtk_widget_queue_draw_area (splash->area,
304
296
gtk_window_set_auto_startup_notification (TRUE);
308
splash_pick_from_dir (const gchar *dirname)
299
/* area returns the union of the previous and new ink rectangles */
301
splash_position_layouts (GimpSplash *splash,
310
GdkPixbuf *pixbuf = NULL;
311
GDir *dir = g_dir_open (dirname, 0, NULL);
316
GList *splashes = NULL;
318
while ((entry = g_dir_read_name (dir)))
319
splashes = g_list_prepend (splashes, g_strdup (entry));
325
gint32 i = g_random_int_range (0, g_list_length (splashes));
326
gchar *filename = g_build_filename (dirname,
327
g_list_nth_data (splashes, i),
330
pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
333
g_list_foreach (splashes, (GFunc) g_free, NULL);
334
g_list_free (splashes);
307
PangoRectangle logical;
311
pango_layout_get_pixel_extents (splash->upper, &ink, NULL);
314
splash_rectangle_union (area, &ink, splash->upper_x, splash->upper_y);
316
pango_layout_set_text (splash->upper, text1, -1);
317
pango_layout_get_pixel_extents (splash->upper, &ink, &logical);
319
splash->upper_x = (splash->width - logical.width) / 2;
320
splash->upper_y = splash->height - 2 * (logical.height + 6);
323
splash_rectangle_union (area, &ink, splash->upper_x, splash->upper_y);
328
pango_layout_get_pixel_extents (splash->lower, &ink, NULL);
331
splash_rectangle_union (area, &ink, splash->lower_x, splash->lower_y);
333
pango_layout_set_text (splash->lower, text2, -1);
334
pango_layout_get_pixel_extents (splash->lower, &ink, &logical);
336
splash->lower_x = (splash->width - logical.width) / 2;
337
splash->lower_y = splash->height - (logical.height + 6);
340
splash_rectangle_union (area, &ink, splash->lower_x, splash->lower_y);
360
363
/* This function chooses a gray value for the text color, based on
361
* the average intensity of the lower 60 rows of the splash image.
364
* the average luminance of the text area of the splash image.
364
splash_average_bottom (GtkWidget *widget,
367
splash_average_text_area (GimpSplash *splash,
368
371
const guchar *pixels;
375
guint sum[3] = { 0, 0, 0 };
375
guint sum[3] = { 0, 0, 0 };
376
GdkRectangle image = { 0, 0, 0, 0 };
377
GdkRectangle area = { 0, 0, 0, 0 };
377
379
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), FALSE);
378
380
g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8, FALSE);
380
width = gdk_pixbuf_get_width (pixbuf);
381
height = gdk_pixbuf_get_height (pixbuf);
382
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
383
channels = gdk_pixbuf_get_n_channels (pixbuf);
384
pixels = gdk_pixbuf_get_pixels (pixbuf);
386
y = MAX (0, height - 60);
387
count = width * (height - y);
389
pixels += y * rowstride;
391
for (; y < height; y++)
382
image.width = gdk_pixbuf_get_width (pixbuf);
383
image.height = gdk_pixbuf_get_height (pixbuf);
384
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
385
channels = gdk_pixbuf_get_n_channels (pixbuf);
386
pixels = gdk_pixbuf_get_pixels (pixbuf);
388
splash_position_layouts (splash, "Short text", "Somewhat longer text", &area);
389
splash_position_layouts (splash, "", "", NULL);
391
if (gdk_rectangle_intersect (&image, &area, &area))
393
const guchar *src = pixels;
395
for (x = 0; x < width; x++)
393
const gint count = area.width * area.height;
396
pixels += area.x * channels;
397
pixels += area.y * rowstride;
399
for (y = 0; y < area.height; y++)
401
const guchar *src = pixels;
403
for (x = 0; x < area.width; x++)
415
luminance = GIMP_RGB_LUMINANCE (sum[0] / count,
419
luminance = CLAMP0255 (luminance > 127 ?
420
luminance - 223 : luminance + 223);
407
intensity = GIMP_RGB_INTENSITY (sum[0] / count,
411
intensity = CLAMP0255 (intensity > 127 ? intensity - 223 : intensity + 223);
413
color->red = color->green = color->blue = (intensity << 8 | intensity);
415
return gdk_colormap_alloc_color (gtk_widget_get_colormap (widget),
424
color->red = color->green = color->blue = (luminance << 8 | luminance);
426
return gdk_colormap_alloc_color (gtk_widget_get_colormap (splash->area),
416
427
color, FALSE, TRUE);
430
static GdkPixbufAnimation *
431
splash_image_load (gboolean be_verbose)
433
GdkPixbufAnimation *pixbuf;
436
filename = gimp_personal_rc_file ("gimp-splash.png");
439
g_printerr ("Trying splash '%s' ... ", filename);
441
pixbuf = gdk_pixbuf_animation_new_from_file (filename, NULL);
445
g_printerr (pixbuf ? "OK\n" : "failed\n");
450
filename = gimp_personal_rc_file ("splashes");
451
pixbuf = splash_image_pick_from_dir (filename, be_verbose);
457
filename = g_build_filename (gimp_data_directory (),
458
"images", "gimp-splash.png", NULL);
461
g_printerr ("Trying splash '%s' ... ", filename);
463
pixbuf = gdk_pixbuf_animation_new_from_file (filename, NULL);
467
g_printerr (pixbuf ? "OK\n" : "failed\n");
472
filename = g_build_filename (gimp_data_directory (), "splashes", NULL);
473
pixbuf = splash_image_pick_from_dir (filename, be_verbose);
479
static GdkPixbufAnimation *
480
splash_image_pick_from_dir (const gchar *dirname,
483
GdkPixbufAnimation *pixbuf = NULL;
484
GDir *dir = g_dir_open (dirname, 0, NULL);
489
GList *splashes = NULL;
491
while ((entry = g_dir_read_name (dir)))
492
splashes = g_list_prepend (splashes, g_strdup (entry));
498
gint32 i = g_random_int_range (0, g_list_length (splashes));
499
gchar *filename = g_build_filename (dirname,
500
g_list_nth_data (splashes, i),
504
g_printerr ("Trying splash '%s' ... ", filename);
506
pixbuf = gdk_pixbuf_animation_new_from_file (filename, NULL);
510
g_printerr (pixbuf ? "OK\n" : "failed\n");
512
g_list_foreach (splashes, (GFunc) g_free, NULL);
513
g_list_free (splashes);
522
splash_timer_elapsed (const gchar *text1,
526
gdouble elapsed = g_timer_elapsed (splash->timer, NULL);
530
g_free (splash->text1);
531
splash->text1 = g_strdup (text1);
536
g_free (splash->text2);
537
splash->text2 = g_strdup (text2);
540
g_printerr ("%8g %8g - %s %g%% - %s\n",
542
elapsed - splash->last_time,
543
splash->text1 ? splash->text1 : "",
545
splash->text2 ? splash->text2 : "");
547
splash->last_time = elapsed;