diff options
Diffstat (limited to '')
-rw-r--r-- | app/tests/test-xcf.c | 1016 |
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; +} |