summaryrefslogtreecommitdiffstats
path: root/libgimpbase
diff options
context:
space:
mode:
Diffstat (limited to 'libgimpbase')
-rw-r--r--libgimpbase/Makefile.am264
-rw-r--r--libgimpbase/Makefile.in1660
-rw-r--r--libgimpbase/gimpbase-private.c93
-rw-r--r--libgimpbase/gimpbase-private.h69
-rw-r--r--libgimpbase/gimpbase.def244
-rw-r--r--libgimpbase/gimpbase.h46
-rw-r--r--libgimpbase/gimpbaseenums.c2045
-rw-r--r--libgimpbase/gimpbaseenums.h1558
-rw-r--r--libgimpbase/gimpbasetypes.c244
-rw-r--r--libgimpbase/gimpbasetypes.h113
-rw-r--r--libgimpbase/gimpchecks.c73
-rw-r--r--libgimpbase/gimpchecks.h68
-rw-r--r--libgimpbase/gimpcompatenums.c581
-rw-r--r--libgimpbase/gimpcompatenums.h252
-rw-r--r--libgimpbase/gimpcpuaccel.c531
-rw-r--r--libgimpbase/gimpcpuaccel.h76
-rw-r--r--libgimpbase/gimpdatafiles.c225
-rw-r--r--libgimpbase/gimpdatafiles.h72
-rw-r--r--libgimpbase/gimpenv.c1277
-rw-r--r--libgimpbase/gimpenv.h96
-rw-r--r--libgimpbase/gimplimits.h97
-rw-r--r--libgimpbase/gimpmemsize.c288
-rw-r--r--libgimpbase/gimpmemsize.h68
-rw-r--r--libgimpbase/gimpmetadata.c1796
-rw-r--r--libgimpbase/gimpmetadata.h154
-rw-r--r--libgimpbase/gimpparam.h66
-rw-r--r--libgimpbase/gimpparasite.c352
-rw-r--r--libgimpbase/gimpparasite.h113
-rw-r--r--libgimpbase/gimpparasiteio.c204
-rw-r--r--libgimpbase/gimpparasiteio.h92
-rw-r--r--libgimpbase/gimpprotocol.c1934
-rw-r--r--libgimpbase/gimpprotocol.h245
-rw-r--r--libgimpbase/gimprectangle.c133
-rw-r--r--libgimpbase/gimprectangle.h60
-rw-r--r--libgimpbase/gimpreloc.c435
-rw-r--r--libgimpbase/gimpreloc.h46
-rw-r--r--libgimpbase/gimpsignal.c110
-rw-r--r--libgimpbase/gimpsignal.h48
-rw-r--r--libgimpbase/gimpunit.c755
-rw-r--r--libgimpbase/gimpunit.h110
-rw-r--r--libgimpbase/gimputils.c1603
-rw-r--r--libgimpbase/gimputils.h87
-rw-r--r--libgimpbase/gimpvaluearray.c589
-rw-r--r--libgimpbase/gimpvaluearray.h104
-rw-r--r--libgimpbase/gimpversion.h70
-rw-r--r--libgimpbase/gimpwin32-io.h99
-rw-r--r--libgimpbase/gimpwire.c695
-rw-r--r--libgimpbase/gimpwire.h146
-rw-r--r--libgimpbase/test-cpu-accel.c48
49 files changed, 20134 insertions, 0 deletions
diff --git a/libgimpbase/Makefile.am b/libgimpbase/Makefile.am
new file mode 100644
index 0000000..4214939
--- /dev/null
+++ b/libgimpbase/Makefile.am
@@ -0,0 +1,264 @@
+## Process this file with automake to produce Makefile.in
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+endif
+
+if PLATFORM_OSX
+xobjective_c = "-xobjective-c"
+xobjective_cxx = "-xobjective-c++"
+xnone = "-xnone"
+framework_cocoa = -framework Cocoa
+endif
+
+if OS_WIN32
+ole32_lib = -lole32
+gimpbase_def = gimpbase.def
+libgimpbase_export_symbols = -export-symbols $(srcdir)/gimpbase.def
+
+install-libtool-import-lib:
+ $(INSTALL) .libs/libgimpbase-$(GIMP_API_VERSION).dll.a $(DESTDIR)$(libdir)
+ $(INSTALL) $(srcdir)/gimpbase.def $(DESTDIR)$(libdir)
+
+uninstall-libtool-import-lib:
+ -rm $(DESTDIR)$(libdir)/libgimpbase-$(GIMP_API_VERSION).dll.a
+ -rm $(DESTDIR)$(libdir)/gimpbase.def
+else
+libm = -lm
+install-libtool-import-lib:
+uninstall-libtool-import-lib:
+endif
+
+if MS_LIB_AVAILABLE
+noinst_DATA = gimpbase-$(GIMP_API_VERSION).lib
+
+install-ms-lib:
+ $(INSTALL) gimpbase-$(GIMP_API_VERSION).lib $(DESTDIR)$(libdir)
+
+uninstall-ms-lib:
+ -rm $(DESTDIR)$(libdir)/gimpbase-$(GIMP_API_VERSION).lib
+
+gimpbase-@GIMP_API_VERSION@.lib: gimpbase.def
+ lib -name:libgimpbase-$(GIMP_API_VERSION)-@LT_CURRENT_MINUS_AGE@.dll -def:gimpbase.def -out:$@
+
+else
+install-ms-lib:
+uninstall-ms-lib:
+endif
+
+libgimpbaseincludedir = $(includedir)/gimp-$(GIMP_API_VERSION)/libgimpbase
+
+AM_CPPFLAGS = \
+ -DPREFIX=\""$(prefix)"\" \
+ -DGIMPDIR=\""$(gimpdir)"\" \
+ -DGIMPDATADIR=\""$(gimpdatadir)"\" \
+ -DLOCALEDIR=\""$(gimplocaledir)"\" \
+ -DPLUGINDIR=\""$(gimpplugindir)"\" \
+ -DGIMPSYSCONFDIR=\""$(gimpsysconfdir)"\" \
+ -DGIMP_PACKAGE=\""@PACKAGE@"\" \
+ -DGIMP_DATA_VERSION=\"$(GIMP_DATA_VERSION)\" \
+ -DGIMP_USER_VERSION=\"$(GIMP_USER_VERSION)\" \
+ -DGIMP_SYSCONF_VERSION=\"$(GIMP_SYSCONF_VERSION)\" \
+ -DGIMP_PLUGIN_VERSION=\"$(GIMP_PLUGIN_VERSION)\" \
+ -DG_LOG_DOMAIN=\"LibGimpBase\" \
+ -DGIMP_BASE_COMPILATION \
+ -I$(top_srcdir) \
+ $(GIO_CFLAGS) \
+ $(GEXIV2_CFLAGS) \
+ -I$(includedir)
+
+AM_CFLAGS = \
+ $(xobjective_c)
+
+AM_CXXFLAGS = \
+ $(xobjective_cxx)
+
+AM_CCASFLAGS = \
+ -I$(top_builddir) \
+ -I$(top_srcdir)
+
+AM_LDFLAGS = \
+ $(xnone)
+
+EXTRA_DIST = \
+ gimpbase.def
+
+lib_LTLIBRARIES = libgimpbase-@GIMP_API_VERSION@.la
+
+# help `make' along by giving another name for the file, which it knows
+# how to build
+../libgimpbase/gimpversion.h: gimpversion.h
+ @:
+
+
+libgimpbase_sources = \
+ gimpbase.h \
+ gimpbaseenums.h \
+ gimpcompatenums.h \
+ gimpbasetypes.h \
+ gimpbasetypes.c \
+ gimplimits.h \
+ gimpparam.h \
+ gimpversion.h \
+ \
+ gimpbase-private.c \
+ gimpbase-private.h \
+ gimpchecks.c \
+ gimpchecks.h \
+ gimpcpuaccel.c \
+ gimpcpuaccel.h \
+ gimpdatafiles.c \
+ gimpdatafiles.h \
+ gimpenv.c \
+ gimpenv.h \
+ gimpmemsize.c \
+ gimpmemsize.h \
+ gimpmetadata.c \
+ gimpmetadata.h \
+ gimpparasite.c \
+ gimpparasite.h \
+ gimpparasiteio.c \
+ gimpparasiteio.h \
+ gimpprotocol.c \
+ gimpprotocol.h \
+ gimprectangle.c \
+ gimprectangle.h \
+ gimpreloc.c \
+ gimpreloc.h \
+ gimpsignal.c \
+ gimpsignal.h \
+ gimpunit.c \
+ gimpunit.h \
+ gimputils.c \
+ gimputils.h \
+ gimpvaluearray.c \
+ gimpvaluearray.h \
+ gimpwin32-io.h \
+ gimpwire.c \
+ gimpwire.h
+
+libgimpbase_built_sources = \
+ gimpbaseenums.c \
+ gimpcompatenums.c
+
+libgimpbase_@GIMP_API_VERSION@_la_SOURCES = \
+ $(libgimpbase_sources) \
+ $(libgimpbase_built_sources)
+
+
+libgimpbaseinclude_HEADERS = \
+ gimpbase.h \
+ gimpbaseenums.h \
+ gimpbasetypes.h \
+ gimpcpuaccel.h \
+ gimplimits.h \
+ gimpparam.h \
+ gimpversion.h \
+ \
+ gimpchecks.h \
+ gimpdatafiles.h \
+ gimpenv.h \
+ gimpmemsize.h \
+ gimpmetadata.h \
+ gimpparasite.h \
+ gimpparasiteio.h \
+ gimprectangle.h \
+ gimpsignal.h \
+ gimpunit.h \
+ gimputils.h \
+ gimpvaluearray.h
+
+libgimpbase_@GIMP_API_VERSION@_la_LDFLAGS = \
+ -version-info $(LT_VERSION_INFO) \
+ $(no_undefined) \
+ $(libgimpbase_export_symbols) \
+ $(framework_cocoa) \
+ $(xnone)
+
+EXTRA_libgimpbase_@GIMP_API_VERSION@_la_DEPENDENCIES = $(gimpbase_def)
+
+libgimpbase_@GIMP_API_VERSION@_la_LIBADD = \
+ $(GIO_LIBS) \
+ $(GEXIV2_LIBS) \
+ $(libm) \
+ $(ole32_lib)
+
+install-data-local: install-ms-lib install-libtool-import-lib
+
+uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib
+
+#
+# test programs, not to be built by default and never installed
+#
+
+TESTS = test-cpu-accel
+
+test_cpu_accel_SOURCES = test-cpu-accel.c
+
+test_cpu_accel_DEPENDENCIES = \
+ $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la
+
+test_cpu_accel_LDADD = \
+ $(GLIB_LIBS) \
+ $(test_cpu_accel_DEPENDENCIES)
+
+
+EXTRA_PROGRAMS = test-cpu-accel
+
+
+#
+# rules to generate built sources
+#
+
+gen_sources = xgen-bec xgen-cec
+CLEANFILES = $(EXTRA_PROGRAMS) $(gen_sources)
+
+xgen-bec: $(srcdir)/gimpbaseenums.h $(GIMP_MKENUMS) Makefile.am
+ $(AM_V_GEN) $(GIMP_MKENUMS) \
+ --fhead "#include \"config.h\"\n#include <glib-object.h>\n#undef GIMP_DISABLE_DEPRECATED\n#include \"gimpbasetypes.h\"\n#include \"libgimp/libgimp-intl.h\"" \
+ --fprod "\n/* enumerations from \"@basename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static const G@Type@Value values[] =\n {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n" \
+ --dhead " static const Gimp@Type@Desc descs[] =\n {" \
+ --dprod " { @VALUENAME@, @valuedesc@, @valuehelp@ },@if ('@valueabbrev@' ne 'NULL')@\n /* Translators: this is an abbreviated version of @valueudesc@.\n Keep it short. */\n { @VALUENAME@, @valueabbrev@, NULL },@endif@" \
+ --dtail " { 0, NULL, NULL }\n };\n\n static GType type = 0;\n\n if (G_UNLIKELY (! type))\n {\n type = g_@type@_register_static (\"@EnumName@\", values);\n gimp_type_set_translation_domain (type, GETTEXT_PACKAGE \"-libgimp\");\n gimp_type_set_translation_context (type, \"@enumnick@\");\n gimp_@type@_set_value_descriptions (type, descs);\n }\n\n return type;\n}\n" \
+ $< > $@
+
+# copy the generated enum file back to the source directory only if it's
+# changed; otherwise, only update its timestamp, so that the recipe isn't
+# executed again on the next build, however, allow this to (harmlessly) fail,
+# to support building from a read-only source tree.
+$(srcdir)/gimpbaseenums.c: xgen-bec
+ $(AM_V_GEN) if ! cmp -s $< $@; then \
+ cp $< $@; \
+ else \
+ touch $@ 2> /dev/null \
+ || true; \
+ fi
+
+xgen-cec: $(srcdir)/gimpcompatenums.h $(GIMP_MKENUMS) Makefile.am
+ $(AM_V_GEN) $(GIMP_MKENUMS) \
+ --fhead "#include \"config.h\"\n#include <glib-object.h>\n#include \"gimpbasetypes.h\"\n#include \"gimpcompatenums.h\"\n#include \"libgimp/libgimp-intl.h\"" \
+ --fprod "\n/* enumerations from \"@basename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static const G@Type@Value values[] =\n {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n" \
+ --dhead " static const Gimp@Type@Desc descs[] =\n {" \
+ --dprod " { @VALUENAME@, @valuedesc@, @valuehelp@ },@if ('@valueabbrev@' ne 'NULL')@\n /* Translators: this is an abbreviated version of @valueudesc@.\n Keep it short. */\n { @VALUENAME@, @valueabbrev@, NULL },@endif@" \
+ --dtail " { 0, NULL, NULL }\n };\n\n static GType type = 0;\n\n if (G_UNLIKELY (! type))\n {\n type = g_@type@_register_static (\"@EnumName@\", values);\n gimp_type_set_translation_domain (type, GETTEXT_PACKAGE \"-libgimp\");\n gimp_type_set_translation_context (type, \"@enumnick@\");\n gimp_@type@_set_value_descriptions (type, descs);\n }\n\n return type;\n}\n" \
+ $< > $@
+
+# copy the generated enum file back to the source directory only if it's
+# changed; otherwise, only update its timestamp, so that the recipe isn't
+# executed again on the next build, however, allow this to (harmlessly) fail,
+# to support building from a read-only source tree.
+$(srcdir)/gimpcompatenums.c: xgen-cec
+ $(AM_V_GEN) if ! cmp -s $< $@; then \
+ cp $< $@; \
+ else \
+ touch $@ 2> /dev/null \
+ || true; \
+ fi
+
+DISTCLEANFILES = gimpversion.h
diff --git a/libgimpbase/Makefile.in b/libgimpbase/Makefile.in
new file mode 100644
index 0000000..419ea65
--- /dev/null
+++ b/libgimpbase/Makefile.in
@@ -0,0 +1,1660 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS = test-cpu-accel$(EXEEXT)
+EXTRA_PROGRAMS = test-cpu-accel$(EXEEXT)
+subdir = libgimpbase
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4macros/alsa.m4 \
+ $(top_srcdir)/m4macros/ax_compare_version.m4 \
+ $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \
+ $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \
+ $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \
+ $(top_srcdir)/m4macros/detectcflags.m4 \
+ $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(libgimpbaseinclude_HEADERS) \
+ $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libgimpbaseincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgimpbase_@GIMP_API_VERSION@_la_DEPENDENCIES = \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__objects_1 = gimpbasetypes.lo gimpbase-private.lo gimpchecks.lo \
+ gimpcpuaccel.lo gimpdatafiles.lo gimpenv.lo gimpmemsize.lo \
+ gimpmetadata.lo gimpparasite.lo gimpparasiteio.lo \
+ gimpprotocol.lo gimprectangle.lo gimpreloc.lo gimpsignal.lo \
+ gimpunit.lo gimputils.lo gimpvaluearray.lo gimpwire.lo
+am__objects_2 = gimpbaseenums.lo gimpcompatenums.lo
+am_libgimpbase_@GIMP_API_VERSION@_la_OBJECTS = $(am__objects_1) \
+ $(am__objects_2)
+libgimpbase_@GIMP_API_VERSION@_la_OBJECTS = \
+ $(am_libgimpbase_@GIMP_API_VERSION@_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libgimpbase_@GIMP_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) \
+ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libgimpbase_@GIMP_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@
+am_test_cpu_accel_OBJECTS = test-cpu-accel.$(OBJEXT)
+test_cpu_accel_OBJECTS = $(am_test_cpu_accel_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/gimpbase-private.Plo \
+ ./$(DEPDIR)/gimpbaseenums.Plo ./$(DEPDIR)/gimpbasetypes.Plo \
+ ./$(DEPDIR)/gimpchecks.Plo ./$(DEPDIR)/gimpcompatenums.Plo \
+ ./$(DEPDIR)/gimpcpuaccel.Plo ./$(DEPDIR)/gimpdatafiles.Plo \
+ ./$(DEPDIR)/gimpenv.Plo ./$(DEPDIR)/gimpmemsize.Plo \
+ ./$(DEPDIR)/gimpmetadata.Plo ./$(DEPDIR)/gimpparasite.Plo \
+ ./$(DEPDIR)/gimpparasiteio.Plo ./$(DEPDIR)/gimpprotocol.Plo \
+ ./$(DEPDIR)/gimprectangle.Plo ./$(DEPDIR)/gimpreloc.Plo \
+ ./$(DEPDIR)/gimpsignal.Plo ./$(DEPDIR)/gimpunit.Plo \
+ ./$(DEPDIR)/gimputils.Plo ./$(DEPDIR)/gimpvaluearray.Plo \
+ ./$(DEPDIR)/gimpwire.Plo ./$(DEPDIR)/test-cpu-accel.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libgimpbase_@GIMP_API_VERSION@_la_SOURCES) \
+ $(test_cpu_accel_SOURCES)
+DIST_SOURCES = $(libgimpbase_@GIMP_API_VERSION@_la_SOURCES) \
+ $(test_cpu_accel_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DATA = $(noinst_DATA)
+HEADERS = $(libgimpbaseinclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)'
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
+ $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+AA_LIBS = @AA_LIBS@
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+ALL_LINGUAS = @ALL_LINGUAS@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APPSTREAM_UTIL = @APPSTREAM_UTIL@
+AR = @AR@
+AS = @AS@
+ATK_CFLAGS = @ATK_CFLAGS@
+ATK_LIBS = @ATK_LIBS@
+ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BABL_CFLAGS = @BABL_CFLAGS@
+BABL_LIBS = @BABL_LIBS@
+BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@
+BUG_REPORT_URL = @BUG_REPORT_URL@
+BUILD_EXEEXT = @BUILD_EXEEXT@
+BUILD_OBJEXT = @BUILD_OBJEXT@
+BZIP2_LIBS = @BZIP2_LIBS@
+CAIRO_CFLAGS = @CAIRO_CFLAGS@
+CAIRO_LIBS = @CAIRO_LIBS@
+CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@
+CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@
+CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@
+CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CC_VERSION = @CC_VERSION@
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+CPP_FOR_BUILD = @CPP_FOR_BUILD@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DESKTOP_DATADIR = @DESKTOP_DATADIR@
+DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@
+DLLTOOL = @DLLTOOL@
+DOC_SHOOTER = @DOC_SHOOTER@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILE_AA = @FILE_AA@
+FILE_EXR = @FILE_EXR@
+FILE_HEIF = @FILE_HEIF@
+FILE_JP2_LOAD = @FILE_JP2_LOAD@
+FILE_JPEGXL = @FILE_JPEGXL@
+FILE_MNG = @FILE_MNG@
+FILE_PDF_SAVE = @FILE_PDF_SAVE@
+FILE_PS = @FILE_PS@
+FILE_WMF = @FILE_WMF@
+FILE_XMC = @FILE_XMC@
+FILE_XPM = @FILE_XPM@
+FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
+FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
+FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@
+FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+GDBUS_CODEGEN = @GDBUS_CODEGEN@
+GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@
+GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@
+GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@
+GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@
+GEGL = @GEGL@
+GEGL_CFLAGS = @GEGL_CFLAGS@
+GEGL_LIBS = @GEGL_LIBS@
+GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@
+GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GEXIV2_CFLAGS = @GEXIV2_CFLAGS@
+GEXIV2_LIBS = @GEXIV2_LIBS@
+GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@
+GIMP_API_VERSION = @GIMP_API_VERSION@
+GIMP_APP_VERSION = @GIMP_APP_VERSION@
+GIMP_BINARY_AGE = @GIMP_BINARY_AGE@
+GIMP_COMMAND = @GIMP_COMMAND@
+GIMP_DATA_VERSION = @GIMP_DATA_VERSION@
+GIMP_FULL_NAME = @GIMP_FULL_NAME@
+GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@
+GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@
+GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@
+GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@
+GIMP_MKENUMS = @GIMP_MKENUMS@
+GIMP_MODULES = @GIMP_MODULES@
+GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@
+GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@
+GIMP_PLUGINS = @GIMP_PLUGINS@
+GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@
+GIMP_REAL_VERSION = @GIMP_REAL_VERSION@
+GIMP_RELEASE = @GIMP_RELEASE@
+GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@
+GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@
+GIMP_UNSTABLE = @GIMP_UNSTABLE@
+GIMP_USER_VERSION = @GIMP_USER_VERSION@
+GIMP_VERSION = @GIMP_VERSION@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@
+GIO_UNIX_LIBS = @GIO_UNIX_LIBS@
+GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@
+GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@
+GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@
+GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+GS_LIBS = @GS_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_LIBS = @GTK_LIBS@
+GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@
+GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@
+GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@
+GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@
+HARFBUZZ_LIBS = @HARFBUZZ_LIBS@
+HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@
+HAVE_CXX14 = @HAVE_CXX14@
+HAVE_FINITE = @HAVE_FINITE@
+HAVE_ISFINITE = @HAVE_ISFINITE@
+HAVE_VFORK = @HAVE_VFORK@
+HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@
+ISO_CODES_LOCATION = @ISO_CODES_LOCATION@
+JPEG_LIBS = @JPEG_LIBS@
+JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@
+JSON_GLIB_LIBS = @JSON_GLIB_LIBS@
+JXL_CFLAGS = @JXL_CFLAGS@
+JXL_LIBS = @JXL_LIBS@
+JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@
+JXL_THREADS_LIBS = @JXL_THREADS_LIBS@
+LCMS_CFLAGS = @LCMS_CFLAGS@
+LCMS_LIBS = @LCMS_LIBS@
+LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
+LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@
+LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@
+LIBHEIF_LIBS = @LIBHEIF_LIBS@
+LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@
+LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@
+LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@
+LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@
+LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@
+LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@
+LIBOBJS = @LIBOBJS@
+LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@
+LIBUNWIND_LIBS = @LIBUNWIND_LIBS@
+LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+LT_VERSION_INFO = @LT_VERSION_INFO@
+LZMA_CFLAGS = @LZMA_CFLAGS@
+LZMA_LIBS = @LZMA_LIBS@
+MAIL = @MAIL@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@
+MIME_INFO_LIBS = @MIME_INFO_LIBS@
+MIME_TYPES = @MIME_TYPES@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@
+MNG_CFLAGS = @MNG_CFLAGS@
+MNG_LIBS = @MNG_LIBS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@
+MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@
+NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@
+NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENEXR_CFLAGS = @OPENEXR_CFLAGS@
+OPENEXR_LIBS = @OPENEXR_LIBS@
+OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@
+OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@
+OPENJPEG_LIBS = @OPENJPEG_LIBS@
+OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@
+PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@
+PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@
+PATHSEP = @PATHSEP@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@
+PERL_VERSION = @PERL_VERSION@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PNG_CFLAGS = @PNG_CFLAGS@
+PNG_LIBS = @PNG_LIBS@
+POFILES = @POFILES@
+POPPLER_CFLAGS = @POPPLER_CFLAGS@
+POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@
+POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@
+POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@
+POPPLER_LIBS = @POPPLER_LIBS@
+POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PYBIN_PATH = @PYBIN_PATH@
+PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@
+PYCAIRO_LIBS = @PYCAIRO_LIBS@
+PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@
+PYGTK_CFLAGS = @PYGTK_CFLAGS@
+PYGTK_CODEGEN = @PYGTK_CODEGEN@
+PYGTK_DEFSDIR = @PYGTK_DEFSDIR@
+PYGTK_LIBS = @PYGTK_LIBS@
+PYLINK_LIBS = @PYLINK_LIBS@
+PYTHON = @PYTHON@
+PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_INCLUDES = @PYTHON_INCLUDES@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@
+RT_LIBS = @RT_LIBS@
+SCREENSHOT_LIBS = @SCREENSHOT_LIBS@
+SED = @SED@
+SENDMAIL = @SENDMAIL@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKET_LIBS = @SOCKET_LIBS@
+SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@
+SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@
+SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@
+STRIP = @STRIP@
+SVG_CFLAGS = @SVG_CFLAGS@
+SVG_LIBS = @SVG_LIBS@
+SYMPREFIX = @SYMPREFIX@
+TIFF_LIBS = @TIFF_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WEBKIT_CFLAGS = @WEBKIT_CFLAGS@
+WEBKIT_LIBS = @WEBKIT_LIBS@
+WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@
+WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@
+WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@
+WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@
+WEBPMUX_LIBS = @WEBPMUX_LIBS@
+WEBP_CFLAGS = @WEBP_CFLAGS@
+WEBP_LIBS = @WEBP_LIBS@
+WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@
+WEB_PAGE = @WEB_PAGE@
+WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@
+WINDRES = @WINDRES@
+WMF_CFLAGS = @WMF_CFLAGS@
+WMF_CONFIG = @WMF_CONFIG@
+WMF_LIBS = @WMF_LIBS@
+WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@
+XDG_EMAIL = @XDG_EMAIL@
+XFIXES_CFLAGS = @XFIXES_CFLAGS@
+XFIXES_LIBS = @XFIXES_LIBS@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@
+XMC_CFLAGS = @XMC_CFLAGS@
+XMC_LIBS = @XMC_LIBS@
+XMKMF = @XMKMF@
+XMLLINT = @XMLLINT@
+XMU_LIBS = @XMU_LIBS@
+XPM_LIBS = @XPM_LIBS@
+XSLTPROC = @XSLTPROC@
+XVFB_RUN = @XVFB_RUN@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+Z_LIBS = @Z_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gimpdatadir = @gimpdatadir@
+gimpdir = @gimpdir@
+gimplocaledir = @gimplocaledir@
+gimpplugindir = @gimpplugindir@
+gimpsysconfdir = @gimpsysconfdir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+manpage_gimpdir = @manpage_gimpdir@
+mkdir_p = @mkdir_p@
+ms_librarian = @ms_librarian@
+mypaint_brushes_dir = @mypaint_brushes_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@PLATFORM_WIN32_TRUE@no_undefined = -no-undefined
+@PLATFORM_OSX_TRUE@xobjective_c = "-xobjective-c"
+@PLATFORM_OSX_TRUE@xobjective_cxx = "-xobjective-c++"
+@PLATFORM_OSX_TRUE@xnone = "-xnone"
+@PLATFORM_OSX_TRUE@framework_cocoa = -framework Cocoa
+@OS_WIN32_TRUE@ole32_lib = -lole32
+@OS_WIN32_TRUE@gimpbase_def = gimpbase.def
+@OS_WIN32_TRUE@libgimpbase_export_symbols = -export-symbols $(srcdir)/gimpbase.def
+@OS_WIN32_FALSE@libm = -lm
+@MS_LIB_AVAILABLE_TRUE@noinst_DATA = gimpbase-$(GIMP_API_VERSION).lib
+libgimpbaseincludedir = $(includedir)/gimp-$(GIMP_API_VERSION)/libgimpbase
+AM_CPPFLAGS = \
+ -DPREFIX=\""$(prefix)"\" \
+ -DGIMPDIR=\""$(gimpdir)"\" \
+ -DGIMPDATADIR=\""$(gimpdatadir)"\" \
+ -DLOCALEDIR=\""$(gimplocaledir)"\" \
+ -DPLUGINDIR=\""$(gimpplugindir)"\" \
+ -DGIMPSYSCONFDIR=\""$(gimpsysconfdir)"\" \
+ -DGIMP_PACKAGE=\""@PACKAGE@"\" \
+ -DGIMP_DATA_VERSION=\"$(GIMP_DATA_VERSION)\" \
+ -DGIMP_USER_VERSION=\"$(GIMP_USER_VERSION)\" \
+ -DGIMP_SYSCONF_VERSION=\"$(GIMP_SYSCONF_VERSION)\" \
+ -DGIMP_PLUGIN_VERSION=\"$(GIMP_PLUGIN_VERSION)\" \
+ -DG_LOG_DOMAIN=\"LibGimpBase\" \
+ -DGIMP_BASE_COMPILATION \
+ -I$(top_srcdir) \
+ $(GIO_CFLAGS) \
+ $(GEXIV2_CFLAGS) \
+ -I$(includedir)
+
+AM_CFLAGS = \
+ $(xobjective_c)
+
+AM_CXXFLAGS = \
+ $(xobjective_cxx)
+
+AM_CCASFLAGS = \
+ -I$(top_builddir) \
+ -I$(top_srcdir)
+
+AM_LDFLAGS = \
+ $(xnone)
+
+EXTRA_DIST = \
+ gimpbase.def
+
+lib_LTLIBRARIES = libgimpbase-@GIMP_API_VERSION@.la
+libgimpbase_sources = \
+ gimpbase.h \
+ gimpbaseenums.h \
+ gimpcompatenums.h \
+ gimpbasetypes.h \
+ gimpbasetypes.c \
+ gimplimits.h \
+ gimpparam.h \
+ gimpversion.h \
+ \
+ gimpbase-private.c \
+ gimpbase-private.h \
+ gimpchecks.c \
+ gimpchecks.h \
+ gimpcpuaccel.c \
+ gimpcpuaccel.h \
+ gimpdatafiles.c \
+ gimpdatafiles.h \
+ gimpenv.c \
+ gimpenv.h \
+ gimpmemsize.c \
+ gimpmemsize.h \
+ gimpmetadata.c \
+ gimpmetadata.h \
+ gimpparasite.c \
+ gimpparasite.h \
+ gimpparasiteio.c \
+ gimpparasiteio.h \
+ gimpprotocol.c \
+ gimpprotocol.h \
+ gimprectangle.c \
+ gimprectangle.h \
+ gimpreloc.c \
+ gimpreloc.h \
+ gimpsignal.c \
+ gimpsignal.h \
+ gimpunit.c \
+ gimpunit.h \
+ gimputils.c \
+ gimputils.h \
+ gimpvaluearray.c \
+ gimpvaluearray.h \
+ gimpwin32-io.h \
+ gimpwire.c \
+ gimpwire.h
+
+libgimpbase_built_sources = \
+ gimpbaseenums.c \
+ gimpcompatenums.c
+
+libgimpbase_@GIMP_API_VERSION@_la_SOURCES = \
+ $(libgimpbase_sources) \
+ $(libgimpbase_built_sources)
+
+libgimpbaseinclude_HEADERS = \
+ gimpbase.h \
+ gimpbaseenums.h \
+ gimpbasetypes.h \
+ gimpcpuaccel.h \
+ gimplimits.h \
+ gimpparam.h \
+ gimpversion.h \
+ \
+ gimpchecks.h \
+ gimpdatafiles.h \
+ gimpenv.h \
+ gimpmemsize.h \
+ gimpmetadata.h \
+ gimpparasite.h \
+ gimpparasiteio.h \
+ gimprectangle.h \
+ gimpsignal.h \
+ gimpunit.h \
+ gimputils.h \
+ gimpvaluearray.h
+
+libgimpbase_@GIMP_API_VERSION@_la_LDFLAGS = \
+ -version-info $(LT_VERSION_INFO) \
+ $(no_undefined) \
+ $(libgimpbase_export_symbols) \
+ $(framework_cocoa) \
+ $(xnone)
+
+EXTRA_libgimpbase_@GIMP_API_VERSION@_la_DEPENDENCIES = $(gimpbase_def)
+libgimpbase_@GIMP_API_VERSION@_la_LIBADD = \
+ $(GIO_LIBS) \
+ $(GEXIV2_LIBS) \
+ $(libm) \
+ $(ole32_lib)
+
+test_cpu_accel_SOURCES = test-cpu-accel.c
+test_cpu_accel_DEPENDENCIES = \
+ $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la
+
+test_cpu_accel_LDADD = \
+ $(GLIB_LIBS) \
+ $(test_cpu_accel_DEPENDENCIES)
+
+
+#
+# rules to generate built sources
+#
+gen_sources = xgen-bec xgen-cec
+CLEANFILES = $(EXTRA_PROGRAMS) $(gen_sources)
+DISTCLEANFILES = gimpversion.h
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libgimpbase/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libgimpbase/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libgimpbase-@GIMP_API_VERSION@.la: $(libgimpbase_@GIMP_API_VERSION@_la_OBJECTS) $(libgimpbase_@GIMP_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgimpbase_@GIMP_API_VERSION@_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgimpbase_@GIMP_API_VERSION@_la_LINK) -rpath $(libdir) $(libgimpbase_@GIMP_API_VERSION@_la_OBJECTS) $(libgimpbase_@GIMP_API_VERSION@_la_LIBADD) $(LIBS)
+
+test-cpu-accel$(EXEEXT): $(test_cpu_accel_OBJECTS) $(test_cpu_accel_DEPENDENCIES) $(EXTRA_test_cpu_accel_DEPENDENCIES)
+ @rm -f test-cpu-accel$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_cpu_accel_OBJECTS) $(test_cpu_accel_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbase-private.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbaseenums.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpbasetypes.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpchecks.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcompatenums.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpcpuaccel.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpdatafiles.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpenv.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmemsize.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmetadata.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpparasite.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpparasiteio.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpprotocol.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimprectangle.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpreloc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpsignal.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpunit.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimputils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpvaluearray.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpwire.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-cpu-accel.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-libgimpbaseincludeHEADERS: $(libgimpbaseinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(libgimpbaseinclude_HEADERS)'; test -n "$(libgimpbaseincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libgimpbaseincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libgimpbaseincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libgimpbaseincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgimpbaseincludedir)" || exit $$?; \
+ done
+
+uninstall-libgimpbaseincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libgimpbaseinclude_HEADERS)'; test -n "$(libgimpbaseincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libgimpbaseincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS:
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+test-cpu-accel.log: test-cpu-accel$(EXEEXT)
+ @p='test-cpu-accel$(EXEEXT)'; \
+ b='test-cpu-accel'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libgimpbaseincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/gimpbase-private.Plo
+ -rm -f ./$(DEPDIR)/gimpbaseenums.Plo
+ -rm -f ./$(DEPDIR)/gimpbasetypes.Plo
+ -rm -f ./$(DEPDIR)/gimpchecks.Plo
+ -rm -f ./$(DEPDIR)/gimpcompatenums.Plo
+ -rm -f ./$(DEPDIR)/gimpcpuaccel.Plo
+ -rm -f ./$(DEPDIR)/gimpdatafiles.Plo
+ -rm -f ./$(DEPDIR)/gimpenv.Plo
+ -rm -f ./$(DEPDIR)/gimpmemsize.Plo
+ -rm -f ./$(DEPDIR)/gimpmetadata.Plo
+ -rm -f ./$(DEPDIR)/gimpparasite.Plo
+ -rm -f ./$(DEPDIR)/gimpparasiteio.Plo
+ -rm -f ./$(DEPDIR)/gimpprotocol.Plo
+ -rm -f ./$(DEPDIR)/gimprectangle.Plo
+ -rm -f ./$(DEPDIR)/gimpreloc.Plo
+ -rm -f ./$(DEPDIR)/gimpsignal.Plo
+ -rm -f ./$(DEPDIR)/gimpunit.Plo
+ -rm -f ./$(DEPDIR)/gimputils.Plo
+ -rm -f ./$(DEPDIR)/gimpvaluearray.Plo
+ -rm -f ./$(DEPDIR)/gimpwire.Plo
+ -rm -f ./$(DEPDIR)/test-cpu-accel.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-libgimpbaseincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/gimpbase-private.Plo
+ -rm -f ./$(DEPDIR)/gimpbaseenums.Plo
+ -rm -f ./$(DEPDIR)/gimpbasetypes.Plo
+ -rm -f ./$(DEPDIR)/gimpchecks.Plo
+ -rm -f ./$(DEPDIR)/gimpcompatenums.Plo
+ -rm -f ./$(DEPDIR)/gimpcpuaccel.Plo
+ -rm -f ./$(DEPDIR)/gimpdatafiles.Plo
+ -rm -f ./$(DEPDIR)/gimpenv.Plo
+ -rm -f ./$(DEPDIR)/gimpmemsize.Plo
+ -rm -f ./$(DEPDIR)/gimpmetadata.Plo
+ -rm -f ./$(DEPDIR)/gimpparasite.Plo
+ -rm -f ./$(DEPDIR)/gimpparasiteio.Plo
+ -rm -f ./$(DEPDIR)/gimpprotocol.Plo
+ -rm -f ./$(DEPDIR)/gimprectangle.Plo
+ -rm -f ./$(DEPDIR)/gimpreloc.Plo
+ -rm -f ./$(DEPDIR)/gimpsignal.Plo
+ -rm -f ./$(DEPDIR)/gimpunit.Plo
+ -rm -f ./$(DEPDIR)/gimputils.Plo
+ -rm -f ./$(DEPDIR)/gimpvaluearray.Plo
+ -rm -f ./$(DEPDIR)/gimpwire.Plo
+ -rm -f ./$(DEPDIR)/test-cpu-accel.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES \
+ uninstall-libgimpbaseincludeHEADERS uninstall-local
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
+ check-am clean clean-generic clean-libLTLIBRARIES \
+ clean-libtool cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES \
+ install-libgimpbaseincludeHEADERS install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ recheck tags tags-am uninstall uninstall-am \
+ uninstall-libLTLIBRARIES uninstall-libgimpbaseincludeHEADERS \
+ uninstall-local
+
+.PRECIOUS: Makefile
+
+
+@OS_WIN32_TRUE@install-libtool-import-lib:
+@OS_WIN32_TRUE@ $(INSTALL) .libs/libgimpbase-$(GIMP_API_VERSION).dll.a $(DESTDIR)$(libdir)
+@OS_WIN32_TRUE@ $(INSTALL) $(srcdir)/gimpbase.def $(DESTDIR)$(libdir)
+
+@OS_WIN32_TRUE@uninstall-libtool-import-lib:
+@OS_WIN32_TRUE@ -rm $(DESTDIR)$(libdir)/libgimpbase-$(GIMP_API_VERSION).dll.a
+@OS_WIN32_TRUE@ -rm $(DESTDIR)$(libdir)/gimpbase.def
+@OS_WIN32_FALSE@install-libtool-import-lib:
+@OS_WIN32_FALSE@uninstall-libtool-import-lib:
+
+@MS_LIB_AVAILABLE_TRUE@install-ms-lib:
+@MS_LIB_AVAILABLE_TRUE@ $(INSTALL) gimpbase-$(GIMP_API_VERSION).lib $(DESTDIR)$(libdir)
+
+@MS_LIB_AVAILABLE_TRUE@uninstall-ms-lib:
+@MS_LIB_AVAILABLE_TRUE@ -rm $(DESTDIR)$(libdir)/gimpbase-$(GIMP_API_VERSION).lib
+
+@MS_LIB_AVAILABLE_TRUE@gimpbase-@GIMP_API_VERSION@.lib: gimpbase.def
+@MS_LIB_AVAILABLE_TRUE@ lib -name:libgimpbase-$(GIMP_API_VERSION)-@LT_CURRENT_MINUS_AGE@.dll -def:gimpbase.def -out:$@
+
+@MS_LIB_AVAILABLE_FALSE@install-ms-lib:
+@MS_LIB_AVAILABLE_FALSE@uninstall-ms-lib:
+
+# help `make' along by giving another name for the file, which it knows
+# how to build
+../libgimpbase/gimpversion.h: gimpversion.h
+ @:
+
+install-data-local: install-ms-lib install-libtool-import-lib
+
+uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib
+
+xgen-bec: $(srcdir)/gimpbaseenums.h $(GIMP_MKENUMS) Makefile.am
+ $(AM_V_GEN) $(GIMP_MKENUMS) \
+ --fhead "#include \"config.h\"\n#include <glib-object.h>\n#undef GIMP_DISABLE_DEPRECATED\n#include \"gimpbasetypes.h\"\n#include \"libgimp/libgimp-intl.h\"" \
+ --fprod "\n/* enumerations from \"@basename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static const G@Type@Value values[] =\n {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n" \
+ --dhead " static const Gimp@Type@Desc descs[] =\n {" \
+ --dprod " { @VALUENAME@, @valuedesc@, @valuehelp@ },@if ('@valueabbrev@' ne 'NULL')@\n /* Translators: this is an abbreviated version of @valueudesc@.\n Keep it short. */\n { @VALUENAME@, @valueabbrev@, NULL },@endif@" \
+ --dtail " { 0, NULL, NULL }\n };\n\n static GType type = 0;\n\n if (G_UNLIKELY (! type))\n {\n type = g_@type@_register_static (\"@EnumName@\", values);\n gimp_type_set_translation_domain (type, GETTEXT_PACKAGE \"-libgimp\");\n gimp_type_set_translation_context (type, \"@enumnick@\");\n gimp_@type@_set_value_descriptions (type, descs);\n }\n\n return type;\n}\n" \
+ $< > $@
+
+# copy the generated enum file back to the source directory only if it's
+# changed; otherwise, only update its timestamp, so that the recipe isn't
+# executed again on the next build, however, allow this to (harmlessly) fail,
+# to support building from a read-only source tree.
+$(srcdir)/gimpbaseenums.c: xgen-bec
+ $(AM_V_GEN) if ! cmp -s $< $@; then \
+ cp $< $@; \
+ else \
+ touch $@ 2> /dev/null \
+ || true; \
+ fi
+
+xgen-cec: $(srcdir)/gimpcompatenums.h $(GIMP_MKENUMS) Makefile.am
+ $(AM_V_GEN) $(GIMP_MKENUMS) \
+ --fhead "#include \"config.h\"\n#include <glib-object.h>\n#include \"gimpbasetypes.h\"\n#include \"gimpcompatenums.h\"\n#include \"libgimp/libgimp-intl.h\"" \
+ --fprod "\n/* enumerations from \"@basename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static const G@Type@Value values[] =\n {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n" \
+ --dhead " static const Gimp@Type@Desc descs[] =\n {" \
+ --dprod " { @VALUENAME@, @valuedesc@, @valuehelp@ },@if ('@valueabbrev@' ne 'NULL')@\n /* Translators: this is an abbreviated version of @valueudesc@.\n Keep it short. */\n { @VALUENAME@, @valueabbrev@, NULL },@endif@" \
+ --dtail " { 0, NULL, NULL }\n };\n\n static GType type = 0;\n\n if (G_UNLIKELY (! type))\n {\n type = g_@type@_register_static (\"@EnumName@\", values);\n gimp_type_set_translation_domain (type, GETTEXT_PACKAGE \"-libgimp\");\n gimp_type_set_translation_context (type, \"@enumnick@\");\n gimp_@type@_set_value_descriptions (type, descs);\n }\n\n return type;\n}\n" \
+ $< > $@
+
+# copy the generated enum file back to the source directory only if it's
+# changed; otherwise, only update its timestamp, so that the recipe isn't
+# executed again on the next build, however, allow this to (harmlessly) fail,
+# to support building from a read-only source tree.
+$(srcdir)/gimpcompatenums.c: xgen-cec
+ $(AM_V_GEN) if ! cmp -s $< $@; then \
+ cp $< $@; \
+ else \
+ touch $@ 2> /dev/null \
+ || true; \
+ fi
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libgimpbase/gimpbase-private.c b/libgimpbase/gimpbase-private.c
new file mode 100644
index 0000000..7703fce
--- /dev/null
+++ b/libgimpbase/gimpbase-private.c
@@ -0,0 +1,93 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpbase-private.c
+ * Copyright (C) 2003 Sven Neumann <sven@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "gimpbasetypes.h"
+
+#include "gimpbase-private.h"
+#include "gimpcompatenums.h"
+
+
+GimpUnitVtable _gimp_unit_vtable = { NULL, };
+
+
+void
+gimp_base_init (GimpUnitVtable *vtable)
+{
+ static gboolean gimp_base_initialized = FALSE;
+
+ g_return_if_fail (vtable != NULL);
+
+ if (gimp_base_initialized)
+ g_error ("gimp_base_init() must only be called once!");
+
+ _gimp_unit_vtable = *vtable;
+
+ gimp_base_compat_enums_init ();
+
+ gimp_base_initialized = TRUE;
+}
+
+void
+gimp_base_compat_enums_init (void)
+{
+ static gboolean gimp_base_compat_initialized = FALSE;
+ GQuark quark;
+
+ if (gimp_base_compat_initialized)
+ return;
+
+ quark = g_quark_from_static_string ("gimp-compat-enum");
+
+ g_type_set_qdata (GIMP_TYPE_ADD_MASK_TYPE, quark,
+ (gpointer) GIMP_TYPE_ADD_MASK_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_BLEND_MODE, quark,
+ (gpointer) GIMP_TYPE_BLEND_MODE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_BUCKET_FILL_MODE, quark,
+ (gpointer) GIMP_TYPE_BUCKET_FILL_MODE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_CHANNEL_TYPE, quark,
+ (gpointer) GIMP_TYPE_CHANNEL_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_CLONE_TYPE, quark,
+ (gpointer) GIMP_TYPE_CLONE_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_CONVERT_PALETTE_TYPE, quark,
+ (gpointer) GIMP_TYPE_CONVERT_PALETTE_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_CONVOLVE_TYPE, quark,
+ (gpointer) GIMP_TYPE_CONVOLVE_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_DESATURATE_MODE, quark,
+ (gpointer) GIMP_TYPE_DESATURATE_MODE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_DODGE_BURN_TYPE, quark,
+ (gpointer) GIMP_TYPE_DODGE_BURN_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_FILL_TYPE, quark,
+ (gpointer) GIMP_TYPE_FILL_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_HUE_RANGE, quark,
+ (gpointer) GIMP_TYPE_HUE_RANGE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_ICON_TYPE, quark,
+ (gpointer) GIMP_TYPE_ICON_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_INTERPOLATION_TYPE, quark,
+ (gpointer) GIMP_TYPE_INTERPOLATION_TYPE_COMPAT);
+ g_type_set_qdata (GIMP_TYPE_TRANSFER_MODE, quark,
+ (gpointer) GIMP_TYPE_TRANSFER_MODE_COMPAT);
+
+ gimp_base_compat_initialized = TRUE;
+}
diff --git a/libgimpbase/gimpbase-private.h b/libgimpbase/gimpbase-private.h
new file mode 100644
index 0000000..a36b4a7
--- /dev/null
+++ b/libgimpbase/gimpbase-private.h
@@ -0,0 +1,69 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpbase-private.h
+ * Copyright (C) 2003 Sven Neumann <sven@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_BASE_PRIVATE_H__
+#define __GIMP_BASE_PRIVATE_H__
+
+
+typedef struct _GimpUnitVtable GimpUnitVtable;
+
+struct _GimpUnitVtable
+{
+ gint (* unit_get_number_of_units) (void);
+ gint (* unit_get_number_of_built_in_units) (void);
+
+ GimpUnit (* unit_new) (gchar *identifier,
+ gdouble factor,
+ gint digits,
+ gchar *symbol,
+ gchar *abbreviation,
+ gchar *singular,
+ gchar *plural);
+ gboolean (* unit_get_deletion_flag) (GimpUnit unit);
+ void (* unit_set_deletion_flag) (GimpUnit unit,
+ gboolean deletion_flag);
+
+ gdouble (* unit_get_factor) (GimpUnit unit);
+ gint (* unit_get_digits) (GimpUnit unit);
+ const gchar * (* unit_get_identifier) (GimpUnit unit);
+ const gchar * (* unit_get_symbol) (GimpUnit unit);
+ const gchar * (* unit_get_abbreviation) (GimpUnit unit);
+ const gchar * (* unit_get_singular) (GimpUnit unit);
+ const gchar * (* unit_get_plural) (GimpUnit unit);
+
+ void (* _reserved_1) (void);
+ void (* _reserved_2) (void);
+ void (* _reserved_3) (void);
+ void (* _reserved_4) (void);
+};
+
+
+extern GimpUnitVtable _gimp_unit_vtable;
+
+
+G_BEGIN_DECLS
+
+void gimp_base_init (GimpUnitVtable *vtable);
+void gimp_base_compat_enums_init (void);
+
+G_END_DECLS
+
+#endif /* __GIMP_BASE_PRIVATE_H__ */
diff --git a/libgimpbase/gimpbase.def b/libgimpbase/gimpbase.def
new file mode 100644
index 0000000..2efc1de
--- /dev/null
+++ b/libgimpbase/gimpbase.def
@@ -0,0 +1,244 @@
+EXPORTS
+ gimp_add_mask_type_compat_get_type
+ gimp_add_mask_type_get_type
+ gimp_any_to_utf8
+ gimp_base_compat_enums_init
+ gimp_base_init
+ gimp_blend_mode_compat_get_type
+ gimp_blend_mode_get_type
+ gimp_brush_generated_shape_get_type
+ gimp_bucket_fill_mode_compat_get_type
+ gimp_bucket_fill_mode_get_type
+ gimp_cache_directory
+ gimp_canonicalize_identifier
+ gimp_cap_style_get_type
+ gimp_channel_ops_get_type
+ gimp_channel_type_compat_get_type
+ gimp_channel_type_get_type
+ gimp_check_size_get_type
+ gimp_check_type_get_type
+ gimp_checks_get_shades
+ gimp_clone_type_compat_get_type
+ gimp_clone_type_get_type
+ gimp_color_tag_get_type
+ gimp_component_type_get_type
+ gimp_convert_dither_type_compat_get_type
+ gimp_convert_palette_type_compat_get_type
+ gimp_convert_palette_type_get_type
+ gimp_convolve_type_compat_get_type
+ gimp_convolve_type_get_type
+ gimp_cpu_accel_get_support
+ gimp_cpu_accel_set_use
+ gimp_data_directory
+ gimp_data_directory_file
+ gimp_datafiles_check_extension
+ gimp_datafiles_read_directories
+ gimp_desaturate_mode_compat_get_type
+ gimp_desaturate_mode_get_type
+ gimp_directory
+ gimp_directory_file
+ gimp_dodge_burn_type_compat_get_type
+ gimp_dodge_burn_type_get_type
+ gimp_enum_get_desc
+ gimp_enum_get_value
+ gimp_enum_get_value_descriptions
+ gimp_enum_set_value_descriptions
+ gimp_enum_value_get_abbrev
+ gimp_enum_value_get_desc
+ gimp_enum_value_get_help
+ gimp_env_init
+ gimp_escape_uline
+ gimp_file_get_utf8_name
+ gimp_file_has_extension
+ gimp_file_show_in_file_manager
+ gimp_filename_to_utf8
+ gimp_fill_type_compat_get_type
+ gimp_fill_type_get_type
+ gimp_flags_get_first_desc
+ gimp_flags_get_first_value
+ gimp_flags_get_value_descriptions
+ gimp_flags_set_value_descriptions
+ gimp_flags_value_get_abbrev
+ gimp_flags_value_get_desc
+ gimp_flags_value_get_help
+ gimp_foreground_extract_mode_get_type
+ gimp_gradient_blend_color_space_get_type
+ gimp_gradient_segment_color_get_type
+ gimp_gradient_segment_type_get_type
+ gimp_gradient_type_get_type
+ gimp_grid_style_get_type
+ gimp_gtkrc
+ gimp_hue_range_compat_get_type
+ gimp_hue_range_get_type
+ gimp_icon_type_compat_get_type
+ gimp_icon_type_get_type
+ gimp_image_base_type_get_type
+ gimp_image_type_get_type
+ gimp_ink_blob_type_get_type
+ gimp_installation_directory
+ gimp_installation_directory_file
+ gimp_interpolation_type_compat_get_type
+ gimp_interpolation_type_get_type
+ gimp_join_style_get_type
+ gimp_layer_mode_effects_get_type
+ gimp_locale_directory
+ gimp_locale_directory_file
+ gimp_major_version
+ gimp_mask_apply_mode_get_type
+ gimp_memsize_deserialize
+ gimp_memsize_get_type
+ gimp_memsize_serialize
+ gimp_memsize_to_string
+ gimp_merge_type_get_type
+ gimp_message_handler_type_get_type
+ gimp_metadata_add_xmp_history
+ gimp_metadata_deserialize
+ gimp_metadata_duplicate
+ gimp_metadata_get_colorspace
+ gimp_metadata_get_guid
+ gimp_metadata_get_resolution
+ gimp_metadata_get_type
+ gimp_metadata_is_tag_supported
+ gimp_metadata_load_from_file
+ gimp_metadata_new
+ gimp_metadata_save_to_file
+ gimp_metadata_serialize
+ gimp_metadata_set_bits_per_sample
+ gimp_metadata_set_colorspace
+ gimp_metadata_set_from_exif
+ gimp_metadata_set_from_iptc
+ gimp_metadata_set_from_xmp
+ gimp_metadata_set_pixel_size
+ gimp_metadata_set_resolution
+ gimp_micro_version
+ gimp_minor_version
+ gimp_offset_type_get_type
+ gimp_orientation_type_get_type
+ gimp_paint_application_mode_get_type
+ gimp_param_memsize_get_type
+ gimp_param_parasite_get_type
+ gimp_param_spec_memsize
+ gimp_param_spec_parasite
+ gimp_param_spec_unit
+ gimp_param_spec_value_array
+ gimp_param_unit_get_type
+ gimp_param_value_array_get_type
+ gimp_parasite_compare
+ gimp_parasite_copy
+ gimp_parasite_data
+ gimp_parasite_data_size
+ gimp_parasite_flags
+ gimp_parasite_free
+ gimp_parasite_get_type
+ gimp_parasite_has_flag
+ gimp_parasite_is_persistent
+ gimp_parasite_is_type
+ gimp_parasite_is_undoable
+ gimp_parasite_name
+ gimp_parasite_new
+ gimp_path_free
+ gimp_path_get_user_writable_dir
+ gimp_path_parse
+ gimp_path_to_str
+ gimp_pdb_arg_type_get_type
+ gimp_pdb_error_handler_get_type
+ gimp_pdb_proc_type_get_type
+ gimp_pdb_status_type_get_type
+ gimp_personal_rc_file
+ gimp_pixels_to_units
+ gimp_pixpipe_params_build
+ gimp_pixpipe_params_free
+ gimp_pixpipe_params_init
+ gimp_pixpipe_params_parse
+ gimp_plug_in_directory
+ gimp_plug_in_directory_file
+ gimp_precision_get_type
+ gimp_progress_command_get_type
+ gimp_rectangle_intersect
+ gimp_rectangle_union
+ gimp_repeat_mode_get_type
+ gimp_rotation_type_get_type
+ gimp_run_mode_get_type
+ gimp_select_criterion_get_type
+ gimp_signal_private
+ gimp_size_type_get_type
+ gimp_stack_trace_available
+ gimp_stack_trace_mode_get_type
+ gimp_stack_trace_print
+ gimp_stack_trace_query
+ gimp_strip_uline
+ gimp_stroke_method_get_type
+ gimp_sysconf_directory
+ gimp_sysconf_directory_file
+ gimp_temp_directory
+ gimp_text_direction_get_type
+ gimp_text_hint_style_get_type
+ gimp_text_justification_get_type
+ gimp_transfer_mode_compat_get_type
+ gimp_transfer_mode_get_type
+ gimp_transform_direction_get_type
+ gimp_transform_resize_get_type
+ gimp_type_get_translation_context
+ gimp_type_get_translation_domain
+ gimp_type_set_translation_context
+ gimp_type_set_translation_domain
+ gimp_unit_format_string
+ gimp_unit_get_abbreviation
+ gimp_unit_get_deletion_flag
+ gimp_unit_get_digits
+ gimp_unit_get_factor
+ gimp_unit_get_identifier
+ gimp_unit_get_number_of_built_in_units
+ gimp_unit_get_number_of_units
+ gimp_unit_get_plural
+ gimp_unit_get_scaled_digits
+ gimp_unit_get_singular
+ gimp_unit_get_symbol
+ gimp_unit_get_type
+ gimp_unit_is_metric
+ gimp_unit_new
+ gimp_unit_set_deletion_flag
+ gimp_units_to_pixels
+ gimp_units_to_points
+ gimp_user_directory
+ gimp_user_directory_get_type
+ gimp_utf8_strtrim
+ gimp_value_array_append
+ gimp_value_array_get_type
+ gimp_value_array_index
+ gimp_value_array_insert
+ gimp_value_array_length
+ gimp_value_array_new
+ gimp_value_array_prepend
+ gimp_value_array_ref
+ gimp_value_array_remove
+ gimp_value_array_truncate
+ gimp_value_array_unref
+ gimp_vectors_stroke_type_get_type
+ gimp_wire_clear_error
+ gimp_wire_destroy
+ gimp_wire_error
+ gimp_wire_flush
+ gimp_wire_read
+ gimp_wire_read_msg
+ gimp_wire_register
+ gimp_wire_set_flusher
+ gimp_wire_set_reader
+ gimp_wire_set_writer
+ gimp_wire_write
+ gimp_wire_write_msg
+ gp_config_write
+ gp_extension_ack_write
+ gp_has_init_write
+ gp_init
+ gp_params_destroy
+ gp_proc_install_write
+ gp_proc_return_write
+ gp_proc_run_write
+ gp_proc_uninstall_write
+ gp_quit_write
+ gp_temp_proc_return_write
+ gp_temp_proc_run_write
+ gp_tile_ack_write
+ gp_tile_data_write
+ gp_tile_req_write
diff --git a/libgimpbase/gimpbase.h b/libgimpbase/gimpbase.h
new file mode 100644
index 0000000..2cc1c4f
--- /dev/null
+++ b/libgimpbase/gimpbase.h
@@ -0,0 +1,46 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_BASE_H__
+#define __GIMP_BASE_H__
+
+#define __GIMP_BASE_H_INSIDE__
+
+#include <libgimpbase/gimpbasetypes.h>
+
+#include <libgimpbase/gimpchecks.h>
+#include <libgimpbase/gimpcpuaccel.h>
+#include <libgimpbase/gimpdatafiles.h>
+#include <libgimpbase/gimpenv.h>
+#include <libgimpbase/gimplimits.h>
+#include <libgimpbase/gimpmemsize.h>
+#include <libgimpbase/gimpmetadata.h>
+#include <libgimpbase/gimpparasite.h>
+#include <libgimpbase/gimprectangle.h>
+#include <libgimpbase/gimpunit.h>
+#include <libgimpbase/gimputils.h>
+#include <libgimpbase/gimpversion.h>
+#include <libgimpbase/gimpvaluearray.h>
+
+#ifndef G_OS_WIN32
+#include <libgimpbase/gimpsignal.h>
+#endif
+
+#undef __GIMP_BASE_H_INSIDE__
+
+#endif /* __GIMP_BASE_H__ */
diff --git a/libgimpbase/gimpbaseenums.c b/libgimpbase/gimpbaseenums.c
new file mode 100644
index 0000000..186e48e
--- /dev/null
+++ b/libgimpbase/gimpbaseenums.c
@@ -0,0 +1,2045 @@
+
+/* Generated data (by gimp-mkenums) */
+
+#include "config.h"
+#include <glib-object.h>
+#undef GIMP_DISABLE_DEPRECATED
+#include "gimpbasetypes.h"
+#include "libgimp/libgimp-intl.h"
+
+/* enumerations from "gimpbaseenums.h" */
+GType
+gimp_add_mask_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_ADD_MASK_WHITE, "GIMP_ADD_MASK_WHITE", "white" },
+ { GIMP_ADD_MASK_BLACK, "GIMP_ADD_MASK_BLACK", "black" },
+ { GIMP_ADD_MASK_ALPHA, "GIMP_ADD_MASK_ALPHA", "alpha" },
+ { GIMP_ADD_MASK_ALPHA_TRANSFER, "GIMP_ADD_MASK_ALPHA_TRANSFER", "alpha-transfer" },
+ { GIMP_ADD_MASK_SELECTION, "GIMP_ADD_MASK_SELECTION", "selection" },
+ { GIMP_ADD_MASK_COPY, "GIMP_ADD_MASK_COPY", "copy" },
+ { GIMP_ADD_MASK_CHANNEL, "GIMP_ADD_MASK_CHANNEL", "channel" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_ADD_MASK_WHITE, NC_("add-mask-type", "_White (full opacity)"), NULL },
+ { GIMP_ADD_MASK_BLACK, NC_("add-mask-type", "_Black (full transparency)"), NULL },
+ { GIMP_ADD_MASK_ALPHA, NC_("add-mask-type", "Layer's _alpha channel"), NULL },
+ { GIMP_ADD_MASK_ALPHA_TRANSFER, NC_("add-mask-type", "_Transfer layer's alpha channel"), NULL },
+ { GIMP_ADD_MASK_SELECTION, NC_("add-mask-type", "_Selection"), NULL },
+ { GIMP_ADD_MASK_COPY, NC_("add-mask-type", "_Grayscale copy of layer"), NULL },
+ { GIMP_ADD_MASK_CHANNEL, NC_("add-mask-type", "C_hannel"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpAddMaskType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "add-mask-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_blend_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_BLEND_FG_BG_RGB, "GIMP_BLEND_FG_BG_RGB", "fg-bg-rgb" },
+ { GIMP_BLEND_FG_BG_HSV, "GIMP_BLEND_FG_BG_HSV", "fg-bg-hsv" },
+ { GIMP_BLEND_FG_TRANSPARENT, "GIMP_BLEND_FG_TRANSPARENT", "fg-transparent" },
+ { GIMP_BLEND_CUSTOM, "GIMP_BLEND_CUSTOM", "custom" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_BLEND_FG_BG_RGB, NC_("blend-mode", "FG to BG (RGB)"), NULL },
+ { GIMP_BLEND_FG_BG_HSV, NC_("blend-mode", "FG to BG (HSV)"), NULL },
+ { GIMP_BLEND_FG_TRANSPARENT, NC_("blend-mode", "FG to transparent"), NULL },
+ { GIMP_BLEND_CUSTOM, NC_("blend-mode", "Custom gradient"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpBlendMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "blend-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_brush_generated_shape_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_BRUSH_GENERATED_CIRCLE, "GIMP_BRUSH_GENERATED_CIRCLE", "circle" },
+ { GIMP_BRUSH_GENERATED_SQUARE, "GIMP_BRUSH_GENERATED_SQUARE", "square" },
+ { GIMP_BRUSH_GENERATED_DIAMOND, "GIMP_BRUSH_GENERATED_DIAMOND", "diamond" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_BRUSH_GENERATED_CIRCLE, NC_("brush-generated-shape", "Circle"), NULL },
+ { GIMP_BRUSH_GENERATED_SQUARE, NC_("brush-generated-shape", "Square"), NULL },
+ { GIMP_BRUSH_GENERATED_DIAMOND, NC_("brush-generated-shape", "Diamond"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpBrushGeneratedShape", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "brush-generated-shape");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_bucket_fill_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_BUCKET_FILL_FG, "GIMP_BUCKET_FILL_FG", "fg" },
+ { GIMP_BUCKET_FILL_BG, "GIMP_BUCKET_FILL_BG", "bg" },
+ { GIMP_BUCKET_FILL_PATTERN, "GIMP_BUCKET_FILL_PATTERN", "pattern" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_BUCKET_FILL_FG, NC_("bucket-fill-mode", "FG color fill"), NULL },
+ { GIMP_BUCKET_FILL_BG, NC_("bucket-fill-mode", "BG color fill"), NULL },
+ { GIMP_BUCKET_FILL_PATTERN, NC_("bucket-fill-mode", "Pattern fill"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpBucketFillMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "bucket-fill-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_cap_style_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CAP_BUTT, "GIMP_CAP_BUTT", "butt" },
+ { GIMP_CAP_ROUND, "GIMP_CAP_ROUND", "round" },
+ { GIMP_CAP_SQUARE, "GIMP_CAP_SQUARE", "square" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CAP_BUTT, NC_("cap-style", "Butt"), NULL },
+ { GIMP_CAP_ROUND, NC_("cap-style", "Round"), NULL },
+ { GIMP_CAP_SQUARE, NC_("cap-style", "Square"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpCapStyle", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "cap-style");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_channel_ops_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CHANNEL_OP_ADD, "GIMP_CHANNEL_OP_ADD", "add" },
+ { GIMP_CHANNEL_OP_SUBTRACT, "GIMP_CHANNEL_OP_SUBTRACT", "subtract" },
+ { GIMP_CHANNEL_OP_REPLACE, "GIMP_CHANNEL_OP_REPLACE", "replace" },
+ { GIMP_CHANNEL_OP_INTERSECT, "GIMP_CHANNEL_OP_INTERSECT", "intersect" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CHANNEL_OP_ADD, NC_("channel-ops", "Add to the current selection"), NULL },
+ { GIMP_CHANNEL_OP_SUBTRACT, NC_("channel-ops", "Subtract from the current selection"), NULL },
+ { GIMP_CHANNEL_OP_REPLACE, NC_("channel-ops", "Replace the current selection"), NULL },
+ { GIMP_CHANNEL_OP_INTERSECT, NC_("channel-ops", "Intersect with the current selection"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpChannelOps", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "channel-ops");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_channel_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CHANNEL_RED, "GIMP_CHANNEL_RED", "red" },
+ { GIMP_CHANNEL_GREEN, "GIMP_CHANNEL_GREEN", "green" },
+ { GIMP_CHANNEL_BLUE, "GIMP_CHANNEL_BLUE", "blue" },
+ { GIMP_CHANNEL_GRAY, "GIMP_CHANNEL_GRAY", "gray" },
+ { GIMP_CHANNEL_INDEXED, "GIMP_CHANNEL_INDEXED", "indexed" },
+ { GIMP_CHANNEL_ALPHA, "GIMP_CHANNEL_ALPHA", "alpha" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CHANNEL_RED, NC_("channel-type", "Red"), NULL },
+ { GIMP_CHANNEL_GREEN, NC_("channel-type", "Green"), NULL },
+ { GIMP_CHANNEL_BLUE, NC_("channel-type", "Blue"), NULL },
+ { GIMP_CHANNEL_GRAY, NC_("channel-type", "Gray"), NULL },
+ { GIMP_CHANNEL_INDEXED, NC_("channel-type", "Indexed"), NULL },
+ { GIMP_CHANNEL_ALPHA, NC_("channel-type", "Alpha"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpChannelType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "channel-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_check_size_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CHECK_SIZE_SMALL_CHECKS, "GIMP_CHECK_SIZE_SMALL_CHECKS", "small-checks" },
+ { GIMP_CHECK_SIZE_MEDIUM_CHECKS, "GIMP_CHECK_SIZE_MEDIUM_CHECKS", "medium-checks" },
+ { GIMP_CHECK_SIZE_LARGE_CHECKS, "GIMP_CHECK_SIZE_LARGE_CHECKS", "large-checks" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CHECK_SIZE_SMALL_CHECKS, NC_("check-size", "Small"), NULL },
+ { GIMP_CHECK_SIZE_MEDIUM_CHECKS, NC_("check-size", "Medium"), NULL },
+ { GIMP_CHECK_SIZE_LARGE_CHECKS, NC_("check-size", "Large"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpCheckSize", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "check-size");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_check_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CHECK_TYPE_LIGHT_CHECKS, "GIMP_CHECK_TYPE_LIGHT_CHECKS", "light-checks" },
+ { GIMP_CHECK_TYPE_GRAY_CHECKS, "GIMP_CHECK_TYPE_GRAY_CHECKS", "gray-checks" },
+ { GIMP_CHECK_TYPE_DARK_CHECKS, "GIMP_CHECK_TYPE_DARK_CHECKS", "dark-checks" },
+ { GIMP_CHECK_TYPE_WHITE_ONLY, "GIMP_CHECK_TYPE_WHITE_ONLY", "white-only" },
+ { GIMP_CHECK_TYPE_GRAY_ONLY, "GIMP_CHECK_TYPE_GRAY_ONLY", "gray-only" },
+ { GIMP_CHECK_TYPE_BLACK_ONLY, "GIMP_CHECK_TYPE_BLACK_ONLY", "black-only" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CHECK_TYPE_LIGHT_CHECKS, NC_("check-type", "Light checks"), NULL },
+ { GIMP_CHECK_TYPE_GRAY_CHECKS, NC_("check-type", "Mid-tone checks"), NULL },
+ { GIMP_CHECK_TYPE_DARK_CHECKS, NC_("check-type", "Dark checks"), NULL },
+ { GIMP_CHECK_TYPE_WHITE_ONLY, NC_("check-type", "White only"), NULL },
+ { GIMP_CHECK_TYPE_GRAY_ONLY, NC_("check-type", "Gray only"), NULL },
+ { GIMP_CHECK_TYPE_BLACK_ONLY, NC_("check-type", "Black only"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpCheckType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "check-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_clone_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CLONE_IMAGE, "GIMP_CLONE_IMAGE", "image" },
+ { GIMP_CLONE_PATTERN, "GIMP_CLONE_PATTERN", "pattern" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CLONE_IMAGE, NC_("clone-type", "Image"), NULL },
+ { GIMP_CLONE_PATTERN, NC_("clone-type", "Pattern"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpCloneType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "clone-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_color_tag_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_COLOR_TAG_NONE, "GIMP_COLOR_TAG_NONE", "none" },
+ { GIMP_COLOR_TAG_BLUE, "GIMP_COLOR_TAG_BLUE", "blue" },
+ { GIMP_COLOR_TAG_GREEN, "GIMP_COLOR_TAG_GREEN", "green" },
+ { GIMP_COLOR_TAG_YELLOW, "GIMP_COLOR_TAG_YELLOW", "yellow" },
+ { GIMP_COLOR_TAG_ORANGE, "GIMP_COLOR_TAG_ORANGE", "orange" },
+ { GIMP_COLOR_TAG_BROWN, "GIMP_COLOR_TAG_BROWN", "brown" },
+ { GIMP_COLOR_TAG_RED, "GIMP_COLOR_TAG_RED", "red" },
+ { GIMP_COLOR_TAG_VIOLET, "GIMP_COLOR_TAG_VIOLET", "violet" },
+ { GIMP_COLOR_TAG_GRAY, "GIMP_COLOR_TAG_GRAY", "gray" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_COLOR_TAG_NONE, NC_("color-tag", "None"), NULL },
+ { GIMP_COLOR_TAG_BLUE, NC_("color-tag", "Blue"), NULL },
+ { GIMP_COLOR_TAG_GREEN, NC_("color-tag", "Green"), NULL },
+ { GIMP_COLOR_TAG_YELLOW, NC_("color-tag", "Yellow"), NULL },
+ { GIMP_COLOR_TAG_ORANGE, NC_("color-tag", "Orange"), NULL },
+ { GIMP_COLOR_TAG_BROWN, NC_("color-tag", "Brown"), NULL },
+ { GIMP_COLOR_TAG_RED, NC_("color-tag", "Red"), NULL },
+ { GIMP_COLOR_TAG_VIOLET, NC_("color-tag", "Violet"), NULL },
+ { GIMP_COLOR_TAG_GRAY, NC_("color-tag", "Gray"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpColorTag", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "color-tag");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_component_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_COMPONENT_TYPE_U8, "GIMP_COMPONENT_TYPE_U8", "u8" },
+ { GIMP_COMPONENT_TYPE_U16, "GIMP_COMPONENT_TYPE_U16", "u16" },
+ { GIMP_COMPONENT_TYPE_U32, "GIMP_COMPONENT_TYPE_U32", "u32" },
+ { GIMP_COMPONENT_TYPE_HALF, "GIMP_COMPONENT_TYPE_HALF", "half" },
+ { GIMP_COMPONENT_TYPE_FLOAT, "GIMP_COMPONENT_TYPE_FLOAT", "float" },
+ { GIMP_COMPONENT_TYPE_DOUBLE, "GIMP_COMPONENT_TYPE_DOUBLE", "double" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_COMPONENT_TYPE_U8, NC_("component-type", "8-bit integer"), NULL },
+ { GIMP_COMPONENT_TYPE_U16, NC_("component-type", "16-bit integer"), NULL },
+ { GIMP_COMPONENT_TYPE_U32, NC_("component-type", "32-bit integer"), NULL },
+ { GIMP_COMPONENT_TYPE_HALF, NC_("component-type", "16-bit floating point"), NULL },
+ { GIMP_COMPONENT_TYPE_FLOAT, NC_("component-type", "32-bit floating point"), NULL },
+ { GIMP_COMPONENT_TYPE_DOUBLE, NC_("component-type", "64-bit floating point"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpComponentType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "component-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_convert_palette_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CONVERT_PALETTE_GENERATE, "GIMP_CONVERT_PALETTE_GENERATE", "generate" },
+ { GIMP_CONVERT_PALETTE_WEB, "GIMP_CONVERT_PALETTE_WEB", "web" },
+ { GIMP_CONVERT_PALETTE_MONO, "GIMP_CONVERT_PALETTE_MONO", "mono" },
+ { GIMP_CONVERT_PALETTE_CUSTOM, "GIMP_CONVERT_PALETTE_CUSTOM", "custom" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CONVERT_PALETTE_GENERATE, NC_("convert-palette-type", "Generate optimum palette"), NULL },
+ { GIMP_CONVERT_PALETTE_WEB, NC_("convert-palette-type", "Use web-optimized palette"), NULL },
+ { GIMP_CONVERT_PALETTE_MONO, NC_("convert-palette-type", "Use black and white (1-bit) palette"), NULL },
+ { GIMP_CONVERT_PALETTE_CUSTOM, NC_("convert-palette-type", "Use custom palette"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpConvertPaletteType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "convert-palette-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_convolve_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_CONVOLVE_BLUR, "GIMP_CONVOLVE_BLUR", "blur" },
+ { GIMP_CONVOLVE_SHARPEN, "GIMP_CONVOLVE_SHARPEN", "sharpen" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_CONVOLVE_BLUR, NC_("convolve-type", "Blur"), NULL },
+ { GIMP_CONVOLVE_SHARPEN, NC_("convolve-type", "Sharpen"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpConvolveType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "convolve-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_desaturate_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_DESATURATE_LIGHTNESS, "GIMP_DESATURATE_LIGHTNESS", "lightness" },
+ { GIMP_DESATURATE_LUMA, "GIMP_DESATURATE_LUMA", "luma" },
+ { GIMP_DESATURATE_AVERAGE, "GIMP_DESATURATE_AVERAGE", "average" },
+ { GIMP_DESATURATE_LUMINANCE, "GIMP_DESATURATE_LUMINANCE", "luminance" },
+ { GIMP_DESATURATE_VALUE, "GIMP_DESATURATE_VALUE", "value" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_DESATURATE_LIGHTNESS, NC_("desaturate-mode", "Lightness (HSL)"), NULL },
+ { GIMP_DESATURATE_LUMA, NC_("desaturate-mode", "Luma"), NULL },
+ { GIMP_DESATURATE_AVERAGE, NC_("desaturate-mode", "Average (HSI Intensity)"), NULL },
+ { GIMP_DESATURATE_LUMINANCE, NC_("desaturate-mode", "Luminance"), NULL },
+ { GIMP_DESATURATE_VALUE, NC_("desaturate-mode", "Value (HSV)"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpDesaturateMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "desaturate-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_dodge_burn_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_DODGE_BURN_TYPE_DODGE, "GIMP_DODGE_BURN_TYPE_DODGE", "dodge" },
+ { GIMP_DODGE_BURN_TYPE_BURN, "GIMP_DODGE_BURN_TYPE_BURN", "burn" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_DODGE_BURN_TYPE_DODGE, NC_("dodge-burn-type", "Dodge"), NULL },
+ { GIMP_DODGE_BURN_TYPE_BURN, NC_("dodge-burn-type", "Burn"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpDodgeBurnType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "dodge-burn-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_fill_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_FILL_FOREGROUND, "GIMP_FILL_FOREGROUND", "foreground" },
+ { GIMP_FILL_BACKGROUND, "GIMP_FILL_BACKGROUND", "background" },
+ { GIMP_FILL_WHITE, "GIMP_FILL_WHITE", "white" },
+ { GIMP_FILL_TRANSPARENT, "GIMP_FILL_TRANSPARENT", "transparent" },
+ { GIMP_FILL_PATTERN, "GIMP_FILL_PATTERN", "pattern" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_FILL_FOREGROUND, NC_("fill-type", "Foreground color"), NULL },
+ { GIMP_FILL_BACKGROUND, NC_("fill-type", "Background color"), NULL },
+ { GIMP_FILL_WHITE, NC_("fill-type", "White"), NULL },
+ { GIMP_FILL_TRANSPARENT, NC_("fill-type", "Transparency"), NULL },
+ { GIMP_FILL_PATTERN, NC_("fill-type", "Pattern"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpFillType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "fill-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_foreground_extract_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_FOREGROUND_EXTRACT_SIOX, "GIMP_FOREGROUND_EXTRACT_SIOX", "siox" },
+ { GIMP_FOREGROUND_EXTRACT_MATTING, "GIMP_FOREGROUND_EXTRACT_MATTING", "matting" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_FOREGROUND_EXTRACT_SIOX, "GIMP_FOREGROUND_EXTRACT_SIOX", NULL },
+ { GIMP_FOREGROUND_EXTRACT_MATTING, "GIMP_FOREGROUND_EXTRACT_MATTING", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpForegroundExtractMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "foreground-extract-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_gradient_blend_color_space_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL, "GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL", "rgb-perceptual" },
+ { GIMP_GRADIENT_BLEND_RGB_LINEAR, "GIMP_GRADIENT_BLEND_RGB_LINEAR", "rgb-linear" },
+ { GIMP_GRADIENT_BLEND_CIE_LAB, "GIMP_GRADIENT_BLEND_CIE_LAB", "cie-lab" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL, NC_("gradient-blend-color-space", "Perceptual RGB"), NULL },
+ { GIMP_GRADIENT_BLEND_RGB_LINEAR, NC_("gradient-blend-color-space", "Linear RGB"), NULL },
+ { GIMP_GRADIENT_BLEND_CIE_LAB, NC_("gradient-blend-color-space", "CIE Lab"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpGradientBlendColorSpace", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "gradient-blend-color-space");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_gradient_segment_color_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_GRADIENT_SEGMENT_RGB, "GIMP_GRADIENT_SEGMENT_RGB", "rgb" },
+ { GIMP_GRADIENT_SEGMENT_HSV_CCW, "GIMP_GRADIENT_SEGMENT_HSV_CCW", "hsv-ccw" },
+ { GIMP_GRADIENT_SEGMENT_HSV_CW, "GIMP_GRADIENT_SEGMENT_HSV_CW", "hsv-cw" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_GRADIENT_SEGMENT_RGB, NC_("gradient-segment-color", "RGB"), NULL },
+ { GIMP_GRADIENT_SEGMENT_HSV_CCW, NC_("gradient-segment-color", "HSV (counter-clockwise hue)"), NULL },
+ /* Translators: this is an abbreviated version of "HSV (counter-clockwise hue)".
+ Keep it short. */
+ { GIMP_GRADIENT_SEGMENT_HSV_CCW, NC_("gradient-segment-color", "HSV (ccw)"), NULL },
+ { GIMP_GRADIENT_SEGMENT_HSV_CW, NC_("gradient-segment-color", "HSV (clockwise hue)"), NULL },
+ /* Translators: this is an abbreviated version of "HSV (clockwise hue)".
+ Keep it short. */
+ { GIMP_GRADIENT_SEGMENT_HSV_CW, NC_("gradient-segment-color", "HSV (cw)"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpGradientSegmentColor", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "gradient-segment-color");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_gradient_segment_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_GRADIENT_SEGMENT_LINEAR, "GIMP_GRADIENT_SEGMENT_LINEAR", "linear" },
+ { GIMP_GRADIENT_SEGMENT_CURVED, "GIMP_GRADIENT_SEGMENT_CURVED", "curved" },
+ { GIMP_GRADIENT_SEGMENT_SINE, "GIMP_GRADIENT_SEGMENT_SINE", "sine" },
+ { GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING, "GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING", "sphere-increasing" },
+ { GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING, "GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING", "sphere-decreasing" },
+ { GIMP_GRADIENT_SEGMENT_STEP, "GIMP_GRADIENT_SEGMENT_STEP", "step" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_GRADIENT_SEGMENT_LINEAR, NC_("gradient-segment-type", "Linear"), NULL },
+ { GIMP_GRADIENT_SEGMENT_CURVED, NC_("gradient-segment-type", "Curved"), NULL },
+ { GIMP_GRADIENT_SEGMENT_SINE, NC_("gradient-segment-type", "Sinusoidal"), NULL },
+ { GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING, NC_("gradient-segment-type", "Spherical (increasing)"), NULL },
+ /* Translators: this is an abbreviated version of "Spherical (increasing)".
+ Keep it short. */
+ { GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING, NC_("gradient-segment-type", "Spherical (inc)"), NULL },
+ { GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING, NC_("gradient-segment-type", "Spherical (decreasing)"), NULL },
+ /* Translators: this is an abbreviated version of "Spherical (decreasing)".
+ Keep it short. */
+ { GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING, NC_("gradient-segment-type", "Spherical (dec)"), NULL },
+ { GIMP_GRADIENT_SEGMENT_STEP, NC_("gradient-segment-type", "Step"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpGradientSegmentType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "gradient-segment-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_gradient_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_GRADIENT_LINEAR, "GIMP_GRADIENT_LINEAR", "linear" },
+ { GIMP_GRADIENT_BILINEAR, "GIMP_GRADIENT_BILINEAR", "bilinear" },
+ { GIMP_GRADIENT_RADIAL, "GIMP_GRADIENT_RADIAL", "radial" },
+ { GIMP_GRADIENT_SQUARE, "GIMP_GRADIENT_SQUARE", "square" },
+ { GIMP_GRADIENT_CONICAL_SYMMETRIC, "GIMP_GRADIENT_CONICAL_SYMMETRIC", "conical-symmetric" },
+ { GIMP_GRADIENT_CONICAL_ASYMMETRIC, "GIMP_GRADIENT_CONICAL_ASYMMETRIC", "conical-asymmetric" },
+ { GIMP_GRADIENT_SHAPEBURST_ANGULAR, "GIMP_GRADIENT_SHAPEBURST_ANGULAR", "shapeburst-angular" },
+ { GIMP_GRADIENT_SHAPEBURST_SPHERICAL, "GIMP_GRADIENT_SHAPEBURST_SPHERICAL", "shapeburst-spherical" },
+ { GIMP_GRADIENT_SHAPEBURST_DIMPLED, "GIMP_GRADIENT_SHAPEBURST_DIMPLED", "shapeburst-dimpled" },
+ { GIMP_GRADIENT_SPIRAL_CLOCKWISE, "GIMP_GRADIENT_SPIRAL_CLOCKWISE", "spiral-clockwise" },
+ { GIMP_GRADIENT_SPIRAL_ANTICLOCKWISE, "GIMP_GRADIENT_SPIRAL_ANTICLOCKWISE", "spiral-anticlockwise" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_GRADIENT_LINEAR, NC_("gradient-type", "Linear"), NULL },
+ { GIMP_GRADIENT_BILINEAR, NC_("gradient-type", "Bi-linear"), NULL },
+ { GIMP_GRADIENT_RADIAL, NC_("gradient-type", "Radial"), NULL },
+ { GIMP_GRADIENT_SQUARE, NC_("gradient-type", "Square"), NULL },
+ { GIMP_GRADIENT_CONICAL_SYMMETRIC, NC_("gradient-type", "Conical (symmetric)"), NULL },
+ /* Translators: this is an abbreviated version of "Conical (symmetric)".
+ Keep it short. */
+ { GIMP_GRADIENT_CONICAL_SYMMETRIC, NC_("gradient-type", "Conical (sym)"), NULL },
+ { GIMP_GRADIENT_CONICAL_ASYMMETRIC, NC_("gradient-type", "Conical (asymmetric)"), NULL },
+ /* Translators: this is an abbreviated version of "Conical (asymmetric)".
+ Keep it short. */
+ { GIMP_GRADIENT_CONICAL_ASYMMETRIC, NC_("gradient-type", "Conical (asym)"), NULL },
+ { GIMP_GRADIENT_SHAPEBURST_ANGULAR, NC_("gradient-type", "Shaped (angular)"), NULL },
+ { GIMP_GRADIENT_SHAPEBURST_SPHERICAL, NC_("gradient-type", "Shaped (spherical)"), NULL },
+ { GIMP_GRADIENT_SHAPEBURST_DIMPLED, NC_("gradient-type", "Shaped (dimpled)"), NULL },
+ { GIMP_GRADIENT_SPIRAL_CLOCKWISE, NC_("gradient-type", "Spiral (clockwise)"), NULL },
+ /* Translators: this is an abbreviated version of "Spiral (clockwise)".
+ Keep it short. */
+ { GIMP_GRADIENT_SPIRAL_CLOCKWISE, NC_("gradient-type", "Spiral (cw)"), NULL },
+ { GIMP_GRADIENT_SPIRAL_ANTICLOCKWISE, NC_("gradient-type", "Spiral (counter-clockwise)"), NULL },
+ /* Translators: this is an abbreviated version of "Spiral (counter-clockwise)".
+ Keep it short. */
+ { GIMP_GRADIENT_SPIRAL_ANTICLOCKWISE, NC_("gradient-type", "Spiral (ccw)"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpGradientType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "gradient-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_grid_style_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_GRID_DOTS, "GIMP_GRID_DOTS", "dots" },
+ { GIMP_GRID_INTERSECTIONS, "GIMP_GRID_INTERSECTIONS", "intersections" },
+ { GIMP_GRID_ON_OFF_DASH, "GIMP_GRID_ON_OFF_DASH", "on-off-dash" },
+ { GIMP_GRID_DOUBLE_DASH, "GIMP_GRID_DOUBLE_DASH", "double-dash" },
+ { GIMP_GRID_SOLID, "GIMP_GRID_SOLID", "solid" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_GRID_DOTS, NC_("grid-style", "Intersections (dots)"), NULL },
+ { GIMP_GRID_INTERSECTIONS, NC_("grid-style", "Intersections (crosshairs)"), NULL },
+ { GIMP_GRID_ON_OFF_DASH, NC_("grid-style", "Dashed"), NULL },
+ { GIMP_GRID_DOUBLE_DASH, NC_("grid-style", "Double dashed"), NULL },
+ { GIMP_GRID_SOLID, NC_("grid-style", "Solid"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpGridStyle", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "grid-style");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_hue_range_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_HUE_RANGE_ALL, "GIMP_HUE_RANGE_ALL", "all" },
+ { GIMP_HUE_RANGE_RED, "GIMP_HUE_RANGE_RED", "red" },
+ { GIMP_HUE_RANGE_YELLOW, "GIMP_HUE_RANGE_YELLOW", "yellow" },
+ { GIMP_HUE_RANGE_GREEN, "GIMP_HUE_RANGE_GREEN", "green" },
+ { GIMP_HUE_RANGE_CYAN, "GIMP_HUE_RANGE_CYAN", "cyan" },
+ { GIMP_HUE_RANGE_BLUE, "GIMP_HUE_RANGE_BLUE", "blue" },
+ { GIMP_HUE_RANGE_MAGENTA, "GIMP_HUE_RANGE_MAGENTA", "magenta" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_HUE_RANGE_ALL, "GIMP_HUE_RANGE_ALL", NULL },
+ { GIMP_HUE_RANGE_RED, "GIMP_HUE_RANGE_RED", NULL },
+ { GIMP_HUE_RANGE_YELLOW, "GIMP_HUE_RANGE_YELLOW", NULL },
+ { GIMP_HUE_RANGE_GREEN, "GIMP_HUE_RANGE_GREEN", NULL },
+ { GIMP_HUE_RANGE_CYAN, "GIMP_HUE_RANGE_CYAN", NULL },
+ { GIMP_HUE_RANGE_BLUE, "GIMP_HUE_RANGE_BLUE", NULL },
+ { GIMP_HUE_RANGE_MAGENTA, "GIMP_HUE_RANGE_MAGENTA", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpHueRange", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "hue-range");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_icon_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_ICON_TYPE_ICON_NAME, "GIMP_ICON_TYPE_ICON_NAME", "icon-name" },
+ { GIMP_ICON_TYPE_INLINE_PIXBUF, "GIMP_ICON_TYPE_INLINE_PIXBUF", "inline-pixbuf" },
+ { GIMP_ICON_TYPE_IMAGE_FILE, "GIMP_ICON_TYPE_IMAGE_FILE", "image-file" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_ICON_TYPE_ICON_NAME, NC_("icon-type", "Icon name"), NULL },
+ { GIMP_ICON_TYPE_INLINE_PIXBUF, NC_("icon-type", "Inline pixbuf"), NULL },
+ { GIMP_ICON_TYPE_IMAGE_FILE, NC_("icon-type", "Image file"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpIconType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "icon-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_image_base_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_RGB, "GIMP_RGB", "rgb" },
+ { GIMP_GRAY, "GIMP_GRAY", "gray" },
+ { GIMP_INDEXED, "GIMP_INDEXED", "indexed" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_RGB, NC_("image-base-type", "RGB color"), NULL },
+ { GIMP_GRAY, NC_("image-base-type", "Grayscale"), NULL },
+ { GIMP_INDEXED, NC_("image-base-type", "Indexed color"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpImageBaseType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "image-base-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_image_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_RGB_IMAGE, "GIMP_RGB_IMAGE", "rgb-image" },
+ { GIMP_RGBA_IMAGE, "GIMP_RGBA_IMAGE", "rgba-image" },
+ { GIMP_GRAY_IMAGE, "GIMP_GRAY_IMAGE", "gray-image" },
+ { GIMP_GRAYA_IMAGE, "GIMP_GRAYA_IMAGE", "graya-image" },
+ { GIMP_INDEXED_IMAGE, "GIMP_INDEXED_IMAGE", "indexed-image" },
+ { GIMP_INDEXEDA_IMAGE, "GIMP_INDEXEDA_IMAGE", "indexeda-image" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_RGB_IMAGE, NC_("image-type", "RGB"), NULL },
+ { GIMP_RGBA_IMAGE, NC_("image-type", "RGB-alpha"), NULL },
+ { GIMP_GRAY_IMAGE, NC_("image-type", "Grayscale"), NULL },
+ { GIMP_GRAYA_IMAGE, NC_("image-type", "Grayscale-alpha"), NULL },
+ { GIMP_INDEXED_IMAGE, NC_("image-type", "Indexed"), NULL },
+ { GIMP_INDEXEDA_IMAGE, NC_("image-type", "Indexed-alpha"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpImageType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "image-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_ink_blob_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_INK_BLOB_TYPE_CIRCLE, "GIMP_INK_BLOB_TYPE_CIRCLE", "circle" },
+ { GIMP_INK_BLOB_TYPE_SQUARE, "GIMP_INK_BLOB_TYPE_SQUARE", "square" },
+ { GIMP_INK_BLOB_TYPE_DIAMOND, "GIMP_INK_BLOB_TYPE_DIAMOND", "diamond" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_INK_BLOB_TYPE_CIRCLE, NC_("ink-blob-type", "Circle"), NULL },
+ { GIMP_INK_BLOB_TYPE_SQUARE, NC_("ink-blob-type", "Square"), NULL },
+ { GIMP_INK_BLOB_TYPE_DIAMOND, NC_("ink-blob-type", "Diamond"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpInkBlobType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "ink-blob-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_interpolation_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_INTERPOLATION_NONE, "GIMP_INTERPOLATION_NONE", "none" },
+ { GIMP_INTERPOLATION_LINEAR, "GIMP_INTERPOLATION_LINEAR", "linear" },
+ { GIMP_INTERPOLATION_CUBIC, "GIMP_INTERPOLATION_CUBIC", "cubic" },
+ { GIMP_INTERPOLATION_NOHALO, "GIMP_INTERPOLATION_NOHALO", "nohalo" },
+ { GIMP_INTERPOLATION_LOHALO, "GIMP_INTERPOLATION_LOHALO", "lohalo" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_INTERPOLATION_NONE, NC_("interpolation-type", "None"), NULL },
+ { GIMP_INTERPOLATION_LINEAR, NC_("interpolation-type", "Linear"), NULL },
+ { GIMP_INTERPOLATION_CUBIC, NC_("interpolation-type", "Cubic"), NULL },
+ { GIMP_INTERPOLATION_NOHALO, NC_("interpolation-type", "NoHalo"), NULL },
+ { GIMP_INTERPOLATION_LOHALO, NC_("interpolation-type", "LoHalo"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpInterpolationType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "interpolation-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_join_style_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_JOIN_MITER, "GIMP_JOIN_MITER", "miter" },
+ { GIMP_JOIN_ROUND, "GIMP_JOIN_ROUND", "round" },
+ { GIMP_JOIN_BEVEL, "GIMP_JOIN_BEVEL", "bevel" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_JOIN_MITER, NC_("join-style", "Miter"), NULL },
+ { GIMP_JOIN_ROUND, NC_("join-style", "Round"), NULL },
+ { GIMP_JOIN_BEVEL, NC_("join-style", "Bevel"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpJoinStyle", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "join-style");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_mask_apply_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_MASK_APPLY, "GIMP_MASK_APPLY", "apply" },
+ { GIMP_MASK_DISCARD, "GIMP_MASK_DISCARD", "discard" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_MASK_APPLY, "GIMP_MASK_APPLY", NULL },
+ { GIMP_MASK_DISCARD, "GIMP_MASK_DISCARD", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpMaskApplyMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "mask-apply-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_merge_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_EXPAND_AS_NECESSARY, "GIMP_EXPAND_AS_NECESSARY", "expand-as-necessary" },
+ { GIMP_CLIP_TO_IMAGE, "GIMP_CLIP_TO_IMAGE", "clip-to-image" },
+ { GIMP_CLIP_TO_BOTTOM_LAYER, "GIMP_CLIP_TO_BOTTOM_LAYER", "clip-to-bottom-layer" },
+ { GIMP_FLATTEN_IMAGE, "GIMP_FLATTEN_IMAGE", "flatten-image" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_EXPAND_AS_NECESSARY, NC_("merge-type", "Expanded as necessary"), NULL },
+ { GIMP_CLIP_TO_IMAGE, NC_("merge-type", "Clipped to image"), NULL },
+ { GIMP_CLIP_TO_BOTTOM_LAYER, NC_("merge-type", "Clipped to bottom layer"), NULL },
+ { GIMP_FLATTEN_IMAGE, NC_("merge-type", "Flatten"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpMergeType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "merge-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_message_handler_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_MESSAGE_BOX, "GIMP_MESSAGE_BOX", "message-box" },
+ { GIMP_CONSOLE, "GIMP_CONSOLE", "console" },
+ { GIMP_ERROR_CONSOLE, "GIMP_ERROR_CONSOLE", "error-console" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_MESSAGE_BOX, "GIMP_MESSAGE_BOX", NULL },
+ { GIMP_CONSOLE, "GIMP_CONSOLE", NULL },
+ { GIMP_ERROR_CONSOLE, "GIMP_ERROR_CONSOLE", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpMessageHandlerType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "message-handler-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_offset_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_OFFSET_BACKGROUND, "GIMP_OFFSET_BACKGROUND", "background" },
+ { GIMP_OFFSET_TRANSPARENT, "GIMP_OFFSET_TRANSPARENT", "transparent" },
+ { GIMP_OFFSET_WRAP_AROUND, "GIMP_OFFSET_WRAP_AROUND", "wrap-around" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_OFFSET_BACKGROUND, "GIMP_OFFSET_BACKGROUND", NULL },
+ { GIMP_OFFSET_TRANSPARENT, "GIMP_OFFSET_TRANSPARENT", NULL },
+ { GIMP_OFFSET_WRAP_AROUND, "GIMP_OFFSET_WRAP_AROUND", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpOffsetType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "offset-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_orientation_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_ORIENTATION_HORIZONTAL, "GIMP_ORIENTATION_HORIZONTAL", "horizontal" },
+ { GIMP_ORIENTATION_VERTICAL, "GIMP_ORIENTATION_VERTICAL", "vertical" },
+ { GIMP_ORIENTATION_UNKNOWN, "GIMP_ORIENTATION_UNKNOWN", "unknown" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_ORIENTATION_HORIZONTAL, NC_("orientation-type", "Horizontal"), NULL },
+ { GIMP_ORIENTATION_VERTICAL, NC_("orientation-type", "Vertical"), NULL },
+ { GIMP_ORIENTATION_UNKNOWN, NC_("orientation-type", "Unknown"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpOrientationType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "orientation-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_paint_application_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PAINT_CONSTANT, "GIMP_PAINT_CONSTANT", "constant" },
+ { GIMP_PAINT_INCREMENTAL, "GIMP_PAINT_INCREMENTAL", "incremental" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PAINT_CONSTANT, NC_("paint-application-mode", "Constant"), NULL },
+ { GIMP_PAINT_INCREMENTAL, NC_("paint-application-mode", "Incremental"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpPaintApplicationMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "paint-application-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_pdb_arg_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PDB_INT32, "GIMP_PDB_INT32", "int32" },
+ { GIMP_PDB_INT16, "GIMP_PDB_INT16", "int16" },
+ { GIMP_PDB_INT8, "GIMP_PDB_INT8", "int8" },
+ { GIMP_PDB_FLOAT, "GIMP_PDB_FLOAT", "float" },
+ { GIMP_PDB_STRING, "GIMP_PDB_STRING", "string" },
+ { GIMP_PDB_INT32ARRAY, "GIMP_PDB_INT32ARRAY", "int32array" },
+ { GIMP_PDB_INT16ARRAY, "GIMP_PDB_INT16ARRAY", "int16array" },
+ { GIMP_PDB_INT8ARRAY, "GIMP_PDB_INT8ARRAY", "int8array" },
+ { GIMP_PDB_FLOATARRAY, "GIMP_PDB_FLOATARRAY", "floatarray" },
+ { GIMP_PDB_STRINGARRAY, "GIMP_PDB_STRINGARRAY", "stringarray" },
+ { GIMP_PDB_COLOR, "GIMP_PDB_COLOR", "color" },
+ { GIMP_PDB_ITEM, "GIMP_PDB_ITEM", "item" },
+ { GIMP_PDB_DISPLAY, "GIMP_PDB_DISPLAY", "display" },
+ { GIMP_PDB_IMAGE, "GIMP_PDB_IMAGE", "image" },
+ { GIMP_PDB_LAYER, "GIMP_PDB_LAYER", "layer" },
+ { GIMP_PDB_CHANNEL, "GIMP_PDB_CHANNEL", "channel" },
+ { GIMP_PDB_DRAWABLE, "GIMP_PDB_DRAWABLE", "drawable" },
+ { GIMP_PDB_SELECTION, "GIMP_PDB_SELECTION", "selection" },
+ { GIMP_PDB_COLORARRAY, "GIMP_PDB_COLORARRAY", "colorarray" },
+ { GIMP_PDB_VECTORS, "GIMP_PDB_VECTORS", "vectors" },
+ { GIMP_PDB_PARASITE, "GIMP_PDB_PARASITE", "parasite" },
+ { GIMP_PDB_STATUS, "GIMP_PDB_STATUS", "status" },
+ { GIMP_PDB_END, "GIMP_PDB_END", "end" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PDB_INT32, "GIMP_PDB_INT32", NULL },
+ { GIMP_PDB_INT16, "GIMP_PDB_INT16", NULL },
+ { GIMP_PDB_INT8, "GIMP_PDB_INT8", NULL },
+ { GIMP_PDB_FLOAT, "GIMP_PDB_FLOAT", NULL },
+ { GIMP_PDB_STRING, "GIMP_PDB_STRING", NULL },
+ { GIMP_PDB_INT32ARRAY, "GIMP_PDB_INT32ARRAY", NULL },
+ { GIMP_PDB_INT16ARRAY, "GIMP_PDB_INT16ARRAY", NULL },
+ { GIMP_PDB_INT8ARRAY, "GIMP_PDB_INT8ARRAY", NULL },
+ { GIMP_PDB_FLOATARRAY, "GIMP_PDB_FLOATARRAY", NULL },
+ { GIMP_PDB_STRINGARRAY, "GIMP_PDB_STRINGARRAY", NULL },
+ { GIMP_PDB_COLOR, "GIMP_PDB_COLOR", NULL },
+ { GIMP_PDB_ITEM, "GIMP_PDB_ITEM", NULL },
+ { GIMP_PDB_DISPLAY, "GIMP_PDB_DISPLAY", NULL },
+ { GIMP_PDB_IMAGE, "GIMP_PDB_IMAGE", NULL },
+ { GIMP_PDB_LAYER, "GIMP_PDB_LAYER", NULL },
+ { GIMP_PDB_CHANNEL, "GIMP_PDB_CHANNEL", NULL },
+ { GIMP_PDB_DRAWABLE, "GIMP_PDB_DRAWABLE", NULL },
+ { GIMP_PDB_SELECTION, "GIMP_PDB_SELECTION", NULL },
+ { GIMP_PDB_COLORARRAY, "GIMP_PDB_COLORARRAY", NULL },
+ { GIMP_PDB_VECTORS, "GIMP_PDB_VECTORS", NULL },
+ { GIMP_PDB_PARASITE, "GIMP_PDB_PARASITE", NULL },
+ { GIMP_PDB_STATUS, "GIMP_PDB_STATUS", NULL },
+ { GIMP_PDB_END, "GIMP_PDB_END", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpPDBArgType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "pdb-arg-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_pdb_error_handler_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PDB_ERROR_HANDLER_INTERNAL, "GIMP_PDB_ERROR_HANDLER_INTERNAL", "internal" },
+ { GIMP_PDB_ERROR_HANDLER_PLUGIN, "GIMP_PDB_ERROR_HANDLER_PLUGIN", "plugin" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PDB_ERROR_HANDLER_INTERNAL, "GIMP_PDB_ERROR_HANDLER_INTERNAL", NULL },
+ { GIMP_PDB_ERROR_HANDLER_PLUGIN, "GIMP_PDB_ERROR_HANDLER_PLUGIN", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpPDBErrorHandler", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "pdb-error-handler");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_pdb_proc_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_INTERNAL, "GIMP_INTERNAL", "internal" },
+ { GIMP_PLUGIN, "GIMP_PLUGIN", "plugin" },
+ { GIMP_EXTENSION, "GIMP_EXTENSION", "extension" },
+ { GIMP_TEMPORARY, "GIMP_TEMPORARY", "temporary" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_INTERNAL, NC_("pdb-proc-type", "Internal GIMP procedure"), NULL },
+ { GIMP_PLUGIN, NC_("pdb-proc-type", "GIMP Plug-In"), NULL },
+ { GIMP_EXTENSION, NC_("pdb-proc-type", "GIMP Extension"), NULL },
+ { GIMP_TEMPORARY, NC_("pdb-proc-type", "Temporary Procedure"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpPDBProcType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "pdb-proc-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_pdb_status_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PDB_EXECUTION_ERROR, "GIMP_PDB_EXECUTION_ERROR", "execution-error" },
+ { GIMP_PDB_CALLING_ERROR, "GIMP_PDB_CALLING_ERROR", "calling-error" },
+ { GIMP_PDB_PASS_THROUGH, "GIMP_PDB_PASS_THROUGH", "pass-through" },
+ { GIMP_PDB_SUCCESS, "GIMP_PDB_SUCCESS", "success" },
+ { GIMP_PDB_CANCEL, "GIMP_PDB_CANCEL", "cancel" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PDB_EXECUTION_ERROR, "GIMP_PDB_EXECUTION_ERROR", NULL },
+ { GIMP_PDB_CALLING_ERROR, "GIMP_PDB_CALLING_ERROR", NULL },
+ { GIMP_PDB_PASS_THROUGH, "GIMP_PDB_PASS_THROUGH", NULL },
+ { GIMP_PDB_SUCCESS, "GIMP_PDB_SUCCESS", NULL },
+ { GIMP_PDB_CANCEL, "GIMP_PDB_CANCEL", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpPDBStatusType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "pdb-status-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_precision_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PRECISION_U8_LINEAR, "GIMP_PRECISION_U8_LINEAR", "u8-linear" },
+ { GIMP_PRECISION_U8_GAMMA, "GIMP_PRECISION_U8_GAMMA", "u8-gamma" },
+ { GIMP_PRECISION_U16_LINEAR, "GIMP_PRECISION_U16_LINEAR", "u16-linear" },
+ { GIMP_PRECISION_U16_GAMMA, "GIMP_PRECISION_U16_GAMMA", "u16-gamma" },
+ { GIMP_PRECISION_U32_LINEAR, "GIMP_PRECISION_U32_LINEAR", "u32-linear" },
+ { GIMP_PRECISION_U32_GAMMA, "GIMP_PRECISION_U32_GAMMA", "u32-gamma" },
+ { GIMP_PRECISION_HALF_LINEAR, "GIMP_PRECISION_HALF_LINEAR", "half-linear" },
+ { GIMP_PRECISION_HALF_GAMMA, "GIMP_PRECISION_HALF_GAMMA", "half-gamma" },
+ { GIMP_PRECISION_FLOAT_LINEAR, "GIMP_PRECISION_FLOAT_LINEAR", "float-linear" },
+ { GIMP_PRECISION_FLOAT_GAMMA, "GIMP_PRECISION_FLOAT_GAMMA", "float-gamma" },
+ { GIMP_PRECISION_DOUBLE_LINEAR, "GIMP_PRECISION_DOUBLE_LINEAR", "double-linear" },
+ { GIMP_PRECISION_DOUBLE_GAMMA, "GIMP_PRECISION_DOUBLE_GAMMA", "double-gamma" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PRECISION_U8_LINEAR, NC_("precision", "8-bit linear integer"), NULL },
+ { GIMP_PRECISION_U8_GAMMA, NC_("precision", "8-bit gamma integer"), NULL },
+ { GIMP_PRECISION_U16_LINEAR, NC_("precision", "16-bit linear integer"), NULL },
+ { GIMP_PRECISION_U16_GAMMA, NC_("precision", "16-bit gamma integer"), NULL },
+ { GIMP_PRECISION_U32_LINEAR, NC_("precision", "32-bit linear integer"), NULL },
+ { GIMP_PRECISION_U32_GAMMA, NC_("precision", "32-bit gamma integer"), NULL },
+ { GIMP_PRECISION_HALF_LINEAR, NC_("precision", "16-bit linear floating point"), NULL },
+ { GIMP_PRECISION_HALF_GAMMA, NC_("precision", "16-bit gamma floating point"), NULL },
+ { GIMP_PRECISION_FLOAT_LINEAR, NC_("precision", "32-bit linear floating point"), NULL },
+ { GIMP_PRECISION_FLOAT_GAMMA, NC_("precision", "32-bit gamma floating point"), NULL },
+ { GIMP_PRECISION_DOUBLE_LINEAR, NC_("precision", "64-bit linear floating point"), NULL },
+ { GIMP_PRECISION_DOUBLE_GAMMA, NC_("precision", "64-bit gamma floating point"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpPrecision", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "precision");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_progress_command_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PROGRESS_COMMAND_START, "GIMP_PROGRESS_COMMAND_START", "start" },
+ { GIMP_PROGRESS_COMMAND_END, "GIMP_PROGRESS_COMMAND_END", "end" },
+ { GIMP_PROGRESS_COMMAND_SET_TEXT, "GIMP_PROGRESS_COMMAND_SET_TEXT", "set-text" },
+ { GIMP_PROGRESS_COMMAND_SET_VALUE, "GIMP_PROGRESS_COMMAND_SET_VALUE", "set-value" },
+ { GIMP_PROGRESS_COMMAND_PULSE, "GIMP_PROGRESS_COMMAND_PULSE", "pulse" },
+ { GIMP_PROGRESS_COMMAND_GET_WINDOW, "GIMP_PROGRESS_COMMAND_GET_WINDOW", "get-window" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PROGRESS_COMMAND_START, "GIMP_PROGRESS_COMMAND_START", NULL },
+ { GIMP_PROGRESS_COMMAND_END, "GIMP_PROGRESS_COMMAND_END", NULL },
+ { GIMP_PROGRESS_COMMAND_SET_TEXT, "GIMP_PROGRESS_COMMAND_SET_TEXT", NULL },
+ { GIMP_PROGRESS_COMMAND_SET_VALUE, "GIMP_PROGRESS_COMMAND_SET_VALUE", NULL },
+ { GIMP_PROGRESS_COMMAND_PULSE, "GIMP_PROGRESS_COMMAND_PULSE", NULL },
+ { GIMP_PROGRESS_COMMAND_GET_WINDOW, "GIMP_PROGRESS_COMMAND_GET_WINDOW", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpProgressCommand", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "progress-command");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_repeat_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_REPEAT_NONE, "GIMP_REPEAT_NONE", "none" },
+ { GIMP_REPEAT_SAWTOOTH, "GIMP_REPEAT_SAWTOOTH", "sawtooth" },
+ { GIMP_REPEAT_TRIANGULAR, "GIMP_REPEAT_TRIANGULAR", "triangular" },
+ { GIMP_REPEAT_TRUNCATE, "GIMP_REPEAT_TRUNCATE", "truncate" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_REPEAT_NONE, NC_("repeat-mode", "None (extend)"), NULL },
+ { GIMP_REPEAT_SAWTOOTH, NC_("repeat-mode", "Sawtooth wave"), NULL },
+ { GIMP_REPEAT_TRIANGULAR, NC_("repeat-mode", "Triangular wave"), NULL },
+ { GIMP_REPEAT_TRUNCATE, NC_("repeat-mode", "Truncate"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpRepeatMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "repeat-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_rotation_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_ROTATE_90, "GIMP_ROTATE_90", "90" },
+ { GIMP_ROTATE_180, "GIMP_ROTATE_180", "180" },
+ { GIMP_ROTATE_270, "GIMP_ROTATE_270", "270" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_ROTATE_90, "GIMP_ROTATE_90", NULL },
+ { GIMP_ROTATE_180, "GIMP_ROTATE_180", NULL },
+ { GIMP_ROTATE_270, "GIMP_ROTATE_270", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpRotationType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "rotation-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_run_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_RUN_INTERACTIVE, "GIMP_RUN_INTERACTIVE", "interactive" },
+ { GIMP_RUN_NONINTERACTIVE, "GIMP_RUN_NONINTERACTIVE", "noninteractive" },
+ { GIMP_RUN_WITH_LAST_VALS, "GIMP_RUN_WITH_LAST_VALS", "with-last-vals" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_RUN_INTERACTIVE, NC_("run-mode", "Run interactively"), NULL },
+ { GIMP_RUN_NONINTERACTIVE, NC_("run-mode", "Run non-interactively"), NULL },
+ { GIMP_RUN_WITH_LAST_VALS, NC_("run-mode", "Run with last used values"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpRunMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "run-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_select_criterion_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_SELECT_CRITERION_COMPOSITE, "GIMP_SELECT_CRITERION_COMPOSITE", "composite" },
+ { GIMP_SELECT_CRITERION_R, "GIMP_SELECT_CRITERION_R", "r" },
+ { GIMP_SELECT_CRITERION_G, "GIMP_SELECT_CRITERION_G", "g" },
+ { GIMP_SELECT_CRITERION_B, "GIMP_SELECT_CRITERION_B", "b" },
+ { GIMP_SELECT_CRITERION_H, "GIMP_SELECT_CRITERION_H", "h" },
+ { GIMP_SELECT_CRITERION_S, "GIMP_SELECT_CRITERION_S", "s" },
+ { GIMP_SELECT_CRITERION_V, "GIMP_SELECT_CRITERION_V", "v" },
+ { GIMP_SELECT_CRITERION_A, "GIMP_SELECT_CRITERION_A", "a" },
+ { GIMP_SELECT_CRITERION_LCH_L, "GIMP_SELECT_CRITERION_LCH_L", "lch-l" },
+ { GIMP_SELECT_CRITERION_LCH_C, "GIMP_SELECT_CRITERION_LCH_C", "lch-c" },
+ { GIMP_SELECT_CRITERION_LCH_H, "GIMP_SELECT_CRITERION_LCH_H", "lch-h" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_SELECT_CRITERION_COMPOSITE, NC_("select-criterion", "Composite"), NULL },
+ { GIMP_SELECT_CRITERION_R, NC_("select-criterion", "Red"), NULL },
+ { GIMP_SELECT_CRITERION_G, NC_("select-criterion", "Green"), NULL },
+ { GIMP_SELECT_CRITERION_B, NC_("select-criterion", "Blue"), NULL },
+ { GIMP_SELECT_CRITERION_H, NC_("select-criterion", "HSV Hue"), NULL },
+ { GIMP_SELECT_CRITERION_S, NC_("select-criterion", "HSV Saturation"), NULL },
+ { GIMP_SELECT_CRITERION_V, NC_("select-criterion", "HSV Value"), NULL },
+ { GIMP_SELECT_CRITERION_A, NC_("select-criterion", "Alpha"), NULL },
+ { GIMP_SELECT_CRITERION_LCH_L, NC_("select-criterion", "LCh Lightness"), NULL },
+ { GIMP_SELECT_CRITERION_LCH_C, NC_("select-criterion", "LCh Chroma"), NULL },
+ { GIMP_SELECT_CRITERION_LCH_H, NC_("select-criterion", "LCh Hue"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpSelectCriterion", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "select-criterion");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_size_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PIXELS, "GIMP_PIXELS", "pixels" },
+ { GIMP_POINTS, "GIMP_POINTS", "points" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PIXELS, NC_("size-type", "Pixels"), NULL },
+ { GIMP_POINTS, NC_("size-type", "Points"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpSizeType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "size-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_stack_trace_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_STACK_TRACE_NEVER, "GIMP_STACK_TRACE_NEVER", "never" },
+ { GIMP_STACK_TRACE_QUERY, "GIMP_STACK_TRACE_QUERY", "query" },
+ { GIMP_STACK_TRACE_ALWAYS, "GIMP_STACK_TRACE_ALWAYS", "always" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_STACK_TRACE_NEVER, "GIMP_STACK_TRACE_NEVER", NULL },
+ { GIMP_STACK_TRACE_QUERY, "GIMP_STACK_TRACE_QUERY", NULL },
+ { GIMP_STACK_TRACE_ALWAYS, "GIMP_STACK_TRACE_ALWAYS", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpStackTraceMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "stack-trace-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_stroke_method_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_STROKE_LINE, "GIMP_STROKE_LINE", "line" },
+ { GIMP_STROKE_PAINT_METHOD, "GIMP_STROKE_PAINT_METHOD", "paint-method" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_STROKE_LINE, NC_("stroke-method", "Stroke line"), NULL },
+ { GIMP_STROKE_PAINT_METHOD, NC_("stroke-method", "Stroke with a paint tool"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpStrokeMethod", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "stroke-method");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_text_direction_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_TEXT_DIRECTION_LTR, "GIMP_TEXT_DIRECTION_LTR", "ltr" },
+ { GIMP_TEXT_DIRECTION_RTL, "GIMP_TEXT_DIRECTION_RTL", "rtl" },
+ { GIMP_TEXT_DIRECTION_TTB_RTL, "GIMP_TEXT_DIRECTION_TTB_RTL", "ttb-rtl" },
+ { GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT, "GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT", "ttb-rtl-upright" },
+ { GIMP_TEXT_DIRECTION_TTB_LTR, "GIMP_TEXT_DIRECTION_TTB_LTR", "ttb-ltr" },
+ { GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT, "GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT", "ttb-ltr-upright" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_TEXT_DIRECTION_LTR, NC_("text-direction", "From left to right"), NULL },
+ { GIMP_TEXT_DIRECTION_RTL, NC_("text-direction", "From right to left"), NULL },
+ { GIMP_TEXT_DIRECTION_TTB_RTL, NC_("text-direction", "Vertical, right to left (mixed orientation)"), NULL },
+ { GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT, NC_("text-direction", "Vertical, right to left (upright orientation)"), NULL },
+ { GIMP_TEXT_DIRECTION_TTB_LTR, NC_("text-direction", "Vertical, left to right (mixed orientation)"), NULL },
+ { GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT, NC_("text-direction", "Vertical, left to right (upright orientation)"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTextDirection", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "text-direction");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_text_hint_style_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_TEXT_HINT_STYLE_NONE, "GIMP_TEXT_HINT_STYLE_NONE", "none" },
+ { GIMP_TEXT_HINT_STYLE_SLIGHT, "GIMP_TEXT_HINT_STYLE_SLIGHT", "slight" },
+ { GIMP_TEXT_HINT_STYLE_MEDIUM, "GIMP_TEXT_HINT_STYLE_MEDIUM", "medium" },
+ { GIMP_TEXT_HINT_STYLE_FULL, "GIMP_TEXT_HINT_STYLE_FULL", "full" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_TEXT_HINT_STYLE_NONE, NC_("text-hint-style", "None"), NULL },
+ { GIMP_TEXT_HINT_STYLE_SLIGHT, NC_("text-hint-style", "Slight"), NULL },
+ { GIMP_TEXT_HINT_STYLE_MEDIUM, NC_("text-hint-style", "Medium"), NULL },
+ { GIMP_TEXT_HINT_STYLE_FULL, NC_("text-hint-style", "Full"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTextHintStyle", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "text-hint-style");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_text_justification_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_TEXT_JUSTIFY_LEFT, "GIMP_TEXT_JUSTIFY_LEFT", "left" },
+ { GIMP_TEXT_JUSTIFY_RIGHT, "GIMP_TEXT_JUSTIFY_RIGHT", "right" },
+ { GIMP_TEXT_JUSTIFY_CENTER, "GIMP_TEXT_JUSTIFY_CENTER", "center" },
+ { GIMP_TEXT_JUSTIFY_FILL, "GIMP_TEXT_JUSTIFY_FILL", "fill" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_TEXT_JUSTIFY_LEFT, NC_("text-justification", "Left justified"), NULL },
+ { GIMP_TEXT_JUSTIFY_RIGHT, NC_("text-justification", "Right justified"), NULL },
+ { GIMP_TEXT_JUSTIFY_CENTER, NC_("text-justification", "Centered"), NULL },
+ { GIMP_TEXT_JUSTIFY_FILL, NC_("text-justification", "Filled"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTextJustification", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "text-justification");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_transfer_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_TRANSFER_SHADOWS, "GIMP_TRANSFER_SHADOWS", "shadows" },
+ { GIMP_TRANSFER_MIDTONES, "GIMP_TRANSFER_MIDTONES", "midtones" },
+ { GIMP_TRANSFER_HIGHLIGHTS, "GIMP_TRANSFER_HIGHLIGHTS", "highlights" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_TRANSFER_SHADOWS, NC_("transfer-mode", "Shadows"), NULL },
+ { GIMP_TRANSFER_MIDTONES, NC_("transfer-mode", "Midtones"), NULL },
+ { GIMP_TRANSFER_HIGHLIGHTS, NC_("transfer-mode", "Highlights"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTransferMode", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "transfer-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_transform_direction_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_TRANSFORM_FORWARD, "GIMP_TRANSFORM_FORWARD", "forward" },
+ { GIMP_TRANSFORM_BACKWARD, "GIMP_TRANSFORM_BACKWARD", "backward" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_TRANSFORM_FORWARD, NC_("transform-direction", "Normal (Forward)"), NULL },
+ { GIMP_TRANSFORM_BACKWARD, NC_("transform-direction", "Corrective (Backward)"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTransformDirection", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "transform-direction");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_transform_resize_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_TRANSFORM_RESIZE_ADJUST, "GIMP_TRANSFORM_RESIZE_ADJUST", "adjust" },
+ { GIMP_TRANSFORM_RESIZE_CLIP, "GIMP_TRANSFORM_RESIZE_CLIP", "clip" },
+ { GIMP_TRANSFORM_RESIZE_CROP, "GIMP_TRANSFORM_RESIZE_CROP", "crop" },
+ { GIMP_TRANSFORM_RESIZE_CROP_WITH_ASPECT, "GIMP_TRANSFORM_RESIZE_CROP_WITH_ASPECT", "crop-with-aspect" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_TRANSFORM_RESIZE_ADJUST, NC_("transform-resize", "Adjust"), NULL },
+ { GIMP_TRANSFORM_RESIZE_CLIP, NC_("transform-resize", "Clip"), NULL },
+ { GIMP_TRANSFORM_RESIZE_CROP, NC_("transform-resize", "Crop to result"), NULL },
+ { GIMP_TRANSFORM_RESIZE_CROP_WITH_ASPECT, NC_("transform-resize", "Crop with aspect"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTransformResize", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "transform-resize");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_user_directory_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_USER_DIRECTORY_DESKTOP, "GIMP_USER_DIRECTORY_DESKTOP", "desktop" },
+ { GIMP_USER_DIRECTORY_DOCUMENTS, "GIMP_USER_DIRECTORY_DOCUMENTS", "documents" },
+ { GIMP_USER_DIRECTORY_DOWNLOAD, "GIMP_USER_DIRECTORY_DOWNLOAD", "download" },
+ { GIMP_USER_DIRECTORY_MUSIC, "GIMP_USER_DIRECTORY_MUSIC", "music" },
+ { GIMP_USER_DIRECTORY_PICTURES, "GIMP_USER_DIRECTORY_PICTURES", "pictures" },
+ { GIMP_USER_DIRECTORY_PUBLIC_SHARE, "GIMP_USER_DIRECTORY_PUBLIC_SHARE", "public-share" },
+ { GIMP_USER_DIRECTORY_TEMPLATES, "GIMP_USER_DIRECTORY_TEMPLATES", "templates" },
+ { GIMP_USER_DIRECTORY_VIDEOS, "GIMP_USER_DIRECTORY_VIDEOS", "videos" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_USER_DIRECTORY_DESKTOP, "GIMP_USER_DIRECTORY_DESKTOP", NULL },
+ { GIMP_USER_DIRECTORY_DOCUMENTS, "GIMP_USER_DIRECTORY_DOCUMENTS", NULL },
+ { GIMP_USER_DIRECTORY_DOWNLOAD, "GIMP_USER_DIRECTORY_DOWNLOAD", NULL },
+ { GIMP_USER_DIRECTORY_MUSIC, "GIMP_USER_DIRECTORY_MUSIC", NULL },
+ { GIMP_USER_DIRECTORY_PICTURES, "GIMP_USER_DIRECTORY_PICTURES", NULL },
+ { GIMP_USER_DIRECTORY_PUBLIC_SHARE, "GIMP_USER_DIRECTORY_PUBLIC_SHARE", NULL },
+ { GIMP_USER_DIRECTORY_TEMPLATES, "GIMP_USER_DIRECTORY_TEMPLATES", NULL },
+ { GIMP_USER_DIRECTORY_VIDEOS, "GIMP_USER_DIRECTORY_VIDEOS", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpUserDirectory", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "user-directory");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_vectors_stroke_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_VECTORS_STROKE_TYPE_BEZIER, "GIMP_VECTORS_STROKE_TYPE_BEZIER", "bezier" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_VECTORS_STROKE_TYPE_BEZIER, "GIMP_VECTORS_STROKE_TYPE_BEZIER", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpVectorsStrokeType", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "vectors-stroke-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+
+/* Generated data ends here */
+
diff --git a/libgimpbase/gimpbaseenums.h b/libgimpbase/gimpbaseenums.h
new file mode 100644
index 0000000..b3c6fb7
--- /dev/null
+++ b/libgimpbase/gimpbaseenums.h
@@ -0,0 +1,1558 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_BASE_ENUMS_H__
+#define __GIMP_BASE_ENUMS_H__
+
+
+/**
+ * SECTION: gimpbaseenums
+ * @title: gimpbaseenums
+ * @short_description: Basic GIMP enumeration data types.
+ *
+ * Basic GIMP enumeration data types.
+ **/
+
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/**
+ * GimpAddMaskType:
+ * @GIMP_ADD_MASK_WHITE: White (full opacity)
+ * @GIMP_ADD_MASK_BLACK: Black (full transparency)
+ * @GIMP_ADD_MASK_ALPHA: Layer's alpha channel
+ * @GIMP_ADD_MASK_ALPHA_TRANSFER: Transfer layer's alpha channel
+ * @GIMP_ADD_MASK_SELECTION: Selection
+ * @GIMP_ADD_MASK_COPY: Grayscale copy of layer
+ * @GIMP_ADD_MASK_CHANNEL: Channel
+ * @GIMP_ADD_WHITE_MASK: Deprecated alias for @GIMP_ADD_MASK_WHITE
+ * @GIMP_ADD_BLACK_MASK: Deprecated alias for @GIMP_ADD_MASK_BLACK
+ * @GIMP_ADD_ALPHA_MASK: Deprecated alias for @GIMP_ADD_MASK_ALPHA
+ * @GIMP_ADD_ALPHA_TRANSFER_MASK: Deprecated alias for
+ * @GIMP_ADD_MASK_ALPHA_TRANSFER
+ * @GIMP_ADD_SELECTION_MASK: Deprecated alias for @GIMP_ADD_MASK_SELECTION
+ * @GIMP_ADD_COPY_MASK: Deprecated alias for @GIMP_ADD_MASK_COPY
+ * @GIMP_ADD_CHANNEL_MASK: Deprecated aliaa for @GIMP_ADD_MASK_CHANNEL
+ *
+ * Modes of initialising a layer mask.
+ **/
+#define GIMP_TYPE_ADD_MASK_TYPE (gimp_add_mask_type_get_type ())
+
+GType gimp_add_mask_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_ADD_MASK_WHITE, /*< desc="_White (full opacity)" >*/
+ GIMP_ADD_MASK_BLACK, /*< desc="_Black (full transparency)" >*/
+ GIMP_ADD_MASK_ALPHA, /*< desc="Layer's _alpha channel" >*/
+ GIMP_ADD_MASK_ALPHA_TRANSFER, /*< desc="_Transfer layer's alpha channel" >*/
+ GIMP_ADD_MASK_SELECTION, /*< desc="_Selection" >*/
+ GIMP_ADD_MASK_COPY, /*< desc="_Grayscale copy of layer" >*/
+ GIMP_ADD_MASK_CHANNEL, /*< desc="C_hannel" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_ADD_WHITE_MASK = GIMP_ADD_MASK_WHITE, /*< skip, pdb-skip >*/
+ GIMP_ADD_BLACK_MASK = GIMP_ADD_MASK_BLACK, /*< skip, pdb-skip >*/
+ GIMP_ADD_ALPHA_MASK = GIMP_ADD_MASK_ALPHA, /*< skip, pdb-skip >*/
+ GIMP_ADD_ALPHA_TRANSFER_MASK = GIMP_ADD_MASK_ALPHA_TRANSFER, /*< skip, pdb-skip >*/
+ GIMP_ADD_SELECTION_MASK = GIMP_ADD_MASK_SELECTION, /*< skip, pdb-skip >*/
+ GIMP_ADD_COPY_MASK = GIMP_ADD_MASK_COPY, /*< skip, pdb-skip >*/
+ GIMP_ADD_CHANNEL_MASK = GIMP_ADD_MASK_CHANNEL /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpAddMaskType;
+
+
+/**
+ * GimpBlendMode:
+ * @GIMP_BLEND_FG_BG_RGB: FG to BG (RGB)
+ * @GIMP_BLEND_FG_BG_HSV: FG to BG (HSV)
+ * @GIMP_BLEND_FG_TRANSPARENT: FG to transparent
+ * @GIMP_BLEND_CUSTOM: Custom gradient
+ * @GIMP_FG_BG_RGB_MODE: Deprecated alias for @GIMP_BLEND_FG_BG_RGB
+ * @GIMP_FG_BG_HSV_MODE: Deprecated alias for @GIMP_BLEND_FG_BG_HSV
+ * @GIMP_FG_TRANSPARENT_MODE: Deprecated alias for @GIMP_BLEND_FG_TRANSPARENT
+ * @GIMP_CUSTOM_MODE: Deprecated alias for @GIMP_BLEND_CUSTOM
+ *
+ * Types of gradients.
+ **/
+#define GIMP_TYPE_BLEND_MODE (gimp_blend_mode_get_type ())
+
+GType gimp_blend_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_BLEND_FG_BG_RGB, /*< desc="FG to BG (RGB)" >*/
+ GIMP_BLEND_FG_BG_HSV, /*< desc="FG to BG (HSV)" >*/
+ GIMP_BLEND_FG_TRANSPARENT, /*< desc="FG to transparent" >*/
+ GIMP_BLEND_CUSTOM, /*< desc="Custom gradient" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_FG_BG_RGB_MODE = GIMP_BLEND_FG_BG_RGB, /*< skip, pdb-skip >*/
+ GIMP_FG_BG_HSV_MODE = GIMP_BLEND_FG_BG_HSV, /*< skip, pdb-skip >*/
+ GIMP_FG_TRANSPARENT_MODE = GIMP_BLEND_FG_TRANSPARENT, /*< skip, pdb-skip >*/
+ GIMP_CUSTOM_MODE = GIMP_BLEND_CUSTOM /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpBlendMode;
+
+
+/**
+ * GimpBrushGeneratedShape:
+ * @GIMP_BRUSH_GENERATED_CIRCLE: Circle
+ * @GIMP_BRUSH_GENERATED_SQUARE: Square
+ * @GIMP_BRUSH_GENERATED_DIAMOND: Diamond
+ *
+ * Shapes of generated brushes.
+ **/
+#define GIMP_TYPE_BRUSH_GENERATED_SHAPE (gimp_brush_generated_shape_get_type ())
+
+GType gimp_brush_generated_shape_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_BRUSH_GENERATED_CIRCLE, /*< desc="Circle" >*/
+ GIMP_BRUSH_GENERATED_SQUARE, /*< desc="Square" >*/
+ GIMP_BRUSH_GENERATED_DIAMOND /*< desc="Diamond" >*/
+} GimpBrushGeneratedShape;
+
+
+/**
+ * GimpBucketFillMode:
+ * @GIMP_BUCKET_FILL_FG: FG color fill
+ * @GIMP_BUCKET_FILL_BG: BG color fill
+ * @GIMP_BUCKET_FILL_PATTERN: Pattern fill
+ * @GIMP_FG_BUCKET_FILL: Deprecated alias for @GIMP_BUCKET_FILL_FG
+ * @GIMP_BG_BUCKET_FILL: Deprecated alias for @GIMP_BUCKET_FILL_BG
+ * @GIMP_PATTERN_BUCKET_FILL: Deprecated alias for @GIMP_BUCKET_FILL_PATTERN
+ *
+ * Bucket fill modes.
+ */
+#define GIMP_TYPE_BUCKET_FILL_MODE (gimp_bucket_fill_mode_get_type ())
+
+GType gimp_bucket_fill_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_BUCKET_FILL_FG, /*< desc="FG color fill" >*/
+ GIMP_BUCKET_FILL_BG, /*< desc="BG color fill" >*/
+ GIMP_BUCKET_FILL_PATTERN, /*< desc="Pattern fill" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_FG_BUCKET_FILL = GIMP_BUCKET_FILL_FG, /*< skip, pdb-skip >*/
+ GIMP_BG_BUCKET_FILL = GIMP_BUCKET_FILL_BG, /*< skip, pdb-skip >*/
+ GIMP_PATTERN_BUCKET_FILL = GIMP_BUCKET_FILL_PATTERN /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpBucketFillMode;
+
+
+/**
+ * GimpCapStyle:
+ * @GIMP_CAP_BUTT: Butt
+ * @GIMP_CAP_ROUND: Round
+ * @GIMP_CAP_SQUARE: Square
+ *
+ * Style of line endings.
+ **/
+#define GIMP_TYPE_CAP_STYLE (gimp_cap_style_get_type ())
+
+GType gimp_cap_style_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_CAP_BUTT, /*< desc="Butt" >*/
+ GIMP_CAP_ROUND, /*< desc="Round" >*/
+ GIMP_CAP_SQUARE /*< desc="Square" >*/
+} GimpCapStyle;
+
+
+/**
+ * GimpChannelOps:
+ * @GIMP_CHANNEL_OP_ADD: Add to the current selection
+ * @GIMP_CHANNEL_OP_SUBTRACT: Subtract from the current selection
+ * @GIMP_CHANNEL_OP_REPLACE: Replace the current selection
+ * @GIMP_CHANNEL_OP_INTERSECT: Intersect with the current selection
+ *
+ * Operations to combine channels and selections.
+ **/
+#define GIMP_TYPE_CHANNEL_OPS (gimp_channel_ops_get_type ())
+
+GType gimp_channel_ops_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_CHANNEL_OP_ADD, /*< desc="Add to the current selection" >*/
+ GIMP_CHANNEL_OP_SUBTRACT, /*< desc="Subtract from the current selection" >*/
+ GIMP_CHANNEL_OP_REPLACE, /*< desc="Replace the current selection" >*/
+ GIMP_CHANNEL_OP_INTERSECT /*< desc="Intersect with the current selection" >*/
+} GimpChannelOps;
+
+
+/**
+ * GimpChannelType:
+ * @GIMP_CHANNEL_RED: Red
+ * @GIMP_CHANNEL_GREEN: Green
+ * @GIMP_CHANNEL_BLUE: Blue
+ * @GIMP_CHANNEL_GRAY: Gray
+ * @GIMP_CHANNEL_INDEXED: Indexed
+ * @GIMP_CHANNEL_ALPHA: Alpha
+ * @GIMP_RED_CHANNEL: Deprecated alias for @GIMP_CHANNEL_RED
+ * @GIMP_GREEN_CHANNEL: Deprecated alias for @GIMP_CHANNEL_GREEN
+ * @GIMP_BLUE_CHANNEL: Deprecated alias for @GIMP_CHANNEL_BLUE
+ * @GIMP_GRAY_CHANNEL: Deprecated alias for @GIMP_CHANNEL_GRAY
+ * @GIMP_INDEXED_CHANNEL: Deprecated alias for @GIMP_CHANNEL_INDEXED
+ * @GIMP_ALPHA_CHANNEL: Deprecated alias for @GIMP_CHANNEL_ALPHA
+ *
+ * Channels (as in color components).
+ **/
+#define GIMP_TYPE_CHANNEL_TYPE (gimp_channel_type_get_type ())
+
+GType gimp_channel_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_CHANNEL_RED, /*< desc="Red" >*/
+ GIMP_CHANNEL_GREEN, /*< desc="Green" >*/
+ GIMP_CHANNEL_BLUE, /*< desc="Blue" >*/
+ GIMP_CHANNEL_GRAY, /*< desc="Gray" >*/
+ GIMP_CHANNEL_INDEXED, /*< desc="Indexed" >*/
+ GIMP_CHANNEL_ALPHA, /*< desc="Alpha" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_RED_CHANNEL = GIMP_CHANNEL_RED, /*< skip, pdb-skip >*/
+ GIMP_GREEN_CHANNEL = GIMP_CHANNEL_GREEN, /*< skip, pdb-skip >*/
+ GIMP_BLUE_CHANNEL = GIMP_CHANNEL_BLUE, /*< skip, pdb-skip >*/
+ GIMP_GRAY_CHANNEL = GIMP_CHANNEL_GRAY, /*< skip, pdb-skip >*/
+ GIMP_INDEXED_CHANNEL = GIMP_CHANNEL_INDEXED, /*< skip, pdb-skip >*/
+ GIMP_ALPHA_CHANNEL = GIMP_CHANNEL_ALPHA /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpChannelType;
+
+
+/**
+ * GimpCheckSize:
+ * @GIMP_CHECK_SIZE_SMALL_CHECKS: Small
+ * @GIMP_CHECK_SIZE_MEDIUM_CHECKS: Medium
+ * @GIMP_CHECK_SIZE_LARGE_CHECKS: Large
+ *
+ * Size of the checkerboard indicating transparency.
+ **/
+#define GIMP_TYPE_CHECK_SIZE (gimp_check_size_get_type ())
+
+GType gimp_check_size_get_type (void) G_GNUC_CONST;
+
+typedef enum /*< pdb-skip >*/
+{
+ GIMP_CHECK_SIZE_SMALL_CHECKS = 0, /*< desc="Small" >*/
+ GIMP_CHECK_SIZE_MEDIUM_CHECKS = 1, /*< desc="Medium" >*/
+ GIMP_CHECK_SIZE_LARGE_CHECKS = 2 /*< desc="Large" >*/
+} GimpCheckSize;
+
+
+/**
+ * GimpCheckType:
+ * @GIMP_CHECK_TYPE_LIGHT_CHECKS: Light checks
+ * @GIMP_CHECK_TYPE_GRAY_CHECKS: Mid-tone checks
+ * @GIMP_CHECK_TYPE_DARK_CHECKS: Dark checks
+ * @GIMP_CHECK_TYPE_WHITE_ONLY: White only
+ * @GIMP_CHECK_TYPE_GRAY_ONLY: Gray only
+ * @GIMP_CHECK_TYPE_BLACK_ONLY: Black only
+ *
+ * Color/Brightness of the checkerboard indicating transparency.
+ **/
+#define GIMP_TYPE_CHECK_TYPE (gimp_check_type_get_type ())
+
+GType gimp_check_type_get_type (void) G_GNUC_CONST;
+
+typedef enum /*< pdb-skip >*/
+{
+ GIMP_CHECK_TYPE_LIGHT_CHECKS = 0, /*< desc="Light checks" >*/
+ GIMP_CHECK_TYPE_GRAY_CHECKS = 1, /*< desc="Mid-tone checks" >*/
+ GIMP_CHECK_TYPE_DARK_CHECKS = 2, /*< desc="Dark checks" >*/
+ GIMP_CHECK_TYPE_WHITE_ONLY = 3, /*< desc="White only" >*/
+ GIMP_CHECK_TYPE_GRAY_ONLY = 4, /*< desc="Gray only" >*/
+ GIMP_CHECK_TYPE_BLACK_ONLY = 5 /*< desc="Black only" >*/
+} GimpCheckType;
+
+
+/**
+ * GimpCloneType:
+ * @GIMP_CLONE_IMAGE: Clone from an image/drawable source
+ * @GIMP_CLONE_PATTERN: Clone from a pattern source
+ * @GIMP_IMAGE_CLONE: Deprecated alias for @GIMP_CLONE_IMAGE
+ * @GIMP_PATTERN_CLONE: Deprecated alias for @GIMP_CLONE_PATTERN
+ *
+ * Clone sources.
+ **/
+#define GIMP_TYPE_CLONE_TYPE (gimp_clone_type_get_type ())
+
+GType gimp_clone_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_CLONE_IMAGE, /*< desc="Image" >*/
+ GIMP_CLONE_PATTERN, /*< desc="Pattern" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_IMAGE_CLONE = GIMP_CLONE_IMAGE, /*< skip, pdb-skip >*/
+ GIMP_PATTERN_CLONE = GIMP_CLONE_PATTERN /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpCloneType;
+
+
+/**
+ * GimpColorTag:
+ * @GIMP_COLOR_TAG_NONE: None
+ * @GIMP_COLOR_TAG_BLUE: Blue
+ * @GIMP_COLOR_TAG_GREEN: Green
+ * @GIMP_COLOR_TAG_YELLOW: Yellow
+ * @GIMP_COLOR_TAG_ORANGE: Orange
+ * @GIMP_COLOR_TAG_BROWN: Brown
+ * @GIMP_COLOR_TAG_RED: Red
+ * @GIMP_COLOR_TAG_VIOLET: Violet
+ * @GIMP_COLOR_TAG_GRAY: Gray
+ *
+ * Possible tag colors.
+ *
+ * Since: 2.10
+ **/
+#define GIMP_TYPE_COLOR_TAG (gimp_color_tag_get_type ())
+
+GType gimp_color_tag_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_COLOR_TAG_NONE, /*< desc="None" >*/
+ GIMP_COLOR_TAG_BLUE, /*< desc="Blue" >*/
+ GIMP_COLOR_TAG_GREEN, /*< desc="Green" >*/
+ GIMP_COLOR_TAG_YELLOW, /*< desc="Yellow" >*/
+ GIMP_COLOR_TAG_ORANGE, /*< desc="Orange" >*/
+ GIMP_COLOR_TAG_BROWN, /*< desc="Brown" >*/
+ GIMP_COLOR_TAG_RED, /*< desc="Red" >*/
+ GIMP_COLOR_TAG_VIOLET, /*< desc="Violet" >*/
+ GIMP_COLOR_TAG_GRAY /*< desc="Gray" >*/
+} GimpColorTag;
+
+
+/**
+ * GimpComponentType:
+ * @GIMP_COMPONENT_TYPE_U8: 8-bit integer
+ * @GIMP_COMPONENT_TYPE_U16: 16-bit integer
+ * @GIMP_COMPONENT_TYPE_U32: 32-bit integer
+ * @GIMP_COMPONENT_TYPE_HALF: 16-bit floating point
+ * @GIMP_COMPONENT_TYPE_FLOAT: 32-bit floating point
+ * @GIMP_COMPONENT_TYPE_DOUBLE: 64-bit floating point
+ *
+ * Encoding types of image components.
+ *
+ * Since: 2.10
+ **/
+#define GIMP_TYPE_COMPONENT_TYPE (gimp_component_type_get_type ())
+
+GType gimp_component_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_COMPONENT_TYPE_U8 = 100, /*< desc="8-bit integer" >*/
+ GIMP_COMPONENT_TYPE_U16 = 200, /*< desc="16-bit integer" >*/
+ GIMP_COMPONENT_TYPE_U32 = 300, /*< desc="32-bit integer" >*/
+ GIMP_COMPONENT_TYPE_HALF = 500, /*< desc="16-bit floating point" >*/
+ GIMP_COMPONENT_TYPE_FLOAT = 600, /*< desc="32-bit floating point" >*/
+ GIMP_COMPONENT_TYPE_DOUBLE = 700 /*< desc="64-bit floating point" >*/
+} GimpComponentType;
+
+
+/**
+ * GimpConvertPaletteType:
+ * @GIMP_CONVERT_PALETTE_GENERATE: Generate optimum palette
+ * @GIMP_CONVERT_PALETTE_REUSE: Don't use this one
+ * @GIMP_CONVERT_PALETTE_WEB: Use web-optimized palette
+ * @GIMP_CONVERT_PALETTE_MONO: Use black and white (1-bit) palette
+ * @GIMP_CONVERT_PALETTE_CUSTOM: Use custom palette
+ * @GIMP_MAKE_PALETTE: Deprecated alias for
+ * @GIMP_CONVERT_PALETTE_GENERATE
+ * @GIMP_REUSE_PALETTE: Deprecated alias for
+ * @GIMP_CONVERT_PALETTE_REUSE
+ * @GIMP_WEB_PALETTE: Deprecated alias for
+ * @GIMP_CONVERT_PALETTE_WEB
+ * @GIMP_MONO_PALETTE: Deprecated alias for
+ @GIMP_CONVERT_PALETTE_MONO
+ * @GIMP_CUSTOM_PALETTE: Deprecated alias for
+ * @GIMP_CONVERT_PALETTE_CUSTOM
+ *
+ * Types of palettes for indexed conversion.
+ **/
+#define GIMP_TYPE_CONVERT_PALETTE_TYPE (gimp_convert_palette_type_get_type ())
+
+GType gimp_convert_palette_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_CONVERT_PALETTE_GENERATE, /*< desc="Generate optimum palette" >*/
+ GIMP_CONVERT_PALETTE_REUSE, /*< skip >*/
+ GIMP_CONVERT_PALETTE_WEB, /*< desc="Use web-optimized palette" >*/
+ GIMP_CONVERT_PALETTE_MONO, /*< desc="Use black and white (1-bit) palette" >*/
+ GIMP_CONVERT_PALETTE_CUSTOM, /*< desc="Use custom palette" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_MAKE_PALETTE = GIMP_CONVERT_PALETTE_GENERATE, /*< skip, pdb-skip >*/
+ GIMP_REUSE_PALETTE = GIMP_CONVERT_PALETTE_REUSE, /*< skip, pdb-skip >*/
+ GIMP_WEB_PALETTE = GIMP_CONVERT_PALETTE_WEB, /*< skip, pdb-skip >*/
+ GIMP_MONO_PALETTE = GIMP_CONVERT_PALETTE_MONO, /*< skip, pdb-skip >*/
+ GIMP_CUSTOM_PALETTE = GIMP_CONVERT_PALETTE_CUSTOM /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpConvertPaletteType;
+
+
+/**
+ * GimpConvolveType:
+ * @GIMP_CONVOLVE_BLUR: Blur
+ * @GIMP_CONVOLVE_SHARPEN: Sharpen
+ * @GIMP_BLUR_CONVOLVE: Deprecated alias for @GIMP_CONVOLVE_BLUR
+ * @GIMP_SHARPEN_CONVOLVE: Deprecated alias for @GIMP_CONVOLVE_SHARPEN
+ *
+ * Types of convolutions.
+ **/
+#define GIMP_TYPE_CONVOLVE_TYPE (gimp_convolve_type_get_type ())
+
+GType gimp_convolve_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_CONVOLVE_BLUR, /*< desc="Blur" >*/
+ GIMP_CONVOLVE_SHARPEN, /*< desc="Sharpen" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_BLUR_CONVOLVE = GIMP_CONVOLVE_BLUR, /*< skip, pdb-skip >*/
+ GIMP_SHARPEN_CONVOLVE = GIMP_CONVOLVE_SHARPEN /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpConvolveType;
+
+
+/**
+ * GimpDesaturateMode:
+ * @GIMP_DESATURATE_LIGHTNESS: Lightness (HSL)
+ * @GIMP_DESATURATE_LUMA: Luma
+ * @GIMP_DESATURATE_AVERAGE: Average (HSI Intensity)
+ * @GIMP_DESATURATE_LUMINANCE: Luminance
+ * @GIMP_DESATURATE_VALUE: Value (HSV)
+ * @GIMP_DESATURATE_LUMINOSITY: Deprecated alias for @GIMP_DESATURATE_LUMA
+ *
+ * Grayscale conversion methods.
+ **/
+#define GIMP_TYPE_DESATURATE_MODE (gimp_desaturate_mode_get_type ())
+
+GType gimp_desaturate_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_DESATURATE_LIGHTNESS, /*< desc="Lightness (HSL)" >*/
+ GIMP_DESATURATE_LUMA, /*< desc="Luma" >*/
+ GIMP_DESATURATE_AVERAGE, /*< desc="Average (HSI Intensity)" >*/
+ GIMP_DESATURATE_LUMINANCE, /*< desc="Luminance" >*/
+ GIMP_DESATURATE_VALUE, /*< desc="Value (HSV)" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_DESATURATE_LUMINOSITY = GIMP_DESATURATE_LUMA /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpDesaturateMode;
+
+
+/**
+ * GimpDodgeBurnType:
+ * @GIMP_DODGE_BURN_TYPE_DODGE: Dodge
+ * @GIMP_DODGE_BURN_TYPE_BURN: Burn
+ * @GIMP_DODGE: Deprecated alias for @GIMP_DODGE_BURN_TYPE_DODGE
+ * @GIMP_BURN: Deprecated alias for @GIMP_DODGE_BURN_TYPE_BURN
+ *
+ * Methods for the dodge/burn operation.
+ **/
+#define GIMP_TYPE_DODGE_BURN_TYPE (gimp_dodge_burn_type_get_type ())
+
+GType gimp_dodge_burn_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_DODGE_BURN_TYPE_DODGE, /*< desc="Dodge" >*/
+ GIMP_DODGE_BURN_TYPE_BURN, /*< desc="Burn" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_DODGE = GIMP_DODGE_BURN_TYPE_DODGE, /*< skip, pdb-skip >*/
+ GIMP_BURN = GIMP_DODGE_BURN_TYPE_BURN /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpDodgeBurnType;
+
+
+/**
+ * GimpFillType:
+ * @GIMP_FILL_FOREGROUND: Foreground color
+ * @GIMP_FILL_BACKGROUND: Background color
+ * @GIMP_FILL_WHITE: White
+ * @GIMP_FILL_TRANSPARENT: Transparency
+ * @GIMP_FILL_PATTERN: Pattern
+ * @GIMP_FOREGROUND_FILL: Deprecated alias for @GIMP_FILL_FOREGROUND
+ * @GIMP_BACKGROUND_FILL: Deprecated alias for @GIMP_FILL_BACKGROUND
+ * @GIMP_WHITE_FILL: Deprecated alias for @GIMP_FILL_WHITE
+ * @GIMP_TRANSPARENT_FILL: Deprecated alias for @GIMP_FILL_TRANSPARENT
+ * @GIMP_PATTERN_FILL: Deprecated alias for @GIMP_FILL_PATTERN
+ *
+ * Types of filling.
+ **/
+#define GIMP_TYPE_FILL_TYPE (gimp_fill_type_get_type ())
+
+GType gimp_fill_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_FILL_FOREGROUND, /*< desc="Foreground color" >*/
+ GIMP_FILL_BACKGROUND, /*< desc="Background color" >*/
+ GIMP_FILL_WHITE, /*< desc="White" >*/
+ GIMP_FILL_TRANSPARENT, /*< desc="Transparency" >*/
+ GIMP_FILL_PATTERN, /*< desc="Pattern" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_FOREGROUND_FILL = GIMP_FILL_FOREGROUND, /*< skip, pdb-skip >*/
+ GIMP_BACKGROUND_FILL = GIMP_FILL_BACKGROUND, /*< skip, pdb-skip >*/
+ GIMP_WHITE_FILL = GIMP_FILL_WHITE, /*< skip, pdb-skip >*/
+ GIMP_TRANSPARENT_FILL = GIMP_FILL_TRANSPARENT, /*< skip, pdb-skip >*/
+ GIMP_PATTERN_FILL = GIMP_FILL_PATTERN /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpFillType;
+
+
+/**
+ * GimpForegroundExtractMode:
+ * @GIMP_FOREGROUND_EXTRACT_SIOX: Siox
+ * @GIMP_FOREGROUND_EXTRACT_MATTING: Matting (Since 2.10)
+ *
+ * Foreground extraxt engines.
+ **/
+#define GIMP_TYPE_FOREGROUND_EXTRACT_MODE (gimp_foreground_extract_mode_get_type ())
+
+GType gimp_foreground_extract_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_FOREGROUND_EXTRACT_SIOX,
+ GIMP_FOREGROUND_EXTRACT_MATTING
+} GimpForegroundExtractMode;
+
+
+/**
+ * GimpGradientBlendColorSpace:
+ * @GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL: Perceptual RGB
+ * @GIMP_GRADIENT_BLEND_RGB_LINEAR: Linear RGB
+ * @GIMP_GRADIENT_BLEND_CIE_LAB: CIE Lab
+ *
+ * Color space for blending gradients.
+ *
+ * Since: 2.10
+ */
+#define GIMP_TYPE_GRADIENT_BLEND_COLOR_SPACE (gimp_gradient_blend_color_space_get_type ())
+
+GType gimp_gradient_blend_color_space_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL, /*< desc="Perceptual RGB", nick=rgb-perceptual >*/
+ GIMP_GRADIENT_BLEND_RGB_LINEAR, /*< desc="Linear RGB", nick=rgb-linear >*/
+ GIMP_GRADIENT_BLEND_CIE_LAB /*< desc="CIE Lab", nick=cie-lab >*/
+} GimpGradientBlendColorSpace;
+
+
+/**
+ * GimpGradientSegmentColor:
+ * @GIMP_GRADIENT_SEGMENT_RGB: RGB
+ * @GIMP_GRADIENT_SEGMENT_HSV_CCW: HSV (counter-clockwise hue)
+ * @GIMP_GRADIENT_SEGMENT_HSV_CW: HSV (clockwise hue)
+ *
+ * Coloring types for gradient segments.
+ **/
+#define GIMP_TYPE_GRADIENT_SEGMENT_COLOR (gimp_gradient_segment_color_get_type ())
+
+GType gimp_gradient_segment_color_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_GRADIENT_SEGMENT_RGB, /*< desc="RGB" >*/
+ GIMP_GRADIENT_SEGMENT_HSV_CCW, /*< desc="HSV (counter-clockwise hue)", abbrev="HSV (ccw)" >*/
+ GIMP_GRADIENT_SEGMENT_HSV_CW /*< desc="HSV (clockwise hue)", abbrev="HSV (cw)" >*/
+} GimpGradientSegmentColor;
+
+
+/**
+ * GimpGradientSegmentType:
+ * @GIMP_GRADIENT_SEGMENT_LINEAR: Linear
+ * @GIMP_GRADIENT_SEGMENT_CURVED: Curved
+ * @GIMP_GRADIENT_SEGMENT_SINE: Sinusoidal
+ * @GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING: Spherical (increasing)
+ * @GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING: Spherical (decreasing)
+ * @GIMP_GRADIENT_SEGMENT_STEP: Step
+ *
+ * Transition functions for gradient segments.
+ **/
+#define GIMP_TYPE_GRADIENT_SEGMENT_TYPE (gimp_gradient_segment_type_get_type ())
+
+GType gimp_gradient_segment_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_GRADIENT_SEGMENT_LINEAR, /*< desc="Linear" >*/
+ GIMP_GRADIENT_SEGMENT_CURVED, /*< desc="Curved" >*/
+ GIMP_GRADIENT_SEGMENT_SINE, /*< desc="Sinusoidal" >*/
+ GIMP_GRADIENT_SEGMENT_SPHERE_INCREASING, /*< desc="Spherical (increasing)", abbrev="Spherical (inc)" >*/
+ GIMP_GRADIENT_SEGMENT_SPHERE_DECREASING, /*< desc="Spherical (decreasing)", abbrev="Spherical (dec)" >*/
+ GIMP_GRADIENT_SEGMENT_STEP /*< desc="Step" >*/
+} GimpGradientSegmentType;
+
+
+/**
+ * GimpGradientType:
+ * @GIMP_GRADIENT_LINEAR: Linear
+ * @GIMP_GRADIENT_BILINEAR: Bi-linear
+ * @GIMP_GRADIENT_RADIAL: Radial
+ * @GIMP_GRADIENT_SQUARE: Square
+ * @GIMP_GRADIENT_CONICAL_SYMMETRIC: Conical (symmetric)
+ * @GIMP_GRADIENT_CONICAL_ASYMMETRIC: Conical (asymmetric)
+ * @GIMP_GRADIENT_SHAPEBURST_ANGULAR: Shaped (angular)
+ * @GIMP_GRADIENT_SHAPEBURST_SPHERICAL: Shaped (spherical)
+ * @GIMP_GRADIENT_SHAPEBURST_DIMPLED: Shaped (dimpled)
+ * @GIMP_GRADIENT_SPIRAL_CLOCKWISE: Spiral (clockwise)
+ * @GIMP_GRADIENT_SPIRAL_ANTICLOCKWISE: Spiral (counter-clockwise)
+ *
+ * Gradient shapes.
+ **/
+#define GIMP_TYPE_GRADIENT_TYPE (gimp_gradient_type_get_type ())
+
+GType gimp_gradient_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_GRADIENT_LINEAR, /*< desc="Linear" >*/
+ GIMP_GRADIENT_BILINEAR, /*< desc="Bi-linear" >*/
+ GIMP_GRADIENT_RADIAL, /*< desc="Radial" >*/
+ GIMP_GRADIENT_SQUARE, /*< desc="Square" >*/
+ GIMP_GRADIENT_CONICAL_SYMMETRIC, /*< desc="Conical (symmetric)", abbrev="Conical (sym)" >*/
+ GIMP_GRADIENT_CONICAL_ASYMMETRIC, /*< desc="Conical (asymmetric)", abbrev="Conical (asym)" >*/
+ GIMP_GRADIENT_SHAPEBURST_ANGULAR, /*< desc="Shaped (angular)" >*/
+ GIMP_GRADIENT_SHAPEBURST_SPHERICAL, /*< desc="Shaped (spherical)" >*/
+ GIMP_GRADIENT_SHAPEBURST_DIMPLED, /*< desc="Shaped (dimpled)" >*/
+ GIMP_GRADIENT_SPIRAL_CLOCKWISE, /*< desc="Spiral (clockwise)", abbrev="Spiral (cw)" >*/
+ GIMP_GRADIENT_SPIRAL_ANTICLOCKWISE /*< desc="Spiral (counter-clockwise)", abbrev="Spiral (ccw)" >*/
+} GimpGradientType;
+
+
+/**
+ * GimpGridStyle:
+ * @GIMP_GRID_DOTS: Intersections (dots)
+ * @GIMP_GRID_INTERSECTIONS: Intersections (crosshairs)
+ * @GIMP_GRID_ON_OFF_DASH: Dashed
+ * @GIMP_GRID_DOUBLE_DASH: Double dashed
+ * @GIMP_GRID_SOLID: Solid
+ *
+ * Rendering types for the display grid.
+ **/
+#define GIMP_TYPE_GRID_STYLE (gimp_grid_style_get_type ())
+
+GType gimp_grid_style_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_GRID_DOTS, /*< desc="Intersections (dots)" >*/
+ GIMP_GRID_INTERSECTIONS, /*< desc="Intersections (crosshairs)" >*/
+ GIMP_GRID_ON_OFF_DASH, /*< desc="Dashed" >*/
+ GIMP_GRID_DOUBLE_DASH, /*< desc="Double dashed" >*/
+ GIMP_GRID_SOLID /*< desc="Solid" >*/
+} GimpGridStyle;
+
+
+/**
+ * GimpHueRange:
+ * @GIMP_HUE_RANGE_ALL: All hues
+ * @GIMP_HUE_RANGE_RED: Red hues
+ * @GIMP_HUE_RANGE_YELLOW: Yellow hues
+ * @GIMP_HUE_RANGE_GREEN: Green hues
+ * @GIMP_HUE_RANGE_CYAN: Cyan hues
+ * @GIMP_HUE_RANGE_BLUE: Blue hues
+ * @GIMP_HUE_RANGE_MAGENTA: Magenta hues
+ * @GIMP_ALL_HUES: Deprecated alias for @GIMP_HUE_RANGE_ALL
+ * @GIMP_RED_HUES: Deprecated alias for @GIMP_HUE_RANGE_RED
+ * @GIMP_YELLOW_HUES: Deprecated alias for @GIMP_HUE_RANGE_YELLOW
+ * @GIMP_GREEN_HUES: Deprecated alias for @GIMP_HUE_RANGE_GREEN
+ * @GIMP_CYAN_HUES: Deprecated alias for @GIMP_HUE_RANGE_CYAN
+ * @GIMP_BLUE_HUES: Deprecated alias for @GIMP_HUE_RANGE_BLUE
+ * @GIMP_MAGENTA_HUES: Deprecated alias for @GIMP_HUE_RANGE_MAGENTA
+ *
+ * Hue ranges.
+ **/
+#define GIMP_TYPE_HUE_RANGE (gimp_hue_range_get_type ())
+
+GType gimp_hue_range_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_HUE_RANGE_ALL,
+ GIMP_HUE_RANGE_RED,
+ GIMP_HUE_RANGE_YELLOW,
+ GIMP_HUE_RANGE_GREEN,
+ GIMP_HUE_RANGE_CYAN,
+ GIMP_HUE_RANGE_BLUE,
+ GIMP_HUE_RANGE_MAGENTA,
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_ALL_HUES = GIMP_HUE_RANGE_ALL, /*< skip, pdb-skip >*/
+ GIMP_RED_HUES = GIMP_HUE_RANGE_RED, /*< skip, pdb-skip >*/
+ GIMP_YELLOW_HUES = GIMP_HUE_RANGE_YELLOW, /*< skip, pdb-skip >*/
+ GIMP_GREEN_HUES = GIMP_HUE_RANGE_GREEN, /*< skip, pdb-skip >*/
+ GIMP_CYAN_HUES = GIMP_HUE_RANGE_CYAN, /*< skip, pdb-skip >*/
+ GIMP_BLUE_HUES = GIMP_HUE_RANGE_BLUE, /*< skip, pdb-skip >*/
+ GIMP_MAGENTA_HUES = GIMP_HUE_RANGE_MAGENTA /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpHueRange;
+
+
+/**
+ * GimpIconType:
+ * @GIMP_ICON_TYPE_ICON_NAME: Icon name
+ * @GIMP_ICON_TYPE_INLINE_PIXBUF: Inline pixbuf
+ * @GIMP_ICON_TYPE_IMAGE_FILE: Image file
+ * @GIMP_ICON_TYPE_STOCK_ID: Deprecated alias for
+ * @GIMP_ICON_TYPE_ICON_NAME, old stock IDs
+ * are interpreted as icon names
+ *
+ * Icon types for plug-ins to register.
+ **/
+#define GIMP_TYPE_ICON_TYPE (gimp_icon_type_get_type ())
+
+GType gimp_icon_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_ICON_TYPE_ICON_NAME, /*< desc="Icon name" >*/
+ GIMP_ICON_TYPE_INLINE_PIXBUF, /*< desc="Inline pixbuf" >*/
+ GIMP_ICON_TYPE_IMAGE_FILE, /*< desc="Image file" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_ICON_TYPE_STOCK_ID = GIMP_ICON_TYPE_ICON_NAME /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpIconType;
+
+
+/**
+ * GimpImageBaseType:
+ * @GIMP_RGB: RGB color
+ * @GIMP_GRAY: Grayscale
+ * @GIMP_INDEXED: Indexed color
+ *
+ * Image color models.
+ **/
+#define GIMP_TYPE_IMAGE_BASE_TYPE (gimp_image_base_type_get_type ())
+
+GType gimp_image_base_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_RGB, /*< desc="RGB color" >*/
+ GIMP_GRAY, /*< desc="Grayscale" >*/
+ GIMP_INDEXED /*< desc="Indexed color" >*/
+} GimpImageBaseType;
+
+
+/**
+ * GimpImageType:
+ * @GIMP_RGB_IMAGE: RGB
+ * @GIMP_RGBA_IMAGE: RGB-alpha
+ * @GIMP_GRAY_IMAGE: Grayscale
+ * @GIMP_GRAYA_IMAGE: Grayscale-alpha
+ * @GIMP_INDEXED_IMAGE: Indexed
+ * @GIMP_INDEXEDA_IMAGE: Indexed-alpha
+ *
+ * Possible drawable types.
+ **/
+#define GIMP_TYPE_IMAGE_TYPE (gimp_image_type_get_type ())
+
+GType gimp_image_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_RGB_IMAGE, /*< desc="RGB" >*/
+ GIMP_RGBA_IMAGE, /*< desc="RGB-alpha" >*/
+ GIMP_GRAY_IMAGE, /*< desc="Grayscale" >*/
+ GIMP_GRAYA_IMAGE, /*< desc="Grayscale-alpha" >*/
+ GIMP_INDEXED_IMAGE, /*< desc="Indexed" >*/
+ GIMP_INDEXEDA_IMAGE /*< desc="Indexed-alpha" >*/
+} GimpImageType;
+
+
+/**
+ * GimpInkBlobType:
+ * @GIMP_INK_BLOB_TYPE_CIRCLE: Circle
+ * @GIMP_INK_BLOB_TYPE_SQUARE: Square
+ * @GIMP_INK_BLOB_TYPE_DIAMOND: Diamond
+ *
+ * Ink tool tips.
+ **/
+#define GIMP_TYPE_INK_BLOB_TYPE (gimp_ink_blob_type_get_type ())
+
+GType gimp_ink_blob_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_INK_BLOB_TYPE_CIRCLE, /*< desc="Circle" >*/
+ GIMP_INK_BLOB_TYPE_SQUARE, /*< desc="Square" >*/
+ GIMP_INK_BLOB_TYPE_DIAMOND /*< desc="Diamond" >*/
+} GimpInkBlobType;
+
+
+/**
+ * GimpInterpolationType:
+ * @GIMP_INTERPOLATION_NONE: None
+ * @GIMP_INTERPOLATION_LINEAR: Linear
+ * @GIMP_INTERPOLATION_CUBIC: Cubic
+ * @GIMP_INTERPOLATION_NOHALO: NoHalo
+ * @GIMP_INTERPOLATION_LOHALO: LoHalo
+ * @GIMP_INTERPOLATION_LANCZOS: Deprecated alias for @GIMP_INTERPOLATION_NOHALO
+ *
+ * Interpolation types.
+ **/
+#define GIMP_TYPE_INTERPOLATION_TYPE (gimp_interpolation_type_get_type ())
+
+GType gimp_interpolation_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_INTERPOLATION_NONE, /*< desc="None" >*/
+ GIMP_INTERPOLATION_LINEAR, /*< desc="Linear" >*/
+ GIMP_INTERPOLATION_CUBIC, /*< desc="Cubic" >*/
+ GIMP_INTERPOLATION_NOHALO, /*< desc="NoHalo" >*/
+ GIMP_INTERPOLATION_LOHALO, /*< desc="LoHalo" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_INTERPOLATION_LANCZOS = GIMP_INTERPOLATION_NOHALO /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpInterpolationType;
+
+
+/**
+ * GimpJoinStyle:
+ * @GIMP_JOIN_MITER: Miter
+ * @GIMP_JOIN_ROUND: Round
+ * @GIMP_JOIN_BEVEL: Bevel
+ *
+ * Line join styles.
+ **/
+#define GIMP_TYPE_JOIN_STYLE (gimp_join_style_get_type ())
+
+GType gimp_join_style_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_JOIN_MITER, /*< desc="Miter" >*/
+ GIMP_JOIN_ROUND, /*< desc="Round" >*/
+ GIMP_JOIN_BEVEL /*< desc="Bevel" >*/
+} GimpJoinStyle;
+
+
+/**
+ * GimpMaskApplyMode:
+ * @GIMP_MASK_APPLY: Apply the mask
+ * @GIMP_MASK_DISCARD: Discard the mask
+ *
+ * Layer mask apply modes.
+ **/
+#define GIMP_TYPE_MASK_APPLY_MODE (gimp_mask_apply_mode_get_type ())
+
+GType gimp_mask_apply_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_MASK_APPLY,
+ GIMP_MASK_DISCARD
+} GimpMaskApplyMode;
+
+
+/**
+ * GimpMergeType:
+ * @GIMP_EXPAND_AS_NECESSARY: Expanded as necessary
+ * @GIMP_CLIP_TO_IMAGE: Clipped to image
+ * @GIMP_CLIP_TO_BOTTOM_LAYER: Clipped to bottom layer
+ * @GIMP_FLATTEN_IMAGE: Flatten
+ *
+ * Types of merging layers.
+ **/
+#define GIMP_TYPE_MERGE_TYPE (gimp_merge_type_get_type ())
+
+GType gimp_merge_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_EXPAND_AS_NECESSARY, /*< desc="Expanded as necessary" >*/
+ GIMP_CLIP_TO_IMAGE, /*< desc="Clipped to image" >*/
+ GIMP_CLIP_TO_BOTTOM_LAYER, /*< desc="Clipped to bottom layer" >*/
+ GIMP_FLATTEN_IMAGE /*< desc="Flatten" >*/
+} GimpMergeType;
+
+
+/**
+ * GimpMessageHandlerType:
+ * @GIMP_MESSAGE_BOX: A popup dialog
+ * @GIMP_CONSOLE: The terminal
+ * @GIMP_ERROR_CONSOLE: The error console dockable
+ *
+ * How to present messages.
+ **/
+#define GIMP_TYPE_MESSAGE_HANDLER_TYPE (gimp_message_handler_type_get_type ())
+
+GType gimp_message_handler_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_MESSAGE_BOX,
+ GIMP_CONSOLE,
+ GIMP_ERROR_CONSOLE
+} GimpMessageHandlerType;
+
+
+/**
+ * GimpOffsetType:
+ * @GIMP_OFFSET_BACKGROUND: Background
+ * @GIMP_OFFSET_TRANSPARENT: Transparent
+ * @GIMP_OFFSET_WRAP_AROUND: Wrap image around
+ *
+ * Background fill types for the offset operation.
+ **/
+#define GIMP_TYPE_OFFSET_TYPE (gimp_offset_type_get_type ())
+
+GType gimp_offset_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_OFFSET_BACKGROUND,
+ GIMP_OFFSET_TRANSPARENT,
+ GIMP_OFFSET_WRAP_AROUND
+} GimpOffsetType;
+
+
+/**
+ * GimpOrientationType:
+ * @GIMP_ORIENTATION_HORIZONTAL: Horizontal
+ * @GIMP_ORIENTATION_VERTICAL: Vertical
+ * @GIMP_ORIENTATION_UNKNOWN: Unknown
+ *
+ * Orientations for various purposes.
+ **/
+#define GIMP_TYPE_ORIENTATION_TYPE (gimp_orientation_type_get_type ())
+
+GType gimp_orientation_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_ORIENTATION_HORIZONTAL, /*< desc="Horizontal" >*/
+ GIMP_ORIENTATION_VERTICAL, /*< desc="Vertical" >*/
+ GIMP_ORIENTATION_UNKNOWN /*< desc="Unknown" >*/
+} GimpOrientationType;
+
+
+/**
+ * GimpPaintApplicationMode:
+ * @GIMP_PAINT_CONSTANT: Constant
+ * @GIMP_PAINT_INCREMENTAL: Incremental
+ *
+ * Paint application modes.
+ **/
+#define GIMP_TYPE_PAINT_APPLICATION_MODE (gimp_paint_application_mode_get_type ())
+
+GType gimp_paint_application_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_PAINT_CONSTANT, /*< desc="Constant" >*/
+ GIMP_PAINT_INCREMENTAL /*< desc="Incremental" >*/
+} GimpPaintApplicationMode;
+
+
+/**
+ * GimpPDBArgType:
+ * @GIMP_PDB_INT32: 32-bit integer
+ * @GIMP_PDB_INT16: 16-bit integer
+ * @GIMP_PDB_INT8: 8-bit integer
+ * @GIMP_PDB_FLOAT: Float
+ * @GIMP_PDB_STRING: String
+ * @GIMP_PDB_INT32ARRAY: Array of INT32
+ * @GIMP_PDB_INT16ARRAY: Array of INT16
+ * @GIMP_PDB_INT8ARRAY: Array of INT8
+ * @GIMP_PDB_FLOATARRAY: Array of floats
+ * @GIMP_PDB_STRINGARRAY: Array of strings
+ * @GIMP_PDB_COLOR: Color
+ * @GIMP_PDB_ITEM: Item ID
+ * @GIMP_PDB_DISPLAY: Display ID
+ * @GIMP_PDB_IMAGE: Image ID
+ * @GIMP_PDB_LAYER: Layer ID
+ * @GIMP_PDB_CHANNEL: Channel ID
+ * @GIMP_PDB_DRAWABLE: Drawable ID
+ * @GIMP_PDB_SELECTION: Selection ID
+ * @GIMP_PDB_COLORARRAY: Array of colors
+ * @GIMP_PDB_VECTORS: Vectors (psath) ID
+ * @GIMP_PDB_PARASITE: Parasite
+ * @GIMP_PDB_STATUS: Procedure return status
+ * @GIMP_PDB_END: Marker for last enum value
+ * @GIMP_PDB_PATH: Deprecated alias for @GIMP_PDB_VECTORS
+ * @GIMP_PDB_BOUNDARY: Deprecated alias for @GIMP_PDB_COLORARRAY
+ * @GIMP_PDB_REGION: Deprecated alias for @GIMP_PDB_ITEM
+ *
+ * Parameter types of the PDB.
+ **/
+#define GIMP_TYPE_PDB_ARG_TYPE (gimp_pdb_arg_type_get_type ())
+
+GType gimp_pdb_arg_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_PDB_INT32,
+ GIMP_PDB_INT16,
+ GIMP_PDB_INT8,
+ GIMP_PDB_FLOAT,
+ GIMP_PDB_STRING,
+ GIMP_PDB_INT32ARRAY,
+ GIMP_PDB_INT16ARRAY,
+ GIMP_PDB_INT8ARRAY,
+ GIMP_PDB_FLOATARRAY,
+ GIMP_PDB_STRINGARRAY,
+ GIMP_PDB_COLOR,
+ GIMP_PDB_ITEM,
+ GIMP_PDB_DISPLAY,
+ GIMP_PDB_IMAGE,
+ GIMP_PDB_LAYER,
+ GIMP_PDB_CHANNEL,
+ GIMP_PDB_DRAWABLE,
+ GIMP_PDB_SELECTION,
+ GIMP_PDB_COLORARRAY,
+ GIMP_PDB_VECTORS,
+ GIMP_PDB_PARASITE,
+ GIMP_PDB_STATUS,
+ GIMP_PDB_END,
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_PDB_PATH = GIMP_PDB_VECTORS, /*< skip >*/
+ GIMP_PDB_BOUNDARY = GIMP_PDB_COLORARRAY, /*< skip >*/
+ GIMP_PDB_REGION = GIMP_PDB_ITEM /*< skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpPDBArgType;
+
+
+/**
+ * GimpPDBErrorHandler:
+ * @GIMP_PDB_ERROR_HANDLER_INTERNAL: Internal
+ * @GIMP_PDB_ERROR_HANDLER_PLUGIN: Plug-In
+ *
+ * PDB error handlers.
+ **/
+#define GIMP_TYPE_PDB_ERROR_HANDLER (gimp_pdb_error_handler_get_type ())
+
+GType gimp_pdb_error_handler_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_PDB_ERROR_HANDLER_INTERNAL,
+ GIMP_PDB_ERROR_HANDLER_PLUGIN
+} GimpPDBErrorHandler;
+
+
+/**
+ * GimpPDBProcType:
+ * @GIMP_INTERNAL: Internal GIMP procedure
+ * @GIMP_PLUGIN: GIMP Plug-In
+ * @GIMP_EXTENSION: GIMP Extension
+ * @GIMP_TEMPORARY: Temporary Procedure
+ *
+ * Types of PDB procedures.
+ **/
+#define GIMP_TYPE_PDB_PROC_TYPE (gimp_pdb_proc_type_get_type ())
+
+GType gimp_pdb_proc_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_INTERNAL, /*< desc="Internal GIMP procedure" >*/
+ GIMP_PLUGIN, /*< desc="GIMP Plug-In" >*/
+ GIMP_EXTENSION, /*< desc="GIMP Extension" >*/
+ GIMP_TEMPORARY /*< desc="Temporary Procedure" >*/
+} GimpPDBProcType;
+
+
+/**
+ * GimpPDBStatusType:
+ * @GIMP_PDB_EXECUTION_ERROR: Execution error
+ * @GIMP_PDB_CALLING_ERROR: Calling error
+ * @GIMP_PDB_PASS_THROUGH: Pass through
+ * @GIMP_PDB_SUCCESS: Success
+ * @GIMP_PDB_CANCEL: User cancel
+ *
+ * Return status of PDB calls.
+ **/
+#define GIMP_TYPE_PDB_STATUS_TYPE (gimp_pdb_status_type_get_type ())
+
+GType gimp_pdb_status_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_PDB_EXECUTION_ERROR,
+ GIMP_PDB_CALLING_ERROR,
+ GIMP_PDB_PASS_THROUGH,
+ GIMP_PDB_SUCCESS,
+ GIMP_PDB_CANCEL
+} GimpPDBStatusType;
+
+
+/**
+ * GimpPrecision:
+ * @GIMP_PRECISION_U8_LINEAR: 8-bit linear integer
+ * @GIMP_PRECISION_U8_GAMMA: 8-bit gamma integer
+ * @GIMP_PRECISION_U16_LINEAR: 16-bit linear integer
+ * @GIMP_PRECISION_U16_GAMMA: 16-bit gamma integer
+ * @GIMP_PRECISION_U32_LINEAR: 32-bit linear integer
+ * @GIMP_PRECISION_U32_GAMMA: 32-bit gamma integer
+ * @GIMP_PRECISION_HALF_LINEAR: 16-bit linear floating point
+ * @GIMP_PRECISION_HALF_GAMMA: 16-bit gamma floating point
+ * @GIMP_PRECISION_FLOAT_LINEAR: 32-bit linear floating point
+ * @GIMP_PRECISION_FLOAT_GAMMA: 32-bit gamma floating point
+ * @GIMP_PRECISION_DOUBLE_LINEAR: 64-bit linear floating point
+ * @GIMP_PRECISION_DOUBLE_GAMMA: 64-bit gamma floating point
+ *
+ * Precisions for pixel encoding.
+ *
+ * Since: 2.10
+ **/
+#define GIMP_TYPE_PRECISION (gimp_precision_get_type ())
+
+GType gimp_precision_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_PRECISION_U8_LINEAR = 100, /*< desc="8-bit linear integer" >*/
+ GIMP_PRECISION_U8_GAMMA = 150, /*< desc="8-bit gamma integer" >*/
+ GIMP_PRECISION_U16_LINEAR = 200, /*< desc="16-bit linear integer" >*/
+ GIMP_PRECISION_U16_GAMMA = 250, /*< desc="16-bit gamma integer" >*/
+ GIMP_PRECISION_U32_LINEAR = 300, /*< desc="32-bit linear integer" >*/
+ GIMP_PRECISION_U32_GAMMA = 350, /*< desc="32-bit gamma integer" >*/
+ GIMP_PRECISION_HALF_LINEAR = 500, /*< desc="16-bit linear floating point" >*/
+ GIMP_PRECISION_HALF_GAMMA = 550, /*< desc="16-bit gamma floating point" >*/
+ GIMP_PRECISION_FLOAT_LINEAR = 600, /*< desc="32-bit linear floating point" >*/
+ GIMP_PRECISION_FLOAT_GAMMA = 650, /*< desc="32-bit gamma floating point" >*/
+ GIMP_PRECISION_DOUBLE_LINEAR = 700, /*< desc="64-bit linear floating point" >*/
+ GIMP_PRECISION_DOUBLE_GAMMA = 750 /*< desc="64-bit gamma floating point" >*/
+} GimpPrecision;
+
+
+/**
+ * GimpProgressCommand:
+ * @GIMP_PROGRESS_COMMAND_START: Start a progress
+ * @GIMP_PROGRESS_COMMAND_END: End the progress
+ * @GIMP_PROGRESS_COMMAND_SET_TEXT: Set the text
+ * @GIMP_PROGRESS_COMMAND_SET_VALUE: Set the percentage
+ * @GIMP_PROGRESS_COMMAND_PULSE: Pulse the progress
+ * @GIMP_PROGRESS_COMMAND_GET_WINDOW: Get the window where the progress is shown
+ *
+ * Commands for the progress API.
+ **/
+#define GIMP_TYPE_PROGRESS_COMMAND (gimp_progress_command_get_type ())
+
+GType gimp_progress_command_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_PROGRESS_COMMAND_START,
+ GIMP_PROGRESS_COMMAND_END,
+ GIMP_PROGRESS_COMMAND_SET_TEXT,
+ GIMP_PROGRESS_COMMAND_SET_VALUE,
+ GIMP_PROGRESS_COMMAND_PULSE,
+ GIMP_PROGRESS_COMMAND_GET_WINDOW
+} GimpProgressCommand;
+
+
+/**
+ * GimpRepeatMode:
+ * @GIMP_REPEAT_NONE: None (extend)
+ * @GIMP_REPEAT_SAWTOOTH: Sawtooth wave
+ * @GIMP_REPEAT_TRIANGULAR: Triangular wave
+ * @GIMP_REPEAT_TRUNCATE: Truncate
+ *
+ * Repeat modes for example for gradients.
+ **/
+#define GIMP_TYPE_REPEAT_MODE (gimp_repeat_mode_get_type ())
+
+GType gimp_repeat_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_REPEAT_NONE, /*< desc="None (extend)" >*/
+ GIMP_REPEAT_SAWTOOTH, /*< desc="Sawtooth wave" >*/
+ GIMP_REPEAT_TRIANGULAR, /*< desc="Triangular wave" >*/
+ GIMP_REPEAT_TRUNCATE /*< desc="Truncate" >*/
+} GimpRepeatMode;
+
+
+/**
+ * GimpRotationType:
+ * @GIMP_ROTATE_90: 90 degrees
+ * @GIMP_ROTATE_180: 180 degrees
+ * @GIMP_ROTATE_270: 270 degrees
+ *
+ * Types of simple rotations.
+ **/
+#define GIMP_TYPE_ROTATION_TYPE (gimp_rotation_type_get_type ())
+
+GType gimp_rotation_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_ROTATE_90,
+ GIMP_ROTATE_180,
+ GIMP_ROTATE_270
+} GimpRotationType;
+
+
+/**
+ * GimpRunMode:
+ * @GIMP_RUN_INTERACTIVE: Run interactively
+ * @GIMP_RUN_NONINTERACTIVE: Run non-interactively
+ * @GIMP_RUN_WITH_LAST_VALS: Run with last used values
+ *
+ * Run modes for plug-ins.
+ **/
+#define GIMP_TYPE_RUN_MODE (gimp_run_mode_get_type ())
+
+GType gimp_run_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_RUN_INTERACTIVE, /*< desc="Run interactively" >*/
+ GIMP_RUN_NONINTERACTIVE, /*< desc="Run non-interactively" >*/
+ GIMP_RUN_WITH_LAST_VALS /*< desc="Run with last used values" >*/
+} GimpRunMode;
+
+
+/**
+ * GimpSelectCriterion:
+ * @GIMP_SELECT_CRITERION_COMPOSITE: Composite
+ * @GIMP_SELECT_CRITERION_R: Red
+ * @GIMP_SELECT_CRITERION_G: Green
+ * @GIMP_SELECT_CRITERION_B: Blue
+ * @GIMP_SELECT_CRITERION_H: HSV Hue
+ * @GIMP_SELECT_CRITERION_S: HSV Saturation
+ * @GIMP_SELECT_CRITERION_V: HSV Value
+ * @GIMP_SELECT_CRITERION_A: Alpha
+ * @GIMP_SELECT_CRITERION_LCH_L: LCh Lightness
+ * @GIMP_SELECT_CRITERION_LCH_C: LCh Chroma
+ * @GIMP_SELECT_CRITERION_LCH_H: LCh Hue
+ *
+ * Criterions for color similarity.
+ **/
+#define GIMP_TYPE_SELECT_CRITERION (gimp_select_criterion_get_type ())
+
+GType gimp_select_criterion_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_SELECT_CRITERION_COMPOSITE, /*< desc="Composite" >*/
+ GIMP_SELECT_CRITERION_R, /*< desc="Red" >*/
+ GIMP_SELECT_CRITERION_G, /*< desc="Green" >*/
+ GIMP_SELECT_CRITERION_B, /*< desc="Blue" >*/
+ GIMP_SELECT_CRITERION_H, /*< desc="HSV Hue" >*/
+ GIMP_SELECT_CRITERION_S, /*< desc="HSV Saturation" >*/
+ GIMP_SELECT_CRITERION_V, /*< desc="HSV Value" >*/
+ GIMP_SELECT_CRITERION_A, /*< desc="Alpha" >*/
+ GIMP_SELECT_CRITERION_LCH_L, /*< desc="LCh Lightness" >*/
+ GIMP_SELECT_CRITERION_LCH_C, /*< desc="LCh Chroma" >*/
+ GIMP_SELECT_CRITERION_LCH_H, /*< desc="LCh Hue" >*/
+} GimpSelectCriterion;
+
+
+/**
+ * GimpSizeType:
+ * @GIMP_PIXELS: Pixels
+ * @GIMP_POINTS: Points
+ *
+ * Size types for the old-style text API.
+ **/
+#define GIMP_TYPE_SIZE_TYPE (gimp_size_type_get_type ())
+
+GType gimp_size_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_PIXELS, /*< desc="Pixels" >*/
+ GIMP_POINTS /*< desc="Points" >*/
+} GimpSizeType;
+
+
+/**
+ * GimpStackTraceMode:
+ * @GIMP_STACK_TRACE_NEVER: Never
+ * @GIMP_STACK_TRACE_QUERY: Ask each time
+ * @GIMP_STACK_TRACE_ALWAYS: Always
+ *
+ * When to generate stack traces in case of an error.
+ **/
+#define GIMP_TYPE_STACK_TRACE_MODE (gimp_stack_trace_mode_get_type ())
+
+GType gimp_stack_trace_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_STACK_TRACE_NEVER,
+ GIMP_STACK_TRACE_QUERY,
+ GIMP_STACK_TRACE_ALWAYS
+} GimpStackTraceMode;
+
+
+/**
+ * GimpStrokeMethod:
+ * @GIMP_STROKE_LINE: Stroke line
+ * @GIMP_STROKE_PAINT_METHOD: Stroke with a paint tool
+ *
+ * Methods of stroking selections and paths.
+ **/
+#define GIMP_TYPE_STROKE_METHOD (gimp_stroke_method_get_type ())
+
+GType gimp_stroke_method_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_STROKE_LINE, /*< desc="Stroke line" >*/
+ GIMP_STROKE_PAINT_METHOD /*< desc="Stroke with a paint tool" >*/
+} GimpStrokeMethod;
+
+
+/**
+ * GimpTextDirection:
+ * @GIMP_TEXT_DIRECTION_LTR: From left to right
+ * @GIMP_TEXT_DIRECTION_RTL: From right to left
+ * @GIMP_TEXT_DIRECTION_TTB_RTL: Characters are from top to bottom, Lines are from right to left
+ * @GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT: Upright characters are from top to bottom, Lines are from right to left
+ * @GIMP_TEXT_DIRECTION_TTB_LTR: Characters are from top to bottom, Lines are from left to right
+ * @GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT: Upright characters are from top to bottom, Lines are from left to right
+ *
+ * Text directions.
+ **/
+#define GIMP_TYPE_TEXT_DIRECTION (gimp_text_direction_get_type ())
+
+GType gimp_text_direction_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_TEXT_DIRECTION_LTR, /*< desc="From left to right" >*/
+ GIMP_TEXT_DIRECTION_RTL, /*< desc="From right to left" >*/
+ GIMP_TEXT_DIRECTION_TTB_RTL, /*< desc="Vertical, right to left (mixed orientation)" >*/
+ GIMP_TEXT_DIRECTION_TTB_RTL_UPRIGHT, /*< desc="Vertical, right to left (upright orientation)" >*/
+ GIMP_TEXT_DIRECTION_TTB_LTR, /*< desc="Vertical, left to right (mixed orientation)" >*/
+ GIMP_TEXT_DIRECTION_TTB_LTR_UPRIGHT /*< desc="Vertical, left to right (upright orientation)" >*/
+} GimpTextDirection;
+
+
+/**
+ * GimpTextHintStyle:
+ * @GIMP_TEXT_HINT_STYLE_NONE: None
+ * @GIMP_TEXT_HINT_STYLE_SLIGHT: Slight
+ * @GIMP_TEXT_HINT_STYLE_MEDIUM: Medium
+ * @GIMP_TEXT_HINT_STYLE_FULL: Full
+ *
+ * Text hint strengths.
+ **/
+#define GIMP_TYPE_TEXT_HINT_STYLE (gimp_text_hint_style_get_type ())
+
+GType gimp_text_hint_style_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_TEXT_HINT_STYLE_NONE, /*< desc="None" >*/
+ GIMP_TEXT_HINT_STYLE_SLIGHT, /*< desc="Slight" >*/
+ GIMP_TEXT_HINT_STYLE_MEDIUM, /*< desc="Medium" >*/
+ GIMP_TEXT_HINT_STYLE_FULL /*< desc="Full" >*/
+} GimpTextHintStyle;
+
+
+/**
+ * GimpTextJustification:
+ * @GIMP_TEXT_JUSTIFY_LEFT: Left justified
+ * @GIMP_TEXT_JUSTIFY_RIGHT: Right justified
+ * @GIMP_TEXT_JUSTIFY_CENTER: Centered
+ * @GIMP_TEXT_JUSTIFY_FILL: Filled
+ *
+ * Text justifications.
+ **/
+#define GIMP_TYPE_TEXT_JUSTIFICATION (gimp_text_justification_get_type ())
+
+GType gimp_text_justification_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_TEXT_JUSTIFY_LEFT, /*< desc="Left justified" >*/
+ GIMP_TEXT_JUSTIFY_RIGHT, /*< desc="Right justified" >*/
+ GIMP_TEXT_JUSTIFY_CENTER, /*< desc="Centered" >*/
+ GIMP_TEXT_JUSTIFY_FILL /*< desc="Filled" >*/
+} GimpTextJustification;
+
+
+/**
+ * GimpTransferMode:
+ * @GIMP_TRANSFER_SHADOWS: Shadows
+ * @GIMP_TRANSFER_MIDTONES: Midtones
+ * @GIMP_TRANSFER_HIGHLIGHTS: Highlights
+ * @GIMP_SHADOWS: Deprecated alias for @GIMP_TRANSFER_SHADOWS
+ * @GIMP_MIDTONES: Deprecated alias for @GIMP_TRANSFER_MIDTONES
+ * @GIMP_HIGHLIGHTS: Deprecated alias for @GIMP_TRANSFER_HIGHLIGHTS
+ *
+ * For choosing which brightness ranges to transform.
+ **/
+#define GIMP_TYPE_TRANSFER_MODE (gimp_transfer_mode_get_type ())
+
+GType gimp_transfer_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_TRANSFER_SHADOWS, /*< desc="Shadows" >*/
+ GIMP_TRANSFER_MIDTONES, /*< desc="Midtones" >*/
+ GIMP_TRANSFER_HIGHLIGHTS, /*< desc="Highlights" >*/
+
+#ifndef GIMP_DISABLE_DEPRECATED
+ GIMP_SHADOWS = GIMP_TRANSFER_SHADOWS, /*< skip, pdb-skip >*/
+ GIMP_MIDTONES = GIMP_TRANSFER_MIDTONES, /*< skip, pdb-skip >*/
+ GIMP_HIGHLIGHTS = GIMP_TRANSFER_HIGHLIGHTS /*< skip, pdb-skip >*/
+#endif /* GIMP_DISABLE_DEPRECATED */
+} GimpTransferMode;
+
+
+/**
+ * GimpTransformDirection:
+ * @GIMP_TRANSFORM_FORWARD: Normal (Forward)
+ * @GIMP_TRANSFORM_BACKWARD: Corrective (Backward)
+ *
+ * Transform directions.
+ **/
+#define GIMP_TYPE_TRANSFORM_DIRECTION (gimp_transform_direction_get_type ())
+
+GType gimp_transform_direction_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_TRANSFORM_FORWARD, /*< desc="Normal (Forward)" >*/
+ GIMP_TRANSFORM_BACKWARD /*< desc="Corrective (Backward)" >*/
+} GimpTransformDirection;
+
+
+/**
+ * GimpTransformResize:
+ * @GIMP_TRANSFORM_RESIZE_ADJUST: Adjust
+ * @GIMP_TRANSFORM_RESIZE_CLIP: Clip
+ * @GIMP_TRANSFORM_RESIZE_CROP: Crop to result
+ * @GIMP_TRANSFORM_RESIZE_CROP_WITH_ASPECT: Crop with aspect
+ *
+ * Ways of clipping the result when transforming drawables.
+ **/
+#define GIMP_TYPE_TRANSFORM_RESIZE (gimp_transform_resize_get_type ())
+
+GType gimp_transform_resize_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_TRANSFORM_RESIZE_ADJUST, /*< desc="Adjust" >*/
+ GIMP_TRANSFORM_RESIZE_CLIP, /*< desc="Clip" >*/
+ GIMP_TRANSFORM_RESIZE_CROP, /*< desc="Crop to result" >*/
+ GIMP_TRANSFORM_RESIZE_CROP_WITH_ASPECT /*< desc="Crop with aspect" >*/
+} GimpTransformResize;
+
+
+/**
+ * GimpUnit:
+ * @GIMP_UNIT_PIXEL: Pixels
+ * @GIMP_UNIT_INCH: Inches
+ * @GIMP_UNIT_MM: Millimeters
+ * @GIMP_UNIT_POINT: Points
+ * @GIMP_UNIT_PICA: Picas
+ * @GIMP_UNIT_END: Marker for end-of-builtin-units
+ * @GIMP_UNIT_PERCENT: Pseudo-unit percent
+ *
+ * Units used for dimensions in images.
+ **/
+typedef enum /*< skip >*/
+{
+ GIMP_UNIT_PIXEL = 0,
+
+ GIMP_UNIT_INCH = 1,
+ GIMP_UNIT_MM = 2,
+ GIMP_UNIT_POINT = 3,
+ GIMP_UNIT_PICA = 4,
+
+ GIMP_UNIT_END = 5,
+
+ GIMP_UNIT_PERCENT = 65536 /*< pdb-skip >*/
+} GimpUnit;
+
+
+#ifndef GIMP_DISABLE_DEPRECATED
+/**
+ * GimpUserDirectory:
+ * @GIMP_USER_DIRECTORY_DESKTOP: Deprecated
+ * @GIMP_USER_DIRECTORY_DOCUMENTS: Deprecated
+ * @GIMP_USER_DIRECTORY_DOWNLOAD: Deprecated
+ * @GIMP_USER_DIRECTORY_MUSIC: Deprecated
+ * @GIMP_USER_DIRECTORY_PICTURES: Deprecated
+ * @GIMP_USER_DIRECTORY_PUBLIC_SHARE: Deprecated
+ * @GIMP_USER_DIRECTORY_TEMPLATES: Deprecated
+ * @GIMP_USER_DIRECTORY_VIDEOS: Deprecated
+ *
+ * Deprecated enum, don't use.
+ **/
+#define GIMP_TYPE_USER_DIRECTORY (gimp_user_directory_get_type ())
+
+GType gimp_user_directory_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_USER_DIRECTORY_DESKTOP,
+ GIMP_USER_DIRECTORY_DOCUMENTS,
+ GIMP_USER_DIRECTORY_DOWNLOAD,
+ GIMP_USER_DIRECTORY_MUSIC,
+ GIMP_USER_DIRECTORY_PICTURES,
+ GIMP_USER_DIRECTORY_PUBLIC_SHARE,
+ GIMP_USER_DIRECTORY_TEMPLATES,
+ GIMP_USER_DIRECTORY_VIDEOS
+} GimpUserDirectory;
+#endif /* !GIMP_DISABLE_DEPRECATED */
+
+
+/**
+ * GimpVectorsStrokeType:
+ * @GIMP_VECTORS_STROKE_TYPE_BEZIER: A bezier stroke
+ *
+ * Possible type of strokes in vectors objects.
+ **/
+#define GIMP_TYPE_VECTORS_STROKE_TYPE (gimp_vectors_stroke_type_get_type ())
+
+GType gimp_vectors_stroke_type_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_VECTORS_STROKE_TYPE_BEZIER
+} GimpVectorsStrokeType;
+
+G_END_DECLS
+
+#endif /* __GIMP_BASE_ENUMS_H__ */
diff --git a/libgimpbase/gimpbasetypes.c b/libgimpbase/gimpbasetypes.c
new file mode 100644
index 0000000..fe22464
--- /dev/null
+++ b/libgimpbase/gimpbasetypes.c
@@ -0,0 +1,244 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimpbasetypes.c
+ * Copyright (C) 2004 Sven Neumann <sven@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gimpbasetypes.h"
+
+
+/**
+ * SECTION: gimpbasetypes
+ * @title: gimpbasetypes
+ * @short_description: Translation between gettext translation domain
+ * identifier and GType.
+ *
+ * Translation between gettext translation domain identifier and
+ * GType.
+ **/
+
+
+static GQuark gimp_translation_domain_quark (void) G_GNUC_CONST;
+static GQuark gimp_translation_context_quark (void) G_GNUC_CONST;
+static GQuark gimp_value_descriptions_quark (void) G_GNUC_CONST;
+
+
+/**
+ * gimp_type_set_translation_domain:
+ * @type: a #GType
+ * @domain: a constant string that identifies a translation domain or %NULL
+ *
+ * This function attaches a constant string as a gettext translation
+ * domain identifier to a #GType. The only purpose of this function is
+ * to use it when registering a #G_TYPE_ENUM with translatable value
+ * names.
+ *
+ * Since: 2.2
+ **/
+void
+gimp_type_set_translation_domain (GType type,
+ const gchar *domain)
+{
+ g_type_set_qdata (type,
+ gimp_translation_domain_quark (), (gpointer) domain);
+}
+
+/**
+ * gimp_type_get_translation_domain:
+ * @type: a #GType
+ *
+ * Retrieves the gettext translation domain identifier that has been
+ * previously set using gimp_type_set_translation_domain(). You should
+ * not need to use this function directly, use gimp_enum_get_value()
+ * or gimp_enum_value_get_desc() instead.
+ *
+ * Return value: the translation domain associated with @type
+ * or %NULL if no domain was set
+ *
+ * Since: 2.2
+ **/
+const gchar *
+gimp_type_get_translation_domain (GType type)
+{
+ return (const gchar *) g_type_get_qdata (type,
+ gimp_translation_domain_quark ());
+}
+
+/**
+ * gimp_type_set_translation_context:
+ * @type: a #GType
+ * @context: a constant string that identifies a translation context or %NULL
+ *
+ * This function attaches a constant string as a translation context
+ * to a #GType. The only purpose of this function is to use it when
+ * registering a #G_TYPE_ENUM with translatable value names.
+ *
+ * Since: 2.8
+ **/
+void
+gimp_type_set_translation_context (GType type,
+ const gchar *context)
+{
+ g_type_set_qdata (type,
+ gimp_translation_context_quark (), (gpointer) context);
+}
+
+/**
+ * gimp_type_get_translation_context:
+ * @type: a #GType
+ *
+ * Retrieves the translation context that has been previously set
+ * using gimp_type_set_translation_context(). You should not need to
+ * use this function directly, use gimp_enum_get_value() or
+ * gimp_enum_value_get_desc() instead.
+ *
+ * Return value: the translation context associated with @type
+ * or %NULL if no context was set
+ *
+ * Since: 2.8
+ **/
+const gchar *
+gimp_type_get_translation_context (GType type)
+{
+ return (const gchar *) g_type_get_qdata (type,
+ gimp_translation_context_quark ());
+}
+
+/**
+ * gimp_enum_set_value_descriptions:
+ * @enum_type: a #GType
+ * @descriptions: a %NULL terminated constant static array of #GimpEnumDesc
+ *
+ * Sets the array of human readable and translatable descriptions
+ * and help texts for enum values.
+ *
+ * Since: 2.2
+ **/
+void
+gimp_enum_set_value_descriptions (GType enum_type,
+ const GimpEnumDesc *descriptions)
+{
+ g_return_if_fail (g_type_is_a (enum_type, G_TYPE_ENUM));
+ g_return_if_fail (descriptions != NULL);
+
+ g_type_set_qdata (enum_type,
+ gimp_value_descriptions_quark (),
+ (gpointer) descriptions);
+}
+
+/**
+ * gimp_enum_get_value_descriptions:
+ * @enum_type: a #GType
+ *
+ * Retreives the array of human readable and translatable descriptions
+ * and help texts for enum values.
+ *
+ * Returns: a %NULL terminated constant array of #GimpEnumDesc
+ *
+ * Since: 2.2
+ **/
+const GimpEnumDesc *
+gimp_enum_get_value_descriptions (GType enum_type)
+{
+ g_return_val_if_fail (g_type_is_a (enum_type, G_TYPE_ENUM), NULL);
+
+ return (const GimpEnumDesc *)
+ g_type_get_qdata (enum_type, gimp_value_descriptions_quark ());
+}
+
+/**
+ * gimp_flags_set_value_descriptions:
+ * @flags_type: a #GType
+ * @descriptions: a %NULL terminated constant static array of #GimpFlagsDesc
+ *
+ * Sets the array of human readable and translatable descriptions
+ * and help texts for flags values.
+ *
+ * Since: 2.2
+ **/
+void
+gimp_flags_set_value_descriptions (GType flags_type,
+ const GimpFlagsDesc *descriptions)
+{
+ g_return_if_fail (g_type_is_a (flags_type, G_TYPE_FLAGS));
+ g_return_if_fail (descriptions != NULL);
+
+ g_type_set_qdata (flags_type,
+ gimp_value_descriptions_quark (),
+ (gpointer) descriptions);
+}
+
+/**
+ * gimp_flags_get_value_descriptions:
+ * @flags_type: a #GType
+ *
+ * Retreives the array of human readable and translatable descriptions
+ * and help texts for flags values.
+ *
+ * Returns: a %NULL terminated constant array of #GimpFlagsDesc
+ *
+ * Since: 2.2
+ **/
+const GimpFlagsDesc *
+gimp_flags_get_value_descriptions (GType flags_type)
+{
+ g_return_val_if_fail (g_type_is_a (flags_type, G_TYPE_FLAGS), NULL);
+
+ return (const GimpFlagsDesc *)
+ g_type_get_qdata (flags_type, gimp_value_descriptions_quark ());
+}
+
+
+/* private functions */
+
+static GQuark
+gimp_translation_domain_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (! quark)
+ quark = g_quark_from_static_string ("gimp-translation-domain-quark");
+
+ return quark;
+}
+
+static GQuark
+gimp_translation_context_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (! quark)
+ quark = g_quark_from_static_string ("gimp-translation-context-quark");
+
+ return quark;
+}
+
+static GQuark
+gimp_value_descriptions_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (! quark)
+ quark = g_quark_from_static_string ("gimp-value-descriptions-quark");
+
+ return quark;
+}
diff --git a/libgimpbase/gimpbasetypes.h b/libgimpbase/gimpbasetypes.h
new file mode 100644
index 0000000..9c3680d
--- /dev/null
+++ b/libgimpbase/gimpbasetypes.h
@@ -0,0 +1,113 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_BASE_TYPES_H__
+#define __GIMP_BASE_TYPES_H__
+
+
+#include <libgimpcolor/gimpcolortypes.h>
+#include <libgimpmath/gimpmathtypes.h>
+
+#include <libgimpbase/gimpbaseenums.h>
+#include <libgimpbase/gimpparam.h>
+
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/* XXX FIXME move these to a separate file */
+
+#ifdef GIMP_DISABLE_DEPRECATION_WARNINGS
+#define GIMP_DEPRECATED
+#define GIMP_DEPRECATED_FOR(f)
+#define GIMP_UNAVAILABLE(maj,min)
+#else
+#define GIMP_DEPRECATED G_DEPRECATED
+#define GIMP_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f)
+#define GIMP_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min)
+#endif
+
+
+typedef struct _GimpParasite GimpParasite;
+typedef struct _GimpDatafileData GimpDatafileData;
+typedef struct _GimpEnumDesc GimpEnumDesc;
+typedef struct _GimpFlagsDesc GimpFlagsDesc;
+typedef struct _GimpValueArray GimpValueArray;
+
+
+typedef void (* GimpDatafileLoaderFunc) (const GimpDatafileData *file_data,
+ gpointer user_data);
+
+typedef struct _GimpMetadata GimpMetadata;
+
+
+/**
+ * GimpEnumDesc:
+ * @value: An enum value.
+ * @value_desc: The value's description.
+ * @value_help: The value's help text.
+ *
+ * This structure is used to register translatable descriptions and
+ * help texts for enum values. See gimp_enum_set_value_descriptions().
+ **/
+struct _GimpEnumDesc
+{
+ gint value;
+ const gchar *value_desc;
+ const gchar *value_help;
+};
+
+/**
+ * GimpFlagsDesc:
+ * @value: A flag value.
+ * @value_desc: The value's description.
+ * @value_help: The value's help text.
+ *
+ * This structure is used to register translatable descriptions and
+ * help texts for flag values. See gimp_flags_set_value_descriptions().
+ **/
+struct _GimpFlagsDesc
+{
+ guint value;
+ const gchar *value_desc;
+ const gchar *value_help;
+};
+
+
+void gimp_type_set_translation_domain (GType type,
+ const gchar *domain);
+const gchar * gimp_type_get_translation_domain (GType type);
+
+void gimp_type_set_translation_context (GType type,
+ const gchar *context);
+const gchar * gimp_type_get_translation_context (GType type);
+
+void gimp_enum_set_value_descriptions (GType enum_type,
+ const GimpEnumDesc *descriptions);
+const GimpEnumDesc * gimp_enum_get_value_descriptions (GType enum_type);
+
+void gimp_flags_set_value_descriptions (GType flags_type,
+ const GimpFlagsDesc *descriptions);
+const GimpFlagsDesc * gimp_flags_get_value_descriptions (GType flags_type);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_BASE_TYPES_H__ */
diff --git a/libgimpbase/gimpchecks.c b/libgimpbase/gimpchecks.c
new file mode 100644
index 0000000..589bf6f
--- /dev/null
+++ b/libgimpbase/gimpchecks.c
@@ -0,0 +1,73 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimpchecks.c
+ * Copyright (C) 2004 Sven Neumann <sven@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gimpbasetypes.h"
+
+#include "gimpchecks.h"
+
+
+/**
+ * SECTION: gimpchecks
+ * @title: gimpchecks
+ * @short_description: Constants and functions related to rendering
+ * checkerboards.
+ *
+ * Constants and functions related to rendering checkerboards.
+ **/
+
+
+/**
+ * gimp_checks_get_shades:
+ * @type: the checkerboard type
+ * @light: return location for the light shade
+ * @dark: return location for the dark shade
+ *
+ * Retrieves the actual shades of gray to use when drawing a
+ * checkerboard for a certain #GimpCheckType.
+ *
+ * Since: 2.2
+ **/
+void
+gimp_checks_get_shades (GimpCheckType type,
+ guchar *light,
+ guchar *dark)
+{
+ const guchar shades[6][2] =
+ {
+ { 204, 255 }, /* LIGHT_CHECKS */
+ { 102, 153 }, /* GRAY_CHECKS */
+ { 0, 51 }, /* DARK_CHECKS */
+ { 255, 255 }, /* WHITE_ONLY */
+ { 127, 127 }, /* GRAY_ONLY */
+ { 0, 0 } /* BLACK_ONLY */
+ };
+
+ type = MIN (type, 5);
+
+ if (light)
+ *light = shades[type][1];
+ if (dark)
+ *dark = shades[type][0];
+}
diff --git a/libgimpbase/gimpchecks.h b/libgimpbase/gimpchecks.h
new file mode 100644
index 0000000..c41a4d6
--- /dev/null
+++ b/libgimpbase/gimpchecks.h
@@ -0,0 +1,68 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_CHECKS_H__
+#define __GIMP_CHECKS_H__
+
+G_BEGIN_DECLS
+
+
+/**
+ * GIMP_CHECK_SIZE:
+ *
+ * The default checkerboard size in pixels. This is configurable in
+ * the core but GIMP plug-ins can't access the user preference and
+ * should use this constant instead.
+ **/
+#define GIMP_CHECK_SIZE 8
+
+/**
+ * GIMP_CHECK_SIZE_SM:
+ *
+ * The default small checkerboard size in pixels.
+ **/
+#define GIMP_CHECK_SIZE_SM 4
+
+
+/**
+ * GIMP_CHECK_DARK:
+ *
+ * The dark gray value for the default checkerboard pattern.
+ **/
+#define GIMP_CHECK_DARK 0.4
+
+/**
+ * GIMP_CHECK_LIGHT:
+ *
+ * The dark light value for the default checkerboard pattern.
+ **/
+#define GIMP_CHECK_LIGHT 0.6
+
+
+void gimp_checks_get_shades (GimpCheckType type,
+ guchar *light,
+ guchar *dark);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_CHECKS_H__ */
diff --git a/libgimpbase/gimpcompatenums.c b/libgimpbase/gimpcompatenums.c
new file mode 100644
index 0000000..82fdafe
--- /dev/null
+++ b/libgimpbase/gimpcompatenums.c
@@ -0,0 +1,581 @@
+
+/* Generated data (by gimp-mkenums) */
+
+#include "config.h"
+#include <glib-object.h>
+#include "gimpbasetypes.h"
+#include "gimpcompatenums.h"
+#include "libgimp/libgimp-intl.h"
+
+/* enumerations from "gimpcompatenums.h" */
+GType
+gimp_add_mask_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_ADD_WHITE_MASK, "GIMP_ADD_WHITE_MASK", "white-mask" },
+ { GIMP_ADD_BLACK_MASK, "GIMP_ADD_BLACK_MASK", "black-mask" },
+ { GIMP_ADD_ALPHA_MASK, "GIMP_ADD_ALPHA_MASK", "alpha-mask" },
+ { GIMP_ADD_ALPHA_TRANSFER_MASK, "GIMP_ADD_ALPHA_TRANSFER_MASK", "alpha-transfer-mask" },
+ { GIMP_ADD_SELECTION_MASK, "GIMP_ADD_SELECTION_MASK", "selection-mask" },
+ { GIMP_ADD_COPY_MASK, "GIMP_ADD_COPY_MASK", "copy-mask" },
+ { GIMP_ADD_CHANNEL_MASK, "GIMP_ADD_CHANNEL_MASK", "channel-mask" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_ADD_WHITE_MASK, "GIMP_ADD_WHITE_MASK", NULL },
+ { GIMP_ADD_BLACK_MASK, "GIMP_ADD_BLACK_MASK", NULL },
+ { GIMP_ADD_ALPHA_MASK, "GIMP_ADD_ALPHA_MASK", NULL },
+ { GIMP_ADD_ALPHA_TRANSFER_MASK, "GIMP_ADD_ALPHA_TRANSFER_MASK", NULL },
+ { GIMP_ADD_SELECTION_MASK, "GIMP_ADD_SELECTION_MASK", NULL },
+ { GIMP_ADD_COPY_MASK, "GIMP_ADD_COPY_MASK", NULL },
+ { GIMP_ADD_CHANNEL_MASK, "GIMP_ADD_CHANNEL_MASK", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpAddMaskTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "add-mask-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_blend_mode_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_FG_BG_RGB_MODE, "GIMP_FG_BG_RGB_MODE", "fg-bg-rgb-mode" },
+ { GIMP_FG_BG_HSV_MODE, "GIMP_FG_BG_HSV_MODE", "fg-bg-hsv-mode" },
+ { GIMP_FG_TRANSPARENT_MODE, "GIMP_FG_TRANSPARENT_MODE", "fg-transparent-mode" },
+ { GIMP_CUSTOM_MODE, "GIMP_CUSTOM_MODE", "custom-mode" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_FG_BG_RGB_MODE, "GIMP_FG_BG_RGB_MODE", NULL },
+ { GIMP_FG_BG_HSV_MODE, "GIMP_FG_BG_HSV_MODE", NULL },
+ { GIMP_FG_TRANSPARENT_MODE, "GIMP_FG_TRANSPARENT_MODE", NULL },
+ { GIMP_CUSTOM_MODE, "GIMP_CUSTOM_MODE", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpBlendModeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "blend-mode-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_bucket_fill_mode_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_FG_BUCKET_FILL, "GIMP_FG_BUCKET_FILL", "fg-bucket-fill" },
+ { GIMP_BG_BUCKET_FILL, "GIMP_BG_BUCKET_FILL", "bg-bucket-fill" },
+ { GIMP_PATTERN_BUCKET_FILL, "GIMP_PATTERN_BUCKET_FILL", "pattern-bucket-fill" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_FG_BUCKET_FILL, "GIMP_FG_BUCKET_FILL", NULL },
+ { GIMP_BG_BUCKET_FILL, "GIMP_BG_BUCKET_FILL", NULL },
+ { GIMP_PATTERN_BUCKET_FILL, "GIMP_PATTERN_BUCKET_FILL", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpBucketFillModeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "bucket-fill-mode-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_channel_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_RED_CHANNEL, "GIMP_RED_CHANNEL", "red-channel" },
+ { GIMP_GREEN_CHANNEL, "GIMP_GREEN_CHANNEL", "green-channel" },
+ { GIMP_BLUE_CHANNEL, "GIMP_BLUE_CHANNEL", "blue-channel" },
+ { GIMP_GRAY_CHANNEL, "GIMP_GRAY_CHANNEL", "gray-channel" },
+ { GIMP_INDEXED_CHANNEL, "GIMP_INDEXED_CHANNEL", "indexed-channel" },
+ { GIMP_ALPHA_CHANNEL, "GIMP_ALPHA_CHANNEL", "alpha-channel" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_RED_CHANNEL, "GIMP_RED_CHANNEL", NULL },
+ { GIMP_GREEN_CHANNEL, "GIMP_GREEN_CHANNEL", NULL },
+ { GIMP_BLUE_CHANNEL, "GIMP_BLUE_CHANNEL", NULL },
+ { GIMP_GRAY_CHANNEL, "GIMP_GRAY_CHANNEL", NULL },
+ { GIMP_INDEXED_CHANNEL, "GIMP_INDEXED_CHANNEL", NULL },
+ { GIMP_ALPHA_CHANNEL, "GIMP_ALPHA_CHANNEL", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpChannelTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "channel-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_clone_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_IMAGE_CLONE, "GIMP_IMAGE_CLONE", "image-clone" },
+ { GIMP_PATTERN_CLONE, "GIMP_PATTERN_CLONE", "pattern-clone" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_IMAGE_CLONE, "GIMP_IMAGE_CLONE", NULL },
+ { GIMP_PATTERN_CLONE, "GIMP_PATTERN_CLONE", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpCloneTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "clone-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_convert_dither_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_NO_DITHER, "GIMP_NO_DITHER", "no-dither" },
+ { GIMP_FS_DITHER, "GIMP_FS_DITHER", "fs-dither" },
+ { GIMP_FSLOWBLEED_DITHER, "GIMP_FSLOWBLEED_DITHER", "fslowbleed-dither" },
+ { GIMP_FIXED_DITHER, "GIMP_FIXED_DITHER", "fixed-dither" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_NO_DITHER, "GIMP_NO_DITHER", NULL },
+ { GIMP_FS_DITHER, "GIMP_FS_DITHER", NULL },
+ { GIMP_FSLOWBLEED_DITHER, "GIMP_FSLOWBLEED_DITHER", NULL },
+ { GIMP_FIXED_DITHER, "GIMP_FIXED_DITHER", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpConvertDitherTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "convert-dither-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_convert_palette_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_MAKE_PALETTE, "GIMP_MAKE_PALETTE", "make-palette" },
+ { GIMP_REUSE_PALETTE, "GIMP_REUSE_PALETTE", "reuse-palette" },
+ { GIMP_WEB_PALETTE, "GIMP_WEB_PALETTE", "web-palette" },
+ { GIMP_MONO_PALETTE, "GIMP_MONO_PALETTE", "mono-palette" },
+ { GIMP_CUSTOM_PALETTE, "GIMP_CUSTOM_PALETTE", "custom-palette" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_MAKE_PALETTE, "GIMP_MAKE_PALETTE", NULL },
+ { GIMP_REUSE_PALETTE, "GIMP_REUSE_PALETTE", NULL },
+ { GIMP_WEB_PALETTE, "GIMP_WEB_PALETTE", NULL },
+ { GIMP_MONO_PALETTE, "GIMP_MONO_PALETTE", NULL },
+ { GIMP_CUSTOM_PALETTE, "GIMP_CUSTOM_PALETTE", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpConvertPaletteTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "convert-palette-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_convolve_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_BLUR_CONVOLVE, "GIMP_BLUR_CONVOLVE", "blur-convolve" },
+ { GIMP_SHARPEN_CONVOLVE, "GIMP_SHARPEN_CONVOLVE", "sharpen-convolve" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_BLUR_CONVOLVE, "GIMP_BLUR_CONVOLVE", NULL },
+ { GIMP_SHARPEN_CONVOLVE, "GIMP_SHARPEN_CONVOLVE", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpConvolveTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "convolve-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_desaturate_mode_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_DESATURATE_LUMINOSITY, "GIMP_DESATURATE_LUMINOSITY", "luminosity" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_DESATURATE_LUMINOSITY, "GIMP_DESATURATE_LUMINOSITY", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpDesaturateModeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "desaturate-mode-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_dodge_burn_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_DODGE, "GIMP_DODGE", "dodge" },
+ { GIMP_BURN, "GIMP_BURN", "burn" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_DODGE, "GIMP_DODGE", NULL },
+ { GIMP_BURN, "GIMP_BURN", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpDodgeBurnTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "dodge-burn-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_fill_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_FOREGROUND_FILL, "GIMP_FOREGROUND_FILL", "foreground-fill" },
+ { GIMP_BACKGROUND_FILL, "GIMP_BACKGROUND_FILL", "background-fill" },
+ { GIMP_WHITE_FILL, "GIMP_WHITE_FILL", "white-fill" },
+ { GIMP_TRANSPARENT_FILL, "GIMP_TRANSPARENT_FILL", "transparent-fill" },
+ { GIMP_PATTERN_FILL, "GIMP_PATTERN_FILL", "pattern-fill" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_FOREGROUND_FILL, "GIMP_FOREGROUND_FILL", NULL },
+ { GIMP_BACKGROUND_FILL, "GIMP_BACKGROUND_FILL", NULL },
+ { GIMP_WHITE_FILL, "GIMP_WHITE_FILL", NULL },
+ { GIMP_TRANSPARENT_FILL, "GIMP_TRANSPARENT_FILL", NULL },
+ { GIMP_PATTERN_FILL, "GIMP_PATTERN_FILL", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpFillTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "fill-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_hue_range_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_ALL_HUES, "GIMP_ALL_HUES", "all-hues" },
+ { GIMP_RED_HUES, "GIMP_RED_HUES", "red-hues" },
+ { GIMP_YELLOW_HUES, "GIMP_YELLOW_HUES", "yellow-hues" },
+ { GIMP_GREEN_HUES, "GIMP_GREEN_HUES", "green-hues" },
+ { GIMP_CYAN_HUES, "GIMP_CYAN_HUES", "cyan-hues" },
+ { GIMP_BLUE_HUES, "GIMP_BLUE_HUES", "blue-hues" },
+ { GIMP_MAGENTA_HUES, "GIMP_MAGENTA_HUES", "magenta-hues" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_ALL_HUES, "GIMP_ALL_HUES", NULL },
+ { GIMP_RED_HUES, "GIMP_RED_HUES", NULL },
+ { GIMP_YELLOW_HUES, "GIMP_YELLOW_HUES", NULL },
+ { GIMP_GREEN_HUES, "GIMP_GREEN_HUES", NULL },
+ { GIMP_CYAN_HUES, "GIMP_CYAN_HUES", NULL },
+ { GIMP_BLUE_HUES, "GIMP_BLUE_HUES", NULL },
+ { GIMP_MAGENTA_HUES, "GIMP_MAGENTA_HUES", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpHueRangeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "hue-range-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_icon_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_ICON_TYPE_STOCK_ID, "GIMP_ICON_TYPE_STOCK_ID", "id" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_ICON_TYPE_STOCK_ID, "GIMP_ICON_TYPE_STOCK_ID", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpIconTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "icon-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_interpolation_type_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_INTERPOLATION_LANCZOS, "GIMP_INTERPOLATION_LANCZOS", "lanczos" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_INTERPOLATION_LANCZOS, "GIMP_INTERPOLATION_LANCZOS", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpInterpolationTypeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "interpolation-type-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_layer_mode_effects_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_NORMAL_MODE, "GIMP_NORMAL_MODE", "normal-mode" },
+ { GIMP_DISSOLVE_MODE, "GIMP_DISSOLVE_MODE", "dissolve-mode" },
+ { GIMP_BEHIND_MODE, "GIMP_BEHIND_MODE", "behind-mode" },
+ { GIMP_MULTIPLY_MODE, "GIMP_MULTIPLY_MODE", "multiply-mode" },
+ { GIMP_SCREEN_MODE, "GIMP_SCREEN_MODE", "screen-mode" },
+ { GIMP_OVERLAY_MODE, "GIMP_OVERLAY_MODE", "overlay-mode" },
+ { GIMP_DIFFERENCE_MODE, "GIMP_DIFFERENCE_MODE", "difference-mode" },
+ { GIMP_ADDITION_MODE, "GIMP_ADDITION_MODE", "addition-mode" },
+ { GIMP_SUBTRACT_MODE, "GIMP_SUBTRACT_MODE", "subtract-mode" },
+ { GIMP_DARKEN_ONLY_MODE, "GIMP_DARKEN_ONLY_MODE", "darken-only-mode" },
+ { GIMP_LIGHTEN_ONLY_MODE, "GIMP_LIGHTEN_ONLY_MODE", "lighten-only-mode" },
+ { GIMP_HUE_MODE, "GIMP_HUE_MODE", "hue-mode" },
+ { GIMP_SATURATION_MODE, "GIMP_SATURATION_MODE", "saturation-mode" },
+ { GIMP_COLOR_MODE, "GIMP_COLOR_MODE", "color-mode" },
+ { GIMP_VALUE_MODE, "GIMP_VALUE_MODE", "value-mode" },
+ { GIMP_DIVIDE_MODE, "GIMP_DIVIDE_MODE", "divide-mode" },
+ { GIMP_DODGE_MODE, "GIMP_DODGE_MODE", "dodge-mode" },
+ { GIMP_BURN_MODE, "GIMP_BURN_MODE", "burn-mode" },
+ { GIMP_HARDLIGHT_MODE, "GIMP_HARDLIGHT_MODE", "hardlight-mode" },
+ { GIMP_SOFTLIGHT_MODE, "GIMP_SOFTLIGHT_MODE", "softlight-mode" },
+ { GIMP_GRAIN_EXTRACT_MODE, "GIMP_GRAIN_EXTRACT_MODE", "grain-extract-mode" },
+ { GIMP_GRAIN_MERGE_MODE, "GIMP_GRAIN_MERGE_MODE", "grain-merge-mode" },
+ { GIMP_COLOR_ERASE_MODE, "GIMP_COLOR_ERASE_MODE", "color-erase-mode" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_NORMAL_MODE, "GIMP_NORMAL_MODE", NULL },
+ { GIMP_DISSOLVE_MODE, "GIMP_DISSOLVE_MODE", NULL },
+ { GIMP_BEHIND_MODE, "GIMP_BEHIND_MODE", NULL },
+ { GIMP_MULTIPLY_MODE, "GIMP_MULTIPLY_MODE", NULL },
+ { GIMP_SCREEN_MODE, "GIMP_SCREEN_MODE", NULL },
+ { GIMP_OVERLAY_MODE, "GIMP_OVERLAY_MODE", NULL },
+ { GIMP_DIFFERENCE_MODE, "GIMP_DIFFERENCE_MODE", NULL },
+ { GIMP_ADDITION_MODE, "GIMP_ADDITION_MODE", NULL },
+ { GIMP_SUBTRACT_MODE, "GIMP_SUBTRACT_MODE", NULL },
+ { GIMP_DARKEN_ONLY_MODE, "GIMP_DARKEN_ONLY_MODE", NULL },
+ { GIMP_LIGHTEN_ONLY_MODE, "GIMP_LIGHTEN_ONLY_MODE", NULL },
+ { GIMP_HUE_MODE, "GIMP_HUE_MODE", NULL },
+ { GIMP_SATURATION_MODE, "GIMP_SATURATION_MODE", NULL },
+ { GIMP_COLOR_MODE, "GIMP_COLOR_MODE", NULL },
+ { GIMP_VALUE_MODE, "GIMP_VALUE_MODE", NULL },
+ { GIMP_DIVIDE_MODE, "GIMP_DIVIDE_MODE", NULL },
+ { GIMP_DODGE_MODE, "GIMP_DODGE_MODE", NULL },
+ { GIMP_BURN_MODE, "GIMP_BURN_MODE", NULL },
+ { GIMP_HARDLIGHT_MODE, "GIMP_HARDLIGHT_MODE", NULL },
+ { GIMP_SOFTLIGHT_MODE, "GIMP_SOFTLIGHT_MODE", NULL },
+ { GIMP_GRAIN_EXTRACT_MODE, "GIMP_GRAIN_EXTRACT_MODE", NULL },
+ { GIMP_GRAIN_MERGE_MODE, "GIMP_GRAIN_MERGE_MODE", NULL },
+ { GIMP_COLOR_ERASE_MODE, "GIMP_COLOR_ERASE_MODE", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpLayerModeEffects", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "layer-mode-effects");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
+gimp_transfer_mode_compat_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_SHADOWS, "GIMP_SHADOWS", "shadows" },
+ { GIMP_MIDTONES, "GIMP_MIDTONES", "midtones" },
+ { GIMP_HIGHLIGHTS, "GIMP_HIGHLIGHTS", "highlights" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_SHADOWS, "GIMP_SHADOWS", NULL },
+ { GIMP_MIDTONES, "GIMP_MIDTONES", NULL },
+ { GIMP_HIGHLIGHTS, "GIMP_HIGHLIGHTS", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTransferModeCompat", values);
+ gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+ gimp_type_set_translation_context (type, "transfer-mode-compat");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+
+/* Generated data ends here */
+
diff --git a/libgimpbase/gimpcompatenums.h b/libgimpbase/gimpcompatenums.h
new file mode 100644
index 0000000..173dee9
--- /dev/null
+++ b/libgimpbase/gimpcompatenums.h
@@ -0,0 +1,252 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_COMPAT_ENUMS_H__
+#define __GIMP_COMPAT_ENUMS_H__
+
+
+G_BEGIN_DECLS
+
+/* These enums exist only for compatibility, their nicks are needed
+ * for config file parsing; they are registered in gimp_base_init().
+ */
+
+
+#define GIMP_TYPE_ADD_MASK_TYPE_COMPAT (gimp_add_mask_type_compat_get_type ())
+
+GType gimp_add_mask_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_ADD_WHITE_MASK = GIMP_ADD_MASK_WHITE,
+ GIMP_ADD_BLACK_MASK = GIMP_ADD_MASK_BLACK,
+ GIMP_ADD_ALPHA_MASK = GIMP_ADD_MASK_ALPHA,
+ GIMP_ADD_ALPHA_TRANSFER_MASK = GIMP_ADD_MASK_ALPHA_TRANSFER,
+ GIMP_ADD_SELECTION_MASK = GIMP_ADD_MASK_SELECTION,
+ GIMP_ADD_COPY_MASK = GIMP_ADD_MASK_COPY,
+ GIMP_ADD_CHANNEL_MASK = GIMP_ADD_MASK_CHANNEL
+} GimpAddMaskTypeCompat;
+
+
+#define GIMP_TYPE_BLEND_MODE_COMPAT (gimp_blend_mode_compat_get_type ())
+
+GType gimp_blend_mode_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_FG_BG_RGB_MODE = GIMP_BLEND_FG_BG_RGB,
+ GIMP_FG_BG_HSV_MODE = GIMP_BLEND_FG_BG_HSV,
+ GIMP_FG_TRANSPARENT_MODE = GIMP_BLEND_FG_TRANSPARENT,
+ GIMP_CUSTOM_MODE = GIMP_BLEND_CUSTOM
+} GimpBlendModeCompat;
+
+
+#define GIMP_TYPE_BUCKET_FILL_MODE_COMPAT (gimp_bucket_fill_mode_compat_get_type ())
+
+GType gimp_bucket_fill_mode_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_FG_BUCKET_FILL = GIMP_BUCKET_FILL_FG,
+ GIMP_BG_BUCKET_FILL = GIMP_BUCKET_FILL_BG,
+ GIMP_PATTERN_BUCKET_FILL = GIMP_BUCKET_FILL_PATTERN
+} GimpBucketFillModeCompat;
+
+
+#define GIMP_TYPE_CHANNEL_TYPE_COMPAT (gimp_channel_type_compat_get_type ())
+
+GType gimp_channel_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_RED_CHANNEL = GIMP_CHANNEL_RED,
+ GIMP_GREEN_CHANNEL = GIMP_CHANNEL_GREEN,
+ GIMP_BLUE_CHANNEL = GIMP_CHANNEL_BLUE,
+ GIMP_GRAY_CHANNEL = GIMP_CHANNEL_GRAY,
+ GIMP_INDEXED_CHANNEL = GIMP_CHANNEL_INDEXED,
+ GIMP_ALPHA_CHANNEL = GIMP_CHANNEL_ALPHA
+} GimpChannelTypeCompat;
+
+
+#define GIMP_TYPE_CLONE_TYPE_COMPAT (gimp_clone_type_compat_get_type ())
+
+GType gimp_clone_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_IMAGE_CLONE = GIMP_CLONE_IMAGE,
+ GIMP_PATTERN_CLONE = GIMP_CLONE_PATTERN
+} GimpCloneTypeCompat;
+
+
+#define GIMP_TYPE_CONVERT_DITHER_TYPE_COMPAT (gimp_convert_dither_type_compat_get_type ())
+
+GType gimp_convert_dither_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_NO_DITHER,
+ GIMP_FS_DITHER,
+ GIMP_FSLOWBLEED_DITHER,
+ GIMP_FIXED_DITHER
+} GimpConvertDitherTypeCompat;
+
+
+#define GIMP_TYPE_CONVERT_PALETTE_TYPE_COMPAT (gimp_convert_palette_type_compat_get_type ())
+
+GType gimp_convert_palette_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_MAKE_PALETTE,
+ GIMP_REUSE_PALETTE,
+ GIMP_WEB_PALETTE,
+ GIMP_MONO_PALETTE,
+ GIMP_CUSTOM_PALETTE
+} GimpConvertPaletteTypeCompat;
+
+
+#define GIMP_TYPE_CONVOLVE_TYPE_COMPAT (gimp_convolve_type_compat_get_type ())
+
+GType gimp_convolve_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_BLUR_CONVOLVE = GIMP_CONVOLVE_BLUR,
+ GIMP_SHARPEN_CONVOLVE = GIMP_CONVOLVE_SHARPEN
+} GimpConvolveTypeCompat;
+
+
+#define GIMP_TYPE_DESATURATE_MODE_COMPAT (gimp_desaturate_mode_compat_get_type ())
+
+GType gimp_desaturate_mode_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_DESATURATE_LUMINOSITY = GIMP_DESATURATE_LUMA
+} GimpDesaturateModeCompat;
+
+
+#define GIMP_TYPE_DODGE_BURN_TYPE_COMPAT (gimp_dodge_burn_type_compat_get_type ())
+
+GType gimp_dodge_burn_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_DODGE = GIMP_DODGE_BURN_TYPE_DODGE,
+ GIMP_BURN = GIMP_DODGE_BURN_TYPE_BURN
+} GimpDodgeBurnTypeCompat;
+
+
+#define GIMP_TYPE_FILL_TYPE_COMPAT (gimp_fill_type_compat_get_type ())
+
+GType gimp_fill_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_FOREGROUND_FILL = GIMP_FILL_FOREGROUND,
+ GIMP_BACKGROUND_FILL = GIMP_FILL_BACKGROUND,
+ GIMP_WHITE_FILL = GIMP_FILL_WHITE,
+ GIMP_TRANSPARENT_FILL = GIMP_FILL_TRANSPARENT,
+ GIMP_PATTERN_FILL = GIMP_FILL_PATTERN
+} GimpFillTypeCompat;
+
+
+#define GIMP_TYPE_HUE_RANGE_COMPAT (gimp_hue_range_compat_get_type ())
+
+GType gimp_hue_range_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_ALL_HUES = GIMP_HUE_RANGE_ALL,
+ GIMP_RED_HUES = GIMP_HUE_RANGE_RED,
+ GIMP_YELLOW_HUES = GIMP_HUE_RANGE_YELLOW,
+ GIMP_GREEN_HUES = GIMP_HUE_RANGE_GREEN,
+ GIMP_CYAN_HUES = GIMP_HUE_RANGE_CYAN,
+ GIMP_BLUE_HUES = GIMP_HUE_RANGE_BLUE,
+ GIMP_MAGENTA_HUES = GIMP_HUE_RANGE_MAGENTA
+} GimpHueRangeCompat;
+
+
+#define GIMP_TYPE_ICON_TYPE_COMPAT (gimp_icon_type_compat_get_type ())
+
+GType gimp_icon_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_ICON_TYPE_STOCK_ID = GIMP_ICON_TYPE_ICON_NAME
+} GimpIconTypeCompat;
+
+
+#define GIMP_TYPE_INTERPOLATION_TYPE_COMPAT (gimp_interpolation_type_compat_get_type ())
+
+GType gimp_interpolation_type_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_INTERPOLATION_LANCZOS = GIMP_INTERPOLATION_NOHALO
+} GimpInterpolationTypeCompat;
+
+
+#define GIMP_TYPE_LAYER_MODE_EFFECTS (gimp_layer_mode_effects_get_type ())
+
+GType gimp_layer_mode_effects_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_NORMAL_MODE,
+ GIMP_DISSOLVE_MODE,
+ GIMP_BEHIND_MODE,
+ GIMP_MULTIPLY_MODE,
+ GIMP_SCREEN_MODE,
+ GIMP_OVERLAY_MODE,
+ GIMP_DIFFERENCE_MODE,
+ GIMP_ADDITION_MODE,
+ GIMP_SUBTRACT_MODE,
+ GIMP_DARKEN_ONLY_MODE,
+ GIMP_LIGHTEN_ONLY_MODE,
+ GIMP_HUE_MODE,
+ GIMP_SATURATION_MODE,
+ GIMP_COLOR_MODE,
+ GIMP_VALUE_MODE,
+ GIMP_DIVIDE_MODE,
+ GIMP_DODGE_MODE,
+ GIMP_BURN_MODE,
+ GIMP_HARDLIGHT_MODE,
+ GIMP_SOFTLIGHT_MODE,
+ GIMP_GRAIN_EXTRACT_MODE,
+ GIMP_GRAIN_MERGE_MODE,
+ GIMP_COLOR_ERASE_MODE
+} GimpLayerModeEffects;
+
+
+#define GIMP_TYPE_TRANSFER_MODE_COMPAT (gimp_transfer_mode_compat_get_type ())
+
+GType gimp_transfer_mode_compat_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_SHADOWS = GIMP_TRANSFER_SHADOWS,
+ GIMP_MIDTONES = GIMP_TRANSFER_MIDTONES,
+ GIMP_HIGHLIGHTS = GIMP_TRANSFER_HIGHLIGHTS
+} GimpTransferModeCompat;
+
+
+G_END_DECLS
+
+#endif /* __GIMP_COMPAT_ENUMS_H__ */
diff --git a/libgimpbase/gimpcpuaccel.c b/libgimpbase/gimpcpuaccel.c
new file mode 100644
index 0000000..86a2d49
--- /dev/null
+++ b/libgimpbase/gimpcpuaccel.c
@@ -0,0 +1,531 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ * x86 bits Copyright (C) Manish Singh <yosh@gimp.org>
+ */
+
+/*
+ * PPC CPU acceleration detection was taken from DirectFB but seems to be
+ * originating from mpeg2dec with the following copyright:
+ *
+ * Copyright (C) 1999-2001 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#include <glib.h>
+
+#include "gimpcpuaccel.h"
+
+
+/**
+ * SECTION: gimpcpuaccel
+ * @title: gimpcpuaccel
+ * @short_description: Functions to query and configure CPU acceleration.
+ *
+ * Functions to query and configure CPU acceleration.
+ **/
+
+
+static GimpCpuAccelFlags cpu_accel (void) G_GNUC_CONST;
+
+
+static gboolean use_cpu_accel = TRUE;
+
+
+/**
+ * gimp_cpu_accel_get_support:
+ *
+ * Query for CPU acceleration support.
+ *
+ * Return value: #GimpCpuAccelFlags as supported by the CPU.
+ *
+ * Since: 2.4
+ */
+GimpCpuAccelFlags
+gimp_cpu_accel_get_support (void)
+{
+ return use_cpu_accel ? cpu_accel () : GIMP_CPU_ACCEL_NONE;
+}
+
+/**
+ * gimp_cpu_accel_set_use:
+ * @use: whether to use CPU acceleration features or not
+ *
+ * This function is for internal use only.
+ *
+ * Since: 2.4
+ */
+void
+gimp_cpu_accel_set_use (gboolean use)
+{
+ use_cpu_accel = use ? TRUE : FALSE;
+}
+
+
+#if defined(ARCH_X86) && defined(USE_MMX) && defined(__GNUC__)
+
+#define HAVE_ACCEL 1
+
+
+typedef enum
+{
+ ARCH_X86_VENDOR_NONE,
+ ARCH_X86_VENDOR_INTEL,
+ ARCH_X86_VENDOR_AMD,
+ ARCH_X86_VENDOR_CENTAUR,
+ ARCH_X86_VENDOR_CYRIX,
+ ARCH_X86_VENDOR_NSC,
+ ARCH_X86_VENDOR_TRANSMETA,
+ ARCH_X86_VENDOR_NEXGEN,
+ ARCH_X86_VENDOR_RISE,
+ ARCH_X86_VENDOR_UMC,
+ ARCH_X86_VENDOR_SIS,
+ ARCH_X86_VENDOR_HYGON,
+ ARCH_X86_VENDOR_UNKNOWN = 0xff
+} X86Vendor;
+
+enum
+{
+ ARCH_X86_INTEL_FEATURE_MMX = 1 << 23,
+ ARCH_X86_INTEL_FEATURE_XMM = 1 << 25,
+ ARCH_X86_INTEL_FEATURE_XMM2 = 1 << 26,
+
+ ARCH_X86_AMD_FEATURE_MMXEXT = 1 << 22,
+ ARCH_X86_AMD_FEATURE_3DNOW = 1 << 31,
+
+ ARCH_X86_CENTAUR_FEATURE_MMX = 1 << 23,
+ ARCH_X86_CENTAUR_FEATURE_MMXEXT = 1 << 24,
+ ARCH_X86_CENTAUR_FEATURE_3DNOW = 1 << 31,
+
+ ARCH_X86_CYRIX_FEATURE_MMX = 1 << 23,
+ ARCH_X86_CYRIX_FEATURE_MMXEXT = 1 << 24
+};
+
+enum
+{
+ ARCH_X86_INTEL_FEATURE_PNI = 1 << 0,
+ ARCH_X86_INTEL_FEATURE_SSSE3 = 1 << 9,
+ ARCH_X86_INTEL_FEATURE_SSE4_1 = 1 << 19,
+ ARCH_X86_INTEL_FEATURE_SSE4_2 = 1 << 20,
+ ARCH_X86_INTEL_FEATURE_AVX = 1 << 28
+};
+
+#if !defined(ARCH_X86_64) && (defined(PIC) || defined(__PIC__))
+#define cpuid(op,eax,ebx,ecx,edx) \
+ __asm__ ("movl %%ebx, %%esi\n\t" \
+ "cpuid\n\t" \
+ "xchgl %%ebx,%%esi" \
+ : "=a" (eax), \
+ "=S" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "0" (op))
+#else
+#define cpuid(op,eax,ebx,ecx,edx) \
+ __asm__ ("cpuid" \
+ : "=a" (eax), \
+ "=b" (ebx), \
+ "=c" (ecx), \
+ "=d" (edx) \
+ : "0" (op))
+#endif
+
+
+static X86Vendor
+arch_get_vendor (void)
+{
+ guint32 eax, ebx, ecx, edx;
+ union{
+ gchar idaschar[16];
+ int idasint[4];
+ }id;
+
+#ifndef ARCH_X86_64
+ /* Only need to check this on ia32 */
+ __asm__ ("pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl $0x200000,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl"
+ : "=a" (eax),
+ "=c" (ecx)
+ :
+ : "cc");
+
+ if (eax == ecx)
+ return ARCH_X86_VENDOR_NONE;
+#endif
+
+ cpuid (0, eax, ebx, ecx, edx);
+
+ if (eax == 0)
+ return ARCH_X86_VENDOR_NONE;
+
+ id.idasint[0] = ebx;
+ id.idasint[1] = edx;
+ id.idasint[2] = ecx;
+
+ id.idaschar[12] = '\0';
+
+#ifdef ARCH_X86_64
+ if (strcmp (id.idaschar, "AuthenticAMD") == 0)
+ return ARCH_X86_VENDOR_AMD;
+ else if (strcmp (id.idaschar, "HygonGenuine") == 0)
+ return ARCH_X86_VENDOR_HYGON;
+ else if (strcmp (id.idaschar, "GenuineIntel") == 0)
+ return ARCH_X86_VENDOR_INTEL;
+#else
+ if (strcmp (id.idaschar, "GenuineIntel") == 0)
+ return ARCH_X86_VENDOR_INTEL;
+ else if (strcmp (id.idaschar, "AuthenticAMD") == 0)
+ return ARCH_X86_VENDOR_AMD;
+ else if (strcmp (id.idaschar, "HygonGenuine") == 0)
+ return ARCH_X86_VENDOR_HYGON;
+ else if (strcmp (id.idaschar, "CentaurHauls") == 0)
+ return ARCH_X86_VENDOR_CENTAUR;
+ else if (strcmp (id.idaschar, "CyrixInstead") == 0)
+ return ARCH_X86_VENDOR_CYRIX;
+ else if (strcmp (id.idaschar, "Geode by NSC") == 0)
+ return ARCH_X86_VENDOR_NSC;
+ else if (strcmp (id.idaschar, "GenuineTMx86") == 0 ||
+ strcmp (id.idaschar, "TransmetaCPU") == 0)
+ return ARCH_X86_VENDOR_TRANSMETA;
+ else if (strcmp (id.idaschar, "NexGenDriven") == 0)
+ return ARCH_X86_VENDOR_NEXGEN;
+ else if (strcmp (id.idaschar, "RiseRiseRise") == 0)
+ return ARCH_X86_VENDOR_RISE;
+ else if (strcmp (id.idaschar, "UMC UMC UMC ") == 0)
+ return ARCH_X86_VENDOR_UMC;
+ else if (strcmp (id.idaschar, "SiS SiS SiS ") == 0)
+ return ARCH_X86_VENDOR_SIS;
+#endif
+
+ return ARCH_X86_VENDOR_UNKNOWN;
+}
+
+static guint32
+arch_accel_intel (void)
+{
+ guint32 caps = 0;
+
+#ifdef USE_MMX
+ {
+ guint32 eax, ebx, ecx, edx;
+
+ cpuid (1, eax, ebx, ecx, edx);
+
+ if ((edx & ARCH_X86_INTEL_FEATURE_MMX) == 0)
+ return 0;
+
+ caps = GIMP_CPU_ACCEL_X86_MMX;
+
+#ifdef USE_SSE
+ if (edx & ARCH_X86_INTEL_FEATURE_XMM)
+ caps |= GIMP_CPU_ACCEL_X86_SSE | GIMP_CPU_ACCEL_X86_MMXEXT;
+
+ if (edx & ARCH_X86_INTEL_FEATURE_XMM2)
+ caps |= GIMP_CPU_ACCEL_X86_SSE2;
+
+ if (ecx & ARCH_X86_INTEL_FEATURE_PNI)
+ caps |= GIMP_CPU_ACCEL_X86_SSE3;
+
+ if (ecx & ARCH_X86_INTEL_FEATURE_SSSE3)
+ caps |= GIMP_CPU_ACCEL_X86_SSSE3;
+
+ if (ecx & ARCH_X86_INTEL_FEATURE_SSE4_1)
+ caps |= GIMP_CPU_ACCEL_X86_SSE4_1;
+
+ if (ecx & ARCH_X86_INTEL_FEATURE_SSE4_2)
+ caps |= GIMP_CPU_ACCEL_X86_SSE4_2;
+
+ if (ecx & ARCH_X86_INTEL_FEATURE_AVX)
+ caps |= GIMP_CPU_ACCEL_X86_AVX;
+#endif /* USE_SSE */
+ }
+#endif /* USE_MMX */
+
+ return caps;
+}
+
+static guint32
+arch_accel_amd (void)
+{
+ guint32 caps;
+
+ caps = arch_accel_intel ();
+
+#ifdef USE_MMX
+ {
+ guint32 eax, ebx, ecx, edx;
+
+ cpuid (0x80000000, eax, ebx, ecx, edx);
+
+ if (eax < 0x80000001)
+ return caps;
+
+#ifdef USE_SSE
+ cpuid (0x80000001, eax, ebx, ecx, edx);
+
+ if (edx & ARCH_X86_AMD_FEATURE_3DNOW)
+ caps |= GIMP_CPU_ACCEL_X86_3DNOW;
+
+ if (edx & ARCH_X86_AMD_FEATURE_MMXEXT)
+ caps |= GIMP_CPU_ACCEL_X86_MMXEXT;
+#endif /* USE_SSE */
+ }
+#endif /* USE_MMX */
+
+ return caps;
+}
+
+static guint32
+arch_accel_centaur (void)
+{
+ guint32 caps;
+
+ caps = arch_accel_intel ();
+
+#ifdef USE_MMX
+ {
+ guint32 eax, ebx, ecx, edx;
+
+ cpuid (0x80000000, eax, ebx, ecx, edx);
+
+ if (eax < 0x80000001)
+ return caps;
+
+ cpuid (0x80000001, eax, ebx, ecx, edx);
+
+ if (edx & ARCH_X86_CENTAUR_FEATURE_MMX)
+ caps |= GIMP_CPU_ACCEL_X86_MMX;
+
+#ifdef USE_SSE
+ if (edx & ARCH_X86_CENTAUR_FEATURE_3DNOW)
+ caps |= GIMP_CPU_ACCEL_X86_3DNOW;
+
+ if (edx & ARCH_X86_CENTAUR_FEATURE_MMXEXT)
+ caps |= GIMP_CPU_ACCEL_X86_MMXEXT;
+#endif /* USE_SSE */
+ }
+#endif /* USE_MMX */
+
+ return caps;
+}
+
+static guint32
+arch_accel_cyrix (void)
+{
+ guint32 caps;
+
+ caps = arch_accel_intel ();
+
+#ifdef USE_MMX
+ {
+ guint32 eax, ebx, ecx, edx;
+
+ cpuid (0, eax, ebx, ecx, edx);
+
+ if (eax != 2)
+ return caps;
+
+ cpuid (0x80000001, eax, ebx, ecx, edx);
+
+ if (edx & ARCH_X86_CYRIX_FEATURE_MMX)
+ caps |= GIMP_CPU_ACCEL_X86_MMX;
+
+#ifdef USE_SSE
+ if (edx & ARCH_X86_CYRIX_FEATURE_MMXEXT)
+ caps |= GIMP_CPU_ACCEL_X86_MMXEXT;
+#endif /* USE_SSE */
+ }
+#endif /* USE_MMX */
+
+ return caps;
+}
+
+#ifdef USE_SSE
+static jmp_buf sigill_return;
+
+static void
+sigill_handler (gint n)
+{
+ longjmp (sigill_return, 1);
+}
+
+static gboolean
+arch_accel_sse_os_support (void)
+{
+ if (setjmp (sigill_return))
+ {
+ return FALSE;
+ }
+ else
+ {
+ signal (SIGILL, sigill_handler);
+ __asm__ __volatile__ ("xorps %xmm0, %xmm0");
+ signal (SIGILL, SIG_DFL);
+ }
+
+ return TRUE;
+}
+#endif /* USE_SSE */
+
+static guint32
+arch_accel (void)
+{
+ guint32 caps;
+ X86Vendor vendor;
+
+ vendor = arch_get_vendor ();
+
+ switch (vendor)
+ {
+ case ARCH_X86_VENDOR_NONE:
+ caps = 0;
+ break;
+
+ case ARCH_X86_VENDOR_AMD:
+ case ARCH_X86_VENDOR_HYGON:
+ caps = arch_accel_amd ();
+ break;
+
+ case ARCH_X86_VENDOR_CENTAUR:
+ caps = arch_accel_centaur ();
+ break;
+
+ case ARCH_X86_VENDOR_CYRIX:
+ case ARCH_X86_VENDOR_NSC:
+ caps = arch_accel_cyrix ();
+ break;
+
+ /* check for what Intel speced, even if UNKNOWN */
+ default:
+ caps = arch_accel_intel ();
+ break;
+ }
+
+#ifdef USE_SSE
+ if ((caps & GIMP_CPU_ACCEL_X86_SSE) && !arch_accel_sse_os_support ())
+ caps &= ~(GIMP_CPU_ACCEL_X86_SSE | GIMP_CPU_ACCEL_X86_SSE2);
+#endif
+
+ return caps;
+}
+
+#endif /* ARCH_X86 && USE_MMX && __GNUC__ */
+
+
+#if defined(ARCH_PPC) && defined (USE_ALTIVEC)
+
+#if defined(HAVE_ALTIVEC_SYSCTL)
+
+#include <sys/sysctl.h>
+
+#define HAVE_ACCEL 1
+
+static guint32
+arch_accel (void)
+{
+ gint sels[2] = { CTL_HW, HW_VECTORUNIT };
+ gboolean has_vu = FALSE;
+ gsize length = sizeof(has_vu);
+ gint err;
+
+ err = sysctl (sels, 2, &has_vu, &length, NULL, 0);
+
+ if (err == 0 && has_vu)
+ return GIMP_CPU_ACCEL_PPC_ALTIVEC;
+
+ return 0;
+}
+
+#elif defined(__GNUC__)
+
+#define HAVE_ACCEL 1
+
+static sigjmp_buf jmpbuf;
+static volatile sig_atomic_t canjump = 0;
+
+static void
+sigill_handler (gint sig)
+{
+ if (!canjump)
+ {
+ signal (sig, SIG_DFL);
+ raise (sig);
+ }
+
+ canjump = 0;
+ siglongjmp (jmpbuf, 1);
+}
+
+static guint32
+arch_accel (void)
+{
+ signal (SIGILL, sigill_handler);
+
+ if (sigsetjmp (jmpbuf, 1))
+ {
+ signal (SIGILL, SIG_DFL);
+ return 0;
+ }
+
+ canjump = 1;
+
+ asm volatile ("mtspr 256, %0\n\t"
+ "vand %%v0, %%v0, %%v0"
+ :
+ : "r" (-1));
+
+ signal (SIGILL, SIG_DFL);
+
+ return GIMP_CPU_ACCEL_PPC_ALTIVEC;
+}
+#endif /* __GNUC__ */
+
+#endif /* ARCH_PPC && USE_ALTIVEC */
+
+
+static GimpCpuAccelFlags
+cpu_accel (void)
+{
+#ifdef HAVE_ACCEL
+ static guint32 accel = ~0U;
+
+ if (accel != ~0U)
+ return accel;
+
+ accel = arch_accel ();
+
+ return (GimpCpuAccelFlags) accel;
+
+#else /* !HAVE_ACCEL */
+ return GIMP_CPU_ACCEL_NONE;
+#endif
+}
diff --git a/libgimpbase/gimpcpuaccel.h b/libgimpbase/gimpcpuaccel.h
new file mode 100644
index 0000000..03c0d4b
--- /dev/null
+++ b/libgimpbase/gimpcpuaccel.h
@@ -0,0 +1,76 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_CPU_ACCEL_H__
+#define __GIMP_CPU_ACCEL_H__
+
+G_BEGIN_DECLS
+
+
+/**
+ * GimpCpuAccelFlags:
+ * @GIMP_CPU_ACCEL_NONE: None
+ * @GIMP_CPU_ACCEL_X86_MMX: MMX
+ * @GIMP_CPU_ACCEL_X86_3DNOW: 3dNow
+ * @GIMP_CPU_ACCEL_X86_MMXEXT: MMXEXT
+ * @GIMP_CPU_ACCEL_X86_SSE: SSE
+ * @GIMP_CPU_ACCEL_X86_SSE2: SSE2
+ * @GIMP_CPU_ACCEL_X86_SSE3: SSE3
+ * @GIMP_CPU_ACCEL_X86_SSSE3: SSSE3
+ * @GIMP_CPU_ACCEL_X86_SSE4_1: SSE4_1
+ * @GIMP_CPU_ACCEL_X86_SSE4_2: SSE4_2
+ * @GIMP_CPU_ACCEL_X86_AVX: AVX
+ * @GIMP_CPU_ACCEL_PPC_ALTIVEC: Altivec
+ *
+ * Types of detectable CPU accelerations
+ **/
+typedef enum
+{
+ GIMP_CPU_ACCEL_NONE = 0x0,
+
+ /* x86 accelerations */
+ GIMP_CPU_ACCEL_X86_MMX = 0x80000000,
+ GIMP_CPU_ACCEL_X86_3DNOW = 0x40000000,
+ GIMP_CPU_ACCEL_X86_MMXEXT = 0x20000000,
+ GIMP_CPU_ACCEL_X86_SSE = 0x10000000,
+ GIMP_CPU_ACCEL_X86_SSE2 = 0x08000000,
+ GIMP_CPU_ACCEL_X86_SSE3 = 0x02000000,
+ GIMP_CPU_ACCEL_X86_SSSE3 = 0x01000000,
+ GIMP_CPU_ACCEL_X86_SSE4_1 = 0x00800000,
+ GIMP_CPU_ACCEL_X86_SSE4_2 = 0x00400000,
+ GIMP_CPU_ACCEL_X86_AVX = 0x00200000,
+
+ /* powerpc accelerations */
+ GIMP_CPU_ACCEL_PPC_ALTIVEC = 0x04000000
+} GimpCpuAccelFlags;
+
+
+GimpCpuAccelFlags gimp_cpu_accel_get_support (void);
+
+
+/* for internal use only */
+void gimp_cpu_accel_set_use (gboolean use);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_CPU_ACCEL_H__ */
diff --git a/libgimpbase/gimpdatafiles.c b/libgimpbase/gimpdatafiles.c
new file mode 100644
index 0000000..535f275
--- /dev/null
+++ b/libgimpbase/gimpdatafiles.c
@@ -0,0 +1,225 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * Datafiles module copyight (C) 1996 Federico Mena Quintero
+ * federico@nuclecu.unam.mx
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gio/gio.h>
+
+#include "gimpbasetypes.h"
+
+#include "gimpdatafiles.h"
+#include "gimpenv.h"
+
+
+/**
+ * SECTION: gimpdatafiles
+ * @title: gimpdatafiles
+ * @short_description: Functions to handle GIMP data files.
+ *
+ * Functions to handle GIMP data files.
+ **/
+
+
+static inline gboolean is_script (const gchar *filename);
+
+
+/* public functions */
+
+gboolean
+gimp_datafiles_check_extension (const gchar *filename,
+ const gchar *extension)
+{
+ gint name_len;
+ gint ext_len;
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (extension != NULL, FALSE);
+
+ name_len = strlen (filename);
+ ext_len = strlen (extension);
+
+ if (! (name_len && ext_len && (name_len > ext_len)))
+ return FALSE;
+
+ return (g_ascii_strcasecmp (&filename[name_len - ext_len], extension) == 0);
+}
+
+void
+gimp_datafiles_read_directories (const gchar *path_str,
+ GFileTest flags,
+ GimpDatafileLoaderFunc loader_func,
+ gpointer user_data)
+{
+ gchar *local_path;
+ GList *path;
+ GList *list;
+
+ g_return_if_fail (path_str != NULL);
+ g_return_if_fail (loader_func != NULL);
+
+ local_path = g_strdup (path_str);
+
+ path = gimp_path_parse (local_path, 256, TRUE, NULL);
+
+ for (list = path; list; list = g_list_next (list))
+ {
+ const gchar *dirname = list->data;
+ GDir *dir;
+
+ dir = g_dir_open (dirname, 0, NULL);
+
+ if (dir)
+ {
+ const gchar *dir_ent;
+
+ while ((dir_ent = g_dir_read_name (dir)))
+ {
+ gchar *filename;
+ GFile *file;
+ GFileInfo *info;
+
+ filename = g_build_filename (dirname, dir_ent, NULL);
+ file = g_file_new_for_path (filename);
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
+ G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+ G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE ","
+ "time::*",
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+
+ if (info)
+ {
+ GimpDatafileData file_data;
+ GFileType file_type;
+
+ file_data.filename = filename;
+ file_data.dirname = dirname;
+ file_data.basename = dir_ent;
+
+ file_data.atime =
+ g_file_info_get_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_ACCESS);
+
+ file_data.mtime =
+ g_file_info_get_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ file_data.ctime =
+ g_file_info_get_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_TIME_CREATED);
+
+ file_type = g_file_info_get_file_type (info);
+
+ if (g_file_info_get_is_hidden (info))
+ {
+ /* do nothing */
+ }
+ else if (flags & G_FILE_TEST_EXISTS)
+ {
+ (* loader_func) (&file_data, user_data);
+ }
+ else if ((flags & G_FILE_TEST_IS_REGULAR) &&
+ (file_type == G_FILE_TYPE_REGULAR))
+ {
+ (* loader_func) (&file_data, user_data);
+ }
+ else if ((flags & G_FILE_TEST_IS_DIR) &&
+ (file_type == G_FILE_TYPE_DIRECTORY))
+ {
+ (* loader_func) (&file_data, user_data);
+ }
+ else if ((flags & G_FILE_TEST_IS_SYMLINK) &&
+ (file_type == G_FILE_TYPE_SYMBOLIC_LINK))
+ {
+ (* loader_func) (&file_data, user_data);
+ }
+ else if ((flags & G_FILE_TEST_IS_EXECUTABLE) &&
+ (g_file_info_get_attribute_boolean (info,
+ G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE) ||
+ ((file_type == G_FILE_TYPE_REGULAR) &&
+ is_script (filename))))
+ {
+ (* loader_func) (&file_data, user_data);
+ }
+
+ g_object_unref (info);
+ }
+
+ g_object_unref (file);
+ g_free (filename);
+ }
+
+ g_dir_close (dir);
+ }
+ }
+
+ gimp_path_free (path);
+ g_free (local_path);
+}
+
+
+/* private functions */
+
+static inline gboolean
+is_script (const gchar *filename)
+{
+#ifdef G_OS_WIN32
+ /* On Windows there is no concept like the Unix executable flag.
+ * There is a weak emulation provided by the MS C Runtime using file
+ * extensions (com, exe, cmd, bat). This needs to be extended to treat
+ * scripts (Python, Perl, ...) as executables, too. We use the PATHEXT
+ * variable, which is also used by cmd.exe.
+ */
+ static gchar **exts = NULL;
+
+ const gchar *ext = strrchr (filename, '.');
+ gchar *pathext;
+ gint i;
+
+ if (exts == NULL)
+ {
+ pathext = (gchar *) g_getenv ("PATHEXT");
+ if (pathext != NULL)
+ {
+ exts = g_strsplit (pathext, G_SEARCHPATH_SEPARATOR_S, 100);
+ }
+ else
+ {
+ exts = g_new (gchar *, 1);
+ exts[0] = NULL;
+ }
+ }
+
+ i = 0;
+ while (exts[i] != NULL)
+ {
+ if (g_ascii_strcasecmp (ext, exts[i]) == 0)
+ return TRUE;
+ i++;
+ }
+#endif /* G_OS_WIN32 */
+
+ return FALSE;
+}
diff --git a/libgimpbase/gimpdatafiles.h b/libgimpbase/gimpdatafiles.h
new file mode 100644
index 0000000..c75edab
--- /dev/null
+++ b/libgimpbase/gimpdatafiles.h
@@ -0,0 +1,72 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * Datafiles module copyight (C) 1996 Federico Mena Quintero
+ * federico@nuclecu.unam.mx
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_DATAFILES_H__
+#define __GIMP_DATAFILES_H__
+
+#include <time.h>
+
+G_BEGIN_DECLS
+
+
+/**
+ * GimpDatafileData:
+ * @filename: the data file's full path.
+ * @dirname: the folder the data file is in.
+ * @basename: the data file's basename.
+ * @atime: the last time the file was accessed for reading.
+ * @mtime: the last time the file was modified.
+ * @ctime: the time the file was created.
+ *
+ * This structure is passed to the #GimpDatafileLoaderFunc given to
+ * gimp_datafiles_read_directories() for each file encountered in the
+ * data path.
+ **/
+struct _GimpDatafileData
+{
+ const gchar *filename;
+ const gchar *dirname;
+ const gchar *basename;
+
+ time_t atime;
+ time_t mtime;
+ time_t ctime;
+};
+
+
+GIMP_DEPRECATED
+gboolean gimp_datafiles_check_extension (const gchar *filename,
+ const gchar *extension);
+
+GIMP_DEPRECATED_FOR(GFileEnumerator)
+void gimp_datafiles_read_directories (const gchar *path_str,
+ GFileTest flags,
+ GimpDatafileLoaderFunc loader_func,
+ gpointer user_data);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_DATAFILES_H__ */
diff --git a/libgimpbase/gimpenv.c b/libgimpbase/gimpenv.c
new file mode 100644
index 0000000..10696a5
--- /dev/null
+++ b/libgimpbase/gimpenv.c
@@ -0,0 +1,1277 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpenv.c
+ * Copyright (C) 1999 Tor Lillqvist <tml@iki.fi>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef PLATFORM_OSX
+#include <AppKit/AppKit.h>
+#endif
+
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+
+#undef GIMP_DISABLE_DEPRECATED
+#include "gimpbasetypes.h"
+
+#define __GIMP_ENV_C__
+#include "gimpenv.h"
+#include "gimpversion.h"
+#include "gimpreloc.h"
+
+#ifdef G_OS_WIN32
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <io.h>
+#ifndef S_IWUSR
+# define S_IWUSR _S_IWRITE
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP (_S_IWRITE>>3)
+#define S_IWOTH (_S_IWRITE>>6)
+#endif
+#ifndef S_ISDIR
+# define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
+# define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
+#endif
+#define uid_t gint
+#define gid_t gint
+#define geteuid() 0
+#define getegid() 0
+
+#include <shlobj.h>
+
+/* Constant available since Shell32.dll 4.72 */
+#ifndef CSIDL_APPDATA
+#define CSIDL_APPDATA 0x001a
+#endif
+
+#endif
+
+
+/**
+ * SECTION: gimpenv
+ * @title: gimpenv
+ * @short_description: Functions to access the GIMP environment.
+ *
+ * A set of functions to find the locations of GIMP's data directories
+ * and configuration files.
+ **/
+
+
+static gchar * gimp_env_get_dir (const gchar *gimp_env_name,
+ const gchar *compile_time_dir,
+ const gchar *relative_subdir);
+#ifdef G_OS_WIN32
+static gchar * get_special_folder (gint csidl);
+#endif
+
+
+const guint gimp_major_version = GIMP_MAJOR_VERSION;
+const guint gimp_minor_version = GIMP_MINOR_VERSION;
+const guint gimp_micro_version = GIMP_MICRO_VERSION;
+
+
+/**
+ * gimp_env_init:
+ * @plug_in: must be %TRUE if this function is called from a plug-in
+ *
+ * You don't need to care about this function. It is being called for
+ * you automatically (by means of the MAIN() macro that every plug-in
+ * runs). Calling it again will cause a fatal error.
+ *
+ * Since: 2.4
+ */
+void
+gimp_env_init (gboolean plug_in)
+{
+ static gboolean gimp_env_initialized = FALSE;
+ const gchar *data_home = g_get_user_data_dir ();
+
+ if (gimp_env_initialized)
+ g_error ("gimp_env_init() must only be called once!");
+
+ gimp_env_initialized = TRUE;
+
+#ifndef G_OS_WIN32
+ if (plug_in)
+ {
+ _gimp_reloc_init_lib (NULL);
+ }
+ else if (_gimp_reloc_init (NULL))
+ {
+ /* Set $LD_LIBRARY_PATH to ensure that plugins can be loaded. */
+
+ const gchar *ldpath = g_getenv ("LD_LIBRARY_PATH");
+ gchar *libdir = g_build_filename (gimp_installation_directory (),
+ "lib",
+ NULL);
+
+ if (ldpath && *ldpath)
+ {
+ gchar *tmp = g_strconcat (libdir, ":", ldpath, NULL);
+
+ g_setenv ("LD_LIBRARY_PATH", tmp, TRUE);
+
+ g_free (tmp);
+ }
+ else
+ {
+ g_setenv ("LD_LIBRARY_PATH", libdir, TRUE);
+ }
+
+ g_free (libdir);
+ }
+#endif
+
+ /* The user data directory (XDG_DATA_HOME on Unix) is used to store
+ * various data, like crash logs (win32) or recently used file history
+ * (by GTK+). Yet it may be absent, in particular on non-Linux
+ * platforms. Make sure it exists.
+ */
+ if (! g_file_test (data_home, G_FILE_TEST_IS_DIR))
+ {
+ if (g_mkdir_with_parents (data_home, S_IRUSR | S_IWUSR | S_IXUSR) != 0)
+ {
+ g_warning ("Failed to create the data directory '%s': %s",
+ data_home, g_strerror (errno));
+ }
+ }
+}
+
+/**
+ * gimp_directory:
+ *
+ * Returns the user-specific GIMP settings directory. If the
+ * environment variable GIMP2_DIRECTORY exists, it is used. If it is
+ * an absolute path, it is used as is. If it is a relative path, it
+ * is taken to be a subdirectory of the home directory. If it is a
+ * relative path, and no home directory can be determined, it is taken
+ * to be a subdirectory of gimp_data_directory().
+ *
+ * The usual case is that no GIMP2_DIRECTORY environment variable
+ * exists, and then we use the GIMPDIR subdirectory of the local
+ * configuration directory:
+ *
+ * - UNIX: $XDG_CONFIG_HOME (defaults to $HOME/.config/)
+ *
+ * - Windows: CSIDL_APPDATA
+ *
+ * - OSX (UNIX exception): the Application Support Directory.
+ *
+ * If neither the configuration nor home directory exist,
+ * g_get_user_config_dir() will return {tmp}/{user_name}/.config/ where
+ * the temporary directory {tmp} and the {user_name} are determined
+ * according to platform rules.
+ *
+ * In any case, we always return some non-empty string, whether it
+ * corresponds to an existing directory or not.
+ *
+ * In config files such as gimprc, the string ${gimp_dir} expands to
+ * this directory.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8 (on Windows it is always
+ * UTF-8.)
+ *
+ * Returns: The user-specific GIMP settings directory.
+ **/
+const gchar *
+gimp_directory (void)
+{
+ static gchar *gimp_dir = NULL;
+ static gchar *last_env_gimp_dir = NULL;
+
+ const gchar *env_gimp_dir;
+
+ env_gimp_dir = g_getenv ("GIMP2_DIRECTORY");
+
+ if (gimp_dir)
+ {
+ gboolean gimp2_directory_changed = FALSE;
+
+ /* We have constructed the gimp_dir already. We can return
+ * gimp_dir unless some parameter gimp_dir depends on has
+ * changed. For now we just check for changes to GIMP2_DIRECTORY
+ */
+ gimp2_directory_changed =
+ (env_gimp_dir == NULL &&
+ last_env_gimp_dir != NULL) ||
+ (env_gimp_dir != NULL &&
+ last_env_gimp_dir == NULL) ||
+ (env_gimp_dir != NULL &&
+ last_env_gimp_dir != NULL &&
+ strcmp (env_gimp_dir, last_env_gimp_dir) != 0);
+
+ if (! gimp2_directory_changed)
+ {
+ return gimp_dir;
+ }
+ else
+ {
+ /* Free the old gimp_dir and go on to update it */
+ g_free (gimp_dir);
+ gimp_dir = NULL;
+ }
+ }
+
+ /* Remember the GIMP2_DIRECTORY to next invocation so we can check
+ * if it changes
+ */
+ g_free (last_env_gimp_dir);
+ last_env_gimp_dir = g_strdup (env_gimp_dir);
+
+ if (env_gimp_dir)
+ {
+ if (g_path_is_absolute (env_gimp_dir))
+ {
+ gimp_dir = g_strdup (env_gimp_dir);
+ }
+ else
+ {
+ const gchar *home_dir = g_get_home_dir ();
+
+ if (home_dir)
+ gimp_dir = g_build_filename (home_dir, env_gimp_dir, NULL);
+ else
+ gimp_dir = g_build_filename (gimp_data_directory (), env_gimp_dir, NULL);
+ }
+ }
+ else if (g_path_is_absolute (GIMPDIR))
+ {
+ gimp_dir = g_strdup (GIMPDIR);
+ }
+ else
+ {
+#ifdef PLATFORM_OSX
+
+ NSAutoreleasePool *pool;
+ NSArray *path;
+ NSString *library_dir;
+
+ pool = [[NSAutoreleasePool alloc] init];
+
+ path = NSSearchPathForDirectoriesInDomains (NSApplicationSupportDirectory,
+ NSUserDomainMask, YES);
+ library_dir = [path objectAtIndex:0];
+
+ gimp_dir = g_build_filename ([library_dir UTF8String],
+ GIMPDIR, GIMP_USER_VERSION, NULL);
+
+ [pool drain];
+
+#elif defined G_OS_WIN32
+
+ gchar *conf_dir = get_special_folder (CSIDL_APPDATA);
+
+ gimp_dir = g_build_filename (conf_dir,
+ GIMPDIR, GIMP_USER_VERSION, NULL);
+ g_free(conf_dir);
+
+#else /* UNIX */
+
+ /* g_get_user_config_dir () always returns a path as a non-null
+ * and non-empty string
+ */
+ gimp_dir = g_build_filename (g_get_user_config_dir (),
+ GIMPDIR, GIMP_USER_VERSION, NULL);
+
+#endif /* PLATFORM_OSX */
+ }
+
+ return gimp_dir;
+}
+
+#ifdef G_OS_WIN32
+
+/* Taken from glib 2.35 code. */
+static gchar *
+get_special_folder (int csidl)
+{
+ wchar_t path[MAX_PATH+1];
+ HRESULT hr;
+ LPITEMIDLIST pidl = NULL;
+ BOOL b;
+ gchar *retval = NULL;
+
+ hr = SHGetSpecialFolderLocation (NULL, csidl, &pidl);
+ if (hr == S_OK)
+ {
+ b = SHGetPathFromIDListW (pidl, path);
+ if (b)
+ retval = g_utf16_to_utf8 (path, -1, NULL, NULL, NULL);
+ CoTaskMemFree (pidl);
+ }
+
+ return retval;
+}
+
+static HMODULE libgimpbase_dll = NULL;
+
+/* Minimal DllMain that just stores the handle to this DLL */
+
+BOOL WINAPI /* Avoid silly "no previous prototype" gcc warning */
+DllMain (HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved);
+
+BOOL WINAPI
+DllMain (HINSTANCE hinstDLL,
+ DWORD fdwReason,
+ LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ libgimpbase_dll = hinstDLL;
+ break;
+ }
+
+ return TRUE;
+}
+
+#endif
+
+/**
+ * gimp_installation_directory:
+ *
+ * Returns the top installation directory of GIMP. On Unix the
+ * compile-time defined installation prefix is used. On Windows, the
+ * installation directory as deduced from the executable's full
+ * filename is used. On OSX we ask [NSBundle mainBundle] for the
+ * resource path to check if GIMP is part of a relocatable bundle.
+ *
+ * In config files such as gimprc, the string ${gimp_installation_dir}
+ * expands to this directory.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8. (On Windows it always is
+ * UTF-8.)
+ *
+ * Since: 2.8
+ *
+ * Returns: The toplevel installation directory of GIMP.
+ **/
+const gchar *
+gimp_installation_directory (void)
+{
+ static gchar *toplevel = NULL;
+
+ if (toplevel)
+ return toplevel;
+
+#ifdef G_OS_WIN32
+
+ toplevel = g_win32_get_package_installation_directory_of_module (libgimpbase_dll);
+ if (! toplevel)
+ g_error ("g_win32_get_package_installation_directory_of_module() failed");
+
+#elif PLATFORM_OSX
+
+ {
+ NSAutoreleasePool *pool;
+ NSString *resource_path;
+ gchar *basename;
+ gchar *basepath;
+ gchar *dirname;
+
+ pool = [[NSAutoreleasePool alloc] init];
+
+ resource_path = [[NSBundle mainBundle] resourcePath];
+
+ basename = g_path_get_basename ([resource_path UTF8String]);
+ basepath = g_path_get_dirname ([resource_path UTF8String]);
+ dirname = g_path_get_basename (basepath);
+
+ if (! strcmp (basename, ".libs"))
+ {
+ /* we are running from the source dir, do normal unix things */
+
+ toplevel = _gimp_reloc_find_prefix (PREFIX);
+ }
+ else if (! strcmp (basename, "bin"))
+ {
+ /* we are running the main app, but not from a bundle, the resource
+ * path is the directory which contains the executable
+ */
+
+ toplevel = g_strdup (basepath);
+ }
+ else if (! strcmp (basename, "plug-ins"))
+ {
+ /* same for plug-ins, go three levels up from prefix/lib/gimp/x.y */
+
+ gchar *tmp = g_path_get_dirname (basepath);
+ gchar *tmp2 = g_path_get_dirname (tmp);
+
+ toplevel = g_path_get_dirname (tmp2);
+
+ g_free (tmp);
+ g_free (tmp2);
+ }
+ else if (! strcmp (dirname, "plug-ins"))
+ {
+ /* same for plug-ins in subdirectory, go three levels up from prefix/lib/gimp/x.y */
+
+ gchar *tmp = g_path_get_dirname (basepath);
+ gchar *tmp2 = g_path_get_dirname (tmp);
+ gchar *tmp3 = g_path_get_dirname (tmp2);
+
+ toplevel = g_path_get_dirname (tmp3);
+
+ g_free (tmp);
+ g_free (tmp2);
+ g_free (tmp3);
+ }
+ else
+ {
+ /* if none of the above match, we assume that we are really in a bundle */
+
+ toplevel = g_strdup ([resource_path UTF8String]);
+ }
+
+ g_free (basename);
+ g_free (basepath);
+ g_free (dirname);
+
+ [pool drain];
+ }
+
+#else
+
+ toplevel = _gimp_reloc_find_prefix (PREFIX);
+
+#endif
+
+ return toplevel;
+}
+
+/**
+ * gimp_data_directory:
+ *
+ * Returns the default top directory for GIMP data. If the environment
+ * variable GIMP2_DATADIR exists, that is used. It should be an
+ * absolute pathname. Otherwise, on Unix the compile-time defined
+ * directory is used. On Windows, the installation directory as
+ * deduced from the executable's full filename is used.
+ *
+ * Note that the actual directories used for GIMP data files can be
+ * overridden by the user in the preferences dialog.
+ *
+ * In config files such as gimprc, the string ${gimp_data_dir} expands
+ * to this directory.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8. (On Windows it always is
+ * UTF-8.)
+ *
+ * Returns: The top directory for GIMP data.
+ **/
+const gchar *
+gimp_data_directory (void)
+{
+ static gchar *gimp_data_dir = NULL;
+
+ if (! gimp_data_dir)
+ {
+ gchar *tmp = g_build_filename ("share",
+ GIMP_PACKAGE,
+ GIMP_DATA_VERSION,
+ NULL);
+
+ gimp_data_dir = gimp_env_get_dir ("GIMP2_DATADIR", GIMPDATADIR, tmp);
+ g_free (tmp);
+ }
+
+ return gimp_data_dir;
+}
+
+/**
+ * gimp_locale_directory:
+ *
+ * Returns the top directory for GIMP locale files. If the environment
+ * variable GIMP2_LOCALEDIR exists, that is used. It should be an
+ * absolute pathname. Otherwise, on Unix the compile-time defined
+ * directory is used. On Windows, the installation directory as deduced
+ * from the executable's full filename is used.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * the C library, which isn't necessarily UTF-8. (On Windows, unlike
+ * the other similar functions here, the return value from this
+ * function is in the system codepage, never in UTF-8. It can thus be
+ * passed directly to the bindtextdomain() function from libintl which
+ * does not handle UTF-8.)
+ *
+ * Returns: The top directory for GIMP locale files.
+ */
+const gchar *
+gimp_locale_directory (void)
+{
+ static gchar *gimp_locale_dir = NULL;
+
+ if (! gimp_locale_dir)
+ {
+ gchar *tmp = g_build_filename ("share",
+ "locale",
+ NULL);
+
+ gimp_locale_dir = gimp_env_get_dir ("GIMP2_LOCALEDIR", LOCALEDIR, tmp);
+ g_free (tmp);
+
+#ifdef G_OS_WIN32
+ /* FIXME: g_win32_locale_filename_from_utf8() can actually return
+ * NULL (we had actual cases of this). Not sure exactly what
+ * gimp_locale_directory() should do when this happens. Anyway
+ * that's really broken, and something should be done some day
+ * about this!
+ */
+ tmp = g_win32_locale_filename_from_utf8 (gimp_locale_dir);
+ g_free (gimp_locale_dir);
+ gimp_locale_dir = tmp;
+#endif
+ }
+
+ return gimp_locale_dir;
+}
+
+/**
+ * gimp_sysconf_directory:
+ *
+ * Returns the top directory for GIMP config files. If the environment
+ * variable GIMP2_SYSCONFDIR exists, that is used. It should be an
+ * absolute pathname. Otherwise, on Unix the compile-time defined
+ * directory is used. On Windows, the installation directory as deduced
+ * from the executable's full filename is used.
+ *
+ * In config files such as gimprc, the string ${gimp_sysconf_dir}
+ * expands to this directory.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8. (On Windows it always is
+ * UTF-8.).
+ *
+ * Returns: The top directory for GIMP config files.
+ **/
+const gchar *
+gimp_sysconf_directory (void)
+{
+ static gchar *gimp_sysconf_dir = NULL;
+
+ if (! gimp_sysconf_dir)
+ {
+ gchar *tmp = g_build_filename ("etc",
+ GIMP_PACKAGE,
+ GIMP_SYSCONF_VERSION,
+ NULL);
+
+ gimp_sysconf_dir = gimp_env_get_dir ("GIMP2_SYSCONFDIR", GIMPSYSCONFDIR, tmp);
+ g_free (tmp);
+ }
+
+ return gimp_sysconf_dir;
+}
+
+/**
+ * gimp_plug_in_directory:
+ *
+ * Returns the default top directory for GIMP plug-ins and modules. If
+ * the environment variable GIMP2_PLUGINDIR exists, that is used. It
+ * should be an absolute pathname. Otherwise, on Unix the compile-time
+ * defined directory is used. On Windows, the installation directory
+ * as deduced from the executable's full filename is used.
+ *
+ * Note that the actual directories used for GIMP plug-ins and modules
+ * can be overridden by the user in the preferences dialog.
+ *
+ * In config files such as gimprc, the string ${gimp_plug_in_dir}
+ * expands to this directory.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8. (On Windows it always is
+ * UTF-8.)
+ *
+ * Returns: The top directory for GIMP plug_ins and modules.
+ **/
+const gchar *
+gimp_plug_in_directory (void)
+{
+ static gchar *gimp_plug_in_dir = NULL;
+
+ if (! gimp_plug_in_dir)
+ {
+ gchar *tmp = g_build_filename ("lib",
+ GIMP_PACKAGE,
+ GIMP_PLUGIN_VERSION,
+ NULL);
+
+ gimp_plug_in_dir = gimp_env_get_dir ("GIMP2_PLUGINDIR", PLUGINDIR, tmp);
+ g_free (tmp);
+ }
+
+ return gimp_plug_in_dir;
+}
+
+/**
+ * gimp_cache_directory:
+ *
+ * Returns the default top directory for GIMP cached files. If the
+ * environment variable GIMP2_CACHEDIR exists, that is used. It
+ * should be an absolute pathname. Otherwise, a subdirectory of the
+ * directory returned by g_get_user_cache_dir() is used.
+ *
+ * Note that the actual directories used for GIMP caches files can
+ * be overridden by the user in the preferences dialog.
+ *
+ * In config files such as gimprc, the string ${gimp_cache_dir}
+ * expands to this directory.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8. (On Windows it always is
+ * UTF-8.).
+ *
+ * Since: 2.10.10
+ *
+ * Returns: The default top directory for GIMP cached files.
+ **/
+const gchar *
+gimp_cache_directory (void)
+{
+ static gchar *gimp_cache_dir = NULL;
+
+ if (! gimp_cache_dir)
+ {
+ gchar *tmp = g_build_filename (g_get_user_cache_dir (),
+ GIMP_PACKAGE,
+ GIMP_USER_VERSION,
+ NULL);
+
+ gimp_cache_dir = gimp_env_get_dir ("GIMP2_CACHEDIR", NULL, tmp);
+ g_free (tmp);
+ }
+
+ return gimp_cache_dir;
+}
+
+/**
+ * gimp_temp_directory:
+ *
+ * Returns the default top directory for GIMP temporary files. If the
+ * environment variable GIMP2_TEMPDIR exists, that is used. It
+ * should be an absolute pathname. Otherwise, a subdirectory of the
+ * directory returned by g_get_tmp_dir() is used.
+ *
+ * In config files such as gimprc, the string ${gimp_temp_dir} expands
+ * to this directory.
+ *
+ * Note that the actual directories used for GIMP temporary files can
+ * be overridden by the user in the preferences dialog.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8. (On Windows it always is
+ * UTF-8.).
+ *
+ * Since: 2.10.10
+ *
+ * Returns: The default top directory for GIMP temporary files.
+ **/
+const gchar *
+gimp_temp_directory (void)
+{
+ static gchar *gimp_temp_dir = NULL;
+
+ if (! gimp_temp_dir)
+ {
+ gchar *tmp = g_build_filename (g_get_tmp_dir (),
+ GIMP_PACKAGE,
+ GIMP_USER_VERSION,
+ NULL);
+
+ gimp_temp_dir = gimp_env_get_dir ("GIMP2_TEMPDIR", NULL, tmp);
+ g_free (tmp);
+ }
+
+ return gimp_temp_dir;
+}
+
+static GFile *
+gimp_child_file (const gchar *parent,
+ const gchar *element,
+ va_list args)
+{
+ GFile *file = g_file_new_for_path (parent);
+
+ while (element)
+ {
+ GFile *child = g_file_get_child (file, element);
+
+ g_object_unref (file);
+ file = child;
+
+ element = va_arg (args, const gchar *);
+ }
+
+ return file;
+}
+
+/**
+ * gimp_directory_file:
+ * @first_element: the first element of a path to a file in the
+ * user's GIMP directory, or %NULL.
+ * @...: a %NULL terminated list of the remaining elements of the path
+ * to the file.
+ *
+ * Returns a #GFile in the user's GIMP directory, or the data
+ * directory itself if @first_element is %NULL.
+ *
+ * See also: gimp_directory().
+ *
+ * Since: 2.10
+ *
+ * Returns: a new @GFile for the path, Free with g_object_unref().
+ **/
+GFile *
+gimp_directory_file (const gchar *first_element,
+ ...)
+{
+ GFile *file;
+ va_list args;
+
+ va_start (args, first_element);
+ file = gimp_child_file (gimp_directory (), first_element, args);
+ va_end (args);
+
+ return file;
+}
+
+/**
+ * gimp_installation_directory_file:
+ * @first_element: the first element of a path to a file in the
+ * top installation directory, or %NULL.
+ * @...: a %NULL terminated list of the remaining elements of the path
+ * to the file.
+ *
+ * Returns a #GFile in the installation directory, or the installation
+ * directory itself if @first_element is %NULL.
+ *
+ * See also: gimp_installation_directory().
+ *
+ * Since: 2.10.10
+ *
+ * Returns: a new @GFile for the path, Free with g_object_unref().
+ **/
+GFile *
+gimp_installation_directory_file (const gchar *first_element,
+ ...)
+{
+ GFile *file;
+ va_list args;
+
+ va_start (args, first_element);
+ file = gimp_child_file (gimp_installation_directory (), first_element, args);
+ va_end (args);
+
+ return file;
+}
+
+/**
+ * gimp_data_directory_file:
+ * @first_element: the first element of a path to a file in the
+ * data directory, or %NULL.
+ * @...: a %NULL terminated list of the remaining elements of the path
+ * to the file.
+ *
+ * Returns a #GFile in the data directory, or the data directory
+ * itself if @first_element is %NULL.
+ *
+ * See also: gimp_data_directory().
+ *
+ * Since: 2.10
+ *
+ * Returns: a new @GFile for the path, Free with g_object_unref().
+ **/
+GFile *
+gimp_data_directory_file (const gchar *first_element,
+ ...)
+{
+ GFile *file;
+ va_list args;
+
+ va_start (args, first_element);
+ file = gimp_child_file (gimp_data_directory (), first_element, args);
+ va_end (args);
+
+ return file;
+}
+
+/**
+ * gimp_locale_directory_file:
+ * @first_element: the first element of a path to a file in the
+ * locale directory, or %NULL.
+ * @...: a %NULL terminated list of the remaining elements of the path
+ * to the file.
+ *
+ * Returns a #GFile in the locale directory, or the locale directory
+ * itself if @first_element is %NULL.
+ *
+ * See also: gimp_locale_directory().
+ *
+ * Since: 2.10
+ *
+ * Returns: a new @GFile for the path, Free with g_object_unref().
+ **/
+GFile *
+gimp_locale_directory_file (const gchar *first_element,
+ ...)
+{
+ GFile *file;
+ va_list args;
+
+ va_start (args, first_element);
+ file = gimp_child_file (gimp_locale_directory (), first_element, args);
+ va_end (args);
+
+ return file;
+}
+
+/**
+ * gimp_sysconf_directory_file:
+ * @first_element: the first element of a path to a file in the
+ * sysconf directory, or %NULL.
+ * @...: a %NULL terminated list of the remaining elements of the path
+ * to the file.
+ *
+ * Returns a #GFile in the sysconf directory, or the sysconf directory
+ * itself if @first_element is %NULL.
+ *
+ * See also: gimp_sysconf_directory().
+ *
+ * Since: 2.10
+ *
+ * Returns: a new @GFile for the path, Free with g_object_unref().
+ **/
+GFile *
+gimp_sysconf_directory_file (const gchar *first_element,
+ ...)
+{
+ GFile *file;
+ va_list args;
+
+ va_start (args, first_element);
+ file = gimp_child_file (gimp_sysconf_directory (), first_element, args);
+ va_end (args);
+
+ return file;
+}
+
+/**
+ * gimp_plug_in_directory_file:
+ * @first_element: the first element of a path to a file in the
+ * plug-in directory, or %NULL.
+ * @...: a %NULL terminated list of the remaining elements of the path
+ * to the file.
+ *
+ * Returns a #GFile in the plug-in directory, or the plug-in directory
+ * itself if @first_element is %NULL.
+ *
+ * See also: gimp_plug_in_directory().
+ *
+ * Since: 2.10
+ *
+ * Returns: a new @GFile for the path, Free with g_object_unref().
+ **/
+GFile *
+gimp_plug_in_directory_file (const gchar *first_element,
+ ...)
+{
+ GFile *file;
+ va_list args;
+
+ va_start (args, first_element);
+ file = gimp_child_file (gimp_plug_in_directory (), first_element, args);
+ va_end (args);
+
+ return file;
+}
+
+/**
+ * gimp_user_directory:
+ * @type: the type of user directory to retrieve
+ *
+ * This procedure is deprecated! Use g_get_user_special_dir() instead.
+ *
+ * Returns: The path to the specified user directory, or %NULL if the
+ * logical ID was not found.
+ *
+ * Since: 2.4
+ **/
+const gchar *
+gimp_user_directory (GimpUserDirectory type)
+{
+ return g_get_user_special_dir ((GUserDirectory) type);
+}
+
+/**
+ * gimp_personal_rc_file:
+ * @basename: The basename of a rc_file.
+ *
+ * Returns the name of a file in the user-specific GIMP settings directory.
+ *
+ * The returned string is newly allocated and should be freed with
+ * g_free() after use. The returned string is in the encoding used for
+ * filenames by GLib, which isn't necessarily UTF-8. (On Windows it
+ * always is UTF-8.)
+ *
+ * Returns: The name of a file in the user-specific GIMP settings directory.
+ **/
+gchar *
+gimp_personal_rc_file (const gchar *basename)
+{
+ return g_build_filename (gimp_directory (), basename, NULL);
+}
+
+/**
+ * gimp_gtkrc:
+ *
+ * Returns the name of GIMP's application-specific gtkrc file.
+ *
+ * The returned string is owned by GIMP and must not be modified or
+ * freed. The returned string is in the encoding used for filenames by
+ * GLib, which isn't necessarily UTF-8. (On Windows it always is
+ * UTF-8.)
+ *
+ * Returns: The name of GIMP's application-specific gtkrc file.
+ **/
+const gchar *
+gimp_gtkrc (void)
+{
+ static gchar *gimp_gtkrc_filename = NULL;
+
+ if (! gimp_gtkrc_filename)
+ gimp_gtkrc_filename = g_build_filename (gimp_data_directory (),
+ "themes", "System", "gtkrc",
+ NULL);
+
+ return gimp_gtkrc_filename;
+}
+
+/**
+ * gimp_path_runtime_fix:
+ * @path: A pointer to a string (allocated with g_malloc) that is
+ * (or could be) a pathname.
+ *
+ * On Windows, this function checks if the string pointed to by @path
+ * starts with the compile-time prefix, and in that case, replaces the
+ * prefix with the run-time one. @path should be a pointer to a
+ * dynamically allocated (with g_malloc, g_strconcat, etc) string. If
+ * the replacement takes place, the original string is deallocated,
+ * and *@path is replaced with a pointer to a new string with the
+ * run-time prefix spliced in.
+ *
+ * On Linux, it does the same thing, but only if BinReloc support is enabled.
+ * On other Unices, it does nothing because those platforms don't have a
+ * way to find out where our binary is.
+ */
+static void
+gimp_path_runtime_fix (gchar **path)
+{
+#if defined (G_OS_WIN32) && defined (PREFIX)
+ gchar *p;
+
+ /* Yes, I do mean forward slashes below */
+ if (strncmp (*path, PREFIX "/", strlen (PREFIX "/")) == 0)
+ {
+ /* This is a compile-time entry. Replace the path with the
+ * real one on this machine.
+ */
+ p = *path;
+ *path = g_strconcat (gimp_installation_directory (),
+ "\\",
+ *path + strlen (PREFIX "/"),
+ NULL);
+ g_free (p);
+ }
+ /* Replace forward slashes with backslashes, just for
+ * completeness */
+ p = *path;
+ while ((p = strchr (p, '/')) != NULL)
+ {
+ *p = '\\';
+ p++;
+ }
+#elif defined (G_OS_WIN32)
+ /* without defineing PREFIX do something useful too */
+ gchar *p = *path;
+ if (!g_path_is_absolute (p))
+ {
+ *path = g_build_filename (gimp_installation_directory (), *path, NULL);
+ g_free (p);
+ }
+#else
+ gchar *p;
+
+ if (strncmp (*path, PREFIX G_DIR_SEPARATOR_S,
+ strlen (PREFIX G_DIR_SEPARATOR_S)) == 0)
+ {
+ /* This is a compile-time entry. Replace the path with the
+ * real one on this machine.
+ */
+ p = *path;
+ *path = g_build_filename (gimp_installation_directory (),
+ *path + strlen (PREFIX G_DIR_SEPARATOR_S),
+ NULL);
+ g_free (p);
+ }
+#endif
+}
+
+/**
+ * gimp_path_parse:
+ * @path: A list of directories separated by #G_SEARCHPATH_SEPARATOR.
+ * @max_paths: The maximum number of directories to return.
+ * @check: %TRUE if you want the directories to be checked.
+ * @check_failed: Returns a #GList of path elements for which the
+ * check failed.
+ *
+ * Returns: A #GList of all directories in @path.
+ **/
+GList *
+gimp_path_parse (const gchar *path,
+ gint max_paths,
+ gboolean check,
+ GList **check_failed)
+{
+ gchar **patharray;
+ GList *list = NULL;
+ GList *fail_list = NULL;
+ gint i;
+ gboolean exists = TRUE;
+
+ if (!path || !*path || max_paths < 1 || max_paths > 256)
+ return NULL;
+
+ patharray = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, max_paths);
+
+ for (i = 0; i < max_paths; i++)
+ {
+ GString *dir;
+
+ if (! patharray[i])
+ break;
+
+#ifndef G_OS_WIN32
+ if (*patharray[i] == '~')
+ {
+ dir = g_string_new (g_get_home_dir ());
+ g_string_append (dir, patharray[i] + 1);
+ }
+ else
+#endif
+ {
+ gimp_path_runtime_fix (&patharray[i]);
+ dir = g_string_new (patharray[i]);
+ }
+
+ if (check)
+ exists = g_file_test (dir->str, G_FILE_TEST_IS_DIR);
+
+ if (exists)
+ {
+ GList *dup;
+
+ /* check for duplicate entries, see bug #784502 */
+ for (dup = list; dup; dup = g_list_next (dup))
+ {
+ if (! strcmp (dir->str, dup->data))
+ break;
+ }
+
+ /* only add to the list if it's not a duplicate */
+ if (! dup)
+ list = g_list_prepend (list, g_strdup (dir->str));
+ }
+ else if (check_failed)
+ {
+ fail_list = g_list_prepend (fail_list, g_strdup (dir->str));
+ }
+
+ g_string_free (dir, TRUE);
+ }
+
+ g_strfreev (patharray);
+
+ list = g_list_reverse (list);
+
+ if (check && check_failed)
+ {
+ fail_list = g_list_reverse (fail_list);
+ *check_failed = fail_list;
+ }
+
+ return list;
+}
+
+/**
+ * gimp_path_to_str:
+ * @path: A list of directories as returned by gimp_path_parse().
+ *
+ * Returns: A searchpath string separated by #G_SEARCHPATH_SEPARATOR.
+ **/
+gchar *
+gimp_path_to_str (GList *path)
+{
+ GString *str = NULL;
+ GList *list;
+ gchar *retval = NULL;
+
+ for (list = path; list; list = g_list_next (list))
+ {
+ gchar *dir = list->data;
+
+ if (str)
+ {
+ g_string_append_c (str, G_SEARCHPATH_SEPARATOR);
+ g_string_append (str, dir);
+ }
+ else
+ {
+ str = g_string_new (dir);
+ }
+ }
+
+ if (str)
+ retval = g_string_free (str, FALSE);
+
+ return retval;
+}
+
+/**
+ * gimp_path_free:
+ * @path: A list of directories as returned by gimp_path_parse().
+ *
+ * This function frees the memory allocated for the list and the strings
+ * it contains.
+ **/
+void
+gimp_path_free (GList *path)
+{
+ g_list_free_full (path, (GDestroyNotify) g_free);
+}
+
+/**
+ * gimp_path_get_user_writable_dir:
+ * @path: A list of directories as returned by gimp_path_parse().
+ *
+ * Note that you have to g_free() the returned string.
+ *
+ * Returns: The first directory in @path where the user has write permission.
+ **/
+gchar *
+gimp_path_get_user_writable_dir (GList *path)
+{
+ GList *list;
+ uid_t euid;
+ gid_t egid;
+ GStatBuf filestat;
+ gint err;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ euid = geteuid ();
+ egid = getegid ();
+
+ for (list = path; list; list = g_list_next (list))
+ {
+ gchar *dir = list->data;
+
+ /* check if directory exists */
+ err = g_stat (dir, &filestat);
+
+ /* this is tricky:
+ * if a file is e.g. owned by the current user but not user-writable,
+ * the user has no permission to write to the file regardless
+ * of his group's or other's write permissions
+ */
+ if (!err && S_ISDIR (filestat.st_mode) &&
+
+ ((filestat.st_mode & S_IWUSR) ||
+
+ ((filestat.st_mode & S_IWGRP) &&
+ (euid != filestat.st_uid)) ||
+
+ ((filestat.st_mode & S_IWOTH) &&
+ (euid != filestat.st_uid) &&
+ (egid != filestat.st_gid))))
+ {
+ return g_strdup (dir);
+ }
+ }
+
+ return NULL;
+}
+
+static gchar *
+gimp_env_get_dir (const gchar *gimp_env_name,
+ const gchar *compile_time_dir,
+ const gchar *relative_subdir)
+{
+ const gchar *env = g_getenv (gimp_env_name);
+
+ if (env)
+ {
+ if (! g_path_is_absolute (env))
+ g_error ("%s environment variable should be an absolute path.",
+ gimp_env_name);
+
+ return g_strdup (env);
+ }
+ else if (compile_time_dir)
+ {
+ gchar *retval = g_strdup (compile_time_dir);
+
+ gimp_path_runtime_fix (&retval);
+
+ return retval;
+ }
+ else if (! g_path_is_absolute (relative_subdir))
+ {
+ return g_build_filename (gimp_installation_directory (),
+ relative_subdir,
+ NULL);
+ }
+
+ return g_strdup (relative_subdir);
+}
diff --git a/libgimpbase/gimpenv.h b/libgimpbase/gimpenv.h
new file mode 100644
index 0000000..04a83af
--- /dev/null
+++ b/libgimpbase/gimpenv.h
@@ -0,0 +1,96 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpenv.h
+ * Copyright (C) 1999 Tor Lillqvist <tml@iki.fi>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_ENV_H__
+#define __GIMP_ENV_H__
+
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+#ifdef G_OS_WIN32
+# ifdef __GIMP_ENV_C__
+# define GIMPVAR extern __declspec(dllexport)
+# else /* !__GIMP_ENV_C__ */
+# define GIMPVAR extern __declspec(dllimport)
+# endif /* !__GIMP_ENV_C__ */
+#else /* !G_OS_WIN32 */
+# define GIMPVAR extern
+#endif
+
+GIMPVAR const guint gimp_major_version;
+GIMPVAR const guint gimp_minor_version;
+GIMPVAR const guint gimp_micro_version;
+
+
+const gchar * gimp_directory (void) G_GNUC_CONST;
+const gchar * gimp_installation_directory (void) G_GNUC_CONST;
+const gchar * gimp_data_directory (void) G_GNUC_CONST;
+const gchar * gimp_locale_directory (void) G_GNUC_CONST;
+const gchar * gimp_sysconf_directory (void) G_GNUC_CONST;
+const gchar * gimp_plug_in_directory (void) G_GNUC_CONST;
+const gchar * gimp_cache_directory (void) G_GNUC_CONST;
+const gchar * gimp_temp_directory (void) G_GNUC_CONST;
+
+GFile * gimp_directory_file (const gchar *first_element,
+ ...) G_GNUC_MALLOC;
+GFile * gimp_installation_directory_file (const gchar *first_element,
+ ...) G_GNUC_MALLOC;
+GFile * gimp_data_directory_file (const gchar *first_element,
+ ...) G_GNUC_MALLOC;
+GFile * gimp_locale_directory_file (const gchar *first_element,
+ ...) G_GNUC_MALLOC;
+GFile * gimp_sysconf_directory_file (const gchar *first_element,
+ ...) G_GNUC_MALLOC;
+GFile * gimp_plug_in_directory_file (const gchar *first_element,
+ ...) G_GNUC_MALLOC;
+
+#ifndef GIMP_DISABLE_DEPRECATED
+GIMP_DEPRECATED_FOR(g_get_user_special_dir)
+const gchar * gimp_user_directory (GimpUserDirectory type) G_GNUC_CONST;
+#endif /* !GIMP_DISABLE_DEPRECATED */
+
+const gchar * gimp_gtkrc (void) G_GNUC_CONST;
+gchar * gimp_personal_rc_file (const gchar *basename) G_GNUC_MALLOC;
+
+GList * gimp_path_parse (const gchar *path,
+ gint max_paths,
+ gboolean check,
+ GList **check_failed);
+gchar * gimp_path_to_str (GList *path) G_GNUC_MALLOC;
+void gimp_path_free (GList *path);
+
+gchar * gimp_path_get_user_writable_dir (GList *path) G_GNUC_MALLOC;
+
+
+/* should be considered private, don't use! */
+void gimp_env_init (gboolean plug_in);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_ENV_H__ */
diff --git a/libgimpbase/gimplimits.h b/libgimpbase/gimplimits.h
new file mode 100644
index 0000000..75a08b9
--- /dev/null
+++ b/libgimpbase/gimplimits.h
@@ -0,0 +1,97 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1999 Peter Mattis and Spencer Kimball
+ *
+ * gimplimits.h
+ * Copyright (C) 1999 Michael Natterer <mitschel@cs.tu-berlin.de>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_LIMITS_H__
+#define __GIMP_LIMITS_H__
+
+G_BEGIN_DECLS
+
+
+/**
+ * SECTION: gimplimits
+ * @title: gimplimits
+ * @short_description: Boundaries of some GIMP data types and some
+ * global constants.
+ *
+ * Boundaries of some GIMP data types and some global constants.
+ **/
+
+
+/**
+ * GIMP_MIN_IMAGE_SIZE:
+ *
+ * The minimum width and height of a GIMP image in pixels.
+ **/
+#define GIMP_MIN_IMAGE_SIZE 1
+
+/**
+ * GIMP_MAX_IMAGE_SIZE:
+ *
+ * The maximum width and height of a GIMP image in pixels. This is a
+ * somewhat arbitrary value that can be used when an upper value for
+ * pixel sizes is needed; for example to give a spin button an upper
+ * limit.
+ **/
+#define GIMP_MAX_IMAGE_SIZE 524288 /* 2^19 */
+
+
+/**
+ * GIMP_MIN_RESOLUTION:
+ *
+ * The minimum resolution of a GIMP image in pixels per inch. This is
+ * a somewhat arbitrary value that can be used when a lower value for a
+ * resolution is needed. GIMP will not accept resolutions smaller than
+ * this value.
+ **/
+#define GIMP_MIN_RESOLUTION 5e-3 /* shouldn't display as 0.000 */
+
+/**
+ * GIMP_MAX_RESOLUTION:
+ *
+ * The maximum resolution of a GIMP image in pixels per inch. This is
+ * a somewhat arbitrary value that can be used to when an upper value
+ * for a resolution is needed. GIMP will not accept resolutions larger
+ * than this value.
+ **/
+#define GIMP_MAX_RESOLUTION 1048576.0
+
+
+/**
+ * GIMP_MAX_MEMSIZE:
+ *
+ * A large but arbitrary value that can be used when an upper limit
+ * for a memory size (in bytes) is needed. It is smaller than
+ * %G_MAXDOUBLE since the #GimpMemsizeEntry doesn't handle larger
+ * values.
+ **/
+#define GIMP_MAX_MEMSIZE ((guint64) 1 << 42) /* 4 terabyte;
+ * needs a 64bit variable
+ * and must be < G_MAXDOUBLE
+ */
+
+
+G_END_DECLS
+
+#endif /* __GIMP_LIMITS_H__ */
diff --git a/libgimpbase/gimpmemsize.c b/libgimpbase/gimpmemsize.c
new file mode 100644
index 0000000..4be14b6
--- /dev/null
+++ b/libgimpbase/gimpmemsize.c
@@ -0,0 +1,288 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <errno.h>
+
+#include <glib-object.h>
+
+#include "gimpbasetypes.h"
+
+#include "gimpmemsize.h"
+
+#include "libgimp/libgimp-intl.h"
+
+
+/**
+ * SECTION: gimpmemsize
+ * @title: gimpmemsize
+ * @short_description: Functions to (de)serialize a given memory size.
+ *
+ * Functions to (de)serialize a given memory size.
+ **/
+
+
+static void memsize_to_string (const GValue *src_value,
+ GValue *dest_value);
+static void string_to_memsize (const GValue *src_value,
+ GValue *dest_value);
+
+
+GType
+gimp_memsize_get_type (void)
+{
+ static GType memsize_type = 0;
+
+ if (! memsize_type)
+ {
+ const GTypeInfo type_info = { 0, };
+
+ memsize_type = g_type_register_static (G_TYPE_UINT64, "GimpMemsize",
+ &type_info, 0);
+
+ g_value_register_transform_func (memsize_type, G_TYPE_STRING,
+ memsize_to_string);
+ g_value_register_transform_func (G_TYPE_STRING, memsize_type,
+ string_to_memsize);
+ }
+
+ return memsize_type;
+}
+
+/**
+ * gimp_memsize_serialize:
+ * @memsize: memory size in bytes
+ *
+ * Creates a string representation of a given memory size. This string
+ * can be parsed by gimp_memsize_deserialize() and can thus be used in
+ * config files. It should not be displayed to the user. If you need a
+ * nice human-readable string please use g_format_size().
+ *
+ * Return value: A newly allocated string representation of @memsize.
+ *
+ * Since: 2.2
+ **/
+gchar *
+gimp_memsize_serialize (guint64 memsize)
+{
+ if (memsize > (1 << 30) && memsize % (1 << 30) == 0)
+ return g_strdup_printf ("%" G_GUINT64_FORMAT "G", memsize >> 30);
+ else if (memsize > (1 << 20) && memsize % (1 << 20) == 0)
+ return g_strdup_printf ("%" G_GUINT64_FORMAT "M", memsize >> 20);
+ else if (memsize > (1 << 10) && memsize % (1 << 10) == 0)
+ return g_strdup_printf ("%" G_GUINT64_FORMAT "k", memsize >> 10);
+ else
+ return g_strdup_printf ("%" G_GUINT64_FORMAT, memsize);
+}
+
+/**
+ * gimp_memsize_deserialize:
+ * @string: a string as returned by gimp_memsize_serialize()
+ * @memsize: return location for memory size in bytes
+ *
+ * Parses a string representation of a memory size as returned by
+ * gimp_memsize_serialize().
+ *
+ * Return value: %TRUE if the @string was successfully parsed and
+ * @memsize has been set, %FALSE otherwise.
+ *
+ * Since: 2.2
+ **/
+gboolean
+gimp_memsize_deserialize (const gchar *string,
+ guint64 *memsize)
+{
+ gchar *end;
+ guint64 size;
+
+ g_return_val_if_fail (string != NULL, FALSE);
+ g_return_val_if_fail (memsize != NULL, FALSE);
+
+ size = g_ascii_strtoull (string, &end, 0);
+
+ if (size == G_MAXUINT64 && errno == ERANGE)
+ return FALSE;
+
+ if (end && *end)
+ {
+ guint shift;
+
+ switch (g_ascii_tolower (*end))
+ {
+ case 'b':
+ shift = 0;
+ break;
+ case 'k':
+ shift = 10;
+ break;
+ case 'm':
+ shift = 20;
+ break;
+ case 'g':
+ shift = 30;
+ break;
+ default:
+ return FALSE;
+ }
+
+ /* protect against overflow */
+ if (shift)
+ {
+ guint64 limit = G_MAXUINT64 >> shift;
+
+ if (size != (size & limit))
+ return FALSE;
+
+ size <<= shift;
+ }
+ }
+
+ *memsize = size;
+
+ return TRUE;
+}
+
+
+/**
+ * gimp_memsize_to_string:
+ * @memsize: A memory size in bytes.
+ *
+ * This function is deprecated! Use g_format_size() instead.
+ *
+ * Return value: A newly allocated human-readable, translated string.
+ **/
+gchar *
+gimp_memsize_to_string (guint64 memsize)
+{
+ return g_format_size (memsize);
+}
+
+
+static void
+memsize_to_string (const GValue *src_value,
+ GValue *dest_value)
+{
+ g_value_take_string (dest_value,
+ gimp_memsize_serialize (g_value_get_uint64 (src_value)));
+}
+
+static void
+string_to_memsize (const GValue *src_value,
+ GValue *dest_value)
+{
+ const gchar *str;
+ guint64 memsize;
+
+ str = g_value_get_string (src_value);
+
+ if (str && gimp_memsize_deserialize (str, &memsize))
+ {
+ g_value_set_uint64 (dest_value, memsize);
+ }
+ else
+ {
+ g_warning ("Can't convert string to GimpMemsize.");
+ }
+}
+
+
+/*
+ * GIMP_TYPE_PARAM_MEMSIZE
+ */
+
+static void gimp_param_memsize_class_init (GParamSpecClass *class);
+
+/**
+ * gimp_param_memsize_get_type:
+ *
+ * Reveals the object type
+ *
+ * Returns: the #GType for a memsize object
+ *
+ * Since: 2.4
+ **/
+GType
+gimp_param_memsize_get_type (void)
+{
+ static GType spec_type = 0;
+
+ if (! spec_type)
+ {
+ const GTypeInfo type_info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_memsize_class_init,
+ NULL, NULL,
+ sizeof (GParamSpecUInt64),
+ 0, NULL, NULL
+ };
+
+ spec_type = g_type_register_static (G_TYPE_PARAM_UINT64,
+ "GimpParamMemsize",
+ &type_info, 0);
+ }
+
+ return spec_type;
+}
+
+static void
+gimp_param_memsize_class_init (GParamSpecClass *class)
+{
+ class->value_type = GIMP_TYPE_MEMSIZE;
+}
+
+/**
+ * gimp_param_spec_memsize:
+ * @name: Canonical name of the param
+ * @nick: Nickname of the param
+ * @blurb: Brief description of param.
+ * @minimum: Smallest allowed value of the parameter.
+ * @maximum: Largest allowed value of the parameter.
+ * @default_value: Value to use if none is assigned.
+ * @flags: a combination of #GParamFlags
+ *
+ * Creates a param spec to hold a memory size value.
+ * See g_param_spec_internal() for more information.
+ *
+ * Returns: a newly allocated #GParamSpec instance
+ *
+ * Since: 2.4
+ **/
+GParamSpec *
+gimp_param_spec_memsize (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ guint64 minimum,
+ guint64 maximum,
+ guint64 default_value,
+ GParamFlags flags)
+{
+ GParamSpecUInt64 *pspec;
+
+ pspec = g_param_spec_internal (GIMP_TYPE_PARAM_MEMSIZE,
+ name, nick, blurb, flags);
+
+ pspec->minimum = minimum;
+ pspec->maximum = maximum;
+ pspec->default_value = default_value;
+
+ return G_PARAM_SPEC (pspec);
+}
+
diff --git a/libgimpbase/gimpmemsize.h b/libgimpbase/gimpmemsize.h
new file mode 100644
index 0000000..f9f1201
--- /dev/null
+++ b/libgimpbase/gimpmemsize.h
@@ -0,0 +1,68 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_MEMSIZE_H__
+#define __GIMP_MEMSIZE_H__
+
+G_BEGIN_DECLS
+
+
+/**
+ * GIMP_TYPE_MEMSIZE:
+ *
+ * #GIMP_TYPE_MEMSIZE is a #GType derived from #G_TYPE_UINT64.
+ **/
+
+#define GIMP_TYPE_MEMSIZE (gimp_memsize_get_type ())
+#define GIMP_VALUE_HOLDS_MEMSIZE(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_MEMSIZE))
+
+GType gimp_memsize_get_type (void) G_GNUC_CONST;
+
+gchar * gimp_memsize_serialize (guint64 memsize) G_GNUC_MALLOC;
+gboolean gimp_memsize_deserialize (const gchar *string,
+ guint64 *memsize);
+
+GIMP_DEPRECATED_FOR(g_format_size)
+gchar * gimp_memsize_to_string (guint64 memsize) G_GNUC_MALLOC;
+
+
+/*
+ * GIMP_TYPE_PARAM_MEMSIZE
+ */
+
+#define GIMP_TYPE_PARAM_MEMSIZE (gimp_param_memsize_get_type ())
+#define GIMP_IS_PARAM_SPEC_MEMSIZE(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_MEMSIZE))
+
+GType gimp_param_memsize_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_memsize (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ guint64 minimum,
+ guint64 maximum,
+ guint64 default_value,
+ GParamFlags flags);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_MEMSIZE_H__ */
diff --git a/libgimpbase/gimpmetadata.c b/libgimpbase/gimpmetadata.c
new file mode 100644
index 0000000..8bf3ed8
--- /dev/null
+++ b/libgimpbase/gimpmetadata.c
@@ -0,0 +1,1796 @@
+/* LIBGIMPBASE - The GIMP Basic Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpmetadata.c
+ * Copyright (C) 2013 Hartmut Kuhse <hartmutkuhse@src.gnome.org>
+ * Michael Natterer <mitch@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gio/gio.h>
+#include <gexiv2/gexiv2.h>
+
+#include "libgimpmath/gimpmath.h"
+
+#include "gimpbasetypes.h"
+
+#include "gimplimits.h"
+#include "gimpmetadata.h"
+#include "gimpunit.h"
+
+#include "libgimp/libgimp-intl.h"
+
+typedef struct _GimpMetadataClass GimpMetadataClass;
+typedef struct _GimpMetadataPrivate GimpMetadataPrivate;
+
+struct _GimpMetadata
+{
+ GExiv2Metadata parent_instance;
+};
+
+struct _GimpMetadataPrivate
+{
+ /* dummy entry to avoid a critical warning due to size 0 */
+ gpointer _gimp_reserved1;
+};
+
+struct _GimpMetadataClass
+{
+ GExiv2MetadataClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gimp_reserved1) (void);
+ void (*_gimp_reserved2) (void);
+ void (*_gimp_reserved3) (void);
+ void (*_gimp_reserved4) (void);
+ void (*_gimp_reserved5) (void);
+ void (*_gimp_reserved6) (void);
+ void (*_gimp_reserved7) (void);
+ void (*_gimp_reserved8) (void);
+};
+
+/**
+ * SECTION: gimpmetadata
+ * @title: GimpMetadata
+ * @short_description: Basic functions for handling #GimpMetadata objects.
+ * @see_also: gimp_image_metadata_load_prepare(),
+ * gimp_image_metadata_load_finish(),
+ * gimp_image_metadata_save_prepare(),
+ * gimp_image_metadata_save_finish().
+ *
+ * Basic functions for handling #GimpMetadata objects.
+ **/
+
+
+#define GIMP_METADATA_ERROR gimp_metadata_error_quark ()
+
+static GQuark gimp_metadata_error_quark (void);
+static void gimp_metadata_copy_tag (GExiv2Metadata *src,
+ GExiv2Metadata *dest,
+ const gchar *tag);
+static void gimp_metadata_copy_tags (GExiv2Metadata *src,
+ GExiv2Metadata *dest,
+ const gchar **tags);
+static void gimp_metadata_add (GimpMetadata *src,
+ GimpMetadata *dest);
+
+
+static const gchar *tiff_tags[] =
+{
+ "Xmp.tiff",
+ "Exif.Image.ImageWidth",
+ "Exif.Image.ImageLength",
+ "Exif.Image.BitsPerSample",
+ "Exif.Image.Compression",
+ "Exif.Image.PhotometricInterpretation",
+ "Exif.Image.FillOrder",
+ "Exif.Image.SamplesPerPixel",
+ "Exif.Image.StripOffsets",
+ "Exif.Image.RowsPerStrip",
+ "Exif.Image.StripByteCounts",
+ "Exif.Image.PlanarConfiguration"
+};
+
+static const gchar *jpeg_tags[] =
+{
+ "Exif.Image.JPEGProc",
+ "Exif.Image.JPEGInterchangeFormat",
+ "Exif.Image.JPEGInterchangeFormatLength",
+ "Exif.Image.JPEGRestartInterval",
+ "Exif.Image.JPEGLosslessPredictors",
+ "Exif.Image.JPEGPointTransforms",
+ "Exif.Image.JPEGQTables",
+ "Exif.Image.JPEGDCTables",
+ "Exif.Image.JPEGACTables"
+};
+
+static const gchar *unsupported_tags[] =
+{
+ "Exif.Image.SubIFDs",
+ "Exif.Image.ClipPath",
+ "Exif.Image.XClipPathUnits",
+ "Exif.Image.YClipPathUnits",
+ "Exif.Image.XPTitle",
+ "Exif.Image.XPComment",
+ "Exif.Image.XPAuthor",
+ "Exif.Image.XPKeywords",
+ "Exif.Image.XPSubject",
+ "Exif.Image.DNGVersion",
+ "Exif.Image.DNGBackwardVersion",
+ "Exif.Iop",
+ /* FIXME Even though adding the tags below fixes the issue it's not very flexible.
+ It might be better in the long run if there was a way for a user to configure which
+ tags to block or a way for us to detect problems with tags before writing them. */
+ /* Issues #1367, #2253. Offending tag is PreviewOffset but the other Preview tags
+ (PreviewResolution, PreviewLength, PreviewImageBorders) also make no sense because
+ we are not including a Pentax specific preview image. */
+ "Exif.Pentax.Preview",
+ "Exif.PentaxDng.Preview",
+ /* Never save the complete brand specific MakerNote data. We load and
+ * should only save the specific brand tags inside the MakerNote.
+ * Sometimes the MakerNote is invalid or exiv2 doesn't know how to parse
+ * it. In that case we still get the (invalid) MakerNote, but not the
+ * individual tags or just a subset of them.
+ * If there are recognized brand specific tags, exiv2 will create the
+ * required MakerNote itself (which in can still be invalid but that's an
+ * exiv2 issue not ours). */
+ "Exif.Photo.MakerNote",
+ "Exif.MakerNote.ByteOrder",
+ "Exif.MakerNote.Offset",
+};
+
+static const guint8 minimal_exif[] =
+{
+ 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
+ 0x01, 0x01, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xe1
+};
+
+static const guint8 wilber_jpg[] =
+{
+ 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
+ 0x01, 0x01, 0x00, 0x5a, 0x00, 0x5a, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
+ 0x00, 0x50, 0x37, 0x3c, 0x46, 0x3c, 0x32, 0x50, 0x46, 0x41, 0x46, 0x5a,
+ 0x55, 0x50, 0x5f, 0x78, 0xc8, 0x82, 0x78, 0x6e, 0x6e, 0x78, 0xf5, 0xaf,
+ 0xb9, 0x91, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x55, 0x5a,
+ 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82, 0x82, 0xeb, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x10, 0x03,
+ 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
+ 0x16, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0xff, 0xc4, 0x00,
+ 0x1e, 0x10, 0x00, 0x01, 0x05, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x03, 0x11, 0x31,
+ 0x04, 0x12, 0x51, 0x61, 0x71, 0xff, 0xc4, 0x00, 0x14, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xc4, 0x00, 0x14, 0x11, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11,
+ 0x00, 0x3f, 0x00, 0x18, 0xa0, 0x0e, 0x6d, 0xbc, 0xf5, 0xca, 0xf7, 0x78,
+ 0xb6, 0xfe, 0x3b, 0x23, 0xb2, 0x1d, 0x64, 0x68, 0xf0, 0x8a, 0x39, 0x4b,
+ 0x74, 0x9c, 0xa5, 0x5f, 0x35, 0x8a, 0xb2, 0x7e, 0xa0, 0xff, 0xd9, 0x00
+};
+
+static const guint wilber_jpg_len = G_N_ELEMENTS (wilber_jpg);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GimpMetadata, gimp_metadata, GEXIV2_TYPE_METADATA)
+
+
+static void
+gimp_metadata_class_init (GimpMetadataClass *klass)
+{
+ if (! gexiv2_metadata_register_xmp_namespace ("http://ns.adobe.com/DICOM/",
+ "DICOM"))
+ {
+ g_printerr ("Failed to register XMP namespace 'DICOM'\n");
+ }
+
+ if (! gexiv2_metadata_register_xmp_namespace ("http://darktable.sf.net/",
+ "darktable"))
+ {
+ g_printerr ("Failed to register XMP namespace 'darktable'\n");
+ }
+
+ /* Usage example Xmp.GIMP.tagname */
+ if (! gexiv2_metadata_register_xmp_namespace ("http://www.gimp.org/xmp/",
+ "GIMP"))
+ {
+ g_printerr ("Failed to register XMP namespace 'GIMP'\n");
+ }
+}
+
+static void
+gimp_metadata_init (GimpMetadata *metadata)
+{
+}
+
+/**
+ * gimp_metadata_get_guid:
+ *
+ * Generate Version 4 UUID/GUID.
+ *
+ * Return value: The new GUID/UUID string.
+ *
+ * Since: 2.10
+ */
+gchar *
+gimp_metadata_get_guid (void)
+{
+ GRand *rand;
+ gint bake;
+ gchar *GUID;
+ const gchar *szHex = "0123456789abcdef-";
+
+ rand = g_rand_new ();
+
+#define DALLOC 36
+
+ GUID = g_malloc0 (DALLOC + 1);
+
+ for (bake = 0; bake < DALLOC; bake++)
+ {
+ gint r = g_rand_int (rand) % 16;
+ gchar c = ' ';
+
+ switch (bake)
+ {
+ default:
+ c = szHex [r];
+ break;
+
+ case 19 :
+ c = szHex [(r & 0x03) | 0x08];
+ break;
+
+ case 8:
+ case 13:
+ case 18:
+ case 23:
+ c = '-';
+ break;
+
+ case 14:
+ c = '4';
+ break;
+ }
+
+ GUID[bake] = (bake < DALLOC) ? c : 0x00;
+ }
+
+ g_rand_free (rand);
+
+ return GUID;
+}
+
+/**
+ * gimp_metadata_add_history:
+ *
+ * Add XMP mm History data to file metadata.
+ *
+ * Since: 2.10
+ */
+void
+gimp_metadata_add_xmp_history (GimpMetadata *metadata,
+ gchar *state_status)
+{
+ time_t now;
+ struct tm *now_tm;
+ gchar *tmp;
+ char timestr[256];
+ char tzstr[7];
+ gchar iid_data[256];
+ gchar strdata[1024];
+ gchar tagstr[1024];
+ gchar *uuid;
+ gchar *did;
+ gchar *odid;
+ gint id_count;
+ gint found;
+ gint lastfound;
+ gint count;
+ int ii;
+
+ static const gchar *tags[] =
+ {
+ "Xmp.xmpMM.InstanceID",
+ "Xmp.xmpMM.DocumentID",
+ "Xmp.xmpMM.OriginalDocumentID",
+ "Xmp.xmpMM.History"
+ };
+
+ static const gchar *history_tags[] =
+ {
+ "/stEvt:action",
+ "/stEvt:instanceID",
+ "/stEvt:when",
+ "/stEvt:softwareAgent",
+ "/stEvt:changed"
+ };
+
+ g_return_if_fail (GIMP_IS_METADATA (metadata));
+
+ /* Update new Instance ID */
+ uuid = gimp_metadata_get_guid ();
+
+ strcpy (iid_data, "xmp.iid:");
+ strcat (iid_data, uuid);
+
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tags[0], iid_data);
+ g_free (uuid);
+
+ /* Update new Document ID if none found */
+ did = gexiv2_metadata_get_tag_interpreted_string (GEXIV2_METADATA (metadata),
+ tags[1]);
+ if (! did || ! strlen (did))
+ {
+ gchar did_data[256];
+
+ uuid = gimp_metadata_get_guid ();
+
+ strcpy (did_data, "gimp:docid:gimp:");
+ strcat (did_data, uuid);
+
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tags[1], did_data);
+ g_free (uuid);
+ }
+
+ /* Update new Original Document ID if none found */
+ odid = gexiv2_metadata_get_tag_interpreted_string (GEXIV2_METADATA (metadata),
+ tags[2]);
+ if (! odid || ! strlen (odid))
+ {
+ gchar did_data[256];
+ gchar *uuid = gimp_metadata_get_guid ();
+
+ strcpy (did_data, "xmp.did:");
+ strcat (did_data, uuid);
+
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tags[2], did_data);
+ g_free (uuid);
+ }
+
+ /* Handle Xmp.xmpMM.History */
+
+ gexiv2_metadata_set_xmp_tag_struct (GEXIV2_METADATA (metadata),
+ tags[3],
+ GEXIV2_STRUCTURE_XA_SEQ);
+
+ /* Find current number of entries for Xmp.xmpMM.History */
+ found = 0;
+ for (count = 1; count < 65536; count++)
+ {
+ lastfound = 0;
+ for (ii = 0; ii < 5; ii++)
+ {
+ g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
+ tags[3], count, history_tags[ii]);
+
+ if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
+ tagstr))
+ {
+ lastfound = 1;
+ }
+ }
+
+ if (lastfound == 0)
+ break;
+
+ found++;
+ }
+
+ id_count = found + 1;
+
+ memset (tagstr, 0, sizeof (tagstr));
+ memset (strdata, 0, sizeof (strdata));
+
+ g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
+ tags[3], id_count, history_tags[0]);
+
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tagstr, "saved");
+
+ memset (tagstr, 0, sizeof (tagstr));
+ memset (strdata, 0, sizeof (strdata));
+
+ uuid = gimp_metadata_get_guid ();
+
+ g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
+ tags[3], id_count, history_tags[1]);
+ g_snprintf (strdata, sizeof (strdata), "xmp.iid:%s",
+ uuid);
+
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tagstr, strdata);
+ g_free(uuid);
+
+ memset (tagstr, 0, sizeof (tagstr));
+ memset (strdata, 0, sizeof (strdata));
+
+ g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
+ tags[3], id_count, history_tags[2]);
+
+ /* get local time */
+ time (&now);
+ now_tm = localtime (&now);
+
+ /* get timezone and fix format */
+ strftime (tzstr, 7, "%z", now_tm);
+ tzstr[6] = '\0';
+ tzstr[5] = tzstr[4];
+ tzstr[4] = tzstr[3];
+ tzstr[3] = ':';
+
+ /* get current time and timezone string */
+ strftime (timestr, 256, "%Y-%m-%dT%H:%M:%S", now_tm);
+ tmp = g_strdup_printf ("%s%s", timestr, tzstr);
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tagstr, tmp);
+ g_free (tmp);
+
+ memset (tagstr, 0, sizeof (tagstr));
+ memset (strdata, 0, sizeof (strdata));
+
+ g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
+ tags[3], id_count, history_tags[3]);
+
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tagstr,
+ "Gimp 2.10 "
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+ "(Windows)");
+#elif defined(__linux__)
+ "(Linux)");
+#elif defined(__APPLE__) && defined(__MACH__)
+ "(Mac OS)");
+#elif defined(unix) || defined(__unix__) || defined(__unix)
+ "(Unix)");
+#else
+ "(Unknown)");
+#endif
+
+ memset (tagstr, 0, sizeof (tagstr));
+ memset (strdata, 0, sizeof (strdata));
+
+ g_snprintf (tagstr, sizeof (tagstr), "%s[%d]%s",
+ tags[3], id_count, history_tags[4]);
+
+ strcpy (strdata, "/");
+ strcat (strdata, state_status);
+
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ tagstr, strdata);
+}
+
+/**
+ * gimp_metadata_new:
+ *
+ * Creates a new #GimpMetadata instance.
+ *
+ * Return value: The new #GimpMetadata.
+ *
+ * Since: 2.10
+ */
+GimpMetadata *
+gimp_metadata_new (void)
+{
+ GimpMetadata *metadata = NULL;
+
+ if (gexiv2_initialize ())
+ {
+ metadata = g_object_new (GIMP_TYPE_METADATA, NULL);
+
+ if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (metadata),
+ wilber_jpg, wilber_jpg_len,
+ NULL))
+ {
+ g_object_unref (metadata);
+
+ return NULL;
+ }
+ }
+
+ return metadata;
+}
+
+/**
+ * gimp_metadata_duplicate:
+ * @metadata: The object to duplicate, or %NULL.
+ *
+ * Duplicates a #GimpMetadata instance.
+ *
+ * Return value: The new #GimpMetadata, or %NULL if @metadata is %NULL.
+ *
+ * Since: 2.10
+ */
+GimpMetadata *
+gimp_metadata_duplicate (GimpMetadata *metadata)
+{
+ GimpMetadata *new_metadata = NULL;
+
+ g_return_val_if_fail (metadata == NULL || GIMP_IS_METADATA (metadata), NULL);
+
+ if (metadata)
+ {
+ gchar *xml;
+
+ xml = gimp_metadata_serialize (metadata);
+ new_metadata = gimp_metadata_deserialize (xml);
+ g_free (xml);
+ }
+
+ return new_metadata;
+}
+
+typedef struct
+{
+ gchar name[1024];
+ gboolean base64;
+ gboolean excessive_message_shown;
+ GimpMetadata *metadata;
+} GimpMetadataParseData;
+
+static const gchar*
+gimp_metadata_attribute_name_to_value (const gchar **attribute_names,
+ const gchar **attribute_values,
+ const gchar *name)
+{
+ while (*attribute_names)
+ {
+ if (! strcmp (*attribute_names, name))
+ {
+ return *attribute_values;
+ }
+
+ attribute_names++;
+ attribute_values++;
+ }
+
+ return NULL;
+}
+
+static void
+gimp_metadata_deserialize_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ GimpMetadataParseData *parse_data = user_data;
+
+ if (! strcmp (element_name, "tag"))
+ {
+ const gchar *name;
+ const gchar *encoding;
+
+ name = gimp_metadata_attribute_name_to_value (attribute_names,
+ attribute_values,
+ "name");
+ encoding = gimp_metadata_attribute_name_to_value (attribute_names,
+ attribute_values,
+ "encoding");
+
+ if (! name)
+ {
+ g_set_error (error, GIMP_METADATA_ERROR, 1001,
+ "Element 'tag' does not contain required attribute 'name'.");
+ return;
+ }
+
+ strncpy (parse_data->name, name, sizeof (parse_data->name));
+ parse_data->name[sizeof (parse_data->name) - 1] = 0;
+
+ parse_data->base64 = (encoding && ! strcmp (encoding, "base64"));
+ }
+}
+
+static void
+gimp_metadata_deserialize_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+}
+
+static void
+gimp_metadata_deserialize_text (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ GimpMetadataParseData *parse_data = user_data;
+ const gchar *current_element;
+
+ current_element = g_markup_parse_context_get_element (context);
+
+ if (! g_strcmp0 (current_element, "tag"))
+ {
+ gchar *value = g_strndup (text, text_len);
+
+ if (parse_data->base64)
+ {
+ guchar *decoded;
+ gsize len;
+
+ decoded = g_base64_decode (value, &len);
+
+ if (decoded[len - 1] == '\0')
+ {
+ g_free (value);
+ value = (gchar *) decoded;
+ }
+ else
+ {
+ g_clear_pointer (&value, g_free);
+ g_clear_pointer (&decoded, g_free);
+ }
+ }
+
+ if (value)
+ {
+ GExiv2Metadata *g2_metadata = GEXIV2_METADATA (parse_data->metadata);
+ gchar **values;
+
+ values = gexiv2_metadata_get_tag_multiple (g2_metadata,
+ parse_data->name);
+
+ if (values)
+ {
+ guint length = g_strv_length (values);
+
+ if (length > 1000 &&
+ ! g_strcmp0 (parse_data->name, "Xmp.photoshop.DocumentAncestors"))
+ {
+ /* Issue #8025, see also #7464 Some XCF images can have huge
+ * amounts of this tag, apparently due to a bug in PhotoShop.
+ * This makes deserializing it in the way we currently do
+ * too slow. Until we can change this let's ignore everything
+ * but the first 1000 values when serializing. */
+
+ if (! parse_data->excessive_message_shown)
+ {
+ g_message ("Excessive number of Xmp.photoshop.DocumentAncestors tags found. "
+ "Only keeping the first 1000 values.");
+ parse_data->excessive_message_shown = TRUE;
+ }
+ }
+ else
+ {
+ values = g_renew (gchar *, values, length + 2);
+ values[length] = value;
+ values[length + 1] = NULL;
+
+ gexiv2_metadata_set_tag_multiple (g2_metadata,
+ parse_data->name,
+ (const gchar **) values);
+ }
+ g_strfreev (values);
+ }
+ else
+ {
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (g2_metadata),
+ parse_data->name,
+ value);
+ g_free (value);
+ }
+ }
+ }
+}
+
+static void
+gimp_metadata_deserialize_error (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ g_printerr ("Metadata parse error: %s\n", error->message);
+}
+
+/**
+ * gimp_metadata_deserialize:
+ * @metadata_xml: A string of serialized metadata XML.
+ *
+ * Deserializes a string of XML that has been created by
+ * gimp_metadata_serialize().
+ *
+ * Return value: The new #GimpMetadata.
+ *
+ * Since: 2.10
+ */
+GimpMetadata *
+gimp_metadata_deserialize (const gchar *metadata_xml)
+{
+ GimpMetadata *metadata;
+ GMarkupParser markup_parser;
+ GimpMetadataParseData parse_data;
+ GMarkupParseContext *context;
+
+ g_return_val_if_fail (metadata_xml != NULL, NULL);
+
+ metadata = gimp_metadata_new ();
+
+ parse_data.metadata = metadata;
+ parse_data.excessive_message_shown = FALSE;
+
+ markup_parser.start_element = gimp_metadata_deserialize_start_element;
+ markup_parser.end_element = gimp_metadata_deserialize_end_element;
+ markup_parser.text = gimp_metadata_deserialize_text;
+ markup_parser.passthrough = NULL;
+ markup_parser.error = gimp_metadata_deserialize_error;
+
+ context = g_markup_parse_context_new (&markup_parser, 0, &parse_data, NULL);
+
+ g_markup_parse_context_parse (context,
+ metadata_xml, strlen (metadata_xml),
+ NULL);
+
+ g_markup_parse_context_unref (context);
+
+ return metadata;
+}
+
+static gchar *
+gimp_metadata_escape (const gchar *name,
+ const gchar *value,
+ gboolean *base64)
+{
+ if (! g_utf8_validate (value, -1, NULL))
+ {
+ gchar *encoded;
+
+ encoded = g_base64_encode ((const guchar *) value, strlen (value) + 1);
+
+ g_printerr ("Invalid UTF-8 in metadata value %s, encoding as base64: %s\n",
+ name, encoded);
+
+ *base64 = TRUE;
+
+ return encoded;
+ }
+
+ *base64 = FALSE;
+
+ return g_markup_escape_text (value, -1);
+}
+
+static void
+gimp_metadata_append_tag (GString *string,
+ const gchar *name,
+ gchar *value,
+ gboolean base64)
+{
+ if (value)
+ {
+ if (base64)
+ {
+ g_string_append_printf (string, " <tag name=\"%s\" encoding=\"base64\">%s</tag>\n",
+ name, value);
+ }
+ else
+ {
+ g_string_append_printf (string, " <tag name=\"%s\">%s</tag>\n",
+ name, value);
+ }
+
+ g_free (value);
+ }
+}
+
+/**
+ * gimp_metadata_serialize:
+ * @metadata: A #GimpMetadata instance.
+ *
+ * Serializes @metadata into an XML string that can later be deserialized
+ * using gimp_metadata_deserialize().
+ *
+ * Return value: The serialized XML string.
+ *
+ * Since: 2.10
+ */
+gchar *
+gimp_metadata_serialize (GimpMetadata *metadata)
+{
+ GString *string;
+ gchar **exif_data = NULL;
+ gchar **iptc_data = NULL;
+ gchar **xmp_data = NULL;
+ gchar *value;
+ gchar *escaped;
+ gboolean base64;
+ gint i;
+
+ g_return_val_if_fail (GIMP_IS_METADATA (metadata), NULL);
+
+ string = g_string_new (NULL);
+
+ g_string_append (string, "<?xml version='1.0' encoding='UTF-8'?>\n");
+ g_string_append (string, "<metadata>\n");
+
+ exif_data = gexiv2_metadata_get_exif_tags (GEXIV2_METADATA (metadata));
+
+ if (exif_data)
+ {
+ for (i = 0; exif_data[i] != NULL; i++)
+ {
+ value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
+ exif_data[i]);
+ escaped = gimp_metadata_escape (exif_data[i], value, &base64);
+ g_free (value);
+
+ gimp_metadata_append_tag (string, exif_data[i], escaped, base64);
+ }
+
+ g_strfreev (exif_data);
+ }
+
+ xmp_data = gexiv2_metadata_get_xmp_tags (GEXIV2_METADATA (metadata));
+
+ if (xmp_data)
+ {
+ for (i = 0; xmp_data[i] != NULL; i++)
+ {
+ /* XmpText is always a single value, but structures like
+ * XmpBag and XmpSeq can have multiple values that need to be
+ * treated separately or else saving will do things wrong. */
+ if (! g_strcmp0 (gexiv2_metadata_get_tag_type (xmp_data[i]), "XmpText"))
+ {
+ value = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
+ xmp_data[i]);
+ escaped = gimp_metadata_escape (xmp_data[i], value, &base64);
+ g_free (value);
+
+ gimp_metadata_append_tag (string, xmp_data[i], escaped, base64);
+ }
+ else
+ {
+ gchar **values;
+
+ values = gexiv2_metadata_get_tag_multiple (GEXIV2_METADATA (metadata),
+ xmp_data[i]);
+
+ if (values)
+ {
+ gint vi;
+ gint cnt = 0;
+
+ if (! g_strcmp0 (xmp_data[i], "Xmp.photoshop.DocumentAncestors"))
+ {
+ /* Issue #7464 Some images can have huge amounts of this
+ * tag (more than 100000 in certain cases), apparently
+ * due to a bug in PhotoShop. This makes deserializing it
+ * in the way we currently do too slow. Until we can
+ * change this let's remove everything but the first 1000
+ * values when serializing. */
+ cnt = g_strv_length (values);
+
+ if (cnt > 1000)
+ {
+ g_message ("Excessive number of Xmp.photoshop.DocumentAncestors tags found: %d. "
+ "Only keeping the first 1000 values.", cnt);
+ }
+ }
+
+ for (vi = 0; values[vi] != NULL && (cnt <= 1000 || vi < 1000); vi++)
+ {
+ escaped = gimp_metadata_escape (xmp_data[i], values[vi], &base64);
+ gimp_metadata_append_tag (string, xmp_data[i], escaped, base64);
+ }
+
+ g_strfreev (values);
+ }
+ }
+ }
+ g_strfreev (xmp_data);
+ }
+
+ iptc_data = gexiv2_metadata_get_iptc_tags (GEXIV2_METADATA (metadata));
+
+ if (iptc_data)
+ {
+ gchar **iptc_tags = iptc_data;
+ gchar *last_tag = NULL;
+
+ while (*iptc_tags)
+ {
+ gchar **values;
+
+ if (last_tag && ! strcmp (*iptc_tags, last_tag))
+ {
+ iptc_tags++;
+ continue;
+ }
+ last_tag = *iptc_tags;
+
+ values = gexiv2_metadata_get_tag_multiple (GEXIV2_METADATA (metadata),
+ *iptc_tags);
+
+ if (values)
+ {
+ for (i = 0; values[i] != NULL; i++)
+ {
+ escaped = gimp_metadata_escape (*iptc_tags, values[i], &base64);
+ gimp_metadata_append_tag (string, *iptc_tags, escaped, base64);
+ }
+
+ g_strfreev (values);
+ }
+
+ iptc_tags++;
+ }
+
+ g_strfreev (iptc_data);
+ }
+
+ g_string_append (string, "</metadata>\n");
+
+ return g_string_free (string, FALSE);
+}
+
+/**
+ * gimp_metadata_load_from_file:
+ * @file: The #GFile to load the metadata from
+ * @error: Return location for error message
+ *
+ * Loads #GimpMetadata from @file.
+ *
+ * Return value: The loaded #GimpMetadata.
+ *
+ * Since: 2.10
+ */
+GimpMetadata *
+gimp_metadata_load_from_file (GFile *file,
+ GError **error)
+{
+ GimpMetadata *meta = NULL;
+ gchar *path;
+ gchar *filename;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ path = g_file_get_path (file);
+
+ if (! path)
+ {
+ g_set_error (error, GIMP_METADATA_ERROR, 0,
+ _("Can load metadata only from local files"));
+ return NULL;
+ }
+
+ filename = g_strdup (path);
+
+ g_free (path);
+
+ if (gexiv2_initialize ())
+ {
+ meta = g_object_new (GIMP_TYPE_METADATA, NULL);
+
+ if (! gexiv2_metadata_open_path (GEXIV2_METADATA (meta), filename, error))
+ {
+ g_object_unref (meta);
+ g_free (filename);
+
+ return NULL;
+ }
+ }
+
+ g_free (filename);
+
+ return meta;
+}
+
+/**
+ * gimp_metadata_save_to_file:
+ * @metadata: A #GimpMetadata instance.
+ * @file: The file to save the metadata to
+ * @error: Return location for error message
+ *
+ * Saves @metadata to @file.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gimp_metadata_save_to_file (GimpMetadata *metadata,
+ GFile *file,
+ GError **error)
+{
+ gchar *path;
+ gchar *filename;
+ gboolean success;
+
+ g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ path = g_file_get_path (file);
+
+ if (! path)
+ {
+ g_set_error (error, GIMP_METADATA_ERROR, 0,
+ _("Can save metadata only to local files"));
+ return FALSE;
+ }
+
+ filename = g_strdup (path);
+
+ g_free (path);
+
+ success = gexiv2_metadata_save_file (GEXIV2_METADATA (metadata),
+ filename, error);
+
+ g_free (filename);
+
+ return success;
+}
+
+/**
+ * gimp_metadata_set_from_exif:
+ * @metadata: A #GimpMetadata instance.
+ * @exif_data: The blob of Exif data to set
+ * @exif_data_length: Length of @exif_data, in bytes
+ * @error: Return location for error message
+ *
+ * Sets the tags from a piece of Exif data on @metadata.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gimp_metadata_set_from_exif (GimpMetadata *metadata,
+ const guchar *exif_data,
+ gint exif_data_length,
+ GError **error)
+{
+
+ GByteArray *exif_bytes;
+ GimpMetadata *exif_metadata;
+ guint8 data_size[2] = { 0, };
+ const guint8 eoi[2] = { 0xff, 0xd9 };
+
+ g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
+ g_return_val_if_fail (exif_data != NULL || exif_data_length == 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (exif_data_length < 0 || exif_data_length + 2 >= 65536)
+ {
+ g_set_error (error, GIMP_METADATA_ERROR, 0,
+ _("Invalid Exif data size."));
+ return FALSE;
+ }
+
+ data_size[0] = ((exif_data_length + 2) & 0xFF00) >> 8;
+ data_size[1] = ((exif_data_length + 2) & 0x00FF);
+
+ exif_bytes = g_byte_array_new ();
+ exif_bytes = g_byte_array_append (exif_bytes,
+ minimal_exif, G_N_ELEMENTS (minimal_exif));
+ exif_bytes = g_byte_array_append (exif_bytes,
+ data_size, 2);
+ exif_bytes = g_byte_array_append (exif_bytes,
+ (guint8 *) exif_data, exif_data_length);
+ exif_bytes = g_byte_array_append (exif_bytes, eoi, 2);
+
+ exif_metadata = gimp_metadata_new ();
+
+ if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (exif_metadata),
+ exif_bytes->data, exif_bytes->len, error))
+ {
+ g_object_unref (exif_metadata);
+ g_byte_array_free (exif_bytes, TRUE);
+ return FALSE;
+ }
+
+ if (! gexiv2_metadata_has_exif (GEXIV2_METADATA (exif_metadata)))
+ {
+ g_set_error (error, GIMP_METADATA_ERROR, 0,
+ _("Parsing Exif data failed."));
+ g_object_unref (exif_metadata);
+ g_byte_array_free (exif_bytes, TRUE);
+ return FALSE;
+ }
+
+ gimp_metadata_add (exif_metadata, metadata);
+ g_object_unref (exif_metadata);
+ g_byte_array_free (exif_bytes, TRUE);
+
+ return TRUE;
+}
+
+/**
+ * gimp_metadata_set_from_iptc:
+ * @metadata: A #GimpMetadata instance.
+ * @iptc_data: The blob of Ipc data to set
+ * @iptc_data_length:Length of @iptc_data, in bytes
+ * @error: Return location for error message
+ *
+ * Sets the tags from a piece of IPTC data on @metadata.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gimp_metadata_set_from_iptc (GimpMetadata *metadata,
+ const guchar *iptc_data,
+ gint iptc_data_length,
+ GError **error)
+{
+ GimpMetadata *iptc_metadata;
+
+ g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
+ g_return_val_if_fail (iptc_data != NULL || iptc_data_length == 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ iptc_metadata = gimp_metadata_new ();
+
+ if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (iptc_metadata),
+ iptc_data, iptc_data_length, error))
+ {
+ g_object_unref (iptc_metadata);
+ return FALSE;
+ }
+
+ if (! gexiv2_metadata_has_iptc (GEXIV2_METADATA (iptc_metadata)))
+ {
+ g_set_error (error, GIMP_METADATA_ERROR, 0,
+ _("Parsing IPTC data failed."));
+ g_object_unref (iptc_metadata);
+ return FALSE;
+ }
+
+ gimp_metadata_add (iptc_metadata, metadata);
+ g_object_unref (iptc_metadata);
+
+ return TRUE;
+}
+
+/**
+ * gimp_metadata_set_from_xmp:
+ * @metadata: A #GimpMetadata instance.
+ * @xmp_data: The blob of Exif data to set
+ * @xmp_data_length: Length of @exif_data, in bytes
+ * @error: Return location for error message
+ *
+ * Sets the tags from a piece of XMP data on @metadata.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gimp_metadata_set_from_xmp (GimpMetadata *metadata,
+ const guchar *xmp_data,
+ gint xmp_data_length,
+ GError **error)
+{
+ GimpMetadata *xmp_metadata;
+
+ g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
+ g_return_val_if_fail (xmp_data != NULL || xmp_data_length == 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ xmp_metadata = gimp_metadata_new ();
+
+ if (! gexiv2_metadata_open_buf (GEXIV2_METADATA (xmp_metadata),
+ xmp_data, xmp_data_length, error))
+ {
+ g_object_unref (xmp_metadata);
+ return FALSE;
+ }
+
+ if (! gexiv2_metadata_has_xmp (GEXIV2_METADATA (xmp_metadata)))
+ {
+ g_set_error (error, GIMP_METADATA_ERROR, 0,
+ _("Parsing XMP data failed."));
+ g_object_unref (xmp_metadata);
+ return FALSE;
+ }
+
+ gimp_metadata_add (xmp_metadata, metadata);
+ g_object_unref (xmp_metadata);
+
+ return TRUE;
+}
+
+/**
+ * gimp_metadata_set_pixel_size:
+ * @metadata: A #GimpMetadata instance.
+ * @width: Width in pixels
+ * @height: Height in pixels
+ *
+ * Sets Exif.Image.ImageWidth and Exif.Image.ImageLength on @metadata.
+ *
+ * Since: 2.10
+ */
+void
+gimp_metadata_set_pixel_size (GimpMetadata *metadata,
+ gint width,
+ gint height)
+{
+ gchar buffer[32];
+
+ g_return_if_fail (GIMP_IS_METADATA (metadata));
+
+ g_snprintf (buffer, sizeof (buffer), "%d", width);
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ "Exif.Image.ImageWidth", buffer);
+
+ g_snprintf (buffer, sizeof (buffer), "%d", height);
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ "Exif.Image.ImageLength", buffer);
+}
+
+/**
+ * gimp_metadata_set_bits_per_sample:
+ * @metadata: A #GimpMetadata instance.
+ * @bits_per_sample: Bits per pixel, per component
+ *
+ * Sets Exif.Image.BitsPerSample on @metadata.
+ *
+ * Since: 2.10
+ */
+void
+gimp_metadata_set_bits_per_sample (GimpMetadata *metadata,
+ gint bits_per_sample)
+{
+ gchar buffer[32];
+
+ g_return_if_fail (GIMP_IS_METADATA (metadata));
+
+ g_snprintf (buffer, sizeof (buffer), "%d %d %d",
+ bits_per_sample, bits_per_sample, bits_per_sample);
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ "Exif.Image.BitsPerSample", buffer);
+}
+
+/**
+ * gimp_metadata_get_resolution:
+ * @metadata: A #GimpMetadata instance.
+ * @xres: Return location for the X Resolution, in ppi
+ * @yres: Return location for the Y Resolution, in ppi
+ * @unit: Return location for the unit unit
+ *
+ * Returns values based on Exif.Image.XResolution,
+ * Exif.Image.YResolution and Exif.Image.ResolutionUnit of @metadata.
+ *
+ * Return value: %TRUE on success, %FALSE otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gimp_metadata_get_resolution (GimpMetadata *metadata,
+ gdouble *xres,
+ gdouble *yres,
+ GimpUnit *unit)
+{
+ gint xnom, xdenom;
+ gint ynom, ydenom;
+
+ g_return_val_if_fail (GIMP_IS_METADATA (metadata), FALSE);
+
+ if (gexiv2_metadata_get_exif_tag_rational (GEXIV2_METADATA (metadata),
+ "Exif.Image.XResolution",
+ &xnom, &xdenom) &&
+ gexiv2_metadata_get_exif_tag_rational (GEXIV2_METADATA (metadata),
+ "Exif.Image.YResolution",
+ &ynom, &ydenom))
+ {
+ gchar *un;
+ gint exif_unit = 2;
+
+ un = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
+ "Exif.Image.ResolutionUnit");
+ if (un)
+ {
+ exif_unit = atoi (un);
+ g_free (un);
+ }
+
+ if (xnom != 0 && xdenom != 0 &&
+ ynom != 0 && ydenom != 0)
+ {
+ gdouble xresolution = (gdouble) xnom / (gdouble) xdenom;
+ gdouble yresolution = (gdouble) ynom / (gdouble) ydenom;
+
+ if (exif_unit == 3)
+ {
+ xresolution *= 2.54;
+ yresolution *= 2.54;
+ }
+
+ if (xresolution >= GIMP_MIN_RESOLUTION &&
+ xresolution <= GIMP_MAX_RESOLUTION &&
+ yresolution >= GIMP_MIN_RESOLUTION &&
+ yresolution <= GIMP_MAX_RESOLUTION)
+ {
+ if (xres)
+ *xres = xresolution;
+
+ if (yres)
+ *yres = yresolution;
+
+ if (unit)
+ {
+ if (exif_unit == 3)
+ *unit = GIMP_UNIT_MM;
+ else
+ *unit = GIMP_UNIT_INCH;
+ }
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * gimp_metadata_set_resolution:
+ * @metadata: A #GimpMetadata instance.
+ * @xres: The image's X Resolution, in ppi
+ * @yres: The image's Y Resolution, in ppi
+ * @unit: The image's unit
+ *
+ * Sets Exif.Image.XResolution, Exif.Image.YResolution and
+ * Exif.Image.ResolutionUnit of @metadata.
+ *
+ * Since: 2.10
+ */
+void
+gimp_metadata_set_resolution (GimpMetadata *metadata,
+ gdouble xres,
+ gdouble yres,
+ GimpUnit unit)
+{
+ gchar buffer[32];
+ gint exif_unit;
+ gint factor;
+
+ g_return_if_fail (GIMP_IS_METADATA (metadata));
+
+ if (gimp_unit_is_metric (unit))
+ {
+ xres /= 2.54;
+ yres /= 2.54;
+
+ exif_unit = 3;
+ }
+ else
+ {
+ exif_unit = 2;
+ }
+
+ for (factor = 1; factor <= 100 /* arbitrary */; factor++)
+ {
+ if (fabs (xres * factor - ROUND (xres * factor)) < 0.01 &&
+ fabs (yres * factor - ROUND (yres * factor)) < 0.01)
+ break;
+ }
+
+ gexiv2_metadata_set_exif_tag_rational (GEXIV2_METADATA (metadata),
+ "Exif.Image.XResolution",
+ ROUND (xres * factor), factor);
+
+ gexiv2_metadata_set_exif_tag_rational (GEXIV2_METADATA (metadata),
+ "Exif.Image.YResolution",
+ ROUND (yres * factor), factor);
+
+ g_snprintf (buffer, sizeof (buffer), "%d", exif_unit);
+ gexiv2_metadata_set_tag_string (GEXIV2_METADATA (metadata),
+ "Exif.Image.ResolutionUnit", buffer);
+}
+
+/**
+ * gimp_metadata_get_colorspace:
+ * @metadata: A #GimpMetadata instance.
+ *
+ * Returns values based on Exif.Photo.ColorSpace, Xmp.exif.ColorSpace,
+ * Exif.Iop.InteroperabilityIndex, Exif.Nikon3.ColorSpace,
+ * Exif.Canon.ColorSpace of @metadata.
+ *
+ * Return value: The colorspace specified by above tags.
+ *
+ * Since: 2.10
+ */
+GimpMetadataColorspace
+gimp_metadata_get_colorspace (GimpMetadata *metadata)
+{
+ glong exif_cs = -1;
+
+ g_return_val_if_fail (GIMP_IS_METADATA (metadata),
+ GIMP_METADATA_COLORSPACE_UNSPECIFIED);
+
+ /* the logic here was mostly taken from darktable and libkexiv2 */
+
+ if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
+ "Exif.Photo.ColorSpace"))
+ {
+ exif_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
+ "Exif.Photo.ColorSpace");
+ }
+ else if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
+ "Xmp.exif.ColorSpace"))
+ {
+ exif_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
+ "Xmp.exif.ColorSpace");
+ }
+
+ if (exif_cs == 0x01)
+ {
+ return GIMP_METADATA_COLORSPACE_SRGB;
+ }
+ else if (exif_cs == 0x02)
+ {
+ return GIMP_METADATA_COLORSPACE_ADOBERGB;
+ }
+ else
+ {
+ if (exif_cs == 0xffff)
+ {
+ gchar *iop_index;
+
+ iop_index = gexiv2_metadata_get_tag_string (GEXIV2_METADATA (metadata),
+ "Exif.Iop.InteroperabilityIndex");
+
+ if (! g_strcmp0 (iop_index, "R03"))
+ {
+ g_free (iop_index);
+
+ return GIMP_METADATA_COLORSPACE_ADOBERGB;
+ }
+ else if (! g_strcmp0 (iop_index, "R98"))
+ {
+ g_free (iop_index);
+
+ return GIMP_METADATA_COLORSPACE_SRGB;
+ }
+
+ g_free (iop_index);
+ }
+
+ if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
+ "Exif.Nikon3.ColorSpace"))
+ {
+ glong nikon_cs;
+
+ nikon_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
+ "Exif.Nikon3.ColorSpace");
+
+ if (nikon_cs == 0x01)
+ {
+ return GIMP_METADATA_COLORSPACE_SRGB;
+ }
+ else if (nikon_cs == 0x02)
+ {
+ return GIMP_METADATA_COLORSPACE_ADOBERGB;
+ }
+ }
+
+ if (gexiv2_metadata_has_tag (GEXIV2_METADATA (metadata),
+ "Exif.Canon.ColorSpace"))
+ {
+ glong canon_cs;
+
+ canon_cs = gexiv2_metadata_get_tag_long (GEXIV2_METADATA (metadata),
+ "Exif.Canon.ColorSpace");
+
+ if (canon_cs == 0x01)
+ {
+ return GIMP_METADATA_COLORSPACE_SRGB;
+ }
+ else if (canon_cs == 0x02)
+ {
+ return GIMP_METADATA_COLORSPACE_ADOBERGB;
+ }
+ }
+
+ if (exif_cs == 0xffff)
+ return GIMP_METADATA_COLORSPACE_UNCALIBRATED;
+ }
+
+ return GIMP_METADATA_COLORSPACE_UNSPECIFIED;
+}
+
+/**
+ * gimp_metadata_set_colorspace:
+ * @metadata: A #GimpMetadata instance.
+ * @colorspace: The color space.
+ *
+ * Sets Exif.Photo.ColorSpace, Xmp.exif.ColorSpace,
+ * Exif.Iop.InteroperabilityIndex, Exif.Nikon3.ColorSpace,
+ * Exif.Canon.ColorSpace of @metadata.
+ *
+ * Since: 2.10
+ */
+void
+gimp_metadata_set_colorspace (GimpMetadata *metadata,
+ GimpMetadataColorspace colorspace)
+{
+ GExiv2Metadata *g2metadata = GEXIV2_METADATA (metadata);
+
+ switch (colorspace)
+ {
+ case GIMP_METADATA_COLORSPACE_UNSPECIFIED:
+ gexiv2_metadata_clear_tag (g2metadata, "Exif.Photo.ColorSpace");
+ gexiv2_metadata_clear_tag (g2metadata, "Xmp.exif.ColorSpace");
+ gexiv2_metadata_clear_tag (g2metadata, "Exif.Iop.InteroperabilityIndex");
+ gexiv2_metadata_clear_tag (g2metadata, "Exif.Nikon3.ColorSpace");
+ gexiv2_metadata_clear_tag (g2metadata, "Exif.Canon.ColorSpace");
+ break;
+
+ case GIMP_METADATA_COLORSPACE_UNCALIBRATED:
+ gexiv2_metadata_set_tag_long (g2metadata, "Exif.Photo.ColorSpace", 0xffff);
+ if (gexiv2_metadata_has_tag (g2metadata, "Xmp.exif.ColorSpace"))
+ gexiv2_metadata_set_tag_long (g2metadata, "Xmp.exif.ColorSpace", 0xffff);
+ gexiv2_metadata_clear_tag (g2metadata, "Exif.Iop.InteroperabilityIndex");
+ gexiv2_metadata_clear_tag (g2metadata, "Exif.Nikon3.ColorSpace");
+ gexiv2_metadata_clear_tag (g2metadata, "Exif.Canon.ColorSpace");
+ break;
+
+ case GIMP_METADATA_COLORSPACE_SRGB:
+ gexiv2_metadata_set_tag_long (g2metadata, "Exif.Photo.ColorSpace", 0x01);
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Xmp.exif.ColorSpace"))
+ gexiv2_metadata_set_tag_long (g2metadata, "Xmp.exif.ColorSpace", 0x01);
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Exif.Iop.InteroperabilityIndex"))
+ gexiv2_metadata_set_tag_string (g2metadata,
+ "Exif.Iop.InteroperabilityIndex", "R98");
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Exif.Nikon3.ColorSpace"))
+ gexiv2_metadata_set_tag_long (g2metadata, "Exif.Nikon3.ColorSpace", 0x01);
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Exif.Canon.ColorSpace"))
+ gexiv2_metadata_set_tag_long (g2metadata, "Exif.Canon.ColorSpace", 0x01);
+ break;
+
+ case GIMP_METADATA_COLORSPACE_ADOBERGB:
+ gexiv2_metadata_set_tag_long (g2metadata, "Exif.Photo.ColorSpace", 0x02);
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Xmp.exif.ColorSpace"))
+ gexiv2_metadata_set_tag_long (g2metadata, "Xmp.exif.ColorSpace", 0x02);
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Exif.Iop.InteroperabilityIndex"))
+ gexiv2_metadata_set_tag_string (g2metadata,
+ "Exif.Iop.InteroperabilityIndex", "R03");
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Exif.Nikon3.ColorSpace"))
+ gexiv2_metadata_set_tag_long (g2metadata, "Exif.Nikon3.ColorSpace", 0x02);
+
+ if (gexiv2_metadata_has_tag (g2metadata, "Exif.Canon.ColorSpace"))
+ gexiv2_metadata_set_tag_long (g2metadata, "Exif.Canon.ColorSpace", 0x02);
+ break;
+ }
+}
+
+/**
+ * gimp_metadata_is_tag_supported:
+ * @tag: A metadata tag name
+ * @mime_type: A mime type
+ *
+ * Returns whether @tag is supported in a file of type @mime_type.
+ *
+ * Return value: %TRUE if the @tag supported with @mime_type, %FALSE otherwise.
+ *
+ * Since: 2.10
+ */
+gboolean
+gimp_metadata_is_tag_supported (const gchar *tag,
+ const gchar *mime_type)
+{
+ gint j;
+
+ g_return_val_if_fail (tag != NULL, FALSE);
+ g_return_val_if_fail (mime_type != NULL, FALSE);
+
+ for (j = 0; j < G_N_ELEMENTS (unsupported_tags); j++)
+ {
+ if (g_str_has_prefix (tag, unsupported_tags[j]))
+ {
+ return FALSE;
+ }
+ }
+
+ if (! strcmp (mime_type, "image/jpeg"))
+ {
+ for (j = 0; j < G_N_ELEMENTS (tiff_tags); j++)
+ {
+ if (g_str_has_prefix (tag, tiff_tags[j]))
+ {
+ return FALSE;
+ }
+ }
+ }
+ else if (! strcmp (mime_type, "image/tiff"))
+ {
+ for (j = 0; j < G_N_ELEMENTS (jpeg_tags); j++)
+ {
+ if (g_str_has_prefix (tag, jpeg_tags[j]))
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+/* private functions */
+
+static GQuark
+gimp_metadata_error_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (G_UNLIKELY (quark == 0))
+ quark = g_quark_from_static_string ("gimp-metadata-error-quark");
+
+ return quark;
+}
+
+static void
+gimp_metadata_copy_tag (GExiv2Metadata *src,
+ GExiv2Metadata *dest,
+ const gchar *tag)
+{
+#if GEXIV2_CHECK_VERSION(0, 12, 2)
+ gchar **values;
+ GError *error = NULL;
+
+ values = gexiv2_metadata_try_get_tag_multiple (src, tag, &error);
+
+ if (error)
+ {
+ g_printerr ("%s: %s\n", G_STRFUNC, error->message);
+ g_clear_error (&error);
+ g_strfreev (values);
+ }
+ else if (values)
+ {
+ gexiv2_metadata_try_set_tag_multiple (dest, tag, (const gchar **) values, &error);
+ if (error)
+ {
+ g_warning ("%s: failed to set multiple metadata '%s': %s\n",
+ G_STRFUNC, tag, error->message);
+ g_clear_error (&error);
+ }
+
+ g_strfreev (values);
+ }
+ else
+ {
+ gchar *value = gexiv2_metadata_try_get_tag_string (src, tag, &error);
+
+ if (value)
+ {
+ gexiv2_metadata_try_set_tag_string (dest, tag, value, &error);
+ if (error)
+ {
+ g_warning ("%s: failed to set metadata '%s': %s\n",
+ G_STRFUNC, tag, error->message);
+ g_clear_error (&error);
+ }
+ g_free (value);
+ }
+ else if (error)
+ {
+ g_warning ("%s: failed to get metadata '%s': %s\n",
+ G_STRFUNC, tag, error->message);
+ g_clear_error (&error);
+ }
+ }
+#else
+ gchar **values = gexiv2_metadata_get_tag_multiple (src, tag);
+
+ if (values)
+ {
+ gexiv2_metadata_set_tag_multiple (dest, tag, (const gchar **) values);
+ g_strfreev (values);
+ }
+ else
+ {
+ gchar *value = gexiv2_metadata_get_tag_string (src, tag);
+
+ if (value)
+ {
+ gexiv2_metadata_set_tag_string (dest, tag, value);
+ g_free (value);
+ }
+ }
+#endif
+}
+
+static void
+gimp_metadata_copy_tags (GExiv2Metadata *src,
+ GExiv2Metadata *dest,
+ const gchar **tags)
+{
+ gint i;
+
+ for (i = 0; tags[i] != NULL; i++)
+ {
+ /* don't copy the same tag multiple times */
+ if (i > 0 && ! strcmp (tags[i], tags[i - 1]))
+ continue;
+
+ gimp_metadata_copy_tag (src, dest, tags[i]);
+ }
+ }
+
+static void
+gimp_metadata_add (GimpMetadata *src,
+ GimpMetadata *dest)
+{
+ GExiv2Metadata *g2src = GEXIV2_METADATA (src);
+ GExiv2Metadata *g2dest = GEXIV2_METADATA (dest);
+
+ if (gexiv2_metadata_get_supports_exif (g2src) &&
+ gexiv2_metadata_get_supports_exif (g2dest))
+ {
+ gchar **exif_tags = gexiv2_metadata_get_exif_tags (g2src);
+
+ if (exif_tags)
+ {
+ gimp_metadata_copy_tags (g2src, g2dest,
+ (const gchar **) exif_tags);
+ g_strfreev (exif_tags);
+ }
+ }
+
+ if (gexiv2_metadata_get_supports_xmp (g2src) &&
+ gexiv2_metadata_get_supports_xmp (g2dest))
+ {
+ gchar **xmp_tags = gexiv2_metadata_get_xmp_tags (g2src);
+
+ if (xmp_tags)
+ {
+ gimp_metadata_copy_tags (g2src, g2dest,
+ (const gchar **) xmp_tags);
+ g_strfreev (xmp_tags);
+ }
+ }
+
+ if (gexiv2_metadata_get_supports_iptc (g2src) &&
+ gexiv2_metadata_get_supports_iptc (g2dest))
+ {
+ gchar **iptc_tags = gexiv2_metadata_get_iptc_tags (g2src);
+
+ if (iptc_tags)
+ {
+ gimp_metadata_copy_tags (g2src, g2dest,
+ (const gchar **) iptc_tags);
+ g_strfreev (iptc_tags);
+ }
+ }
+}
diff --git a/libgimpbase/gimpmetadata.h b/libgimpbase/gimpmetadata.h
new file mode 100644
index 0000000..30a6f39
--- /dev/null
+++ b/libgimpbase/gimpmetadata.h
@@ -0,0 +1,154 @@
+/* LIBGIMPBASE - The GIMP Basic Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpmetadata.h
+ * Copyright (C) 2013 Hartmut Kuhse <hartmutkuhse@src.gnome.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_METADATA_H__
+#define __GIMP_METADATA_H__
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_METADATA (gimp_metadata_get_type ())
+#define GIMP_METADATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_METADATA, GimpMetadata))
+#define GIMP_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_METADATA, GimpMetadataClass))
+#define GIMP_IS_METADATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_METADATA))
+#define GIMP_IS_METADATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_METADATA))
+#define GIMP_METADATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_METADATA, GimpMetadataClass))
+
+
+/**
+ * GimpMetadataLoadFlags:
+ * @GIMP_METADATA_LOAD_COMMENT: Load the comment
+ * @GIMP_METADATA_LOAD_RESOLUTION: Load the resolution
+ * @GIMP_METADATA_LOAD_ORIENTATION: Load the orientation (rotation)
+ * @GIMP_METADATA_LOAD_COLORSPACE: Load the colorspace
+ * @GIMP_METADATA_LOAD_ALL: Load all of the above
+ *
+ * What metadata to load when importing images.
+ **/
+typedef enum
+{
+ GIMP_METADATA_LOAD_COMMENT = 1 << 0,
+ GIMP_METADATA_LOAD_RESOLUTION = 1 << 1,
+ GIMP_METADATA_LOAD_ORIENTATION = 1 << 2,
+ GIMP_METADATA_LOAD_COLORSPACE = 1 << 3,
+
+ GIMP_METADATA_LOAD_ALL = 0xffffffff
+} GimpMetadataLoadFlags;
+
+
+/**
+ * GimpMetadataSaveFlags:
+ * @GIMP_METADATA_SAVE_EXIF: Save EXIF
+ * @GIMP_METADATA_SAVE_XMP: Save XMP
+ * @GIMP_METADATA_SAVE_IPTC: Save IPTC
+ * @GIMP_METADATA_SAVE_THUMBNAIL: Save a thumbnail of the image
+ * @GIMP_METADATA_SAVE_COLOR_PROFILE: Save the image's color profile
+ * Since: 2.10.10
+ * @GIMP_METADATA_SAVE_ALL: Save all of the above
+ *
+ * What kinds of metadata to save when exporting images.
+ **/
+typedef enum
+{
+ GIMP_METADATA_SAVE_EXIF = 1 << 0,
+ GIMP_METADATA_SAVE_XMP = 1 << 1,
+ GIMP_METADATA_SAVE_IPTC = 1 << 2,
+ GIMP_METADATA_SAVE_THUMBNAIL = 1 << 3,
+ GIMP_METADATA_SAVE_COLOR_PROFILE = 1 << 4,
+
+ GIMP_METADATA_SAVE_ALL = 0xffffffff
+} GimpMetadataSaveFlags;
+
+
+/**
+ * GimpMetadataColorspace:
+ * @GIMP_METADATA_COLORSPACE_UNSPECIFIED: Unspecified
+ * @GIMP_METADATA_COLORSPACE_UNCALIBRATED: Uncalibrated
+ * @GIMP_METADATA_COLORSPACE_SRGB: sRGB
+ * @GIMP_METADATA_COLORSPACE_ADOBERGB: Adobe RGB
+ *
+ * Well-defined colorspace information available from metadata
+ **/
+typedef enum
+{
+ GIMP_METADATA_COLORSPACE_UNSPECIFIED,
+ GIMP_METADATA_COLORSPACE_UNCALIBRATED,
+ GIMP_METADATA_COLORSPACE_SRGB,
+ GIMP_METADATA_COLORSPACE_ADOBERGB
+} GimpMetadataColorspace;
+
+
+GType gimp_metadata_get_type (void) G_GNUC_CONST;
+
+GimpMetadata * gimp_metadata_new (void);
+GimpMetadata * gimp_metadata_duplicate (GimpMetadata *metadata);
+
+GimpMetadata * gimp_metadata_deserialize (const gchar *metadata_xml);
+gchar * gimp_metadata_serialize (GimpMetadata *metadata);
+gchar * gimp_metadata_get_guid (void);
+
+void gimp_metadata_add_xmp_history (GimpMetadata *metadata,
+ gchar *state_status);
+
+GimpMetadata * gimp_metadata_load_from_file (GFile *file,
+ GError **error);
+gboolean gimp_metadata_save_to_file (GimpMetadata *metadata,
+ GFile *file,
+ GError **error);
+
+gboolean gimp_metadata_set_from_exif (GimpMetadata *metadata,
+ const guchar *exif_data,
+ gint exif_data_length,
+ GError **error);
+gboolean gimp_metadata_set_from_iptc (GimpMetadata *metadata,
+ const guchar *iptc_data,
+ gint iptc_data_length,
+ GError **error);
+gboolean gimp_metadata_set_from_xmp (GimpMetadata *metadata,
+ const guchar *xmp_data,
+ gint xmp_data_length,
+ GError **error);
+
+void gimp_metadata_set_pixel_size (GimpMetadata *metadata,
+ gint width,
+ gint height);
+void gimp_metadata_set_bits_per_sample (GimpMetadata *metadata,
+ gint bits_per_sample);
+
+gboolean gimp_metadata_get_resolution (GimpMetadata *metadata,
+ gdouble *xres,
+ gdouble *yres,
+ GimpUnit *unit);
+void gimp_metadata_set_resolution (GimpMetadata *metadata,
+ gdouble xres,
+ gdouble yres,
+ GimpUnit unit);
+
+GimpMetadataColorspace
+ gimp_metadata_get_colorspace (GimpMetadata *metadata);
+void gimp_metadata_set_colorspace (GimpMetadata *metadata,
+ GimpMetadataColorspace colorspace);
+
+gboolean gimp_metadata_is_tag_supported (const gchar *tag,
+ const gchar *mime_type);
+
+G_END_DECLS
+
+#endif /* __GIMP_METADATA_H__ */
diff --git a/libgimpbase/gimpparam.h b/libgimpbase/gimpparam.h
new file mode 100644
index 0000000..6b6427c
--- /dev/null
+++ b/libgimpbase/gimpparam.h
@@ -0,0 +1,66 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_PARAM_H__
+#define __GIMP_PARAM_H__
+
+
+/**
+ * SECTION: gimpparam
+ * @title: gimpparam
+ * @short_description: Definitions of useful #GParamFlags.
+ *
+ * Definitions of useful #GParamFlags.
+ **/
+
+
+/**
+ * GIMP_PARAM_STATIC_STRINGS:
+ *
+ * Since: 2.4
+ **/
+#define GIMP_PARAM_STATIC_STRINGS (G_PARAM_STATIC_NAME | \
+ G_PARAM_STATIC_NICK | \
+ G_PARAM_STATIC_BLURB)
+
+/**
+ * GIMP_PARAM_READABLE:
+ *
+ * Since: 2.4
+ **/
+#define GIMP_PARAM_READABLE (G_PARAM_READABLE | \
+ GIMP_PARAM_STATIC_STRINGS)
+
+/**
+ * GIMP_PARAM_WRITABLE:
+ *
+ * Since: 2.4
+ **/
+#define GIMP_PARAM_WRITABLE (G_PARAM_WRITABLE | \
+ GIMP_PARAM_STATIC_STRINGS)
+
+/**
+ * GIMP_PARAM_READWRITE:
+ *
+ * Since: 2.4
+ **/
+#define GIMP_PARAM_READWRITE (G_PARAM_READWRITE | \
+ GIMP_PARAM_STATIC_STRINGS)
+
+
+#endif /* __GIMP_PARAM_H__ */
diff --git a/libgimpbase/gimpparasite.c b/libgimpbase/gimpparasite.c
new file mode 100644
index 0000000..ac66491
--- /dev/null
+++ b/libgimpbase/gimpparasite.c
@@ -0,0 +1,352 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpparasite.c
+ * Copyright (C) 1998 Jay Cox <jaycox@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+
+#include <glib-object.h>
+
+#ifdef G_OS_WIN32
+#include <process.h> /* For _getpid() */
+#endif
+
+#include "gimpbasetypes.h"
+
+#include "gimpparasite.h"
+
+
+/**
+ * SECTION: gimpparasite
+ * @title: GimpParasite
+ * @short_description: Arbitrary pieces of data which can be attached
+ * to various GIMP objects.
+ * @see_also: gimp_image_parasite_attach(),
+ * gimp_drawable_parasite_attach(), gimp_parasite_attach()
+ * and their related functions.
+ *
+ * Arbitrary pieces of data which can be attached to various GIMP objects.
+ **/
+
+
+/*
+ * GIMP_TYPE_PARASITE
+ */
+
+GType
+gimp_parasite_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type)
+ type = g_boxed_type_register_static ("GimpParasite",
+ (GBoxedCopyFunc) gimp_parasite_copy,
+ (GBoxedFreeFunc) gimp_parasite_free);
+
+ return type;
+}
+
+
+/*
+ * GIMP_TYPE_PARAM_PARASITE
+ */
+
+#define GIMP_PARAM_SPEC_PARASITE(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_PARASITE, GimpParamSpecParasite))
+
+typedef struct _GimpParamSpecParasite GimpParamSpecParasite;
+
+struct _GimpParamSpecParasite
+{
+ GParamSpecBoxed parent_instance;
+};
+
+static void gimp_param_parasite_class_init (GParamSpecClass *class);
+static void gimp_param_parasite_init (GParamSpec *pspec);
+static gboolean gimp_param_parasite_validate (GParamSpec *pspec,
+ GValue *value);
+static gint gimp_param_parasite_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2);
+
+GType
+gimp_param_parasite_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type)
+ {
+ const GTypeInfo type_info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_parasite_class_init,
+ NULL, NULL,
+ sizeof (GimpParamSpecParasite),
+ 0,
+ (GInstanceInitFunc) gimp_param_parasite_init
+ };
+
+ type = g_type_register_static (G_TYPE_PARAM_BOXED,
+ "GimpParamParasite",
+ &type_info, 0);
+ }
+
+ return type;
+}
+
+static void
+gimp_param_parasite_class_init (GParamSpecClass *class)
+{
+ class->value_type = GIMP_TYPE_PARASITE;
+ class->value_validate = gimp_param_parasite_validate;
+ class->values_cmp = gimp_param_parasite_values_cmp;
+}
+
+static void
+gimp_param_parasite_init (GParamSpec *pspec)
+{
+}
+
+static gboolean
+gimp_param_parasite_validate (GParamSpec *pspec,
+ GValue *value)
+{
+ GimpParasite *parasite = value->data[0].v_pointer;
+
+ if (! parasite)
+ {
+ return TRUE;
+ }
+ else if (parasite->name == NULL ||
+ *parasite->name == '\0' ||
+ ! g_utf8_validate (parasite->name, -1, NULL) ||
+ (parasite->size == 0 && parasite->data != NULL) ||
+ (parasite->size > 0 && parasite->data == NULL))
+ {
+ g_value_set_boxed (value, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gint
+gimp_param_parasite_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2)
+{
+ GimpParasite *parasite1 = value1->data[0].v_pointer;
+ GimpParasite *parasite2 = value2->data[0].v_pointer;
+
+ /* try to return at least *something*, it's useless anyway... */
+
+ if (! parasite1)
+ return parasite2 != NULL ? -1 : 0;
+ else if (! parasite2)
+ return parasite1 != NULL;
+ else
+ return gimp_parasite_compare (parasite1, parasite2);
+}
+
+GParamSpec *
+gimp_param_spec_parasite (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamFlags flags)
+{
+ GimpParamSpecParasite *parasite_spec;
+
+ parasite_spec = g_param_spec_internal (GIMP_TYPE_PARAM_PARASITE,
+ name, nick, blurb, flags);
+
+ return G_PARAM_SPEC (parasite_spec);
+}
+
+
+#ifdef DEBUG
+static void
+gimp_parasite_print (GimpParasite *parasite)
+{
+ if (parasite == NULL)
+ {
+ g_print ("pid %d: attempt to print a null parasite\n", getpid ());
+ return;
+ }
+
+ g_print ("pid %d: parasite: %p\n", getpid (), parasite);
+
+ if (parasite->name)
+ g_print ("\tname: %s\n", parasite->name);
+ else
+ g_print ("\tname: NULL\n");
+
+ g_print ("\tflags: %d\n", parasite->flags);
+ g_print ("\tsize: %d\n", parasite->size);
+ if (parasite->size > 0)
+ g_print ("\tdata: %p\n", parasite->data);
+}
+#endif
+
+GimpParasite *
+gimp_parasite_new (const gchar *name,
+ guint32 flags,
+ guint32 size,
+ gconstpointer data)
+{
+ GimpParasite *parasite;
+
+ if (! (name && *name))
+ return NULL;
+
+ parasite = g_slice_new (GimpParasite);
+ parasite->name = g_strdup (name);
+ parasite->flags = (flags & 0xFF);
+ parasite->size = size;
+
+ if (size)
+ parasite->data = g_memdup (data, size);
+ else
+ parasite->data = NULL;
+
+ return parasite;
+}
+
+void
+gimp_parasite_free (GimpParasite *parasite)
+{
+ if (parasite == NULL)
+ return;
+
+ if (parasite->name)
+ g_free (parasite->name);
+
+ if (parasite->data)
+ g_free (parasite->data);
+
+ g_slice_free (GimpParasite, parasite);
+}
+
+gboolean
+gimp_parasite_is_type (const GimpParasite *parasite,
+ const gchar *name)
+{
+ if (!parasite || !parasite->name)
+ return FALSE;
+
+ return (strcmp (parasite->name, name) == 0);
+}
+
+GimpParasite *
+gimp_parasite_copy (const GimpParasite *parasite)
+{
+ if (parasite == NULL)
+ return NULL;
+
+ return gimp_parasite_new (parasite->name, parasite->flags,
+ parasite->size, parasite->data);
+}
+
+gboolean
+gimp_parasite_compare (const GimpParasite *a,
+ const GimpParasite *b)
+{
+ if (a && b &&
+ a->name && b->name &&
+ strcmp (a->name, b->name) == 0 &&
+ a->flags == b->flags &&
+ a->size == b->size)
+ {
+ if (a->data == NULL && b->data == NULL)
+ return TRUE;
+ else if (a->data && b->data && memcmp (a->data, b->data, a->size) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gulong
+gimp_parasite_flags (const GimpParasite *parasite)
+{
+ if (parasite == NULL)
+ return 0;
+
+ return parasite->flags;
+}
+
+gboolean
+gimp_parasite_is_persistent (const GimpParasite *parasite)
+{
+ if (parasite == NULL)
+ return FALSE;
+
+ return (parasite->flags & GIMP_PARASITE_PERSISTENT);
+}
+
+gboolean
+gimp_parasite_is_undoable (const GimpParasite *parasite)
+{
+ if (parasite == NULL)
+ return FALSE;
+
+ return (parasite->flags & GIMP_PARASITE_UNDOABLE);
+}
+
+gboolean
+gimp_parasite_has_flag (const GimpParasite *parasite,
+ gulong flag)
+{
+ if (parasite == NULL)
+ return FALSE;
+
+ return (parasite->flags & flag);
+}
+
+const gchar *
+gimp_parasite_name (const GimpParasite *parasite)
+{
+ if (parasite)
+ return parasite->name;
+
+ return NULL;
+}
+
+gconstpointer
+gimp_parasite_data (const GimpParasite *parasite)
+{
+ if (parasite)
+ return parasite->data;
+
+ return NULL;
+}
+
+glong
+gimp_parasite_data_size (const GimpParasite *parasite)
+{
+ if (parasite)
+ return parasite->size;
+
+ return 0;
+}
diff --git a/libgimpbase/gimpparasite.h b/libgimpbase/gimpparasite.h
new file mode 100644
index 0000000..3c17bf7
--- /dev/null
+++ b/libgimpbase/gimpparasite.h
@@ -0,0 +1,113 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpparasite.h
+ * Copyright (C) 1998 Jay Cox <jaycox@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_PARASITE_H__
+#define __GIMP_PARASITE_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/*
+ * GIMP_TYPE_PARASITE
+ */
+
+#define GIMP_TYPE_PARASITE (gimp_parasite_get_type ())
+#define GIMP_VALUE_HOLDS_PARASITE(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_PARASITE))
+
+GType gimp_parasite_get_type (void) G_GNUC_CONST;
+
+
+/*
+ * GIMP_TYPE_PARAM_PARASITE
+ */
+
+#define GIMP_TYPE_PARAM_PARASITE (gimp_param_parasite_get_type ())
+#define GIMP_IS_PARAM_SPEC_PARASITE(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_PARASITE))
+
+GType gimp_param_parasite_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_parasite (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamFlags flags);
+
+
+#define GIMP_PARASITE_PERSISTENT 1
+#define GIMP_PARASITE_UNDOABLE 2
+
+#define GIMP_PARASITE_ATTACH_PARENT (0x80 << 8)
+#define GIMP_PARASITE_PARENT_PERSISTENT (GIMP_PARASITE_PERSISTENT << 8)
+#define GIMP_PARASITE_PARENT_UNDOABLE (GIMP_PARASITE_UNDOABLE << 8)
+
+#define GIMP_PARASITE_ATTACH_GRANDPARENT (0x80 << 16)
+#define GIMP_PARASITE_GRANDPARENT_PERSISTENT (GIMP_PARASITE_PERSISTENT << 16)
+#define GIMP_PARASITE_GRANDPARENT_UNDOABLE (GIMP_PARASITE_UNDOABLE << 16)
+
+
+/**
+ * GimpParasite:
+ * @name: the parasite name, USE A UNIQUE PREFIX
+ * @flags: the parasite flags, like save in XCF etc.
+ * @size: the parasite size in bytes
+ * @data: the parasite data, the owner os the parasite is responsible
+ * for tracking byte order and internal structure
+ **/
+struct _GimpParasite
+{
+ gchar *name;
+ guint32 flags;
+ guint32 size;
+ gpointer data;
+};
+
+
+GimpParasite * gimp_parasite_new (const gchar *name,
+ guint32 flags,
+ guint32 size,
+ gconstpointer data);
+void gimp_parasite_free (GimpParasite *parasite);
+
+GimpParasite * gimp_parasite_copy (const GimpParasite *parasite);
+
+gboolean gimp_parasite_compare (const GimpParasite *a,
+ const GimpParasite *b);
+
+gboolean gimp_parasite_is_type (const GimpParasite *parasite,
+ const gchar *name);
+gboolean gimp_parasite_is_persistent (const GimpParasite *parasite);
+gboolean gimp_parasite_is_undoable (const GimpParasite *parasite);
+gboolean gimp_parasite_has_flag (const GimpParasite *parasite,
+ gulong flag);
+gulong gimp_parasite_flags (const GimpParasite *parasite);
+const gchar * gimp_parasite_name (const GimpParasite *parasite);
+gconstpointer gimp_parasite_data (const GimpParasite *parasite);
+glong gimp_parasite_data_size (const GimpParasite *parasite);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_PARASITE_H__ */
diff --git a/libgimpbase/gimpparasiteio.c b/libgimpbase/gimpparasiteio.c
new file mode 100644
index 0000000..727048a
--- /dev/null
+++ b/libgimpbase/gimpparasiteio.c
@@ -0,0 +1,204 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpparasiteio.c
+ * Copyright (C) 1999 Tor Lillqvist <tml@iki.fi>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Functions for building and parsing string representations of
+ * various standard parasite types.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "gimpparasiteio.h"
+
+
+/**
+ * SECTION: gimpparasiteio
+ * @title: gimpparasiteio
+ * @short_description: Utility functions to (de)serialize certain C
+ * structures to/from #GimpParasite's.
+ * @see_also: #GimpParasite
+ *
+ * Utility functions to (de)serialize certain C structures to/from*
+ * #GimpParasite's.
+ **/
+
+
+void
+gimp_pixpipe_params_init (GimpPixPipeParams *params)
+{
+ gint i;
+
+ g_return_if_fail (params != NULL);
+
+ params->step = 100;
+ params->ncells = 1;
+ params->cellwidth = 1;
+ params->cellheight = 1;
+ params->dim = 1;
+ params->cols = 1;
+ params->rows = 1;
+ params->placement = g_strdup ("constant");
+
+ for (i = 0; i < GIMP_PIXPIPE_MAXDIM; i++)
+ params->selection[i] = g_strdup ("random");
+
+ params->rank[0] = 1;
+ for (i = 1; i < GIMP_PIXPIPE_MAXDIM; i++)
+ params->rank[i] = 0;
+}
+
+void
+gimp_pixpipe_params_parse (const gchar *string,
+ GimpPixPipeParams *params)
+{
+ gchar *copy;
+ gchar *p, *q, *r;
+ gint i;
+
+ g_return_if_fail (string != NULL);
+ g_return_if_fail (params != NULL);
+
+ copy = g_strdup (string);
+
+ q = copy;
+ while ((p = strtok (q, " \r\n")) != NULL)
+ {
+ q = NULL;
+ r = strchr (p, ':');
+ if (r)
+ *r = 0;
+
+ if (strcmp (p, "ncells") == 0)
+ {
+ if (r)
+ params->ncells = atoi (r + 1);
+ }
+ else if (strcmp (p, "step") == 0)
+ {
+ if (r)
+ params->step = atoi (r + 1);
+ }
+ else if (strcmp (p, "dim") == 0)
+ {
+ if (r)
+ {
+ params->dim = atoi (r + 1);
+ params->dim = CLAMP (params->dim, 1, GIMP_PIXPIPE_MAXDIM);
+ }
+ }
+ else if (strcmp (p, "cols") == 0)
+ {
+ if (r)
+ params->cols = atoi (r + 1);
+ }
+ else if (strcmp (p, "rows") == 0)
+ {
+ if (r)
+ params->rows = atoi (r + 1);
+ }
+ else if (strcmp (p, "cellwidth") == 0)
+ {
+ if (r)
+ params->cellwidth = atoi (r + 1);
+ }
+ else if (strcmp (p, "cellheight") == 0)
+ {
+ if (r)
+ params->cellheight = atoi (r + 1);
+ }
+ else if (strcmp (p, "placement") == 0)
+ {
+ if (r)
+ {
+ g_free (params->placement);
+ params->placement = g_strdup (r + 1);
+ }
+ }
+ else if (strncmp (p, "rank", strlen ("rank")) == 0 && r)
+ {
+ if (r)
+ {
+ i = atoi (p + strlen ("rank"));
+ if (i >= 0 && i < params->dim)
+ params->rank[i] = atoi (r + 1);
+ }
+ }
+ else if (strncmp (p, "sel", strlen ("sel")) == 0 && r)
+ {
+ if (r)
+ {
+ i = atoi (p + strlen ("sel"));
+ if (i >= 0 && i < params->dim)
+ {
+ g_free (params->selection[i]);
+ params->selection[i] = g_strdup (r + 1);
+ }
+ }
+ }
+ if (r)
+ *r = ':';
+ }
+
+ g_free (copy);
+}
+
+gchar *
+gimp_pixpipe_params_build (GimpPixPipeParams *params)
+{
+ GString *str;
+ gint i;
+
+ g_return_val_if_fail (params != NULL, NULL);
+
+ str = g_string_new (NULL);
+
+ g_string_printf (str, "ncells:%d cellwidth:%d cellheight:%d "
+ "step:%d dim:%d cols:%d rows:%d placement:%s",
+ params->ncells, params->cellwidth, params->cellheight,
+ params->step, params->dim,
+ params->cols, params->rows,
+ params->placement);
+
+ for (i = 0; i < params->dim; i++)
+ {
+ g_string_append_printf (str, " rank%d:%d", i, params->rank[i]);
+ g_string_append_printf (str, " sel%d:%s", i, params->selection[i]);
+ }
+
+ return g_string_free (str, FALSE);
+}
+
+void
+gimp_pixpipe_params_free (GimpPixPipeParams *params)
+{
+ gint i;
+
+ g_free (params->placement);
+
+ for (i = 0; i < GIMP_PIXPIPE_MAXDIM; i++)
+ g_free (params->selection[i]);
+}
diff --git a/libgimpbase/gimpparasiteio.h b/libgimpbase/gimpparasiteio.h
new file mode 100644
index 0000000..9024b48
--- /dev/null
+++ b/libgimpbase/gimpparasiteio.h
@@ -0,0 +1,92 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpparasiteio.h
+ * Copyright (C) 1999 Tor Lillqvist <tml@iki.fi>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_PARASITE_IO_H__
+#define __GIMP_PARASITE_IO_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/* Data structures for various standard parasites used by plug-ins and
+ * the GIMP core, and functions to build and parse their string
+ * representations.
+ */
+
+/*
+ * Pixmap brush pipes.
+ */
+
+#define GIMP_PIXPIPE_MAXDIM 4
+
+typedef struct _GimpPixPipeParams GimpPixPipeParams;
+
+/**
+ * GimpPixPipeParams:
+ * @step: Step
+ * @ncells: Number of cells
+ * @dim: Dimension
+ * @cols: Columns
+ * @rows: Rows
+ * @cellwidth: Cell width
+ * @cellheight: Cell height
+ * @placement: Placement
+ * @free_placement_string: Unused, ignore
+ * @rank: Rank
+ * @selection: Selection
+ * @free_selection_string: Unused, ignore
+ *
+ * PLease somebody help documenting this.
+ **/
+struct _GimpPixPipeParams
+{
+ gint step;
+ gint ncells;
+ gint dim;
+ gint cols;
+ gint rows;
+ gint cellwidth;
+ gint cellheight;
+ gchar *placement;
+ gboolean free_placement_string;
+ gint rank[GIMP_PIXPIPE_MAXDIM];
+ gchar *selection[GIMP_PIXPIPE_MAXDIM];
+ /* this flag is now useless. All selection strings are allocated. */
+ gboolean free_selection_string;
+};
+
+/* Initialize with dummy values */
+void gimp_pixpipe_params_init (GimpPixPipeParams *params);
+
+/* Parse a string into a GimpPixPipeParams */
+void gimp_pixpipe_params_parse (const gchar *parameters,
+ GimpPixPipeParams *params);
+
+/* Build a string representation of GimpPixPipeParams */
+gchar * gimp_pixpipe_params_build (GimpPixPipeParams *params) G_GNUC_MALLOC;
+
+/* Free the internal values. It does not free the struct itself. */
+void gimp_pixpipe_params_free (GimpPixPipeParams *params);
+
+G_END_DECLS
+
+#endif /* __GIMP_PARASITE_IO_H__ */
diff --git a/libgimpbase/gimpprotocol.c b/libgimpbase/gimpprotocol.c
new file mode 100644
index 0000000..ded796b
--- /dev/null
+++ b/libgimpbase/gimpprotocol.c
@@ -0,0 +1,1934 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gimpbasetypes.h"
+
+#include "gimpparasite.h"
+#include "gimpprotocol.h"
+#include "gimpwire.h"
+
+
+static void _gp_quit_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_quit_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_quit_destroy (GimpWireMessage *msg);
+
+static void _gp_config_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_config_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_config_destroy (GimpWireMessage *msg);
+
+static void _gp_tile_req_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_tile_req_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_tile_req_destroy (GimpWireMessage *msg);
+
+static void _gp_tile_ack_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_tile_ack_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_tile_ack_destroy (GimpWireMessage *msg);
+
+static void _gp_tile_data_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_tile_data_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_tile_data_destroy (GimpWireMessage *msg);
+
+static void _gp_proc_run_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_run_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_run_destroy (GimpWireMessage *msg);
+
+static void _gp_proc_return_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_return_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_return_destroy (GimpWireMessage *msg);
+
+static void _gp_temp_proc_run_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_temp_proc_run_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_temp_proc_run_destroy (GimpWireMessage *msg);
+
+static void _gp_temp_proc_return_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_temp_proc_return_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_temp_proc_return_destroy (GimpWireMessage *msg);
+
+static void _gp_proc_install_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_install_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_install_destroy (GimpWireMessage *msg);
+
+static void _gp_proc_uninstall_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_uninstall_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_proc_uninstall_destroy (GimpWireMessage *msg);
+
+static void _gp_extension_ack_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_extension_ack_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_extension_ack_destroy (GimpWireMessage *msg);
+
+static void _gp_params_read (GIOChannel *channel,
+ GPParam **params,
+ guint *nparams,
+ gpointer user_data);
+static void _gp_params_write (GIOChannel *channel,
+ GPParam *params,
+ gint nparams,
+ gpointer user_data);
+
+static void _gp_has_init_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_has_init_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+static void _gp_has_init_destroy (GimpWireMessage *msg);
+
+
+
+void
+gp_init (void)
+{
+ gimp_wire_register (GP_QUIT,
+ _gp_quit_read,
+ _gp_quit_write,
+ _gp_quit_destroy);
+ gimp_wire_register (GP_CONFIG,
+ _gp_config_read,
+ _gp_config_write,
+ _gp_config_destroy);
+ gimp_wire_register (GP_TILE_REQ,
+ _gp_tile_req_read,
+ _gp_tile_req_write,
+ _gp_tile_req_destroy);
+ gimp_wire_register (GP_TILE_ACK,
+ _gp_tile_ack_read,
+ _gp_tile_ack_write,
+ _gp_tile_ack_destroy);
+ gimp_wire_register (GP_TILE_DATA,
+ _gp_tile_data_read,
+ _gp_tile_data_write,
+ _gp_tile_data_destroy);
+ gimp_wire_register (GP_PROC_RUN,
+ _gp_proc_run_read,
+ _gp_proc_run_write,
+ _gp_proc_run_destroy);
+ gimp_wire_register (GP_PROC_RETURN,
+ _gp_proc_return_read,
+ _gp_proc_return_write,
+ _gp_proc_return_destroy);
+ gimp_wire_register (GP_TEMP_PROC_RUN,
+ _gp_temp_proc_run_read,
+ _gp_temp_proc_run_write,
+ _gp_temp_proc_run_destroy);
+ gimp_wire_register (GP_TEMP_PROC_RETURN,
+ _gp_temp_proc_return_read,
+ _gp_temp_proc_return_write,
+ _gp_temp_proc_return_destroy);
+ gimp_wire_register (GP_PROC_INSTALL,
+ _gp_proc_install_read,
+ _gp_proc_install_write,
+ _gp_proc_install_destroy);
+ gimp_wire_register (GP_PROC_UNINSTALL,
+ _gp_proc_uninstall_read,
+ _gp_proc_uninstall_write,
+ _gp_proc_uninstall_destroy);
+ gimp_wire_register (GP_EXTENSION_ACK,
+ _gp_extension_ack_read,
+ _gp_extension_ack_write,
+ _gp_extension_ack_destroy);
+ gimp_wire_register (GP_HAS_INIT,
+ _gp_has_init_read,
+ _gp_has_init_write,
+ _gp_has_init_destroy);
+}
+
+gboolean
+gp_quit_write (GIOChannel *channel,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_QUIT;
+ msg.data = NULL;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_config_write (GIOChannel *channel,
+ GPConfig *config,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_CONFIG;
+ msg.data = config;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_tile_req_write (GIOChannel *channel,
+ GPTileReq *tile_req,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_TILE_REQ;
+ msg.data = tile_req;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_tile_ack_write (GIOChannel *channel,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_TILE_ACK;
+ msg.data = NULL;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_tile_data_write (GIOChannel *channel,
+ GPTileData *tile_data,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_TILE_DATA;
+ msg.data = tile_data;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_proc_run_write (GIOChannel *channel,
+ GPProcRun *proc_run,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_PROC_RUN;
+ msg.data = proc_run;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_proc_return_write (GIOChannel *channel,
+ GPProcReturn *proc_return,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_PROC_RETURN;
+ msg.data = proc_return;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_temp_proc_run_write (GIOChannel *channel,
+ GPProcRun *proc_run,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_TEMP_PROC_RUN;
+ msg.data = proc_run;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_temp_proc_return_write (GIOChannel *channel,
+ GPProcReturn *proc_return,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_TEMP_PROC_RETURN;
+ msg.data = proc_return;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_proc_install_write (GIOChannel *channel,
+ GPProcInstall *proc_install,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_PROC_INSTALL;
+ msg.data = proc_install;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_proc_uninstall_write (GIOChannel *channel,
+ GPProcUninstall *proc_uninstall,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_PROC_UNINSTALL;
+ msg.data = proc_uninstall;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_extension_ack_write (GIOChannel *channel,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_EXTENSION_ACK;
+ msg.data = NULL;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+gp_has_init_write (GIOChannel *channel,
+ gpointer user_data)
+{
+ GimpWireMessage msg;
+
+ msg.type = GP_HAS_INIT;
+ msg.data = NULL;
+
+ if (! gimp_wire_write_msg (channel, &msg, user_data))
+ return FALSE;
+
+ if (! gimp_wire_flush (channel, user_data))
+ return FALSE;
+
+ return TRUE;
+}
+
+/* quit */
+
+static void
+_gp_quit_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_quit_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_quit_destroy (GimpWireMessage *msg)
+{
+}
+
+/* config */
+
+static void
+_gp_config_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPConfig *config = g_slice_new0 (GPConfig);
+
+ if (! _gimp_wire_read_int32 (channel,
+ &config->version, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &config->tile_width, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &config->tile_height, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &config->shm_ID, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->check_size, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->check_type, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->show_help_button, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->use_cpu_accel, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->use_opencl, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->export_exif, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->export_xmp, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->export_iptc, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->export_profile, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) &config->show_tooltips, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &config->min_colors, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &config->gdisp_ID, 1, user_data))
+ goto cleanup;
+
+ if (! _gimp_wire_read_string (channel,
+ &config->app_name, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &config->wm_class, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &config->display_name, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &config->monitor_number, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &config->timestamp, 1, user_data))
+ goto cleanup;
+
+ if (config->version < 0x0017)
+ goto end;
+
+ if (! _gimp_wire_read_string (channel,
+ &config->icon_theme_dir, 1, user_data))
+ goto cleanup;
+
+ if (config->version < 0x0019)
+ goto end;
+
+ if (! _gimp_wire_read_int64 (channel,
+ &config->tile_cache_size, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &config->swap_path, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &config->num_processors, 1,
+ user_data))
+ goto cleanup;
+
+ if (config->version < 0x001A)
+ goto end;
+
+ if (! _gimp_wire_read_string (channel,
+ &config->swap_compression, 1, user_data))
+ goto cleanup;
+
+ end:
+ msg->data = config;
+ return;
+
+ cleanup:
+ g_free (config->app_name);
+ g_free (config->wm_class);
+ g_free (config->display_name);
+ g_free (config->icon_theme_dir);
+ g_free (config->swap_path);
+ g_free (config->swap_compression);
+ g_slice_free (GPConfig, config);
+}
+
+static void
+_gp_config_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPConfig *config = msg->data;
+
+ if (! _gimp_wire_write_int32 (channel,
+ &config->version, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &config->tile_width, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &config->tile_height, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &config->shm_ID, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->check_size, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->check_type, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->show_help_button, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->use_cpu_accel, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->use_opencl, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->export_exif, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->export_xmp, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->export_iptc, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->export_profile, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &config->show_tooltips, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &config->min_colors, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &config->gdisp_ID, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &config->app_name, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &config->wm_class, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &config->display_name, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &config->monitor_number, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &config->timestamp, 1,
+ user_data))
+ return;
+
+ if (config->version < 0x0017)
+ return;
+
+ if (! _gimp_wire_write_string (channel,
+ &config->icon_theme_dir, 1, user_data))
+ return;
+
+ if (config->version < 0x0019)
+ return;
+
+ if (! _gimp_wire_write_int64 (channel,
+ &config->tile_cache_size, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &config->swap_path, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &config->num_processors, 1,
+ user_data))
+ return;
+
+ if (config->version < 0x001A)
+ return;
+
+ if (! _gimp_wire_write_string (channel,
+ &config->swap_compression, 1, user_data))
+ return;
+}
+
+static void
+_gp_config_destroy (GimpWireMessage *msg)
+{
+ GPConfig *config = msg->data;
+
+ if (config)
+ {
+ g_free (config->app_name);
+ g_free (config->wm_class);
+ g_free (config->display_name);
+ g_free (config->icon_theme_dir);
+ g_free (config->swap_path);
+ g_free (config->swap_compression);
+ g_slice_free (GPConfig, config);
+ }
+}
+
+/* tile_req */
+
+static void
+_gp_tile_req_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPTileReq *tile_req = g_slice_new0 (GPTileReq);
+
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &tile_req->drawable_ID, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_req->tile_num, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_req->shadow, 1, user_data))
+ goto cleanup;
+
+ msg->data = tile_req;
+ return;
+
+ cleanup:
+ g_slice_free (GPTileReq, tile_req);
+ msg->data = NULL;
+}
+
+static void
+_gp_tile_req_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPTileReq *tile_req = msg->data;
+
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &tile_req->drawable_ID, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_req->tile_num, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_req->shadow, 1, user_data))
+ return;
+}
+
+static void
+_gp_tile_req_destroy (GimpWireMessage *msg)
+{
+ GPTileReq *tile_req = msg->data;
+
+ if (tile_req)
+ g_slice_free (GPTileReq, msg->data);
+}
+
+/* tile_ack */
+
+static void
+_gp_tile_ack_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_tile_ack_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_tile_ack_destroy (GimpWireMessage *msg)
+{
+}
+
+/* tile_data */
+
+static void
+_gp_tile_data_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPTileData *tile_data = g_slice_new0 (GPTileData);
+
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &tile_data->drawable_ID, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_data->tile_num, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_data->shadow, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_data->bpp, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_data->width, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_data->height, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &tile_data->use_shm, 1, user_data))
+ goto cleanup;
+
+ if (!tile_data->use_shm)
+ {
+ guint length = tile_data->width * tile_data->height * tile_data->bpp;
+
+ tile_data->data = g_new (guchar, length);
+
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) tile_data->data, length,
+ user_data))
+ goto cleanup;
+ }
+
+ msg->data = tile_data;
+ return;
+
+ cleanup:
+ g_free (tile_data->data);
+ g_slice_free (GPTileData, tile_data);
+ msg->data = NULL;
+}
+
+static void
+_gp_tile_data_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPTileData *tile_data = msg->data;
+
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &tile_data->drawable_ID, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_data->tile_num, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_data->shadow, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_data->bpp, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_data->width, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_data->height, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &tile_data->use_shm, 1, user_data))
+ return;
+
+ if (!tile_data->use_shm)
+ {
+ guint length = tile_data->width * tile_data->height * tile_data->bpp;
+
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) tile_data->data, length,
+ user_data))
+ return;
+ }
+}
+
+static void
+_gp_tile_data_destroy (GimpWireMessage *msg)
+{
+ GPTileData *tile_data = msg->data;
+
+ if (tile_data)
+ {
+ if (tile_data->data)
+ {
+ g_free (tile_data->data);
+ tile_data->data = NULL;
+ }
+
+ g_slice_free (GPTileData, tile_data);
+ }
+}
+
+/* proc_run */
+
+static void
+_gp_proc_run_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcRun *proc_run = g_slice_new0 (GPProcRun);
+
+ if (! _gimp_wire_read_string (channel, &proc_run->name, 1, user_data))
+ goto cleanup;
+
+ _gp_params_read (channel,
+ &proc_run->params, (guint *) &proc_run->nparams,
+ user_data);
+
+ msg->data = proc_run;
+ return;
+
+ cleanup:
+ g_slice_free (GPProcRun, proc_run);
+ msg->data = NULL;
+}
+
+static void
+_gp_proc_run_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcRun *proc_run = msg->data;
+
+ if (! _gimp_wire_write_string (channel, &proc_run->name, 1, user_data))
+ return;
+
+ _gp_params_write (channel, proc_run->params, proc_run->nparams, user_data);
+}
+
+static void
+_gp_proc_run_destroy (GimpWireMessage *msg)
+{
+ GPProcRun *proc_run = msg->data;
+
+ if (proc_run)
+ {
+ gp_params_destroy (proc_run->params, proc_run->nparams);
+
+ g_free (proc_run->name);
+ g_slice_free (GPProcRun, proc_run);
+ }
+}
+
+/* proc_return */
+
+static void
+_gp_proc_return_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcReturn *proc_return = g_slice_new0 (GPProcReturn);
+
+ if (! _gimp_wire_read_string (channel, &proc_return->name, 1, user_data))
+ goto cleanup;
+
+ _gp_params_read (channel,
+ &proc_return->params, (guint *) &proc_return->nparams,
+ user_data);
+
+ msg->data = proc_return;
+ return;
+
+ cleanup:
+ g_slice_free (GPProcReturn, proc_return);
+ msg->data = NULL;
+}
+
+static void
+_gp_proc_return_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcReturn *proc_return = msg->data;
+
+ if (! _gimp_wire_write_string (channel, &proc_return->name, 1, user_data))
+ return;
+
+ _gp_params_write (channel,
+ proc_return->params, proc_return->nparams, user_data);
+}
+
+static void
+_gp_proc_return_destroy (GimpWireMessage *msg)
+{
+ GPProcReturn *proc_return = msg->data;
+
+ if (proc_return)
+ {
+ gp_params_destroy (proc_return->params, proc_return->nparams);
+
+ g_free (proc_return->name);
+ g_slice_free (GPProcReturn, proc_return);
+ }
+}
+
+/* temp_proc_run */
+
+static void
+_gp_temp_proc_run_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ _gp_proc_run_read (channel, msg, user_data);
+}
+
+static void
+_gp_temp_proc_run_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ _gp_proc_run_write (channel, msg, user_data);
+}
+
+static void
+_gp_temp_proc_run_destroy (GimpWireMessage *msg)
+{
+ _gp_proc_run_destroy (msg);
+}
+
+/* temp_proc_return */
+
+static void
+_gp_temp_proc_return_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ _gp_proc_return_read (channel, msg, user_data);
+}
+
+static void
+_gp_temp_proc_return_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ _gp_proc_return_write (channel, msg, user_data);
+}
+
+static void
+_gp_temp_proc_return_destroy (GimpWireMessage *msg)
+{
+ _gp_proc_return_destroy (msg);
+}
+
+/* proc_install */
+
+static void
+_gp_proc_install_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcInstall *proc_install = g_slice_new0 (GPProcInstall);
+ gint i;
+
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->name, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->blurb, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->help, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->author, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->copyright, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->date, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->menu_path, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->image_types, 1, user_data))
+ goto cleanup;
+
+ if (! _gimp_wire_read_int32 (channel,
+ &proc_install->type, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &proc_install->nparams, 1, user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &proc_install->nreturn_vals, 1, user_data))
+ goto cleanup;
+
+ proc_install->params = g_new0 (GPParamDef, proc_install->nparams);
+
+ for (i = 0; i < proc_install->nparams; i++)
+ {
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &proc_install->params[i].type, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->params[i].name, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->params[i].description, 1,
+ user_data))
+ goto cleanup;
+ }
+
+ proc_install->return_vals = g_new0 (GPParamDef, proc_install->nreturn_vals);
+
+ for (i = 0; i < proc_install->nreturn_vals; i++)
+ {
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &proc_install->return_vals[i].type, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->return_vals[i].name, 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_string (channel,
+ &proc_install->return_vals[i].description, 1,
+ user_data))
+ goto cleanup;
+ }
+
+ msg->data = proc_install;
+ return;
+
+ cleanup:
+ g_free (proc_install->name);
+ g_free (proc_install->blurb);
+ g_free (proc_install->help);
+ g_free (proc_install->author);
+ g_free (proc_install->copyright);
+ g_free (proc_install->date);
+ g_free (proc_install->menu_path);
+ g_free (proc_install->image_types);
+
+ if (proc_install->params)
+ {
+ for (i = 0; i < proc_install->nparams; i++)
+ {
+ if (!proc_install->params[i].name)
+ break;
+
+ g_free (proc_install->params[i].name);
+ g_free (proc_install->params[i].description);
+ }
+
+ g_free (proc_install->params);
+ }
+
+ if (proc_install->return_vals)
+ {
+ for (i = 0; i < proc_install->nreturn_vals; i++)
+ {
+ if (!proc_install->return_vals[i].name)
+ break;
+
+ g_free (proc_install->return_vals[i].name);
+ g_free (proc_install->return_vals[i].description);
+ }
+
+ g_free (proc_install->return_vals);
+ }
+
+ g_slice_free (GPProcInstall, proc_install);
+ msg->data = NULL;
+}
+
+static void
+_gp_proc_install_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcInstall *proc_install = msg->data;
+ gint i;
+
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->name, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->blurb, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->help, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->author, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->copyright, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->date, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->menu_path, 1, user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->image_types, 1, user_data))
+ return;
+
+ if (! _gimp_wire_write_int32 (channel,
+ &proc_install->type, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &proc_install->nparams, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel,
+ &proc_install->nreturn_vals, 1, user_data))
+ return;
+
+ for (i = 0; i < proc_install->nparams; i++)
+ {
+ if (! _gimp_wire_write_int32 (channel,
+ (guint32 *) &proc_install->params[i].type, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->params[i].name, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->params[i].description, 1,
+ user_data))
+ return;
+ }
+
+ for (i = 0; i < proc_install->nreturn_vals; i++)
+ {
+ if (! _gimp_wire_write_int32 (channel,
+ (guint32 *) &proc_install->return_vals[i].type, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->return_vals[i].name, 1,
+ user_data))
+ return;
+ if (! _gimp_wire_write_string (channel,
+ &proc_install->return_vals[i].description, 1,
+ user_data))
+ return;
+ }
+}
+
+static void
+_gp_proc_install_destroy (GimpWireMessage *msg)
+{
+ GPProcInstall *proc_install = msg->data;
+
+ if (proc_install)
+ {
+ gint i;
+
+ g_free (proc_install->name);
+ g_free (proc_install->blurb);
+ g_free (proc_install->help);
+ g_free (proc_install->author);
+ g_free (proc_install->copyright);
+ g_free (proc_install->date);
+ g_free (proc_install->menu_path);
+ g_free (proc_install->image_types);
+
+ for (i = 0; i < proc_install->nparams; i++)
+ {
+ g_free (proc_install->params[i].name);
+ g_free (proc_install->params[i].description);
+ }
+
+ for (i = 0; i < proc_install->nreturn_vals; i++)
+ {
+ g_free (proc_install->return_vals[i].name);
+ g_free (proc_install->return_vals[i].description);
+ }
+
+ g_free (proc_install->params);
+ g_free (proc_install->return_vals);
+ g_slice_free (GPProcInstall, proc_install);
+ }
+}
+
+/* proc_uninstall */
+
+static void
+_gp_proc_uninstall_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcUninstall *proc_uninstall = g_slice_new0 (GPProcUninstall);
+
+ if (! _gimp_wire_read_string (channel, &proc_uninstall->name, 1, user_data))
+ goto cleanup;
+
+ msg->data = proc_uninstall;
+ return;
+
+ cleanup:
+ g_slice_free (GPProcUninstall, proc_uninstall);
+}
+
+static void
+_gp_proc_uninstall_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GPProcUninstall *proc_uninstall = msg->data;
+
+ if (! _gimp_wire_write_string (channel, &proc_uninstall->name, 1, user_data))
+ return;
+}
+
+static void
+_gp_proc_uninstall_destroy (GimpWireMessage *msg)
+{
+ GPProcUninstall *proc_uninstall = msg->data;
+
+ if (proc_uninstall)
+ {
+ g_free (proc_uninstall->name);
+ g_slice_free (GPProcUninstall, proc_uninstall);
+ }
+}
+
+/* extension_ack */
+
+static void
+_gp_extension_ack_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_extension_ack_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_extension_ack_destroy (GimpWireMessage *msg)
+{
+}
+
+/* params */
+
+static void
+_gp_params_read (GIOChannel *channel,
+ GPParam **params,
+ guint *nparams,
+ gpointer user_data)
+{
+ gint i, j;
+
+ if (! _gimp_wire_read_int32 (channel, (guint32 *) nparams, 1, user_data))
+ return;
+
+ if (*nparams == 0)
+ {
+ *params = NULL;
+ return;
+ }
+
+ *params = g_new0 (GPParam, *nparams);
+
+ for (i = 0; i < *nparams; i++)
+ {
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].type, 1,
+ user_data))
+ goto cleanup;
+
+ switch ((*params)[i].type)
+ {
+ case GIMP_PDB_INT32:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_int32, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_INT16:
+ if (! _gimp_wire_read_int16 (channel,
+ (guint16 *) &(*params)[i].data.d_int16, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_INT8:
+ if (! _gimp_wire_read_int8 (channel,
+ &(*params)[i].data.d_int8, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_FLOAT:
+ if (! _gimp_wire_read_double (channel,
+ &(*params)[i].data.d_float, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_STRING:
+ if (! _gimp_wire_read_string (channel,
+ &(*params)[i].data.d_string, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_INT32ARRAY:
+ (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
+ (*params)[i].data.d_int32array = g_new (gint32,
+ (*params)[i-1].data.d_int32);
+
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) (*params)[i].data.d_int32array,
+ (*params)[i-1].data.d_int32,
+ user_data))
+ {
+ g_free ((*params)[i].data.d_int32array);
+ goto cleanup;
+ }
+ break;
+
+ case GIMP_PDB_INT16ARRAY:
+ (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
+ (*params)[i].data.d_int16array = g_new (gint16,
+ (*params)[i-1].data.d_int32);
+ if (! _gimp_wire_read_int16 (channel,
+ (guint16 *) (*params)[i].data.d_int16array,
+ (*params)[i-1].data.d_int32,
+ user_data))
+ {
+ g_free ((*params)[i].data.d_int16array);
+ goto cleanup;
+ }
+ break;
+
+ case GIMP_PDB_INT8ARRAY:
+ (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
+ (*params)[i].data.d_int8array = g_new (guint8,
+ (*params)[i-1].data.d_int32);
+ if (! _gimp_wire_read_int8 (channel,
+ (*params)[i].data.d_int8array,
+ (*params)[i-1].data.d_int32,
+ user_data))
+ {
+ g_free ((*params)[i].data.d_int8array);
+ goto cleanup;
+ }
+ break;
+
+ case GIMP_PDB_FLOATARRAY:
+ (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
+ (*params)[i].data.d_floatarray = g_new (gdouble,
+ (*params)[i-1].data.d_int32);
+ if (! _gimp_wire_read_double (channel,
+ (*params)[i].data.d_floatarray,
+ (*params)[i-1].data.d_int32,
+ user_data))
+ {
+ g_free ((*params)[i].data.d_floatarray);
+ goto cleanup;
+ }
+ break;
+
+ case GIMP_PDB_STRINGARRAY:
+ (*params)[i-1].data.d_int32 = MAX (0, (*params)[i-1].data.d_int32);
+ (*params)[i].data.d_stringarray = g_new0 (gchar *,
+ (*params)[i-1].data.d_int32);
+ if (! _gimp_wire_read_string (channel,
+ (*params)[i].data.d_stringarray,
+ (*params)[i-1].data.d_int32,
+ user_data))
+ {
+ for (j = 0; j < (*params)[i-1].data.d_int32; j++)
+ g_free (((*params)[i].data.d_stringarray)[j]);
+ g_free ((*params)[i].data.d_stringarray);
+ goto cleanup;
+ }
+ break;
+
+ case GIMP_PDB_COLOR:
+ if (! _gimp_wire_read_color (channel,
+ &(*params)[i].data.d_color, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_ITEM:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_item, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_DISPLAY:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_display, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_IMAGE:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_image, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_LAYER:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_layer, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_CHANNEL:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_channel, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_DRAWABLE:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_drawable, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_SELECTION:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_selection, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_COLORARRAY:
+ (*params)[i].data.d_colorarray = g_new (GimpRGB,
+ (*params)[i-1].data.d_int32);
+ if (! _gimp_wire_read_color (channel,
+ (*params)[i].data.d_colorarray,
+ (*params)[i-1].data.d_int32,
+ user_data))
+ {
+ g_free ((*params)[i].data.d_colorarray);
+ goto cleanup;
+ }
+ break;
+
+ case GIMP_PDB_VECTORS:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_vectors, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_PARASITE:
+ if (! _gimp_wire_read_string (channel,
+ &(*params)[i].data.d_parasite.name, 1,
+ user_data))
+ goto cleanup;
+ if ((*params)[i].data.d_parasite.name == NULL)
+ {
+ /* we have a null parasite */
+ (*params)[i].data.d_parasite.data = NULL;
+ break;
+ }
+ if (! _gimp_wire_read_int32 (channel,
+ &((*params)[i].data.d_parasite.flags), 1,
+ user_data))
+ goto cleanup;
+ if (! _gimp_wire_read_int32 (channel,
+ &((*params)[i].data.d_parasite.size), 1,
+ user_data))
+ goto cleanup;
+ if ((*params)[i].data.d_parasite.size > 0)
+ {
+ (*params)[i].data.d_parasite.data =
+ g_malloc ((*params)[i].data.d_parasite.size);
+ if (! _gimp_wire_read_int8 (channel,
+ (*params)[i].data.d_parasite.data,
+ (*params)[i].data.d_parasite.size,
+ user_data))
+ {
+ g_free ((*params)[i].data.d_parasite.data);
+ goto cleanup;
+ }
+ }
+ else
+ (*params)[i].data.d_parasite.data = NULL;
+ break;
+
+ case GIMP_PDB_STATUS:
+ if (! _gimp_wire_read_int32 (channel,
+ (guint32 *) &(*params)[i].data.d_status, 1,
+ user_data))
+ goto cleanup;
+ break;
+
+ case GIMP_PDB_END:
+ break;
+ }
+ }
+
+ return;
+
+ cleanup:
+ *nparams = 0;
+ g_free (*params);
+ *params = NULL;
+}
+
+static void
+_gp_params_write (GIOChannel *channel,
+ GPParam *params,
+ gint nparams,
+ gpointer user_data)
+{
+ gint i;
+
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &nparams, 1, user_data))
+ return;
+
+ for (i = 0; i < nparams; i++)
+ {
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].type, 1,
+ user_data))
+ return;
+
+ switch (params[i].type)
+ {
+ case GIMP_PDB_INT32:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_int32, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_INT16:
+ if (! _gimp_wire_write_int16 (channel,
+ (const guint16 *) &params[i].data.d_int16, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_INT8:
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &params[i].data.d_int8, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_FLOAT:
+ if (! _gimp_wire_write_double (channel,
+ &params[i].data.d_float, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_STRING:
+ if (! _gimp_wire_write_string (channel,
+ &params[i].data.d_string, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_INT32ARRAY:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) params[i].data.d_int32array,
+ params[i-1].data.d_int32,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_INT16ARRAY:
+ if (! _gimp_wire_write_int16 (channel,
+ (const guint16 *) params[i].data.d_int16array,
+ params[i-1].data.d_int32,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_INT8ARRAY:
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) params[i].data.d_int8array,
+ params[i-1].data.d_int32,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_FLOATARRAY:
+ if (! _gimp_wire_write_double (channel,
+ params[i].data.d_floatarray,
+ params[i-1].data.d_int32,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_STRINGARRAY:
+ if (! _gimp_wire_write_string (channel,
+ params[i].data.d_stringarray,
+ params[i-1].data.d_int32,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_COLOR:
+ if (! _gimp_wire_write_color (channel,
+ &params[i].data.d_color, 1, user_data))
+ return;
+ break;
+
+ case GIMP_PDB_ITEM:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_item, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_DISPLAY:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_display, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_IMAGE:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_image, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_LAYER:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_layer, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_CHANNEL:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_channel, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_DRAWABLE:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_drawable, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_SELECTION:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_selection, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_COLORARRAY:
+ if (! _gimp_wire_write_color (channel,
+ params[i].data.d_colorarray,
+ params[i-1].data.d_int32,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_VECTORS:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_vectors, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_PARASITE:
+ {
+ GimpParasite *p = &params[i].data.d_parasite;
+
+ if (p->name == NULL)
+ {
+ /* write a null string to signal a null parasite */
+ _gimp_wire_write_string (channel, &p->name, 1, user_data);
+ break;
+ }
+
+ if (! _gimp_wire_write_string (channel, &p->name, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel, &p->flags, 1, user_data))
+ return;
+ if (! _gimp_wire_write_int32 (channel, &p->size, 1, user_data))
+ return;
+ if (p->size > 0)
+ {
+ if (! _gimp_wire_write_int8 (channel,
+ p->data, p->size, user_data))
+ return;
+ }
+ }
+ break;
+
+ case GIMP_PDB_STATUS:
+ if (! _gimp_wire_write_int32 (channel,
+ (const guint32 *) &params[i].data.d_status, 1,
+ user_data))
+ return;
+ break;
+
+ case GIMP_PDB_END:
+ break;
+ }
+ }
+}
+
+void
+gp_params_destroy (GPParam *params,
+ gint nparams)
+{
+ gint i;
+
+ for (i = 0; i < nparams; i++)
+ {
+ switch (params[i].type)
+ {
+ case GIMP_PDB_INT32:
+ case GIMP_PDB_INT16:
+ case GIMP_PDB_INT8:
+ case GIMP_PDB_FLOAT:
+ case GIMP_PDB_COLOR:
+ case GIMP_PDB_ITEM:
+ case GIMP_PDB_DISPLAY:
+ case GIMP_PDB_IMAGE:
+ case GIMP_PDB_LAYER:
+ case GIMP_PDB_CHANNEL:
+ case GIMP_PDB_DRAWABLE:
+ case GIMP_PDB_SELECTION:
+ case GIMP_PDB_VECTORS:
+ case GIMP_PDB_STATUS:
+ break;
+
+ case GIMP_PDB_STRING:
+ g_free (params[i].data.d_string);
+ break;
+
+ case GIMP_PDB_INT32ARRAY:
+ g_free (params[i].data.d_int32array);
+ break;
+
+ case GIMP_PDB_INT16ARRAY:
+ g_free (params[i].data.d_int16array);
+ break;
+
+ case GIMP_PDB_INT8ARRAY:
+ g_free (params[i].data.d_int8array);
+ break;
+
+ case GIMP_PDB_FLOATARRAY:
+ g_free (params[i].data.d_floatarray);
+ break;
+
+ case GIMP_PDB_STRINGARRAY:
+ if ((i > 0) && (params[i-1].type == GIMP_PDB_INT32))
+ {
+ gint count = params[i-1].data.d_int32;
+ gint j;
+
+ for (j = 0; j < count; j++)
+ g_free (params[i].data.d_stringarray[j]);
+
+ g_free (params[i].data.d_stringarray);
+ }
+ break;
+
+ case GIMP_PDB_COLORARRAY:
+ g_free (params[i].data.d_colorarray);
+ break;
+
+ case GIMP_PDB_PARASITE:
+ if (params[i].data.d_parasite.name)
+ g_free (params[i].data.d_parasite.name);
+ if (params[i].data.d_parasite.data)
+ g_free (params[i].data.d_parasite.data);
+ break;
+
+ case GIMP_PDB_END:
+ break;
+ }
+ }
+
+ g_free (params);
+}
+
+/* has_init */
+
+static void
+_gp_has_init_read (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_has_init_write (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+}
+
+static void
+_gp_has_init_destroy (GimpWireMessage *msg)
+{
+}
diff --git a/libgimpbase/gimpprotocol.h b/libgimpbase/gimpprotocol.h
new file mode 100644
index 0000000..991abed
--- /dev/null
+++ b/libgimpbase/gimpprotocol.h
@@ -0,0 +1,245 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_PROTOCOL_H__
+#define __GIMP_PROTOCOL_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/* Increment every time the protocol changes
+ */
+#define GIMP_PROTOCOL_VERSION 0x001A
+
+
+enum
+{
+ GP_QUIT,
+ GP_CONFIG,
+ GP_TILE_REQ,
+ GP_TILE_ACK,
+ GP_TILE_DATA,
+ GP_PROC_RUN,
+ GP_PROC_RETURN,
+ GP_TEMP_PROC_RUN,
+ GP_TEMP_PROC_RETURN,
+ GP_PROC_INSTALL,
+ GP_PROC_UNINSTALL,
+ GP_EXTENSION_ACK,
+ GP_HAS_INIT
+};
+
+
+typedef struct _GPConfig GPConfig;
+typedef struct _GPTileReq GPTileReq;
+typedef struct _GPTileAck GPTileAck;
+typedef struct _GPTileData GPTileData;
+typedef struct _GPParam GPParam;
+typedef struct _GPParamDef GPParamDef;
+typedef struct _GPProcRun GPProcRun;
+typedef struct _GPProcReturn GPProcReturn;
+typedef struct _GPProcInstall GPProcInstall;
+typedef struct _GPProcUninstall GPProcUninstall;
+
+
+struct _GPConfig
+{
+ guint32 version;
+ guint32 tile_width;
+ guint32 tile_height;
+ gint32 shm_ID;
+ gint8 check_size;
+ gint8 check_type;
+ gint8 show_help_button;
+ gint8 use_cpu_accel;
+ gint8 use_opencl;
+ gint8 export_exif;
+ gint8 export_xmp;
+ gint8 export_iptc;
+ gint8 export_profile;
+ gint8 show_tooltips;
+ gint32 min_colors;
+ gint32 gdisp_ID;
+ gchar *app_name;
+ gchar *wm_class;
+ gchar *display_name;
+ gint32 monitor_number;
+ guint32 timestamp;
+
+ /* since protocol version 0x0017: */
+ gchar *icon_theme_dir;
+
+ /* since protocol version 0x0019: */
+ guint64 tile_cache_size;
+ gchar *swap_path;
+ gint32 num_processors;
+
+ /* since protocol version 0x001a: */
+ gchar *swap_compression;
+};
+
+struct _GPTileReq
+{
+ gint32 drawable_ID;
+ guint32 tile_num;
+ guint32 shadow;
+};
+
+struct _GPTileData
+{
+ gint32 drawable_ID;
+ guint32 tile_num;
+ guint32 shadow;
+ guint32 bpp;
+ guint32 width;
+ guint32 height;
+ guint32 use_shm;
+ guchar *data;
+};
+
+struct _GPParam
+{
+ guint32 type;
+
+ union
+ {
+ gint32 d_int32;
+ gint16 d_int16;
+ guint8 d_int8;
+ gdouble d_float;
+ gchar *d_string;
+ gint32 *d_int32array;
+ gint16 *d_int16array;
+ guint8 *d_int8array;
+ gdouble *d_floatarray;
+ gchar **d_stringarray;
+ GimpRGB *d_colorarray;
+ GimpRGB d_color;
+ struct
+ {
+ gint32 x;
+ gint32 y;
+ gint32 width;
+ gint32 height;
+ } d_region; /* deprecated */
+ gint32 d_display;
+ gint32 d_image;
+ gint32 d_item;
+ gint32 d_layer;
+ gint32 d_channel;
+ gint32 d_drawable;
+ gint32 d_selection;
+ gint32 d_boundary;
+ gint32 d_path; /* deprecated */
+ gint32 d_vectors;
+ gint32 d_status;
+ GimpParasite d_parasite;
+ } data;
+};
+
+struct _GPParamDef
+{
+ guint32 type;
+ gchar *name;
+ gchar *description;
+};
+
+struct _GPProcRun
+{
+ gchar *name;
+ guint32 nparams;
+ GPParam *params;
+};
+
+struct _GPProcReturn
+{
+ gchar *name;
+ guint32 nparams;
+ GPParam *params;
+};
+
+struct _GPProcInstall
+{
+ gchar *name;
+ gchar *blurb;
+ gchar *help;
+ gchar *author;
+ gchar *copyright;
+ gchar *date;
+ gchar *menu_path;
+ gchar *image_types;
+ guint32 type;
+ guint32 nparams;
+ guint32 nreturn_vals;
+ GPParamDef *params;
+ GPParamDef *return_vals;
+};
+
+struct _GPProcUninstall
+{
+ gchar *name;
+};
+
+
+void gp_init (void);
+
+gboolean gp_quit_write (GIOChannel *channel,
+ gpointer user_data);
+gboolean gp_config_write (GIOChannel *channel,
+ GPConfig *config,
+ gpointer user_data);
+gboolean gp_tile_req_write (GIOChannel *channel,
+ GPTileReq *tile_req,
+ gpointer user_data);
+gboolean gp_tile_ack_write (GIOChannel *channel,
+ gpointer user_data);
+gboolean gp_tile_data_write (GIOChannel *channel,
+ GPTileData *tile_data,
+ gpointer user_data);
+gboolean gp_proc_run_write (GIOChannel *channel,
+ GPProcRun *proc_run,
+ gpointer user_data);
+gboolean gp_proc_return_write (GIOChannel *channel,
+ GPProcReturn *proc_return,
+ gpointer user_data);
+gboolean gp_temp_proc_run_write (GIOChannel *channel,
+ GPProcRun *proc_run,
+ gpointer user_data);
+gboolean gp_temp_proc_return_write (GIOChannel *channel,
+ GPProcReturn *proc_return,
+ gpointer user_data);
+gboolean gp_proc_install_write (GIOChannel *channel,
+ GPProcInstall *proc_install,
+ gpointer user_data);
+gboolean gp_proc_uninstall_write (GIOChannel *channel,
+ GPProcUninstall *proc_uninstall,
+ gpointer user_data);
+gboolean gp_extension_ack_write (GIOChannel *channel,
+ gpointer user_data);
+gboolean gp_has_init_write (GIOChannel *channel,
+ gpointer user_data);
+
+void gp_params_destroy (GPParam *params,
+ gint nparams);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_PROTOCOL_H__ */
diff --git a/libgimpbase/gimprectangle.c b/libgimpbase/gimprectangle.c
new file mode 100644
index 0000000..678ff82
--- /dev/null
+++ b/libgimpbase/gimprectangle.c
@@ -0,0 +1,133 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimprectangle.c
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "gimprectangle.h"
+
+
+/**
+ * SECTION: gimprectangle
+ * @title: gimprectangle
+ * @short_description: Utility functions dealing with rectangle extents.
+ *
+ * Utility functions dealing with rectangle extents.
+ **/
+
+
+/**
+ * gimp_rectangle_intersect:
+ * @x1: origin of first rectangle
+ * @y1: origin of first rectangle
+ * @width1: width of first rectangle
+ * @height1: height of first rectangle
+ * @x2: origin of second rectangle
+ * @y2: origin of second rectangle
+ * @width2: width of second rectangle
+ * @height2: height of second rectangle
+ * @dest_x: return location for origin of intersection (may be %NULL)
+ * @dest_y: return location for origin of intersection (may be %NULL)
+ * @dest_width: return location for width of intersection (may be %NULL)
+ * @dest_height: return location for height of intersection (may be %NULL)
+ *
+ * Calculates the intersection of two rectangles.
+ *
+ * Return value: %TRUE if the intersection is non-empty, %FALSE otherwise
+ *
+ * Since: 2.4
+ **/
+gboolean
+gimp_rectangle_intersect (gint x1,
+ gint y1,
+ gint width1,
+ gint height1,
+ gint x2,
+ gint y2,
+ gint width2,
+ gint height2,
+ gint *dest_x,
+ gint *dest_y,
+ gint *dest_width,
+ gint *dest_height)
+{
+ gint d_x, d_y;
+ gint d_w, d_h;
+
+ d_x = MAX (x1, x2);
+ d_y = MAX (y1, y2);
+ d_w = MIN (x1 + width1, x2 + width2) - d_x;
+ d_h = MIN (y1 + height1, y2 + height2) - d_y;
+
+ if (dest_x) *dest_x = d_x;
+ if (dest_y) *dest_y = d_y;
+ if (dest_width) *dest_width = d_w;
+ if (dest_height) *dest_height = d_h;
+
+ return (d_w > 0 && d_h > 0);
+}
+
+/**
+ * gimp_rectangle_union:
+ * @x1: origin of first rectangle
+ * @y1: origin of first rectangle
+ * @width1: width of first rectangle
+ * @height1: height of first rectangle
+ * @x2: origin of second rectangle
+ * @y2: origin of second rectangle
+ * @width2: width of second rectangle
+ * @height2: height of second rectangle
+ * @dest_x: return location for origin of union (may be %NULL)
+ * @dest_y: return location for origin of union (may be %NULL)
+ * @dest_width: return location for width of union (may be %NULL)
+ * @dest_height: return location for height of union (may be %NULL)
+ *
+ * Calculates the union of two rectangles.
+ *
+ * Since: 2.8
+ **/
+void
+gimp_rectangle_union (gint x1,
+ gint y1,
+ gint width1,
+ gint height1,
+ gint x2,
+ gint y2,
+ gint width2,
+ gint height2,
+ gint *dest_x,
+ gint *dest_y,
+ gint *dest_width,
+ gint *dest_height)
+{
+ gint d_x, d_y;
+ gint d_w, d_h;
+
+ d_x = MIN (x1, x2);
+ d_y = MIN (y1, y2);
+ d_w = MAX (x1 + width1, x2 + width2) - d_x;
+ d_h = MAX (y1 + height1, y2 + height2) - d_y;
+
+ if (dest_x) *dest_x = d_x;
+ if (dest_y) *dest_y = d_y;
+ if (dest_width) *dest_width = d_w;
+ if (dest_height) *dest_height = d_h;
+}
diff --git a/libgimpbase/gimprectangle.h b/libgimpbase/gimprectangle.h
new file mode 100644
index 0000000..8ace674
--- /dev/null
+++ b/libgimpbase/gimprectangle.h
@@ -0,0 +1,60 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_RECTANGLE_H__
+#define __GIMP_RECTANGLE_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+gboolean gimp_rectangle_intersect (gint x1,
+ gint y1,
+ gint width1,
+ gint height1,
+ gint x2,
+ gint y2,
+ gint width2,
+ gint height2,
+ gint *dest_x,
+ gint *dest_y,
+ gint *dest_width,
+ gint *dest_height);
+
+void gimp_rectangle_union (gint x1,
+ gint y1,
+ gint width1,
+ gint height1,
+ gint x2,
+ gint y2,
+ gint width2,
+ gint height2,
+ gint *dest_x,
+ gint *dest_y,
+ gint *dest_width,
+ gint *dest_height);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_RECTANGLE_H__ */
diff --git a/libgimpbase/gimpreloc.c b/libgimpbase/gimpreloc.c
new file mode 100644
index 0000000..b9fa4df
--- /dev/null
+++ b/libgimpbase/gimpreloc.c
@@ -0,0 +1,435 @@
+/*
+ * BinReloc - a library for creating relocatable executables
+ * Written by: Hongli Lai <h.lai@chello.nl>
+ * http://autopackage.org/
+ *
+ * This source code is public domain. You can relicense this code
+ * under whatever license you want.
+ *
+ * See http://autopackage.org/docs/binreloc/ for
+ * more information and how to use this.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+
+#if defined(ENABLE_RELOCATABLE_RESOURCES) && ! defined(G_OS_WIN32)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif /* ENABLE_RELOCATABLE_RESOURCES && ! G_OS_WIN32 */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "gimpreloc.h"
+
+
+/*
+ * Find the canonical filename of the executable. Returns the filename
+ * (which must be freed) or NULL on error. If the parameter 'error' is
+ * not NULL, the error code will be stored there, if an error occurred.
+ */
+static char *
+_br_find_exe (GimpBinrelocInitError *error)
+{
+#if ! defined(ENABLE_RELOCATABLE_RESOURCES) || defined(G_OS_WIN32)
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_DISABLED;
+ return NULL;
+#else
+ char *path, *path2, *line, *result;
+ size_t buf_size;
+ ssize_t size;
+ struct stat stat_buf;
+ FILE *f;
+
+ /* Read from /proc/self/exe (symlink) */
+ if (sizeof (path) > SSIZE_MAX)
+ buf_size = SSIZE_MAX - 1;
+ else
+ buf_size = PATH_MAX - 1;
+ path = g_try_new (char, buf_size);
+ if (path == NULL)
+ {
+ /* Cannot allocate memory. */
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_NOMEM;
+ return NULL;
+ }
+ path2 = g_try_new (char, buf_size);
+ if (path2 == NULL)
+ {
+ /* Cannot allocate memory. */
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_NOMEM;
+ g_free (path);
+ return NULL;
+ }
+
+ strncpy (path2, "/proc/self/exe", buf_size - 1);
+
+ while (1)
+ {
+ int i;
+
+ size = readlink (path2, path, buf_size - 1);
+ if (size == -1)
+ {
+ /* Error. */
+ g_free (path2);
+ break;
+ }
+
+ /* readlink() success. */
+ path[size] = '\0';
+
+ /* Check whether the symlink's target is also a symlink.
+ * We want to get the final target. */
+ i = stat (path, &stat_buf);
+ if (i == -1)
+ {
+ /* Error. */
+ g_free (path2);
+ break;
+ }
+
+ /* stat() success. */
+ if (!S_ISLNK (stat_buf.st_mode))
+ {
+ /* path is not a symlink. Done. */
+ g_free (path2);
+ return path;
+ }
+
+ /* path is a symlink. Continue loop and resolve this. */
+ strncpy (path, path2, buf_size - 1);
+ }
+
+
+ /* readlink() or stat() failed; this can happen when the program is
+ * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
+
+ buf_size = PATH_MAX + 128;
+ line = (char *) g_try_realloc (path, buf_size);
+ if (line == NULL)
+ {
+ /* Cannot allocate memory. */
+ g_free (path);
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_NOMEM;
+ return NULL;
+ }
+
+ f = g_fopen ("/proc/self/maps", "r");
+ if (f == NULL)
+ {
+ g_free (line);
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_OPEN_MAPS;
+ return NULL;
+ }
+
+ /* The first entry should be the executable name. */
+ result = fgets (line, (int) buf_size, f);
+ if (result == NULL)
+ {
+ fclose (f);
+ g_free (line);
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_READ_MAPS;
+ return NULL;
+ }
+
+ /* Get rid of newline character. */
+ buf_size = strlen (line);
+ if (buf_size == 0)
+ {
+ /* Huh? An empty string? */
+ fclose (f);
+ g_free (line);
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_INVALID_MAPS;
+ return NULL;
+ }
+ if (line[buf_size - 1] == 10)
+ line[buf_size - 1] = 0;
+
+ /* Extract the filename; it is always an absolute path. */
+ path = strchr (line, '/');
+
+ /* Sanity check. */
+ if (strstr (line, " r-xp ") == NULL || path == NULL)
+ {
+ fclose (f);
+ g_free (line);
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_INVALID_MAPS;
+ return NULL;
+ }
+
+ path = g_strdup (path);
+ g_free (line);
+ fclose (f);
+ return path;
+#endif /* ! ENABLE_RELOCATABLE_RESOURCES || G_OS_WIN32 */
+}
+
+
+/*
+ * Find the canonical filename of the executable which owns symbol.
+ * Returns a filename which must be freed, or NULL on error.
+ */
+static char *
+_br_find_exe_for_symbol (const void *symbol, GimpBinrelocInitError *error)
+{
+#if ! defined(ENABLE_RELOCATABLE_RESOURCES) || defined(G_OS_WIN32)
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_DISABLED;
+ return (char *) NULL;
+#else
+#define SIZE PATH_MAX + 100
+ FILE *f;
+ size_t address_string_len;
+ char *address_string, line[SIZE], *found;
+
+ if (symbol == NULL)
+ return (char *) NULL;
+
+ f = g_fopen ("/proc/self/maps", "r");
+ if (f == NULL)
+ return (char *) NULL;
+
+ address_string_len = 4;
+ address_string = g_try_new (char, address_string_len);
+ found = (char *) NULL;
+
+ while (!feof (f))
+ {
+ char *start_addr, *end_addr, *end_addr_end, *file;
+ void *start_addr_p, *end_addr_p;
+ size_t len;
+
+ if (fgets (line, SIZE, f) == NULL)
+ break;
+
+ /* Sanity check. */
+ if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
+ continue;
+
+ /* Parse line. */
+ start_addr = line;
+ end_addr = strchr (line, '-');
+ file = strchr (line, '/');
+
+ /* More sanity check. */
+ if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
+ continue;
+
+ end_addr[0] = '\0';
+ end_addr++;
+ end_addr_end = strchr (end_addr, ' ');
+ if (end_addr_end == NULL)
+ continue;
+
+ end_addr_end[0] = '\0';
+ len = strlen (file);
+ if (len == 0)
+ continue;
+ if (file[len - 1] == '\n')
+ file[len - 1] = '\0';
+
+ /* Get rid of "(deleted)" from the filename. */
+ len = strlen (file);
+ if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
+ file[len - 10] = '\0';
+
+ /* I don't know whether this can happen but better safe than sorry. */
+ len = strlen (start_addr);
+ if (len != strlen (end_addr))
+ continue;
+
+
+ /* Transform the addresses into a string in the form of 0xdeadbeef,
+ * then transform that into a pointer. */
+ if (address_string_len < len + 3)
+ {
+ address_string_len = len + 3;
+ address_string = (char *) g_try_realloc (address_string, address_string_len);
+ }
+
+ memcpy (address_string, "0x", 2);
+ memcpy (address_string + 2, start_addr, len);
+ address_string[2 + len] = '\0';
+ sscanf (address_string, "%p", &start_addr_p);
+
+ memcpy (address_string, "0x", 2);
+ memcpy (address_string + 2, end_addr, len);
+ address_string[2 + len] = '\0';
+ sscanf (address_string, "%p", &end_addr_p);
+
+
+ if (symbol >= start_addr_p && symbol < end_addr_p)
+ {
+ found = file;
+ break;
+ }
+ }
+
+ g_free (address_string);
+ fclose (f);
+
+ if (found == NULL)
+ return (char *) NULL;
+ else
+ return g_strdup (found);
+#endif /* ! ENABLE_RELOCATABLE_RESOURCES || G_OS_WIN32 */
+}
+
+
+static gchar *exe = NULL;
+
+static void set_gerror (GError **error, GimpBinrelocInitError errcode);
+
+
+/* Initialize the BinReloc library (for applications).
+ *
+ * This function must be called before using any other BinReloc functions.
+ * It attempts to locate the application's canonical filename.
+ *
+ * @note If you want to use BinReloc for a library, then you should call
+ * _gimp_reloc_init_lib() instead.
+ * @note Initialization failure is not fatal. BinReloc functions will just
+ * fallback to the supplied default path.
+ *
+ * @param error If BinReloc failed to initialize, then the error report will
+ * be stored in this variable. Set to NULL if you don't want an
+ * error report. See the #GimpBinrelocInitError for a list of error
+ * codes.
+ *
+ * @returns TRUE on success, FALSE if BinReloc failed to initialize.
+ */
+gboolean
+_gimp_reloc_init (GError **error)
+{
+ GimpBinrelocInitError errcode;
+
+ /* Shut up compiler warning about uninitialized variable. */
+ errcode = GIMP_RELOC_INIT_ERROR_NOMEM;
+
+ /* Locate the application's filename. */
+ exe = _br_find_exe (&errcode);
+ if (exe != NULL)
+ /* Success! */
+ return TRUE;
+ else
+ {
+ /* Failed :-( */
+ set_gerror (error, errcode);
+ return FALSE;
+ }
+}
+
+
+/* Initialize the BinReloc library (for libraries).
+ *
+ * This function must be called before using any other BinReloc functions.
+ * It attempts to locate the calling library's canonical filename.
+ *
+ * @note The BinReloc source code MUST be included in your library, or this
+ * function won't work correctly.
+ * @note Initialization failure is not fatal. BinReloc functions will just
+ * fallback to the supplied default path.
+ *
+ * @returns TRUE on success, FALSE if a filename cannot be found.
+ */
+gboolean
+_gimp_reloc_init_lib (GError **error)
+{
+ GimpBinrelocInitError errcode;
+
+ /* Shut up compiler warning about uninitialized variable. */
+ errcode = GIMP_RELOC_INIT_ERROR_NOMEM;
+
+ exe = _br_find_exe_for_symbol ((const void *) "", &errcode);
+ if (exe != NULL)
+ /* Success! */
+ return TRUE;
+ else
+ {
+ /* Failed :-( */
+ set_gerror (error, errcode);
+ return exe != NULL;
+ }
+}
+
+static void
+set_gerror (GError **error, GimpBinrelocInitError errcode)
+{
+ const gchar *error_message;
+
+ if (error == NULL)
+ return;
+
+ switch (errcode)
+ {
+ case GIMP_RELOC_INIT_ERROR_NOMEM:
+ error_message = "Cannot allocate memory.";
+ break;
+ case GIMP_RELOC_INIT_ERROR_OPEN_MAPS:
+ error_message = "Unable to open /proc/self/maps for reading.";
+ break;
+ case GIMP_RELOC_INIT_ERROR_READ_MAPS:
+ error_message = "Unable to read from /proc/self/maps.";
+ break;
+ case GIMP_RELOC_INIT_ERROR_INVALID_MAPS:
+ error_message = "The file format of /proc/self/maps is invalid.";
+ break;
+ case GIMP_RELOC_INIT_ERROR_DISABLED:
+ error_message = "Binary relocation support is disabled.";
+ break;
+ default:
+ error_message = "Unknown error.";
+ break;
+ };
+ g_set_error (error, g_quark_from_static_string ("GBinReloc"),
+ errcode, "%s", error_message);
+}
+
+
+/* Locate the prefix in which the current application is installed.
+ *
+ * The prefix is generated by the following pseudo-code evaluation:
+ * \code
+ * dirname(dirname(exename))
+ * \endcode
+ *
+ * @param default_prefix A default prefix which will used as fallback.
+ * @return A string containing the prefix, which must be freed when no
+ * longer necessary. If BinReloc is not initialized, or if the
+ * initialization function failed, then a copy of default_prefix
+ * will be returned. If default_prefix is NULL, then NULL will be
+ * returned.
+ */
+gchar *
+_gimp_reloc_find_prefix (const gchar *default_prefix)
+{
+ gchar *dir1, *dir2;
+
+ if (exe == NULL)
+ {
+ /* BinReloc not initialized. */
+ if (default_prefix != NULL)
+ return g_strdup (default_prefix);
+ else
+ return NULL;
+ }
+
+ dir1 = g_path_get_dirname (exe);
+ dir2 = g_path_get_dirname (dir1);
+ g_free (dir1);
+ return dir2;
+}
diff --git a/libgimpbase/gimpreloc.h b/libgimpbase/gimpreloc.h
new file mode 100644
index 0000000..a7af912
--- /dev/null
+++ b/libgimpbase/gimpreloc.h
@@ -0,0 +1,46 @@
+/*
+ * BinReloc - a library for creating relocatable executables
+ * Written by: Hongli Lai <h.lai@chello.nl>
+ * http://autopackage.org/
+ *
+ * This source code is public domain. You can relicense this code
+ * under whatever license you want.
+ *
+ * See http://autopackage.org/docs/binreloc/ for
+ * more information and how to use this.
+ */
+
+#ifndef __GIMP_RELOC_H__
+#define __GIMP_RELOC_H__
+
+G_BEGIN_DECLS
+
+
+/* These error codes can be returned from _gimp_reloc_init() or
+ * _gimp_reloc_init_lib().
+ */
+
+typedef enum
+{
+ /** Cannot allocate memory. */
+ GIMP_RELOC_INIT_ERROR_NOMEM,
+ /** Unable to open /proc/self/maps; see errno for details. */
+ GIMP_RELOC_INIT_ERROR_OPEN_MAPS,
+ /** Unable to read from /proc/self/maps; see errno for details. */
+ GIMP_RELOC_INIT_ERROR_READ_MAPS,
+ /** The file format of /proc/self/maps is invalid; kernel bug? */
+ GIMP_RELOC_INIT_ERROR_INVALID_MAPS,
+ /** BinReloc is disabled (the ENABLE_BINRELOC macro is not defined). */
+ GIMP_RELOC_INIT_ERROR_DISABLED
+} GimpBinrelocInitError;
+
+
+G_GNUC_INTERNAL gboolean _gimp_reloc_init (GError **error);
+G_GNUC_INTERNAL gboolean _gimp_reloc_init_lib (GError **error);
+
+G_GNUC_INTERNAL gchar * _gimp_reloc_find_prefix (const gchar *default_prefix);
+
+
+G_END_DECLS
+
+#endif /* _GIMPRELOC_H_ */
diff --git a/libgimpbase/gimpsignal.c b/libgimpbase/gimpsignal.c
new file mode 100644
index 0000000..a0221f3
--- /dev/null
+++ b/libgimpbase/gimpsignal.c
@@ -0,0 +1,110 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ *
+ * $Revision$
+ */
+
+#include "config.h"
+
+#define _GNU_SOURCE /* for the sigaction stuff */
+
+#include <glib.h>
+
+#include "gimpsignal.h"
+
+
+/**
+ * SECTION: gimpsignal
+ * @title: gimpsignal
+ * @short_description: Portable signal handling.
+ * @see_also: signal(2), signal(5 or 7), sigaction(2).
+ *
+ * Portable signal handling.
+ **/
+
+
+/* Courtesy of Austin Donnelly 06-04-2000 to address bug #2742 */
+
+/**
+ * gimp_signal_private:
+ * @signum: Selects signal to be handled see man 5 signal (or man 7 signal)
+ * @handler: Handler that maps to signum. Invoked by O/S.
+ * Handler gets signal that caused invocation. Corresponds
+ * to the @sa_handler field of the @sigaction struct.
+ * @flags: Preferences. OR'ed SA_&lt;xxx&gt;. See man sigaction. Corresponds
+ * to the @sa_flags field of the @sigaction struct.
+ *
+ * This function furnishes a workalike for signal(2) but
+ * which internally invokes sigaction(2) after certain
+ * sa_flags are set; these primarily to ensure restarting
+ * of interrupted system calls. See sigaction(2) It is a
+ * aid to transition and not new development: that effort
+ * should employ sigaction directly. [gosgood 18.04.2000]
+ *
+ * Cause @handler to be run when @signum is delivered. We
+ * use sigaction(2) rather than signal(2) so that we can control the
+ * signal handler's environment completely via @flags: some signal(2)
+ * implementations differ in their semantics, so we need to nail down
+ * exactly what we want. [austin 06.04.2000]
+ *
+ * Returns: A reference to the signal handling function which was
+ * active before the call to gimp_signal_private().
+ */
+GimpSignalHandlerFunc
+gimp_signal_private (gint signum,
+ GimpSignalHandlerFunc handler,
+ gint flags)
+{
+#ifndef G_OS_WIN32
+ gint ret;
+ struct sigaction sa;
+ struct sigaction osa;
+
+ /* The sa_handler (mandated by POSIX.1) and sa_sigaction (a
+ * common extension) are often implemented by the OS as members
+ * of a union. This means you CAN NOT set both, you set one or
+ * the other. Caveat programmer!
+ */
+
+ /* Passing gimp_signal_private a gimp_sighandler of NULL is not
+ * an error, and generally results in the action for that signal
+ * being set to SIG_DFL (default behavior). Many OSes define
+ * SIG_DFL as (void (*)()0, so setting sa_handler to NULL is
+ * the same thing as passing SIG_DFL to it.
+ */
+ sa.sa_handler = handler;
+
+ /* Mask all signals while handler runs to avoid re-entrancy
+ * problems.
+ */
+ sigfillset (&sa.sa_mask);
+
+ sa.sa_flags = flags;
+
+ ret = sigaction (signum, &sa, &osa);
+
+ if (ret < 0)
+ g_error ("unable to set handler for signal %d\n", signum);
+
+ return (GimpSignalHandlerFunc) osa.sa_handler;
+#else
+ return NULL; /* Or g_error()? Should all calls to
+ * this function really be inside
+ * #ifdef G_OS_UNIX?
+ */
+#endif
+}
diff --git a/libgimpbase/gimpsignal.h b/libgimpbase/gimpsignal.h
new file mode 100644
index 0000000..978a394
--- /dev/null
+++ b/libgimpbase/gimpsignal.h
@@ -0,0 +1,48 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_SIGNAL_H__
+#define __GIMP_SIGNAL_H__
+
+#include <signal.h>
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/**
+ * GimpSignalHandlerFunc:
+ * @signum: The number of the signal. Useful if different signals are
+ * handled by a single handler.
+ *
+ * A prototype for a reference to a signal handler functions. Note
+ * that each function which takes or returns a variable of this type
+ * also accepts or may return special values defined by your system's
+ * signal.h header file (like @SIG_DFL or @SIG_IGN).
+ **/
+typedef void (* GimpSignalHandlerFunc) (gint signum);
+
+GimpSignalHandlerFunc gimp_signal_private (gint signum,
+ GimpSignalHandlerFunc handler,
+ gint flags);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_SIGNAL_H__ */
diff --git a/libgimpbase/gimpunit.c b/libgimpbase/gimpunit.c
new file mode 100644
index 0000000..e0aa626
--- /dev/null
+++ b/libgimpbase/gimpunit.c
@@ -0,0 +1,755 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpunit.c
+ * Copyright (C) 2003 Michael Natterer <mitch@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <string.h>
+
+#include <glib-object.h>
+
+#include "gimpbasetypes.h"
+
+#include "gimpbase-private.h"
+#include "gimpunit.h"
+
+
+/**
+ * SECTION: gimpunit
+ * @title: gimpunit
+ * @short_description: Provides a collection of predefined units and
+ * functions for creating user-defined units.
+ * @see_also: #GimpUnitMenu, #GimpSizeEntry.
+ *
+ * Provides a collection of predefined units and functions for
+ * creating user-defined units.
+ **/
+
+
+static void unit_to_string (const GValue *src_value,
+ GValue *dest_value);
+static void string_to_unit (const GValue *src_value,
+ GValue *dest_value);
+
+GType
+gimp_unit_get_type (void)
+{
+ static GType unit_type = 0;
+
+ if (! unit_type)
+ {
+ const GTypeInfo type_info = { 0, };
+
+ unit_type = g_type_register_static (G_TYPE_INT, "GimpUnit",
+ &type_info, 0);
+
+ g_value_register_transform_func (unit_type, G_TYPE_STRING,
+ unit_to_string);
+ g_value_register_transform_func (G_TYPE_STRING, unit_type,
+ string_to_unit);
+ }
+
+ return unit_type;
+}
+
+static void
+unit_to_string (const GValue *src_value,
+ GValue *dest_value)
+{
+ GimpUnit unit = (GimpUnit) g_value_get_int (src_value);
+
+ g_value_set_string (dest_value, gimp_unit_get_identifier (unit));
+}
+
+static void
+string_to_unit (const GValue *src_value,
+ GValue *dest_value)
+{
+ const gchar *str;
+ gint num_units;
+ gint i;
+
+ str = g_value_get_string (src_value);
+
+ if (!str || !*str)
+ goto error;
+
+ num_units = gimp_unit_get_number_of_units ();
+
+ for (i = GIMP_UNIT_PIXEL; i < num_units; i++)
+ if (strcmp (str, gimp_unit_get_identifier (i)) == 0)
+ break;
+
+ if (i == num_units)
+ {
+ if (strcmp (str, gimp_unit_get_identifier (GIMP_UNIT_PERCENT)) == 0)
+ i = GIMP_UNIT_PERCENT;
+ else
+ goto error;
+ }
+
+ g_value_set_int (dest_value, i);
+ return;
+
+ error:
+ g_warning ("Can't convert string '%s' to GimpUnit.", str);
+}
+
+
+/**
+ * gimp_unit_get_number_of_units:
+ *
+ * Returns the number of units which are known to the #GimpUnit system.
+ *
+ * Returns: The number of defined units.
+ **/
+gint
+gimp_unit_get_number_of_units (void)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_number_of_units != NULL,
+ GIMP_UNIT_END);
+
+ return _gimp_unit_vtable.unit_get_number_of_units ();
+}
+
+/**
+ * gimp_unit_get_number_of_built_in_units:
+ *
+ * Returns the number of #GimpUnit's which are hardcoded in the unit system
+ * (UNIT_INCH, UNIT_MM, UNIT_POINT, UNIT_PICA and the two "pseudo unit"
+ * UNIT_PIXEL).
+ *
+ * Returns: The number of built-in units.
+ **/
+gint
+gimp_unit_get_number_of_built_in_units (void)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_number_of_built_in_units
+ != NULL, GIMP_UNIT_END);
+
+ return _gimp_unit_vtable.unit_get_number_of_built_in_units ();
+}
+
+/**
+ * gimp_unit_new:
+ * @identifier: The unit's identifier string.
+ * @factor: The unit's factor (how many units are in one inch).
+ * @digits: The unit's suggested number of digits (see gimp_unit_get_digits()).
+ * @symbol: The symbol of the unit (e.g. "''" for inch).
+ * @abbreviation: The abbreviation of the unit.
+ * @singular: The singular form of the unit.
+ * @plural: The plural form of the unit.
+ *
+ * Returns the integer ID of the new #GimpUnit.
+ *
+ * Note that a new unit is always created with its deletion flag
+ * set to %TRUE. You will have to set it to %FALSE with
+ * gimp_unit_set_deletion_flag() to make the unit definition persistent.
+ *
+ * Returns: The ID of the new unit.
+ **/
+GimpUnit
+gimp_unit_new (gchar *identifier,
+ gdouble factor,
+ gint digits,
+ gchar *symbol,
+ gchar *abbreviation,
+ gchar *singular,
+ gchar *plural)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_new != NULL, GIMP_UNIT_INCH);
+
+ return _gimp_unit_vtable.unit_new (identifier, factor, digits,
+ symbol, abbreviation, singular, plural);
+}
+
+/**
+ * gimp_unit_get_deletion_flag:
+ * @unit: The unit you want to know the @deletion_flag of.
+ *
+ * Returns: The unit's @deletion_flag.
+ **/
+gboolean
+gimp_unit_get_deletion_flag (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_deletion_flag != NULL, FALSE);
+
+ return _gimp_unit_vtable.unit_get_deletion_flag (unit);
+}
+
+/**
+ * gimp_unit_set_deletion_flag:
+ * @unit: The unit you want to set the @deletion_flag for.
+ * @deletion_flag: The new deletion_flag.
+ *
+ * Sets a #GimpUnit's @deletion_flag. If the @deletion_flag of a unit is
+ * %TRUE when GIMP exits, this unit will not be saved in the users's
+ * "unitrc" file.
+ *
+ * Trying to change the @deletion_flag of a built-in unit will be silently
+ * ignored.
+ **/
+void
+gimp_unit_set_deletion_flag (GimpUnit unit,
+ gboolean deletion_flag)
+{
+ g_return_if_fail (_gimp_unit_vtable.unit_set_deletion_flag != NULL);
+
+ _gimp_unit_vtable.unit_set_deletion_flag (unit, deletion_flag);
+}
+
+/**
+ * gimp_unit_get_factor:
+ * @unit: The unit you want to know the factor of.
+ *
+ * A #GimpUnit's @factor is defined to be:
+ *
+ * distance_in_units == (@factor * distance_in_inches)
+ *
+ * Returns 0 for @unit == GIMP_UNIT_PIXEL.
+ *
+ * Returns: The unit's factor.
+ **/
+gdouble
+gimp_unit_get_factor (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_factor != NULL, 1.0);
+
+ return _gimp_unit_vtable.unit_get_factor (unit);
+}
+
+/**
+ * gimp_unit_get_digits:
+ * @unit: The unit you want to know the digits.
+ *
+ * Returns the number of digits set for @unit.
+ * Built-in units' accuracy is approximately the same as an inch with
+ * two digits. User-defined units can suggest a different accuracy.
+ *
+ * Note: the value is as-set by defaults or by the user and does not
+ * necessary provide enough precision on high-resolution images.
+ * When the information is needed for a specific image, the use of
+ * gimp_unit_get_scaled_digits() may be more appropriate.
+ *
+ * Returns 0 for @unit == GIMP_UNIT_PIXEL.
+ *
+ * Returns: The suggested number of digits.
+ **/
+gint
+gimp_unit_get_digits (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_digits != NULL, 2);
+
+ return _gimp_unit_vtable.unit_get_digits (unit);
+}
+
+/**
+ * gimp_unit_get_scaled_digits:
+ * @unit: The unit you want to know the digits.
+ * @resolution: the resolution in PPI.
+ *
+ * Returns the number of digits a @unit field should provide to get
+ * enough accuracy so that every pixel position shows a different
+ * value from neighboring pixels.
+ *
+ * Note: when needing digit accuracy to display a diagonal distance,
+ * the @resolution may not correspond to the image's horizontal or
+ * vertical resolution, but instead to the result of:
+ * `distance_in_pixel / distance_in_inch`.
+ *
+ * Returns: The suggested number of digits.
+ **/
+gint
+gimp_unit_get_scaled_digits (GimpUnit unit,
+ gdouble resolution)
+{
+ gint digits;
+
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_digits != NULL, 2);
+
+ digits = ceil (log10 (1.0 /
+ gimp_pixels_to_units (1.0, unit, resolution)));
+
+ return MAX (digits, gimp_unit_get_digits (unit));
+}
+
+/**
+ * gimp_unit_get_identifier:
+ * @unit: The unit you want to know the identifier of.
+ *
+ * This is an untranslated string and must not be changed or freed.
+ *
+ * Returns: The unit's identifier.
+ **/
+const gchar *
+gimp_unit_get_identifier (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_identifier != NULL, NULL);
+
+ return _gimp_unit_vtable.unit_get_identifier (unit);
+}
+
+/**
+ * gimp_unit_get_symbol:
+ * @unit: The unit you want to know the symbol of.
+ *
+ * This is e.g. "''" for UNIT_INCH.
+ *
+ * NOTE: This string must not be changed or freed.
+ *
+ * Returns: The unit's symbol.
+ **/
+const gchar *
+gimp_unit_get_symbol (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_symbol != NULL, NULL);
+
+ return _gimp_unit_vtable.unit_get_symbol (unit);
+}
+
+/**
+ * gimp_unit_get_abbreviation:
+ * @unit: The unit you want to know the abbreviation of.
+ *
+ * For built-in units, this function returns the translated abbreviation
+ * of the unit.
+ *
+ * NOTE: This string must not be changed or freed.
+ *
+ * Returns: The unit's abbreviation.
+ **/
+const gchar *
+gimp_unit_get_abbreviation (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_abbreviation != NULL, NULL);
+
+ return _gimp_unit_vtable.unit_get_abbreviation (unit);
+}
+
+/**
+ * gimp_unit_get_singular:
+ * @unit: The unit you want to know the singular form of.
+ *
+ * For built-in units, this function returns the translated singular form
+ * of the unit's name.
+ *
+ * NOTE: This string must not be changed or freed.
+ *
+ * Returns: The unit's singular form.
+ **/
+const gchar *
+gimp_unit_get_singular (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_singular != NULL, NULL);
+
+ return _gimp_unit_vtable.unit_get_singular (unit);
+}
+
+/**
+ * gimp_unit_get_plural:
+ * @unit: The unit you want to know the plural form of.
+ *
+ * For built-in units, this function returns the translated plural form
+ * of the unit's name.
+ *
+ * NOTE: This string must not be changed or freed.
+ *
+ * Returns: The unit's plural form.
+ **/
+const gchar *
+gimp_unit_get_plural (GimpUnit unit)
+{
+ g_return_val_if_fail (_gimp_unit_vtable.unit_get_plural != NULL, NULL);
+
+ return _gimp_unit_vtable.unit_get_plural (unit);
+}
+
+static gint print (gchar *buf,
+ gint len,
+ gint start,
+ const gchar *fmt,
+ ...) G_GNUC_PRINTF (4, 5);
+
+static gint
+print (gchar *buf,
+ gint len,
+ gint start,
+ const gchar *fmt,
+ ...)
+{
+ va_list args;
+ gint printed;
+
+ va_start (args, fmt);
+
+ printed = g_vsnprintf (buf + start, len - start, fmt, args);
+ if (printed < 0)
+ printed = len - start;
+
+ va_end (args);
+
+ return printed;
+}
+
+/**
+ * gimp_unit_format_string:
+ * @format: A printf-like format string which is used to create the unit
+ * string.
+ * @unit: A unit.
+ *
+ * The @format string supports the following percent expansions:
+ *
+ * <informaltable pgwide="1" frame="none" role="enum">
+ * <tgroup cols="2"><colspec colwidth="1*"/><colspec colwidth="8*"/>
+ * <tbody>
+ * <row>
+ * <entry>% f</entry>
+ * <entry>Factor (how many units make up an inch)</entry>
+ * </row>
+ * <row>
+ * <entry>% y</entry>
+ * <entry>Symbol (e.g. "''" for GIMP_UNIT_INCH)</entry>
+ * </row>
+ * <row>
+ * <entry>% a</entry>
+ * <entry>Abbreviation</entry>
+ * </row>
+ * <row>
+ * <entry>% s</entry>
+ * <entry>Singular</entry>
+ * </row>
+ * <row>
+ * <entry>% p</entry>
+ * <entry>Plural</entry>
+ * </row>
+ * <row>
+ * <entry>%%</entry>
+ * <entry>Literal percent</entry>
+ * </row>
+ * </tbody>
+ * </tgroup>
+ * </informaltable>
+ *
+ * Returns: A newly allocated string with above percent expressions
+ * replaced with the resp. strings for @unit.
+ *
+ * Since: 2.8
+ **/
+gchar *
+gimp_unit_format_string (const gchar *format,
+ GimpUnit unit)
+{
+ gchar buffer[1024];
+ gint i = 0;
+
+ g_return_val_if_fail (format != NULL, NULL);
+ g_return_val_if_fail (unit == GIMP_UNIT_PERCENT ||
+ (unit >= GIMP_UNIT_PIXEL &&
+ unit < gimp_unit_get_number_of_units ()), NULL);
+
+ while (i < (sizeof (buffer) - 1) && *format)
+ {
+ switch (*format)
+ {
+ case '%':
+ format++;
+ switch (*format)
+ {
+ case 0:
+ g_warning ("%s: unit-menu-format string ended within %%-sequence",
+ G_STRFUNC);
+ break;
+
+ case '%':
+ buffer[i++] = '%';
+ break;
+
+ case 'f': /* factor (how many units make up an inch) */
+ i += print (buffer, sizeof (buffer), i, "%f",
+ gimp_unit_get_factor (unit));
+ break;
+
+ case 'y': /* symbol ("''" for inch) */
+ i += print (buffer, sizeof (buffer), i, "%s",
+ gimp_unit_get_symbol (unit));
+ break;
+
+ case 'a': /* abbreviation */
+ i += print (buffer, sizeof (buffer), i, "%s",
+ gimp_unit_get_abbreviation (unit));
+ break;
+
+ case 's': /* singular */
+ i += print (buffer, sizeof (buffer), i, "%s",
+ gimp_unit_get_singular (unit));
+ break;
+
+ case 'p': /* plural */
+ i += print (buffer, sizeof (buffer), i, "%s",
+ gimp_unit_get_plural (unit));
+ break;
+
+ default:
+ g_warning ("%s: unit-menu-format contains unknown format "
+ "sequence '%%%c'", G_STRFUNC, *format);
+ break;
+ }
+ break;
+
+ default:
+ buffer[i++] = *format;
+ break;
+ }
+
+ format++;
+ }
+
+ buffer[MIN (i, sizeof (buffer) - 1)] = 0;
+
+ return g_strdup (buffer);
+}
+
+/*
+ * GIMP_TYPE_PARAM_UNIT
+ */
+
+#define GIMP_PARAM_SPEC_UNIT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_UNIT, GimpParamSpecUnit))
+
+typedef struct _GimpParamSpecUnit GimpParamSpecUnit;
+
+struct _GimpParamSpecUnit
+{
+ GParamSpecInt parent_instance;
+
+ gboolean allow_percent;
+};
+
+static void gimp_param_unit_class_init (GParamSpecClass *class);
+static gboolean gimp_param_unit_value_validate (GParamSpec *pspec,
+ GValue *value);
+
+/**
+ * gimp_param_unit_get_type:
+ *
+ * Reveals the object type
+ *
+ * Returns: the #GType for a unit param object
+ *
+ * Since: 2.4
+ **/
+GType
+gimp_param_unit_get_type (void)
+{
+ static GType spec_type = 0;
+
+ if (! spec_type)
+ {
+ const GTypeInfo type_info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_unit_class_init,
+ NULL, NULL,
+ sizeof (GimpParamSpecUnit),
+ 0, NULL, NULL
+ };
+
+ spec_type = g_type_register_static (G_TYPE_PARAM_INT,
+ "GimpParamUnit",
+ &type_info, 0);
+ }
+
+ return spec_type;
+}
+
+static void
+gimp_param_unit_class_init (GParamSpecClass *class)
+{
+ class->value_type = GIMP_TYPE_UNIT;
+ class->value_validate = gimp_param_unit_value_validate;
+}
+
+static gboolean
+gimp_param_unit_value_validate (GParamSpec *pspec,
+ GValue *value)
+{
+ GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
+ GimpParamSpecUnit *uspec = GIMP_PARAM_SPEC_UNIT (pspec);
+ gint oval = value->data[0].v_int;
+
+ if (!(uspec->allow_percent && value->data[0].v_int == GIMP_UNIT_PERCENT))
+ {
+ value->data[0].v_int = CLAMP (value->data[0].v_int,
+ ispec->minimum,
+ gimp_unit_get_number_of_units () - 1);
+ }
+
+ return value->data[0].v_int != oval;
+}
+
+/**
+ * gimp_param_spec_unit:
+ * @name: Canonical name of the param
+ * @nick: Nickname of the param
+ * @blurb: Brief description of param.
+ * @allow_pixels: Whether "pixels" is an allowed unit.
+ * @allow_percent: Whether "percent" is an allowed unit.
+ * @default_value: Unit to use if none is assigned.
+ * @flags: a combination of #GParamFlags
+ *
+ * Creates a param spec to hold a units param.
+ * See g_param_spec_internal() for more information.
+ *
+ * Returns: a newly allocated #GParamSpec instance
+ *
+ * Since: 2.4
+ **/
+GParamSpec *
+gimp_param_spec_unit (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean allow_pixels,
+ gboolean allow_percent,
+ GimpUnit default_value,
+ GParamFlags flags)
+{
+ GimpParamSpecUnit *pspec;
+ GParamSpecInt *ispec;
+
+ pspec = g_param_spec_internal (GIMP_TYPE_PARAM_UNIT,
+ name, nick, blurb, flags);
+
+ ispec = G_PARAM_SPEC_INT (pspec);
+
+ ispec->default_value = default_value;
+ ispec->minimum = allow_pixels ? GIMP_UNIT_PIXEL : GIMP_UNIT_INCH;
+ ispec->maximum = GIMP_UNIT_PERCENT - 1;
+
+ pspec->allow_percent = allow_percent;
+
+ return G_PARAM_SPEC (pspec);
+}
+
+/**
+ * gimp_pixels_to_units:
+ * @pixels: value in pixels
+ * @unit: unit to convert to
+ * @resolution: resolution in DPI
+ *
+ * Converts a @value specified in pixels to @unit.
+ *
+ * Returns: @pixels converted to units.
+ *
+ * Since: 2.8
+ **/
+gdouble
+gimp_pixels_to_units (gdouble pixels,
+ GimpUnit unit,
+ gdouble resolution)
+{
+ if (unit == GIMP_UNIT_PIXEL)
+ return pixels;
+
+ return pixels * gimp_unit_get_factor (unit) / resolution;
+}
+
+/**
+ * gimp_units_to_pixels:
+ * @value: value in units
+ * @unit: unit of @value
+ * @resolution: resloution in DPI
+ *
+ * Converts a @value specified in @unit to pixels.
+ *
+ * Returns: @value converted to pixels.
+ *
+ * Since: 2.8
+ **/
+gdouble
+gimp_units_to_pixels (gdouble value,
+ GimpUnit unit,
+ gdouble resolution)
+{
+ if (unit == GIMP_UNIT_PIXEL)
+ return value;
+
+ return value * resolution / gimp_unit_get_factor (unit);
+}
+
+/**
+ * gimp_units_to_points:
+ * @value: value in units
+ * @unit: unit of @value
+ * @resolution: resloution in DPI
+ *
+ * Converts a @value specified in @unit to points.
+ *
+ * Returns: @value converted to points.
+ *
+ * Since: 2.8
+ **/
+gdouble
+gimp_units_to_points (gdouble value,
+ GimpUnit unit,
+ gdouble resolution)
+{
+ if (unit == GIMP_UNIT_POINT)
+ return value;
+
+ if (unit == GIMP_UNIT_PIXEL)
+ return (value * gimp_unit_get_factor (GIMP_UNIT_POINT) / resolution);
+
+ return (value *
+ gimp_unit_get_factor (GIMP_UNIT_POINT) / gimp_unit_get_factor (unit));
+}
+
+/**
+ * gimp_unit_is_metric:
+ * @unit: The unit
+ *
+ * Checks if the given @unit is metric. A simplistic test is used
+ * that looks at the unit's factor and checks if it is 2.54 multiplied
+ * by some common powers of 10. Currently it checks for mm, cm, dm, m.
+ *
+ * See also: gimp_unit_get_factor()
+ *
+ * Returns: %TRUE if the @unit is metric.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_unit_is_metric (GimpUnit unit)
+{
+ gdouble factor;
+
+ if (unit == GIMP_UNIT_MM)
+ return TRUE;
+
+ factor = gimp_unit_get_factor (unit);
+
+ if (factor == 0.0)
+ return FALSE;
+
+ return ((ABS (factor - 0.0254) < 1e-7) || /* m */
+ (ABS (factor - 0.254) < 1e-6) || /* dm */
+ (ABS (factor - 2.54) < 1e-5) || /* cm */
+ (ABS (factor - 25.4) < 1e-4)); /* mm */
+}
diff --git a/libgimpbase/gimpunit.h b/libgimpbase/gimpunit.h
new file mode 100644
index 0000000..c24d94e
--- /dev/null
+++ b/libgimpbase/gimpunit.h
@@ -0,0 +1,110 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpunit.h
+ * Copyright (C) 1999-2003 Michael Natterer <mitch@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_UNIT_H__
+#define __GIMP_UNIT_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+/**
+ * GIMP_TYPE_UNIT:
+ *
+ * #GIMP_TYPE_UNIT is a #GType derived from #G_TYPE_INT.
+ **/
+
+#define GIMP_TYPE_UNIT (gimp_unit_get_type ())
+#define GIMP_VALUE_HOLDS_UNIT(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_UNIT))
+
+GType gimp_unit_get_type (void) G_GNUC_CONST;
+
+
+/*
+ * GIMP_TYPE_PARAM_UNIT
+ */
+
+#define GIMP_TYPE_PARAM_UNIT (gimp_param_unit_get_type ())
+#define GIMP_IS_PARAM_SPEC_UNIT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_UNIT))
+
+GType gimp_param_unit_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_unit (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ gboolean allow_pixels,
+ gboolean allow_percent,
+ GimpUnit default_value,
+ GParamFlags flags);
+
+
+
+gint gimp_unit_get_number_of_units (void);
+gint gimp_unit_get_number_of_built_in_units (void) G_GNUC_CONST;
+
+GimpUnit gimp_unit_new (gchar *identifier,
+ gdouble factor,
+ gint digits,
+ gchar *symbol,
+ gchar *abbreviation,
+ gchar *singular,
+ gchar *plural);
+
+gboolean gimp_unit_get_deletion_flag (GimpUnit unit);
+void gimp_unit_set_deletion_flag (GimpUnit unit,
+ gboolean deletion_flag);
+
+gdouble gimp_unit_get_factor (GimpUnit unit);
+
+gint gimp_unit_get_digits (GimpUnit unit);
+gint gimp_unit_get_scaled_digits (GimpUnit unit,
+ gdouble resolution);
+
+const gchar * gimp_unit_get_identifier (GimpUnit unit);
+
+const gchar * gimp_unit_get_symbol (GimpUnit unit);
+const gchar * gimp_unit_get_abbreviation (GimpUnit unit);
+const gchar * gimp_unit_get_singular (GimpUnit unit);
+const gchar * gimp_unit_get_plural (GimpUnit unit);
+
+gchar * gimp_unit_format_string (const gchar *format,
+ GimpUnit unit);
+
+gdouble gimp_pixels_to_units (gdouble pixels,
+ GimpUnit unit,
+ gdouble resolution);
+gdouble gimp_units_to_pixels (gdouble value,
+ GimpUnit unit,
+ gdouble resolution);
+gdouble gimp_units_to_points (gdouble value,
+ GimpUnit unit,
+ gdouble resolution);
+
+gboolean gimp_unit_is_metric (GimpUnit unit);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_UNIT_H__ */
diff --git a/libgimpbase/gimputils.c b/libgimpbase/gimputils.c
new file mode 100644
index 0000000..2ee1338
--- /dev/null
+++ b/libgimpbase/gimputils.c
@@ -0,0 +1,1603 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimputils.c
+ * Copyright (C) 2003 Sven Neumann <sven@gimp.org>
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef PLATFORM_OSX
+#include <AppKit/AppKit.h>
+#endif
+
+#ifdef HAVE_EXECINFO_H
+/* Allowing backtrace() API. */
+#include <execinfo.h>
+#endif
+
+#include <gio/gio.h>
+#include <glib/gprintf.h>
+
+#if defined(G_OS_WIN32)
+# include <windows.h>
+# include <shlobj.h>
+
+#else /* G_OS_WIN32 */
+
+/* For waitpid() */
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* For thread IDs. */
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
+#ifdef HAVE_SYS_THR_H
+#include <sys/thr.h>
+#endif
+
+#endif /* G_OS_WIN32 */
+
+#include "gimpbasetypes.h"
+#include "gimputils.h"
+
+#include "libgimp/libgimp-intl.h"
+
+
+/**
+ * SECTION: gimputils
+ * @title: gimputils
+ * @short_description: Utilities of general interest
+ *
+ * Utilities of general interest
+ **/
+
+static gboolean gimp_utils_generic_available (const gchar *program,
+ gint major,
+ gint minor);
+static gboolean gimp_utils_gdb_available (gint major,
+ gint minor);
+
+/**
+ * gimp_utf8_strtrim:
+ * @str: an UTF-8 encoded string (or %NULL)
+ * @max_chars: the maximum number of characters before the string get
+ * trimmed
+ *
+ * Creates a (possibly trimmed) copy of @str. The string is cut if it
+ * exceeds @max_chars characters or on the first newline. The fact
+ * that the string was trimmed is indicated by appending an ellipsis.
+ *
+ * Returns: A (possibly trimmed) copy of @str which should be freed
+ * using g_free() when it is not needed any longer.
+ **/
+gchar *
+gimp_utf8_strtrim (const gchar *str,
+ gint max_chars)
+{
+ /* FIXME: should we make this translatable? */
+ const gchar ellipsis[] = "...";
+ const gint e_len = strlen (ellipsis);
+
+ if (str)
+ {
+ const gchar *p;
+ const gchar *newline = NULL;
+ gint chars = 0;
+ gunichar unichar;
+
+ for (p = str; *p; p = g_utf8_next_char (p))
+ {
+ if (++chars > max_chars)
+ break;
+
+ unichar = g_utf8_get_char (p);
+
+ switch (g_unichar_break_type (unichar))
+ {
+ case G_UNICODE_BREAK_MANDATORY:
+ case G_UNICODE_BREAK_LINE_FEED:
+ newline = p;
+ break;
+ default:
+ continue;
+ }
+
+ break;
+ }
+
+ if (*p)
+ {
+ gsize len = p - str;
+ gchar *trimmed = g_new (gchar, len + e_len + 2);
+
+ memcpy (trimmed, str, len);
+ if (newline)
+ trimmed[len++] = ' ';
+
+ g_strlcpy (trimmed + len, ellipsis, e_len + 1);
+
+ return trimmed;
+ }
+
+ return g_strdup (str);
+ }
+
+ return NULL;
+}
+
+/**
+ * gimp_any_to_utf8:
+ * @str: The string to be converted to UTF-8.
+ * @len: The length of the string, or -1 if the string
+ * is nul-terminated.
+ * @warning_format: The message format for the warning message if conversion
+ * to UTF-8 fails. See the <function>printf()</function>
+ * documentation.
+ * @...: The parameters to insert into the format string.
+ *
+ * This function takes any string (UTF-8 or not) and always returns a valid
+ * UTF-8 string.
+ *
+ * If @str is valid UTF-8, a copy of the string is returned.
+ *
+ * If UTF-8 validation fails, g_locale_to_utf8() is tried and if it
+ * succeeds the resulting string is returned.
+ *
+ * Otherwise, the portion of @str that is UTF-8, concatenated
+ * with "(invalid UTF-8 string)" is returned. If not even the start
+ * of @str is valid UTF-8, only "(invalid UTF-8 string)" is returned.
+ *
+ * Return value: The UTF-8 string as described above.
+ **/
+gchar *
+gimp_any_to_utf8 (const gchar *str,
+ gssize len,
+ const gchar *warning_format,
+ ...)
+{
+ const gchar *start_invalid;
+ gchar *utf8;
+
+ g_return_val_if_fail (str != NULL, NULL);
+
+ if (g_utf8_validate (str, len, &start_invalid))
+ {
+ if (len < 0)
+ utf8 = g_strdup (str);
+ else
+ utf8 = g_strndup (str, len);
+ }
+ else
+ {
+ utf8 = g_locale_to_utf8 (str, len, NULL, NULL, NULL);
+ }
+
+ if (! utf8)
+ {
+ if (warning_format)
+ {
+ va_list warning_args;
+
+ va_start (warning_args, warning_format);
+
+ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE,
+ warning_format, warning_args);
+
+ va_end (warning_args);
+ }
+
+ if (start_invalid > str)
+ {
+ gchar *tmp;
+
+ tmp = g_strndup (str, start_invalid - str);
+ utf8 = g_strconcat (tmp, " ", _("(invalid UTF-8 string)"), NULL);
+ g_free (tmp);
+ }
+ else
+ {
+ utf8 = g_strdup (_("(invalid UTF-8 string)"));
+ }
+ }
+
+ return utf8;
+}
+
+/**
+ * gimp_filename_to_utf8:
+ * @filename: The filename to be converted to UTF-8.
+ *
+ * Convert a filename in the filesystem's encoding to UTF-8
+ * temporarily. The return value is a pointer to a string that is
+ * guaranteed to be valid only during the current iteration of the
+ * main loop or until the next call to gimp_filename_to_utf8().
+ *
+ * The only purpose of this function is to provide an easy way to pass
+ * a filename in the filesystem encoding to a function that expects an
+ * UTF-8 encoded filename.
+ *
+ * Return value: A temporarily valid UTF-8 representation of @filename.
+ * This string must not be changed or freed.
+ **/
+const gchar *
+gimp_filename_to_utf8 (const gchar *filename)
+{
+ /* Simpleminded implementation, but at least allocates just one copy
+ * of each translation. Could check if already UTF-8, and if so
+ * return filename as is. Could perhaps (re)use a suitably large
+ * cyclic buffer, but then would have to verify that all calls
+ * really need the return value just for a "short" time.
+ */
+
+ static GHashTable *ht = NULL;
+ gchar *filename_utf8;
+
+ if (! filename)
+ return NULL;
+
+ if (! ht)
+ ht = g_hash_table_new (g_str_hash, g_str_equal);
+
+ filename_utf8 = g_hash_table_lookup (ht, filename);
+
+ if (! filename_utf8)
+ {
+ filename_utf8 = g_filename_display_name (filename);
+ g_hash_table_insert (ht, g_strdup (filename), filename_utf8);
+ }
+
+ return filename_utf8;
+}
+
+/**
+ * gimp_file_get_utf8_name:
+ * @file: a #GFile
+ *
+ * This function works like gimp_filename_to_utf8() and returns
+ * a UTF-8 encoded string that does not need to be freed.
+ *
+ * It converts a #GFile's path or uri to UTF-8 temporarily. The
+ * return value is a pointer to a string that is guaranteed to be
+ * valid only during the current iteration of the main loop or until
+ * the next call to gimp_file_get_utf8_name().
+ *
+ * The only purpose of this function is to provide an easy way to pass
+ * a #GFile's name to a function that expects an UTF-8 encoded string.
+ *
+ * See g_file_get_parse_name().
+ *
+ * Since: 2.10
+ *
+ * Return value: A temporarily valid UTF-8 representation of @file's name.
+ * This string must not be changed or freed.
+ **/
+const gchar *
+gimp_file_get_utf8_name (GFile *file)
+{
+ gchar *name;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+ name = g_file_get_parse_name (file);
+
+ g_object_set_data_full (G_OBJECT (file), "gimp-parse-name", name,
+ (GDestroyNotify) g_free);
+
+ return name;
+}
+
+/**
+ * gimp_file_has_extension:
+ * @file: a #GFile
+ * @extension: an ASCII extension
+ *
+ * This function checks if @file's URI ends with @extension. It behaves
+ * like g_str_has_suffix() on g_file_get_uri(), except that the string
+ * comparison is done case-insensitively using g_ascii_strcasecmp().
+ *
+ * Since: 2.10
+ *
+ * Return value: %TRUE if @file's URI ends with @extension,
+ * %FALSE otherwise.
+ **/
+gboolean
+gimp_file_has_extension (GFile *file,
+ const gchar *extension)
+{
+ gchar *uri;
+ gint uri_len;
+ gint ext_len;
+ gboolean result = FALSE;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (extension != NULL, FALSE);
+
+ uri = g_file_get_uri (file);
+
+ uri_len = strlen (uri);
+ ext_len = strlen (extension);
+
+ if (uri_len && ext_len && (uri_len > ext_len))
+ {
+ if (g_ascii_strcasecmp (uri + uri_len - ext_len, extension) == 0)
+ result = TRUE;
+ }
+
+ g_free (uri);
+
+ return result;
+}
+
+/**
+ * gimp_file_show_in_file_manager:
+ * @file: a #GFile
+ * @error: return location for a #GError
+ *
+ * Shows @file in the system file manager.
+ *
+ * Since: 2.10
+ *
+ * Return value: %TRUE on success, %FALSE otherwise. On %FALSE, @error
+ * is set.
+ **/
+gboolean
+gimp_file_show_in_file_manager (GFile *file,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+#if defined(G_OS_WIN32)
+
+ {
+ gboolean ret;
+ char *filename;
+ int n;
+ LPWSTR w_filename = NULL;
+ ITEMIDLIST *pidl = NULL;
+
+ ret = FALSE;
+
+ /* Calling this function multiple times should do no harm, but it is
+ easier to put this here as it needs linking against ole32. */
+ CoInitialize (NULL);
+
+ filename = g_file_get_path (file);
+ if (!filename)
+ {
+ g_set_error_literal (error, G_FILE_ERROR, 0,
+ _("File path is NULL"));
+ goto out;
+ }
+
+ n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+ filename, -1, NULL, 0);
+ if (n == 0)
+ {
+ g_set_error_literal (error, G_FILE_ERROR, 0,
+ _("Error converting UTF-8 filename to wide char"));
+ goto out;
+ }
+
+ w_filename = g_malloc_n (n + 1, sizeof (wchar_t));
+ n = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
+ filename, -1,
+ w_filename, (n + 1) * sizeof (wchar_t));
+ if (n == 0)
+ {
+ g_set_error_literal (error, G_FILE_ERROR, 0,
+ _("Error converting UTF-8 filename to wide char"));
+ goto out;
+ }
+
+ pidl = ILCreateFromPathW (w_filename);
+ if (!pidl)
+ {
+ g_set_error_literal (error, G_FILE_ERROR, 0,
+ _("ILCreateFromPath() failed"));
+ goto out;
+ }
+
+ SHOpenFolderAndSelectItems (pidl, 0, NULL, 0);
+ ret = TRUE;
+
+ out:
+ if (pidl)
+ ILFree (pidl);
+ g_free (w_filename);
+ g_free (filename);
+
+ return ret;
+ }
+
+#elif defined(PLATFORM_OSX)
+
+ {
+ gchar *uri;
+ NSString *filename;
+ NSURL *url;
+ gboolean retval = TRUE;
+
+ uri = g_file_get_uri (file);
+ filename = [NSString stringWithUTF8String:uri];
+
+ url = [NSURL URLWithString:filename];
+ if (url)
+ {
+ NSArray *url_array = [NSArray arrayWithObject:url];
+
+ [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:url_array];
+ }
+ else
+ {
+ g_set_error (error, G_FILE_ERROR, 0,
+ _("Cannot convert '%s' into a valid NSURL."), uri);
+ retval = FALSE;
+ }
+
+ g_free (uri);
+
+ return retval;
+ }
+
+#else /* UNIX */
+
+ {
+ GDBusProxy *proxy;
+ GVariant *retval;
+ GVariantBuilder *builder;
+ gchar *uri;
+
+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.FileManager1",
+ "/org/freedesktop/FileManager1",
+ "org.freedesktop.FileManager1",
+ NULL, error);
+
+ if (! proxy)
+ {
+ g_prefix_error (error,
+ _("Connecting to org.freedesktop.FileManager1 failed: "));
+ return FALSE;
+ }
+
+ uri = g_file_get_uri (file);
+
+ builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ g_variant_builder_add (builder, "s", uri);
+
+ g_free (uri);
+
+ retval = g_dbus_proxy_call_sync (proxy,
+ "ShowItems",
+ g_variant_new ("(ass)",
+ builder,
+ ""),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, error);
+
+ g_variant_builder_unref (builder);
+ g_object_unref (proxy);
+
+ if (! retval)
+ {
+ g_prefix_error (error, _("Calling ShowItems failed: "));
+ return FALSE;
+ }
+
+ g_variant_unref (retval);
+
+ return TRUE;
+ }
+
+#endif
+}
+
+/**
+ * gimp_strip_uline:
+ * @str: underline infested string (or %NULL)
+ *
+ * This function returns a copy of @str stripped of underline
+ * characters. This comes in handy when needing to strip mnemonics
+ * from menu paths etc.
+ *
+ * In some languages, mnemonics are handled by adding the mnemonic
+ * character in brackets (like "File (_F)"). This function recognizes
+ * this construct and removes the whole bracket construction to get
+ * rid of the mnemonic (see bug 157561).
+ *
+ * Return value: A (possibly stripped) copy of @str which should be
+ * freed using g_free() when it is not needed any longer.
+ **/
+gchar *
+gimp_strip_uline (const gchar *str)
+{
+ gchar *escaped;
+ gchar *p;
+ gboolean past_bracket = FALSE;
+
+ if (! str)
+ return NULL;
+
+ p = escaped = g_strdup (str);
+
+ while (*str)
+ {
+ if (*str == '_')
+ {
+ /* "__" means a literal "_" in the menu path */
+ if (str[1] == '_')
+ {
+ *p++ = *str++;
+ str++;
+ continue;
+ }
+
+ /* find the "(_X)" construct and remove it entirely */
+ if (past_bracket && str[1] && *(g_utf8_next_char (str + 1)) == ')')
+ {
+ str = g_utf8_next_char (str + 1) + 1;
+ p--;
+ }
+ else
+ {
+ str++;
+ }
+ }
+ else
+ {
+ past_bracket = (*str == '(');
+
+ *p++ = *str++;
+ }
+ }
+
+ *p = '\0';
+
+ return escaped;
+}
+
+/**
+ * gimp_escape_uline:
+ * @str: Underline infested string (or %NULL)
+ *
+ * This function returns a copy of @str with all underline converted
+ * to two adjacent underlines. This comes in handy when needing to display
+ * strings with underlines (like filenames) in a place that would convert
+ * them to mnemonics.
+ *
+ * Return value: A (possibly escaped) copy of @str which should be
+ * freed using g_free() when it is not needed any longer.
+ *
+ * Since: 2.2
+ **/
+gchar *
+gimp_escape_uline (const gchar *str)
+{
+ gchar *escaped;
+ gchar *p;
+ gint n_ulines = 0;
+
+ if (! str)
+ return NULL;
+
+ for (p = (gchar *) str; *p; p++)
+ if (*p == '_')
+ n_ulines++;
+
+ p = escaped = g_malloc (strlen (str) + n_ulines + 1);
+
+ while (*str)
+ {
+ if (*str == '_')
+ *p++ = '_';
+
+ *p++ = *str++;
+ }
+
+ *p = '\0';
+
+ return escaped;
+}
+
+/**
+ * gimp_canonicalize_identifier:
+ * @identifier: The identifier string to canonicalize.
+ *
+ * Turns any input string into a canonicalized string.
+ *
+ * Canonical identifiers are e.g. expected by the PDB for procedure
+ * and parameter names. Every character of the input string that is
+ * not either '-', 'a-z', 'A-Z' or '0-9' will be replaced by a '-'.
+ *
+ * Return value: The canonicalized identifier. This is a newly
+ * allocated string that should be freed with g_free()
+ * when no longer needed.
+ *
+ * Since: 2.4
+ **/
+gchar *
+gimp_canonicalize_identifier (const gchar *identifier)
+{
+ gchar *canonicalized = NULL;
+
+ if (identifier)
+ {
+ gchar *p;
+
+ canonicalized = g_strdup (identifier);
+
+ for (p = canonicalized; *p != 0; p++)
+ {
+ gchar c = *p;
+
+ if (c != '-' &&
+ (c < '0' || c > '9') &&
+ (c < 'A' || c > 'Z') &&
+ (c < 'a' || c > 'z'))
+ *p = '-';
+ }
+ }
+
+ return canonicalized;
+}
+
+/**
+ * gimp_enum_get_desc:
+ * @enum_class: a #GEnumClass
+ * @value: a value from @enum_class
+ *
+ * Retrieves #GimpEnumDesc associated with the given value, or %NULL.
+ *
+ * Return value: the value's #GimpEnumDesc.
+ *
+ * Since: 2.2
+ **/
+GimpEnumDesc *
+gimp_enum_get_desc (GEnumClass *enum_class,
+ gint value)
+{
+ const GimpEnumDesc *value_desc;
+
+ g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), NULL);
+
+ value_desc =
+ gimp_enum_get_value_descriptions (G_TYPE_FROM_CLASS (enum_class));
+
+ if (value_desc)
+ {
+ while (value_desc->value_desc)
+ {
+ if (value_desc->value == value)
+ return (GimpEnumDesc *) value_desc;
+
+ value_desc++;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * gimp_enum_get_value:
+ * @enum_type: the #GType of a registered enum
+ * @value: an integer value
+ * @value_name: return location for the value's name (or %NULL)
+ * @value_nick: return location for the value's nick (or %NULL)
+ * @value_desc: return location for the value's translated description (or %NULL)
+ * @value_help: return location for the value's translated help (or %NULL)
+ *
+ * Checks if @value is valid for the enum registered as @enum_type.
+ * If the value exists in that enum, its name, nick and its translated
+ * description and help are returned (if @value_name, @value_nick,
+ * @value_desc and @value_help are not %NULL).
+ *
+ * Return value: %TRUE if @value is valid for the @enum_type,
+ * %FALSE otherwise
+ *
+ * Since: 2.2
+ **/
+gboolean
+gimp_enum_get_value (GType enum_type,
+ gint value,
+ const gchar **value_name,
+ const gchar **value_nick,
+ const gchar **value_desc,
+ const gchar **value_help)
+{
+ GEnumClass *enum_class;
+ GEnumValue *enum_value;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), FALSE);
+
+ enum_class = g_type_class_ref (enum_type);
+ enum_value = g_enum_get_value (enum_class, value);
+
+ if (enum_value)
+ {
+ if (value_name)
+ *value_name = enum_value->value_name;
+
+ if (value_nick)
+ *value_nick = enum_value->value_nick;
+
+ if (value_desc || value_help)
+ {
+ GimpEnumDesc *enum_desc;
+
+ enum_desc = gimp_enum_get_desc (enum_class, value);
+
+ if (value_desc)
+ {
+ if (enum_desc && enum_desc->value_desc)
+ {
+ const gchar *context;
+
+ context = gimp_type_get_translation_context (enum_type);
+
+ if (context) /* the new way, using NC_() */
+ *value_desc = g_dpgettext2 (gimp_type_get_translation_domain (enum_type),
+ context,
+ enum_desc->value_desc);
+ else /* for backward compatibility */
+ *value_desc = g_strip_context (enum_desc->value_desc,
+ dgettext (gimp_type_get_translation_domain (enum_type),
+ enum_desc->value_desc));
+ }
+ else
+ {
+ *value_desc = NULL;
+ }
+ }
+
+ if (value_help)
+ {
+ *value_help = ((enum_desc && enum_desc->value_help) ?
+ dgettext (gimp_type_get_translation_domain (enum_type),
+ enum_desc->value_help) :
+ NULL);
+ }
+ }
+
+ success = TRUE;
+ }
+
+ g_type_class_unref (enum_class);
+
+ return success;
+}
+
+/**
+ * gimp_enum_value_get_desc:
+ * @enum_class: a #GEnumClass
+ * @enum_value: a #GEnumValue from @enum_class
+ *
+ * Retrieves the translated description for a given @enum_value.
+ *
+ * Return value: the translated description of the enum value
+ *
+ * Since: 2.2
+ **/
+const gchar *
+gimp_enum_value_get_desc (GEnumClass *enum_class,
+ GEnumValue *enum_value)
+{
+ GType type = G_TYPE_FROM_CLASS (enum_class);
+ GimpEnumDesc *enum_desc;
+
+ enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
+
+ if (enum_desc && enum_desc->value_desc)
+ {
+ const gchar *context;
+
+ context = gimp_type_get_translation_context (type);
+
+ if (context) /* the new way, using NC_() */
+ return g_dpgettext2 (gimp_type_get_translation_domain (type),
+ context,
+ enum_desc->value_desc);
+ else /* for backward compatibility */
+ return g_strip_context (enum_desc->value_desc,
+ dgettext (gimp_type_get_translation_domain (type),
+ enum_desc->value_desc));
+ }
+
+ return enum_value->value_name;
+}
+
+/**
+ * gimp_enum_value_get_help:
+ * @enum_class: a #GEnumClass
+ * @enum_value: a #GEnumValue from @enum_class
+ *
+ * Retrieves the translated help for a given @enum_value.
+ *
+ * Return value: the translated help of the enum value
+ *
+ * Since: 2.2
+ **/
+const gchar *
+gimp_enum_value_get_help (GEnumClass *enum_class,
+ GEnumValue *enum_value)
+{
+ GType type = G_TYPE_FROM_CLASS (enum_class);
+ GimpEnumDesc *enum_desc;
+
+ enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
+
+ if (enum_desc && enum_desc->value_help)
+ return dgettext (gimp_type_get_translation_domain (type),
+ enum_desc->value_help);
+
+ return NULL;
+}
+
+/**
+ * gimp_enum_value_get_abbrev:
+ * @enum_class: a #GEnumClass
+ * @enum_value: a #GEnumValue from @enum_class
+ *
+ * Retrieves the translated abbreviation for a given @enum_value.
+ *
+ * Return value: the translated abbreviation of the enum value
+ *
+ * Since: 2.10
+ **/
+const gchar *
+gimp_enum_value_get_abbrev (GEnumClass *enum_class,
+ GEnumValue *enum_value)
+{
+ GType type = G_TYPE_FROM_CLASS (enum_class);
+ GimpEnumDesc *enum_desc;
+
+ enum_desc = gimp_enum_get_desc (enum_class, enum_value->value);
+
+ if (enum_desc &&
+ enum_desc[1].value == enum_desc->value &&
+ enum_desc[1].value_desc)
+ {
+ return g_dpgettext2 (gimp_type_get_translation_domain (type),
+ gimp_type_get_translation_context (type),
+ enum_desc[1].value_desc);
+ }
+
+ return NULL;
+}
+
+/**
+ * gimp_flags_get_first_desc:
+ * @flags_class: a #GFlagsClass
+ * @value: a value from @flags_class
+ *
+ * Retrieves the first #GimpFlagsDesc that matches the given value, or %NULL.
+ *
+ * Return value: the value's #GimpFlagsDesc.
+ *
+ * Since: 2.2
+ **/
+GimpFlagsDesc *
+gimp_flags_get_first_desc (GFlagsClass *flags_class,
+ guint value)
+{
+ const GimpFlagsDesc *value_desc;
+
+ g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL);
+
+ value_desc =
+ gimp_flags_get_value_descriptions (G_TYPE_FROM_CLASS (flags_class));
+
+ if (value_desc)
+ {
+ while (value_desc->value_desc)
+ {
+ if ((value_desc->value & value) == value_desc->value)
+ return (GimpFlagsDesc *) value_desc;
+
+ value_desc++;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * gimp_flags_get_first_value:
+ * @flags_type: the #GType of registered flags
+ * @value: an integer value
+ * @value_name: return location for the value's name (or %NULL)
+ * @value_nick: return location for the value's nick (or %NULL)
+ * @value_desc: return location for the value's translated description (or %NULL)
+ * @value_help: return location for the value's translated help (or %NULL)
+ *
+ * Checks if @value is valid for the flags registered as @flags_type.
+ * If the value exists in that flags, its name, nick and its
+ * translated description and help are returned (if @value_name,
+ * @value_nick, @value_desc and @value_help are not %NULL).
+ *
+ * Return value: %TRUE if @value is valid for the @flags_type,
+ * %FALSE otherwise
+ *
+ * Since: 2.2
+ **/
+gboolean
+gimp_flags_get_first_value (GType flags_type,
+ guint value,
+ const gchar **value_name,
+ const gchar **value_nick,
+ const gchar **value_desc,
+ const gchar **value_help)
+{
+ GFlagsClass *flags_class;
+ GFlagsValue *flags_value;
+
+ g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), FALSE);
+
+ flags_class = g_type_class_peek (flags_type);
+ flags_value = g_flags_get_first_value (flags_class, value);
+
+ if (flags_value)
+ {
+ if (value_name)
+ *value_name = flags_value->value_name;
+
+ if (value_nick)
+ *value_nick = flags_value->value_nick;
+
+ if (value_desc || value_help)
+ {
+ GimpFlagsDesc *flags_desc;
+
+ flags_desc = gimp_flags_get_first_desc (flags_class, value);
+
+ if (value_desc)
+ *value_desc = ((flags_desc && flags_desc->value_desc) ?
+ dgettext (gimp_type_get_translation_domain (flags_type),
+ flags_desc->value_desc) :
+ NULL);
+
+ if (value_help)
+ *value_help = ((flags_desc && flags_desc->value_desc) ?
+ dgettext (gimp_type_get_translation_domain (flags_type),
+ flags_desc->value_help) :
+ NULL);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * gimp_flags_value_get_desc:
+ * @flags_class: a #GFlagsClass
+ * @flags_value: a #GFlagsValue from @flags_class
+ *
+ * Retrieves the translated description for a given @flags_value.
+ *
+ * Return value: the translated description of the flags value
+ *
+ * Since: 2.2
+ **/
+const gchar *
+gimp_flags_value_get_desc (GFlagsClass *flags_class,
+ GFlagsValue *flags_value)
+{
+ GType type = G_TYPE_FROM_CLASS (flags_class);
+ GimpFlagsDesc *flags_desc;
+
+ flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
+
+ if (flags_desc->value_desc)
+ {
+ const gchar *context;
+
+ context = gimp_type_get_translation_context (type);
+
+ if (context) /* the new way, using NC_() */
+ return g_dpgettext2 (gimp_type_get_translation_domain (type),
+ context,
+ flags_desc->value_desc);
+ else /* for backward compatibility */
+ return g_strip_context (flags_desc->value_desc,
+ dgettext (gimp_type_get_translation_domain (type),
+ flags_desc->value_desc));
+ }
+
+ return flags_value->value_name;
+}
+
+/**
+ * gimp_flags_value_get_help:
+ * @flags_class: a #GFlagsClass
+ * @flags_value: a #GFlagsValue from @flags_class
+ *
+ * Retrieves the translated help for a given @flags_value.
+ *
+ * Return value: the translated help of the flags value
+ *
+ * Since: 2.2
+ **/
+const gchar *
+gimp_flags_value_get_help (GFlagsClass *flags_class,
+ GFlagsValue *flags_value)
+{
+ GType type = G_TYPE_FROM_CLASS (flags_class);
+ GimpFlagsDesc *flags_desc;
+
+ flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
+
+ if (flags_desc->value_help)
+ return dgettext (gimp_type_get_translation_domain (type),
+ flags_desc->value_help);
+
+ return NULL;
+}
+
+/**
+ * gimp_flags_value_get_abbrev:
+ * @flags_class: a #GFlagsClass
+ * @flags_value: a #GFlagsValue from @flags_class
+ *
+ * Retrieves the translated abbreviation for a given @flags_value.
+ *
+ * Return value: the translated abbreviation of the flags value
+ *
+ * Since: 2.10
+ **/
+const gchar *
+gimp_flags_value_get_abbrev (GFlagsClass *flags_class,
+ GFlagsValue *flags_value)
+{
+ GType type = G_TYPE_FROM_CLASS (flags_class);
+ GimpFlagsDesc *flags_desc;
+
+ flags_desc = gimp_flags_get_first_desc (flags_class, flags_value->value);
+
+ if (flags_desc &&
+ flags_desc[1].value == flags_desc->value &&
+ flags_desc[1].value_desc)
+ {
+ return g_dpgettext2 (gimp_type_get_translation_domain (type),
+ gimp_type_get_translation_context (type),
+ flags_desc[1].value_desc);
+ }
+
+ return NULL;
+}
+
+/**
+ * gimp_stack_trace_available:
+ * @optimal: whether we get optimal traces.
+ *
+ * Returns #TRUE if we have dependencies to generate backtraces. If
+ * @optimal is #TRUE, the function will return #TRUE only when we
+ * are able to generate optimal traces (i.e. with GDB or LLDB);
+ * otherwise we return #TRUE even if only backtrace() API is available.
+ *
+ * On Win32, we return TRUE if Dr. Mingw is built-in, FALSE otherwise.
+ *
+ * Note: this function is not crash-safe, i.e. you should not try to use
+ * it in a callback when the program is already crashing. In such a
+ * case, call gimp_stack_trace_print() or gimp_stack_trace_query()
+ * directly.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_stack_trace_available (gboolean optimal)
+{
+#ifndef G_OS_WIN32
+ gchar *lld_path = NULL;
+ gboolean has_lldb = FALSE;
+
+ /* Similarly to gdb, we could check for lldb by calling:
+ * gimp_utils_generic_available ("lldb", major, minor).
+ * We don't do so on purpose because on macOS, when lldb is absent, it
+ * triggers a popup asking to install Xcode. So instead, we just
+ * search for the executable in path.
+ * This is the reason why this function is not crash-safe, since
+ * g_find_program_in_path() allocates memory.
+ * See issue #1999.
+ */
+ lld_path = g_find_program_in_path ("lldb");
+ if (lld_path)
+ {
+ has_lldb = TRUE;
+ g_free (lld_path);
+ }
+
+ if (gimp_utils_gdb_available (7, 0) || has_lldb)
+ return TRUE;
+#ifdef HAVE_EXECINFO_H
+ if (! optimal)
+ return TRUE;
+#endif
+#else /* G_OS_WIN32 */
+#ifdef HAVE_EXCHNDL
+ return TRUE;
+#endif
+#endif /* G_OS_WIN32 */
+ return FALSE;
+}
+
+/**
+ * gimp_stack_trace_print:
+ * @prog_name: the program to attach to.
+ * @stream: a #FILE * stream.
+ * @trace: location to store a newly allocated string of the trace.
+ *
+ * Attempts to generate a stack trace at current code position in
+ * @prog_name. @prog_name is mostly a helper and can be set to NULL.
+ * Nevertheless if set, it has to be the current program name (argv[0]).
+ * This function is not meant to generate stack trace for third-party
+ * programs, and will attach the current process id only.
+ * Internally, this function uses `gdb` or `lldb` if they are available,
+ * or the stacktrace() API on platforms where it is available. It always
+ * fails on Win32.
+ *
+ * The stack trace, once generated, will either be printed to @stream or
+ * returned as a newly allocated string in @trace, if not #NULL.
+ *
+ * In some error cases (e.g. segmentation fault), trying to allocate
+ * more memory will trigger more segmentation faults and therefore loop
+ * our error handling (which is just wrong). Therefore printing to a
+ * file description is an implementation without any memory allocation.
+
+ * Return value: #TRUE if a stack trace could be generated, #FALSE
+ * otherwise.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gimp_stack_trace_print (const gchar *prog_name,
+ gpointer stream,
+ gchar **trace)
+{
+ gboolean stack_printed = FALSE;
+
+ /* This works only on UNIX systems. */
+#ifndef G_OS_WIN32
+ GString *gtrace = NULL;
+ gchar gimp_pid[16];
+ gchar buffer[256];
+ ssize_t read_n;
+ int sync_fd[2];
+ int out_fd[2];
+ pid_t fork_pid;
+ pid_t pid = getpid();
+ gint eintr_count = 0;
+#if defined(G_OS_WIN32)
+ DWORD tid = GetCurrentThreadId ();
+#elif defined(PLATFORM_OSX)
+ uint64 tid64;
+ long tid;
+
+ pthread_threadid_np (NULL, &tid64);
+ tid = (long) tid64;
+#elif defined(SYS_gettid)
+ long tid = syscall (SYS_gettid);
+#elif defined(HAVE_THR_SELF)
+ long tid = 0;
+ thr_self (&tid);
+#endif
+
+ g_snprintf (gimp_pid, 16, "%u", (guint) pid);
+
+ if (pipe (sync_fd) == -1)
+ {
+ return FALSE;
+ }
+
+ if (pipe (out_fd) == -1)
+ {
+ close (sync_fd[0]);
+ close (sync_fd[1]);
+
+ return FALSE;
+ }
+
+ fork_pid = fork ();
+ if (fork_pid == 0)
+ {
+ /* Child process. */
+ gchar *args[9] = { "gdb", "-batch",
+ "-ex", "info threads",
+ "-ex", "thread apply all backtrace full",
+ (gchar *) prog_name, NULL, NULL };
+
+ if (prog_name == NULL)
+ args[6] = "-p";
+
+ args[7] = gimp_pid;
+
+ /* Wait until the parent enabled us to ptrace it. */
+ {
+ gchar dummy;
+
+ close (sync_fd[1]);
+ while (read (sync_fd[0], &dummy, 1) < 0 && errno == EINTR);
+ close (sync_fd[0]);
+ }
+
+ /* Redirect the debugger output. */
+ dup2 (out_fd[1], STDOUT_FILENO);
+ close (out_fd[0]);
+ close (out_fd[1]);
+
+ /* Run GDB if version 7.0 or over. Why I do such a check is that
+ * it turns out older versions may not only fail, but also have
+ * very undesirable side effects like terminating the debugged
+ * program, at least on FreeBSD where GDB 6.1 is apparently
+ * installed by default on the stable release at day of writing.
+ * See bug 793514. */
+ if (! gimp_utils_gdb_available (7, 0) ||
+ execvp (args[0], args) == -1)
+ {
+ /* LLDB as alternative if the GDB call failed or if it was in
+ * a too-old version. */
+ gchar *args_lldb[15] = { "lldb", "--attach-pid", NULL, "--batch",
+ "--one-line", "thread list",
+ "--one-line", "thread backtrace all",
+ "--one-line", "bt all",
+ "--one-line-on-crash", "bt",
+ "--one-line-on-crash", "quit", NULL };
+
+ args_lldb[2] = gimp_pid;
+
+ execvp (args_lldb[0], args_lldb);
+ }
+
+ _exit (0);
+ }
+ else if (fork_pid > 0)
+ {
+ /* Main process */
+ int status;
+
+ /* Allow the child to ptrace us, and signal it to start. */
+ close (sync_fd[0]);
+#ifdef PR_SET_PTRACER
+ prctl (PR_SET_PTRACER, fork_pid, 0, 0, 0);
+#endif
+ close (sync_fd[1]);
+
+ /* It is important to close the writing side of the pipe, otherwise
+ * the read() will wait forever without getting the information that
+ * writing is finished.
+ */
+ close (out_fd[1]);
+
+ while ((read_n = read (out_fd[0], buffer, 256)) != 0)
+ {
+ if (read_n < 0)
+ {
+ /* LLDB on macOS seems to trigger a few EINTR error (see
+ * !13), though read() finally ends up working later. So
+ * let's not make this error fatal, and instead try again.
+ * Yet to avoid infinite loop (in case the error really
+ * happens at every call), we abandon after a few
+ * consecutive errors.
+ */
+ if (errno == EINTR && eintr_count <= 5)
+ {
+ eintr_count++;
+ continue;
+ }
+ break;
+ }
+ eintr_count = 0;
+ if (! stack_printed)
+ {
+#if defined(PLATFORM_OSX)
+ if (stream)
+ g_fprintf (stream,
+ "\n# Stack traces obtained from PID %d - Thread 0x%lx #\n\n",
+ pid, tid);
+#elif defined(G_OS_WIN32) || defined(SYS_gettid) || defined(HAVE_THR_SELF)
+ if (stream)
+ g_fprintf (stream,
+ "\n# Stack traces obtained from PID %d - Thread %lu #\n\n",
+ pid, tid);
+#endif
+ if (trace)
+ {
+ gtrace = g_string_new (NULL);
+#if defined(PLATFORM_OSX)
+ g_string_printf (gtrace,
+ "\n# Stack traces obtained from PID %d - Thread 0x%lx #\n\n",
+ pid, tid);
+#elif defined(G_OS_WIN32) || defined(SYS_gettid) || defined(HAVE_THR_SELF)
+ g_string_printf (gtrace,
+ "\n# Stack traces obtained from PID %d - Thread %lu #\n\n",
+ pid, tid);
+#endif
+ }
+ }
+ /* It's hard to know if the debugger was found since it
+ * happened in the child. Let's just assume that any output
+ * means it succeeded.
+ */
+ stack_printed = TRUE;
+
+ buffer[read_n] = '\0';
+ if (stream)
+ g_fprintf (stream, "%s", buffer);
+ if (trace)
+ g_string_append (gtrace, (const gchar *) buffer);
+ }
+ close (out_fd[0]);
+
+#ifdef PR_SET_PTRACER
+ /* Clear ptrace permission set above */
+ prctl (PR_SET_PTRACER, 0, 0, 0, 0);
+#endif
+
+ waitpid (fork_pid, &status, 0);
+ }
+ /* else if (fork_pid == (pid_t) -1)
+ * Fork failed!
+ * Just continue, maybe the backtrace() API will succeed.
+ */
+
+#ifdef HAVE_EXECINFO_H
+ if (! stack_printed)
+ {
+ /* As a last resort, try using the backtrace() Linux API. It is a bit
+ * less fancy than gdb or lldb, which is why it is not given priority.
+ */
+ void *bt_buf[100];
+ int n_symbols;
+
+ n_symbols = backtrace (bt_buf, 100);
+ if (trace && n_symbols)
+ {
+ char **symbols;
+ int i;
+
+ symbols = backtrace_symbols (bt_buf, n_symbols);
+ if (symbols)
+ {
+ for (i = 0; i < n_symbols; i++)
+ {
+ if (stream)
+ g_fprintf (stream, "%s\n", (const gchar *) symbols[i]);
+ if (trace)
+ {
+ if (! gtrace)
+ gtrace = g_string_new (NULL);
+ g_string_append (gtrace,
+ (const gchar *) symbols[i]);
+ g_string_append_c (gtrace, '\n');
+ }
+ }
+ free (symbols);
+ }
+ }
+ else if (n_symbols)
+ {
+ /* This allows to generate traces without memory allocation.
+ * In some cases, this is necessary, especially during
+ * segfault-type crashes.
+ */
+ backtrace_symbols_fd (bt_buf, n_symbols, fileno ((FILE *) stream));
+ }
+ stack_printed = (n_symbols > 0);
+ }
+#endif /* HAVE_EXECINFO_H */
+
+ if (trace)
+ {
+ if (gtrace)
+ *trace = g_string_free (gtrace, FALSE);
+ else
+ *trace = NULL;
+ }
+#endif /* G_OS_WIN32 */
+
+ return stack_printed;
+}
+
+/**
+ * gimp_stack_trace_query:
+ * @prog_name: the program to attach to.
+ *
+ * This is mostly the same as g_on_error_query() except that we use our
+ * own backtrace function, much more complete.
+ * @prog_name must be the current program name (argv[0]).
+ * It does nothing on Win32.
+ *
+ * Since: 2.10
+ **/
+void
+gimp_stack_trace_query (const gchar *prog_name)
+{
+#ifndef G_OS_WIN32
+ gchar buf[16];
+
+ retry:
+
+ g_fprintf (stdout,
+ "%s (pid:%u): %s: ",
+ prog_name,
+ (guint) getpid (),
+ "[E]xit, show [S]tack trace or [P]roceed");
+ fflush (stdout);
+
+ if (isatty(0) && isatty(1))
+ fgets (buf, 8, stdin);
+ else
+ strcpy (buf, "E\n");
+
+ if ((buf[0] == 'E' || buf[0] == 'e')
+ && buf[1] == '\n')
+ _exit (0);
+ else if ((buf[0] == 'P' || buf[0] == 'p')
+ && buf[1] == '\n')
+ return;
+ else if ((buf[0] == 'S' || buf[0] == 's')
+ && buf[1] == '\n')
+ {
+ if (! gimp_stack_trace_print (prog_name, stdout, NULL))
+ g_fprintf (stderr, "%s\n", "Stack trace not available on your system.");
+ goto retry;
+ }
+ else
+ goto retry;
+#endif
+}
+
+
+/* Private functions. */
+
+static gboolean
+gimp_utils_generic_available (const gchar *program,
+ gint major,
+ gint minor)
+{
+#ifndef G_OS_WIN32
+ pid_t pid;
+ int out_fd[2];
+
+ if (pipe (out_fd) == -1)
+ {
+ return FALSE;
+ }
+
+ /* XXX: I don't use g_spawn_sync() or similar glib functions because
+ * to read the contents of the stdout, these functions would allocate
+ * memory dynamically. As we know, when debugging crashes, this is a
+ * definite blocker. So instead I simply use a buffer on the stack
+ * with a lower level fork() call.
+ */
+ pid = fork ();
+ if (pid == 0)
+ {
+ /* Child process. */
+ gchar *args[3] = { (gchar *) program, "--version", NULL };
+
+ /* Redirect the debugger output. */
+ dup2 (out_fd[1], STDOUT_FILENO);
+ close (out_fd[0]);
+ close (out_fd[1]);
+
+ /* Run version check. */
+ execvp (args[0], args);
+ _exit (-1);
+ }
+ else if (pid > 0)
+ {
+ /* Main process */
+ gchar buffer[256];
+ ssize_t read_n;
+ int status;
+ gint installed_major = 0;
+ gint installed_minor = 0;
+ gboolean major_reading = FALSE;
+ gboolean minor_reading = FALSE;
+ gint i;
+ gchar c;
+
+ waitpid (pid, &status, 0);
+
+ if (! WIFEXITED (status) || WEXITSTATUS (status) != 0)
+ return FALSE;
+
+ /* It is important to close the writing side of the pipe, otherwise
+ * the read() will wait forever without getting the information that
+ * writing is finished.
+ */
+ close (out_fd[1]);
+
+ /* I could loop forever until EOL, but I am pretty sure the
+ * version information is stored on the first line and one call to
+ * read() with 256 characters should be more than enough.
+ */
+ read_n = read (out_fd[0], buffer, 256);
+
+ /* This is quite a very stupid parser. I only look for the first
+ * numbers and consider them as version information. This works
+ * fine for both GDB and LLDB as far as I can see for the output
+ * of `${program} --version` but this should obviously not be
+ * considered as a *really* generic version test.
+ */
+ for (i = 0; i < read_n; i++)
+ {
+ c = buffer[i];
+ if (c >= '0' && c <= '9')
+ {
+ if (minor_reading)
+ {
+ installed_minor = 10 * installed_minor + (c - '0');
+ }
+ else
+ {
+ major_reading = TRUE;
+ installed_major = 10 * installed_major + (c - '0');
+ }
+ }
+ else if (c == '.')
+ {
+ if (major_reading)
+ {
+ minor_reading = TRUE;
+ major_reading = FALSE;
+ }
+ else if (minor_reading)
+ {
+ break;
+ }
+ }
+ else if (c == '\n')
+ {
+ /* Version information should be in the first line. */
+ break;
+ }
+ }
+ close (out_fd[0]);
+
+ return (installed_major > 0 &&
+ (installed_major > major ||
+ (installed_major == major && installed_minor >= minor)));
+ }
+#endif
+
+ /* Fork failed, or Win32. */
+ return FALSE;
+}
+
+static gboolean
+gimp_utils_gdb_available (gint major,
+ gint minor)
+{
+ return gimp_utils_generic_available ("gdb", major, minor);
+}
diff --git a/libgimpbase/gimputils.h b/libgimpbase/gimputils.h
new file mode 100644
index 0000000..ca7b730
--- /dev/null
+++ b/libgimpbase/gimputils.h
@@ -0,0 +1,87 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_UTILS_H__
+#define __GIMP_UTILS_H__
+
+G_BEGIN_DECLS
+
+
+gchar * gimp_utf8_strtrim (const gchar *str,
+ gint max_chars) G_GNUC_MALLOC;
+gchar * gimp_any_to_utf8 (const gchar *str,
+ gssize len,
+ const gchar *warning_format,
+ ...) G_GNUC_PRINTF (3, 4) G_GNUC_MALLOC;
+const gchar * gimp_filename_to_utf8 (const gchar *filename);
+
+const gchar * gimp_file_get_utf8_name (GFile *file);
+gboolean gimp_file_has_extension (GFile *file,
+ const gchar *extension);
+gboolean gimp_file_show_in_file_manager (GFile *file,
+ GError **error);
+
+gchar * gimp_strip_uline (const gchar *str) G_GNUC_MALLOC;
+gchar * gimp_escape_uline (const gchar *str) G_GNUC_MALLOC;
+
+gchar * gimp_canonicalize_identifier (const gchar *identifier) G_GNUC_MALLOC;
+
+GimpEnumDesc * gimp_enum_get_desc (GEnumClass *enum_class,
+ gint value);
+gboolean gimp_enum_get_value (GType enum_type,
+ gint value,
+ const gchar **value_name,
+ const gchar **value_nick,
+ const gchar **value_desc,
+ const gchar **value_help);
+const gchar * gimp_enum_value_get_desc (GEnumClass *enum_class,
+ GEnumValue *enum_value);
+const gchar * gimp_enum_value_get_help (GEnumClass *enum_class,
+ GEnumValue *enum_value);
+const gchar * gimp_enum_value_get_abbrev (GEnumClass *enum_class,
+ GEnumValue *enum_value);
+
+GimpFlagsDesc * gimp_flags_get_first_desc (GFlagsClass *flags_class,
+ guint value);
+gboolean gimp_flags_get_first_value (GType flags_type,
+ guint value,
+ const gchar **value_name,
+ const gchar **value_nick,
+ const gchar **value_desc,
+ const gchar **value_help);
+const gchar * gimp_flags_value_get_desc (GFlagsClass *flags_class,
+ GFlagsValue *flags_value);
+const gchar * gimp_flags_value_get_help (GFlagsClass *flags_class,
+ GFlagsValue *flags_value);
+const gchar * gimp_flags_value_get_abbrev (GFlagsClass *flags_class,
+ GFlagsValue *flags_value);
+
+gboolean gimp_stack_trace_available (gboolean optimal);
+gboolean gimp_stack_trace_print (const gchar *prog_name,
+ gpointer stream,
+ gchar **trace);
+void gimp_stack_trace_query (const gchar *prog_name);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_UTILS_H__ */
diff --git a/libgimpbase/gimpvaluearray.c b/libgimpbase/gimpvaluearray.c
new file mode 100644
index 0000000..eb23b82
--- /dev/null
+++ b/libgimpbase/gimpvaluearray.c
@@ -0,0 +1,589 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpvaluearray.c ported from GValueArray
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib-object.h>
+
+#include "gimpbasetypes.h"
+
+#include "gimpvaluearray.h"
+
+
+/**
+ * SECTION:gimpvaluearray
+ * @short_description: A container structure to maintain an array of
+ * generic values
+ * @see_also: #GValue, #GParamSpecValueArray, gimp_param_spec_value_array()
+ * @title: GimpValueArray
+ *
+ * The prime purpose of a #GimpValueArray is for it to be used as an
+ * object property that holds an array of values. A #GimpValueArray wraps
+ * an array of #GValue elements in order for it to be used as a boxed
+ * type through %GIMP_TYPE_VALUE_ARRAY.
+ */
+
+
+#define GROUP_N_VALUES (1) /* power of 2 !! */
+
+
+/**
+ * GimpValueArray:
+ *
+ * A #GimpValueArray contains an array of #GValue elements.
+ *
+ * Since: 2.10
+ */
+struct _GimpValueArray
+{
+ gint n_values;
+ GValue *values;
+
+ gint n_prealloced;
+ gint ref_count;
+};
+
+
+G_DEFINE_BOXED_TYPE (GimpValueArray, gimp_value_array,
+ gimp_value_array_ref, gimp_value_array_unref)
+
+
+/**
+ * gimp_value_array_index:
+ * @value_array: #GimpValueArray to get a value from
+ * @index: index of the value of interest
+ *
+ * Return a pointer to the value at @index contained in @value_array.
+ *
+ * Returns: (transfer none): pointer to a value at @index in @value_array
+ *
+ * Since: 2.10
+ */
+GValue *
+gimp_value_array_index (const GimpValueArray *value_array,
+ gint index)
+{
+ g_return_val_if_fail (value_array != NULL, NULL);
+ g_return_val_if_fail (index < value_array->n_values, NULL);
+
+ return value_array->values + index;
+}
+
+static inline void
+value_array_grow (GimpValueArray *value_array,
+ gint n_values,
+ gboolean zero_init)
+{
+ g_return_if_fail ((guint) n_values >= (guint) value_array->n_values);
+
+ value_array->n_values = n_values;
+ if (value_array->n_values > value_array->n_prealloced)
+ {
+ gint i = value_array->n_prealloced;
+
+ value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
+ value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
+
+ if (!zero_init)
+ i = value_array->n_values;
+
+ memset (value_array->values + i, 0,
+ (value_array->n_prealloced - i) * sizeof (value_array->values[0]));
+ }
+}
+
+static inline void
+value_array_shrink (GimpValueArray *value_array)
+{
+ if (value_array->n_prealloced >= value_array->n_values + GROUP_N_VALUES)
+ {
+ value_array->n_prealloced = (value_array->n_values + GROUP_N_VALUES - 1) & ~(GROUP_N_VALUES - 1);
+ value_array->values = g_renew (GValue, value_array->values, value_array->n_prealloced);
+ }
+}
+
+/**
+ * gimp_value_array_new:
+ * @n_prealloced: number of values to preallocate space for
+ *
+ * Allocate and initialize a new #GimpValueArray, optionally preserve space
+ * for @n_prealloced elements. New arrays always contain 0 elements,
+ * regardless of the value of @n_prealloced.
+ *
+ * Returns: a newly allocated #GimpValueArray with 0 values
+ *
+ * Since: 2.10
+ */
+GimpValueArray *
+gimp_value_array_new (gint n_prealloced)
+{
+ GimpValueArray *value_array = g_slice_new (GimpValueArray);
+
+ value_array->n_values = 0;
+ value_array->n_prealloced = 0;
+ value_array->values = NULL;
+ value_array_grow (value_array, n_prealloced, TRUE);
+ value_array->n_values = 0;
+ value_array->ref_count = 1;
+
+ return value_array;
+}
+
+/**
+ * gimp_value_array_ref:
+ * @value_array: #GimpValueArray to ref
+ *
+ * Adds a reference to a #GimpValueArray.
+ *
+ * Return value: the same @value_array
+ *
+ * Since: 2.10
+ */
+GimpValueArray *
+gimp_value_array_ref (GimpValueArray *value_array)
+{
+ g_return_val_if_fail (value_array != NULL, NULL);
+
+ value_array->ref_count++;
+
+ return value_array;
+}
+
+/**
+ * gimp_value_array_unref:
+ * @value_array: #GimpValueArray to unref
+ *
+ * Unref a #GimpValueArray. If the reference count drops to zero, the
+ * array including its contents are freed.
+ *
+ * Since: 2.10
+ */
+void
+gimp_value_array_unref (GimpValueArray *value_array)
+{
+ g_return_if_fail (value_array != NULL);
+
+ value_array->ref_count--;
+
+ if (value_array->ref_count < 1)
+ {
+ gint i;
+
+ for (i = 0; i < value_array->n_values; i++)
+ {
+ GValue *value = value_array->values + i;
+
+ if (G_VALUE_TYPE (value) != 0) /* we allow unset values in the array */
+ g_value_unset (value);
+ }
+
+ g_free (value_array->values);
+ g_slice_free (GimpValueArray, value_array);
+ }
+}
+
+gint
+gimp_value_array_length (const GimpValueArray *value_array)
+{
+ g_return_val_if_fail (value_array != NULL, 0);
+
+ return value_array->n_values;
+}
+
+/**
+ * gimp_value_array_prepend:
+ * @value_array: #GimpValueArray to add an element to
+ * @value: (allow-none): #GValue to copy into #GimpValueArray, or %NULL
+ *
+ * Insert a copy of @value as first element of @value_array. If @value is
+ * %NULL, an uninitialized value is prepended.
+ *
+ * Returns: (transfer none): the #GimpValueArray passed in as @value_array
+ *
+ * Since: 2.10
+ */
+GimpValueArray *
+gimp_value_array_prepend (GimpValueArray *value_array,
+ const GValue *value)
+{
+ g_return_val_if_fail (value_array != NULL, NULL);
+
+ return gimp_value_array_insert (value_array, 0, value);
+}
+
+/**
+ * gimp_value_array_append:
+ * @value_array: #GimpValueArray to add an element to
+ * @value: (allow-none): #GValue to copy into #GimpValueArray, or %NULL
+ *
+ * Insert a copy of @value as last element of @value_array. If @value is
+ * %NULL, an uninitialized value is appended.
+ *
+ * Returns: (transfer none): the #GimpValueArray passed in as @value_array
+ *
+ * Since: 2.10
+ */
+GimpValueArray *
+gimp_value_array_append (GimpValueArray *value_array,
+ const GValue *value)
+{
+ g_return_val_if_fail (value_array != NULL, NULL);
+
+ return gimp_value_array_insert (value_array, value_array->n_values, value);
+}
+
+/**
+ * gimp_value_array_insert:
+ * @value_array: #GimpValueArray to add an element to
+ * @index: insertion position, must be &lt;= gimp_value_array_length()
+ * @value: (allow-none): #GValue to copy into #GimpValueArray, or %NULL
+ *
+ * Insert a copy of @value at specified position into @value_array. If @value
+ * is %NULL, an uninitialized value is inserted.
+ *
+ * Returns: (transfer none): the #GimpValueArray passed in as @value_array
+ *
+ * Since: 2.10
+ */
+GimpValueArray *
+gimp_value_array_insert (GimpValueArray *value_array,
+ gint index,
+ const GValue *value)
+{
+ gint i;
+
+ g_return_val_if_fail (value_array != NULL, NULL);
+ g_return_val_if_fail (index <= value_array->n_values, value_array);
+
+ i = value_array->n_values;
+ value_array_grow (value_array, value_array->n_values + 1, FALSE);
+
+ if (index + 1 < value_array->n_values)
+ memmove (value_array->values + index + 1, value_array->values + index,
+ (i - index) * sizeof (value_array->values[0]));
+
+ memset (value_array->values + index, 0, sizeof (value_array->values[0]));
+
+ if (value)
+ {
+ g_value_init (value_array->values + index, G_VALUE_TYPE (value));
+ g_value_copy (value, value_array->values + index);
+ }
+
+ return value_array;
+}
+
+/**
+ * gimp_value_array_remove:
+ * @value_array: #GimpValueArray to remove an element from
+ * @index: position of value to remove, which must be less than
+ * gimp_value_array_length()
+ *
+ * Remove the value at position @index from @value_array.
+ *
+ * Returns: (transfer none): the #GimpValueArray passed in as @value_array
+ *
+ * Since: 2.10
+ */
+GimpValueArray *
+gimp_value_array_remove (GimpValueArray *value_array,
+ gint index)
+{
+ g_return_val_if_fail (value_array != NULL, NULL);
+ g_return_val_if_fail (index < value_array->n_values, value_array);
+
+ if (G_VALUE_TYPE (value_array->values + index) != 0)
+ g_value_unset (value_array->values + index);
+
+ value_array->n_values--;
+
+ if (index < value_array->n_values)
+ memmove (value_array->values + index, value_array->values + index + 1,
+ (value_array->n_values - index) * sizeof (value_array->values[0]));
+
+ value_array_shrink (value_array);
+
+ if (value_array->n_prealloced > value_array->n_values)
+ memset (value_array->values + value_array->n_values, 0, sizeof (value_array->values[0]));
+
+ return value_array;
+}
+
+void
+gimp_value_array_truncate (GimpValueArray *value_array,
+ gint n_values)
+{
+ gint i;
+
+ g_return_if_fail (value_array != NULL);
+ g_return_if_fail (n_values > 0 && n_values <= value_array->n_values);
+
+ for (i = value_array->n_values; i > n_values; i--)
+ gimp_value_array_remove (value_array, i - 1);
+}
+
+
+/*
+ * GIMP_TYPE_PARAM_VALUE_ARRAY
+ */
+
+static void gimp_param_value_array_class_init (GParamSpecClass *klass);
+static void gimp_param_value_array_init (GParamSpec *pspec);
+static void gimp_param_value_array_finalize (GParamSpec *pspec);
+static void gimp_param_value_array_set_default (GParamSpec *pspec,
+ GValue *value);
+static gboolean gimp_param_value_array_validate (GParamSpec *pspec,
+ GValue *value);
+static gint gimp_param_value_array_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2);
+
+GType
+gimp_param_value_array_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type)
+ {
+ const GTypeInfo info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_value_array_class_init,
+ NULL, NULL,
+ sizeof (GimpParamSpecValueArray),
+ 0,
+ (GInstanceInitFunc) gimp_param_value_array_init
+ };
+
+ type = g_type_register_static (G_TYPE_PARAM_BOXED,
+ "GimpParamValueArray", &info, 0);
+ }
+
+ return type;
+}
+
+
+static void
+gimp_param_value_array_class_init (GParamSpecClass *klass)
+{
+ klass->value_type = GIMP_TYPE_VALUE_ARRAY;
+ klass->finalize = gimp_param_value_array_finalize;
+ klass->value_set_default = gimp_param_value_array_set_default;
+ klass->value_validate = gimp_param_value_array_validate;
+ klass->values_cmp = gimp_param_value_array_values_cmp;
+}
+
+static void
+gimp_param_value_array_init (GParamSpec *pspec)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+
+ aspec->element_spec = NULL;
+ aspec->fixed_n_elements = 0; /* disable */
+}
+
+static inline guint
+gimp_value_array_ensure_size (GimpValueArray *value_array,
+ guint fixed_n_elements)
+{
+ guint changed = 0;
+
+ if (fixed_n_elements)
+ {
+ while (gimp_value_array_length (value_array) < fixed_n_elements)
+ {
+ gimp_value_array_append (value_array, NULL);
+ changed++;
+ }
+
+ while (gimp_value_array_length (value_array) > fixed_n_elements)
+ {
+ gimp_value_array_remove (value_array,
+ gimp_value_array_length (value_array) - 1);
+ changed++;
+ }
+ }
+
+ return changed;
+}
+
+static void
+gimp_param_value_array_finalize (GParamSpec *pspec)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+ GParamSpecClass *parent_class;
+
+ parent_class = g_type_class_peek (g_type_parent (GIMP_TYPE_PARAM_VALUE_ARRAY));
+
+ g_clear_pointer (&aspec->element_spec, g_param_spec_unref);
+
+ parent_class->finalize (pspec);
+}
+
+static void
+gimp_param_value_array_set_default (GParamSpec *pspec,
+ GValue *value)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+
+ if (! value->data[0].v_pointer && aspec->fixed_n_elements)
+ value->data[0].v_pointer = gimp_value_array_new (aspec->fixed_n_elements);
+
+ if (value->data[0].v_pointer)
+ {
+ /* g_value_reset (value); already done */
+ gimp_value_array_ensure_size (value->data[0].v_pointer,
+ aspec->fixed_n_elements);
+ }
+}
+
+static gboolean
+gimp_param_value_array_validate (GParamSpec *pspec,
+ GValue *value)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+ GimpValueArray *value_array = value->data[0].v_pointer;
+ guint changed = 0;
+
+ if (! value->data[0].v_pointer && aspec->fixed_n_elements)
+ value->data[0].v_pointer = gimp_value_array_new (aspec->fixed_n_elements);
+
+ if (value->data[0].v_pointer)
+ {
+ /* ensure array size validity */
+ changed += gimp_value_array_ensure_size (value_array,
+ aspec->fixed_n_elements);
+
+ /* ensure array values validity against a present element spec */
+ if (aspec->element_spec)
+ {
+ GParamSpec *element_spec = aspec->element_spec;
+ gint length = gimp_value_array_length (value_array);
+ gint i;
+
+ for (i = 0; i < length; i++)
+ {
+ GValue *element = gimp_value_array_index (value_array, i);
+
+ /* need to fixup value type, or ensure that the array
+ * value is initialized at all
+ */
+ if (! g_value_type_compatible (G_VALUE_TYPE (element),
+ G_PARAM_SPEC_VALUE_TYPE (element_spec)))
+ {
+ if (G_VALUE_TYPE (element) != 0)
+ g_value_unset (element);
+
+ g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec));
+ g_param_value_set_default (element_spec, element);
+ changed++;
+ }
+
+ /* validate array value against element_spec */
+ changed += g_param_value_validate (element_spec, element);
+ }
+ }
+ }
+
+ return changed;
+}
+
+static gint
+gimp_param_value_array_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2)
+{
+ GimpParamSpecValueArray *aspec = GIMP_PARAM_SPEC_VALUE_ARRAY (pspec);
+ GimpValueArray *value_array1 = value1->data[0].v_pointer;
+ GimpValueArray *value_array2 = value2->data[0].v_pointer;
+ gint length1;
+ gint length2;
+
+ if (!value_array1 || !value_array2)
+ return value_array2 ? -1 : value_array1 != value_array2;
+
+ length1 = gimp_value_array_length (value_array1);
+ length2 = gimp_value_array_length (value_array2);
+
+ if (length1 != length2)
+ {
+ return length1 < length2 ? -1 : 1;
+ }
+ else if (! aspec->element_spec)
+ {
+ /* we need an element specification for comparisons, so there's
+ * not much to compare here, try to at least provide stable
+ * lesser/greater result
+ */
+ return length1 < length2 ? -1 : length1 > length2;
+ }
+ else /* length1 == length2 */
+ {
+ guint i;
+
+ for (i = 0; i < length1; i++)
+ {
+ GValue *element1 = gimp_value_array_index (value_array1, i);
+ GValue *element2 = gimp_value_array_index (value_array2, i);
+ gint cmp;
+
+ /* need corresponding element types, provide stable result
+ * otherwise
+ */
+ if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2))
+ return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1;
+
+ cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
+ if (cmp)
+ return cmp;
+ }
+
+ return 0;
+ }
+}
+
+GParamSpec *
+gimp_param_spec_value_array (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamSpec *element_spec,
+ GParamFlags flags)
+{
+ GimpParamSpecValueArray *aspec;
+
+ if (element_spec)
+ g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
+
+ aspec = g_param_spec_internal (GIMP_TYPE_PARAM_VALUE_ARRAY,
+ name,
+ nick,
+ blurb,
+ flags);
+ if (element_spec)
+ {
+ aspec->element_spec = g_param_spec_ref (element_spec);
+ g_param_spec_sink (element_spec);
+ }
+
+ return G_PARAM_SPEC (aspec);
+}
diff --git a/libgimpbase/gimpvaluearray.h b/libgimpbase/gimpvaluearray.h
new file mode 100644
index 0000000..d7aefcb
--- /dev/null
+++ b/libgimpbase/gimpvaluearray.h
@@ -0,0 +1,104 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpvaluearray.h ported from GValueArray
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_VALUE_ARRAY_H__
+#define __GIMP_VALUE_ARRAY_H__
+
+G_BEGIN_DECLS
+
+/**
+ * GIMP_TYPE_VALUE_ARRAY:
+ *
+ * The type ID of the "GimpValueArray" type which is a boxed type,
+ * used to pass around pointers to GimpValueArrays.
+ *
+ * Since: 2.10
+ */
+#define GIMP_TYPE_VALUE_ARRAY (gimp_value_array_get_type ())
+
+
+GType gimp_value_array_get_type (void) G_GNUC_CONST;
+
+GimpValueArray * gimp_value_array_new (gint n_prealloced);
+
+GimpValueArray * gimp_value_array_ref (GimpValueArray *value_array);
+void gimp_value_array_unref (GimpValueArray *value_array);
+
+gint gimp_value_array_length (const GimpValueArray *value_array);
+
+GValue * gimp_value_array_index (const GimpValueArray *value_array,
+ gint index);
+
+GimpValueArray * gimp_value_array_prepend (GimpValueArray *value_array,
+ const GValue *value);
+GimpValueArray * gimp_value_array_append (GimpValueArray *value_array,
+ const GValue *value);
+GimpValueArray * gimp_value_array_insert (GimpValueArray *value_array,
+ gint index,
+ const GValue *value);
+
+GimpValueArray * gimp_value_array_remove (GimpValueArray *value_array,
+ gint index);
+void gimp_value_array_truncate (GimpValueArray *value_array,
+ gint n_values);
+
+
+/*
+ * GIMP_TYPE_PARAM_VALUE_ARRAY
+ */
+
+#define GIMP_TYPE_PARAM_VALUE_ARRAY (gimp_param_value_array_get_type ())
+#define GIMP_IS_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_VALUE_ARRAY))
+#define GIMP_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_VALUE_ARRAY, GimpParamSpecValueArray))
+
+typedef struct _GimpParamSpecValueArray GimpParamSpecValueArray;
+
+/**
+ * GimpParamSpecValueArray:
+ * @parent_instance: private #GParamSpec portion
+ * @element_spec: the #GParamSpec of the array elements
+ * @fixed_n_elements: default length of the array
+ *
+ * A #GParamSpec derived structure that contains the meta data for
+ * value array properties.
+ **/
+struct _GimpParamSpecValueArray
+{
+ GParamSpec parent_instance;
+ GParamSpec *element_spec;
+ gint fixed_n_elements;
+};
+
+GType gimp_param_value_array_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_value_array (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ GParamSpec *element_spec,
+ GParamFlags flags);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_VALUE_ARRAY_H__ */
diff --git a/libgimpbase/gimpversion.h b/libgimpbase/gimpversion.h
new file mode 100644
index 0000000..5871d3c
--- /dev/null
+++ b/libgimpbase/gimpversion.h
@@ -0,0 +1,70 @@
+/* gimpversion.h
+ *
+ * This is a generated file. Please modify 'configure.ac'
+ */
+
+#if !defined (__GIMP_BASE_H_INSIDE__) && !defined (GIMP_BASE_COMPILATION)
+#error "Only <libgimpbase/gimpbase.h> can be included directly."
+#endif
+
+#ifndef __GIMP_VERSION_H__
+#define __GIMP_VERSION_H__
+
+G_BEGIN_DECLS
+
+
+/**
+ * SECTION: gimpversion
+ * @title: gimpversion
+ * @short_description: Macros and constants useful for determining
+ * GIMP's version number and capabilities.
+ *
+ * Macros and constants useful for determining GIMP's version number and
+ * capabilities.
+ **/
+
+/**
+ * GIMP_MAJOR_VERSION:
+ *
+ * The major GIMP version number.
+ **/
+#define GIMP_MAJOR_VERSION (2)
+
+/**
+ * GIMP_MINOR_VERSION:
+ *
+ * The minor GIMP version number.
+ **/
+#define GIMP_MINOR_VERSION (10)
+
+/**
+ * GIMP_MICRO_VERSION:
+ *
+ * The micro GIMP version number.
+ **/
+#define GIMP_MICRO_VERSION (34)
+
+/**
+ * GIMP_VERSION:
+ *
+ * The GIMP version as a string.
+ **/
+#define GIMP_VERSION "2.10.34"
+
+/**
+ * GIMP_API_VERSION:
+ *
+ * Since: 2.2
+ **/
+#define GIMP_API_VERSION "2.0"
+
+#define GIMP_CHECK_VERSION(major, minor, micro) \
+ (GIMP_MAJOR_VERSION > (major) || \
+ (GIMP_MAJOR_VERSION == (major) && GIMP_MINOR_VERSION > (minor)) || \
+ (GIMP_MAJOR_VERSION == (major) && GIMP_MINOR_VERSION == (minor) && \
+ GIMP_MICRO_VERSION >= (micro)))
+
+
+G_END_DECLS
+
+#endif /* __GIMP_VERSION_H__ */
diff --git a/libgimpbase/gimpwin32-io.h b/libgimpbase/gimpwin32-io.h
new file mode 100644
index 0000000..45a3104
--- /dev/null
+++ b/libgimpbase/gimpwin32-io.h
@@ -0,0 +1,99 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpwin32-io.h
+ * Compatibility defines, you mostly need this as unistd.h replacement
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_WIN32_IO_H__
+#define __GIMP_WIN32_IO_H__
+
+#include <io.h>
+#include <direct.h>
+
+G_BEGIN_DECLS
+
+
+#define mkdir(n,a) _mkdir(n)
+#define chmod(n,f) _chmod(n,f)
+#define access(f,p) _access(f,p)
+
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
+#endif
+
+#ifndef S_IRUSR
+#define S_IRUSR _S_IREAD
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR _S_IWRITE
+#endif
+#ifndef S_IXUSR
+#define S_IXUSR _S_IEXEC
+#endif
+
+#ifndef S_IRGRP
+#define S_IRGRP _S_IREAD
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP _S_IEXEC
+#endif
+#ifndef S_IROTH
+#define S_IROTH _S_IREAD
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH _S_IEXEC
+#endif
+
+#ifndef _O_BINARY
+#define _O_BINARY 0
+#endif
+#ifndef _O_TEMPORARY
+#define _O_TEMPORARY 0
+#endif
+
+#ifndef F_OK
+#define F_OK 0
+#endif
+#ifndef W_OK
+#define W_OK 2
+#endif
+#ifndef R_OK
+#define R_OK 4
+#endif
+#ifndef X_OK
+#define X_OK 0 /* not really */
+#endif
+
+/*
+2004-09-15 Tor Lillqvist <tml@iki.fi>
+
+ * glib/gwin32.h: Don't define ftruncate as a macro. Was never a
+ good idea, and it clashes with newest mingw headers, which have a
+ ftruncate implementation as an inline function. Thanks to Dominik R.
+ */
+/* needs coorection for msvc though ;( */
+#ifdef _MSC_VER
+#define ftruncate(f,s) g_win32_ftruncate(f,s)
+#endif
+
+G_END_DECLS
+
+#endif /* __GIMP_WIN32_IO_H__ */
diff --git a/libgimpbase/gimpwire.c b/libgimpbase/gimpwire.c
new file mode 100644
index 0000000..9382bee
--- /dev/null
+++ b/libgimpbase/gimpwire.c
@@ -0,0 +1,695 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib-object.h>
+
+#include <libgimpcolor/gimpcolortypes.h>
+
+#include "gimpwire.h"
+
+
+typedef struct _GimpWireHandler GimpWireHandler;
+
+struct _GimpWireHandler
+{
+ guint32 type;
+ GimpWireReadFunc read_func;
+ GimpWireWriteFunc write_func;
+ GimpWireDestroyFunc destroy_func;
+};
+
+
+static GHashTable *wire_ht = NULL;
+static GimpWireIOFunc wire_read_func = NULL;
+static GimpWireIOFunc wire_write_func = NULL;
+static GimpWireFlushFunc wire_flush_func = NULL;
+static gboolean wire_error_val = FALSE;
+
+
+static void gimp_wire_init (void);
+
+
+void
+gimp_wire_register (guint32 type,
+ GimpWireReadFunc read_func,
+ GimpWireWriteFunc write_func,
+ GimpWireDestroyFunc destroy_func)
+{
+ GimpWireHandler *handler;
+
+ if (! wire_ht)
+ gimp_wire_init ();
+
+ handler = g_hash_table_lookup (wire_ht, &type);
+
+ if (! handler)
+ handler = g_slice_new0 (GimpWireHandler);
+
+ handler->type = type;
+ handler->read_func = read_func;
+ handler->write_func = write_func;
+ handler->destroy_func = destroy_func;
+
+ g_hash_table_insert (wire_ht, &handler->type, handler);
+}
+
+void
+gimp_wire_set_reader (GimpWireIOFunc read_func)
+{
+ wire_read_func = read_func;
+}
+
+void
+gimp_wire_set_writer (GimpWireIOFunc write_func)
+{
+ wire_write_func = write_func;
+}
+
+void
+gimp_wire_set_flusher (GimpWireFlushFunc flush_func)
+{
+ wire_flush_func = flush_func;
+}
+
+gboolean
+gimp_wire_read (GIOChannel *channel,
+ guint8 *buf,
+ gsize count,
+ gpointer user_data)
+{
+ if (wire_read_func)
+ {
+ if (!(* wire_read_func) (channel, buf, count, user_data))
+ {
+ /* Gives a confusing error message most of the time, disable:
+ g_warning ("%s: gimp_wire_read: error", g_get_prgname ());
+ */
+ wire_error_val = TRUE;
+ return FALSE;
+ }
+ }
+ else
+ {
+ GIOStatus status;
+ GError *error = NULL;
+ gsize bytes;
+
+ while (count > 0)
+ {
+ do
+ {
+ bytes = 0;
+ status = g_io_channel_read_chars (channel,
+ (gchar *) buf, count,
+ &bytes,
+ &error);
+ }
+ while (G_UNLIKELY (status == G_IO_STATUS_AGAIN));
+
+ if (G_UNLIKELY (status != G_IO_STATUS_NORMAL))
+ {
+ if (error)
+ {
+ g_warning ("%s: gimp_wire_read(): error: %s",
+ g_get_prgname (), error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ g_warning ("%s: gimp_wire_read(): error",
+ g_get_prgname ());
+ }
+
+ wire_error_val = TRUE;
+ return FALSE;
+ }
+
+ if (G_UNLIKELY (bytes == 0))
+ {
+ g_warning ("%s: gimp_wire_read(): unexpected EOF",
+ g_get_prgname ());
+ wire_error_val = TRUE;
+ return FALSE;
+ }
+
+ count -= bytes;
+ buf += bytes;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+gimp_wire_write (GIOChannel *channel,
+ const guint8 *buf,
+ gsize count,
+ gpointer user_data)
+{
+ if (wire_write_func)
+ {
+ if (!(* wire_write_func) (channel, (guint8 *) buf, count, user_data))
+ {
+ g_warning ("%s: gimp_wire_write: error", g_get_prgname ());
+ wire_error_val = TRUE;
+ return FALSE;
+ }
+ }
+ else
+ {
+ GIOStatus status;
+ GError *error = NULL;
+ gsize bytes;
+
+ while (count > 0)
+ {
+ do
+ {
+ bytes = 0;
+ status = g_io_channel_write_chars (channel,
+ (const gchar *) buf, count,
+ &bytes,
+ &error);
+ }
+ while (G_UNLIKELY (status == G_IO_STATUS_AGAIN));
+
+ if (G_UNLIKELY (status != G_IO_STATUS_NORMAL))
+ {
+ if (error)
+ {
+ g_warning ("%s: gimp_wire_write(): error: %s",
+ g_get_prgname (), error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ g_warning ("%s: gimp_wire_write(): error",
+ g_get_prgname ());
+ }
+
+ wire_error_val = TRUE;
+ return FALSE;
+ }
+
+ count -= bytes;
+ buf += bytes;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+gimp_wire_flush (GIOChannel *channel,
+ gpointer user_data)
+{
+ if (wire_flush_func)
+ return (* wire_flush_func) (channel, user_data);
+
+ return FALSE;
+}
+
+gboolean
+gimp_wire_error (void)
+{
+ return wire_error_val;
+}
+
+void
+gimp_wire_clear_error (void)
+{
+ wire_error_val = FALSE;
+}
+
+gboolean
+gimp_wire_read_msg (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GimpWireHandler *handler;
+
+ if (G_UNLIKELY (! wire_ht))
+ g_error ("gimp_wire_read_msg: the wire protocol has not been initialized");
+
+ if (wire_error_val)
+ return !wire_error_val;
+
+ if (! _gimp_wire_read_int32 (channel, &msg->type, 1, user_data))
+ return FALSE;
+
+ handler = g_hash_table_lookup (wire_ht, &msg->type);
+
+ if (G_UNLIKELY (! handler))
+ g_error ("gimp_wire_read_msg: could not find handler for message: %d",
+ msg->type);
+
+ (* handler->read_func) (channel, msg, user_data);
+
+ return !wire_error_val;
+}
+
+gboolean
+gimp_wire_write_msg (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data)
+{
+ GimpWireHandler *handler;
+
+ if (G_UNLIKELY (! wire_ht))
+ g_error ("gimp_wire_write_msg: the wire protocol has not been initialized");
+
+ if (wire_error_val)
+ return !wire_error_val;
+
+ handler = g_hash_table_lookup (wire_ht, &msg->type);
+
+ if (G_UNLIKELY (! handler))
+ g_error ("gimp_wire_write_msg: could not find handler for message: %d",
+ msg->type);
+
+ if (! _gimp_wire_write_int32 (channel, &msg->type, 1, user_data))
+ return FALSE;
+
+ (* handler->write_func) (channel, msg, user_data);
+
+ return !wire_error_val;
+}
+
+void
+gimp_wire_destroy (GimpWireMessage *msg)
+{
+ GimpWireHandler *handler;
+
+ if (G_UNLIKELY (! wire_ht))
+ g_error ("gimp_wire_destroy: the wire protocol has not been initialized");
+
+ handler = g_hash_table_lookup (wire_ht, &msg->type);
+
+ if (G_UNLIKELY (! handler))
+ g_error ("gimp_wire_destroy: could not find handler for message: %d\n",
+ msg->type);
+
+ (* handler->destroy_func) (msg);
+}
+
+gboolean
+_gimp_wire_read_int64 (GIOChannel *channel,
+ guint64 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ if (count > 0)
+ {
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) data, count * 8, user_data))
+ return FALSE;
+
+ while (count--)
+ {
+ *data = GUINT64_FROM_BE (*data);
+ data++;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_read_int32 (GIOChannel *channel,
+ guint32 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ if (count > 0)
+ {
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) data, count * 4, user_data))
+ return FALSE;
+
+ while (count--)
+ {
+ *data = g_ntohl (*data);
+ data++;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_read_int16 (GIOChannel *channel,
+ guint16 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ if (count > 0)
+ {
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) data, count * 2, user_data))
+ return FALSE;
+
+ while (count--)
+ {
+ *data = g_ntohs (*data);
+ data++;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_read_int8 (GIOChannel *channel,
+ guint8 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ return gimp_wire_read (channel, data, count, user_data);
+}
+
+gboolean
+_gimp_wire_read_double (GIOChannel *channel,
+ gdouble *data,
+ gint count,
+ gpointer user_data)
+{
+ gdouble *t;
+ guint8 tmp[8];
+ gint i;
+
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ t = (gdouble *) tmp;
+
+ for (i = 0; i < count; i++)
+ {
+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ gint j;
+#endif
+
+ if (! _gimp_wire_read_int8 (channel, tmp, 8, user_data))
+ return FALSE;
+
+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ for (j = 0; j < 4; j++)
+ {
+ guint8 swap;
+
+ swap = tmp[j];
+ tmp[j] = tmp[7 - j];
+ tmp[7 - j] = swap;
+ }
+#endif
+
+ data[i] = *t;
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_read_string (GIOChannel *channel,
+ gchar **data,
+ gint count,
+ gpointer user_data)
+{
+ gint i;
+
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ for (i = 0; i < count; i++)
+ {
+ guint32 tmp;
+
+ if (! _gimp_wire_read_int32 (channel, &tmp, 1, user_data))
+ return FALSE;
+
+ if (tmp > 0)
+ {
+ data[i] = g_try_new (gchar, tmp);
+
+ if (! data[i])
+ {
+ g_printerr ("%s: failed to allocate %u bytes\n", G_STRFUNC, tmp);
+ return FALSE;
+ }
+
+ if (! _gimp_wire_read_int8 (channel,
+ (guint8 *) data[i], tmp, user_data))
+ {
+ g_free (data[i]);
+ return FALSE;
+ }
+
+ /* make sure that the string is NULL-terminated */
+ data[i][tmp - 1] = '\0';
+ }
+ else
+ {
+ data[i] = NULL;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_read_color (GIOChannel *channel,
+ GimpRGB *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ return _gimp_wire_read_double (channel,
+ (gdouble *) data, 4 * count, user_data);
+}
+
+gboolean
+_gimp_wire_write_int64 (GIOChannel *channel,
+ const guint64 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ if (count > 0)
+ {
+ gint i;
+
+ for (i = 0; i < count; i++)
+ {
+ guint64 tmp = GUINT64_TO_BE (data[i]);
+
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &tmp, 8, user_data))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_write_int32 (GIOChannel *channel,
+ const guint32 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ if (count > 0)
+ {
+ gint i;
+
+ for (i = 0; i < count; i++)
+ {
+ guint32 tmp = g_htonl (data[i]);
+
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &tmp, 4, user_data))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_write_int16 (GIOChannel *channel,
+ const guint16 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ if (count > 0)
+ {
+ gint i;
+
+ for (i = 0; i < count; i++)
+ {
+ guint16 tmp = g_htons (data[i]);
+
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) &tmp, 2, user_data))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_write_int8 (GIOChannel *channel,
+ const guint8 *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ return gimp_wire_write (channel, data, count, user_data);
+}
+
+gboolean
+_gimp_wire_write_double (GIOChannel *channel,
+ const gdouble *data,
+ gint count,
+ gpointer user_data)
+{
+ gdouble *t;
+ guint8 tmp[8];
+ gint i;
+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ gint j;
+#endif
+
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ t = (gdouble *) tmp;
+
+ for (i = 0; i < count; i++)
+ {
+ *t = data[i];
+
+#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ for (j = 0; j < 4; j++)
+ {
+ guint8 swap;
+
+ swap = tmp[j];
+ tmp[j] = tmp[7 - j];
+ tmp[7 - j] = swap;
+ }
+#endif
+
+ if (! _gimp_wire_write_int8 (channel, tmp, 8, user_data))
+ return FALSE;
+
+#if 0
+ {
+ gint k;
+
+ g_print ("Wire representation of %f:\t", data[i]);
+
+ for (k = 0; k < 8; k++)
+ g_print ("%02x ", tmp[k]);
+
+ g_print ("\n");
+ }
+#endif
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_write_string (GIOChannel *channel,
+ gchar **data,
+ gint count,
+ gpointer user_data)
+{
+ gint i;
+
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ for (i = 0; i < count; i++)
+ {
+ guint32 tmp;
+
+ if (data[i])
+ tmp = strlen (data[i]) + 1;
+ else
+ tmp = 0;
+
+ if (! _gimp_wire_write_int32 (channel, &tmp, 1, user_data))
+ return FALSE;
+
+ if (tmp > 0)
+ if (! _gimp_wire_write_int8 (channel,
+ (const guint8 *) data[i], tmp, user_data))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+_gimp_wire_write_color (GIOChannel *channel,
+ const GimpRGB *data,
+ gint count,
+ gpointer user_data)
+{
+ g_return_val_if_fail (count >= 0, FALSE);
+
+ return _gimp_wire_write_double (channel,
+ (gdouble *) data, 4 * count, user_data);
+}
+
+static guint
+gimp_wire_hash (const guint32 *key)
+{
+ return *key;
+}
+
+static gboolean
+gimp_wire_compare (const guint32 *a,
+ const guint32 *b)
+{
+ return (*a == *b);
+}
+
+static void
+gimp_wire_init (void)
+{
+ if (! wire_ht)
+ wire_ht = g_hash_table_new ((GHashFunc) gimp_wire_hash,
+ (GCompareFunc) gimp_wire_compare);
+}
diff --git a/libgimpbase/gimpwire.h b/libgimpbase/gimpwire.h
new file mode 100644
index 0000000..dde69d9
--- /dev/null
+++ b/libgimpbase/gimpwire.h
@@ -0,0 +1,146 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_WIRE_H__
+#define __GIMP_WIRE_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+typedef struct _GimpWireMessage GimpWireMessage;
+
+typedef void (* GimpWireReadFunc) (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+typedef void (* GimpWireWriteFunc) (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+typedef void (* GimpWireDestroyFunc) (GimpWireMessage *msg);
+typedef gboolean (* GimpWireIOFunc) (GIOChannel *channel,
+ const guint8 *buf,
+ gulong count,
+ gpointer user_data);
+typedef gboolean (* GimpWireFlushFunc) (GIOChannel *channel,
+ gpointer user_data);
+
+
+struct _GimpWireMessage
+{
+ guint32 type;
+ gpointer data;
+};
+
+
+void gimp_wire_register (guint32 type,
+ GimpWireReadFunc read_func,
+ GimpWireWriteFunc write_func,
+ GimpWireDestroyFunc destroy_func);
+
+void gimp_wire_set_reader (GimpWireIOFunc read_func);
+void gimp_wire_set_writer (GimpWireIOFunc write_func);
+void gimp_wire_set_flusher (GimpWireFlushFunc flush_func);
+
+gboolean gimp_wire_read (GIOChannel *channel,
+ guint8 *buf,
+ gsize count,
+ gpointer user_data);
+gboolean gimp_wire_write (GIOChannel *channel,
+ const guint8 *buf,
+ gsize count,
+ gpointer user_data);
+gboolean gimp_wire_flush (GIOChannel *channel,
+ gpointer user_data);
+
+gboolean gimp_wire_error (void);
+void gimp_wire_clear_error (void);
+
+gboolean gimp_wire_read_msg (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+gboolean gimp_wire_write_msg (GIOChannel *channel,
+ GimpWireMessage *msg,
+ gpointer user_data);
+
+void gimp_wire_destroy (GimpWireMessage *msg);
+
+
+/* for internal use in libgimpbase */
+
+G_GNUC_INTERNAL gboolean _gimp_wire_read_int64 (GIOChannel *channel,
+ guint64 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_read_int32 (GIOChannel *channel,
+ guint32 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_read_int16 (GIOChannel *channel,
+ guint16 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_read_int8 (GIOChannel *channel,
+ guint8 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_read_double (GIOChannel *channel,
+ gdouble *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_read_string (GIOChannel *channel,
+ gchar **data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_read_color (GIOChannel *channel,
+ GimpRGB *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_write_int64 (GIOChannel *channel,
+ const guint64 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_write_int32 (GIOChannel *channel,
+ const guint32 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_write_int16 (GIOChannel *channel,
+ const guint16 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_write_int8 (GIOChannel *channel,
+ const guint8 *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_write_double (GIOChannel *channel,
+ const gdouble *data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_write_string (GIOChannel *channel,
+ gchar **data,
+ gint count,
+ gpointer user_data);
+G_GNUC_INTERNAL gboolean _gimp_wire_write_color (GIOChannel *channel,
+ const GimpRGB *data,
+ gint count,
+ gpointer user_data);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_WIRE_H__ */
diff --git a/libgimpbase/test-cpu-accel.c b/libgimpbase/test-cpu-accel.c
new file mode 100644
index 0000000..5c0349f
--- /dev/null
+++ b/libgimpbase/test-cpu-accel.c
@@ -0,0 +1,48 @@
+/* A small test program for the CPU detection code */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib.h>
+
+#include "gimpcpuaccel.h"
+
+
+static void
+cpu_accel_print_results (void)
+{
+ GimpCpuAccelFlags support;
+
+ g_printerr ("Testing CPU features...\n");
+
+ support = gimp_cpu_accel_get_support ();
+
+#ifdef ARCH_X86
+ g_printerr (" mmx : %s\n",
+ (support & GIMP_CPU_ACCEL_X86_MMX) ? "yes" : "no");
+ g_printerr (" 3dnow : %s\n",
+ (support & GIMP_CPU_ACCEL_X86_3DNOW) ? "yes" : "no");
+ g_printerr (" mmxext : %s\n",
+ (support & GIMP_CPU_ACCEL_X86_MMXEXT) ? "yes" : "no");
+ g_printerr (" sse : %s\n",
+ (support & GIMP_CPU_ACCEL_X86_SSE) ? "yes" : "no");
+ g_printerr (" sse2 : %s\n",
+ (support & GIMP_CPU_ACCEL_X86_SSE2) ? "yes" : "no");
+ g_printerr (" sse3 : %s\n",
+ (support & GIMP_CPU_ACCEL_X86_SSE3) ? "yes" : "no");
+#endif
+#ifdef ARCH_PPC
+ g_printerr (" altivec : %s\n",
+ (support & GIMP_CPU_ACCEL_PPC_ALTIVEC) ? "yes" : "no");
+#endif
+ g_printerr ("\n");
+}
+
+int
+main (void)
+{
+ cpu_accel_print_results ();
+
+ return EXIT_SUCCESS;
+}