summaryrefslogtreecommitdiffstats
path: root/app/tests/test-xcf.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/tests/test-xcf.c')
-rw-r--r--app/tests/test-xcf.c1016
1 files changed, 1016 insertions, 0 deletions
diff --git a/app/tests/test-xcf.c b/app/tests/test-xcf.c
new file mode 100644
index 0000000..1ce7b08
--- /dev/null
+++ b/app/tests/test-xcf.c
@@ -0,0 +1,1016 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 2009 Martin Nordholts
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+
+#include "widgets/widgets-types.h"
+
+#include "widgets/gimpuimanager.h"
+
+#include "core/gimp.h"
+#include "core/gimpchannel.h"
+#include "core/gimpchannel-select.h"
+#include "core/gimpdrawable.h"
+#include "core/gimpgrid.h"
+#include "core/gimpgrouplayer.h"
+#include "core/gimpguide.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-grid.h"
+#include "core/gimpimage-guides.h"
+#include "core/gimpimage-sample-points.h"
+#include "core/gimplayer.h"
+#include "core/gimplayer-new.h"
+#include "core/gimpsamplepoint.h"
+#include "core/gimpselection.h"
+
+#include "vectors/gimpanchor.h"
+#include "vectors/gimpbezierstroke.h"
+#include "vectors/gimpvectors.h"
+
+#include "plug-in/gimppluginmanager-file.h"
+
+#include "file/file-open.h"
+#include "file/file-save.h"
+
+#include "tests.h"
+
+#include "gimp-app-test-utils.h"
+
+
+/* we continue to use LEGACY layers for testing, so we can use the
+ * same test image for all tests, including loading
+ * files/gimp-2-6-file.xcf which can't have any non-LEGACY modes
+ */
+
+#define GIMP_MAINIMAGE_WIDTH 100
+#define GIMP_MAINIMAGE_HEIGHT 90
+#define GIMP_MAINIMAGE_TYPE GIMP_RGB
+#define GIMP_MAINIMAGE_PRECISION GIMP_PRECISION_U8_GAMMA
+
+#define GIMP_MAINIMAGE_LAYER1_NAME "layer1"
+#define GIMP_MAINIMAGE_LAYER1_WIDTH 50
+#define GIMP_MAINIMAGE_LAYER1_HEIGHT 51
+#define GIMP_MAINIMAGE_LAYER1_FORMAT babl_format ("R'G'B'A u8")
+#define GIMP_MAINIMAGE_LAYER1_OPACITY GIMP_OPACITY_OPAQUE
+#define GIMP_MAINIMAGE_LAYER1_MODE GIMP_LAYER_MODE_NORMAL_LEGACY
+
+#define GIMP_MAINIMAGE_LAYER2_NAME "layer2"
+#define GIMP_MAINIMAGE_LAYER2_WIDTH 25
+#define GIMP_MAINIMAGE_LAYER2_HEIGHT 251
+#define GIMP_MAINIMAGE_LAYER2_FORMAT babl_format ("R'G'B' u8")
+#define GIMP_MAINIMAGE_LAYER2_OPACITY GIMP_OPACITY_TRANSPARENT
+#define GIMP_MAINIMAGE_LAYER2_MODE GIMP_LAYER_MODE_MULTIPLY_LEGACY
+
+#define GIMP_MAINIMAGE_GROUP1_NAME "group1"
+
+#define GIMP_MAINIMAGE_LAYER3_NAME "layer3"
+
+#define GIMP_MAINIMAGE_LAYER4_NAME "layer4"
+
+#define GIMP_MAINIMAGE_GROUP2_NAME "group2"
+
+#define GIMP_MAINIMAGE_LAYER5_NAME "layer5"
+
+#define GIMP_MAINIMAGE_VGUIDE1_POS 42
+#define GIMP_MAINIMAGE_VGUIDE2_POS 82
+#define GIMP_MAINIMAGE_HGUIDE1_POS 3
+#define GIMP_MAINIMAGE_HGUIDE2_POS 4
+
+#define GIMP_MAINIMAGE_SAMPLEPOINT1_X 10
+#define GIMP_MAINIMAGE_SAMPLEPOINT1_Y 12
+#define GIMP_MAINIMAGE_SAMPLEPOINT2_X 41
+#define GIMP_MAINIMAGE_SAMPLEPOINT2_Y 49
+
+#define GIMP_MAINIMAGE_RESOLUTIONX 400
+#define GIMP_MAINIMAGE_RESOLUTIONY 410
+
+#define GIMP_MAINIMAGE_PARASITE_NAME "test-parasite"
+#define GIMP_MAINIMAGE_PARASITE_DATA "foo"
+#define GIMP_MAINIMAGE_PARASITE_SIZE 4 /* 'f' 'o' 'o' '\0' */
+
+#define GIMP_MAINIMAGE_COMMENT "Created with code from "\
+ "app/tests/test-xcf.c in the GIMP "\
+ "source tree, i.e. it was not created "\
+ "manually and may thus look weird if "\
+ "opened and inspected in GIMP."
+
+#define GIMP_MAINIMAGE_UNIT GIMP_UNIT_PICA
+
+#define GIMP_MAINIMAGE_GRIDXSPACING 25.0
+#define GIMP_MAINIMAGE_GRIDYSPACING 27.0
+
+#define GIMP_MAINIMAGE_CHANNEL1_NAME "channel1"
+#define GIMP_MAINIMAGE_CHANNEL1_WIDTH GIMP_MAINIMAGE_WIDTH
+#define GIMP_MAINIMAGE_CHANNEL1_HEIGHT GIMP_MAINIMAGE_HEIGHT
+#define GIMP_MAINIMAGE_CHANNEL1_COLOR { 1.0, 0.0, 1.0, 1.0 }
+
+#define GIMP_MAINIMAGE_SELECTION_X 5
+#define GIMP_MAINIMAGE_SELECTION_Y 6
+#define GIMP_MAINIMAGE_SELECTION_W 7
+#define GIMP_MAINIMAGE_SELECTION_H 8
+
+#define GIMP_MAINIMAGE_VECTORS1_NAME "vectors1"
+#define GIMP_MAINIMAGE_VECTORS1_COORDS { { 11.0, 12.0, /* pad zeroes */ },\
+ { 21.0, 22.0, /* pad zeroes */ },\
+ { 31.0, 32.0, /* pad zeroes */ }, }
+
+#define GIMP_MAINIMAGE_VECTORS2_NAME "vectors2"
+#define GIMP_MAINIMAGE_VECTORS2_COORDS { { 911.0, 912.0, /* pad zeroes */ },\
+ { 921.0, 922.0, /* pad zeroes */ },\
+ { 931.0, 932.0, /* pad zeroes */ }, }
+
+#define ADD_TEST(function) \
+ g_test_add_data_func ("/gimp-xcf/" #function, gimp, function);
+
+
+GimpImage * gimp_test_load_image (Gimp *gimp,
+ GFile *file);
+static void gimp_write_and_read_file (Gimp *gimp,
+ gboolean with_unusual_stuff,
+ gboolean compat_paths,
+ gboolean use_gimp_2_8_features);
+static GimpImage * gimp_create_mainimage (Gimp *gimp,
+ gboolean with_unusual_stuff,
+ gboolean compat_paths,
+ gboolean use_gimp_2_8_features);
+static void gimp_assert_mainimage (GimpImage *image,
+ gboolean with_unusual_stuff,
+ gboolean compat_paths,
+ gboolean use_gimp_2_8_features);
+
+
+/**
+ * write_and_read_gimp_2_6_format:
+ * @data:
+ *
+ * Do a write and read test on a file that could as well be
+ * constructed with GIMP 2.6.
+ **/
+static void
+write_and_read_gimp_2_6_format (gconstpointer data)
+{
+ Gimp *gimp = GIMP (data);
+
+ gimp_write_and_read_file (gimp,
+ FALSE /*with_unusual_stuff*/,
+ FALSE /*compat_paths*/,
+ FALSE /*use_gimp_2_8_features*/);
+}
+
+/**
+ * write_and_read_gimp_2_6_format_unusual:
+ * @data:
+ *
+ * Do a write and read test on a file that could as well be
+ * constructed with GIMP 2.6, and make it unusual, like compatible
+ * vectors and with a floating selection.
+ **/
+static void
+write_and_read_gimp_2_6_format_unusual (gconstpointer data)
+{
+ Gimp *gimp = GIMP (data);
+
+ gimp_write_and_read_file (gimp,
+ TRUE /*with_unusual_stuff*/,
+ TRUE /*compat_paths*/,
+ FALSE /*use_gimp_2_8_features*/);
+}
+
+/**
+ * load_gimp_2_6_file:
+ * @data:
+ *
+ * Loads a file created with GIMP 2.6 and makes sure it loaded as
+ * expected.
+ **/
+static void
+load_gimp_2_6_file (gconstpointer data)
+{
+ Gimp *gimp = GIMP (data);
+ GimpImage *image;
+ gchar *filename;
+ GFile *file;
+
+ filename = g_build_filename (g_getenv ("GIMP_TESTING_ABS_TOP_SRCDIR"),
+ "app/tests/files/gimp-2-6-file.xcf",
+ NULL);
+ file = g_file_new_for_path (filename);
+ g_free (filename);
+
+ image = gimp_test_load_image (gimp, file);
+
+ /* The image file was constructed by running
+ * gimp_write_and_read_file (FALSE, FALSE) in GIMP 2.6 by
+ * copy-pasting the code to GIMP 2.6 and adapting it to changes in
+ * the core API, so we can use gimp_assert_mainimage() to make sure
+ * the file was loaded successfully.
+ */
+ gimp_assert_mainimage (image,
+ FALSE /*with_unusual_stuff*/,
+ FALSE /*compat_paths*/,
+ FALSE /*use_gimp_2_8_features*/);
+}
+
+/**
+ * write_and_read_gimp_2_8_format:
+ * @data:
+ *
+ * Writes an XCF file that uses GIMP 2.8 features such as layer
+ * groups, then reads the file and make sure no relevant information
+ * was lost.
+ **/
+static void
+write_and_read_gimp_2_8_format (gconstpointer data)
+{
+ Gimp *gimp = GIMP (data);
+
+ gimp_write_and_read_file (gimp,
+ FALSE /*with_unusual_stuff*/,
+ FALSE /*compat_paths*/,
+ TRUE /*use_gimp_2_8_features*/);
+}
+
+GimpImage *
+gimp_test_load_image (Gimp *gimp,
+ GFile *file)
+{
+ GimpPlugInProcedure *proc;
+ GimpImage *image;
+ GimpPDBStatusType unused;
+
+ proc = gimp_plug_in_manager_file_procedure_find (gimp->plug_in_manager,
+ GIMP_FILE_PROCEDURE_GROUP_OPEN,
+ file,
+ NULL /*error*/);
+ image = file_open_image (gimp,
+ gimp_get_user_context (gimp),
+ NULL /*progress*/,
+ file,
+ file,
+ FALSE /*as_new*/,
+ proc,
+ GIMP_RUN_NONINTERACTIVE,
+ &unused /*status*/,
+ NULL /*mime_type*/,
+ NULL /*error*/);
+
+ return image;
+}
+
+/**
+ * gimp_write_and_read_file:
+ *
+ * Constructs the main test image and asserts its state, writes it to
+ * a file, reads the image from the file, and asserts the state of the
+ * loaded file. The function takes various parameters so the same
+ * function can be used for different formats.
+ **/
+static void
+gimp_write_and_read_file (Gimp *gimp,
+ gboolean with_unusual_stuff,
+ gboolean compat_paths,
+ gboolean use_gimp_2_8_features)
+{
+ GimpImage *image;
+ GimpImage *loaded_image;
+ GimpPlugInProcedure *proc;
+ gchar *filename;
+ GFile *file;
+
+ /* Create the image */
+ image = gimp_create_mainimage (gimp,
+ with_unusual_stuff,
+ compat_paths,
+ use_gimp_2_8_features);
+
+ /* Assert valid state */
+ gimp_assert_mainimage (image,
+ with_unusual_stuff,
+ compat_paths,
+ use_gimp_2_8_features);
+
+ /* Write to file */
+ filename = g_build_filename (g_get_tmp_dir (), "gimp-test.xcf", NULL);
+ file = g_file_new_for_path (filename);
+ g_free (filename);
+
+ proc = gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager,
+ GIMP_FILE_PROCEDURE_GROUP_SAVE,
+ file,
+ NULL /*error*/);
+ file_save (gimp,
+ image,
+ NULL /*progress*/,
+ file,
+ proc,
+ GIMP_RUN_NONINTERACTIVE,
+ FALSE /*change_saved_state*/,
+ FALSE /*export_backward*/,
+ FALSE /*export_forward*/,
+ NULL /*error*/);
+
+ /* Load from file */
+ loaded_image = gimp_test_load_image (image->gimp, file);
+
+ /* Assert on the loaded file. If success, it means that there is no
+ * significant information loss when we wrote the image to a file
+ * and loaded it again
+ */
+ gimp_assert_mainimage (loaded_image,
+ with_unusual_stuff,
+ compat_paths,
+ use_gimp_2_8_features);
+
+ g_file_delete (file, NULL, NULL);
+ g_object_unref (file);
+}
+
+/**
+ * gimp_create_mainimage:
+ *
+ * Creates the main test image, i.e. the image that we use for most of
+ * our XCF testing purposes.
+ *
+ * Returns: The #GimpImage
+ **/
+static GimpImage *
+gimp_create_mainimage (Gimp *gimp,
+ gboolean with_unusual_stuff,
+ gboolean compat_paths,
+ gboolean use_gimp_2_8_features)
+{
+ GimpImage *image = NULL;
+ GimpLayer *layer = NULL;
+ GimpParasite *parasite = NULL;
+ GimpGrid *grid = NULL;
+ GimpChannel *channel = NULL;
+ GimpRGB channel_color = GIMP_MAINIMAGE_CHANNEL1_COLOR;
+ GimpChannel *selection = NULL;
+ GimpVectors *vectors = NULL;
+ GimpCoords vectors1_coords[] = GIMP_MAINIMAGE_VECTORS1_COORDS;
+ GimpCoords vectors2_coords[] = GIMP_MAINIMAGE_VECTORS2_COORDS;
+ GimpStroke *stroke = NULL;
+ GimpLayerMask *layer_mask = NULL;
+
+ /* Image size and type */
+ image = gimp_image_new (gimp,
+ GIMP_MAINIMAGE_WIDTH,
+ GIMP_MAINIMAGE_HEIGHT,
+ GIMP_MAINIMAGE_TYPE,
+ GIMP_MAINIMAGE_PRECISION);
+
+ /* Layers */
+ layer = gimp_layer_new (image,
+ GIMP_MAINIMAGE_LAYER1_WIDTH,
+ GIMP_MAINIMAGE_LAYER1_HEIGHT,
+ GIMP_MAINIMAGE_LAYER1_FORMAT,
+ GIMP_MAINIMAGE_LAYER1_NAME,
+ GIMP_MAINIMAGE_LAYER1_OPACITY,
+ GIMP_MAINIMAGE_LAYER1_MODE);
+ gimp_image_add_layer (image,
+ layer,
+ NULL,
+ 0,
+ FALSE/*push_undo*/);
+ layer = gimp_layer_new (image,
+ GIMP_MAINIMAGE_LAYER2_WIDTH,
+ GIMP_MAINIMAGE_LAYER2_HEIGHT,
+ GIMP_MAINIMAGE_LAYER2_FORMAT,
+ GIMP_MAINIMAGE_LAYER2_NAME,
+ GIMP_MAINIMAGE_LAYER2_OPACITY,
+ GIMP_MAINIMAGE_LAYER2_MODE);
+ gimp_image_add_layer (image,
+ layer,
+ NULL,
+ 0,
+ FALSE /*push_undo*/);
+
+ /* Layer mask */
+ layer_mask = gimp_layer_create_mask (layer,
+ GIMP_ADD_MASK_BLACK,
+ NULL /*channel*/);
+ gimp_layer_add_mask (layer,
+ layer_mask,
+ FALSE /*push_undo*/,
+ NULL /*error*/);
+
+ /* Image compression type
+ *
+ * We don't do any explicit test, only implicit when we read tile
+ * data in other tests
+ */
+
+ /* Guides, note we add them in reversed order */
+ gimp_image_add_hguide (image,
+ GIMP_MAINIMAGE_HGUIDE2_POS,
+ FALSE /*push_undo*/);
+ gimp_image_add_hguide (image,
+ GIMP_MAINIMAGE_HGUIDE1_POS,
+ FALSE /*push_undo*/);
+ gimp_image_add_vguide (image,
+ GIMP_MAINIMAGE_VGUIDE2_POS,
+ FALSE /*push_undo*/);
+ gimp_image_add_vguide (image,
+ GIMP_MAINIMAGE_VGUIDE1_POS,
+ FALSE /*push_undo*/);
+
+
+ /* Sample points */
+ gimp_image_add_sample_point_at_pos (image,
+ GIMP_MAINIMAGE_SAMPLEPOINT1_X,
+ GIMP_MAINIMAGE_SAMPLEPOINT1_Y,
+ FALSE /*push_undo*/);
+ gimp_image_add_sample_point_at_pos (image,
+ GIMP_MAINIMAGE_SAMPLEPOINT2_X,
+ GIMP_MAINIMAGE_SAMPLEPOINT2_Y,
+ FALSE /*push_undo*/);
+
+ /* Tattoo
+ * We don't bother testing this, not yet at least
+ */
+
+ /* Resolution */
+ gimp_image_set_resolution (image,
+ GIMP_MAINIMAGE_RESOLUTIONX,
+ GIMP_MAINIMAGE_RESOLUTIONY);
+
+
+ /* Parasites */
+ parasite = gimp_parasite_new (GIMP_MAINIMAGE_PARASITE_NAME,
+ GIMP_PARASITE_PERSISTENT,
+ GIMP_MAINIMAGE_PARASITE_SIZE,
+ GIMP_MAINIMAGE_PARASITE_DATA);
+ gimp_image_parasite_attach (image,
+ parasite, TRUE);
+ gimp_parasite_free (parasite);
+ parasite = gimp_parasite_new ("gimp-comment",
+ GIMP_PARASITE_PERSISTENT,
+ strlen (GIMP_MAINIMAGE_COMMENT) + 1,
+ GIMP_MAINIMAGE_COMMENT);
+ gimp_image_parasite_attach (image, parasite, TRUE);
+ gimp_parasite_free (parasite);
+
+
+ /* Unit */
+ gimp_image_set_unit (image,
+ GIMP_MAINIMAGE_UNIT);
+
+ /* Grid */
+ grid = g_object_new (GIMP_TYPE_GRID,
+ "xspacing", GIMP_MAINIMAGE_GRIDXSPACING,
+ "yspacing", GIMP_MAINIMAGE_GRIDYSPACING,
+ NULL);
+ gimp_image_set_grid (image,
+ grid,
+ FALSE /*push_undo*/);
+ g_object_unref (grid);
+
+ /* Channel */
+ channel = gimp_channel_new (image,
+ GIMP_MAINIMAGE_CHANNEL1_WIDTH,
+ GIMP_MAINIMAGE_CHANNEL1_HEIGHT,
+ GIMP_MAINIMAGE_CHANNEL1_NAME,
+ &channel_color);
+ gimp_image_add_channel (image,
+ channel,
+ NULL,
+ -1,
+ FALSE /*push_undo*/);
+
+ /* Selection */
+ selection = gimp_image_get_mask (image);
+ gimp_channel_select_rectangle (selection,
+ GIMP_MAINIMAGE_SELECTION_X,
+ GIMP_MAINIMAGE_SELECTION_Y,
+ GIMP_MAINIMAGE_SELECTION_W,
+ GIMP_MAINIMAGE_SELECTION_H,
+ GIMP_CHANNEL_OP_REPLACE,
+ FALSE /*feather*/,
+ 0.0 /*feather_radius_x*/,
+ 0.0 /*feather_radius_y*/,
+ FALSE /*push_undo*/);
+
+ /* Vectors 1 */
+ vectors = gimp_vectors_new (image,
+ GIMP_MAINIMAGE_VECTORS1_NAME);
+ /* The XCF file can save vectors in two kind of ways, one old way
+ * and a new way. Parameterize the way so we can test both variants,
+ * i.e. gimp_vectors_compat_is_compatible() must return both TRUE
+ * and FALSE.
+ */
+ if (! compat_paths)
+ {
+ gimp_item_set_visible (GIMP_ITEM (vectors),
+ TRUE,
+ FALSE /*push_undo*/);
+ }
+ /* TODO: Add test for non-closed stroke. The order of the anchor
+ * points changes for open strokes, so it's boring to test
+ */
+ stroke = gimp_bezier_stroke_new_from_coords (vectors1_coords,
+ G_N_ELEMENTS (vectors1_coords),
+ TRUE /*closed*/);
+ gimp_vectors_stroke_add (vectors, stroke);
+ gimp_image_add_vectors (image,
+ vectors,
+ NULL /*parent*/,
+ -1 /*position*/,
+ FALSE /*push_undo*/);
+
+ /* Vectors 2 */
+ vectors = gimp_vectors_new (image,
+ GIMP_MAINIMAGE_VECTORS2_NAME);
+
+ stroke = gimp_bezier_stroke_new_from_coords (vectors2_coords,
+ G_N_ELEMENTS (vectors2_coords),
+ TRUE /*closed*/);
+ gimp_vectors_stroke_add (vectors, stroke);
+ gimp_image_add_vectors (image,
+ vectors,
+ NULL /*parent*/,
+ -1 /*position*/,
+ FALSE /*push_undo*/);
+
+ /* Some of these things are pretty unusual, parameterize the
+ * inclusion of this in the written file so we can do our test both
+ * with and without
+ */
+ if (with_unusual_stuff)
+ {
+ /* Floating selection */
+ gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
+ gimp_image_get_active_drawable (image),
+ gimp_get_user_context (gimp),
+ TRUE /*cut_image*/,
+ 0 /*off_x*/,
+ 0 /*off_y*/,
+ NULL /*error*/);
+ }
+
+ /* Adds stuff like layer groups */
+ if (use_gimp_2_8_features)
+ {
+ GimpLayer *parent;
+
+ /* Add a layer group and some layers:
+ *
+ * group1
+ * layer3
+ * layer4
+ * group2
+ * layer5
+ */
+
+ /* group1 */
+ layer = gimp_group_layer_new (image);
+ gimp_object_set_name (GIMP_OBJECT (layer), GIMP_MAINIMAGE_GROUP1_NAME);
+ gimp_image_add_layer (image,
+ layer,
+ NULL /*parent*/,
+ -1 /*position*/,
+ FALSE /*push_undo*/);
+ parent = layer;
+
+ /* layer3 */
+ layer = gimp_layer_new (image,
+ GIMP_MAINIMAGE_LAYER1_WIDTH,
+ GIMP_MAINIMAGE_LAYER1_HEIGHT,
+ GIMP_MAINIMAGE_LAYER1_FORMAT,
+ GIMP_MAINIMAGE_LAYER3_NAME,
+ GIMP_MAINIMAGE_LAYER1_OPACITY,
+ GIMP_MAINIMAGE_LAYER1_MODE);
+ gimp_image_add_layer (image,
+ layer,
+ parent,
+ -1 /*position*/,
+ FALSE /*push_undo*/);
+
+ /* layer4 */
+ layer = gimp_layer_new (image,
+ GIMP_MAINIMAGE_LAYER1_WIDTH,
+ GIMP_MAINIMAGE_LAYER1_HEIGHT,
+ GIMP_MAINIMAGE_LAYER1_FORMAT,
+ GIMP_MAINIMAGE_LAYER4_NAME,
+ GIMP_MAINIMAGE_LAYER1_OPACITY,
+ GIMP_MAINIMAGE_LAYER1_MODE);
+ gimp_image_add_layer (image,
+ layer,
+ parent,
+ -1 /*position*/,
+ FALSE /*push_undo*/);
+
+ /* group2 */
+ layer = gimp_group_layer_new (image);
+ gimp_object_set_name (GIMP_OBJECT (layer), GIMP_MAINIMAGE_GROUP2_NAME);
+ gimp_image_add_layer (image,
+ layer,
+ parent,
+ -1 /*position*/,
+ FALSE /*push_undo*/);
+ parent = layer;
+
+ /* layer5 */
+ layer = gimp_layer_new (image,
+ GIMP_MAINIMAGE_LAYER1_WIDTH,
+ GIMP_MAINIMAGE_LAYER1_HEIGHT,
+ GIMP_MAINIMAGE_LAYER1_FORMAT,
+ GIMP_MAINIMAGE_LAYER5_NAME,
+ GIMP_MAINIMAGE_LAYER1_OPACITY,
+ GIMP_MAINIMAGE_LAYER1_MODE);
+ gimp_image_add_layer (image,
+ layer,
+ parent,
+ -1 /*position*/,
+ FALSE /*push_undo*/);
+ }
+
+ /* Todo, should be tested somehow:
+ *
+ * - Color maps
+ * - Custom user units
+ * - Text layers
+ * - Layer parasites
+ * - Channel parasites
+ * - Different tile compression methods
+ */
+
+ return image;
+}
+
+static void
+gimp_assert_vectors (GimpImage *image,
+ const gchar *name,
+ GimpCoords coords[],
+ gsize coords_size,
+ gboolean visible)
+{
+ GimpVectors *vectors = NULL;
+ GimpStroke *stroke = NULL;
+ GArray *control_points = NULL;
+ gboolean closed = FALSE;
+ gint i = 0;
+
+ vectors = gimp_image_get_vectors_by_name (image, name);
+ stroke = gimp_vectors_stroke_get_next (vectors, NULL);
+ g_assert (stroke != NULL);
+ control_points = gimp_stroke_control_points_get (stroke,
+ &closed);
+ g_assert (closed);
+ g_assert_cmpint (control_points->len,
+ ==,
+ coords_size);
+ for (i = 0; i < control_points->len; i++)
+ {
+ g_assert_cmpint (coords[i].x,
+ ==,
+ g_array_index (control_points,
+ GimpAnchor,
+ i).position.x);
+ g_assert_cmpint (coords[i].y,
+ ==,
+ g_array_index (control_points,
+ GimpAnchor,
+ i).position.y);
+ }
+
+ g_assert (gimp_item_get_visible (GIMP_ITEM (vectors)) ? TRUE : FALSE ==
+ visible ? TRUE : FALSE);
+}
+
+/**
+ * gimp_assert_mainimage:
+ * @image:
+ *
+ * Verifies that the passed #GimpImage contains all the information
+ * that was put in it by gimp_create_mainimage().
+ **/
+static void
+gimp_assert_mainimage (GimpImage *image,
+ gboolean with_unusual_stuff,
+ gboolean compat_paths,
+ gboolean use_gimp_2_8_features)
+{
+ const GimpParasite *parasite = NULL;
+ GimpLayer *layer = NULL;
+ GList *iter = NULL;
+ GimpGuide *guide = NULL;
+ GimpSamplePoint *sample_point = NULL;
+ gint sample_point_x = 0;
+ gint sample_point_y = 0;
+ gdouble xres = 0.0;
+ gdouble yres = 0.0;
+ GimpGrid *grid = NULL;
+ gdouble xspacing = 0.0;
+ gdouble yspacing = 0.0;
+ GimpChannel *channel = NULL;
+ GimpRGB expected_channel_color = GIMP_MAINIMAGE_CHANNEL1_COLOR;
+ GimpRGB actual_channel_color = { 0, };
+ GimpChannel *selection = NULL;
+ gint x = -1;
+ gint y = -1;
+ gint w = -1;
+ gint h = -1;
+ GimpCoords vectors1_coords[] = GIMP_MAINIMAGE_VECTORS1_COORDS;
+ GimpCoords vectors2_coords[] = GIMP_MAINIMAGE_VECTORS2_COORDS;
+
+ /* Image size and type */
+ g_assert_cmpint (gimp_image_get_width (image),
+ ==,
+ GIMP_MAINIMAGE_WIDTH);
+ g_assert_cmpint (gimp_image_get_height (image),
+ ==,
+ GIMP_MAINIMAGE_HEIGHT);
+ g_assert_cmpint (gimp_image_get_base_type (image),
+ ==,
+ GIMP_MAINIMAGE_TYPE);
+
+ /* Layers */
+ layer = gimp_image_get_layer_by_name (image,
+ GIMP_MAINIMAGE_LAYER1_NAME);
+ g_assert_cmpint (gimp_item_get_width (GIMP_ITEM (layer)),
+ ==,
+ GIMP_MAINIMAGE_LAYER1_WIDTH);
+ g_assert_cmpint (gimp_item_get_height (GIMP_ITEM (layer)),
+ ==,
+ GIMP_MAINIMAGE_LAYER1_HEIGHT);
+ g_assert_cmpstr (babl_get_name (gimp_drawable_get_format (GIMP_DRAWABLE (layer))),
+ ==,
+ babl_get_name (GIMP_MAINIMAGE_LAYER1_FORMAT));
+ g_assert_cmpstr (gimp_object_get_name (GIMP_DRAWABLE (layer)),
+ ==,
+ GIMP_MAINIMAGE_LAYER1_NAME);
+ g_assert_cmpfloat (gimp_layer_get_opacity (layer),
+ ==,
+ GIMP_MAINIMAGE_LAYER1_OPACITY);
+ g_assert_cmpint (gimp_layer_get_mode (layer),
+ ==,
+ GIMP_MAINIMAGE_LAYER1_MODE);
+ layer = gimp_image_get_layer_by_name (image,
+ GIMP_MAINIMAGE_LAYER2_NAME);
+ g_assert_cmpint (gimp_item_get_width (GIMP_ITEM (layer)),
+ ==,
+ GIMP_MAINIMAGE_LAYER2_WIDTH);
+ g_assert_cmpint (gimp_item_get_height (GIMP_ITEM (layer)),
+ ==,
+ GIMP_MAINIMAGE_LAYER2_HEIGHT);
+ g_assert_cmpstr (babl_get_name (gimp_drawable_get_format (GIMP_DRAWABLE (layer))),
+ ==,
+ babl_get_name (GIMP_MAINIMAGE_LAYER2_FORMAT));
+ g_assert_cmpstr (gimp_object_get_name (GIMP_DRAWABLE (layer)),
+ ==,
+ GIMP_MAINIMAGE_LAYER2_NAME);
+ g_assert_cmpfloat (gimp_layer_get_opacity (layer),
+ ==,
+ GIMP_MAINIMAGE_LAYER2_OPACITY);
+ g_assert_cmpint (gimp_layer_get_mode (layer),
+ ==,
+ GIMP_MAINIMAGE_LAYER2_MODE);
+
+ /* Guides, note that we rely on internal ordering */
+ iter = gimp_image_get_guides (image);
+ g_assert (iter != NULL);
+ guide = iter->data;
+ g_assert_cmpint (gimp_guide_get_position (guide),
+ ==,
+ GIMP_MAINIMAGE_VGUIDE1_POS);
+ iter = g_list_next (iter);
+ g_assert (iter != NULL);
+ guide = iter->data;
+ g_assert_cmpint (gimp_guide_get_position (guide),
+ ==,
+ GIMP_MAINIMAGE_VGUIDE2_POS);
+ iter = g_list_next (iter);
+ g_assert (iter != NULL);
+ guide = iter->data;
+ g_assert_cmpint (gimp_guide_get_position (guide),
+ ==,
+ GIMP_MAINIMAGE_HGUIDE1_POS);
+ iter = g_list_next (iter);
+ g_assert (iter != NULL);
+ guide = iter->data;
+ g_assert_cmpint (gimp_guide_get_position (guide),
+ ==,
+ GIMP_MAINIMAGE_HGUIDE2_POS);
+ iter = g_list_next (iter);
+ g_assert (iter == NULL);
+
+ /* Sample points, we rely on the same ordering as when we added
+ * them, although this ordering is not a necessity
+ */
+ iter = gimp_image_get_sample_points (image);
+ g_assert (iter != NULL);
+ sample_point = iter->data;
+ gimp_sample_point_get_position (sample_point,
+ &sample_point_x, &sample_point_y);
+ g_assert_cmpint (sample_point_x,
+ ==,
+ GIMP_MAINIMAGE_SAMPLEPOINT1_X);
+ g_assert_cmpint (sample_point_y,
+ ==,
+ GIMP_MAINIMAGE_SAMPLEPOINT1_Y);
+ iter = g_list_next (iter);
+ g_assert (iter != NULL);
+ sample_point = iter->data;
+ gimp_sample_point_get_position (sample_point,
+ &sample_point_x, &sample_point_y);
+ g_assert_cmpint (sample_point_x,
+ ==,
+ GIMP_MAINIMAGE_SAMPLEPOINT2_X);
+ g_assert_cmpint (sample_point_y,
+ ==,
+ GIMP_MAINIMAGE_SAMPLEPOINT2_Y);
+ iter = g_list_next (iter);
+ g_assert (iter == NULL);
+
+ /* Resolution */
+ gimp_image_get_resolution (image, &xres, &yres);
+ g_assert_cmpint (xres,
+ ==,
+ GIMP_MAINIMAGE_RESOLUTIONX);
+ g_assert_cmpint (yres,
+ ==,
+ GIMP_MAINIMAGE_RESOLUTIONY);
+
+ /* Parasites */
+ parasite = gimp_image_parasite_find (image,
+ GIMP_MAINIMAGE_PARASITE_NAME);
+ g_assert_cmpint (gimp_parasite_data_size (parasite),
+ ==,
+ GIMP_MAINIMAGE_PARASITE_SIZE);
+ g_assert_cmpstr (gimp_parasite_data (parasite),
+ ==,
+ GIMP_MAINIMAGE_PARASITE_DATA);
+ parasite = gimp_image_parasite_find (image,
+ "gimp-comment");
+ g_assert_cmpint (gimp_parasite_data_size (parasite),
+ ==,
+ strlen (GIMP_MAINIMAGE_COMMENT) + 1);
+ g_assert_cmpstr (gimp_parasite_data (parasite),
+ ==,
+ GIMP_MAINIMAGE_COMMENT);
+
+ /* Unit */
+ g_assert_cmpint (gimp_image_get_unit (image),
+ ==,
+ GIMP_MAINIMAGE_UNIT);
+
+ /* Grid */
+ grid = gimp_image_get_grid (image);
+ g_object_get (grid,
+ "xspacing", &xspacing,
+ "yspacing", &yspacing,
+ NULL);
+ g_assert_cmpint (xspacing,
+ ==,
+ GIMP_MAINIMAGE_GRIDXSPACING);
+ g_assert_cmpint (yspacing,
+ ==,
+ GIMP_MAINIMAGE_GRIDYSPACING);
+
+
+ /* Channel */
+ channel = gimp_image_get_channel_by_name (image,
+ GIMP_MAINIMAGE_CHANNEL1_NAME);
+ gimp_channel_get_color (channel, &actual_channel_color);
+ g_assert_cmpint (gimp_item_get_width (GIMP_ITEM (channel)),
+ ==,
+ GIMP_MAINIMAGE_CHANNEL1_WIDTH);
+ g_assert_cmpint (gimp_item_get_height (GIMP_ITEM (channel)),
+ ==,
+ GIMP_MAINIMAGE_CHANNEL1_HEIGHT);
+ g_assert (memcmp (&expected_channel_color,
+ &actual_channel_color,
+ sizeof (GimpRGB)) == 0);
+
+ /* Selection, if the image contains unusual stuff it contains a
+ * floating select, and when floating a selection, the selection
+ * mask is cleared, so don't test for the presence of the selection
+ * mask in that case
+ */
+ if (! with_unusual_stuff)
+ {
+ selection = gimp_image_get_mask (image);
+ gimp_item_bounds (GIMP_ITEM (selection), &x, &y, &w, &h);
+ g_assert_cmpint (x,
+ ==,
+ GIMP_MAINIMAGE_SELECTION_X);
+ g_assert_cmpint (y,
+ ==,
+ GIMP_MAINIMAGE_SELECTION_Y);
+ g_assert_cmpint (w,
+ ==,
+ GIMP_MAINIMAGE_SELECTION_W);
+ g_assert_cmpint (h,
+ ==,
+ GIMP_MAINIMAGE_SELECTION_H);
+ }
+
+ /* Vectors 1 */
+ gimp_assert_vectors (image,
+ GIMP_MAINIMAGE_VECTORS1_NAME,
+ vectors1_coords,
+ G_N_ELEMENTS (vectors1_coords),
+ ! compat_paths /*visible*/);
+
+ /* Vectors 2 (always visible FALSE) */
+ gimp_assert_vectors (image,
+ GIMP_MAINIMAGE_VECTORS2_NAME,
+ vectors2_coords,
+ G_N_ELEMENTS (vectors2_coords),
+ FALSE /*visible*/);
+
+ if (with_unusual_stuff)
+ g_assert (gimp_image_get_floating_selection (image) != NULL);
+ else /* if (! with_unusual_stuff) */
+ g_assert (gimp_image_get_floating_selection (image) == NULL);
+
+ if (use_gimp_2_8_features)
+ {
+ /* Only verify the parent relationships, the layer attributes
+ * are tested above
+ */
+ GimpItem *group1 = GIMP_ITEM (gimp_image_get_layer_by_name (image, GIMP_MAINIMAGE_GROUP1_NAME));
+ GimpItem *layer3 = GIMP_ITEM (gimp_image_get_layer_by_name (image, GIMP_MAINIMAGE_LAYER3_NAME));
+ GimpItem *layer4 = GIMP_ITEM (gimp_image_get_layer_by_name (image, GIMP_MAINIMAGE_LAYER4_NAME));
+ GimpItem *group2 = GIMP_ITEM (gimp_image_get_layer_by_name (image, GIMP_MAINIMAGE_GROUP2_NAME));
+ GimpItem *layer5 = GIMP_ITEM (gimp_image_get_layer_by_name (image, GIMP_MAINIMAGE_LAYER5_NAME));
+
+ g_assert (gimp_item_get_parent (group1) == NULL);
+ g_assert (gimp_item_get_parent (layer3) == group1);
+ g_assert (gimp_item_get_parent (layer4) == group1);
+ g_assert (gimp_item_get_parent (group2) == group1);
+ g_assert (gimp_item_get_parent (layer5) == group2);
+ }
+}
+
+
+/**
+ * main:
+ * @argc:
+ * @argv:
+ *
+ * These tests intend to
+ *
+ * - Make sure that we are backwards compatible with files created by
+ * older version of GIMP, i.e. that we can load files from earlier
+ * version of GIMP
+ *
+ * - Make sure that the information put into a #GimpImage is not lost
+ * when the #GimpImage is written to a file and then read again
+ **/
+int
+main (int argc,
+ char **argv)
+{
+ Gimp *gimp;
+ int result;
+
+ g_test_init (&argc, &argv, NULL);
+
+ gimp_test_utils_set_gimp2_directory ("GIMP_TESTING_ABS_TOP_SRCDIR",
+ "app/tests/gimpdir");
+
+ /* We share the same application instance across all tests. We need
+ * the GUI variant for the file procs
+ */
+ gimp = gimp_init_for_testing ();
+
+ /* Add tests */
+ ADD_TEST (write_and_read_gimp_2_6_format);
+ ADD_TEST (write_and_read_gimp_2_6_format_unusual);
+ ADD_TEST (load_gimp_2_6_file);
+ ADD_TEST (write_and_read_gimp_2_8_format);
+
+ /* Don't write files to the source dir */
+ gimp_test_utils_set_gimp2_directory ("GIMP_TESTING_ABS_TOP_BUILDDIR",
+ "app/tests/gimpdir-output");
+
+ /* Run the tests */
+ result = g_test_run ();
+
+ /* Exit so we don't break script-fu plug-in wire */
+ gimp_exit (gimp, TRUE);
+
+ return result;
+}