~ubuntu-branches/ubuntu/karmic/xfce4-session/karmic

« back to all changes in this revision

Viewing changes to engines/balou/balou-theme.c

  • Committer: Bazaar Package Importer
  • Author(s): Yves-Alexis Perez
  • Date: 2005-11-06 22:01:12 UTC
  • mto: (4.1.1 lenny) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20051106220112-5rusox237ymjghsp
Tags: upstream-4.2.3
ImportĀ upstreamĀ versionĀ 4.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: balou-theme.c 4618 2004-07-14 20:17:58Z benny $ */
 
2
/*-
 
3
 * Copyright (c) 2004 Benedikt Meurer <benny@xfce.org>
 
4
 * All rights reserved.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2, or (at your option)
 
9
 * any later version.
 
10
 *                                                                              
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *                                                                              
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
 
 
26
#ifdef HAVE_SYS_STAT_H
 
27
#include <sys/stat.h>
 
28
#endif
 
29
 
 
30
#include <math.h>
 
31
#ifdef HAVE_MEMORY_H
 
32
#include <memory.h>
 
33
#endif
 
34
#ifdef HAVE_STRING_H
 
35
#include <string.h>
 
36
#endif
 
37
#ifdef HAVE_TIME_H
 
38
#include <time.h>
 
39
#endif
 
40
#ifdef HAVE_UNISTD_H
 
41
#include <unistd.h>
 
42
#endif
 
43
 
 
44
#include <libxfce4util/libxfce4util.h>
 
45
 
 
46
#include <engines/balou/balou-theme.h>
 
47
 
 
48
 
 
49
static void       load_color_pair (const XfceRc *rc,
 
50
                                   const gchar  *name,
 
51
                                   GdkColor     *color1_return, 
 
52
                                   GdkColor     *color2_return,
 
53
                                   const gchar  *color_default);
 
54
static GdkPixbuf  *load_pixbuf    (const gchar *path,
 
55
                                   gint         available_width,
 
56
                                   gint         available_height);
 
57
static time_t mtime (const gchar *path);
 
58
static GdkPixbuf *load_cached_preview (const BalouTheme *theme);
 
59
static void store_cached_preview (const BalouTheme *theme,
 
60
                                  GdkPixbuf        *pixbuf);
 
61
 
 
62
 
 
63
struct _BalouTheme
 
64
{
 
65
  GdkColor  bgcolor1;
 
66
  GdkColor  bgcolor2;
 
67
  GdkColor  fgcolor;
 
68
  gchar    *name;
 
69
  gchar    *description;
 
70
  gchar    *font;
 
71
  gchar    *theme_file;
 
72
  gchar    *logo_file;
 
73
};
 
74
 
 
75
 
 
76
#define DEFAULT_BGCOLOR "White"
 
77
#define DEFAULT_FGCOLOR "Black"
 
78
#define DEFAULT_FONT    "Sans Bold 12"
 
79
 
 
80
 
 
81
BalouTheme*
 
82
balou_theme_load (const gchar *name)
 
83
{
 
84
  BalouTheme  *theme;
 
85
  const gchar *image_file;
 
86
  const gchar *spec;
 
87
  gchar       *resource;
 
88
  gchar       *file;
 
89
  XfceRc      *rc;
 
90
 
 
91
  theme = g_new0 (BalouTheme, 1);
 
92
 
 
93
  resource = g_strdup_printf ("%s/balou/themerc", name);
 
94
  file = xfce_resource_lookup (XFCE_RESOURCE_THEMES, resource);
 
95
  g_free (resource);
 
96
 
 
97
  if (file != NULL)
 
98
    {
 
99
      rc = xfce_rc_simple_open (file, TRUE);
 
100
      if (rc == NULL)
 
101
        {
 
102
          g_free (file);
 
103
          goto set_defaults;
 
104
        }
 
105
 
 
106
      theme->theme_file = g_strdup (file);
 
107
 
 
108
      xfce_rc_set_group (rc, "Info");
 
109
      theme->name = g_strdup (xfce_rc_read_entry (rc, "Name", name));
 
110
      theme->description = g_strdup (xfce_rc_read_entry (rc, "Description", _("No description given")));
 
111
 
 
112
      xfce_rc_set_group (rc, "Splash Screen");
 
113
      load_color_pair (rc, "bgcolor", &theme->bgcolor1, &theme->bgcolor2,
 
114
                       DEFAULT_BGCOLOR);
 
115
 
 
116
      spec = xfce_rc_read_entry (rc, "fgcolor", DEFAULT_FGCOLOR);
 
117
      if (!gdk_color_parse (spec, &theme->fgcolor))
 
118
        gdk_color_parse (DEFAULT_FGCOLOR, &theme->fgcolor);
 
119
 
 
120
      spec = xfce_rc_read_entry (rc, "font", DEFAULT_FONT);
 
121
      theme->font = g_strdup (spec);
 
122
 
 
123
      image_file = xfce_rc_read_entry (rc, "logo", NULL);
 
124
      if (image_file != NULL)
 
125
        {
 
126
          resource = g_path_get_dirname (file);
 
127
          theme->logo_file = g_build_filename (resource, image_file, NULL);
 
128
          g_free (resource);
 
129
        }
 
130
      else
 
131
        {
 
132
          theme->logo_file = NULL;
 
133
        }
 
134
 
 
135
      xfce_rc_close (rc);
 
136
      g_free (file);
 
137
 
 
138
      return theme;
 
139
    }
 
140
 
 
141
set_defaults:
 
142
  gdk_color_parse (DEFAULT_BGCOLOR, &theme->bgcolor1);
 
143
  gdk_color_parse (DEFAULT_BGCOLOR, &theme->bgcolor2);
 
144
  gdk_color_parse (DEFAULT_FGCOLOR, &theme->fgcolor);
 
145
  theme->font = g_strdup (DEFAULT_FONT);
 
146
  theme->logo_file = NULL;
 
147
 
 
148
  return theme;
 
149
}
 
150
 
 
151
 
 
152
const gchar*
 
153
balou_theme_get_name (const BalouTheme *theme)
 
154
{
 
155
  return theme->name;
 
156
}
 
157
 
 
158
 
 
159
const gchar*
 
160
balou_theme_get_description (const BalouTheme *theme)
 
161
{
 
162
  return theme->description;
 
163
}
 
164
 
 
165
 
 
166
const gchar*
 
167
balou_theme_get_font (const BalouTheme *theme)
 
168
{
 
169
  return theme->font;
 
170
}
 
171
 
 
172
 
 
173
void
 
174
balou_theme_get_bgcolor (const BalouTheme *theme,
 
175
                         GdkColor         *color_return)
 
176
{
 
177
  *color_return = theme->bgcolor1;
 
178
}
 
179
 
 
180
 
 
181
void
 
182
balou_theme_get_fgcolor (const BalouTheme *theme,
 
183
                         GdkColor         *color_return)
 
184
{
 
185
  *color_return = theme->fgcolor;
 
186
}
 
187
 
 
188
 
 
189
GdkPixbuf*
 
190
balou_theme_get_logo (const BalouTheme *theme,
 
191
                      gint              available_width,
 
192
                      gint              available_height)
 
193
{
 
194
  return load_pixbuf (theme->logo_file,
 
195
                      available_width,
 
196
                      available_height);
 
197
}
 
198
 
 
199
 
 
200
void
 
201
balou_theme_draw_gradient (const BalouTheme *theme,
 
202
                           GdkDrawable      *drawable,
 
203
                           GdkGC            *gc,
 
204
                           GdkRectangle      logobox,
 
205
                           GdkRectangle      textbox)
 
206
{
 
207
  GdkColor color;
 
208
  gint     dred;
 
209
  gint     dgreen;
 
210
  gint     dblue;
 
211
  gint     i;
 
212
 
 
213
  if (gdk_color_equal (&theme->bgcolor1, &theme->bgcolor2))
 
214
    {
 
215
      gdk_gc_set_rgb_fg_color (gc, &theme->bgcolor1);
 
216
      gdk_draw_rectangle (drawable, gc, TRUE, logobox.x, logobox.y,
 
217
                          logobox.width, logobox.height);
 
218
      gdk_draw_rectangle (drawable, gc, TRUE, textbox.x, textbox.y,
 
219
                          textbox.width, textbox.height);
 
220
    }
 
221
  else
 
222
    {
 
223
      /* calculate differences */
 
