[layers] Implemented layer insertion. No keys or menu yet, but it's already used when loading images, to make an image with right number of layers. Undoing/redoing such change works. Implemented single-layer deletion (untested)

git-svn-id: svn://pulkomandy.tk/GrafX2/branches/layers@1069 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2009-10-08 23:54:02 +00:00
parent dc70d2f59f
commit 2049f96c59
9 changed files with 174 additions and 25 deletions

View File

@ -1365,7 +1365,7 @@ void Button_Page(void)
SWAP_WORDS (Main_fileselector_position,Spare_fileselector_position)
SWAP_WORDS (Main_fileselector_offset,Spare_fileselector_offset)
SWAP_SHORTS(Main_current_layer,Spare_current_layer)
SWAP_BYTES (Main_layers_visible,Spare_layers_visible)
SWAP_WORDS (Main_layers_visible,Spare_layers_visible)
// A la fin, on affiche l'écran
for (factor_index=0; ZOOM_FACTOR[factor_index]!=Main_magnifier_factor; factor_index++);
@ -4285,7 +4285,7 @@ void Transparency_set(byte amount)
void Layer_activate(short layer, short side)
{
byte old_layers;
word old_layers;
if (layer >= Main_backups->Pages->Nb_layers)
return;
@ -4300,7 +4300,7 @@ void Layer_activate(short layer, short side)
if (Main_layers_visible == (1<<layer))
{
// Set all layers visible
Main_layers_visible = 0xFF;
Main_layers_visible = 0xFFFF;
}
else
{

BIN
gfx2.cfg

Binary file not shown.

View File

@ -348,7 +348,7 @@ GFX2_GLOBAL short Main_magnifier_offset_Y;
/// Index of layer currently being edited
GFX2_GLOBAL int Main_current_layer;
/// Bitfield that records which layers are visible. 2^0 for 0, 2^1 for 1, 2^2 for 2, etc.
GFX2_GLOBAL byte Main_layers_visible;
GFX2_GLOBAL word Main_layers_visible;
// -- Spare page data
@ -412,7 +412,7 @@ GFX2_GLOBAL short Spare_magnifier_offset_Y;
/// Index of layer currently being edited
GFX2_GLOBAL short Spare_current_layer;
/// Bitfield that records which layers are visible. 2^0 for 0, 2^1 for 1, 2^2 for 2, etc.
GFX2_GLOBAL byte Spare_layers_visible;
GFX2_GLOBAL word Spare_layers_visible;
// -- Image backups
/// Backup of the current screen, used during drawing when FX feedback is OFF.

View File

@ -595,7 +595,7 @@ void Resize_image(word chosen_width,word chosen_height)
// |B| | C = Nouvelle image
// +-+-+
if (Backup_with_new_dimensions(1,chosen_width,chosen_height))
if (Backup_with_new_dimensions(1,Main_backups->Pages->Nb_layers,chosen_width,chosen_height))
{
// La nouvelle page a pu être allouée, elle est pour l'instant pleine de
// 0s. Elle fait Main_image_width de large.

View File

@ -460,7 +460,7 @@ void Init_preview(short width,short height,long size,int format, enum PIXEL_RATI
{
if (Pixel_load_function==Pixel_load_in_current_screen)
{
if (Backup_with_new_dimensions(0,width,height))
if (Backup_with_new_dimensions(0,1,width,height))
{
// La nouvelle page a pu être allouée, elle est pour l'instant pleine
// de 0s. Elle fait Main_image_width de large.
@ -3174,6 +3174,7 @@ void Load_GIF(void)
if (number_LID!=0)
{
Main_current_layer++;
Add_layer(Main_backups, Main_current_layer);
}
number_LID++;

4
main.c
View File

@ -370,9 +370,9 @@ int Init_program(int argc,char * argv[])
Main_fileselector_offset=0; // Au début, le fileselect est en haut de la liste des fichiers
Main_format=0;
Main_current_layer=0;
Main_layers_visible=0xFF;
Main_layers_visible=0xFFFF;
Spare_current_layer=0;
Spare_layers_visible=0xFF;
Spare_layers_visible=0xFFFF;
Spare_fileselector_position=0;
Spare_fileselector_offset=0;

168
pages.c
View File

@ -43,7 +43,7 @@ T_Page * New_page(byte nb_layers)
{
T_Page * page;
page = (T_Page *)malloc(sizeof(T_Page)+NB_LAYERS*sizeof(byte *));
page = (T_Page *)malloc(sizeof(T_Page)+nb_layers*sizeof(byte *));
if (page!=NULL)
{
int i;
@ -469,7 +469,7 @@ void Free_last_page_of_list(T_List_of_pages * list)
}
// layer_mask tells which layers have to be fresh copies instead of references
int Create_new_page(T_Page * new_page,T_List_of_pages * list, byte layer_mask)
int Create_new_page(T_Page * new_page, T_List_of_pages * list, word layer_mask)
{
// Cette fonction crée une nouvelle page dont les attributs correspondent à
@ -659,13 +659,12 @@ void Set_number_of_backups(int nb_backups)
// (nb_backups = Nombre de backups, sans compter les pages courantes)
}
int Backup_with_new_dimensions(int upload,int width,int height)
int Backup_with_new_dimensions(int upload,byte layers,int width,int height)
{
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
// 0 sinon.
T_Page * new_page;
byte nb_layers;
int return_code=0;
int i;
@ -674,9 +673,8 @@ int Backup_with_new_dimensions(int upload,int width,int height)
// retrouver plus tard)
Upload_infos_page_main(Main_backups->Pages);
nb_layers=Main_backups->Pages->Nb_layers;
// On crée un descripteur pour la nouvelle page courante
new_page=New_page(nb_layers);
new_page=New_page(layers);
if (!new_page)
{
Error(0);
@ -685,9 +683,9 @@ int Backup_with_new_dimensions(int upload,int width,int height)
Upload_infos_page_main(new_page);
new_page->Width=width;
new_page->Height=height;
if (Create_new_page(new_page,Main_backups,255))
if (Create_new_page(new_page,Main_backups,0xFFFF))
{
for (i=0; i<nb_layers;i++)
for (i=0; i<layers;i++)
{
memset(Main_backups->Pages->Image[i], 0, width*height);
}
@ -727,7 +725,7 @@ int Backup_and_resize_the_spare(int width,int height)
Upload_infos_page_spare(new_page);
new_page->Width=width;
new_page->Height=height;
if (Create_new_page(new_page,Spare_backups,255))
if (Create_new_page(new_page,Spare_backups,0xFFFF))
{
byte i;
@ -752,10 +750,9 @@ void Backup(void)
Backup_layers(1<<Main_current_layer);
}
void Backup_layers(byte layer_mask)
void Backup_layers(word layer_mask)
{
int i;
int i;
T_Page *new_page;
/*
@ -922,3 +919,150 @@ void End_of_modification(void)
Backup();
*/
}
/// Add a new layer to latest page of a list. Returns 0 on success.
byte Add_layer(T_List_of_pages *list, byte layer)
{
T_Page * source_page;
T_Page * new_page;
byte * new_image;
int i;
source_page = list->Pages;
// Keep the position reasonable
if (layer > list->Pages->Nb_layers)
layer = list->Pages->Nb_layers;
// Allocate the pixel data
new_image = New_layer(list->Pages->Height*list->Pages->Width);
if (! new_image)
{
Error(0);
return 1;
}
// Re-allocate the page itself, with room for one more pointer
new_page = realloc(source_page, sizeof(T_Page)+(list->Pages->Nb_layers+1)*sizeof(byte *));
if (!new_page)
{
Error(0);
return 1;
}
if (new_page != source_page)
{
// Need some housekeeping because the page moved in memory.
// Update all pointers that pointed to it:
new_page->Prev->Next = new_page;
new_page->Next->Prev = new_page;
list->Pages = new_page;
}
list->Pages->Nb_layers++;
// Move around the pointers. This part is going to be tricky when we
// have 'animations x layers' in this vector.
for (i=list->Pages->Nb_layers-1; i>layer ; i--)
{
new_page->Image[i]=new_page->Image[i-1];
}
new_page->Image[layer]=new_image;
// Fill with transparency, initially
memset(new_image, 0, list->Pages->Height*list->Pages->Width); // transparent color
// Done. Note that the visible buffer is already ok since we
// only inserted a transparent "slide" somewhere.
// The depth buffer is all wrong though.
// Update the flags of visible layers.
{
word layers_before;
word layers_after;
word *visible_layers_flag;
// Determine if we're modifying the spare or the main page.
if (list == Main_backups)
{
visible_layers_flag = &Main_layers_visible;
Main_current_layer = layer;
}
else
{
visible_layers_flag = &Spare_layers_visible;
Spare_current_layer = layer;
}
// Fun with binary!
layers_before = ((1<<layer)-1) & *visible_layers_flag;
layers_after = (*visible_layers_flag & (!layers_before))<<1;
*visible_layers_flag = (1<<layer) | layers_before | layers_after;
}
// All ok
return 0;
}
/// Delete a layer from the latest page of a list. Returns 0 on success.
byte Delete_layer(T_List_of_pages *list, byte layer)
{
T_Page * page;
int i;
page = list->Pages;
// Keep the position reasonable
if (layer >= list->Pages->Nb_layers)
layer = list->Pages->Nb_layers - 1;
if (list->Pages->Nb_layers == 1)
return 1;
// For simplicity, we won't actually shrink the page in terms of allocation.
// It would only save the size of a pointer, and anyway, as the user draws,
// this page is going to fall off the end of the Undo-list
// and so it will be cleared anyway.
// Smart freeing of the pixel data
Free_layer(list->Pages->Image[layer]);
list->Pages->Nb_layers--;
// Move around the pointers. This part is going to be tricky when we
// have 'animations x layers' in this vector.
for (i=layer; i < list->Pages->Nb_layers; i++)
{
list->Pages->Image[i]=list->Pages->Image[i+1];
}
// Done. At this point the visible buffer and the depth buffer are
// all wrong.
// Update the flags of visible layers.
{
word layers_before;
word layers_after;
word *visible_layers_flag;
byte new_current_layer;
// Determine if we're modifying the spare or the main page.
if (list == Main_backups)
{
visible_layers_flag = &Main_layers_visible;
if (Main_current_layer>=layer && Main_current_layer>0)
Main_current_layer--;
new_current_layer = Main_current_layer;
}
else
{
visible_layers_flag = &Spare_layers_visible;
if (Spare_current_layer>=layer && Spare_current_layer>0)
Spare_current_layer--;
new_current_layer = Spare_current_layer;
}
// Fun with binary!
layers_before = ((1<<layer)-1) & *visible_layers_flag;
layers_after = (*visible_layers_flag & (!layers_before))>>1;
*visible_layers_flag = layers_before | layers_after;
// Ensure the current layer is part what is shown.
*visible_layers_flag |= 1<<new_current_layer;
}
// All ok
return 0;
}

10
pages.h
View File

@ -37,6 +37,10 @@
void Download_infos_page_main(T_Page * page);
void Upload_infos_page_main(T_Page * page);
/// Add a new layer to latest page of a list. Returns 0 on success.
byte Add_layer(T_List_of_pages *list, byte layer);
/// Delete a layer from the latest page of a list. Returns 0 on success.
byte Delete_layer(T_List_of_pages *list, byte layer);
// private
T_Page * New_page(byte nb_layers);
@ -58,7 +62,7 @@ int Allocate_list_of_pages(T_List_of_pages * list);
void Backward_in_list_of_pages(T_List_of_pages * list);
void Advance_in_list_of_pages(T_List_of_pages * list);
void Free_last_page_of_list(T_List_of_pages * list);
int Create_new_page(T_Page * new_page,T_List_of_pages * current_list, byte layer_mask);
int Create_new_page(T_Page * new_page,T_List_of_pages * current_list, word layer_mask);
void Change_page_number_of_list(T_List_of_pages * list,int number);
void Free_page_of_a_list(T_List_of_pages * list);
@ -70,12 +74,12 @@ void Free_page_of_a_list(T_List_of_pages * list);
int Init_all_backup_lists(int width,int height);
void Set_number_of_backups(int nb_backups);
int Backup_with_new_dimensions(int upload,int width,int height);
int Backup_with_new_dimensions(int upload,byte layers,int width,int height);
int Backup_and_resize_the_spare(int width,int height);
/// Backup with a new copy for the working layer, and references for all others.
void Backup(void);
/// Backup with a new copy of some layers (the others are references).
void Backup_layers(byte layer_mask);
void Backup_layers(word layer_mask);
void Undo(void);
void Redo(void);
void Free_current_page(void); // 'Kill' button

View File

@ -368,7 +368,7 @@ void Button_Transform_menu(void)
old_height=Main_image_height;
// Allocate a new page
if (Backup_with_new_dimensions(1,new_width,new_height))
if (Backup_with_new_dimensions(1,Main_backups->Pages->Nb_layers,new_width,new_height))
{
// The new image is allocated, the new dimensions are already updated.