filters

xcf-load.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>     /* strcmp, memcmp */
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 "config/gimpcoreconfig.h"
00036 
00037 //#include "core/gimp.h"
00038 //#include "core/gimpcontainer.h"
00039 //#include "core/gimpdrawable.h"
00040 //#include "core/gimpgrid.h"
00041 //#include "core/gimpimage.h"
00042 //#include "core/gimpimage-grid.h"
00043 //#include "core/gimpimage-guides.h"
00044 //#include "core/gimplayer.h"
00045 //#include "core/gimplayer-floating-sel.h"
00046 //#include "core/gimplayermask.h"
00047 //#include "core/gimpparasitelist.h"
00048 //#include "core/gimpselection.h"
00049 //#include "core/gimptemplate.h"
00050 //#include "core/gimpunit.h"
00051 
00052 //#include "text/gimptextlayer.h"
00053 //#include "text/gimptextlayer-xcf.h"
00054 
00055 //#include "vectors/gimpanchor.h"
00056 //#include "vectors/gimpstroke.h"
00057 //#include "vectors/gimpbezierstroke.h"
00058 //#include "vectors/gimpvectors.h"
00059 //#include "vectors/gimpvectors-compat.h"
00060 
00061 #include "xcf-private.h"
00062 #include "xcf-load.h"
00063 #include "xcf-read.h"
00064 #include "xcf-seek.h"
00065 
00066 //#include "gimp-intl.h"
00067 
00068 static bool xcf_load_image_props (XcfInfo * info, KisImage * gimage);
00069 static bool xcf_load_layer_props (XcfInfo * info,
00070                   KisImage * gimage,
00071                   KisLayer * layer,
00072                   bool * apply_mask,
00073                   bool * edit_mask,
00074                   bool * show_mask,
00075                   Q_INT32 * text_layer_flags);
00076 static bool xcf_load_channel_props (XcfInfo * info,
00077                     KisImage * gimage,
00078                     GimpChannel ** channel);
00079 static bool xcf_load_prop (XcfInfo * info,
00080                PropType * prop_type, Q_INT32 * prop_size);
00081 static KisLayer *xcf_load_layer (XcfInfo * info, KisImage * gimage);
00082 //static GimpChannel   * xcf_load_channel       (XcfInfo      *info,
00083 //                                               KisImage    *gimage);
00084 //static GimpLayerMask * xcf_load_layer_mask    (XcfInfo      *info,
00085 //                                               KisImage    *gimage);
00086 static bool xcf_load_hierarchy (XcfInfo * info, TileManager * tiles);
00087 static bool xcf_load_level (XcfInfo * info, TileManager * tiles);
00088 static bool xcf_load_tile (XcfInfo * info, Tile * tile);
00089 static bool xcf_load_tile_rle (XcfInfo * info,
00090                    Tile * tile, Q_INT32 data_length);
00091 //static GimpParasite  * xcf_load_parasite      (XcfInfo      *info);
00092 static bool xcf_load_old_paths (XcfInfo * info, KisImage * gimage);
00093 static bool xcf_load_old_path (XcfInfo * info, KisImage * gimage);
00094 static bool xcf_load_vectors (XcfInfo * info, KisImage * gimage);
00095 static bool xcf_load_vector (XcfInfo * info, KisImage * gimage);
00096 
00097 #ifdef SWAP_FROM_FILE
00098 static bool xcf_swap_func (Q_INT32 fd,
00099                Tile * tile, Q_INT32 cmd, gpointer user_data);
00100 #endif
00101 
00102 
00103 KisImage *
00104 xcf_load_image (XcfInfo * info)
00105 {
00106     KisImage *gimage;
00107     KisLayer *layer;
00108     //GimpChannel  *channel;
00109     //KisAnnotation *parasite;
00110     Q_INT32 saved_pos;
00111     Q_INT32 offset;
00112     Q_INT32 width;
00113     Q_INT32 height;
00114     Q_INT32 image_type;
00115     Q_INT32 num_successful_elements = 0;
00116 
00117     /* read in the image width, height and type */
00118     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & width, 1);
00119     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & height, 1);
00120     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & image_type, 1);
00121 
00122     gimage = gimp_create_image (gimp, width, height, image_type, FALSE);
00123 
00124     gimp_image_undo_disable (gimage);
00125 
00126     /* read the image properties */
00127     if (!xcf_load_image_props (info, gimage))
00128         goto hard_error;
00129 
00130     /* check for a GimpGrid parasite */
00131     parasite = gimp_image_parasite_find (GIMP_IMAGE (gimage),
00132                                          gimp_grid_parasite_name ());
00133     if (parasite)
00134     {
00135         GimpGrid *grid = gimp_grid_from_parasite (parasite);
00136 
00137         if (grid)
00138     {
00139             gimp_parasite_list_remove (GIMP_IMAGE (gimage)->parasites,
00140                                        gimp_parasite_name (parasite));
00141 
00142             gimp_image_set_grid (GIMP_IMAGE (gimage), grid, FALSE);
00143     }
00144     }
00145 
00146     while (TRUE)
00147     {
00148         /* read in the offset of the next layer */
00149         info->cp += xcf_read_int32 (info->fp, &offset, 1);
00150 
00151         /* if the offset is 0 then we are at the end
00152          *  of the layer list.
00153          */
00154         if (offset == 0)
00155             break;
00156 
00157         /* save the current position as it is where the
00158          *  next layer offset is stored.
00159          */
00160         saved_pos = info->cp;
00161 
00162         /* seek to the layer offset */
00163         if (!xcf_seek_pos (info, offset, NULL))
00164             goto error;
00165 
00166         /* read in the layer */
00167         layer = xcf_load_layer (info, gimage);
00168         if (!layer)
00169             goto error;
00170 
00171         num_successful_elements++;
00172 
00173         /* add the layer to the image if its not the floating selection */
00174         if (layer != info->floating_sel)
00175             gimp_image_add_layer (gimage, layer,
00176                                   gimp_container_num_children (gimage->layers));
00177 
00178         /* restore the saved position so we'll be ready to
00179          *  read the next offset.
00180          */
00181         if (!xcf_seek_pos (info, saved_pos, NULL))
00182             goto error;
00183     }
00184 
00185     while (TRUE)
00186     {
00187         /* read in the offset of the next channel */
00188         info->cp += xcf_read_int32 (info->fp, &offset, 1);
00189 
00190         /* if the offset is 0 then we are at the end
00191          *  of the channel list.
00192          */
00193         if (offset == 0)
00194             break;
00195 
00196         /* save the current position as it is where the
00197          *  next channel offset is stored.
00198          */
00199         saved_pos = info->cp;
00200 
00201         /* seek to the channel offset */
00202         if (!xcf_seek_pos (info, offset, NULL))
00203             goto error;
00204 
00205         /* read in the layer */
00206         channel = xcf_load_channel (info, gimage);
00207         if (!channel)
00208             goto error;
00209 
00210         num_successful_elements++;
00211 
00212         /* add the channel to the image if its not the selection */
00213         if (channel != gimage->selection_mask)
00214             gimp_image_add_channel (gimage, channel, -1);
00215 
00216         /* restore the saved position so we'll be ready to
00217          *  read the next offset.
00218          */
00219         if (!xcf_seek_pos (info, saved_pos, NULL))
00220             goto error;
00221     }
00222 
00223     if (info->floating_sel && info->floating_sel_drawable)
00224         floating_sel_attach (info->floating_sel, info->floating_sel_drawable);
00225 
00226     if (info->active_layer)
00227         gimp_image_set_active_layer (gimage, info->active_layer);
00228 
00229     if (info->active_channel)
00230         gimp_image_set_active_channel (gimage, info->active_channel);
00231 
00232     gimp_image_set_filename (gimage, info->filename);
00233 
00234     if (info->tattoo_state > 0)
00235         gimp_image_set_tattoo_state (gimage, info->tattoo_state);
00236 
00237     gimp_image_undo_enable (gimage);
00238 
00239     return gimage;
00240 
00241 error:
00242     if (num_successful_elements == 0)
00243         goto hard_error;
00244 
00245     g_message ("XCF: This file is corrupt!  I have loaded as much\n"
00246                "of it as I can, but it is incomplete.");
00247 
00248     gimp_image_undo_enable (gimage);
00249 
00250     return gimage;
00251 
00252 hard_error:
00253     g_message ("XCF: This file is corrupt!  I could not even\n"
00254                "salvage any partial image data from it.");
00255 
00256     g_object_unref (gimage);
00257 
00258     return NULL;
00259 }
00260 
00261 static bool
00262 xcf_load_image_props (XcfInfo * info, KisImage * gimage)
00263 {
00264     PropType prop_type;
00265     Q_INT32 prop_size;
00266 
00267     while (TRUE)
00268     {
00269         if (!xcf_load_prop (info, &prop_type, &prop_size))
00270             return FALSE;
00271 
00272         switch (prop_type)
00273     {
00274     case PROP_END:
00275             return TRUE;
00276 
00277     case PROP_COLORMAP:
00278             if (info->file_version == 0)
00279         {
00280                 Q_INT32 i;
00281 
00282                 g_message (_("XCF warning: version 0 of XCF file format\n"
00283                              "did not save indexed colormaps correctly.\n"
00284                              "Substituting grayscale map."));
00285                 info->cp +=
00286                     xcf_read_int32 (info->fp, (Q_INT32 *) & gimage->num_cols, 1);
00287                 gimage->cmap = g_new (guchar, gimage->num_cols * 3);
00288                 if (!xcf_seek_pos (info, info->cp + gimage->num_cols, NULL))
00289                     return FALSE;
00290 
00291                 for (i = 0; i < gimage->num_cols; i++)
00292         {
00293                     gimage->cmap[i * 3 + 0] = i;
00294                     gimage->cmap[i * 3 + 1] = i;
00295                     gimage->cmap[i * 3 + 2] = i;
00296         }
00297         }
00298             else
00299         {
00300                 info->cp +=
00301                     xcf_read_int32 (info->fp, (Q_INT32 *) & gimage->num_cols, 1);
00302                 gimage->cmap = g_new (guchar, gimage->num_cols * 3);
00303                 info->cp +=
00304                     xcf_read_int8 (info->fp,
00305                                    (Q_UINT8 *) gimage->cmap,
00306                                    gimage->num_cols * 3);
00307         }
00308 
00309             /* discard color map, if image is not indexed, this is just
00310              * sanity checking to make sure gimp doesn't end up with an
00311              * image state that is impossible.
00312              */
00313             if (gimp_image_base_type (gimage) != GIMP_INDEXED)
00314         {
00315                 g_free (gimage->cmap);
00316                 gimage->cmap = NULL;
00317                 gimage->num_cols = 0;
00318         }
00319             break;
00320 
00321     case PROP_COMPRESSION:
00322         {
00323         Q_UINT8 compression;
00324 
00325         info->cp +=
00326                 xcf_read_int8 (info->fp, (Q_UINT8 *) & compression, 1);
00327 
00328         if ((compression != COMPRESS_NONE) &&
00329         (compression != COMPRESS_RLE) &&
00330         (compression != COMPRESS_ZLIB) &&
00331         (compression != COMPRESS_FRACTAL))
00332             {
00333         g_message ("unknown compression type: %d", (int) compression);
00334         return FALSE;
00335             }
00336 
00337         info->compression = compression;
00338         }
00339         break;
00340 
00341     case PROP_GUIDES:
00342         {
00343         Q_INT3232 position;
00344         Q_INT328 orientation;
00345         Q_INT32 i, nguides;
00346 
00347         nguides = prop_size / (4 + 1);
00348         for (i = 0; i < nguides; i++)
00349             {
00350         info->cp +=
00351                     xcf_read_int32 (info->fp, (Q_INT32 *) & position, 1);
00352         info->cp +=
00353                     xcf_read_int8 (info->fp, (Q_UINT8 *) & orientation, 1);
00354 
00355         /*  skip -1 guides from old XCFs  */
00356         if (position < 0)
00357                     continue;
00358 
00359         switch (orientation)
00360                 {
00361                 case XCF_ORIENTATION_HORIZONTAL:
00362             gimp_image_add_hguide (gimage, position, FALSE);
00363             break;
00364 
00365                 case XCF_ORIENTATION_VERTICAL:
00366             gimp_image_add_vguide (gimage, position, FALSE);
00367             break;
00368 
00369                 default:
00370             g_message ("guide orientation out of range in XCF file");
00371             continue;
00372                 }
00373             }
00374 
00375         /*  this is silly as the order of guides doesn't really matter,
00376          *  but it restores the list to it's original order, which
00377          *  cannot be wrong  --Mitch
00378          */
00379         gimage->guides = g_list_reverse (gimage->guides);
00380         }
00381         break;
00382 
00383     case PROP_RESOLUTION:
00384         {
00385         float xres, yres;
00386 
00387         info->cp += xcf_read_float (info->fp, &xres, 1);
00388         info->cp += xcf_read_float (info->fp, &yres, 1);
00389         if (xres < GIMP_MIN_RESOLUTION || xres > GIMP_MAX_RESOLUTION ||
00390         yres < GIMP_MIN_RESOLUTION || yres > GIMP_MAX_RESOLUTION)
00391             {
00392         g_message ("Warning, resolution out of range in XCF file");
00393         xres = gimage->gimp->config->default_image->xresolution;
00394         yres = gimage->gimp->config->default_image->yresolution;
00395             }
00396         gimage->xresolution = xres;
00397         gimage->yresolution = yres;
00398         }
00399         break;
00400 
00401     case PROP_TATTOO:
00402         {
00403         info->cp += xcf_read_int32 (info->fp, &info->tattoo_state, 1);
00404         }
00405         break;
00406 
00407     case PROP_PARASITES:
00408         {
00409         glong base = info->cp;
00410         KisAnnotation *p;
00411 
00412         while (info->cp - base < prop_size)
00413             {
00414         p = xcf_load_parasite (info);
00415         gimp_image_parasite_attach (gimage, p);
00416         gimp_parasite_free (p);
00417             }
00418         if (info->cp - base != prop_size)
00419                 g_message ("Error while loading an image's parasites");
00420         }
00421         break;
00422 
00423     case PROP_UNIT:
00424         {
00425         Q_INT32 unit;
00426 
00427         info->cp += xcf_read_int32 (info->fp, &unit, 1);
00428 
00429         if ((unit <= GIMP_UNIT_PIXEL) ||
00430         (unit >=
00431          _gimp_unit_get_number_of_built_in_units (gimage->gimp)))
00432             {
00433         g_message ("Warning, unit out of range in XCF file, "
00434                "falling back to inches");
00435         unit = GIMP_UNIT_INCH;
00436             }
00437 
00438         gimage->resolution_unit = unit;
00439         }
00440         break;
00441 
00442     case PROP_PATHS:
00443             xcf_load_old_paths (info, gimage);
00444             break;
00445 
00446     case PROP_USER_UNIT:
00447         {
00448         QCString *unit_strings[5];
00449         float factor;
00450         Q_INT32 digits;
00451         GimpUnit unit;
00452         Q_INT32 num_units;
00453         Q_INT32 i;
00454 
00455         info->cp += xcf_read_float (info->fp, &factor, 1);
00456         info->cp += xcf_read_int32 (info->fp, &digits, 1);
00457         info->cp += xcf_read_string (info->fp, unit_strings, 5);
00458 
00459         for (i = 0; i < 5; i++)
00460                 if (unit_strings[i] == NULL)
00461                     unit_strings[i] = g_strdup ("");
00462 
00463         num_units = _gimp_unit_get_number_of_units (gimage->gimp);
00464 
00465         for (unit =
00466                      _gimp_unit_get_number_of_built_in_units (gimage->gimp);
00467          unit < num_units; unit++)
00468             {
00469         /* if the factor and the identifier match some unit
00470          * in unitrc, use the unitrc unit
00471          */
00472         if ((ABS (_gimp_unit_get_factor (gimage->gimp,
00473                          unit) - factor) < 1e-5) &&
00474             (strcmp (unit_strings[0],
00475                  _gimp_unit_get_identifier (gimage->gimp,
00476                             unit)) == 0))
00477                 {
00478             break;
00479                 }
00480             }
00481 
00482         /* no match */
00483         if (unit == num_units)
00484                 unit = _gimp_unit_new (gimage->gimp,
00485                                        unit_strings[0],
00486                                        factor,
00487                                        digits,
00488                                        unit_strings[1],
00489                                        unit_strings[2],
00490                                        unit_strings[3], unit_strings[4]);
00491 
00492         gimage->resolution_unit = unit;
00493 
00494         for (i = 0; i < 5; i++)
00495                 g_free (unit_strings[i]);
00496         }
00497         break;
00498 
00499     case PROP_VECTORS:
00500         {
00501         Q_INT32 base = info->cp;
00502 
00503         if (xcf_load_vectors (info, gimage))
00504             {
00505         if (base + prop_size != info->cp)
00506                 {
00507             g_warning
00508                         ("Mismatch in PROP_VECTORS size: skipping %d bytes.",
00509                          base + prop_size - info->cp);
00510             xcf_seek_pos (info, base + prop_size, NULL);
00511                 }
00512             }
00513         else
00514             {
00515         /* skip silently since we don't understand the format and
00516          * xcf_load_vectors already explained what was wrong
00517          */
00518         xcf_seek_pos (info, base + prop_size, NULL);
00519             }
00520         }
00521         break;
00522 
00523     default:
00524 #ifdef GIMP_UNSTABLE
00525             g_printerr ("unexpected/unknown image property: %d (skipping)",
00526                         prop_type);
00527 #endif
00528             {
00529                 Q_UINT8 buf[16];
00530                 Q_UINT32 amount;
00531 
00532                 while (prop_size > 0)
00533                 {
00534                     amount = MIN (16, prop_size);
00535                     info->cp += xcf_read_int8 (info->fp, buf, amount);
00536                     prop_size -= MIN (16, amount);
00537                 }
00538             }
00539             break;
00540     }
00541     }
00542 
00543     return FALSE;
00544 }
00545 
00546 static bool
00547 xcf_load_layer_props (XcfInfo * info,
00548               KisImage * gimage,
00549               KisLayer * layer,
00550               bool * apply_mask,
00551               bool * edit_mask,
00552               bool * show_mask, Q_INT32 * text_layer_flags)
00553 {
00554     PropType prop_type;
00555     Q_INT32 prop_size;
00556 
00557     while (TRUE)
00558     {
00559         if (!xcf_load_prop (info, &prop_type, &prop_size))
00560             return FALSE;
00561 
00562         switch (prop_type)
00563     {
00564     case PROP_END:
00565             return TRUE;
00566 
00567     case PROP_ACTIVE_LAYER:
00568             info->active_layer = layer;
00569             break;
00570 
00571     case PROP_FLOATING_SELECTION:
00572             info->floating_sel = layer;
00573             info->cp +=
00574                 xcf_read_int32 (info->fp,
00575                                 (Q_INT32 *) & info->floating_sel_offset, 1);
00576             break;
00577 
00578     case PROP_OPACITY:
00579         {
00580         Q_INT32 opacity;
00581 
00582         info->cp += xcf_read_int32 (info->fp, &opacity, 1);
00583         layer->opacity = CLAMP ((gdouble) opacity / 255.0,
00584                     GIMP_OPACITY_TRANSPARENT,
00585                     GIMP_OPACITY_OPAQUE);
00586         }
00587         break;
00588 
00589     case PROP_VISIBLE:
00590         {
00591         bool visible;
00592 
00593         info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & visible, 1);
00594         gimp_item_set_visible (GIMP_ITEM (layer),
00595                    visible ? TRUE : FALSE, FALSE);
00596         }
00597         break;
00598 
00599     case PROP_LINKED:
00600         {
00601         bool linked;
00602 
00603         info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & linked, 1);
00604         gimp_item_set_linked (GIMP_ITEM (layer),
00605                   linked ? TRUE : FALSE, FALSE);
00606         }
00607         break;
00608 
00609     case PROP_LOCK_ALPHA:
00610             info->cp +=
00611                 xcf_read_int32 (info->fp, (Q_INT32 *) & layer->lock_alpha, 1);
00612             break;
00613 
00614     case PROP_APPLY_MASK:
00615             info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) apply_mask, 1);
00616             break;
00617 
00618     case PROP_EDIT_MASK:
00619             info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) edit_mask, 1);
00620             break;
00621 
00622     case PROP_SHOW_MASK:
00623             info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) show_mask, 1);
00624             break;
00625 
00626     case PROP_OFFSETS:
00627             info->cp +=
00628                 xcf_read_int32 (info->fp,
00629                                 (Q_INT32 *) & GIMP_ITEM (layer)->offset_x, 1);
00630             info->cp +=
00631                 xcf_read_int32 (info->fp,
00632                                 (Q_INT32 *) & GIMP_ITEM (layer)->offset_y, 1);
00633             break;
00634 
00635     case PROP_MODE:
00636             info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & layer->mode, 1);
00637             break;
00638 
00639     case PROP_TATTOO:
00640             info->cp += xcf_read_int32 (info->fp,
00641                                         (Q_INT32 *) & GIMP_ITEM (layer)->tattoo,
00642                                         1);
00643             break;
00644 
00645     case PROP_PARASITES:
00646         {
00647         glong base = info->cp;
00648         KisAnnotation *p;
00649 
00650         while (info->cp - base < prop_size)
00651             {
00652         p = xcf_load_parasite (info);
00653         gimp_item_parasite_attach (GIMP_ITEM (layer), p);
00654         gimp_parasite_free (p);
00655             }
00656         if (info->cp - base != prop_size)
00657                 g_message ("Error while loading a layer's parasites");
00658         }
00659         break;
00660 
00661     case PROP_TEXT_LAYER_FLAGS:
00662             info->cp += xcf_read_int32 (info->fp, text_layer_flags, 1);
00663             break;
00664 
00665     default:
00666         {
00667         Q_UINT8 buf[16];
00668         Q_UINT32 amount;
00669 
00670 #ifdef GIMP_UNSTABLE
00671         g_printerr ("unexpected/unknown layer property: %d (skipping)",
00672             prop_type);
00673 #endif
00674         while (prop_size > 0)
00675             {
00676         amount = MIN (16, prop_size);
00677         info->cp += xcf_read_int8 (info->fp, buf, amount);
00678         prop_size -= MIN (16, amount);
00679             }
00680         }
00681         break;
00682     }
00683     }
00684 
00685     return FALSE;
00686 }
00687 
00688 static bool
00689 xcf_load_channel_props (XcfInfo * info,
00690             KisImage * gimage, GimpChannel ** channel)
00691 {
00692     PropType prop_type;
00693     Q_INT32 prop_size;
00694 
00695     while (TRUE)
00696     {
00697         if (!xcf_load_prop (info, &prop_type, &prop_size))
00698             return FALSE;
00699 
00700         switch (prop_type)
00701     {
00702     case PROP_END:
00703             return TRUE;
00704 
00705     case PROP_ACTIVE_CHANNEL:
00706             info->active_channel = *channel;
00707             break;
00708 
00709     case PROP_SELECTION:
00710             g_object_unref (gimage->selection_mask);
00711             gimage->selection_mask =
00712                 gimp_selection_new (gimage,
00713                                     gimp_item_width (GIMP_ITEM (*channel)),
00714                                     gimp_item_height (GIMP_ITEM (*channel)));
00715             g_object_ref (gimage->selection_mask);
00716             gimp_item_sink (GIMP_ITEM (gimage->selection_mask));
00717 
00718             tile_manager_unref (GIMP_DRAWABLE (gimage->selection_mask)->tiles);
00719             GIMP_DRAWABLE (gimage->selection_mask)->tiles =
00720                 GIMP_DRAWABLE (*channel)->tiles;
00721             GIMP_DRAWABLE (*channel)->tiles = NULL;
00722             g_object_unref (*channel);
00723             *channel = gimage->selection_mask;
00724             (*channel)->boundary_known = FALSE;
00725             (*channel)->bounds_known = FALSE;
00726             break;
00727 
00728     case PROP_OPACITY:
00729         {
00730         Q_INT32 opacity;
00731 
00732         info->cp += xcf_read_int32 (info->fp, &opacity, 1);
00733         (*channel)->color.a = opacity / 255.0;
00734         }
00735         break;
00736 
00737     case PROP_VISIBLE:
00738         {
00739         bool visible;
00740 
00741         info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & visible, 1);
00742         gimp_item_set_visible (GIMP_ITEM (*channel),
00743                    visible ? TRUE : FALSE, FALSE);
00744         }
00745         break;
00746 
00747     case PROP_LINKED:
00748         {
00749         bool linked;
00750 
00751         info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & linked, 1);
00752         gimp_item_set_linked (GIMP_ITEM (*channel),
00753                   linked ? TRUE : FALSE, FALSE);
00754         }
00755         break;
00756 
00757     case PROP_SHOW_MASKED:
00758         {
00759         bool show_masked;
00760 
00761         info->cp +=
00762                 xcf_read_int32 (info->fp, (Q_INT32 *) & show_masked, 1);
00763         gimp_channel_set_show_masked (*channel, show_masked);
00764         }
00765         break;
00766 
00767     case PROP_COLOR:
00768         {
00769         guchar col[3];
00770 
00771         info->cp += xcf_read_int8 (info->fp, (Q_UINT8 *) col, 3);
00772 
00773         gimp_rgb_set_uchar (&(*channel)->color, col[0], col[1], col[2]);
00774         }
00775         break;
00776 
00777     case PROP_TATTOO:
00778             info->cp +=
00779                 xcf_read_int32 (info->fp, &GIMP_ITEM (*channel)->tattoo, 1);
00780             break;
00781 
00782     case PROP_PARASITES:
00783         {
00784         glong base = info->cp;
00785         KisAnnotation *p;
00786 
00787         while ((info->cp - base) < prop_size)
00788             {
00789         p = xcf_load_parasite (info);
00790         gimp_item_parasite_attach (GIMP_ITEM (*channel), p);
00791         gimp_parasite_free (p);
00792             }
00793         if (info->cp - base != prop_size)
00794                 g_message ("Error while loading a channel's parasites");
00795         }
00796         break;
00797 
00798     default:
00799 #ifdef GIMP_UNSTABLE
00800             g_printerr ("unexpected/unknown channel property: %d (skipping)",
00801                         prop_type);
00802 #endif
00803 
00804             {
00805                 Q_UINT8 buf[16];
00806                 Q_UINT32 amount;
00807 
00808                 while (prop_size > 0)
00809                 {
00810                     amount = MIN (16, prop_size);
00811                     info->cp += xcf_read_int8 (info->fp, buf, amount);
00812                     prop_size -= MIN (16, amount);
00813                 }
00814             }
00815             break;
00816     }
00817     }
00818 
00819     return FALSE;
00820 }
00821 
00822 static bool
00823 xcf_load_prop (XcfInfo * info, PropType * prop_type, Q_INT32 * prop_size)
00824 {
00825     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) prop_type, 1);
00826     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) prop_size, 1);
00827     return TRUE;
00828 }
00829 
00830 static KisLayer *
00831 xcf_load_layer (XcfInfo * info, KisImage * gimage)
00832 {
00833     KisLayer *layer;
00834     GimpLayerMask *layer_mask;
00835     Q_INT32 hierarchy_offset;
00836     Q_INT32 layer_mask_offset;
00837     bool apply_mask = TRUE;
00838     bool edit_mask = FALSE;
00839     bool show_mask = FALSE;
00840     bool active;
00841     bool floating;
00842     Q_INT32 text_layer_flags = 0;
00843     Q_INT32 width;
00844     Q_INT32 height;
00845     Q_INT32 type;
00846     bool is_fs_drawable;
00847     QCString *name;
00848 
00849     /* check and see if this is the drawable the floating selection
00850      *  is attached to. if it is then we'll do the attachment in our caller.
00851      */
00852     is_fs_drawable = (info->cp == info->floating_sel_offset);
00853 
00854     /* read in the layer width, height, type and name */
00855     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & width, 1);
00856     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & height, 1);
00857     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & type, 1);
00858     info->cp += xcf_read_string (info->fp, &name, 1);
00859 
00860     /* create a new layer */
00861     layer = gimp_layer_new (gimage, width, height,
00862                             type, name, 255, GIMP_NORMAL_MODE);
00863     g_free (name);
00864     if (!layer)
00865         return NULL;
00866 
00867     /* read in the layer properties */
00868     if (!xcf_load_layer_props (info, gimage, layer,
00869                                &apply_mask, &edit_mask, &show_mask,
00870                                &text_layer_flags))
00871         goto error;
00872 
00873     /* call the evil text layer hack that might change our layer pointer */
00874     active = (info->active_layer == layer);
00875     floating = (info->floating_sel == layer);
00876 
00877     if (gimp_text_layer_xcf_load_hack (&layer))
00878     {
00879         gimp_text_layer_set_xcf_flags (GIMP_TEXT_LAYER (layer),
00880                                        text_layer_flags);
00881 
00882         if (active)
00883             info->active_layer = layer;
00884         if (floating)
00885             info->floating_sel = layer;
00886     }
00887 
00888     /* read the hierarchy and layer mask offsets */
00889     info->cp += xcf_read_int32 (info->fp, &hierarchy_offset, 1);
00890     info->cp += xcf_read_int32 (info->fp, &layer_mask_offset, 1);
00891 
00892     /* read in the hierarchy */
00893     if (!xcf_seek_pos (info, hierarchy_offset, NULL))
00894         goto error;
00895 
00896     if (!xcf_load_hierarchy (info, GIMP_DRAWABLE (layer)->tiles))
00897         goto error;
00898 
00899     /* read in the layer mask */
00900     if (layer_mask_offset != 0)
00901     {
00902         if (!xcf_seek_pos (info, layer_mask_offset, NULL))
00903             goto error;
00904 
00905         layer_mask = xcf_load_layer_mask (info, gimage);
00906         if (!layer_mask)
00907             goto error;
00908 
00909         layer_mask->apply_mask = apply_mask;
00910         layer_mask->edit_mask = edit_mask;
00911         layer_mask->show_mask = show_mask;
00912 
00913         gimp_layer_add_mask (layer, layer_mask, FALSE);
00914     }
00915 
00916     /* attach the floating selection... */
00917     if (is_fs_drawable)
00918         info->floating_sel_drawable = GIMP_DRAWABLE (layer);
00919 
00920     return layer;
00921 
00922 error:
00923     g_object_unref (layer);
00924     return NULL;
00925 }
00926 
00927 static GimpChannel *
00928 xcf_load_channel (XcfInfo * info, KisImage * gimage)
00929 {
00930     GimpChannel *channel;
00931     Q_INT32 hierarchy_offset;
00932     Q_INT32 width;
00933     Q_INT32 height;
00934     bool is_fs_drawable;
00935     QCString *name;
00936     GimpRGB color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
00937 
00938     /* check and see if this is the drawable the floating selection
00939      *  is attached to. if it is then we'll do the attachment in our caller.
00940      */
00941     is_fs_drawable = (info->cp == info->floating_sel_offset);
00942 
00943     /* read in the layer width, height and name */
00944     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & width, 1);
00945     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & height, 1);
00946     info->cp += xcf_read_string (info->fp, &name, 1);
00947 
00948     /* create a new channel */
00949     channel = gimp_channel_new (gimage, width, height, name, &color);
00950     g_free (name);
00951     if (!channel)
00952         return NULL;
00953 
00954     /* read in the channel properties */
00955     if (!xcf_load_channel_props (info, gimage, &channel))
00956         goto error;
00957 
00958     /* read the hierarchy and layer mask offsets */
00959     info->cp += xcf_read_int32 (info->fp, &hierarchy_offset, 1);
00960 
00961     /* read in the hierarchy */
00962     if (!xcf_seek_pos (info, hierarchy_offset, NULL))
00963         goto error;
00964 
00965     if (!xcf_load_hierarchy (info, GIMP_DRAWABLE (channel)->tiles))
00966         goto error;
00967 
00968     if (is_fs_drawable)
00969         info->floating_sel_drawable = GIMP_DRAWABLE (channel);
00970 
00971     return channel;
00972 
00973 error:
00974     g_object_unref (channel);
00975     return NULL;
00976 }
00977 
00978 static GimpLayerMask *
00979 xcf_load_layer_mask (XcfInfo * info, KisImage * gimage)
00980 {
00981     GimpLayerMask *layer_mask;
00982     GimpChannel *channel;
00983     Q_INT32 hierarchy_offset;
00984     Q_INT32 width;
00985     Q_INT32 height;
00986     bool is_fs_drawable;
00987     QCString *name;
00988     GimpRGB color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
00989 
00990     /* check and see if this is the drawable the floating selection
00991      *  is attached to. if it is then we'll do the attachment in our caller.
00992      */
00993     is_fs_drawable = (info->cp == info->floating_sel_offset);
00994 
00995     /* read in the layer width, height and name */
00996     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & width, 1);
00997     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & height, 1);
00998     info->cp += xcf_read_string (info->fp, &name, 1);
00999 
01000     /* create a new layer mask */
01001     layer_mask = gimp_layer_mask_new (gimage, width, height, name, &color);
01002     g_free (name);
01003     if (!layer_mask)
01004         return NULL;
01005 
01006     /* read in the layer_mask properties */
01007     channel = GIMP_CHANNEL (layer_mask);
01008     if (!xcf_load_channel_props (info, gimage, &channel))
01009         goto error;
01010 
01011     /* read the hierarchy and layer mask offsets */
01012     info->cp += xcf_read_int32 (info->fp, &hierarchy_offset, 1);
01013 
01014     /* read in the hierarchy */
01015     if (!xcf_seek_pos (info, hierarchy_offset, NULL))
01016         goto error;
01017 
01018     if (!xcf_load_hierarchy (info, GIMP_DRAWABLE (layer_mask)->tiles))
01019         goto error;
01020 
01021     /* attach the floating selection... */
01022     if (is_fs_drawable)
01023         info->floating_sel_drawable = GIMP_DRAWABLE (layer_mask);
01024 
01025     return layer_mask;
01026 
01027 error:
01028     g_object_unref (layer_mask);
01029     return NULL;
01030 }
01031 
01032 static bool
01033 xcf_load_hierarchy (XcfInfo * info, TileManager * tiles)
01034 {
01035     Q_INT32 saved_pos;
01036     Q_INT32 offset;
01037     Q_INT32 junk;
01038     Q_INT32 width;
01039     Q_INT32 height;
01040     Q_INT32 bpp;
01041 
01042     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & width, 1);
01043     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & height, 1);
01044     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & bpp, 1);
01045 
01046     /* make sure the values in the file correspond to the values
01047      *  calculated when the TileManager was created.
01048      */
01049     if (width != tile_manager_width (tiles) ||
01050         height != tile_manager_height (tiles) ||
01051         bpp != tile_manager_bpp (tiles))
01052         return FALSE;
01053 
01054     /* load in the levels...we make sure that the number of levels
01055      *  calculated when the TileManager was created is the same
01056      *  as the number of levels found in the file.
01057      */
01058 
01059     info->cp += xcf_read_int32 (info->fp, &offset, 1);  /* top level */
01060 
01061     /* discard offsets for layers below first, if any.
01062      */
01063     do
01064     {
01065         info->cp += xcf_read_int32 (info->fp, &junk, 1);
01066     }
01067     while (junk != 0);
01068 
01069     /* save the current position as it is where the
01070      *  next level offset is stored.
01071      */
01072     saved_pos = info->cp;
01073 
01074     /* seek to the level offset */
01075     if (!xcf_seek_pos (info, offset, NULL))
01076         return FALSE;
01077 
01078     /* read in the level */
01079     if (!xcf_load_level (info, tiles))
01080         return FALSE;
01081 
01082     /* restore the saved position so we'll be ready to
01083      *  read the next offset.
01084      */
01085     if (!xcf_seek_pos (info, saved_pos, NULL))
01086         return FALSE;
01087 
01088     return TRUE;
01089 }
01090 
01091 
01092 static bool
01093 xcf_load_level (XcfInfo * info, TileManager * tiles)
01094 {
01095     Q_INT32 saved_pos;
01096     Q_INT32 offset, offset2;
01097     Q_UINT32 ntiles;
01098     Q_INT32 width;
01099     Q_INT32 height;
01100     Q_INT32 i;
01101     Q_INT32 fail;
01102     Tile *previous;
01103     Tile *tile;
01104 
01105     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & width, 1);
01106     info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & height, 1);
01107 
01108     if (width != tile_manager_width (tiles) ||
01109         height != tile_manager_height (tiles))
01110         return FALSE;
01111 
01112     /* read in the first tile offset.
01113      *  if it is '0', then this tile level is empty
01114      *  and we can simply return.
01115      */
01116     info->cp += xcf_read_int32 (info->fp, &offset, 1);
01117     if (offset == 0)
01118         return TRUE;
01119 
01120     /* Initialise the reference for the in-memory tile-compression
01121      */
01122     previous = NULL;
01123 
01124     ntiles = tiles->ntile_rows * tiles->ntile_cols;
01125     for (i = 0; i < ntiles; i++)
01126     {
01127         fail = FALSE;
01128 
01129         if (offset == 0)
01130     {
01131             g_message ("not enough tiles found in level");
01132             return FALSE;
01133     }
01134 
01135         /* save the current position as it is where the
01136          *  next tile offset is stored.
01137          */
01138         saved_pos = info->cp;
01139 
01140         /* read in the offset of the next tile so we can calculate the amount
01141            of data needed for this tile */
01142         info->cp += xcf_read_int32 (info->fp, &offset2, 1);
01143 
01144         /* if the offset is 0 then we need to read in the maximum possible
01145            allowing for negative compression */
01146         if (offset2 == 0)
01147             offset2 = offset + TILE_WIDTH * TILE_WIDTH * 4 * 1.5;
01148         /* 1.5 is probably more
01149            than we need to allow */
01150 
01151         /* seek to the tile offset */
01152         if (!xcf_seek_pos (info, offset, NULL))
01153             return FALSE;
01154 
01155         /* get the tile from the tile manager */
01156         tile = tile_manager_get (tiles, i, TRUE, TRUE);
01157 
01158         /* read in the tile */
01159         switch (info->compression)
01160     {
01161     case COMPRESS_NONE:
01162             if (!xcf_load_tile (info, tile))
01163                 fail = TRUE;
01164             break;
01165     case COMPRESS_RLE:
01166             if (!xcf_load_tile_rle (info, tile, offset2 - offset))
01167                 fail = TRUE;
01168             break;
01169     case COMPRESS_ZLIB:
01170             g_error ("xcf: zlib compression unimplemented");
01171             fail = TRUE;
01172             break;
01173     case COMPRESS_FRACTAL:
01174             g_error ("xcf: fractal compression unimplemented");
01175             fail = TRUE;
01176             break;
01177     }
01178 
01179         if (fail)
01180     {
01181             tile_release (tile, TRUE);
01182             return FALSE;
01183     }
01184 
01185         /* To potentially save memory, we compare the
01186          *  newly-fetched tile against the last one, and
01187          *  if they're the same we copy-on-write mirror one against
01188          *  the other.
01189          */
01190         if (previous != NULL)
01191     {
01192             tile_lock (previous);
01193             if (tile_ewidth (tile) == tile_ewidth (previous) &&
01194                 tile_eheight (tile) == tile_eheight (previous) &&
01195                 tile_bpp (tile) == tile_bpp (previous) &&
01196                 memcmp (tile_data_pointer (tile, 0, 0),
01197                         tile_data_pointer (previous, 0, 0),
01198                         tile_size (tile)) == 0)
01199                 tile_manager_map (tiles, i, previous);
01200             tile_release (previous, FALSE);
01201     }
01202         tile_release (tile, TRUE);
01203         previous = tile_manager_get (tiles, i, FALSE, FALSE);
01204 
01205         /* restore the saved position so we'll be ready to
01206          *  read the next offset.
01207          */
01208         if (!xcf_seek_pos (info, saved_pos, NULL))
01209             return FALSE;
01210 
01211         /* read in the offset of the next tile */
01212         info->cp += xcf_read_int32 (info->fp, &offset, 1);
01213     }
01214 
01215     if (offset != 0)
01216     {
01217         g_message ("encountered garbage after reading level: %d", offset);
01218         return FALSE;
01219     }
01220 
01221     return TRUE;
01222 }
01223 
01224 static bool
01225 xcf_load_tile (XcfInfo * info, Tile * tile)
01226 {
01227 #ifdef SWAP_FROM_FILE
01228 
01229     if (!info->swap_num)
01230     {
01231         info->ref_count = g_new (int, 1);
01232         info->swap_num = tile_swap_add (info->filename,
01233                                         xcf_swap_func, info->ref_count);
01234     }
01235 
01236     tile->swap_num = info->swap_num;
01237     tile->swap_offset = info->cp;
01238     *info->ref_count += 1;
01239 
01240 #else
01241 
01242     info->cp += xcf_read_int8 (info->fp, tile_data_pointer (tile, 0, 0),
01243                                tile_size (tile));
01244 
01245 #endif
01246 
01247     return TRUE;
01248 }
01249 
01250 static bool
01251 xcf_load_tile_rle (XcfInfo * info, Tile * tile, int data_length)
01252 {
01253     guchar *data;
01254     guchar val;
01255     Q_INT32 size;
01256     Q_INT32 count;
01257     Q_INT32 length;
01258     Q_INT32 bpp;
01259     Q_INT32 i, j;
01260     Q_INT32 nmemb_read_successfully;
01261     guchar *xcfdata, *xcfodata, *xcfdatalimit;
01262 
01263     data = tile_data_pointer (tile, 0, 0);
01264     bpp = tile_bpp (tile);
01265 
01266     xcfdata = xcfodata = g_malloc (data_length);
01267 
01268     /* we have to use fread instead of xcf_read_* because we may be
01269        reading past the end of the file here */
01270     nmemb_read_successfully = fread ((QCString *) xcfdata, sizeof (QCString),
01271                                      data_length, info->fp);
01272     info->cp += nmemb_read_successfully;
01273 
01274     xcfdatalimit = &xcfodata[nmemb_read_successfully - 1];
01275 
01276     for (i = 0; i < bpp; i++)
01277     {
01278         data = (guchar *) tile_data_pointer (tile, 0, 0) + i;
01279         size = tile_ewidth (tile) * tile_eheight (tile);
01280         count = 0;
01281 
01282         while (size > 0)
01283     {
01284             if (xcfdata > xcfdatalimit)
01285         {
01286                 goto bogus_rle;
01287         }
01288 
01289             val = *xcfdata++;
01290 
01291             length = val;
01292             if (length >= 128)
01293         {
01294                 length = 255 - (length - 1);
01295                 if (length == 128)
01296         {
01297                     if (xcfdata >= xcfdatalimit)
01298             {
01299                         goto bogus_rle;
01300             }
01301 
01302                     length = (*xcfdata << 8) + xcfdata[1];
01303                     xcfdata += 2;
01304         }
01305 
01306                 count += length;
01307                 size -= length;
01308 
01309                 if (size < 0)
01310         {
01311                     goto bogus_rle;
01312         }
01313 
01314                 if (&xcfdata[length - 1] > xcfdatalimit)
01315         {
01316                     goto bogus_rle;
01317         }
01318 
01319                 while (length-- > 0)
01320         {
01321                     *data = *xcfdata++;
01322                     data += bpp;
01323         }
01324         }
01325             else
01326         {
01327                 length += 1;
01328                 if (length == 128)
01329         {
01330                     if (xcfdata >= xcfdatalimit)
01331             {
01332                         goto bogus_rle;
01333             }
01334 
01335                     length = (*xcfdata << 8) + xcfdata[1];
01336                     xcfdata += 2;
01337         }
01338 
01339                 count += length;
01340                 size -= length;
01341 
01342                 if (size < 0)
01343         {
01344                     goto bogus_rle;
01345         }
01346 
01347                 if (xcfdata > xcfdatalimit)
01348         {
01349                     goto bogus_rle;
01350         }
01351 
01352                 val = *xcfdata++;
01353 
01354                 for (j = 0; j < length; j++)
01355         {
01356                     *data = val;
01357                     data += bpp;
01358         }
01359         }
01360     }
01361     }
01362     g_free (xcfodata);
01363     return TRUE;
01364 
01365 bogus_rle:
01366     if (xcfodata)
01367         g_free (xcfodata);
01368     return FALSE;
01369 }
01370 
01371 static KisAnnotation *
01372 xcf_load_parasite (XcfInfo * info)
01373 {
01374     KisAnnotation *p;
01375 
01376     p = g_new (KisAnnotation, 1);
01377     info->cp += xcf_read_string (info->fp, &p->name, 1);
01378     info->cp += xcf_read_int32 (info->fp, &p->flags, 1);
01379     info->cp += xcf_read_int32 (info->fp, &p->size, 1);
01380     p->data = g_new (QCString, p->size);
01381     info->cp += xcf_read_int8 (info->fp, p->data, p->size);
01382 
01383     return p;
01384 }
01385 
01386 static bool
01387 xcf_load_old_paths (XcfInfo * info, KisImage * gimage)
01388 {
01389     Q_INT32 num_paths;
01390     Q_INT32 last_selected_row;
01391     GimpVectors *active_vectors;
01392 
01393     info->cp += xcf_read_int32 (info->fp, &last_selected_row, 1);
01394     info->cp += xcf_read_int32 (info->fp, &num_paths, 1);
01395 
01396     while (num_paths-- > 0)
01397         xcf_load_old_path (info, gimage);
01398 
01399     active_vectors = (GimpVectors *)
01400                      gimp_container_get_child_by_index (gimage->vectors, last_selected_row);
01401 
01402     if (active_vectors)
01403         gimp_image_set_active_vectors (gimage, active_vectors);
01404 
01405     return TRUE;
01406 }
01407 
01408 static bool
01409 xcf_load_old_path (XcfInfo * info, KisImage * gimage)
01410 {
01411     QCString *name;
01412     Q_INT32 locked;
01413     Q_UINT8 state;
01414     Q_INT32 closed;
01415     Q_INT32 num_points;
01416     Q_INT32 version;        /* changed from num_paths */
01417     GimpTattoo tattoo = 0;
01418     GimpVectors *vectors;
01419     GimpVectorsCompatPoint *points;
01420     Q_INT32 i;
01421 
01422     info->cp += xcf_read_string (info->fp, &name, 1);
01423     info->cp += xcf_read_int32 (info->fp, &locked, 1);
01424     info->cp += xcf_read_int8 (info->fp, &state, 1);
01425     info->cp += xcf_read_int32 (info->fp, &closed, 1);
01426     info->cp += xcf_read_int32 (info->fp, &num_points, 1);
01427     info->cp += xcf_read_int32 (info->fp, &version, 1);
01428 
01429     if (version == 2)
01430     {
01431         Q_INT32 dummy;
01432 
01433         /* Had extra type field and points are stored as doubles */
01434         info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & dummy, 1);
01435     }
01436     else if (version == 3)
01437     {
01438         Q_INT32 dummy;
01439 
01440         /* Has extra tatto field */
01441         info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & dummy, 1);
01442         info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & tattoo, 1);
01443     }
01444     else if (version != 1)
01445     {
01446         g_warning ("Unknown path type. Possibly corrupt XCF file");
01447 
01448         return FALSE;
01449     }
01450 
01451     /* skip empty compatibility paths */
01452     if (num_points == 0)
01453         return FALSE;
01454 
01455     points = g_new0 (GimpVectorsCompatPoint, num_points);
01456 
01457     for (i = 0; i < num_points; i++)
01458     {
01459         if (version == 1)
01460     {
01461             Q_INT3232 x;
01462             Q_INT3232 y;
01463 
01464             info->cp += xcf_read_int32 (info->fp, &points[i].type, 1);
01465             info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & x, 1);
01466             info->cp += xcf_read_int32 (info->fp, (Q_INT32 *) & y, 1);
01467 
01468             points[i].x = x;
01469             points[i].y = y;
01470     }
01471         else
01472     {
01473             float x;
01474             float y;
01475 
01476             info->cp += xcf_read_int32 (info->fp, &points[i].type, 1);
01477             info->cp += xcf_read_float (info->fp, &x, 1);
01478             info->cp += xcf_read_float (info->fp, &y, 1);
01479 
01480             points[i].x = x;
01481             points[i].y = y;
01482     }
01483     }
01484 
01485     vectors =
01486         gimp_vectors_compat_new (gimage, name, points, num_points, closed);
01487 
01488     g_free (name);
01489     g_free (points);
01490 
01491     GIMP_ITEM (vectors)->linked = locked;
01492 
01493     if (tattoo)
01494         GIMP_ITEM (vectors)->tattoo = tattoo;
01495 
01496     gimp_image_add_vectors (gimage, vectors,
01497                             gimp_container_num_children (gimage->vectors));
01498 
01499     return TRUE;
01500 }
01501 
01502 static bool
01503 xcf_load_vectors (XcfInfo * info, KisImage * gimage)
01504 {
01505     Q_INT32 version;
01506     Q_INT32 active_index;
01507     Q_INT32 num_paths;
01508     GimpVectors *active_vectors;
01509     Q_INT32 base;
01510 
01511 #ifdef GIMP_XCF_PATH_DEBUG
01512     g_printerr ("xcf_load_vectors\n");
01513 #endif
01514 
01515     base = info->cp;
01516 
01517     info->cp += xcf_read_int32 (info->fp, &version, 1);
01518 
01519     if (version != 1)
01520     {
01521         g_message ("Unknown vectors version: %d (skipping)", version);
01522         return FALSE;
01523     }
01524 
01525     info->cp += xcf_read_int32 (info->fp, &active_index, 1);
01526     info->cp += xcf_read_int32 (info->fp, &num_paths, 1);
01527 
01528 #ifdef GIMP_XCF_PATH_DEBUG
01529     g_printerr ("%d paths (active: %d)\n", num_paths, active_index);
01530 #endif
01531 
01532     while (num_paths-- > 0)
01533         if (!xcf_load_vector (info, gimage))
01534             return FALSE;
01535 
01536     active_vectors = (GimpVectors *)
01537                      gimp_container_get_child_by_index (gimage->vectors, active_index);
01538 
01539     if (active_vectors)
01540         gimp_image_set_active_vectors (gimage, active_vectors);
01541 
01542 #ifdef GIMP_XCF_PATH_DEBUG
01543     g_printerr ("xcf_load_vectors: loaded %d bytes\n", info->cp - base);
01544 #endif
01545     return TRUE;
01546 }
01547 
01548 static bool
01549 xcf_load_vector (XcfInfo * info, KisImage * gimage)
01550 {
01551     QCString *name;
01552     GimpTattoo tattoo = 0;
01553     Q_INT32 visible;
01554     Q_INT32 linked;
01555     Q_INT32 num_parasites;
01556     Q_INT32 num_strokes;
01557     GimpVectors *vectors;
01558     Q_INT32 i;
01559 
01560 #ifdef GIMP_XCF_PATH_DEBUG
01561     g_printerr ("xcf_load_vector\n");
01562 #endif
01563 
01564     info->cp += xcf_read_string (info->fp, &name, 1);
01565     info->cp += xcf_read_int32 (info->fp, &tattoo, 1);
01566     info->cp += xcf_read_int32 (info->fp, &visible, 1);
01567     info->cp += xcf_read_int32 (info->fp, &linked, 1);
01568     info->cp += xcf_read_int32 (info->fp, &num_parasites, 1);
01569     info->cp += xcf_read_int32 (info->fp, &num_strokes, 1);
01570 
01571 #ifdef GIMP_XCF_PATH_DEBUG
01572     g_printerr
01573         ("name: %s, tattoo: %d, visible: %d, linked: %d, num_parasites %d, "
01574          "num_strokes %d\n", name, tattoo, visible, linked, num_parasites,
01575          num_strokes);
01576 #endif
01577 
01578     vectors = gimp_vectors_new (gimage, name);
01579 
01580     GIMP_ITEM (vectors)->visible = visible ? TRUE : FALSE;
01581     GIMP_ITEM (vectors)->linked = linked ? TRUE : FALSE;
01582 
01583     if (tattoo)
01584         GIMP_ITEM (vectors)->tattoo = tattoo;
01585 
01586     for (i = 0; i < num_parasites; i++)
01587     {
01588         KisAnnotation *parasite;
01589 
01590         parasite = xcf_load_parasite (info);
01591 
01592         if (!parasite)
01593             return FALSE;
01594 
01595         gimp_item_parasite_attach (GIMP_ITEM (vectors), parasite);
01596         gimp_parasite_free (parasite);
01597     }
01598 
01599     for (i = 0; i < num_strokes; i++)
01600     {
01601         Q_INT32 stroke_type_id;
01602         Q_INT32 closed;
01603         Q_INT32 num_axes;
01604         Q_INT32 num_control_points;
01605         Q_INT32 type;
01606         float coords[6] = { 0.0, 0.0, 1.0, 0.5, 0.5, 0.5 };
01607         GimpStroke *stroke;
01608         Q_INT32 j;
01609 
01610         GValueArray *control_points;
01611         GValue value = { 0, };
01612         GimpAnchor anchor;
01613         GType stroke_type;
01614 
01615         g_value_init (&value, GIMP_TYPE_ANCHOR);
01616 
01617         info->cp += xcf_read_int32 (info->fp, &stroke_type_id, 1);
01618         info->cp += xcf_read_int32 (info->fp, &closed, 1);
01619         info->cp += xcf_read_int32 (info->fp, &num_axes, 1);
01620         info->cp += xcf_read_int32 (info->fp, &num_control_points, 1);
01621 
01622 #ifdef GIMP_XCF_PATH_DEBUG
01623         g_printerr ("stroke_type: %d, closed: %d, num_axes %d, len %d\n",
01624                     stroke_type_id, closed, num_axes, num_control_points);
01625 #endif
01626 
01627         switch (stroke_type_id)
01628     {
01629     case XCF_STROKETYPE_BEZIER_STROKE:
01630             stroke_type = GIMP_TYPE_BEZIER_STROKE;
01631             break;
01632 
01633     default:
01634             g_printerr ("skipping unknown stroke type\n");
01635             xcf_seek_pos (info,
01636                           info->cp + 4 * num_axes * num_control_points, NULL);
01637             continue;
01638     }
01639 
01640         control_points = g_value_array_new (num_control_points);
01641 
01642         anchor.selected = FALSE;
01643 
01644         for (j = 0; j < num_control_points; j++)
01645     {
01646             info->cp += xcf_read_int32 (info->fp, &type, 1);
01647             info->cp += xcf_read_float (info->fp, coords, num_axes);
01648 
01649             anchor.type = type;
01650             anchor.position.x = coords[0];
01651             anchor.position.y = coords[1];
01652             anchor.position.pressure = coords[2];
01653             anchor.position.xtilt = coords[3];
01654             anchor.position.ytilt = coords[4];
01655             anchor.position.wheel = coords[5];
01656 
01657             g_value_set_boxed (&value, &anchor);
01658             g_value_array_append (control_points, &value);
01659 
01660 #ifdef GIMP_XCF_PATH_DEBUG
01661             g_printerr ("Anchor: %d, (%f, %f, %f, %f, %f, %f)\n", type,
01662                         coords[0], coords[1], coords[2], coords[3],
01663                         coords[4], coords[5]);
01664 #endif
01665     }
01666 
01667         g_value_unset (&value);
01668 
01669         stroke = g_object_new (stroke_type,
01670                                "closed", closed,
01671                                "control-points", control_points, NULL);
01672 
01673         gimp_vectors_stroke_add (vectors, stroke);
01674     }
01675 
01676     gimp_image_add_vectors (gimage, vectors,
01677                             gimp_container_num_children (gimage->vectors));
01678 
01679     return TRUE;
01680 }
01681 
01682 #ifdef SWAP_FROM_FILE
01683 
01684 static bool
01685 xcf_swap_func (Q_INT32 fd, Tile * tile, Q_INT32 cmd, gpointer user_data)
01686 {
01687     Q_INT32 bytes;
01688     Q_INT32 err;
01689     Q_INT32 nleft;
01690     Q_INT32 *ref_count;
01691 
01692     switch (cmd)
01693     {
01694     case SWAP_IN:
01695         lseek (fd, tile->swap_offset, SEEK_SET);
01696 
01697         bytes = tile_size (tile);
01698         tile_alloc (tile);
01699 
01700         nleft = bytes;
01701         while (nleft > 0)
01702     {
01703             do
01704         {
01705                 err = read (fd, tile->data + bytes - nleft, nleft);
01706         }
01707             while ((err == -1) && ((errno == EAGAIN) || (errno == EINTR)));
01708 
01709             if (err <= 0)
01710         {
01711                 g_message ("unable to read tile data from xcf file: "
01712                            "%d ( %d ) bytes read", err, nleft);
01713                 return FALSE;
01714         }
01715 
01716             nleft -= err;
01717     }
01718         break;
01719 
01720     case SWAP_OUT:
01721     case SWAP_DELETE:
01722     case SWAP_COMPRESS:
01723         ref_count = user_data;
01724         *ref_count -= 1;
01725         if (*ref_count == 0)
01726     {
01727             tile_swap_remove (tile->swap_num);
01728             g_free (ref_count);
01729     }
01730 
01731         tile->swap_num = 1;
01732         tile->swap_offset = -1;
01733 
01734         return TRUE;
01735     }
01736 
01737     return FALSE;
01738 }
01739 
01740 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys