filters

xcf-save.cc

00001 /* The GIMP -- an image manipulation program
00002  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "config.h"
00020 
00021 #include <stdio.h>
00022 #include <string.h> /* strcpy, strlen */
00023 
00024 #include <glib-object.h>
00025 
00026 #include "libgimpbase/gimpbase.h"
00027 #include "libgimpcolor/gimpcolor.h"
00028 
00029 #include "core/core-types.h"
00030 
00031 #include "base/tile.h"
00032 #include "base/tile-manager.h"
00033 #include "base/tile-manager-private.h"
00034 
00035 #include "core/gimpchannel.h"
00036 #include "core/gimpdrawable.h"
00037 #include "core/gimpgrid.h"
00038 #include "core/gimpimage.h"
00039 #include "core/gimpimage-grid.h"
00040 #include "core/gimpimage-guides.h"
00041 #include "core/gimplayer.h"
00042 #include "core/gimplayer-floating-sel.h"
00043 #include "core/gimplayermask.h"
00044 #include "core/gimplist.h"
00045 #include "core/gimpparasitelist.h"
00046 #include "core/gimpunit.h"
00047 
00048 #include "text/gimptextlayer.h"
00049 #include "text/gimptextlayer-xcf.h"
00050 
00051 #include "vectors/gimpanchor.h"
00052 #include "vectors/gimpstroke.h"
00053 #include "vectors/gimpbezierstroke.h"
00054 #include "vectors/gimpvectors.h"
00055 #include "vectors/gimpvectors-compat.h"
00056 
00057 #include "xcf-private.h"
00058 #include "xcf-read.h"
00059 #include "xcf-seek.h"
00060 #include "xcf-write.h"
00061 
00062 #include "gimp-intl.h"
00063 
00064 
00065 static bool xcf_save_image_props   (XcfInfo           *info,
00066                                     KisImage         *gimage,
00067                                     GError           **error);
00068 static bool xcf_save_layer_props   (XcfInfo           *info,
00069                                     KisImage         *gimage,
00070                                     KisLayer         *layer,
00071                                     GError           **error);
00072 static bool xcf_save_channel_props (XcfInfo           *info,
00073                                     KisImage         *gimage,
00074                                     GimpChannel       *channel,
00075                                     GError           **error);
00076 static bool xcf_save_prop          (XcfInfo           *info,
00077                                     KisImage         *gimage,
00078                                     PropType           prop_type,
00079                                     GError           **error,
00080                                     ...);
00081 static bool xcf_save_layer         (XcfInfo           *info,
00082                                     KisImage         *gimage,
00083                                     KisLayer         *layer,
00084                                     GError           **error);
00085 static bool xcf_save_channel       (XcfInfo           *info,
00086                                     KisImage         *gimage,
00087                                     GimpChannel       *channel,
00088                                     GError           **error);
00089 static bool xcf_save_hierarchy     (XcfInfo           *info,
00090                                     TileManager       *tiles,
00091                                     GError           **error);
00092 static bool xcf_save_level         (XcfInfo           *info,
00093                                     TileManager       *tiles,
00094                                     GError           **error);
00095 static bool xcf_save_tile          (XcfInfo           *info,
00096                                     Tile              *tile,
00097                                     GError           **error);
00098 static bool xcf_save_tile_rle      (XcfInfo           *info,
00099                                     Tile              *tile,
00100                                     guchar            *rlebuf,
00101                                     GError           **error);
00102 static bool xcf_save_parasite      (XcfInfo           *info,
00103                                     KisAnnotation      *parasite,
00104                                     GError           **error);
00105 static bool xcf_save_parasite_list (XcfInfo           *info,
00106                                     KisAnnotationList  *parasite,
00107                                     GError           **error);
00108 static bool xcf_save_old_paths     (XcfInfo           *info,
00109                                     KisImage         *gimage,
00110                                     GError           **error);
00111 static bool xcf_save_vectors       (XcfInfo           *info,
00112                                     KisImage         *gimage,
00113                                     GError           **error);
00114 
00115 
00116 /* private convenience macros */
00117 #define xcf_write_int32_check_error(info, data, count) G_STMT_START {   \
00118         info->cp += xcf_write_int32 (info->fp, data, count, &tmp_error); \
00119         if (tmp_error)                                                  \
00120         {                                                               \
00121             g_propagate_error (error, tmp_error);                       \
00122             return FALSE;                                               \
00123         }                                                               \
00124     } G_STMT_END
00125 
00126 #define xcf_write_int8_check_error(info, data, count) G_STMT_START {    \
00127         info->cp += xcf_write_int8 (info->fp, data, count, &tmp_error); \
00128         if (tmp_error)                                                  \
00129         {                                                               \
00130             g_propagate_error (error, tmp_error);                       \
00131             return FALSE;                                               \
00132         }                                                               \
00133     } G_STMT_END
00134 
00135 #define xcf_write_float_check_error(info, data, count) G_STMT_START {   \
00136         info->cp += xcf_write_float (info->fp, data, count, &tmp_error); \
00137         if (tmp_error)                                                  \
00138         {                                                               \
00139             g_propagate_error (error, tmp_error);                       \
00140             return FALSE;                                               \
00141         }                                                               \
00142     } G_STMT_END
00143 
00144 #define xcf_write_string_check_error(info, data, count) G_STMT_START {  \
00145         info->cp += xcf_write_string (info->fp, data, count, &tmp_error); \
00146         if (tmp_error)                                                  \
00147         {                                                               \
00148             g_propagate_error (error, tmp_error);                       \
00149             return FALSE;                                               \
00150         }                                                               \
00151     } G_STMT_END
00152 
00153 #define xcf_write_int32_print_error(info, data, count) G_STMT_START {   \
00154         info->cp += xcf_write_int32 (info->fp, data, count, &error);    \
00155         if (error)                                                      \
00156         {                                                               \
00157             g_message (_("Error saving XCF file: %s"),                  \
00158                        error->message);                                 \
00159             return FALSE;                                               \
00160         }                                                               \
00161     } G_STMT_END
00162 
00163 #define xcf_write_int8_print_error(info, data, count) G_STMT_START {    \
00164         info->cp += xcf_write_int8 (info->fp, data, count, &error);     \
00165         if (error)                                                      \
00166         {                                                               \
00167             g_message (_("Error saving XCF file: %s"),                  \
00168                        error->message);                                 \
00169             return FALSE;                                               \
00170         }                                                               \
00171     } G_STMT_END
00172 
00173 #define xcf_write_float_print_error(info, data, count) G_STMT_START {   \
00174         info->cp += xcf_write_float (info->fp, data, count, &error);    \
00175         if (error)                                                      \
00176         {                                                               \
00177             g_message (_("Error saving XCF file: %s"),                  \
00178                        error->message);                                 \
00179             return FALSE;                                               \
00180         }                                                               \
00181     } G_STMT_END
00182 
00183 #define xcf_write_string_print_error(info, data, count) G_STMT_START {  \
00184         info->cp += xcf_write_string (info->fp, data, count, &error);   \
00185         if (error)                                                      \
00186         {                                                               \
00187             g_message (_("Error saving XCF file: %s"),                  \
00188                        error->message);                                 \
00189             return FALSE;                                               \
00190         }                                                               \
00191     } G_STMT_END
00192 
00193 #define xcf_write_prop_type_check_error(info, prop_type) G_STMT_START { \
00194         Q_INT32 _prop_int32 = prop_type;                                \
00195         xcf_write_int32_check_error (info, &_prop_int32, 1);            \
00196     } G_STMT_END
00197 
00198 #define xcf_write_prop_type_print_error(info, prop_type) G_STMT_START { \
00199         Q_INT32 _prop_int32 = prop_type;                                \
00200         xcf_write_int32_print_error (info, &_prop_int32, 1);            \
00201     } G_STMT_END
00202 
00203 #define xcf_check_error(x) G_STMT_START {       \
00204         if (! (x))                              \
00205             return FALSE;                       \
00206     } G_STMT_END
00207 
00208 #define xcf_print_error(x) G_STMT_START {               \
00209         if (! (x))                                      \
00210         {                                               \
00211             g_message (_("Error saving XCF file: %s"),  \
00212                        error->message);                 \
00213             return FALSE;                               \
00214         }                                               \
00215     } G_STMT_END
00216 
00217 
00218 void
00219 xcf_save_choose_format (XcfInfo   *info,
00220                         KisImage *gimage)
00221 {
00222     KisLayer *layer;
00223     GList     *list;
00224 
00225     Q_INT32 save_version = 0;                /* default to oldest */
00226 
00227     if (gimage->cmap)
00228         save_version = 1;                   /* need version 1 for colormaps */
00229 
00230     for (list = GIMP_LIST (gimage->layers)->list;
00231          list && save_version < 2;
00232          list = g_list_next (list))
00233     {
00234         layer = GIMP_LAYER (list->data);
00235 
00236         switch (layer->mode)
00237         {
00238             /* new layer modes not supported by gimp-1.2 */
00239         case GIMP_SOFTLIGHT_MODE:
00240         case GIMP_GRAIN_EXTRACT_MODE:
00241         case GIMP_GRAIN_MERGE_MODE:
00242         case GIMP_COLOR_ERASE_MODE:
00243             save_version = 2;
00244             break;
00245 
00246         default:
00247             break;
00248         }
00249     }
00250 
00251     info->file_version = save_version;
00252 }
00253 
00254 Q_INT32
00255 xcf_save_image (XcfInfo   *info,
00256         KisImage *gimage)
00257 {
00258     KisLayer   *layer;
00259     KisLayer   *floating_layer;
00260     GimpChannel *channel;
00261     Q_INT32      saved_pos;
00262     Q_INT32      offset;
00263     Q_UINT32        nlayers;
00264     Q_UINT32        nchannels;
00265     GList       *list;
00266     bool     have_selection;
00267     Q_INT32         t1, t2, t3, t4;
00268     QCString        version_tag[14];
00269     GError      *error = NULL;
00270 
00271     floating_layer = gimp_image_floating_sel (gimage);
00272     if (floating_layer)
00273         floating_sel_relax (floating_layer, FALSE);
00274 
00275     /* write out the tag information for the image */
00276     if (info->file_version > 0)
00277     {
00278         sprintf (version_tag, "gimp xcf v%03d", info->file_version);
00279     }
00280     else
00281     {
00282         strcpy (version_tag, "gimp xcf file");
00283     }
00284     xcf_write_int8_print_error  (info, (Q_UINT8 *) version_tag, 14);
00285 
00286     /* write out the width, height and image type information for the image */
00287     xcf_write_int32_print_error (info, (Q_INT32 *) &gimage->width, 1);
00288     xcf_write_int32_print_error (info, (Q_INT32 *) &gimage->height, 1);
00289     xcf_write_int32_print_error (info, (Q_INT32 *) &gimage->base_type, 1);
00290 
00291     /* determine the number of layers and channels in the image */
00292     nlayers   = (Q_UINT32) gimp_container_num_children (gimage->layers);
00293     nchannels = (Q_UINT32) gimp_container_num_children (gimage->channels);
00294 
00295     /* check and see if we have to save out the selection */
00296     have_selection = gimp_channel_bounds (gimp_image_get_mask (gimage),
00297                                           &t1, &t2, &t3, &t4);
00298     if (have_selection)
00299         nchannels += 1;
00300 
00301     /* write the property information for the image.
00302      */
00303 
00304     xcf_print_error (xcf_save_image_props (info, gimage, &error));
00305 
00306     /* save the current file position as it is the start of where
00307      *  we place the layer offset information.
00308      */
00309     saved_pos = info->cp;
00310 
00311     /* seek to after the offset lists */
00312     xcf_print_error (xcf_seek_pos (info,
00313                                    info->cp + (nlayers + nchannels + 2) * 4,
00314                                    &error));
00315 
00316     for (list = GIMP_LIST (gimage->layers)->list;
00317          list;
00318          list = g_list_next (list))
00319     {
00320         layer = (KisLayer *) list->data;
00321 
00322         /* save the start offset of where we are writing
00323          *  out the next layer.
00324          */
00325         offset = info->cp;
00326 
00327         /* write out the layer. */
00328         xcf_print_error (xcf_save_layer (info, gimage, layer, &error));
00329 
00330         /* seek back to where we are to write out the next
00331          *  layer offset and write it out.
00332          */
00333         xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
00334         xcf_write_int32_print_error (info, &offset, 1);
00335 
00336         /* increment the location we are to write out the
00337          *  next offset.
00338          */
00339         saved_pos = info->cp;
00340 
00341         /* seek to the end of the file which is where
00342          *  we will write out the next layer.
00343          */
00344         xcf_print_error (xcf_seek_end (info, &error));
00345     }
00346 
00347     /* write out a '0' offset position to indicate the end
00348      *  of the layer offsets.
00349      */
00350     offset = 0;
00351     xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
00352     xcf_write_int32_print_error (info, &offset, 1);
00353     saved_pos = info->cp;
00354     xcf_print_error (xcf_seek_end (info, &error));
00355 
00356     list = GIMP_LIST (gimage->channels)->list;
00357 
00358     while (list || have_selection)
00359     {
00360         if (list)
00361     {
00362             channel = (GimpChannel *) list->data;
00363 
00364             list = g_list_next (list);
00365     }
00366         else
00367     {
00368             channel = gimage->selection_mask;
00369             have_selection = FALSE;
00370     }
00371 
00372         /* save the start offset of where we are writing
00373          *  out the next channel.
00374          */
00375         offset = info->cp;
00376 
00377         /* write out the layer. */
00378         xcf_print_error (xcf_save_channel (info, gimage, channel, &error));
00379 
00380         /* seek back to where we are to write out the next
00381          *  channel offset and write it out.
00382          */
00383         xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
00384         xcf_write_int32_print_error (info, &offset, 1);
00385 
00386         /* increment the location we are to write out the
00387          *  next offset.
00388          */
00389         saved_pos = info->cp;
00390 
00391         /* seek to the end of the file which is where
00392          *  we will write out the next channel.
00393          */
00394         xcf_print_error (xcf_seek_end (info, &error));
00395     }
00396 
00397     /* write out a '0' offset position to indicate the end
00398      *  of the channel offsets.
00399      */
00400     offset = 0;
00401     xcf_print_error (xcf_seek_pos (info, saved_pos, &error));
00402     xcf_write_int32_print_error (info, &offset, 1);
00403     saved_pos = info->cp;
00404 
00405     if (floating_layer)
00406         floating_sel_rigor (floating_layer, FALSE);
00407 
00408     return !ferror(info->fp);
00409 }
00410 
00411 static bool
00412 xcf_save_image_props (XcfInfo   *info,
00413               KisImage *gimage,
00414               GError   **error)
00415 {
00416     KisAnnotation *parasite = NULL;
00417     GimpUnit      unit     = gimp_image_get_unit (gimage);
00418 
00419     /* check and see if we should save the colormap property */
00420     if (gimage->cmap)
00421         xcf_check_error (xcf_save_prop (info, gimage, PROP_COLORMAP, error,
00422                                         gimage->num_cols, gimage->cmap));
00423 
00424     if (info->compression != COMPRESS_NONE)
00425         xcf_check_error (xcf_save_prop (info, gimage, PROP_COMPRESSION,
00426                                         error, info->compression));
00427 
00428     if (gimage->guides)
00429         xcf_check_error (xcf_save_prop (info, gimage, PROP_GUIDES,
00430                                         error, gimage->guides));
00431 
00432     xcf_check_error (xcf_save_prop (info, gimage, PROP_RESOLUTION, error,
00433                                     gimage->xresolution, gimage->yresolution));
00434 
00435     xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
00436                                     gimage->tattoo_state));
00437 
00438     if (gimp_parasite_list_length (gimage->parasites) > 0)
00439         xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES,
00440                                         error, gimage->parasites));
00441 
00442     if (unit < _gimp_unit_get_number_of_built_in_units (gimage->gimp))
00443         xcf_check_error (xcf_save_prop (info, gimage, PROP_UNIT, error, unit));
00444 
00445     if (gimp_container_num_children (gimage->vectors) > 0)
00446     {
00447         if (gimp_vectors_compat_is_compatible (gimage))
00448             xcf_check_error (xcf_save_prop (info, gimage, PROP_PATHS, error));
00449         else
00450             xcf_check_error (xcf_save_prop (info, gimage, PROP_VECTORS, error));
00451     }
00452 
00453     if (unit >= _gimp_unit_get_number_of_built_in_units (gimage->gimp))
00454         xcf_check_error (xcf_save_prop (info, gimage, PROP_USER_UNIT, error, unit));
00455 
00456     if (GIMP_IS_GRID (gimage->grid))
00457     {
00458         GimpGrid *grid = gimp_image_get_grid (gimage);
00459 
00460         parasite = gimp_grid_to_parasite (grid);
00461         gimp_parasite_list_add (GIMP_IMAGE (gimage)->parasites, parasite);
00462     }
00463 
00464     if (gimp_parasite_list_length (GIMP_IMAGE (gimage)->parasites) > 0)
00465     {
00466         xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
00467                                         GIMP_IMAGE (gimage)->parasites));
00468     }
00469 
00470     if (parasite)
00471     {
00472         gimp_parasite_list_remove (GIMP_IMAGE (gimage)->parasites,
00473                                    gimp_parasite_name (parasite));
00474         gimp_parasite_free (parasite);
00475     }
00476 
00477     xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
00478 
00479     return TRUE;
00480 }
00481 
00482 static bool
00483 xcf_save_layer_props (XcfInfo   *info,
00484               KisImage *gimage,
00485               KisLayer *layer,
00486               GError   **error)
00487 {
00488     KisAnnotation *parasite = NULL;
00489 
00490     if (layer == gimp_image_get_active_layer (gimage))
00491         xcf_check_error (xcf_save_prop (info, gimage, PROP_ACTIVE_LAYER, error));
00492 
00493     if (layer == gimp_image_floating_sel (gimage))
00494     {
00495         info->floating_sel_drawable = layer->fs.drawable;
00496         xcf_check_error (xcf_save_prop (info, gimage, PROP_FLOATING_SELECTION,
00497                                         error));
00498     }
00499 
00500     xcf_check_error (xcf_save_prop (info, gimage, PROP_OPACITY, error,
00501                                     layer->opacity));
00502     xcf_check_error (xcf_save_prop (info, gimage, PROP_VISIBLE, error,
00503                                     gimp_item_get_visible (GIMP_ITEM (layer))));
00504     xcf_check_error (xcf_save_prop (info, gimage, PROP_LINKED, error,
00505                                     gimp_item_get_linked (GIMP_ITEM (layer))));
00506     xcf_check_error (xcf_save_prop (info, gimage, PROP_LOCK_ALPHA,
00507                                     error, layer->lock_alpha));
00508 
00509     if (layer->mask)
00510     {
00511         xcf_check_error (xcf_save_prop (info, gimage, PROP_APPLY_MASK,
00512                                         error, layer->mask->apply_mask));
00513         xcf_check_error (xcf_save_prop (info, gimage, PROP_EDIT_MASK,
00514                                         error, layer->mask->edit_mask));
00515         xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASK,
00516                                         error, layer->mask->show_mask));
00517     }
00518     else
00519     {
00520         xcf_check_error (xcf_save_prop (info, gimage, PROP_APPLY_MASK,
00521                                         error, FALSE));
00522         xcf_check_error (xcf_save_prop (info, gimage, PROP_EDIT_MASK,
00523                                         error, FALSE));
00524         xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASK,
00525                                         error, FALSE));
00526     }
00527 
00528     xcf_check_error (xcf_save_prop (info, gimage, PROP_OFFSETS, error,
00529                                     GIMP_ITEM (layer)->offset_x,
00530                                     GIMP_ITEM (layer)->offset_y));
00531     xcf_check_error (xcf_save_prop (info, gimage, PROP_MODE, error,
00532                                     layer->mode));
00533     xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
00534                                     GIMP_ITEM (layer)->tattoo));
00535 
00536     if (GIMP_IS_TEXT_LAYER (layer) && GIMP_TEXT_LAYER (layer)->text)
00537     {
00538         GimpTextLayer *text_layer = GIMP_TEXT_LAYER (layer);
00539         Q_INT32        flags      = gimp_text_layer_get_xcf_flags (text_layer);
00540 
00541         gimp_text_layer_xcf_save_prepare (text_layer);
00542 
00543         if (flags)
00544             xcf_check_error (xcf_save_prop (info,
00545                                             gimage, PROP_TEXT_LAYER_FLAGS, error,
00546                                             flags));
00547     }
00548 
00549     if (gimp_parasite_list_length (GIMP_ITEM (layer)->parasites) > 0)
00550     {
00551         xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
00552                                         GIMP_ITEM (layer)->parasites));
00553     }
00554 
00555     if (parasite)
00556     {
00557         gimp_parasite_list_remove (GIMP_ITEM (layer)->parasites,
00558                                    gimp_parasite_name (parasite));
00559         gimp_parasite_free (parasite);
00560     }
00561 
00562     xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
00563 
00564     return TRUE;
00565 }
00566 
00567 static bool
00568 xcf_save_channel_props (XcfInfo     *info,
00569             KisImage   *gimage,
00570             GimpChannel *channel,
00571             GError     **error)
00572 {
00573     guchar col[3];
00574 
00575     if (channel == gimp_image_get_active_channel (gimage))
00576         xcf_check_error (xcf_save_prop (info, gimage, PROP_ACTIVE_CHANNEL, error));
00577 
00578     if (channel == gimage->selection_mask)
00579         xcf_check_error (xcf_save_prop (info, gimage, PROP_SELECTION, error));
00580 
00581     xcf_check_error (xcf_save_prop (info, gimage, PROP_OPACITY, error,
00582                                     channel->color.a));
00583     xcf_check_error (xcf_save_prop (info, gimage, PROP_VISIBLE, error,
00584                                     gimp_item_get_visible (GIMP_ITEM (channel))));
00585     xcf_check_error (xcf_save_prop (info, gimage, PROP_LINKED, error,
00586                                     gimp_item_get_linked (GIMP_ITEM (channel))));
00587     xcf_check_error (xcf_save_prop (info, gimage, PROP_SHOW_MASKED, error,
00588                                     channel->show_masked));
00589 
00590     gimp_rgb_get_uchar (&channel->color, &col[0], &col[1], &col[2]);
00591     xcf_check_error (xcf_save_prop (info, gimage, PROP_COLOR, error, col));
00592 
00593     xcf_check_error (xcf_save_prop (info, gimage, PROP_TATTOO, error,
00594                                     GIMP_ITEM (channel)->tattoo));
00595 
00596     if (gimp_parasite_list_length (GIMP_ITEM (channel)->parasites) > 0)
00597         xcf_check_error (xcf_save_prop (info, gimage, PROP_PARASITES, error,
00598                                         GIMP_ITEM (channel)->parasites));
00599 
00600     xcf_check_error (xcf_save_prop (info, gimage, PROP_END, error));
00601 
00602     return TRUE;
00603 }
00604 
00605 static bool
00606 xcf_save_prop (XcfInfo   *info,
00607            KisImage *gimage,
00608            PropType   prop_type,
00609            GError   **error,
00610            ...)
00611 {
00612     Q_INT32 size;
00613     va_list args;
00614 
00615     GError *tmp_error = NULL;
00616 
00617     va_start (args, error);
00618 
00619     switch (prop_type)
00620     {
00621     case PROP_END:
00622         size = 0;
00623 
00624         xcf_write_prop_type_check_error (info, prop_type);
00625         xcf_write_int32_check_error (info, &size, 1);
00626         break;
00627 
00628     case PROP_COLORMAP:
00629     {
00630     Q_INT32  ncolors;
00631     guchar  *colors;
00632 
00633     ncolors = va_arg (args, Q_INT32);
00634     colors = va_arg (args, guchar*);
00635     size = 4 + ncolors * 3;
00636 
00637         xcf_write_prop_type_check_error (info, prop_type);
00638     xcf_write_int32_check_error (info, &size, 1);
00639     xcf_write_int32_check_error (info, &ncolors, 1);
00640     xcf_write_int8_check_error  (info, colors, ncolors * 3);
00641     }
00642     break;
00643 
00644     case PROP_ACTIVE_LAYER:
00645     case PROP_ACTIVE_CHANNEL:
00646     case PROP_SELECTION:
00647         size = 0;
00648 
00649         xcf_write_prop_type_check_error (info, prop_type);
00650         xcf_write_int32_check_error (info, &size, 1);
00651         break;
00652 
00653     case PROP_FLOATING_SELECTION:
00654     {
00655     Q_INT32 dummy;
00656 
00657     dummy = 0;
00658     size = 4;
00659 
00660         xcf_write_prop_type_check_error (info, prop_type);
00661     xcf_write_int32_check_error (info, &size, 1);
00662     info->floating_sel_offset = info->cp;
00663     xcf_write_int32_check_error (info, &dummy, 1);
00664     }
00665     break;
00666 
00667     case PROP_OPACITY:
00668     {
00669     gdouble opacity;
00670         Q_INT32 uint_opacity;
00671 
00672     opacity = va_arg (args, gdouble);
00673 
00674         uint_opacity = opacity * 255.999;
00675 
00676     size = 4;
00677 
00678         xcf_write_prop_type_check_error (info, prop_type);
00679     xcf_write_int32_check_error (info, &size, 1);
00680     xcf_write_int32_check_error (info, &uint_opacity, 1);
00681     }
00682     break;
00683 
00684     case PROP_MODE:
00685     {
00686     Q_INT3232 mode;
00687 
00688     mode = va_arg (args, Q_INT3232);
00689     size = 4;
00690 
00691         xcf_write_prop_type_check_error (info, prop_type);
00692     xcf_write_int32_check_error (info, &size, 1);
00693     xcf_write_int32_check_error (info, (Q_INT32 *) &mode, 1);
00694     }
00695     break;
00696 
00697     case PROP_VISIBLE:
00698     {
00699     Q_INT32 visible;
00700 
00701     visible = va_arg (args, Q_INT32);
00702     size = 4;
00703 
00704         xcf_write_prop_type_check_error (info, prop_type);
00705     xcf_write_int32_check_error (info, &size, 1);
00706     xcf_write_int32_check_error (info, &visible, 1);
00707     }
00708     break;
00709 
00710     case PROP_LINKED:
00711     {
00712     Q_INT32 linked;
00713 
00714     linked = va_arg (args, Q_INT32);
00715     size = 4;
00716 
00717         xcf_write_prop_type_check_error (info, prop_type);
00718     xcf_write_int32_check_error (info, &size, 1);
00719     xcf_write_int32_check_error (info, &linked, 1);
00720     }
00721     break;
00722 
00723     case PROP_LOCK_ALPHA:
00724     {
00725     Q_INT32 lock_alpha;
00726 
00727     lock_alpha = va_arg (args, Q_INT32);
00728     size = 4;
00729 
00730         xcf_write_prop_type_check_error (info, prop_type);
00731     xcf_write_int32_check_error (info, &size, 1);
00732     xcf_write_int32_check_error (info, &lock_alpha, 1);
00733     }
00734     break;
00735 
00736     case PROP_APPLY_MASK:
00737     {
00738     Q_INT32 apply_mask;
00739 
00740     apply_mask = va_arg (args, Q_INT32);
00741     size = 4;
00742 
00743         xcf_write_prop_type_check_error (info, prop_type);
00744     xcf_write_int32_check_error (info, &size, 1);
00745     xcf_write_int32_check_error (info, &apply_mask, 1);
00746     }
00747     break;
00748 
00749     case PROP_EDIT_MASK:
00750     {
00751     Q_INT32 edit_mask;
00752 
00753     edit_mask = va_arg (args, Q_INT32);
00754     size = 4;
00755 
00756         xcf_write_prop_type_check_error (info, prop_type);
00757     xcf_write_int32_check_error (info, &size, 1);
00758     xcf_write_int32_check_error (info, &edit_mask, 1);
00759     }
00760     break;
00761 
00762     case PROP_SHOW_MASK:
00763     {
00764     Q_INT32 show_mask;
00765 
00766     show_mask = va_arg (args, Q_INT32);
00767     size = 4;
00768 
00769         xcf_write_prop_type_check_error (info, prop_type);
00770     xcf_write_int32_check_error (info, &size, 1);
00771     xcf_write_int32_check_error (info, &show_mask, 1);
00772     }
00773     break;
00774 
00775     case PROP_SHOW_MASKED:
00776     {
00777     Q_INT32 show_masked;
00778 
00779     show_masked = va_arg (args, Q_INT32);
00780     size = 4;
00781 
00782         xcf_write_prop_type_check_error (info, prop_type);
00783     xcf_write_int32_check_error (info, &size, 1);
00784     xcf_write_int32_check_error (info, &show_masked, 1);
00785     }
00786     break;
00787 
00788     case PROP_OFFSETS:
00789     {
00790     Q_INT3232 offsets[2];
00791 
00792     offsets[0] = va_arg (args, Q_INT3232);
00793     offsets[1] = va_arg (args, Q_INT3232);
00794     size = 8;
00795 
00796         xcf_write_prop_type_check_error (info, prop_type);
00797     xcf_write_int32_check_error (info, &size, 1);
00798     xcf_write_int32_check_error (info, (Q_INT32 *) offsets, 2);
00799     }
00800     break;
00801 
00802     case PROP_COLOR:
00803     {
00804     guchar *color;
00805 
00806     color = va_arg (args, guchar*);
00807     size = 3;
00808 
00809         xcf_write_prop_type_check_error (info, prop_type);
00810     xcf_write_int32_check_error (info, &size, 1);
00811     xcf_write_int8_check_error  (info, color, 3);
00812     }
00813     break;
00814 
00815     case PROP_COMPRESSION:
00816     {
00817     Q_UINT8 compression;
00818 
00819     compression = (Q_UINT8) va_arg (args, Q_INT32);
00820     size = 1;
00821 
00822         xcf_write_prop_type_check_error (info, prop_type);
00823     xcf_write_int32_check_error (info, &size, 1);
00824     xcf_write_int8_check_error  (info, &compression, 1);
00825     }
00826     break;
00827 
00828     case PROP_GUIDES:
00829     {
00830     GList     *guides;
00831     GimpGuide *guide;
00832     Q_INT3232     position;
00833     Q_INT328      orientation;
00834     Q_INT32       nguides;
00835 
00836     guides = va_arg (args, GList *);
00837     nguides = g_list_length (guides);
00838 
00839     size = nguides * (4 + 1);
00840 
00841         xcf_write_prop_type_check_error (info, prop_type);
00842     xcf_write_int32_check_error (info, &size, 1);
00843 
00844     for (; guides; guides = g_list_next (guides))
00845         {
00846         guide = (GimpGuide *) guides->data;
00847 
00848         position = guide->position;
00849 
00850             switch (guide->orientation)
00851             {
00852             case GIMP_ORIENTATION_HORIZONTAL:
00853                 orientation = XCF_ORIENTATION_HORIZONTAL;
00854                 break;
00855 
00856             case GIMP_ORIENTATION_VERTICAL:
00857                 orientation = XCF_ORIENTATION_VERTICAL;
00858                 break;
00859 
00860             default:
00861                 g_warning ("%s: skipping guide with bad orientation",
00862                            G_STRFUNC);
00863                 continue;
00864             }
00865 
00866         xcf_write_int32_check_error (info, (Q_INT32 *) &position,    1);
00867         xcf_write_int8_check_error  (info, (Q_UINT8 *)  &orientation, 1);
00868         }
00869     }
00870     break;
00871 
00872     case PROP_RESOLUTION:
00873     {
00874     float xresolution, yresolution;
00875 
00876     /* we pass in floats,
00877            but they are promoted to double by the compiler */
00878     xresolution =  va_arg (args, double);
00879     yresolution =  va_arg (args, double);
00880 
00881     size = 4*2;
00882 
00883         xcf_write_prop_type_check_error (info, prop_type);
00884     xcf_write_int32_check_error (info, &size, 1);
00885 
00886     xcf_write_float_check_error (info, &xresolution, 1);
00887     xcf_write_float_check_error (info, &yresolution, 1);
00888     }
00889     break;
00890 
00891     case PROP_TATTOO:
00892     {
00893     Q_INT32 tattoo;
00894 
00895     tattoo =  va_arg (args, Q_INT32);
00896     size = 4;
00897 
00898         xcf_write_prop_type_check_error (info, prop_type);
00899     xcf_write_int32_check_error (info, &size, 1);
00900     xcf_write_int32_check_error (info, &tattoo, 1);
00901     }
00902     break;
00903 
00904     case PROP_PARASITES:
00905     {
00906     KisAnnotationList *list;
00907     Q_INT32           base, length;
00908     long              pos;
00909 
00910     list = va_arg (args, KisAnnotationList *);
00911 
00912     if (gimp_parasite_list_persistent_length (list) > 0)
00913         {
00914             xcf_write_prop_type_check_error (info, prop_type);
00915 
00916         /* because we don't know how much room the parasite list will take
00917          * we save the file position and write the length later
00918          */
00919             pos = info->cp;
00920         xcf_write_int32_check_error (info, &length, 1);
00921         base = info->cp;
00922 
00923             xcf_check_error (xcf_save_parasite_list (info, list, error));
00924 
00925         length = info->cp - base;
00926         /* go back to the saved position and write the length */
00927             xcf_check_error (xcf_seek_pos (info, pos, error));
00928         xcf_write_int32 (info->fp, &length, 1, &tmp_error);
00929         if (tmp_error)
00930             {
00931             g_propagate_error (error, tmp_error);
00932             return FALSE;
00933             }
00934 
00935             xcf_check_error (xcf_seek_end (info, error));
00936         }
00937     }
00938     break;
00939 
00940     case PROP_UNIT:
00941     {
00942     Q_INT32 unit;
00943 
00944     unit = va_arg (args, Q_INT32);
00945 
00946     size = 4;
00947 
00948         xcf_write_prop_type_check_error (info, prop_type);
00949     xcf_write_int32_check_error (info, &size, 1);
00950     xcf_write_int32_check_error (info, &unit, 1);
00951     }
00952     break;
00953 
00954     case PROP_PATHS:
00955     {
00956     Q_INT32 base, length;
00957     glong   pos;
00958 
00959         xcf_write_prop_type_check_error (info, prop_type);
00960 
00961         /* because we don't know how much room the paths list will take
00962          * we save the file position and write the length later
00963          */
00964         pos = info->cp;
00965         xcf_write_int32_check_error (info, &length, 1);
00966 
00967         base = info->cp;
00968 
00969         xcf_check_error (xcf_save_old_paths (info, gimage, error));
00970 
00971         length = info->cp - base;
00972 
00973         /* go back to the saved position and write the length */
00974         xcf_check_error (xcf_seek_pos (info, pos, error));
00975         xcf_write_int32 (info->fp, &length, 1, &tmp_error);
00976         if (tmp_error)
00977         {
00978             g_propagate_error (error, tmp_error);
00979             return FALSE;
00980         }
00981 
00982         xcf_check_error (xcf_seek_end (info, error));
00983     }
00984     break;
00985 
00986     case PROP_USER_UNIT:
00987     {
00988     GimpUnit     unit;
00989     const QCString *unit_strings[5];
00990     float       factor;
00991     Q_INT32      digits;
00992 
00993     unit = va_arg (args, Q_INT32);
00994 
00995     /* write the entire unit definition */
00996     unit_strings[0] = _gimp_unit_get_identifier (gimage->gimp, unit);
00997     factor          = _gimp_unit_get_factor (gimage->gimp, unit);
00998     digits          = _gimp_unit_get_digits (gimage->gimp, unit);
00999     unit_strings[1] = _gimp_unit_get_symbol (gimage->gimp, unit);
01000     unit_strings[2] = _gimp_unit_get_abbreviation (gimage->gimp, unit);
01001     unit_strings[3] = _gimp_unit_get_singular (gimage->gimp, unit);
01002     unit_strings[4] = _gimp_unit_get_plural (gimage->gimp, unit);
01003 
01004     size =
01005             2 * 4 +
01006             strlen (unit_strings[0]) ? strlen (unit_strings[0]) + 5 : 4 +
01007             strlen (unit_strings[1]) ? strlen (unit_strings[1]) + 5 : 4 +
01008             strlen (unit_strings[2]) ? strlen (unit_strings[2]) + 5 : 4 +
01009             strlen (unit_strings[3]) ? strlen (unit_strings[3]) + 5 : 4 +
01010             strlen (unit_strings[4]) ? strlen (unit_strings[4]) + 5 : 4;
01011 
01012         xcf_write_prop_type_check_error (info, prop_type);
01013     xcf_write_int32_check_error (info, &size, 1);
01014     xcf_write_float_check_error (info, &factor, 1);
01015     xcf_write_int32_check_error (info, &digits, 1);
01016     xcf_write_string_check_error (info, (QCString **) unit_strings, 5);
01017     }
01018     break;
01019 
01020     case PROP_VECTORS:
01021     {
01022     Q_INT32 base, length;
01023     glong   pos;
01024 
01025         xcf_write_prop_type_check_error (info, prop_type);
01026 
01027         /* because we don't know how much room the paths list will take
01028          * we save the file position and write the length later
01029          */
01030         pos = info->cp;
01031         xcf_write_int32_check_error (info, &length, 1);
01032 
01033         base = info->cp;
01034 
01035         xcf_check_error (xcf_save_vectors (info, gimage, error));
01036 
01037         length = info->cp - base;
01038 
01039         /* go back to the saved position and write the length */
01040         xcf_check_error (xcf_seek_pos (info, pos, error));
01041         xcf_write_int32 (info->fp, &length, 1, &tmp_error);
01042         if (tmp_error)
01043         {
01044             g_propagate_error (error, tmp_error);
01045             return FALSE;
01046         }
01047 
01048         xcf_check_error (xcf_seek_end (info, error));
01049     }
01050     break;
01051 
01052     case PROP_TEXT_LAYER_FLAGS:
01053     {
01054     Q_INT32 flags;
01055 
01056     flags = va_arg (args, Q_INT32);
01057     size = 4;
01058 
01059         xcf_write_prop_type_check_error (info, prop_type);
01060     xcf_write_int32_check_error (info, &size, 1);
01061     xcf_write_int32_check_error (info, &flags, 1);
01062     }
01063     break;
01064     }
01065 
01066     va_end (args);
01067 
01068     return TRUE;
01069 }
01070 
01071 static bool
01072 xcf_save_layer (XcfInfo   *info,
01073         KisImage *gimage,
01074         KisLayer *layer,
01075         GError   **error)
01076 {
01077     Q_INT32 saved_pos;
01078     Q_INT32 offset;
01079 
01080     GError *tmp_error = NULL;
01081 
01082     /* check and see if this is the drawable that the floating
01083      *  selection is attached to.
01084      */
01085     if (GIMP_DRAWABLE (layer) == info->floating_sel_drawable)
01086     {
01087         saved_pos = info->cp;
01088         xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
01089         xcf_write_int32_check_error (info, &saved_pos, 1);
01090         xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01091     }
01092 
01093     /* write out the width, height and image type information for the layer */
01094     xcf_write_int32_check_error (info,
01095                                  (Q_INT32 *) &GIMP_ITEM (layer)->width, 1);
01096     xcf_write_int32_check_error (info,
01097                                  (Q_INT32 *) &GIMP_ITEM (layer)->height, 1);
01098     xcf_write_int32_check_error (info,
01099                                  (Q_INT32 *) &GIMP_DRAWABLE (layer)->type, 1);
01100 
01101     /* write out the layers name */
01102     xcf_write_string_check_error (info, &GIMP_OBJECT (layer)->name, 1);
01103 
01104     /* write out the layer properties */
01105     xcf_save_layer_props (info, gimage, layer, error);
01106 
01107     /* save the current position which is where the hierarchy offset
01108      *  will be stored.
01109      */
01110     saved_pos = info->cp;
01111 
01112     /* write out the layer tile hierarchy */
01113     xcf_check_error (xcf_seek_pos (info, info->cp + 8, error));
01114     offset = info->cp;
01115 
01116     xcf_check_error (xcf_save_hierarchy (info,
01117                                          GIMP_DRAWABLE(layer)->tiles, error));
01118 
01119     xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01120     xcf_write_int32_check_error (info, &offset, 1);
01121     saved_pos = info->cp;
01122 
01123     /* write out the layer mask */
01124     if (layer->mask)
01125     {
01126         xcf_check_error (xcf_seek_end (info, error));
01127         offset = info->cp;
01128 
01129         xcf_check_error (xcf_save_channel (info,
01130                                            gimage, GIMP_CHANNEL(layer->mask),
01131                                            error));
01132     }
01133     else
01134         offset = 0;
01135 
01136     xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01137     xcf_write_int32_check_error (info, &offset, 1);
01138 
01139     return TRUE;
01140 }
01141 
01142 static bool
01143 xcf_save_channel (XcfInfo      *info,
01144           KisImage    *gimage,
01145           GimpChannel  *channel,
01146           GError      **error)
01147 {
01148     Q_INT32 saved_pos;
01149     Q_INT32 offset;
01150 
01151     GError *tmp_error = NULL;
01152 
01153     /* check and see if this is the drawable that the floating
01154      *  selection is attached to.
01155      */
01156     if (GIMP_DRAWABLE (channel) == info->floating_sel_drawable)
01157     {
01158         saved_pos = info->cp;
01159         xcf_check_error (xcf_seek_pos (info, info->floating_sel_offset, error));
01160         xcf_write_int32_check_error (info, &saved_pos, 1);
01161         xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01162     }
01163 
01164     /* write out the width and height information for the channel */
01165     xcf_write_int32_check_error (info,
01166                                  (Q_INT32 *) &GIMP_ITEM (channel)->width, 1);
01167     xcf_write_int32_check_error (info,
01168                                  (Q_INT32 *) &GIMP_ITEM (channel)->height, 1);
01169 
01170     /* write out the channels name */
01171     xcf_write_string_check_error (info, &GIMP_OBJECT (channel)->name, 1);
01172 
01173     /* write out the channel properties */
01174     xcf_save_channel_props (info, gimage, channel, error);
01175 
01176     /* save the current position which is where the hierarchy offset
01177      *  will be stored.
01178      */
01179     saved_pos = info->cp;
01180 
01181     /* write out the channel tile hierarchy */
01182     xcf_check_error (xcf_seek_pos (info, info->cp + 4, error));
01183     offset = info->cp;
01184 
01185     xcf_check_error (xcf_save_hierarchy (info,
01186                                          GIMP_DRAWABLE (channel)->tiles, error));
01187 
01188     xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01189     xcf_write_int32_check_error (info, &offset, 1);
01190     saved_pos = info->cp;
01191 
01192     return TRUE;
01193 }
01194 
01195 static Q_INT32
01196 xcf_calc_levels (Q_INT32 size,
01197          Q_INT32 tile_size)
01198 {
01199     int levels;
01200 
01201     levels = 1;
01202     while (size > tile_size)
01203     {
01204         size /= 2;
01205         levels += 1;
01206     }
01207 
01208     return levels;
01209 }
01210 
01211 
01212 static bool
01213 xcf_save_hierarchy (XcfInfo     *info,
01214             TileManager *tiles,
01215             GError     **error)
01216 {
01217     Q_INT32 saved_pos;
01218     Q_INT32 offset;
01219     Q_INT32 width;
01220     Q_INT32 height;
01221     Q_INT32 bpp;
01222     Q_INT32    i;
01223     Q_INT32    nlevels;
01224     Q_INT32    tmp1, tmp2;
01225 
01226     GError *tmp_error = NULL;
01227 
01228     width  = tile_manager_width (tiles);
01229     height = tile_manager_height (tiles);
01230     bpp    = tile_manager_bpp (tiles);
01231 
01232     xcf_write_int32_check_error (info, (Q_INT32 *) &width, 1);
01233     xcf_write_int32_check_error (info, (Q_INT32 *) &height, 1);
01234     xcf_write_int32_check_error (info, (Q_INT32 *) &bpp, 1);
01235 
01236     saved_pos = info->cp;
01237 
01238     tmp1 = xcf_calc_levels (width, TILE_WIDTH);
01239     tmp2 = xcf_calc_levels (height, TILE_HEIGHT);
01240     nlevels = MAX (tmp1, tmp2);
01241 
01242     xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
01243 
01244     for (i = 0; i < nlevels; i++)
01245     {
01246         offset = info->cp;
01247 
01248         if (i == 0)
01249     {
01250             /* write out the level. */
01251             xcf_check_error (xcf_save_level (info, tiles, error));
01252     }
01253         else
01254     {
01255             /* fake an empty level */
01256             tmp1 = 0;
01257             width  /= 2;
01258             height /= 2;
01259             xcf_write_int32_check_error (info, (Q_INT32 *) &width,  1);
01260             xcf_write_int32_check_error (info, (Q_INT32 *) &height, 1);
01261             xcf_write_int32_check_error (info, (Q_INT32 *) &tmp1,   1);
01262     }
01263 
01264         /* seek back to where we are to write out the next
01265          *  level offset and write it out.
01266          */
01267         xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01268         xcf_write_int32_check_error (info, &offset, 1);
01269 
01270         /* increment the location we are to write out the
01271          *  next offset.
01272          */
01273         saved_pos = info->cp;
01274 
01275         /* seek to the end of the file which is where
01276          *  we will write out the next level.
01277          */
01278         xcf_check_error (xcf_seek_end (info, error));
01279     }
01280 
01281     /* write out a '0' offset position to indicate the end
01282      *  of the level offsets.
01283      */
01284     offset = 0;
01285     xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01286     xcf_write_int32_check_error (info, &offset, 1);
01287 
01288     return TRUE;
01289 }
01290 
01291 static bool
01292 xcf_save_level (XcfInfo     *info,
01293         TileManager *level,
01294         GError     **error)
01295 {
01296     Q_INT32  saved_pos;
01297     Q_INT32  offset;
01298     Q_INT32  width;
01299     Q_INT32  height;
01300     Q_UINT32    ntiles;
01301     Q_INT32     i;
01302     guchar  *rlebuf;
01303 
01304     GError *tmp_error = NULL;
01305 
01306     width  = tile_manager_width (level);
01307     height = tile_manager_height (level);
01308 
01309     xcf_write_int32_check_error (info, (Q_INT32 *) &width, 1);
01310     xcf_write_int32_check_error (info, (Q_INT32 *) &height, 1);
01311 
01312     saved_pos = info->cp;
01313 
01314     /* allocate a temporary buffer to store the rle data before it is
01315        written to disk */
01316     rlebuf =
01317         g_malloc (TILE_WIDTH * TILE_HEIGHT * tile_manager_bpp (level) * 1.5);
01318 
01319     if (level->tiles)
01320     {
01321         ntiles = level->ntile_rows * level->ntile_cols;
01322         xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
01323 
01324         for (i = 0; i < ntiles; i++)
01325     {
01326             /* save the start offset of where we are writing
01327              *  out the next tile.
01328              */
01329             offset = info->cp;
01330 
01331             /* write out the tile. */
01332             switch (info->compression)
01333         {
01334         case COMPRESS_NONE:
01335                 xcf_check_error(xcf_save_tile (info, level->tiles[i], error));
01336                 break;
01337         case COMPRESS_RLE:
01338                 xcf_check_error (xcf_save_tile_rle (info, level->tiles[i],
01339                                                     rlebuf, error));
01340                 break;
01341         case COMPRESS_ZLIB:
01342                 g_error ("xcf: zlib compression unimplemented");
01343                 break;
01344         case COMPRESS_FRACTAL:
01345                 g_error ("xcf: fractal compression unimplemented");
01346                 break;
01347         }
01348 
01349             /* seek back to where we are to write out the next
01350              *  tile offset and write it out.
01351              */
01352             xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01353             xcf_write_int32_check_error (info, &offset, 1);
01354 
01355             /* increment the location we are to write out the
01356              *  next offset.
01357              */
01358             saved_pos = info->cp;
01359 
01360             /* seek to the end of the file which is where
01361              *  we will write out the next tile.
01362              */
01363             xcf_check_error (xcf_seek_end (info, error));
01364     }
01365     }
01366 
01367     g_free (rlebuf);
01368 
01369     /* write out a '0' offset position to indicate the end
01370      *  of the level offsets.
01371      */
01372     offset = 0;
01373     xcf_check_error (xcf_seek_pos (info, saved_pos, error));
01374     xcf_write_int32_check_error (info, &offset, 1);
01375 
01376     return TRUE;
01377 
01378 }
01379 
01380 static bool
01381 xcf_save_tile (XcfInfo  *info,
01382            Tile     *tile,
01383            GError  **error)
01384 {
01385     GError *tmp_error = NULL;
01386 
01387     tile_lock (tile);
01388     xcf_write_int8_check_error (info, tile_data_pointer (tile, 0, 0),
01389                                 tile_size (tile));
01390     tile_release (tile, FALSE);
01391 
01392     return TRUE;
01393 }
01394 
01395 static bool
01396 xcf_save_tile_rle (XcfInfo  *info,
01397            Tile     *tile,
01398            guchar   *rlebuf,
01399            GError  **error)
01400 {
01401     guchar *data, *t;
01402     unsigned int last;
01403     Q_INT32 state;
01404     Q_INT32 length;
01405     Q_INT32 count;
01406     Q_INT32 size;
01407     Q_INT32 bpp;
01408     Q_INT32 i, j;
01409     Q_INT32 len = 0;
01410 
01411     GError *tmp_error = NULL;
01412 
01413     tile_lock (tile);
01414 
01415     bpp = tile_bpp (tile);
01416 
01417     for (i = 0; i < bpp; i++)
01418     {
01419         data = (guchar*) tile_data_pointer (tile, 0, 0) + i;
01420 
01421         state = 0;
01422         length = 0;
01423         count = 0;
01424         size = tile_ewidth(tile) * tile_eheight(tile);
01425         last = -1;
01426 
01427         while (size > 0)
01428     {
01429             switch (state)
01430         {
01431         case 0:
01432                 /* in state 0 we try to find a long sequence of
01433                  *  matching values.
01434                  */
01435                 if ((length == 32768) ||
01436                     ((size - length) <= 0) ||
01437                     ((length > 1) && (last != *data)))
01438         {
01439                     count += length;
01440                     if (length >= 128)
01441             {
01442                         rlebuf[len++] = 127;
01443                         rlebuf[len++] = (length >> 8);
01444                         rlebuf[len++] = length & 0x00FF;
01445                         rlebuf[len++] = last;
01446             }
01447                     else
01448             {
01449                         rlebuf[len++] = length - 1;
01450                         rlebuf[len++] = last;
01451             }
01452                     size -= length;
01453                     length = 0;
01454         }
01455                 else if ((length == 1) && (last != *data))
01456                     state = 1;
01457                 break;
01458 
01459         case 1:
01460                 /* in state 1 we try and find a long sequence of
01461                  *  non-matching values.
01462                  */
01463                 if ((length == 32768) ||
01464                     ((size - length) == 0) ||
01465                     ((length > 0) && (last == *data) &&
01466                      ((size - length) == 1 || last == data[bpp])))
01467         {
01468                     count += length;
01469                     state = 0;
01470 
01471                     if (length >= 128)
01472             {
01473                         rlebuf[len++] = 255 - 127;
01474                         rlebuf[len++] = (length >> 8);
01475                         rlebuf[len++] = length & 0x00FF;
01476             }
01477                     else
01478             {
01479                         rlebuf[len++] = 255 - (length - 1);
01480             }
01481 
01482                     t = data - length * bpp;
01483                     for (j = 0; j < length; j++)
01484             {
01485                         rlebuf[len++] = *t;
01486                         t += bpp;
01487             }
01488 
01489                     size -= length;
01490                     length = 0;
01491         }
01492                 break;
01493         }
01494 
01495             if (size > 0) {
01496                 length += 1;
01497                 last = *data;
01498                 data += bpp;
01499             }
01500     }
01501 
01502         if (count != (tile_ewidth (tile) * tile_eheight (tile)))
01503             g_message ("xcf: uh oh! xcf rle tile saving error: %d", count);
01504     }
01505     xcf_write_int8_check_error (info, rlebuf, len);
01506     tile_release (tile, FALSE);
01507 
01508     return TRUE;
01509 }
01510 
01511 static bool
01512 xcf_save_parasite (XcfInfo       *info,
01513                    KisAnnotation  *parasite,
01514                    GError       **error)
01515 {
01516     if (gimp_parasite_is_persistent (parasite))
01517     {
01518         GError *tmp_error = NULL;
01519 
01520         xcf_write_string_check_error (info, &parasite->name,  1);
01521         xcf_write_int32_check_error  (info, &parasite->flags, 1);
01522         xcf_write_int32_check_error  (info, &parasite->size,  1);
01523         xcf_write_int8_check_error   (info, parasite->data, parasite->size);
01524     }
01525 
01526     return TRUE;
01527 }
01528 
01529 typedef struct
01530 {
01531     XcfInfo *info;
01532     GError  *error;
01533 } XcfParasiteData;
01534 
01535 static void
01536 xcf_save_parasite_func (QCString           *key,
01537                         KisAnnotation    *parasite,
01538                         XcfParasiteData *data)
01539 {
01540     if (! data->error)
01541         xcf_save_parasite (data->info, parasite, &data->error);
01542 }
01543 
01544 static bool
01545 xcf_save_parasite_list (XcfInfo           *info,
01546                         KisAnnotationList  *list,
01547                         GError           **error)
01548 {
01549     XcfParasiteData data;
01550 
01551     data.info  = info;
01552     data.error = NULL;
01553 
01554     gimp_parasite_list_foreach (list, (GHFunc) xcf_save_parasite_func, &data);
01555 
01556     if (data.error)
01557     {
01558         g_propagate_error (error, data.error);
01559         return FALSE;
01560     }
01561 
01562     return TRUE;
01563 }
01564 
01565 static bool
01566 xcf_save_old_paths (XcfInfo    *info,
01567                     KisImage  *gimage,
01568                     GError    **error)
01569 {
01570     GimpVectors *active_vectors;
01571     Q_INT32      num_paths;
01572     Q_INT32      active_index = 0;
01573     GList       *list;
01574     GError      *tmp_error = NULL;
01575 
01576     /* Write out the following:-
01577      *
01578      * last_selected_row (Q_INT32)
01579      * number_of_paths (Q_INT32)
01580      *
01581      * then each path:-
01582      */
01583 
01584     num_paths = gimp_container_num_children (gimage->vectors);
01585 
01586     active_vectors = gimp_image_get_active_vectors (gimage);
01587 
01588     if (active_vectors)
01589         active_index = gimp_container_get_child_index (gimage->vectors,
01590                                                        GIMP_OBJECT (active_vectors));
01591 
01592     xcf_write_int32_check_error (info, &active_index, 1);
01593     xcf_write_int32_check_error (info, &num_paths,    1);
01594 
01595     for (list = GIMP_LIST (gimage->vectors)->list;
01596          list;
01597          list = g_list_next (list))
01598     {
01599         GimpVectors            *vectors = list->data;
01600         QCString                  *name;
01601         Q_INT32                 locked;
01602         Q_UINT8                  state;
01603         Q_INT32                 version;
01604         Q_INT32                 pathtype;
01605         Q_INT32                 tattoo;
01606         GimpVectorsCompatPoint *points;
01607         Q_INT3232                  num_points;
01608         Q_INT3232                  closed;
01609         Q_INT32                    i;
01610 
01611         /*
01612          * name (string)
01613          * locked (Q_INT32)
01614          * state (QCString)
01615          * closed (Q_INT32)
01616          * number points (Q_INT32)
01617          * version (Q_INT32)
01618          * pathtype (Q_INT32)
01619          * tattoo (Q_INT32)
01620          * then each point.
01621          */
01622 
01623         points = gimp_vectors_compat_get_points (vectors, &num_points, &closed);
01624 
01625         /* if no points are generated because of a faulty path we should
01626          * skip saving the path - this is unfortunately impossible, because
01627          * we already saved the number of paths and I wont start seeking
01628          * around to fix that cruft  */
01629 
01630         name     = (QCString *) gimp_object_get_name (GIMP_OBJECT (vectors));
01631         locked   = gimp_item_get_linked (GIMP_ITEM (vectors));
01632         state    = closed ? 4 : 2;  /* EDIT : ADD  (editing state, 1.2 compat) */
01633         version  = 3;
01634         pathtype = 1;  /* BEZIER  (1.2 compat) */
01635         tattoo   = gimp_item_get_tattoo (GIMP_ITEM (vectors));
01636 
01637         xcf_write_string_check_error (info, &name,       1);
01638         xcf_write_int32_check_error  (info, &locked,     1);
01639         xcf_write_int8_check_error   (info, &state,      1);
01640         xcf_write_int32_check_error  (info, &closed,     1);
01641         xcf_write_int32_check_error  (info, &num_points, 1);
01642         xcf_write_int32_check_error  (info, &version,    1);
01643         xcf_write_int32_check_error  (info, &pathtype,   1);
01644         xcf_write_int32_check_error  (info, &tattoo,     1);
01645 
01646         for (i = 0; i < num_points; i++)
01647         {
01648             float x;
01649             float y;
01650 
01651             x = points[i].x;
01652             y = points[i].y;
01653 
01654             /*
01655              * type (Q_INT32)
01656              * x (float)
01657              * y (float)
01658              */
01659 
01660             xcf_write_int32_check_error (info, &points[i].type, 1);
01661             xcf_write_float_check_error (info, &x,              1);
01662             xcf_write_float_check_error (info, &y,              1);
01663         }
01664 
01665         g_free (points);
01666     }
01667 
01668     return TRUE;
01669 }
01670 
01671 static bool
01672 xcf_save_vectors (XcfInfo    *info,
01673                   KisImage  *gimage,
01674                   GError    **error)
01675 {
01676     GimpVectors *active_vectors;
01677     Q_INT32      version      = 1;
01678     Q_INT32      active_index = 0;
01679     Q_INT32      num_paths;
01680     GList       *list;
01681     GList       *stroke_list;
01682     GError      *tmp_error = NULL;
01683 
01684     /* Write out the following:-
01685      *
01686      * version (Q_INT32)
01687      * active_index (Q_INT32)
01688      * num_paths (Q_INT32)
01689      *
01690      * then each path:-
01691      */
01692 
01693     active_vectors = gimp_image_get_active_vectors (gimage);
01694 
01695     if (active_vectors)
01696         active_index = gimp_container_get_child_index (gimage->vectors,
01697                                                        GIMP_OBJECT (active_vectors));
01698 
01699     num_paths = gimp_container_num_children (gimage->vectors);
01700 
01701     xcf_write_int32_check_error (info, &version,      1);
01702     xcf_write_int32_check_error (info, &active_index, 1);
01703     xcf_write_int32_check_error (info, &num_paths,    1);
01704 
01705     for (list = GIMP_LIST (gimage->vectors)->list;
01706          list;
01707          list = g_list_next (list))
01708     {
01709         GimpVectors      *vectors = list->data;
01710         KisAnnotationList *parasites;
01711         QCString            *name;
01712         Q_INT32           tattoo;
01713         Q_INT32           visible;
01714         Q_INT32           linked;
01715         Q_INT32           num_parasites;
01716         Q_INT32           num_strokes;
01717 
01718         /*
01719          * name (string)
01720          * tattoo (Q_INT32)
01721          * visible (Q_INT32)
01722          * linked (Q_INT32)
01723          * num_parasites (Q_INT32)
01724          * num_strokes (Q_INT32)
01725          *
01726          * then each parasite
01727          * then each stroke
01728          */
01729 
01730         parasites = GIMP_ITEM (vectors)->parasites;
01731 
01732         name          = (QCString *) gimp_object_get_name (GIMP_OBJECT (vectors));
01733         visible       = gimp_item_get_visible (GIMP_ITEM (vectors));
01734         linked        = gimp_item_get_linked (GIMP_ITEM (vectors));
01735         tattoo        = gimp_item_get_tattoo (GIMP_ITEM (vectors));
01736         num_parasites = gimp_parasite_list_persistent_length (parasites);
01737         num_strokes   = g_list_length (vectors->strokes);
01738 
01739         xcf_write_string_check_error (info, &name,          1);
01740         xcf_write_int32_check_error  (info, &tattoo,        1);
01741         xcf_write_int32_check_error  (info, &visible,       1);
01742         xcf_write_int32_check_error  (info, &linked,        1);
01743         xcf_write_int32_check_error  (info, &num_parasites, 1);
01744         xcf_write_int32_check_error  (info, &num_strokes,   1);
01745 
01746         xcf_check_error (xcf_save_parasite_list (info, parasites, error));
01747 
01748         for (stroke_list = g_list_first (vectors->strokes);
01749              stroke_list;
01750              stroke_list = g_list_next (stroke_list))
01751         {
01752             GimpStroke *stroke;
01753             Q_INT32     stroke_type;
01754             Q_INT32     closed;
01755             Q_INT32     num_axes;
01756             GArray     *control_points;
01757             Q_INT32        i;
01758 
01759             Q_INT32     type;
01760             float      coords[6];
01761 
01762             /*
01763              * stroke_type (Q_INT32)
01764              * closed (Q_INT32)
01765              * num_axes (Q_INT32)
01766              * num_control_points (Q_INT32)
01767              *
01768              * then each control point.
01769              */
01770 
01771             stroke = GIMP_STROKE (stroke_list->data);
01772 
01773             if (GIMP_IS_BEZIER_STROKE (stroke))
01774             {
01775                 stroke_type = XCF_STROKETYPE_BEZIER_STROKE;
01776                 num_axes = 2;   /* hardcoded, might be increased later */
01777             }
01778             else
01779             {
01780                 g_printerr ("Skipping unknown stroke type!\n");
01781                 continue;
01782             }
01783 
01784             control_points = gimp_stroke_control_points_get (stroke, &closed);
01785 
01786             xcf_write_int32_check_error (info, &stroke_type,         1);
01787             xcf_write_int32_check_error (info, &closed,              1);
01788             xcf_write_int32_check_error (info, &num_axes,            1);
01789             xcf_write_int32_check_error (info, &control_points->len, 1);
01790 
01791             for (i = 0; i < control_points->len; i++)
01792             {
01793                 GimpAnchor *anchor;
01794 
01795                 anchor = & (g_array_index (control_points, GimpAnchor, i));
01796 
01797                 type      = anchor->type;
01798                 coords[0] = anchor->position.x;
01799                 coords[1] = anchor->position.y;
01800                 coords[2] = anchor->position.pressure;
01801                 coords[3] = anchor->position.xtilt;
01802                 coords[4] = anchor->position.ytilt;
01803                 coords[5] = anchor->position.wheel;
01804 
01805                 /*
01806                  * type (Q_INT32)
01807                  *
01808                  * the first num_axis elements of:
01809                  * [0] x (float)
01810                  * [1] y (float)
01811                  * [2] pressure (float)
01812                  * [3] xtilt (float)
01813                  * [4] ytilt (float)
01814                  * [5] wheel (float)
01815                  */
01816 
01817                 xcf_write_int32_check_error (info, &type, 1);
01818                 xcf_write_float_check_error (info, coords, num_axes);
01819             }
01820 
01821             g_array_free (control_points, TRUE);
01822         }
01823     }
01824 
01825     return TRUE;
01826 }
KDE Home | KDE Accessibility Home | Description of Access Keys