Re-integrated anim in trunk, fixing the 999-layer limit at the same time

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1841 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud
2011-10-19 23:35:56 +00:00
parent 775ee56ed0
commit 8fb16e7089
28 changed files with 753 additions and 174 deletions

View File

@@ -1706,18 +1706,26 @@ typedef struct
typedef struct
{
// byte Block_identifier : 0x21
// byte Function : 0xF9
// byte Block_size // 4
byte Block_identifier; // 0x21
byte Function; // 0xF9
byte Block_size; // 4
byte Packed_fields; // 11100000 : Reserved
// 00011100 : Disposal method
// 00000010 : User input flag
// 00000001 : Transparent flag
word Delay_time; // Time for this frame to stay displayed
byte Transparent_color; // Which color index acts as transparent
//word Bloc_terminator; // 0x00
word Block_terminator; // 0x00
} T_GIF_GCE; // Graphic Control Extension
enum DISPOSAL_METHOD
{
DISPOSAL_METHOD_UNDEFINED = 0,
DISPOSAL_METHOD_DO_NOT_DISPOSE = 1,
DISPOSAL_METHOD_RESTORE_BGCOLOR = 2,
DISPOSAL_METHOD_RESTORE_PREVIOUS = 3,
};
// -- Tester si un fichier est au format GIF --------------------------------
void Test_GIF(T_IO_Context * context)
@@ -1801,8 +1809,9 @@ word GIF_get_next_code(void)
// -- Affiche un nouveau pixel --
void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, byte color)
void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, int is_transparent, byte color)
{
if (!is_transparent || color!=context->Transparent_color)
Set_pixel(context, idb->Pos_X+GIF_pos_X, idb->Pos_Y+GIF_pos_Y,color);
GIF_pos_X++;
@@ -1872,7 +1881,11 @@ void Load_GIF(T_IO_Context * context)
word value_eof; // Valeur <=> End d'image
long file_size;
int number_LID; // Nombre d'images trouvées dans le fichier
short current_layer = 0;
int current_layer = 0;
int last_delay = 0;
byte is_transparent = 0;
byte disposal_method = DISPOSAL_METHOD_RESTORE_BGCOLOR;
byte previous_disposal_method = DISPOSAL_METHOD_RESTORE_BGCOLOR;
/////////////////////////////////////////////////// FIN DES DECLARATIONS //
@@ -1972,19 +1985,23 @@ void Load_GIF(T_IO_Context * context)
&& Read_word_le(GIF_file,&(GCE.Delay_time))
&& Read_byte(GIF_file,&(GCE.Transparent_color)))
{
previous_disposal_method = disposal_method;
disposal_method = (GCE.Packed_fields >> 2) & 7;
last_delay = GCE.Delay_time;
context->Transparent_color= GCE.Transparent_color;
if (GCE.Packed_fields & 1)
{
if (number_LID == 0)
context->Background_transparent = 1;
context->Transparent_color= GCE.Transparent_color;
}
else
{
if (number_LID == 0)
context->Background_transparent = 0;
context->Transparent_color = 0; // Reset transparent color
}
is_transparent =
(previous_disposal_method==DISPOSAL_METHOD_DO_NOT_DISPOSE
||previous_disposal_method==DISPOSAL_METHOD_UNDEFINED);
}
else
File_error=2;
@@ -2117,7 +2134,35 @@ void Load_GIF(T_IO_Context * context)
// Attempt to add a layer to current image
current_layer++;
Set_loading_layer(context, current_layer);
#ifdef NOLAYERS
if (context->Type == CONTEXT_MAIN_IMAGE)
{
if (is_transparent)
// Copy the content of previous layer, in case of loading a GIF
// that uses transparency compression
memcpy(
Main_backups->Pages->Image[Main_current_layer].Pixels,
Main_backups->Pages->Image[Main_current_layer-1].Pixels,
Main_backups->Pages->Width*Main_backups->Pages->Height);
else
memset(
Main_backups->Pages->Image[Main_current_layer].Pixels,
LSDB.Backcol,
Main_backups->Pages->Width*Main_backups->Pages->Height);
}
#endif
}
else
{
if (context->Type == CONTEXT_MAIN_IMAGE)
memset(
Main_backups->Pages->Image[Main_current_layer].Pixels,
LSDB.Backcol,
Main_backups->Pages->Width*Main_backups->Pages->Height);
}
// Duration was set in the previously loaded GCE
Set_frame_duration(context, last_delay*10);
number_LID++;
// lecture de 10 derniers octets
@@ -2202,7 +2247,7 @@ void Load_GIF(T_IO_Context * context)
special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code;
do
GIF_new_pixel(context, &IDB, alphabet_stack[--alphabet_stack_pos]);
GIF_new_pixel(context, &IDB, is_transparent, alphabet_stack[--alphabet_stack_pos]);
while (alphabet_stack_pos!=0);
alphabet_prefix[alphabet_free ]=old_code;
@@ -2222,7 +2267,7 @@ void Load_GIF(T_IO_Context * context)
alphabet_free =(1<<initial_nb_bits)+2;
special_case =GIF_get_next_code();
old_code =GIF_current_code;
GIF_new_pixel(context, &IDB, GIF_current_code);
GIF_new_pixel(context, &IDB, is_transparent, GIF_current_code);
}
}
else
@@ -2371,7 +2416,7 @@ void Save_GIF(T_IO_Context * context)
word current_string; // Code de la chaîne en cours de traitement
byte current_char; // Caractère à coder
word index; // index de recherche de chaîne
short current_layer;
int current_layer;
/////////////////////////////////////////////////// FIN DES DECLARATIONS //
@@ -2436,6 +2481,10 @@ void Save_GIF(T_IO_Context * context)
// Write_bytes(GIF_file,"\x21\xFF\x0BNETSCAPE2.0\x03\xLL\xSS\xSS\x00",19);
// LL : 01 to loop
// SSSS : number of loops
#ifdef NOLAYERS
if (context->Nb_layers>1)
Write_bytes(GIF_file,"\x21\xFF\x0BNETSCAPE2.0\x03\x01\x00\x00\x00",19);
#endif
// Ecriture du commentaire
if (context->Comment[0])
@@ -2471,24 +2520,36 @@ void Save_GIF(T_IO_Context * context)
current_layer++)
{
// Write a Graphic Control Extension
byte GCE_block[] = "\x21\xF9\x04\x04\x05\x00\x00\x00";
// 'Default' values:
// Disposal method "Do not dispose"
// Duration 5/100s (minimum viable value for current web browsers)
if (current_layer > 0 || context->Background_transparent)
GCE_block[3] |= 1; // Transparent color flag
GCE_block[6] = context->Transparent_color;
T_GIF_GCE GCE;
Set_saving_layer(context, current_layer);
GCE.Block_identifier = 0x21;
GCE.Function = 0xF9;
GCE.Block_size=4;
#ifdef NOLAYERS
GCE.Packed_fields=(2<<2)|(context->Background_transparent);
GCE.Delay_time=Get_frame_duration(context)/10;
#else
if (current_layer==0)
GCE.Packed_fields=(1<<2)|(context->Background_transparent);
else
GCE.Packed_fields=(1<<2)|(1);
GCE.Delay_time=5; // Duration 5/100s (minimum viable value for current web browsers)
if (current_layer == context->Nb_layers -1)
{
// "Infinite" delay for last frame
GCE_block[4] = 255;
GCE_block[5] = 255;
}
if (Write_bytes(GIF_file,GCE_block,8))
GCE.Delay_time=0xFFFF; // Infinity (10 minutes)
#endif
GCE.Transparent_color=context->Transparent_color;
GCE.Block_terminator=0x00;
if (Write_byte(GIF_file,GCE.Block_identifier)
&& Write_byte(GIF_file,GCE.Function)
&& Write_byte(GIF_file,GCE.Block_size)
&& Write_byte(GIF_file,GCE.Packed_fields)
&& Write_word_le(GIF_file,GCE.Delay_time)
&& Write_byte(GIF_file,GCE.Transparent_color)
&& Write_byte(GIF_file,GCE.Block_terminator)
)
{
// On va écrire un block indicateur d'IDB et l'IDB du fichier