[gimp] Bug 730211 - Extra zeroes appear in XCF files



commit 1368f73354070a40c0a73e92c5075164b3a07848
Author: Massimo Valentini <mvalentini src gnome org>
Date:   Wed Oct 15 23:15:18 2014 +0200

    Bug 730211 - Extra zeroes appear in XCF files
    
    Don't use xcf_seek_end() because that seems to be broken on certain
    file systems / operating systems / FUSE mounts / whatever. Instead,
    seek to explicitly calculated file offsets.
    
    Ported Massimo's patch to master and added comments --Mitch
    
    The same commit in gimp-2-8 is a57e49b1bbd318b06c4f8d578557b63256a1e66d

 app/xcf/xcf-save.c |  235 +++++++++++++++++++++-------------------------------
 1 files changed, 93 insertions(+), 142 deletions(-)
---
diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c
index 1ceb521..b52d6ce 100644
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -185,6 +185,9 @@ static gboolean xcf_save_vectors       (XcfInfo           *info,
   } G_STMT_END
 
 
+static const guint32 zero = 0;
+
+
 gboolean
 xcf_save_image (XcfInfo    *info,
                 GimpImage  *image,
@@ -255,98 +258,66 @@ xcf_save_image (XcfInfo    *info,
 
   xcf_progress_update (info);
 
-  /* save the current file position as it is the start of where
-   *  we place the layer offset information.
+  /* 'offset' is where we will write the next layer or channel, which
+   * is after the offset table
    */
-  saved_pos = info->cp;
-
-  /* seek to after the offset lists */
-  xcf_check_error (xcf_seek_pos (info,
-                                 info->cp + (n_layers + n_channels + 2) * 4,
-                                 error));
+  offset = info->cp + (n_layers + n_channels + 2) * 4;
 
   for (list = all_layers; list; list = g_list_next (list))
     {
       GimpLayer *layer = list->data;
 
-      /* save the start offset of where we are writing
-       *  out the next layer.
-       */
-      offset = info->cp;
+      /* write the offset of the layer */
+      xcf_write_int32_check_error (info, &offset, 1);
 
-      /* write out the layer. */
+      /* 'saved_pos' is the next slot in the layer offset table */
+      saved_pos = info->cp;
+
+      /* seek to the layer offset and save the layer */
+      xcf_check_error (xcf_seek_pos (info, offset, error));
       xcf_check_error (xcf_save_layer (info, image, layer, error));
 
-      xcf_progress_update (info);
+      /* the next layer's offset is after the layer we just wrote */
+      offset = info->cp;
 
-      /* seek back to where we are to write out the next
-       *  layer offset and write it out.
-       */
+      /* seek back to the next slot in the offset table */
       xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-      xcf_write_int32_check_error (info, &offset, 1);
-
-      /* increment the location we are to write out the
-       *  next offset.
-       */
-      saved_pos = info->cp;
 
-      /* seek to the end of the file which is where
-       *  we will write out the next layer.
-       */
-      xcf_check_error (xcf_seek_end (info, error));
+      xcf_progress_update (info);
     }
 
-  /* write out a '0' offset position to indicate the end
-   *  of the layer offsets.
-   */
-  offset = 0;
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
-  saved_pos = info->cp;
-  xcf_check_error (xcf_seek_end (info, error));
+  /* write out a '0' offset to indicate the end of the layer offsets */
+  xcf_write_int32_check_error (info, &zero, 1);
 
   for (list = all_channels; list; list = g_list_next (list))
     {
       GimpChannel *channel = list->data;
 
-      /* save the start offset of where we are writing
-       *  out the next channel.
-       */
-      offset = info->cp;
+      /* write the offset of the channel */
+      xcf_write_int32_check_error (info, &offset, 1);
 
-      /* write out the layer. */
+      /* 'saved_pos' is the next slot in the channel offset table */
+      saved_pos = info->cp;
+
+      /* seek to the channel offset and save the channel */
+      xcf_check_error (xcf_seek_pos (info, offset, error));
       xcf_check_error (xcf_save_channel (info, image, channel, error));
 
-      xcf_progress_update (info);
+      /* the next channels's offset is after the layer we just wrote */
+      offset = info->cp;
 
-      /* seek back to where we are to write out the next
-       *  channel offset and write it out.
-       */
+      /* seek back to the next slot in the offset table */
       xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-      xcf_write_int32_check_error (info, &offset, 1);
 
-      /* increment the location we are to write out the
-       *  next offset.
-       */
-      saved_pos = info->cp;
-
-      /* seek to the end of the file which is where
-       *  we will write out the next channel.
-       */
-      xcf_check_error (xcf_seek_end (info, error));
+      xcf_progress_update (info);
     }
 
+  /* write out a '0' offset to indicate the end of the channel offsets */
+  xcf_write_int32_check_error (info, &zero, 1);
+
   g_list_free (all_layers);
   g_list_free (all_channels);
 
-  /* write out a '0' offset position to indicate the end
-   *  of the channel offsets.
-   */
-  offset = 0;
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
-  saved_pos = info->cp;
-
   return ! g_output_stream_is_closed (info->output);
 }
 
@@ -994,7 +965,7 @@ xcf_save_prop (XcfInfo    *info,
                 return FALSE;
               }
 
-            xcf_check_error (xcf_seek_end (info, error));
+            xcf_check_error (xcf_seek_pos (info, base + length, error));
           }
       }
       break;