224
      dred = theme->bgcolor1.red - theme->bgcolor2.red;
 
225
      dgreen = theme->bgcolor1.green - theme->bgcolor2.green;
 
226
      dblue = theme->bgcolor1.blue - theme->bgcolor2.blue;
 
227
 
 
228
      for (i = 0; i < logobox.height; ++i)
 
229
        {
 
230
          color.red = theme->bgcolor2.red + (i * dred / logobox.height);
 
231
          color.green = theme->bgcolor2.green + (i * dgreen / logobox.height);
 
232
          color.blue = theme->bgcolor2.blue + (i * dblue / logobox.height);
 
233
 
 
234
          gdk_gc_set_rgb_fg_color (gc, &color);
 
235
          gdk_draw_line (drawable, gc, logobox.x, logobox.y + i,
 
236
                         logobox.x + logobox.width, logobox.y + i);
 
237
        }
 
238
 
 
239
    if (textbox.width != 0 && textbox.height != 0)
 
240
      {
 
241
        gdk_gc_set_rgb_fg_color (gc, &theme->bgcolor1);
 
242
        gdk_draw_rectangle (drawable, gc, TRUE, textbox.x, textbox.y,
 
243
                            textbox.width, textbox.height);
 
244
      }
 
245
    }
 
246
}
 
