xcf-save.cpp
1/* The GIMP -- an image manipulation program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include "config.h"
20
21#include <stdio.h>
22#include <string.h> /* strcpy, strlen */
23
24#include <glib-object.h>
25
26#include "libgimpbase/gimpbase.h"
27#include "libgimpcolor/gimpcolor.h"
28
29#include "core/core-types.h"
30
31#include "base/tile.h"
32#include "base/tile-manager.h"
33#include "base/tile-manager-private.h"
34
35#include "core/gimpchannel.h"
36#include "core/gimpdrawable.h"
37#include "core/gimpgrid.h"
38#include "core/gimpimage.h"
39#include "core/gimpimage-grid.h"
40#include "core/gimpimage-guides.h"
41#include "core/gimplayer.h"
42#include "core/gimplayer-floating-sel.h"
43#include "core/gimplayermask.h"
44#include "core/gimplist.h"
45#include "core/gimpparasitelist.h"
46#include "core/gimpunit.h"
47
48#include "text/gimptextlayer.h"
49#include "text/gimptextlayer-xcf.h"
50
51#include "vectors/gimpanchor.h"
52#include "vectors/gimpstroke.h"
53#include "vectors/gimpbezierstroke.h"
54#include "vectors/gimpvectors.h"
55#include "vectors/gimpvectors-compat.h"
56
57#include "xcf-private.h"
58#include "xcf-read.h"
59#include "xcf-seek.h"
60#include "xcf-write.h"
61
62#include "gimp-intl.h"
63
64
65static bool xcf_save_image_props (XcfInfo *info,
66 KisImage *gimage,
67 GError **error);
68static bool xcf_save_layer_props (XcfInfo *info,
69 KisImage *gimage,
70 KisLayer *layer,
71 GError **error);
72static bool xcf_save_channel_props (XcfInfo *info,
73 KisImage *gimage,
74 GimpChannel *channel,
75 GError **error);
76static bool xcf_save_prop (XcfInfo *info,
77 KisImage *gimage,
78 PropType prop_type,
79 GError **error,
80 ...);
81static bool xcf_save_layer (XcfInfo *info,
82 KisImage *gimage,
83 KisLayer *layer,
84 GError **error);
85static bool xcf_save_channel (XcfInfo *info,
86 KisImage *gimage,
87 GimpChannel *channel,
88 GError **error);
89static bool xcf_save_hierarchy (XcfInfo *info,
90 TileManager *tiles,
91 GError **error);
92static bool xcf_save_level (XcfInfo *info,
93 TileManager *tiles,
94 GError **error);
95static bool xcf_save_tile (XcfInfo *info,
96 Tile *tile,
97 GError **error);
98static bool xcf_save_tile_rle (XcfInfo *info,
99 Tile *tile,
100 guchar *rlebuf,
101 GError **error);
102static bool xcf_save_parasite (XcfInfo *info,
103 KisAnnotation *parasite,
104 GError **error);
105static bool xcf_save_parasite_list (XcfInfo *info,
106 KisAnnotationList *parasite,
107 GError **error);
108static bool xcf_save_old_paths (XcfInfo *info,
109 KisImage *gimage,
110 GError **error);
111static bool xcf_save_vectors (XcfInfo *info,
112 KisImage *gimage,
113 GError **error);
114
115
116/* private convenience macros */
117#define xcf_write_int32_check_error(info, data, count) G_STMT_START { \
118 info->cp += xcf_write_int32 (info->fp, data, count, &tmp_error); \
119 if (tmp_error) \
120 { \
121 g_propagate_error (error, tmp_error); \
122 return false; \
123 } \
124 } G_STMT_END
125
126#define xcf_write_int8_check_error(info, data, count) G_STMT_START { \
127 info->cp += xcf_write_int8 (info->fp, data, count, &tmp_error); \
128 if (tmp_error) \
129 { \
130 g_propagate_error (error, tmp_error); \
131 return false; \
132 } \
133 } G_STMT_END
134
135#define xcf_write_float_check_error(info, data, count) G_STMT_START { \
136 info->cp += xcf_write_float (info->fp, data, count, &tmp_error); \
137 if (tmp_error) \
138 { \
139 g_propagate_error (error, tmp_error); \
140 return false; \
141 } \
142 } G_STMT_END
143
144#define xcf_write_string_check_error(info, data, count) G_STMT_START { \
145 info->cp += xcf_write_string (info->fp, data, count, &tmp_error); \
146 if (tmp_error) \
147 { \
148 g_propagate_error (error, tmp_error); \
149 return false; \
150 } \
151 } G_STMT_END
152
153#define xcf_write_int32_print_error(info, data, count) G_STMT_START { \
154 info->cp += xcf_write_int32 (info->fp, data, count, &error); \
155 if (error) \
156 { \
157 g_message (_("Error saving XCF file: %s"), \
158 error->message); \
159 return false; \
160 } \
161 } G_STMT_END
162
163#define xcf_write_int8_print_error(info, data, count) G_STMT_START { \
164 info->cp += xcf_write_int8 (info->fp, data, count, &error); \
165 if (error) \
166 { \
167 g_message (_("Error saving XCF file: %s"), \
168 error->message); \
169 return false; \
170 } \
171 } G_STMT_END
172
173#define xcf_write_float_print_error(info, data, count) G_STMT_START { \
174 info->cp += xcf_write_float (info->fp, data, count, &error); \
175 if (error) \
176 { \
177 g_message (_("Error saving XCF file: %s"), \
178 error->message); \
179 return false; \
180 } \
181 } G_STMT_END
182
183#define xcf_write_string_print_error(info, data, count) G_STMT_START { \
184 info->cp += xcf_write_string (info->fp, data, count, &error); \
185 if (error) \
186 { \
187 g_message (_("Error saving XCF file: %s"), \
188 error->message); \
189 return false; \
190 } \
191 } G_STMT_END
192
193#define xcf_write_prop_type_check_error(info, prop_type) G_STMT_START { \
194 TQ_INT32 _prop_int32 = prop_type; \
195 xcf_write_int32_check_error (info, &_prop_int32, 1); \
196 } G_STMT_END
197
198#define xcf_write_prop_type_print_error(info, prop_type) G_STMT_START { \
199 TQ_INT32 _prop_int32 = prop_type; \
200 xcf_write_int32_print_error (info, &_prop_int32, 1); \
201 } G_STMT_END
202
203#define xcf_check_error(x) G_STMT_START { \
204 if (! (x)) \
205 return false; \
206 } G_STMT_END
207
208#define xcf_print_error(x) G_STMT_START { \
209 if (! (x)) \
210 { \
211 g_message (_("Error saving XCF file: %s"), \
212 error->message); \
213 return false; \
214 } \
215 } G_STMT_END
216
217
218void
219xcf_save_choose_format (XcfInfo *info,
220 KisImage *gimage)
221{
222 KisLayer *layer;
223 GList *list;
224
225 TQ_INT32 save_version = 0; /* default to oldest */
226
227 if (gimage->cmap)
228 save_version = 1; /* need version 1 for colormaps */
229
230 for (list = GIMP_LIST (gimage->layers)->list;
231 list && save_version < 2;
232 list = g_list_next (list))
233 {
234 layer = GIMP_LAYER (list->data);
235
236 switch (layer->mode)
237 {
238 /* new layer modes not supported by gimp-1.2 */
239 case GIMP_SOFTLIGHT_MODE:
240 case GIMP_GRAIN_EXTRACT_MODE:
241 case GIMP_GRAIN_MERGE_MODE:
242 case GIMP_COLOR_ERASE_MODE:
243 save_version = 2;
244 break;
245
246 default:
247 break;
248 }
249 }
250
251 info->file_version = save_version;
252}
253
254TQ_INT32
255xcf_save_image (XcfInfo *info,
256 KisImage *gimage)
257{
258 KisLayer *layer;
259 KisLayer *floating_layer;
260 GimpChannel *channel;
261 TQ_INT32 saved_pos;
262 TQ_INT32 offset;
263 TQ_UINT32 nlayers;
264 TQ_UINT32 nchannels;
265 GList *list;
266 bool have_selection;
267 TQ_INT32 t1, t2, t3, t4;
268 TQCString version_tag[14];
269 GError *error = NULL;
270
271 floating_layer = gimp_image_floating_sel (gimage);
272 if (floating_layer)
273 floating_sel_relax (floating_layer, FALSE);
274
275 /* write out the tag information for the image */
276 if (info->file_version > 0)
277 {
278 sprintf (version_tag, "gimp xcf v%03d", info->file_version);
279 }
280 else
281 {
282 strcpy (version_tag, "gimp xcf file");
283 }
284 xcf_write_int8_print_error (info, (TQ_UINT8 *) version_tag, 14);
285
286 /* write out the width, height and image type information for the image */
287 xcf_write_int32_print_error (info, (TQ_INT32 *) &gimage->width, 1);
288 xcf_write_int32_print_error (info, (TQ_INT32 *) &gimage->height, 1);
289 xcf_write_int32_print_error (info, (TQ_INT32 *) &gimage->base_type, 1);
290
291 /* determine the number of layers and channels in the image */
292 nlayers = (TQ_UINT32) gimp_container_num_children (gimage->layers);
293 nchannels = (TQ_UINT32) gimp_container_num_children (gimage->channels);
294
295 /* check and see if we have to save out the selection */
296 have_selection = gimp_channel_bounds (gimp_image_get_mask (gimage),
297 &t1, &t2, &t3, &t4);
298 if (have_selection)
299 nchannels += 1;
300
301 /* write the property information for the image.
302 */
303
304 xcf_print_error (xcf_save_image_props (info, gimage, &error));
305
306 /* save the current file position as it is the start of where
307 * we place the layer offset information.
308 */
309 saved_pos = info->cp;
310
311 /* seek to after the offset lists */
312 xcf_print_error (xcf_seek_pos (info,
313 info->cp + (nlayers + nchannels + 2) * 4,
314 &error));
315
316 for (list = GIMP_LIST (gimage->layers)->list;
317 list;
318 list = g_list_next (list))
319 {
320 layer = (KisLayer *) list->data;
321
322 /* save the start offset of where we are writing
323 * out the next layer.
324 */
325 offset = info->cp;
326
327 /* write out the layer. */
328 xcf_print_error (xcf_save_layer (info, gimage, layer, &error));
329
330 /* seek back to where we are to write out the next
331 * layer offset and write it out.
332 */
333 xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
334 xcf_write_int32_print_error (info, &offset, 1);
335
336 /* increment the location we are to write out the
337 * next offset.
338 */
339 saved_pos = info->cp;
340
341 /* seek to the end of the file which is where
342 * we will write out the next layer.
343 */
344 xcf_print_error (xcf_seek_end (info, &error));
345 }
346
347 /* write out a '0' offset position to indicate the end
348 * of the layer offsets.
349 */
350 offset = 0;
351 xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
352 xcf_write_int32_print_error (info, &offset, 1);
353 saved_pos = info->cp;
354 xcf_print_error (xcf_seek_end (info, &error));
355
356 list = GIMP_LIST (gimage->channels)->list;
357
358 while (list || have_selection)
359 {
360 if (list)
361 {
362 channel = (GimpChannel *) list->data;
363
364 list = g_list_next (list);
365 }
366 else
367 {
368 channel = gimage->selection_mask;
369 have_selection = false;
370 }
371
372 /* save the start offset of where we are writing
373 * out the next channel.
374 */
375 offset = info->cp;
376
377 /* write out the layer. */
378 xcf_print_error (xcf_save_channel (info, gimage, channel, &error));
379
380 /* seek back to where we are to write out the next
381 * channel offset and write it out.
382 */
383 xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
384 xcf_write_int32_print_error (info, &offset, 1);
385
386 /* increment the location we are to write out the
387 * next offset.
388 */
389 saved_pos = info->cp;
390
391 /* seek to the end of the file which is where
392 * we will write out the next channel.
393 */
394 xcf_print_error (xcf_seek_end (info, &error));
395 }
396
397 /* write out a '0' offset position to indicate the end
398 * of the channel offsets.
399 */
400 offset = 0;
401 xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
402 xcf_write_int32_print_error (info, &offset, 1);
403 saved_pos = info->cp;
404
405 if (floating_layer)
406 floating_sel_rigor (floating_layer, FALSE);
407
408 return !ferror(info->fp);
409}
410
411static bool
412xcf_save_image_props (XcfInfo *info,
413 KisImage *gimage,
414 GError **error)
415{
416 KisAnnotation *parasite = NULL;
417 GimpUnit unit = gimp_image_get_unit (gimage);
418
419 /* check and see if we should save the colormap property */
420 if (gimage->cmap)
421 xcf_check_error (xcf_save_prop (info, gimage, PROP_COLORMAP, error,
422 gimage->num_cols, gimage->cmap));
423
424 if (info->compression != COMPRESS_NONE)
425 xcf_check_error (xcf_save_prop (info, gimage, PROP_COMPRESSION,
426 error, info->compression));
427
428 if (gimage->guides)
429 xcf_check_error (xcf_save_prop (info, gimage, PROP_GUIDES,
430 error, gimage->guides));
431
432 xcf_check_error (xcf_save_prop (info, gimage, PROP_RESOLUTION, error,
433 gimage->xresolution, gimage->yresolution));
434
435 xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
436 gimage->tattoo_state));
437
438 if (gimp_parasite_list_length (gimage->parasites) > 0)
439 xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES,
440 error, gimage->parasites));
441
442 if (unit < _gimp_unit_get_number_of_built_in_units (gimage->gimp))
443 xcf_check_error (xcf_save_prop (info, gimage, PROP_UNIT, error, unit));
444
445 if (gimp_container_num_children (gimage->vectors) > 0)
446 {
447 if (gimp_vectors_compat_is_compatible (gimage))
448 xcf_check_error (xcf_save_prop (info, gimage, PROP_PATHS, error));
449 else
450 xcf_check_error (xcf_save_prop (info, gimage, PROP_VECTORS, error));
451 }
452
453 if (unit >= _gimp_unit_get_number_of_built_in_units (gimage->gimp))
454 xcf_check_error (xcf_save_prop (info, gimage, PROP_USER_UNIT, error, unit));
455
456 if (GIMP_IS_GRID (gimage->grid))
457 {
458 GimpGrid *grid = gimp_image_get_grid (gimage);
459
460 parasite = gimp_grid_to_parasite (grid);
461 gimp_parasite_list_add (GIMP_IMAGE (gimage)->parasites, parasite);
462 }
463
464 if (gimp_parasite_list_length (GIMP_IMAGE (gimage)->parasites) > 0)
465 {
466 xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
467 GIMP_IMAGE (gimage)->parasites));
468 }
469
470 if (parasite)
471 {
472 gimp_parasite_list_remove (GIMP_IMAGE (gimage)->parasites,
473 gimp_parasite_name (parasite));
474 gimp_parasite_free (parasite);
475 }
476
477 xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
478
479 return true;
480}
481
482static bool
483xcf_save_layer_props (XcfInfo *info,
484 KisImage *gimage,
485 KisLayer *layer,
486 GError **error)
487{
488 KisAnnotation *parasite = NULL;
489
490 if (layer == gimp_image_get_active_layer (gimage))
491 xcf_check_error (xcf_save_prop (info, gimage, PROP_ACTIVE_LAYER, error));
492
493 if (layer == gimp_image_floating_sel (gimage))
494 {
495 info->floating_sel_drawable = layer->fs.drawable;
496 xcf_check_error (xcf_save_prop (info, gimage, PROP_FLOATING_SELECTION,
497 error));
498 }
499
500 xcf_check_error (xcf_save_prop (info, gimage, PROP_OPACITY, error,
501 layer->opacity));
502 xcf_check_error (xcf_save_prop (info, gimage, PROP_VISIBLE, error,
503 gimp_item_get_visible (GIMP_ITEM (layer))));
504 xcf_check_error (xcf_save_prop (info, gimage, PROP_LINKED, error,
505 gimp_item_get_linked (GIMP_ITEM (layer))));
506 xcf_check_error (xcf_save_prop (info, gimage, PROP_LOCK_ALPHA,
507 error, layer->lock_alpha));
508
509 if (layer->mask)
510 {
511 xcf_check_error (xcf_save_prop (info, gimage, PROP_APPLY_MASK,
512 error, layer->mask->apply_mask));
513 xcf_check_error (xcf_save_prop (info, gimage, PROP_EDIT_MASK,
514 error, layer->mask->edit_mask));
515 xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASK,
516 error, layer->mask->show_mask));
517 }
518 else
519 {
520 xcf_check_error (xcf_save_prop (info, gimage, PROP_APPLY_MASK,
521 error, FALSE));
522 xcf_check_error (xcf_save_prop (info, gimage, PROP_EDIT_MASK,
523 error, FALSE));
524 xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASK,
525 error, FALSE));
526 }
527
528 xcf_check_error (xcf_save_prop (info, gimage, PROP_OFFSETS, error,
529 GIMP_ITEM (layer)->offset_x,
530 GIMP_ITEM (layer)->offset_y));
531 xcf_check_error (xcf_save_prop (info, gimage, PROP_MODE, error,
532 layer->mode));
533 xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
534 GIMP_ITEM (layer)->tattoo));
535
536 if (GIMP_IS_TEXT_LAYER (layer) && GIMP_TEXT_LAYER (layer)->text)
537 {
538 GimpTextLayer *text_layer = GIMP_TEXT_LAYER (layer);
539 TQ_INT32 flags = gimp_text_layer_get_xcf_flags (text_layer);
540
541 gimp_text_layer_xcf_save_prepare (text_layer);
542
543 if (flags)
544 xcf_check_error (xcf_save_prop (info,
545 gimage, PROP_TEXT_LAYER_FLAGS, error,
546 flags));
547 }
548
549 if (gimp_parasite_list_length (GIMP_ITEM (layer)->parasites) > 0)
550 {
551 xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
552 GIMP_ITEM (layer)->parasites));
553 }
554
555 if (parasite)
556 {
557 gimp_parasite_list_remove (GIMP_ITEM (layer)->parasites,
558 gimp_parasite_name (parasite));
559 gimp_parasite_free (parasite);
560 }
561
562 xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
563
564 return true;
565}
566
567static bool
568xcf_save_channel_props (XcfInfo *info,
569 KisImage *gimage,
570 GimpChannel *channel,
571 GError **error)
572{
573 guchar col[3];
574
575 if (channel == gimp_image_get_active_channel (gimage))
576 xcf_check_error (xcf_save_prop (info, gimage, PROP_ACTIVE_CHANNEL, error));
577
578 if (channel == gimage->selection_mask)
579 xcf_check_error (xcf_save_prop (info, gimage, PROP_SELECTION, error));
580
581 xcf_check_error (xcf_save_prop (info, gimage, PROP_OPACITY, error,
582 channel->color.a));
583 xcf_check_error (xcf_save_prop (info, gimage, PROP_VISIBLE, error,
584 gimp_item_get_visible (GIMP_ITEM (channel))));
585 xcf_check_error (xcf_save_prop (info, gimage, PROP_LINKED, error,
586 gimp_item_get_linked (GIMP_ITEM (channel))));
587 xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASKED, error,
588 channel->show_masked));
589
590 gimp_rgb_get_uchar (&channel->color, &col[0], &col[1], &col[2]);
591 xcf_check_error (xcf_save_prop (info, gimage, PROP_COLOR, error, col));
592
593 xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
594 GIMP_ITEM (channel)->tattoo));
595
596 if (gimp_parasite_list_length (GIMP_ITEM (channel)->parasites) > 0)
597 xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
598 GIMP_ITEM (channel)->parasites));
599
600 xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
601
602 return true;
603}
604
605static bool
606xcf_save_prop (XcfInfo *info,
607 KisImage *gimage,
608 PropType prop_type,
609 GError **error,
610 ...)
611{
612 TQ_INT32 size;
613 va_list args;
614
615 GError *tmp_error = NULL;
616
617 va_start (args, error);
618
619 switch (prop_type)
620 {
621 case PROP_END:
622 size = 0;
623
624 xcf_write_prop_type_check_error (info, prop_type);
625 xcf_write_int32_check_error (info, &size, 1);
626 break;
627
628 case PROP_COLORMAP:
629 {
630 TQ_INT32 ncolors;
631 guchar *colors;
632
633 ncolors = va_arg (args, TQ_INT32);
634 colors = va_arg (args, guchar*);
635 size = 4 + ncolors * 3;
636
637 xcf_write_prop_type_check_error (info, prop_type);
638 xcf_write_int32_check_error (info, &size, 1);
639 xcf_write_int32_check_error (info, &ncolors, 1);
640 xcf_write_int8_check_error (info, colors, ncolors * 3);
641 }
642 break;
643
644 case PROP_ACTIVE_LAYER:
645 case PROP_ACTIVE_CHANNEL:
646 case PROP_SELECTION:
647 size = 0;
648
649 xcf_write_prop_type_check_error (info, prop_type);
650 xcf_write_int32_check_error (info, &size, 1);
651 break;
652
653 case PROP_FLOATING_SELECTION:
654 {
655 TQ_INT32 dummy;
656
657 dummy = 0;
658 size = 4;
659
660 xcf_write_prop_type_check_error (info, prop_type);
661 xcf_write_int32_check_error (info, &size, 1);
662 info->floating_sel_offset = info->cp;
663 xcf_write_int32_check_error (info, &dummy, 1);
664 }
665 break;
666
667 case PROP_OPACITY:
668 {
669 gdouble opacity;
670 TQ_INT32 uint_opacity;
671
672 opacity = va_arg (args, gdouble);
673
674 uint_opacity = opacity * 255.999;
675
676 size = 4;
677
678 xcf_write_prop_type_check_error (info, prop_type);
679 xcf_write_int32_check_error (info, &size, 1);
680 xcf_write_int32_check_error (info, &uint_opacity, 1);
681 }
682 break;
683
684 case PROP_MODE:
685 {
686 TQ_INT3232 mode;
687
688 mode = va_arg (args, TQ_INT3232);
689 size = 4;
690
691 xcf_write_prop_type_check_error (info, prop_type);
692 xcf_write_int32_check_error (info, &size, 1);
693 xcf_write_int32_check_error (info, (TQ_INT32 *) &mode, 1);
694 }
695 break;
696
697 case PROP_VISIBLE:
698 {
699 TQ_INT32 visible;
700
701 visible = va_arg (args, TQ_INT32);
702 size = 4;
703
704 xcf_write_prop_type_check_error (info, prop_type);
705 xcf_write_int32_check_error (info, &size, 1);
706 xcf_write_int32_check_error (info, &visible, 1);
707 }
708 break;
709
710 case PROP_LINKED:
711 {
712 TQ_INT32 linked;
713
714 linked = va_arg (args, TQ_INT32);
715 size = 4;
716
717 xcf_write_prop_type_check_error (info, prop_type);
718 xcf_write_int32_check_error (info, &size, 1);
719 xcf_write_int32_check_error (info, &linked, 1);
720 }
721 break;
722
723 case PROP_LOCK_ALPHA:
724 {
725 TQ_INT32 lock_alpha;
726
727 lock_alpha = va_arg (args, TQ_INT32);
728 size = 4;
729
730 xcf_write_prop_type_check_error (info, prop_type);
731 xcf_write_int32_check_error (info, &size, 1);
732 xcf_write_int32_check_error (info, &lock_alpha, 1);
733 }
734 break;
735
736 case PROP_APPLY_MASK:
737 {
738 TQ_INT32 apply_mask;
739
740 apply_mask = va_arg (args, TQ_INT32);
741 size = 4;
742
743 xcf_write_prop_type_check_error (info, prop_type);
744 xcf_write_int32_check_error (info, &size, 1);
745 xcf_write_int32_check_error (info, &apply_mask, 1);
746 }
747 break;
748
749 case PROP_EDIT_MASK:
750 {
751 TQ_INT32 edit_mask;
752
753 edit_mask = va_arg (args, TQ_INT32);
754 size = 4;
755
756 xcf_write_prop_type_check_error (info, prop_type);
757 xcf_write_int32_check_error (info, &size, 1);
758 xcf_write_int32_check_error (info, &edit_mask, 1);
759 }
760 break;
761
762 case PROP_SHOW_MASK:
763 {
764 TQ_INT32 show_mask;
765
766 show_mask = va_arg (args, TQ_INT32);
767 size = 4;
768
769 xcf_write_prop_type_check_error (info, prop_type);
770 xcf_write_int32_check_error (info, &size, 1);
771 xcf_write_int32_check_error (info, &show_mask, 1);
772 }
773 break;
774
775 case PROP_SHOW_MASKED:
776 {
777 TQ_INT32 show_masked;
778
779 show_masked = va_arg (args, TQ_INT32);
780 size = 4;
781
782 xcf_write_prop_type_check_error (info, prop_type);
783 xcf_write_int32_check_error (info, &size, 1);
784 xcf_write_int32_check_error (info, &show_masked, 1);
785 }
786 break;
787
788 case PROP_OFFSETS:
789 {
790 TQ_INT3232 offsets[2];
791
792 offsets[0] = va_arg (args, TQ_INT3232);
793 offsets[1] = va_arg (args, TQ_INT3232);
794 size = 8;
795
796 xcf_write_prop_type_check_error (info, prop_type);
797 xcf_write_int32_check_error (info, &size, 1);
798 xcf_write_int32_check_error (info, (TQ_INT32 *) offsets, 2);
799 }
800 break;
801
802 case PROP_COLOR:
803 {
804 guchar *color;
805
806 color = va_arg (args, guchar*);
807 size = 3;
808
809 xcf_write_prop_type_check_error (info, prop_type);
810 xcf_write_int32_check_error (info, &size, 1);
811 xcf_write_int8_check_error (info, color, 3);
812 }
813 break;
814
815 case PROP_COMPRESSION:
816 {
817 TQ_UINT8 compression;
818
819 compression = (TQ_UINT8) va_arg (args, TQ_INT32);
820 size = 1;
821
822 xcf_write_prop_type_check_error (info, prop_type);
823 xcf_write_int32_check_error (info, &size, 1);
824 xcf_write_int8_check_error (info, &compression, 1);
825 }
826 break;
827
828 case PROP_GUIDES:
829 {
830 GList *guides;
831 GimpGuide *guide;
832 TQ_INT3232 position;
833 TQ_INT328 orientation;
834 TQ_INT32 nguides;
835
836 guides = va_arg (args, GList *);
837 nguides = g_list_length (guides);
838
839 size = nguides * (4 + 1);
840
841 xcf_write_prop_type_check_error (info, prop_type);
842 xcf_write_int32_check_error (info, &size, 1);
843
844 for (; guides; guides = g_list_next (guides))
845 {
846 guide = (GimpGuide *) guides->data;
847
848 position = guide->position;
849
850 switch (guide->orientation)
851 {
852 case GIMP_ORIENTATION_HORIZONTAL:
853 orientation = XCF_ORIENTATION_HORIZONTAL;
854 break;
855
856 case GIMP_ORIENTATION_VERTICAL:
857 orientation = XCF_ORIENTATION_VERTICAL;
858 break;
859
860 default:
861 g_warning ("%s: skipping guide with bad orientation",
862 G_STRFUNC);
863 continue;
864 }
865
866 xcf_write_int32_check_error (info, (TQ_INT32 *) &position, 1);
867 xcf_write_int8_check_error (info, (TQ_UINT8 *) &orientation, 1);
868 }
869 }
870 break;
871
872 case PROP_RESOLUTION:
873 {
874 float xresolution, yresolution;
875
876 /* we pass in floats,
877 but they are promoted to double by the compiler */
878 xresolution = va_arg (args, double);
879 yresolution = va_arg (args, double);
880
881 size = 4*2;
882
883 xcf_write_prop_type_check_error (info, prop_type);
884 xcf_write_int32_check_error (info, &size, 1);
885
886 xcf_write_float_check_error (info, &xresolution, 1);
887 xcf_write_float_check_error (info, &yresolution, 1);
888 }
889 break;
890
891 case PROP_TATTOO:
892 {
893 TQ_INT32 tattoo;
894
895 tattoo = va_arg (args, TQ_INT32);
896 size = 4;
897
898 xcf_write_prop_type_check_error (info, prop_type);
899 xcf_write_int32_check_error (info, &size, 1);
900 xcf_write_int32_check_error (info, &tattoo, 1);
901 }
902 break;
903
904 case PROP_PARASITES:
905 {
906 KisAnnotationList *list;
907 TQ_INT32 base, length;
908 long pos;
909
910 list = va_arg (args, KisAnnotationList *);
911
912 if (gimp_parasite_list_persistent_length (list) > 0)
913 {
914 xcf_write_prop_type_check_error (info, prop_type);
915
916 /* because we don't know how much room the parasite list will take
917 * we save the file position and write the length later
918 */
919 pos = info->cp;
920 xcf_write_int32_check_error (info, &length, 1);
921 base = info->cp;
922
923 xcf_check_error (xcf_save_parasite_list (info, list, error));
924
925 length = info->cp - base;
926 /* go back to the saved position and write the length */
927 xcf_check_error (xcf_seek_pos (info, pos, error));
928 xcf_write_int32 (info->fp, &length, 1, &tmp_error);
929 if (tmp_error)
930 {
931 g_propagate_error (error, tmp_error);
932 return false;
933 }
934
935 xcf_check_error (xcf_seek_end (info, error));
936 }
937 }
938 break;
939
940 case PROP_UNIT:
941 {
942 TQ_INT32 unit;
943
944 unit = va_arg (args, TQ_INT32);
945
946 size = 4;
947
948 xcf_write_prop_type_check_error (info, prop_type);
949 xcf_write_int32_check_error (info, &size, 1);
950 xcf_write_int32_check_error (info, &unit, 1);
951 }
952 break;
953
954 case PROP_PATHS:
955 {
956 TQ_INT32 base, length;
957 glong pos;
958
959 xcf_write_prop_type_check_error (info, prop_type);
960
961 /* because we don't know how much room the paths list will take
962 * we save the file position and write the length later
963 */
964 pos = info->cp;
965 xcf_write_int32_check_error (info, &length, 1);
966
967 base = info->cp;
968
969 xcf_check_error (xcf_save_old_paths (info, gimage, error));
970
971 length = info->cp - base;
972
973 /* go back to the saved position and write the length */
974 xcf_check_error (xcf_seek_pos (info, pos, error));
975 xcf_write_int32 (info->fp, &length, 1, &tmp_error);
976 if (tmp_error)
977 {
978 g_propagate_error (error, tmp_error);
979 return false;
980 }
981
982 xcf_check_error (xcf_seek_end (info, error));
983 }
984 break;
985
986 case PROP_USER_UNIT:
987 {
988 GimpUnit unit;
989 const TQCString *unit_strings[5];
990 float factor;
991 TQ_INT32 digits;
992
993 unit = va_arg (args, TQ_INT32);
994
995 /* write the entire unit definition */
996 unit_strings[0] = _gimp_unit_get_identifier (gimage->gimp, unit);
997 factor = _gimp_unit_get_factor (gimage->gimp, unit);
998 digits = _gimp_unit_get_digits (gimage->gimp, unit);
999 unit_strings[1] = _gimp_unit_get_symbol (gimage->gimp, unit);
1000 unit_strings[2] = _gimp_unit_get_abbreviation (gimage->gimp, unit);
1001 unit_strings[3] = _gimp_unit_get_singular (gimage->gimp, unit);
1002 unit_strings[4] = _gimp_unit_get_plural (gimage->gimp, unit);
1003
1004 size =
1005 2 * 4 +
1006 strlen (unit_strings[0]) ? strlen (unit_strings[0]) + 5 : 4 +
1007 strlen (unit_strings[1]) ? strlen (unit_strings[1]) + 5 : 4 +
1008 strlen (unit_strings[2]) ? strlen (unit_strings[2]) + 5 : 4 +
1009 strlen (unit_strings[3]) ? strlen (unit_strings[3]) + 5 : 4 +
1010 strlen (unit_strings[4]) ? strlen (unit_strings[4]) + 5 : 4;
1011
1012 xcf_write_prop_type_check_error (info, prop_type);
1013 xcf_write_int32_check_error (info, &size, 1);
1014 xcf_write_float_check_error (info, &factor, 1);
1015 xcf_write_int32_check_error (info, &digits, 1);
1016 xcf_write_string_check_error (info, (TQCString **) unit_strings, 5);
1017 }
1018 break;
1019
1020 case PROP_VECTORS:
1021 {
1022 TQ_INT32 base, length;
1023 glong pos;
1024
1025 xcf_write_prop_type_check_error (info, prop_type);
1026
1027 /* because we don't know how much room the paths list will take
1028 * we save the file position and write the length later
1029 */
1030 pos = info->cp;
1031 xcf_write_int32_check_error (info, &length, 1);
1032
1033 base = info->cp;
1034
1035 xcf_check_error (xcf_save_vectors (info, gimage, error));
1036
1037 length = info->cp - base;
1038
1039 /* go back to the saved position and write the length */
1040 xcf_check_error (xcf_seek_pos (info, pos, error));
1041 xcf_write_int32 (info->fp, &length, 1, &tmp_error);
1042 if (tmp_error)
1043 {
1044 g_propagate_error (error, tmp_error);
1045 return false;
1046 }
1047
1048 xcf_check_error (xcf_seek_end (info, error));
1049 }
1050 break;
1051
1052 case PROP_TEXT_LAYER_FLAGS:
1053 {
1054 TQ_INT32 flags;
1055
1056 flags = va_arg (args, TQ_INT32);
1057 size = 4;
1058
1059 xcf_write_prop_type_check_error (info, prop_type);
1060 xcf_write_int32_check_error (info, &size, 1);
1061 xcf_write_int32_check_error (info, &flags, 1);
1062 }
1063 break;
1064 }
1065
1066 va_end (args);
1067
1068 return true;
1069}
1070
1071static bool
1072xcf_save_layer (XcfInfo *info,
1073 KisImage *gimage,
1074 KisLayer *layer,
1075 GError **error)
1076{
1077 TQ_INT32 saved_pos;
1078 TQ_INT32 offset;
1079
1080 GError *tmp_error = NULL;
1081
1082 /* check and see if this is the drawable that the floating
1083 * selection is attached to.
1084 */
1085 if (GIMP_DRAWABLE (layer) == info->floating_sel_drawable)
1086 {
1087 saved_pos = info->cp;
1088 xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
1089 xcf_write_int32_check_error (info, &saved_pos, 1);
1090 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1091 }
1092
1093 /* write out the width, height and image type information for the layer */
1094 xcf_write_int32_check_error (info,
1095 (TQ_INT32 *) &GIMP_ITEM (layer)->width, 1);
1096 xcf_write_int32_check_error (info,
1097 (TQ_INT32 *) &GIMP_ITEM (layer)->height, 1);
1098 xcf_write_int32_check_error (info,
1099 (TQ_INT32 *) &GIMP_DRAWABLE (layer)->type, 1);
1100
1101 /* write out the layers name */
1102 xcf_write_string_check_error (info, &GIMP_OBJECT (layer)->name, 1);
1103
1104 /* write out the layer properties */
1105 xcf_save_layer_props (info, gimage, layer, error);
1106
1107 /* save the current position which is where the hierarchy offset
1108 * will be stored.
1109 */
1110 saved_pos = info->cp;
1111
1112 /* write out the layer tile hierarchy */
1113 xcf_check_error (xcf_seek_pos (info, info->cp + 8, error));
1114 offset = info->cp;
1115
1116 xcf_check_error (xcf_save_hierarchy (info,
1117 GIMP_DRAWABLE(layer)->tiles, error));
1118
1119 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1120 xcf_write_int32_check_error (info, &offset, 1);
1121 saved_pos = info->cp;
1122
1123 /* write out the layer mask */
1124 if (layer->mask)
1125 {
1126 xcf_check_error (xcf_seek_end (info, error));
1127 offset = info->cp;
1128
1129 xcf_check_error (xcf_save_channel (info,
1130 gimage, GIMP_CHANNEL(layer->mask),
1131 error));
1132 }
1133 else
1134 offset = 0;
1135
1136 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1137 xcf_write_int32_check_error (info, &offset, 1);
1138
1139 return true;
1140}
1141
1142static bool
1143xcf_save_channel (XcfInfo *info,
1144 KisImage *gimage,
1145 GimpChannel *channel,
1146 GError **error)
1147{
1148 TQ_INT32 saved_pos;
1149 TQ_INT32 offset;
1150
1151 GError *tmp_error = NULL;
1152
1153 /* check and see if this is the drawable that the floating
1154 * selection is attached to.
1155 */
1156 if (GIMP_DRAWABLE (channel) == info->floating_sel_drawable)
1157 {
1158 saved_pos = info->cp;
1159 xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
1160 xcf_write_int32_check_error (info, &saved_pos, 1);
1161 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1162 }
1163
1164 /* write out the width and height information for the channel */
1165 xcf_write_int32_check_error (info,
1166 (TQ_INT32 *) &GIMP_ITEM (channel)->width, 1);
1167 xcf_write_int32_check_error (info,
1168 (TQ_INT32 *) &GIMP_ITEM (channel)->height, 1);
1169
1170 /* write out the channels name */
1171 xcf_write_string_check_error (info, &GIMP_OBJECT (channel)->name, 1);
1172
1173 /* write out the channel properties */
1174 xcf_save_channel_props (info, gimage, channel, error);
1175
1176 /* save the current position which is where the hierarchy offset
1177 * will be stored.
1178 */
1179 saved_pos = info->cp;
1180
1181 /* write out the channel tile hierarchy */
1182 xcf_check_error (xcf_seek_pos (info, info->cp + 4, error));
1183 offset = info->cp;
1184
1185 xcf_check_error (xcf_save_hierarchy (info,
1186 GIMP_DRAWABLE (channel)->tiles, error));
1187
1188 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1189 xcf_write_int32_check_error (info, &offset, 1);
1190 saved_pos = info->cp;
1191
1192 return true;
1193}
1194
1195static TQ_INT32
1196xcf_calc_levels (TQ_INT32 size,
1197 TQ_INT32 tile_size)
1198{
1199 int levels;
1200
1201 levels = 1;
1202 while (size > tile_size)
1203 {
1204 size /= 2;
1205 levels += 1;
1206 }
1207
1208 return levels;
1209}
1210
1211
1212static bool
1213xcf_save_hierarchy (XcfInfo *info,
1214 TileManager *tiles,
1215 GError **error)
1216{
1217 TQ_INT32 saved_pos;
1218 TQ_INT32 offset;
1219 TQ_INT32 width;
1220 TQ_INT32 height;
1221 TQ_INT32 bpp;
1222 TQ_INT32 i;
1223 TQ_INT32 nlevels;
1224 TQ_INT32 tmp1, tmp2;
1225
1226 GError *tmp_error = NULL;
1227
1228 width = tile_manager_width (tiles);
1229 height = tile_manager_height (tiles);
1230 bpp = tile_manager_bpp (tiles);
1231
1232 xcf_write_int32_check_error (info, (TQ_INT32 *) &width, 1);
1233 xcf_write_int32_check_error (info, (TQ_INT32 *) &height, 1);
1234 xcf_write_int32_check_error (info, (TQ_INT32 *) &bpp, 1);
1235
1236 saved_pos = info->cp;
1237
1238 tmp1 = xcf_calc_levels (width, TILE_WIDTH);
1239 tmp2 = xcf_calc_levels (height, TILE_HEIGHT);
1240 nlevels = MAX (tmp1, tmp2);
1241
1242 xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
1243
1244 for (i = 0; i < nlevels; i++)
1245 {
1246 offset = info->cp;
1247
1248 if (i == 0)
1249 {
1250 /* write out the level. */
1251 xcf_check_error (xcf_save_level (info, tiles, error));
1252 }
1253 else
1254 {
1255 /* fake an empty level */
1256 tmp1 = 0;
1257 width /= 2;
1258 height /= 2;
1259 xcf_write_int32_check_error (info, (TQ_INT32 *) &width, 1);
1260 xcf_write_int32_check_error (info, (TQ_INT32 *) &height, 1);
1261 xcf_write_int32_check_error (info, (TQ_INT32 *) &tmp1, 1);
1262 }
1263
1264 /* seek back to where we are to write out the next
1265 * level offset and write it out.
1266 */
1267 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1268 xcf_write_int32_check_error (info, &offset, 1);
1269
1270 /* increment the location we are to write out the
1271 * next offset.
1272 */
1273 saved_pos = info->cp;
1274
1275 /* seek to the end of the file which is where
1276 * we will write out the next level.
1277 */
1278 xcf_check_error (xcf_seek_end (info, error));
1279 }
1280
1281 /* write out a '0' offset position to indicate the end
1282 * of the level offsets.
1283 */
1284 offset = 0;
1285 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1286 xcf_write_int32_check_error (info, &offset, 1);
1287
1288 return true;
1289}
1290
1291static bool
1292xcf_save_level (XcfInfo *info,
1293 TileManager *level,
1294 GError **error)
1295{
1296 TQ_INT32 saved_pos;
1297 TQ_INT32 offset;
1298 TQ_INT32 width;
1299 TQ_INT32 height;
1300 TQ_UINT32 ntiles;
1301 TQ_INT32 i;
1302 guchar *rlebuf;
1303
1304 GError *tmp_error = NULL;
1305
1306 width = tile_manager_width (level);
1307 height = tile_manager_height (level);
1308
1309 xcf_write_int32_check_error (info, (TQ_INT32 *) &width, 1);
1310 xcf_write_int32_check_error (info, (TQ_INT32 *) &height, 1);
1311
1312 saved_pos = info->cp;
1313
1314 /* allocate a temporary buffer to store the rle data before it is
1315 written to disk */
1316 rlebuf =
1317 g_malloc (TILE_WIDTH * TILE_HEIGHT * tile_manager_bpp (level) * 1.5);
1318
1319 if (level->tiles)
1320 {
1321 ntiles = level->ntile_rows * level->ntile_cols;
1322 xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
1323
1324 for (i = 0; i < ntiles; i++)
1325 {
1326 /* save the start offset of where we are writing
1327 * out the next tile.
1328 */
1329 offset = info->cp;
1330
1331 /* write out the tile. */
1332 switch (info->compression)
1333 {
1334 case COMPRESS_NONE:
1335 xcf_check_error(xcf_save_tile (info, level->tiles[i], error));
1336 break;
1337 case COMPRESS_RLE:
1338 xcf_check_error (xcf_save_tile_rle (info, level->tiles[i],
1339 rlebuf, error));
1340 break;
1341 case COMPRESS_ZLIB:
1342 g_error ("xcf: zlib compression unimplemented");
1343 break;
1344 case COMPRESS_FRACTAL:
1345 g_error ("xcf: fractal compression unimplemented");
1346 break;
1347 }
1348
1349 /* seek back to where we are to write out the next
1350 * tile offset and write it out.
1351 */
1352 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1353 xcf_write_int32_check_error (info, &offset, 1);
1354
1355 /* increment the location we are to write out the
1356 * next offset.
1357 */
1358 saved_pos = info->cp;
1359
1360 /* seek to the end of the file which is where
1361 * we will write out the next tile.
1362 */
1363 xcf_check_error (xcf_seek_end (info, error));
1364 }
1365 }
1366
1367 g_free (rlebuf);
1368
1369 /* write out a '0' offset position to indicate the end
1370 * of the level offsets.
1371 */
1372 offset = 0;
1373 xcf_check_error (xcf_seek_pos (info, saved_pos, error));
1374 xcf_write_int32_check_error (info, &offset, 1);
1375
1376 return true;
1377
1378}
1379
1380static bool
1381xcf_save_tile (XcfInfo *info,
1382 Tile *tile,
1383 GError **error)
1384{
1385 GError *tmp_error = NULL;
1386
1387 tile_lock (tile);
1388 xcf_write_int8_check_error (info, tile_data_pointer (tile, 0, 0),
1389 tile_size (tile));
1390 tile_release (tile, false);
1391
1392 return true;
1393}
1394
1395static bool
1396xcf_save_tile_rle (XcfInfo *info,
1397 Tile *tile,
1398 guchar *rlebuf,
1399 GError **error)
1400{
1401 guchar *data, *t;
1402 unsigned int last;
1403 TQ_INT32 state;
1404 TQ_INT32 length;
1405 TQ_INT32 count;
1406 TQ_INT32 size;
1407 TQ_INT32 bpp;
1408 TQ_INT32 i, j;
1409 TQ_INT32 len = 0;
1410
1411 GError *tmp_error = NULL;
1412
1413 tile_lock (tile);
1414
1415 bpp = tile_bpp (tile);
1416
1417 for (i = 0; i < bpp; i++)
1418 {
1419 data = (guchar*) tile_data_pointer (tile, 0, 0) + i;
1420
1421 state = 0;
1422 length = 0;
1423 count = 0;
1424 size = tile_ewidth(tile) * tile_eheight(tile);
1425 last = -1;
1426
1427 while (size > 0)
1428 {
1429 switch (state)
1430 {
1431 case 0:
1432 /* in state 0 we try to find a long sequence of
1433 * matching values.
1434 */
1435 if ((length == 32768) ||
1436 ((size - length) <= 0) ||
1437 ((length > 1) && (last != *data)))
1438 {
1439 count += length;
1440 if (length >= 128)
1441 {
1442 rlebuf[len++] = 127;
1443 rlebuf[len++] = (length >> 8);
1444 rlebuf[len++] = length & 0x00FF;
1445 rlebuf[len++] = last;
1446 }
1447 else
1448 {
1449 rlebuf[len++] = length - 1;
1450 rlebuf[len++] = last;
1451 }
1452 size -= length;
1453 length = 0;
1454 }
1455 else if ((length == 1) && (last != *data))
1456 state = 1;
1457 break;
1458
1459 case 1:
1460 /* in state 1 we try and find a long sequence of
1461 * non-matching values.
1462 */
1463 if ((length == 32768) ||
1464 ((size - length) == 0) ||
1465 ((length > 0) && (last == *data) &&
1466 ((size - length) == 1 || last == data[bpp])))
1467 {
1468 count += length;
1469 state = 0;
1470
1471 if (length >= 128)
1472 {
1473 rlebuf[len++] = 255 - 127;
1474 rlebuf[len++] = (length >> 8);
1475 rlebuf[len++] = length & 0x00FF;
1476 }
1477 else
1478 {
1479 rlebuf[len++] = 255 - (length - 1);
1480 }
1481
1482 t = data - length * bpp;
1483 for (j = 0; j < length; j++)
1484 {
1485 rlebuf[len++] = *t;
1486 t += bpp;
1487 }
1488
1489 size -= length;
1490 length = 0;
1491 }
1492 break;
1493 }
1494
1495 if (size > 0) {
1496 length += 1;
1497 last = *data;
1498 data += bpp;
1499 }
1500 }
1501
1502 if (count != (tile_ewidth (tile) * tile_eheight (tile)))
1503 g_message ("xcf: uh oh! xcf rle tile saving error: %d", count);
1504 }
1505 xcf_write_int8_check_error (info, rlebuf, len);
1506 tile_release (tile, false);
1507
1508 return true;
1509}
1510
1511static bool
1512xcf_save_parasite (XcfInfo *info,
1513 KisAnnotation *parasite,
1514 GError **error)
1515{
1516 if (gimp_parasite_is_persistent (parasite))
1517 {
1518 GError *tmp_error = NULL;
1519
1520 xcf_write_string_check_error (info, &parasite->name, 1);
1521 xcf_write_int32_check_error (info, &parasite->flags, 1);
1522 xcf_write_int32_check_error (info, &parasite->size, 1);
1523 xcf_write_int8_check_error (info, parasite->data, parasite->size);
1524 }
1525
1526 return true;
1527}
1528
1529typedef struct
1530{
1531 XcfInfo *info;
1532 GError *error;
1533} XcfParasiteData;
1534
1535static void
1536xcf_save_parasite_func (TQCString *key,
1537 KisAnnotation *parasite,
1538 XcfParasiteData *data)
1539{
1540 if (! data->error)
1541 xcf_save_parasite (data->info, parasite, &data->error);
1542}
1543
1544static bool
1545xcf_save_parasite_list (XcfInfo *info,
1546 KisAnnotationList *list,
1547 GError **error)
1548{
1549 XcfParasiteData data;
1550
1551 data.info = info;
1552 data.error = NULL;
1553
1554 gimp_parasite_list_foreach (list, (GHFunc) xcf_save_parasite_func, &data);
1555
1556 if (data.error)
1557 {
1558 g_propagate_error (error, data.error);
1559 return false;
1560 }
1561
1562 return true;
1563}
1564
1565static bool
1566xcf_save_old_paths (XcfInfo *info,
1567 KisImage *gimage,
1568 GError **error)
1569{
1570 GimpVectors *active_vectors;
1571 TQ_INT32 num_paths;
1572 TQ_INT32 active_index = 0;
1573 GList *list;
1574 GError *tmp_error = NULL;
1575
1576 /* Write out the following:-
1577 *
1578 * last_selected_row (TQ_INT32)
1579 * number_of_paths (TQ_INT32)
1580 *
1581 * then each path:-
1582 */
1583
1584 num_paths = gimp_container_num_children (gimage->vectors);
1585
1586 active_vectors = gimp_image_get_active_vectors (gimage);
1587
1588 if (active_vectors)
1589 active_index = gimp_container_get_child_index (gimage->vectors,
1590 GIMP_OBJECT (active_vectors));
1591
1592 xcf_write_int32_check_error (info, &active_index, 1);
1593 xcf_write_int32_check_error (info, &num_paths, 1);
1594
1595 for (list = GIMP_LIST (gimage->vectors)->list;
1596 list;
1597 list = g_list_next (list))
1598 {
1599 GimpVectors *vectors = list->data;
1600 TQCString *name;
1601 TQ_INT32 locked;
1602 TQ_UINT8 state;
1603 TQ_INT32 version;
1604 TQ_INT32 pathtype;
1605 TQ_INT32 tattoo;
1606 GimpVectorsCompatPoint *points;
1607 TQ_INT3232 num_points;
1608 TQ_INT3232 closed;
1609 TQ_INT32 i;
1610
1611 /*
1612 * name (string)
1613 * locked (TQ_INT32)
1614 * state (TQCString)
1615 * closed (TQ_INT32)
1616 * number points (TQ_INT32)
1617 * version (TQ_INT32)
1618 * pathtype (TQ_INT32)
1619 * tattoo (TQ_INT32)
1620 * then each point.
1621 */
1622
1623 points = gimp_vectors_compat_get_points (vectors, &num_points, &closed);
1624
1625 /* if no points are generated because of a faulty path we should
1626 * skip saving the path - this is unfortunately impossible, because
1627 * we already saved the number of paths and I wont start seeking
1628 * around to fix that cruft */
1629
1630 name = (TQCString *) gimp_object_get_name (GIMP_OBJECT (vectors));
1631 locked = gimp_item_get_linked (GIMP_ITEM (vectors));
1632 state = closed ? 4 : 2; /* EDIT : ADD (editing state, 1.2 compat) */
1633 version = 3;
1634 pathtype = 1; /* BEZIER (1.2 compat) */
1635 tattoo = gimp_item_get_tattoo (GIMP_ITEM (vectors));
1636
1637 xcf_write_string_check_error (info, &name, 1);
1638 xcf_write_int32_check_error (info, &locked, 1);
1639 xcf_write_int8_check_error (info, &state, 1);
1640 xcf_write_int32_check_error (info, &closed, 1);
1641 xcf_write_int32_check_error (info, &num_points, 1);
1642 xcf_write_int32_check_error (info, &version, 1);
1643 xcf_write_int32_check_error (info, &pathtype, 1);
1644 xcf_write_int32_check_error (info, &tattoo, 1);
1645
1646 for (i = 0; i < num_points; i++)
1647 {
1648 float x;
1649 float y;
1650
1651 x = points[i].x;
1652 y = points[i].y;
1653
1654 /*
1655 * type (TQ_INT32)
1656 * x (float)
1657 * y (float)
1658 */
1659
1660 xcf_write_int32_check_error (info, &points[i].type, 1);
1661 xcf_write_float_check_error (info, &x, 1);
1662 xcf_write_float_check_error (info, &y, 1);
1663 }
1664
1665 g_free (points);
1666 }
1667
1668 return true;
1669}
1670
1671static bool
1672xcf_save_vectors (XcfInfo *info,
1673 KisImage *gimage,
1674 GError **error)
1675{
1676 GimpVectors *active_vectors;
1677 TQ_INT32 version = 1;
1678 TQ_INT32 active_index = 0;
1679 TQ_INT32 num_paths;
1680 GList *list;
1681 GList *stroke_list;
1682 GError *tmp_error = NULL;
1683
1684 /* Write out the following:-
1685 *
1686 * version (TQ_INT32)
1687 * active_index (TQ_INT32)
1688 * num_paths (TQ_INT32)
1689 *
1690 * then each path:-
1691 */
1692
1693 active_vectors = gimp_image_get_active_vectors (gimage);
1694
1695 if (active_vectors)
1696 active_index = gimp_container_get_child_index (gimage->vectors,
1697 GIMP_OBJECT (active_vectors));
1698
1699 num_paths = gimp_container_num_children (gimage->vectors);
1700
1701 xcf_write_int32_check_error (info, &version, 1);
1702 xcf_write_int32_check_error (info, &active_index, 1);
1703 xcf_write_int32_check_error (info, &num_paths, 1);
1704
1705 for (list = GIMP_LIST (gimage->vectors)->list;
1706 list;
1707 list = g_list_next (list))
1708 {
1709 GimpVectors *vectors = list->data;
1710 KisAnnotationList *parasites;
1711 TQCString *name;
1712 TQ_INT32 tattoo;
1713 TQ_INT32 visible;
1714 TQ_INT32 linked;
1715 TQ_INT32 num_parasites;
1716 TQ_INT32 num_strokes;
1717
1718 /*
1719 * name (string)
1720 * tattoo (TQ_INT32)
1721 * visible (TQ_INT32)
1722 * linked (TQ_INT32)
1723 * num_parasites (TQ_INT32)
1724 * num_strokes (TQ_INT32)
1725 *
1726 * then each parasite
1727 * then each stroke
1728 */
1729
1730 parasites = GIMP_ITEM (vectors)->parasites;
1731
1732 name = (TQCString *) gimp_object_get_name (GIMP_OBJECT (vectors));
1733 visible = gimp_item_get_visible (GIMP_ITEM (vectors));
1734 linked = gimp_item_get_linked (GIMP_ITEM (vectors));
1735 tattoo = gimp_item_get_tattoo (GIMP_ITEM (vectors));
1736 num_parasites = gimp_parasite_list_persistent_length (parasites);
1737 num_strokes = g_list_length (vectors->strokes);
1738
1739 xcf_write_string_check_error (info, &name, 1);
1740 xcf_write_int32_check_error (info, &tattoo, 1);
1741 xcf_write_int32_check_error (info, &visible, 1);
1742 xcf_write_int32_check_error (info, &linked, 1);
1743 xcf_write_int32_check_error (info, &num_parasites, 1);
1744 xcf_write_int32_check_error (info, &num_strokes, 1);
1745
1746 xcf_check_error (xcf_save_parasite_list (info, parasites, error));
1747
1748 for (stroke_list = g_list_first (vectors->strokes);
1749 stroke_list;
1750 stroke_list = g_list_next (stroke_list))
1751 {
1752 GimpStroke *stroke;
1753 TQ_INT32 stroke_type;
1754 TQ_INT32 closed;
1755 TQ_INT32 num_axes;
1756 GArray *control_points;
1757 TQ_INT32 i;
1758
1759 TQ_INT32 type;
1760 float coords[6];
1761
1762 /*
1763 * stroke_type (TQ_INT32)
1764 * closed (TQ_INT32)
1765 * num_axes (TQ_INT32)
1766 * num_control_points (TQ_INT32)
1767 *
1768 * then each control point.
1769 */
1770
1771 stroke = GIMP_STROKE (stroke_list->data);
1772
1773 if (GIMP_IS_BEZIER_STROKE (stroke))
1774 {
1775 stroke_type = XCF_STROKETYPE_BEZIER_STROKE;
1776 num_axes = 2; /* hardcoded, might be increased later */
1777 }
1778 else
1779 {
1780 g_printerr ("Skipping unknown stroke type!\n");
1781 continue;
1782 }
1783
1784 control_points = gimp_stroke_control_points_get (stroke, &closed);
1785
1786 xcf_write_int32_check_error (info, &stroke_type, 1);
1787 xcf_write_int32_check_error (info, &closed, 1);
1788 xcf_write_int32_check_error (info, &num_axes, 1);
1789 xcf_write_int32_check_error (info, &control_points->len, 1);
1790
1791 for (i = 0; i < control_points->len; i++)
1792 {
1793 GimpAnchor *anchor;
1794
1795 anchor = & (g_array_index (control_points, GimpAnchor, i));
1796
1797 type = anchor->type;
1798 coords[0] = anchor->position.x;
1799 coords[1] = anchor->position.y;
1800 coords[2] = anchor->position.pressure;
1801 coords[3] = anchor->position.xtilt;
1802 coords[4] = anchor->position.ytilt;
1803 coords[5] = anchor->position.wheel;
1804
1805 /*
1806 * type (TQ_INT32)
1807 *
1808 * the first num_axis elements of:
1809 * [0] x (float)
1810 * [1] y (float)
1811 * [2] pressure (float)
1812 * [3] xtilt (float)
1813 * [4] ytilt (float)
1814 * [5] wheel (float)
1815 */
1816
1817 xcf_write_int32_check_error (info, &type, 1);
1818 xcf_write_float_check_error (info, coords, num_axes);
1819 }
1820
1821 g_array_free (control_points, true);
1822 }
1823 }
1824
1825 return true;
1826}