[gimp/osx-build: 44/44] Bug 730211 - Extra zeroes appear in XCF files (draft)



commit faa8ad2ac74b081e4d5714ee1c8ac8cf2245c1c0
Author: Massimo Valentini <mvalentini src gnome org>
Date:   Sat Jun 14 17:57:11 2014 +0200

    Bug 730211 - Extra zeroes appear in XCF files (draft)
    
    Patch to solve bug 730211. GIMP can be built with it and a simple
    test to save and load "layers recovered.xcf" passes.
    Needs further review and extensive testing as proposed by Massimo
    in comment 14 of the bug report.

 app/xcf/xcf-save.c |  184 ++++++++++++++--------------------------------------
 1 files changed, 50 insertions(+), 134 deletions(-)
---
diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c
index 50809df..d4c943b 100644
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -174,6 +174,7 @@ static gboolean xcf_save_vectors       (XcfInfo           *info,
                                (gdouble) progress / (gdouble) max_progress); \
   } G_STMT_END
 
+static const guint32 zero;
 
 void
 xcf_save_choose_format (XcfInfo   *info,
@@ -278,85 +279,45 @@ 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.
-   */
-  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;
+      xcf_write_int32_check_error (info, &offset, 1);
 
-      /* write out the layer. */
-      xcf_check_error (xcf_save_layer (info, image, layer, error));
+      saved_pos = info->cp;
+      xcf_check_error (xcf_seek_pos (info, offset, error));
 
-      xcf_progress_update (info);
+      xcf_check_error (xcf_save_layer (info, image, layer, error));
 
-      /* seek back to where we are to write out the next
-       *  layer offset and write it out.
-       */
+      offset = info->cp;
       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));
+  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;
+      xcf_write_int32_check_error (info, &offset, 1);
 
-      /* write out the layer. */
-      xcf_check_error (xcf_save_channel (info, image, channel, error));
+      saved_pos = info->cp;
+      xcf_check_error (xcf_seek_pos (info, offset, error));
 
-      xcf_progress_update (info);
+      xcf_check_error (xcf_save_channel (info, image, channel, error));
 
-      /* seek back to where we are to write out the next
-       *  channel offset and write it out.
-       */
+      offset = info->cp;
       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);
     }
 
   g_list_free (all_layers);
@@ -365,10 +326,7 @@ xcf_save_image (XcfInfo    *info,
   /* 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;
+  xcf_write_int32_check_error (info, &zero, 1);
 
   return !ferror (info->fp);
 }
@@ -976,7 +934,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;
@@ -1023,7 +981,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;
 
@@ -1089,7 +1047,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;
 
@@ -1189,40 +1147,37 @@ xcf_save_layer (XcfInfo    *info,
   /*  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_hierarchy (info,
                                        gimp_drawable_get_tiles (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;
 }
@@ -1264,23 +1219,13 @@ 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_hierarchy (info,
                                        gimp_drawable_get_tiles (GIMP_DRAWABLE (channel)),
                                        error));
 
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
-  saved_pos = info->cp;
-
   return TRUE;
 }
 
@@ -1331,11 +1276,14 @@ xcf_save_hierarchy (XcfInfo      *info,
   tmp2 = xcf_calc_levels (height, TILE_HEIGHT);
   nlevels = MAX (tmp1, tmp2);
 
-  xcf_check_error (xcf_seek_pos (info, info->cp + (1 + nlevels) * 4, error));
+  offset = info->cp + (1 + nlevels) * 4;
 
   for (i = 0; i < nlevels; i++)
     {
-      offset = info->cp;
+      xcf_write_int32_check_error (info, &offset, 1);
+
+      saved_pos = info->cp;
+      xcf_check_error (xcf_seek_pos (info, offset, error));
 
       if (i == 0)
         {
@@ -1353,29 +1301,15 @@ xcf_save_hierarchy (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.
-       */
+      offset = info->cp;
       xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-      xcf_write_int32_check_error (info, &offset, 1);
-
-      /* increment the location we are to write out the
-       *  next offset.
-       */
-      saved_pos = info->cp;
-
-      /* seek to the end of the file which is where
-       *  we will write out the next level.
-       */
-      xcf_check_error (xcf_seek_end (info, error));
     }
 
   /* write out a '0' offset position to indicate the end
    *  of the level offsets.
    */
-  offset = 0;
-  xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-  xcf_write_int32_check_error (info, &offset, 1);
+  xcf_write_int32_check_error (info, &zero, 1);
+  xcf_check_error (xcf_seek_pos (info, offset, error));
 
   return TRUE;
 }
@@ -1401,24 +1335,21 @@ xcf_save_level (XcfInfo      *info,
   xcf_write_int32_check_error (info, (guint32 *) &width, 1);
   xcf_write_int32_check_error (info, (guint32 *) &height, 1);
 
-  saved_pos = info->cp;
-
   /* allocate a temporary buffer to store the rle data before it is
      written to disk */
   rlebuf =
     g_malloc (TILE_WIDTH * TILE_HEIGHT * tile_manager_bpp (level) * 1.5);
+  ntiles = level->ntile_rows * level->ntile_cols;
+  offset = info->cp + (ntiles + 1) * 4;
 
   if (level->tiles)
     {
-      ntiles = level->ntile_rows * level->ntile_cols;
-      xcf_check_error (xcf_seek_pos (info, info->cp + (ntiles + 1) * 4, error));
-
       for (i = 0; i < ntiles; i++)
         {
-          /* save the start offset of where we are writing
-           *  out the next tile.
-           */
-          offset = info->cp;
+          xcf_write_int32_check_error (info, &offset, 1);
+
+          saved_pos = info->cp;
+          xcf_check_error (xcf_seek_pos (info, offset, error));
 
           /* write out the tile. */
           switch (info->compression)
@@ -1438,21 +1369,8 @@ xcf_save_level (XcfInfo      *info,
               break;
             }
 
-          /* seek back to where we are to write out the next
-           *  tile offset and write it out.
-           */
+          offset = info->cp;
           xcf_check_error (xcf_seek_pos (info, saved_pos, error));
-          xcf_write_int32_check_error (info, &offset, 1);
-
-          /* increment the location we are to write out the
-           *  next offset.
-           */
-          saved_pos = info->cp;
-
-          /* seek to the end of the file which is where
-           *  we will write out the next tile.
-           */
-          xcf_check_error (xcf_seek_end (info, error));
         }
     }
 
@@ -1461,12 +1379,10 @@ xcf_save_level (XcfInfo      *info,
   /* 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);
+  xcf_write_int32_check_error (info, &zero, 1);
+  xcf_check_error (xcf_seek_pos (info, offset, error));
 
   return TRUE;
-
 }
 
 static gboolean


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