1 /* layer.c
2 Copyright (C) 2005-2017 Mark Tyler and Dmitry Groshev
3
4 This file is part of mtPaint.
5
6 mtPaint is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 mtPaint is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with mtPaint in the file COPYING.
18 */
19
20 #include "global.h"
21 #undef _
22 #define _(X) X
23
24 #include "mygtk.h"
25 #include "memory.h"
26 #include "vcode.h"
27 #include "ani.h"
28 #include "png.h"
29 #include "layer.h"
30 #include "mainwindow.h"
31 #include "otherwindow.h"
32 #include "canvas.h"
33 #include "inifile.h"
34 #include "viewer.h"
35 #include "channels.h"
36 #include "icons.h"
37
38
39 int layers_total, // Layers currently being used
40 layer_selected, // Layer currently selected in the layers window
41 layers_changed; // 0=Unchanged
42
43 char layers_filename[PATHBUF]; // Current filename for layers file
44 int show_layers_main, // Show all layers in main window
45 layer_overlay; // Toggle overlays per layer
46
47
48 // !!! Always follow adding/changing layer's image_info by update_undo()
49 layer_node layer_table[(MAX_LAYERS + 1) * 2]; // Table of layer info & its backup
50 layer_node *layer_table_p = layer_table; // Unmodified layer table
51
52
layer_clear_slot(int l,int visible)53 static void layer_clear_slot(int l, int visible)
54 {
55 memset(layer_table + l, 0, sizeof(layer_node));
56 layer_table[l].opacity = 100;
57 layer_table[l].visible = visible;
58 }
59
layers_init()60 void layers_init()
61 {
62 layer_clear_slot(0, TRUE);
63 strncpy0(layer_table[0].name, __("Background"), LAYER_NAMELEN);
64 layer_table[0].image = calloc(1, sizeof(layer_image));
65 }
66
67 /* Allocate layer image, its channels and undo stack
68 * !!! Must be followed by update_undo() after setting up image is done */
alloc_layer(int w,int h,int bpp,int cmask,image_info * src)69 layer_image *alloc_layer(int w, int h, int bpp, int cmask, image_info *src)
70 {
71 layer_image *lim;
72
73 lim = calloc(1, sizeof(layer_image));
74 if (!lim) return (NULL);
75 if (init_undo(&lim->image_.undo_, mem_undo_depth) &&
76 mem_alloc_image(src ? AI_COPY : 0, &lim->image_, w, h, bpp, cmask, src))
77 return (lim);
78 mem_free_image(&lim->image_, FREE_UNDO);
79 free(lim);
80 return (NULL);
81 }
82
83 /* Repaint layer in view/main window */
repaint_layer(int l)84 static void repaint_layer(int l)
85 {
86 image_info *image = l == layer_selected ? &mem_image :
87 &layer_table[l].image->image_;
88 lr_update_area(l, 0, 0, image->width, image->height);
89 }
90
repaint_layers()91 static void repaint_layers()
92 {
93 update_stuff(show_layers_main ? UPD_ALLV : UPD_VIEW);
94 }
95
96
97 /// LAYERS WINDOW
98
99 typedef struct {
100 int lock;
101 int x, y, opacity, trans;
102 int nlayer, lnum;
103 int vis;
104 char *lname;
105 void **llist, **nmentry, **xspin, **yspin, **opslider, **trspin;
106 void **ltb_new, **ltb_raise, **ltb_lower, **ltb_dup, **ltb_center,
107 **ltb_del, **ltb_close;
108 } layers_dd;
109
110 static void **layers_box_, **layers_window_;
111
112
layers_update_titlebar()113 static void layers_update_titlebar() // Update filename in titlebar
114 {
115 char txt[300], txt2[PATHTXT];
116
117
118 if (!layers_window_) return; // Don't bother if window is not showing
119
120 gtkuncpy(txt2, layers_filename, PATHTXT);
121 snprintf(txt, 290, "%s %s %s", __("Layers"),
122 layers_changed ? __("(Modified)") : "-",
123 txt2[0] ? txt2 : __("Untitled"));
124 cmd_setv(GET_WINDOW(layers_window_), txt, WINDOW_TITLE);
125 }
126
layers_notify_changed()127 void layers_notify_changed() // Layers have just changed - update vars as needed
128 {
129 if ( layers_changed != 1 )
130 {
131 layers_changed = 1;
132 layers_update_titlebar();
133 }
134 }
135
layers_notify_unchanged()136 static void layers_notify_unchanged() // Layers have just been unchanged (saved) - update vars as needed
137 {
138 if ( layers_changed != 0 )
139 {
140 layers_changed = 0;
141 layers_update_titlebar();
142 }
143 }
144
145
layer_copy_from_main(int l)146 void layer_copy_from_main( int l ) // Copy info from main image to layer
147 {
148 layer_image *lp = layer_table[l].image;
149
150 lp->image_ = mem_image;
151 lp->state_ = mem_state;
152 lp->image_.undo_.size = 0; // Invalidate
153 update_undo(&lp->image_); // Safety net
154 }
155
layer_copy_to_main(int l)156 void layer_copy_to_main( int l ) // Copy info from layer to main image
157 {
158 layer_image *lp = layer_table[l].image;
159
160 if (!layer_overlay)
161 {
162 lp->state_.iover = mem_state.iover;
163 lp->state_.aover = mem_state.aover;
164 }
165 mem_image = lp->image_;
166 mem_state = lp->state_;
167 }
168
shift_layer(int val)169 void shift_layer(int val)
170 {
171 layers_dd *dt = GET_DDATA(layers_box_);
172 layer_node temp;
173 int newbkg, lv = layer_selected + val;
174
175 if ((lv < 0) || (lv > layers_total)) return; // Cannot move
176
177 /* Update source layer */
178 if ((blend_src == SRC_LAYER + layer_selected) || (blend_src == SRC_LAYER + lv))
179 blend_src ^= (SRC_LAYER + layer_selected) ^ (SRC_LAYER + lv);
180
181 layer_copy_from_main(layer_selected);
182 temp = layer_table[layer_selected];
183 layer_table[layer_selected] = layer_table[lv];
184 layer_table[lv] = temp;
185 newbkg = (layer_selected == 0) || (lv == 0);
186
187 cmd_setv(dt->llist, (void *)layer_selected, LISTCC_RESET_ROW);
188 cmd_setv(dt->llist, (void *)lv, LISTCC_RESET_ROW);
189 cmd_set(dt->llist, layer_selected = lv);
190 layers_notify_changed();
191
192 if (newbkg) // Background layer changed
193 {
194 vw_realign();
195 repaint_layers();
196 }
197 else repaint_layer(layer_selected); // Regular layer shifted
198 }
199
layer_show_new()200 void layer_show_new()
201 {
202 layer_refresh_list(layers_total);
203 layers_notify_changed();
204 }
205
layer_add(int w,int h,int bpp,int cols,png_color * pal,int cmask)206 int layer_add(int w, int h, int bpp, int cols, png_color *pal, int cmask)
207 {
208 layer_image *lim;
209
210 if (layers_total >= MAX_LAYERS) return (FALSE);
211
212 lim = alloc_layer(w, h, bpp, cmask, NULL);
213 if (!lim)
214 {
215 memory_errors(1);
216 return (FALSE);
217 }
218 lim->state_.xbm_hot_x = lim->state_.xbm_hot_y = -1;
219 lim->state_.channel = lim->image_.img[mem_channel] ? mem_channel : CHN_IMAGE;
220
221 lim->image_.trans = -1;
222 lim->image_.cols = cols;
223 if (pal) mem_pal_copy(lim->image_.pal, pal);
224 else mem_bw_pal(lim->image_.pal, 0, cols - 1);
225
226 init_istate(&lim->state_, &lim->image_);
227 update_undo(&lim->image_);
228
229 layers_total++;
230 layer_clear_slot(layers_total, TRUE);
231 layer_table[layers_total].image = lim;
232
233 /* Start with fresh animation data if new */
234 if (layers_total == 1) ani_init();
235
236 return (TRUE);
237 }
238
layer_new(int w,int h,int bpp,int cols,png_color * pal,int cmask)239 void layer_new(int w, int h, int bpp, int cols, png_color *pal, int cmask)
240 {
241 if (layer_add(w, h, bpp, cols, pal, cmask)) layer_show_new();
242 }
243
244 /* !!! Same as above: modify structures, *then* show results - WJ */
layer_press_duplicate()245 void layer_press_duplicate()
246 {
247 layer_image *lim, *ls;
248
249 if (layers_total >= MAX_LAYERS) return;
250
251 lim = alloc_layer(0, 0, 0, 0, &mem_image);
252 if (!lim)
253 {
254 memory_errors(1);
255 return;
256 }
257
258 // Copy layer info
259 layer_copy_from_main(layer_selected);
260 layers_total++;
261 layer_table[layers_total] = layer_table[layer_selected];
262 layer_table[layers_total].image = lim;
263 ls = layer_table[layer_selected].image;
264
265 lim->state_ = ls->state_;
266 mem_pal_copy(lim->image_.pal, ls->image_.pal);
267 lim->image_.cols = ls->image_.cols;
268 lim->image_.trans = ls->image_.trans;
269 update_undo(&lim->image_);
270
271 // Copy across position data
272 lim->ani_ = ls->ani_;
273
274 layer_show_new();
275 }
276
layer_delete(int item)277 void layer_delete(int item)
278 {
279 layer_image *lp = layer_table[item].image;
280 int i;
281
282 mem_free_image(&lp->image_, FREE_ALL);
283 free(lp);
284
285 // If deleted item is not at the end shuffle rest down
286 for (i = item; i < layers_total; i++)
287 layer_table[i] = layer_table[i + 1];
288 memset(layer_table + layers_total, 0, sizeof(layer_node));
289 layers_total--;
290 }
291
layer_refresh_list(int slot)292 void layer_refresh_list(int slot)
293 {
294 layers_dd *dt = GET_DDATA(layers_box_);
295
296 dt->nlayer = slot;
297 dt->lnum = layers_total + 1;
298 cmd_reset(dt->llist, dt);
299 cmd_set(dt->llist, slot); // !!! For the rest of updates
300 }
301
layer_press_delete()302 void layer_press_delete()
303 {
304 char txt[256];
305 int i;
306
307 if (!layer_selected) return; // Deleting background is forbidden
308 snprintf(txt, 256, __("Do you really want to delete layer %i (%s) ?"),
309 layer_selected, layer_table[layer_selected].name );
310
311 i = alert_box(_("Warning"), txt, _("No"), _("Yes"), NULL);
312 if ((i != 2) || (check_for_changes() == 1)) return;
313
314 if (blend_src == SRC_LAYER + layer_selected) blend_src = SRC_NORMAL;
315 layer_copy_from_main(layer_selected);
316 layer_copy_to_main(--layer_selected);
317 update_main_with_new_layer();
318 layer_delete(layer_selected + 1);
319
320 layer_refresh_list(layer_selected);
321 layers_notify_changed();
322 }
323
layer_show_position()324 static void layer_show_position()
325 {
326 layers_dd *dt = GET_DDATA(layers_box_);
327 layer_node *t = layer_table + layer_selected;
328
329 dt->lock++;
330 cmd_set(dt->xspin, t->x);
331 cmd_set(dt->yspin, t->y);
332 dt->lock--;
333 }
334
layer_show_trans()335 void layer_show_trans()
336 {
337 layers_dd *dt = GET_DDATA(layers_box_);
338
339 if (dt->trans != mem_xpm_trans)
340 {
341 dt->lock++;
342 cmd_set(dt->trspin, mem_xpm_trans);
343 dt->lock--;
344 }
345 }
346
layer_press_centre()347 void layer_press_centre()
348 {
349 if (!layer_selected) return; // Nothing to do
350 layer_table[layer_selected].x = layer_table[0].x +
351 layer_table[0].image->image_.width / 2 - mem_width / 2;
352 layer_table[layer_selected].y = layer_table[0].y +
353 layer_table[0].image->image_.height / 2 - mem_height / 2;
354 layer_show_position();
355 layers_notify_changed();
356 repaint_layers();
357 }
358
359 /* Return 1 if some layers are modified, 2 if some are nameless, 3 if both,
360 * 0 if neither */
layers_changed_tot()361 static int layers_changed_tot()
362 {
363 image_info *image;
364 int j, k;
365
366 for (j = k = 0; k <= layers_total; k++) // Check each layer for mem_changed
367 {
368 image = k == layer_selected ? &mem_image :
369 &layer_table[k].image->image_;
370 j |= !!image->changed + !image->filename * 2;
371 }
372
373 return (j);
374 }
375
check_layers_for_changes()376 int check_layers_for_changes() // 1=STOP, 2=IGNORE, -10=NOT CHANGED
377 {
378 if (!(layers_changed_tot() + layers_changed)) return (-10);
379 return (alert_box(_("Warning"),
380 _("One or more of the layers contains changes that have not been saved. Do you really want to lose these changes?"),
381 _("Cancel Operation"), _("Lose Changes"), NULL));
382 }
383
layer_update_filename(char * name)384 static void layer_update_filename( char *name )
385 {
386 strncpy(layers_filename, name, PATHBUF);
387 layers_changed = 1; // Forces update of titlebar
388 layers_notify_unchanged();
389 }
390
layers_free_all()391 static void layers_free_all()
392 {
393 layer_node *t;
394
395 if (blend_src > SRC_LAYER + 0) blend_src = SRC_NORMAL;
396
397 if (layers_total && layer_selected) // Copy over layer 0
398 {
399 layer_copy_from_main(layer_selected);
400 layer_copy_to_main(0);
401 layer_selected = 0;
402 }
403
404 for (t = layer_table + layers_total; t != layer_table; t--)
405 {
406 mem_free_image(&t->image->image_, FREE_ALL);
407 free(t->image);
408 }
409 memset(layer_table + 1, 0, sizeof(layer_node) * MAX_LAYERS);
410 layers_total = 0;
411 layers_filename[0] = 0;
412 layers_changed = 0;
413 }
414
string_chop(char * txt)415 void string_chop( char *txt )
416 {
417 char *cp = txt + strlen(txt) - 1;
418
419 // Chop off unwanted non ASCII characters at end
420 while ((cp - txt >= 0) && ((unsigned char)*cp < 32)) *cp-- = 0;
421 }
422
read_file_num(FILE * fp,char * txt)423 int read_file_num(FILE *fp, char *txt)
424 {
425 int i;
426
427 if (!fgets(txt, 32, fp)) return -987654321;
428 sscanf(txt, "%i", &i);
429
430 return i;
431 }
432
load_layers(char * file_name)433 int load_layers( char *file_name )
434 {
435 layer_node *t;
436 layer_image *lim2;
437 char tin[300], load_name[PATHBUF], *c;
438 int i, j, k, kk;
439 int layers_to_read = -1, /*layer_file_version = -1,*/ lfail = 0, lplen = 0;
440 FILE *fp;
441
442 c = strrchr(file_name, DIR_SEP);
443 if (c) lplen = c - file_name + 1;
444
445 // Try to save text file, return -1 if failure
446 if ((fp = fopen(file_name, "r")) == NULL) goto fail;
447
448 if (!fgets(tin, 32, fp)) goto fail2;
449
450 string_chop( tin );
451 if ( strcmp( tin, LAYERS_HEADER ) != 0 ) goto fail2; // Bad header
452
453 i = read_file_num(fp, tin);
454 if ( i==-987654321 ) goto fail2;
455 // layer_file_version = i;
456 if ( i>LAYERS_VERSION ) goto fail2; // Version number must be compatible
457
458 i = read_file_num(fp, tin);
459 if ( i==-987654321 ) goto fail2;
460 layers_to_read = i < MAX_LAYERS ? i : MAX_LAYERS;
461
462 /* !!! Can use lock field instead, but this is the original way */
463 cmd_sensitive(GET_WINDOW(layers_box_), FALSE);
464
465 if (layers_total) layers_free_all(); // Remove all current layers if any
466 for ( i=0; i<=layers_to_read; i++ )
467 {
468 // Read filename, strip end chars & try to load (if name length > 0)
469 fgets(tin, 256, fp);
470 string_chop(tin);
471 wjstrcat(load_name, PATHBUF, file_name, lplen, tin, NULL);
472 k = 1;
473 j = detect_image_format(load_name);
474 if ((j > 0) && (j != FT_NONE) && (j != FT_LAYERS1))
475 k = load_image(load_name, FS_LAYER_LOAD, j) != 1;
476
477 if (k) /* Failure - skip this layer */
478 {
479 for ( j=0; j<7; j++ ) read_file_num(fp, tin);
480 lfail++;
481 continue;
482 }
483
484 /* Update image variables after load */
485 t = layer_table + layers_total;
486 lim2 = t->image;
487 // !!! No old name so no fuss with saving it
488 lim2->image_.filename = strdup(load_name);
489
490 fgets(tin, 256, fp);
491 string_chop(tin);
492 strncpy0(t->name, tin, LAYER_NAMELEN);
493
494 k = read_file_num(fp, tin);
495 t->visible = k > 0;
496
497 t->x = read_file_num(fp, tin);
498 t->y = read_file_num(fp, tin);
499
500 kk = read_file_num(fp, tin);
501 k = read_file_num(fp, tin);
502 lim2->image_.trans = kk <= 0 ? -1 : k < 0 ? 0 : k > 255 ? 255 : k;
503
504 k = read_file_num(fp, tin);
505 t->opacity = k < 1 ? 1 : k > 100 ? 100 : k;
506
507 init_istate(&lim2->state_, &lim2->image_);
508 if (!layers_total++) layer_copy_to_main(0); // Update mem_state
509 }
510 if (layers_total) layers_total--;
511
512 /* Read in animation data - only if all layers loaded OK
513 * (to do otherwise is likely to result in SIGSEGV) */
514 if (!lfail) ani_read_file(fp);
515 fclose(fp);
516
517 layer_refresh_list(layers_total);
518 cmd_sensitive(GET_WINDOW(layers_box_), TRUE);
519 layer_update_filename( file_name );
520
521 if (lfail) /* There were failures */
522 {
523 snprintf(tin, 300, __("%d layers failed to load"), lfail);
524 alert_box(_("Error"), tin, NULL);
525 }
526
527 return 1; // Success
528 fail2:
529 fclose(fp);
530 fail:
531 return -1;
532 }
533
load_to_layers(char * file_name,int ftype,int ani_mode)534 int load_to_layers(char *file_name, int ftype, int ani_mode)
535 {
536 char *buf, *tail;
537 image_frame *frm;
538 image_info *image;
539 image_state *state;
540 layer_node *t;
541 layer_image *lim;
542 frameset fset;
543 int anim = ani_mode > ANM_PAGE;
544 int i, j, l, res, res0, lname;
545
546
547 /* Create buffer for name mangling */
548 lname = strlen(file_name);
549 buf = malloc(lname + 64);
550 if (!buf) return (FILE_MEM_ERROR);
551 strcpy(buf, file_name);
552 tail = buf + lname;
553
554 /* !!! Can use lock field instead, but this is the original way */
555 cmd_sensitive(GET_WINDOW(layers_box_), FALSE);
556
557 /* Remove old layers, load new frames */
558 if (layers_total) layers_free_all(); // Remove all current layers
559 res = res0 = load_frameset(&fset, ani_mode, file_name, FS_LAYER_LOAD, ftype);
560
561 if (!fset.cnt) /* Failure - we have no image */
562 {
563 if (res == FILE_LIB_ERROR) res = -1; // Failure is complete
564 }
565 else /* Got some frames - convert into layers */
566 {
567 l = 0; // Start from layer 0
568 if (anim) /* Animation */
569 {
570 int x0, y0, x1, y1, x, y;
571
572 frm = fset.frames;
573 /* Calculate a bounding box for the anim */
574 x1 = (x0 = frm->x) + frm->width;
575 y1 = (y0 = frm->y) + frm->height;
576 for (i = 1; i < fset.cnt; i++)
577 {
578 frm++;
579 x = frm->x; if (x0 > x) x0 = x;
580 x += frm->width; if (x1 < x) x1 = x;
581 y = frm->y; if (y0 > y) y0 = y;
582 y += frm->height; if (y1 < y) y1 = y;
583 }
584 /* Create an empty indexed background of that size */
585 do_new_one(x1 - x0, y1 - y0, 256, mem_pal_def, 1, FALSE);
586 /* Remember the offsets */
587 layer_table[0].x = x0;
588 layer_table[0].y = y0;
589 l = 1; // Frames start from layer 1
590 }
591
592 for (i = 0; i < fset.cnt; i++ , l++)
593 {
594 frm = fset.frames + i;
595
596 t = layer_table + l;
597 res = FILE_MEM_ERROR;
598 if (!l) // Layer 0 aka current image
599 {
600 if (mem_new(frm->width, frm->height, frm->bpp, 0))
601 break;
602 layer_copy_from_main(0);
603 }
604 else
605 {
606 if (!(t->image = alloc_layer(frm->width, frm->height,
607 frm->bpp, 0, NULL))) break;
608 }
609 res = res0;
610 lim = t->image;
611 t->visible = !anim;
612 t->opacity = 100;
613 image = &lim->image_; state = &lim->state_;
614
615 /* Move frame data to image */
616 memcpy(image->img, frm->img, sizeof(chanlist));
617 memset(frm->img, 0, sizeof(chanlist));
618 image->trans = frm->trans;
619 mem_pal_copy(image->pal, frm->pal ? frm->pal :
620 fset.pal ? fset.pal : mem_pal_def);
621 image->cols = frm->cols;
622 t->x = frm->x; t->y = frm->y;
623 update_undo(image);
624
625 /* Create a name for this frame */
626 sprintf(tail, ".%03d", i);
627 // !!! No old name so no fuss with saving it
628 image->filename = strdup(buf);
629
630 init_istate(state, image);
631 if (!l) layer_copy_to_main(0); // Update everything
632 }
633 layers_total = l ? l - 1 : 0;
634
635 if (anim)
636 {
637 // !!! These legacy things need be replaced by a per-layer field
638 preserved_gif_delay = ani_gif_delay = fset.frames[0].delay;
639
640 /* Clear stale cycles */
641 memset(ani_cycle_table, 0, sizeof(ani_cycle_table));
642 /* Build animation cycle for these layers */
643 ani_frame1 = ani_cycle_table[0].frame0 = 1;
644 ani_frame2 = ani_cycle_table[0].frame1 = l - 1;
645 ani_cycle_table[0].len = l - 1;
646 for (j = 1; j < l; j++)
647 {
648 unsigned char *cp = layer_table[j].image->ani_.cycles;
649 cp[0] = 1; // Cycle # + 1
650 cp[1] = j - 1; // Position
651 }
652
653 /* Display 1st layer in sequence */
654 layer_table[1].visible = TRUE;
655 layer_copy_from_main(0);
656 layer_copy_to_main(layer_selected = 1);
657 }
658 update_main_with_new_layer();
659 }
660 mem_free_frames(&fset);
661
662 layer_refresh_list(layer_selected);
663 cmd_sensitive(GET_WINDOW(layers_box_), TRUE);
664
665 /* Name change so that layers file would not overwrite the source */
666 strcpy(tail, ".txt");
667 layer_update_filename(buf);
668
669 free(buf);
670 return (res);
671 }
672
673 /* Convert absolute filename 'file' into one relative to prefix */
parse_filename(char * dest,char * prefix,char * file,int len)674 static void parse_filename(char *dest, char *prefix, char *file, int len)
675 {
676 int i, k;
677
678 /* # of chars that match at start */
679 for (i = 0; (i < len) && (prefix[i] == file[i]); i++);
680
681 if (!i || (i == len)) /* Complete match, or no match at all */
682 strncpy(dest, file + i, PATHBUF);
683 else /* Partial match */
684 {
685 dest[0] = 0;
686 /* Count number of DIR_SEP encountered on and after point i in
687 * 'prefix', add a '../' for each found */
688 for (k = i; k < len; k++)
689 {
690 if (prefix[k] == DIR_SEP)
691 strnncat(dest, ".." DIR_SEP_STR, PATHBUF);
692 }
693 /* nip backwards on 'file' from i to previous DIR_SEP or
694 * beginning and ... */
695 for (k = i; (k >= 0) && (file[k] != DIR_SEP); k--);
696 /* ... add rest of 'file' */
697 strnncat(dest, file + k + 1, PATHBUF);
698 }
699 }
700
layer_save_composite(char * fname,ls_settings * settings)701 int layer_save_composite(char *fname, ls_settings *settings)
702 {
703 image_info *image;
704 unsigned char *layer_rgb;
705 int w, h, res = 0, tf = comp_need_alpha(settings->ftype);
706
707 image = layer_selected ? &layer_table[0].image->image_ : &mem_image;
708 w = image->width;
709 h = image->height;
710 layer_rgb = calloc(1, w * h * (3 + !!tf));
711 if (layer_rgb)
712 {
713 view_render_rgb(layer_rgb, 0, 0, w, h, 1); // Render layer
714 if (tf)
715 {
716 unsigned char *alpha = layer_rgb + w * h * 3;
717 collect_alpha(alpha, w, h);
718 mem_demultiply(layer_rgb, alpha, w * h, 3);
719 settings->img[CHN_ALPHA] = alpha;
720 }
721 settings->img[CHN_IMAGE] = layer_rgb;
722 settings->width = w;
723 settings->height = h;
724 settings->bpp = 3;
725 if (layers_total) /* Remember global offset */
726 {
727 settings->x = layer_table[0].x;
728 settings->y = layer_table[0].y;
729 }
730 /* Set up palette to go with transparency */
731 if (settings->xpm_trans >= 0)
732 {
733 settings->pal = image->pal;
734 settings->colors = image->cols;
735 }
736 res = save_image(fname, settings);
737 free( layer_rgb );
738 }
739 else memory_errors(1);
740
741 return res;
742 }
743
layer_add_composite()744 void layer_add_composite()
745 {
746 layer_image *lim;
747 image_info *image = layer_selected ? &layer_table[0].image->image_ :
748 &mem_image;
749 unsigned char **img;
750 int w = image->width, h = image->height;
751
752 if (layers_total >= MAX_LAYERS) return;
753 if (layer_add(w, h, 3, image->cols, image->pal,
754 comp_need_alpha(FT_NONE) ? CMASK_RGBA : CMASK_IMAGE))
755 {
756 /* Render to an invisible layer */
757 layer_table[layers_total].visible = FALSE;
758 lim = layer_table[layers_total].image;
759 img = lim->image_.img;
760 view_render_rgb(img[CHN_IMAGE], 0, 0, w, h, 1);
761 /* Add alpha if wanted */
762 if (img[CHN_ALPHA])
763 {
764 collect_alpha(img[CHN_ALPHA], w, h);
765 mem_demultiply(img[CHN_IMAGE], img[CHN_ALPHA], w * h, 3);
766 }
767 /* Copy background's transparency and position */
768 lim->image_.trans = image->trans;
769 layer_table[layers_total].x = layer_table[0].x;
770 layer_table[layers_total].y = layer_table[0].y;
771 /* Activate the result */
772 layer_show_new();
773 }
774 else memory_errors(1);
775 }
776
save_layers(char * file_name)777 int save_layers( char *file_name )
778 {
779 layer_node *t;
780 char comp_name[PATHBUF], *c, *msg;
781 int i, l = 0, xpm;
782 FILE *fp;
783
784
785 layer_copy_from_main(layer_selected);
786
787 c = strrchr(file_name, DIR_SEP);
788 if (c) l = c - file_name + 1;
789
790 // Try to save text file, return -1 if failure
791 if ((fp = fopen(file_name, "w")) == NULL) goto fail;
792
793 fprintf( fp, "%s\n%i\n%i\n", LAYERS_HEADER, LAYERS_VERSION, layers_total );
794 for ( i=0; i<=layers_total; i++ )
795 {
796 t = layer_table + i;
797 parse_filename(comp_name, file_name, t->image->image_.filename, l);
798 fprintf( fp, "%s\n", comp_name );
799
800 xpm = t->image->image_.trans;
801 fprintf(fp, "%s\n%i\n%i\n%i\n%i\n%i\n%i\n", t->name,
802 t->visible, t->x, t->y, xpm >= 0, xpm, t->opacity);
803 }
804
805 ani_write_file(fp); // Write animation data
806
807 fclose(fp);
808 layer_update_filename( file_name );
809 register_file( file_name ); // Recently used file list / last directory
810
811 return 1; // Success
812 fail:
813 c = gtkuncpy(NULL, layers_filename, 0);
814 msg = g_strdup_printf(__("Unable to save file: %s"), c);
815 alert_box(_("Error"), msg, NULL);
816 g_free(msg);
817 g_free(c);
818
819 return -1;
820 }
821
822
check_layers_all_saved()823 int check_layers_all_saved()
824 {
825 if (layers_changed_tot() < 2) return (0);
826 alert_box(_("Warning"), _("One or more of the image layers has not been saved. You must save each image individually before saving the layers text file in order to load this composite image in the future."), NULL);
827 return (1);
828 }
829
layer_press_save()830 void layer_press_save()
831 {
832 if (!layers_filename[0]) file_selector(FS_LAYER_SAVE);
833 else if (!check_layers_all_saved()) save_layers(layers_filename);
834 }
835
layer_press_remove_all()836 void layer_press_remove_all()
837 {
838 int i = check_layers_for_changes();
839
840 if (i < 0) i = alert_box(_("Warning"),
841 _("Do you really want to delete all of the layers?"),
842 _("No"), _("Yes"), NULL);
843 if (i != 2) return;
844
845 layers_free_all();
846
847 layer_refresh_list(0);
848 update_main_with_new_layer();
849 }
850
layer_tog_visible(layers_dd * dt,void ** wdata,int what,void ** where,void * xdata)851 static void layer_tog_visible(layers_dd *dt, void **wdata, int what,
852 void **where, void *xdata)
853 {
854 /* !!! Column is self-reading */
855 if (dt->lock) return;
856 layers_notify_changed();
857 repaint_layer((int)xdata); // !!! row passed in there
858 }
859
layer_inputs_changed(layers_dd * dt,void ** wdata,int what,void ** where)860 static void layer_inputs_changed(layers_dd *dt, void **wdata, int what,
861 void **where)
862 {
863 layer_node *t = layer_table + layer_selected;
864 void *cause;
865 int dx, dy;
866
867 cause = cmd_read(where, dt);
868 if (cause == &show_layers_main)
869 {
870 update_stuff(UPD_RENDER);
871 return;
872 }
873 if (dt->lock) return;
874
875 layers_notify_changed();
876
877 if (cause == &dt->lname) // Name entry
878 {
879 strncpy0(t->name, dt->lname, LAYER_NAMELEN);
880 cmd_setv(dt->llist, (void *)layer_selected, LISTCC_RESET_ROW);
881 }
882 else if ((cause == &dt->x) || (cause == &dt->y)) // Position spin
883 {
884 dx = dt->x - t->x;
885 dy = dt->y - t->y;
886 if (dx | dy) move_layer_relative(layer_selected, dx, dy);
887 }
888 else if (cause == &dt->opacity) // Opacity slider
889 {
890 t->opacity = dt->opacity;
891 repaint_layer(layer_selected);
892 }
893 else if (cause == &dt->vis) // Scripted visibility toggle
894 {
895 t->visible = dt->vis;
896 cmd_setv(dt->llist, (void *)layer_selected, LISTCC_RESET_ROW);
897 repaint_layer(layer_selected);
898 }
899 else /* if (cause == &dt->trans) */ // Transparency spin
900 {
901 mem_set_trans(dt->trans);
902 }
903 }
904
layer_choose(int l)905 void layer_choose(int l) // Select a new layer from the list
906 {
907 if ((l <= layers_total) && (l >= 0) && (l != layer_selected))
908 {
909 layers_dd *dt = GET_DDATA(layers_box_);
910 cmd_set(dt->llist, l);
911 }
912 }
913
layer_select(layers_dd * dt,void ** wdata,int what,void ** where)914 static void layer_select(layers_dd *dt, void **wdata, int what, void **where)
915 {
916 layer_node *t;
917 int j;
918
919 cmd_read(where, dt);
920 if (dt->lock) return; // Paranoia
921
922 j = dt->nlayer;
923 if (j > layers_total) return; // Paranoia
924
925 dt->lock++;
926 if (j != layer_selected) /* Move data before doing anything else */
927 {
928 layer_copy_from_main(layer_selected);
929 layer_copy_to_main(layer_selected = j);
930 update_main_with_new_layer();
931 }
932
933 t = layer_table + j;
934 cmd_setv(dt->nmentry, t->name, ENTRY_VALUE);
935 cmd_sensitive(dt->ltb_raise, j < layers_total);
936 cmd_sensitive(dt->ltb_lower, j);
937 cmd_sensitive(dt->ltb_del, j);
938 cmd_sensitive(dt->ltb_center, j);
939 // Disable new/duplicate if we have max layers
940 cmd_sensitive(dt->ltb_new, layers_total < MAX_LAYERS);
941 cmd_sensitive(dt->ltb_dup, layers_total < MAX_LAYERS);
942
943 cmd_set(dt->opslider, t->opacity);
944 layer_show_position();
945 layer_show_trans();
946
947 dt->lock--;
948 }
949
delete_layers_window()950 void delete_layers_window()
951 {
952 void **wdata = layers_window_;
953
954 // No deletion if no window
955 if (!wdata) return;
956
957 layers_window_ = NULL;
958 cmd_set(menu_slots[MENU_LAYER], FALSE); // Ensure it's unchecked
959 run_destroy(wdata);
960 }
961
pressed_paste_layer()962 void pressed_paste_layer()
963 {
964 layer_image *lim;
965 unsigned char *dest;
966 int i, j, k, chan = mem_channel, cmask = CMASK_IMAGE;
967
968 if (layers_total >= MAX_LAYERS)
969 {
970 alert_box(_("Error"), _("You cannot add any more layers."), NULL);
971 return;
972 }
973
974 /* No way to put RGB clipboard into utility channel */
975 if (mem_clip_bpp == 3) chan = CHN_IMAGE;
976
977 if ((mem_clip_alpha || mem_clip_mask) && !channel_dis[CHN_ALPHA])
978 cmask = CMASK_RGBA;
979 cmask |= CMASK_FOR(chan);
980
981 if (!layer_add(mem_clip_w, mem_clip_h, mem_clip_bpp, mem_cols, mem_pal,
982 cmask)) return; // Failed
983
984 layer_table[layers_total].x = layer_table[layer_selected].x + mem_clip_x;
985 layer_table[layers_total].y = layer_table[layer_selected].y + mem_clip_y;
986 lim = layer_table[layers_total].image;
987
988 lim->state_ = mem_state;
989 lim->state_.channel = chan;
990
991 j = mem_clip_w * mem_clip_h;
992 memcpy(lim->image_.img[chan], mem_clipboard, j * mem_clip_bpp);
993
994 /* Image channel with alpha */
995 dest = lim->image_.img[CHN_ALPHA];
996 if (dest && (chan == CHN_IMAGE))
997 {
998 /* Fill alpha channel */
999 if (mem_clip_alpha) memcpy(dest, mem_clip_alpha, j);
1000 else memset(dest, 255, j);
1001 }
1002
1003 /* Image channel with mask */
1004 if (mem_clip_mask && (chan == CHN_IMAGE))
1005 {
1006 /* Mask image - fill unselected part with color A */
1007 dest = lim->image_.img[CHN_IMAGE];
1008 k = mem_clip_bpp == 1 ? mem_col_A : mem_col_A24.red;
1009 for (i = 0; i < j; i++ , dest += mem_clip_bpp)
1010 {
1011 if (mem_clip_mask[i]) continue;
1012 dest[0] = k;
1013 if (mem_clip_bpp == 1) continue;
1014 dest[1] = mem_col_A24.green;
1015 dest[2] = mem_col_A24.blue;
1016 }
1017 }
1018
1019 /* Utility channel with mask */
1020 dest = lim->image_.img[CHN_ALPHA];
1021 if (chan != CHN_IMAGE) dest = lim->image_.img[chan];
1022 if (dest && mem_clip_mask)
1023 {
1024 /* Mask the channel */
1025 for (i = 0; i < j; i++)
1026 {
1027 k = dest[i] * mem_clip_mask[i];
1028 dest[i] = (k + (k >> 8) + 1) >> 8;
1029 }
1030 }
1031
1032 set_new_filename(layers_total, NULL);
1033
1034 layer_show_new();
1035 view_show();
1036 }
1037
1038 /* Move a layer & update window labels */
move_layer_relative(int l,int change_x,int change_y)1039 void move_layer_relative(int l, int change_x, int change_y)
1040 {
1041 image_info *image = l == layer_selected ? &mem_image :
1042 &layer_table[l].image->image_;
1043 int upd = 0;
1044
1045 layer_table[l].x += change_x;
1046 layer_table[l].y += change_y;
1047
1048 layers_notify_changed();
1049 if (l == layer_selected)
1050 {
1051 layer_show_position();
1052 // All layers get moved while the current one stays still
1053 if (show_layers_main) upd |= UPD_RENDER;
1054 }
1055 // All layers get moved while the background stays still
1056 if (l == 0) upd |= UPD_VIEW;
1057
1058 lr_update_area(l, change_x < 0 ? 0 : -change_x, change_y < 0 ? 0 : -change_y,
1059 image->width + abs(change_x), image->height + abs(change_y));
1060 if (upd) update_stuff(upd);
1061 }
1062
layer_bar_click(layers_dd * dt,void ** wdata,int what,void ** where)1063 static void layer_bar_click(layers_dd *dt, void **wdata, int what, void **where)
1064 {
1065 int act_m = TOOL_ID(where);
1066
1067 action_dispatch(act_m >> 16, (act_m & 0xFFFF) - 0x8000, TRUE, FALSE);
1068 }
1069
1070 #define WBbase layers_dd
1071 static void *layers_code[] = {
1072 TOPVBOX,
1073 SCRIPTED, BORDER(SCROLL, 0), BORDER(LISTCC, 0),
1074 XSCROLL(1, 1), // auto/auto
1075 WLIST,
1076 IDXCOLUMN(0, 1, 40, 1), // center
1077 XTXTCOLUMNv(layer_table[0].name, sizeof(layer_table[0]), 0, 0), // left
1078 CHKCOLUMNv(layer_table[0].visible, sizeof(layer_table[0]), 0, 0,
1079 layer_tog_visible),
1080 REF(llist), LISTCCHr(nlayer, lnum, MAX_LAYERS + 1, layer_select), TRIGGER,
1081 BORDER(TOOLBAR, 0),
1082 TOOLBAR(layer_bar_click),
1083 REF(ltb_new), TBBUTTON(_("New Layer"), XPM_ICON(new),
1084 ACTMOD(ACT_LR_ADD, LR_NEW)),
1085 REF(ltb_raise), TBBUTTON(_("Raise"), XPM_ICON(up),
1086 ACTMOD(ACT_LR_SHIFT, 1)),
1087 REF(ltb_lower), TBBUTTON(_("Lower"), XPM_ICON(down),
1088 ACTMOD(ACT_LR_SHIFT, -1)),
1089 REF(ltb_dup), TBBUTTON(_("Duplicate Layer"), XPM_ICON(copy),
1090 ACTMOD(ACT_LR_ADD, LR_DUP)),
1091 REF(ltb_center), TBBUTTON(_("Centralise Layer"), XPM_ICON(centre),
1092 ACTMOD(ACT_LR_CENTER, 0)),
1093 REF(ltb_del), TBBUTTON(_("Delete Layer"), XPM_ICON(cut),
1094 ACTMOD(ACT_LR_DEL, 0)),
1095 REF(ltb_close), TBBUTTON(_("Close Layers Window"), XPM_ICON(close),
1096 ACTMOD(DLG_LAYERS, 1)), UNNAME,
1097 WDONE,
1098 TABLEs(3, 4, 5),
1099 BORDER(LABEL, 0), BORDER(ENTRY, 0),
1100 BORDER(SPIN, 0), BORDER(SPINSLIDE, 0),
1101 TLABEL(_("Layer Name")),
1102 REF(nmentry), MINWIDTH(100), TLENTRY(lname, LAYER_NAMELEN - 1, 1, 0, 2),
1103 EVENT(CHANGE, layer_inputs_changed),
1104 TLABEL(_("Position")),
1105 REF(xspin), TLSPIN(x, -MAX_WIDTH, MAX_WIDTH, 1, 1),
1106 EVENT(CHANGE, layer_inputs_changed), OPNAME("X"),
1107 REF(yspin), TLSPIN(y, -MAX_HEIGHT, MAX_HEIGHT, 2, 1),
1108 EVENT(CHANGE, layer_inputs_changed), OPNAME("Y"),
1109 TLABEL(_("Opacity")),
1110 REF(opslider), TLSPINSLIDExl(opacity, 0, 100, 1, 2, 2),
1111 EVENT(CHANGE, layer_inputs_changed),
1112 TLLABELl(_("Transparent Colour"), 0, 3, 2),
1113 REF(trspin), TLSPIN(trans, -1, 255, 2, 3),
1114 EVENT(CHANGE, layer_inputs_changed),
1115 uCHECK("Visible", vis), EVENT(SCRIPT, layer_inputs_changed),
1116 WDONE,
1117 CHECKv(_("Show all layers in main window"), show_layers_main),
1118 EVENT(CHANGE, layer_inputs_changed), UNNAME,
1119 WEND
1120 };
1121 #undef WBbase
1122
create_layers_box()1123 void **create_layers_box()
1124 {
1125 static char *noscript;
1126 layers_dd tdata;
1127 void **res;
1128
1129 memset(&tdata, 0, sizeof(tdata));
1130 tdata.nlayer = layer_selected;
1131 tdata.lnum = layers_total + 1;
1132 tdata.lname = "";
1133 layers_box_ = res = run_create_(layers_code, &tdata, sizeof(tdata),
1134 cmd_mode ? &noscript : NULL);
1135
1136 return (res);
1137 }
1138
1139 static void *layersw_code[] = {
1140 WPWHEREVER, WINDOW(""), EVENT(CANCEL, delete_layers_window),
1141 WXYWH("layers", 400, 400),
1142 REMOUNTv(layers_dock),
1143 WSHOW
1144 };
1145
pressed_layers()1146 void pressed_layers()
1147 {
1148 void **res;
1149
1150 if (cmd_mode) return;
1151 if (layers_window_) return; // Already have it open
1152 layers_window_ = res = run_create(layersw_code, layersw_code, 0);
1153
1154 layers_update_titlebar();
1155
1156 cmd_setv(GET_WINDOW(res),
1157 ((layers_dd *)GET_DDATA(layers_box_))->ltb_close, WINDOW_ESC_BTN);
1158 }
1159