PIKApp/app/tests/test-xcf.c

1048 lines
37 KiB
C

/* PIKA - Photo and Image Kooker Application
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
*
* Original copyright, applying to most contents (license remains unchanged):
* 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>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef G_OS_WIN32
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <io.h>
#endif
#include <gegl.h>
#include <gtk/gtk.h>
#include "libpikabase/pikabase.h"
#include "widgets/widgets-types.h"
#include "widgets/pikauimanager.h"
#include "core/pika.h"
#include "core/pikachannel.h"
#include "core/pikachannel-select.h"
#include "core/pikadrawable.h"
#include "core/pikagrid.h"
#include "core/pikagrouplayer.h"
#include "core/pikaguide.h"
#include "core/pikaimage.h"
#include "core/pikaimage-grid.h"
#include "core/pikaimage-guides.h"
#include "core/pikaimage-sample-points.h"
#include "core/pikalayer.h"
#include "core/pikalayer-new.h"
#include "core/pikasamplepoint.h"
#include "core/pikaselection.h"
#include "vectors/pikaanchor.h"
#include "vectors/pikabezierstroke.h"
#include "vectors/pikavectors.h"
#include "plug-in/pikapluginmanager-file.h"
#include "file/file-open.h"
#include "file/file-save.h"
#include "tests.h"
#include "pika-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/pika-2-6-file.xcf which can't have any non-LEGACY modes
*/
#define PIKA_MAINIMAGE_WIDTH 100
#define PIKA_MAINIMAGE_HEIGHT 90
#define PIKA_MAINIMAGE_TYPE PIKA_RGB
#define PIKA_MAINIMAGE_PRECISION PIKA_PRECISION_U8_NON_LINEAR
#define PIKA_MAINIMAGE_LAYER1_NAME "layer1"
#define PIKA_MAINIMAGE_LAYER1_WIDTH 50
#define PIKA_MAINIMAGE_LAYER1_HEIGHT 51
#define PIKA_MAINIMAGE_LAYER1_FORMAT babl_format ("R'G'B'A u8")
#define PIKA_MAINIMAGE_LAYER1_OPACITY PIKA_OPACITY_OPAQUE
#define PIKA_MAINIMAGE_LAYER1_MODE PIKA_LAYER_MODE_NORMAL_LEGACY
#define PIKA_MAINIMAGE_LAYER2_NAME "layer2"
#define PIKA_MAINIMAGE_LAYER2_WIDTH 25
#define PIKA_MAINIMAGE_LAYER2_HEIGHT 251
#define PIKA_MAINIMAGE_LAYER2_FORMAT babl_format ("R'G'B' u8")
#define PIKA_MAINIMAGE_LAYER2_OPACITY PIKA_OPACITY_TRANSPARENT
#define PIKA_MAINIMAGE_LAYER2_MODE PIKA_LAYER_MODE_MULTIPLY_LEGACY
#define PIKA_MAINIMAGE_GROUP1_NAME "group1"
#define PIKA_MAINIMAGE_LAYER3_NAME "layer3"
#define PIKA_MAINIMAGE_LAYER4_NAME "layer4"
#define PIKA_MAINIMAGE_GROUP2_NAME "group2"
#define PIKA_MAINIMAGE_LAYER5_NAME "layer5"
#define PIKA_MAINIMAGE_VGUIDE1_POS 42
#define PIKA_MAINIMAGE_VGUIDE2_POS 82
#define PIKA_MAINIMAGE_HGUIDE1_POS 3
#define PIKA_MAINIMAGE_HGUIDE2_POS 4
#define PIKA_MAINIMAGE_SAMPLEPOINT1_X 10
#define PIKA_MAINIMAGE_SAMPLEPOINT1_Y 12
#define PIKA_MAINIMAGE_SAMPLEPOINT2_X 41
#define PIKA_MAINIMAGE_SAMPLEPOINT2_Y 49
#define PIKA_MAINIMAGE_RESOLUTIONX 400
#define PIKA_MAINIMAGE_RESOLUTIONY 410
#define PIKA_MAINIMAGE_PARASITE_NAME "test-parasite"
#define PIKA_MAINIMAGE_PARASITE_DATA "foo"
#define PIKA_MAINIMAGE_PARASITE_SIZE 4 /* 'f' 'o' 'o' '\0' */
#define PIKA_MAINIMAGE_COMMENT "Created with code from "\
"app/tests/test-xcf.c in the PIKA "\
"source tree, i.e. it was not created "\
"manually and may thus look weird if "\
"opened and inspected in PIKA."
#define PIKA_MAINIMAGE_UNIT PIKA_UNIT_PICA
#define PIKA_MAINIMAGE_GRIDXSPACING 25.0
#define PIKA_MAINIMAGE_GRIDYSPACING 27.0
#define PIKA_MAINIMAGE_CHANNEL1_NAME "channel1"
#define PIKA_MAINIMAGE_CHANNEL1_WIDTH PIKA_MAINIMAGE_WIDTH
#define PIKA_MAINIMAGE_CHANNEL1_HEIGHT PIKA_MAINIMAGE_HEIGHT
#define PIKA_MAINIMAGE_CHANNEL1_COLOR { 1.0, 0.0, 1.0, 1.0 }
#define PIKA_MAINIMAGE_SELECTION_X 5
#define PIKA_MAINIMAGE_SELECTION_Y 6
#define PIKA_MAINIMAGE_SELECTION_W 7
#define PIKA_MAINIMAGE_SELECTION_H 8
#define PIKA_MAINIMAGE_VECTORS1_NAME "vectors1"
#define PIKA_MAINIMAGE_VECTORS1_COORDS { { 11.0, 12.0, /* pad zeroes */ },\
{ 21.0, 22.0, /* pad zeroes */ },\
{ 31.0, 32.0, /* pad zeroes */ }, }
#define PIKA_MAINIMAGE_VECTORS2_NAME "vectors2"
#define PIKA_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 ("/pika-xcf/" #function, pika, function);
PikaImage * pika_test_load_image (Pika *pika,
GFile *file);
static void pika_write_and_read_file (Pika *pika,
gboolean with_unusual_stuff,
gboolean compat_paths,
gboolean use_pika_2_8_features);
static PikaImage * pika_create_mainimage (Pika *pika,
gboolean with_unusual_stuff,
gboolean compat_paths,
gboolean use_pika_2_8_features);
static void pika_assert_mainimage (PikaImage *image,
gboolean with_unusual_stuff,
gboolean compat_paths,
gboolean use_pika_2_8_features);
/**
* write_and_read_pika_2_6_format:
* @data:
*
* Do a write and read test on a file that could as well be
* constructed with PIKA 2.6.
**/
static void
write_and_read_pika_2_6_format (gconstpointer data)
{
Pika *pika = PIKA (data);
pika_write_and_read_file (pika,
FALSE /*with_unusual_stuff*/,
FALSE /*compat_paths*/,
FALSE /*use_pika_2_8_features*/);
}
/**
* write_and_read_pika_2_6_format_unusual:
* @data:
*
* Do a write and read test on a file that could as well be
* constructed with PIKA 2.6, and make it unusual, like compatible
* vectors and with a floating selection.
**/
static void
write_and_read_pika_2_6_format_unusual (gconstpointer data)
{
Pika *pika = PIKA (data);
pika_write_and_read_file (pika,
TRUE /*with_unusual_stuff*/,
TRUE /*compat_paths*/,
FALSE /*use_pika_2_8_features*/);
}
/**
* load_pika_2_6_file:
* @data:
*
* Loads a file created with PIKA 2.6 and makes sure it loaded as
* expected.
**/
static void
load_pika_2_6_file (gconstpointer data)
{
Pika *pika = PIKA (data);
PikaImage *image;
gchar *filename;
GFile *file;
filename = g_build_filename (g_getenv ("PIKA_TESTING_ABS_TOP_SRCDIR"),
"app/tests/files/pika-2-6-file.xcf",
NULL);
file = g_file_new_for_path (filename);
g_free (filename);
image = pika_test_load_image (pika, file);
/* The image file was constructed by running
* pika_write_and_read_file (FALSE, FALSE) in PIKA 2.6 by
* copy-pasting the code to PIKA 2.6 and adapting it to changes in
* the core API, so we can use pika_assert_mainimage() to make sure
* the file was loaded successfully.
*/
pika_assert_mainimage (image,
FALSE /*with_unusual_stuff*/,
FALSE /*compat_paths*/,
FALSE /*use_pika_2_8_features*/);
}
/**
* write_and_read_pika_2_8_format:
* @data:
*
* Writes an XCF file that uses PIKA 2.8 features such as layer
* groups, then reads the file and make sure no relevant information
* was lost.
**/
static void
write_and_read_pika_2_8_format (gconstpointer data)
{
Pika *pika = PIKA (data);
pika_write_and_read_file (pika,
FALSE /*with_unusual_stuff*/,
FALSE /*compat_paths*/,
TRUE /*use_pika_2_8_features*/);
}
PikaImage *
pika_test_load_image (Pika *pika,
GFile *file)
{
PikaPlugInProcedure *proc;
PikaImage *image;
PikaPDBStatusType unused;
proc = pika_plug_in_manager_file_procedure_find (pika->plug_in_manager,
PIKA_FILE_PROCEDURE_GROUP_OPEN,
file,
NULL /*error*/);
image = file_open_image (pika,
pika_get_user_context (pika),
NULL /*progress*/,
file,
FALSE /*as_new*/,
proc,
PIKA_RUN_NONINTERACTIVE,
&unused /*status*/,
NULL /*mime_type*/,
NULL /*error*/);
return image;
}
/**
* pika_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
pika_write_and_read_file (Pika *pika,
gboolean with_unusual_stuff,
gboolean compat_paths,
gboolean use_pika_2_8_features)
{
PikaImage *image;
PikaImage *loaded_image;
PikaPlugInProcedure *proc;
gchar *filename = NULL;
gint file_handle;
GFile *file;
/* Create the image */
image = pika_create_mainimage (pika,
with_unusual_stuff,
compat_paths,
use_pika_2_8_features);
/* Assert valid state */
pika_assert_mainimage (image,
with_unusual_stuff,
compat_paths,
use_pika_2_8_features);
/* Write to file */
file_handle = g_file_open_tmp ("pika-test-XXXXXX.xcf", &filename, NULL);
g_assert (file_handle != -1);
close (file_handle);
file = g_file_new_for_path (filename);
g_free (filename);
proc = pika_plug_in_manager_file_procedure_find (image->pika->plug_in_manager,
PIKA_FILE_PROCEDURE_GROUP_SAVE,
file,
NULL /*error*/);
file_save (pika,
image,
NULL /*progress*/,
file,
proc,
PIKA_RUN_NONINTERACTIVE,
FALSE /*change_saved_state*/,
FALSE /*export_backward*/,
FALSE /*export_forward*/,
NULL /*error*/);
/* Load from file */
loaded_image = pika_test_load_image (image->pika, 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
*/
pika_assert_mainimage (loaded_image,
with_unusual_stuff,
compat_paths,
use_pika_2_8_features);
g_file_delete (file, NULL, NULL);
g_object_unref (file);
}
/**
* pika_create_mainimage:
*
* Creates the main test image, i.e. the image that we use for most of
* our XCF testing purposes.
*
* Returns: The #PikaImage
**/
static PikaImage *
pika_create_mainimage (Pika *pika,
gboolean with_unusual_stuff,
gboolean compat_paths,
gboolean use_pika_2_8_features)
{
PikaImage *image = NULL;
PikaLayer *layer = NULL;
PikaParasite *parasite = NULL;
PikaGrid *grid = NULL;
PikaChannel *channel = NULL;
PikaRGB channel_color = PIKA_MAINIMAGE_CHANNEL1_COLOR;
PikaChannel *selection = NULL;
PikaVectors *vectors = NULL;
PikaCoords vectors1_coords[] = PIKA_MAINIMAGE_VECTORS1_COORDS;
PikaCoords vectors2_coords[] = PIKA_MAINIMAGE_VECTORS2_COORDS;
PikaStroke *stroke = NULL;
PikaLayerMask *layer_mask = NULL;
/* Image size and type */
image = pika_image_new (pika,
PIKA_MAINIMAGE_WIDTH,
PIKA_MAINIMAGE_HEIGHT,
PIKA_MAINIMAGE_TYPE,
PIKA_MAINIMAGE_PRECISION);
/* Layers */
layer = pika_layer_new (image,
PIKA_MAINIMAGE_LAYER1_WIDTH,
PIKA_MAINIMAGE_LAYER1_HEIGHT,
PIKA_MAINIMAGE_LAYER1_FORMAT,
PIKA_MAINIMAGE_LAYER1_NAME,
PIKA_MAINIMAGE_LAYER1_OPACITY,
PIKA_MAINIMAGE_LAYER1_MODE);
pika_image_add_layer (image,
layer,
NULL,
0,
FALSE/*push_undo*/);
layer = pika_layer_new (image,
PIKA_MAINIMAGE_LAYER2_WIDTH,
PIKA_MAINIMAGE_LAYER2_HEIGHT,
PIKA_MAINIMAGE_LAYER2_FORMAT,
PIKA_MAINIMAGE_LAYER2_NAME,
PIKA_MAINIMAGE_LAYER2_OPACITY,
PIKA_MAINIMAGE_LAYER2_MODE);
pika_image_add_layer (image,
layer,
NULL,
0,
FALSE /*push_undo*/);
/* Layer mask */
layer_mask = pika_layer_create_mask (layer,
PIKA_ADD_MASK_BLACK,
NULL /*channel*/);
pika_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 */
pika_image_add_hguide (image,
PIKA_MAINIMAGE_HGUIDE2_POS,
FALSE /*push_undo*/);
pika_image_add_hguide (image,
PIKA_MAINIMAGE_HGUIDE1_POS,
FALSE /*push_undo*/);
pika_image_add_vguide (image,
PIKA_MAINIMAGE_VGUIDE2_POS,
FALSE /*push_undo*/);
pika_image_add_vguide (image,
PIKA_MAINIMAGE_VGUIDE1_POS,
FALSE /*push_undo*/);
/* Sample points */
pika_image_add_sample_point_at_pos (image,
PIKA_MAINIMAGE_SAMPLEPOINT1_X,
PIKA_MAINIMAGE_SAMPLEPOINT1_Y,
FALSE /*push_undo*/);
pika_image_add_sample_point_at_pos (image,
PIKA_MAINIMAGE_SAMPLEPOINT2_X,
PIKA_MAINIMAGE_SAMPLEPOINT2_Y,
FALSE /*push_undo*/);
/* Tattoo
* We don't bother testing this, not yet at least
*/
/* Resolution */
pika_image_set_resolution (image,
PIKA_MAINIMAGE_RESOLUTIONX,
PIKA_MAINIMAGE_RESOLUTIONY);
/* Parasites */
parasite = pika_parasite_new (PIKA_MAINIMAGE_PARASITE_NAME,
PIKA_PARASITE_PERSISTENT,
PIKA_MAINIMAGE_PARASITE_SIZE,
PIKA_MAINIMAGE_PARASITE_DATA);
pika_image_parasite_attach (image,
parasite, FALSE);
pika_parasite_free (parasite);
parasite = pika_parasite_new ("pika-comment",
PIKA_PARASITE_PERSISTENT,
strlen (PIKA_MAINIMAGE_COMMENT) + 1,
PIKA_MAINIMAGE_COMMENT);
pika_image_parasite_attach (image, parasite, FALSE);
pika_parasite_free (parasite);
/* Unit */
pika_image_set_unit (image,
PIKA_MAINIMAGE_UNIT);
/* Grid */
grid = g_object_new (PIKA_TYPE_GRID,
"xspacing", PIKA_MAINIMAGE_GRIDXSPACING,
"yspacing", PIKA_MAINIMAGE_GRIDYSPACING,
NULL);
pika_image_set_grid (image,
grid,
FALSE /*push_undo*/);
g_object_unref (grid);
/* Channel */
channel = pika_channel_new (image,
PIKA_MAINIMAGE_CHANNEL1_WIDTH,
PIKA_MAINIMAGE_CHANNEL1_HEIGHT,
PIKA_MAINIMAGE_CHANNEL1_NAME,
&channel_color);
pika_image_add_channel (image,
channel,
NULL,
-1,
FALSE /*push_undo*/);
/* Selection */
selection = pika_image_get_mask (image);
pika_channel_select_rectangle (selection,
PIKA_MAINIMAGE_SELECTION_X,
PIKA_MAINIMAGE_SELECTION_Y,
PIKA_MAINIMAGE_SELECTION_W,
PIKA_MAINIMAGE_SELECTION_H,
PIKA_CHANNEL_OP_REPLACE,
FALSE /*feather*/,
0.0 /*feather_radius_x*/,
0.0 /*feather_radius_y*/,
FALSE /*push_undo*/);
/* Vectors 1 */
vectors = pika_vectors_new (image,
PIKA_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. pika_vectors_compat_is_compatible() must return both TRUE
* and FALSE.
*/
if (! compat_paths)
{
pika_item_set_visible (PIKA_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 = pika_bezier_stroke_new_from_coords (vectors1_coords,
G_N_ELEMENTS (vectors1_coords),
TRUE /*closed*/);
pika_vectors_stroke_add (vectors, stroke);
pika_image_add_vectors (image,
vectors,
NULL /*parent*/,
-1 /*position*/,
FALSE /*push_undo*/);
/* Vectors 2 */
vectors = pika_vectors_new (image,
PIKA_MAINIMAGE_VECTORS2_NAME);
stroke = pika_bezier_stroke_new_from_coords (vectors2_coords,
G_N_ELEMENTS (vectors2_coords),
TRUE /*closed*/);
pika_vectors_stroke_add (vectors, stroke);
pika_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)
{
GList *drawables;
drawables = pika_image_get_selected_drawables (image);
/* Floating selection */
pika_selection_float (PIKA_SELECTION (pika_image_get_mask (image)),
drawables,
pika_get_user_context (pika),
TRUE /*cut_image*/,
0 /*off_x*/,
0 /*off_y*/,
NULL /*error*/);
g_list_free (drawables);
}
/* Adds stuff like layer groups */
if (use_pika_2_8_features)
{
PikaLayer *parent;
/* Add a layer group and some layers:
*
* group1
* layer3
* layer4
* group2
* layer5
*/
/* group1 */
layer = pika_group_layer_new (image);
pika_object_set_name (PIKA_OBJECT (layer), PIKA_MAINIMAGE_GROUP1_NAME);
pika_image_add_layer (image,
layer,
NULL /*parent*/,
-1 /*position*/,
FALSE /*push_undo*/);
parent = layer;
/* layer3 */
layer = pika_layer_new (image,
PIKA_MAINIMAGE_LAYER1_WIDTH,
PIKA_MAINIMAGE_LAYER1_HEIGHT,
PIKA_MAINIMAGE_LAYER1_FORMAT,
PIKA_MAINIMAGE_LAYER3_NAME,
PIKA_MAINIMAGE_LAYER1_OPACITY,
PIKA_MAINIMAGE_LAYER1_MODE);
pika_image_add_layer (image,
layer,
parent,
-1 /*position*/,
FALSE /*push_undo*/);
/* layer4 */
layer = pika_layer_new (image,
PIKA_MAINIMAGE_LAYER1_WIDTH,
PIKA_MAINIMAGE_LAYER1_HEIGHT,
PIKA_MAINIMAGE_LAYER1_FORMAT,
PIKA_MAINIMAGE_LAYER4_NAME,
PIKA_MAINIMAGE_LAYER1_OPACITY,
PIKA_MAINIMAGE_LAYER1_MODE);
pika_image_add_layer (image,
layer,
parent,
-1 /*position*/,
FALSE /*push_undo*/);
/* group2 */
layer = pika_group_layer_new (image);
pika_object_set_name (PIKA_OBJECT (layer), PIKA_MAINIMAGE_GROUP2_NAME);
pika_image_add_layer (image,
layer,
parent,
-1 /*position*/,
FALSE /*push_undo*/);
parent = layer;
/* layer5 */
layer = pika_layer_new (image,
PIKA_MAINIMAGE_LAYER1_WIDTH,
PIKA_MAINIMAGE_LAYER1_HEIGHT,
PIKA_MAINIMAGE_LAYER1_FORMAT,
PIKA_MAINIMAGE_LAYER5_NAME,
PIKA_MAINIMAGE_LAYER1_OPACITY,
PIKA_MAINIMAGE_LAYER1_MODE);
pika_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
pika_assert_vectors (PikaImage *image,
const gchar *name,
PikaCoords coords[],
gsize coords_size,
gboolean visible)
{
PikaVectors *vectors = NULL;
PikaStroke *stroke = NULL;
GArray *control_points = NULL;
gboolean closed = FALSE;
gint i = 0;
vectors = pika_image_get_vectors_by_name (image, name);
stroke = pika_vectors_stroke_get_next (vectors, NULL);
g_assert (stroke != NULL);
control_points = pika_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,
PikaAnchor,
i).position.x);
g_assert_cmpint (coords[i].y,
==,
g_array_index (control_points,
PikaAnchor,
i).position.y);
}
g_assert (pika_item_get_visible (PIKA_ITEM (vectors)) ? TRUE : FALSE ==
visible ? TRUE : FALSE);
}
/**
* pika_assert_mainimage:
* @image:
*
* Verifies that the passed #PikaImage contains all the information
* that was put in it by pika_create_mainimage().
**/
static void
pika_assert_mainimage (PikaImage *image,
gboolean with_unusual_stuff,
gboolean compat_paths,
gboolean use_pika_2_8_features)
{
const PikaParasite *parasite = NULL;
gchar *parasite_data = NULL;
guint32 parasite_size = -1;
PikaLayer *layer = NULL;
GList *iter = NULL;
PikaGuide *guide = NULL;
PikaSamplePoint *sample_point = NULL;
gint sample_point_x = 0;
gint sample_point_y = 0;
gdouble xres = 0.0;
gdouble yres = 0.0;
PikaGrid *grid = NULL;
gdouble xspacing = 0.0;
gdouble yspacing = 0.0;
PikaChannel *channel = NULL;
PikaRGB expected_channel_color = PIKA_MAINIMAGE_CHANNEL1_COLOR;
PikaRGB actual_channel_color = { 0, };
PikaChannel *selection = NULL;
gint x = -1;
gint y = -1;
gint w = -1;
gint h = -1;
PikaCoords vectors1_coords[] = PIKA_MAINIMAGE_VECTORS1_COORDS;
PikaCoords vectors2_coords[] = PIKA_MAINIMAGE_VECTORS2_COORDS;
/* Image size and type */
g_assert_cmpint (pika_image_get_width (image),
==,
PIKA_MAINIMAGE_WIDTH);
g_assert_cmpint (pika_image_get_height (image),
==,
PIKA_MAINIMAGE_HEIGHT);
g_assert_cmpint (pika_image_get_base_type (image),
==,
PIKA_MAINIMAGE_TYPE);
/* Layers */
layer = pika_image_get_layer_by_name (image,
PIKA_MAINIMAGE_LAYER1_NAME);
g_assert_cmpint (pika_item_get_width (PIKA_ITEM (layer)),
==,
PIKA_MAINIMAGE_LAYER1_WIDTH);
g_assert_cmpint (pika_item_get_height (PIKA_ITEM (layer)),
==,
PIKA_MAINIMAGE_LAYER1_HEIGHT);
g_assert_cmpstr (babl_get_name (pika_drawable_get_format (PIKA_DRAWABLE (layer))),
==,
babl_get_name (PIKA_MAINIMAGE_LAYER1_FORMAT));
g_assert_cmpstr (pika_object_get_name (PIKA_DRAWABLE (layer)),
==,
PIKA_MAINIMAGE_LAYER1_NAME);
g_assert_cmpfloat (pika_layer_get_opacity (layer),
==,
PIKA_MAINIMAGE_LAYER1_OPACITY);
g_assert_cmpint (pika_layer_get_mode (layer),
==,
PIKA_MAINIMAGE_LAYER1_MODE);
layer = pika_image_get_layer_by_name (image,
PIKA_MAINIMAGE_LAYER2_NAME);
g_assert_cmpint (pika_item_get_width (PIKA_ITEM (layer)),
==,
PIKA_MAINIMAGE_LAYER2_WIDTH);
g_assert_cmpint (pika_item_get_height (PIKA_ITEM (layer)),
==,
PIKA_MAINIMAGE_LAYER2_HEIGHT);
g_assert_cmpstr (babl_get_name (pika_drawable_get_format (PIKA_DRAWABLE (layer))),
==,
babl_get_name (PIKA_MAINIMAGE_LAYER2_FORMAT));
g_assert_cmpstr (pika_object_get_name (PIKA_DRAWABLE (layer)),
==,
PIKA_MAINIMAGE_LAYER2_NAME);
g_assert_cmpfloat (pika_layer_get_opacity (layer),
==,
PIKA_MAINIMAGE_LAYER2_OPACITY);
g_assert_cmpint (pika_layer_get_mode (layer),
==,
PIKA_MAINIMAGE_LAYER2_MODE);
/* Guides, note that we rely on internal ordering */
iter = pika_image_get_guides (image);
g_assert (iter != NULL);
guide = iter->data;
g_assert_cmpint (pika_guide_get_position (guide),
==,
PIKA_MAINIMAGE_VGUIDE1_POS);
iter = g_list_next (iter);
g_assert (iter != NULL);
guide = iter->data;
g_assert_cmpint (pika_guide_get_position (guide),
==,
PIKA_MAINIMAGE_VGUIDE2_POS);
iter = g_list_next (iter);
g_assert (iter != NULL);
guide = iter->data;
g_assert_cmpint (pika_guide_get_position (guide),
==,
PIKA_MAINIMAGE_HGUIDE1_POS);
iter = g_list_next (iter);
g_assert (iter != NULL);
guide = iter->data;
g_assert_cmpint (pika_guide_get_position (guide),
==,
PIKA_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 = pika_image_get_sample_points (image);
g_assert (iter != NULL);
sample_point = iter->data;
pika_sample_point_get_position (sample_point,
&sample_point_x, &sample_point_y);
g_assert_cmpint (sample_point_x,
==,
PIKA_MAINIMAGE_SAMPLEPOINT1_X);
g_assert_cmpint (sample_point_y,
==,
PIKA_MAINIMAGE_SAMPLEPOINT1_Y);
iter = g_list_next (iter);
g_assert (iter != NULL);
sample_point = iter->data;
pika_sample_point_get_position (sample_point,
&sample_point_x, &sample_point_y);
g_assert_cmpint (sample_point_x,
==,
PIKA_MAINIMAGE_SAMPLEPOINT2_X);
g_assert_cmpint (sample_point_y,
==,
PIKA_MAINIMAGE_SAMPLEPOINT2_Y);
iter = g_list_next (iter);
g_assert (iter == NULL);
/* Resolution */
pika_image_get_resolution (image, &xres, &yres);
g_assert_cmpint (xres,
==,
PIKA_MAINIMAGE_RESOLUTIONX);
g_assert_cmpint (yres,
==,
PIKA_MAINIMAGE_RESOLUTIONY);
/* Parasites */
parasite = pika_image_parasite_find (image,
PIKA_MAINIMAGE_PARASITE_NAME);
parasite_data = (gchar *) pika_parasite_get_data (parasite, &parasite_size);
parasite_data = g_strndup (parasite_data, parasite_size);
g_assert_cmpint (parasite_size,
==,
PIKA_MAINIMAGE_PARASITE_SIZE);
g_assert_cmpstr (parasite_data,
==,
PIKA_MAINIMAGE_PARASITE_DATA);
g_free (parasite_data);
parasite = pika_image_parasite_find (image,
"pika-comment");
parasite_data = (gchar *) pika_parasite_get_data (parasite, &parasite_size);
parasite_data = g_strndup (parasite_data, parasite_size);
g_assert_cmpint (parasite_size,
==,
strlen (PIKA_MAINIMAGE_COMMENT) + 1);
g_assert_cmpstr (parasite_data,
==,
PIKA_MAINIMAGE_COMMENT);
g_free (parasite_data);
/* Unit */
g_assert_cmpint (pika_image_get_unit (image),
==,
PIKA_MAINIMAGE_UNIT);
/* Grid */
grid = pika_image_get_grid (image);
g_object_get (grid,
"xspacing", &xspacing,
"yspacing", &yspacing,
NULL);
g_assert_cmpint (xspacing,
==,
PIKA_MAINIMAGE_GRIDXSPACING);
g_assert_cmpint (yspacing,
==,
PIKA_MAINIMAGE_GRIDYSPACING);
/* Channel */
channel = pika_image_get_channel_by_name (image,
PIKA_MAINIMAGE_CHANNEL1_NAME);
pika_channel_get_color (channel, &actual_channel_color);
g_assert_cmpint (pika_item_get_width (PIKA_ITEM (channel)),
==,
PIKA_MAINIMAGE_CHANNEL1_WIDTH);
g_assert_cmpint (pika_item_get_height (PIKA_ITEM (channel)),
==,
PIKA_MAINIMAGE_CHANNEL1_HEIGHT);
g_assert (memcmp (&expected_channel_color,
&actual_channel_color,
sizeof (PikaRGB)) == 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 = pika_image_get_mask (image);
pika_item_bounds (PIKA_ITEM (selection), &x, &y, &w, &h);
g_assert_cmpint (x,
==,
PIKA_MAINIMAGE_SELECTION_X);
g_assert_cmpint (y,
==,
PIKA_MAINIMAGE_SELECTION_Y);
g_assert_cmpint (w,
==,
PIKA_MAINIMAGE_SELECTION_W);
g_assert_cmpint (h,
==,
PIKA_MAINIMAGE_SELECTION_H);
}
/* Vectors 1 */
pika_assert_vectors (image,
PIKA_MAINIMAGE_VECTORS1_NAME,
vectors1_coords,
G_N_ELEMENTS (vectors1_coords),
! compat_paths /*visible*/);
/* Vectors 2 (always visible FALSE) */
pika_assert_vectors (image,
PIKA_MAINIMAGE_VECTORS2_NAME,
vectors2_coords,
G_N_ELEMENTS (vectors2_coords),
FALSE /*visible*/);
if (with_unusual_stuff)
g_assert (pika_image_get_floating_selection (image) != NULL);
else /* if (! with_unusual_stuff) */
g_assert (pika_image_get_floating_selection (image) == NULL);
if (use_pika_2_8_features)
{
/* Only verify the parent relationships, the layer attributes
* are tested above
*/
PikaItem *group1 = PIKA_ITEM (pika_image_get_layer_by_name (image, PIKA_MAINIMAGE_GROUP1_NAME));
PikaItem *layer3 = PIKA_ITEM (pika_image_get_layer_by_name (image, PIKA_MAINIMAGE_LAYER3_NAME));
PikaItem *layer4 = PIKA_ITEM (pika_image_get_layer_by_name (image, PIKA_MAINIMAGE_LAYER4_NAME));
PikaItem *group2 = PIKA_ITEM (pika_image_get_layer_by_name (image, PIKA_MAINIMAGE_GROUP2_NAME));
PikaItem *layer5 = PIKA_ITEM (pika_image_get_layer_by_name (image, PIKA_MAINIMAGE_LAYER5_NAME));
g_assert (pika_item_get_parent (group1) == NULL);
g_assert (pika_item_get_parent (layer3) == group1);
g_assert (pika_item_get_parent (layer4) == group1);
g_assert (pika_item_get_parent (group2) == group1);
g_assert (pika_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 PIKA, i.e. that we can load files from earlier
* version of PIKA
*
* - Make sure that the information put into a #PikaImage is not lost
* when the #PikaImage is written to a file and then read again
**/
int
main (int argc,
char **argv)
{
Pika *pika;
int result;
g_test_init (&argc, &argv, NULL);
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_SRCDIR",
"app/tests/pikadir");
/* We share the same application instance across all tests. We need
* the GUI variant for the file procs
*/
pika = pika_init_for_testing ();
/* Add tests */
ADD_TEST (write_and_read_pika_2_6_format);
ADD_TEST (write_and_read_pika_2_6_format_unusual);
ADD_TEST (load_pika_2_6_file);
ADD_TEST (write_and_read_pika_2_8_format);
/* Don't write files to the source dir */
pika_test_utils_set_pika3_directory ("PIKA_TESTING_ABS_TOP_BUILDDIR",
"app/tests/pikadir-output");
/* Run the tests */
result = g_test_run ();
/* Exit so we don't break script-fu plug-in wire */
pika_exit (pika, TRUE);
return result;
}