1 /* vim:expandtab:ts=2 sw=2:
2 */
3 /*  Grafx2 - The Ultimate 256-color bitmap paint program
4 
5 	Copyright owned by various GrafX2 authors, see COPYRIGHT.txt for details.
6 
7     Grafx2 is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; version 2
10     of the License.
11 
12     Grafx2 is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with Grafx2; if not, see <http://www.gnu.org/licenses/>
19 */
20 //////////////////////////////////////////////////////////////////////////
21 /////////////////////////// GESTION DU BACKUP ////////////////////////////
22 //////////////////////////////////////////////////////////////////////////
23 
24 #include <stddef.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #ifdef _MSC_VER
28 #define strdup _strdup
29 #endif
30 
31 #include "gfx2mem.h"
32 #include "global.h"
33 #include "pages.h"
34 #include "errors.h"
35 #include "loadsave.h"
36 #include "misc.h"
37 #include "windows.h"
38 #include "tiles.h"
39 #include "graph.h"
40 #include "layers.h"
41 #include "unicode.h"
42 
43 // -- Layers data
44 
45 /// Array of two images, that contains the "flattened" version of the visible layers.
46 //T_Bitmap Main_visible_image;
47 T_Bitmap Main_visible_image_backup;
48 T_Bitmap Main_visible_image_depth_buffer;
49 //T_Bitmap Spare_visible_image;
50 
51   ///
52   /// GESTION DES PAGES
53   ///
54 
55 /// Bitfield which records which layers are backed up in Page 0.
56 static dword Last_backed_up_layers=0;
57 
58 /// Total number of unique bitmaps (layers, animation frames, backups)
59 long Stats_pages_number=0;
60 /// Total memory used by bitmaps (layers, animation frames, backups)
61 long long Stats_pages_memory=0;
62 
63 /// Allocate and initialize a new page.
New_page(int nb_layers)64 T_Page * New_page(int nb_layers)
65 {
66   T_Page * page;
67 
68   page = (T_Page *)GFX2_malloc(sizeof(T_Page)+nb_layers*sizeof(T_Image));
69   if (page!=NULL)
70   {
71     int i;
72     for (i=0; i<nb_layers; i++)
73     {
74       page->Image[i].Pixels = NULL;
75       page->Image[i].Duration = 100;
76     }
77     page->Width=0;
78     page->Height=0;
79     page->Image_mode = IMAGE_MODE_LAYERED;
80     memset(page->Palette, 0, sizeof(T_Palette));
81     page->Comment[0] = '\0';
82     page->File_directory = NULL;
83     page->Filename = NULL;
84     page->Filename_unicode = NULL;
85     page->File_format = DEFAULT_FILEFORMAT;
86     page->Nb_layers = nb_layers;
87     page->Gradients = NULL;
88     page->Transparent_color = 0; // Default transparent color
89     page->Background_transparent = 0;
90     page->Next = page->Prev = NULL;
91   }
92   return page;
93 }
94 
95 // ==============================================================
96 // Layers allocation functions.
97 //
98 // Layers are made of a "number of users" (short), followed by
99 // the actual pixel data (a large number of bytes).
100 // Every time a layer is 'duplicated' as a reference, the number
101 // of users is incremented.
102 // Every time a layer is freed, the number of users is decreased,
103 // and only when it reaches zero the pixel data is freed.
104 // ==============================================================
105 
106 /// Allocate a new layer
New_layer(long pixel_size)107 byte * New_layer(long pixel_size)
108 {
109   short * ptr = GFX2_malloc(sizeof(short)+pixel_size);
110   if (ptr==NULL)
111     return NULL;
112 
113   // Stats
114   Stats_pages_number++;
115   Stats_pages_memory+=pixel_size;
116 
117   *ptr = 1;
118   return (byte *)(ptr+1);
119 }
120 
121 /// Free a layer
Free_layer(T_Page * page,int layer)122 void Free_layer(T_Page * page, int layer)
123 {
124   short * ptr;
125   if (page->Image[layer].Pixels==NULL)
126     return;
127 
128   ptr = (short *)(page->Image[layer].Pixels);
129   if (-- (*(ptr-1))) // Users--
130     return;
131   else {
132     free(ptr-1);
133   }
134 
135   // Stats
136   Stats_pages_number--;
137   Stats_pages_memory-=page->Width * page->Height;
138 }
139 
140 /// Duplicate a layer (new reference)
Dup_layer(byte * layer)141 byte * Dup_layer(byte * layer)
142 {
143   short * ptr = (short *)(layer);
144 
145   if (layer==NULL)
146     return NULL;
147 
148   (*(ptr-1)) ++; // Users ++
149   return layer;
150 }
151 
152 // ==============================================================
153 
154 /// Adds a shared reference to the gradient data of another page. Pass NULL for new.
Dup_gradient(T_Page * page)155 T_Gradient_array *Dup_gradient(T_Page * page)
156 {
157   // new
158   if (page==NULL || page->Gradients==NULL)
159   {
160     T_Gradient_array *array;
161     array=(T_Gradient_array *)calloc(1, sizeof(T_Gradient_array));
162     if (!array)
163       return NULL;
164     array->Used=1;
165     return array;
166   }
167   // shared
168   page->Gradients->Used++;
169   return page->Gradients;
170 }
171 
Download_infos_page_main(T_Page * page)172 void Download_infos_page_main(T_Page * page)
173 // Affiche la page à l'écran
174 {
175   //int factor_index;
176   int size_is_modified;
177 
178   if (page!=NULL)
179   {
180     size_is_modified=(Main.image_width!=page->Width) ||
181                          (Main.image_height!=page->Height);
182 
183     Main.image_width=page->Width;
184     Main.image_height=page->Height;
185     memcpy(Main.palette,page->Palette,sizeof(T_Palette));
186     Main.fileformat=page->File_format;
187 
188     if (size_is_modified)
189     {
190       Main.magnifier_mode=0;
191       Main.offset_X=0;
192       Main.offset_Y=0;
193       Pixel_preview=Pixel_preview_normal;
194       Compute_limits();
195       Compute_paintbrush_coordinates();
196     }
197 
198   }
199   //Update_buffers( page->Width, page->Height);
200   //memcpy(Main_screen, page->Image[Main.current_layer].Pixels, page->Width*page->Height);
201 
202 }
203 
Redraw_layered_image(void)204 void Redraw_layered_image(void)
205 {
206   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
207   {
208     // Re-construct the image with the visible layers
209     byte layer=0;
210     // First layer
211     if ((Main.backups->Pages->Image_mode == IMAGE_MODE_MODE5
212 		|| Main.backups->Pages->Image_mode == IMAGE_MODE_RASTER) && Main.layers_visible & (1<<4))
213     {
214       // The raster result layer is visible: start there
215       // Copy it in Main_visible_image
216       int i;
217       for (i=0; i< Main.image_width*Main.image_height; i++)
218       {
219         layer = *(Main.backups->Pages->Image[4].Pixels+i);
220         if (Main.layers_visible & (1 << layer))
221           Main.visible_image.Image[i]=*(Main.backups->Pages->Image[layer].Pixels+i);
222         else
223           Main.visible_image.Image[i] = layer;
224       }
225 
226       // Copy it to the depth buffer
227       memcpy(Main_visible_image_depth_buffer.Image,
228         Main.backups->Pages->Image[4].Pixels,
229         Main.image_width*Main.image_height);
230 
231       // Next
232       layer= (1<<4)+1;
233     }
234     else
235     {
236       for (layer=0; layer<Main.backups->Pages->Nb_layers; layer++)
237       {
238         if ((1<<layer) & Main.layers_visible)
239         {
240            // Copy it in Main_visible_image
241            memcpy(Main.visible_image.Image,
242              Main.backups->Pages->Image[layer].Pixels,
243              Main.image_width*Main.image_height);
244 
245            // Initialize the depth buffer
246            memset(Main_visible_image_depth_buffer.Image,
247              layer,
248              Main.image_width*Main.image_height);
249 
250            // skip all other layers
251            layer++;
252            break;
253         }
254       }
255     }
256     // subsequent layer(s)
257     for (; layer<Main.backups->Pages->Nb_layers; layer++)
258     {
259       if ((1<<layer) & Main.layers_visible)
260       {
261         int i;
262         for (i=0; i<Main.image_width*Main.image_height; i++)
263         {
264           byte color = *(Main.backups->Pages->Image[layer].Pixels+i);
265           if (color != Main.backups->Pages->Transparent_color) // transparent color
266           {
267             *(Main.visible_image.Image+i) = color;
268             if (layer != Main.current_layer)
269               *(Main_visible_image_depth_buffer.Image+i) = layer;
270           }
271         }
272       }
273     }
274   }
275   else
276   {
277     Update_screen_targets();
278   }
279   Update_FX_feedback(Config.FX_Feedback);
280 }
281 
Update_depth_buffer(void)282 void Update_depth_buffer(void)
283 {
284   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
285   {
286     // Re-construct the depth buffer with the visible layers.
287     // This function doesn't touch the visible buffer, it assumes
288     // that it was already up-to-date. (Ex. user only changed active layer)
289 
290     int layer;
291     // First layer
292     for (layer=0; layer<Main.backups->Pages->Nb_layers; layer++)
293     {
294       if ((1<<layer) & Main.layers_visible)
295       {
296          // Initialize the depth buffer
297          memset(Main_visible_image_depth_buffer.Image,
298            layer,
299            Main.image_width*Main.image_height);
300 
301          // skip all other layers
302          layer++;
303          break;
304       }
305     }
306     // subsequent layer(s)
307     for (; layer<Main.backups->Pages->Nb_layers; layer++)
308     {
309       // skip the current layer, whenever we reach it
310       if (layer == Main.current_layer)
311         continue;
312 
313       if ((1<<layer) & Main.layers_visible)
314       {
315         int i;
316         for (i=0; i<Main.image_width*Main.image_height; i++)
317         {
318           byte color = *(Main.backups->Pages->Image[layer].Pixels+i);
319           if (color != Main.backups->Pages->Transparent_color) // transparent color
320           {
321             *(Main_visible_image_depth_buffer.Image+i) = layer;
322           }
323         }
324       }
325     }
326   }
327   Update_FX_feedback(Config.FX_Feedback);
328 }
329 
Redraw_spare_image(void)330 void Redraw_spare_image(void)
331 {
332   if (Spare.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
333   {
334     // Re-construct the image with the visible layers
335     byte layer;
336     // First layer
337     for (layer=0; layer<Spare.backups->Pages->Nb_layers; layer++)
338     {
339       if ((1<<layer) & Spare.layers_visible)
340       {
341          // Copy it in Spare_visible_image
342          memcpy(Spare.visible_image.Image,
343            Spare.backups->Pages->Image[layer].Pixels,
344            Spare.image_width*Spare.image_height);
345 
346          // No depth buffer in the spare
347          //memset(Spare_visible_image_depth_buffer.Image,
348          //  layer,
349          //  Spare.image_width*Spare.image_height);
350 
351          // skip all other layers
352          layer++;
353          break;
354       }
355     }
356     // subsequent layer(s)
357     for (; layer<Spare.backups->Pages->Nb_layers; layer++)
358     {
359       if ((1<<layer) & Spare.layers_visible)
360       {
361         int i;
362         for (i=0; i<Spare.image_width*Spare.image_height; i++)
363         {
364           byte color = *(Spare.backups->Pages->Image[layer].Pixels+i);
365           if (color != Spare.backups->Pages->Transparent_color) // transparent color
366           {
367             *(Spare.visible_image.Image+i) = color;
368             //if (layer != Spare.current_layer)
369             //  *(Spare_visible_image_depth_buffer.Image+i) = layer;
370           }
371         }
372       }
373     }
374   }
375 }
376 
Redraw_current_layer(void)377 void Redraw_current_layer(void)
378 {
379   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
380   {
381     int i;
382     for (i=0; i<Main.image_width*Main.image_height; i++)
383     {
384       byte depth = *(Main_visible_image_depth_buffer.Image+i);
385       if (depth<=Main.current_layer)
386       {
387         byte color = *(Main.backups->Pages->Image[Main.current_layer].Pixels+i);
388         if (color != Main.backups->Pages->Transparent_color) // transparent color
389         {
390           *(Main.visible_image.Image+i) = color;
391         }
392         else
393         {
394           *(Main.visible_image.Image+i) = *(Main.backups->Pages->Image[depth].Pixels+i);
395         }
396       }
397     }
398   }
399 }
400 
Upload_infos_page(T_Document * doc)401 void Upload_infos_page(T_Document * doc)
402 // Sauve l'écran courant dans la page
403 {
404   if (doc->backups->Pages != NULL)
405   {
406     doc->backups->Pages->Width = doc->image_width;
407     doc->backups->Pages->Height = doc->image_height;
408     memcpy(doc->backups->Pages->Palette, doc->palette, sizeof(T_Palette));
409     doc->backups->Pages->File_format = doc->fileformat;
410   }
411 }
412 
Download_infos_page_spare(T_Page * page)413 void Download_infos_page_spare(T_Page * page)
414 {
415   if (page!=NULL)
416   {
417     Spare.image_width=page->Width;
418     Spare.image_height=page->Height;
419     memcpy(Spare.palette,page->Palette,sizeof(T_Palette));
420     Spare.fileformat=page->File_format;
421   }
422 }
423 
424 byte * FX_feedback_screen;
425 
Update_FX_feedback(byte with_feedback)426 void Update_FX_feedback(byte with_feedback)
427 {
428 
429   if (with_feedback)
430     FX_feedback_screen=Main.backups->Pages->Image[Main.current_layer].Pixels;
431   else
432     FX_feedback_screen=Main.backups->Pages->Next->Image[Main.current_layer].Pixels;
433 }
434 
Clear_page(T_Page * page)435 void Clear_page(T_Page * page)
436 {
437   // On peut appeler cette fonction sur une page non allouée.
438   int i;
439   for (i=0; i<page->Nb_layers; i++)
440   {
441     Free_layer(page, i);
442     page->Image[i].Pixels=NULL;
443     page->Image[i].Duration=0;
444   }
445 
446   // Free_gradient() : This data is reference-counted
447   if (page->Gradients)
448   {
449     page->Gradients->Used--;
450     if (page->Gradients->Used==0)
451       free(page->Gradients);
452     page->Gradients=NULL;
453   }
454 
455   page->Width=0;
456   page->Height=0;
457   // On ne se préoccupe pas de ce que deviens le reste des infos de l'image.
458 }
459 
Copy_S_page(T_Page * dest,T_Page * source)460 void Copy_S_page(T_Page * dest, T_Page * source)
461 {
462   *dest = *source;
463   dest->Gradients = Dup_gradient(source);
464   if (source->File_directory != NULL)
465     dest->File_directory = strdup(source->File_directory);
466   if (source->Filename != NULL)
467     dest->Filename = strdup(source->Filename);
468   if (source->Filename_unicode != NULL)
469     dest->Filename_unicode = Unicode_strdup(source->Filename_unicode);
470 }
471 
472 
473   ///
474   /// GESTION DES LISTES DE PAGES
475   ///
476 
Init_list_of_pages(T_List_of_pages * list)477 void Init_list_of_pages(T_List_of_pages * list)
478 {
479   // Important: appeler cette fonction sur toute nouvelle structure
480   //            T_List_of_pages!
481 
482   list->List_size=0;
483   list->Pages=NULL;
484 }
485 
Allocate_list_of_pages(T_List_of_pages * list)486 int Allocate_list_of_pages(T_List_of_pages * list)
487 {
488   // Important: la T_List_of_pages ne doit pas déjà désigner une liste de
489   //            pages allouée auquel cas celle-ci serait perdue.
490   T_Page * page;
491 
492   // On initialise chacune des nouvelles pages
493   page=New_page(1);
494   if (!page)
495     return 0;
496 
497   // Set as first page of the list
498   page->Next = page;
499   page->Prev = page;
500   list->Pages = page;
501 
502   list->List_size=1;
503 
504   page->Gradients = Dup_gradient(NULL);
505   if (!page->Gradients)
506     return 0;
507 
508   return 1; // Succès
509 }
510 
511 
Backward_in_list_of_pages(T_List_of_pages * list)512 void Backward_in_list_of_pages(T_List_of_pages * list)
513 {
514   // Cette fonction fait l'équivalent d'un "Undo" dans la liste de pages.
515   // Elle effectue une sorte de ROL (Rotation Left) sur la liste:
516   // +---+-+-+-+-+-+-+-+-+-+  |
517   // ¦0¦1¦2¦3¦4¦5¦6¦7¦8¦9¦A¦  |
518   // +---+-+-+-+-+-+-+-+-+-+  |  0=page courante
519   //  ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦   |_ A=page la plus ancienne
520   //  v v v v v v v v v v v   |  1=DerniÞre page (1er backup)
521   // +---+-+-+-+-+-+-+-+-+-+  |
522   // ¦1¦2¦3¦4¦5¦6¦7¦8¦9¦A¦0¦  |
523   // +---+-+-+-+-+-+-+-+-+-+  |
524 
525   // Pour simuler un véritable Undo, l'appelant doit mettre la structure
526   // de page courante à jour avant l'appel, puis en réextraire les infos en
527   // sortie, ainsi que celles relatives à la plus récente page d'undo (1ère
528   // page de la liste).
529 
530   if (Last_backed_up_layers)
531   {
532     // First page contains a ready-made backup of its ->Next.
533     // We have swap the first two pages, so the original page 0
534     // will end up in position 0 again, and then overwrite it with a backup
535     // of the 'new' page1.
536     T_Page * page0;
537     T_Page * page1;
538 
539       page0 = list->Pages;
540       page1 = list->Pages->Next;
541 
542       page0->Next = page1->Next;
543       page1->Prev = page0->Prev;
544       page0->Prev = page1;
545       page1->Next = page0;
546       list->Pages = page0;
547       return;
548   }
549   list->Pages = list->Pages->Next;
550 }
551 
Advance_in_list_of_pages(T_List_of_pages * list)552 void Advance_in_list_of_pages(T_List_of_pages * list)
553 {
554   // Cette fonction fait l'équivalent d'un "Redo" dans la liste de pages.
555   // Elle effectue une sorte de ROR (Rotation Right) sur la liste:
556   // +-+-+-+-+-+-+-+-+-+-+-+  |
557   // |0|1|2|3|4|5|6|7|8|9|A|  |
558   // +-+-+-+-+-+-+-+-+-+-+-+  |  0=page courante
559   //  | | | | | | | | | | |   |_ A=page la plus ancienne
560   //  v v v v v v v v v v v   |  1=Dernière page (1er backup)
561   // +-+-+-+-+-+-+-+-+-+-+-+  |
562   // |A|0|1|2|3|4|5|6|7|8|9|  |
563   // +-+-+-+-+-+-+-+-+-+-+-+  |
564 
565   // Pour simuler un véritable Redo, l'appelant doit mettre la structure
566   // de page courante à jour avant l'appel, puis en réextraire les infos en
567   // sortie, ainsi que celles relatives à la plus récente page d'undo (1ère
568   // page de la liste).
569   if (Last_backed_up_layers)
570   {
571     // First page contains a ready-made backup of its ->Next.
572     // We have swap the first two pages, so the original page 0
573     // will end up in position -1 again, and then overwrite it with a backup
574     // of the 'new' page1.
575     T_Page * page0;
576     T_Page * page1;
577 
578       page0 = list->Pages;
579       page1 = list->Pages->Prev;
580 
581       page0->Prev = page1->Prev;
582       page1->Next = page0->Next;
583       page0->Next = page1;
584       page1->Prev = page0;
585       list->Pages = page1;
586       return;
587   }
588   list->Pages = list->Pages->Prev;
589 }
590 
Free_last_page_of_list(T_List_of_pages * list)591 void Free_last_page_of_list(T_List_of_pages * list)
592 {
593   if (list!=NULL)
594   {
595     if (list->List_size>0)
596     {
597         T_Page * page;
598         // The last page is the one before first
599         page = list->Pages->Prev;
600 
601         page->Next->Prev = page->Prev;
602         page->Prev->Next = page->Next;
603         Clear_page(page);
604         free(page->File_directory);
605         free(page->Filename);
606         free(page->Filename_unicode);
607         free(page);
608         page = NULL;
609         list->List_size--;
610     }
611   }
612 }
613 
614 // layer tells which layers have to be fresh copies instead of references :
615 // it's a layer number (>=0) or LAYER_NONE or LAYER_ALL
Create_new_page(T_Page * new_page,T_List_of_pages * list,int layer)616 int Create_new_page(T_Page * new_page, T_List_of_pages * list, int layer)
617 {
618 
619 //   This function fills the "Image" field of a new Page,
620 // based on the pages's attributes (width,height,...)
621 // then pushes it on front of a Page list.
622 
623   if (list->List_size >= (Config.Max_undo_pages+1))
624   {
625     // List is full.
626     // If some other memory-limit was to be implemented, here would
627     // be the right place to do it.
628     // For example, we could rely on Stats_pages_memory,
629     // because it's the sum of all bitmaps in use (in bytes).
630 
631     // Destroy the latest page
632     Free_last_page_of_list(list);
633   }
634   {
635     int i;
636     for (i=0; i<new_page->Nb_layers; i++)
637     {
638       if (layer == LAYER_ALL || i == layer)
639         new_page->Image[i].Pixels=New_layer(new_page->Height*new_page->Width);
640       else
641         new_page->Image[i].Pixels=Dup_layer(list->Pages->Image[i].Pixels);
642       new_page->Image[i].Duration=list->Pages->Image[i].Duration;
643     }
644   }
645 
646 
647   // Insert as first
648   new_page->Next = list->Pages;
649   new_page->Prev = list->Pages->Prev;
650   list->Pages->Prev->Next = new_page;
651   list->Pages->Prev = new_page;
652   list->Pages = new_page;
653   list->List_size++;
654 
655   return 1;
656 }
657 
Change_page_number_of_list(T_List_of_pages * list,int number)658 void Change_page_number_of_list(T_List_of_pages * list,int number)
659 {
660   // Truncate the list if larger than requested
661   while(list->List_size > number)
662   {
663     Free_last_page_of_list(list);
664   }
665 }
666 
Free_page_of_a_list(T_List_of_pages * list)667 void Free_page_of_a_list(T_List_of_pages * list)
668 {
669   // On ne peut pas détruire la page courante de la liste si après
670   // destruction il ne reste pas encore au moins une page.
671   if (list->List_size>1)
672   {
673     // On fait faire un undo à la liste, comme ça, la nouvelle page courante
674     // est la page précédente
675     Backward_in_list_of_pages(Main.backups);
676 
677     // Puis on détruit la dernière page, qui est l'ancienne page courante
678     Free_last_page_of_list(list);
679   }
680 }
681 
Update_screen_targets(void)682 void Update_screen_targets(void)
683 {
684   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
685   {
686     Main_screen=Main.visible_image.Image;
687     Screen_backup=Main_visible_image_backup.Image;
688   }
689   else
690   {
691     Main_screen=Main.backups->Pages->Image[Main.current_layer].Pixels;
692     // Sometimes this function will be called in situations where the
693     // current history step and previous one don't have as many layers.
694     // I don't like the idea of letting Screen_backup NULL or dangling,
695     // so in case Screen_backup was queried, it will point to a valid
696     // readable bitmap of correct size : current image.
697     if (Main.backups->Pages->Nb_layers != Main.backups->Pages->Next->Nb_layers
698      || Main.backups->Pages->Width != Main.backups->Pages->Next->Width
699      || Main.backups->Pages->Height != Main.backups->Pages->Next->Height)
700       Screen_backup=Main_screen;
701     else
702       Screen_backup=Main.backups->Pages->Next->Image[Main.current_layer].Pixels;
703   }
704   Update_pixel_renderer();
705 }
706 
707 /// Update all the special image buffers, if necessary.
Update_buffers(int width,int height)708 int Update_buffers(int width, int height)
709 {
710   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
711   {
712     // At least one dimension is different
713     if (Main.visible_image.Width*Main.visible_image.Height != width*height)
714     {
715       // Current image
716       free(Main.visible_image.Image);
717       Main.visible_image.Image = (byte *)GFX2_malloc(width * height);
718       if (Main.visible_image.Image == NULL)
719         return 0;
720     }
721     Main.visible_image.Width = width;
722     Main.visible_image.Height = height;
723 
724     if (Main_visible_image_backup.Width*Main_visible_image_backup.Height != width*height)
725     {
726       // Previous image
727       free(Main_visible_image_backup.Image);
728       Main_visible_image_backup.Image = (byte *)GFX2_malloc(width * height);
729       if (Main_visible_image_backup.Image == NULL)
730         return 0;
731     }
732     Main_visible_image_backup.Width = width;
733     Main_visible_image_backup.Height = height;
734 
735     if (Main_visible_image_depth_buffer.Width*Main_visible_image_depth_buffer.Height != width*height)
736     {
737       // Depth buffer
738       free(Main_visible_image_depth_buffer.Image);
739       Main_visible_image_depth_buffer.Image = (byte *)GFX2_malloc(width * height);
740       if (Main_visible_image_depth_buffer.Image == NULL)
741         return 0;
742     }
743     Main_visible_image_depth_buffer.Width = width;
744     Main_visible_image_depth_buffer.Height = height;
745   }
746   Update_screen_targets();
747   return 1;
748 }
749 /// Update all the special image buffers of the spare page, if necessary.
Update_spare_buffers(int width,int height)750 int Update_spare_buffers(int width, int height)
751 {
752   if (Spare.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
753   {
754     // At least one dimension is different
755     if (Spare.visible_image.Width*Spare.visible_image.Height != width*height)
756     {
757       // Current image
758       free(Spare.visible_image.Image);
759       Spare.visible_image.Image = (byte *)GFX2_malloc(width * height);
760       if (Spare.visible_image.Image == NULL)
761         return 0;
762     }
763     Spare.visible_image.Width = width;
764     Spare.visible_image.Height = height;
765 
766   }
767   return 1;
768 }
769 
770 ///
771 /// GESTION DES BACKUPS
772 ///
773 
Init_all_backup_lists(enum IMAGE_MODES image_mode,int width,int height)774 int Init_all_backup_lists(enum IMAGE_MODES image_mode, int width, int height)
775 {
776   // width et height correspondent à la dimension des images de départ.
777   int i;
778 
779   if (! Allocate_list_of_pages(Main.backups) ||
780       ! Allocate_list_of_pages(Spare.backups))
781     return 0;
782   // On a réussi à allouer deux listes de pages dont la taille correspond à
783   // celle demandée par l'utilisateur.
784 
785   // On crée un descripteur de page correspondant à la page principale
786   Upload_infos_page(&Main);
787   // On y met les infos sur la dimension de démarrage
788   Main.backups->Pages->Width = width;
789   Main.backups->Pages->Height = height;
790   Main.backups->Pages->File_directory = strdup(Main.selector.Directory);
791   Main.backups->Pages->Filename = strdup("NO_NAME.GIF");
792   Main.backups->Pages->Filename_unicode = NULL;
793 
794 
795   for (i=0; i<Main.backups->Pages->Nb_layers; i++)
796   {
797     Main.backups->Pages->Image[i].Pixels=New_layer(width*height);
798     if (! Main.backups->Pages->Image[i].Pixels)
799       return 0;
800     memset(Main.backups->Pages->Image[i].Pixels, 0, width*height);
801   }
802   Main.visible_image.Width = 0;
803   Main.visible_image.Height = 0;
804   Main.visible_image.Image = NULL;
805   Main_visible_image_backup.Image = NULL;
806   Main_visible_image_depth_buffer.Image = NULL;
807   Main.backups->Pages->Image_mode = image_mode;
808   Spare.visible_image.Width = 0;
809   Spare.visible_image.Height = 0;
810   Spare.visible_image.Image = NULL;
811   Spare.backups->Pages->Image_mode = image_mode;
812 
813   if (!Update_buffers(width, height))
814     return 0;
815   if (!Update_spare_buffers(width, height))
816     return 0;
817 
818   // For speed, instead of Redraw_layered_image() we'll directly set the buffers.
819   if (Main.visible_image.Image != NULL)
820   {
821     memset(Main.visible_image.Image, 0, width*height);
822     memset(Main_visible_image_backup.Image, 0, width*height);
823     memset(Main_visible_image_depth_buffer.Image, 0, width*height);
824   }
825   if (Spare.visible_image.Image != NULL)
826     memset(Spare.visible_image.Image, 0, width*height);
827 
828   Download_infos_page_main(Main.backups->Pages);
829   Update_FX_feedback(Config.FX_Feedback);
830 
831   // Default values for spare page
832   Spare.backups->Pages->Width = width;
833   Spare.backups->Pages->Height = height;
834   memcpy(Spare.backups->Pages->Palette,Main.palette,sizeof(T_Palette));
835   strcpy(Spare.backups->Pages->Comment,"");
836   Spare.backups->Pages->File_directory = strdup(Main.selector.Directory);
837   Spare.backups->Pages->Filename = strdup("NO_NAME2.GIF");
838   Spare.backups->Pages->Filename_unicode = NULL;
839 
840   Spare.backups->Pages->File_format=DEFAULT_FILEFORMAT;
841   // Copy this informations in the global Spare_ variables
842   Download_infos_page_spare(Spare.backups->Pages);
843 
844   // Clear the initial Visible buffer
845   //memset(Main_screen,0,Main.image_width*Main.image_height);
846 
847   // Spare
848   for (i=0; i<NB_LAYERS; i++)
849   {
850     Spare.backups->Pages->Image[i].Pixels=New_layer(width*height);
851     if (! Spare.backups->Pages->Image[i].Pixels)
852       return 0;
853     memset(Spare.backups->Pages->Image[i].Pixels, 0, width*height);
854 
855   }
856   //memset(Spare_screen,0,Spare.image_width*Spare.image_height);
857 
858   End_of_modification();
859   return 1;
860 }
861 
Set_number_of_backups(int nb_backups)862 void Set_number_of_backups(int nb_backups)
863 {
864   Change_page_number_of_list(Main.backups,nb_backups+1);
865   Change_page_number_of_list(Spare.backups,nb_backups+1);
866 
867   // Le +1 vient du fait que dans chaque liste, en 1ère position on retrouve
868   // les infos de la page courante sur le brouillon et la page principale.
869   // (nb_backups = Nombre de backups, sans compter les pages courantes)
870 }
871 
Backup_new_image(int layers,int width,int height)872 int Backup_new_image(int layers,int width,int height)
873 {
874   // Retourne 1 si une nouvelle page est disponible et 0 sinon
875   T_Page * new_page;
876 
877   // On crée un descripteur pour la nouvelle page courante
878   new_page=New_page(layers);
879   if (!new_page)
880   {
881     Error(0);
882     return 0;
883   }
884   new_page->Width=width;
885   new_page->Height=height;
886   new_page->Transparent_color=0;
887   new_page->Gradients = Dup_gradient(NULL);
888   if (!Create_new_page(new_page,Main.backups,LAYER_ALL))
889   {
890     Error(0);
891     return 0;
892   }
893 
894   Update_buffers(width, height);
895   memset(Main_visible_image_depth_buffer.Image, 0, width*height);
896 
897   Download_infos_page_main(Main.backups->Pages);
898 
899   return 1;
900 }
901 
902 
Backup_with_new_dimensions(int width,int height)903 int Backup_with_new_dimensions(int width,int height)
904 {
905   // Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
906   // 0 sinon.
907 
908   T_Page * new_page;
909   int i;
910 
911   // On crée un descripteur pour la nouvelle page courante
912   new_page=New_page(Main.backups->Pages->Nb_layers);
913   if (!new_page)
914   {
915     Error(0);
916     return 0;
917   }
918   new_page->Width=width;
919   new_page->Height=height;
920   new_page->Transparent_color=0;
921   if (!Create_new_page(new_page,Main.backups,LAYER_ALL))
922   {
923     Error(0);
924     return 0;
925   }
926 
927   // Copy data from previous history step
928   memcpy(Main.backups->Pages->Palette, Main.backups->Pages->Next->Palette, sizeof(T_Palette));
929   strcpy(Main.backups->Pages->Comment ,Main.backups->Pages->Next->Comment);
930   Main.backups->Pages->File_format = Main.backups->Pages->Next->File_format;
931   Main.backups->Pages->Filename = strdup(Main.backups->Pages->Next->Filename);
932   Main.backups->Pages->Filename_unicode = Unicode_strdup(Main.backups->Pages->Next->Filename_unicode);
933   Main.backups->Pages->File_directory = strdup(Main.backups->Pages->Next->File_directory);
934   Main.backups->Pages->Gradients = Dup_gradient(Main.backups->Pages->Next);
935   Main.backups->Pages->Background_transparent = Main.backups->Pages->Next->Background_transparent;
936   Main.backups->Pages->Transparent_color = Main.backups->Pages->Next->Transparent_color;
937   Main.backups->Pages->Image_mode = Main.backups->Pages->Next->Image_mode;
938 
939   // Fill with transparent color
940   for (i=0; i<Main.backups->Pages->Nb_layers;i++)
941   {
942     memset(Main.backups->Pages->Image[i].Pixels, Main.backups->Pages->Transparent_color, width*height);
943   }
944 
945   Update_buffers(width, height);
946 
947   Download_infos_page_main(Main.backups->Pages);
948 
949   // Same code as in End_of_modification(),
950   // Without saving a safety backup:
951   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
952   {
953     memcpy(Main_visible_image_backup.Image,
954            Main.visible_image.Image,
955            Main.image_width*Main.image_height);
956   }
957   else
958   {
959     Update_screen_targets();
960   }
961   Update_FX_feedback(Config.FX_Feedback);
962   // --
963 
964   return 1;
965 }
966 
967 ///
968 /// Resizes a backup step in-place (doesn't add a Undo/Redo step).
969 /// Should only be called after an actual backup, because it loses the current.
970 /// pixels. This function is meant to be used from within Lua scripts.
Backup_in_place(int width,int height)971 int Backup_in_place(int width,int height)
972 {
973   // Retourne 1 si une nouvelle page est disponible (alors pleine de 0) et
974   // 0 sinon.
975 
976   int i;
977   byte ** new_layer;
978 
979   // Perform all allocations first
980 
981   new_layer=calloc(Main.backups->Pages->Nb_layers,sizeof(byte *));
982   if (!new_layer)
983     return 0;
984 
985   for (i=0; i<Main.backups->Pages->Nb_layers; i++)
986   {
987     new_layer[i]=New_layer(height*width);
988     if (!new_layer[i])
989     {
990       // Allocation error
991       for (; i>0; i--)
992         free(new_layer[i]);
993       free(new_layer);
994       return 0;
995     }
996   }
997 
998   // Now ok to proceed
999 
1000   for (i=0; i<Main.backups->Pages->Nb_layers; i++)
1001   {
1002     // Replace layers
1003     Free_layer(Main.backups->Pages,i);
1004     Main.backups->Pages->Image[i].Pixels=new_layer[i];
1005 
1006     // Fill with transparency
1007     memset(Main.backups->Pages->Image[i].Pixels, Main.backups->Pages->Transparent_color, width*height);
1008   }
1009 
1010   Main.backups->Pages->Width=width;
1011   Main.backups->Pages->Height=height;
1012 
1013   Download_infos_page_main(Main.backups->Pages);
1014 
1015   // The following is part of Update_buffers()
1016   // (without changing the backup buffer)
1017   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
1018   {
1019     // At least one dimension is different
1020     if (Main.visible_image.Width*Main.visible_image.Height != width*height)
1021     {
1022       // Current image
1023       free(Main.visible_image.Image);
1024       Main.visible_image.Image = (byte *)GFX2_malloc(width * height);
1025       if (Main.visible_image.Image == NULL)
1026         return 0;
1027     }
1028     Main.visible_image.Width = width;
1029     Main.visible_image.Height = height;
1030 
1031     if (Main_visible_image_depth_buffer.Width*Main_visible_image_depth_buffer.Height != width*height)
1032     {
1033       // Depth buffer
1034       free(Main_visible_image_depth_buffer.Image);
1035       Main_visible_image_depth_buffer.Image = (byte *)GFX2_malloc(width * height);
1036       if (Main_visible_image_depth_buffer.Image == NULL)
1037         return 0;
1038     }
1039     Main_visible_image_depth_buffer.Width = width;
1040     Main_visible_image_depth_buffer.Height = height;
1041 
1042   }
1043   Update_screen_targets();
1044 
1045   return 1;
1046 }
1047 
Backup_and_resize_the_spare(int width,int height)1048 int Backup_and_resize_the_spare(int width,int height)
1049 {
1050   // Retourne 1 si la page de dimension souhaitee est disponible en brouillon
1051   // et 0 sinon.
1052 
1053   T_Page * new_page;
1054   int return_code=0;
1055   int nb_layers;
1056 
1057   nb_layers=Spare.backups->Pages->Nb_layers;
1058   // On crée un descripteur pour la nouvelle page de brouillon
1059   new_page=New_page(nb_layers);
1060   if (!new_page)
1061   {
1062     Error(0);
1063     return 0;
1064   }
1065 
1066   // Fill it with a copy of the latest history
1067   Copy_S_page(new_page,Spare.backups->Pages);
1068 
1069   new_page->Width=width;
1070   new_page->Height=height;
1071   if (Create_new_page(new_page,Spare.backups,LAYER_ALL))
1072   {
1073     byte i;
1074 
1075     for (i=0; i<nb_layers;i++)
1076     {
1077       memset(Spare.backups->Pages->Image[i].Pixels, Spare.backups->Pages->Transparent_color, width*height);
1078     }
1079 
1080     // Update_buffers(width, height); // Not for spare
1081 
1082     Download_infos_page_spare(Spare.backups->Pages);
1083 
1084     // Light up the 'has unsaved changes' indicator
1085     Spare.image_is_modified=1;
1086 
1087     return_code=1;
1088   }
1089   return return_code;
1090 }
1091 
Backup(void)1092 void Backup(void)
1093 // Sauve la page courante comme première page de backup et crée une nouvelle page
1094 // pur continuer à dessiner. Utilisé par exemple pour le fill
1095 {
1096   Backup_layers(Main.current_layer);
1097 }
1098 
Backup_layers(int layer)1099 void Backup_layers(int layer)
1100 {
1101   int i;
1102   T_Page *new_page;
1103 
1104   /*
1105   if (Last_backed_up_layers == (1<<Main.current_layer))
1106     return; // Already done.
1107   */
1108 
1109   // On remet à jour l'état des infos de la page courante (pour pouvoir les
1110   // retrouver plus tard)
1111   Upload_infos_page(&Main);
1112 
1113   // Create a fresh Page descriptor
1114   new_page=New_page(Main.backups->Pages->Nb_layers);
1115   if (!new_page)
1116   {
1117     Error(0);
1118     return;
1119   }
1120 
1121   // Fill it with a copy of the latest history
1122   Copy_S_page(new_page,Main.backups->Pages);
1123   Create_new_page(new_page,Main.backups,layer);
1124   Download_infos_page_main(new_page);
1125 
1126   Update_FX_feedback(Config.FX_Feedback);
1127 
1128   // Copy the actual pixels from the backup to the latest page
1129   if (layer != LAYER_NONE)
1130   {
1131     for (i=0; i<Main.backups->Pages->Nb_layers;i++)
1132     {
1133       if (layer == LAYER_ALL || i == layer)
1134         memcpy(Main.backups->Pages->Image[i].Pixels,
1135                Main.backups->Pages->Next->Image[i].Pixels,
1136                Main.image_width*Main.image_height);
1137     }
1138   }
1139   // Light up the 'has unsaved changes' indicator
1140   Main.image_is_modified=1;
1141 
1142   /*
1143   Last_backed_up_layers = 1<<Main.current_layer;
1144   */
1145 }
1146 
1147 /// Backs up a layer, unless it's already different from previous history step.
1148 // This function checks if a layer/frame shares the same
1149 // bitmap as its Undo history parent.
1150 // If this is the case, it instanciates a new copy, and returns true.
1151 // Otherwise, it returns false.
Dup_layer_if_shared(T_Page * page,int layer)1152 int Dup_layer_if_shared(T_Page * page, int layer)
1153 {
1154   if (page->Image[layer].Pixels == page->Next->Image[layer].Pixels)
1155   {
1156     Free_layer(page, layer);
1157     page->Image[layer].Pixels=New_layer(page->Height*page->Width);
1158     memcpy(
1159       page->Image[layer].Pixels,
1160       page->Next->Image[layer].Pixels,
1161       page->Width*page->Height);
1162     return 1;
1163   }
1164   return 0;
1165 }
1166 
Backup_the_spare(int layer)1167 void Backup_the_spare(int layer)
1168 {
1169   int i;
1170   T_Page *new_page;
1171 
1172   // Create a fresh Page descriptor
1173   new_page=New_page(Spare.backups->Pages->Nb_layers);
1174   if (!new_page)
1175   {
1176     Error(0);
1177     return;
1178   }
1179 
1180   // Fill it with a copy of the latest history
1181   Copy_S_page(new_page,Spare.backups->Pages);
1182   Create_new_page(new_page,Spare.backups,layer);
1183 
1184   // Copy the actual pixels from the backup to the latest page
1185   if (layer != LAYER_NONE)
1186   {
1187     for (i=0; i<Spare.backups->Pages->Nb_layers;i++)
1188     {
1189       if (layer == LAYER_ALL || i == layer)
1190         memcpy(Spare.backups->Pages->Image[i].Pixels,
1191                Spare.backups->Pages->Next->Image[i].Pixels,
1192                Spare.image_width*Spare.image_height);
1193     }
1194   }
1195   // Light up the 'has unsaved changes' indicator
1196   Spare.image_is_modified=1;
1197 
1198 }
1199 
Check_layers_limits()1200 void Check_layers_limits()
1201 {
1202   if (Main.current_layer > Main.backups->Pages->Nb_layers-1)
1203   {
1204     Main.current_layer = Main.backups->Pages->Nb_layers-1;
1205     Main.layers_visible |= 1<<Main.current_layer;
1206   }
1207 }
1208 
Undo(void)1209 void Undo(void)
1210 {
1211   int width = Main.image_width;
1212   int height = Main.image_height;
1213 
1214   if (Last_backed_up_layers)
1215   {
1216     Free_page_of_a_list(Main.backups);
1217     Last_backed_up_layers=0;
1218   }
1219 
1220   // On remet à jour l'état des infos de la page courante (pour pouvoir les
1221   // retrouver plus tard)
1222   Upload_infos_page(&Main);
1223   // On fait faire un undo à la liste des backups de la page principale
1224   Backward_in_list_of_pages(Main.backups);
1225 
1226   Update_buffers(Main.backups->Pages->Width, Main.backups->Pages->Height);
1227 
1228   // On extrait ensuite les infos sur la nouvelle page courante
1229   Download_infos_page_main(Main.backups->Pages);
1230   // Note: le backup n'a pas obligatoirement les mêmes dimensions ni la même
1231   //       palette que la page courante. Mais en temps normal, le backup
1232   //       n'est pas utilisé à la suite d'un Undo. Donc ça ne devrait pas
1233   //       poser de problèmes.
1234 
1235   Check_layers_limits();
1236   Redraw_layered_image();
1237   End_of_modification();
1238 
1239   if (width != Main.image_width || height != Main.image_height)
1240     Tilemap_update();
1241 }
1242 
Redo(void)1243 void Redo(void)
1244 {
1245   int width = Main.image_width;
1246   int height = Main.image_height;
1247 
1248   if (Last_backed_up_layers)
1249   {
1250     Free_page_of_a_list(Main.backups);
1251     Last_backed_up_layers=0;
1252   }
1253   // On remet à jour l'état des infos de la page courante (pour pouvoir les
1254   // retrouver plus tard)
1255   Upload_infos_page(&Main);
1256   // On fait faire un redo à la liste des backups de la page principale
1257   Advance_in_list_of_pages(Main.backups);
1258 
1259   Update_buffers(Main.backups->Pages->Width, Main.backups->Pages->Height);
1260 
1261   // On extrait ensuite les infos sur la nouvelle page courante
1262   Download_infos_page_main(Main.backups->Pages);
1263   // Note: le backup n'a pas obligatoirement les mêmes dimensions ni la même
1264   //       palette que la page courante. Mais en temps normal, le backup
1265   //       n'est pas utilisé à la suite d'un Redo. Donc ça ne devrait pas
1266   //       poser de problèmes.
1267 
1268   Check_layers_limits();
1269   Redraw_layered_image();
1270   End_of_modification();
1271 
1272   if (width != Main.image_width || height != Main.image_height)
1273     Tilemap_update();
1274 }
1275 
Free_current_page(void)1276 void Free_current_page(void)
1277 {
1278   // On détruit la page courante de la liste principale
1279   Free_page_of_a_list(Main.backups);
1280 
1281   // On extrait ensuite les infos sur la nouvelle page courante
1282   Download_infos_page_main(Main.backups->Pages);
1283   // Note: le backup n'a pas obligatoirement les mêmes dimensions ni la même
1284   //       palette que la page courante. Mais en temps normal, le backup
1285   //       n'est pas utilisé à la suite d'une destruction de page. Donc ça ne
1286   //       devrait pas poser de problèmes.
1287 
1288   Update_buffers(Main.backups->Pages->Width, Main.backups->Pages->Height);
1289   Check_layers_limits();
1290   Redraw_layered_image();
1291   End_of_modification();
1292 }
1293 
End_of_modification(void)1294 void End_of_modification(void)
1295 {
1296 
1297   //Update_buffers(Main.image_width, Main.image_height);
1298 
1299   if (Main.backups->Pages->Image_mode != IMAGE_MODE_ANIMATION)
1300   {
1301     // Backup buffer can have "wrong" size if a Lua script
1302     // performs a resize.
1303     Update_buffers(Main.image_width, Main.image_height);
1304     //
1305 
1306     memcpy(Main_visible_image_backup.Image,
1307            Main.visible_image.Image,
1308            Main.image_width*Main.image_height);
1309   }
1310   else
1311   {
1312     Update_screen_targets();
1313   }
1314   Update_FX_feedback(Config.FX_Feedback);
1315 /*
1316   Last_backed_up_layers = 0;
1317   Backup();
1318   */
1319   //
1320   // Processing safety backups
1321   //
1322   Main.edits_since_safety_backup++;
1323   Rotate_safety_backups();
1324 }
1325 
1326 /// Add a new layer to latest page of a list. Returns 0 on success.
Add_layer(T_List_of_pages * list,int layer)1327 byte Add_layer(T_List_of_pages *list, int layer)
1328 {
1329   T_Page * source_page;
1330   T_Page * new_page;
1331   byte * new_image;
1332   int i;
1333   int duration;
1334 
1335   source_page = list->Pages;
1336 
1337   if (list->Pages->Nb_layers >= Layers_max(list->Pages->Image_mode)) // MAX_NB_LAYERS
1338     return 1;
1339 
1340   // Keep the position reasonable
1341   if (layer > list->Pages->Nb_layers)
1342     layer = list->Pages->Nb_layers;
1343 
1344   // Allocate the pixel data
1345   new_image = New_layer(list->Pages->Height*list->Pages->Width);
1346   if (! new_image)
1347   {
1348     Error(0);
1349     return 1;
1350   }
1351   // Re-allocate the page itself, with room for one more pointer
1352   new_page = realloc(source_page, sizeof(T_Page)+(list->Pages->Nb_layers+1)*sizeof(T_Image));
1353   if (!new_page)
1354   {
1355     Error(0);
1356     return 1;
1357   }
1358   if (new_page != source_page)
1359   {
1360     // Need some housekeeping because the page moved in memory.
1361     // Update all pointers that pointed to it:
1362     new_page->Prev->Next = new_page;
1363     new_page->Next->Prev = new_page;
1364     list->Pages = new_page;
1365   }
1366   list->Pages->Nb_layers++;
1367   // Move around the pointers. This part is going to be tricky when we
1368   // have 'animations x layers' in this vector.
1369   for (i=list->Pages->Nb_layers-1; i>layer ; i--)
1370   {
1371     new_page->Image[i]=new_page->Image[i-1];
1372   }
1373   new_page->Image[layer].Pixels=new_image;
1374   if (list->Pages->Nb_layers==0)
1375     duration=100;
1376   else if (layer>0)
1377     duration=new_page->Image[layer-1].Duration;
1378   else
1379     duration=new_page->Image[1].Duration;
1380   new_page->Image[layer].Duration=duration;
1381   // Fill with transparency, initially
1382   memset(new_image, Main.backups->Pages->Transparent_color, list->Pages->Height*list->Pages->Width); // transparent color
1383 
1384   // Done. Note that the visible buffer is already ok since we
1385   // only inserted a transparent "slide" somewhere.
1386   // The depth buffer is all wrong though.
1387 
1388   // Update the flags of visible layers.
1389   {
1390     dword layers_before;
1391     dword layers_after;
1392     dword *visible_layers_flag;
1393 
1394     // Determine if we're modifying the spare or the main page.
1395     if (list == Main.backups)
1396     {
1397       visible_layers_flag = &Main.layers_visible;
1398       Main.current_layer = layer;
1399     }
1400     else
1401     {
1402       visible_layers_flag = &Spare.layers_visible;
1403       Spare.current_layer = layer;
1404     }
1405 
1406     // Fun with binary!
1407     layers_before = ((1<<layer)-1) & *visible_layers_flag;
1408     layers_after = (*visible_layers_flag & (~layers_before))<<1;
1409     *visible_layers_flag = (1<<layer) | layers_before | layers_after;
1410   }
1411 
1412   // All ok
1413   return 0;
1414 }
1415 
1416 /// Delete a layer from the latest page of a list. Returns 0 on success.
Delete_layer(T_List_of_pages * list,int layer)1417 byte Delete_layer(T_List_of_pages *list, int layer)
1418 {
1419   int i;
1420 
1421   // Keep the position reasonable
1422   if (layer >= list->Pages->Nb_layers)
1423     layer = list->Pages->Nb_layers - 1;
1424   if (list->Pages->Nb_layers == 1)
1425     return 1;
1426 
1427   // For simplicity, we won't actually shrink the page in terms of allocation.
1428   // It would only save the size of a pointer, and anyway, as the user draws,
1429   // this page is going to fall off the end of the Undo-list
1430   // and so it will be cleared anyway.
1431 
1432   // Smart freeing of the pixel data
1433   Free_layer(list->Pages, layer);
1434 
1435   list->Pages->Nb_layers--;
1436   // Move around the pointers. This part is going to be tricky when we
1437   // have 'animations x layers' in this vector.
1438   for (i=layer; i < list->Pages->Nb_layers; i++)
1439   {
1440     list->Pages->Image[i]=list->Pages->Image[i+1];
1441   }
1442 
1443   // Done. At this point the visible buffer and the depth buffer are
1444   // all wrong.
1445 
1446   // Update the flags of visible layers.
1447   {
1448     dword layers_before;
1449     dword layers_after;
1450     dword *visible_layers_flag;
1451     byte new_current_layer;
1452 
1453     // Determine if we're modifying the spare or the main page.
1454     if (list == Main.backups)
1455     {
1456       visible_layers_flag = &Main.layers_visible;
1457       if (Main.current_layer>=layer && Main.current_layer>0)
1458         Main.current_layer--;
1459       new_current_layer = Main.current_layer;
1460     }
1461     else
1462     {
1463       visible_layers_flag = &Spare.layers_visible;
1464       if (Spare.current_layer>=layer && Spare.current_layer>0)
1465         Spare.current_layer--;
1466       new_current_layer = Spare.current_layer;
1467     }
1468 
1469     // Fun with binary!
1470     layers_before = ((1<<layer)-1) & *visible_layers_flag;
1471     layers_after = (*visible_layers_flag & (~layers_before))>>1;
1472     *visible_layers_flag = layers_before | layers_after;
1473     // Ensure the current layer is part what is shown.
1474     *visible_layers_flag |= 1<<new_current_layer;
1475   }
1476 
1477   // All ok
1478   return 0;
1479 }
1480 
1481 
1482 /// Merges the current layer onto the one below it.
Merge_layer(void)1483 byte Merge_layer(void)
1484 {
1485   int i;
1486   for (i=0; i<Main.image_width*Main.image_height; i++)
1487   {
1488     byte color = *(Main.backups->Pages->Image[Main.current_layer].Pixels+i);
1489     if (color != Main.backups->Pages->Transparent_color) // transparent color
1490       *(Main.backups->Pages->Image[Main.current_layer-1].Pixels+i) = color;
1491   }
1492   return Delete_layer(Main.backups,Main.current_layer);
1493 }
1494 
1495 
Switch_layer_mode(enum IMAGE_MODES new_mode)1496 void Switch_layer_mode(enum IMAGE_MODES new_mode)
1497 {
1498   if (new_mode == Main.backups->Pages->Image_mode)
1499     return;
1500 
1501   Main.backups->Pages->Image_mode = new_mode;
1502 
1503   if (new_mode != IMAGE_MODE_ANIMATION)
1504   {
1505       Update_buffers(Main.image_width, Main.image_height);
1506       Redraw_layered_image();
1507   }
1508   // TODO Eventually, in animation mode we may clear the buffers to save a bit of memory...
1509 
1510   Update_pixel_renderer();
1511 }
1512