247
 
 
248
 
 
249
GdkPixbuf*
 
250
balou_theme_generate_preview (const BalouTheme *theme,
 
251
                              gint              width,
 
252
                              gint              height)
 
253
{
 
254
#define WIDTH   320
 
255
#define HEIGHT  240
 
256
 
 
257
  GdkRectangle logobox;
 
258
  GdkRectangle textbox;
 
259
  GdkPixmap *pixmap;
 
260
  GdkPixbuf *pixbuf;
 
261
  GdkPixbuf *scaled;
 
262
  GdkWindow *root;
 
263
  GdkGC     *gc;
 
264
  gint       pw, ph;
 
265
 
 
266
  /* check for a cached preview first */
 
267
  pixbuf = load_cached_preview (theme);
 
268
  if (pixbuf != NULL)
 
269
    {
 
270
      pw = gdk_pixbuf_get_width (pixbuf);
 
271
      ph = gdk_pixbuf_get_height (pixbuf);
 
272
 
 
273
      if (pw == width && ph == height)
 
274
        {
 
275
          return pixbuf;
 
276
        }
 
277
      else if (pw >= width && ph >= height)
 
278
        {
 
279
          scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
 
280
                                            GDK_INTERP_BILINEAR);
 
281
          g_object_unref (pixbuf);
 
282
          return scaled;
 
283
        }
 
284
 
 
285
      g_object_unref (pixbuf);
 
286
    }
 
287
 
 
288
  root = gdk_screen_get_root_window (gdk_screen_get_default ());
 
289
  pixmap = gdk_pixmap_new (GDK_DRAWABLE (root), WIDTH, HEIGHT, -1);
 
290
  gc = gdk_gc_new (pixmap);
 
291
  gdk_gc_set_function (gc, GDK_COPY);
 
292
 
 
293
  logobox.x = 0;
 
294
  logobox.y = 0;
 
295
  logobox.width = WIDTH;
 
296
  logobox.height = HEIGHT;
 
297
  textbox.x = 0;
 
298
  textbox.y = 0;
 
299
  balou_theme_draw_gradient (theme, GDK_DRAWABLE (pixmap),
 
300
                             gc, logobox, textbox);
 
301
 
 
302
  pixbuf = balou_theme_get_logo (theme, WIDTH, HEIGHT);
 
303
  if (pixbuf != NULL)
 
