~andrewsomething/imagination/debian

« back to all changes in this revision

Viewing changes to src/support.c

  • Committer: Andrew Starr-Bochicchio
  • Date: 2009-09-29 23:38:39 UTC
  • mfrom: (1.1.2)
  • Revision ID: a.starr.b@gmail.com-20090929233839-ucjnl2f35kw5fbx8
Tags: 2.0-1
* New upstream release. (Closes: #543218).
* debian/control: Build-depend on xsltproc, docbook-xsl, quilt,
  and doc-base.
* debian/imagination.doc-base: Register docs.
* debian/patches/10_link_math_lib.patch:
 - Add '-lm' to link to the math lib.
* debian/README.source: Explain quilt.
* debian/rules: Add quilt magic.

Show diffs side-by-side

added added

removed removed

Lines of Context:
91
91
void img_set_statusbar_message(img_window_struct *img_struct, gint selected)
92
92
{
93
93
        gchar *message = NULL;
 
94
        gchar *total_slides = NULL;
94
95
 
95
96
        if (img_struct->slides_nr == 0)
96
97
        {
97
98
                message = g_strdup_printf(_("Welcome to Imagination - %d transitions loaded."),img_struct->nr_transitions_loaded);
98
99
                gtk_statusbar_push(GTK_STATUSBAR(img_struct->statusbar),img_struct->context_id,message);
99
100
                g_free(message);
 
101
                gtk_label_set_text(GTK_LABEL(img_struct->total_slide_number_label),NULL);
100
102
        }
101
103
        else if (selected)
102
104
        {
106
108
        }
107
109
        else
108
110
        {
 
111
                total_slides = g_strdup_printf("%d",img_struct->slides_nr);
 
112
                gtk_label_set_text(GTK_LABEL(img_struct->total_slide_number_label),total_slides);
109
113
                message = g_strdup_printf(ngettext("%d slide imported %s" ,"%d slides imported %s",img_struct->slides_nr),img_struct->slides_nr,_(" - Use the CTRL key to select/unselect or SHIFT for multiple select"));
110
114
                gtk_statusbar_push(GTK_STATUSBAR(img_struct->statusbar),img_struct->context_id,message);
 
115
                g_free(total_slides);
111
116
                g_free(message);
112
117
        }
113
118
}
118
123
        const gchar   *transition_name;
119
124
        gchar         *fname = NULL, *name, *filename;
120
125
        gchar        **trans, **bak;
121
 
        GError       **error = NULL;
122
126
        GModule       *module;
123
127
        GdkPixbuf     *pixbuf;
124
128
        GtkTreeIter    piter, citer;
146
150
        /* Search all paths listed in array */
147
151
        for( path = search_paths; *path; path++ )
148
152
        {
149
 
                /* I removed error from here since it hasn't been used and leaks away */
150
 
                dir = g_dir_open(*path, 0, NULL);
 
153
                dir = g_dir_open( *path, 0, NULL );
151
154
                if( dir == NULL )
152
155
                {
153
156
                        g_free( *path );
157
160
                while( TRUE )
158
161
                {
159
162
                        transition_name = g_dir_read_name( dir );
160
 
                        if (transition_name == NULL)
 
163
                        if ( transition_name == NULL )
161
164
                                break;
162
165
                        
163
 
                        fname = g_build_filename(*path, transition_name, NULL);
164
 
                        module = g_module_open(fname, G_MODULE_BIND_LOCAL);
165
 
                        if (module && img_plugin_is_loaded(img, module) == FALSE)
 
166
                        fname = g_build_filename( *path, transition_name, NULL );
 
167
                        module = g_module_open( fname, G_MODULE_BIND_LOCAL );
 
168
                        if( module && img_plugin_is_loaded(img, module) == FALSE )
166
169
                        {
167
170
                                /* Obtain the name from the plugin function */
168
171
                                g_module_symbol( module, "img_get_plugin_info",
169
172
                                                                 (void *)&plugin_set_name);
170
 
                                plugin_set_name(&name, &trans);
 
173
                                plugin_set_name( &name, &trans );
171
174
                                
172
175
                                /* Add group name to the store */
173
176
                                gtk_tree_store_append( model, &piter, NULL );
196
199
                                                g_free( filename );
197
200
                                                filename =
198
201
                                                        g_strdup_printf( "%s/.imagination/pixmaps/imagination-%d.png",
199
 
                                                                                         g_get_home_dir(), GPOINTER_TO_INT( trans[2] ) );
 
202
                                                                                         g_get_home_dir(),
 
203
                                                                                         GPOINTER_TO_INT( trans[2] ) );
200
204
                                                pixbuf = gdk_pixbuf_new_from_file( filename, NULL );
201
205
                                        }
202
 
                                        g_free(filename);
 
206
                                        g_free( filename );
203
207
                                        g_module_symbol( module, trans[1], &address );
204
208
                                        gtk_tree_store_append( model, &citer, &piter );
205
 
                                        gtk_tree_store_set( model, &citer, 0, pixbuf, 1, trans[0], 2, address, 3, GPOINTER_TO_INT( trans[2] ), -1 );
206
 
                                img->nr_transitions_loaded++;
 
209
                                        gtk_tree_store_set( model, &citer, 0, pixbuf,
 
210
                                                                                                           1, trans[0],
 
211
                                                                                                           2, address,
 
212
                                                                                                           3, GPOINTER_TO_INT( trans[2] ),
 
213
                                                                                                           -1 );
 
214
                                        img->nr_transitions_loaded++;
207
215
                                }
208
216
                                g_free( bak );
209
217
                        }
210
 
                        g_free(fname);
 
218
                        g_free( fname );
211
219
                }
