~ml-launchpad/ubuntu/natty/gcompris/fix-for-777349

« back to all changes in this revision

Viewing changes to src/gcompris/gameutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Marc Gariepy, Marc Gariepy, Stephane Graber
  • Date: 2010-01-04 17:42:49 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100104174249-7bupatd9dtxyhvs4
Tags: 9.0-0ubuntu1
[Marc Gariepy]
* New upstream release (9.0).
* Remove cache.c from POTFILES to avoid FTBFS
* Remove unneeded rm in debian/rules (file no longer exists upstream)

[Stephane Graber]
* Bump Debian standards to 3.8.3
* Add patch system (dpatch)

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
 
32
32
#include "gcompris.h"
33
33
 
 
34
extern GooCanvas *canvas;
 
35
 
 
36
typedef void (*sighandler_t)(int);
 
37
 
34
38
/* GdkPixbuf RGBA C-Source image dump for a NULL image*/
35
39
#ifdef __SUNPRO_C
36
40
#pragma align 4 (null_img)
38
42
#ifdef __GNUC__
39
43
static const guint8 null_img[] __attribute__ ((__aligned__ (4))) =
40
44
#else
41
 
static const guint8 null_img[] =
 
45
  static const guint8 null_img[] =
42
46
#endif
43
47
{ ""
44
48
  /* Pixbuf magic (0x47646b50) */
56
60
  /* pixel_data: */
57
61
  "%%%\0"};
58
62
 
59
 
/** load a pixmap from the filesystem
 
63
/** load a pixmap from the filesystem, return NULL if
 
64
 *  not found and do not display an error message.
60
65
 *
61
66
 * \param format: If format contains $LOCALE, it will be first replaced by the current long locale
62
67
 *                and if not found the short locale name. It support printf formating.
64
69
 *
65
70
 * \return a new allocated pixbuf or NULL
66
71
 */
 
72
GdkPixbuf *gc_pixmap_load_or_null(const gchar *format, ...)
 
73
{
 
74
  va_list args;
 
75
  gchar *filename;
 
76
  gchar *pixmapfile;
 
77
  GdkPixbuf *pixmap=NULL;
 
78
 
 
79
  if (!format)
 
80
    return NULL;
 
81
 
 
82
  va_start (args, format);
 
83
  pixmapfile = g_strdup_vprintf (format, args);
 
84
  va_end (args);
 
85
 
 
86
  /* Search */
 
87
  filename = gc_file_find_absolute(pixmapfile);
 
88
 
 
89
  if(filename)
 
90
     pixmap = gdk_pixbuf_new_from_file(filename,NULL);
 
91
 
 
92
  g_free(pixmapfile);
 
93
  g_free(filename);
 
94
 
 
95
 
 
96
  return(pixmap);
 
97
}
 
98
 
 
99
/** load a pixmap from the filesystem, if not found display
 
100
 *  an error message and return an small 1x1 pixmap.
 
101
 *
 
102
 * \param format: If format contains $LOCALE, it will be first replaced by the current long locale
 
103
 *                and if not found the short locale name. It support printf formating.
 
104
 * \param ...:    additional params for the format (printf like)
 
105
 *
 
106
 * \return a new allocated pixbuf or a 1x1 pixmap
 
107
 */
67
108
GdkPixbuf *gc_pixmap_load(const gchar *format, ...)
68
109
{
69
110
  va_list args;
82
123
  filename = gc_file_find_absolute(pixmapfile);
83
124
 
84
125
  if(filename)
85
 
     pixmap = gdk_pixbuf_new_from_file(filename,NULL);
 
126
    pixmap = gc_pixmap_load_or_null(filename);
86
127
 
87
128
  if (!filename || !pixmap)
88
129
    {
113
154
  return(pixmap);
114
155
}
115
156
 
116
 
/*************************************************************
117
 
 * colorshift a pixbuf
118
 
 * code taken from the gnome-panel of gnome-core
 
157
/** load an svg image from the filesystem
 
158
 *
 
159
 * \param format: If format contains $LOCALE, it will be first replaced by the current long locale
 
160
 *                and if not found the short locale name. It support printf formating.
 
161
 * \param ...:    additional params for the format (printf like)
 
162
 *
 
163
 * \return a new allocated pixbuf or NULL
 
164
 */
 
165
RsvgHandle *gc_rsvg_load(const gchar *format, ...)
 
166
{
 
167
  va_list args;
 
168
  gchar *filename;
 
169
  gchar *rsvghandlefile;
 
170
  RsvgHandle *rsvghandle = NULL;
 
171
  GError *error = NULL;
 
172
 
 
173
  if (!format)
 
174
    return NULL;
 
175
 
 
176
  va_start (args, format);
 
177
  rsvghandlefile = g_strdup_vprintf (format, args);
 
178
  va_end (args);
 
179
 
 
180
  /* Search */
 
181
  filename = gc_file_find_absolute(rsvghandlefile);
 
182
 
 
183
  if(filename)
 
184
    rsvghandle = rsvg_handle_new_from_file (filename, &error);
 
185
 
 
186
  if (!filename || !rsvghandle)
 
187
    {
 
188
      char *str;
 
189
 
 
190
      if(!rsvghandle)
 
191
        g_warning("Loading image '%s' returned a null pointer", rsvghandlefile);
 
192
      else
 
193
        g_warning ("Couldn't find file %s !", rsvghandlefile);
 
194
 
 
195
      str = g_strdup_printf("%s\n%s\n%s\n%s",
 
196
                            _("Couldn't find or load the file"),
 
197
                            rsvghandlefile,
 
198
                            _("This activity is incomplete."),
 
199
                            _("Exit it and report\nthe problem to the authors."));
 
200
      gc_dialog (str, NULL);
 
201
      g_free(rsvghandlefile);
 
202
      g_free(str);
 
203
 
 
204
      /* Create an empty rsvghandle because activities does not manage loading error */
 
205
      return rsvg_handle_new();
 
206
    }
 
207
 
 
208
  g_free(rsvghandlefile);
 
209
  g_free(filename);
 
210
 
 
211
  return(rsvghandle);
 
212
}
 
213
 
 
214
/**
 
215
 * Set the focus of the given item (highlight or not)
 
216
 *
119
217
 */
120
218
static void
121
 
do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift)
122
 
{
123
 
  gint i, j;
124
 
  gint width, height, has_alpha, srcrowstride, destrowstride;
125
 
  guchar *target_pixels;
126
 
  guchar *original_pixels;
127
 
  guchar *pixsrc;
128
 
  guchar *pixdest;
129
 
  int val;
130
 
  guchar r,g,b;
131
 
 
132
 
  has_alpha = gdk_pixbuf_get_has_alpha (src);
133
 
  width = gdk_pixbuf_get_width (src);
134
 
  height = gdk_pixbuf_get_height (src);
135
 
  srcrowstride = gdk_pixbuf_get_rowstride (src);
136
 
  destrowstride = gdk_pixbuf_get_rowstride (dest);
137
 
  target_pixels = gdk_pixbuf_get_pixels (dest);
138
 
  original_pixels = gdk_pixbuf_get_pixels (src);
139
 
 
140
 
  for (i = 0; i < height; i++) {
141
 
    pixdest = target_pixels + i*destrowstride;
142
 
    pixsrc = original_pixels + i*srcrowstride;
143
 
    for (j = 0; j < width; j++) {
144
 
      r = *(pixsrc++);
145
 
      g = *(pixsrc++);
146
 
      b = *(pixsrc++);
147
 
      val = r + shift;
148
 
      *(pixdest++) = CLAMP(val, 0, 255);
149
 
      val = g + shift;
150
 
      *(pixdest++) = CLAMP(val, 0, 255);
151
 
      val = b + shift;
152
 
      *(pixdest++) = CLAMP(val, 0, 255);
153
 
      if (has_alpha)
154
 
        *(pixdest++) = *(pixsrc++);
155
 
    }
156
 
  }
157
 
}
158
 
 
159
 
 
160
 
 
161
 
GdkPixbuf *
162
 
make_hc_pixbuf(GdkPixbuf *pb, gint val)
163
 
{
164
 
  GdkPixbuf *new;
165
 
  if(!pb)
166
 
    return NULL;
167
 
 
168
 
  new = gdk_pixbuf_new(gdk_pixbuf_get_colorspace(pb),
169
 
                       gdk_pixbuf_get_has_alpha(pb),
170
 
                       gdk_pixbuf_get_bits_per_sample(pb),
171
 
                       gdk_pixbuf_get_width(pb),
172
 
                       gdk_pixbuf_get_height(pb));
173
 
  do_colorshift(new, pb, val);
174
 
  /*do_saturate_darken (new, pb, (int)(1.00*255), (int)(1.15*255));*/
175
 
 
176
 
  return new;
177
 
}
178
 
 
179
 
/**
180
 
 * Free the highlight image from our image_focus system
181
 
 *
182
 
 * It must be called before assigning a new image to an item that
183
 
 * already has a focus enabled with gc_item_focus_event().
184
 
 */
185
 
void
186
 
gc_item_focus_free(GnomeCanvasItem *item, void *none)
187
 
{
188
 
  GdkPixbuf *pixbuf;
189
 
 
190
 
  pixbuf = (GdkPixbuf *)g_object_get_data (G_OBJECT (item), "pixbuf_ref");
191
 
  if(pixbuf)
192
 
    {
193
 
      g_object_set_data (G_OBJECT (item), "pixbuf_ref", NULL);
194
 
      gdk_pixbuf_unref(pixbuf);
195
 
    }
196
 
}
197
 
 
198
 
/**
199
 
 * Set the focus of the given image (highlight or not)
200
 
 *
201
 
 */
202
 
void gc_item_focus_set(GnomeCanvasItem *item, gboolean focus)
203
 
