[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_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
|
||||
{
|
||||
|
||||
4
global.h
4
global.h
@ -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.
|
||||
|
||||
2
graph.c
2
graph.c
@ -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.
|
||||
|
||||
@ -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
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_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
168
pages.c
@ -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
10
pages.h
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user