212
 
                g_free(*path);
213
 
                g_dir_close(dir);
 
220
                g_free( *path );
 
221
                g_dir_close( dir );
214
222
        }
215
223
}
216
224
 
245
253
        gtk_widget_destroy(file_selector);
246
254
}
247
255
 
248
 
GdkPixbuf *img_load_pixbuf_from_file(gchar *filename)
249
 
{
250
 
        GdkPixbuf *thumb = NULL;
251
 
 
252
 
        thumb = gdk_pixbuf_new_from_file_at_scale(filename, 93, 70, TRUE, NULL);
253
 
        return thumb;
254
 
}
255
 
 
256
 
slide_struct *img_set_slide_info(gint duration, guint speed, void (*render), gint transition_id, gchar *path, gchar *filename)
257
 
{
258
 
        slide_struct *slide_info = NULL;
259
 
        GdkPixbufFormat *pixbuf_format;
260
 
        gint width,height;
261
 
 
262
 
        slide_info = g_new0(slide_struct,1);
263
 
        if (slide_info)
264
 
        {
265
 
                slide_info->duration = duration;
266
 
                slide_info->speed = speed;
267
 
                slide_info->render = render;
268
 
                slide_info->transition_id = transition_id;
269
 
                slide_info->path = g_strdup( path );
270
 
                slide_info->filename = g_strdup(filename);
271
 
                pixbuf_format = gdk_pixbuf_get_file_info(filename,&width,&height);
272
 
                slide_info->resolution = g_strdup_printf("%d x %d",width,height);
273
 
                slide_info->type = gdk_pixbuf_format_get_name(pixbuf_format);
274
 
        }
275
 
        return slide_info;
 
256
slide_struct *
 
257
img_create_new_slide( void )
 
258
{
 
259
        slide_struct    *slide = NULL;
 
260
 
 
261
        slide = g_slice_new0( slide_struct );
 
262
        if( slide )
 
263
        {
 
264
                /* Still part */
 
265
                slide->duration = 1;
 
266
 
 
267
                /* Transition */
 
268
                slide->path = g_strdup( "0" );
 
269
                slide->transition_id = -1;
 
270
                slide->speed = NORMAL;
 
271
 
 
272
                /* Ken Burns */
 
273
                slide->cur_point = -1;
 
274
 
 
275
                /* Subtitles */
 
276
                slide->anim_duration = 1;
 
277
                slide->position = IMG_SUB_POS_MIDDLE_CENTER;
 
278
                slide->placing = IMG_REL_PLACING_EXPORTED_VIDEO;
 
279
                slide->font_desc = pango_font_description_from_string( "Sans 12" );
 
280
                slide->font_color[0] = 0; /* R */
 
281
                slide->font_color[1] = 0; /* G */
 
282
                slide->font_color[2] = 0; /* B */
 
283
                slide->font_color[3] = 1; /* A */
 
284
        }
 
285
 
 
286
        return( slide );
 
287
}
 
288
 
 
289
void
 
290
img_set_slide_file_info( slide_struct *slide,
 
291
                                                 const gchar  *filename )
 
292
{
 
293
        GdkPixbufFormat *format;
 
294
        gint             width,
 
295
                                         height;
 
296
 
 
297
        format = gdk_pixbuf_get_file_info( filename, &width, &height );
 
298
 
 
299
        slide->filename = g_strdup( filename );
 
300
        slide->original_filename = NULL;
 
301
        
 
302
        slide->resolution = g_strdup_printf( "%d x %d", width, height );
 
303
        slide->type = gdk_pixbuf_format_get_name( format );
 
304
}
 
305
 
 
306
void
 
307
img_set_slide_gradient_info( slide_struct *slide,
 
308
                                                         gint          gradient,
 
309
                                                         gdouble      *start_color,
 
310
                                                         gdouble      *stop_color,
 
311
                                                         gdouble      *start_point,
 
312
                                                         gdouble      *stop_point )
 
313
{
 
314
        gint i;
 
315
 
 
316
        slide->gradient = gradient;
 
317
        for( i = 0; i < 3; i++ )
 
318
        {
 
319
                slide->g_start_color[i] = start_color[i];
 
320
                slide->g_stop_color[i]  = stop_color[i];
 
321
        }
 
322
        for( i = 0; i < 2; i++ )
 
323
        {
 
324
                slide->g_start_point[i] = start_point[i];
 
325
                slide->g_stop_point[i]  = stop_point[i];
 
326
        }
 
327
}
 
328
 
 
329
void
 
330
img_set_slide_still_info( slide_struct      *slide,
 
331
                                                  gint               duration,
 
332
                                                  img_window_struct *img )
 
333
{
 
334
        if( slide->duration != duration )
 
335
        {
 
336
                slide->duration = duration;
 
337
 
 
338
                if( ! img->total_dur_id )
 
339
                        img->total_dur_id =
 
340
                                g_idle_add( (GSourceFunc)img_set_total_slideshow_duration, img );
 
341
        }
 
342
}
 
343
 
 
344
void
 
345
img_set_slide_transition_info( slide_struct      *slide,
 
346
                                                           GtkListStore      *store,
 
347
                                                           GtkTreeIter       *iter,
 
348
                                                           GdkPixbuf         *pix,
 
349
                                                           const gchar       *path,
 
350
                                                           gint               transition_id,
 
351
                                                           ImgRender          render,
 
352
                                                           guint              speed,
 
353
                                                           img_window_struct *img )
 
354
{
 
355
        /* Set transition render. */
 
356
        if( path && ( slide->transition_id != transition_id ) )
 
357
        {
 
358
                if( slide->path )
 
359
                        g_free( slide->path );
 
360
 
 
361
                slide->path = g_strdup( path );
 
362
                slide->transition_id = transition_id;
 
363
                slide->render = render;
 
364
 
 
365
                gtk_list_store_set( store, iter, 2, pix, -1 );
 
366
        }
 
367
 
 
368
        if( speed && ( slide->speed != speed ) )
 
369
        {
 
370
                slide->speed = speed;
 
371
 
 
372
                if( ! img->total_dur_id )
 
373
                        img->total_dur_id =
 
374
                                g_idle_add( (GSourceFunc)img_set_total_slideshow_duration, img );
 
375
        }
 
376
}
 
377
 
 
378
void
 
379
img_set_slide_ken_burns_info( slide_struct *slide,
 
380
                                                          gint          cur_point,
 
381
                                                          gsize         length,
 
382
                                                          gdouble      *points )
 
383
{
 
384
        ImgStopPoint *point;
 
385
        gint          i,
 
386
                                  full;
 
387
 
 
388
        if( slide->no_points )
 
389
        {
 
390
                g_list_free( slide->points );
 
391
                slide->no_points = 0;
 
392
        }
 
393
 
 
394
        for( i = 0; i < length; i += 4 )
 
395
        {
 
396
                /* Create new point */
 
397
                point = g_slice_new( ImgStopPoint );
 
398
                point->time = (gint)( points[0 + i] + 0.5 );
 
399
                point->offx = points[1 + i];
 
400
                point->offy = points[2 + i];
 
401
                point->zoom = points[3 + i];
 
402
                
 
403
                /* Append it to the list */
 
404
                slide->points = g_list_append( slide->points, point );
 
405
                slide->no_points++;
 
406
        }
 
407
 
 
408
        slide->cur_point = CLAMP( cur_point, -1, slide->no_points - 1 );
 
409
 
 
410
        full = img_calc_slide_duration_points( slide->points,
 
411
                                                                                   slide->no_points );
 
412
        if( full )
 
413
                slide->duration = full;
 
414
}
 
415
 
 
416
void
 
417
img_set_slide_text_info( slide_struct      *slide,
 
418
                                                 GtkListStore      *store,
 
419
                                                 GtkTreeIter       *iter,
 
420
                                                 const gchar       *subtitle,
 
421
                                                 gint               anim_id,
 
422
                                                 gint               anim_duration,
 
423
                                                 gint               position,
 
424
                                                 gint               placing,
 
425
                                                 const gchar       *font_desc,
 
426
                                                 gdouble           *font_color,
 
427
                                                 img_window_struct *img )
 
428
{
 
429
        /* Set the slide text info parameters */
 
430
        if( store && iter )
 
431
        {
 
432
                gboolean flag;
 
433
 
 
434
                if( slide->subtitle )
 
435
                        g_free( slide->subtitle );
 
436
                slide->subtitle = g_strdup( subtitle );
 
437
 
 
438
                flag = ( subtitle ? TRUE : FALSE );
 
439
                gtk_list_store_set( store, iter, 3, flag, -1 );
 
440
        }
 
441
 
 
442
        if( ( anim_id > -1 ) && ( anim_id != slide->anim_id ) )
 
443
        {
 
444
                GtkTreeModel *model;
 
445
                gchar        *path;
 
446
                GtkTreeIter   iter;
 
447
 
 
448
                path = g_strdup_printf( "%d", anim_id );
 
449
                model = gtk_combo_box_get_model( GTK_COMBO_BOX( img->sub_anim ) );
 
450
                gtk_tree_model_get_iter_from_string( model, &iter, path );
 
451
                g_free( path );
 
452
 
 
453
                slide->anim_id = anim_id;
 
454
                gtk_tree_model_get( model, &iter, 1, &slide->anim, -1 );
 
455
 
 
456
                /* Sync timings */
 
457
                img_sync_timings( slide, img );
 
458
        }
 
459
 
 
460
        if( ( anim_duration > 0 ) && ( anim_duration != slide->anim_duration ) )
 
461
        {
 
462
                slide->anim_duration = anim_duration;
 
463
 
 
464
                /* Synchronize timings */
 
465
                img_sync_timings( slide, img );
 
466
        }
 
467
 
 
468
        if( ( position > -1 ) && ( position != slide->position ) )
 
469
                slide->position = position;
 
470
 
 
471
        if( ( placing > -1 ) && ( placing != slide->placing ) )
 
472
                slide->placing = placing;
 
473
 
 
474
        if( font_desc )
 
475
        {
 
476
                if( slide->font_desc )
 
477
                        pango_font_description_free( slide->font_desc );
 
478
                slide->font_desc = pango_font_description_from_string( font_desc );
 
479
        }
 
480
 
 
481
        if( font_color )
 
482
        {
 
483
                slide->font_color[0] = font_color[0];
 
484
                slide->font_color[1] = font_color[1];
 
485
                slide->font_color[2] = font_color[2];
 
486
                slide->font_color[3] = font_color[3];
 
487
        }
 
488
}                                                               
 
489
 
 
490
void
 
491
img_free_slide_struct( slide_struct *entry )
 
492
{
 
493
        GList *tmp;
 
494
 
 
495
        if (entry->original_filename)
 
496
                g_free(entry->original_filename);
 
497
        g_free(entry->filename);
 
498
        g_free(entry->resolution);
 
499
        g_free(entry->type);
 
500
        
 
501
        /* Free stop point list */
 
502
        for( tmp = entry->points; tmp; tmp = g_list_next( tmp ) )
 
503
                g_slice_free( ImgStopPoint, tmp->data );
 
504
        g_list_free( entry->points );
 
505
 
 
506
        g_slice_free( slide_struct, entry );
 
507
}
 
508
 
 
509
gboolean
 
510
img_set_total_slideshow_duration( img_window_struct *img )
 
511
{
 
512
        gchar        *time;
 
513
        GtkTreeIter   iter;
 
514
        slide_struct *entry;
 
515
        GtkTreeModel *model;
 
516
 
 
517
        img->total_secs = 0;
 
518
 
 
519
        model = GTK_TREE_MODEL( img->thumbnail_model );
 
520
        if( gtk_tree_model_get_iter_first( model, &iter ) )
 
521
        {
 
522
                do
 
523
                {
 
524
                        gtk_tree_model_get( model, &iter, 1, &entry, -1 );
 
525
                        img->total_secs += entry->duration;
 
526
                        
 
527
                        if(entry->render)
 
528
                                img->total_secs += entry->speed;
 
529
                }
 
530
                while( gtk_tree_model_iter_next( model, &iter ) );
 
531
 
 
532
                /* Add time of last pseudo slide */
 
533
                if( img->final_transition.render )
 
534
                        img->total_secs += img->final_transition.speed;
 
535
        }
 
536
                
 
537
        time = img_convert_seconds_to_time(img->total_secs);
 
538
        gtk_label_set_text(GTK_LABEL (img->total_time_data),time);
 
539
        g_free(time);
 
540
 
 
541
        /* This is here only to be able to add this to idle source. */
 
542
        img->total_dur_id = 0;
 
543
        return( FALSE );
 
544
}
 
545
 
 
546
gint
 
547
img_calc_slide_duration_points( GList *list,
 
548
                                                                gint   length )
 
549
{
 
550
        GList        *tmp;
 
551
        gint          i, duration = 0;
 
552
        ImgStopPoint *point;
 
553
 
 
554
        /* If we have no points, return 0 */
 
555
        if( length == 0 )
 
556
                return( 0 );
 
557
 
 
558
        /* Calculate length */
 
559
        for( tmp = list, i = 0; i < length; tmp = g_list_next( tmp ), i++ )
 
560
        {
 
561
                point = (ImgStopPoint *)tmp->data;
 
562
                duration += point->time;
 
563
        }
 
564
 
 
565
        return( duration );
 
566
}
 
567
 
 
568
/*
 
569
 * img_scale_image:
 
570
 *
 
571
 * This function should be called for all image loading needs. It'll properly
 
572
 * scale and trim loaded images, add borders if needed and return surface or
 
573
 * pixbuf of requested size.
 
574
 *
 
575
 * If one of the size requests is 0, the other one will be calculated from
 
576
 * first one with aspect ratio calculation. If both dimensions are 0, image
 
577
 * will be loaded from disk at original size (this is mainly used for export,
 
578
 * when we want to have images at their best quality).
 
579
 *
 
580
 * Return value: TRUE if image loading succeded, FALSE otherwise.
 
581
 */
 
582
gboolean
 
583
img_scale_image( const gchar      *filename,
 
584
                                 gdouble           ratio,
 
585
                                 gint              width,
 
586
                                 gint              height,
 
587
                                 gboolean          distort,
 
588
                                 gdouble          *color,
 
589
                                 GdkPixbuf       **pixbuf,
 
590
                                 cairo_surface_t **surface )
 
591
{
 
592
        GdkPixbuf *loader;             /* Pixbuf used for loading */
 
593
        gint       i_width, i_height;  /* Image dimensions */
 
594
        gint       offset_x, offset_y; /* Offset values for borders */
 
595
        gdouble    i_ratio;            /* Export and image aspect ratios */
 
596
        gdouble    skew;               /* Transformation between ratio and
 
597
                                                                                         i_ratio */
 
598
        gboolean   transform = FALSE;  /* Flag that controls scalling */
 
599
 
 
600
        /* MAximal distortion values */
 
601
        gdouble max_stretch = 0.1280;
 
602
        gdouble max_crop    = 0.8500;
 
603
 
 
604
        /* Borderline skew values */
 
605
        gdouble max_skew = ( 1 + max_stretch ) / max_crop;
 
606
        gdouble min_skew = ( 1 - max_stretch ) * max_crop;
 
607
 
 
608
        /* Obtain information about image being loaded */
 
609
        if( ! gdk_pixbuf_get_file_info( filename, &i_width, &i_height ) )
 
610
                return( FALSE );
 
611
 
 
612
        /* How distorted images would be if we scaled them */
 
613
        i_ratio = (gdouble)i_width / i_height;
 
614
        skew = ratio / i_ratio;
 
615
 
 
616
        /* Calculationg surface dimensions.
 
617
         *
 
618
         * In order to be as flexible as possible, this function can load images at
 
619
         * various sizes, but at aspect ration that matches the aspect ratio of main
 
620
         * preview area. How size is determined? If width argument is not -1, this
 
621
         * is taken as a reference dimension from which height is calculated (if
 
622
         * height argument also present, it's ignored). If width argument is -1,
 
623
         * height is taken as a reference dimension. If both width and height are
 
624
         * -1, surface dimensions are calculated to to fit original image.
 
625
         */
 
626
        if( width > 0 )
 
627
        {
 
628
                /* Calculate height according to width */
 
629
                height = width / ratio;
 
630
        }
 
631
        else if( height > 0 )
 
632
        {
 
633
                /* Calculate width from height */
 
634
                width = height * ratio;
 
635
        }
 
636
        else
 
637
        {
 
638
                /* Load image at maximum quality
 
639
                 *
 
640
                 * If the user doesn't want to have distorted images, we create slightly
 
641
                 * bigger surface that will hold borders too.
 
642
                 *
 
643
                 * If images should be distorted, we first check if we're able to fit
 
644
                 * image without distorting it too much. If images would be largely
 
645
                 * distorted, we simply load them undistorted.
 
646
                 *
 
647
                 * If we came all the way to  here, then we're able to distort image.
 
648
                 */
 
649
                if( ( ! distort )       || /* Don't distort */
 
650
                        ( skew > max_skew ) || /* Image is too wide */
 
651
                        ( skew < min_skew )  ) /* Image is too tall */
 
652
                {
 
653
                        /* User doesn't want images to be distorted or distortion would be
 
654
                         * too intrusive. */
 
655
                        if( ratio < i_ratio )
 
656
                        {
 
657
                                /* Borders will be added on left and right */
 
658
                                width = i_width;
 
659
                                height = width / ratio;
 
660
                        }
 
661
                        else
 
662
                        {
 
663
                                /* Borders will be added on top and bottom */
 
664
                                height = i_height;
 
665
                                width = height * ratio;
 
666
                        }
 
667
                }
 
668
                else
 
669
                {
 
670
                        /* User wants images to be distorted and we're able to do it
 
671
                         * without ruining images. */
 
672
                        if( ratio < i_ratio )
 
673
                        {
 
674
                                /* Image will be distorted horizontally */
 
675
                                height = i_height;
 
676
                                width = height * ratio;
 
677
                        }
 
678
                        else
 
679
                        {
 
680
                                /* Image will be distorted vertically */
 
681
                                width = i_width;
 
682
                                height = width / ratio;
 
683
                        }
 
684
                }
 
685
        }
 
686
 
 
687
        /* Will image be disotrted?
 
688
         *
 
689
         * Conditions:
 
690
         *  - user allows us to do it
 
691
         *  - skew is in sensible range
 
692
         *  - image is not smaller than exported wideo size
 
693
         */
 
694
        transform = distort && skew < max_skew && skew > min_skew &&
 
695
                                ( i_width >= width || i_height >= height );
 
696
 
 
697
        /* Load image into pixbuf at proper size */
 
698
        if( transform )
 
699
        {
 
700
                gint lw, lh;
 
701
 
 
702
                /* Images will be loaded at slightly modified dimensions */
 
703
                if( ratio < i_ratio )
 
704
                {
 
705
                        /* Horizontal scaling */
 
706
                        lw = (gdouble)width / ( skew + 1 ) * 2;
 
707
                        lh = height;
 
708
                }
 
709
                else
 
710
                {
 
711
                        /* Vertical scaling */
 
712
                        lw = width;
 
713
                        lh = (gdouble)height * ( skew + 1 ) / 2;
 
714
                }
 
715
                loader = gdk_pixbuf_new_from_file_at_scale( filename, lw, lh,
 
716
                                                                                                        FALSE, NULL );
 
717
        }
 
718
        else
 
719
        {
 
720
                /* Simply load image into pixbuf at size */
 
721
                loader = gdk_pixbuf_new_from_file_at_size( filename, width,
 
722
                                                                                                   height, NULL );
 
723
        }
 
724
        if( ! loader )
 
725
                return( FALSE );
 
726
 
 
727
        i_width  = gdk_pixbuf_get_width( loader );
 
728
        i_height = gdk_pixbuf_get_height( loader );
 
729
 
 
730
        /* Calculate offsets */
 
731
        offset_x = ( width - i_width ) / 2;   /* CAN BE NEGATIVE!!! */
 
732
        offset_y = ( height - i_height ) / 2; /* CAN BE NEGATIVE!!! */
 
733
 
 
734
        /* Prepare output
 
735
         *
 
736
         * We can give two different output formats: cairo_surface_t and GdkPixbuf.
 
737
         */
 
738
        if( pixbuf )
 
739
        {
 
740
                /* Create new pixbuf with loaded image */
 
741
                GdkPixbuf *tmp_pix;   /* Pixbuf used for loading */
 
742
                guint32    tmp_color; /* Background color */
 
743
 
 
744
                tmp_color = ( (gint)( color[0] * 0xff ) << 24 ) |
 
745
                                        ( (gint)( color[1] * 0xff ) << 16 ) |
 
746
                                        ( (gint)( color[2] * 0xff ) <<  8 );
 
747
                tmp_pix = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, width, height );
 
748
                gdk_pixbuf_fill( tmp_pix, tmp_color );
 
749
                gdk_pixbuf_composite( loader, tmp_pix,
 
750
                                                          MAX( 0, offset_x ), MAX( 0, offset_y ),
 
751
                                                          MIN( i_width, width ), MIN( i_height, height ),
 
752
                                                          offset_x, offset_y, 1, 1,
 
753
                                                          GDK_INTERP_BILINEAR, 255 );
 
754
 
 
755
                *pixbuf = tmp_pix;
 
756
        }
 
757
        if( surface )
 
758
        {
 
759
                /* Paint surface with loaded image
 
760
                 * 
 
761
                 * If image cannot be scalled, transform is FALSE. In this case, just
 
762
                 * borders are added. If transform is not 0, than scale image before
 
763
                 * painting it. */
 
764
                cairo_t         *cr;       /* Cairo, used to transform image */
 
765
                cairo_surface_t *tmp_surf; /* Surface to draw on */
 
766
 
 
767
                /* Create image surface with proper dimensions */
 
768
                tmp_surf = cairo_image_surface_create( CAIRO_FORMAT_RGB24,
 
769
                                                                                           width, height );
 
770
 
 
771
                cr = cairo_create( tmp_surf );
 
772
                
 
773
                if( ! transform )
 
774
                {
 
775
                        /* Fill with background color */
 
776
                        cairo_set_source_rgb( cr, color[0], color[1], color[2] );
 
777
                        cairo_paint( cr );
 
778
                }
 
779
                
 
780
                /* Paint image */
 
781
                gdk_cairo_set_source_pixbuf( cr, loader, offset_x, offset_y );
 
782
                cairo_paint( cr );
 
783
                
 
784
                cairo_destroy( cr );
 
785
 
 
786
                /* Return surface */
 
787
                *surface = tmp_surf;
 
788
        }
 
789
 
 
790
        /* Free temporary pixbuf */
 
791
        g_object_unref( G_OBJECT( loader ) );
 
792
 
 
793
        return( TRUE );
 
794
}
 
