diff --git a/app/core/gimplayer-xcf.c b/app/core/gimplayer-xcf.c new file mode 100644 index 0000000000..c2fdf951b4 --- /dev/null +++ b/app/core/gimplayer-xcf.c @@ -0,0 +1,111 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimplayer-xcf.c + * + * Copyright 2003 Sven Neumann + * Copyright 2025 Jehan + * + * 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 . + */ + +#include "config.h" + +#include + +#include "core-types.h" + +#include "gimpimage.h" +#include "gimplayer.h" +#include "gimplayer-xcf.h" + +/** + * gimp_layer_from_layer: + * @layer: a #GimpLayer object + * @options: a #GimpVectorLayerOptions object + * + * Converts a standard #GimpLayer into a more specific type of + * #GimpLayer. The new layer takes ownership of properties of @layer. + * The @layer object is rendered unusable by this function. Don't even + * try to use it afterwards! + * + * This is a gross hack that is needed in order to load text or vector + * layers from XCF files in a backwards-compatible way, or as a + * secondary step (after more data has been loaded). Please don't use it + * for anything else! + * + * The variable list of arguments will be the properties which will be + * used to create the new layer of type @new_layer_type. Note that the + * "image" property needs to be set at the minimum. + * + * Return value: a newly allocated object of a subtype of #GimpLayer. + **/ +GimpLayer * +gimp_layer_from_layer (GimpLayer *layer, + GType new_layer_type, + ...) +{ + GimpLayer *new_layer; + GimpDrawable *drawable; + GimpImage *image; + gboolean attached; + GimpLayer *parent = NULL; + gint position = 0; + va_list args; + const gchar *first_prop; + + g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL); + g_return_val_if_fail (g_type_is_a (new_layer_type, GIMP_TYPE_LAYER), NULL); + + image = gimp_item_get_image (GIMP_ITEM (layer)); + + if ((attached = gimp_item_is_attached (GIMP_ITEM (layer)))) + { + parent = gimp_layer_get_parent (layer); + position = gimp_item_get_index (GIMP_ITEM (layer)); + + g_object_ref (layer); + gimp_image_remove_layer (image, layer, FALSE, NULL); + } + + va_start (args, new_layer_type); + first_prop = va_arg (args, gchar *); + new_layer = GIMP_LAYER (g_object_new_valist (new_layer_type, first_prop, args)); + va_end (args); + + gimp_item_replace_item (GIMP_ITEM (new_layer), GIMP_ITEM (layer)); + + drawable = GIMP_DRAWABLE (new_layer); + gimp_drawable_steal_buffer (drawable, GIMP_DRAWABLE (layer)); + + gimp_layer_set_opacity (GIMP_LAYER (new_layer), + gimp_layer_get_opacity (layer), FALSE); + gimp_layer_set_mode (GIMP_LAYER (new_layer), + gimp_layer_get_mode (layer), FALSE); + gimp_layer_set_blend_space (GIMP_LAYER (new_layer), + gimp_layer_get_blend_space (layer), FALSE); + gimp_layer_set_composite_space (GIMP_LAYER (new_layer), + gimp_layer_get_composite_space (layer), FALSE); + gimp_layer_set_composite_mode (GIMP_LAYER (new_layer), + gimp_layer_get_composite_mode (layer), FALSE); + gimp_layer_set_lock_alpha (GIMP_LAYER (new_layer), + gimp_layer_get_lock_alpha (layer), FALSE); + + g_object_unref (layer); + + if (attached) + gimp_image_add_layer (image, new_layer, parent, position, FALSE); + + return new_layer; +} diff --git a/app/core/gimplayer-xcf.h b/app/core/gimplayer-xcf.h new file mode 100644 index 0000000000..cb4c7843f2 --- /dev/null +++ b/app/core/gimplayer-xcf.h @@ -0,0 +1,27 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimplayer-xcf.h + * + * Copyright 2003 Sven Neumann + * Copyright 2025 Jehan + * + * 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 . + */ + +#pragma once + +GimpLayer * gimp_layer_from_layer (GimpLayer *layer, + GType new_layer_type, + ...) G_GNUC_NULL_TERMINATED; diff --git a/app/core/meson.build b/app/core/meson.build index 40db629f0b..31b1aaaa87 100644 --- a/app/core/meson.build +++ b/app/core/meson.build @@ -185,6 +185,7 @@ libappcore_sources = [ 'gimpitemundo.c', 'gimplayer-floating-selection.c', 'gimplayer-new.c', + 'gimplayer-xcf.c', 'gimplayer.c', 'gimplayermask.c', 'gimplayermaskpropundo.c', diff --git a/app/text/gimptextlayer-xcf.c b/app/text/gimptextlayer-xcf.c index bcff068c94..8bb315fe9d 100644 --- a/app/text/gimptextlayer-xcf.c +++ b/app/text/gimptextlayer-xcf.c @@ -30,6 +30,7 @@ #include "core/gimp.h" #include "core/gimpdrawable-private.h" /* eek */ #include "core/gimpimage.h" +#include "core/gimplayer-xcf.h" #include "core/gimpparasitelist.h" #include "gimptext.h" @@ -48,10 +49,6 @@ enum }; -static GimpLayer * gimp_text_layer_from_layer (GimpLayer *layer, - GimpText *text); - - gboolean gimp_text_layer_xcf_load_hack (GimpLayer **layer) { @@ -105,7 +102,11 @@ gimp_text_layer_xcf_load_hack (GimpLayer **layer) if (text) { - *layer = gimp_text_layer_from_layer (*layer, text); + *layer = gimp_layer_from_layer (*layer, GIMP_TYPE_TEXT_LAYER, + "image", gimp_item_get_image (GIMP_ITEM (*layer)), + NULL); + gimp_text_layer_set_text (GIMP_TEXT_LAYER (*layer), text); + g_object_unref (text); /* let the text layer knows what parasite was used to create it */ GIMP_TEXT_LAYER (*layer)->text_parasite = name; @@ -169,61 +170,3 @@ gimp_text_layer_set_xcf_flags (GimpTextLayer *text_layer, "modified", (flags & TEXT_LAYER_XCF_MODIFIED) != 0, NULL); } - - -/** - * gimp_text_layer_from_layer: - * @layer: a #GimpLayer object - * @text: a #GimpText object - * - * Converts a standard #GimpLayer and a #GimpText object into a - * #GimpTextLayer. The new text layer takes ownership of the @text and - * @layer objects. The @layer object is rendered unusable by this - * function. Don't even try to use if afterwards! - * - * This is a gross hack that is needed in order to load text layers - * from XCF files in a backwards-compatible way. Please don't use it - * for anything else! - * - * Returns: a newly allocated #GimpTextLayer object - **/ -static GimpLayer * -gimp_text_layer_from_layer (GimpLayer *layer, - GimpText *text) -{ - GimpTextLayer *text_layer; - GimpDrawable *drawable; - - g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL); - g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); - - text_layer = g_object_new (GIMP_TYPE_TEXT_LAYER, - "image", gimp_item_get_image (GIMP_ITEM (layer)), - NULL); - - gimp_item_replace_item (GIMP_ITEM (text_layer), GIMP_ITEM (layer)); - - drawable = GIMP_DRAWABLE (text_layer); - - gimp_drawable_steal_buffer (drawable, GIMP_DRAWABLE (layer)); - - gimp_layer_set_opacity (GIMP_LAYER (text_layer), - gimp_layer_get_opacity (layer), FALSE); - gimp_layer_set_mode (GIMP_LAYER (text_layer), - gimp_layer_get_mode (layer), FALSE); - gimp_layer_set_blend_space (GIMP_LAYER (text_layer), - gimp_layer_get_blend_space (layer), FALSE); - gimp_layer_set_composite_space (GIMP_LAYER (text_layer), - gimp_layer_get_composite_space (layer), FALSE); - gimp_layer_set_composite_mode (GIMP_LAYER (text_layer), - gimp_layer_get_composite_mode (layer), FALSE); - gimp_layer_set_lock_alpha (GIMP_LAYER (text_layer), - gimp_layer_get_lock_alpha (layer), FALSE); - - gimp_text_layer_set_text (text_layer, text); - - g_object_unref (text); - g_object_unref (layer); - - return GIMP_LAYER (text_layer); -}