summaryrefslogtreecommitdiffstats
path: root/libgimpmath
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libgimpmath/Makefile.am93
-rw-r--r--libgimpmath/Makefile.in1070
-rw-r--r--libgimpmath/gimpmath.def78
-rw-r--r--libgimpmath/gimpmath.h153
-rw-r--r--libgimpmath/gimpmathtypes.h114
-rw-r--r--libgimpmath/gimpmatrix.c1080
-rw-r--r--libgimpmath/gimpmatrix.h157
-rw-r--r--libgimpmath/gimpmd5.c53
-rw-r--r--libgimpmath/gimpmd5.h26
-rw-r--r--libgimpmath/gimpvector.c1129
-rw-r--r--libgimpmath/gimpvector.h160
11 files changed, 4113 insertions, 0 deletions
diff --git a/libgimpmath/Makefile.am b/libgimpmath/Makefile.am
new file mode 100644
index 0000000..be67ba8
--- /dev/null
+++ b/libgimpmath/Makefile.am
@@ -0,0 +1,93 @@
+## Process this file with automake to produce Makefile.in
+
+libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+endif
+
+if PLATFORM_WIN32
+else
+libm = -lm
+endif
+
+if OS_WIN32
+gimpmath_def = gimpmath.def
+libgimpmath_export_symbols = -export-symbols $(srcdir)/gimpmath.def
+
+install-libtool-import-lib:
+ $(INSTALL) .libs/libgimpmath-$(GIMP_API_VERSION).dll.a $(DESTDIR)$(libdir)
+ $(INSTALL) $(srcdir)/gimpmath.def $(DESTDIR)$(libdir)
+
+uninstall-libtool-import-lib:
+ -rm $(DESTDIR)$(libdir)/libgimpmath-$(GIMP_API_VERSION).dll.a
+ -rm $(DESTDIR)$(libdir)/gimpmath.def
+else
+install-libtool-import-lib:
+uninstall-libtool-import-lib:
+endif
+
+if MS_LIB_AVAILABLE
+noinst_DATA = gimpmath-$(GIMP_API_VERSION).lib
+
+install-ms-lib:
+ $(INSTALL) gimpmath-$(GIMP_API_VERSION).lib $(DESTDIR)$(libdir)
+
+uninstall-ms-lib:
+ -rm $(DESTDIR)$(libdir)/gimpmath-$(GIMP_API_VERSION).lib
+
+gimpmath-@GIMP_API_VERSION@.lib: gimpmath.def
+ lib -name:libgimpmath-$(GIMP_API_VERSION)-@LT_CURRENT_MINUS_AGE@.dll -def:gimpmath.def -out:$@
+
+else
+install-ms-lib:
+uninstall-ms-lib:
+endif
+
+libgimpmathincludedir = $(includedir)/gimp-$(GIMP_API_VERSION)/libgimpmath
+
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"LibGimpMath\" \
+ -DGIMP_MATH_COMPILATION \
+ -I$(top_srcdir) \
+ $(GLIB_CFLAGS) \
+ -I$(includedir)
+
+EXTRA_DIST = \
+ gimpmath.def
+
+lib_LTLIBRARIES = libgimpmath-@GIMP_API_VERSION@.la
+
+libgimpmath_@GIMP_API_VERSION@_la_SOURCES = \
+ gimpmath.h \
+ gimpmathtypes.h \
+ gimpmatrix.c \
+ gimpmatrix.h \
+ gimpmd5.c \
+ gimpmd5.h \
+ gimpvector.c \
+ gimpvector.h
+
+libgimpmathinclude_HEADERS = \
+ gimpmath.h \
+ gimpmathtypes.h \
+ gimpmatrix.h \
+ gimpmd5.h \
+ gimpvector.h
+
+libgimpmath_@GIMP_API_VERSION@_la_LDFLAGS = \
+ -version-info $(LT_VERSION_INFO) \
+ $(no_undefined) \
+ $(libgimpmath_export_symbols)
+
+EXTRA_libgimpmath_@GIMP_API_VERSION@_la_DEPENDENCIES = $(gimpmath_def)
+
+libgimpmath_@GIMP_API_VERSION@_la_LIBADD = \
+ $(libgimpbase) \
+ $(GLIB_LIBS) \
+ $(libm)
+
+
+install-data-local: install-ms-lib install-libtool-import-lib
+
+uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib
diff --git a/libgimpmath/Makefile.in b/libgimpmath/Makefile.in
new file mode 100644
index 0000000..be39a21
--- /dev/null
+++ b/libgimpmath/Makefile.in
@@ -0,0 +1,1070 @@
+# Makefile.in generated by automake 1.16.2 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@
+subdir = libgimpmath
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4macros/gtk-doc.m4 \
+ $(top_srcdir)/m4macros/intltool.m4 \
+ $(top_srcdir)/m4macros/libtool.m4 \
+ $(top_srcdir)/m4macros/ltoptions.m4 \
+ $(top_srcdir)/m4macros/ltsugar.m4 \
+ $(top_srcdir)/m4macros/ltversion.m4 \
+ $(top_srcdir)/m4macros/lt~obsolete.m4 \
+ $(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 $(libgimpmathinclude_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)$(libgimpmathincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libgimpmath_@GIMP_API_VERSION@_la_DEPENDENCIES = $(libgimpbase) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libgimpmath_@GIMP_API_VERSION@_la_OBJECTS = gimpmatrix.lo \
+ gimpmd5.lo gimpvector.lo
+libgimpmath_@GIMP_API_VERSION@_la_OBJECTS = \
+ $(am_libgimpmath_@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 =
+libgimpmath_@GIMP_API_VERSION@_la_LINK = $(LIBTOOL) $(AM_V_lt) \
+ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \
+ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libgimpmath_@GIMP_API_VERSION@_la_LDFLAGS) $(LDFLAGS) -o $@
+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)/gimpmatrix.Plo \
+ ./$(DEPDIR)/gimpmd5.Plo ./$(DEPDIR)/gimpvector.Plo
+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 = $(libgimpmath_@GIMP_API_VERSION@_la_SOURCES)
+DIST_SOURCES = $(libgimpmath_@GIMP_API_VERSION@_la_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 = $(libgimpmathinclude_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__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+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_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_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@
+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@
+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@
+libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la
+@PLATFORM_WIN32_TRUE@no_undefined = -no-undefined
+@PLATFORM_WIN32_FALSE@libm = -lm
+@OS_WIN32_TRUE@gimpmath_def = gimpmath.def
+@OS_WIN32_TRUE@libgimpmath_export_symbols = -export-symbols $(srcdir)/gimpmath.def
+@MS_LIB_AVAILABLE_TRUE@noinst_DATA = gimpmath-$(GIMP_API_VERSION).lib
+libgimpmathincludedir = $(includedir)/gimp-$(GIMP_API_VERSION)/libgimpmath
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"LibGimpMath\" \
+ -DGIMP_MATH_COMPILATION \
+ -I$(top_srcdir) \
+ $(GLIB_CFLAGS) \
+ -I$(includedir)
+
+EXTRA_DIST = \
+ gimpmath.def
+
+lib_LTLIBRARIES = libgimpmath-@GIMP_API_VERSION@.la
+libgimpmath_@GIMP_API_VERSION@_la_SOURCES = \
+ gimpmath.h \
+ gimpmathtypes.h \
+ gimpmatrix.c \
+ gimpmatrix.h \
+ gimpmd5.c \
+ gimpmd5.h \
+ gimpvector.c \
+ gimpvector.h
+
+libgimpmathinclude_HEADERS = \
+ gimpmath.h \
+ gimpmathtypes.h \
+ gimpmatrix.h \
+ gimpmd5.h \
+ gimpvector.h
+
+libgimpmath_@GIMP_API_VERSION@_la_LDFLAGS = \
+ -version-info $(LT_VERSION_INFO) \
+ $(no_undefined) \
+ $(libgimpmath_export_symbols)
+
+EXTRA_libgimpmath_@GIMP_API_VERSION@_la_DEPENDENCIES = $(gimpmath_def)
+libgimpmath_@GIMP_API_VERSION@_la_LIBADD = \
+ $(libgimpbase) \
+ $(GLIB_LIBS) \
+ $(libm)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(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 libgimpmath/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libgimpmath/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}; \
+ }
+
+libgimpmath-@GIMP_API_VERSION@.la: $(libgimpmath_@GIMP_API_VERSION@_la_OBJECTS) $(libgimpmath_@GIMP_API_VERSION@_la_DEPENDENCIES) $(EXTRA_libgimpmath_@GIMP_API_VERSION@_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgimpmath_@GIMP_API_VERSION@_la_LINK) -rpath $(libdir) $(libgimpmath_@GIMP_API_VERSION@_la_OBJECTS) $(libgimpmath_@GIMP_API_VERSION@_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmatrix.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpmd5.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gimpvector.Plo@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-libgimpmathincludeHEADERS: $(libgimpmathinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(libgimpmathinclude_HEADERS)'; test -n "$(libgimpmathincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libgimpmathincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libgimpmathincludedir)" || 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)$(libgimpmathincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libgimpmathincludedir)" || exit $$?; \
+ done
+
+uninstall-libgimpmathincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libgimpmathinclude_HEADERS)'; test -n "$(libgimpmathincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libgimpmathincludedir)'; $(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
+
+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
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libgimpmathincludedir)"; 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:
+
+clean-generic:
+
+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)
+
+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)/gimpmatrix.Plo
+ -rm -f ./$(DEPDIR)/gimpmd5.Plo
+ -rm -f ./$(DEPDIR)/gimpvector.Plo
+ -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-libgimpmathincludeHEADERS
+
+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)/gimpmatrix.Plo
+ -rm -f ./$(DEPDIR)/gimpmd5.Plo
+ -rm -f ./$(DEPDIR)/gimpvector.Plo
+ -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-libgimpmathincludeHEADERS uninstall-local
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check 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-libgimpmathincludeHEADERS 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 \
+ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \
+ uninstall-libgimpmathincludeHEADERS uninstall-local
+
+.PRECIOUS: Makefile
+
+
+@OS_WIN32_TRUE@install-libtool-import-lib:
+@OS_WIN32_TRUE@ $(INSTALL) .libs/libgimpmath-$(GIMP_API_VERSION).dll.a $(DESTDIR)$(libdir)
+@OS_WIN32_TRUE@ $(INSTALL) $(srcdir)/gimpmath.def $(DESTDIR)$(libdir)
+
+@OS_WIN32_TRUE@uninstall-libtool-import-lib:
+@OS_WIN32_TRUE@ -rm $(DESTDIR)$(libdir)/libgimpmath-$(GIMP_API_VERSION).dll.a
+@OS_WIN32_TRUE@ -rm $(DESTDIR)$(libdir)/gimpmath.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) gimpmath-$(GIMP_API_VERSION).lib $(DESTDIR)$(libdir)
+
+@MS_LIB_AVAILABLE_TRUE@uninstall-ms-lib:
+@MS_LIB_AVAILABLE_TRUE@ -rm $(DESTDIR)$(libdir)/gimpmath-$(GIMP_API_VERSION).lib
+
+@MS_LIB_AVAILABLE_TRUE@gimpmath-@GIMP_API_VERSION@.lib: gimpmath.def
+@MS_LIB_AVAILABLE_TRUE@ lib -name:libgimpmath-$(GIMP_API_VERSION)-@LT_CURRENT_MINUS_AGE@.dll -def:gimpmath.def -out:$@
+
+@MS_LIB_AVAILABLE_FALSE@install-ms-lib:
+@MS_LIB_AVAILABLE_FALSE@uninstall-ms-lib:
+
+install-data-local: install-ms-lib install-libtool-import-lib
+
+uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib
+
+# 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/libgimpmath/gimpmath.def b/libgimpmath/gimpmath.def
new file mode 100644
index 0000000..a32a5ba
--- /dev/null
+++ b/libgimpmath/gimpmath.def
@@ -0,0 +1,78 @@
+EXPORTS
+ gimp_matrix2_determinant
+ gimp_matrix2_get_type
+ gimp_matrix2_identity
+ gimp_matrix2_invert
+ gimp_matrix2_mult
+ gimp_matrix2_transform_point
+ gimp_matrix3_affine
+ gimp_matrix3_determinant
+ gimp_matrix3_equal
+ gimp_matrix3_get_type
+ gimp_matrix3_identity
+ gimp_matrix3_invert
+ gimp_matrix3_is_affine
+ gimp_matrix3_is_diagonal
+ gimp_matrix3_is_identity
+ gimp_matrix3_is_simple
+ gimp_matrix3_mult
+ gimp_matrix3_rotate
+ gimp_matrix3_scale
+ gimp_matrix3_transform_point
+ gimp_matrix3_translate
+ gimp_matrix3_xshear
+ gimp_matrix3_yshear
+ gimp_matrix4_identity
+ gimp_matrix4_mult
+ gimp_matrix4_to_deg
+ gimp_matrix4_transform_point
+ gimp_md5_get_digest
+ gimp_param_matrix2_get_type
+ gimp_param_matrix3_get_type
+ gimp_param_spec_matrix2
+ gimp_param_spec_matrix3
+ gimp_vector2_add
+ gimp_vector2_add_val
+ gimp_vector2_cross_product
+ gimp_vector2_cross_product_val
+ gimp_vector2_inner_product
+ gimp_vector2_inner_product_val
+ gimp_vector2_length
+ gimp_vector2_length_val
+ gimp_vector2_mul
+ gimp_vector2_mul_val
+ gimp_vector2_neg
+ gimp_vector2_neg_val
+ gimp_vector2_new
+ gimp_vector2_normal
+ gimp_vector2_normal_val
+ gimp_vector2_normalize
+ gimp_vector2_normalize_val
+ gimp_vector2_rotate
+ gimp_vector2_rotate_val
+ gimp_vector2_set
+ gimp_vector2_sub
+ gimp_vector2_sub_val
+ gimp_vector3_add
+ gimp_vector3_add_val
+ gimp_vector3_cross_product
+ gimp_vector3_cross_product_val
+ gimp_vector3_inner_product
+ gimp_vector3_inner_product_val
+ gimp_vector3_length
+ gimp_vector3_length_val
+ gimp_vector3_mul
+ gimp_vector3_mul_val
+ gimp_vector3_neg
+ gimp_vector3_neg_val
+ gimp_vector3_new
+ gimp_vector3_normalize
+ gimp_vector3_normalize_val
+ gimp_vector3_rotate
+ gimp_vector3_rotate_val
+ gimp_vector3_set
+ gimp_vector3_sub
+ gimp_vector3_sub_val
+ gimp_vector_2d_to_3d
+ gimp_vector_2d_to_3d_val
+ gimp_vector_3d_to_2d
diff --git a/libgimpmath/gimpmath.h b/libgimpmath/gimpmath.h
new file mode 100644
index 0000000..c20b16f
--- /dev/null
+++ b/libgimpmath/gimpmath.h
@@ -0,0 +1,153 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpmath.h
+ *
+ * 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_MATH_H__
+#define __GIMP_MATH_H__
+
+
+#include <math.h>
+
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+
+#ifdef G_OS_WIN32
+#include <float.h>
+#endif
+
+#define __GIMP_MATH_H_INSIDE__
+
+#include <libgimpmath/gimpmathtypes.h>
+
+#include <libgimpmath/gimpmatrix.h>
+#include <libgimpmath/gimpmd5.h>
+#include <libgimpmath/gimpvector.h>
+
+#undef __GIMP_MATH_H_INSIDE__
+
+
+G_BEGIN_DECLS
+
+
+/**
+ * SECTION: gimpmath
+ * @title: GimpMath
+ * @short_description: Mathematical definitions and macros.
+ *
+ * Mathematical definitions and macros for use both by the GIMP
+ * application and plug-ins. These macros should be used rather than
+ * the ones from &lt;math.h&gt; for enhanced portability.
+ **/
+
+
+/**
+ * RINT:
+ * @x: the value to be rounded
+ *
+ * This macro rounds its argument @x to an integer value in floating
+ * point format. Use RINT() instead of rint().
+ **/
+#if defined (HAVE_RINT) && 0
+/* note: rint() depends on the current floating-point rounding mode. when the
+ * rounding mode is FE_TONEAREST, it, in parctice, breaks ties to even. this
+ * is different from 'floor (x + 0.5)', which breaks ties up. in other words
+ * 'rint (2.5) == 2.0', while 'floor (2.5 + 0.5) == 3.0'. this is asking for
+ * trouble, so let's just use the latter.
+ */
+#define RINT(x) rint(x)
+#else
+#define RINT(x) floor ((x) + 0.5)
+#endif
+
+/**
+ * ROUND:
+ * @x: the value to be rounded.
+ *
+ * This macro rounds its positive argument @x to the nearest integer.
+ **/
+#define ROUND(x) ((int) ((x) + 0.5))
+
+/**
+ * SIGNED_ROUND:
+ * @x: the value to be rounded.
+ *
+ * This macro rounds its argument @x to the nearest integer.
+ **/
+#define SIGNED_ROUND(x) ((int) RINT (x))
+
+/**
+ * SQR:
+ * @x: the value to be squared.
+ *
+ * This macro squares its argument @x.
+ **/
+#define SQR(x) ((x) * (x))
+
+/**
+ * MAX255:
+ * @a: the value to be limited.
+ *
+ * This macro limits it argument @a, an (0-511) int, to 255.
+ **/
+#define MAX255(a) ((a) | (((a) & 256) - (((a) & 256) >> 8)))
+
+/**
+ * CLAMP0255:
+ * @a: the value to be clamped.
+ *
+ * This macro clamps its argument @a, an int32-range int, between 0
+ * and 255 inclusive.
+ **/
+#define CLAMP0255(a) CLAMP(a,0,255)
+
+/**
+ * SAFE_CLAMP:
+ * @x: the value to be limited.
+ * @low: the lower limit.
+ * @high: the upper limit.
+ *
+ * Ensures that @x is between the limits set by @low and @high,
+ * even if @x is NaN. If @low is greater than @high, or if either
+ * of them is NaN, the result is undefined.
+ *
+ * Since: 2.10
+ **/
+#define SAFE_CLAMP(x, low, high) ((x) > (low) ? (x) < (high) ? (x) : (high) : (low))
+
+/**
+ * gimp_deg_to_rad:
+ * @angle: the angle to be converted.
+ *
+ * This macro converts its argument @angle from degree to radian.
+ **/
+#define gimp_deg_to_rad(angle) ((angle) * (2.0 * G_PI) / 360.0)
+
+/**
+ * gimp_rad_to_deg:
+ * @angle: the angle to be converted.
+ *
+ * This macro converts its argument @angle from radian to degree.
+ **/
+#define gimp_rad_to_deg(angle) ((angle) * 360.0 / (2.0 * G_PI))
+
+
+G_END_DECLS
+
+#endif /* __GIMP_MATH_H__ */
diff --git a/libgimpmath/gimpmathtypes.h b/libgimpmath/gimpmathtypes.h
new file mode 100644
index 0000000..a6f4628
--- /dev/null
+++ b/libgimpmath/gimpmathtypes.h
@@ -0,0 +1,114 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpmathtypes.h
+ *
+ * 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_MATH_TYPES_H__
+#define __GIMP_MATH_TYPES_H__
+
+
+#include <libgimpbase/gimpbasetypes.h>
+
+
+G_BEGIN_DECLS
+
+typedef struct _GimpMatrix2 GimpMatrix2;
+typedef struct _GimpMatrix3 GimpMatrix3;
+typedef struct _GimpMatrix4 GimpMatrix4;
+
+/**
+ * GimpMatrix2
+ * @coeff: the coefficients
+ *
+ * A two by two matrix.
+ **/
+struct _GimpMatrix2
+{
+ gdouble coeff[2][2];
+};
+
+/**
+ * GimpMatrix3
+ * @coeff: the coefficients
+ *
+ * A three by three matrix.
+ **/
+struct _GimpMatrix3
+{
+ gdouble coeff[3][3];
+};
+
+/**
+ * GimpMatrix4
+ * @coeff: the coefficients
+ *
+ * A four by four matrix.
+ **/
+struct _GimpMatrix4
+{
+ gdouble coeff[4][4];
+};
+
+
+typedef struct _GimpVector2 GimpVector2;
+typedef struct _GimpVector3 GimpVector3;
+typedef struct _GimpVector4 GimpVector4;
+
+/**
+ * GimpVector2:
+ * @x: the x axis
+ * @y: the y axis
+ *
+ * A two dimensional vector.
+ **/
+struct _GimpVector2
+{
+ gdouble x, y;
+};
+
+/**
+ * GimpVector3:
+ * @x: the x axis
+ * @y: the y axis
+ * @z: the z axis
+ *
+ * A three dimensional vector.
+ **/
+struct _GimpVector3
+{
+ gdouble x, y, z;
+};
+
+/**
+ * GimpVector4:
+ * @x: the x axis
+ * @y: the y axis
+ * @z: the z axis
+ * @w: the w axis
+ *
+ * A four dimensional vector.
+ **/
+struct _GimpVector4
+{
+ gdouble x, y, z, w;
+};
+
+
+G_END_DECLS
+
+#endif /* __GIMP_MATH_TYPES_H__ */
diff --git a/libgimpmath/gimpmatrix.c b/libgimpmath/gimpmatrix.c
new file mode 100644
index 0000000..ebee392
--- /dev/null
+++ b/libgimpmath/gimpmatrix.c
@@ -0,0 +1,1080 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpmatrix.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 <glib-object.h>
+
+#include "gimpmath.h"
+
+
+/**
+ * SECTION: gimpmatrix
+ * @title: GimpMatrix
+ * @short_description: Utilities to set up and manipulate 3x3
+ * transformation matrices.
+ * @see_also: #GimpVector2, #GimpVector3, #GimpVector4
+ *
+ * When doing image manipulation you will often need 3x3
+ * transformation matrices that define translation, rotation, scaling,
+ * shearing and arbitrary perspective transformations using a 3x3
+ * matrix. Here you'll find a set of utility functions to set up those
+ * matrices and to perform basic matrix manipulations and tests.
+ *
+ * Each matrix class has a 2 dimensional gdouble coeff member. The
+ * element for row r and column c of the matrix is coeff[r][c].
+ **/
+
+
+#define EPSILON 1e-6
+
+
+static GimpMatrix2 * matrix2_copy (const GimpMatrix2 *matrix);
+
+/**
+ * gimp_matrix2_get_type:
+ *
+ * Reveals the object type
+ *
+ * Returns: the #GType for Matrix2 objects
+ *
+ * Since: 2.4
+ **/
+GType
+gimp_matrix2_get_type (void)
+{
+ static GType matrix_type = 0;
+
+ if (!matrix_type)
+ matrix_type = g_boxed_type_register_static ("GimpMatrix2",
+ (GBoxedCopyFunc) matrix2_copy,
+ (GBoxedFreeFunc) g_free);
+
+ return matrix_type;
+}
+
+
+/*
+ * GIMP_TYPE_PARAM_MATRIX2
+ */
+
+#define GIMP_PARAM_SPEC_MATRIX2(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_MATRIX2, GimpParamSpecMatrix2))
+
+static void gimp_param_matrix2_class_init (GParamSpecClass *class);
+static void gimp_param_matrix2_init (GParamSpec *pspec);
+static void gimp_param_matrix2_set_default (GParamSpec *pspec,
+ GValue *value);
+static gint gimp_param_matrix2_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2);
+
+typedef struct _GimpParamSpecMatrix2 GimpParamSpecMatrix2;
+
+struct _GimpParamSpecMatrix2
+{
+ GParamSpecBoxed parent_instance;
+
+ GimpMatrix2 default_value;
+};
+
+/**
+ * gimp_param_matrix2_get_type:
+ *
+ * Reveals the object type
+ *
+ * Returns: the #GType for a GimpMatrix2 object
+ *
+ * Since: 2.4
+ **/
+GType
+gimp_param_matrix2_get_type (void)
+{
+ static GType spec_type = 0;
+
+ if (!spec_type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_matrix2_class_init,
+ NULL, NULL,
+ sizeof (GimpParamSpecMatrix2),
+ 0,
+ (GInstanceInitFunc) gimp_param_matrix2_init
+ };
+
+ spec_type = g_type_register_static (G_TYPE_PARAM_BOXED,
+ "GimpParamMatrix2",
+ &type_info, 0);
+ }
+
+ return spec_type;
+}
+
+static void
+gimp_param_matrix2_class_init (GParamSpecClass *class)
+{
+ class->value_type = GIMP_TYPE_MATRIX2;
+ class->value_set_default = gimp_param_matrix2_set_default;
+ class->values_cmp = gimp_param_matrix2_values_cmp;
+}
+
+static void
+gimp_param_matrix2_init (GParamSpec *pspec)
+{
+ GimpParamSpecMatrix2 *cspec = GIMP_PARAM_SPEC_MATRIX2 (pspec);
+
+ gimp_matrix2_identity (&cspec->default_value);
+}
+
+static void
+gimp_param_matrix2_set_default (GParamSpec *pspec,
+ GValue *value)
+{
+ GimpParamSpecMatrix2 *cspec = GIMP_PARAM_SPEC_MATRIX2 (pspec);
+
+ g_value_set_static_boxed (value, &cspec->default_value);
+}
+
+static gint
+gimp_param_matrix2_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2)
+{
+ GimpMatrix2 *matrix1;
+ GimpMatrix2 *matrix2;
+ gint i, j;
+
+ matrix1 = value1->data[0].v_pointer;
+ matrix2 = value2->data[0].v_pointer;
+
+ /* try to return at least *something*, it's useless anyway... */
+
+ if (! matrix1)
+ return matrix2 != NULL ? -1 : 0;
+ else if (! matrix2)
+ return matrix1 != NULL;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 2; j++)
+ if (matrix1->coeff[i][j] != matrix2->coeff[i][j])
+ return 1;
+
+ return 0;
+}
+
+/**
+ * gimp_param_spec_matrix2:
+ * @name: Canonical name of the param
+ * @nick: Nickname of the param
+ * @blurb: Brief description of param.
+ * @default_value: Value to use if none is assigned.
+ * @flags: a combination of #GParamFlags
+ *
+ * Creates a param spec to hold a #GimpMatrix2 value.
+ * See g_param_spec_internal() for more information.
+ *
+ * Returns: a newly allocated #GParamSpec instance
+ *
+ * Since: 2.4
+ **/
+GParamSpec *
+gimp_param_spec_matrix2 (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const GimpMatrix2 *default_value,
+ GParamFlags flags)
+{
+ GimpParamSpecMatrix2 *cspec;
+
+ g_return_val_if_fail (default_value != NULL, NULL);
+
+ cspec = g_param_spec_internal (GIMP_TYPE_PARAM_MATRIX2,
+ name, nick, blurb, flags);
+
+ cspec->default_value = *default_value;
+
+ return G_PARAM_SPEC (cspec);
+}
+
+
+static GimpMatrix2 *
+matrix2_copy (const GimpMatrix2 *matrix)
+{
+ return (GimpMatrix2 *) g_memdup (matrix, sizeof (GimpMatrix2));
+}
+
+
+/**
+ * gimp_matrix2_identity:
+ * @matrix: A matrix.
+ *
+ * Sets the matrix to the identity matrix.
+ */
+void
+gimp_matrix2_identity (GimpMatrix2 *matrix)
+{
+ static const GimpMatrix2 identity = { { { 1.0, 0.0 },
+ { 0.0, 1.0 } } };
+
+ *matrix = identity;
+}
+
+/**
+ * gimp_matrix2_mult:
+ * @matrix1: The first input matrix.
+ * @matrix2: The second input matrix which will be overwritten by the result.
+ *
+ * Multiplies two matrices and puts the result into the second one.
+ */
+void
+gimp_matrix2_mult (const GimpMatrix2 *matrix1,
+ GimpMatrix2 *matrix2)
+{
+ GimpMatrix2 tmp;
+
+ tmp.coeff[0][0] = (matrix1->coeff[0][0] * matrix2->coeff[0][0] +
+ matrix1->coeff[0][1] * matrix2->coeff[1][0]);
+ tmp.coeff[0][1] = (matrix1->coeff[0][0] * matrix2->coeff[0][1] +
+ matrix1->coeff[0][1] * matrix2->coeff[1][1]);
+ tmp.coeff[1][0] = (matrix1->coeff[1][0] * matrix2->coeff[0][0] +
+ matrix1->coeff[1][1] * matrix2->coeff[1][0]);
+ tmp.coeff[1][1] = (matrix1->coeff[1][0] * matrix2->coeff[0][1] +
+ matrix1->coeff[1][1] * matrix2->coeff[1][1]);
+
+ *matrix2 = tmp;
+}
+
+/**
+ * gimp_matrix2_determinant:
+ * @matrix: The input matrix.
+ *
+ * Calculates the determinant of the given matrix.
+ *
+ * Returns: The determinant.
+ *
+ * Since: 2.10.16
+ */
+
+gdouble
+gimp_matrix2_determinant (const GimpMatrix2 *matrix)
+{
+ return matrix->coeff[0][0] * matrix->coeff[1][1] -
+ matrix->coeff[0][1] * matrix->coeff[1][0];
+}
+
+/**
+ * gimp_matrix2_invert:
+ * @matrix: The matrix that is to be inverted.
+ *
+ * Inverts the given matrix.
+ *
+ * Since: 2.10.16
+ */
+void
+gimp_matrix2_invert (GimpMatrix2 *matrix)
+{
+ gdouble det = gimp_matrix2_determinant (matrix);
+ gdouble temp;
+
+ if (fabs (det) <= EPSILON)
+ return;
+
+ temp = matrix->coeff[0][0];
+
+ matrix->coeff[0][0] = matrix->coeff[1][1] / det;
+ matrix->coeff[0][1] /= -det;
+ matrix->coeff[1][0] /= -det;
+ matrix->coeff[1][1] = temp / det;
+}
+
+/**
+ * gimp_matrix2_transform_point:
+ * @matrix: The transformation matrix.
+ * @x: The source X coordinate.
+ * @y: The source Y coordinate.
+ * @newx: The transformed X coordinate.
+ * @newy: The transformed Y coordinate.
+ *
+ * Transforms a point in 2D as specified by the transformation matrix.
+ *
+ * Since: 2.10.16
+ */
+void
+gimp_matrix2_transform_point (const GimpMatrix2 *matrix,
+ gdouble x,
+ gdouble y,
+ gdouble *newx,
+ gdouble *newy)
+{
+ *newx = matrix->coeff[0][0] * x + matrix->coeff[0][1] * y;
+ *newy = matrix->coeff[1][0] * x + matrix->coeff[1][1] * y;
+}
+
+
+static GimpMatrix3 * matrix3_copy (const GimpMatrix3 *matrix);
+
+/**
+ * gimp_matrix3_get_type:
+ *
+ * Reveals the object type
+ *
+ * Returns: the #GType for Matrix3 objects
+ *
+ * Since: 2.8
+ **/
+GType
+gimp_matrix3_get_type (void)
+{
+ static GType matrix_type = 0;
+
+ if (!matrix_type)
+ matrix_type = g_boxed_type_register_static ("GimpMatrix3",
+ (GBoxedCopyFunc) matrix3_copy,
+ (GBoxedFreeFunc) g_free);
+
+ return matrix_type;
+}
+
+
+/*
+ * GIMP_TYPE_PARAM_MATRIX3
+ */
+
+#define GIMP_PARAM_SPEC_MATRIX3(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_MATRIX3, GimpParamSpecMatrix3))
+
+static void gimp_param_matrix3_class_init (GParamSpecClass *class);
+static void gimp_param_matrix3_init (GParamSpec *pspec);
+static void gimp_param_matrix3_set_default (GParamSpec *pspec,
+ GValue *value);
+static gint gimp_param_matrix3_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2);
+
+typedef struct _GimpParamSpecMatrix3 GimpParamSpecMatrix3;
+
+struct _GimpParamSpecMatrix3
+{
+ GParamSpecBoxed parent_instance;
+
+ GimpMatrix3 default_value;
+};
+
+/**
+ * gimp_param_matrix3_get_type:
+ *
+ * Reveals the object type
+ *
+ * Returns: the #GType for a GimpMatrix3 object
+ *
+ * Since: 2.8
+ **/
+GType
+gimp_param_matrix3_get_type (void)
+{
+ static GType spec_type = 0;
+
+ if (!spec_type)
+ {
+ static const GTypeInfo type_info =
+ {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) gimp_param_matrix3_class_init,
+ NULL, NULL,
+ sizeof (GimpParamSpecMatrix3),
+ 0,
+ (GInstanceInitFunc) gimp_param_matrix3_init
+ };
+
+ spec_type = g_type_register_static (G_TYPE_PARAM_BOXED,
+ "GimpParamMatrix3",
+ &type_info, 0);
+ }
+
+ return spec_type;
+}
+
+static void
+gimp_param_matrix3_class_init (GParamSpecClass *class)
+{
+ class->value_type = GIMP_TYPE_MATRIX3;
+ class->value_set_default = gimp_param_matrix3_set_default;
+ class->values_cmp = gimp_param_matrix3_values_cmp;
+}
+
+static void
+gimp_param_matrix3_init (GParamSpec *pspec)
+{
+ GimpParamSpecMatrix3 *cspec = GIMP_PARAM_SPEC_MATRIX3 (pspec);
+
+ gimp_matrix3_identity (&cspec->default_value);
+}
+
+static void
+gimp_param_matrix3_set_default (GParamSpec *pspec,
+ GValue *value)
+{
+ GimpParamSpecMatrix3 *cspec = GIMP_PARAM_SPEC_MATRIX3 (pspec);
+
+ g_value_set_static_boxed (value, &cspec->default_value);
+}
+
+static gint
+gimp_param_matrix3_values_cmp (GParamSpec *pspec,
+ const GValue *value1,
+ const GValue *value2)
+{
+ GimpMatrix3 *matrix1;
+ GimpMatrix3 *matrix2;
+ gint i, j;
+
+ matrix1 = value1->data[0].v_pointer;
+ matrix2 = value2->data[0].v_pointer;
+
+ /* try to return at least *something*, it's useless anyway... */
+
+ if (! matrix1)
+ return matrix2 != NULL ? -1 : 0;
+ else if (! matrix2)
+ return matrix1 != NULL;
+
+ for (i = 0; i < 3; i++)
+ for (j = 0; j < 3; j++)
+ if (matrix1->coeff[i][j] != matrix2->coeff[i][j])
+ return 1;
+
+ return 0;
+}
+
+/**
+ * gimp_param_spec_matrix3:
+ * @name: Canonical name of the param
+ * @nick: Nickname of the param
+ * @blurb: Brief description of param.
+ * @default_value: Value to use if none is assigned.
+ * @flags: a combination of #GParamFlags
+ *
+ * Creates a param spec to hold a #GimpMatrix3 value.
+ * See g_param_spec_internal() for more information.
+ *
+ * Returns: a newly allocated #GParamSpec instance
+ *
+ * Since: 2.8
+ **/
+GParamSpec *
+gimp_param_spec_matrix3 (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const GimpMatrix3 *default_value,
+ GParamFlags flags)
+{
+ GimpParamSpecMatrix3 *cspec;
+
+ cspec = g_param_spec_internal (GIMP_TYPE_PARAM_MATRIX3,
+ name, nick, blurb, flags);
+
+ if (default_value)
+ cspec->default_value = *default_value;
+
+ return G_PARAM_SPEC (cspec);
+}
+
+
+static GimpMatrix3 *
+matrix3_copy (const GimpMatrix3 *matrix)
+{
+ return (GimpMatrix3 *) g_memdup (matrix, sizeof (GimpMatrix3));
+}
+
+
+/**
+ * gimp_matrix3_identity:
+ * @matrix: A matrix.
+ *
+ * Sets the matrix to the identity matrix.
+ */
+void
+gimp_matrix3_identity (GimpMatrix3 *matrix)
+{
+ static const GimpMatrix3 identity = { { { 1.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 1.0 } } };
+
+ *matrix = identity;
+}
+
+/**
+ * gimp_matrix3_transform_point:
+ * @matrix: The transformation matrix.
+ * @x: The source X coordinate.
+ * @y: The source Y coordinate.
+ * @newx: The transformed X coordinate.
+ * @newy: The transformed Y coordinate.
+ *
+ * Transforms a point in 2D as specified by the transformation matrix.
+ */
+void
+gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
+ gdouble x,
+ gdouble y,
+ gdouble *newx,
+ gdouble *newy)
+{
+ gdouble w;
+
+ w = matrix->coeff[2][0] * x + matrix->coeff[2][1] * y + matrix->coeff[2][2];
+
+ if (w == 0.0)
+ w = 1.0;
+ else
+ w = 1.0/w;
+
+ *newx = (matrix->coeff[0][0] * x +
+ matrix->coeff[0][1] * y +
+ matrix->coeff[0][2]) * w;
+ *newy = (matrix->coeff[1][0] * x +
+ matrix->coeff[1][1] * y +
+ matrix->coeff[1][2]) * w;
+}
+
+/**
+ * gimp_matrix3_mult:
+ * @matrix1: The first input matrix.
+ * @matrix2: The second input matrix which will be overwritten by the result.
+ *
+ * Multiplies two matrices and puts the result into the second one.
+ */
+void
+gimp_matrix3_mult (const GimpMatrix3 *matrix1,
+ GimpMatrix3 *matrix2)
+{
+ gint i, j;
+ GimpMatrix3 tmp;
+ gdouble t1, t2, t3;
+
+ for (i = 0; i < 3; i++)
+ {
+ t1 = matrix1->coeff[i][0];
+ t2 = matrix1->coeff[i][1];
+ t3 = matrix1->coeff[i][2];
+
+ for (j = 0; j < 3; j++)
+ {
+ tmp.coeff[i][j] = t1 * matrix2->coeff[0][j];
+ tmp.coeff[i][j] += t2 * matrix2->coeff[1][j];
+ tmp.coeff[i][j] += t3 * matrix2->coeff[2][j];
+ }
+ }
+
+ *matrix2 = tmp;
+}
+
+/**
+ * gimp_matrix3_translate:
+ * @matrix: The matrix that is to be translated.
+ * @x: Translation in X direction.
+ * @y: Translation in Y direction.
+ *
+ * Translates the matrix by x and y.
+ */
+void
+gimp_matrix3_translate (GimpMatrix3 *matrix,
+ gdouble x,
+ gdouble y)
+{
+ gdouble g, h, i;
+
+ g = matrix->coeff[2][0];
+ h = matrix->coeff[2][1];
+ i = matrix->coeff[2][2];
+
+ matrix->coeff[0][0] += x * g;
+ matrix->coeff[0][1] += x * h;
+ matrix->coeff[0][2] += x * i;
+ matrix->coeff[1][0] += y * g;
+ matrix->coeff[1][1] += y * h;
+ matrix->coeff[1][2] += y * i;
+}
+
+/**
+ * gimp_matrix3_scale:
+ * @matrix: The matrix that is to be scaled.
+ * @x: X scale factor.
+ * @y: Y scale factor.
+ *
+ * Scales the matrix by x and y
+ */
+void
+gimp_matrix3_scale (GimpMatrix3 *matrix,
+ gdouble x,
+ gdouble y)
+{
+ matrix->coeff[0][0] *= x;
+ matrix->coeff[0][1] *= x;
+ matrix->coeff[0][2] *= x;
+
+ matrix->coeff[1][0] *= y;
+ matrix->coeff[1][1] *= y;
+ matrix->coeff[1][2] *= y;
+}
+
+/**
+ * gimp_matrix3_rotate:
+ * @matrix: The matrix that is to be rotated.
+ * @theta: The angle of rotation (in radians).
+ *
+ * Rotates the matrix by theta degrees.
+ */
+void
+gimp_matrix3_rotate (GimpMatrix3 *matrix,
+ gdouble theta)
+{
+ gdouble t1, t2;
+ gdouble cost, sint;
+
+ cost = cos (theta);
+ sint = sin (theta);
+
+ t1 = matrix->coeff[0][0];
+ t2 = matrix->coeff[1][0];
+ matrix->coeff[0][0] = cost * t1 - sint * t2;
+ matrix->coeff[1][0] = sint * t1 + cost * t2;
+
+ t1 = matrix->coeff[0][1];
+ t2 = matrix->coeff[1][1];
+ matrix->coeff[0][1] = cost * t1 - sint * t2;
+ matrix->coeff[1][1] = sint * t1 + cost * t2;
+
+ t1 = matrix->coeff[0][2];
+ t2 = matrix->coeff[1][2];
+ matrix->coeff[0][2] = cost * t1 - sint * t2;
+ matrix->coeff[1][2] = sint * t1 + cost * t2;
+}
+
+/**
+ * gimp_matrix3_xshear:
+ * @matrix: The matrix that is to be sheared.
+ * @amount: X shear amount.
+ *
+ * Shears the matrix in the X direction.
+ */
+void
+gimp_matrix3_xshear (GimpMatrix3 *matrix,
+ gdouble amount)
+{
+ matrix->coeff[0][0] += amount * matrix->coeff[1][0];
+ matrix->coeff[0][1] += amount * matrix->coeff[1][1];
+ matrix->coeff[0][2] += amount * matrix->coeff[1][2];
+}
+
+/**
+ * gimp_matrix3_yshear:
+ * @matrix: The matrix that is to be sheared.
+ * @amount: Y shear amount.
+ *
+ * Shears the matrix in the Y direction.
+ */
+void
+gimp_matrix3_yshear (GimpMatrix3 *matrix,
+ gdouble amount)
+{
+ matrix->coeff[1][0] += amount * matrix->coeff[0][0];
+ matrix->coeff[1][1] += amount * matrix->coeff[0][1];
+ matrix->coeff[1][2] += amount * matrix->coeff[0][2];
+}
+
+/**
+ * gimp_matrix3_affine:
+ * @matrix: The input matrix.
+ * @a: the 'a' coefficient
+ * @b: the 'b' coefficient
+ * @c: the 'c' coefficient
+ * @d: the 'd' coefficient
+ * @e: the 'e' coefficient
+ * @f: the 'f' coefficient
+ *
+ * Applies the affine transformation given by six values to @matrix.
+ * The six values form define an affine transformation matrix as
+ * illustrated below:
+ *
+ * ( a c e )
+ * ( b d f )
+ * ( 0 0 1 )
+ **/
+void
+gimp_matrix3_affine (GimpMatrix3 *matrix,
+ gdouble a,
+ gdouble b,
+ gdouble c,
+ gdouble d,
+ gdouble e,
+ gdouble f)
+{
+ GimpMatrix3 affine;
+
+ affine.coeff[0][0] = a;
+ affine.coeff[1][0] = b;
+ affine.coeff[2][0] = 0.0;
+
+ affine.coeff[0][1] = c;
+ affine.coeff[1][1] = d;
+ affine.coeff[2][1] = 0.0;
+
+ affine.coeff[0][2] = e;
+ affine.coeff[1][2] = f;
+ affine.coeff[2][2] = 1.0;
+
+ gimp_matrix3_mult (&affine, matrix);
+}
+
+/**
+ * gimp_matrix3_determinant:
+ * @matrix: The input matrix.
+ *
+ * Calculates the determinant of the given matrix.
+ *
+ * Returns: The determinant.
+ */
+gdouble
+gimp_matrix3_determinant (const GimpMatrix3 *matrix)
+{
+ gdouble determinant;
+
+ determinant = (matrix->coeff[0][0] *
+ (matrix->coeff[1][1] * matrix->coeff[2][2] -
+ matrix->coeff[1][2] * matrix->coeff[2][1]));
+ determinant -= (matrix->coeff[1][0] *
+ (matrix->coeff[0][1] * matrix->coeff[2][2] -
+ matrix->coeff[0][2] * matrix->coeff[2][1]));
+ determinant += (matrix->coeff[2][0] *
+ (matrix->coeff[0][1] * matrix->coeff[1][2] -
+ matrix->coeff[0][2] * matrix->coeff[1][1]));
+
+ return determinant;
+}
+
+/**
+ * gimp_matrix3_invert:
+ * @matrix: The matrix that is to be inverted.
+ *
+ * Inverts the given matrix.
+ */
+void
+gimp_matrix3_invert (GimpMatrix3 *matrix)
+{
+ GimpMatrix3 inv;
+ gdouble det;
+
+ det = gimp_matrix3_determinant (matrix);
+
+ if (det == 0.0)
+ return;
+
+ det = 1.0 / det;
+
+ inv.coeff[0][0] = (matrix->coeff[1][1] * matrix->coeff[2][2] -
+ matrix->coeff[1][2] * matrix->coeff[2][1]) * det;
+
+ inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] -
+ matrix->coeff[1][2] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[2][0] = (matrix->coeff[1][0] * matrix->coeff[2][1] -
+ matrix->coeff[1][1] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[0][1] = - (matrix->coeff[0][1] * matrix->coeff[2][2] -
+ matrix->coeff[0][2] * matrix->coeff[2][1]) * det;
+
+ inv.coeff[1][1] = (matrix->coeff[0][0] * matrix->coeff[2][2] -
+ matrix->coeff[0][2] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] -
+ matrix->coeff[0][1] * matrix->coeff[2][0]) * det;
+
+ inv.coeff[0][2] = (matrix->coeff[0][1] * matrix->coeff[1][2] -
+ matrix->coeff[0][2] * matrix->coeff[1][1]) * det;
+
+ inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] -
+ matrix->coeff[0][2] * matrix->coeff[1][0]) * det;
+
+ inv.coeff[2][2] = (matrix->coeff[0][0] * matrix->coeff[1][1] -
+ matrix->coeff[0][1] * matrix->coeff[1][0]) * det;
+
+ *matrix = inv;
+}
+
+
+/* functions to test for matrix properties */
+
+/**
+ * gimp_matrix3_is_identity:
+ * @matrix: The matrix that is to be tested.
+ *
+ * Checks if the given matrix is the identity matrix.
+ *
+ * Returns: %TRUE if the matrix is the identity matrix, %FALSE otherwise
+ */
+gboolean
+gimp_matrix3_is_identity (const GimpMatrix3 *matrix)
+{
+ gint i, j;
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (i == j)
+ {
+ if (fabs (matrix->coeff[i][j] - 1.0) > EPSILON)
+ return FALSE;
+ }
+ else
+ {
+ if (fabs (matrix->coeff[i][j]) > EPSILON)
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * gimp_matrix3_is_diagonal:
+ * @matrix: The matrix that is to be tested.
+ *
+ * Checks if the given matrix is diagonal.
+ *
+ * Returns: %TRUE if the matrix is diagonal, %FALSE otherwise
+ */
+gboolean
+gimp_matrix3_is_diagonal (const GimpMatrix3 *matrix)
+{
+ gint i, j;
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (i != j && fabs (matrix->coeff[i][j]) > EPSILON)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * gimp_matrix3_is_affine:
+ * @matrix: The matrix that is to be tested.
+ *
+ * Checks if the given matrix defines an affine transformation.
+ *
+ * Returns: %TRUE if the matrix defines an affine transformation,
+ * %FALSE otherwise
+ *
+ * Since: 2.4
+ */
+gboolean
+gimp_matrix3_is_affine (const GimpMatrix3 *matrix)
+{
+ return (fabs (matrix->coeff[2][0]) < EPSILON &&
+ fabs (matrix->coeff[2][1]) < EPSILON &&
+ fabs (matrix->coeff[2][2] - 1.0) < EPSILON);
+}
+
+/**
+ * gimp_matrix3_is_simple:
+ * @matrix: The matrix that is to be tested.
+ *
+ * Checks if we'll need to interpolate when applying this matrix as
+ * a transformation.
+ *
+ * Returns: %TRUE if all entries of the upper left 2x2 matrix are
+ * either 0 or 1, %FALSE otherwise
+ */
+gboolean
+gimp_matrix3_is_simple (const GimpMatrix3 *matrix)
+{
+ gdouble absm;
+ gint i, j;
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ absm = fabs (matrix->coeff[i][j]);
+ if (absm > EPSILON && fabs (absm - 1.0) > EPSILON)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * gimp_matrix3_equal:
+ * @matrix1: The first matrix
+ * @matrix2: The second matrix
+ *
+ * Checks if two matrices are equal.
+ *
+ * Returns: %TRUE the matrices are equal, %FALSE otherwise
+ *
+ * Since: 2.10.16
+ */
+gboolean
+gimp_matrix3_equal (const GimpMatrix3 *matrix1,
+ const GimpMatrix3 *matrix2)
+{
+ gint i, j;
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (fabs (matrix1->coeff[i][j] - matrix2->coeff[i][j]) > EPSILON)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * gimp_matrix4_identity:
+ * @matrix: A matrix.
+ *
+ * Sets the matrix to the identity matrix.
+ *
+ * Since: 2.10.16
+ */
+void
+gimp_matrix4_identity (GimpMatrix4 *matrix)
+{
+ gint i, j;
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ matrix->coeff[i][j] = i == j;
+ }
+}
+
+/**
+ * gimp_matrix4_mult:
+ * @matrix1: The first input matrix.
+ * @matrix2: The second input matrix which will be overwritten by the result.
+ *
+ * Multiplies two matrices and puts the result into the second one.
+ *
+ * Since: 2.10.16
+ */
+void
+gimp_matrix4_mult (const GimpMatrix4 *matrix1,
+ GimpMatrix4 *matrix2)
+{
+ GimpMatrix4 result = {};
+ gint i, j, k;
+
+ for (i = 0; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ for (k = 0; k < 4; k++)
+ result.coeff[i][j] += matrix1->coeff[i][k] * matrix2->coeff[k][j];
+ }
+ }
+
+ *matrix2 = result;
+}
+
+/**
+ * gimp_matrix4_to_deg:
+ * @matrix:
+ * @a:
+ * @b:
+ * @c:
+ *
+ *
+ **/
+void
+gimp_matrix4_to_deg (const GimpMatrix4 *matrix,
+ gdouble *a,
+ gdouble *b,
+ gdouble *c)
+{
+ *a = 180 * (asin (matrix->coeff[1][0]) / G_PI_2);
+ *b = 180 * (asin (matrix->coeff[2][0]) / G_PI_2);
+ *c = 180 * (asin (matrix->coeff[2][1]) / G_PI_2);
+}
+
+/**
+ * gimp_matrix4_transform_point:
+ * @matrix: The transformation matrix.
+ * @x: The source X coordinate.
+ * @y: The source Y coordinate.
+ * @z: The source Z coordinate.
+ * @newx: The transformed X coordinate.
+ * @newy: The transformed Y coordinate.
+ * @newz: The transformed Z coordinate.
+ *
+ * Transforms a point in 3D as specified by the transformation matrix.
+ *
+ * Returns: The transformed W coordinate.
+ *
+ * Since: 2.10.16
+ */
+gdouble
+gimp_matrix4_transform_point (const GimpMatrix4 *matrix,
+ gdouble x,
+ gdouble y,
+ gdouble z,
+ gdouble *newx,
+ gdouble *newy,
+ gdouble *newz)
+{
+ gdouble neww;
+
+ *newx = matrix->coeff[0][0] * x +
+ matrix->coeff[0][1] * y +
+ matrix->coeff[0][2] * z +
+ matrix->coeff[0][3];
+ *newy = matrix->coeff[1][0] * x +
+ matrix->coeff[1][1] * y +
+ matrix->coeff[1][2] * z +
+ matrix->coeff[1][3];
+ *newz = matrix->coeff[2][0] * x +
+ matrix->coeff[2][1] * y +
+ matrix->coeff[2][2] * z +
+ matrix->coeff[2][3];
+ neww = matrix->coeff[3][0] * x +
+ matrix->coeff[3][1] * y +
+ matrix->coeff[3][2] * z +
+ matrix->coeff[3][3];
+
+ *newx /= neww;
+ *newy /= neww;
+ *newz /= neww;
+
+ return neww;
+}
diff --git a/libgimpmath/gimpmatrix.h b/libgimpmath/gimpmatrix.h
new file mode 100644
index 0000000..a71a218
--- /dev/null
+++ b/libgimpmath/gimpmatrix.h
@@ -0,0 +1,157 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpmatrix.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_MATH_H_INSIDE__) && !defined (GIMP_MATH_COMPILATION)
+#error "Only <libgimpmath/gimpmath.h> can be included directly."
+#endif
+
+#ifndef __GIMP_MATRIX_H__
+#define __GIMP_MATRIX_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/*****************/
+/* GimpMatrix2 */
+/*****************/
+
+#define GIMP_TYPE_MATRIX2 (gimp_matrix2_get_type ())
+#define GIMP_VALUE_HOLDS_MATRIX2(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_MATRIX2))
+
+GType gimp_matrix2_get_type (void) G_GNUC_CONST;
+
+
+#define GIMP_TYPE_PARAM_MATRIX2 (gimp_param_matrix2_get_type ())
+#define GIMP_IS_PARAM_SPEC_MATRIX2(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_MATRIX2))
+
+GType gimp_param_matrix2_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_matrix2 (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const GimpMatrix2 *default_value,
+ GParamFlags flags);
+
+
+void gimp_matrix2_identity (GimpMatrix2 *matrix);
+void gimp_matrix2_mult (const GimpMatrix2 *matrix1,
+ GimpMatrix2 *matrix2);
+
+gdouble gimp_matrix2_determinant (const GimpMatrix2 *matrix);
+void gimp_matrix2_invert (GimpMatrix2 *matrix);
+
+void gimp_matrix2_transform_point (const GimpMatrix2 *matrix,
+ gdouble x,
+ gdouble y,
+ gdouble *newx,
+ gdouble *newy);
+
+
+/*****************/
+/* GimpMatrix3 */
+/*****************/
+
+#define GIMP_TYPE_MATRIX3 (gimp_matrix3_get_type ())
+#define GIMP_VALUE_HOLDS_MATRIX3(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_MATRIX3))
+
+GType gimp_matrix3_get_type (void) G_GNUC_CONST;
+
+
+#define GIMP_TYPE_PARAM_MATRIX3 (gimp_param_matrix3_get_type ())
+#define GIMP_IS_PARAM_SPEC_MATRIX3(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GIMP_TYPE_PARAM_MATRIX3))
+
+GType gimp_param_matrix3_get_type (void) G_GNUC_CONST;
+
+GParamSpec * gimp_param_spec_matrix3 (const gchar *name,
+ const gchar *nick,
+ const gchar *blurb,
+ const GimpMatrix3 *default_value,
+ GParamFlags flags);
+
+
+void gimp_matrix3_identity (GimpMatrix3 *matrix);
+void gimp_matrix3_mult (const GimpMatrix3 *matrix1,
+ GimpMatrix3 *matrix2);
+void gimp_matrix3_translate (GimpMatrix3 *matrix,
+ gdouble x,
+ gdouble y);
+void gimp_matrix3_scale (GimpMatrix3 *matrix,
+ gdouble x,
+ gdouble y);
+void gimp_matrix3_rotate (GimpMatrix3 *matrix,
+ gdouble theta);
+void gimp_matrix3_xshear (GimpMatrix3 *matrix,
+ gdouble amount);
+void gimp_matrix3_yshear (GimpMatrix3 *matrix,
+ gdouble amount);
+void gimp_matrix3_affine (GimpMatrix3 *matrix,
+ gdouble a,
+ gdouble b,
+ gdouble c,
+ gdouble d,
+ gdouble e,
+ gdouble f);
+
+gdouble gimp_matrix3_determinant (const GimpMatrix3 *matrix);
+void gimp_matrix3_invert (GimpMatrix3 *matrix);
+
+gboolean gimp_matrix3_is_identity (const GimpMatrix3 *matrix);
+gboolean gimp_matrix3_is_diagonal (const GimpMatrix3 *matrix);
+gboolean gimp_matrix3_is_affine (const GimpMatrix3 *matrix);
+gboolean gimp_matrix3_is_simple (const GimpMatrix3 *matrix);
+
+gboolean gimp_matrix3_equal (const GimpMatrix3 *matrix1,
+ const GimpMatrix3 *matrix2);
+
+void gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
+ gdouble x,
+ gdouble y,
+ gdouble *newx,
+ gdouble *newy);
+
+
+/*****************/
+/* GimpMatrix4 */
+/*****************/
+
+void gimp_matrix4_identity (GimpMatrix4 *matrix);
+void gimp_matrix4_mult (const GimpMatrix4 *matrix1,
+ GimpMatrix4 *matrix2);
+
+void gimp_matrix4_to_deg (const GimpMatrix4 *matrix,
+ gdouble *a,
+ gdouble *b,
+ gdouble *c);
+
+gdouble gimp_matrix4_transform_point (const GimpMatrix4 *matrix,
+ gdouble x,
+ gdouble y,
+ gdouble z,
+ gdouble *newx,
+ gdouble *newy,
+ gdouble *newz);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_MATRIX_H__ */
diff --git a/libgimpmath/gimpmd5.c b/libgimpmath/gimpmd5.c
new file mode 100644
index 0000000..712c3a9
--- /dev/null
+++ b/libgimpmath/gimpmd5.c
@@ -0,0 +1,53 @@
+/* LIBGIMP - The GIMP Library
+ *
+ * gimpmd5.c
+ *
+ * Use of this code is deprecated! Use %GChecksum from GLib instead.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gimpmathtypes.h"
+
+#include "gimpmd5.h"
+
+
+/**
+ * SECTION: gimpmd5
+ * @title: GimpMD5
+ * @short_description: The MD5 message-digest algorithm
+ *
+ * The MD5 message-digest algorithm
+ **/
+
+
+/**
+ * gimp_md5_get_digest:
+ * @buffer: byte buffer
+ * @buffer_size: buffer size (in bytes) or -1 if @buffer is nul-terminated.
+ * @digest: 16 bytes buffer receiving the hash code.
+ *
+ * This function is deprecated! Use %GChecksum from GLib instead.
+ *
+ * Get the md5 hash of a buffer. The result is put in the 16 bytes
+ * buffer @digest. For more information see RFC 1321.
+ **/
+void
+gimp_md5_get_digest (const gchar *buffer,
+ gint buffer_size,
+ guchar digest[16])
+{
+ GChecksum *checksum;
+ gsize len = 16;
+
+ g_return_if_fail (buffer != NULL);
+ g_return_if_fail (digest != NULL);
+
+ checksum = g_checksum_new (G_CHECKSUM_MD5);
+
+ g_checksum_update (checksum, (const guchar *) buffer, buffer_size);
+ g_checksum_get_digest (checksum, digest, &len);
+ g_checksum_free (checksum);
+}
diff --git a/libgimpmath/gimpmd5.h b/libgimpmath/gimpmd5.h
new file mode 100644
index 0000000..1e04e91
--- /dev/null
+++ b/libgimpmath/gimpmd5.h
@@ -0,0 +1,26 @@
+/* LIBGIMP - The GIMP Library
+ *
+ * gimpmd5.h
+ *
+ * Use of this code is deprecated! Use %GChecksum from GLib instead.
+ */
+
+#if !defined (__GIMP_MATH_H_INSIDE__) && !defined (GIMP_MATH_COMPILATION)
+#error "Only <libgimpmath/gimpmath.h> can be included directly."
+#endif
+
+#ifndef __GIMP_MD5_H__
+#define __GIMP_MD5_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+GIMP_DEPRECATED_FOR(GChecksum)
+void gimp_md5_get_digest (const gchar *buffer,
+ gint buffer_size,
+ guchar digest[16]);
+
+G_END_DECLS
+
+#endif /* __GIMP_MD5_H__ */
diff --git a/libgimpmath/gimpvector.c b/libgimpmath/gimpvector.c
new file mode 100644
index 0000000..5f2b174
--- /dev/null
+++ b/libgimpmath/gimpvector.c
@@ -0,0 +1,1129 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpvector.c
+ *
+ * The gimp_vector* functions were taken from:
+ * GCK - The General Convenience Kit
+ * Copyright (C) 1996 Tom Bech
+ *
+ * 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/>.
+ */
+
+/**********************************************/
+/* A little collection of useful vector stuff */
+/**********************************************/
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gimpmath.h"
+
+
+/**
+ * SECTION: gimpvector
+ * @title: GimpVector
+ * @short_description: Utilities to set up and manipulate vectors.
+ * @see_also: #GimpMatrix2, #GimpMatrix3, #GimpMatrix4
+ *
+ * Utilities to set up and manipulate vectors.
+ **/
+
+
+/*************************/
+/* Some useful constants */
+/*************************/
+
+static const GimpVector2 gimp_vector2_zero = { 0.0, 0.0 };
+#if 0
+static const GimpVector2 gimp_vector2_unit_x = { 1.0, 0.0 };
+static const GimpVector2 gimp_vector2_unit_y = { 0.0, 1.0 };
+#endif
+
+static const GimpVector3 gimp_vector3_zero = { 0.0, 0.0, 0.0 };
+#if 0
+static const GimpVector3 gimp_vector3_unit_x = { 1.0, 0.0, 0.0 };
+static const GimpVector3 gimp_vector3_unit_y = { 0.0, 1.0, 0.0 };
+static const GimpVector3 gimp_vector3_unit_z = { 0.0, 0.0, 1.0 };
+#endif
+
+/**************************************/
+/* Two dimensional vector functions */
+/**************************************/
+
+/**
+ * gimp_vector2_new:
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ *
+ * Creates a #GimpVector2 of coordinates @x and @y.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_new (gdouble x,
+ gdouble y)
+{
+ GimpVector2 vector;
+
+ vector.x = x;
+ vector.y = y;
+
+ return vector;
+}
+
+/**
+ * gimp_vector2_set:
+ * @vector: a pointer to a #GimpVector2.
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ *
+ * Sets the X and Y coordinates of @vector to @x and @y.
+ **/
+void
+gimp_vector2_set (GimpVector2 *vector,
+ gdouble x,
+ gdouble y)
+{
+ vector->x = x;
+ vector->y = y;
+}
+
+/**
+ * gimp_vector2_length:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Computes the length of a 2D vector.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector2_length (const GimpVector2 *vector)
+{
+ return (sqrt (vector->x * vector->x + vector->y * vector->y));
+}
+
+/**
+ * gimp_vector2_length_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_length() but the
+ * vector is passed by value rather than by reference.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector2_length_val (GimpVector2 vector)
+{
+ return (sqrt (vector.x * vector.x + vector.y * vector.y));
+}
+
+/**
+ * gimp_vector2_mul:
+ * @vector: a pointer to a #GimpVector2.
+ * @factor: a scalar.
+ *
+ * Multiplies each component of the @vector by @factor. Note that this
+ * is equivalent to multiplying the vectors length by @factor.
+ **/
+void
+gimp_vector2_mul (GimpVector2 *vector,
+ gdouble factor)
+{
+ vector->x *= factor;
+ vector->y *= factor;
+}
+
+/**
+ * gimp_vector2_mul_val:
+ * @vector: a #GimpVector2.
+ * @factor: a scalar.
+ *
+ * This function is identical to gimp_vector2_mul() but the vector is
+ * passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_mul_val (GimpVector2 vector,
+ gdouble factor)
+{
+ GimpVector2 result;
+
+ result.x = vector.x * factor;
+ result.y = vector.y * factor;
+
+ return result;
+}
+
+
+/**
+ * gimp_vector2_normalize:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Normalizes the @vector so the length of the @vector is 1.0. The nul
+ * vector will not be changed.
+ **/
+void
+gimp_vector2_normalize (GimpVector2 *vector)
+{
+ gdouble len;
+
+ len = gimp_vector2_length (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ vector->x *= len;
+ vector->y *= len;
+ }
+ else
+ {
+ *vector = gimp_vector2_zero;
+ }
+}
+
+/**
+ * gimp_vector2_normalize_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_normalize() but the
+ * vector is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector2 parallel to @vector, pointing in the same
+ * direction but with a length of 1.0.
+ **/
+GimpVector2
+gimp_vector2_normalize_val (GimpVector2 vector)
+{
+ GimpVector2 normalized;
+ gdouble len;
+
+ len = gimp_vector2_length_val (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ normalized.x = vector.x * len;
+ normalized.y = vector.y * len;
+ return normalized;
+ }
+ else
+ {
+ return gimp_vector2_zero;
+ }
+}
+
+/**
+ * gimp_vector2_neg:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Negates the @vector (i.e. negate all its coordinates).
+ **/
+void
+gimp_vector2_neg (GimpVector2 *vector)
+{
+ vector->x *= -1.0;
+ vector->y *= -1.0;
+}
+
+/**
+ * gimp_vector2_neg_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_neg() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: the negated #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_neg_val (GimpVector2 vector)
+{
+ GimpVector2 result;
+
+ result.x = vector.x * -1.0;
+ result.y = vector.y * -1.0;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_add:
+ * @result: destination for the resulting #GimpVector2.
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Computes the sum of two 2D vectors. The resulting #GimpVector2 is
+ * stored in @result.
+ **/
+void
+gimp_vector2_add (GimpVector2 *result,
+ const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ result->x = vector1->x + vector2->x;
+ result->y = vector1->y + vector2->y;
+}
+
+/**
+ * gimp_vector2_add_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_add() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_add_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ GimpVector2 result;
+
+ result.x = vector1.x + vector2.x;
+ result.y = vector1.y + vector2.y;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_sub:
+ * @result: the destination for the resulting #GimpVector2.
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Computes the difference of two 2D vectors (@vector1 minus @vector2).
+ * The resulting #GimpVector2 is stored in @result.
+ **/
+void
+gimp_vector2_sub (GimpVector2 *result,
+ const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ result->x = vector1->x - vector2->x;
+ result->y = vector1->y - vector2->y;
+}
+
+/**
+ * gimp_vector2_sub_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_sub() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector2.
+ **/
+GimpVector2
+gimp_vector2_sub_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ GimpVector2 result;
+
+ result.x = vector1.x - vector2.x;
+ result.y = vector1.y - vector2.y;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_inner_product:
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Computes the inner (dot) product of two 2D vectors.
+ * This product is zero if and only if the two vectors are orthogonal.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector2_inner_product (const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ return (vector1->x * vector2->x + vector1->y * vector2->y);
+}
+
+/**
+ * gimp_vector2_inner_product_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_inner_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector2_inner_product_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ return (vector1.x * vector2.x + vector1.y * vector2.y);
+}
+
+/**
+ * gimp_vector2_cross_product:
+ * @vector1: a pointer to the first #GimpVector2.
+ * @vector2: a pointer to the second #GimpVector2.
+ *
+ * Compute the cross product of two vectors. The result is a
+ * #GimpVector2 which is orthogonal to both @vector1 and @vector2. If
+ * @vector1 and @vector2 are parallel, the result will be the nul
+ * vector.
+ *
+ * Note that in 2D, this function is useful to test if two vectors are
+ * parallel or not, or to compute the area spawned by two vectors.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector2
+gimp_vector2_cross_product (const GimpVector2 *vector1,
+ const GimpVector2 *vector2)
+{
+ GimpVector2 normal;
+
+ normal.x = vector1->x * vector2->y - vector1->y * vector2->x;
+ normal.y = vector1->y * vector2->x - vector1->x * vector2->y;
+
+ return normal;
+}
+
+/**
+ * gimp_vector2_cross_product_val:
+ * @vector1: the first #GimpVector2.
+ * @vector2: the second #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_cross_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector2
+gimp_vector2_cross_product_val (GimpVector2 vector1,
+ GimpVector2 vector2)
+{
+ GimpVector2 normal;
+
+ normal.x = vector1.x * vector2.y - vector1.y * vector2.x;
+ normal.y = vector1.y * vector2.x - vector1.x * vector2.y;
+
+ return normal;
+}
+
+/**
+ * gimp_vector2_rotate:
+ * @vector: a pointer to a #GimpVector2.
+ * @alpha: an angle (in radians).
+ *
+ * Rotates the @vector counterclockwise by @alpha radians.
+ **/
+void
+gimp_vector2_rotate (GimpVector2 *vector,
+ gdouble alpha)
+{
+ GimpVector2 result;
+
+ result.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
+ result.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
+
+ *vector = result;
+}
+
+/**
+ * gimp_vector2_rotate_val:
+ * @vector: a #GimpVector2.
+ * @alpha: an angle (in radians).
+ *
+ * This function is identical to gimp_vector2_rotate() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector2 representing @vector rotated by @alpha
+ * radians.
+ **/
+GimpVector2
+gimp_vector2_rotate_val (GimpVector2 vector,
+ gdouble alpha)
+{
+ GimpVector2 result;
+
+ result.x = cos (alpha) * vector.x + sin (alpha) * vector.y;
+ result.y = cos (alpha) * vector.y - sin (alpha) * vector.x;
+
+ return result;
+}
+
+/**
+ * gimp_vector2_normal:
+ * @vector: a pointer to a #GimpVector2.
+ *
+ * Compute a normalized perpendicular vector to @vector
+ *
+ * Returns: a #GimpVector2 perpendicular to @vector, with a length of 1.0.
+ *
+ * Since: 2.8
+ **/
+GimpVector2
+gimp_vector2_normal (GimpVector2 *vector)
+{
+ GimpVector2 result;
+
+ result.x = - vector->y;
+ result.y = vector->x;
+
+ gimp_vector2_normalize (&result);
+
+ return result;
+}
+
+/**
+ * gimp_vector2_normal_val:
+ * @vector: a #GimpVector2.
+ *
+ * This function is identical to gimp_vector2_normal() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector2 perpendicular to @vector, with a length of 1.0.
+ *
+ * Since: 2.8
+ **/
+GimpVector2
+gimp_vector2_normal_val (GimpVector2 vector)
+{
+ GimpVector2 result;
+
+ result.x = - vector.y;
+ result.y = vector.x;
+
+ gimp_vector2_normalize (&result);
+
+ return result;
+}
+/**************************************/
+/* Three dimensional vector functions */
+/**************************************/
+
+/**
+ * gimp_vector3_new:
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ * @z: the Z coordinate.
+ *
+ * Creates a #GimpVector3 of coordinate @x, @y and @z.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_new (gdouble x,
+ gdouble y,
+ gdouble z)
+{
+ GimpVector3 vector;
+
+ vector.x = x;
+ vector.y = y;
+ vector.z = z;
+
+ return vector;
+}
+
+/**
+ * gimp_vector3_set:
+ * @vector: a pointer to a #GimpVector3.
+ * @x: the X coordinate.
+ * @y: the Y coordinate.
+ * @z: the Z coordinate.
+ *
+ * Sets the X, Y and Z coordinates of @vector to @x, @y and @z.
+ **/
+void
+gimp_vector3_set (GimpVector3 *vector,
+ gdouble x,
+ gdouble y,
+ gdouble z)
+{
+ vector->x = x;
+ vector->y = y;
+ vector->z = z;
+}
+
+/**
+ * gimp_vector3_length:
+ * @vector: a pointer to a #GimpVector3.
+ *
+ * Computes the length of a 3D vector.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector3_length (const GimpVector3 *vector)
+{
+ return (sqrt (vector->x * vector->x +
+ vector->y * vector->y +
+ vector->z * vector->z));
+}
+
+/**
+ * gimp_vector3_length_val:
+ * @vector: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_length() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: the length of @vector (a positive gdouble).
+ **/
+gdouble
+gimp_vector3_length_val (GimpVector3 vector)
+{
+ return (sqrt (vector.x * vector.x +
+ vector.y * vector.y +
+ vector.z * vector.z));
+}
+
+/**
+ * gimp_vector3_mul:
+ * @vector: a pointer to a #GimpVector3.
+ * @factor: a scalar.
+ *
+ * Multiplies each component of the @vector by @factor. Note that
+ * this is equivalent to multiplying the vectors length by @factor.
+ **/
+void
+gimp_vector3_mul (GimpVector3 *vector,
+ gdouble factor)
+{
+ vector->x *= factor;
+ vector->y *= factor;
+ vector->z *= factor;
+}
+
+/**
+ * gimp_vector3_mul_val:
+ * @vector: a #GimpVector3.
+ * @factor: a scalar.
+ *
+ * This function is identical to gimp_vector3_mul() but the vector is
+ * passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_mul_val (GimpVector3 vector,
+ gdouble factor)
+{
+ GimpVector3 result;
+
+ result.x = vector.x * factor;
+ result.y = vector.y * factor;
+ result.z = vector.z * factor;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_normalize:
+ * @vector: a pointer to a #GimpVector3.
+ *
+ * Normalizes the @vector so the length of the @vector is 1.0. The nul
+ * vector will not be changed.
+ **/
+void
+gimp_vector3_normalize (GimpVector3 *vector)
+{
+ gdouble len;
+
+ len = gimp_vector3_length (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ vector->x *= len;
+ vector->y *= len;
+ vector->z *= len;
+ }
+ else
+ {
+ *vector = gimp_vector3_zero;
+ }
+}
+
+/**
+ * gimp_vector3_normalize_val:
+ * @vector: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_normalize() but the
+ * vector is passed by value rather than by reference.
+ *
+ * Returns: a #GimpVector3 parallel to @vector, pointing in the same
+ * direction but with a length of 1.0.
+ **/
+GimpVector3
+gimp_vector3_normalize_val (GimpVector3 vector)
+{
+ GimpVector3 result;
+ gdouble len;
+
+ len = gimp_vector3_length_val (vector);
+
+ if (len != 0.0)
+ {
+ len = 1.0 / len;
+ result.x = vector.x * len;
+ result.y = vector.y * len;
+ result.z = vector.z * len;
+ return result;
+ }
+ else
+ {
+ return gimp_vector3_zero;
+ }
+}
+
+/**
+ * gimp_vector3_neg:
+ * @vector: a pointer to a #GimpVector3.
+ *
+ * Negates the @vector (i.e. negate all its coordinates).
+ **/
+void
+gimp_vector3_neg (GimpVector3 *vector)
+{
+ vector->x *= -1.0;
+ vector->y *= -1.0;
+ vector->z *= -1.0;
+}
+
+/**
+ * gimp_vector3_neg_val:
+ * @vector: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_neg() but the vector
+ * is passed by value rather than by reference.
+ *
+ * Returns: the negated #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_neg_val (GimpVector3 vector)
+{
+ GimpVector3 result;
+
+ result.x = vector.x * -1.0;
+ result.y = vector.y * -1.0;
+ result.z = vector.z * -1.0;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_add:
+ * @result: destination for the resulting #GimpVector3.
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Computes the sum of two 3D vectors. The resulting #GimpVector3 is
+ * stored in @result.
+ **/
+void
+gimp_vector3_add (GimpVector3 *result,
+ const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ result->x = vector1->x + vector2->x;
+ result->y = vector1->y + vector2->y;
+ result->z = vector1->z + vector2->z;
+}
+
+/**
+ * gimp_vector3_add_val:
+ * @vector1: a #GimpVector3.
+ * @vector2: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_add() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_add_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ GimpVector3 result;
+
+ result.x = vector1.x + vector2.x;
+ result.y = vector1.y + vector2.y;
+ result.z = vector1.z + vector2.z;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_sub:
+ * @result: the destination for the resulting #GimpVector3.
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Computes the difference of two 3D vectors (@vector1 minus @vector2).
+ * The resulting #GimpVector3 is stored in @result.
+ **/
+void
+gimp_vector3_sub (GimpVector3 *result,
+ const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ result->x = vector1->x - vector2->x;
+ result->y = vector1->y - vector2->y;
+ result->z = vector1->z - vector2->z;
+}
+
+/**
+ * gimp_vector3_sub_val:
+ * @vector1: a #GimpVector3.
+ * @vector2: a #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_sub() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the resulting #GimpVector3.
+ **/
+GimpVector3
+gimp_vector3_sub_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ GimpVector3 result;
+
+ result.x = vector1.x - vector2.x;
+ result.y = vector1.y - vector2.y;
+ result.z = vector1.z - vector2.z;
+
+ return result;
+}
+
+/**
+ * gimp_vector3_inner_product:
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Computes the inner (dot) product of two 3D vectors. This product
+ * is zero if and only if the two vectors are orthogonal.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector3_inner_product (const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ return (vector1->x * vector2->x +
+ vector1->y * vector2->y +
+ vector1->z * vector2->z);
+}
+
+/**
+ * gimp_vector3_inner_product_val:
+ * @vector1: the first #GimpVector3.
+ * @vector2: the second #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_inner_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The inner product.
+ **/
+gdouble
+gimp_vector3_inner_product_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ return (vector1.x * vector2.x +
+ vector1.y * vector2.y +
+ vector1.z * vector2.z);
+}
+
+/**
+ * gimp_vector3_cross_product:
+ * @vector1: a pointer to the first #GimpVector3.
+ * @vector2: a pointer to the second #GimpVector3.
+ *
+ * Compute the cross product of two vectors. The result is a
+ * #GimpVector3 which is orthogonal to both @vector1 and @vector2. If
+ * @vector1 and @vector2 and parallel, the result will be the nul
+ * vector.
+ *
+ * This function can be used to compute the normal of the plane
+ * defined by @vector1 and @vector2.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector3
+gimp_vector3_cross_product (const GimpVector3 *vector1,
+ const GimpVector3 *vector2)
+{
+ GimpVector3 normal;
+
+ normal.x = vector1->y * vector2->z - vector1->z * vector2->y;
+ normal.y = vector1->z * vector2->x - vector1->x * vector2->z;
+ normal.z = vector1->x * vector2->y - vector1->y * vector2->x;
+
+ return normal;
+}
+
+/**
+ * gimp_vector3_cross_product_val:
+ * @vector1: the first #GimpVector3.
+ * @vector2: the second #GimpVector3.
+ *
+ * This function is identical to gimp_vector3_cross_product() but the
+ * vectors are passed by value rather than by reference.
+ *
+ * Returns: The cross product.
+ **/
+GimpVector3
+gimp_vector3_cross_product_val (GimpVector3 vector1,
+ GimpVector3 vector2)
+{
+ GimpVector3 normal;
+
+ normal.x = vector1.y * vector2.z - vector1.z * vector2.y;
+ normal.y = vector1.z * vector2.x - vector1.x * vector2.z;
+ normal.z = vector1.x * vector2.y - vector1.y * vector2.x;
+
+ return normal;
+}
+
+/**
+ * gimp_vector3_rotate:
+ * @vector: a pointer to a #GimpVector3.
+ * @alpha: the angle (in radian) of rotation around the Z axis.
+ * @beta: the angle (in radian) of rotation around the Y axis.
+ * @gamma: the angle (in radian) of rotation around the X axis.
+ *
+ * Rotates the @vector around the three axis (Z, Y, and X) by @alpha,
+ * @beta and @gamma, respectively.
+ *
+ * Note that the order of the rotation is very important. If you
+ * expect a vector to be rotated around X, and then around Y, you will
+ * have to call this function twice. Also, it is often wise to call
+ * this function with only one of @alpha, @beta and @gamma non-zero.
+ **/
+void
+gimp_vector3_rotate (GimpVector3 *vector,
+ gdouble alpha,
+ gdouble beta,
+ gdouble gamma)
+{
+ GimpVector3 s, t;
+
+ /* First we rotate it around the Z axis (XY plane).. */
+ /* ================================================= */
+
+ s.x = cos (alpha) * vector->x + sin (alpha) * vector->y;
+ s.y = cos (alpha) * vector->y - sin (alpha) * vector->x;
+
+ /* ..then around the Y axis (XZ plane).. */
+ /* ===================================== */
+
+ t = s;
+
+ vector->x = cos (beta) *t.x + sin (beta) * vector->z;
+ s.z = cos (beta) *vector->z - sin (beta) * t.x;
+
+ /* ..and at last around the X axis (YZ plane) */
+ /* ========================================== */
+
+ vector->y = cos (gamma) * t.y + sin (gamma) * s.z;
+ vector->z = cos (gamma) * s.z - sin (gamma) * t.y;
+}
+
+/**
+ * gimp_vector3_rotate_val:
+ * @vector: a #GimpVector3.
+ * @alpha: the angle (in radian) of rotation around the Z axis.
+ * @beta: the angle (in radian) of rotation around the Y axis.
+ * @gamma: the angle (in radian) of rotation around the X axis.
+ *
+ * This function is identical to gimp_vector3_rotate() but the vectors
+ * are passed by value rather than by reference.
+ *
+ * Returns: the rotated vector.
+ **/
+GimpVector3
+gimp_vector3_rotate_val (GimpVector3 vector,
+ gdouble alpha,
+ gdouble beta,
+ gdouble gamma)
+{
+ GimpVector3 s, t, result;
+
+ /* First we rotate it around the Z axis (XY plane).. */
+ /* ================================================= */
+
+ s.x = cos (alpha) * vector.x + sin (alpha) * vector.y;
+ s.y = cos (alpha) * vector.y - sin (alpha) * vector.x;
+
+ /* ..then around the Y axis (XZ plane).. */
+ /* ===================================== */
+
+ t = s;
+
+ result.x = cos (beta) *t.x + sin (beta) * vector.z;
+ s.z = cos (beta) *vector.z - sin (beta) * t.x;
+
+ /* ..and at last around the X axis (YZ plane) */
+ /* ========================================== */
+
+ result.y = cos (gamma) * t.y + sin (gamma) * s.z;
+ result.z = cos (gamma) * s.z - sin (gamma) * t.y;
+
+ return result;
+}
+
+/**
+ * gimp_vector_2d_to_3d:
+ * @sx: the abscissa of the upper-left screen rectangle.
+ * @sy: the ordinate of the upper-left screen rectangle.
+ * @w: the width of the screen rectangle.
+ * @h: the height of the screen rectangle.
+ * @x: the abscissa of the point in the screen rectangle to map.
+ * @y: the ordinate of the point in the screen rectangle to map.
+ * @vp: the position of the observer.
+ * @p: the resulting point.
+ *
+ * \"Compute screen (sx, sy) - (sx + w, sy + h) to 3D unit square
+ * mapping. The plane to map to is given in the z field of p. The
+ * observer is located at position vp (vp->z != 0.0).\"
+ *
+ * In other words, this computes the projection of the point (@x, @y)
+ * to the plane z = @p->z (parallel to XY), from the @vp point of view
+ * through the screen (@sx, @sy)->(@sx + @w, @sy + @h)
+ **/
+
+void
+gimp_vector_2d_to_3d (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gint x,
+ gint y,
+ const GimpVector3 *vp,
+ GimpVector3 *p)
+{
+ gdouble t = 0.0;
+
+ if (vp->x != 0.0)
+ t = (p->z - vp->z) / vp->z;
+
+ if (t != 0.0)
+ {
+ p->x = vp->x + t * (vp->x - ((gdouble) (x - sx) / (gdouble) w));
+ p->y = vp->y + t * (vp->y - ((gdouble) (y - sy) / (gdouble) h));
+ }
+ else
+ {
+ p->x = (gdouble) (x - sx) / (gdouble) w;
+ p->y = (gdouble) (y - sy) / (gdouble) h;
+ }
+}
+
+/**
+ * gimp_vector_2d_to_3d_val:
+ * @sx: the abscissa of the upper-left screen rectangle.
+ * @sy: the ordinate of the upper-left screen rectangle.
+ * @w: the width of the screen rectangle.
+ * @h: the height of the screen rectangle.
+ * @x: the abscissa of the point in the screen rectangle to map.
+ * @y: the ordinate of the point in the screen rectangle to map.
+ * @vp: position of the observer.
+ * @p: the resulting point.
+ *
+ * This function is identical to gimp_vector_2d_to_3d() but the
+ * position of the @observer and the resulting point @p are passed by
+ * value rather than by reference.
+ *
+ * Returns: the computed #GimpVector3 point.
+ **/
+GimpVector3
+gimp_vector_2d_to_3d_val (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gint x,
+ gint y,
+ GimpVector3 vp,
+ GimpVector3 p)
+{
+ GimpVector3 result;
+ gdouble t = 0.0;
+
+ if (vp.x != 0.0)
+ t = (p.z - vp.z) / vp.z;
+
+ if (t != 0.0)
+ {
+ result.x = vp.x + t * (vp.x - ((gdouble) (x - sx) / (gdouble) w));
+ result.y = vp.y + t * (vp.y - ((gdouble) (y - sy) / (gdouble) h));
+ }
+ else
+ {
+ result.x = (gdouble) (x - sx) / (gdouble) w;
+ result.y = (gdouble) (y - sy) / (gdouble) h;
+ }
+
+ result.z = 0;
+ return result;
+}
+
+/**
+ * gimp_vector_3d_to_2d:
+ * @sx: the abscissa of the upper-left screen rectangle.
+ * @sy: the ordinate of the upper-left screen rectangle.
+ * @w: the width of the screen rectangle.
+ * @h: the height of the screen rectangle.
+ * @x: the abscissa of the point in the screen rectangle to map (return value).
+ * @y: the ordinate of the point in the screen rectangle to map (return value).
+ * @vp: position of the observer.
+ * @p: the 3D point to project to the plane.
+ *
+ * Convert the given 3D point to 2D (project it onto the viewing
+ * plane, (sx, sy, 0) - (sx + w, sy + h, 0). The input is assumed to
+ * be in the unit square (0, 0, z) - (1, 1, z). The viewpoint of the
+ * observer is passed in vp.
+ *
+ * This is basically the opposite of gimp_vector_2d_to_3d().
+ **/
+void
+gimp_vector_3d_to_2d (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gdouble *x,
+ gdouble *y,
+ const GimpVector3 *vp,
+ const GimpVector3 *p)
+{
+ gdouble t;
+ GimpVector3 dir;
+
+ gimp_vector3_sub (&dir, p, vp);
+ gimp_vector3_normalize (&dir);
+
+ if (dir.z != 0.0)
+ {
+ t = (-1.0 * vp->z) / dir.z;
+ *x = (gdouble) sx + ((vp->x + t * dir.x) * (gdouble) w);
+ *y = (gdouble) sy + ((vp->y + t * dir.y) * (gdouble) h);
+ }
+ else
+ {
+ *x = (gdouble) sx + (p->x * (gdouble) w);
+ *y = (gdouble) sy + (p->y * (gdouble) h);
+ }
+}
diff --git a/libgimpmath/gimpvector.h b/libgimpmath/gimpvector.h
new file mode 100644
index 0000000..77230da
--- /dev/null
+++ b/libgimpmath/gimpvector.h
@@ -0,0 +1,160 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
+ *
+ * gimpvector.h
+ *
+ * The gimp_vector* functions were taken from:
+ * GCK - The General Convenience Kit
+ * Copyright (C) 1996 Tom Bech
+ *
+ * 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_MATH_H_INSIDE__) && !defined (GIMP_MATH_COMPILATION)
+#error "Only <libgimpmath/gimpmath.h> can be included directly."
+#endif
+
+#ifndef __GIMP_VECTOR_H__
+#define __GIMP_VECTOR_H__
+
+G_BEGIN_DECLS
+
+/* For information look into the C source or the html documentation */
+
+
+/* Two dimensional vector functions */
+/* ================================ */
+
+GimpVector2 gimp_vector2_new (gdouble x,
+ gdouble y);
+void gimp_vector2_set (GimpVector2 *vector,
+ gdouble x,
+ gdouble y);
+gdouble gimp_vector2_length (const GimpVector2 *vector);
+gdouble gimp_vector2_length_val (GimpVector2 vector);
+void gimp_vector2_mul (GimpVector2 *vector,
+ gdouble factor);
+GimpVector2 gimp_vector2_mul_val (GimpVector2 vector,
+ gdouble factor);
+void gimp_vector2_normalize (GimpVector2 *vector);
+GimpVector2 gimp_vector2_normalize_val (GimpVector2 vector);
+void gimp_vector2_neg (GimpVector2 *vector);
+GimpVector2 gimp_vector2_neg_val (GimpVector2 vector);
+void gimp_vector2_add (GimpVector2 *result,
+ const GimpVector2 *vector1,
+ const GimpVector2 *vector2);
+GimpVector2 gimp_vector2_add_val (GimpVector2 vector1,
+ GimpVector2 vector2);
+void gimp_vector2_sub (GimpVector2 *result,
+ const GimpVector2 *vector1,
+ const GimpVector2 *vector2);
+GimpVector2 gimp_vector2_sub_val (GimpVector2 vector1,
+ GimpVector2 vector2);
+gdouble gimp_vector2_inner_product (const GimpVector2 *vector1,
+ const GimpVector2 *vector2);
+gdouble gimp_vector2_inner_product_val (GimpVector2 vector1,
+ GimpVector2 vector2);
+GimpVector2 gimp_vector2_cross_product (const GimpVector2 *vector1,
+ const GimpVector2 *vector2);
+GimpVector2 gimp_vector2_cross_product_val (GimpVector2 vector1,
+ GimpVector2 vector2);
+void gimp_vector2_rotate (GimpVector2 *vector,
+ gdouble alpha);
+GimpVector2 gimp_vector2_rotate_val (GimpVector2 vector,
+ gdouble alpha);
+GimpVector2 gimp_vector2_normal (GimpVector2 *vector);
+GimpVector2 gimp_vector2_normal_val (GimpVector2 vector);
+
+/* Three dimensional vector functions */
+/* ================================== */
+
+GimpVector3 gimp_vector3_new (gdouble x,
+ gdouble y,
+ gdouble z);
+void gimp_vector3_set (GimpVector3 *vector,
+ gdouble x,
+ gdouble y,
+ gdouble z);
+gdouble gimp_vector3_length (const GimpVector3 *vector);
+gdouble gimp_vector3_length_val (GimpVector3 vector);
+void gimp_vector3_mul (GimpVector3 *vector,
+ gdouble factor);
+GimpVector3 gimp_vector3_mul_val (GimpVector3 vector,
+ gdouble factor);
+void gimp_vector3_normalize (GimpVector3 *vector);
+GimpVector3 gimp_vector3_normalize_val (GimpVector3 vector);
+void gimp_vector3_neg (GimpVector3 *vector);
+GimpVector3 gimp_vector3_neg_val (GimpVector3 vector);
+void gimp_vector3_add (GimpVector3 *result,
+ const GimpVector3 *vector1,
+ const GimpVector3 *vector2);
+GimpVector3 gimp_vector3_add_val (GimpVector3 vector1,
+ GimpVector3 vector2);
+void gimp_vector3_sub (GimpVector3 *result,
+ const GimpVector3 *vector1,
+ const GimpVector3 *vector2);
+GimpVector3 gimp_vector3_sub_val (GimpVector3 vector1,
+ GimpVector3 vector2);
+gdouble gimp_vector3_inner_product (const GimpVector3 *vector1,
+ const GimpVector3 *vector2);
+gdouble gimp_vector3_inner_product_val (GimpVector3 vector1,
+ GimpVector3 vector2);
+GimpVector3 gimp_vector3_cross_product (const GimpVector3 *vector1,
+ const GimpVector3 *vector2);
+GimpVector3 gimp_vector3_cross_product_val (GimpVector3 vector1,
+ GimpVector3 vector2);
+void gimp_vector3_rotate (GimpVector3 *vector,
+ gdouble alpha,
+ gdouble beta,
+ gdouble gamma);
+GimpVector3 gimp_vector3_rotate_val (GimpVector3 vector,
+ gdouble alpha,
+ gdouble beta,
+ gdouble gamma);
+
+/* 2d <-> 3d Vector projection functions */
+/* ===================================== */
+
+void gimp_vector_2d_to_3d (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gint x,
+ gint y,
+ const GimpVector3 *vp,
+ GimpVector3 *p);
+
+GimpVector3 gimp_vector_2d_to_3d_val (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gint x,
+ gint y,
+ GimpVector3 vp,
+ GimpVector3 p);
+
+void gimp_vector_3d_to_2d (gint sx,
+ gint sy,
+ gint w,
+ gint h,
+ gdouble *x,
+ gdouble *y,
+ const GimpVector3 *vp,
+ const GimpVector3 *p);
+
+
+G_END_DECLS
+
+#endif /* __GIMP_VECTOR_H__ */