795
 
 
796
void
 
797
img_set_project_mod_state( img_window_struct *img,
 
798
                                                   gboolean           modified )
 
799
{
 
800
        if( ( img->project_is_modified ? modified : ! modified ) )
 
801
                return;
 
802
 
 
803
        img->project_is_modified = modified;
 
804
 
 
805
        /* FIXME: Do any updates here (add "*" to window title, ...). */
 
806
}
 
807
 
 
808
void
 
809
img_sync_timings( slide_struct      *slide,
 
810
                                  img_window_struct *img )
 
811
{
 
812
        /* If times are already synchronized, return */
 
813
        if( slide->duration >= slide->anim_duration )
 
814
                return;
 
815
 
 
816
        /* Do the right thing;) */
 
817
        if( slide->no_points )
 
818
        {
 
819
                gint          diff;
 
820
                ImgStopPoint *point;
 
821
 
 
822
                /* Calculate difference that we need to accomodate */
 
823
                diff = slide->anim_duration - slide->duration;
 
824
 
 
825
                /* Elongate last point */
 
826
                point = (ImgStopPoint *)g_list_last( slide->points )->data;
 
827
                point->time += diff;
 
828
                
 
829
                /* Update Ken Burns display */
 
830
                gtk_spin_button_set_value( GTK_SPIN_BUTTON( img->ken_duration ),
 
831
                                                                   point->time );
 
832
        }
 
833
 
 
834
        /* Update display */
 
835
        gtk_spin_button_set_value( GTK_SPIN_BUTTON( img->duration ),
 
836
                                                           slide->anim_duration );
 
837
}
 