@@ -1041,7 +1012,7 @@ xcf_save_prop (XcfInfo    *info,
             return FALSE;
           }
 
-        xcf_check_error (xcf_seek_end (info, error));
+        xcf_check_error (xcf_seek_pos (info, base + length, error));
       }
       break;
 
@@ -1107,7 +1078,7 @@ xcf_save_prop (XcfInfo    *info,
             return FALSE;
           }
 
-        xcf_check_error (xcf_seek_end (info, error));
+        xcf_check_error (xcf_seek_pos (info, base + length, error));
       }
       break;
 
@@ -1204,43 +1175,36 @@ xcf_save_layer (XcfInfo    *info,
   /* write out the layer properties */
   xcf_save_layer_props (info, image, layer, error);
 
-  /*  save the current position which is where the hierarchy offset
-   *  will be stored.
-   */
-  saved_pos = info->cp;
-
   /*  write out the layer tile hierarchy  */
-  xcf_check_error (xcf_seek_pos (info, info->cp + 8, error));
-  offset = info->cp;
+  offset = info->cp + 8;
+  xcf_write_int32_check_error (info, &offset, 1);
+
+  saved_pos = info->cp;
+  xcf_check_error (xcf_seek_pos (info, offset, error));
 
   xcf_check_error (xcf_save_buffer (info,
                                     gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
                                     error));
 
+  offset = info->cp;
   xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
-
-  /*  save the current position which is where the layer mask offset
-   *  will be stored.
-   */
-  saved_pos = info->cp;
 
   /* write out the layer mask */
   if (gimp_layer_get_mask (layer))
     {
       GimpLayerMask *mask = gimp_layer_get_mask (layer);
 
-      xcf_check_error (xcf_seek_end (info, error));
-      offset = info->cp;
+      xcf_write_int32_check_error (info, &offset, 1);
+      xcf_check_error (xcf_seek_pos (info, offset, error));
 
       xcf_check_error (xcf_save_channel (info, image, GIMP_CHANNEL (mask),
                                          error));
     }
   else
-    offset = 0;
-
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
+    {
+      xcf_write_int32_check_error (info, &zero, 1);
+      xcf_check_error (xcf_seek_pos (info, offset, error));
+    }
 
   return TRUE;
 }
@@ -1282,23 +1246,14 @@ xcf_save_channel (XcfInfo      *info,
   /* write out the channel properties */
   xcf_save_channel_props (info, image, channel, error);
 
-  /* save the current position which is where the hierarchy offset
-   *  will be stored.
-   */
-  saved_pos = info->cp;
-
   /* write out the channel tile hierarchy */
-  xcf_check_error (xcf_seek_pos (info, info->cp + 4, error));
-  offset = info->cp;
+  offset = info->cp + 4;
+  xcf_write_int32_check_error (info, &offset, 1);
 
   xcf_check_error (xcf_save_buffer (info,
                                     gimp_drawable_get_buffer (GIMP_DRAWABLE (channel)),
                                     error));
 
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
-  saved_pos = info->cp;
-
   return TRUE;
 }
 
