mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 17:33:25 +00:00

Several types functions were using the wording "float" historically to mean double-precision, e.g. the float array type (which was in fact a double array). Or the scanner function gimp_scanner_parse_float() was in fact returning a double value. What if we wanted someday to actually add float (usually this naming means in C the single-precision IEEE 754 floating point representation) support? How would we name this? Now technically it's not entirely wrong (a double is still a floating point). So I've been wondering if that is because maybe we never planned to have float and double precision may be good enough for all usage in a plug-in API (which doesn't have to be as generic so the higher precision is enough)? But how can we be sure? Also we already had some functions using the wording double (e.g. gimp_procedure_add_double_argument()), so let's just go the safe route and use the accurate wording. The additional change in PDB is internal, but there too, I was also finding very confusing that we were naming double-precision float as 'float' type. So I took the opportunity to update this. It doesn't change any signature. In fact the whole commit doesn't change any type or code logic, only naming, except for one bug fix in the middle which I encountered while renaming: in gimp_scanner_parse_deprecated_color(), I discovered a hidden bug in scanning (color-hsv*) values, which was mistakenly using a double type for an array of float.
1157 lines
30 KiB
C
1157 lines
30 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
|
|
*
|
|
* gimp.c
|
|
*
|
|
* This library is free software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* 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"
|
|
|
|
#define _GNU_SOURCE /* for the sigaction stuff */
|
|
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
#include <sys/time.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
#include <sys/param.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_WAIT_H
|
|
#include <sys/wait.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#ifndef WAIT_ANY
|
|
#define WAIT_ANY -1
|
|
#endif
|
|
|
|
#include <glib.h>
|
|
#include <glib/gstdio.h>
|
|
|
|
#ifndef G_OS_WIN32
|
|
#include "libgimpbase/gimpsignal.h"
|
|
|
|
#else
|
|
|
|
#ifdef HAVE_EXCHNDL
|
|
#include <time.h>
|
|
#include <exchndl.h>
|
|
#endif
|
|
|
|
#include <signal.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_SELECT_H
|
|
#include <sys/select.h>
|
|
#endif
|
|
|
|
#if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
|
|
# ifdef STRICT
|
|
# undef STRICT
|
|
# endif
|
|
# define STRICT
|
|
|
|
# include <windows.h>
|
|
# include <tlhelp32.h>
|
|
# undef RGB
|
|
#endif
|
|
|
|
#include <locale.h>
|
|
|
|
#include "gimp.h"
|
|
|
|
#include "libgimpbase/gimpbase-private.h"
|
|
#include "libgimpbase/gimpprotocol.h"
|
|
#include "libgimpbase/gimpwire.h"
|
|
|
|
#include "gimp-debug.h"
|
|
#include "gimp-private.h"
|
|
#include "gimp-shm.h"
|
|
#include "gimpgpparams.h"
|
|
#include "gimppdb-private.h"
|
|
#include "gimpplugin-private.h"
|
|
|
|
#include "libgimp-intl.h"
|
|
|
|
|
|
static void gimp_close (void);
|
|
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
#ifdef HAVE_EXCHNDL
|
|
static LONG WINAPI gimp_plugin_sigfatal_handler (PEXCEPTION_POINTERS pExceptionInfo);
|
|
|
|
static LPTOP_LEVEL_EXCEPTION_FILTER _prevExceptionFilter = NULL;
|
|
static gchar *plug_in_backtrace_path = NULL;
|
|
#endif
|
|
|
|
#else /* ! G_OS_WIN32 */
|
|
|
|
static void gimp_plugin_sigfatal_handler (gint sig_num);
|
|
|
|
#endif /* G_OS_WIN32 */
|
|
|
|
|
|
static GimpPlugIn *PLUG_IN = NULL;
|
|
static GimpPDB *PDB = NULL;
|
|
|
|
static gint _tile_width = -1;
|
|
static gint _tile_height = -1;
|
|
static gboolean _show_help_button = TRUE;
|
|
static gboolean _export_color_profile = FALSE;
|
|
static gboolean _export_comment = FALSE;
|
|
static gboolean _export_exif = FALSE;
|
|
static gboolean _export_xmp = FALSE;
|
|
static gboolean _export_iptc = FALSE;
|
|
static gboolean _export_thumbnail = TRUE;
|
|
static gint32 _num_processors = 1;
|
|
static GimpCheckSize _check_size = GIMP_CHECK_SIZE_MEDIUM_CHECKS;
|
|
static GimpCheckType _check_type = GIMP_CHECK_TYPE_GRAY_CHECKS;
|
|
static GeglColor *_check_custom_color1 = NULL;
|
|
static GeglColor *_check_custom_color2 = NULL;
|
|
static gint _default_display_id = -1;
|
|
static gchar *_wm_class = NULL;
|
|
static gchar *_display_name = NULL;
|
|
static gint _monitor_number = 0;
|
|
static guint32 _timestamp = 0;
|
|
static gchar *_icon_theme_dir = NULL;
|
|
static const gchar *progname = NULL;
|
|
|
|
static GimpStackTraceMode stack_trace_mode = GIMP_STACK_TRACE_NEVER;
|
|
|
|
|
|
/**
|
|
* gimp_main:
|
|
* @plug_in_type: the type of the #GimpPlugIn subclass of the plug-in
|
|
* @argc: the number of arguments
|
|
* @argv: (array length=argc): the arguments
|
|
*
|
|
* The main plug-in function that must be called with the plug-in's
|
|
* [class@Gimp.PlugIn] subclass #GType and the 'argc' and 'argv' that are passed
|
|
* to the platform's `main()`.
|
|
*
|
|
* For instance, in Python, you will want to end your plug-in with this
|
|
* call:
|
|
*
|
|
* ```py
|
|
* Gimp.main(MyPlugIn.__gtype__, sys.argv)
|
|
* ```
|
|
*
|
|
* For C plug-ins, use instead the [func@Gimp.MAIN] macro
|
|
*
|
|
* Returns: an exit status as defined by the C library,
|
|
* on success `EXIT_SUCCESS`.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
gint
|
|
gimp_main (GType plug_in_type,
|
|
gint argc,
|
|
gchar *argv[])
|
|
{
|
|
enum
|
|
{
|
|
ARG_PROGNAME,
|
|
ARG_GIMP,
|
|
ARG_PROTOCOL_VERSION,
|
|
ARG_READ_FD,
|
|
ARG_WRITE_FD,
|
|
ARG_MODE,
|
|
ARG_STACK_TRACE_MODE,
|
|
|
|
N_ARGS
|
|
};
|
|
|
|
GIOChannel *read_channel;
|
|
GIOChannel *write_channel;
|
|
gchar *basename;
|
|
gint protocol_version;
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
gint i, j, k;
|
|
|
|
/* Reduce risks */
|
|
SetDllDirectoryW (L"");
|
|
|
|
/* On Windows, set DLL search path to $INSTALLDIR/bin so that GEGL
|
|
* file operations can find their respective file library DLLs (such
|
|
* as jasper, etc.) without needing to set external PATH.
|
|
*/
|
|
{
|
|
const gchar *install_dir;
|
|
gchar *bin_dir;
|
|
LPWSTR w_bin_dir;
|
|
|
|
w_bin_dir = NULL;
|
|
install_dir = gimp_installation_directory ();
|
|
bin_dir = g_build_filename (install_dir, "bin", NULL);
|
|
|
|
w_bin_dir = g_utf8_to_utf16 (bin_dir, -1, NULL, NULL, NULL);
|
|
if (w_bin_dir)
|
|
{
|
|
SetDllDirectoryW (w_bin_dir);
|
|
g_free (w_bin_dir);
|
|
}
|
|
|
|
g_free (bin_dir);
|
|
}
|
|
|
|
#ifdef HAVE_EXCHNDL
|
|
/* Use Dr. Mingw (dumps backtrace on crash) if it is available. */
|
|
{
|
|
time_t t;
|
|
gchar *filename;
|
|
gchar *dir;
|
|
wchar_t *plug_in_backtrace_path_utf16;
|
|
|
|
/* This has to be the non-roaming directory (i.e., the local
|
|
* directory) as backtraces correspond to the binaries on this
|
|
* system.
|
|
*/
|
|
dir = g_build_filename (g_get_user_data_dir (),
|
|
GIMPDIR, GIMP_USER_VERSION, "CrashLog",
|
|
NULL);
|
|
/* Ensure the path exists. */
|
|
g_mkdir_with_parents (dir, 0700);
|
|
|
|
time (&t);
|
|
filename = g_strdup_printf ("%s-crash-%" G_GUINT64_FORMAT ".txt",
|
|
g_get_prgname(), t);
|
|
plug_in_backtrace_path = g_build_filename (dir, filename, NULL);
|
|
g_free (filename);
|
|
g_free (dir);
|
|
|
|
/* Similar to core crash handling in app/signals.c, the order here
|
|
* is very important!
|
|
*/
|
|
if (! _prevExceptionFilter)
|
|
_prevExceptionFilter = SetUnhandledExceptionFilter (gimp_plugin_sigfatal_handler);
|
|
|
|
ExcHndlInit ();
|
|
|
|
plug_in_backtrace_path_utf16 = g_utf8_to_utf16 (plug_in_backtrace_path,
|
|
-1, NULL, NULL, NULL);
|
|
if (plug_in_backtrace_path_utf16)
|
|
{
|
|
ExcHndlSetLogFileNameW (plug_in_backtrace_path_utf16);
|
|
g_free (plug_in_backtrace_path_utf16);
|
|
}
|
|
}
|
|
#endif /* HAVE_EXCHNDL */
|
|
|
|
#ifndef _WIN64
|
|
{
|
|
typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags);
|
|
t_SetProcessDEPPolicy p_SetProcessDEPPolicy;
|
|
|
|
p_SetProcessDEPPolicy = GetProcAddress (GetModuleHandleW (L"kernel32.dll"),
|
|
"SetProcessDEPPolicy");
|
|
if (p_SetProcessDEPPolicy)
|
|
(*p_SetProcessDEPPolicy) (PROCESS_DEP_ENABLE|PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION);
|
|
}
|
|
#endif /* _WIN64 */
|
|
|
|
/* Group all our windows together on the taskbar */
|
|
{
|
|
typedef HRESULT (WINAPI *t_SetCurrentProcessExplicitAppUserModelID) (PCWSTR lpPathName);
|
|
t_SetCurrentProcessExplicitAppUserModelID p_SetCurrentProcessExplicitAppUserModelID;
|
|
|
|
p_SetCurrentProcessExplicitAppUserModelID = (t_SetCurrentProcessExplicitAppUserModelID) GetProcAddress (GetModuleHandleW (L"shell32.dll"),
|
|
"SetCurrentProcessExplicitAppUserModelID");
|
|
if (p_SetCurrentProcessExplicitAppUserModelID)
|
|
(*p_SetCurrentProcessExplicitAppUserModelID) (L"gimp.GimpApplication");
|
|
}
|
|
|
|
/* Check for exe file name with spaces in the path having been split up
|
|
* by buggy NT C runtime, or something. I don't know why this happens
|
|
* on NT (including w2k), but not on w95/98.
|
|
*/
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
k = strlen (argv[i]);
|
|
|
|
if (k > 10)
|
|
{
|
|
if (g_ascii_strcasecmp (argv[i] + k - 4, ".exe") == 0)
|
|
{
|
|
/* Found the end of the executable name, most probably.
|
|
* Splice the parts of the name back together.
|
|
*/
|
|
GString *s;
|
|
|
|
s = g_string_new (argv[ARG_PROGNAME]);
|
|
|
|
for (j = 1; j <= i; j++)
|
|
{
|
|
s = g_string_append_c (s, ' ');
|
|
s = g_string_append (s, argv[j]);
|
|
}
|
|
|
|
argv[ARG_PROGNAME] = s->str;
|
|
|
|
/* Move rest of argv down */
|
|
for (j = 1; j < argc - i; j++)
|
|
argv[j] = argv[j + i];
|
|
|
|
argv[argc - i] = NULL;
|
|
argc -= i;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* G_OS_WIN32 */
|
|
|
|
g_assert (plug_in_type != G_TYPE_NONE);
|
|
|
|
if ((argc != N_ARGS) || (strcmp (argv[ARG_GIMP], "-gimp") != 0))
|
|
{
|
|
g_printerr ("%s is a GIMP plug-in and must be run by GIMP to be used\n",
|
|
argv[ARG_PROGNAME]);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
gimp_env_init (TRUE);
|
|
|
|
progname = argv[ARG_PROGNAME];
|
|
|
|
basename = g_path_get_basename (progname);
|
|
|
|
g_set_prgname (basename);
|
|
|
|
protocol_version = atoi (argv[ARG_PROTOCOL_VERSION]);
|
|
|
|
if (protocol_version < GIMP_PROTOCOL_VERSION)
|
|
{
|
|
g_printerr ("Could not execute plug-in \"%s\"\n(%s)\n"
|
|
"because GIMP is using an older version of the "
|
|
"plug-in protocol.\n",
|
|
gimp_filename_to_utf8 (g_get_prgname ()),
|
|
gimp_filename_to_utf8 (progname));
|
|
return EXIT_FAILURE;
|
|
}
|
|
else if (protocol_version > GIMP_PROTOCOL_VERSION)
|
|
{
|
|
g_printerr ("Could not execute plug-in \"%s\"\n(%s)\n"
|
|
"because it uses an obsolete version of the "
|
|
"plug-in protocol.\n",
|
|
gimp_filename_to_utf8 (g_get_prgname ()),
|
|
gimp_filename_to_utf8 (progname));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
_gimp_debug_init (basename);
|
|
|
|
g_free (basename);
|
|
|
|
stack_trace_mode = (GimpStackTraceMode) CLAMP (atoi (argv[ARG_STACK_TRACE_MODE]),
|
|
GIMP_STACK_TRACE_NEVER,
|
|
GIMP_STACK_TRACE_ALWAYS);
|
|
|
|
#ifndef G_OS_WIN32
|
|
|
|
/* No use catching these on Win32, the user won't get any meaningful
|
|
* stack trace from glib anyhow. It's better to let Windows inform
|
|
* about the program error, and offer debugging if the plug-in
|
|
* has been built with MSVC, and the user has MSVC installed.
|
|
*/
|
|
gimp_signal_private (SIGHUP, gimp_plugin_sigfatal_handler, 0);
|
|
gimp_signal_private (SIGINT, gimp_plugin_sigfatal_handler, 0);
|
|
gimp_signal_private (SIGQUIT, gimp_plugin_sigfatal_handler, 0);
|
|
gimp_signal_private (SIGTERM, gimp_plugin_sigfatal_handler, 0);
|
|
|
|
gimp_signal_private (SIGABRT, gimp_plugin_sigfatal_handler, 0);
|
|
gimp_signal_private (SIGBUS, gimp_plugin_sigfatal_handler, 0);
|
|
gimp_signal_private (SIGSEGV, gimp_plugin_sigfatal_handler, 0);
|
|
gimp_signal_private (SIGFPE, gimp_plugin_sigfatal_handler, 0);
|
|
|
|
/* Ignore SIGPIPE from crashing Gimp */
|
|
gimp_signal_private (SIGPIPE, SIG_IGN, 0);
|
|
|
|
/* Restart syscalls interrupted by SIGCHLD */
|
|
gimp_signal_private (SIGCHLD, SIG_DFL, SA_RESTART);
|
|
|
|
#endif /* ! G_OS_WIN32 */
|
|
|
|
#ifdef G_OS_WIN32
|
|
read_channel = g_io_channel_win32_new_fd (atoi (argv[ARG_READ_FD]));
|
|
write_channel = g_io_channel_win32_new_fd (atoi (argv[ARG_WRITE_FD]));
|
|
#else
|
|
read_channel = g_io_channel_unix_new (atoi (argv[ARG_READ_FD]));
|
|
write_channel = g_io_channel_unix_new (atoi (argv[ARG_WRITE_FD]));
|
|
#endif
|
|
|
|
g_io_channel_set_encoding (read_channel, NULL, NULL);
|
|
g_io_channel_set_encoding (write_channel, NULL, NULL);
|
|
|
|
g_io_channel_set_buffered (read_channel, FALSE);
|
|
g_io_channel_set_buffered (write_channel, FALSE);
|
|
|
|
g_io_channel_set_close_on_unref (read_channel, TRUE);
|
|
g_io_channel_set_close_on_unref (write_channel, TRUE);
|
|
|
|
/* initialize GTypes, they need to be known to g_type_from_name() */
|
|
{
|
|
GType init_types[] =
|
|
{
|
|
G_TYPE_INT, G_TYPE_PARAM_INT,
|
|
G_TYPE_UCHAR, G_TYPE_PARAM_UCHAR,
|
|
|
|
G_TYPE_STRING, G_TYPE_PARAM_STRING,
|
|
G_TYPE_STRV, G_TYPE_PARAM_BOXED,
|
|
|
|
G_TYPE_BYTES, G_TYPE_PARAM_BOXED,
|
|
|
|
GIMP_TYPE_ARRAY, GIMP_TYPE_PARAM_ARRAY,
|
|
GIMP_TYPE_INT32_ARRAY, GIMP_TYPE_PARAM_INT32_ARRAY,
|
|
GIMP_TYPE_DOUBLE_ARRAY, GIMP_TYPE_PARAM_DOUBLE_ARRAY,
|
|
GIMP_TYPE_CORE_OBJECT_ARRAY, GIMP_TYPE_PARAM_CORE_OBJECT_ARRAY,
|
|
|
|
GIMP_TYPE_DISPLAY, GIMP_TYPE_PARAM_DISPLAY,
|
|
GIMP_TYPE_IMAGE, GIMP_TYPE_PARAM_IMAGE,
|
|
GIMP_TYPE_ITEM, GIMP_TYPE_PARAM_ITEM,
|
|
GIMP_TYPE_DRAWABLE, GIMP_TYPE_PARAM_DRAWABLE,
|
|
GIMP_TYPE_LAYER, GIMP_TYPE_PARAM_LAYER,
|
|
GIMP_TYPE_TEXT_LAYER, GIMP_TYPE_PARAM_TEXT_LAYER,
|
|
GIMP_TYPE_GROUP_LAYER, GIMP_TYPE_PARAM_GROUP_LAYER,
|
|
GIMP_TYPE_CHANNEL, GIMP_TYPE_PARAM_CHANNEL,
|
|
GIMP_TYPE_LAYER_MASK, GIMP_TYPE_PARAM_LAYER_MASK,
|
|
GIMP_TYPE_SELECTION, GIMP_TYPE_PARAM_SELECTION,
|
|
GIMP_TYPE_PATH, GIMP_TYPE_PARAM_PATH,
|
|
|
|
GIMP_TYPE_BRUSH, GIMP_TYPE_PARAM_BRUSH,
|
|
GIMP_TYPE_FONT, GIMP_TYPE_PARAM_FONT,
|
|
GIMP_TYPE_GRADIENT, GIMP_TYPE_PARAM_GRADIENT,
|
|
GIMP_TYPE_PALETTE, GIMP_TYPE_PARAM_PALETTE,
|
|
GIMP_TYPE_PATTERN, GIMP_TYPE_PARAM_PATTERN,
|
|
|
|
GIMP_TYPE_UNIT, GIMP_TYPE_PARAM_UNIT,
|
|
};
|
|
|
|
gint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (init_types); i++, i++)
|
|
{
|
|
GType type = init_types[i];
|
|
|
|
if (G_TYPE_IS_CLASSED (type))
|
|
g_type_class_ref (type);
|
|
}
|
|
|
|
gimp_enums_init ();
|
|
}
|
|
|
|
/* initialize units */
|
|
{
|
|
GimpUnitVtable vtable = { 0 };
|
|
|
|
vtable.get_deletion_flag = _gimp_unit_get_deletion_flag;
|
|
vtable.set_deletion_flag = _gimp_unit_set_deletion_flag;
|
|
vtable.get_data = _gimp_unit_get_data;
|
|
|
|
gimp_base_init (&vtable);
|
|
}
|
|
|
|
/* initialize i18n support */
|
|
setlocale (LC_ALL, "");
|
|
|
|
gimp_bind_text_domain (GETTEXT_PACKAGE"-libgimp", gimp_locale_directory ());
|
|
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
|
|
bind_textdomain_codeset (GETTEXT_PACKAGE"-libgimp", "UTF-8");
|
|
#endif
|
|
|
|
_gimp_debug_configure (stack_trace_mode);
|
|
|
|
PLUG_IN = g_object_new (plug_in_type,
|
|
"program-name", progname,
|
|
"read-channel", read_channel,
|
|
"write-channel", write_channel,
|
|
NULL);
|
|
|
|
g_assert (GIMP_IS_PLUG_IN (PLUG_IN));
|
|
|
|
if (strcmp (argv[ARG_MODE], "-query") == 0)
|
|
{
|
|
if (_gimp_get_debug_flags () & GIMP_DEBUG_QUERY)
|
|
_gimp_debug_stop ();
|
|
|
|
_gimp_plug_in_query (PLUG_IN);
|
|
|
|
gimp_close ();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
if (strcmp (argv[ARG_MODE], "-init") == 0)
|
|
{
|
|
if (_gimp_get_debug_flags () & GIMP_DEBUG_INIT)
|
|
_gimp_debug_stop ();
|
|
|
|
_gimp_plug_in_init (PLUG_IN);
|
|
|
|
gimp_close ();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
if (_gimp_get_debug_flags () & GIMP_DEBUG_RUN)
|
|
_gimp_debug_stop ();
|
|
else if (_gimp_get_debug_flags () & GIMP_DEBUG_PID)
|
|
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Here I am!");
|
|
|
|
_gimp_plug_in_run (PLUG_IN);
|
|
|
|
gimp_close ();
|
|
g_io_channel_unref (read_channel);
|
|
g_io_channel_unref (write_channel);
|
|
g_clear_object (&_check_custom_color1);
|
|
g_clear_object (&_check_custom_color2);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* gimp_get_plug_in:
|
|
*
|
|
* This function returns the plug-in's #GimpPlugIn instance, which is
|
|
* a a singleton that can exist exactly once per running plug-in.
|
|
*
|
|
* Returns: (transfer none) (nullable): The plug-in's #GimpPlugIn singleton.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GimpPlugIn *
|
|
gimp_get_plug_in (void)
|
|
{
|
|
return PLUG_IN;
|
|
}
|
|
|
|
/**
|
|
* gimp_get_pdb:
|
|
*
|
|
* This function returns the plug-in's #GimpPDB instance, which is a
|
|
* singleton that can exist exactly once per running plug-in.
|
|
*
|
|
* Returns: (transfer none) (nullable): The plug-in's #GimpPDB singleton.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GimpPDB *
|
|
gimp_get_pdb (void)
|
|
{
|
|
if (! PDB)
|
|
PDB = _gimp_pdb_new (PLUG_IN);
|
|
|
|
return PDB;
|
|
}
|
|
|
|
/**
|
|
* gimp_quit:
|
|
*
|
|
* Forcefully causes the GIMP library to exit and close down its
|
|
* connection to main gimp application. This function never returns.
|
|
**/
|
|
void
|
|
gimp_quit (void)
|
|
{
|
|
gimp_close ();
|
|
|
|
#if defined G_OS_WIN32 && defined HAVE_EXCHNDL
|
|
if (plug_in_backtrace_path)
|
|
g_free (plug_in_backtrace_path);
|
|
#endif
|
|
|
|
exit (EXIT_SUCCESS);
|
|
}
|
|
|
|
/**
|
|
* gimp_tile_width:
|
|
*
|
|
* Returns the tile width GIMP is using.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the tile_width
|
|
**/
|
|
guint
|
|
gimp_tile_width (void)
|
|
{
|
|
return _tile_width;
|
|
}
|
|
|
|
/**
|
|
* gimp_tile_height:
|
|
*
|
|
* Returns the tile height GIMP is using.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the tile_height
|
|
**/
|
|
guint
|
|
gimp_tile_height (void)
|
|
{
|
|
return _tile_height;
|
|
}
|
|
|
|
/**
|
|
* gimp_show_help_button:
|
|
*
|
|
* Returns whether or not GimpDialog should automatically add a help
|
|
* button if help_func and help_id are given.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the show_help_button boolean
|
|
*
|
|
* Since: 2.2
|
|
**/
|
|
gboolean
|
|
gimp_show_help_button (void)
|
|
{
|
|
return _show_help_button;
|
|
}
|
|
|
|
/**
|
|
* gimp_export_color_profile:
|
|
*
|
|
* Returns whether file plug-ins should default to exporting the
|
|
* image's color profile.
|
|
*
|
|
* Returns: TRUE if preferences are set to export the color profile.
|
|
*
|
|
* Since: 2.10.4
|
|
**/
|
|
gboolean
|
|
gimp_export_color_profile (void)
|
|
{
|
|
return _export_color_profile;
|
|
}
|
|
|
|
/**
|
|
* gimp_export_comment:
|
|
*
|
|
* Returns whether file plug-ins should default to exporting the
|
|
* image's comment.
|
|
*
|
|
* Returns: TRUE if preferences are set to export the comment.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
gboolean
|
|
gimp_export_comment (void)
|
|
{
|
|
return _export_comment;
|
|
}
|
|
|
|
/**
|
|
* gimp_export_exif:
|
|
*
|
|
* Returns whether file plug-ins should default to exporting Exif
|
|
* metadata, according preferences (original settings is %FALSE since
|
|
* metadata can contain sensitive information).
|
|
*
|
|
* Returns: TRUE if preferences are set to export Exif.
|
|
*
|
|
* Since: 2.10
|
|
**/
|
|
gboolean
|
|
gimp_export_exif (void)
|
|
{
|
|
return _export_exif;
|
|
}
|
|
|
|
/**
|
|
* gimp_export_xmp:
|
|
*
|
|
* Returns whether file plug-ins should default to exporting XMP
|
|
* metadata, according preferences (original settings is %FALSE since
|
|
* metadata can contain sensitive information).
|
|
*
|
|
* Returns: TRUE if preferences are set to export XMP.
|
|
*
|
|
* Since: 2.10
|
|
**/
|
|
gboolean
|
|
gimp_export_xmp (void)
|
|
{
|
|
return _export_xmp;
|
|
}
|
|
|
|
/**
|
|
* gimp_export_iptc:
|
|
*
|
|
* Returns whether file plug-ins should default to exporting IPTC
|
|
* metadata, according preferences (original settings is %FALSE since
|
|
* metadata can contain sensitive information).
|
|
*
|
|
* Returns: TRUE if preferences are set to export IPTC.
|
|
*
|
|
* Since: 2.10
|
|
**/
|
|
gboolean
|
|
gimp_export_iptc (void)
|
|
{
|
|
return _export_iptc;
|
|
}
|
|
|
|
/**
|
|
* gimp_export_thumbnail:
|
|
*
|
|
* Returns whether file plug-ins should default to exporting the
|
|
* image's comment.
|
|
*
|
|
* Returns: TRUE if preferences are set to export the thumbnail.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
gboolean
|
|
gimp_export_thumbnail (void)
|
|
{
|
|
return _export_thumbnail;
|
|
}
|
|
|
|
/**
|
|
* gimp_get_num_processors:
|
|
*
|
|
* Returns the number of threads set explicitly by the user in the
|
|
* preferences. This information can be used by plug-ins wishing to
|
|
* follow user settings for multi-threaded implementations.
|
|
*
|
|
* Returns: the preferred number of threads to use.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
gint32
|
|
gimp_get_num_processors (void)
|
|
{
|
|
return _num_processors;
|
|
}
|
|
|
|
/**
|
|
* gimp_check_size:
|
|
*
|
|
* Returns the size of the checkerboard to be used in previews.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the check_size value
|
|
*
|
|
* Since: 2.2
|
|
**/
|
|
GimpCheckSize
|
|
gimp_check_size (void)
|
|
{
|
|
return _check_size;
|
|
}
|
|
|
|
/**
|
|
* gimp_check_type:
|
|
*
|
|
* Returns the type of the checkerboard to be used in previews.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the check_type value
|
|
*
|
|
* Since: 2.2
|
|
**/
|
|
GimpCheckType
|
|
gimp_check_type (void)
|
|
{
|
|
return _check_type;
|
|
}
|
|
|
|
/**
|
|
* gimp_check_custom_color1:
|
|
*
|
|
* Returns the first checkerboard custom color that can
|
|
* be used in previews.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Return value: the _check_custom_color1 value
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
const GeglColor *
|
|
gimp_check_custom_color1 (void)
|
|
{
|
|
return (const GeglColor *) _check_custom_color1;
|
|
}
|
|
|
|
/**
|
|
* gimp_check_custom_color2:
|
|
*
|
|
* Returns the second checkerboard custom color that can
|
|
* be used in previews.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Return value: the _check_custom_color2 value
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
const GeglColor *
|
|
gimp_check_custom_color2 (void)
|
|
{
|
|
return (const GeglColor *) _check_custom_color2;
|
|
}
|
|
|
|
/**
|
|
* gimp_default_display:
|
|
*
|
|
* Returns the default display ID. This corresponds to the display the
|
|
* running procedure's menu entry was invoked from.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: (transfer none): the default display ID
|
|
* The object belongs to libgimp and you should not free it.
|
|
**/
|
|
GimpDisplay *
|
|
gimp_default_display (void)
|
|
{
|
|
return gimp_display_get_by_id (_default_display_id);
|
|
}
|
|
|
|
/**
|
|
* gimp_wm_class:
|
|
*
|
|
* Returns the window manager class to be used for plug-in windows.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the window manager class
|
|
**/
|
|
const gchar *
|
|
gimp_wm_class (void)
|
|
{
|
|
return _wm_class;
|
|
}
|
|
|
|
/**
|
|
* gimp_display_name:
|
|
*
|
|
* Returns the display to be used for plug-in windows.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
* Will return %NULL if GIMP has been started with no GUI, either
|
|
* via "--no-interface" flag, or a console build.
|
|
*
|
|
* Returns: the display name
|
|
**/
|
|
const gchar *
|
|
gimp_display_name (void)
|
|
{
|
|
return _display_name;
|
|
}
|
|
|
|
/**
|
|
* gimp_monitor_number:
|
|
*
|
|
* Returns the monitor number to be used for plug-in windows.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the monitor number
|
|
**/
|
|
gint
|
|
gimp_monitor_number (void)
|
|
{
|
|
return _monitor_number;
|
|
}
|
|
|
|
/**
|
|
* gimp_user_time:
|
|
*
|
|
* Returns the timestamp of the user interaction that should be set on
|
|
* the plug-in window. This is handled transparently, plug-in authors
|
|
* do not have to care about it.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: timestamp for plug-in window
|
|
*
|
|
* Since: 2.6
|
|
**/
|
|
guint32
|
|
gimp_user_time (void)
|
|
{
|
|
return _timestamp;
|
|
}
|
|
|
|
/**
|
|
* gimp_icon_theme_dir:
|
|
*
|
|
* Returns the directory of the current icon theme.
|
|
*
|
|
* This is a constant value given at plug-in configuration time.
|
|
*
|
|
* Returns: the icon theme directory
|
|
*
|
|
* Since: 2.10.4
|
|
**/
|
|
const gchar *
|
|
gimp_icon_theme_dir (void)
|
|
{
|
|
return _icon_theme_dir;
|
|
}
|
|
|
|
/**
|
|
* gimp_get_progname:
|
|
*
|
|
* Returns the plug-in's executable name.
|
|
*
|
|
* Returns: the executable name
|
|
**/
|
|
const gchar *
|
|
gimp_get_progname (void)
|
|
{
|
|
return progname;
|
|
}
|
|
|
|
|
|
/* private functions */
|
|
|
|
static void
|
|
gimp_close (void)
|
|
{
|
|
if (_gimp_get_debug_flags () & GIMP_DEBUG_QUIT)
|
|
_gimp_debug_stop ();
|
|
|
|
gimp_base_exit ();
|
|
|
|
_gimp_plug_in_quit (PLUG_IN);
|
|
|
|
if (PDB)
|
|
g_object_run_dispose (G_OBJECT (PDB));
|
|
g_clear_object (&PDB);
|
|
|
|
g_object_run_dispose (G_OBJECT (PLUG_IN));
|
|
g_clear_object (&PLUG_IN);
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
#ifdef HAVE_EXCHNDL
|
|
static LONG WINAPI
|
|
gimp_plugin_sigfatal_handler (PEXCEPTION_POINTERS pExceptionInfo)
|
|
{
|
|
g_printerr ("Plugin signal handler: %s: fatal error\n", progname);
|
|
|
|
SetUnhandledExceptionFilter (_prevExceptionFilter);
|
|
|
|
/* For simplicity, do not make a difference between QUERY and ALWAYS
|
|
* on Windows (at least not for now).
|
|
*/
|
|
if (stack_trace_mode != GIMP_STACK_TRACE_NEVER &&
|
|
g_file_test (plug_in_backtrace_path, G_FILE_TEST_IS_REGULAR))
|
|
{
|
|
FILE *stream;
|
|
guchar buffer[256];
|
|
size_t read_len;
|
|
|
|
stream = g_fopen (plug_in_backtrace_path, "r");
|
|
do
|
|
{
|
|
/* Just read and output directly the file content. */
|
|
read_len = fread (buffer, 1, sizeof (buffer) - 1, stream);
|
|
buffer[read_len] = '\0';
|
|
g_printerr ("%s", buffer);
|
|
}
|
|
while (read_len);
|
|
fclose (stream);
|
|
}
|
|
|
|
if (_prevExceptionFilter && _prevExceptionFilter != gimp_plugin_sigfatal_handler)
|
|
return _prevExceptionFilter (pExceptionInfo);
|
|
else
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
#endif /* HAVE_EXCHNDL */
|
|
|
|
#else /* ! G_OS_WIN32 */
|
|
|
|
static void
|
|
gimp_plugin_sigfatal_handler (gint sig_num)
|
|
{
|
|
switch (sig_num)
|
|
{
|
|
case SIGHUP:
|
|
case SIGINT:
|
|
case SIGQUIT:
|
|
case SIGTERM:
|
|
g_printerr ("%s terminated: %s\n", progname, g_strsignal (sig_num));
|
|
break;
|
|
|
|
case SIGABRT:
|
|
case SIGBUS:
|
|
case SIGSEGV:
|
|
case SIGFPE:
|
|
case SIGPIPE:
|
|
default:
|
|
g_printerr ("%s: fatal error: %s\n", progname, g_strsignal (sig_num));
|
|
switch (stack_trace_mode)
|
|
{
|
|
case GIMP_STACK_TRACE_NEVER:
|
|
break;
|
|
|
|
case GIMP_STACK_TRACE_QUERY:
|
|
{
|
|
sigset_t sigset;
|
|
|
|
sigemptyset (&sigset);
|
|
sigprocmask (SIG_SETMASK, &sigset, NULL);
|
|
gimp_stack_trace_query (progname);
|
|
}
|
|
break;
|
|
|
|
case GIMP_STACK_TRACE_ALWAYS:
|
|
{
|
|
sigset_t sigset;
|
|
|
|
sigemptyset (&sigset);
|
|
sigprocmask (SIG_SETMASK, &sigset, NULL);
|
|
gimp_stack_trace_print (progname, stdout, NULL);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Do not end with gimp_quit().
|
|
* We want the plug-in to continue its normal crash course, otherwise
|
|
* we won't get the "Plug-in crashed" error in GIMP.
|
|
*/
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
#endif /* G_OS_WIN32 */
|
|
|
|
void
|
|
_gimp_config (GPConfig *config)
|
|
{
|
|
GFile *file;
|
|
gchar *path;
|
|
gsize bpp;
|
|
const guint8 *pixel;
|
|
const guint8 *icc;
|
|
gsize icc_length;
|
|
const Babl *format = NULL;
|
|
const Babl *space = NULL;
|
|
|
|
_tile_width = config->tile_width;
|
|
_tile_height = config->tile_height;
|
|
_check_size = config->check_size;
|
|
_check_type = config->check_type;
|
|
|
|
_show_help_button = config->show_help_button ? TRUE : FALSE;
|
|
_export_color_profile = config->export_color_profile ? TRUE : FALSE;
|
|
_export_exif = config->export_exif ? TRUE : FALSE;
|
|
_export_xmp = config->export_xmp ? TRUE : FALSE;
|
|
_export_iptc = config->export_iptc ? TRUE : FALSE;
|
|
_export_comment = config->export_comment;
|
|
_num_processors = config->num_processors;
|
|
_default_display_id = config->default_display_id;
|
|
_wm_class = g_strdup (config->wm_class);
|
|
_display_name = g_strdup (config->display_name);
|
|
_monitor_number = config->monitor_number;
|
|
_timestamp = config->timestamp;
|
|
_icon_theme_dir = g_strdup (config->icon_theme_dir);
|
|
|
|
if (config->app_name)
|
|
g_set_application_name (config->app_name);
|
|
|
|
gimp_cpu_accel_set_use (config->use_cpu_accel);
|
|
|
|
file = gimp_file_new_for_config_path (config->swap_path, NULL);
|
|
path = g_file_get_path (file);
|
|
|
|
g_object_set (gegl_config (),
|
|
"tile-cache-size", config->tile_cache_size,
|
|
"swap", path,
|
|
"swap-compression", config->swap_compression,
|
|
"threads", (gint) config->num_processors,
|
|
"use-opencl", config->use_opencl,
|
|
"application-license", "GPL3",
|
|
NULL);
|
|
|
|
/* XXX Running gegl_init() before gegl_config() is not appreciated by
|
|
* GEGL and generates a bunch of CRITICALs.
|
|
*/
|
|
babl_init ();
|
|
|
|
g_clear_object (&_check_custom_color1);
|
|
_check_custom_color1 = gegl_color_new (NULL);
|
|
pixel = g_bytes_get_data (config->check_custom_color1, &bpp);
|
|
icc = g_bytes_get_data (config->check_custom_icc1, &icc_length);
|
|
space = babl_space_from_icc ((const char *) icc, (int) icc_length,
|
|
BABL_ICC_INTENT_RELATIVE_COLORIMETRIC,
|
|
NULL);
|
|
format = babl_format_with_space (config->check_custom_encoding1, space);
|
|
if (bpp != babl_format_get_bytes_per_pixel (format))
|
|
{
|
|
g_warning ("%s: checker board color 1's format expects %d bpp but %" G_GSIZE_FORMAT " bytes were passed.",
|
|
G_STRFUNC, babl_format_get_bytes_per_pixel (format), bpp);
|
|
gegl_color_set_pixel (_check_custom_color1, babl_format ("R'G'B'A double"), GIMP_CHECKS_CUSTOM_COLOR1);
|
|
}
|
|
else
|
|
{
|
|
gegl_color_set_pixel (_check_custom_color1, format, pixel);
|
|
}
|
|
|
|
g_clear_object (&_check_custom_color2);
|
|
_check_custom_color2 = gegl_color_new (NULL);
|
|
pixel = g_bytes_get_data (config->check_custom_color2, &bpp);
|
|
icc = g_bytes_get_data (config->check_custom_icc2, &icc_length);
|
|
space = babl_space_from_icc ((const char *) icc, (int) icc_length,
|
|
BABL_ICC_INTENT_RELATIVE_COLORIMETRIC,
|
|
NULL);
|
|
format = babl_format_with_space (config->check_custom_encoding2, space);
|
|
if (bpp != babl_format_get_bytes_per_pixel (format))
|
|
{
|
|
g_warning ("%s: checker board color 2's format expects %d bpp but %" G_GSIZE_FORMAT " bytes were passed.",
|
|
G_STRFUNC, babl_format_get_bytes_per_pixel (format), bpp);
|
|
gegl_color_set_pixel (_check_custom_color2, babl_format ("R'G'B'A double"), GIMP_CHECKS_CUSTOM_COLOR2);
|
|
}
|
|
else
|
|
{
|
|
gegl_color_set_pixel (_check_custom_color2, format, pixel);
|
|
}
|
|
|
|
g_free (path);
|
|
g_object_unref (file);
|
|
|
|
_gimp_shm_open (config->shm_id);
|
|
}
|