838
 
 
839
void img_select_nth_slide(img_window_struct *img, gint slide_to_select)
 
840
{
 
841
        GtkTreePath *path;
 
842
 
 
843
        gtk_icon_view_unselect_all(GTK_ICON_VIEW (img->active_icon));
 
844
        path = gtk_tree_path_new_from_indices(slide_to_select, -1);
 
845
        gtk_icon_view_set_cursor (GTK_ICON_VIEW (img->active_icon), path, NULL, FALSE);
 
846
        gtk_icon_view_select_path (GTK_ICON_VIEW (img->active_icon), path);
 
847
        gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (img->active_icon), path, FALSE, 0, 0);
 
848
        gtk_tree_path_free (path);
 
849
}
 
850
 
 
851
GdkPixbuf *
 
852
img_convert_surface_to_pixbuf( cairo_surface_t *surface )
 
853
{
 
854
        GdkPixbuf *pixbuf;
 
855
        gint       w, h, ss, sp, row, col;
 
856
        guchar    *data_s, *data_p;
 
857
 
 
858
        /* Information about surface */
 
859
        w = cairo_image_surface_get_width( surface );
 
860
        h = cairo_image_surface_get_height( surface );
 
861
        ss = cairo_image_surface_get_stride( surface );
 
862
        data_s = cairo_image_surface_get_data( surface );
 
863
 
 
864
        /* Create new pixbuf according to upper specs */
 
865
        pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, w, h );
 