@@ -1351,11 +1306,21 @@ xcf_save_buffer (XcfInfo     *info,
   tmp2 = xcf_calc_levels (height, XCF_TILE_HEIGHT);
   nlevels = MAX (tmp1, tmp2);
 
-  xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
+  /* 'offset' is where we will save the next level, which is after the
+   * level offset table
+   */
+  offset = info->cp + (1 + nlevels) * 4;
 
   for (i = 0; i < nlevels; i++)
     {
-      offset = info->cp;
+      /* write the offset of the level */
+      xcf_write_int32_check_error (info, &offset, 1);
+
+      /* 'saved_pos' is the next slot in the level offset table */
+      saved_pos = info->cp;
+
+      /* seek to the level offset and save the level */
+      xcf_check_error (xcf_seek_pos (info, offset, error));
 
       if (i == 0)
         {
@@ -1373,29 +1338,18 @@ xcf_save_buffer (XcfInfo     *info,
           xcf_write_int32_check_error (info, (guint32 *) &tmp1,   1);
         }
 
-      /* seek back to where we are to write out the next
-       *  level offset and write it out.
-       */
-      xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-      xcf_write_int32_check_error (info, &offset, 1);
-
-      /* increment the location we are to write out the
-       *  next offset.
-       */
-      saved_pos = info->cp;
+      /* the next level's offset if after the level we just wrote */
+      offset = info->cp;
 
-      /* seek to the end of the file which is where
-       *  we will write out the next level.
-       */
-      xcf_check_error (xcf_seek_end (info, error));
+      /* seek back to the next slot in the offset table */
+      xcf_check_error (xcf_seek_pos (info, saved_pos, error));
     }
 
-  /* write out a '0' offset position to indicate the end
-   *  of the level offsets.
-   */
-  offset = 0;
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
+  /* write out a '0' offset to indicate the end of the level offsets */
+  xcf_write_int32_check_error (info, &zero, 1);
+
+  /* seek to after the last level we just wrote */
+  xcf_check_error (xcf_seek_pos (info, offset, error));
 
   return TRUE;
 }
@@ -1438,16 +1392,24 @@ xcf_save_level (XcfInfo     *info,
   n_tile_cols = gimp_gegl_buffer_get_n_tile_cols (buffer, XCF_TILE_WIDTH);
 
   ntiles = n_tile_rows * n_tile_cols;
-  xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
+
+  /* 'offset' is where we will write the next tile, which is after the
+   * tile offset table
+   */
+  offset = info->cp + (ntiles + 1) * 4;
 
   for (i = 0; i < ntiles; i++)
     {
       GeglRectangle rect;
 
-      /* save the start offset of where we are writing
-       *  out the next tile.
-       */
-      offset = info->cp;
+      /* write the offset of the tile */
+      xcf_write_int32_check_error (info, &offset, 1);
+
+      /* 'saved_pos' is the next slot in the tile offset table */
+      saved_pos = info->cp;
+
+      /* seek to the tile offset and save the tile */
+      xcf_check_error (xcf_seek_pos (info, offset, error));
 
       gimp_gegl_buffer_get_tile_rect (buffer,
                                       XCF_TILE_WIDTH, XCF_TILE_HEIGHT,
@@ -1473,29 +1435,18 @@ xcf_save_level (XcfInfo     *info,
           return FALSE;
         }
 
-      /* seek back to where we are to write out the next
-       *  tile offset and write it out.
-       */
-      xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-      xcf_write_int32_check_error (info, &offset, 1);
-
-      /* increment the location we are to write out the
-       *  next offset.
-       */
-      saved_pos = info->cp;
+      /* the next tile's offset is after the tile we just wrote */
+      offset = info->cp;
 
-      /* seek to the end of the file which is where
-       *  we will write out the next tile.
-       */
-      xcf_check_error (xcf_seek_end (info, error));
+      /* seek back to the next slot in the offset table */
+      xcf_check_error (xcf_seek_pos (info, saved_pos, error));
     }
 
-  /* write out a '0' offset position to indicate the end
-   *  of the level offsets.
-   */
-  offset = 0;
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
+  /* write out a '0' offset to indicate the end of the tile offsets */
+  xcf_write_int32_check_error (info, &zero, 1);
+
+  /* seek to after the last tile we just wrote */
+  xcf_check_error (xcf_seek_pos (info, offset, error));
 
   return TRUE;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]