2001-07-04 02:38:56 +08:00
|
|
|
/* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
2001-07-23 06:18:01 +08:00
|
|
|
#include <string.h> /* strcpy, strlen */
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2001-08-17 22:27:31 +08:00
|
|
|
#include <glib-object.h>
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
|
|
#include "libgimpcolor/gimpcolor.h"
|
|
|
|
|
|
|
|
#include "core/core-types.h"
|
|
|
|
|
|
|
|
#include "base/tile.h"
|
|
|
|
#include "base/tile-manager.h"
|
|
|
|
#include "base/tile-manager-private.h"
|
|
|
|
|
|
|
|
#include "core/gimpchannel.h"
|
|
|
|
#include "core/gimpdrawable.h"
|
|
|
|
#include "core/gimpimage.h"
|
|
|
|
#include "core/gimpimage-mask.h"
|
|
|
|
#include "core/gimplayer.h"
|
2002-02-22 06:19:45 +08:00
|
|
|
#include "core/gimplayer-floating-sel.h"
|
2001-07-04 02:38:56 +08:00
|
|
|
#include "core/gimplayermask.h"
|
|
|
|
#include "core/gimplist.h"
|
2001-07-10 03:48:30 +08:00
|
|
|
#include "core/gimpparasitelist.h"
|
2001-07-11 20:39:49 +08:00
|
|
|
#include "core/gimpunit.h"
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
#include "vectors/gimpanchor.h"
|
|
|
|
#include "vectors/gimpstroke.h"
|
|
|
|
#include "vectors/gimpvectors.h"
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
#include "xcf-private.h"
|
|
|
|
#include "xcf-read.h"
|
|
|
|
#include "xcf-seek.h"
|
|
|
|
#include "xcf-write.h"
|
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
#include "gimp-intl.h"
|
2002-12-20 14:26:34 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_image_props (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
GimpImage *gimage,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_layer_props (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
GimpImage *gimage,
|
|
|
|
GimpLayer *layer,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_channel_props (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
GimpImage *gimage,
|
|
|
|
GimpChannel *channel,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_prop (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
GimpImage *gimage,
|
|
|
|
PropType prop_type,
|
|
|
|
GError **error,
|
|
|
|
...);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_layer (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
GimpImage *gimage,
|
|
|
|
GimpLayer *layer,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_channel (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
GimpImage *gimage,
|
|
|
|
GimpChannel *channel,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_hierarchy (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
TileManager *tiles,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_level (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
TileManager *tiles,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_tile (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
Tile *tile,
|
|
|
|
GError **error);
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean xcf_save_tile_rle (XcfInfo *info,
|
2003-05-15 20:47:42 +08:00
|
|
|
Tile *tile,
|
|
|
|
guchar *rlebuf,
|
|
|
|
GError **error);
|
|
|
|
static void xcf_save_parasite (gchar *key,
|
|
|
|
GimpParasite *parasite,
|
|
|
|
XcfInfo *info);
|
|
|
|
static gboolean xcf_save_old_paths (XcfInfo *info,
|
2003-05-22 01:38:14 +08:00
|
|
|
GimpImage *gimage,
|
2003-05-15 20:47:42 +08:00
|
|
|
GError **error);
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
|
|
|
|
/* private convieniece macros */
|
2003-04-10 22:15:24 +08:00
|
|
|
#define xcf_write_int32_check_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_int32 (fp, data, count, &tmp_error); \
|
|
|
|
if (tmp_error) \
|
|
|
|
{ \
|
|
|
|
g_propagate_error (error, tmp_error); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_write_int8_check_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_int8 (fp, data, count, &tmp_error); \
|
|
|
|
if (tmp_error) \
|
|
|
|
{ \
|
|
|
|
g_propagate_error (error, tmp_error); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_write_float_check_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_float (fp, data, count, &tmp_error); \
|
|
|
|
if (tmp_error) \
|
|
|
|
{ \
|
|
|
|
g_propagate_error (error, tmp_error); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_write_string_check_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_string (fp, data, count, &tmp_error); \
|
|
|
|
if (tmp_error) \
|
|
|
|
{ \
|
|
|
|
g_propagate_error (error, tmp_error); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_write_int32_print_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_int32 (fp, data, count, &error); \
|
|
|
|
if (error) \
|
|
|
|
{ \
|
|
|
|
g_message (_("Error saving XCF file: %s"), \
|
|
|
|
error->message); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_write_int8_print_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_int8 (fp, data, count, &error); \
|
|
|
|
if (error) \
|
|
|
|
{ \
|
|
|
|
g_message (_("Error saving XCF file: %s"), \
|
|
|
|
error->message); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_write_float_print_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_float (fp, data, count, &error); \
|
|
|
|
if (error) \
|
|
|
|
{ \
|
|
|
|
g_message (_("Error saving XCF file: %s"), \
|
|
|
|
error->message); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_write_string_print_error(fp, data, count) G_STMT_START { \
|
|
|
|
info->cp += xcf_write_string (fp, data, count, &error); \
|
|
|
|
if (error) \
|
|
|
|
{ \
|
|
|
|
g_message (_("Error saving XCF file: %s"), \
|
|
|
|
error->message); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_check_error(x) G_STMT_START { \
|
|
|
|
if (! (x)) \
|
|
|
|
return FALSE; \
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
#define xcf_print_error(x) G_STMT_START { \
|
|
|
|
if (! (x)) \
|
|
|
|
{ \
|
|
|
|
g_message (_("Error saving XCF file: %s"), \
|
|
|
|
error->message); \
|
|
|
|
return FALSE; \
|
|
|
|
} \
|
|
|
|
} G_STMT_END
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
xcf_save_choose_format (XcfInfo *info,
|
2003-04-10 22:15:24 +08:00
|
|
|
GimpImage *gimage)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
2002-11-06 18:07:31 +08:00
|
|
|
GimpLayer *layer;
|
|
|
|
GList *list;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
gint save_version = 0; /* default to oldest */
|
|
|
|
|
|
|
|
if (gimage->cmap)
|
|
|
|
save_version = 1; /* need version 1 for colormaps */
|
|
|
|
|
2002-11-06 18:07:31 +08:00
|
|
|
for (list = GIMP_LIST (gimage->layers)->list;
|
|
|
|
list && save_version < 2;
|
|
|
|
list = g_list_next (list))
|
|
|
|
{
|
|
|
|
layer = GIMP_LAYER (list->data);
|
|
|
|
|
|
|
|
switch (layer->mode)
|
|
|
|
{
|
|
|
|
/* new layer modes not supported by gimp-1.2 */
|
|
|
|
case GIMP_SOFTLIGHT_MODE:
|
|
|
|
case GIMP_GRAIN_EXTRACT_MODE:
|
|
|
|
case GIMP_GRAIN_MERGE_MODE:
|
|
|
|
case GIMP_COLOR_ERASE_MODE:
|
|
|
|
save_version = 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
info->file_version = save_version;
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
xcf_save_image (XcfInfo *info,
|
|
|
|
GimpImage *gimage)
|
|
|
|
{
|
|
|
|
GimpLayer *layer;
|
|
|
|
GimpLayer *floating_layer;
|
|
|
|
GimpChannel *channel;
|
|
|
|
guint32 saved_pos;
|
|
|
|
guint32 offset;
|
|
|
|
guint nlayers;
|
|
|
|
guint nchannels;
|
|
|
|
GList *list;
|
|
|
|
gboolean have_selection;
|
|
|
|
gint t1, t2, t3, t4;
|
|
|
|
gchar version_tag[14];
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *error = NULL;
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
floating_layer = gimp_image_floating_sel (gimage);
|
|
|
|
if (floating_layer)
|
|
|
|
floating_sel_relax (floating_layer, FALSE);
|
|
|
|
|
|
|
|
/* write out the tag information for the image */
|
|
|
|
if (info->file_version > 0)
|
|
|
|
{
|
|
|
|
sprintf (version_tag, "gimp xcf v%03d", info->file_version);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strcpy (version_tag, "gimp xcf file");
|
|
|
|
}
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int8_print_error (info->fp, (guint8 *) version_tag, 14);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* write out the width, height and image type information for the image */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_print_error (info->fp, (guint32 *) &gimage->width, 1);
|
|
|
|
xcf_write_int32_print_error (info->fp, (guint32 *) &gimage->height, 1);
|
|
|
|
xcf_write_int32_print_error (info->fp, (guint32 *) &gimage->base_type, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* determine the number of layers and channels in the image */
|
|
|
|
nlayers = (guint) gimp_container_num_children (gimage->layers);
|
|
|
|
nchannels = (guint) gimp_container_num_children (gimage->channels);
|
|
|
|
|
|
|
|
/* check and see if we have to save out the selection */
|
2001-11-29 06:42:19 +08:00
|
|
|
have_selection = gimp_image_mask_bounds (gimage, &t1, &t2, &t3, &t4);
|
2001-07-04 02:38:56 +08:00
|
|
|
if (have_selection)
|
|
|
|
nchannels += 1;
|
|
|
|
|
|
|
|
/* write the property information for the image.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
|
|
|
|
xcf_print_error (xcf_save_image_props (info, gimage, &error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* save the current file position as it is the start of where
|
|
|
|
* we place the layer offset information.
|
|
|
|
*/
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* seek to after the offset lists */
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_print_error (xcf_seek_pos (info,
|
|
|
|
info->cp + (nlayers + nchannels + 2) * 4,
|
|
|
|
&error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
for (list = GIMP_LIST (gimage->layers)->list;
|
|
|
|
list;
|
|
|
|
list = g_list_next (list))
|
|
|
|
{
|
|
|
|
layer = (GimpLayer *) list->data;
|
|
|
|
|
|
|
|
/* save the start offset of where we are writing
|
|
|
|
* out the next layer.
|
|
|
|
*/
|
|
|
|
offset = info->cp;
|
|
|
|
|
|
|
|
/* write out the layer. */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_save_layer (info, gimage, layer, &error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* seek back to where we are to write out the next
|
|
|
|
* layer offset and write it out.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
|
|
|
|
xcf_write_int32_print_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* increment the location we are to write out the
|
|
|
|
* next offset.
|
|
|
|
*/
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* seek to the end of the file which is where
|
|
|
|
* we will write out the next layer.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_seek_end (info, &error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* write out a '0' offset position to indicate the end
|
|
|
|
* of the layer offsets.
|
|
|
|
*/
|
|
|
|
offset = 0;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
|
|
|
|
xcf_write_int32_print_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
saved_pos = info->cp;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_seek_end (info, &error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
list = GIMP_LIST (gimage->channels)->list;
|
|
|
|
|
|
|
|
while (list || have_selection)
|
|
|
|
{
|
|
|
|
if (list)
|
|
|
|
{
|
|
|
|
channel = (GimpChannel *) list->data;
|
|
|
|
|
|
|
|
list = g_list_next (list);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
channel = gimage->selection_mask;
|
|
|
|
have_selection = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save the start offset of where we are writing
|
|
|
|
* out the next channel.
|
|
|
|
*/
|
|
|
|
offset = info->cp;
|
|
|
|
|
|
|
|
/* write out the layer. */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_save_channel (info, gimage, channel, &error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* seek back to where we are to write out the next
|
|
|
|
* channel offset and write it out.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
|
|
|
|
xcf_write_int32_print_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* increment the location we are to write out the
|
|
|
|
* next offset.
|
|
|
|
*/
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* seek to the end of the file which is where
|
|
|
|
* we will write out the next channel.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_seek_end (info, &error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* write out a '0' offset position to indicate the end
|
|
|
|
* of the channel offsets.
|
|
|
|
*/
|
|
|
|
offset = 0;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
|
|
|
|
xcf_write_int32_print_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
if (floating_layer)
|
|
|
|
floating_sel_rigor (floating_layer, FALSE);
|
|
|
|
|
|
|
|
return !ferror(info->fp);
|
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
2001-07-04 02:38:56 +08:00
|
|
|
xcf_save_image_props (XcfInfo *info,
|
2002-12-20 14:26:34 +08:00
|
|
|
GimpImage *gimage,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
/* check and see if we should save the colormap property */
|
|
|
|
if (gimage->cmap)
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_COLORMAP, error,
|
|
|
|
gimage->num_cols, gimage->cmap));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
if (info->compression != COMPRESS_NONE)
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_COMPRESSION,
|
|
|
|
error, info->compression));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
if (gimage->guides)
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_GUIDES,
|
|
|
|
error, gimage->guides));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_RESOLUTION, error,
|
|
|
|
gimage->xresolution, gimage->yresolution));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
|
|
|
|
gimage->tattoo_state));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
if (gimp_parasite_list_length(gimage->parasites) > 0)
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES,
|
|
|
|
error, gimage->parasites));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
if (gimage->unit < _gimp_unit_get_number_of_built_in_units (gimage->gimp))
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_UNIT,
|
|
|
|
error, gimage->unit));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
if (gimp_container_num_children (gimage->vectors) > 0)
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_PATHS, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
if (gimage->unit >= _gimp_unit_get_number_of_built_in_units (gimage->gimp))
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_USER_UNIT,
|
|
|
|
error, gimage->unit));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
|
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
2001-07-04 02:38:56 +08:00
|
|
|
xcf_save_layer_props (XcfInfo *info,
|
|
|
|
GimpImage *gimage,
|
2002-12-20 14:26:34 +08:00
|
|
|
GimpLayer *layer,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
if (layer == gimp_image_get_active_layer (gimage))
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_ACTIVE_LAYER, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
if (layer == gimp_image_floating_sel (gimage))
|
|
|
|
{
|
|
|
|
info->floating_sel_drawable = layer->fs.drawable;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_FLOATING_SELECTION,
|
|
|
|
error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_OPACITY, error,
|
|
|
|
layer->opacity));
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_VISIBLE, error,
|
|
|
|
gimp_drawable_get_visible (GIMP_DRAWABLE (layer))));
|
2003-05-14 02:30:15 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_LINKED, error,
|
|
|
|
gimp_item_get_linked (GIMP_ITEM (layer))));
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_PRESERVE_TRANSPARENCY,
|
|
|
|
error, layer->preserve_trans));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
if (layer->mask)
|
|
|
|
{
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_APPLY_MASK,
|
|
|
|
error, layer->mask->apply_mask));
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_EDIT_MASK,
|
|
|
|
error, layer->mask->edit_mask));
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASK,
|
|
|
|
error, layer->mask->show_mask));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_APPLY_MASK,
|
|
|
|
error, FALSE));
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_EDIT_MASK,
|
|
|
|
error, FALSE));
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASK,
|
|
|
|
error, FALSE));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_OFFSETS, error,
|
2003-05-08 19:52:31 +08:00
|
|
|
GIMP_ITEM (layer)->offset_x,
|
|
|
|
GIMP_ITEM (layer)->offset_y));
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_MODE, error,
|
|
|
|
layer->mode));
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
|
|
|
|
GIMP_ITEM (layer)->tattoo));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-02-26 01:58:50 +08:00
|
|
|
if (gimp_parasite_list_length (GIMP_ITEM (layer)->parasites) > 0)
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
|
|
|
|
GIMP_ITEM (layer)->parasites));
|
|
|
|
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
2001-07-04 02:38:56 +08:00
|
|
|
xcf_save_channel_props (XcfInfo *info,
|
|
|
|
GimpImage *gimage,
|
2002-12-20 14:26:34 +08:00
|
|
|
GimpChannel *channel,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
guchar col[3];
|
|
|
|
|
|
|
|
if (channel == gimp_image_get_active_channel (gimage))
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_ACTIVE_CHANNEL, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
if (channel == gimage->selection_mask)
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_SELECTION, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_OPACITY, error,
|
|
|
|
channel->color.a));
|
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_VISIBLE, error,
|
|
|
|
gimp_drawable_get_visible (GIMP_DRAWABLE (channel))));
|
2003-05-14 02:30:15 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_LINKED, error,
|
|
|
|
gimp_item_get_linked (GIMP_ITEM (channel))));
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASKED, error,
|
|
|
|
channel->show_masked));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
gimp_rgb_get_uchar (&channel->color, &col[0], &col[1], &col[2]);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_COLOR, error, col));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
|
|
|
|
GIMP_ITEM (channel)->tattoo));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-02-26 01:58:50 +08:00
|
|
|
if (gimp_parasite_list_length (GIMP_ITEM (channel)->parasites) > 0)
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
|
|
|
|
GIMP_ITEM (channel)->parasites));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
|
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
xcf_save_prop (XcfInfo *info,
|
|
|
|
GimpImage *gimage,
|
|
|
|
PropType prop_type,
|
2002-12-20 14:26:34 +08:00
|
|
|
GError **error,
|
2001-07-04 02:38:56 +08:00
|
|
|
...)
|
|
|
|
{
|
|
|
|
guint32 size;
|
|
|
|
va_list args;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
|
|
|
va_start (args, error);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
switch (prop_type)
|
|
|
|
{
|
|
|
|
case PROP_END:
|
|
|
|
size = 0;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
break;
|
|
|
|
case PROP_COLORMAP:
|
|
|
|
{
|
|
|
|
guint32 ncolors;
|
|
|
|
guchar *colors;
|
|
|
|
|
|
|
|
ncolors = va_arg (args, guint32);
|
|
|
|
colors = va_arg (args, guchar*);
|
|
|
|
size = 4 + ncolors;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &ncolors, 1);
|
|
|
|
xcf_write_int8_check_error (info->fp, colors, ncolors * 3);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_ACTIVE_LAYER:
|
|
|
|
case PROP_ACTIVE_CHANNEL:
|
|
|
|
case PROP_SELECTION:
|
|
|
|
size = 0;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
break;
|
|
|
|
case PROP_FLOATING_SELECTION:
|
|
|
|
{
|
|
|
|
guint32 dummy;
|
|
|
|
|
|
|
|
dummy = 0;
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
info->floating_sel_offset = info->cp;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &dummy, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_OPACITY:
|
|
|
|
{
|
2002-03-04 22:52:54 +08:00
|
|
|
gdouble opacity;
|
|
|
|
guint32 uint_opacity;
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-03-04 22:52:54 +08:00
|
|
|
opacity = va_arg (args, gdouble);
|
|
|
|
|
|
|
|
uint_opacity = opacity * 255.999;
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &uint_opacity, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_MODE:
|
|
|
|
{
|
|
|
|
gint32 mode;
|
|
|
|
|
|
|
|
mode = va_arg (args, gint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &mode, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_VISIBLE:
|
|
|
|
{
|
|
|
|
guint32 visible;
|
|
|
|
|
|
|
|
visible = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &visible, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_LINKED:
|
|
|
|
{
|
|
|
|
guint32 linked;
|
|
|
|
|
|
|
|
linked = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &linked, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_PRESERVE_TRANSPARENCY:
|
|
|
|
{
|
|
|
|
guint32 preserve_trans;
|
|
|
|
|
|
|
|
preserve_trans = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &preserve_trans, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_APPLY_MASK:
|
|
|
|
{
|
|
|
|
guint32 apply_mask;
|
|
|
|
|
|
|
|
apply_mask = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &apply_mask, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_EDIT_MASK:
|
|
|
|
{
|
|
|
|
guint32 edit_mask;
|
|
|
|
|
|
|
|
edit_mask = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &edit_mask, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_SHOW_MASK:
|
|
|
|
{
|
|
|
|
guint32 show_mask;
|
|
|
|
|
|
|
|
show_mask = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &show_mask, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_SHOW_MASKED:
|
|
|
|
{
|
|
|
|
guint32 show_masked;
|
|
|
|
|
|
|
|
show_masked = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &show_masked, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_OFFSETS:
|
|
|
|
{
|
|
|
|
gint32 offsets[2];
|
|
|
|
|
|
|
|
offsets[0] = va_arg (args, gint32);
|
|
|
|
offsets[1] = va_arg (args, gint32);
|
|
|
|
size = 8;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) offsets, 2);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_COLOR:
|
|
|
|
{
|
|
|
|
guchar *color;
|
|
|
|
|
|
|
|
color = va_arg (args, guchar*);
|
|
|
|
size = 3;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int8_check_error (info->fp, color, 3);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_COMPRESSION:
|
|
|
|
{
|
|
|
|
guint8 compression;
|
|
|
|
|
|
|
|
compression = (guint8) va_arg (args, guint32);
|
|
|
|
size = 1;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int8_check_error (info->fp, &compression, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_GUIDES:
|
|
|
|
{
|
|
|
|
GList *guides;
|
|
|
|
GimpGuide *guide;
|
|
|
|
gint32 position;
|
|
|
|
gint8 orientation;
|
|
|
|
gint nguides;
|
|
|
|
|
|
|
|
guides = va_arg (args, GList *);
|
|
|
|
nguides = g_list_length (guides);
|
|
|
|
|
|
|
|
size = nguides * (4 + 1);
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
for (; guides; guides = g_list_next (guides))
|
|
|
|
{
|
|
|
|
guide = (GimpGuide *) guides->data;
|
|
|
|
|
2003-02-08 01:12:21 +08:00
|
|
|
position = guide->position;
|
|
|
|
|
|
|
|
switch (guide->orientation)
|
|
|
|
{
|
|
|
|
case GIMP_ORIENTATION_HORIZONTAL:
|
|
|
|
orientation = XCF_ORIENTATION_HORIZONTAL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_ORIENTATION_VERTICAL:
|
|
|
|
orientation = XCF_ORIENTATION_VERTICAL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_warning ("xcf_save_prop: skipping guide with bad orientation");
|
|
|
|
continue;
|
|
|
|
}
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &position, 1);
|
|
|
|
xcf_write_int8_check_error (info->fp, (guint8 *) &orientation, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_RESOLUTION:
|
|
|
|
{
|
2001-07-05 06:59:25 +08:00
|
|
|
gfloat xresolution, yresolution;
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2001-07-19 23:34:19 +08:00
|
|
|
/* we pass in floats,
|
|
|
|
but they are promoted to double by the compiler */
|
2001-07-04 02:38:56 +08:00
|
|
|
xresolution = va_arg (args, double);
|
|
|
|
yresolution = va_arg (args, double);
|
|
|
|
|
|
|
|
size = 4*2;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_float_check_error (info->fp, &xresolution, 1);
|
|
|
|
xcf_write_float_check_error (info->fp, &yresolution, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_TATTOO:
|
|
|
|
{
|
|
|
|
guint32 tattoo;
|
|
|
|
|
|
|
|
tattoo = va_arg (args, guint32);
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &tattoo, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_PARASITES:
|
|
|
|
{
|
2001-07-05 06:59:25 +08:00
|
|
|
GimpParasiteList *list;
|
|
|
|
guint32 base, length;
|
|
|
|
long pos;
|
|
|
|
|
|
|
|
list = va_arg (args, GimpParasiteList *);
|
|
|
|
|
|
|
|
if (gimp_parasite_list_persistent_length (list) > 0)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
/* because we don't know how much room the parasite list will take
|
|
|
|
* we save the file position and write the length later
|
|
|
|
*/
|
2001-07-19 23:34:19 +08:00
|
|
|
pos = info->cp;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &length, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
base = info->cp;
|
2001-07-19 23:34:19 +08:00
|
|
|
gimp_parasite_list_foreach (list,
|
|
|
|
(GHFunc) xcf_save_parasite, info);
|
2001-07-04 02:38:56 +08:00
|
|
|
length = info->cp - base;
|
|
|
|
/* go back to the saved position and write the length */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, pos, error));
|
|
|
|
xcf_write_int32 (info->fp, &length, 1, &tmp_error);
|
|
|
|
if (tmp_error)
|
|
|
|
{
|
|
|
|
g_propagate_error (error, tmp_error);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcf_check_error (xcf_seek_end (info, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_UNIT:
|
|
|
|
{
|
|
|
|
guint32 unit;
|
|
|
|
|
|
|
|
unit = va_arg (args, guint32);
|
|
|
|
|
|
|
|
size = 4;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &unit, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_PATHS:
|
|
|
|
{
|
2003-05-22 01:38:14 +08:00
|
|
|
guint32 base, length;
|
|
|
|
glong pos;
|
|
|
|
|
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
|
|
|
|
|
|
|
/* because we don't know how much room the paths list will take
|
|
|
|
we save the file position and write the length later
|
|
|
|
*/
|
|
|
|
pos = info->cp;
|
|
|
|
xcf_write_int32_check_error (info->fp, &length, 1);
|
2001-07-19 23:34:19 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
base = info->cp;
|
2001-07-19 23:34:19 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
xcf_check_error (xcf_save_old_paths (info, gimage, error));
|
|
|
|
|
|
|
|
length = info->cp - base;
|
|
|
|
|
|
|
|
/* go back to the saved position and write the length */
|
|
|
|
xcf_check_error (xcf_seek_pos (info, pos, error));
|
|
|
|
xcf_write_int32 (info->fp, &length, 1, &tmp_error);
|
|
|
|
if (tmp_error)
|
2001-07-19 23:34:19 +08:00
|
|
|
{
|
2003-05-22 01:38:14 +08:00
|
|
|
g_propagate_error (error, tmp_error);
|
|
|
|
return FALSE;
|
2001-07-19 23:34:19 +08:00
|
|
|
}
|
2003-05-22 01:38:14 +08:00
|
|
|
|
|
|
|
xcf_check_error (xcf_seek_end (info, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PROP_USER_UNIT:
|
|
|
|
{
|
2001-12-17 00:33:18 +08:00
|
|
|
GimpUnit unit;
|
|
|
|
const gchar *unit_strings[5];
|
|
|
|
gfloat factor;
|
|
|
|
guint32 digits;
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
unit = va_arg (args, guint32);
|
|
|
|
|
|
|
|
/* write the entire unit definition */
|
removed the gimp_busy boolean, check whether user_installation is needed
2001-07-10 Michael Natterer <mitch@gimp.org>
* app/app_procs.[ch]: removed the gimp_busy boolean, check whether
user_installation is needed here, not in user_install.c, parse
gtkrc an friends only if(!no_interface), create the Gimp object
before parsing gimp's rc files an pas it to the parse functions,
many other cleanups.
* app/appenums.h: added MessageHandlerType and StackTraceMode.
* app/appenv.h: removed MessageHandlerType, declare all global
variables from main.c (no more hidden global stuff please).
* app/errors.[ch]: added the fatal message func here (from main.c),
removed the StackTraceMode enum.
* app/gimprc.[ch]: renamed functions to gimprc_*(), pass a Gimp
pointer to some functions.
* app/gimpunit.c
* app/unitrc.h: ok, this is ugly: renamed all functions to
_gimp_unit_*() and made them public. The unit list is part
of the Gimp object now, so pass a Gimp* to all functions.
* app/libgimp_glue.[ch]: added EEKy wrappers for all gimp_unit_*()
functions which are used by widgets.
* app/main.c: cleaned up the global variables, removed the fatal
message handler, call app_init() directly, not via the
user_install stuff, misc. cleanups.
* app/user_install.[ch]: removed the check if user_installation is
needed (done by app_procs.c now).
* app/core/gimp.[ch]: added the user_unit list and the "busy"
boolean. Moved gimp_[set|unset]_busy() here. Added
gimp_initialize() which is called after unitrc and gimprc are
parsed.
* app/batch.c
* app/colormaps.c
* app/devices.c
* app/disp_callbacks.c
* app/gdisplay_ops.c
* app/gimphelp.c
* app/module_db.c
* app/nav_window.c
* app/plug_in.c
* app/core/gimpcontext.c
* app/core/gimpdatafiles.c
* app/core/gimpimage-convert.c
* app/core/gimpimage-duplicate.c
* app/core/gimpimage.c
* app/core/gimpparasite.c
* app/core/gimpparasitelist.h
* app/gui/file-open-dialog.c
* app/gui/gui.[ch]
* app/gui/info-dialog.c
* app/gui/info-window.c
* app/gui/preferences-dialog.c
* app/gui/session.c
* app/gui/tips-dialog.c
* app/gui/toolbox.c
* app/tools/gimpblendtool.c
* app/tools/gimpbucketfilltool.c
* app/tools/gimpcolorpickertool.c
* app/tools/gimpfuzzyselecttool.c
* app/tools/gimptransformtool.c
* app/tools/tool_manager.c
* app/widgets/gimpcolorpanel.c
* app/widgets/gimpcursor.c
* app/xcf/xcf-load.c
* app/xcf/xcf-save.c
* app/xcf/xcf.c
* tools/pdbgen/Makefile.am
* tools/pdbgen/app.pl
* tools/pdbgen/enums.pl
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/message.pdb
* tools/pdbgen/pdb/unit.pdb
* app/pdb/image_cmds.c
* app/pdb/message_cmds.c
* app/pdb/unit_cmds.c: changed accordingly, minor cleanups.
2001-07-11 03:16:16 +08:00
|
|
|
unit_strings[0] = _gimp_unit_get_identifier (gimage->gimp, unit);
|
|
|
|
factor = _gimp_unit_get_factor (gimage->gimp, unit);
|
|
|
|
digits = _gimp_unit_get_digits (gimage->gimp, unit);
|
|
|
|
unit_strings[1] = _gimp_unit_get_symbol (gimage->gimp, unit);
|
|
|
|
unit_strings[2] = _gimp_unit_get_abbreviation (gimage->gimp, unit);
|
|
|
|
unit_strings[3] = _gimp_unit_get_singular (gimage->gimp, unit);
|
|
|
|
unit_strings[4] = _gimp_unit_get_plural (gimage->gimp, unit);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
size =
|
|
|
|
2 * 4 +
|
|
|
|
strlen (unit_strings[0]) ? strlen (unit_strings[0]) + 5 : 4 +
|
|
|
|
strlen (unit_strings[1]) ? strlen (unit_strings[1]) + 5 : 4 +
|
|
|
|
strlen (unit_strings[2]) ? strlen (unit_strings[2]) + 5 : 4 +
|
|
|
|
strlen (unit_strings[3]) ? strlen (unit_strings[3]) + 5 : 4 +
|
|
|
|
strlen (unit_strings[4]) ? strlen (unit_strings[4]) + 5 : 4;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &prop_type, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &size, 1);
|
|
|
|
xcf_write_float_check_error (info->fp, &factor, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &digits, 1);
|
|
|
|
xcf_write_string_check_error (info->fp, (gchar **) unit_strings, 5);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
va_end (args);
|
2002-12-20 14:26:34 +08:00
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
2001-07-04 02:38:56 +08:00
|
|
|
xcf_save_layer (XcfInfo *info,
|
|
|
|
GimpImage *gimage,
|
2002-12-20 14:26:34 +08:00
|
|
|
GimpLayer *layer,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
guint32 saved_pos;
|
|
|
|
guint32 offset;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
/* check and see if this is the drawable that the floating
|
|
|
|
* selection is attached to.
|
|
|
|
*/
|
|
|
|
if (GIMP_DRAWABLE(layer) == info->floating_sel_drawable)
|
|
|
|
{
|
|
|
|
saved_pos = info->cp;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &saved_pos, 1);
|
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* write out the width, height and image type information for the layer */
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp,
|
2003-05-08 19:52:31 +08:00
|
|
|
(guint32 *) &GIMP_ITEM (layer)->width, 1);
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp,
|
2003-05-08 19:52:31 +08:00
|
|
|
(guint32 *) &GIMP_ITEM (layer)->height, 1);
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp,
|
2003-05-08 19:52:31 +08:00
|
|
|
(guint32 *) &GIMP_DRAWABLE (layer)->type, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* write out the layers name */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_string_check_error (info->fp, &GIMP_OBJECT (layer)->name, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* write out the layer properties */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_save_layer_props (info, gimage, layer, error);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* save the current position which is where the hierarchy offset
|
|
|
|
* will be stored.
|
|
|
|
*/
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* write out the layer tile hierarchy */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, info->cp + 8, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
offset = info->cp;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_check_error (xcf_save_hierarchy (info,
|
|
|
|
GIMP_DRAWABLE(layer)->tiles, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* write out the layer mask */
|
|
|
|
if (layer->mask)
|
|
|
|
{
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_end (info, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
offset = info->cp;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_check_error (xcf_save_channel (info,
|
|
|
|
gimage, GIMP_CHANNEL(layer->mask),
|
|
|
|
error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
offset = 0;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &offset, 1);
|
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
|
|
|
xcf_save_channel (XcfInfo *info,
|
|
|
|
GimpImage *gimage,
|
|
|
|
GimpChannel *channel,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
guint32 saved_pos;
|
|
|
|
guint32 offset;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
/* check and see if this is the drawable that the floating
|
|
|
|
* selection is attached to.
|
|
|
|
*/
|
2001-07-19 23:34:19 +08:00
|
|
|
if (GIMP_DRAWABLE (channel) == info->floating_sel_drawable)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
saved_pos = info->cp;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &info->cp, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* write out the width and height information for the channel */
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp,
|
2003-05-08 19:52:31 +08:00
|
|
|
(guint32 *) &GIMP_ITEM (channel)->width, 1);
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp,
|
2003-05-08 19:52:31 +08:00
|
|
|
(guint32 *) &GIMP_ITEM (channel)->height, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* write out the channels name */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_string_check_error (info->fp, &GIMP_OBJECT (channel)->name, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* write out the channel properties */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_save_channel_props (info, gimage, channel, error);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* save the current position which is where the hierarchy offset
|
|
|
|
* will be stored.
|
|
|
|
*/
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* write out the channel tile hierarchy */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, info->cp + 4, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
offset = info->cp;
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_check_error (xcf_save_hierarchy (info,
|
|
|
|
GIMP_DRAWABLE (channel)->tiles, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
saved_pos = info->cp;
|
2002-12-20 14:26:34 +08:00
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
xcf_calc_levels (gint size,
|
|
|
|
gint tile_size)
|
|
|
|
{
|
|
|
|
int levels;
|
|
|
|
|
|
|
|
levels = 1;
|
|
|
|
while (size > tile_size)
|
|
|
|
{
|
|
|
|
size /= 2;
|
|
|
|
levels += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return levels;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
2001-07-04 02:38:56 +08:00
|
|
|
xcf_save_hierarchy (XcfInfo *info,
|
2002-12-20 14:26:34 +08:00
|
|
|
TileManager *tiles,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
guint32 saved_pos;
|
|
|
|
guint32 offset;
|
|
|
|
guint32 width;
|
|
|
|
guint32 height;
|
|
|
|
guint32 bpp;
|
|
|
|
gint i;
|
|
|
|
gint nlevels;
|
|
|
|
gint tmp1, tmp2;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
width = tile_manager_width (tiles);
|
|
|
|
height = tile_manager_height (tiles);
|
|
|
|
bpp = tile_manager_bpp (tiles);
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &width, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &height, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &bpp, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
tmp1 = xcf_calc_levels (width, TILE_WIDTH);
|
|
|
|
tmp2 = xcf_calc_levels (height, TILE_HEIGHT);
|
|
|
|
nlevels = MAX (tmp1, tmp2);
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
for (i = 0; i < nlevels; i++)
|
|
|
|
{
|
|
|
|
offset = info->cp;
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
{
|
|
|
|
/* write out the level. */
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_level (info, tiles, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* fake an empty level */
|
|
|
|
tmp1 = 0;
|
|
|
|
width /= 2;
|
|
|
|
height /= 2;
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &width, 1);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &height, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &tmp1, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* seek back to where we are to write out the next
|
|
|
|
* level offset and write it out.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* increment the location we are to write out the
|
|
|
|
* next offset.
|
|
|
|
*/
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* seek to the end of the file which is where
|
|
|
|
* we will write out the next level.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_end (info, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* write out a '0' offset position to indicate the end
|
|
|
|
* of the level offsets.
|
|
|
|
*/
|
|
|
|
offset = 0;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &offset, 1);
|
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
2001-07-04 02:38:56 +08:00
|
|
|
xcf_save_level (XcfInfo *info,
|
2002-12-20 14:26:34 +08:00
|
|
|
TileManager *level,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
guint32 saved_pos;
|
|
|
|
guint32 offset;
|
|
|
|
guint32 width;
|
|
|
|
guint32 height;
|
|
|
|
guint ntiles;
|
|
|
|
gint i;
|
|
|
|
guchar *rlebuf;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
width = tile_manager_width (level);
|
|
|
|
height = tile_manager_height (level);
|
|
|
|
|
2003-04-10 22:15:24 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &width, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, (guint32 *) &height, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* allocate a temporary buffer to store the rle data before it is
|
|
|
|
written to disk */
|
2001-07-19 23:34:19 +08:00
|
|
|
rlebuf =
|
|
|
|
g_malloc (TILE_WIDTH * TILE_HEIGHT * tile_manager_bpp (level) * 1.5);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
if (level->tiles)
|
|
|
|
{
|
|
|
|
ntiles = level->ntile_rows * level->ntile_cols;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
for (i = 0; i < ntiles; i++)
|
|
|
|
{
|
|
|
|
/* save the start offset of where we are writing
|
|
|
|
* out the next tile.
|
|
|
|
*/
|
|
|
|
offset = info->cp;
|
|
|
|
|
|
|
|
/* write out the tile. */
|
|
|
|
switch (info->compression)
|
|
|
|
{
|
|
|
|
case COMPRESS_NONE:
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error(xcf_save_tile (info, level->tiles[i], error));
|
2001-07-04 02:38:56 +08:00
|
|
|
break;
|
|
|
|
case COMPRESS_RLE:
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_save_tile_rle (info, level->tiles[i],
|
|
|
|
rlebuf, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
break;
|
|
|
|
case COMPRESS_ZLIB:
|
|
|
|
g_error ("xcf: zlib compression unimplemented");
|
|
|
|
break;
|
|
|
|
case COMPRESS_FRACTAL:
|
|
|
|
g_error ("xcf: fractal compression unimplemented");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* seek back to where we are to write out the next
|
|
|
|
* tile offset and write it out.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &offset, 1);
|
2001-07-04 02:38:56 +08:00
|
|
|
|
|
|
|
/* increment the location we are to write out the
|
|
|
|
* next offset.
|
|
|
|
*/
|
|
|
|
saved_pos = info->cp;
|
|
|
|
|
|
|
|
/* seek to the end of the file which is where
|
|
|
|
* we will write out the next tile.
|
|
|
|
*/
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_end (info, error));
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (rlebuf);
|
|
|
|
|
|
|
|
/* write out a '0' offset position to indicate the end
|
|
|
|
* of the level offsets.
|
|
|
|
*/
|
|
|
|
offset = 0;
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
|
|
|
|
xcf_write_int32_check_error (info->fp, &offset, 1);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
|
|
|
xcf_save_tile (XcfInfo *info,
|
|
|
|
Tile *tile,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
tile_lock (tile);
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int8_check_error (info->fp, tile_data_pointer (tile, 0, 0),
|
2001-07-04 02:38:56 +08:00
|
|
|
tile_size (tile));
|
|
|
|
tile_release (tile, FALSE);
|
2002-12-20 14:26:34 +08:00
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
static gboolean
|
|
|
|
xcf_save_tile_rle (XcfInfo *info,
|
|
|
|
Tile *tile,
|
|
|
|
guchar *rlebuf,
|
|
|
|
GError **error)
|
2001-07-04 02:38:56 +08:00
|
|
|
{
|
|
|
|
guchar *data, *t;
|
|
|
|
unsigned int last;
|
|
|
|
gint state;
|
|
|
|
gint length;
|
|
|
|
gint count;
|
|
|
|
gint size;
|
|
|
|
gint bpp;
|
|
|
|
gint i, j;
|
|
|
|
gint len = 0;
|
|
|
|
|
2002-12-20 14:26:34 +08:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
tile_lock (tile);
|
|
|
|
|
|
|
|
bpp = tile_bpp (tile);
|
|
|
|
|
|
|
|
for (i = 0; i < bpp; i++)
|
|
|
|
{
|
|
|
|
data = (guchar*) tile_data_pointer (tile, 0, 0) + i;
|
|
|
|
|
|
|
|
state = 0;
|
|
|
|
length = 0;
|
|
|
|
count = 0;
|
|
|
|
size = tile_ewidth(tile) * tile_eheight(tile);
|
|
|
|
last = -1;
|
|
|
|
|
|
|
|
while (size > 0)
|
|
|
|
{
|
|
|
|
switch (state)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
/* in state 0 we try to find a long sequence of
|
|
|
|
* matching values.
|
|
|
|
*/
|
|
|
|
if ((length == 32768) ||
|
|
|
|
((size - length) <= 0) ||
|
|
|
|
((length > 1) && (last != *data)))
|
|
|
|
{
|
|
|
|
count += length;
|
|
|
|
if (length >= 128)
|
|
|
|
{
|
|
|
|
rlebuf[len++] = 127;
|
|
|
|
rlebuf[len++] = (length >> 8);
|
|
|
|
rlebuf[len++] = length & 0x00FF;
|
|
|
|
rlebuf[len++] = last;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rlebuf[len++] = length - 1;
|
|
|
|
rlebuf[len++] = last;
|
|
|
|
}
|
|
|
|
size -= length;
|
|
|
|
length = 0;
|
|
|
|
}
|
|
|
|
else if ((length == 1) && (last != *data))
|
|
|
|
state = 1;
|
|
|
|
break;
|
2001-07-19 23:34:19 +08:00
|
|
|
|
2001-07-04 02:38:56 +08:00
|
|
|
case 1:
|
|
|
|
/* in state 1 we try and find a long sequence of
|
|
|
|
* non-matching values.
|
|
|
|
*/
|
|
|
|
if ((length == 32768) ||
|
|
|
|
((size - length) == 0) ||
|
|
|
|
((length > 0) && (last == *data) &&
|
|
|
|
((size - length) == 1 || last == data[bpp])))
|
|
|
|
{
|
|
|
|
count += length;
|
|
|
|
state = 0;
|
|
|
|
|
|
|
|
if (length >= 128)
|
|
|
|
{
|
|
|
|
rlebuf[len++] = 255 - 127;
|
|
|
|
rlebuf[len++] = (length >> 8);
|
|
|
|
rlebuf[len++] = length & 0x00FF;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rlebuf[len++] = 255 - (length - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
t = data - length * bpp;
|
|
|
|
for (j = 0; j < length; j++)
|
|
|
|
{
|
|
|
|
rlebuf[len++] = *t;
|
|
|
|
t += bpp;
|
|
|
|
}
|
|
|
|
|
|
|
|
size -= length;
|
|
|
|
length = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (size > 0) {
|
|
|
|
length += 1;
|
|
|
|
last = *data;
|
|
|
|
data += bpp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count != (tile_ewidth (tile) * tile_eheight (tile)))
|
|
|
|
g_message ("xcf: uh oh! xcf rle tile saving error: %d", count);
|
|
|
|
}
|
2002-12-20 14:26:34 +08:00
|
|
|
xcf_write_int8_check_error (info->fp, rlebuf, len);
|
2001-07-04 02:38:56 +08:00
|
|
|
tile_release (tile, FALSE);
|
2002-12-20 14:26:34 +08:00
|
|
|
|
|
|
|
return TRUE;
|
2001-07-04 02:38:56 +08:00
|
|
|
}
|
2003-05-15 20:47:42 +08:00
|
|
|
|
|
|
|
static void
|
|
|
|
xcf_save_parasite (gchar *key,
|
|
|
|
GimpParasite *parasite,
|
|
|
|
XcfInfo *info)
|
|
|
|
{
|
|
|
|
/* can't fail fast because there is no way to exit g_slist_foreach */
|
|
|
|
|
|
|
|
if (! gimp_parasite_is_persistent (parasite))
|
|
|
|
return;
|
|
|
|
|
|
|
|
info->cp += xcf_write_string (info->fp, ¶site->name, 1, NULL);
|
|
|
|
info->cp += xcf_write_int32 (info->fp, ¶site->flags, 1, NULL);
|
|
|
|
info->cp += xcf_write_int32 (info->fp, ¶site->size, 1, NULL);
|
|
|
|
info->cp += xcf_write_int8 (info->fp, parasite->data, parasite->size, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2003-05-22 01:38:14 +08:00
|
|
|
xcf_save_old_paths (XcfInfo *info,
|
|
|
|
GimpImage *gimage,
|
|
|
|
GError **error)
|
2003-05-15 20:47:42 +08:00
|
|
|
{
|
2003-05-22 01:38:14 +08:00
|
|
|
GimpVectors *active_vectors;
|
|
|
|
guint32 num_paths;
|
|
|
|
guint32 active_index = 0;
|
|
|
|
GList *list;
|
|
|
|
GError *tmp_error = NULL;
|
2003-05-15 20:47:42 +08:00
|
|
|
|
|
|
|
/* Write out the following:-
|
|
|
|
*
|
|
|
|
* last_selected_row (gint)
|
|
|
|
* number_of_paths (gint)
|
|
|
|
*
|
|
|
|
* then each path:-
|
|
|
|
*/
|
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
num_paths = gimp_container_num_children (gimage->vectors);
|
|
|
|
|
|
|
|
active_vectors = gimp_image_get_active_vectors (gimage);
|
2003-05-15 20:47:42 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
if (active_vectors)
|
|
|
|
active_index = gimp_container_get_child_index (gimage->vectors,
|
|
|
|
GIMP_OBJECT (active_vectors));
|
|
|
|
|
|
|
|
xcf_write_int32_check_error (info->fp, &active_index, 1);
|
2003-05-15 20:47:42 +08:00
|
|
|
xcf_write_int32_check_error (info->fp, &num_paths, 1);
|
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
for (list = GIMP_LIST (gimage->vectors)->list;
|
|
|
|
list;
|
|
|
|
list = g_list_next (list))
|
2003-05-15 20:47:42 +08:00
|
|
|
{
|
2003-05-22 01:38:14 +08:00
|
|
|
GimpVectors *vectors = list->data;
|
|
|
|
gchar *name;
|
|
|
|
guint32 locked;
|
|
|
|
guint8 state;
|
|
|
|
guint32 num_points = 0;
|
|
|
|
guint32 closed = FALSE;
|
|
|
|
guint32 version;
|
|
|
|
guint32 pathtype;
|
|
|
|
guint32 tattoo;
|
|
|
|
GList *strokes;
|
2003-05-15 20:47:42 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* name (string)
|
|
|
|
* locked (gint)
|
|
|
|
* state (gchar)
|
|
|
|
* closed (gint)
|
|
|
|
* number points (gint)
|
2003-05-22 01:38:14 +08:00
|
|
|
* version (gint)
|
|
|
|
* pathtype (gint)
|
|
|
|
* tattoo (gint)
|
2003-05-15 20:47:42 +08:00
|
|
|
* then each point.
|
|
|
|
*/
|
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
for (strokes = vectors->strokes; strokes; strokes = g_list_next (strokes))
|
|
|
|
{
|
|
|
|
GimpStroke *stroke = strokes->data;
|
|
|
|
gint n_anchors;
|
2003-05-15 20:47:42 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
g_assert (stroke->closed || ! strokes->next);
|
2003-05-15 20:47:42 +08:00
|
|
|
|
2003-05-22 01:38:14 +08:00
|
|
|
n_anchors = g_list_length (stroke->anchors);
|
|
|
|
|
|
|
|
if (! stroke->closed)
|
|
|
|
n_anchors--;
|
|
|
|
|
|
|
|
num_points += n_anchors;
|
|
|
|
|
|
|
|
if (! strokes->next)
|
|
|
|
closed = stroke->closed;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = (gchar *) gimp_object_get_name (GIMP_OBJECT (vectors));
|
|
|
|
locked = gimp_item_get_linked (GIMP_ITEM (vectors));
|
|
|
|
state = closed ? 4 : 2;
|
|
|
|
version = 3;
|
|
|
|
pathtype = 1;
|
|
|
|
tattoo = gimp_item_get_tattoo (GIMP_ITEM (vectors));
|
|
|
|
|
|
|
|
xcf_write_string_check_error (info->fp, &name, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &locked, 1);
|
|
|
|
xcf_write_int8_check_error (info->fp, &state, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &closed, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &num_points, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &version, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &pathtype, 1);
|
|
|
|
xcf_write_int32_check_error (info->fp, &tattoo, 1);
|
|
|
|
|
|
|
|
for (strokes = vectors->strokes;
|
|
|
|
strokes;
|
|
|
|
strokes = g_list_next (strokes))
|
2003-05-15 20:47:42 +08:00
|
|
|
{
|
2003-05-22 01:38:14 +08:00
|
|
|
GimpStroke *stroke = strokes->data;
|
|
|
|
GList *anchors;
|
|
|
|
|
|
|
|
for (anchors = stroke->anchors;
|
|
|
|
anchors;
|
|
|
|
anchors = g_list_next (anchors))
|
|
|
|
{
|
|
|
|
GimpAnchor *anchor = anchors->data;
|
|
|
|
guint32 type;
|
|
|
|
gfloat x;
|
|
|
|
gfloat y;
|
|
|
|
|
|
|
|
/* skip the first anchor, will add it at the end if needed */
|
|
|
|
if (! anchors->prev)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* type (gint32)
|
|
|
|
* x (float)
|
|
|
|
* y (float)
|
|
|
|
*/
|
|
|
|
|
|
|
|
switch (anchor->type)
|
|
|
|
{
|
|
|
|
case GIMP_ANCHOR_ANCHOR:
|
|
|
|
if (strokes->prev && anchors->prev == stroke->anchors)
|
|
|
|
type = 3; /* new stroke marker */
|
|
|
|
else
|
|
|
|
type = 1; /* ordinary anchor */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_ANCHOR_CONTROL:
|
|
|
|
type = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = anchor->position.x;
|
|
|
|
y = anchor->position.y;
|
|
|
|
|
|
|
|
xcf_write_int32_check_error (info->fp, &type, 1);
|
|
|
|
xcf_write_float_check_error (info->fp, &x, 1);
|
|
|
|
xcf_write_float_check_error (info->fp, &y, 1);
|
|
|
|
|
|
|
|
/* write the skipped control point */
|
|
|
|
if (! anchors->next && stroke->closed)
|
|
|
|
{
|
|
|
|
anchor = (GimpAnchor *) stroke->anchors->data;
|
|
|
|
|
|
|
|
type = 2;
|
|
|
|
x = anchor->position.x;
|
|
|
|
y = anchor->position.y;
|
|
|
|
|
|
|
|
xcf_write_int32_check_error (info->fp, &type, 1);
|
|
|
|
xcf_write_float_check_error (info->fp, &x, 1);
|
|
|
|
xcf_write_float_check_error (info->fp, &y, 1);
|
|
|
|
}
|
|
|
|
}
|
2003-05-15 20:47:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|