866
 
 
867
        /* Get info about new pixbuf */
 
868
        sp = gdk_pixbuf_get_rowstride( pixbuf );
 
869
        data_p = gdk_pixbuf_get_pixels( pixbuf );
 
870
 
 
871
        /* Copy pixels */
 
872
        for( row = 0; row < h; row++ )
 
873
        {
 
874
                for( col = 0; col < w; col++ )
 
875
                {
 
876
                        gint index_s, index_p;
 
877
 
 
878
                        index_s = row * ss + col * 4;
 
879
                        index_p = row * sp + col * 3;
 
880
 
 
881
                        data_p[index_p + 0] = data_s[index_s + 2];
 
882
                        data_p[index_p + 1] = data_s[index_s + 1];
 
883
                        data_p[index_p + 2] = data_s[index_s + 0];
 
884
                }
 
885
        }
 
886
 
 
887
        return( pixbuf );
 
888
}
 
889
 
 
890
gboolean
 
891
img_scale_gradient( gint              gradient,
 
892
                                        gdouble          *p_start,
 
893
                                        gdouble          *p_stop,
 
894
                                        gdouble          *c_start,
 
895
                                        gdouble          *c_stop,
 
896
                                        gint              width,
 
897
                                        gint              height,
 
898
                                        GdkPixbuf       **pixbuf,
 
899
                                        cairo_surface_t **surface )
 
