From 2049f96c59d95d84362fdea17f028f156f71d665 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Thu, 8 Oct 2009 23:54:02 +0000 Subject: [PATCH] [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 --- buttons.c | 6 +- gfx2.cfg | Bin 10308 -> 10308 bytes global.h | 4 +- graph.c | 2 +- loadsave.c | 3 +- main.c | 4 +- pages.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++---- pages.h | 10 +++- transform.c | 2 +- 9 files changed, 174 insertions(+), 25 deletions(-) diff --git a/buttons.c b/buttons.c index 4cb44869..142a53eb 100644 --- a/buttons.c +++ b/buttons.c @@ -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<Sa3o*@7ZYQ`W^N`+H2^741Z4mK delta 14 VcmX>Sa3o*@7Zc;A&D>0uY5*%d1h)VH diff --git a/global.h b/global.h index 6e6b780a..9f98c0c3 100644 --- a/global.h +++ b/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. diff --git a/graph.c b/graph.c index 5674d025..e5411ae9 100644 --- a/graph.c +++ b/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. diff --git a/loadsave.c b/loadsave.c index 82388cf1..9ba10821 100644 --- a/loadsave.c +++ b/loadsave.c @@ -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++; diff --git a/main.c b/main.c index 73c4cf8b..650563a6 100644 --- a/main.c +++ b/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; diff --git a/pages.c b/pages.c index cfa6c84d..7e6d96c3 100644 --- a/pages.c +++ b/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; iPages->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<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<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<>1; + *visible_layers_flag = layers_before | layers_after; + // Ensure the current layer is part what is shown. + *visible_layers_flag |= 1<Pages->Nb_layers,new_width,new_height)) { // The new image is allocated, the new dimensions are already updated.