mirror of https://github.com/GNOME/gimp.git
ScriptFu: script-fu-register-filter for GimpImageProcedure.
Resolves #8382 Also v2 scripts infer and set sensitivity to drawables Add two test plugins clothify-v3.scm and test-sphere-v3.scm. Temporary, to be removed when 3.0 ships. Some refactoring (extracting methods, moving functions to new files). Some drive-by fixes to script-fu-arg.c revealed by using GimpProcedureDialog.
This commit is contained in:
parent
25f8b332e9
commit
12c0c18036
|
@ -123,7 +123,15 @@ libgimp_scriptfu_@GIMP_API_VERSION@_la_SOURCES = \
|
|||
script-fu-proc-factory.h \
|
||||
script-fu-proc-factory.c \
|
||||
script-fu-arg.c \
|
||||
script-fu-arg.h
|
||||
script-fu-arg.h \
|
||||
script-fu-command.h \
|
||||
script-fu-command.c \
|
||||
script-fu-dialog.h \
|
||||
script-fu-dialog.c \
|
||||
script-fu-register.h \
|
||||
script-fu-register.c \
|
||||
script-fu-run-func.h \
|
||||
script-fu-run-func.c
|
||||
|
||||
EXTRA_libgimp_scriptfu_@GIMP_API_VERSION@_la_DEPENDENCIES = $(scriptfu_def)
|
||||
|
||||
|
|
|
@ -15,7 +15,11 @@ libscriptfu_sources = [
|
|||
'script-fu-compat.c',
|
||||
'script-fu-lib.c',
|
||||
'script-fu-proc-factory.c',
|
||||
'script-fu-arg.c'
|
||||
'script-fu-arg.c',
|
||||
'script-fu-register.c',
|
||||
'script-fu-dialog.c',
|
||||
'script-fu-run-func.c',
|
||||
'script-fu-command.c'
|
||||
]
|
||||
|
||||
# !! just "library(...)" which means shared versus static depends on configuration of project.
|
||||
|
|
|
@ -51,6 +51,10 @@
|
|||
static void ts_init_constants (scheme *sc);
|
||||
static void ts_init_enum (scheme *sc,
|
||||
GType enum_type);
|
||||
|
||||
static void ts_define_procedure (scheme *sc,
|
||||
const gchar *symbol_name,
|
||||
TsWrapperFunc func);
|
||||
static void ts_init_procedures (scheme *sc,
|
||||
gboolean register_scipts);
|
||||
static void convert_string (gchar *str);
|
||||
|
@ -67,6 +71,8 @@ static pointer script_fu_marshal_procedure_call_deprecated (scheme *sc,
|
|||
|
||||
static pointer script_fu_register_call (scheme *sc,
|
||||
pointer a);
|
||||
static pointer script_fu_register_call_filter (scheme *sc,
|
||||
pointer a);
|
||||
static pointer script_fu_menu_register_call (scheme *sc,
|
||||
pointer a);
|
||||
static pointer script_fu_quit_call (scheme *sc,
|
||||
|
@ -83,6 +89,7 @@ typedef struct
|
|||
gint value;
|
||||
} NamedConstant;
|
||||
|
||||
/* LHS is text in a script, RHS is constant defined in C. */
|
||||
static const NamedConstant script_constants[] =
|
||||
{
|
||||
/* Useful values from libgimpbase/gimplimits.h */
|
||||
|
@ -103,6 +110,8 @@ static const NamedConstant script_constants[] =
|
|||
{ "UNIT-PICA", GIMP_UNIT_PICA },
|
||||
|
||||
/* Script-Fu types */
|
||||
|
||||
/* Arg types. */
|
||||
{ "SF-IMAGE", SF_IMAGE },
|
||||
{ "SF-DRAWABLE", SF_DRAWABLE },
|
||||
{ "SF-LAYER", SF_LAYER },
|
||||
|
@ -125,6 +134,36 @@ static const NamedConstant script_constants[] =
|
|||
{ "SF-ENUM", SF_ENUM },
|
||||
{ "SF-DISPLAY", SF_DISPLAY },
|
||||
|
||||
/* PDB procedure drawable_arity, i.e. sensitivity.
|
||||
* Used with script-fu-register-filter.
|
||||
*
|
||||
* This declares the arity of the algorithm,
|
||||
* and not the signature of the PDB procedure.
|
||||
* Since v3, PDB procedures that are image procedures,
|
||||
* take a container of drawables.
|
||||
* This only describes how many drawables the container *should* hold.
|
||||
*
|
||||
* For calls invoked by a user, this describes
|
||||
* how many drawables the user is expected to select,
|
||||
* which disables/enables the menu item for the procedure.
|
||||
*
|
||||
* Procedures are also called from other procedures.
|
||||
* A call from another procedure may in fact
|
||||
* pass more drawables than declared for drawable_arity.
|
||||
* That is a programming error on behalf of the caller.
|
||||
* A well-written callee that is passed more drawables than declared
|
||||
* should return an error instead of processing any of the drawables.
|
||||
*
|
||||
* Similarly for fewer than declared.
|
||||
*/
|
||||
|
||||
/* Requires two drawables. Often an operation between them, yielding a new drawable */
|
||||
{ "SF-TWO-OR-MORE-DRAWABLE", SF_TWO_OR_MORE_DRAWABLE },
|
||||
/* Often processed independently, sequentially, with side effects on the drawables. */
|
||||
{ "SF-ONE-OR-MORE-DRAWABLE", SF_ONE_OR_MORE_DRAWABLE },
|
||||
/* Requires exactly one drawable. */
|
||||
{ "SF-ONE-DRAWABLE", SF_ONE_DRAWABLE },
|
||||
|
||||
/* For SF-ADJUSTMENT */
|
||||
{ "SF-SLIDER", SF_SLIDER },
|
||||
{ "SF-SPINNER", SF_SPINNER },
|
||||
|
@ -242,6 +281,8 @@ ts_interpret_stdin (void)
|
|||
gint
|
||||
ts_interpret_string (const gchar *expr)
|
||||
{
|
||||
gint result;
|
||||
|
||||
#if DEBUG_SCRIPTS
|
||||
sc.print_output = 1;
|
||||
sc.tracing = 1;
|
||||
|
@ -249,7 +290,10 @@ ts_interpret_string (const gchar *expr)
|
|||
|
||||
sc.vptr->load_string (&sc, (char *) expr);
|
||||
|
||||
return sc.retcode;
|
||||
result = sc.retcode;
|
||||
|
||||
g_debug ("ts_interpret_string returns: %i", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
|
@ -421,6 +465,27 @@ ts_init_enum (scheme *sc,
|
|||
g_type_class_unref (enum_class);
|
||||
}
|
||||
|
||||
/* Define a symbol into interpreter state,
|
||||
* bound to a foreign function, language C, defined here in ScriptFu source.
|
||||
*/
|
||||
static void
|
||||
ts_define_procedure (scheme *sc,
|
||||
const gchar *symbol_name,
|
||||
TsWrapperFunc func)
|
||||
{
|
||||
pointer symbol;
|
||||
|
||||
symbol = sc->vptr->mk_symbol (sc, symbol_name);
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc, func));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
}
|
||||
|
||||
|
||||
/* Define, into interpreter state,
|
||||
* 1) Scheme functions that call wrapper functions in C here in ScriptFu.
|
||||
* 2) Scheme functions wrapping every procedure in the PDB.
|
||||
*/
|
||||
static void
|
||||
ts_init_procedures (scheme *sc,
|
||||
gboolean register_scripts)
|
||||
|
@ -428,55 +493,30 @@ ts_init_procedures (scheme *sc,
|
|||
gchar **proc_list;
|
||||
gint num_procs;
|
||||
gint i;
|
||||
pointer symbol;
|
||||
|
||||
#if USE_DL
|
||||
symbol = sc->vptr->mk_symbol (sc,"load-extension");
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc, scm_load_ext));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
/* scm_load_ext not same as other wrappers, defined in tinyscheme/dynload */
|
||||
ts_define_procedure (sc, "load-extension", scm_load_ext);
|
||||
#endif
|
||||
|
||||
symbol = sc->vptr->mk_symbol (sc, "script-fu-register");
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc,
|
||||
register_scripts ?
|
||||
script_fu_register_call :
|
||||
script_fu_nil_call));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
if (register_scripts)
|
||||
{
|
||||
ts_define_procedure (sc, "script-fu-register", script_fu_register_call);
|
||||
ts_define_procedure (sc, "script-fu-register-filter", script_fu_register_call_filter);
|
||||
ts_define_procedure (sc, "script-fu-menu-register", script_fu_menu_register_call);
|
||||
}
|
||||
else
|
||||
{
|
||||
ts_define_procedure (sc, "script-fu-register", script_fu_nil_call);
|
||||
ts_define_procedure (sc, "script-fu-register-filter", script_fu_nil_call);
|
||||
ts_define_procedure (sc, "script-fu-menu-register", script_fu_nil_call);
|
||||
}
|
||||
|
||||
symbol = sc->vptr->mk_symbol (sc, "script-fu-menu-register");
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc,
|
||||
register_scripts ?
|
||||
script_fu_menu_register_call :
|
||||
script_fu_nil_call));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
ts_define_procedure (sc, "script-fu-quit", script_fu_quit_call);
|
||||
|
||||
symbol = sc->vptr->mk_symbol (sc, "script-fu-quit");
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc, script_fu_quit_call));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
|
||||
/* register normal database execution procedure */
|
||||
symbol = sc->vptr->mk_symbol (sc, "gimp-proc-db-call");
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc,
|
||||
script_fu_marshal_procedure_call_strict));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
|
||||
/* register permissive and deprecated db execution procedure; see comment below */
|
||||
symbol = sc->vptr->mk_symbol (sc, "-gimp-proc-db-call");
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc,
|
||||
script_fu_marshal_procedure_call_permissive));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
|
||||
symbol = sc->vptr->mk_symbol (sc, "--gimp-proc-db-call");
|
||||
sc->vptr->scheme_define (sc, sc->global_env, symbol,
|
||||
sc->vptr->mk_foreign_func (sc,
|
||||
script_fu_marshal_procedure_call_deprecated));
|
||||
sc->vptr->setimmutable (symbol);
|
||||
ts_define_procedure (sc, "gimp-proc-db-call", script_fu_marshal_procedure_call_strict);
|
||||
ts_define_procedure (sc, "-gimp-proc-db-call", script_fu_marshal_procedure_call_permissive);
|
||||
ts_define_procedure (sc, "--gimp-proc-db-call", script_fu_marshal_procedure_call_deprecated);
|
||||
|
||||
proc_list = gimp_pdb_query_procedures (gimp_get_pdb (),
|
||||
".*", ".*", ".*", ".*",
|
||||
|
@ -1598,6 +1638,13 @@ script_fu_register_call (scheme *sc,
|
|||
return script_fu_add_script (sc, a);
|
||||
}
|
||||
|
||||
static pointer
|
||||
script_fu_register_call_filter (scheme *sc,
|
||||
pointer a)
|
||||
{
|
||||
return script_fu_add_script_filter (sc, a);
|
||||
}
|
||||
|
||||
static pointer
|
||||
script_fu_menu_register_call (scheme *sc,
|
||||
pointer a)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "tinyscheme/scheme.h"
|
||||
|
||||
typedef void (*TsCallbackFunc) (void);
|
||||
typedef pointer (*TsWrapperFunc) (scheme*, pointer);
|
||||
|
||||
|
||||
void tinyscheme_init (GList *path,
|
||||
|
|
|
@ -450,6 +450,7 @@ script_fu_arg_append_repr_from_gvalue (SFArg *arg,
|
|||
GString *result_string,
|
||||
GValue *gvalue)
|
||||
{
|
||||
g_debug("script_fu_arg_append_repr_from_gvalue %s", arg->label);
|
||||
switch (arg->type)
|
||||
{
|
||||
case SF_IMAGE:
|
||||
|
@ -504,16 +505,24 @@ script_fu_arg_append_repr_from_gvalue (SFArg *arg,
|
|||
case SF_FILENAME:
|
||||
case SF_DIRNAME:
|
||||
{
|
||||
gchar * filepath = NULL;
|
||||
gchar * filepath = "error in file arg";
|
||||
|
||||
if (g_value_get_gtype (gvalue) == G_TYPE_FILE)
|
||||
/* sanity: GValue initialized. */
|
||||
if (G_VALUE_HOLDS_GTYPE(gvalue))
|
||||
{
|
||||
filepath = g_file_get_path (g_value_get_object (gvalue));
|
||||
/* Not escape special chars for whitespace or double quote. */
|
||||
if (g_value_get_gtype (gvalue) == G_TYPE_FILE)
|
||||
{
|
||||
filepath = g_file_get_path (g_value_get_object (gvalue));
|
||||
/* Not escape special chars for whitespace or double quote. */
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Expecting GFile in gvalue.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Expecting GFile in gvalue.");
|
||||
g_warning ("Expecting GValue holding a GType");
|
||||
}
|
||||
|
||||
g_string_append_printf (result_string, "\"%s\"", filepath);
|
||||
|
@ -539,7 +548,19 @@ script_fu_arg_append_repr_from_gvalue (SFArg *arg,
|
|||
|
||||
case SF_OPTION:
|
||||
case SF_ENUM:
|
||||
g_string_append_printf (result_string, "%d", g_value_get_int (gvalue));
|
||||
/* When sanity test fails, return an arbitrary int.
|
||||
* Fails when GimpConfig or GimpProcedureDialog does not support GParamEnum.
|
||||
*/
|
||||
if (G_VALUE_HOLDS_INT (gvalue))
|
||||
{
|
||||
g_string_append_printf (result_string, "%d", g_value_get_int (gvalue));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Expecting GValue holding an int.");
|
||||
g_string_append (result_string, "1"); /* Arbitrarily a common int. */
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -684,12 +705,16 @@ script_fu_arg_reset_name_generator (void)
|
|||
* It is unique among all names returned between resets of the generator.
|
||||
* Thus name meets uniquity for names of properties of one object.
|
||||
*
|
||||
* The name means nothing to human readers of the spec.
|
||||
* The nick is descriptive.
|
||||
* !!! GimpImageProcedures already have properties for convenience arguments,
|
||||
* e.g. a property named "image" "n_drawables" and "drawables"
|
||||
* So we avoid that name clash by starting with "otherImage"
|
||||
*
|
||||
* The returned string is owned by the generator
|
||||
* and is only stable until the next call to the generator.
|
||||
* That is, the caller should copy it (usually by creating a GParamSpec.)
|
||||
* The name means nothing to human readers of the spec.
|
||||
* Instead, the nick is descriptive for human readers.
|
||||
*
|
||||
* The returned string is owned by the generator, a constant.
|
||||
* The caller need not copy it,
|
||||
* but usually does by creating a GParamSpec.
|
||||
*/
|
||||
void
|
||||
script_fu_arg_generate_name_and_nick (SFArg *arg,
|
||||
|
@ -702,7 +727,7 @@ script_fu_arg_generate_name_and_nick (SFArg *arg,
|
|||
switch (arg->type)
|
||||
{
|
||||
case SF_IMAGE:
|
||||
name = "image";
|
||||
name = "otherImage"; /* !!! Avoid name clash. */
|
||||
break;
|
||||
|
||||
case SF_DRAWABLE:
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libgimp/gimpui.h>
|
||||
|
||||
#include "script-fu-types.h" /* SFScript */
|
||||
#include "script-fu-lib.h"
|
||||
#include "script-fu-script.h"
|
||||
|
||||
#include "script-fu-command.h"
|
||||
|
||||
|
||||
/* Methods for interpreting commands.
|
||||
*
|
||||
* Usually there is a stack of calls similar to:
|
||||
* script_fu_run_image_procedure (outer run func)
|
||||
* calls script_fu_interpret_image_proc
|
||||
* calls script_fu_run_command
|
||||
* calls ts_interpret_string
|
||||
* calls the inner run func in Scheme
|
||||
*
|
||||
* but script_fu_run_command is also called directly for loading scripts.
|
||||
*
|
||||
* FUTURE: see also similar code in script-fu-interface.c
|
||||
* which could be migrated here.
|
||||
*/
|
||||
|
||||
|
||||
/* Interpret a command.
|
||||
*
|
||||
* When errors during interpretation:
|
||||
* 1) set the error message from tinyscheme into GError at given handle.
|
||||
* 2) return FALSE
|
||||
* otherwise, return TRUE and discard any result of interpretation
|
||||
* ScriptFu return values only have a GimpPDBStatus,
|
||||
* since ScriptFu plugin scripts can only be declared returning void.
|
||||
*
|
||||
* While interpreting, any errors from further calls to the PDB
|
||||
* can show error dialogs in any GIMP gui,
|
||||
* unless the caller has taken responsibility with a prior call to
|
||||
* gimp_plug_in_set_pdb_error_handler
|
||||
*
|
||||
* FIXME: see script_fu_run_procedure.
|
||||
* It does not call gimp_plug_in_set_pdb_error_handler for NON-INTERACTIVE mode.
|
||||
*/
|
||||
gboolean
|
||||
script_fu_run_command (const gchar *command,
|
||||
GError **error)
|
||||
{
|
||||
GString *output;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_debug ("script_fu_run_command: %s", command);
|
||||
output = g_string_new (NULL);
|
||||
script_fu_redirect_output_to_gstr (output);
|
||||
|
||||
if (script_fu_interpret_string (command))
|
||||
{
|
||||
g_set_error (error, GIMP_PLUG_IN_ERROR, 0, "%s", output->str);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
g_string_free (output, TRUE);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Interpret a script that defines a GimpImageProcedure.
|
||||
*
|
||||
* Similar to v2 code in script-fu-interface.c, except:
|
||||
* 1) builds a command from a GValueArray from a GimpConfig,
|
||||
* instead of from local array of SFArg.
|
||||
* 2) adds actual args image, drawable, etc. for GimpImageProcedure
|
||||
*/
|
||||
GimpValueArray *
|
||||
script_fu_interpret_image_proc (
|
||||
GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *args)
|
||||
{
|
||||
gchar *command;
|
||||
GimpValueArray *result = NULL;
|
||||
gboolean interpretation_result;
|
||||
GError *error = NULL;
|
||||
|
||||
command = script_fu_script_get_command_for_image_proc (script, image, n_drawables, drawables, args);
|
||||
|
||||
/* Take responsibility for handling errors from the scripts further calls to PDB.
|
||||
* ScriptFu does not show an error dialog, but forwards errors back to GIMP.
|
||||
* This only tells GIMP that ScriptFu itself will forward GimpPDBStatus errors from
|
||||
* this scripts calls to the PDB.
|
||||
* The onus is on this script's called PDB procedures to return errors in the GimpPDBStatus.
|
||||
* Any that do not, but for example only call gimp-message, are breaching contract.
|
||||
*/
|
||||
gimp_plug_in_set_pdb_error_handler (gimp_get_plug_in (),
|
||||
GIMP_PDB_ERROR_HANDLER_PLUGIN);
|
||||
|
||||
interpretation_result = script_fu_run_command (command, &error);
|
||||
g_free (command);
|
||||
if (! interpretation_result)
|
||||
{
|
||||
/* This is to the console.
|
||||
* script->name not localized.
|
||||
* error->message expected to be localized.
|
||||
* GIMP will later display "PDB procedure failed: <message>" localized.
|
||||
*/
|
||||
g_warning ("While executing %s: %s",
|
||||
script->name,
|
||||
error->message);
|
||||
/* A GError was allocated and this will take ownership. */
|
||||
result = gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_SUCCESS,
|
||||
NULL);
|
||||
}
|
||||
|
||||
gimp_plug_in_set_pdb_error_handler (gimp_get_plug_in (),
|
||||
GIMP_PDB_ERROR_HANDLER_INTERNAL);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SCRIPT_FU_COMMAND_H__
|
||||
#define __SCRIPT_FU_COMMAND_H__
|
||||
|
||||
gboolean script_fu_run_command (const gchar *command,
|
||||
GError **error);
|
||||
|
||||
GimpValueArray *script_fu_interpret_image_proc (GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *args);
|
||||
|
||||
#endif /* __SCRIPT_FU_COMMAND_H__ */
|
|
@ -0,0 +1,179 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* script-fu-dialog.c
|
||||
* Copyright (C) 2022 Lloyd Konneker
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libgimp/gimpui.h>
|
||||
|
||||
#include "script-fu-types.h" /* SFScript */
|
||||
#include "script-fu-script.h" /* get_title */
|
||||
#include "script-fu-command.h"
|
||||
|
||||
#include "script-fu-dialog.h"
|
||||
|
||||
|
||||
/* An informal class that shows a dialog for a script then runs the script.
|
||||
* It is internal to libscriptfu.
|
||||
*
|
||||
* The dialog is modal for the script:
|
||||
* OK button hides the dialog then runs the script once.
|
||||
*
|
||||
* The dialog is non-modal with respect to the GIMP app GUI, which remains responsive.
|
||||
*
|
||||
* When called from plugin extension-script-fu, the dialog is modal on the extension:
|
||||
* although GIMP app continues responsive, a user choosing a menu item
|
||||
* that is also implemented by a script and extension-script-fu
|
||||
* will not show a dialog until the first called script finishes.
|
||||
*/
|
||||
|
||||
/* FUTURE: delete this after v3 is stable. */
|
||||
#define DEBUG_CONFIG_PROPERTIES FALSE
|
||||
|
||||
#if DEBUG_CONFIG_PROPERTIES
|
||||
static void
|
||||
dump_properties (GimpProcedureConfig *config)
|
||||
{
|
||||
GParamSpec **pspecs;
|
||||
guint n_pspecs;
|
||||
|
||||
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (config),
|
||||
&n_pspecs);
|
||||
for (guint i = 1; i < n_pspecs; i++)
|
||||
g_printerr ("%s %s\n", pspecs[i]->name, G_PARAM_SPEC_TYPE_NAME (pspecs[i]));
|
||||
g_free (pspecs);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Run a dialog for a procedure, then interpret the script.
|
||||
*
|
||||
* Run dialog: create config, create dialog for config, show dialog, and return a config.
|
||||
* Interpret: marshal config into Scheme text for function call, then interpret script.
|
||||
*
|
||||
* One widget per param of the procedure.
|
||||
* Require the procedure registered with params of GTypes
|
||||
* corresponding to SFType the author declared in script-fu-register call.
|
||||
*
|
||||
* Require initial_args is not NULL or empty.
|
||||
* A caller must ensure a dialog is needed because args is not empty.
|
||||
*/
|
||||
GimpValueArray*
|
||||
script_fu_dialog_run (GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *initial_args)
|
||||
|
||||
{
|
||||
GimpValueArray *result = NULL;
|
||||
GimpProcedureDialog *dialog = NULL;
|
||||
GimpProcedureConfig *config = NULL;
|
||||
gboolean not_canceled;
|
||||
|
||||
if ( (! G_IS_OBJECT (procedure)) || script == NULL)
|
||||
return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR, NULL);
|
||||
|
||||
if ( gimp_value_array_length (initial_args) < 1)
|
||||
return gimp_procedure_new_return_values (procedure, GIMP_PDB_EXECUTION_ERROR, NULL);
|
||||
|
||||
/* We don't prevent concurrent dialogs as in script-fu-interface.c.
|
||||
* For extension-script-fu, Gimp is already preventing concurrent dialogs.
|
||||
* For gimp-script-fu-interpreter, each plugin is a separate process
|
||||
* so concurrent dialogs CAN occur.
|
||||
*/
|
||||
/* There is no progress widget in GimpProcedureDialog.
|
||||
* Also, we don't need to update the progress in Gimp UI,
|
||||
* because Gimp shows progress: the name of all called PDB procedures.
|
||||
*/
|
||||
|
||||
/* Script's menu label */
|
||||
gimp_ui_init (script_fu_script_get_title (script));
|
||||
|
||||
config = gimp_procedure_create_config (procedure);
|
||||
#if DEBUG_CONFIG_PROPERTIES
|
||||
dump_properties (config);
|
||||
g_debug ("Len of initial_args %i", gimp_value_array_length (initial_args) );
|
||||
#endif
|
||||
|
||||
/* Get saved settings (last values) into the config.
|
||||
* Since run mode is INTERACTIVE, initial_args is moot.
|
||||
* Instead, last used values or default values populate the config.
|
||||
*/
|
||||
gimp_procedure_config_begin_run (config, NULL, GIMP_RUN_INTERACTIVE, initial_args);
|
||||
|
||||
/* Create a dialog having properties (describing arguments of the procedure)
|
||||
* taken from the config.
|
||||
*
|
||||
* Title dialog with the menu item, not the procedure name.
|
||||
* Assert menu item is localized.
|
||||
*/
|
||||
dialog = (GimpProcedureDialog*) gimp_procedure_dialog_new (
|
||||
procedure,
|
||||
config,
|
||||
script_fu_script_get_title (script));
|
||||
/* dialog has no widgets except standard buttons. */
|
||||
|
||||
/* It is possible to create custom widget where the provided widget is not adequate.
|
||||
* Then gimp_procedure_dialog_fill_list will create the rest.
|
||||
* For now, the provided widgets should be adequate.
|
||||
*/
|
||||
|
||||
/* NULL means create widgets for all properties of the procedure
|
||||
* that we have not already created widgets for.
|
||||
*/
|
||||
gimp_procedure_dialog_fill_list (dialog, NULL);
|
||||
|
||||
not_canceled = gimp_procedure_dialog_run (dialog);
|
||||
/* Assert config holds validated arg values from a user interaction. */
|
||||
if (not_canceled)
|
||||
{
|
||||
/* initial_args is declared const.
|
||||
* To avoid compiler warning "discarding const"
|
||||
* copy initial_args to a writeable copy.
|
||||
*/
|
||||
GimpValueArray *final_args = (GimpValueArray*) g_value_array_copy ((GValueArray*) initial_args);
|
||||
/* FIXME the above is deprecated.
|
||||
* Non-deprecated, but doesn't work:
|
||||
* GimpValueArray *final_args = (GimpValueArray*) g_array_copy ((GArray*) initial_args);
|
||||
* Maybe we need a gimp_value_array_copy method?
|
||||
*/
|
||||
|
||||
/* Store config's values into final_args. */
|
||||
gimp_procedure_config_get_values (config, final_args);
|
||||
|
||||
result = script_fu_interpret_image_proc (procedure, script, image, n_drawables, drawables, final_args);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = gimp_procedure_new_return_values (procedure, GIMP_PDB_CANCEL, NULL);
|
||||
}
|
||||
|
||||
gtk_widget_destroy ((GtkWidget*) dialog);
|
||||
|
||||
/* Persist config aka settings for the next run of the plugin.
|
||||
* Passing the GimpPDBStatus from result[0].
|
||||
* We must have a matching end_run for the begin_run, regardless of status.
|
||||
*/
|
||||
gimp_procedure_config_end_run (config, g_value_get_enum (gimp_value_array_index (result, 0)));
|
||||
|
||||
g_object_unref (config);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* script-fu-dialog.h
|
||||
* Copyright (C) 2022 Lloyd Konneker
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SCRIPT_FU_DIALOG_H__
|
||||
#define __SCRIPT_FU_DIALOG_H__
|
||||
|
||||
GimpValueArray *script_fu_dialog_run (GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *args);
|
||||
|
||||
#endif /* __SCRIPT_FU_DIALOG_H__ */
|
|
@ -18,8 +18,11 @@
|
|||
#ifndef __SCRIPT_FU_ENUMS_H__
|
||||
#define __SCRIPT_FU_ENUMS_H__
|
||||
|
||||
/* Typedefs for script-fu argument types */
|
||||
/* Note these are C names with underbar.
|
||||
* The Scheme names are usually the same with hyphen substituted for underbar.
|
||||
*/
|
||||
|
||||
/* script-fu argument types */
|
||||
typedef enum
|
||||
{
|
||||
SF_IMAGE = 0,
|
||||
|
@ -51,4 +54,37 @@ typedef enum
|
|||
SF_SPINNER
|
||||
} SFAdjustmentType;
|
||||
|
||||
/* This enum is local to ScriptFu
|
||||
* but the notion is general to other plugins.
|
||||
*
|
||||
* A GimpImageProcedure has drawable arity > 1.
|
||||
* A GimpProcedure often does not take any drawables, i.e. arity zero.
|
||||
* Some GimpProcedure may take drawables i.e. arity > 0,
|
||||
* but the procedure's menu item is always sensitive,
|
||||
* and the drawable can be chosen in the plugin's dialog.
|
||||
*
|
||||
* Script author does not use SF-NO-DRAWABLE, for now.
|
||||
*
|
||||
* Scripts of class GimpProcedure are declared by script-fu-register.
|
||||
* Their GUI is handled by ScriptFu, script-fu-interface.c
|
||||
* An author does not declare drawable_arity.
|
||||
*
|
||||
* Scripts of class GimpImageProcedure are declared by script-fu-register-filter.
|
||||
* Their GUI is handled by libgimpui, GimpProcedureDialog.
|
||||
* Their drawable_arity is declared by the author of the script.
|
||||
*
|
||||
* For backward compatibility, GIMP deprecates but allows PDB procedures
|
||||
* to take a single drawable, and sets their sensitivity automatically.
|
||||
* Their drawable_arity is inferred by ScriptFu.
|
||||
* FUTURE insist that an author use script-fu-register-filter (not script-fu-register)
|
||||
* for GimpImageProcedure taking image and one or more drawables.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SF_NO_DRAWABLE = 0, /* GimpProcedure. */
|
||||
SF_ONE_DRAWABLE, /* GimpImageProcedure, but only process one layer */
|
||||
SF_ONE_OR_MORE_DRAWABLE, /* GimpImageProcedure, multilayer capable */
|
||||
SF_TWO_OR_MORE_DRAWABLE, /* GimpImageProcedure, requires at least two drawables. */
|
||||
} SFDrawableArity;
|
||||
|
||||
#endif /* __SCRIPT_FU_ENUMS__ */
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "tinyscheme/scheme-private.h"
|
||||
#include "scheme-wrapper.h"
|
||||
|
||||
#include "script-fu-types.h"
|
||||
|
|
|
@ -88,7 +88,6 @@ script_fu_proc_factory_make_PLUGIN (GimpPlugIn *plug_in,
|
|||
procedure = script_fu_script_create_PDB_procedure (
|
||||
plug_in,
|
||||
script,
|
||||
script_fu_script_proc, /* run_func */
|
||||
GIMP_PDB_PROC_TYPE_PLUGIN);
|
||||
script_fu_add_menu_to_procedure (procedure, script);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,462 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <libgimp/gimp.h>
|
||||
#include <libgimp/gimpui.h>
|
||||
|
||||
#include "tinyscheme/scheme-private.h"
|
||||
|
||||
#include "script-fu-types.h"
|
||||
#include "script-fu-script.h"
|
||||
#include "script-fu-register.h"
|
||||
|
||||
/* Methods for a script's call to script-fu-register or script-fu-register-filter.
|
||||
* Such calls declare a PDB procedure, that ScriptFu will register in the PDB,
|
||||
* that the script implements by its inner run func.
|
||||
* These methods are only creating structs local to ScriptFu, used later to register.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Traverse Scheme argument list
|
||||
* creating a new SFScript with metadata, but empty SFArgs (formal arg specs)
|
||||
*
|
||||
* Takes a handle to a pointer into the argument list.
|
||||
* Advances the pointer past the metadata args.
|
||||
*
|
||||
* Returns new SFScript.
|
||||
*/
|
||||
SFScript*
|
||||
script_fu_script_new_from_metadata_args (scheme *sc,
|
||||
pointer *handle)
|
||||
{
|
||||
SFScript *script;
|
||||
const gchar *name;
|
||||
const gchar *menu_label;
|
||||
const gchar *blurb;
|
||||
const gchar *author;
|
||||
const gchar *copyright;
|
||||
const gchar *date;
|
||||
const gchar *image_types;
|
||||
guint n_args;
|
||||
|
||||
/* dereference handle into local pointer. */
|
||||
pointer a = *handle;
|
||||
|
||||
g_debug ("script_fu_script_new_from_metadata_args");
|
||||
|
||||
/* Require list_length starting at a is >=7
|
||||
* else strange parsing errors at plugin query time.
|
||||
*/
|
||||
|
||||
name = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
menu_label = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
blurb = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
author = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
copyright = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
date = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
if (sc->vptr->is_pair (a))
|
||||
{
|
||||
image_types = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
{
|
||||
image_types = sc->vptr->string_value (a);
|
||||
a = sc->NIL;
|
||||
}
|
||||
|
||||
/* Store local, advanced pointer at handle from caller. */
|
||||
*handle = a;
|
||||
|
||||
/* Calculate supplied number of formal arguments of the PDB procedure,
|
||||
* each takes three actual args from Scheme call.
|
||||
*/
|
||||
n_args = sc->vptr->list_length (sc, a) / 3;
|
||||
|
||||
/* This allocates empty array of SFArg. Hereafter, script knows its n_args. */
|
||||
script = script_fu_script_new (name,
|
||||
menu_label,
|
||||
blurb,
|
||||
author,
|
||||
copyright,
|
||||
date,
|
||||
image_types,
|
||||
n_args);
|
||||
return script;
|
||||
}
|
||||
|
||||
/* Traverse suffix of Scheme argument list,
|
||||
* creating SFArgs (formal arg specs) from triplets.
|
||||
*
|
||||
* Takes a handle to a pointer into the argument list.
|
||||
* Advances the pointer past the triplets.
|
||||
* Changes state of SFScript.args[]
|
||||
*
|
||||
* Returns a foreign_error or NIL.
|
||||
*/
|
||||
pointer
|
||||
script_fu_script_create_formal_args (scheme *sc,
|
||||
pointer *handle,
|
||||
SFScript *script)
|
||||
{
|
||||
/* dereference handle into local pointer. */
|
||||
pointer a = *handle;
|
||||
|
||||
g_debug ("script_fu_script_create_formal_args");
|
||||
|
||||
for (guint i = 0; i < script->n_args; i++)
|
||||
{
|
||||
SFArg *arg = &script->args[i];
|
||||
|
||||
if (a != sc->NIL)
|
||||
{
|
||||
if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: argument types must be integer values", 0);
|
||||
|
||||
arg->type = sc->vptr->ivalue (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
return foreign_error (sc, "script-fu-register: missing type specifier", 0);
|
||||
|
||||
if (a != sc->NIL)
|
||||
{
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: argument labels must be strings", 0);
|
||||
|
||||
arg->label = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
return foreign_error (sc, "script-fu-register: missing arguments label", 0);
|
||||
|
||||
if (a != sc->NIL)
|
||||
{
|
||||
switch (arg->type)
|
||||
{
|
||||
case SF_IMAGE:
|
||||
case SF_DRAWABLE:
|
||||
case SF_LAYER:
|
||||
case SF_CHANNEL:
|
||||
case SF_VECTORS:
|
||||
case SF_DISPLAY:
|
||||
if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: default IDs must be integer values", 0);
|
||||
|
||||
arg->default_value.sfa_image =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (a));
|
||||
break;
|
||||
|
||||
case SF_COLOR:
|
||||
if (sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
{
|
||||
if (! gimp_rgb_parse_css (&arg->default_value.sfa_color,
|
||||
sc->vptr->string_value (sc->vptr->pair_car (a)),
|
||||
-1))
|
||||
return foreign_error (sc, "script-fu-register: invalid default color name", 0);
|
||||
|
||||
gimp_rgb_set_alpha (&arg->default_value.sfa_color, 1.0);
|
||||
}
|
||||
else if (sc->vptr->is_list (sc, sc->vptr->pair_car (a)) &&
|
||||
sc->vptr->list_length(sc, sc->vptr->pair_car (a)) == 3)
|
||||
{
|
||||
pointer color_list;
|
||||
guchar r, g, b;
|
||||
|
||||
color_list = sc->vptr->pair_car (a);
|
||||
r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
|
||||
color_list = sc->vptr->pair_cdr (color_list);
|
||||
g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
|
||||
color_list = sc->vptr->pair_cdr (color_list);
|
||||
b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
|
||||
|
||||
gimp_rgb_set_uchar (&arg->default_value.sfa_color, r, g, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
return foreign_error (sc, "script-fu-register: color defaults must be a list of 3 integers or a color name", 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_TOGGLE:
|
||||
if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: toggle default must be an integer value", 0);
|
||||
|
||||
arg->default_value.sfa_toggle =
|
||||
(sc->vptr->ivalue (sc->vptr->pair_car (a))) ? TRUE : FALSE;
|
||||
break;
|
||||
|
||||
case SF_VALUE:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: value defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_value =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_STRING:
|
||||
case SF_TEXT:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: string defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_value =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_ADJUSTMENT:
|
||||
{
|
||||
pointer adj_list;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: adjustment defaults must be a list", 0);
|
||||
|
||||
adj_list = sc->vptr->pair_car (a);
|
||||
arg->default_value.sfa_adjustment.value =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.lower =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.upper =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.step =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.page =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.digits =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.type =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_FILENAME:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: filename defaults must be string values", 0);
|
||||
/* fallthrough */
|
||||
|
||||
case SF_DIRNAME:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: dirname defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_file.filename =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
/* Replace POSIX slashes with Win32 backslashes. This
|
||||
* is just so script-fus can be written with only
|
||||
* POSIX directory separators.
|
||||
*/
|
||||
gchar *filename = arg->default_value.sfa_file.filename;
|
||||
|
||||
while (*filename)
|
||||
{
|
||||
if (*filename == '/')
|
||||
*filename = G_DIR_SEPARATOR;
|
||||
|
||||
filename++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SF_FONT:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: font defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_font =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_PALETTE:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: palette defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_palette =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_PATTERN:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: pattern defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_pattern =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_BRUSH:
|
||||
{
|
||||
pointer brush_list;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: brush defaults must be a list", 0);
|
||||
|
||||
brush_list = sc->vptr->pair_car (a);
|
||||
arg->default_value.sfa_brush.name =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list)));
|
||||
|
||||
brush_list = sc->vptr->pair_cdr (brush_list);
|
||||
arg->default_value.sfa_brush.opacity =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (brush_list));
|
||||
|
||||
brush_list = sc->vptr->pair_cdr (brush_list);
|
||||
arg->default_value.sfa_brush.spacing =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
|
||||
|
||||
brush_list = sc->vptr->pair_cdr (brush_list);
|
||||
arg->default_value.sfa_brush.paint_mode =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_GRADIENT:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: gradient defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_gradient =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_OPTION:
|
||||
{
|
||||
pointer option_list;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: option defaults must be a list", 0);
|
||||
|
||||
for (option_list = sc->vptr->pair_car (a);
|
||||
option_list != sc->NIL;
|
||||
option_list = sc->vptr->pair_cdr (option_list))
|
||||
{
|
||||
arg->default_value.sfa_option.list =
|
||||
g_slist_append (arg->default_value.sfa_option.list,
|
||||
g_strdup (sc->vptr->string_value
|
||||
(sc->vptr->pair_car (option_list))));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_ENUM:
|
||||
{
|
||||
pointer option_list;
|
||||
const gchar *val;
|
||||
gchar *type_name;
|
||||
GEnumValue *enum_value;
|
||||
GType enum_type;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: enum defaults must be a list", 0);
|
||||
|
||||
option_list = sc->vptr->pair_car (a);
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
|
||||
return foreign_error (sc, "script-fu-register: first element in enum defaults must be a type-name", 0);
|
||||
|
||||
val = sc->vptr->string_value (sc->vptr->pair_car (option_list));
|
||||
|
||||
if (g_str_has_prefix (val, "Gimp"))
|
||||
type_name = g_strdup (val);
|
||||
else
|
||||
type_name = g_strconcat ("Gimp", val, NULL);
|
||||
|
||||
enum_type = g_type_from_name (type_name);
|
||||
if (! G_TYPE_IS_ENUM (enum_type))
|
||||
{
|
||||
g_free (type_name);
|
||||
return foreign_error (sc, "script-fu-register: first element in enum defaults must be the name of a registered type", 0);
|
||||
}
|
||||
|
||||
arg->default_value.sfa_enum.type_name = type_name;
|
||||
|
||||
option_list = sc->vptr->pair_cdr (option_list);
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
|
||||
return foreign_error (sc, "script-fu-register: second element in enum defaults must be a string", 0);
|
||||
|
||||
enum_value =
|
||||
g_enum_get_value_by_nick (g_type_class_peek (enum_type),
|
||||
sc->vptr->string_value (sc->vptr->pair_car (option_list)));
|
||||
if (enum_value)
|
||||
arg->default_value.sfa_enum.history = enum_value->value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
{
|
||||
return foreign_error (sc, "script-fu-register: missing default argument", 0);
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
/* Store local, advanced pointer at handle from caller. */
|
||||
*handle = a;
|
||||
|
||||
return sc->NIL;
|
||||
}
|
||||
|
||||
/* Traverse next arg in Scheme argument list.
|
||||
* Set SFScript.drawable_arity from the argument.
|
||||
* Used only by script-fu-register-filter.
|
||||
*
|
||||
* Return foreign_error or NIL.
|
||||
*/
|
||||
pointer
|
||||
script_fu_script_parse_drawable_arity_arg (scheme *sc,
|
||||
pointer *handle,
|
||||
SFScript *script)
|
||||
{
|
||||
/* dereference handle into local pointer. */
|
||||
pointer a = *handle;
|
||||
|
||||
/* argument must be an int, usually a symbol from enum e.g. SF-MULTIPLE-DRAWABLE */
|
||||
if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register-filter: drawable arity must be integer value", 0);
|
||||
script->drawable_arity = sc->vptr->ivalue (sc->vptr->pair_car (a));
|
||||
|
||||
/* Advance the pointer into script. */
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
*handle = a;
|
||||
return sc->NIL;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SCRIPT_FU_REGISTER_H__
|
||||
#define __SCRIPT_FU_REGISTER_H__
|
||||
|
||||
pointer script_fu_script_create_formal_args (scheme *sc,
|
||||
pointer *handle,
|
||||
SFScript *script);
|
||||
SFScript *script_fu_script_new_from_metadata_args (scheme *sc,
|
||||
pointer *handle);
|
||||
pointer script_fu_script_parse_drawable_arity_arg (scheme *sc,
|
||||
pointer *handle,
|
||||
SFScript *script);
|
||||
|
||||
#endif /* __SCRIPT_FU_REGISTER_H__ */
|
|
@ -0,0 +1,217 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include <libgimp/gimp.h>
|
||||
#include <libgimp/gimpui.h>
|
||||
|
||||
#include "scheme-wrapper.h" /* type "pointer" */
|
||||
|
||||
#include "script-fu-types.h"
|
||||
#include "script-fu-interface.h" /* ScriptFu's GUI implementation. */
|
||||
#include "script-fu-dialog.h" /* Gimp's GUI implementation. */
|
||||
#include "script-fu-script.h"
|
||||
#include "script-fu-scripts.h" /* script_fu_find_script */
|
||||
#include "script-fu-command.h"
|
||||
|
||||
#include "script-fu-run-func.h"
|
||||
|
||||
/* Outer run_funcs
|
||||
* One each for GimpProcedure and GimpImageProcedure.
|
||||
* These are called from Gimp, with two different signatures.
|
||||
* These form and interpret "commands" which are calls to inner run_funcs
|
||||
* defined in Scheme by a script.
|
||||
|
||||
* These return the result of interpretation,
|
||||
* in a GimpValueArray whose only element is a status.
|
||||
* !!! ScriptFu does not let authors define procedures that return values.
|
||||
*/
|
||||
|
||||
/* run_func for a GimpImageProcedure
|
||||
*
|
||||
* Type is GimpRunImageFunc.
|
||||
*
|
||||
* Uses Gimp's config and gui.
|
||||
*
|
||||
* Since 3.0
|
||||
*/
|
||||
GimpValueArray *
|
||||
script_fu_run_image_procedure ( GimpProcedure *procedure, /* GimpImageProcedure */
|
||||
GimpRunMode run_mode,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *other_args,
|
||||
gpointer data)
|
||||
{
|
||||
|
||||
GimpValueArray *result = NULL;
|
||||
SFScript *script;
|
||||
|
||||
g_debug ("script_fu_run_image_procedure");
|
||||
script = script_fu_find_script (gimp_procedure_get_name (procedure));
|
||||
|
||||
if (! script)
|
||||
return gimp_procedure_new_return_values (procedure, GIMP_PDB_CALLING_ERROR, NULL);
|
||||
|
||||
ts_set_run_mode (run_mode);
|
||||
|
||||
switch (run_mode)
|
||||
{
|
||||
case GIMP_RUN_INTERACTIVE:
|
||||
{
|
||||
if (gimp_value_array_length (other_args) > 0)
|
||||
{
|
||||
/* Let user choose "other" args in a dialog, then interpret. Maintain a config. */
|
||||
result = script_fu_dialog_run (procedure, script, image, n_drawables, drawables, other_args);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No "other" args for user to choose. No config to maintain. */
|
||||
result = script_fu_interpret_image_proc (procedure, script, image, n_drawables, drawables, other_args);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GIMP_RUN_NONINTERACTIVE:
|
||||
{
|
||||
/* A call from another PDB procedure.
|
||||
* Use the given other_args, without interacting with user.
|
||||
* Since no user interaction, no config to maintain.
|
||||
*/
|
||||
result = script_fu_interpret_image_proc (procedure, script, image, n_drawables, drawables, other_args);
|
||||
break;
|
||||
}
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
{
|
||||
/* User invoked from a menu "Filter>Run with last values".
|
||||
* Do not show dialog. other_args are already last values, from a config.
|
||||
*/
|
||||
result = script_fu_interpret_image_proc (procedure, script, image, n_drawables, drawables, other_args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
result = gimp_procedure_new_return_values (procedure, GIMP_PDB_CALLING_ERROR, NULL);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* run_func for a GimpProcedure.
|
||||
*
|
||||
* Type is GimpRunFunc
|
||||
*
|
||||
* Uses ScriptFu's own GUI implementation, and retains settings locally.
|
||||
*
|
||||
* Since prior to 3.0 but formerly named script_fu_script_proc
|
||||
*/
|
||||
GimpValueArray *
|
||||
script_fu_run_procedure (GimpProcedure *procedure,
|
||||
const GimpValueArray *args,
|
||||
gpointer data)
|
||||
{
|
||||
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
||||
SFScript *script;
|
||||
GimpRunMode run_mode;
|
||||
GError *error = NULL;
|
||||
|
||||
script = script_fu_find_script (gimp_procedure_get_name (procedure));
|
||||
|
||||
if (! script)
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_CALLING_ERROR,
|
||||
NULL);
|
||||
|
||||
run_mode = GIMP_VALUES_GET_ENUM (args, 0);
|
||||
|
||||
ts_set_run_mode (run_mode);
|
||||
|
||||
switch (run_mode)
|
||||
{
|
||||
case GIMP_RUN_INTERACTIVE:
|
||||
{
|
||||
gint min_args = 0;
|
||||
|
||||
/* First, try to collect the standard script arguments... */
|
||||
min_args = script_fu_script_collect_standard_args (script, args);
|
||||
|
||||
/* ...then acquire the rest of arguments (if any) with a dialog */
|
||||
if (script->n_args > min_args)
|
||||
{
|
||||
status = script_fu_interface (script, min_args);
|
||||
break;
|
||||
}
|
||||
/* otherwise (if the script takes no more arguments), skip
|
||||
* this part and run the script directly (fallthrough)
|
||||
*/
|
||||
}
|
||||
|
||||
case GIMP_RUN_NONINTERACTIVE:
|
||||
/* Make sure all the arguments are there */
|
||||
if (gimp_value_array_length (args) != (script->n_args + 1))
|
||||
status = GIMP_PDB_CALLING_ERROR;
|
||||
|
||||
if (status == GIMP_PDB_SUCCESS)
|
||||
{
|
||||
gchar *command;
|
||||
|
||||
command = script_fu_script_get_command_from_params (script, args);
|
||||
|
||||
/* run the command through the interpreter */
|
||||
if (! script_fu_run_command (command, &error))
|
||||
{
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
}
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
{
|
||||
gchar *command;
|
||||
|
||||
/* First, try to collect the standard script arguments */
|
||||
script_fu_script_collect_standard_args (script, args);
|
||||
|
||||
command = script_fu_script_get_command (script);
|
||||
|
||||
/* run the command through the interpreter */
|
||||
if (! script_fu_run_command (command, &error))
|
||||
{
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
}
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return gimp_procedure_new_return_values (procedure, status, NULL);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __SCRIPT_FU_RUN_FUNC_H__
|
||||
#define __SCRIPT_FU_RUN_FUNC_H__
|
||||
|
||||
GimpValueArray *script_fu_run_procedure (GimpProcedure *procedure,
|
||||
const GimpValueArray *args,
|
||||
gpointer data);
|
||||
|
||||
GimpValueArray *script_fu_run_image_procedure (GimpProcedure *procedure,
|
||||
GimpRunMode run_mode,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *args,
|
||||
gpointer data);
|
||||
|
||||
#endif /* __SCRIPT_FU_RUN_FUNC__ */
|
|
@ -27,6 +27,8 @@
|
|||
#include "script-fu-types.h"
|
||||
#include "script-fu-arg.h"
|
||||
#include "script-fu-script.h"
|
||||
#include "script-fu-run-func.h"
|
||||
|
||||
#include "script-fu-intl.h"
|
||||
|
||||
|
||||
|
@ -34,14 +36,25 @@
|
|||
* Local Functions
|
||||
*/
|
||||
|
||||
static gboolean script_fu_script_param_init (SFScript *script,
|
||||
const GimpValueArray *args,
|
||||
SFArgType type,
|
||||
gint n);
|
||||
|
||||
|
||||
|
||||
static gboolean script_fu_script_param_init (SFScript *script,
|
||||
const GimpValueArray *args,
|
||||
SFArgType type,
|
||||
gint n);
|
||||
static void script_fu_script_set_proc_metadata (
|
||||
GimpProcedure *procedure,
|
||||
SFScript *script);
|
||||
static void script_fu_script_set_proc_args (
|
||||
GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
guint first_conveyed_arg);
|
||||
static void script_fu_script_set_drawable_sensitivity (
|
||||
GimpProcedure *procedure,
|
||||
SFScript *script);
|
||||
|
||||
static void script_fu_command_append_drawables (
|
||||
GString *s,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables);
|
||||
/*
|
||||
* Function definitions
|
||||
*/
|
||||
|
@ -71,6 +84,8 @@ script_fu_script_new (const gchar *name,
|
|||
script->n_args = n_args;
|
||||
script->args = g_new0 (SFArg, script->n_args);
|
||||
|
||||
script->drawable_arity = SF_NO_DRAWABLE; /* default */
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
|
@ -106,18 +121,15 @@ script_fu_script_free (SFScript *script)
|
|||
*/
|
||||
void
|
||||
script_fu_script_install_proc (GimpPlugIn *plug_in,
|
||||
SFScript *script,
|
||||
GimpRunFunc run_func)
|
||||
SFScript *script)
|
||||
{
|
||||
GimpProcedure *procedure;
|
||||
|
||||
g_return_if_fail (GIMP_IS_PLUG_IN (plug_in));
|
||||
g_return_if_fail (script != NULL);
|
||||
g_return_if_fail (run_func != NULL);
|
||||
|
||||
procedure = script_fu_script_create_PDB_procedure (plug_in,
|
||||
script,
|
||||
run_func,
|
||||
GIMP_PDB_PROC_TYPE_TEMPORARY);
|
||||
|
||||
gimp_plug_in_add_temp_procedure (plug_in, procedure);
|
||||
|
@ -126,67 +138,74 @@ script_fu_script_install_proc (GimpPlugIn *plug_in,
|
|||
|
||||
|
||||
/*
|
||||
* Create and return a GimpProcedure.
|
||||
* Create and return a GimpProcedure or its subclass GimpImageProcedure.
|
||||
* Caller typically either:
|
||||
* install it owned by self as TEMPORARY type procedure
|
||||
* OR return it as the result of a create_procedure callback from GIMP (PLUGIN type procedure.)
|
||||
*
|
||||
* Caller must unref the procedure.
|
||||
*
|
||||
* Understands ScriptFu's internal run funcs for GimpProcedure and GimpImageProcedure
|
||||
*/
|
||||
GimpProcedure *
|
||||
script_fu_script_create_PDB_procedure (GimpPlugIn *plug_in,
|
||||
SFScript *script,
|
||||
GimpRunFunc run_func,
|
||||
GimpPDBProcType plug_in_type)
|
||||
{
|
||||
GimpProcedure *procedure;
|
||||
const gchar *menu_label = NULL;
|
||||
|
||||
g_debug ("script_fu_script_create_PDB_procedure: %s of type %i", script->name, plug_in_type);
|
||||
|
||||
/* Allow scripts with no menus */
|
||||
if (strncmp (script->menu_label, "<None>", 6) != 0)
|
||||
menu_label = script->menu_label;
|
||||
|
||||
procedure = gimp_procedure_new (plug_in, script->name,
|
||||
plug_in_type,
|
||||
run_func, script, NULL);
|
||||
|
||||
gimp_procedure_set_image_types (procedure, script->image_types);
|
||||
|
||||
if (menu_label && strlen (menu_label))
|
||||
gimp_procedure_set_menu_label (procedure, menu_label);
|
||||
|
||||
gimp_procedure_set_documentation (procedure,
|
||||
script->blurb,
|
||||
NULL,
|
||||
script->name);
|
||||
gimp_procedure_set_attribution (procedure,
|
||||
script->author,
|
||||
script->copyright,
|
||||
script->date);
|
||||
|
||||
gimp_procedure_add_argument (procedure,
|
||||
g_param_spec_enum ("run-mode",
|
||||
"Run mode",
|
||||
"The run mode",
|
||||
GIMP_TYPE_RUN_MODE,
|
||||
GIMP_RUN_INTERACTIVE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
script_fu_arg_reset_name_generator ();
|
||||
for (gint i = 0; i < script->n_args; i++)
|
||||
if (script->proc_class == GIMP_TYPE_IMAGE_PROCEDURE)
|
||||
{
|
||||
GParamSpec *pspec = NULL;
|
||||
const gchar *name = NULL;
|
||||
const gchar *nick = NULL;
|
||||
g_debug ("script_fu_script_create_PDB_procedure: %s, plugin type %i, image_proc",
|
||||
script->name, plug_in_type);
|
||||
|
||||
script_fu_arg_generate_name_and_nick (&script->args[i], &name, &nick);
|
||||
pspec = script_fu_arg_get_param_spec (&script->args[i],
|
||||
name,
|
||||
nick);
|
||||
gimp_procedure_add_argument (procedure, pspec);
|
||||
procedure = gimp_image_procedure_new (
|
||||
plug_in, script->name,
|
||||
plug_in_type,
|
||||
(GimpRunImageFunc) script_fu_run_image_procedure,
|
||||
script, /* user_data, pointer in extension-script-fu process */
|
||||
NULL);
|
||||
|
||||
script_fu_script_set_proc_metadata (procedure, script);
|
||||
|
||||
/* Script author does not declare image, drawable in script-fu-register-filter,
|
||||
* and we don't add to formal args in PDB.
|
||||
* The convenience class GimpImageProcedure already has formal args:
|
||||
* run_mode, image, n_drawables, drawables.
|
||||
* "0" means not skip any arguments declared in the script.
|
||||
*/
|
||||
script_fu_script_set_proc_args (procedure, script, 0);
|
||||
|
||||
script_fu_script_set_drawable_sensitivity (procedure, script);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (script->proc_class == GIMP_TYPE_PROCEDURE);
|
||||
g_debug ("script_fu_script_create_PDB_procedure: %s, plugin type %i, ordinary proc",
|
||||
script->name, plug_in_type);
|
||||
|
||||
procedure = gimp_procedure_new (plug_in, script->name,
|
||||
plug_in_type,
|
||||
script_fu_run_procedure,
|
||||
script, NULL);
|
||||
|
||||
script_fu_script_set_proc_metadata (procedure, script);
|
||||
|
||||
gimp_procedure_add_argument (procedure,
|
||||
g_param_spec_enum ("run-mode",
|
||||
"Run mode",
|
||||
"The run mode",
|
||||
GIMP_TYPE_RUN_MODE,
|
||||
GIMP_RUN_INTERACTIVE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
script_fu_script_set_proc_args (procedure, script, 0);
|
||||
|
||||
/* !!! Author did not declare drawable arity, it was inferred. */
|
||||
script_fu_script_set_drawable_sensitivity (procedure, script);
|
||||
}
|
||||
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
|
@ -292,6 +311,10 @@ script_fu_script_collect_standard_args (SFScript *script,
|
|||
return params_consumed;
|
||||
}
|
||||
|
||||
/* Methods that form "commands" i.e. texts in Scheme language
|
||||
* that represent calls to the inner run func defined in a script.
|
||||
*/
|
||||
|
||||
gchar *
|
||||
script_fu_script_get_command (SFScript *script)
|
||||
{
|
||||
|
@ -343,6 +366,96 @@ script_fu_script_get_command_from_params (SFScript *script,
|
|||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
/* Append a literal representing a Scheme container of numerics
|
||||
* where the numerics are the ID's of the given drawables.
|
||||
* Container is scheme vector, meaning its elements are all the same type.
|
||||
*/
|
||||
static void
|
||||
script_fu_command_append_drawables (GString *s,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables)
|
||||
{
|
||||
/* Require non-empty array of drawables. */
|
||||
g_assert (n_drawables > 0);
|
||||
|
||||
/* !!! leading space to separate from prior args.
|
||||
* #() is scheme syntax for a vector.
|
||||
*/
|
||||
g_string_append (s, " #(" );
|
||||
for (guint i=0; i < n_drawables; i++)
|
||||
{
|
||||
g_string_append_printf (s, " %d", gimp_item_get_id ((GimpItem*) drawables[i]));
|
||||
}
|
||||
g_string_append (s, ")" );
|
||||
/* Ensure string is like: " #( 1 2 3)" */
|
||||
}
|
||||
|
||||
|
||||
gchar *
|
||||
script_fu_script_get_command_for_image_proc (SFScript *script,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *args)
|
||||
{
|
||||
GString *s;
|
||||
|
||||
g_return_val_if_fail (script != NULL, NULL);
|
||||
|
||||
s = g_string_new ("(");
|
||||
g_string_append (s, script->name);
|
||||
|
||||
/* The command has no run mode. */
|
||||
|
||||
/* scripts use integer ID's for Gimp objects. */
|
||||
g_string_append_printf (s, " %d", gimp_image_get_id (image));
|
||||
|
||||
/* Not pass n_drawables.
|
||||
* An author must use Scheme functions for length of container of drawables.
|
||||
*/
|
||||
|
||||
/* Append text repr for a container of all drawable ID's.
|
||||
* Even if script->drawable_arity = SF_PROC_IMAGE_SINGLE_DRAWABLE
|
||||
* since that means the inner run func takes many but will only process one.
|
||||
* We are not adapting to an inner run func that expects a single numeric.
|
||||
*/
|
||||
script_fu_command_append_drawables (s, n_drawables, drawables);
|
||||
|
||||
/* args contains the "other" args
|
||||
* Iterate over the GimpValueArray.
|
||||
* But script->args should be the same length, and types should match.
|
||||
*/
|
||||
for (guint i = 0; i < gimp_value_array_length (args); i++)
|
||||
{
|
||||
GValue *value = gimp_value_array_index (args, i);
|
||||
g_string_append_c (s, ' ');
|
||||
script_fu_arg_append_repr_from_gvalue (&script->args[i],
|
||||
s,
|
||||
value);
|
||||
}
|
||||
|
||||
g_string_append_c (s, ')');
|
||||
|
||||
return g_string_free (s, FALSE);
|
||||
}
|
||||
|
||||
/* Infer whether the script, defined using v2 script-fu-register,
|
||||
* which does not specify the arity for drawables,
|
||||
* is actually a script that takes one and only one drawable.
|
||||
* Such plugins are deprecated in v3: each plugin must take container of drawables
|
||||
* and declare its drawable arity via gimp_procedure_set_sensitivity_mask.
|
||||
*/
|
||||
void
|
||||
script_fu_script_infer_drawable_arity (SFScript *script)
|
||||
{
|
||||
if ((script->n_args > 1) &&
|
||||
script->args[0].type == SF_IMAGE &&
|
||||
script->args[1].type == SF_DRAWABLE)
|
||||
{
|
||||
g_debug ("Inferring drawable arity one.");
|
||||
script->drawable_arity = SF_ONE_DRAWABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Functions
|
||||
|
@ -431,3 +544,80 @@ script_fu_script_param_init (SFScript *script,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
script_fu_script_set_proc_metadata (GimpProcedure *procedure,
|
||||
SFScript *script)
|
||||
{
|
||||
const gchar *menu_label = NULL;
|
||||
|
||||
/* Allow scripts with no menus */
|
||||
if (strncmp (script->menu_label, "<None>", 6) != 0)
|
||||
menu_label = script->menu_label;
|
||||
|
||||
gimp_procedure_set_image_types (procedure, script->image_types);
|
||||
|
||||
if (menu_label && strlen (menu_label))
|
||||
gimp_procedure_set_menu_label (procedure, menu_label);
|
||||
|
||||
gimp_procedure_set_documentation (procedure,
|
||||
script->blurb,
|
||||
NULL,
|
||||
script->name);
|
||||
gimp_procedure_set_attribution (procedure,
|
||||
script->author,
|
||||
script->copyright,
|
||||
script->date);
|
||||
}
|
||||
|
||||
/* Convey formal arguments from SFArg to the PDB. */
|
||||
static void
|
||||
script_fu_script_set_proc_args (GimpProcedure *procedure,
|
||||
SFScript *script,
|
||||
guint first_conveyed_arg)
|
||||
{
|
||||
script_fu_arg_reset_name_generator ();
|
||||
for (gint i = first_conveyed_arg; i < script->n_args; i++)
|
||||
{
|
||||
GParamSpec *pspec = NULL;
|
||||
const gchar *name = NULL;
|
||||
const gchar *nick = NULL;
|
||||
|
||||
script_fu_arg_generate_name_and_nick (&script->args[i], &name, &nick);
|
||||
pspec = script_fu_arg_get_param_spec (&script->args[i],
|
||||
name,
|
||||
nick);
|
||||
gimp_procedure_add_argument (procedure, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
/* Convey drawable arity to the PDB.
|
||||
* !!! Unless set, sensitivity defaults to drawable arity 1.
|
||||
* See libgimp/gimpprocedure.c gimp_procedure_set_sensitivity_mask
|
||||
*/
|
||||
static void
|
||||
script_fu_script_set_drawable_sensitivity (GimpProcedure *procedure, SFScript *script)
|
||||
{
|
||||
switch (script->drawable_arity)
|
||||
{
|
||||
case SF_TWO_OR_MORE_DRAWABLE:
|
||||
gimp_procedure_set_sensitivity_mask (procedure,
|
||||
GIMP_PROCEDURE_SENSITIVE_DRAWABLES );
|
||||
break;
|
||||
case SF_ONE_OR_MORE_DRAWABLE:
|
||||
gimp_procedure_set_sensitivity_mask (procedure,
|
||||
GIMP_PROCEDURE_SENSITIVE_DRAWABLES |
|
||||
GIMP_PROCEDURE_SENSITIVE_DRAWABLE );
|
||||
break;
|
||||
case SF_ONE_DRAWABLE:
|
||||
gimp_procedure_set_sensitivity_mask (procedure, GIMP_PROCEDURE_SENSITIVE_DRAWABLE);
|
||||
break;
|
||||
case SF_NO_DRAWABLE:
|
||||
/* menu item always sensitive. */
|
||||
break;
|
||||
default:
|
||||
/* Fail to set sensitivy mask. */
|
||||
g_warning ("Unhandled case for SFDrawableArity");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ SFScript * script_fu_script_new (const gchar *name,
|
|||
void script_fu_script_free (SFScript *script);
|
||||
|
||||
void script_fu_script_install_proc (GimpPlugIn *plug_in,
|
||||
SFScript *script,
|
||||
GimpRunFunc run_func);
|
||||
SFScript *script);
|
||||
void script_fu_script_uninstall_proc (GimpPlugIn *plug_in,
|
||||
SFScript *script);
|
||||
|
||||
|
@ -45,12 +44,17 @@ gint script_fu_script_collect_standard_args (SFScript *scrip
|
|||
gchar * script_fu_script_get_command (SFScript *script);
|
||||
gchar * script_fu_script_get_command_from_params (SFScript *script,
|
||||
const GimpValueArray *args);
|
||||
gchar * script_fu_script_get_command_for_image_proc (
|
||||
SFScript *script,
|
||||
GimpImage *image,
|
||||
guint n_drawables,
|
||||
GimpDrawable **drawables,
|
||||
const GimpValueArray *args);
|
||||
|
||||
GimpProcedure * script_fu_script_create_PDB_procedure (GimpPlugIn *plug_in,
|
||||
SFScript *script,
|
||||
GimpRunFunc run_func,
|
||||
GimpPDBProcType plug_in_type);
|
||||
|
||||
|
||||
void script_fu_script_infer_drawable_arity (SFScript *script);
|
||||
|
||||
#endif /* __SCRIPT_FU_SCRIPT__ */
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
@ -31,14 +30,12 @@
|
|||
|
||||
#include "tinyscheme/scheme-private.h"
|
||||
|
||||
#include "scheme-wrapper.h"
|
||||
|
||||
#include "script-fu-types.h"
|
||||
|
||||
#include "script-fu-interface.h"
|
||||
#include "script-fu-script.h"
|
||||
#include "script-fu-scripts.h"
|
||||
#include "script-fu-utils.h"
|
||||
#include "script-fu-register.h"
|
||||
#include "script-fu-command.h"
|
||||
|
||||
#include "script-fu-intl.h"
|
||||
|
||||
|
@ -47,8 +44,6 @@
|
|||
* Local Functions
|
||||
*/
|
||||
|
||||
static gboolean script_fu_run_command (const gchar *command,
|
||||
GError **error);
|
||||
static void script_fu_load_directory (GFile *directory);
|
||||
static void script_fu_load_script (GFile *file);
|
||||
static gboolean script_fu_install_script (gpointer foo,
|
||||
|
@ -63,6 +58,8 @@ static gchar * script_fu_menu_map (const gchar *menu_pat
|
|||
static gint script_fu_menu_compare (gconstpointer a,
|
||||
gconstpointer b);
|
||||
|
||||
static void script_fu_try_map_menu (SFScript *script);
|
||||
static void script_fu_append_script_to_tree (SFScript *script);
|
||||
|
||||
/*
|
||||
* Local variables
|
||||
|
@ -78,14 +75,14 @@ static GList *script_menu_list = NULL;
|
|||
|
||||
/* Traverse list of paths, finding .scm files.
|
||||
* Load and eval any found script texts.
|
||||
* Script texts will call Scheme functions script-fu-register()
|
||||
* and script-fu-menu-register(),
|
||||
* Script texts will call Scheme functions script-fu-register
|
||||
* and script-fu-menu-register,
|
||||
* which insert a SFScript record into script_tree,
|
||||
* and insert a SFMenu record into script_menu_list.
|
||||
* These are side effects on the state of the outer (SF) interpreter.
|
||||
*
|
||||
* Return the tree of scripts, as well as keeping a local pointer to the tree.
|
||||
* The other result (script_menu_list) is not returned, see script_fu_get_menu_list().
|
||||
* The other result (script_menu_list) is not returned, see script_fu_get_menu_list.
|
||||
*
|
||||
* Caller should free script_tree and script_menu_list,
|
||||
* This should only be called once.
|
||||
|
@ -126,7 +123,7 @@ script_fu_find_scripts_into_tree ( GimpPlugIn *plug_in,
|
|||
|
||||
/*
|
||||
* Return list of SFMenu for recently loaded scripts.
|
||||
* List is non-empty only after a call to script_fu_find_scripts_into_tree().
|
||||
* List is non-empty only after a call to script_fu_find_scripts_into_tree.
|
||||
*/
|
||||
GList *
|
||||
script_fu_get_menu_list (void)
|
||||
|
@ -157,393 +154,99 @@ script_fu_find_scripts (GimpPlugIn *plug_in,
|
|||
script_menu_list = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For a script's call to script-fu-register.
|
||||
* Traverse Scheme argument list creating a new SFScript
|
||||
* whose drawable_arity is SF_PROC_ORDINARY.
|
||||
*
|
||||
* Return NIL or a foreign_error
|
||||
*/
|
||||
pointer
|
||||
script_fu_add_script (scheme *sc,
|
||||
pointer a)
|
||||
{
|
||||
SFScript *script;
|
||||
const gchar *name;
|
||||
const gchar *menu_label;
|
||||
const gchar *blurb;
|
||||
const gchar *author;
|
||||
const gchar *copyright;
|
||||
const gchar *date;
|
||||
const gchar *image_types;
|
||||
gint n_args;
|
||||
gint i;
|
||||
pointer args_error;
|
||||
|
||||
/* Check the length of a */
|
||||
/* Check metadata args args are present */
|
||||
if (sc->vptr->list_length (sc, a) < 7)
|
||||
{
|
||||
g_message (_("Too few arguments to 'script-fu-register' call"));
|
||||
return sc->NIL;
|
||||
}
|
||||
return foreign_error (sc, "script-fu-register: Not enough arguments", 0);
|
||||
|
||||
/* Find the script name */
|
||||
name = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
/* pass handle to pointer into script (on the stack) */
|
||||
script = script_fu_script_new_from_metadata_args (sc, &a);
|
||||
|
||||
/* Find the script menu_label */
|
||||
menu_label = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
/* Require drawable_arity defaults to SF_PROC_ORDINARY.
|
||||
* script-fu-register specifies an ordinary GimpProcedure.
|
||||
* We may go on to infer a different arity.
|
||||
*/
|
||||
g_assert (script->drawable_arity == SF_NO_DRAWABLE);
|
||||
|
||||
/* Find the script blurb */
|
||||
blurb = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
/* Find the script author */
|
||||
author = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
/* Find the script copyright */
|
||||
copyright = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
/* Find the script date */
|
||||
date = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
|
||||
/* Find the script image types */
|
||||
if (sc->vptr->is_pair (a))
|
||||
{
|
||||
image_types = sc->vptr->string_value (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
{
|
||||
image_types = sc->vptr->string_value (a);
|
||||
a = sc->NIL;
|
||||
}
|
||||
|
||||
/* Check the supplied number of arguments */
|
||||
n_args = sc->vptr->list_length (sc, a) / 3;
|
||||
|
||||
/* Create a new script */
|
||||
script = script_fu_script_new (name,
|
||||
menu_label,
|
||||
blurb,
|
||||
author,
|
||||
copyright,
|
||||
date,
|
||||
image_types,
|
||||
n_args);
|
||||
|
||||
for (i = 0; i < script->n_args; i++)
|
||||
{
|
||||
SFArg *arg = &script->args[i];
|
||||
|
||||
if (a != sc->NIL)
|
||||
{
|
||||
if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: argument types must be integer values", 0);
|
||||
|
||||
arg->type = sc->vptr->ivalue (sc->vptr->pair_car (a));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
return foreign_error (sc, "script-fu-register: missing type specifier", 0);
|
||||
|
||||
if (a != sc->NIL)
|
||||
{
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: argument labels must be strings", 0);
|
||||
|
||||
arg->label = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
return foreign_error (sc, "script-fu-register: missing arguments label", 0);
|
||||
|
||||
if (a != sc->NIL)
|
||||
{
|
||||
switch (arg->type)
|
||||
{
|
||||
case SF_IMAGE:
|
||||
case SF_DRAWABLE:
|
||||
case SF_LAYER:
|
||||
case SF_CHANNEL:
|
||||
case SF_VECTORS:
|
||||
case SF_DISPLAY:
|
||||
if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: default IDs must be integer values", 0);
|
||||
|
||||
arg->default_value.sfa_image =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (a));
|
||||
break;
|
||||
|
||||
case SF_COLOR:
|
||||
if (sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
{
|
||||
if (! gimp_rgb_parse_css (&arg->default_value.sfa_color,
|
||||
sc->vptr->string_value (sc->vptr->pair_car (a)),
|
||||
-1))
|
||||
return foreign_error (sc, "script-fu-register: invalid default color name", 0);
|
||||
|
||||
gimp_rgb_set_alpha (&arg->default_value.sfa_color, 1.0);
|
||||
}
|
||||
else if (sc->vptr->is_list (sc, sc->vptr->pair_car (a)) &&
|
||||
sc->vptr->list_length(sc, sc->vptr->pair_car (a)) == 3)
|
||||
{
|
||||
pointer color_list;
|
||||
guchar r, g, b;
|
||||
|
||||
color_list = sc->vptr->pair_car (a);
|
||||
r = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
|
||||
color_list = sc->vptr->pair_cdr (color_list);
|
||||
g = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
|
||||
color_list = sc->vptr->pair_cdr (color_list);
|
||||
b = CLAMP (sc->vptr->ivalue (sc->vptr->pair_car (color_list)), 0, 255);
|
||||
|
||||
gimp_rgb_set_uchar (&arg->default_value.sfa_color, r, g, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
return foreign_error (sc, "script-fu-register: color defaults must be a list of 3 integers or a color name", 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_TOGGLE:
|
||||
if (!sc->vptr->is_integer (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: toggle default must be an integer value", 0);
|
||||
|
||||
arg->default_value.sfa_toggle =
|
||||
(sc->vptr->ivalue (sc->vptr->pair_car (a))) ? TRUE : FALSE;
|
||||
break;
|
||||
|
||||
case SF_VALUE:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: value defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_value =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_STRING:
|
||||
case SF_TEXT:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: string defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_value =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_ADJUSTMENT:
|
||||
{
|
||||
pointer adj_list;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: adjustment defaults must be a list", 0);
|
||||
|
||||
adj_list = sc->vptr->pair_car (a);
|
||||
arg->default_value.sfa_adjustment.value =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.lower =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.upper =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.step =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.page =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.digits =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
|
||||
|
||||
adj_list = sc->vptr->pair_cdr (adj_list);
|
||||
arg->default_value.sfa_adjustment.type =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (adj_list));
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_FILENAME:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: filename defaults must be string values", 0);
|
||||
/* fallthrough */
|
||||
|
||||
case SF_DIRNAME:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: dirname defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_file.filename =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
/* Replace POSIX slashes with Win32 backslashes. This
|
||||
* is just so script-fus can be written with only
|
||||
* POSIX directory separators.
|
||||
*/
|
||||
gchar *filename = arg->default_value.sfa_file.filename;
|
||||
|
||||
while (*filename)
|
||||
{
|
||||
if (*filename == '/')
|
||||
*filename = G_DIR_SEPARATOR;
|
||||
|
||||
filename++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SF_FONT:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: font defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_font =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_PALETTE:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: palette defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_palette =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_PATTERN:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: pattern defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_pattern =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_BRUSH:
|
||||
{
|
||||
pointer brush_list;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: brush defaults must be a list", 0);
|
||||
|
||||
brush_list = sc->vptr->pair_car (a);
|
||||
arg->default_value.sfa_brush.name =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (brush_list)));
|
||||
|
||||
brush_list = sc->vptr->pair_cdr (brush_list);
|
||||
arg->default_value.sfa_brush.opacity =
|
||||
sc->vptr->rvalue (sc->vptr->pair_car (brush_list));
|
||||
|
||||
brush_list = sc->vptr->pair_cdr (brush_list);
|
||||
arg->default_value.sfa_brush.spacing =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
|
||||
|
||||
brush_list = sc->vptr->pair_cdr (brush_list);
|
||||
arg->default_value.sfa_brush.paint_mode =
|
||||
sc->vptr->ivalue (sc->vptr->pair_car (brush_list));
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_GRADIENT:
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (a)))
|
||||
return foreign_error (sc, "script-fu-register: gradient defaults must be string values", 0);
|
||||
|
||||
arg->default_value.sfa_gradient =
|
||||
g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
|
||||
break;
|
||||
|
||||
case SF_OPTION:
|
||||
{
|
||||
pointer option_list;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: option defaults must be a list", 0);
|
||||
|
||||
for (option_list = sc->vptr->pair_car (a);
|
||||
option_list != sc->NIL;
|
||||
option_list = sc->vptr->pair_cdr (option_list))
|
||||
{
|
||||
arg->default_value.sfa_option.list =
|
||||
g_slist_append (arg->default_value.sfa_option.list,
|
||||
g_strdup (sc->vptr->string_value
|
||||
(sc->vptr->pair_car (option_list))));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SF_ENUM:
|
||||
{
|
||||
pointer option_list;
|
||||
const gchar *val;
|
||||
gchar *type_name;
|
||||
GEnumValue *enum_value;
|
||||
GType enum_type;
|
||||
|
||||
if (!sc->vptr->is_list (sc, a))
|
||||
return foreign_error (sc, "script-fu-register: enum defaults must be a list", 0);
|
||||
|
||||
option_list = sc->vptr->pair_car (a);
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
|
||||
return foreign_error (sc, "script-fu-register: first element in enum defaults must be a type-name", 0);
|
||||
|
||||
val = sc->vptr->string_value (sc->vptr->pair_car (option_list));
|
||||
|
||||
if (g_str_has_prefix (val, "Gimp"))
|
||||
type_name = g_strdup (val);
|
||||
else
|
||||
type_name = g_strconcat ("Gimp", val, NULL);
|
||||
|
||||
enum_type = g_type_from_name (type_name);
|
||||
if (! G_TYPE_IS_ENUM (enum_type))
|
||||
{
|
||||
g_free (type_name);
|
||||
return foreign_error (sc, "script-fu-register: first element in enum defaults must be the name of a registered type", 0);
|
||||
}
|
||||
|
||||
arg->default_value.sfa_enum.type_name = type_name;
|
||||
|
||||
option_list = sc->vptr->pair_cdr (option_list);
|
||||
if (!sc->vptr->is_string (sc->vptr->pair_car (option_list)))
|
||||
return foreign_error (sc, "script-fu-register: second element in enum defaults must be a string", 0);
|
||||
|
||||
enum_value =
|
||||
g_enum_get_value_by_nick (g_type_class_peek (enum_type),
|
||||
sc->vptr->string_value (sc->vptr->pair_car (option_list)));
|
||||
if (enum_value)
|
||||
arg->default_value.sfa_enum.history = enum_value->value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
a = sc->vptr->pair_cdr (a);
|
||||
}
|
||||
else
|
||||
{
|
||||
return foreign_error (sc, "script-fu-register: missing default argument", 0);
|
||||
}
|
||||
}
|
||||
args_error = script_fu_script_create_formal_args (sc, &a, script);
|
||||
if (args_error != sc->NIL)
|
||||
return args_error;
|
||||
|
||||
/* fill all values from defaults */
|
||||
script_fu_script_reset (script, TRUE);
|
||||
|
||||
if (script->menu_label[0] == '<')
|
||||
{
|
||||
gchar *mapped = script_fu_menu_map (script->menu_label);
|
||||
/* Infer whether the script really requires one drawable,
|
||||
* so that later we can set the sensitivity.
|
||||
* For backward compatibility:
|
||||
* v2 script-fu-register does not require author to declare drawable arity.
|
||||
*/
|
||||
script_fu_script_infer_drawable_arity (script);
|
||||
|
||||
if (mapped)
|
||||
{
|
||||
g_free (script->menu_label);
|
||||
script->menu_label = mapped;
|
||||
}
|
||||
}
|
||||
script->proc_class = GIMP_TYPE_PROCEDURE;
|
||||
|
||||
{
|
||||
GList *list = g_tree_lookup (script_tree, script->menu_label);
|
||||
script_fu_try_map_menu (script);
|
||||
script_fu_append_script_to_tree (script);
|
||||
return sc->NIL;
|
||||
}
|
||||
|
||||
g_tree_insert (script_tree, (gpointer) script->menu_label,
|
||||
g_list_append (list, script));
|
||||
}
|
||||
/* For a script's call to script-fu-register-filter.
|
||||
* Traverse Scheme argument list creating a new SFScript
|
||||
* whose drawable_arity is SF_PROC_IMAGE_MULTIPLE_DRAWABLE or
|
||||
* SF_PROC_IMAGE_SINGLE_DRAWABLE
|
||||
*
|
||||
* Same as script-fu-register, except one more arg for drawable_arity.
|
||||
*
|
||||
* Return NIL or a foreign_error
|
||||
*/
|
||||
pointer
|
||||
script_fu_add_script_filter (scheme *sc,
|
||||
pointer a)
|
||||
{
|
||||
SFScript *script;
|
||||
pointer args_error; /* a foreign_error or NIL. */
|
||||
|
||||
/* Check metadata args args are present.
|
||||
* Has one more arg than script-fu-register.
|
||||
*/
|
||||
if (sc->vptr->list_length (sc, a) < 8)
|
||||
return foreign_error (sc, "script-fu-register-filter: Not enough arguments", 0);
|
||||
|
||||
/* pass handle i.e. "&a" ("a" of type "pointer" is on the stack) */
|
||||
script = script_fu_script_new_from_metadata_args (sc, &a);
|
||||
|
||||
/* Check semantic error: a script declaring it takes an image must specify
|
||||
* image types. Otherwise the script's menu item will be enabled
|
||||
* even when no images exist.
|
||||
*/
|
||||
if (g_strcmp0(script->image_types, "")==0)
|
||||
return foreign_error (sc, "script-fu-register-filter: A filter must declare image types.", 0);
|
||||
|
||||
args_error = script_fu_script_parse_drawable_arity_arg (sc, &a, script);
|
||||
if (args_error != sc->NIL)
|
||||
return args_error;
|
||||
|
||||
args_error = script_fu_script_create_formal_args (sc, &a, script);
|
||||
if (args_error != sc->NIL)
|
||||
return args_error;
|
||||
|
||||
script->proc_class = GIMP_TYPE_IMAGE_PROCEDURE;
|
||||
|
||||
script_fu_try_map_menu (script);
|
||||
script_fu_append_script_to_tree (script);
|
||||
return sc->NIL;
|
||||
}
|
||||
|
||||
|
@ -594,31 +297,6 @@ script_fu_add_menu (scheme *sc,
|
|||
|
||||
/* private functions */
|
||||
|
||||
static gboolean
|
||||
script_fu_run_command (const gchar *command,
|
||||
GError **error)
|
||||
{
|
||||
GString *output;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_debug ("script_fu_run_command: %s", command);
|
||||
output = g_string_new (NULL);
|
||||
ts_register_output_func (ts_gstring_output_func, output);
|
||||
|
||||
if (ts_interpret_string (command))
|
||||
{
|
||||
g_set_error (error, GIMP_PLUG_IN_ERROR, 0, "%s", output->str);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
g_string_free (output, TRUE);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
script_fu_load_directory (GFile *directory)
|
||||
{
|
||||
|
@ -717,8 +395,7 @@ script_fu_install_script (gpointer foo G_GNUC_UNUSED,
|
|||
|
||||
const gchar* name = script->name;
|
||||
if (script_fu_is_defined (name))
|
||||
script_fu_script_install_proc (plug_in, script,
|
||||
script_fu_script_proc);
|
||||
script_fu_script_install_proc (plug_in, script);
|
||||
else
|
||||
g_warning ("Run function not defined, or does not match PDB procedure name: %s", name);
|
||||
}
|
||||
|
@ -766,105 +443,7 @@ script_fu_remove_script (gpointer foo G_GNUC_UNUSED,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* This is the outer "run func" for this plugin.
|
||||
* When called, the name of the inner run func (code in Scheme language)
|
||||
* is the first element of the value array.
|
||||
* Form a command (text in Scheme language) that is a call to the the inner run func,
|
||||
* evaluate it, and return the result, marshalled into a GimpValueArray.
|
||||
*
|
||||
* In the name 'script_fu_script_proc', 'proc' is a verb meaning 'process the script'
|
||||
*/
|
||||
GimpValueArray *
|
||||
script_fu_script_proc (GimpProcedure *procedure,
|
||||
const GimpValueArray *args,
|
||||
gpointer data)
|
||||
{
|
||||
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
|
||||
SFScript *script;
|
||||
GimpRunMode run_mode;
|
||||
GError *error = NULL;
|
||||
|
||||
script = script_fu_find_script (gimp_procedure_get_name (procedure));
|
||||
|
||||
if (! script)
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_CALLING_ERROR,
|
||||
NULL);
|
||||
|
||||
run_mode = GIMP_VALUES_GET_ENUM (args, 0);
|
||||
|
||||
ts_set_run_mode (run_mode);
|
||||
|
||||
switch (run_mode)
|
||||
{
|
||||
case GIMP_RUN_INTERACTIVE:
|
||||
{
|
||||
gint min_args = 0;
|
||||
|
||||
/* First, try to collect the standard script arguments... */
|
||||
min_args = script_fu_script_collect_standard_args (script, args);
|
||||
|
||||
/* ...then acquire the rest of arguments (if any) with a dialog */
|
||||
if (script->n_args > min_args)
|
||||
{
|
||||
status = script_fu_interface (script, min_args);
|
||||
break;
|
||||
}
|
||||
/* otherwise (if the script takes no more arguments), skip
|
||||
* this part and run the script directly (fallthrough)
|
||||
*/
|
||||
}
|
||||
|
||||
case GIMP_RUN_NONINTERACTIVE:
|
||||
/* Make sure all the arguments are there */
|
||||
if (gimp_value_array_length (args) != (script->n_args + 1))
|
||||
status = GIMP_PDB_CALLING_ERROR;
|
||||
|
||||
if (status == GIMP_PDB_SUCCESS)
|
||||
{
|
||||
gchar *command;
|
||||
|
||||
command = script_fu_script_get_command_from_params (script, args);
|
||||
|
||||
/* run the command through the interpreter */
|
||||
if (! script_fu_run_command (command, &error))
|
||||
{
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
}
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_RUN_WITH_LAST_VALS:
|
||||
{
|
||||
gchar *command;
|
||||
|
||||
/* First, try to collect the standard script arguments */
|
||||
script_fu_script_collect_standard_args (script, args);
|
||||
|
||||
command = script_fu_script_get_command (script);
|
||||
|
||||
/* run the command through the interpreter */
|
||||
if (! script_fu_run_command (command, &error))
|
||||
{
|
||||
return gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_EXECUTION_ERROR,
|
||||
error);
|
||||
}
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return gimp_procedure_new_return_values (procedure, status, NULL);
|
||||
}
|
||||
|
||||
/* this is a GTraverseFunction */
|
||||
static gboolean
|
||||
|
@ -1004,3 +583,32 @@ script_fu_is_defined (const gchar * name)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Side effects on script. */
|
||||
static void
|
||||
script_fu_try_map_menu (SFScript *script)
|
||||
{
|
||||
if (script->menu_label[0] == '<')
|
||||
{
|
||||
gchar *mapped = script_fu_menu_map (script->menu_label);
|
||||
|
||||
if (mapped)
|
||||
{
|
||||
g_free (script->menu_label);
|
||||
script->menu_label = mapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Append to ordered tree.
|
||||
* Side effects on script_tree.
|
||||
*/
|
||||
static void
|
||||
script_fu_append_script_to_tree (SFScript *script)
|
||||
{
|
||||
GList *list = g_tree_lookup (script_tree, script->menu_label);
|
||||
|
||||
g_tree_insert (script_tree, (gpointer) script->menu_label,
|
||||
g_list_append (list, script));
|
||||
}
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
#ifndef __SCRIPT_FU_SCRIPTS_H__
|
||||
#define __SCRIPT_FU_SCRIPTS_H__
|
||||
|
||||
|
||||
void script_fu_find_scripts (GimpPlugIn *plug_in,
|
||||
GList *path);
|
||||
pointer script_fu_add_script (scheme *sc,
|
||||
pointer a);
|
||||
pointer script_fu_add_script (scheme *sc,
|
||||
pointer a);
|
||||
pointer script_fu_add_script_filter (scheme *sc,
|
||||
pointer a);
|
||||
pointer script_fu_add_menu (scheme *sc,
|
||||
pointer a);
|
||||
|
||||
|
@ -30,9 +31,7 @@ GTree * script_fu_find_scripts_into_tree (GimpPlugIn *plug_in,
|
|||
GList *path);
|
||||
SFScript * script_fu_find_script (const gchar *name);
|
||||
GList * script_fu_get_menu_list (void);
|
||||
GimpValueArray * script_fu_script_proc (GimpProcedure *procedure,
|
||||
const GimpValueArray *args,
|
||||
gpointer data);
|
||||
|
||||
gboolean script_fu_is_defined (const gchar *name);
|
||||
|
||||
#endif /* __SCRIPT_FU_SCRIPTS__ */
|
||||
|
|
|
@ -101,6 +101,8 @@ typedef struct
|
|||
|
||||
gint n_args;
|
||||
SFArg *args;
|
||||
SFDrawableArity drawable_arity;
|
||||
GType proc_class; /* GimpProcedure or GimpImageProcedure. */
|
||||
} SFScript;
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -57,18 +57,26 @@ scripts = \
|
|||
weave.scm \
|
||||
xach-effect.scm
|
||||
|
||||
# FIXME: when 3.0 ships, ship only the v3 versions
|
||||
# of clothify.scm and test-sphere.scm
|
||||
# During dev of 2.99, install old and new so devs can compare their GUIs.
|
||||
test_scripts = \
|
||||
contactsheet.scm \
|
||||
test-sphere.scm
|
||||
contactsheet.scm \
|
||||
test-sphere.scm \
|
||||
clothify-v3.scm
|
||||
|
||||
|
||||
# scripts interpreted by gimp-script-fu-interpreter
|
||||
# Each installs to a subdir of /plug-ins
|
||||
# Each should have a shebang and execute permission
|
||||
independent_scripts = \
|
||||
ts-helloworld.scm
|
||||
ts-helloworld.scm \
|
||||
test-sphere-v3.scm
|
||||
|
||||
ts_helloworlddir = $(gimpplugindir)/plug-ins/ts-helloworld
|
||||
ts_helloworld_SCRIPTS = ts-helloworld.scm
|
||||
test_sphere_v3dir = $(gimpplugindir)/plug-ins/test-sphere-v3
|
||||
test_sphere_v3_SCRIPTS = test-sphere-v3.scm
|
||||
|
||||
|
||||
scriptdata_DATA = $(scripts)
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
; CLOTHIFY version 1.02
|
||||
; Gives the current layer in the indicated image a cloth-like texture.
|
||||
; Process invented by Zach Beane (Xath@irc.gimp.net)
|
||||
;
|
||||
; Tim Newsome <drz@froody.bloke.com> 4/11/97
|
||||
|
||||
; v3>>> Adapted to take many drawables, but only handle the first
|
||||
; v3>>> drawables is-a vector, and there is no formal arg for its length i.e. n_drawables
|
||||
|
||||
(define (script-fu-clothify-v3 timg drawables bx by azimuth elevation depth)
|
||||
(let* (
|
||||
(tdrawable (aref drawables 0)) v3>>> only the first drawable
|
||||
(width (car (gimp-drawable-get-width tdrawable)))
|
||||
(height (car (gimp-drawable-get-height tdrawable)))
|
||||
(img (car (gimp-image-new width height RGB)))
|
||||
; (layer-two (car (gimp-layer-new img width height RGB-IMAGE "Y Dots" 100 LAYER-MODE-MULTIPLY)))
|
||||
(layer-one (car (gimp-layer-new img width height RGB-IMAGE "X Dots" 100 LAYER-MODE-NORMAL)))
|
||||
(layer-two 0)
|
||||
(bump-layer 0)
|
||||
)
|
||||
|
||||
(gimp-context-push)
|
||||
(gimp-context-set-defaults)
|
||||
|
||||
(gimp-image-undo-disable img)
|
||||
|
||||
(gimp-image-insert-layer img layer-one 0 0)
|
||||
|
||||
(gimp-context-set-background '(255 255 255))
|
||||
(gimp-drawable-edit-fill layer-one FILL-BACKGROUND)
|
||||
|
||||
(plug-in-noisify RUN-NONINTERACTIVE img layer-one FALSE 0.7 0.7 0.7 0.7)
|
||||
|
||||
(set! layer-two (car (gimp-layer-copy layer-one 0)))
|
||||
(gimp-layer-set-mode layer-two LAYER-MODE-MULTIPLY)
|
||||
(gimp-image-insert-layer img layer-two 0 0)
|
||||
|
||||
(plug-in-gauss-rle RUN-NONINTERACTIVE img layer-one bx TRUE FALSE)
|
||||
(plug-in-gauss-rle RUN-NONINTERACTIVE img layer-two by FALSE TRUE)
|
||||
(gimp-image-flatten img)
|
||||
(set! bump-layer (car (gimp-image-get-active-layer img)))
|
||||
|
||||
(plug-in-c-astretch RUN-NONINTERACTIVE img bump-layer)
|
||||
(plug-in-noisify RUN-NONINTERACTIVE img bump-layer FALSE 0.2 0.2 0.2 0.2)
|
||||
|
||||
(plug-in-bump-map RUN-NONINTERACTIVE img tdrawable bump-layer azimuth elevation depth 0 0 0 0 FALSE FALSE 0)
|
||||
(gimp-image-delete img)
|
||||
(gimp-displays-flush)
|
||||
|
||||
(gimp-context-pop)
|
||||
|
||||
; well-behaved requires error if more than one drawable
|
||||
( if (> (vector-length drawables) 1 )
|
||||
(begin
|
||||
; Msg to status bar, need not be acknowledged by any user
|
||||
(gimp-message "Received more than one drawable.")
|
||||
; Msg propagated in a GError to Gimp's error dialog that must be acknowledged
|
||||
(write "Received more than one drawable.")
|
||||
; Indicate err to programmed callers
|
||||
#f)
|
||||
#t
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
; v3 >>> no image or drawable declared.
|
||||
; v3 >>> SF-ONE-DRAWABLE means contracts to process only one drawable
|
||||
(script-fu-register-filter "script-fu-clothify-v3"
|
||||
_"_Clothify v3..."
|
||||
_"Add a cloth-like texture to the selected region (or alpha)"
|
||||
"Tim Newsome <drz@froody.bloke.com>"
|
||||
"Tim Newsome"
|
||||
"4/11/97"
|
||||
"RGB* GRAY*"
|
||||
SF-ONE-DRAWABLE
|
||||
SF-ADJUSTMENT _"Blur X" '(9 3 100 1 10 0 1)
|
||||
SF-ADJUSTMENT _"Blur Y" '(9 3 100 1 10 0 1)
|
||||
SF-ADJUSTMENT _"Azimuth" '(135 0 360 1 10 1 0)
|
||||
SF-ADJUSTMENT _"Elevation" '(45 0 90 1 10 1 0)
|
||||
SF-ADJUSTMENT _"Depth" '(3 1 50 1 10 0 1)
|
||||
)
|
||||
|
||||
(script-fu-menu-register "script-fu-clothify-v3"
|
||||
"<Image>/Filters/Artistic")
|
|
@ -53,6 +53,7 @@ scripts = [
|
|||
'waves-anim.scm',
|
||||
'weave.scm',
|
||||
'xach-effect.scm',
|
||||
'clothify-v3.scm'
|
||||
]
|
||||
|
||||
if not stable
|
||||
|
@ -75,6 +76,7 @@ install_data(
|
|||
|
||||
scripts_independent = [
|
||||
{ 'name': 'ts-helloworld' },
|
||||
{ 'name': 'test-sphere-v3' },
|
||||
]
|
||||
|
||||
foreach plugin : scripts_independent
|
||||
|
|
|
@ -22,3 +22,16 @@
|
|||
(- 255 (caddr dest-color-1)) (- 255 (caddr dest-color-2)))
|
||||
(gimp-levels layer HISTOGRAM-VALUE 0 255 1.0 255 0)
|
||||
)
|
||||
|
||||
; since 3.0 a layer selection can be many,
|
||||
; so PDB methods to get selections return an int and a GObjectArray,
|
||||
; which in Scheme is a list containing a numeric and a vector.
|
||||
; and the word "active" changed to "selected".
|
||||
; Formerly, such PDB methods returned a list of one element, the ID of a layer.
|
||||
|
||||
; A compatible replacement for gimp-image-get-active-layer.
|
||||
; This should be used only when you know the image has only one layer.
|
||||
; In other situations, you may break a contract to process all selected layers.
|
||||
(define (gimp-image-get-active-layer img)
|
||||
(list (aref (cadr (gimp-image-get-selected-layers img)) 0))
|
||||
)
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
#!/usr/bin/env gimp-script-fu-interpreter-3.0
|
||||
|
||||
; v3 >>> Has shebang, is interpreter
|
||||
|
||||
; This is a a test script to test Script-Fu parameter API.
|
||||
|
||||
; For GIMP 3: uses GimpImageProcedure, GimpProcedureDialog, GimpConfig
|
||||
|
||||
; See also test-sphere.scm, for GIMP 2, from which this is derived
|
||||
; Diffs marked with ; v3 >>>
|
||||
|
||||
|
||||
; v3 >>> signature of GimpImageProcedure
|
||||
; drawables is a vector
|
||||
(define (script-fu-test-sphere-v3
|
||||
image
|
||||
drawables
|
||||
radius
|
||||
light
|
||||
shadow
|
||||
bg-color
|
||||
sphere-color
|
||||
brush
|
||||
text
|
||||
multi-text
|
||||
pattern
|
||||
gradient
|
||||
gradient-reverse
|
||||
font
|
||||
size
|
||||
unused-palette
|
||||
unused-filename
|
||||
unused-orientation
|
||||
unused-interpolation
|
||||
unused-dirname
|
||||
unused-image
|
||||
unused-layer
|
||||
unused-channel
|
||||
unused-drawable)
|
||||
(let* (
|
||||
(width (* radius 3.75))
|
||||
(height (* radius 2.5))
|
||||
(img (car (gimp-image-new width height RGB)))
|
||||
(drawable (car (gimp-layer-new img width height RGB-IMAGE
|
||||
"Sphere Layer" 100 LAYER-MODE-NORMAL)))
|
||||
(radians (/ (* light *pi*) 180))
|
||||
(cx (/ width 2))
|
||||
(cy (/ height 2))
|
||||
(light-x (+ cx (* radius (* 0.6 (cos radians)))))
|
||||
(light-y (- cy (* radius (* 0.6 (sin radians)))))
|
||||
(light-end-x (+ cx (* radius (cos (+ *pi* radians)))))
|
||||
(light-end-y (- cy (* radius (sin (+ *pi* radians)))))
|
||||
(offset (* radius 0.1))
|
||||
(text-extents (gimp-text-get-extents-fontname multi-text
|
||||
size PIXELS
|
||||
font))
|
||||
(x-position (- cx (/ (car text-extents) 2)))
|
||||
(y-position (- cy (/ (cadr text-extents) 2)))
|
||||
(shadow-w 0)
|
||||
(shadow-x 0)
|
||||
)
|
||||
|
||||
(gimp-context-push)
|
||||
(gimp-context-set-defaults)
|
||||
|
||||
(gimp-image-undo-disable img)
|
||||
(gimp-image-insert-layer img drawable 0 0)
|
||||
(gimp-context-set-foreground sphere-color)
|
||||
(gimp-context-set-background bg-color)
|
||||
(gimp-drawable-edit-fill drawable FILL-BACKGROUND)
|
||||
(gimp-context-set-background '(20 20 20))
|
||||
|
||||
(if (and
|
||||
(or (and (>= light 45) (<= light 75))
|
||||
(and (<= light 135) (>= light 105)))
|
||||
(= shadow TRUE))
|
||||
(let ((shadow-w (* (* radius 2.5) (cos (+ *pi* radians))))
|
||||
(shadow-h (* radius 0.5))
|
||||
(shadow-x cx)
|
||||
(shadow-y (+ cy (* radius 0.65))))
|
||||
(if (< shadow-w 0)
|
||||
(begin (set! shadow-x (+ cx shadow-w))
|
||||
(set! shadow-w (- shadow-w))))
|
||||
|
||||
(gimp-context-set-feather TRUE)
|
||||
(gimp-context-set-feather-radius 7.5 7.5)
|
||||
(gimp-image-select-ellipse img CHANNEL-OP-REPLACE shadow-x shadow-y shadow-w shadow-h)
|
||||
(gimp-context-set-pattern pattern)
|
||||
(gimp-drawable-edit-fill drawable FILL-PATTERN)))
|
||||
|
||||
(gimp-context-set-feather FALSE)
|
||||
(gimp-image-select-ellipse img CHANNEL-OP-REPLACE (- cx radius) (- cy radius)
|
||||
(* 2 radius) (* 2 radius))
|
||||
|
||||
(gimp-context-set-gradient-fg-bg-rgb)
|
||||
(gimp-drawable-edit-gradient-fill drawable
|
||||
GRADIENT-RADIAL offset
|
||||
FALSE 0 0
|
||||
TRUE
|
||||
light-x light-y
|
||||
light-end-x light-end-y)
|
||||
|
||||
(gimp-selection-none img)
|
||||
|
||||
(gimp-image-select-ellipse img CHANNEL-OP-REPLACE 10 10 50 50)
|
||||
|
||||
(gimp-context-set-gradient gradient)
|
||||
(gimp-context-set-gradient-reverse gradient-reverse)
|
||||
(gimp-drawable-edit-gradient-fill drawable
|
||||
GRADIENT-LINEAR offset
|
||||
FALSE 0 0
|
||||
TRUE
|
||||
10 10
|
||||
30 60)
|
||||
|
||||
(gimp-selection-none img)
|
||||
|
||||
(gimp-context-set-foreground '(0 0 0))
|
||||
(gimp-floating-sel-anchor (car (gimp-text-fontname img drawable
|
||||
x-position y-position
|
||||
multi-text
|
||||
0 TRUE
|
||||
size PIXELS
|
||||
font)))
|
||||
|
||||
(gimp-image-undo-enable img)
|
||||
(gimp-display-new img)
|
||||
|
||||
(gimp-context-pop)
|
||||
)
|
||||
)
|
||||
|
||||
; v3 >>> use script-fu-register-filter
|
||||
; v3 >>> menu item is v3, alongside old one
|
||||
; v3 >>> not yet localized
|
||||
|
||||
(script-fu-register-filter "script-fu-test-sphere-v3"
|
||||
"Sphere v3..."
|
||||
"Test script-fu-register-filter and GimpProcedureDialog: needs 2 selected layers."
|
||||
"Spencer Kimball, Sven Neumann"
|
||||
"Spencer Kimball"
|
||||
"1996, 1998"
|
||||
"*" ; image types any
|
||||
SF-TWO-OR-MORE-DRAWABLE ; v3 >>> additional argument
|
||||
SF-ADJUSTMENT "Radius (in pixels)" (list 100 1 5000 1 10 0 SF-SPINNER)
|
||||
SF-ADJUSTMENT "Lighting (degrees)" (list 45 0 360 1 10 1 SF-SLIDER)
|
||||
SF-TOGGLE "Shadow" TRUE
|
||||
SF-COLOR "Background color" "white"
|
||||
SF-COLOR "Sphere color" "red"
|
||||
SF-BRUSH "Brush" '("2. Hardness 100" 100 44 0)
|
||||
SF-STRING "Text" "Tiny-Fu rocks!"
|
||||
SF-TEXT "Multi-line text" "Hello,\nWorld!"
|
||||
SF-PATTERN "Pattern" "Maple Leaves"
|
||||
SF-GRADIENT "Gradient" "Deep Sea"
|
||||
SF-TOGGLE "Gradient reverse" FALSE
|
||||
SF-FONT "Font" "Agate"
|
||||
SF-ADJUSTMENT "Font size (pixels)" '(50 1 1000 1 10 0 1)
|
||||
SF-PALETTE "Palette" "Default"
|
||||
SF-FILENAME "Environment map"
|
||||
(string-append gimp-data-directory
|
||||
"/scripts/images/beavis.jpg")
|
||||
SF-OPTION "Orientation" '("Horizontal"
|
||||
"Vertical")
|
||||
SF-ENUM "Interpolation" '("InterpolationType" "linear")
|
||||
SF-DIRNAME "Output directory" "/var/tmp/"
|
||||
SF-IMAGE "Image" -1
|
||||
SF-LAYER "Layer" -1
|
||||
SF-CHANNEL "Channel" -1
|
||||
SF-DRAWABLE "Drawable" -1
|
||||
SF-VECTORS "Vectors" -1
|
||||
)
|
||||
|
||||
(script-fu-menu-register "script-fu-test-sphere-v3"
|
||||
"<Image>/Filters/Development/Script-Fu/Test")
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env gimp-script-fu-interpreter-3.0
|
||||
|
||||
; A script that always fails
|
||||
;
|
||||
; Setup: copy this file w/ executable permission, and its parent dir to /plug-ins
|
||||
; Example: to ~/.gimp-2.99/plug-ins/always-fail/always-fail.scm
|
||||
|
||||
; Expect "Test>Always fail" in the menus
|
||||
; Expect when chosen, message on GIMP message bar "Failing"
|
||||
; Expect a dialog in GIMP app that requires an OK
|
||||
|
||||
(define (script-fu-always-fail)
|
||||
(begin
|
||||
(gimp-message "Failing")
|
||||
; since last expression, the result, and should mean error
|
||||
#f
|
||||
)
|
||||
)
|
||||
|
||||
(script-fu-register "script-fu-always-fail"
|
||||
"Always fail"
|
||||
_"Expect error dialog in Gimp, or PDB execution error when called by another"
|
||||
"lkk"
|
||||
"lkk"
|
||||
"2022"
|
||||
"" ; requires no image
|
||||
; no arguments or dialog
|
||||
)
|
||||
|
||||
(script-fu-menu-register "script-fu-always-fail" "<Image>/Test")
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env gimp-script-fu-interpreter-3.0
|
||||
|
||||
; A script that calls a script that always fails
|
||||
;
|
||||
; Setup: copy this file w/ executable permission, and its parent dir to /plug-ins
|
||||
; Example: to ~/.gimp-2.99/plug-ins/always-fail/always-fail.scm
|
||||
|
||||
; Expect "Test>Call always fail" in the menus
|
||||
; Expect when chosen, message on GIMP message bar "Failing" (from script-fu-always-fail)
|
||||
; Expect a dialog in GIMP app that requires an OK
|
||||
|
||||
(define (script-fu-call-always-fail)
|
||||
; call a script that always fails
|
||||
(script-fu-always-fail)
|
||||
; we have not checked the result and declaring the error on our own.
|
||||
; since this is the last expression, the #f from the call should propogate.
|
||||
)
|
||||
|
||||
(script-fu-register "script-fu-call-always-fail"
|
||||
"Call always fail"
|
||||
_"Expect error dialog in Gimp, having concatenated error messages"
|
||||
"lkk"
|
||||
"lkk"
|
||||
"2022"
|
||||
"" ; requires no image
|
||||
; no arguments or dialog
|
||||
)
|
||||
|
||||
(script-fu-menu-register "script-fu-call-always-fail" "<Image>/Test")
|
|
@ -54,6 +54,7 @@ plug-ins/script-fu/scripts/test/test1/test3.scm
|
|||
plug-ins/script-fu/scripts/test/test4/test4.scm
|
||||
plug-ins/script-fu/scripts/test/test7/test7.scm
|
||||
plug-ins/script-fu/scripts/test/test8/test8.scm
|
||||
plug-ins/script-fu/scripts/clothify-v3.scm
|
||||
plug-ins/selection-to-path
|
||||
plug-ins/twain
|
||||
plug-ins/ui
|
||||
|
|
Loading…
Reference in New Issue