304
    {
 
305
      pw = gdk_pixbuf_get_width (pixbuf);
 
306
      ph = gdk_pixbuf_get_height (pixbuf);
 
307
 
 
308
      gdk_draw_pixbuf (GDK_DRAWABLE (pixmap), gc, pixbuf, 0, 0,
 
309
                       (WIDTH - pw) / 2, (HEIGHT - ph) / 2,
 
310
                       pw, ph, GDK_RGB_DITHER_NONE, 0, 0);
 
311
 
 
312
      g_object_unref (G_OBJECT (pixbuf));
 
313
    }
 
314
 
 
315
  pixbuf = gdk_pixbuf_get_from_drawable (NULL, GDK_DRAWABLE (pixmap),
 
316
                                         NULL, 0, 0, 0, 0, WIDTH, HEIGHT);
 
317
  scaled = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
 
318
 
 
319
  g_object_unref (pixbuf);
 
320
  g_object_unref (pixmap);
 
321
  g_object_unref (gc);
 
322
 
 
323
  /* store preview */
 
324
  store_cached_preview (theme, scaled);
 
325
 
 
326
  return scaled;
 
327
 
 
328
#undef WIDTH
 
329
#undef HEIGHT
 
330
}
 
331
 
 
332
 
 
333
void
 
334
balou_theme_destroy (BalouTheme *theme)
 
335
{
 
336
  if (theme->name != NULL)
 
337
    g_free (theme->name);
 
338
  if (theme->description != NULL)
 
339
    g_free (theme->description);
 
340
  if (theme->theme_file != NULL)
 
341
    g_free (theme->theme_file);
 
342
  if (theme->logo_file != NULL)
 
343
    g_free (theme->logo_file);
 
344
  g_free (theme);
 
345
}
 
346
 
 
347
 
 
348
 
 
349
static void
 
350
load_color_pair (const XfceRc *rc,
 
351
                 const gchar  *name,
 
352
                 GdkColor     *color1_return, 
 
353
                 GdkColor     *color2_return,
 
354
                 const gchar  *color_default)
 
355
{
 
356
  const gchar *spec;
 
357
  gchar      **s;
 
358
 
 
359
  spec = xfce_rc_read_entry (rc, name, color_default);
 
360
  if (spec == NULL)
 
361
    {
 
362
      gdk_color_parse (color_default, color1_return);
 
363
      gdk_color_parse (color_default, color2_return);
 
364
    }
 
365
  else
 
366
    {
 
367
      s = g_strsplit (spec, ":", 2);
 
368
 
 
369
      if (s[0] == NULL)
 
370
        {
 
371
          gdk_color_parse (color_default, color1_return);
 
372
          gdk_color_parse (color_default, color2_return);
 
373
        }
 
374
      else if (s[1] == NULL)
 
375
        {
 
376
          if (!gdk_color_parse (s[0], color1_return))
 
377
            gdk_color_parse (color_default, color1_return);
 
378
          *color2_return = *color1_return;
 
379
        }
 
380
      else
 
381
        {
 
382
          if (!gdk_color_parse (s[0], color2_return))
 
383
            gdk_color_parse (color_default, color2_return);
 
384
          if (!gdk_color_parse (s[1], color1_return))
 
385
            *color1_return = *color2_return;
 
386
        }
 
387
 
 
388
      g_strfreev (s);
 
389
    }
 
390
}
 
391
 
 
392
 
 
393
static GdkPixbuf*
 
394
load_pixbuf (const gchar *path,
 
395
             gint         available_width,
 
396
             gint         available_height)
 