900
{
 
901
        cairo_surface_t *sf;
 
902
        cairo_t         *cr;
 
903
        cairo_pattern_t *pat;
 
904
        gdouble          diffx, diffy, radius;
 
905
 
 
906
        sf = cairo_image_surface_create( CAIRO_FORMAT_RGB24, width, height );
 
907
        cr = cairo_create( sf );
 
908
 
 
909
        switch( gradient )
 
910
        {
 
911
                case 0: /* Solid color */
 
912
                        cairo_set_source_rgb( cr, c_start[0], c_start[1], c_start[2] );
 
913
                        cairo_paint( cr );
 
914
                        break;
 
915
 
 
916
                case 1: /* Linear gradient */
 
917
                        pat = cairo_pattern_create_linear( p_start[0] * width,
 
918
                                                                                           p_start[1] * height,
 
919
                                                                                           p_stop[0] * width,
 
920
                                                                                           p_stop[1] * height );
 
921
                        cairo_pattern_add_color_stop_rgb( pat, 0, c_start[0],
 
922
                                                                                          c_start[1], c_start[2] );
 
923
                        cairo_pattern_add_color_stop_rgb( pat, 1, c_stop[0],
 
924
                                                                                          c_stop[1], c_stop[2] );
 
925
                        cairo_set_source( cr, pat );
 
926
                        cairo_paint( cr );
 
927
                        cairo_pattern_destroy( pat );
 
928
                        break;
 
929
 
 
930
                case 2: /* Radial gradient */
 
931
                        diffx = ABS( p_start[0] - p_stop[0] ) * width;
 
932
                        diffy = ABS( p_start[1] - p_stop[1] ) * height;
 
933
                        radius = sqrt( pow( diffx, 2 ) + pow( diffy, 2 ) );
 
934
 
 
935
                        pat = cairo_pattern_create_radial( p_start[0] * width,
 
936
                                                                                           p_start[1] * height, 0,
 
937
                                                                                           p_start[0] * width,
 
938
                                                                                           p_start[1] * height, radius );
 
939
                        cairo_pattern_add_color_stop_rgb( pat, 0, c_start[0],
 
940
                                                                                          c_start[1], c_start[2] );
 
941
                        cairo_pattern_add_color_stop_rgb( pat, 1, c_stop[0],
 
942
                                                                                          c_stop[1], c_stop[2] );
 
943
                        cairo_set_source( cr, pat );
 
944
                        cairo_paint( cr );
 
945
                        cairo_pattern_destroy( pat );
 
946
                        break;
 
947
        }
 
948
        cairo_destroy( cr );
 
949
 
 
950
        if( surface )
 
951
                *surface = sf;
 
952
        else
 
953
        {
 
954
                *pixbuf = img_convert_surface_to_pixbuf( sf );
 
955
                cairo_surface_destroy( sf );
 
956
        }
 
957
 
 
958
        return( TRUE );
276
959
}
277
960