00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025 #include <iostream>
00026
00027
00028
00029 #include "image_transitions.h"
00030 #include "page_magick.h"
00031 #include "kino_extra.h"
00032
00033
00034
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include <glade/glade.h>
00038
00039 extern "C"
00040 {
00041 #include "support.h"
00042 extern GladeXML* magick_glade;
00043 }
00044
00045 class ImageTransitionNone : public GDKImageTransition
00046 {
00047 char *GetDescription( ) const
00048 {
00049 return _( "No Change" );
00050 }
00051
00052 void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00053 {
00054 }
00055 };
00056
00057 class ImageTransitionSwitch : public GDKImageTransition
00058 {
00059 private:
00060 GtkWidget *window;
00061 double point;
00062
00063 public:
00064 ImageTransitionSwitch()
00065 {
00066 window = glade_xml_get_widget( magick_glade, "image_transition_switch" );
00067 GtkWidget* widget = lookup_widget( window, "hscale_switch" );
00068 g_signal_connect( G_OBJECT( widget ), "value-changed", G_CALLBACK( Repaint ), 0 );
00069 }
00070
00071 virtual ~ImageTransitionSwitch()
00072 {
00073 gtk_widget_destroy( window );
00074 }
00075
00076 char *GetDescription( ) const
00077 {
00078 return _( "Switch" );
00079 }
00080
00081 void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00082 {
00083 GtkRange * range = GTK_RANGE( lookup_widget( window, "hscale_switch" ) );
00084 GtkAdjustment *adjust = gtk_range_get_adjustment( range );
00085 point = adjust->value / 100;
00086
00087 if ( position >= point )
00088 memcpy( pixels, mesh, width * height * 3 );
00089 }
00090
00091 void AttachWidgets( GtkBin *bin )
00092 {
00093 gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00094 }
00095
00096 void DetachWidgets( GtkBin *bin )
00097 {
00098 gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00099 }
00100
00101 double SwitchPoint( )
00102 {
00103 return point;
00104 }
00105 };
00106
00110 class ImageTransitionFade : public GDKImageTransition
00111 {
00112 public:
00113 char *GetDescription( ) const
00114 {
00115 return _( "Dissolve" );
00116 }
00117
00118 void GetFrame( uint8_t *io, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00119 {
00120 uint8_t * k = mesh;
00121 uint8_t *p = io;
00122 uint8_t r, g, b;
00123 uint8_t kr, kg, kb;
00124
00125 if ( reverse )
00126 position = 1 - position;
00127
00128 while ( p < ( io + width * height * 3 ) )
00129 {
00130 r = *p;
00131 g = *( p + 1 );
00132 b = *( p + 2 );
00133 kr = *k ++;
00134 kg = *k ++;
00135 kb = *k ++;
00136 int vr = ( int ) ( kr * position + r * ( 1 - position ) );
00137 int vg = ( int ) ( kg * position + g * ( 1 - position ) );
00138 int vb = ( int ) ( kb * position + b * ( 1 - position ) );
00139 *p ++ = vr < 0xff ? ( uint8_t ) vr : 0xff;
00140 *p ++ = vg < 0xff ? ( uint8_t ) vg : 0xff;
00141 *p ++ = vb < 0xff ? ( uint8_t ) vb : 0xff;
00142 }
00143 }
00144 };
00145
00149 class ImageTransitionBarWipe : public GDKImageTransition
00150 {
00151 private:
00152 GtkWidget *window;
00153 int type;
00154
00155 public:
00156 ImageTransitionBarWipe()
00157 {
00158 window = glade_xml_get_widget( magick_glade, "image_transition_bar_wipe" );
00159 GtkWidget* widget = lookup_widget( window, "optionmenu_wipe" );
00160 g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00161 }
00162
00163 virtual ~ImageTransitionBarWipe()
00164 {
00165 gtk_widget_destroy( window );
00166 }
00167
00168 char *GetDescription( ) const
00169 {
00170 return _( "Push Wipe" );
00171 }
00172
00173 void Left( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00174 {
00175 int roll_width = ( int ) ( width * position );
00176 for ( int y = 0; y < height; y ++ )
00177 {
00178 uint8_t *k = mesh + y * width * 3;
00179 uint8_t *p = io + y * width * 3;
00180 memmove( p, p + roll_width * 3, ( width * 3 ) - roll_width * 3 );
00181 p = io + ( ( y + 1 ) * width * 3 ) - roll_width * 3;
00182 memcpy( p, k, roll_width * 3 );
00183 }
00184 }
00185
00186 void Right( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00187 {
00188 uint8_t temp[ 720 * 3 ];
00189 int roll_width = ( int ) ( width * position );
00190 for ( int y = 0; y < height; y ++ )
00191 {
00192 uint8_t *k = mesh + y * width * 3;
00193 uint8_t *p = io + y * width * 3;
00194 memcpy( temp, k + ( width - roll_width ) * 3, roll_width * 3 );
00195 memcpy( temp + roll_width * 3, p, ( width * 3 ) - roll_width * 3 );
00196 memcpy( p, temp, width * 3 );
00197 }
00198 }
00199
00200 void Down( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00201 {
00202 int roll_height = ( int ) ( height * position );
00203 memmove( io + roll_height * width * 3, io, ( height - roll_height ) * width * 3 );
00204 for ( int y = 0; y < roll_height; y ++ )
00205 {
00206 uint8_t *p = io + y * width * 3;
00207 uint8_t *k = mesh + ( y + height - roll_height ) * width * 3;
00208 memcpy( p, k, width * 3 );
00209 }
00210 }
00211
00212 void Up( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00213 {
00214 int roll_height = ( int ) ( height * ( 1 - position ) );
00215 memmove( io, io + ( height - roll_height ) * width * 3, roll_height * width * 3 );
00216 for ( int y = roll_height; y < height; y ++ )
00217 {
00218 uint8_t *p = io + y * width * 3;
00219 uint8_t *k = mesh + ( y - roll_height ) * width * 3;
00220 memcpy( p, k, width * 3 );
00221 }
00222 }
00223
00224 void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00225 {
00226 GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_wipe" ) ) ) );
00227 GtkWidget *active_item = gtk_menu_get_active( menu );
00228 type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00229
00230 if ( type == 0 && !reverse )
00231 Left( pixels, mesh, width, height, position );
00232 else if ( type == 0 && reverse )
00233 Right( pixels, mesh, width, height, position );
00234 else if ( type == 1 && !reverse )
00235 Down( pixels, mesh, width, height, position );
00236 else if ( type == 1 && reverse )
00237 Up( pixels, mesh, width, height, position );
00238 }
00239
00240 void AttachWidgets( GtkBin *bin )
00241 {
00242 gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00243 }
00244
00245 void DetachWidgets( GtkBin *bin )
00246 {
00247 gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00248 }
00249 };
00250
00254 #define DIFFERS_BY( w, v, o ) ( abs( v - w ) < o )
00255
00256 class ImageTransitionDifferences : public GDKImageTransition
00257 {
00258 private:
00259 GtkWidget *window;
00260 int type;
00261 int sensitivity;
00262 GdkColor color;
00263
00264 public:
00265 ImageTransitionDifferences()
00266 {
00267 window = glade_xml_get_widget( magick_glade, "image_transition_differences" );
00268 GtkWidget* widget = lookup_widget( window, "optionmenu_action" );
00269 g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00270 widget = lookup_widget( window, "colorpicker" );
00271 g_signal_connect( G_OBJECT( widget ), "color-set", G_CALLBACK( Repaint ), 0 );
00272 widget = lookup_widget( window, "hscale_sensitivity" );
00273 g_signal_connect( G_OBJECT( widget ), "value-changed", G_CALLBACK( Repaint ), 0 );
00274 }
00275
00276 virtual ~ImageTransitionDifferences()
00277 {
00278 gtk_widget_destroy( window );
00279 }
00280
00281 char *GetDescription( ) const
00282 {
00283 return _( "Differences" );
00284 }
00285
00286 void GetFrame( uint8_t *io, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00287 {
00288 GtkMenu *menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_action" ) ) ) );
00289 GtkWidget *active_item = gtk_menu_get_active( menu );
00290 type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00291
00292 GtkColorButton *colorButton = GTK_COLOR_BUTTON( lookup_widget( window, "colorpicker" ) );
00293 gtk_color_button_get_color( colorButton, &color );
00294
00295 GtkRange *range = GTK_RANGE( lookup_widget( window, "hscale_sensitivity" ) );
00296 GtkAdjustment *adjust = gtk_range_get_adjustment( range );
00297 sensitivity = ( int ) adjust->value;
00298
00299
00300 uint8_t * k = mesh;
00301 uint8_t *p = io;
00302 uint8_t r, g, b;
00303 uint8_t kr, kg, kb;
00304 for ( int y = 0; y < height; y ++ )
00305 {
00306 for ( int x = 0; x < width; x ++ )
00307 {
00308 r = *p;
00309 g = *( p + 1 );
00310 b = *( p + 2 );
00311 kr = *k ++;
00312 kg = *k ++;
00313 kb = *k ++;
00314
00315 bool differs = DIFFERS_BY( kr, r, sensitivity ) && DIFFERS_BY( kg, g, sensitivity ) && DIFFERS_BY( kb, b, sensitivity );
00316
00317 if ( ( !differs && type == 0 ) || ( differs && type == 1 ) )
00318 {
00319 *p ++ = color.red >> 8;
00320 *p ++ = color.green >> 8;
00321 *p ++ = color.blue >> 8;
00322 }
00323 else
00324 {
00325 *p ++ = r;
00326 *p ++ = g;
00327 *p ++ = b;
00328 }
00329 }
00330 }
00331 }
00332
00333 void AttachWidgets( GtkBin *bin )
00334 {
00335 gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00336 }
00337
00338 void DetachWidgets( GtkBin *bin )
00339 {
00340 gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00341 }
00342 };
00343
00347 class ImageTransitionBarnDoorWipe : public GDKImageTransition
00348 {
00349 private:
00350 GtkWidget *window;
00351 int type;
00352
00353 public:
00354 ImageTransitionBarnDoorWipe()
00355 {
00356 window = glade_xml_get_widget( magick_glade, "image_transition_barndoor" );
00357 GtkWidget* widget = lookup_widget( window, "optionmenu_door" );
00358 g_signal_connect( G_OBJECT( widget ), "changed", G_CALLBACK( Repaint ), 0 );
00359 }
00360
00361 virtual ~ImageTransitionBarnDoorWipe()
00362 {
00363 gtk_widget_destroy( window );
00364 }
00365
00366 char *GetDescription( ) const
00367 {
00368 return _( "Barn Door Wipe" );
00369 }
00370
00371 void VerticalOpen( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00372 {
00373 int roll_width = ( int ) ( width * position ) / 2;
00374 for ( int y = 0; y < height; y ++ )
00375 {
00376 uint8_t *k = mesh + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00377 uint8_t *p = io + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00378 memcpy( p, k, roll_width * 3 * 2 );
00379 }
00380 }
00381
00382 void VerticalClose( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00383 {
00384 int roll_width = ( width - ( int ) ( width * position ) ) / 2;
00385 for ( int y = 0; y < height; y ++ )
00386 {
00387 uint8_t *k = mesh + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00388 uint8_t *p = io + y * width * 3 + ( width * 3 / 2 ) - roll_width * 3;
00389 memcpy( p, k, roll_width * 3 * 2 );
00390 }
00391 }
00392
00393 void HorizontalOpen( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00394 {
00395 int roll_height = ( int ) ( height * position ) / 2;
00396 for ( int y = height / 2 - roll_height; y < height / 2 + roll_height; y ++ )
00397 {
00398 uint8_t *k = mesh + y * width * 3;
00399 uint8_t *p = io + y * width * 3;
00400 memcpy( p, k, width * 3 );
00401 }
00402 }
00403
00404 void HorizontalClose( uint8_t *io, uint8_t *mesh, int width, int height, double position )
00405 {
00406 int roll_height = ( int ) ( height * position ) / 2;
00407 for ( int y = 0; y < roll_height; y ++ )
00408 {
00409 uint8_t *k = mesh + y * width * 3;
00410 uint8_t *p = io + y * width * 3;
00411 memcpy( p, k, width * 3 );
00412 k = mesh + ( height - y - 1 ) * width * 3;
00413 p = io + ( height - y - 1 ) * width * 3;
00414 memcpy( p, k, width * 3 );
00415 }
00416 }
00417
00418 void GetFrame( uint8_t *pixels, uint8_t *mesh, int width, int height, double position, double frame_delta, bool reverse )
00419 {
00420 GtkMenu * menu = GTK_MENU( gtk_option_menu_get_menu( GTK_OPTION_MENU( lookup_widget( window, "optionmenu_door" ) ) ) );
00421 GtkWidget *active_item = gtk_menu_get_active( menu );
00422 type = g_list_index ( GTK_MENU_SHELL ( menu ) ->children, active_item );
00423
00424 if ( type == 0 && !reverse )
00425 VerticalOpen( pixels, mesh, width, height, position );
00426 else if ( type == 0 && reverse )
00427 VerticalClose( pixels, mesh, width, height, position );
00428 else if ( type == 1 && !reverse )
00429 HorizontalOpen( pixels, mesh, width, height, position );
00430 else if ( type == 1 && reverse )
00431 HorizontalClose( pixels, mesh, width, height, position );
00432 }
00433
00434 void AttachWidgets( GtkBin *bin )
00435 {
00436 gtk_widget_reparent( ( GTK_BIN( window ) ) ->child, GTK_WIDGET( bin ) );
00437 }
00438
00439 void DetachWidgets( GtkBin *bin )
00440 {
00441 gtk_widget_reparent( ( GTK_BIN( bin ) ) ->child, GTK_WIDGET( window ) );
00442 }
00443 };
00444
00445
00449 static void
00450 on_optionmenu_selected ( GtkMenuItem *menu_item, gpointer user_data )
00451 {
00452 ( ( GDKImageTransitionRepository * ) user_data ) ->SelectionChange();
00453 }
00454
00455 GDKImageTransitionRepository::GDKImageTransitionRepository()
00456 : selected_transition( 0 )
00457 {
00458
00459 Register( new ImageTransitionFade() );
00460 Register( new ImageTransitionBarnDoorWipe() );
00461 Register( new ImageTransitionDifferences() );
00462 Register( new ImageTransitionNone() );
00463 Register( new ImageTransitionBarWipe() );
00464 Register( new ImageTransitionSwitch() );
00465 }
00466
00467 GDKImageTransitionRepository::~GDKImageTransitionRepository()
00468 {
00469
00470 for ( unsigned int index = 0; index < transitions.size(); index ++ )
00471 delete transitions[ index ];
00472 }
00473
00477 void GDKImageTransitionRepository::Register( GDKImageTransition *transition )
00478 {
00479 std::cerr << ">>> Image Transition: " << transition->GetDescription() << std::endl;
00480 transitions.push_back( transition );
00481 }
00482
00483 void GDKImageTransitionRepository::Initialise( GtkOptionMenu *menu, GtkBin *container )
00484 {
00485
00486 this->menu = menu;
00487 this->container = container;
00488
00489
00490 GtkMenu *menu_new = GTK_MENU( gtk_menu_new( ) );
00491 for ( unsigned int index = 0; index < transitions.size(); index ++ )
00492 {
00493 GtkWidget *item = gtk_menu_item_new_with_label( transitions[ index ] ->GetDescription( ) );
00494 gtk_widget_show( item );
00495 gtk_menu_append( menu_new, item );
00496 g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( on_optionmenu_selected ), this );
00497 }
00498 gtk_menu_set_active( menu_new, 0 );
00499 gtk_option_menu_set_menu( menu, GTK_WIDGET( menu_new ) );
00500
00501
00502 SelectionChange();
00503 }
00504
00505 GDKImageTransition *GDKImageTransitionRepository::Get( ) const
00506 {
00507 GtkMenu * innerMenu = GTK_MENU( gtk_option_menu_get_menu( menu ) );
00508 GtkWidget *active_item = gtk_menu_get_active( innerMenu );
00509 return transitions[ g_list_index( GTK_MENU_SHELL( innerMenu ) ->children, active_item ) ];
00510 }
00511
00515 void GDKImageTransitionRepository::SelectionChange( )
00516 {
00517 bool isPreviewing = false;
00518 PageMagick* magick = 0;
00519
00520 if ( common && common->getPageMagick( ) )
00521 magick = common->getPageMagick( );
00522 if ( magick && magick->IsPreviewing() )
00523 {
00524 isPreviewing = true;
00525 magick->StopPreview();
00526 }
00527
00528
00529 if ( selected_transition != NULL )
00530 selected_transition->DetachWidgets( container );
00531
00532 if ( magick )
00533 {
00534 magick->SetKeyFrameControllerClient(0);
00535 magick->ShowCurrentStatus( magick->GetCurrentPosition(), LOCKED_KEY, false, false );
00536 }
00537
00538
00539 selected_transition = Get();
00540
00541
00542 if ( selected_transition != NULL )
00543 selected_transition->AttachWidgets( container );
00544
00545 if ( magick )
00546 {
00547 if ( isPreviewing )
00548 magick->StartPreview();
00549 else
00550 magick->PreviewFrame();
00551 }
00552 }