397
{
 
398
  static char *suffixes[] = { "svg", "png", "jpeg", "jpg", "xpm", NULL };
 
399
  GdkPixbuf *scaled;
 
400
  GdkPixbuf *pb = NULL;
 
401
  gint pb_width;
 
402
  gint pb_height;
 
403
  gdouble wratio;
 
404
  gdouble hratio;
 
405
  gchar *file;
 
406
  guint n;
 
407
 
 
408
  if (G_UNLIKELY (path == NULL))
 
409
    return NULL;
 
410
 
 
411
  pb = gdk_pixbuf_new_from_file (path, NULL);
 
412
  if (G_UNLIKELY (pb == NULL))
 
413
    {
 
414
      for (n = 0; pb == NULL && suffixes[n] != NULL; ++n)
 
415
        {
 
416
          file = g_strdup_printf ("%s.%s", path, suffixes[n]);
 
417
          pb = gdk_pixbuf_new_from_file (file, NULL);
 
418
          g_free (file);
 
419
        }
 
420
    }
 
421
 
 
422
  if (G_UNLIKELY (pb == NULL))
 
423
    return NULL;
 
424
 
 
425
  pb_width = gdk_pixbuf_get_width (pb);
 
426
  pb_height = gdk_pixbuf_get_height (pb);
 
427
 
 
428
  if (pb_width > available_width || pb_height > available_height)
 
429
    {
 
430
      wratio = (gdouble) pb_width / (gdouble) available_width;
 
431
      hratio = (gdouble) pb_height / (gdouble) available_height;
 
432
 
 
433
      if (hratio > wratio)
 
434
        {
 
435
          pb_width = rint (pb_width / hratio);
 
436
          pb_height = available_height;
 
437
        }
 
438
      else
 
439
        {
 
440
          pb_width = available_width;
 
441
          pb_height = rint (pb_height / wratio);
 
442
        }
 
443
 
 
444
      scaled = gdk_pixbuf_scale_simple (pb,
 
445
                                        pb_width,
 
446
                                        pb_height,
 
447
                                        GDK_INTERP_BILINEAR);
 
448
      g_object_unref (pb);
 
449
      pb = scaled;
 
450
    }
 
451
 
 
452
  return pb;
 
453
}
 
454
 
 
455
 
 
456
static time_t
 
457
mtime (const gchar *path)
 
458
{
 
459
  struct stat sb;
 
460
 
 
461
  if (path == NULL || stat (path, &sb) < 0)
 
462
    return (time_t) 0;
 
463
 
 
464
  return sb.st_mtime;
 
465
}
 
466
 
 
467
 
 
468
static GdkPixbuf*
 
469
load_cached_preview (const BalouTheme *theme)
 
470
{
 
471
  GdkPixbuf *pixbuf;
 
472
  gchar     *resource;
 
473
  gchar     *preview;
 
474
 
 
475
  resource = g_strconcat ("splash-theme-preview-", theme->name, ".png", NULL);
 
476
  preview = xfce_resource_lookup (XFCE_RESOURCE_CACHE, resource);
 
477
  g_free (resource);
 
478
 
 
479
  if (preview == NULL)
 
480
    return NULL;
 
481
 
 
482
  if ((mtime (preview) < mtime (theme->theme_file))
 
483
      || (theme->logo_file != NULL
 
484
        && (mtime (preview) < mtime (theme->logo_file))))
 
485
    {
 
486
      /* preview is outdated, need to regenerate preview */
 
487
      unlink (preview);
 
488
      g_free (preview);
 
489
 
 
490
      return NULL;
 
491
    }
 
492
 
 
493
  pixbuf = gdk_pixbuf_new_from_file (preview, NULL);
 
494
  g_free (preview);
 
495
 
 
496
  return pixbuf;
 
497
}
 
498
 
 
499
 
 
500
static void
 
501
store_cached_preview (const BalouTheme *theme,
 
502
                      GdkPixbuf        *pixbuf)
 
503
{
 
504
  gchar *resource;
 
505
  gchar *preview;
 
506
 
 
507
  resource = g_strconcat ("splash-theme-preview-", theme->name, ".png", NULL);
 
508
  preview = xfce_resource_save_location (XFCE_RESOURCE_CACHE, resource, TRUE);
 
509
  g_free (resource);
 
510
 
 
511
  if (preview != NULL)
 
512
    {
 
513
      gdk_pixbuf_save (pixbuf, preview, "png", NULL, NULL);
 
514
      g_free (preview);
 
515
    }
 
516
}
 
517
 
 
518
 
 
519