{
204
 
  GdkPixbuf *dest = NULL;
205
 
  GdkPixbuf *pixbuf;
206
 
  GdkPixbuf *pixbuf_ref;
207
 
 
208
 
  gtk_object_get (GTK_OBJECT (item), "pixbuf", &pixbuf, NULL);
209
 
  g_return_if_fail (pixbuf != NULL);
210
 
  gdk_pixbuf_unref(pixbuf);
211
 
 
212
 
  /* Store the first pixbuf */
213
 
  pixbuf_ref = (GdkPixbuf *)g_object_get_data (G_OBJECT (item), "pixbuf_ref");
214
 
  if(!pixbuf_ref)
215
 
    {
216
 
      g_object_set_data (G_OBJECT (item), "pixbuf_ref", pixbuf);
217
 
      pixbuf_ref = pixbuf;
218
 
      gdk_pixbuf_ref(pixbuf);
219
 
      g_signal_connect (item, "destroy",
220
 
                        G_CALLBACK (gc_item_focus_free),
221
 
                        NULL);
222
 
 
223
 
    }
224
 
 
 
219
gc_item_focus_set(GooCanvasItem *item, gboolean focus)
 
220
{
 
221
  GooCanvasItem *highlight_item;
 
222
 
 
223
  highlight_item = g_object_get_data (G_OBJECT(item),
 
224
                                      "highlight_item");
 
225
  g_assert(highlight_item);
225
226
 
226
227
  switch (focus)
227
228
    {
228
229
    case TRUE:
229
 
      dest = make_hc_pixbuf(pixbuf, 30);
230
 
      gnome_canvas_item_set (item,
231
 
                             "pixbuf", dest,
232
 
                             NULL);
233
 
 
 
230
      g_object_set (highlight_item,
 
231
                    "visibility", GOO_CANVAS_ITEM_VISIBLE,
 
232
                    NULL);
234
233
      break;
235
234
    case FALSE:
236
 
      gnome_canvas_item_set (item,
237
 
                             "pixbuf", pixbuf_ref,
238
 
                             NULL);
 
235
      g_object_set (highlight_item,
 
236
                    "visibility", GOO_CANVAS_ITEM_INVISIBLE,
 
237
                    NULL);
239
238
      break;
240
239
    default:
241
240
      break;
242
241
    }
243
242
 
244
 
  if(dest!=NULL)
245
 
    gdk_pixbuf_unref (dest);
246
 
 
247
243
}
248
244
 
249
245
/**
251
247
 * or the given one
252
248
 *
253
249
 */
254
 
gint
255
 
gc_item_focus_event(GnomeCanvasItem *item, GdkEvent *event,
256
 
                    GnomeCanvasItem *dest_item)
 
250
static gint
 
251
gc_item_focus_event(GooCanvasItem *item, GooCanvasItem *target,
 
252
                    GdkEvent *event,
 
253
                    GooCanvasItem *target_item)
257
254
{
258
 
 
259
 
  if(dest_item!=NULL)
260
 
    item = dest_item;
 
255
  if(target_item != NULL)
 
256
    item = target_item;
261
257
 
262
258
  switch (event->type)
263
259
    {
274
270
  return FALSE;
275
271
}
276
272
 
 
273
/**
 
274
 * Init an item so that it has a focus
 
275
 * Optionnaly, provide a target_item that will be focused
 
276
 * by events on source_item.
 
277
 *
 
278
 * Warning: You must call it each time the size of the focused
 
279
 *          item size changes.
 
280
 *
 
281
 */
 
282
#define GAP 4
 
283
void gc_item_focus_init(GooCanvasItem *source_item,
 
284
                        GooCanvasItem *target_item)
 
285
{
 
286
  GooCanvasItem *highlight_item;
 
287
  GooCanvasBounds bounds;
 
288
  gboolean already_created = FALSE;
 
289
 
 
290
  if(!target_item)
 
291
    target_item = source_item;
 
292
 
 
293
  goo_canvas_item_get_bounds(target_item, &bounds);
 
294
  goo_canvas_convert_to_item_space(goo_canvas_item_get_canvas(target_item),
 
295
                                   goo_canvas_item_get_parent(target_item),
 
296
                                   &bounds.x1, &bounds.y1);
 
297
  goo_canvas_convert_to_item_space(goo_canvas_item_get_canvas(target_item),
 
298
                                   goo_canvas_item_get_parent(target_item),
 
299
                                   &bounds.x2, &bounds.y2);
 
300
  highlight_item = g_object_get_data (G_OBJECT(target_item),
 
301
                                      "highlight_item");
 
302
 
 
303
  if(highlight_item)
 
304
    {
 
305
      already_created = TRUE;
 
306
      goo_canvas_item_remove(highlight_item);
 
307
    }
 
308
 
 
309
  /* Create the highlight_item */
 
310
  highlight_item =
 
311
    goo_canvas_rect_new (goo_canvas_item_get_parent(target_item),
 
312
                         bounds.x1 - GAP,
 
313
                         bounds.y1 - GAP,
 
314
                         bounds.x2 - bounds.x1 + GAP*2,
 
315
                         bounds.y2 - bounds.y1 + GAP*2,
 
316
                         "stroke_color_rgba", 0xFFFFFFFFL,
 
317
                         "fill_color_rgba", 0xFF000090L,
 
318
                         "line-width", (double) 2,
 
319
                         "radius-x", (double) 10,
 
320
                         "radius-y", (double) 10,
 
321
                         NULL);
 
322
 
 
323
  g_object_set_data (G_OBJECT(target_item), "highlight_item",
 
324
                     highlight_item);
 
325
  goo_canvas_item_lower(highlight_item, target_item);
 
326
  g_object_set (highlight_item,
 
327
                "visibility", GOO_CANVAS_ITEM_INVISIBLE,
 
328
                NULL);
 
329
 
 
330
  /* Avoid double connection */
 
331
  g_signal_handlers_disconnect_by_func(source_item,
 
332
                                       (GtkSignalFunc) gc_item_focus_event,
 
333
                                       target_item);
 
334
 
 
335
  /* connect source to target */
 
336
  g_signal_connect(source_item, "enter_notify_event",
 
337
                   (GtkSignalFunc) gc_item_focus_event,
 
338
                   target_item);
 
339
  g_signal_connect(source_item, "leave_notify_event",
 
340
                   (GtkSignalFunc) gc_item_focus_event,
 
341
                   target_item);
 
342
}
 
343
 
 
344
/**
 
345
 * gc_item_focus_remove
 
346
 *
 
347
 * Remove a previously set of item focus
 
348
 *
 
349
 * @param[in] source_item is the same as the one passed to
 
350
 *            gc_item_focus_init()
 
351
 * @param[in] target_itemis the same as the one passed to
 
352
 *            gc_item_focus_init()
 
353
 */
 
354
void gc_item_focus_remove(GooCanvasItem *source_item,
 
355
                          GooCanvasItem *target_item)
 
356
{
 
357
  GooCanvasItem *highlight_item;
 
358
 
 
359
  if(!target_item)
 
360
    target_item = source_item;
 
361
 
 
362
  g_signal_handlers_disconnect_by_func(source_item,
 
363
                                       (GtkSignalFunc) gc_item_focus_event,
 
364
                                       target_item);
 
365
 
 
366
  highlight_item = g_object_get_data (G_OBJECT(target_item),
 
367
                                      "highlight_item");
 
368
 
 
369
  if(highlight_item)
 
370
    goo_canvas_item_remove(highlight_item);
 
371
 
 
372
  g_object_set_data (G_OBJECT(target_item), "highlight_item",
 
373
                     NULL);
 
374
}
 
375
 
277
376
/*
278
377
 * Return a new copy of the given string in which it has
279
378
 * changes '\''n' to '\n'.
303
402
}
304
403
 
305
404
/* ======================================= */
306
 
void gc_item_absolute_move(GnomeCanvasItem *item, int x, int y) {
307
 
  double dx1, dy1, dx2, dy2;
308
 
  gnome_canvas_item_get_bounds(item, &dx1, &dy1, &dx2, &dy2);
309
 
  gnome_canvas_item_move(item, ((double)x)-dx1, ((double)y)-dy1);
 
405
/* Any previous transformation are reseted first. */
 
406
void gc_item_absolute_move(GooCanvasItem *item, int x, int y)
 
407
{
 
408
  GooCanvasBounds bounds;
 
409
 
 
410
  goo_canvas_item_set_transform(item, NULL);
 
411
  goo_canvas_item_get_bounds(item, &bounds);
 
412
  goo_canvas_item_translate(item, ((double)x)-bounds.x1, ((double)y)-bounds.y1);
310
413
}
311
414
 
312
415
/* ======================================= */
313
416
/** As gnome does not implement its own API : gc_item_rotate
314
 
   we have to do it ourselves ....
315
 
   IMPORTANT NOTE : This is designed for an item with "anchor" =  GTK_ANCHOR_CENTER
316
 
   rotation is clockwise if angle > 0
 
417
    we have to do it ourselves ....
 
418
    rotation is clockwise if angle > 0
317
419
*/
318
420
void
319
 
gc_item_rotate(GnomeCanvasItem *item, double angle) {
320
 
  double r[6],t[6], x1, x2, y1, y2;
321
 
 
322
 
  gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
323
 
  art_affine_translate( t , -(x2+x1)/2, -(y2+y1)/2 );
324
 
  art_affine_rotate( r, angle );
325
 
  art_affine_multiply( r, t, r);
326
 
  art_affine_translate( t , (x2+x1)/2, (y2+y1)/2 );
327
 
  art_affine_multiply( r, r, t);
328
 
 
329
 
  gnome_canvas_item_affine_absolute(item, r );
 
421
gc_item_rotate(GooCanvasItem *item, double angle) {
 
422
  GooCanvasBounds bounds;
 
423
  goo_canvas_item_get_bounds (item, &bounds);
 
424
  goo_canvas_item_rotate(item, angle,
 
425
                         bounds.x1+(bounds.x2-bounds.x1)/2,
 
426
                         bounds.y1+(bounds.y2-bounds.y1)/2);
330
427
}
331
428
 
332
429
/* As gnome does not implement its own API : gc_item_rotate_relative
333
430
   we have to do it ourselves ....
334
431
   IMPORTANT NOTE : This is designed for an item with "anchor" =  GTK_ANCHOR_CENTER
335
432
   rotation is clockwise if angle > 0
336
 
 */
 
433
*/
337
434
void
338
 
gc_item_rotate_relative(GnomeCanvasItem *item, double angle) {
 
435
gc_item_rotate_relative(GooCanvasItem *item, double angle)
 
436
{
339
437
  double x1, x2, y1, y2;
340
438
  double tx1, tx2, ty1, ty2;
341
439
  double cx, cy;
342
 
  double t;
343
 
  double r[6];
344
440
 
345
 
  //  gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
346
 
  /* WARNING: Do not use gnome_canvas_item_get_bounds which gives unpredictable results */
347
 
  if(GNOME_IS_CANVAS_LINE(item)) {
348
 
    GnomeCanvasPoints   *points;
349
 
    gtk_object_get (GTK_OBJECT (item), "points", &points, NULL);
 
441
  //  goo_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
 
442
  /* WARNING: Do not use goo_canvas_item_get_bounds which gives unpredictable results */
 
443
  if(GOO_IS_CANVAS_POLYLINE(item)) {
 
444
    GooCanvasPoints     *points;
 
445
    g_object_get (item, "points", &points, NULL);
350
446
    x1 = points->coords[0];
351
447
    y1 = points->coords[1];
352
448
    x2 = points->coords[2];
353
449
    y2 = points->coords[3];
354
 
  } else if(GNOME_IS_CANVAS_PIXBUF(item)){
355
 
    gtk_object_get (GTK_OBJECT (item), "x", &x1, NULL);
356
 
    gtk_object_get (GTK_OBJECT (item), "y", &y1, NULL);
357
 
    gtk_object_get (GTK_OBJECT (item), "width",  &x2, NULL);
358
 
    gtk_object_get (GTK_OBJECT (item), "height", &y2, NULL);
 
450
  } else if(GOO_IS_CANVAS_IMAGE(item)
 
451
            || GOO_IS_CANVAS_RECT(item)) {
 
452
    g_object_get (item, "x", &x1, NULL);
 
453
    g_object_get (item, "y", &y1, NULL);
 
454
    g_object_get (item, "width",  &x2, NULL);
 
455
    g_object_get (item, "height", &y2, NULL);
359
456
    x2 += x1;
360
457
    y2 += y1;
361
 
  } else if(GNOME_IS_CANVAS_GROUP(item)){
362
 
    gtk_object_get (GTK_OBJECT (item), "x", &x1, NULL);
363
 
    gtk_object_get (GTK_OBJECT (item), "y", &y1, NULL);
 
458
  } else if(GOO_IS_CANVAS_GROUP(item)){
 
459
    g_object_get (item, "x", &x1, NULL);
 
460
    g_object_get (item, "y", &y1, NULL);
364
461
    x2 = x1;
365
462
    y2 = y1;
366
463
  } else {
367
 
    gtk_object_get (GTK_OBJECT (item), "x1", &x1, NULL);
368
 
    gtk_object_get (GTK_OBJECT (item), "y1", &y1, NULL);
369
 
    gtk_object_get (GTK_OBJECT (item), "x2", &x2, NULL);
370
 
    gtk_object_get (GTK_OBJECT (item), "y2", &y2, NULL);
 
464
    g_assert(FALSE);
371
465
  }
372
466
 
373
467
  tx1 = x1;
384
478
  cx = (x2+x1)/2;
385
479
  cy = (y2+y1)/2;
386
480
 
387
 
  /* Taken from anim by Yves Combe
388
 
   * This matrix rotate around ( cx, cy )
389
 
   * This is the result of the product:
390
 
   *            T_{-c}             Rot (t)                 T_c
391
 
   *
392
 
   *       1    0   cx       cos(t) -sin(t)    0        1    0  -cx
393
 
   *       0    1   cy  by   sin(t)  cos(t)    0   by   0    1  -cy
394
 
   *       0    0    1         0       0       1        0    0   1
395
 
   */
396
 
 
397
 
  t = M_PI*angle/180.0;
398
 
 
399
 
  r[0] = cos(t);
400
 
  r[1] = sin(t);
401
 
  r[2] = -sin(t);
402
 
  r[3] = cos(t);
403
 
  r[4] = (1-cos(t))*cx + sin(t)*cy;
404
 
  r[5] = -sin(t)*cx + (1 - cos(t))*cy;
405
 
 
406
 
  gnome_canvas_item_affine_relative(item, r );
 
481
  goo_canvas_item_rotate(item, angle,
 
482
                         x1+(x2-x1)/2,
 
483
                         y1+(y2-y1)/2);
 
484
 
407
485
}
408
486
 
409
487
/** rotates an item around the center (x,y), relative to the widget's coordinates
 
488
 * Any previous transformation are reseted first.
410
489
 */
411
490
void
412
 
gc_item_rotate_with_center(GnomeCanvasItem *item, double angle, int x, int y) {
413
 
  double r[6],t[6], x1, x2, y1, y2, tx, ty;
414
 
 
415
 
  gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
416
 
  tx = x1 + x;
417
 
  ty = y1 + y;
418
 
  art_affine_translate( t , -tx, -ty );
419
 
  art_affine_rotate( r, angle );
420
 
  art_affine_multiply( r, t, r);
421
 
  art_affine_translate( t , tx, ty );
422
 
  art_affine_multiply( r, r, t);
423
 
 
424
 
  gnome_canvas_item_affine_absolute(item, r );
 
491
gc_item_rotate_with_center(GooCanvasItem *item, double angle, int x, int y)
 
492
{
 
493
  GooCanvasBounds bounds;
 
494
 
 
495
  goo_canvas_item_set_transform(item, NULL);
 
496
  goo_canvas_item_get_bounds( item, &bounds );
 
497
  goo_canvas_item_rotate(item, angle, bounds.x1+x, bounds.y1+y);
425
498
}
426
499
 
427
500
/** rotates an item around the center (x,y), relative to the widget's coordinates
428
501
 *  The rotation is relative to the previous rotation
429
502
 */
430
503
void
431
 
gc_item_rotate_relative_with_center(GnomeCanvasItem *item, double angle, int x, int y) {
432
 
  double r[6],t[6], x1, x2, y1, y2, tx, ty;
433
 
 
434
 
  gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
435
 
  tx = x1 + x;
436
 
  ty = y1 + y;
437
 
  art_affine_translate( t , -tx, -ty );
438
 
  art_affine_rotate( r, angle );
439
 
  art_affine_multiply( r, t, r);
440
 
  art_affine_translate( t , tx, ty );
441
 
  art_affine_multiply( r, r, t);
442
 
 
443
 
  gnome_canvas_item_affine_relative(item, r );
444
 
}
445
 
 
446
 
/**
447
 
 * Display the number of stars representing the difficulty level at the x,y location
448
 
 * The stars are created in a group 'parent'
449
 
 * The new group in which the stars are created is returned.
450
 
 * This is only usefull for the menu plugin and the configuration dialog box.
451
 
 */
452
 
GnomeCanvasGroup *gc_difficulty_display(GnomeCanvasGroup *parent,
453
 
                                                    double x, double y,
454
 
                                                    double ratio,
455
 
                                                    gint difficulty)
 
504
gc_item_rotate_relative_with_center(GooCanvasItem *item, double angle, int x, int y)
456
505
{
457
 
  GdkPixbuf *pixmap = NULL;
458
 
  GnomeCanvasGroup *stars_group = NULL;
459
 
  GnomeCanvasPixbuf *item = NULL;
460
 
  gchar *filename = NULL;
461
 
 
462
 
  if(difficulty==0 || difficulty>6)
463
 
    return NULL;
464
 
 
465
 
  filename = g_strdup_printf("difficulty_star%d.png", difficulty);
466
 
  pixmap   = gc_skin_pixmap_load(filename);
467
 
  g_free(filename);
468
 
 
469
 
  if(!pixmap)
470
 
    return NULL;
471
 
 
472
 
  stars_group = GNOME_CANVAS_GROUP(
473
 
                                  gnome_canvas_item_new (parent,
474
 
                                                         gnome_canvas_group_get_type (),
475
 
                                                         "x", (double) 0,
476
 
                                                         "y", (double) 0,
477
 
                                                         NULL));
478
 
 
479
 
  item = GNOME_CANVAS_PIXBUF(gnome_canvas_item_new (stars_group,
480
 
                                                    gnome_canvas_pixbuf_get_type (),
481
 
                                                    "pixbuf", pixmap,
482
 
                                                    "x", x,
483
 
                                                    "y", y,
484
 
                                                    "width", (double) gdk_pixbuf_get_width(pixmap) * ratio,
485
 
                                                    "height", (double) gdk_pixbuf_get_height(pixmap) * ratio,
486
 
                                                    "width_set", TRUE,
487
 
                                                    "height_set", TRUE,
488
 
                                                    NULL));
489
 
 
490
 
  gtk_signal_connect(GTK_OBJECT(item), "event",
491
 
                     (GtkSignalFunc) gc_item_focus_event,
492
 
                     NULL);
493
 
 
494
 
  gdk_pixbuf_unref(pixmap);
495
 
 
496
 
  return(stars_group);
 
506
  double x1, x2, y1, y2;
 
507
 
 
508
  if(GOO_IS_CANVAS_POLYLINE(item)) {
 
509
    GooCanvasPoints *points;
 
510
    g_object_get (item, "points", &points, NULL);
 
511
    x1 = points->coords[0];
 
512
    y1 = points->coords[1];
 
513
    x2 = points->coords[2];
 
514
    y2 = points->coords[3];
 
515
  } else if(GOO_IS_CANVAS_IMAGE(item) || GOO_IS_CANVAS_RECT(item)) {
 
516
    g_object_get (item, "x", &x1, NULL);
 
517
    g_object_get (item, "y", &y1, NULL);
 
518
    g_object_get (item, "width",  &x2, NULL);
 
519
    g_object_get (item, "height", &y2, NULL);
 
520
    x2 += x1 + (x2 - x1);
 
521
    y2 += y1 + (y2 - y1);
 
522
  } else if(GOO_IS_CANVAS_GROUP(item)){
 
523
    g_object_get (item, "x", &x1, NULL);
 
524
    g_object_get (item, "y", &y1, NULL);
 
525
    x2 = x1;
 
526
    y2 = y1;
 
527
  } else {
 
528
    g_object_get (item, "x1", &x1, NULL);
 
529
    g_object_get (item, "y1", &y1, NULL);
 
530
    g_object_get (item, "x2", &x2, NULL);
 
531
    g_object_get (item, "y2", &y2, NULL);
 
532
  }
 
533
 
 
534
  goo_canvas_item_rotate(item, angle, x1+x, y1+y);
497
535
}
498
536
 
499
537
gchar *g_utf8_strndup(gchar* utf8text, gint n)
500
538
{
501
 
 gchar* result;
502
 
 
503
 
 gint len = g_utf8_strlen(utf8text, -1);
504
 
 
505
 
 if( n < len && n > 0 )
506
 
   len = n;
507
 
 
508
 
 result = g_strndup(utf8text, g_utf8_offset_to_pointer(utf8text, len) - utf8text);
509
 
 
510
 
 return result;
 
539
  gchar* result;
 
540
 
 
541
  gint len = g_utf8_strlen(utf8text, -1);
 
542
 
 
543
  if( n < len && n > 0 )
 
544
    len = n;
 
545
 
 
546
  result = g_strndup(utf8text, g_utf8_offset_to_pointer(utf8text, len) - utf8text);
 
547
 
 
548
  return result;
511
549
}
512
550
 
513
551
/** \brief search a given relative file in all gcompris dir it could be found
537
575
  va_end (args);
538
576
 
539
577
  /* Check it's already found */
540
 
  if( g_file_test (filename, G_FILE_TEST_EXISTS))
541
 
    {
542
 
      return filename;
543
 
    }
 
578
  if( g_file_test (filename, G_FILE_TEST_EXISTS) )
 
579
    return filename;
544
580
 
545
581
  /*
546
582
   * Search it on the file system
550
586
        dir_to_search[i++] = "";
551
587
  dir_to_search[i++] = properties->user_dir;
552
588
  dir_to_search[i++] = properties->package_data_dir;
 
589
  dir_to_search[i++] = properties->package_skin_dir;
553
590
  dir_to_search[i++] = NULL;
554
591
 
555
592
  absolute_filename = g_strdup(filename);
576
613
              g_free(filename2);
577
614
              goto FOUND;
578
615
            }
579
 
      g_free(absolute_filename);
580
 
          /* Now check if this file is on the net */
581
 
          if((absolute_filename = gc_net_get_url_from_file(filename2, NULL)))
582
 
            {
583
 
              g_strfreev(tmp);
584
 
              g_free(filename2);
585
 
              goto FOUND;
586
 
            }
587
 
 
588
 
      g_free(filename2);
589
 
      g_free(absolute_filename);
 
616
          g_free(filename2);
590
617
          /* Try the short locale */
591
618
          if(g_strv_length(tmp)>1)
592
619
            {
593
620
              locale[2] = '\0';
594
621
              filename2 = g_strjoinv(locale, tmp);
595
622
              g_strfreev(tmp);
 
623
              g_free(absolute_filename);
596
624
              absolute_filename = g_strdup_printf("%s/%s", dir_to_search[i], filename2);
597
625
              if(g_file_test (absolute_filename, G_FILE_TEST_EXISTS))
598
626
                {
599
627
                  g_free(filename2);
600
628
                  goto FOUND;
601
629
                }
602
 
              g_free(absolute_filename);
603
 
 
604
 
              /* Now check if this file is on the net */
605
 
              if((absolute_filename = gc_net_get_url_from_file(filename2, NULL)))
606
 
                {
607
 
                  g_free(filename2);
608
 
                  goto FOUND;
609
 
                }
610
 
        g_free(filename2);
 
630
              g_free(filename2);
611
631
 
612
632
            }
613
 
      else
614
 
          g_strfreev(tmp);
 
633
          else
 
634
            g_strfreev(tmp);
615
635
        }
616
636
      else
617
637
        {
619
639
 
620
640
          if(g_file_test (absolute_filename, G_FILE_TEST_EXISTS))
621
641
            goto FOUND;
622
 
    g_free(absolute_filename);
623
 
          /* Now check if this file is on the net */
624
 
          if((absolute_filename = gc_net_get_url_from_file(filename, NULL)))
625
 
            goto FOUND;
626
 
      g_free(absolute_filename);
627
642
        }
628
643
 
629
644
      i++;
635
650
 
636
651
 FOUND:
637
652
  g_free(filename);
638
 
  return absolute_filename;
 
653
  char *abs_name = realpath(absolute_filename, NULL);
 
654
  g_free(absolute_filename);
 
655
  return abs_name;
639
656
}
640
657
 
641
658
gchar*
701
718
  gc_sound_play_ogg(str, NULL);
702
719
  g_free(str);
703
720
}
 
721
 
 
722
/** Display a button with the given text
 
723
 *
 
724
 * \param x the x coordinate of the button
 
725
 * \param y the y coordinate of the button
 
726
 * \param button_file the image file to use as the button
 
727
 * \param text is the text to display in the button
 
728
 * \param process is the callback function
 
729
 * \param data is the user data passed to the callback function
 
730
 *
 
731
 * \return void
 
732
 */
 
733
void
 
734
gc_util_button_text(GooCanvasItem *rootitem,
 
735
                    guint x, guint y,
 
736
                    char *button_file,
 
737
                    char *text,
 
738
                    GtkSignalFunc process,
 
739
                    gpointer data)
 
740
{
 
741
  GdkPixbuf *pixmap;
 
742
  GooCanvasItem *item;
 
743
  GooCanvasItem *item_text;
 
744
 
 
745
  /* The Button */
 
746
  pixmap = gc_skin_pixmap_load(button_file);
 
747
  item = goo_canvas_image_new (rootitem,
 
748
                               pixmap,
 
749
                               x,
 
750
                               y,
 
751
                               NULL);
 
752
  g_signal_connect(item,
 
753
                   "button_press_event",
 
754
                   (GtkSignalFunc) process, data);
 
755
  gc_item_focus_init(item, NULL);
 
756
 
 
757
  /* The Text */
 
758
  item_text =
 
759
    goo_canvas_text_new (rootitem,
 
760
                         text,
 
761
                         x + (double)gdk_pixbuf_get_width(pixmap)/2,
 
762
                         y + 24,
 
763
                         -1,
 
764
                         GTK_ANCHOR_CENTER,
 
765
                         "font", gc_skin_font_board_small,
 
766
                         "fill_color_rgba", gc_skin_color_text_button,
 
767
                         NULL);
 
768
  g_signal_connect(item_text,
 
769
                   "button_press_event",
 
770
                   process, data);
 
771
  gc_item_focus_init(item_text, item);
 
772
  gdk_pixbuf_unref(pixmap);
 
773
}
 
774
 
 
775
/** Display a button with the given text (BY SKIN'S SVG ID)
 
776
 *
 
777
 * \param x the x coordinate of the button
 
778
 * \param y the y coordinate of the button
 
779
 * \param button_file the image file to use as the button
 
780
 * \param text is the text to display in the button
 
781
 * \param process is the callback function
 
782
 * \param data is the user data passed to the callback function
 
783
 *
 
784
 * \return void
 
785
 */
 
786
void
 
787
gc_util_button_text_svg(GooCanvasItem *rootitem,
 
788
                        guint x, guint y,
 
789
                        char *button_id,
 
790
                        char *text,
 
791
                        GtkSignalFunc process,
 
792
                        gpointer data)
 
793
{
 
794
  GooCanvasItem *item;
 
795
  GooCanvasItem *item_text;
 
796
 
 
797
  /* The Button */
 
798
  item = goo_canvas_svg_new (rootitem,
 
799
                             gc_skin_rsvg_get(),
 
800
                             "svg-id", button_id,
 
801
                             "autocrop", TRUE,
 
802
                             NULL);
 
803
  SET_ITEM_LOCATION_CENTER(item, x, y);
 
804
 
 
805
  g_signal_connect(item,
 
806
                   "button_press_event",
 
807
                   (GtkSignalFunc) process, data);
 
808
  gc_item_focus_init(item, NULL);
 
809
 
 
810
  /* The Text */
 
811
  item_text =
 
812
    goo_canvas_text_new (rootitem,
 
813
                         text,
 
814
                         x,
 
815
                         y,
 
816
                         -1,
 
817
                         GTK_ANCHOR_CENTER,
 
818
                         "font", gc_skin_font_board_small,
 
819
                         "fill_color_rgba", gc_skin_color_text_button,
 
820
                         NULL);
 
821
  g_signal_connect(item_text,
 
822
                   "button_press_event",
 
823
                   process, data);
 
824
  gc_item_focus_init(item_text, item);
 
825
}