[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:
parent
dc70d2f59f
commit
2049f96c59
@ -1365,7 +1365,7 @@ void Button_Page(void)
|
|||||||
SWAP_WORDS (Main_fileselector_position,Spare_fileselector_position)
|
SWAP_WORDS (Main_fileselector_position,Spare_fileselector_position)
|
||||||
SWAP_WORDS (Main_fileselector_offset,Spare_fileselector_offset)
|
SWAP_WORDS (Main_fileselector_offset,Spare_fileselector_offset)
|
||||||
SWAP_SHORTS(Main_current_layer,Spare_current_layer)
|
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
|
// A la fin, on affiche l'écran
|
||||||
for (factor_index=0; ZOOM_FACTOR[factor_index]!=Main_magnifier_factor; factor_index++);
|
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)
|
void Layer_activate(short layer, short side)
|
||||||
{
|
{
|
||||||
byte old_layers;
|
word old_layers;
|
||||||
|
|
||||||
if (layer >= Main_backups->Pages->Nb_layers)
|
if (layer >= Main_backups->Pages->Nb_layers)
|
||||||
return;
|
return;
|
||||||
@ -4300,7 +4300,7 @@ void Layer_activate(short layer, short side)
|
|||||||
if (Main_layers_visible == (1<<layer))
|
if (Main_layers_visible == (1<<layer))
|
||||||
{
|
{
|
||||||
// Set all layers visible
|
// Set all layers visible
|
||||||
Main_layers_visible = 0xFF;
|
Main_layers_visible = 0xFFFF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
4
global.h
4
global.h
@ -348,7 +348,7 @@ GFX2_GLOBAL short Main_magnifier_offset_Y;
|
|||||||
/// Index of layer currently being edited
|
/// Index of layer currently being edited
|
||||||
GFX2_GLOBAL int Main_current_layer;
|
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.
|
/// 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
|
// -- Spare page data
|
||||||
|
|
||||||
@ -412,7 +412,7 @@ GFX2_GLOBAL short Spare_magnifier_offset_Y;
|
|||||||
/// Index of layer currently being edited
|
/// Index of layer currently being edited
|
||||||
GFX2_GLOBAL short Spare_current_layer;
|
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.
|
/// 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
|
// -- Image backups
|
||||||
|
|
||||||
/// Backup of the current screen, used during drawing when FX feedback is OFF.
|
/// Backup of the current screen, used during drawing when FX feedback is OFF.
|
||||||
|
|||||||
2
graph.c
2
graph.c
@ -595,7 +595,7 @@ void Resize_image(word chosen_width,word chosen_height)
|
|||||||
// |B| | C = Nouvelle image
|
// |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
|
// La nouvelle page a pu être allouée, elle est pour l'instant pleine de
|
||||||
// 0s. Elle fait Main_image_width de large.
|
// 0s. Elle fait Main_image_width de large.
|
||||||
|
|||||||
@ -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 (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
|
// La nouvelle page a pu être allouée, elle est pour l'instant pleine
|
||||||
// de 0s. Elle fait Main_image_width de large.
|
// de 0s. Elle fait Main_image_width de large.
|
||||||
@ -3174,6 +3174,7 @@ void Load_GIF(void)
|
|||||||
if (number_LID!=0)
|
if (number_LID!=0)
|
||||||
{
|
{
|
||||||
Main_current_layer++;
|
Main_current_layer++;
|
||||||
|
Add_layer(Main_backups, Main_current_layer);
|
||||||
}
|
}
|
||||||
number_LID++;
|
number_LID++;
|
||||||
|
|
||||||
|
|||||||
4
main.c
4
main.c
@ -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_fileselector_offset=0; // Au début, le fileselect est en haut de la liste des fichiers
|
||||||
Main_format=0;
|
Main_format=0;
|
||||||
Main_current_layer=0;
|
Main_current_layer=0;
|
||||||
Main_layers_visible=0xFF;
|
Main_layers_visible=0xFFFF;
|
||||||
Spare_current_layer=0;
|
Spare_current_layer=0;
|
||||||
Spare_layers_visible=0xFF;
|
Spare_layers_visible=0xFFFF;
|
||||||
|
|
||||||
Spare_fileselector_position=0;
|
Spare_fileselector_position=0;
|
||||||
Spare_fileselector_offset=0;
|
Spare_fileselector_offset=0;
|
||||||
|
|||||||
168
pages.c
168
pages.c
@ -43,7 +43,7 @@ T_Page * New_page(byte nb_layers)
|
|||||||
{
|
{
|
||||||
T_Page * page;
|
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)
|
if (page!=NULL)
|
||||||
{
|
{
|
||||||
int i;
|
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
|
// 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 à
|
// 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)
|
// (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
|
// Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
|
||||||
// 0 sinon.
|
// 0 sinon.
|
||||||
|
|
||||||
T_Page * new_page;
|
T_Page * new_page;
|
||||||
byte nb_layers;
|
|
||||||
int return_code=0;
|
int return_code=0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -674,9 +673,8 @@ int Backup_with_new_dimensions(int upload,int width,int height)
|
|||||||
// retrouver plus tard)
|
// retrouver plus tard)
|
||||||
Upload_infos_page_main(Main_backups->Pages);
|
Upload_infos_page_main(Main_backups->Pages);
|
||||||
|
|
||||||
nb_layers=Main_backups->Pages->Nb_layers;
|
|
||||||
// On crée un descripteur pour la nouvelle page courante
|
// On crée un descripteur pour la nouvelle page courante
|
||||||
new_page=New_page(nb_layers);
|
new_page=New_page(layers);
|
||||||
if (!new_page)
|
if (!new_page)
|
||||||
{
|
{
|
||||||
Error(0);
|
Error(0);
|
||||||
@ -685,9 +683,9 @@ int Backup_with_new_dimensions(int upload,int width,int height)
|
|||||||
Upload_infos_page_main(new_page);
|
Upload_infos_page_main(new_page);
|
||||||
new_page->Width=width;
|
new_page->Width=width;
|
||||||
new_page->Height=height;
|
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);
|
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);
|
Upload_infos_page_spare(new_page);
|
||||||
new_page->Width=width;
|
new_page->Width=width;
|
||||||
new_page->Height=height;
|
new_page->Height=height;
|
||||||
if (Create_new_page(new_page,Spare_backups,255))
|
if (Create_new_page(new_page,Spare_backups,0xFFFF))
|
||||||
{
|
{
|
||||||
byte i;
|
byte i;
|
||||||
|
|
||||||
@ -752,10 +750,9 @@ void Backup(void)
|
|||||||
Backup_layers(1<<Main_current_layer);
|
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;
|
T_Page *new_page;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -922,3 +919,150 @@ void End_of_modification(void)
|
|||||||
Backup();
|
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
10
pages.h
@ -37,6 +37,10 @@
|
|||||||
|
|
||||||
void Download_infos_page_main(T_Page * page);
|
void Download_infos_page_main(T_Page * page);
|
||||||
void Upload_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
|
// private
|
||||||
T_Page * New_page(byte nb_layers);
|
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 Backward_in_list_of_pages(T_List_of_pages * list);
|
||||||
void Advance_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);
|
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 Change_page_number_of_list(T_List_of_pages * list,int number);
|
||||||
void Free_page_of_a_list(T_List_of_pages * list);
|
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);
|
int Init_all_backup_lists(int width,int height);
|
||||||
void Set_number_of_backups(int nb_backups);
|
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);
|
int Backup_and_resize_the_spare(int width,int height);
|
||||||
/// Backup with a new copy for the working layer, and references for all others.
|
/// Backup with a new copy for the working layer, and references for all others.
|
||||||
void Backup(void);
|
void Backup(void);
|
||||||
/// Backup with a new copy of some layers (the others are references).
|
/// 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 Undo(void);
|
||||||
void Redo(void);
|
void Redo(void);
|
||||||
void Free_current_page(void); // 'Kill' button
|
void Free_current_page(void); // 'Kill' button
|
||||||
|
|||||||
@ -368,7 +368,7 @@ void Button_Transform_menu(void)
|
|||||||
old_height=Main_image_height;
|
old_height=Main_image_height;
|
||||||
|
|
||||||
// Allocate a new page
|
// 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.
|
// The new image is allocated, the new dimensions are already updated.
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user