gimp/app/xcf/xcf-save.c

1868 lines
56 KiB
C
Raw Normal View History

/* GIMP - The GNU 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <gegl.h>
#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/gimp.h"
#include "core/gimpcontainer.h"
#include "core/gimpchannel.h"
#include "core/gimpdrawable.h"
#include "core/gimpgrid.h"
#include "core/gimpguide.h"
#include "core/gimpimage.h"
#include "core/gimpimage-colormap.h"
#include "core/gimpimage-grid.h"
Treat changes to the selection like changes to any other drawable: 2003-10-06 Michael Natterer <mitch@gimp.org> Treat changes to the selection like changes to any other drawable: * app/core/gimpchannel.c * app/core/gimpchannel-combine.c: call gimp_drawable_update() after changing the channel. * app/core/gimpimage.[ch]: added struct GimpImageFlushAccumulator with one member "gboolean mask_changed". Connect to "update" of the selection and set accum.mask_changed to TRUE in the callback. Added default implementation for GimpImage::flush() and emit "mask_changed" there. Unrelated: * app/core/gimpimage.h: removed GimpGuide struct... * app/core/gimpimage-guides.h: ...and added it here. * app/core/gimpimage-undo-push.c (undo_pop_mask) (undo_pop_channel_mod): don't distinguish between selection and non-selection channels and just call gimp_drawable_update(). * app/core/gimpundo.h * app/core/gimpimage-undo.c: removed "gboolean mask_changed" from the GimpUndoAccumulator struct since we don't have to care about that signal explicitly any more. * app/display/gimpdisplay-foreach.[ch]: removed gimp_displays_flush(). * tools/pdbgen/pdb/display.pdb (displays_flush_invoker): call gimp_image_flush() on all images so the flush accumulator is honored. This generalization enables the removal of more special purpose code which was needed to treat the selection different: * app/core/gimpimage-mask-select.[ch]: removed... * app/core/gimpchannel-select.[ch]: ...and added under a new name because it's not selection specific any more. * app/core/gimpimage-mask.[ch]: removed... * app/core/gimpselection.[ch]: ...added the two remaining functions here. Removed all calls to gimp_image_mask_changed(). * app/core/Makefile.am * app/core/gimp-edit.c * app/core/gimpdrawable-transform.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/display/gimpdisplayshell.c * app/gui/channels-commands.c * app/gui/layers-commands.c * app/gui/select-commands.c * app/gui/vectors-commands.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpellipseselecttool.c * app/tools/gimpfreeselecttool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpiscissorstool.c * app/tools/gimprectselecttool.c * app/tools/gimptransformtool.c * app/widgets/gimpchanneltreeview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpvectorstreeview.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/paths.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/selection_tools.pdb: changed accordingly. * app/core/gimpdrawable-bucket-fill.c * app/core/gimpimage-colormap.c * app/core/gimplayer-floating-sel.c * app/core/gimplayer.c * app/gui/image-menu.c * app/paint/gimppaintcore.c * app/tools/gimpcroptool.c * app/tools/gimpinkoptions.c * app/tools/gimpvectortool.c: removed useless and/or obsolete #includes. * app/pdb/display_cmds.c * app/pdb/paths_cmds.c * app/pdb/selection_cmds.c * app/pdb/selection_tools_cmds.c: regenerated.
2003-10-06 20:17:11 +08:00
#include "core/gimpimage-guides.h"
#include "core/gimpimage-sample-points.h"
#include "core/gimplayer.h"
#include "core/gimplayermask.h"
#include "core/gimpparasitelist.h"
#include "core/gimpprogress.h"
#include "core/gimpsamplepoint.h"
app/Makefile.am app/gimpunit.c removed... 2001-07-11 Michael Natterer <mitch@gimp.org> * app/Makefile.am * app/gimpunit.c * app/unitrc.h: removed... * app/core/Makefile.am * app/core/gimpunit.[ch]: ...re-added here. * app/core/gimp.[ch]: added the image and drawable hash tables, next_image_ID, next_guide_ID and next_drawable_ID, added a GimpCoreConfig pointer which is now initalized dynamically. * app/core/gimpcoreconfig.[ch]: don't provide a global core_config variable any more (need to access gimp->config now). * app/gdisplay.[ch] * app/core/gimpdrawable.[ch] * app/core/gimpimage.[ch]: removed all global variables from gimpimage.c and gimpdrawable.c, pass a Gimp* to all *_get_by_ID() functions. * tools/pdbgen/app.pl: pass Gimp* to all _get_by_ID() functions. * app/app_procs.c * app/file-open.c * app/file-save.c * app/gimprc.c * app/libgimp_glue.c * app/module_db.c * app/plug_in.c * app/undo.c * app/user_install.c * app/core/core-types.h * app/core/gimpcontext.c * app/core/gimpimage-crop.c * app/core/gimpimage-new.c * app/core/gimpparasite.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/info-window.c * app/gui/preferences-dialog.c * app/gui/resize-dialog.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/xcf/xcf.c * app/widgets/gimpdnd.c * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/convert_cmds.c * app/pdb/display_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/fileops_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/guides_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/parasite_cmds.c * app/pdb/paths_cmds.c * app/pdb/selection_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/tools_cmds.c * app/pdb/undo_cmds.c * app/pdb/unit_cmds.c * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/unit.pdb: changed accordingly.
2001-07-11 20:39:49 +08:00
#include "core/gimpunit.h"
#include "text/gimptextlayer.h"
#include "text/gimptextlayer-xcf.h"
#include "vectors/gimpanchor.h"
#include "vectors/gimpstroke.h"
#include "vectors/gimpbezierstroke.h"
#include "vectors/gimpvectors.h"
#include "vectors/gimpvectors-compat.h"
#include "xcf-private.h"
#include "xcf-read.h"
#include "xcf-save.h"
#include "xcf-seek.h"
#include "xcf-write.h"
#include "gimp-intl.h"
static gboolean xcf_save_image_props (XcfInfo *info,
GimpImage *image,
GError **error);
static gboolean xcf_save_layer_props (XcfInfo *info,
GimpImage *image,
GimpLayer *layer,
GError **error);
static gboolean xcf_save_channel_props (XcfInfo *info,
GimpImage *image,
GimpChannel *channel,
GError **error);
static gboolean xcf_save_prop (XcfInfo *info,
GimpImage *image,
PropType prop_type,
GError **error,
...);
static gboolean xcf_save_layer (XcfInfo *info,
GimpImage *image,
GimpLayer *layer,
GError **error);
static gboolean xcf_save_channel (XcfInfo *info,
GimpImage *image,
GimpChannel *channel,
GError **error);
static gboolean xcf_save_hierarchy (XcfInfo *info,
TileManager *tiles,
GError **error);
static gboolean xcf_save_level (XcfInfo *info,
TileManager *tiles,
GError **error);
static gboolean xcf_save_tile (XcfInfo *info,
Tile *tile,
GError **error);
static gboolean xcf_save_tile_rle (XcfInfo *info,
Tile *tile,
guchar *rlebuf,
GError **error);
static gboolean xcf_save_parasite (XcfInfo *info,
GimpParasite *parasite,
GError **error);
static gboolean xcf_save_parasite_list (XcfInfo *info,
GimpParasiteList *parasite,
GError **error);
static gboolean xcf_save_old_paths (XcfInfo *info,
GimpImage *image,
GError **error);
static gboolean xcf_save_vectors (XcfInfo *info,
GimpImage *image,
GError **error);
/* private convenience macros */
#define xcf_write_int32_check_error(info, data, count) G_STMT_START { \
info->cp += xcf_write_int32 (info->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(info, data, count) G_STMT_START { \
info->cp += xcf_write_int8 (info->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(info, data, count) G_STMT_START { \
info->cp += xcf_write_float (info->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(info, data, count) G_STMT_START { \
info->cp += xcf_write_string (info->fp, data, count, &tmp_error); \
if (tmp_error) \
{ \
g_propagate_error (error, tmp_error); \
return FALSE; \
} \
} G_STMT_END
#define xcf_write_prop_type_check_error(info, prop_type) G_STMT_START { \
guint32 _prop_int32 = prop_type; \
xcf_write_int32_check_error (info, &_prop_int32, 1); \
} G_STMT_END
#define xcf_check_error(x) G_STMT_START { \
if (! (x)) \
return FALSE; \
} G_STMT_END
#define xcf_progress_update(info) G_STMT_START \
{ \
progress++; \
if (info->progress) \
gimp_progress_set_value (info->progress, \
(gdouble) progress / (gdouble) max_progress); \
} G_STMT_END
void
xcf_save_choose_format (XcfInfo *info,
GimpImage *image)
{
GList *list;
gint save_version = 0; /* default to oldest */
app/actions/channels-commands.c app/actions/colormap-actions.c 2007-12-25 Michael Natterer <mitch@gimp.org> * app/actions/channels-commands.c * app/actions/colormap-actions.c * app/actions/colormap-commands.c * app/actions/image-commands.c * app/core/gimp-edit.c * app/core/gimpdrawable-preview.c * app/core/gimpimage-colorhash.c * app/core/gimpimage-colormap.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-flip.c * app/core/gimpimage-guides.c * app/core/gimpimage-merge.c * app/core/gimpimage-preview.c * app/core/gimpimage-quick-mask.c * app/core/gimpimage-resize.c * app/core/gimpimage-rotate.c * app/core/gimpimage-sample-points.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpimageundo.c * app/core/gimpitem-preview.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimppalette-import.c * app/core/gimpprojection-construct.c * app/core/gimpprojection.c * app/core/gimpselection.c * app/core/gimpundo.c * app/dialogs/layer-options-dialog.c * app/dialogs/print-size-dialog.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/display/gimpstatusbar.c * app/file/file-open.c * app/paint/gimppaintoptions.c * app/tools/gimpaligntool.c * app/tools/gimpcolortool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimpperspectiveclonetool.c * app/tools/gimprectangleselecttool.c * app/tools/gimprectangletool.c * app/tools/gimprotatetool.c * app/vectors/gimpvectors-export.c * app/vectors/gimpvectors-import.c * app/vectors/gimpvectors.c * app/widgets/gimpimagepropview.c * app/widgets/gimpnavigationview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrendererimage.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/image.pdb: use accessors for many image properties. * app/pdb/guides_cmds.c * app/pdb/image_cmds.c: regenerated. svn path=/trunk/; revision=24432
2007-12-26 00:21:40 +08:00
if (gimp_image_get_colormap (image))
save_version = 1; /* need version 1 for colormaps */
for (list = gimp_image_get_layer_iter (image);
list && save_version < 2;
list = g_list_next (list))
{
GimpLayer *layer = GIMP_LAYER (list->data);
switch (gimp_layer_get_mode (layer))
{
/* 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;
}
}
info->file_version = save_version;
}
gint
xcf_save_image (XcfInfo *info,
GimpImage *image,
GError **error)
{
2009-08-31 03:07:22 +08:00
GList *list;
guint32 saved_pos;
guint32 offset;
guint32 value;
guint n_layers;
guint n_channels;
guint progress = 0;
guint max_progress;
gboolean have_selection;
gint t1, t2, t3, t4;
gchar version_tag[16];
GError *tmp_error = NULL;
/* 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");
}
xcf_write_int8_check_error (info, (guint8 *) version_tag, 14);
/* write out the width, height and image type information for the image */
app/actions/channels-commands.c app/actions/colormap-actions.c 2007-12-25 Michael Natterer <mitch@gimp.org> * app/actions/channels-commands.c * app/actions/colormap-actions.c * app/actions/colormap-commands.c * app/actions/image-commands.c * app/core/gimp-edit.c * app/core/gimpdrawable-preview.c * app/core/gimpimage-colorhash.c * app/core/gimpimage-colormap.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-flip.c * app/core/gimpimage-guides.c * app/core/gimpimage-merge.c * app/core/gimpimage-preview.c * app/core/gimpimage-quick-mask.c * app/core/gimpimage-resize.c * app/core/gimpimage-rotate.c * app/core/gimpimage-sample-points.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpimageundo.c * app/core/gimpitem-preview.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimppalette-import.c * app/core/gimpprojection-construct.c * app/core/gimpprojection.c * app/core/gimpselection.c * app/core/gimpundo.c * app/dialogs/layer-options-dialog.c * app/dialogs/print-size-dialog.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/display/gimpstatusbar.c * app/file/file-open.c * app/paint/gimppaintoptions.c * app/tools/gimpaligntool.c * app/tools/gimpcolortool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimpperspectiveclonetool.c * app/tools/gimprectangleselecttool.c * app/tools/gimprectangletool.c * app/tools/gimprotatetool.c * app/vectors/gimpvectors-export.c * app/vectors/gimpvectors-import.c * app/vectors/gimpvectors.c * app/widgets/gimpimagepropview.c * app/widgets/gimpnavigationview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrendererimage.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/image.pdb: use accessors for many image properties. * app/pdb/guides_cmds.c * app/pdb/image_cmds.c: regenerated. svn path=/trunk/; revision=24432
2007-12-26 00:21:40 +08:00
value = gimp_image_get_width (image);
xcf_write_int32_check_error (info, (guint32 *) &value, 1);
value = gimp_image_get_height (image);
xcf_write_int32_check_error (info, (guint32 *) &value, 1);
app/actions/channels-commands.c app/actions/colormap-actions.c 2007-12-25 Michael Natterer <mitch@gimp.org> * app/actions/channels-commands.c * app/actions/colormap-actions.c * app/actions/colormap-commands.c * app/actions/image-commands.c * app/core/gimp-edit.c * app/core/gimpdrawable-preview.c * app/core/gimpimage-colorhash.c * app/core/gimpimage-colormap.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-flip.c * app/core/gimpimage-guides.c * app/core/gimpimage-merge.c * app/core/gimpimage-preview.c * app/core/gimpimage-quick-mask.c * app/core/gimpimage-resize.c * app/core/gimpimage-rotate.c * app/core/gimpimage-sample-points.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpimageundo.c * app/core/gimpitem-preview.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimppalette-import.c * app/core/gimpprojection-construct.c * app/core/gimpprojection.c * app/core/gimpselection.c * app/core/gimpundo.c * app/dialogs/layer-options-dialog.c * app/dialogs/print-size-dialog.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/display/gimpstatusbar.c * app/file/file-open.c * app/paint/gimppaintoptions.c * app/tools/gimpaligntool.c * app/tools/gimpcolortool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimpperspectiveclonetool.c * app/tools/gimprectangleselecttool.c * app/tools/gimprectangletool.c * app/tools/gimprotatetool.c * app/vectors/gimpvectors-export.c * app/vectors/gimpvectors-import.c * app/vectors/gimpvectors.c * app/widgets/gimpimagepropview.c * app/widgets/gimpnavigationview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrendererimage.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/image.pdb: use accessors for many image properties. * app/pdb/guides_cmds.c * app/pdb/image_cmds.c: regenerated. svn path=/trunk/; revision=24432
2007-12-26 00:21:40 +08:00
value = gimp_image_base_type (image);
xcf_write_int32_check_error (info, &value, 1);
/* determine the number of layers and channels in the image */
n_layers = (guint) gimp_container_get_n_children (image->layers);
n_channels = (guint) gimp_container_get_n_children (image->channels);
max_progress = 1 + n_layers + n_channels;
/* check and see if we have to save out the selection */
have_selection = gimp_channel_bounds (gimp_image_get_mask (image),
&t1, &t2, &t3, &t4);
if (have_selection)
n_channels += 1;
/* write the property information for the image.
*/
xcf_check_error (xcf_save_image_props (info, image, error));
xcf_progress_update (info);
/* 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 */
xcf_check_error (xcf_seek_pos (info,
info->cp + (n_layers + n_channels + 2) * 4,
error));
for (list = gimp_image_get_layer_iter (image);
list;
list = g_list_next (list))
{
2009-08-31 03:07:22 +08:00
GimpLayer *layer = list->data;
/* save the start offset of where we are writing
* out the next layer.
*/
offset = info->cp;
/* write out the layer. */
xcf_check_error (xcf_save_layer (info, image, layer, error));
xcf_progress_update (info);
/* seek back to where we are to write out the next
* layer offset and write it out.
*/
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
/* 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.
*/
xcf_check_error (xcf_seek_end (info, error));
}
/* write out a '0' offset position to indicate the end
* of the layer offsets.
*/
offset = 0;
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
saved_pos = info->cp;
xcf_check_error (xcf_seek_end (info, error));
list = gimp_image_get_channel_iter (image);
while (list || have_selection)
{
2009-08-31 03:07:22 +08:00
GimpChannel *channel;
if (list)
{
channel = list->data;
list = g_list_next (list);
}
else
{
app/actions/channels-commands.c app/actions/colormap-actions.c 2007-12-25 Michael Natterer <mitch@gimp.org> * app/actions/channels-commands.c * app/actions/colormap-actions.c * app/actions/colormap-commands.c * app/actions/image-commands.c * app/core/gimp-edit.c * app/core/gimpdrawable-preview.c * app/core/gimpimage-colorhash.c * app/core/gimpimage-colormap.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-flip.c * app/core/gimpimage-guides.c * app/core/gimpimage-merge.c * app/core/gimpimage-preview.c * app/core/gimpimage-quick-mask.c * app/core/gimpimage-resize.c * app/core/gimpimage-rotate.c * app/core/gimpimage-sample-points.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpimageundo.c * app/core/gimpitem-preview.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimppalette-import.c * app/core/gimpprojection-construct.c * app/core/gimpprojection.c * app/core/gimpselection.c * app/core/gimpundo.c * app/dialogs/layer-options-dialog.c * app/dialogs/print-size-dialog.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/display/gimpstatusbar.c * app/file/file-open.c * app/paint/gimppaintoptions.c * app/tools/gimpaligntool.c * app/tools/gimpcolortool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimpperspectiveclonetool.c * app/tools/gimprectangleselecttool.c * app/tools/gimprectangletool.c * app/tools/gimprotatetool.c * app/vectors/gimpvectors-export.c * app/vectors/gimpvectors-import.c * app/vectors/gimpvectors.c * app/widgets/gimpimagepropview.c * app/widgets/gimpnavigationview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrendererimage.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/image.pdb: use accessors for many image properties. * app/pdb/guides_cmds.c * app/pdb/image_cmds.c: regenerated. svn path=/trunk/; revision=24432
2007-12-26 00:21:40 +08:00
channel = gimp_image_get_mask (image);
have_selection = FALSE;
}
/* save the start offset of where we are writing
* out the next channel.
*/
offset = info->cp;
/* write out the layer. */
xcf_check_error (xcf_save_channel (info, image, channel, error));
xcf_progress_update (info);
/* seek back to where we are to write out the next
* channel offset and write it out.
*/
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
/* 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.
*/
xcf_check_error (xcf_seek_end (info, error));
}
/* write out a '0' offset position to indicate the end
* of the channel offsets.
*/
offset = 0;
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
saved_pos = info->cp;
return !ferror (info->fp);
}
static gboolean
xcf_save_image_props (XcfInfo *info,
GimpImage *image,
GError **error)
{
GimpParasite *parasite = NULL;
GimpUnit unit = gimp_image_get_unit (image);
gdouble xres;
gdouble yres;
gimp_image_get_resolution (image, &xres, &yres);
/* check and see if we should save the colormap property */
if (gimp_image_get_colormap (image))
xcf_check_error (xcf_save_prop (info, image, PROP_COLORMAP, error,
gimp_image_get_colormap_size (image),
gimp_image_get_colormap (image)));
if (info->compression != COMPRESS_NONE)
xcf_check_error (xcf_save_prop (info, image, PROP_COMPRESSION, error,
info->compression));
if (gimp_image_get_guides (image))
xcf_check_error (xcf_save_prop (info, image, PROP_GUIDES, error,
gimp_image_get_guides (image)));
if (gimp_image_get_sample_points (image))
xcf_check_error (xcf_save_prop (info, image, PROP_SAMPLE_POINTS, error,
gimp_image_get_sample_points (image)));
xcf_check_error (xcf_save_prop (info, image, PROP_RESOLUTION, error,
xres, yres));
xcf_check_error (xcf_save_prop (info, image, PROP_TATTOO, error,
gimp_image_get_tattoo_state (image)));
if (unit < _gimp_unit_get_number_of_built_in_units (image->gimp))
xcf_check_error (xcf_save_prop (info, image, PROP_UNIT, error, unit));
if (gimp_container_get_n_children (image->vectors) > 0)
{
if (gimp_vectors_compat_is_compatible (image))
xcf_check_error (xcf_save_prop (info, image, PROP_PATHS, error));
else
xcf_check_error (xcf_save_prop (info, image, PROP_VECTORS, error));
}
if (unit >= _gimp_unit_get_number_of_built_in_units (image->gimp))
xcf_check_error (xcf_save_prop (info, image, PROP_USER_UNIT, error, unit));
if (GIMP_IS_GRID (image->grid))
{
GimpGrid *grid = gimp_image_get_grid (image);
parasite = gimp_grid_to_parasite (grid);
gimp_parasite_list_add (GIMP_IMAGE (image)->parasites, parasite);
}
if (gimp_parasite_list_length (GIMP_IMAGE (image)->parasites) > 0)
{
xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error,
GIMP_IMAGE (image)->parasites));
}
if (parasite)
{
gimp_parasite_list_remove (GIMP_IMAGE (image)->parasites,
gimp_parasite_name (parasite));
gimp_parasite_free (parasite);
}
xcf_check_error (xcf_save_prop (info, image, PROP_END, error));
return TRUE;
}
static gboolean
xcf_save_layer_props (XcfInfo *info,
GimpImage *image,
GimpLayer *layer,
GError **error)
{
GimpParasite *parasite = NULL;
gint offset_x;
gint offset_y;
if (layer == gimp_image_get_active_layer (image))
xcf_check_error (xcf_save_prop (info, image, PROP_ACTIVE_LAYER, error));
if (layer == gimp_image_get_floating_selection (image))
{
info->floating_sel_drawable = gimp_layer_get_floating_sel_drawable (layer);
xcf_check_error (xcf_save_prop (info, image, PROP_FLOATING_SELECTION,
error));
}
xcf_check_error (xcf_save_prop (info, image, PROP_OPACITY, error,
gimp_layer_get_opacity (layer)));
xcf_check_error (xcf_save_prop (info, image, PROP_VISIBLE, error,
gimp_item_get_visible (GIMP_ITEM (layer))));
xcf_check_error (xcf_save_prop (info, image, PROP_LINKED, error,
gimp_item_get_linked (GIMP_ITEM (layer))));
xcf_check_error (xcf_save_prop (info, image, PROP_LOCK_CONTENT, error,
gimp_item_get_lock_content (GIMP_ITEM (layer))));
xcf_check_error (xcf_save_prop (info, image, PROP_LOCK_ALPHA, error,
gimp_layer_get_lock_alpha (layer)));
if (gimp_layer_get_mask (layer))
{
GimpLayerMask *mask = gimp_layer_get_mask (layer);
xcf_check_error (xcf_save_prop (info, image, PROP_APPLY_MASK, error,
gimp_layer_mask_get_apply (mask)));
xcf_check_error (xcf_save_prop (info, image, PROP_EDIT_MASK, error,
gimp_layer_mask_get_edit (mask)));
xcf_check_error (xcf_save_prop (info, image, PROP_SHOW_MASK, error,
gimp_layer_mask_get_show (mask)));
}
else
{
xcf_check_error (xcf_save_prop (info, image, PROP_APPLY_MASK, error,
FALSE));
xcf_check_error (xcf_save_prop (info, image, PROP_EDIT_MASK, error,
FALSE));
xcf_check_error (xcf_save_prop (info, image, PROP_SHOW_MASK, error,
FALSE));
}
gimp_item_get_offset (GIMP_ITEM (layer), &offset_x, &offset_y);
xcf_check_error (xcf_save_prop (info, image, PROP_OFFSETS, error,
offset_x, offset_y));
xcf_check_error (xcf_save_prop (info, image, PROP_MODE, error,
gimp_layer_get_mode (layer)));
xcf_check_error (xcf_save_prop (info, image, PROP_TATTOO, error,
gimp_item_get_tattoo (GIMP_ITEM (layer))));
if (GIMP_IS_TEXT_LAYER (layer) && GIMP_TEXT_LAYER (layer)->text)
{
GimpTextLayer *text_layer = GIMP_TEXT_LAYER (layer);
guint32 flags = gimp_text_layer_get_xcf_flags (text_layer);
gimp_text_layer_xcf_save_prepare (text_layer);
if (flags)
xcf_check_error (xcf_save_prop (info,
image, PROP_TEXT_LAYER_FLAGS, error,
flags));
}
app/core/Makefile.am app/core/core-types.h new base class for something 2002-02-25 Michael Natterer <mitch@gimp.org> * app/core/Makefile.am * app/core/core-types.h * app/core/gimpitem.[ch]: new base class for something which is a child of an image, has a PDB ID, a tattoo, parasites and emits a "removed" signal. * app/core/gimpdrawable.[ch] * app/vectors/gimpvectors.[ch]: derive from GimpItem. Removed lots of stuff from GimpDrawable. * app/core/gimp.[ch]: changed gimp->drawable_table and gimp->next_drawable_ID to gimp->item_table and gimp->next_item_id. * app/undo.[ch]: s/undo_push_drawable_parasite/undo_push_item_parasite/, minor cleanups. * app/core/gimplayer.[ch]: changed gimp_layer_new_from_tiles() and gimp_layer_new_from_drawable() to take the "dest_gimage" as second, not first parameter. * app/image_map.c * app/core/gimpchannel.c * app/core/gimpdrawable-blend.c * app/core/gimpdrawable-bucket-fill.c * app/core/gimpdrawable-histogram.c * app/core/gimpdrawable-offset.c * app/core/gimpdrawable-preview.c * app/core/gimpdrawable-transform.c * app/core/gimpedit.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-mask.c * app/core/gimpimage-merge.c * app/core/gimpimage-pick-color.c * app/core/gimpimage.c * app/core/gimplayer-floating-sel.c * app/display/gimpdisplayshell-dnd.c * app/file/file-save.c * app/gui/channels-commands.c * app/gui/file-save-dialog.c * app/gui/layers-commands.c * app/gui/offset-dialog.c * app/gui/paths-dialog.c * app/gui/toolbox.c * app/paint/gimpairbrush.c * app/paint/gimpclone.c * app/paint/gimpconvolve.c * app/paint/gimpdodgeburn.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/paint/gimppaintcore.c * app/paint/gimppencil.c * app/paint/gimpsmudge.c * app/plug-in/plug-in.c * app/tools/gimpbezierselecttool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpinktool.c * app/tools/gimppainttool.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/widgets/gimpdrawablepreview.c: changed accordingly. * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpitemlistview.[ch]: new widget implementing most of the stuff formerly done by GimpDrawableListView. * app/widgets/gimpchannellistview.c * app/widgets/gimpdrawablelistitem.c * app/widgets/gimpdrawablelistview.[ch] * app/widgets/gimplayerlistview.c: changed accordingly. * app/widgets/gimpdnd.[ch]: added a vectors DND type. * app/gui/menus.c * app/gui/dialogs.c * app/gui/dialogs-constructors.[ch]: added a vectors dialog and a vectors item_factory. * app/gui/Makefile.am * app/gui/vectors-commands.[ch]: new files implementing the callbacks for the new vectors dialog and item_factory. * app/pdb/pdb_glue.h: some more ugly hacks to keep intermediate perl code working... * tools/pdbgen/pdb.pl: added a vectors type, use GimpItem for all ID lookups. * tools/pdbgen/pdb/channel.pdb * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/misc_tools.pdb * tools/pdbgen/pdb/parasite.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/selection_tools.pdb: misc changes according to stuff above. * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/misc_tools_cmds.c * app/pdb/paint_tools_cmds.c * app/pdb/parasite_cmds.c * app/pdb/selection_cmds.c * app/pdb/selection_tools_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/transform_tools_cmds.c: regenerated.
2002-02-26 01:58:50 +08:00
if (gimp_parasite_list_length (GIMP_ITEM (layer)->parasites) > 0)
{
xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error,
GIMP_ITEM (layer)->parasites));
}
if (parasite)
{
gimp_parasite_list_remove (GIMP_ITEM (layer)->parasites,
gimp_parasite_name (parasite));
gimp_parasite_free (parasite);
}
xcf_check_error (xcf_save_prop (info, image, PROP_END, error));
return TRUE;
}
static gboolean
xcf_save_channel_props (XcfInfo *info,
GimpImage *image,
GimpChannel *channel,
GError **error)
{
guchar col[3];
if (channel == gimp_image_get_active_channel (image))
xcf_check_error (xcf_save_prop (info, image, PROP_ACTIVE_CHANNEL, error));
app/actions/channels-commands.c app/actions/colormap-actions.c 2007-12-25 Michael Natterer <mitch@gimp.org> * app/actions/channels-commands.c * app/actions/colormap-actions.c * app/actions/colormap-commands.c * app/actions/image-commands.c * app/core/gimp-edit.c * app/core/gimpdrawable-preview.c * app/core/gimpimage-colorhash.c * app/core/gimpimage-colormap.c * app/core/gimpimage-convert.c * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-flip.c * app/core/gimpimage-guides.c * app/core/gimpimage-merge.c * app/core/gimpimage-preview.c * app/core/gimpimage-quick-mask.c * app/core/gimpimage-resize.c * app/core/gimpimage-rotate.c * app/core/gimpimage-sample-points.c * app/core/gimpimage-scale.c * app/core/gimpimage-snap.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpimageundo.c * app/core/gimpitem-preview.c * app/core/gimpitem.c * app/core/gimplayer.c * app/core/gimppalette-import.c * app/core/gimpprojection-construct.c * app/core/gimpprojection.c * app/core/gimpselection.c * app/core/gimpundo.c * app/dialogs/layer-options-dialog.c * app/dialogs/print-size-dialog.c * app/display/gimpdisplay.c * app/display/gimpdisplayshell-draw.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-title.c * app/display/gimpdisplayshell-transform.c * app/display/gimpdisplayshell.c * app/display/gimpstatusbar.c * app/file/file-open.c * app/paint/gimppaintoptions.c * app/tools/gimpaligntool.c * app/tools/gimpcolortool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpiscissorstool.c * app/tools/gimpmeasuretool.c * app/tools/gimpmovetool.c * app/tools/gimpperspectiveclonetool.c * app/tools/gimprectangleselecttool.c * app/tools/gimprectangletool.c * app/tools/gimprotatetool.c * app/vectors/gimpvectors-export.c * app/vectors/gimpvectors-import.c * app/vectors/gimpvectors.c * app/widgets/gimpimagepropview.c * app/widgets/gimpnavigationview.c * app/widgets/gimpselectioneditor.c * app/widgets/gimpviewrendererdrawable.c * app/widgets/gimpviewrendererimage.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * tools/pdbgen/pdb/guides.pdb * tools/pdbgen/pdb/image.pdb: use accessors for many image properties. * app/pdb/guides_cmds.c * app/pdb/image_cmds.c: regenerated. svn path=/trunk/; revision=24432
2007-12-26 00:21:40 +08:00
if (channel == gimp_image_get_mask (image))
xcf_check_error (xcf_save_prop (info, image, PROP_SELECTION, error));
xcf_check_error (xcf_save_prop (info, image, PROP_OPACITY, error,
gimp_channel_get_opacity (channel)));
xcf_check_error (xcf_save_prop (info, image, PROP_VISIBLE, error,
gimp_item_get_visible (GIMP_ITEM (channel))));
xcf_check_error (xcf_save_prop (info, image, PROP_LINKED, error,
gimp_item_get_linked (GIMP_ITEM (channel))));
xcf_check_error (xcf_save_prop (info, image, PROP_LOCK_CONTENT, error,
gimp_item_get_lock_content (GIMP_ITEM (channel))));
xcf_check_error (xcf_save_prop (info, image, PROP_SHOW_MASKED, error,
gimp_channel_get_show_masked (channel)));
gimp_rgb_get_uchar (&channel->color, &col[0], &col[1], &col[2]);
xcf_check_error (xcf_save_prop (info, image, PROP_COLOR, error, col));
xcf_check_error (xcf_save_prop (info, image, PROP_TATTOO, error,
gimp_item_get_tattoo (GIMP_ITEM (channel))));
app/core/Makefile.am app/core/core-types.h new base class for something 2002-02-25 Michael Natterer <mitch@gimp.org> * app/core/Makefile.am * app/core/core-types.h * app/core/gimpitem.[ch]: new base class for something which is a child of an image, has a PDB ID, a tattoo, parasites and emits a "removed" signal. * app/core/gimpdrawable.[ch] * app/vectors/gimpvectors.[ch]: derive from GimpItem. Removed lots of stuff from GimpDrawable. * app/core/gimp.[ch]: changed gimp->drawable_table and gimp->next_drawable_ID to gimp->item_table and gimp->next_item_id. * app/undo.[ch]: s/undo_push_drawable_parasite/undo_push_item_parasite/, minor cleanups. * app/core/gimplayer.[ch]: changed gimp_layer_new_from_tiles() and gimp_layer_new_from_drawable() to take the "dest_gimage" as second, not first parameter. * app/image_map.c * app/core/gimpchannel.c * app/core/gimpdrawable-blend.c * app/core/gimpdrawable-bucket-fill.c * app/core/gimpdrawable-histogram.c * app/core/gimpdrawable-offset.c * app/core/gimpdrawable-preview.c * app/core/gimpdrawable-transform.c * app/core/gimpedit.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-mask.c * app/core/gimpimage-merge.c * app/core/gimpimage-pick-color.c * app/core/gimpimage.c * app/core/gimplayer-floating-sel.c * app/display/gimpdisplayshell-dnd.c * app/file/file-save.c * app/gui/channels-commands.c * app/gui/file-save-dialog.c * app/gui/layers-commands.c * app/gui/offset-dialog.c * app/gui/paths-dialog.c * app/gui/toolbox.c * app/paint/gimpairbrush.c * app/paint/gimpclone.c * app/paint/gimpconvolve.c * app/paint/gimpdodgeburn.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/paint/gimppaintcore.c * app/paint/gimppencil.c * app/paint/gimpsmudge.c * app/plug-in/plug-in.c * app/tools/gimpbezierselecttool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpinktool.c * app/tools/gimppainttool.c * app/xcf/xcf-load.c * app/xcf/xcf-save.c * app/widgets/gimpdrawablepreview.c: changed accordingly. * app/widgets/Makefile.am * app/widgets/widgets-types.h * app/widgets/gimpitemlistview.[ch]: new widget implementing most of the stuff formerly done by GimpDrawableListView. * app/widgets/gimpchannellistview.c * app/widgets/gimpdrawablelistitem.c * app/widgets/gimpdrawablelistview.[ch] * app/widgets/gimplayerlistview.c: changed accordingly. * app/widgets/gimpdnd.[ch]: added a vectors DND type. * app/gui/menus.c * app/gui/dialogs.c * app/gui/dialogs-constructors.[ch]: added a vectors dialog and a vectors item_factory. * app/gui/Makefile.am * app/gui/vectors-commands.[ch]: new files implementing the callbacks for the new vectors dialog and item_factory. * app/pdb/pdb_glue.h: some more ugly hacks to keep intermediate perl code working... * tools/pdbgen/pdb.pl: added a vectors type, use GimpItem for all ID lookups. * tools/pdbgen/pdb/channel.pdb * tools/pdbgen/pdb/color.pdb * tools/pdbgen/pdb/drawable.pdb * tools/pdbgen/pdb/edit.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/misc_tools.pdb * tools/pdbgen/pdb/parasite.pdb * tools/pdbgen/pdb/selection.pdb * tools/pdbgen/pdb/selection_tools.pdb: misc changes according to stuff above. * app/pdb/channel_cmds.c * app/pdb/color_cmds.c * app/pdb/drawable_cmds.c * app/pdb/edit_cmds.c * app/pdb/floating_sel_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/misc_tools_cmds.c * app/pdb/paint_tools_cmds.c * app/pdb/parasite_cmds.c * app/pdb/selection_cmds.c * app/pdb/selection_tools_cmds.c * app/pdb/text_tool_cmds.c * app/pdb/transform_tools_cmds.c: regenerated.
2002-02-26 01:58:50 +08:00
if (gimp_parasite_list_length (GIMP_ITEM (channel)->parasites) > 0)
xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error,
GIMP_ITEM (channel)->parasites));
xcf_check_error (xcf_save_prop (info, image, PROP_END, error));
return TRUE;
}
static gboolean
xcf_save_prop (XcfInfo *info,
GimpImage *image,
PropType prop_type,
GError **error,
...)
{
guint32 size;
va_list args;
GError *tmp_error = NULL;
va_start (args, error);
switch (prop_type)
{
case PROP_END:
size = 0;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
break;
case PROP_COLORMAP:
{
guint32 n_colors;
guchar *colors;
n_colors = va_arg (args, guint32);
colors = va_arg (args, guchar *);
size = 4 + n_colors * 3;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &n_colors, 1);
xcf_write_int8_check_error (info, colors, n_colors * 3);
}
break;
case PROP_ACTIVE_LAYER:
case PROP_ACTIVE_CHANNEL:
case PROP_SELECTION:
size = 0;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
break;
case PROP_FLOATING_SELECTION:
{
guint32 dummy;
dummy = 0;
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
info->floating_sel_offset = info->cp;
xcf_write_int32_check_error (info, &dummy, 1);
}
break;
case PROP_OPACITY:
{
gdouble opacity;
guint32 uint_opacity;
opacity = va_arg (args, gdouble);
uint_opacity = opacity * 255.999;
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &uint_opacity, 1);
}
break;
case PROP_MODE:
{
gint32 mode;
mode = va_arg (args, gint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, (guint32 *) &mode, 1);
}
break;
case PROP_VISIBLE:
{
guint32 visible;
visible = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &visible, 1);
}
break;
case PROP_LINKED:
{
guint32 linked;
linked = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &linked, 1);
}
break;
case PROP_LOCK_CONTENT:
{
guint32 lock_content;
lock_content = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &lock_content, 1);
}
break;
app/actions/layers-actions.c app/actions/layers-commands.[ch] 2005-07-10 Michael Natterer <mitch@gimp.org> * app/actions/layers-actions.c * app/actions/layers-commands.[ch] * app/core/core-enums.[ch] * app/core/gimpimage-undo-push.[ch] * app/core/gimplayer-floating-sel.c * app/core/gimplayer.[ch] * app/text/gimptextlayer-xcf.c * app/widgets/gimphelp-ids.h * app/widgets/gimplayertreeview.[ch] * app/xcf/xcf-load.c * app/xcf/xcf-private.h * app/xcf/xcf-save.c * tools/pdbgen/pdb/layer.pdb * menus/image-menu.xml.in * libgimp/gimp.def: did a global s/preserve_trans/lock_alpha/ in preparation for more layer locking flags. * app/pdb/procedural_db.c * libgimp/gimplayer.[ch]: added compat stuff for preserve_trans. * app/pdb/layer_cmds.c * libgimp/gimplayer_pdb.[ch]: regenerated. * plug-ins/common/colortoalpha.c * plug-ins/common/iwarp.c * plug-ins/common/psd.c * plug-ins/common/psd_save.c * plug-ins/common/psp.c * plug-ins/common/rotate.c * plug-ins/common/threshold_alpha.c * plug-ins/common/vpropagate.c * plug-ins/script-fu/scripts/3d-outline.scm * plug-ins/script-fu/scripts/alien-glow-bar.scm * plug-ins/script-fu/scripts/alien-glow-bullet.scm * plug-ins/script-fu/scripts/alien-glow-logo.scm * plug-ins/script-fu/scripts/basic1-logo.scm * plug-ins/script-fu/scripts/basic2-logo.scm * plug-ins/script-fu/scripts/beveled-pattern-button.scm * plug-ins/script-fu/scripts/blend-anim.scm * plug-ins/script-fu/scripts/blended-logo.scm * plug-ins/script-fu/scripts/bovinated-logo.scm * plug-ins/script-fu/scripts/burn-in-anim.scm * plug-ins/script-fu/scripts/carved-logo.scm * plug-ins/script-fu/scripts/chalk.scm * plug-ins/script-fu/scripts/chip-away.scm * plug-ins/script-fu/scripts/comic-logo.scm * plug-ins/script-fu/scripts/coolmetal-logo.scm * plug-ins/script-fu/scripts/crystal-logo.scm * plug-ins/script-fu/scripts/drop-shadow.scm * plug-ins/script-fu/scripts/gimp-headers.scm * plug-ins/script-fu/scripts/gimp-labels.scm * plug-ins/script-fu/scripts/glowing-logo.scm * plug-ins/script-fu/scripts/gradient-bevel-logo.scm * plug-ins/script-fu/scripts/image-structure.scm * plug-ins/script-fu/scripts/neon-logo.scm * plug-ins/script-fu/scripts/perspective-shadow.scm * plug-ins/script-fu/scripts/starburst-logo.scm * plug-ins/script-fu/scripts/starscape-logo.scm * plug-ins/script-fu/scripts/textured-logo.scm * plug-ins/script-fu/scripts/title-header.scm * plug-ins/script-fu/scripts/waves-anim.scm * plug-ins/xjt/xjt.c: changed accordingly.
2005-07-11 05:17:22 +08:00
case PROP_LOCK_ALPHA:
{
guint32 lock_alpha;
lock_alpha = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &lock_alpha, 1);
}
break;
case PROP_APPLY_MASK:
{
guint32 apply_mask;
apply_mask = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &apply_mask, 1);
}
break;
case PROP_EDIT_MASK:
{
guint32 edit_mask;
edit_mask = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &edit_mask, 1);
}
break;
case PROP_SHOW_MASK:
{
guint32 show_mask;
show_mask = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &show_mask, 1);
}
break;
case PROP_SHOW_MASKED:
{
guint32 show_masked;
show_masked = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &show_masked, 1);
}
break;
case PROP_OFFSETS:
{
gint32 offsets[2];
offsets[0] = va_arg (args, gint32);
offsets[1] = va_arg (args, gint32);
size = 8;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, (guint32 *) offsets, 2);
}
break;
case PROP_COLOR:
{
guchar *color;
color = va_arg (args, guchar*);
size = 3;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int8_check_error (info, color, 3);
}
break;
case PROP_COMPRESSION:
{
guint8 compression;
compression = (guint8) va_arg (args, guint32);
size = 1;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int8_check_error (info, &compression, 1);
}
break;
case PROP_GUIDES:
{
GList *guides;
gint n_guides;
guides = va_arg (args, GList *);
n_guides = g_list_length (guides);
size = n_guides * (4 + 1);
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
for (; guides; guides = g_list_next (guides))
{
GimpGuide *guide = guides->data;
gint32 position = gimp_guide_get_position (guide);
gint8 orientation;
switch (gimp_guide_get_orientation (guide))
Added object properties for almost all tool_options values and registered 2003-02-07 Michael Natterer <mitch@gimp.org> Added object properties for almost all tool_options values and registered lots of enums with the type system: Part I (enum and type cleanup): * app/core/core-enums.[ch] * app/core/core-types.h: removed InternalOrientaionType and register GimpOrientationType. Register GimpChannelOps. Removed GimpToolOptionsGUIFunc. * app/xcf/xcf-private.h: added XcfOrientationType with the same values as the old InternalOrientationType * app/xcf/xcf-load.c * app/xcf/xcf-save.c: translate between GimpOrientationType and XcfOrientationType. * app/core/gimpdrawable-transform-utils.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-guides.c * app/core/gimpimage-resize.c * app/core/gimpimage-scale.c * app/core/gimpimage.h * app/display/gimpdisplayshell.c * tools/pdbgen/stddefs.pdb * tools/pdbgen/pdb/transform_tools.pdb: changed accordingly. * app/pdb/guides_cmds.c * app/pdb/transform_tools_cmds.c * libgimp/gimpenums.h * libgimpproxy/gimpproxytypes.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: regenerated. * libgimptool/gimptoolenums.[ch]: added GimpTransformGridType. * libgimptool/gimptooltypes.h: removed GimpToolOptionsResetFunc, added GimpToolOptionsGUIFunc. Part II (tool options changes): * app/config/gimpconfig-utils.c (gimp_config_reset_properties): don't reset object properties because they have NULL as default value. * app/widgets/gimppropwidgets.[ch]: added gimp_prop_[enum|boolean]_radio_frame_new(), gimp_prop_paint_mode_menu_new() and gimp_prop_scale_entry_new(), which are all needed by the new tool options GUI code. * app/tools/tool_options.[ch]: removed the "reset_func" since the virtual reset() method is used now. * app/paint/gimpairbrushoptions.[ch] * app/paint/gimpcloneoptions.[ch] * app/paint/gimpconvolveoptions.[ch] * app/paint/gimpdodgeburnoptions.[ch] * app/paint/gimperaseroptions.[ch] * app/paint/gimppaintoptions.[ch] * app/paint/gimpsmudgeoptions.[ch]: added properties all over the place and removed the widget and default_value members from the structs. Renamed some values (e.g. s/type/clone_type/). Don't #include <gtk/gtk.h>. * app/paint/gimpairbrush.c * app/paint/gimpclone.c * app/paint/gimpconvolve.c * app/paint/gimpdodgeburn.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/paint/gimppaintcore-stroke.c * app/paint/gimppaintcore.c * app/paint/gimppencil.c * app/paint/gimpsmudge.c * app/paint/paint-types.h * app/paint/paint.c: changed accordingly. Don't #include <gtk/gtk.h>. * tools/pdbgen/pdb/paint_tools.pdb: changed accordingly. * app/pdb/paint_tools_cmds.c: regenerated. * app/tools/gimpblendoptions.[ch] * app/tools/gimpbucketfilloptions.[ch] * app/tools/gimpcolorpickeroptions.[ch] * app/tools/gimpcropoptions.[ch] * app/tools/gimpflipoptions.[ch] * app/tools/gimpinkoptions.c * app/tools/gimpmagnifyoptions.[ch] * app/tools/gimpmeasureoptions.[ch] * app/tools/gimpmoveoptions.[ch] * app/tools/gimptextoptions.c * app/tools/paint_options.[ch] * app/tools/selection_options.[ch] * app/tools/transform_options.[ch]: ditto: added properties and removed widget and default_value stuff. Removed most reset functions. Use gimp_prop widgets all over the place, renamed some values as above. * app/tools/Makefile.am * app/tools/gimpairbrushtool.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpclonetool.c * app/tools/gimpconvolvetool.c * app/tools/gimpcroptool.c * app/tools/gimpdodgeburntool.c * app/tools/gimperasertool.c * app/tools/gimpfliptool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmovetool.c * app/tools/gimpselectiontool.c * app/tools/gimpsheartool.c * app/tools/gimpsmudgetool.c * app/tools/gimptransformtool.c * app/tools/gimpvectoroptions.c: changed accordingly. Ported the paint_options GUI constructors to gimp_prop widgets. * app/widgets/gimpselectioneditor.c * app/gui/tool-options-dialog.c: changed accordingly.
2003-02-08 01:12:21 +08:00
{
case GIMP_ORIENTATION_HORIZONTAL:
orientation = XCF_ORIENTATION_HORIZONTAL;
break;
case GIMP_ORIENTATION_VERTICAL:
orientation = XCF_ORIENTATION_VERTICAL;
break;
default:
g_warning ("%s: skipping guide with bad orientation",
G_STRFUNC);
Added object properties for almost all tool_options values and registered 2003-02-07 Michael Natterer <mitch@gimp.org> Added object properties for almost all tool_options values and registered lots of enums with the type system: Part I (enum and type cleanup): * app/core/core-enums.[ch] * app/core/core-types.h: removed InternalOrientaionType and register GimpOrientationType. Register GimpChannelOps. Removed GimpToolOptionsGUIFunc. * app/xcf/xcf-private.h: added XcfOrientationType with the same values as the old InternalOrientationType * app/xcf/xcf-load.c * app/xcf/xcf-save.c: translate between GimpOrientationType and XcfOrientationType. * app/core/gimpdrawable-transform-utils.[ch] * app/core/gimpdrawable-transform.[ch] * app/core/gimpimage-crop.c * app/core/gimpimage-duplicate.c * app/core/gimpimage-guides.c * app/core/gimpimage-resize.c * app/core/gimpimage-scale.c * app/core/gimpimage.h * app/display/gimpdisplayshell.c * tools/pdbgen/stddefs.pdb * tools/pdbgen/pdb/transform_tools.pdb: changed accordingly. * app/pdb/guides_cmds.c * app/pdb/transform_tools_cmds.c * libgimp/gimpenums.h * libgimpproxy/gimpproxytypes.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: regenerated. * libgimptool/gimptoolenums.[ch]: added GimpTransformGridType. * libgimptool/gimptooltypes.h: removed GimpToolOptionsResetFunc, added GimpToolOptionsGUIFunc. Part II (tool options changes): * app/config/gimpconfig-utils.c (gimp_config_reset_properties): don't reset object properties because they have NULL as default value. * app/widgets/gimppropwidgets.[ch]: added gimp_prop_[enum|boolean]_radio_frame_new(), gimp_prop_paint_mode_menu_new() and gimp_prop_scale_entry_new(), which are all needed by the new tool options GUI code. * app/tools/tool_options.[ch]: removed the "reset_func" since the virtual reset() method is used now. * app/paint/gimpairbrushoptions.[ch] * app/paint/gimpcloneoptions.[ch] * app/paint/gimpconvolveoptions.[ch] * app/paint/gimpdodgeburnoptions.[ch] * app/paint/gimperaseroptions.[ch] * app/paint/gimppaintoptions.[ch] * app/paint/gimpsmudgeoptions.[ch]: added properties all over the place and removed the widget and default_value members from the structs. Renamed some values (e.g. s/type/clone_type/). Don't #include <gtk/gtk.h>. * app/paint/gimpairbrush.c * app/paint/gimpclone.c * app/paint/gimpconvolve.c * app/paint/gimpdodgeburn.c * app/paint/gimperaser.c * app/paint/gimppaintbrush.c * app/paint/gimppaintcore-stroke.c * app/paint/gimppaintcore.c * app/paint/gimppencil.c * app/paint/gimpsmudge.c * app/paint/paint-types.h * app/paint/paint.c: changed accordingly. Don't #include <gtk/gtk.h>. * tools/pdbgen/pdb/paint_tools.pdb: changed accordingly. * app/pdb/paint_tools_cmds.c: regenerated. * app/tools/gimpblendoptions.[ch] * app/tools/gimpbucketfilloptions.[ch] * app/tools/gimpcolorpickeroptions.[ch] * app/tools/gimpcropoptions.[ch] * app/tools/gimpflipoptions.[ch] * app/tools/gimpinkoptions.c * app/tools/gimpmagnifyoptions.[ch] * app/tools/gimpmeasureoptions.[ch] * app/tools/gimpmoveoptions.[ch] * app/tools/gimptextoptions.c * app/tools/paint_options.[ch] * app/tools/selection_options.[ch] * app/tools/transform_options.[ch]: ditto: added properties and removed widget and default_value stuff. Removed most reset functions. Use gimp_prop widgets all over the place, renamed some values as above. * app/tools/Makefile.am * app/tools/gimpairbrushtool.c * app/tools/gimpblendtool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpclonetool.c * app/tools/gimpconvolvetool.c * app/tools/gimpcroptool.c * app/tools/gimpdodgeburntool.c * app/tools/gimperasertool.c * app/tools/gimpfliptool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmovetool.c * app/tools/gimpselectiontool.c * app/tools/gimpsheartool.c * app/tools/gimpsmudgetool.c * app/tools/gimptransformtool.c * app/tools/gimpvectoroptions.c: changed accordingly. Ported the paint_options GUI constructors to gimp_prop widgets. * app/widgets/gimpselectioneditor.c * app/gui/tool-options-dialog.c: changed accordingly.
2003-02-08 01:12:21 +08:00
continue;
}
xcf_write_int32_check_error (info, (guint32 *) &position, 1);
xcf_write_int8_check_error (info, (guint8 *) &orientation, 1);
}
}
break;
case PROP_SAMPLE_POINTS:
{
GList *sample_points;
gint n_sample_points;
sample_points = va_arg (args, GList *);
n_sample_points = g_list_length (sample_points);
size = n_sample_points * (4 + 4);
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
for (; sample_points; sample_points = g_list_next (sample_points))
{
GimpSamplePoint *sample_point = sample_points->data;
gint32 x, y;
x = sample_point->x;
y = sample_point->y;
xcf_write_int32_check_error (info, (guint32 *) &x, 1);
xcf_write_int32_check_error (info, (guint32 *) &y, 1);
}
}
break;
case PROP_RESOLUTION:
{
gfloat xresolution, yresolution;
/* we pass in floats,
but they are promoted to double by the compiler */
xresolution = va_arg (args, double);
yresolution = va_arg (args, double);
size = 4*2;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_float_check_error (info, &xresolution, 1);
xcf_write_float_check_error (info, &yresolution, 1);
}
break;
case PROP_TATTOO:
{
guint32 tattoo;
tattoo = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &tattoo, 1);
}
break;
case PROP_PARASITES:
{
GimpParasiteList *list;
guint32 base, length;
long pos;
list = va_arg (args, GimpParasiteList *);
if (gimp_parasite_list_persistent_length (list) > 0)
{
xcf_write_prop_type_check_error (info, prop_type);
/* because we don't know how much room the parasite list will take
* we save the file position and write the length later
*/
pos = info->cp;
xcf_write_int32_check_error (info, &length, 1);
base = info->cp;
xcf_check_error (xcf_save_parasite_list (info, list, 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)
{
g_propagate_error (error, tmp_error);
return FALSE;
}
xcf_check_error (xcf_seek_end (info, error));
}
}
break;
case PROP_UNIT:
{
guint32 unit;
unit = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &unit, 1);
}
break;
case PROP_PATHS:
{
guint32 base, length;
glong pos;
xcf_write_prop_type_check_error (info, prop_type);
/* 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, &length, 1);
base = info->cp;
xcf_check_error (xcf_save_old_paths (info, image, 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)
{
g_propagate_error (error, tmp_error);
return FALSE;
}
xcf_check_error (xcf_seek_end (info, error));
}
break;
case PROP_USER_UNIT:
{
GimpUnit unit;
const gchar *unit_strings[5];
gfloat factor;
guint32 digits;
unit = va_arg (args, guint32);
/* write the entire unit definition */
unit_strings[0] = _gimp_unit_get_identifier (image->gimp, unit);
factor = _gimp_unit_get_factor (image->gimp, unit);
digits = _gimp_unit_get_digits (image->gimp, unit);
unit_strings[1] = _gimp_unit_get_symbol (image->gimp, unit);
unit_strings[2] = _gimp_unit_get_abbreviation (image->gimp, unit);
unit_strings[3] = _gimp_unit_get_singular (image->gimp, unit);
unit_strings[4] = _gimp_unit_get_plural (image->gimp, unit);
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;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_float_check_error (info, &factor, 1);
xcf_write_int32_check_error (info, &digits, 1);
xcf_write_string_check_error (info, (gchar **) unit_strings, 5);
}
break;
case PROP_VECTORS:
{
guint32 base, length;
glong pos;
xcf_write_prop_type_check_error (info, prop_type);
/* 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, &length, 1);
base = info->cp;
xcf_check_error (xcf_save_vectors (info, image, 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)
{
g_propagate_error (error, tmp_error);
return FALSE;
}
xcf_check_error (xcf_seek_end (info, error));
}
break;
case PROP_TEXT_LAYER_FLAGS:
{
guint32 flags;
flags = va_arg (args, guint32);
size = 4;
xcf_write_prop_type_check_error (info, prop_type);
xcf_write_int32_check_error (info, &size, 1);
xcf_write_int32_check_error (info, &flags, 1);
}
break;
}
va_end (args);
return TRUE;
}
static gboolean
xcf_save_layer (XcfInfo *info,
GimpImage *image,
GimpLayer *layer,
GError **error)
{
guint32 saved_pos;
guint32 offset;
guint32 value;
const gchar *string;
GError *tmp_error = NULL;
/* 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;
xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
xcf_write_int32_check_error (info, &saved_pos, 1);
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
}
/* write out the width, height and image type information for the layer */
value = gimp_item_get_width (GIMP_ITEM (layer));
xcf_write_int32_check_error (info, &value, 1);
value = gimp_item_get_height (GIMP_ITEM (layer));
xcf_write_int32_check_error (info, &value, 1);
value = gimp_drawable_type (GIMP_DRAWABLE (layer));
xcf_write_int32_check_error (info, &value, 1);
/* write out the layers name */
string = gimp_object_get_name (GIMP_OBJECT (layer));
xcf_write_string_check_error (info, (gchar **) &string, 1);
/* write out the layer properties */
xcf_save_layer_props (info, image, layer, error);
/* save the current position which is where the hierarchy offset
* will be stored.
*/
saved_pos = info->cp;
/* write out the layer tile hierarchy */
xcf_check_error (xcf_seek_pos (info, info->cp + 8, error));
offset = info->cp;
xcf_check_error (xcf_save_hierarchy (info,
gimp_drawable_get_tiles (GIMP_DRAWABLE (layer)),
error));
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
saved_pos = info->cp;
/* write out the layer mask */
if (gimp_layer_get_mask (layer))
{
GimpLayerMask *mask = gimp_layer_get_mask (layer);
xcf_check_error (xcf_seek_end (info, error));
offset = info->cp;
xcf_check_error (xcf_save_channel (info, image, GIMP_CHANNEL (mask),
error));
}
else
offset = 0;
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
return TRUE;
}
static gboolean
xcf_save_channel (XcfInfo *info,
GimpImage *image,
GimpChannel *channel,
GError **error)
{
guint32 saved_pos;
guint32 offset;
guint32 value;
const gchar *string;
GError *tmp_error = NULL;
/* check and see if this is the drawable that the floating
* selection is attached to.
*/
if (GIMP_DRAWABLE (channel) == info->floating_sel_drawable)
{
saved_pos = info->cp;
xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
xcf_write_int32_check_error (info, &saved_pos, 1);
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
}
/* write out the width and height information for the channel */
value = gimp_item_get_width (GIMP_ITEM (channel));
xcf_write_int32_check_error (info, &value, 1);
value = gimp_item_get_height (GIMP_ITEM (channel));
xcf_write_int32_check_error (info, &value, 1);
/* write out the channels name */
string = gimp_object_get_name (GIMP_OBJECT (channel));
xcf_write_string_check_error (info, (gchar **) &string, 1);
/* write out the channel properties */
xcf_save_channel_props (info, image, channel, error);
/* save the current position which is where the hierarchy offset
* will be stored.
*/
saved_pos = info->cp;
/* write out the channel tile hierarchy */
xcf_check_error (xcf_seek_pos (info, info->cp + 4, error));
offset = info->cp;
xcf_check_error (xcf_save_hierarchy (info,
gimp_drawable_get_tiles (GIMP_DRAWABLE (channel)),
error));
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
saved_pos = info->cp;
return TRUE;
}
static gint
xcf_calc_levels (gint size,
gint tile_size)
{
int levels;
levels = 1;
while (size > tile_size)
{
size /= 2;
levels += 1;
}
return levels;
}
static gboolean
xcf_save_hierarchy (XcfInfo *info,
TileManager *tiles,
GError **error)
{
guint32 saved_pos;
guint32 offset;
guint32 width;
guint32 height;
guint32 bpp;
gint i;
gint nlevels;
gint tmp1, tmp2;
GError *tmp_error = NULL;
width = tile_manager_width (tiles);
height = tile_manager_height (tiles);
bpp = tile_manager_bpp (tiles);
xcf_write_int32_check_error (info, (guint32 *) &width, 1);
xcf_write_int32_check_error (info, (guint32 *) &height, 1);
xcf_write_int32_check_error (info, (guint32 *) &bpp, 1);
saved_pos = info->cp;
tmp1 = xcf_calc_levels (width, TILE_WIDTH);
tmp2 = xcf_calc_levels (height, TILE_HEIGHT);
nlevels = MAX (tmp1, tmp2);
xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
for (i = 0; i < nlevels; i++)
{
offset = info->cp;
if (i == 0)
{
/* write out the level. */
xcf_check_error (xcf_save_level (info, tiles, error));
}
else
{
/* fake an empty level */
tmp1 = 0;
width /= 2;
height /= 2;
xcf_write_int32_check_error (info, (guint32 *) &width, 1);
xcf_write_int32_check_error (info, (guint32 *) &height, 1);
xcf_write_int32_check_error (info, (guint32 *) &tmp1, 1);
}
/* seek back to where we are to write out the next
* level offset and write it out.
*/
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
/* 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.
*/
xcf_check_error (xcf_seek_end (info, error));
}
/* write out a '0' offset position to indicate the end
* of the level offsets.
*/
offset = 0;
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
return TRUE;
}
static gboolean
xcf_save_level (XcfInfo *info,
TileManager *level,
GError **error)
{
guint32 saved_pos;
guint32 offset;
guint32 width;
guint32 height;
guint ntiles;
gint i;
guchar *rlebuf;
GError *tmp_error = NULL;
width = tile_manager_width (level);
height = tile_manager_height (level);
xcf_write_int32_check_error (info, (guint32 *) &width, 1);
xcf_write_int32_check_error (info, (guint32 *) &height, 1);
saved_pos = info->cp;
/* allocate a temporary buffer to store the rle data before it is
written to disk */
rlebuf =
g_malloc (TILE_WIDTH * TILE_HEIGHT * tile_manager_bpp (level) * 1.5);
if (level->tiles)
{
ntiles = level->ntile_rows * level->ntile_cols;
xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
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:
xcf_check_error (xcf_save_tile (info, level->tiles[i], error));
break;
case COMPRESS_RLE:
xcf_check_error (xcf_save_tile_rle (info, level->tiles[i],
rlebuf, error));
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.
*/
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
/* 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.
*/
xcf_check_error (xcf_seek_end (info, error));
}
}
g_free (rlebuf);
/* write out a '0' offset position to indicate the end
* of the level offsets.
*/
offset = 0;
xcf_check_error (xcf_seek_pos (info, saved_pos, error));
xcf_write_int32_check_error (info, &offset, 1);
return TRUE;
}
static gboolean
xcf_save_tile (XcfInfo *info,
Tile *tile,
GError **error)
{
GError *tmp_error = NULL;
tile_lock (tile);
xcf_write_int8_check_error (info, tile_data_pointer (tile, 0, 0),
tile_size (tile));
tile_release (tile, FALSE);
return TRUE;
}
static gboolean
xcf_save_tile_rle (XcfInfo *info,
Tile *tile,
guchar *rlebuf,
GError **error)
{
GError *tmp_error = NULL;
gint len = 0;
gint bpp;
gint i, j;
tile_lock (tile);
bpp = tile_bpp (tile);
for (i = 0; i < bpp; i++)
{
const guchar *data = (const guchar *) tile_data_pointer (tile, 0, 0) + i;
gint state = 0;
gint length = 0;
gint count = 0;
gint size = tile_ewidth (tile) * tile_eheight (tile);
guint 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;
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])))
{
const guchar *t;
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);
}
xcf_write_int8_check_error (info, rlebuf, len);
tile_release (tile, FALSE);
return TRUE;
}
static gboolean
xcf_save_parasite (XcfInfo *info,
GimpParasite *parasite,
GError **error)
{
if (gimp_parasite_is_persistent (parasite))
{
guint32 value;
const gchar *string;
GError *tmp_error = NULL;
string = gimp_parasite_name (parasite);
xcf_write_string_check_error (info, (gchar **) &string, 1);
value = gimp_parasite_flags (parasite);
xcf_write_int32_check_error (info, &value, 1);
value = gimp_parasite_data_size (parasite);
xcf_write_int32_check_error (info, &value, 1);
xcf_write_int8_check_error (info,
gimp_parasite_data (parasite),
gimp_parasite_data_size (parasite));
}
return TRUE;
}
typedef struct
{
XcfInfo *info;
GError *error;
} XcfParasiteData;
static void
xcf_save_parasite_func (gchar *key,
GimpParasite *parasite,
XcfParasiteData *data)
{
if (! data->error)
xcf_save_parasite (data->info, parasite, &data->error);
}
static gboolean
xcf_save_parasite_list (XcfInfo *info,
GimpParasiteList *list,
GError **error)
{
XcfParasiteData data;
data.info = info;
data.error = NULL;
gimp_parasite_list_foreach (list, (GHFunc) xcf_save_parasite_func, &data);
if (data.error)
{
g_propagate_error (error, data.error);
return FALSE;
}
return TRUE;
}
static gboolean
xcf_save_old_paths (XcfInfo *info,
GimpImage *image,
GError **error)
{
GimpVectors *active_vectors;
guint32 num_paths;
guint32 active_index = 0;
GList *list;
GError *tmp_error = NULL;
/* Write out the following:-
*
* last_selected_row (gint)
* number_of_paths (gint)
*
* then each path:-
*/
num_paths = gimp_container_get_n_children (image->vectors);
active_vectors = gimp_image_get_active_vectors (image);
if (active_vectors)
active_index = gimp_container_get_child_index (image->vectors,
GIMP_OBJECT (active_vectors));
xcf_write_int32_check_error (info, &active_index, 1);
xcf_write_int32_check_error (info, &num_paths, 1);
for (list = gimp_image_get_vectors_iter (image);
list;
list = g_list_next (list))
{
GimpVectors *vectors = list->data;
gchar *name;
guint32 locked;
guint8 state;
guint32 version;
guint32 pathtype;
guint32 tattoo;
GimpVectorsCompatPoint *points;
guint32 num_points;
guint32 closed;
gint i;
/*
* name (string)
* locked (gint)
* state (gchar)
* closed (gint)
* number points (gint)
* version (gint)
* pathtype (gint)
* tattoo (gint)
* then each point.
*/
points = gimp_vectors_compat_get_points (vectors,
(gint32 *) &num_points,
(gint32 *) &closed);
/* if no points are generated because of a faulty path we should
* skip saving the path - this is unfortunately impossible, because
* we already saved the number of paths and I wont start seeking
* around to fix that cruft */
name = (gchar *) gimp_object_get_name (GIMP_OBJECT (vectors));
locked = gimp_item_get_linked (GIMP_ITEM (vectors));
state = closed ? 4 : 2; /* EDIT : ADD (editing state, 1.2 compat) */
version = 3;
pathtype = 1; /* BEZIER (1.2 compat) */
tattoo = gimp_item_get_tattoo (GIMP_ITEM (vectors));
xcf_write_string_check_error (info, &name, 1);
xcf_write_int32_check_error (info, &locked, 1);
xcf_write_int8_check_error (info, &state, 1);
xcf_write_int32_check_error (info, &closed, 1);
xcf_write_int32_check_error (info, &num_points, 1);
xcf_write_int32_check_error (info, &version, 1);
xcf_write_int32_check_error (info, &pathtype, 1);
xcf_write_int32_check_error (info, &tattoo, 1);
for (i = 0; i < num_points; i++)
{
gfloat x;
gfloat y;
x = points[i].x;
y = points[i].y;
/*
* type (gint)
* x (gfloat)
* y (gfloat)
*/
xcf_write_int32_check_error (info, &points[i].type, 1);
xcf_write_float_check_error (info, &x, 1);
xcf_write_float_check_error (info, &y, 1);
}
g_free (points);
}
return TRUE;
}
static gboolean
xcf_save_vectors (XcfInfo *info,
GimpImage *image,
GError **error)
{
GimpVectors *active_vectors;
guint32 version = 1;
guint32 active_index = 0;
guint32 num_paths;
GList *list;
GList *stroke_list;
GError *tmp_error = NULL;
/* Write out the following:-
*
* version (gint)
* active_index (gint)
* num_paths (gint)
*
* then each path:-
*/
active_vectors = gimp_image_get_active_vectors (image);
if (active_vectors)
active_index = gimp_container_get_child_index (image->vectors,
GIMP_OBJECT (active_vectors));
num_paths = gimp_container_get_n_children (image->vectors);
xcf_write_int32_check_error (info, &version, 1);
xcf_write_int32_check_error (info, &active_index, 1);
xcf_write_int32_check_error (info, &num_paths, 1);
for (list = gimp_image_get_vectors_iter (image);
list;
list = g_list_next (list))
{
GimpVectors *vectors = list->data;
GimpParasiteList *parasites;
const gchar *name;
guint32 tattoo;
guint32 visible;
guint32 linked;
guint32 num_parasites;
guint32 num_strokes;
/*
* name (string)
* tattoo (gint)
* visible (gint)
* linked (gint)
* num_parasites (gint)
* num_strokes (gint)
*
* then each parasite
* then each stroke
*/
parasites = GIMP_ITEM (vectors)->parasites;
name = gimp_object_get_name (GIMP_OBJECT (vectors));
visible = gimp_item_get_visible (GIMP_ITEM (vectors));
linked = gimp_item_get_linked (GIMP_ITEM (vectors));
tattoo = gimp_item_get_tattoo (GIMP_ITEM (vectors));
num_parasites = gimp_parasite_list_persistent_length (parasites);
num_strokes = g_list_length (vectors->strokes);
xcf_write_string_check_error (info, (gchar **) &name, 1);
xcf_write_int32_check_error (info, &tattoo, 1);
xcf_write_int32_check_error (info, &visible, 1);
xcf_write_int32_check_error (info, &linked, 1);
xcf_write_int32_check_error (info, &num_parasites, 1);
xcf_write_int32_check_error (info, &num_strokes, 1);
xcf_check_error (xcf_save_parasite_list (info, parasites, error));
for (stroke_list = g_list_first (vectors->strokes);
stroke_list;
stroke_list = g_list_next (stroke_list))
{
GimpStroke *stroke = stroke_list->data;
guint32 stroke_type;
guint32 closed;
guint32 num_axes;
GArray *control_points;
gint i;
guint32 type;
gfloat coords[6];
/*
* stroke_type (gint)
* closed (gint)
* num_axes (gint)
* num_control_points (gint)
*
* then each control point.
*/
if (GIMP_IS_BEZIER_STROKE (stroke))
{
stroke_type = XCF_STROKETYPE_BEZIER_STROKE;
num_axes = 2; /* hardcoded, might be increased later */
}
else
{
g_printerr ("Skipping unknown stroke type!\n");
continue;
}
control_points = gimp_stroke_control_points_get (stroke,
(gint32 *) &closed);
xcf_write_int32_check_error (info, &stroke_type, 1);
xcf_write_int32_check_error (info, &closed, 1);
xcf_write_int32_check_error (info, &num_axes, 1);
xcf_write_int32_check_error (info, &control_points->len, 1);
for (i = 0; i < control_points->len; i++)
{
GimpAnchor *anchor;
anchor = & (g_array_index (control_points, GimpAnchor, i));
type = anchor->type;
coords[0] = anchor->position.x;
coords[1] = anchor->position.y;
coords[2] = anchor->position.pressure;
coords[3] = anchor->position.xtilt;
coords[4] = anchor->position.ytilt;
coords[5] = anchor->position.wheel;
/*
* type (gint)
*
* the first num_axis elements of:
* [0] x (gfloat)
* [1] y (gfloat)
* [2] pressure (gfloat)
* [3] xtilt (gfloat)
* [4] ytilt (gfloat)
* [5] wheel (gfloat)
*/
xcf_write_int32_check_error (info, &type, 1);
xcf_write_float_check_error (info, coords, num_axes);
}
g_array_free (control_points, TRUE);
}
}
return TRUE;
}