mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-04 01:43:24 +00:00
devel-docs: delete ScriptFu docs
After moved to gimp-web-devel repo.
This commit is contained in:
parent
0db5f7dd72
commit
cb4687633c
6 changed files with 0 additions and 1738 deletions
|
@ -1,160 +0,0 @@
|
||||||
PDB-compatability
|
|
||||||
|
|
||||||
# Programmers Reference: PDB procedures for compatabililty
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
The audience is GIMP maintainers.
|
|
||||||
|
|
||||||
This discusses procedures for compatability in the PDB and ScriptFu.
|
|
||||||
A procedure for compatability is:
|
|
||||||
|
|
||||||
* deprecated
|
|
||||||
* OR a wrapper for a plugin now in GEGL
|
|
||||||
|
|
||||||
## What
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
A deprecated procedure is one provided for backward compatibility.
|
|
||||||
Older plugins calling a deprecated procedure still work.
|
|
||||||
Plugin authors should not use deprecated procedures in new plugin code.
|
|
||||||
In the future, gimp.org may obsolete i.e. delete the procedures.
|
|
||||||
Thus breaking any existing plugins still using the procedures.
|
|
||||||
|
|
||||||
A deprecated procedure can for:
|
|
||||||
|
|
||||||
* a renaming, to correct a naming mistake
|
|
||||||
and thereby conform to naming conventions
|
|
||||||
|
|
||||||
* an adaptor, having a signature different from a new signature.
|
|
||||||
For example, to accomodate the "multi-layer select" feature,
|
|
||||||
a new signature takes a container of layers,
|
|
||||||
and a deprecated signature takes a single layer and adapts.
|
|
||||||
|
|
||||||
### Wrappers for GEGL
|
|
||||||
|
|
||||||
These are wrappers/adaptors.
|
|
||||||
In early GIMP 2, the procedures were C plugins in GIMP.
|
|
||||||
Now (since about GIMP 2.8) they are C plugins in GEGL
|
|
||||||
and a wrapper/adaptor delegates to GEGL.
|
|
||||||
|
|
||||||
These are NOT planned for obsolescence.
|
|
||||||
|
|
||||||
Most GEGL plugins are wrapped.
|
|
||||||
A few are not.
|
|
||||||
Occasionally, new GEGL plugins are mistakenly not wrapped in GIMP.
|
|
||||||
|
|
||||||
A plugin in an introspected language can avoid a wrapper
|
|
||||||
by creating a GEGL node and calling GEGL directly.
|
|
||||||
(That is the recourse when there is no wrapper for a GEGL plugin.)
|
|
||||||
|
|
||||||
## Categories of deprecation and wrapping
|
|
||||||
|
|
||||||
1. Aliases for renamed procedures:
|
|
||||||
these are not separate procedures,
|
|
||||||
just alternate names pointing to another procedure
|
|
||||||
|
|
||||||
2. True deprecated procedures:
|
|
||||||
these are separately defined procedures
|
|
||||||
|
|
||||||
3. ScriptFu deprecated procedures:
|
|
||||||
separately defined procedures or aliases, in the Scheme language
|
|
||||||
|
|
||||||
4. GEGL wrappers:
|
|
||||||
separately defined procedures that wrap GEGL plugin filters
|
|
||||||
|
|
||||||
## GUI: how the PDB Browser shows deprecated and wrapped PDB procedures
|
|
||||||
|
|
||||||
This describes how a plugin author may know what procedures are deprecated or wrappers.
|
|
||||||
|
|
||||||
The PDB Browser inconsistently shows this information.
|
|
||||||
|
|
||||||
1. Aliases for renamed procedures:
|
|
||||||
the PDB browser does not reveal this at all.
|
|
||||||
|
|
||||||
2. True deprecated procedures:
|
|
||||||
the PDB browser indicates they are deprecated in the "blurb" field.
|
|
||||||
|
|
||||||
3. ScriptFu deprecated procedures:
|
|
||||||
the PDB browser doesn't show these,
|
|
||||||
since they are Scheme procedures not PDB procedures.
|
|
||||||
|
|
||||||
4. GEGL wrappers:
|
|
||||||
the PDB browser indicates they are GEGL wrappers in the "author" field.
|
|
||||||
|
|
||||||
## Implementation
|
|
||||||
|
|
||||||
This describes how deprecation and wrappers are implemented.
|
|
||||||
|
|
||||||
Read this if you are a maintainer and you want to deprecate a procedure
|
|
||||||
or obsolete a deprecated procedure.
|
|
||||||
|
|
||||||
### Aliased deprecated procedures
|
|
||||||
|
|
||||||
The GIMP core implementation of the PDB has an aliasing mechanism.
|
|
||||||
Declared in app/pdb/gimp-pdb-compat.c.
|
|
||||||
The code enters an alias name in the hash table of PDB procedure names, pointing to the same procedure as another name.
|
|
||||||
The name usually starts with "gimp-".
|
|
||||||
|
|
||||||
ScriptFu has its own aliasing mechanism.
|
|
||||||
ScriptFu has its own mechanism so its can deprecate even after
|
|
||||||
the core PDB has obsoleted a name.
|
|
||||||
Declared in plug-ins/script-fu/libscriptfu/script-fu-compat.c.
|
|
||||||
The name usually starts with "gimp-".
|
|
||||||
|
|
||||||
### True deprecated procedures
|
|
||||||
|
|
||||||
Defined in in pdb/groups/foo.pdb using the "std_pdb_deprecated" tag.
|
|
||||||
The name usually starts with "gimp-".
|
|
||||||
|
|
||||||
These also generate deprecated functions in libgimp.
|
|
||||||
|
|
||||||
### ScriptFu deprecated
|
|
||||||
|
|
||||||
ScriptFu provides some compatibility on top of "true deprecated procedures"
|
|
||||||
|
|
||||||
1. Defined in the latter half of plug-ins/script-fu/scripts/script-fu-compat.init.
|
|
||||||
Adaptors for Scheme functions present in the SIOD dialect of Scheme.
|
|
||||||
That dialect was used in early GIMP ScriptFu.
|
|
||||||
This provides backward compatibility for some older ScriptFu scripts.
|
|
||||||
|
|
||||||
2. Defined in plug-ins/script-fu/scripts/plug-in-compat.init.
|
|
||||||
Adaptors for PDB procedures present in earlier GIMP 2.
|
|
||||||
For example, at one time "plug-in-color-map"
|
|
||||||
and "gimp-image-get-active-layer" were defined in ScriptFu
|
|
||||||
(but not elsewhere) for compatibility.
|
|
||||||
|
|
||||||
The names can start with "gimp-" or "plug-in" or just be from some Scheme language dialect.
|
|
||||||
|
|
||||||
### GEGL wrappers
|
|
||||||
|
|
||||||
Defined in pdb/groups/plug_in_compat.pdb.
|
|
||||||
|
|
||||||
!!! These do not generate functions in libgimp.
|
|
||||||
A C plugin or plugin in an introspected language
|
|
||||||
must call GEGL directly,
|
|
||||||
or call the wrapping PDB procedure.
|
|
||||||
|
|
||||||
The names start with "plug-in-".
|
|
||||||
|
|
||||||
## Process for deprecation, and status
|
|
||||||
|
|
||||||
At a major release,
|
|
||||||
gimp.org might obsolete formerly deprecated procedures.
|
|
||||||
This breaks API (for the PDB and libgimp.)
|
|
||||||
|
|
||||||
API is not usually broken for a minor release.
|
|
||||||
Deprecated procedures are sometimes added, but not removed,
|
|
||||||
for a minor release.
|
|
||||||
|
|
||||||
As of the time of this writing (GIMP 3.0) there are:
|
|
||||||
|
|
||||||
* no aliased procedures
|
|
||||||
* no true deprecated procedures
|
|
||||||
* no ScriptFu deprecated procedures for SIOD dialect or older PDB
|
|
||||||
|
|
||||||
The mechanisms for deprecation (the implementation as described above)
|
|
||||||
is still in place.
|
|
||||||
|
|
||||||
|
|
|
@ -1,175 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
## About this document
|
|
||||||
|
|
||||||
This describes *some* changes needed to port a Scriptfu script to GIMP 3:
|
|
||||||
- changes in types
|
|
||||||
- changes in PDB signatures for multi-layer support
|
|
||||||
- changes in error messages
|
|
||||||
- changes in logging
|
|
||||||
|
|
||||||
It does *not* document:
|
|
||||||
- PDB procedures whose names have changed (see pdb-calls.md)
|
|
||||||
- PDB procedures that have been removed (see removed_functions.md)
|
|
||||||
- PDB procedures that have been added
|
|
||||||
- other changes in signature where arguments are reordered or changed in number
|
|
||||||
|
|
||||||
## Changes in types of PDB signatures
|
|
||||||
|
|
||||||
Calls from a script to GIMP are calls to PDB procedures.
|
|
||||||
PDB procedures are documented in terms of C and GLib types.
|
|
||||||
|
|
||||||
This table summarizes the changes:
|
|
||||||
|
|
||||||
| Purpose | Old C type | New C type | Old Scheme type | New Scheme type |
|
|
||||||
| ---------------|-----------------------|-----------------------| ----------------|-----------------------|
|
|
||||||
| Pass file name | gchar*, gchar* | GFile | string string | string |
|
|
||||||
| Recv file name | gchar* | GFile | string | string |
|
|
||||||
| pass drawable | GimpDrawable | gint, GimpObjectArray | int (an ID) | int (a length) vector |
|
|
||||||
| Pass obj array | gint, GimpInt32Array | gint, GimpObjectArray | int vector | int vector |
|
|
||||||
| Recv obj array | gint, GimpInt32Array | gint, GimpObjectArray | int vector | int vector |
|
|
||||||
| Pass set of str | gint, GimpStringArray | GStrv | int list | list |
|
|
||||||
| Recv set of str | gint, GimpStringArray | GStrv | int list | list |
|
|
||||||
|
|
||||||
(Where "obj" means an object of a GIMP type such as GimpDrawable or similar.)
|
|
||||||
|
|
||||||
### Use one string for a filename instead of two.
|
|
||||||
|
|
||||||
Formerly a PDB procedure taking a filename (usually a full path) required two strings (two gchar* .)
|
|
||||||
Now such PDB procedures require a GFile.
|
|
||||||
|
|
||||||
In Scheme, where formerly you passed two strings, now pass one string.
|
|
||||||
|
|
||||||
Formerly a script passed the second string for a URI, to specify a remote file.
|
|
||||||
Formerly, in most cases you passed an empty second string.
|
|
||||||
Now, the single string in a script can be either a local file path or a remote URI.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
(gimp-file-load RUN-NONINTERACTIVE "/tmp/foo" "")
|
|
||||||
=> (gimp-file-load RUN-NONINTERACTIVE "/tmp/foo")
|
|
||||||
|
|
||||||
|
|
||||||
### PDB procedures still return a string for a filename
|
|
||||||
|
|
||||||
All PDB procedures returning a filename return a single string to Scheme scripts.
|
|
||||||
That is unchanged.
|
|
||||||
|
|
||||||
Formerly a PDB signature for a procedure returning a filename
|
|
||||||
specifies a returned type gchar*, but now specifies a returned type GFile.
|
|
||||||
But a Scheme script continues to receive a string.
|
|
||||||
|
|
||||||
The returned string is either a local file path or a URI.
|
|
||||||
|
|
||||||
|
|
||||||
### Use a vector of drawables for PDB procedures that now take an array of drawables
|
|
||||||
|
|
||||||
Formerly, some PDB procedures took a single GimpDrawable,
|
|
||||||
but now they take an array of GimpDrawable ( type GimpObjectArray.)
|
|
||||||
(Formerly, no PDB procedure took an array of drawables.
|
|
||||||
Some that formerly took a single drawable still take a single drawable.
|
|
||||||
See the list below. )
|
|
||||||
|
|
||||||
For such PDB procedures, in Scheme pass a numeric length and a vector of numeric drawable ID's.
|
|
||||||
|
|
||||||
These changes support a user selecting multiple layers for an operation.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
(gimp-edit-copy drawable) => (gimp-edit-copy 1 (vector drawable))
|
|
||||||
|
|
||||||
(gimp-edit-copy 2) => (gimp-edit-copy 1 '#(2))
|
|
||||||
|
|
||||||
### The PDB procedures which formerly took single Drawable and now take GimpObjectArray
|
|
||||||
|
|
||||||
- Many of the file load/save procedures.
|
|
||||||
- gimp-color-picker
|
|
||||||
- gimp-edit-copy
|
|
||||||
- gimp-edit-cut
|
|
||||||
- gimp-edit-named-copy
|
|
||||||
- gimp-edit-named-cut
|
|
||||||
- gimp-file-save
|
|
||||||
- gimp-image-pick-color
|
|
||||||
- gimp-selection-float
|
|
||||||
- gimp-xcf-save
|
|
||||||
|
|
||||||
|
|
||||||
### Receiving an array of drawables
|
|
||||||
|
|
||||||
Formerly a PDB procedure returning an array of drawables (or other GIMP objects)
|
|
||||||
had a signature specifying a returned gint and GimpInt32Array.
|
|
||||||
Now the signature specifies a returned gint and GimpObjectArray.
|
|
||||||
A script receives an int and a vector.
|
|
||||||
The elements of the vector are numeric ID's,
|
|
||||||
but are opaque to scripts
|
|
||||||
(a script can pass them around, but should not for example use arithmetic on them.)
|
|
||||||
|
|
||||||
No changes are needed to a script.
|
|
||||||
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
(gimp-image-get-layers image)
|
|
||||||
|
|
||||||
Will return a list whose first element is a length,
|
|
||||||
and whose second element is a vector of drawables (Scheme numerics for drawable ID's)
|
|
||||||
|
|
||||||
In the ScriptFu console,
|
|
||||||
|
|
||||||
(gimp-image-get-layers (car (gimp-image-new 10 30 1)))
|
|
||||||
|
|
||||||
would print:
|
|
||||||
|
|
||||||
(0 #())
|
|
||||||
|
|
||||||
Meaning a list length of zero, and an empty vector.
|
|
||||||
(Since a new image has no layers.)
|
|
||||||
|
|
||||||
### Passing or receiving a set of strings
|
|
||||||
|
|
||||||
Formerly, you passed an integer count of strings, and a list of strings.
|
|
||||||
Now you only pass the list.
|
|
||||||
ScriptFu converts to/from the C type GStrv
|
|
||||||
(which is an object knowing its own length.)
|
|
||||||
An example is the PDB procedure file-gih-export.
|
|
||||||
|
|
||||||
Formerly, you received an integer count of strings, and a list of strings.
|
|
||||||
Now you only receive the list
|
|
||||||
(and subsequently get its length using "(length list)").
|
|
||||||
Examples are the many PDB procedures whose name ends in "-list".
|
|
||||||
Remember that the result of a call to the PDB is a list of values,
|
|
||||||
in this case the result is a list containing a list,
|
|
||||||
and for example you get the list of strings like "(car (gimp-fonts-get-list ".*"))"
|
|
||||||
|
|
||||||
## Changes in error messages
|
|
||||||
|
|
||||||
ScriptFu is now more forgiving.
|
|
||||||
|
|
||||||
Formerly, ScriptFu would not accept a call construct where the argument count was wrong,
|
|
||||||
except for the case when you provided one argument to a PDB procedure
|
|
||||||
that took zero arguments (sometimes called a nullary function.)
|
|
||||||
|
|
||||||
Now, when a script has the wrong count of arguments to a PDB procedure:
|
|
||||||
|
|
||||||
- too many actual arguments: ScriptFu will give a warning to the console
|
|
||||||
and call the PDB procedure with a prefix of the actual arguments.
|
|
||||||
This is now true no matter how many arguments the PDB procedure takes.
|
|
||||||
Extra arguments in the script are ignored by Scriptfu,
|
|
||||||
not evaluated and not passed to the PDB.
|
|
||||||
|
|
||||||
- too few actual arguments: ScriptFu will give a warning to the console
|
|
||||||
and call the PDB procedure with the given actual arguments.
|
|
||||||
The warning will say the expected Scheme formal type of the first missing actual argument.
|
|
||||||
Usually the PDB procedure will fail and return its own error message.
|
|
||||||
|
|
||||||
When you suspect errors in a script,
|
|
||||||
it is now important to run GIMP from a console to see warnings.
|
|
||||||
|
|
||||||
|
|
||||||
## ScriptFu logging
|
|
||||||
|
|
||||||
ScriptFu now does some logging using GLib logging.
|
|
||||||
When you define in the environment "G_MESSAGES_DEBUG=scriptfu"
|
|
||||||
ScriptFu will print many messages to the console.
|
|
||||||
|
|
||||||
This is mostly useful for GIMP developers.
|
|
|
@ -1,625 +0,0 @@
|
||||||
# Guide to changes to ScriptFu v3 for script authors
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
The audience is authors of Scriptfu plugins.
|
|
||||||
This discusses how to edit v2 scripts so they will run in GIMP 3.
|
|
||||||
It also discusses enhancements to ScriptFu and its language.
|
|
||||||
|
|
||||||
## Quickstart
|
|
||||||
|
|
||||||
A lucky few existing scripts may work in GIMP v3 without change.
|
|
||||||
|
|
||||||
### Required changes
|
|
||||||
|
|
||||||
Some changes are *required* in existing plugins:
|
|
||||||
|
|
||||||
- many PDB procedures are obsolete or renamed, or their signature changed
|
|
||||||
- the symbol SF-VALUE is obolete
|
|
||||||
|
|
||||||
Once you edit a script for these changes, the script won't work in GIMP v2.
|
|
||||||
|
|
||||||
Most scripts will require edits due to changed PDB API.
|
|
||||||
|
|
||||||
### Optional changes
|
|
||||||
|
|
||||||
Other changes to scripts are *optional*.
|
|
||||||
Such changes use improved features of ScriptFu.
|
|
||||||
|
|
||||||
In approximate order of importance:
|
|
||||||
|
|
||||||
- you can install scripts like plugins in other languages
|
|
||||||
- you can use new, specific registration functions instead of the generic script-fu-register
|
|
||||||
- scripts can use the new mult-layer selection feature of GIMP
|
|
||||||
- scripts can use a v3 dialect having more natural binding of return values from PDB calls
|
|
||||||
- the symbolic constants TRUE and FALSE are deprecated, except for SF-TOGGLE
|
|
||||||
- a script can *quit* with an error code
|
|
||||||
- a script can call *display* to print to the terminal
|
|
||||||
|
|
||||||
Enhancements to ScriptFu might not affect an existing plugin.
|
|
||||||
You need only understand those enhancements when you want to use them.
|
|
||||||
|
|
||||||
### Why these changes now?
|
|
||||||
|
|
||||||
GIMP 3 is a major version change with new features.
|
|
||||||
A major version allows breaking API,
|
|
||||||
meaning old plugins and scripts might not work.
|
|
||||||
|
|
||||||
The GIMP developers understand these changes may be onerous.
|
|
||||||
Script developers might need to maintain two different versions of their scripts.
|
|
||||||
Some users will stick with GIMP 2 for a while and some will switch to GIMP 3.
|
|
||||||
|
|
||||||
A major version is necessary to move forward.
|
|
||||||
The situation is similar to the disruption caused by the move from Python 2 to 3.
|
|
||||||
|
|
||||||
## Changed PDB API
|
|
||||||
|
|
||||||
*You must edit your scripts to conform to version 3 of the PDB API.*
|
|
||||||
|
|
||||||
The GIMP PDB (Programmers Data Base), that you can call in scripts, has changed in GIMP version 3.
|
|
||||||
That also may require you to edit scripts.
|
|
||||||
|
|
||||||
- For changes in signatures of PDB procedures,
|
|
||||||
see devel-docs/GIMP3-plug-in-porting-guide/porting_scriptfu_scripts.md
|
|
||||||
- For added, removed, and replaced PDB procedures,
|
|
||||||
see devel-docs/GIMP3-plug-in-porting-guide/removed_functions.md
|
|
||||||
|
|
||||||
Some of the changes are for the multi-layer select feature of GIMP 3.
|
|
||||||
Many PDB procedures now take a container (a Scheme vector) of drawables
|
|
||||||
instead of a single drawable.
|
|
||||||
|
|
||||||
## SF-VALUE type of argument is obsolete
|
|
||||||
|
|
||||||
*You must edit v2 scripts and replace the symbol SF-VALUE.*
|
|
||||||
|
|
||||||
In v2, SF-VALUE declared a formal argument that is an unquoted, arbitrary string.
|
|
||||||
Usually, SF-VALUE was used for an integer valued argument.
|
|
||||||
In the dialog for a script, ScriptFu showed a text entry widget.
|
|
||||||
Usually the widget showed a default integer literal,
|
|
||||||
but the widget let you enter any text into the string.
|
|
||||||
|
|
||||||
You usually will replace it with an SF-ADJUSTMENT kind of formal argument,
|
|
||||||
where the "digits" field of the SF-ADJUSTMENT is 0,
|
|
||||||
meaning no decimal places, i.e. integer valued.
|
|
||||||
You must also provide other fields, e.g. the lower and upper limits.
|
|
||||||
|
|
||||||
A script that has SF-VALUE replaced with SF-ADJUSTMENT
|
|
||||||
will remain compatible with GIMP 2.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
SF-VALUE "Font size" "50"
|
|
||||||
=>
|
|
||||||
SF-ADJUSTMENT "Font size" '(50 1 1000 1 10 0 SF-SPINNER)
|
|
||||||
|
|
||||||
Here, in the seven-tuple, the 0 denotes: no decimal places.
|
|
||||||
|
|
||||||
Another example, where you formerly
|
|
||||||
used SF-VALUE to declare a formal argument that is float valued:
|
|
||||||
|
|
||||||
SF-VALUE "Lighting (degrees)" "45.0"
|
|
||||||
=>
|
|
||||||
SF-ADJUSTMENT "Lighting (degrees)" '(45.0 0 360 5 10 1 SF-SLIDER)
|
|
||||||
|
|
||||||
Here, the 1 denotes: show 1 decimal place, for example "45.0",
|
|
||||||
in the dialog widget.
|
|
||||||
|
|
||||||
### Use SF-STRING for some use cases
|
|
||||||
|
|
||||||
In v2, a SF-VALUE argument let a user enter executable Scheme code,
|
|
||||||
say "'(1 g 1)", which is a list literal,
|
|
||||||
to be injected into a Scheme call to a plugin.
|
|
||||||
That use is no longer possible.
|
|
||||||
If you must do that, use SF_STRING to get a string,
|
|
||||||
and then your plugin can eval the string.
|
|
||||||
|
|
||||||
### Arbitrary precision floats
|
|
||||||
|
|
||||||
In v2, a SF-VALUE argument let a user enter a float with arbitrary precision,
|
|
||||||
e.g. "0.00000001"
|
|
||||||
|
|
||||||
That is no longer possible. You as a script author must use SF-ADJUSTMENT
|
|
||||||
and specify the maximum precision that makes sense. The user won't be able to
|
|
||||||
enter a value with more precision (more digits after the decimal point.)
|
|
||||||
You should understand the math of your algorithm and know what precision
|
|
||||||
is excess in terms of visible results.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
SF-ADJUSTMENT "Lighting (degrees)" '(45.0 0 360 5 10 4 SF-SLIDER)
|
|
||||||
|
|
||||||
Here, the user will only be able to enter four decimal places,
|
|
||||||
for example by typing "0.0001" into the widget.
|
|
||||||
|
|
||||||
If you actually need arbitrary precision, use SF_STRING to get a string,
|
|
||||||
and then your plugin can eval the string to get a Scheme numeric
|
|
||||||
of the maximum precision that Scheme supports.
|
|
||||||
|
|
||||||
### Rationale
|
|
||||||
|
|
||||||
Formerly, a SF-VALUE argument let a user enter garbage for an argument,
|
|
||||||
which caused an error in the script.
|
|
||||||
SF-ADJUSTMENT or SF-STRING is more user-friendly.
|
|
||||||
|
|
||||||
## You can optionally install scripts like plugins in other languages
|
|
||||||
|
|
||||||
*We recommend this for new plugins.*
|
|
||||||
|
|
||||||
In v3 you can install ScriptFu scripts to a /plug-ins directory,
|
|
||||||
like plugins in other languages.
|
|
||||||
This helps isolate plugins.
|
|
||||||
|
|
||||||
You must edit the script to include a shebang in the first line:
|
|
||||||
|
|
||||||
#!/usr/bin/env gimp-script-fu-interpreter-3.0
|
|
||||||
;!# Close comment started on first line.
|
|
||||||
|
|
||||||
If the script has translatable strings, it should also have a second line
|
|
||||||
as above, to accomodate parsing by gettext.
|
|
||||||
(Note that ScriptFu doesn't actually support multi-line comments using #!,
|
|
||||||
and this is a trick to fool gettext, which parses a script as if
|
|
||||||
it did support multi-line comments.)
|
|
||||||
|
|
||||||
|
|
||||||
In v2 all ScriptFu scripts were installed in a /scripts directory.
|
|
||||||
In v3 you may install ScriptFu scripts with a shebang
|
|
||||||
in a subdirectory of a /plug-ins directory.
|
|
||||||
|
|
||||||
Installation of scripts with a shebang must follow rules for interpreted plugins.
|
|
||||||
A script file must:
|
|
||||||
|
|
||||||
- have a shebang on the first line
|
|
||||||
- be in a directory having the same base name
|
|
||||||
- have executable permission
|
|
||||||
- have a file suffix corresponding to an interpreter
|
|
||||||
|
|
||||||
An example path to a script:
|
|
||||||
|
|
||||||
~/.config/GIMP/2.99/plug-ins/script-fu-my/script-fu-my.scm
|
|
||||||
|
|
||||||
The advantage of installing a script in the /plug-ins directory is that
|
|
||||||
such a script will execute in its own process.
|
|
||||||
If it crashes, it doesn't affect GIMP or other scripts.
|
|
||||||
|
|
||||||
Conversely, in v2, all scripts in the /scripts directory
|
|
||||||
are executed by the long-lived process "extension-script-fu."
|
|
||||||
If one of those scripts crash, menu items implemented by ScriptFu dissappear
|
|
||||||
from the GIMP app, and you should restart GIMP.
|
|
||||||
|
|
||||||
It is only a convention to name scripts starting with "script-fu-".
|
|
||||||
|
|
||||||
## Using new registration functions
|
|
||||||
|
|
||||||
*We recommend this.*
|
|
||||||
|
|
||||||
New registration functions let a plugin dialog have a new look-and-feel
|
|
||||||
and improved settings.
|
|
||||||
ScriptFu "registration" functions let you declare a plugin PDB procedure,
|
|
||||||
and how it's dialog will look.
|
|
||||||
|
|
||||||
ScriptFu v3 has two new registration functions:
|
|
||||||
|
|
||||||
* *script-fu-register-procedure*
|
|
||||||
* *script-fu-register-filter*
|
|
||||||
|
|
||||||
Terminology: you *declare* a plugin's attributes and signature using a registration function.
|
|
||||||
You *define* a run func with a similar signature.
|
|
||||||
ScriptFu *registers* the plugin in the PDB.
|
|
||||||
|
|
||||||
ScriptFu v2 has only *script-fu-register*.
|
|
||||||
It is a generic function used to declare procedures that are either:
|
|
||||||
|
|
||||||
* generic procedures (operating without an image.)
|
|
||||||
* filters/renderers (operating on an image)
|
|
||||||
|
|
||||||
### Registration function *script-fu-register* is now deprecated.
|
|
||||||
|
|
||||||
**You should not use script-fu-register in new ScriptFu scripts.**
|
|
||||||
|
|
||||||
In the future, the GIMP project might obsolete *script-fu-register*.
|
|
||||||
|
|
||||||
While deprecated, *script-fu-register* should still work.
|
|
||||||
But the plugin dialog will:
|
|
||||||
|
|
||||||
* have an old look-and-feel.
|
|
||||||
* will be missing some advantages, such as the handling of settings.
|
|
||||||
|
|
||||||
Also, using *script-fu-register*,
|
|
||||||
you can only declare a plugin taking one drawable (i.e. layer or mask).
|
|
||||||
But GIMP v3 now calls such plugins passing a vector of drawables.
|
|
||||||
GIMP v2 called such plugins passing one drawable.
|
|
||||||
That is, the declared and actual signatures are incongruous.
|
|
||||||
GIMP enables the menu item for such deprecated scripts,
|
|
||||||
declared to take an image and drawable,
|
|
||||||
whenever a user selects at least one drawable.
|
|
||||||
|
|
||||||
### Improved Settings for ScriptFu plugins
|
|
||||||
|
|
||||||
GIMP 3 now handles plugin settings better.
|
|
||||||
(Using more powerful machinery in GIMP that is common to plugins in all languages,
|
|
||||||
not by limited machinery in ScriptFu that is specific to Scheme language plugins.)
|
|
||||||
|
|
||||||
Scripts declared with new registration functions have settings that persist
|
|
||||||
within and between Gimp sessions.
|
|
||||||
That is, the next time a user invokes the script,
|
|
||||||
the dialog will show the same settings as the last time they chose the filter.
|
|
||||||
This is not true for v2 *script-fu-register*,
|
|
||||||
where settings persist only during a GIMP session.
|
|
||||||
|
|
||||||
The dialog for a script declared with the new registration functions
|
|
||||||
will also have buttons for resetting to initial or factory values of settings,
|
|
||||||
and buttons for saving and restoring a set of settings, by name.
|
|
||||||
|
|
||||||
### script-fu-register-procedure
|
|
||||||
|
|
||||||
Use *script-fu-register-procedure* to declare PDB procedures that are not filters
|
|
||||||
or renderers.
|
|
||||||
"Procedure" denotes the general case.
|
|
||||||
Plugins that are filters or renerers,
|
|
||||||
taking an image and drawables, are special
|
|
||||||
and you instead declare them using *script-fu-register-filter.*
|
|
||||||
|
|
||||||
*Script-fu-register-filter* declares a script that:
|
|
||||||
|
|
||||||
* is always enabled
|
|
||||||
* can save its settings between sessions
|
|
||||||
|
|
||||||
You don't declare "image types"
|
|
||||||
as you do with *script-fu-register*.
|
|
||||||
GIMP enables your plugin regardless of the mode of any image a user has selected.
|
|
||||||
|
|
||||||
You don't declare "multilayer capability"
|
|
||||||
as you do with *script-fu-register-filter*.
|
|
||||||
Your plugin doesn't necessarily need an image and drawables.
|
|
||||||
(On your behalf, ScriptFu declares to the PDB that it requires no drawables.)
|
|
||||||
|
|
||||||
The run func that you define in your script has the same signature
|
|
||||||
as you declare in the registration function.
|
|
||||||
(The registration functaion also declares the procedure signature in the PDB,
|
|
||||||
and it will be similar, but in terms of the C language
|
|
||||||
and having an extra argument for run-mode.
|
|
||||||
As in ScriptFu v2, and unlike plugins in other languages,
|
|
||||||
the run-mode argument is hidden by ScriptFu.)
|
|
||||||
|
|
||||||
#### Example
|
|
||||||
|
|
||||||
Here is an abbreviated example:
|
|
||||||
|
|
||||||
(define script-fu-my-plugin (radius)
|
|
||||||
body)
|
|
||||||
|
|
||||||
(script-fu-register-procedure "script-fu-my-plugin"
|
|
||||||
"My plugin..."
|
|
||||||
"Example plugin."
|
|
||||||
"author/copyright holder"
|
|
||||||
"copyright dates"
|
|
||||||
SF-ADJUSTMENT "Radius" (list 100 1 5000 1 10 0 SF-SPINNER)
|
|
||||||
)
|
|
||||||
|
|
||||||
#### Another example: plugins using the context
|
|
||||||
|
|
||||||
A plugin may define a menu item appearing in a context menu.
|
|
||||||
This is a common use case for *script-fu-register-procedure*.
|
|
||||||
The context is the set of choices in GIMP that affect drawing operations,
|
|
||||||
for example, the current Brush.
|
|
||||||
|
|
||||||
Note that the plugin does *NOT* receive the choice in context
|
|
||||||
but must get it from the context before operating with/on it.
|
|
||||||
|
|
||||||
Using the same registration as above:
|
|
||||||
|
|
||||||
(define script-fu-my-plugin (radius)
|
|
||||||
; do something with the current brush
|
|
||||||
(gimp-context-get-brush))
|
|
||||||
|
|
||||||
(script-fu-register-procedure "script-fu-my-brush-plugin"
|
|
||||||
...same registration as above...)
|
|
||||||
|
|
||||||
(script-fu-menu-register "script-fu-my-brush-plugin"
|
|
||||||
"<Brushes>/Brushes Menu")
|
|
||||||
|
|
||||||
In this example, the menu item "My plugin..."
|
|
||||||
appears in the context menu (pops up with right mouse button)
|
|
||||||
in the *Brushes* dockable window,
|
|
||||||
and is always enabled.
|
|
||||||
The script run func gets the current brush
|
|
||||||
and does something to or with it.
|
|
||||||
|
|
||||||
#### Another example: plugin using an unopened file
|
|
||||||
|
|
||||||
A plugin may want to use a file that is *not open as an image.*
|
|
||||||
|
|
||||||
(define script-fu-my-plugin (filename)
|
|
||||||
; open and do something with the file
|
|
||||||
)
|
|
||||||
|
|
||||||
(script-fu-register-procedure "script-fu-my-plugin"
|
|
||||||
"My plugin..."
|
|
||||||
"Example plugin."
|
|
||||||
"author/copyright holder"
|
|
||||||
"copyright dates"
|
|
||||||
SF-FILENAME "Image to do something with" ""
|
|
||||||
)
|
|
||||||
|
|
||||||
(script-fu-menu-register "script-fu-my-plugin"
|
|
||||||
"<Image>/File")
|
|
||||||
|
|
||||||
In this example, the menu item *My plugin...*
|
|
||||||
appears in the *File* menu on the menubar.
|
|
||||||
It is always enabled.
|
|
||||||
|
|
||||||
When a user chooses the menu item,
|
|
||||||
a dialog appears that lets a user choose a file.
|
|
||||||
When the user clicks *OK*,
|
|
||||||
the plugin opens the file and does something with it.
|
|
||||||
|
|
||||||
### script-fu-register-filter
|
|
||||||
|
|
||||||
Use *script-fu-register-filter* to declare a PDB procedure that take an image and drawable components of images.
|
|
||||||
|
|
||||||
*Script-fu-register-filter* declares a script that:
|
|
||||||
|
|
||||||
* is a filter or renderer: taking a user selected image and its selected components
|
|
||||||
* is multi-layer capable, processing one or more drawables
|
|
||||||
* can save its settings between sessions
|
|
||||||
* has a menu item that is enabled/sensitized when a user selects image components
|
|
||||||
|
|
||||||
You don't specify the first two arguments "image" and "drawables"
|
|
||||||
as you do with *script-fu-register* in v2.
|
|
||||||
Those arguments are implicit.
|
|
||||||
As a convenience, ScriptFu registers those arguments in the PDB for you.
|
|
||||||
|
|
||||||
The run func that you define in your script
|
|
||||||
must have those formal arguments. For example:
|
|
||||||
|
|
||||||
(define script-fu-my-plugin (image drawables arg1 arg2) body)
|
|
||||||
|
|
||||||
ScriptFu passes a Scheme vector of drawables, not just one,
|
|
||||||
to a script
|
|
||||||
registering with script-fu-register-filter.
|
|
||||||
|
|
||||||
GIMP enables the menu item of your script
|
|
||||||
when the user has selected an image of the declared image mode, e.g. *Grayscale*,
|
|
||||||
and has selected as many drawables
|
|
||||||
(layers/masks/channels)
|
|
||||||
as you have declared for multi-layer capability.
|
|
||||||
|
|
||||||
#### Declaring multi-layer capabilily
|
|
||||||
|
|
||||||
*Script-fu-register-filter* has an argument "multilayer-capability".
|
|
||||||
(Some documents may refer to the argument as "drawable arity.")
|
|
||||||
The argument declares the capability of the plugin
|
|
||||||
for processing multiple drawables (usually layers.)
|
|
||||||
The argument follows the "image types" argument,
|
|
||||||
which declares the capability of the plugin to process
|
|
||||||
various image modes.
|
|
||||||
|
|
||||||
Here is an example:
|
|
||||||
|
|
||||||
(script-fu-register-filter "script-fu-test-sphere-v3"
|
|
||||||
"Sphere v3..."
|
|
||||||
"Test script-fu-register-filter: needs 2 selected layers."
|
|
||||||
"authors"
|
|
||||||
"copyright holders"
|
|
||||||
"copyright dates"
|
|
||||||
"*" ; image modes: any
|
|
||||||
SF-TWO-OR-MORE-DRAWABLE ; multi-layer capability argument
|
|
||||||
SF-ADJUSTMENT "Radius" (list 100 1 5000 1 10 0 SF-SPINNER)
|
|
||||||
)
|
|
||||||
|
|
||||||
The "multilayer-capability" argument can have the following values:
|
|
||||||
|
|
||||||
SF-ONE-DRAWABLE expects exactly one drawable
|
|
||||||
SF-ONE-OR-MORE-DRAWABLE expects and will process one or more drawables
|
|
||||||
SF-TWO-OR-MORE-DRAWABLE expects and will process two or more drawables
|
|
||||||
|
|
||||||
This is only a declaration; whether your defined run func does what it promises is another matter.
|
|
||||||
|
|
||||||
A script declaring SF-ONE-DRAWABLE still receives a vector of drawables,
|
|
||||||
but the vector should be of length one.
|
|
||||||
|
|
||||||
These do not specify how the script will process the drawables.
|
|
||||||
Typically, SF-ONE-OR-MORE-DRAWABLE means a script will filter
|
|
||||||
the given drawables independently and sequentially.
|
|
||||||
Typically, SF-TWO-OR-MORE-DRAWABLE means a script will
|
|
||||||
combine the given drawables, say into another drawable by a binary operation.
|
|
||||||
|
|
||||||
The "multilayer-capability" argument tells GIMP to enable the script's menu item
|
|
||||||
when a user has selected the appropriate count of drawables.
|
|
||||||
|
|
||||||
#### A well-written script should check how many drawables were passed
|
|
||||||
|
|
||||||
A well-written script should throw an error when it is not passed
|
|
||||||
the declared number of drawables, either more or fewer than declared.
|
|
||||||
|
|
||||||
Starting with GIMP 3,
|
|
||||||
a plugin that takes an image takes a container of possibly many drawables.
|
|
||||||
This is the so-called "multi-layer selection" feature.
|
|
||||||
Existing plugins that don't are deprecated,
|
|
||||||
and may become obsolete in a future version of GIMP.
|
|
||||||
|
|
||||||
Plugins should declare how many drawables they can process,
|
|
||||||
also called the "multi-layer capability" or "drawable arity" of the algorithm.
|
|
||||||
|
|
||||||
The declared drawable arity
|
|
||||||
only describes how many drawables the algorithm is able to process.
|
|
||||||
The declared drawable arity does not denote the signature of the PDB procedure.
|
|
||||||
Well-written image procedures always receive a container of drawables.
|
|
||||||
|
|
||||||
For plugins invoked by a user interactively, the drawable arity describes
|
|
||||||
how many drawables the user is expected to select.
|
|
||||||
GIMP disables/enables the menu item for a plugin procedure
|
|
||||||
according to its declared drawable arity.
|
|
||||||
So a plugin procedure invoked directly by a user should never receive
|
|
||||||
a count of drawables that the plugin can't handle.
|
|
||||||
|
|
||||||
*But PDB procedures are also called from other PDB procedures.*
|
|
||||||
A call from another procedure may in fact
|
|
||||||
pass more drawables than declared for drawable arity.
|
|
||||||
That is a programming error in the calling procedure.
|
|
||||||
|
|
||||||
A well-written called plugin that is passed more drawables than declared
|
|
||||||
should return an error instead of processing any of the drawables.
|
|
||||||
Similarly for fewer than declared.
|
|
||||||
|
|
||||||
## Using the v3 dialect for PDB return values
|
|
||||||
|
|
||||||
*We recommend this for new scripts.*
|
|
||||||
|
|
||||||
ScriptFu in GIMP version 3 will optionally interpret a v3 dialect.
|
|
||||||
The dialect is more natural to the Scheme language.
|
|
||||||
The dialect affects the binding of return values from calls to the PDB.
|
|
||||||
|
|
||||||
A script opts into the v3 dialect at runtime by calling script-fu-use-v3
|
|
||||||
at the beginning of the run func..
|
|
||||||
|
|
||||||
The advantage of the v3 dialect is that scripts are smaller,
|
|
||||||
with fewer calls to car.
|
|
||||||
Also, you can more naturally examine boolean values.
|
|
||||||
|
|
||||||
For more information, see the document in the GIMP source /plugins/script-fu/docs/using-v3-binding.md
|
|
||||||
|
|
||||||
## FALSE and TRUE symbols are deprecated
|
|
||||||
|
|
||||||
*We recommend not using TRUE and FALSE in new scripts, except for an SF-TOGGLE argument.*
|
|
||||||
|
|
||||||
FALSE and TRUE symbols are deprecated in the ScriptFu language.
|
|
||||||
They never were in the Scheme language.
|
|
||||||
|
|
||||||
Instead, you should use the v3 dialect
|
|
||||||
and use the Scheme language symbols #f and #t.
|
|
||||||
|
|
||||||
In ScriptFu, FALSE is 0
|
|
||||||
and TRUE is 1.
|
|
||||||
But FALSE is not equivalent to #f.
|
|
||||||
|
|
||||||
You must use the = operator to compare to FALSE and TRUE.
|
|
||||||
FALSE and TRUE are numeric.
|
|
||||||
The = operator in Scheme is a numeric operator, not a logical operator.
|
|
||||||
|
|
||||||
In Scheme, all values are truthy except for #f.
|
|
||||||
The empty list is truthy.
|
|
||||||
The numeric 0 is truthy.
|
|
||||||
Only #f is not truthy.
|
|
||||||
|
|
||||||
In the v3 dialect, a PDB procedure returning a single Boolean (a predicate)
|
|
||||||
returns one element, for example #f or #t.
|
|
||||||
|
|
||||||
In the v2 dialect, it still returns (0) or (1),
|
|
||||||
that is, numeric 0 or 1 wrapped in a list.
|
|
||||||
|
|
||||||
*You still need to compare boolean SF_TOGGLE arguments to a script with TRUE and FALSE.
|
|
||||||
They are not #t and #f*.
|
|
||||||
|
|
||||||
#### Rationale
|
|
||||||
|
|
||||||
The ScriptFu language is simpler and smaller; TRUE and FALSE duplicated concepts already in the Scheme language.
|
|
||||||
|
|
||||||
#### Example changes
|
|
||||||
|
|
||||||
Declaring a script's SF_TOGGLE arguments can still use TRUE and FALSE.
|
|
||||||
|
|
||||||
SF-TOGGLE "Gradient reverse" FALSE
|
|
||||||
|
|
||||||
Comparing a boolean argument to a script *must* remain as in v2 dialect:
|
|
||||||
|
|
||||||
(if (= should-invert TRUE)
|
|
||||||
; do invert )
|
|
||||||
|
|
||||||
Calling a PDB procedure taking a boolean:
|
|
||||||
|
|
||||||
(gimp-context-set-feather TRUE)
|
|
||||||
=>
|
|
||||||
(gimp-context-set-feather #t)
|
|
||||||
|
|
||||||
Logically examining a variable for truth:
|
|
||||||
|
|
||||||
(if (= shadow TRUE) ...
|
|
||||||
=>
|
|
||||||
(if shadow ...
|
|
||||||
|
|
||||||
## Using the quit function to abort a script
|
|
||||||
|
|
||||||
*We recommend using quit to declare errors* along with gimp-message.
|
|
||||||
|
|
||||||
The function "quit" is in Scheme.
|
|
||||||
It causes a script to exit i.e. return to the system.
|
|
||||||
The function can be used anywhere in a script,
|
|
||||||
like you would a "return" statement in other languages.
|
|
||||||
|
|
||||||
In ScriptFu v3 it causes the interpreter to stop interpreting a script
|
|
||||||
and yield an error of type GimpPDBStatus.
|
|
||||||
That is, it immediately returns an error to the GIMP app or other caller.
|
|
||||||
The GIMP app will show an error message including the phrase
|
|
||||||
"script quit with error code x."
|
|
||||||
|
|
||||||
When the caller is another PDB procedure (a plugin or script)
|
|
||||||
the caller should check the result of a call to the script
|
|
||||||
and propagate the error.
|
|
||||||
ScriptFu itself always checks the result of a call to the PDB
|
|
||||||
and propagates the error,
|
|
||||||
concatenating error message strings.
|
|
||||||
|
|
||||||
In ScriptFu v2, a call such as (quit -1) did abort the script,
|
|
||||||
but did not return an error to the caller
|
|
||||||
(usually the GIMP app)
|
|
||||||
and did not return the error code.
|
|
||||||
|
|
||||||
### A script doesn't return a value
|
|
||||||
|
|
||||||
In ScriptFu, a script returns void.
|
|
||||||
It is not possible to define a plugin script that returns useful values.
|
|
||||||
Note that script registration functions do not declare return values.
|
|
||||||
Scripts only have side effects.
|
|
||||||
|
|
||||||
The last expression in a script plugin is *not* the value of the plugin,
|
|
||||||
as it is in Scheme.
|
|
||||||
|
|
||||||
As a PDB procedure, a script can succeed or fail.
|
|
||||||
But success does not depend on the value of the last evaluated expression.
|
|
||||||
To make a script return failure, you should call the quit function.
|
|
||||||
|
|
||||||
#### Rationale
|
|
||||||
|
|
||||||
Formerly, scripts usually called gimp-message on errors,
|
|
||||||
without yielding an error to the caller.
|
|
||||||
It was easy for a user to overlook the error message.
|
|
||||||
|
|
||||||
You should still call gimp-message just before calling quit,
|
|
||||||
with an informative error message.
|
|
||||||
The numeric code that quit prints is not informative to users,
|
|
||||||
only to the script author.
|
|
||||||
|
|
||||||
#### Example
|
|
||||||
|
|
||||||
This script quits early:
|
|
||||||
|
|
||||||
(define (script-fu-my-plugin)
|
|
||||||
...
|
|
||||||
(gimp-message "Too many drawables.")
|
|
||||||
(quit -1)
|
|
||||||
(display "this never evaluated")
|
|
||||||
)
|
|
||||||
...
|
|
||||||
|
|
||||||
## Using the display function to write to the terminal
|
|
||||||
|
|
||||||
*We recommend using the display function to help debug a script or to log,
|
|
||||||
but not to prompt for user input.*
|
|
||||||
|
|
||||||
Display is a Scheme function, in the R5RS standard.
|
|
||||||
It should write a string to any open terminal (e.g stdout on Linux.)
|
|
||||||
|
|
||||||
In ScriptFu v3, it does.
|
|
||||||
You will see the output in any terminal in which the GIMP app was started
|
|
||||||
(which is optional, and not usually done on a graphical desktop.)
|
|
||||||
|
|
||||||
In ScriptFu v2, it did not write to a terminal.
|
|
||||||
Display wrote to a stream which was returned to the GIMP app, and usually discarded (unless an error occurred, and then the stream
|
|
||||||
was the prefix of the error message.)
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
(display "The script is here") (newline)
|
|
||||||
|
|
||||||
Note that displayln is not in ScriptFu.
|
|
|
@ -1,130 +0,0 @@
|
||||||
# Color in ScriptFu
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
The audience is script authors and developers of ScriptFu.
|
|
||||||
|
|
||||||
For more information, see the test script script-fu/test/tests/pdb/color.scm.
|
|
||||||
The tests demonstrate exactly how ScriptFu behaves.
|
|
||||||
|
|
||||||
## Representation in Scheme
|
|
||||||
|
|
||||||
Colors are represented by lists of numerics, or string names or notation.
|
|
||||||
|
|
||||||
### List representation
|
|
||||||
|
|
||||||
A color *from* GIMP is represented in ScriptFu by a list of from one to four numerics,
|
|
||||||
depending on the image mode.
|
|
||||||
The numerics are "components" of the color.
|
|
||||||
|
|
||||||
You can also represent colors by lists of numeric in calls *to* the PDB.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- RGBA (0 0 0 0)
|
|
||||||
- RGB (0 0 0)
|
|
||||||
- Grayscale with alpha (0 0)
|
|
||||||
- Grayscale (0)
|
|
||||||
|
|
||||||
|
|
||||||
### String name representation
|
|
||||||
|
|
||||||
Color names can be used in PDB calls *to* GIMP. Color names must be CSS names.
|
|
||||||
|
|
||||||
You can also represent default colors by name
|
|
||||||
when declaring script arguments.
|
|
||||||
|
|
||||||
#### Name "transparent"
|
|
||||||
|
|
||||||
The color name "transparent" is a CSS color name.
|
|
||||||
|
|
||||||
You can use color named by "transparent" in calls to the PDB.
|
|
||||||
When setting the context foreground color,
|
|
||||||
it sets to opaque black.
|
|
||||||
When setting pixel of an RGBA image, the pixel
|
|
||||||
is set to black transparent.
|
|
||||||
|
|
||||||
### Other CSS color notation
|
|
||||||
|
|
||||||
You can also use other string notation to denote a color.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
- "#FFFFFF" hexadecimal notation for RGB
|
|
||||||
- "hsl(0, 0, 0)" converter function call from HSL values
|
|
||||||
|
|
||||||
Note that ScriptFu still converts to RGB format.
|
|
||||||
|
|
||||||
### CSS names/notation and grayscale images
|
|
||||||
|
|
||||||
You can use CSS names in procedures on grayscale images.
|
|
||||||
GIMP converts RGB colors to grayscale.
|
|
||||||
|
|
||||||
## Colorspace and Precision
|
|
||||||
|
|
||||||
While the GIMP app supports many colorspaces and precisions,
|
|
||||||
ScriptFu does not.
|
|
||||||
|
|
||||||
Generally speaking, ScriptFu has limited support for dealing with
|
|
||||||
colorspace and precision.
|
|
||||||
Scripts may call any procedures in the PDB that deal with colorspace
|
|
||||||
and precision.
|
|
||||||
But ScriptFu does not handle pixels/colors in high precision
|
|
||||||
or in colorspaces other than RGB and grayscale.
|
|
||||||
ScriptFu is not designed for intense and complicated pixel-level operations.
|
|
||||||
|
|
||||||
### Colorspace
|
|
||||||
|
|
||||||
ScriptFu keeps colors in the sRGB colorspace,
|
|
||||||
or grayscale.
|
|
||||||
|
|
||||||
GIMP converts colorspace when a ScriptFu script operates on images in other colorspaces.
|
|
||||||
|
|
||||||
### Precision
|
|
||||||
|
|
||||||
ScriptFu keeps colors with 8-bit integer precision.
|
|
||||||
This means a script may suffer loss of precision
|
|
||||||
when processing images of higher precision.
|
|
||||||
|
|
||||||
ScriptFu clamps numerics passed to the PDB as color components
|
|
||||||
to the range [0, 255].
|
|
||||||
Numeric color components received from GIMP are also integers in the range [0,255].
|
|
||||||
|
|
||||||
Float numerics may be passed as components of a color,
|
|
||||||
but are converted to integers and clamped.
|
|
||||||
|
|
||||||
## Difference from ScriptFu version 2
|
|
||||||
|
|
||||||
Version 2 represented colors differently,
|
|
||||||
converting to and from C type GimpRGB, which is obsolete.
|
|
||||||
|
|
||||||
Most scripts using colors will continue to work,
|
|
||||||
when they use colors opaquely,
|
|
||||||
receiving and passing colors without looking inside them.
|
|
||||||
It is only scripts that deal with color components
|
|
||||||
that might need to be ported.
|
|
||||||
|
|
||||||
In version 2, gimp-drawable-get-pixel
|
|
||||||
returned a count of components and a list of components e.g. (3 (255 255 255)).
|
|
||||||
Now it just returns a list of components,
|
|
||||||
and the length of the list correlates with format length.
|
|
||||||
|
|
||||||
## The GeglColor type
|
|
||||||
|
|
||||||
In the PDB, the type of colors is GeglColor.
|
|
||||||
When you browse the PDB, you see this type.
|
|
||||||
Arguments of this type are the "colors"
|
|
||||||
that ScriptFu represents as lists of numerics.
|
|
||||||
|
|
||||||
GeglColor is a class i.e. object in GIMP.
|
|
||||||
There are no methods in the PDB API for GeglColor.
|
|
||||||
For example in ScriptFu you can't get the format of a GeglColor.
|
|
||||||
You can get the length of the list representation to know the format.
|
|
||||||
|
|
||||||
## Indexed images
|
|
||||||
|
|
||||||
Colors to and from indexed images are colors, not indexes.
|
|
||||||
That is, in ScriptFu, a color from an indexed image is
|
|
||||||
a list of four numerics, RGBA.
|
|
||||||
|
|
||||||
|
|
|
@ -1,288 +0,0 @@
|
||||||
# String-like objects in ScriptFu's TinyScheme
|
|
||||||
|
|
||||||
!!! Work in progress. This documents what should be, and not what is actually implemented. There are bugs in the current implementation.
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
This is a language reference for the string-like features of
|
|
||||||
Script-fu's TinyScheme language.
|
|
||||||
|
|
||||||
This may differ from other Scheme languages. TinyScheme is a subset of R5RS Scheme, and ScriptFu has more than the original TinyScheme because it has been modified to support unichars and bytes. Both string-ports, bytes, and unichar are recent additions to Scheme, and not standardized among Schemes.
|
|
||||||
|
|
||||||
This is not a tutorial, but a technical document intended to be testable.
|
|
||||||
|
|
||||||
Terminology. We use "read method" to denote the function whose name is "read".
|
|
||||||
We occasionally use "read" to mean "one of the functions: read, read-byte, or read-char.
|
|
||||||
|
|
||||||
## The problem of specification
|
|
||||||
|
|
||||||
TinyScheme is a loose subset of the R5RS specification.
|
|
||||||
|
|
||||||
These are not part of R5RS, but optional implementations:
|
|
||||||
- string-ports
|
|
||||||
- unichar
|
|
||||||
- byte operations
|
|
||||||
|
|
||||||
Racket is a Scheme language that also implements the above.
|
|
||||||
See Racket for specifications, examples, and tests,
|
|
||||||
but ScriptFu's TinyScheme may differ.
|
|
||||||
|
|
||||||
SRFI-6 is one specification for string-port behavior.
|
|
||||||
SRFI-6:
|
|
||||||
- has a reference implementation.
|
|
||||||
- does not describe testable behavior.
|
|
||||||
- does not discuss unichar or byte operations
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Script-fu's TinyScheme has these string-like objects:
|
|
||||||
|
|
||||||
- string
|
|
||||||
- string-port
|
|
||||||
|
|
||||||
Both are:
|
|
||||||
|
|
||||||
- sequences of chars
|
|
||||||
- practically infinite
|
|
||||||
- UTF-8 encoded, i.e. the chars are unichars of multiple bytes
|
|
||||||
|
|
||||||
They are related, you can:
|
|
||||||
|
|
||||||
- initialize an input string-port from a string
|
|
||||||
- get a string from an output string-port
|
|
||||||
|
|
||||||
However, the passed string is not owned by a string-port but is a separate object with its own lifetime.
|
|
||||||
|
|
||||||
Differences are:
|
|
||||||
|
|
||||||
- string-ports implement the port API (open, read, write, and close)
|
|
||||||
- string-ports have byte methods but strings do not
|
|
||||||
- strings have a length method but string-ports do not
|
|
||||||
- strings have indexing and substring methods but string-ports do not
|
|
||||||
- write to a string-port is less expensive than an append to a string
|
|
||||||
|
|
||||||
Note that read and write methods to a string-port traffic in objects, not chars.
|
|
||||||
In other words, they serialize or deserialize, representing objects by text, and parsing text into objects.
|
|
||||||
|
|
||||||
Symbols also have string representations, but no string-like methods besides conversion to and from strings.
|
|
||||||
|
|
||||||
## ScriptFu's implementation is in C
|
|
||||||
|
|
||||||
This section does not describe the language but helps to ground the discussion.
|
|
||||||
|
|
||||||
ScriptFu does not use the reference implementation of SRFI-6.
|
|
||||||
The reference implementation is in Scheme.
|
|
||||||
The reference implementation is on top of strings.
|
|
||||||
|
|
||||||
ScriptFu's implementation of *string-ports is not on top of strings.*
|
|
||||||
ScriptFu's implementation is in C language.
|
|
||||||
(The reason is not recorded, but probably for performance.)
|
|
||||||
|
|
||||||
The reference implementation of SRFI-6 requires that READ and WRITE be redefined to use a redefined READ-CHAR etc. that
|
|
||||||
are string-port aware.
|
|
||||||
TinyScheme does something similar: inbyte() and backbyte() dispatch on the kind of port.
|
|
||||||
|
|
||||||
Internally, TinyScheme terminates all strings and string-ports with the NUL character (the 0 byte.) This is not visible in Scheme.
|
|
||||||
|
|
||||||
## Allocations
|
|
||||||
|
|
||||||
A main concern of string-like objects is how they are allocated and their lifetimes.
|
|
||||||
|
|
||||||
All string-like objects are allocated from the heap and with one cell from TinyScheme's cell pool (which is separately allocated from the heap.)
|
|
||||||
|
|
||||||
A string-port and any string used with a string-port are separate objects with separate lifetimes.
|
|
||||||
|
|
||||||
The length of string-like objects is limited by the underlying allocator (malloc) and the OS.
|
|
||||||
|
|
||||||
### String allocations
|
|
||||||
|
|
||||||
Strings and string literals are allocated.
|
|
||||||
|
|
||||||
They are allocated exactly.
|
|
||||||
|
|
||||||
Any append to a string causes a reallocation.
|
|
||||||
|
|
||||||
Any substring of a string causes a new allocation and returns a new string instance.
|
|
||||||
|
|
||||||
String literals are allocated but are immutable.
|
|
||||||
|
|
||||||
### String-port allocations
|
|
||||||
|
|
||||||
String-ports of kind output have an allocated, internal buffer.
|
|
||||||
A buffer has a "reserve" or free space.
|
|
||||||
|
|
||||||
The buffer can sometimes accomodate writes without a reallocation.
|
|
||||||
Writes to an output string-port can be less expensive (higher performing)
|
|
||||||
than appends to a string, which always reallocates.
|
|
||||||
But note that writes are not the same as appending (see below.)
|
|
||||||
|
|
||||||
The write method can write larger than the size that is pre-allocated for the buffer (256 bytes.)
|
|
||||||
|
|
||||||
A string-port of kind input is not a buffer.
|
|
||||||
It is allocated once.
|
|
||||||
It's size is fixed when opened.
|
|
||||||
|
|
||||||
## Byte, char, and object methods
|
|
||||||
|
|
||||||
### String methods
|
|
||||||
|
|
||||||
Strings are composed of characters.
|
|
||||||
The method string-ref accesses a character component.
|
|
||||||
|
|
||||||
Strings have no byte methods.
|
|
||||||
Characters can be converted to integers and then to bytes.
|
|
||||||
See "Support for byte type" at the Gimp developer web site.
|
|
||||||
|
|
||||||
Strings have no object methods: read and write.
|
|
||||||
|
|
||||||
### Port methods
|
|
||||||
|
|
||||||
Ports, and thus string-ports, have byte and char methods:
|
|
||||||
|
|
||||||
read-byte, read-char
|
|
||||||
write-byte, write-char
|
|
||||||
|
|
||||||
Ports also have methods trafficing in objects:
|
|
||||||
|
|
||||||
read, write
|
|
||||||
|
|
||||||
|
|
||||||
### Methods and port kinds
|
|
||||||
|
|
||||||
String-ports are of two kinds:
|
|
||||||
- input
|
|
||||||
- output
|
|
||||||
|
|
||||||
*There is also an input-output kind of string-port in TinyScheme,
|
|
||||||
but this document does not describe it and any use of it is not supported in ScriptFu*
|
|
||||||
|
|
||||||
You should only use the "read" methods on a string-port of kind input.
|
|
||||||
You should only use the "write" methods on a string-port of kind output.
|
|
||||||
A call of a read method on a string-port of kind output returns an error, and vice versa.
|
|
||||||
|
|
||||||
|
|
||||||
### Mixing byte, char, and object methods
|
|
||||||
|
|
||||||
*You should not mix byte methods with char methods, unless you are careful.*
|
|
||||||
You must understand UTF-8 encoding to do so.
|
|
||||||
|
|
||||||
*You should not mix char methods with read/write methods, unless you are careful.*
|
|
||||||
You must understand parsing and representation of Scheme to do so.
|
|
||||||
|
|
||||||
### The NUL character and byte
|
|
||||||
|
|
||||||
Internally, TinyScheme terminates all strings and string-ports
|
|
||||||
with the NUL character (the 0 byte.)
|
|
||||||
|
|
||||||
*You should not write the NUL character to strings or string-ports. The result can be surprising, and is not described here.*
|
|
||||||
You must understand the role of NUL bytes in C strings.
|
|
||||||
|
|
||||||
You cannot read the NUL character or byte from a string or string-port since the interpreter always sees it as a terminator.
|
|
||||||
|
|
||||||
Note that a string escape sequence for NUL, which is itself a string without a NUL character, can be inside a string or string-port.
|
|
||||||
|
|
||||||
You can read and write the NUL character to file ports that you are treating as binary files and not text files.
|
|
||||||
|
|
||||||
## Length methods
|
|
||||||
|
|
||||||
### Strings
|
|
||||||
|
|
||||||
The length of a string is in units of characters. Remember that each character in UTF-8 encoding may comprise many bytes.
|
|
||||||
|
|
||||||
(string-length "foo") => 3
|
|
||||||
|
|
||||||
### Ports
|
|
||||||
|
|
||||||
Ports have no methods for obtaining the length, either in characters or byte units. Some other Schemes have such methods.
|
|
||||||
|
|
||||||
## String-port and initial strings
|
|
||||||
|
|
||||||
### Input ports
|
|
||||||
|
|
||||||
The method open-input-port takes an initial string.
|
|
||||||
|
|
||||||
The initial string can be large, limited only by malloc.
|
|
||||||
|
|
||||||
TinyScheme copies the initial string to the port.
|
|
||||||
Subsequently, these have no effect on the port:
|
|
||||||
|
|
||||||
- the initial string going out of scope
|
|
||||||
- an append to the initial string
|
|
||||||
|
|
||||||
Subsequent calls to read methods progress along the port contents,
|
|
||||||
until finally EOF is returned.
|
|
||||||
|
|
||||||
The initial string can be the empty string and then the first read will return the EOF object.
|
|
||||||
|
|
||||||
There are no methods for appending to an input string-port after it is opened.
|
|
||||||
|
|
||||||
### Output ports
|
|
||||||
|
|
||||||
*The method open-output-port optionally takes an initial string but it is ignored.*
|
|
||||||
|
|
||||||
In other Schemes, any initial string is the name of the port.
|
|
||||||
|
|
||||||
In version 2 of Script-Fu's TinyScheme, the initial string was loosely speaking the buffer for the string-port.
|
|
||||||
This document does not describe the version 2 behavior.
|
|
||||||
|
|
||||||
An output string-port is initially empty and not the initial string.
|
|
||||||
|
|
||||||
The initial string may go out of scope without effect on an output string-port.
|
|
||||||
|
|
||||||
You can write more to an output port than the length of the initial string.
|
|
||||||
|
|
||||||
## The get-output-string method
|
|
||||||
|
|
||||||
A string-port of kind output is a stream that can be written to
|
|
||||||
but that can be read only by getting its entire contents.
|
|
||||||
|
|
||||||
(get-output-string port)
|
|
||||||
|
|
||||||
Returns a string that is the accumulation of all prior writes to the output string-port. This is a loose definition. Chars, bytes, and objects can be written, and it is the representation of objects that accumulate.
|
|
||||||
|
|
||||||
The port must be open at the time of the call.
|
|
||||||
|
|
||||||
A get-output-string call on a newly opened empty port returns the empty string.
|
|
||||||
|
|
||||||
Consecutive calls to get-output-string return two different string objects, but they are equivalent.
|
|
||||||
|
|
||||||
The returned string is a distinct object from the port.
|
|
||||||
These subsequent events have no effect on the returned string:
|
|
||||||
|
|
||||||
- writes to the port
|
|
||||||
- closing the port
|
|
||||||
- the port subsequently going out of scope
|
|
||||||
|
|
||||||
Again, *you should not mix write-byte, write-char, and write to an output string-port, without care*
|
|
||||||
|
|
||||||
|
|
||||||
## Writing and reading strings to a string-port
|
|
||||||
|
|
||||||
These are different:
|
|
||||||
- write a string to an output string-port
|
|
||||||
- append a string to a string
|
|
||||||
|
|
||||||
A string written to an output string-port writes escaped quotes into the string-port:
|
|
||||||
|
|
||||||
```
|
|
||||||
> (define aPort (open-output-string))
|
|
||||||
> (write "foo" aPort)
|
|
||||||
> (get-output-string aPort)
|
|
||||||
"\"foo\""
|
|
||||||
```
|
|
||||||
|
|
||||||
That is, writing a string to an output string-port
|
|
||||||
writes seven characters, three for foo and two pairs of
|
|
||||||
backslash quote.
|
|
||||||
```
|
|
||||||
\"foo\"
|
|
||||||
1234567
|
|
||||||
```
|
|
||||||
This is a string, which in the REPL prints surrounded by quotes:
|
|
||||||
```
|
|
||||||
"\"foo\""
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,360 +0,0 @@
|
||||||
# Version 3 of the ScriptFu language
|
|
||||||
|
|
||||||
## About
|
|
||||||
|
|
||||||
This describes a new dialect of the ScriptFu language.
|
|
||||||
ScriptFu interprets the dialect after a script calls: (script-fu-use-v3).
|
|
||||||
The new dialect is more like Scheme and makes scripts shorter.
|
|
||||||
The dialect only affects calls to the PDB.
|
|
||||||
ScriptFu inteprets the old version 2 by default,
|
|
||||||
unless a script calls script-fu-use-v3.
|
|
||||||
|
|
||||||
The audience is script authors and other developers.
|
|
||||||
|
|
||||||
This describes the new dialect and how to port old scripts to the new dialect.
|
|
||||||
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
ScriptFu inteprets the old version 2 by default,
|
|
||||||
unless a script calls script-fu-use-v3.
|
|
||||||
After a call to script-fu-use-v3,
|
|
||||||
ScriptFu interprets the new dialect until the script finishes,
|
|
||||||
or until the script calls script-fu-use-v2.
|
|
||||||
A script can switch back and forth between dialects at runtime.
|
|
||||||
|
|
||||||
A script that calls:
|
|
||||||
```
|
|
||||||
(script-fu-use-v3)
|
|
||||||
```
|
|
||||||
binds to certain PDB calls differently:
|
|
||||||
|
|
||||||
1. PDB procedures that return single values (atoms) return just that single value,
|
|
||||||
*not wrapped in a list.*
|
|
||||||
Formerly, every PDB call returned a list (possibly nesting more lists.)
|
|
||||||
|
|
||||||
2. You can use #t and #f as arguments to PDB calls taking a boolean.
|
|
||||||
|
|
||||||
3. PDB calls returning a boolean return #t or #f, not TRUE or FALSE (1 or 0.)
|
|
||||||
|
|
||||||
## Script-Fu Console
|
|
||||||
|
|
||||||
The Script-Fu Console always starts in the v2 dialect.
|
|
||||||
|
|
||||||
You can call *script-fu-use-v3* in the console.
|
|
||||||
Then, the console interprets the v3 dialect.
|
|
||||||
It continues to interpret the v3 dialect in that session,
|
|
||||||
until you call *script-fu-use-v2.*
|
|
||||||
|
|
||||||
## Where to call *script-fu-use-v3* in scripts
|
|
||||||
|
|
||||||
Call *script-fu-use-v3* at the beginning of the run function.
|
|
||||||
This sets the dialect version for the remaining interpretation
|
|
||||||
of the script.
|
|
||||||
|
|
||||||
!!! Do not call *script-fu-use-v3* at the top level of a script.
|
|
||||||
This has no effect, since it is only executed in the query phase
|
|
||||||
of a plugin.
|
|
||||||
The interpreter starts at the run function during the run phase.
|
|
||||||
|
|
||||||
*The interpreter always starts interpreting each script in the v2 dialect.
|
|
||||||
This is true even for extension-script-fu, the long-running interpreter.*
|
|
||||||
There is no need to call *script-fu-use-v2* before returning from a script,
|
|
||||||
to ensure that the next script is interpreted in v2 dialect.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
(define (script-fu-testv3 img drawables )
|
|
||||||
(script-fu-use-v3) ; <<<
|
|
||||||
(let* (
|
|
||||||
...
|
|
||||||
```
|
|
||||||
### Scope
|
|
||||||
|
|
||||||
The dialect version has "execution scope" versus "lexical scope."
|
|
||||||
Setting the dialect version is effective even for
|
|
||||||
other functions defined in the same script but lexically
|
|
||||||
outside the function where the dialect is set.
|
|
||||||
You only need to call script-fu-use-v3 once,
|
|
||||||
not in every defined function.
|
|
||||||
|
|
||||||
|
|
||||||
## Don't call v2 scripts from v3 scripts
|
|
||||||
|
|
||||||
When using the v3 dialect,
|
|
||||||
you cannot call plugin Scheme scripts or other library scripts that are in the v2 dialect.
|
|
||||||
And vice versa.
|
|
||||||
(When a script calls a PDB procedure that is a Scheme script,
|
|
||||||
a new interpreter process is *NOT* started.)
|
|
||||||
|
|
||||||
For example, a new plugin script should not call the PDB procedure
|
|
||||||
script-fu-add-bevel because it is a Scheme script in v2 dialect
|
|
||||||
and for example has:
|
|
||||||
|
|
||||||
```
|
|
||||||
(width (car (gimp-drawable-get-width pic-layer)))
|
|
||||||
```
|
|
||||||
which is v2 dialect and would throw an error such as:
|
|
||||||
```
|
|
||||||
Error: car requires a pair.
|
|
||||||
```
|
|
||||||
|
|
||||||
*It is rare that a script calls another plugin script.*
|
|
||||||
A script usually calls the PDB,
|
|
||||||
but rarely calls a plugin script of the PDB.
|
|
||||||
|
|
||||||
There are very few, obscure library scripts that call the PDB using v2 dialect.
|
|
||||||
These are in scripts/script-fu-util.scm.
|
|
||||||
|
|
||||||
## Pure Scheme is unaffected
|
|
||||||
|
|
||||||
The dialect only affects calls the to PDB.
|
|
||||||
|
|
||||||
This means you can usually call most library scripts when using v3,
|
|
||||||
since most library scripts are pure Scheme,
|
|
||||||
that is, with no calls to the GIMP PDB.
|
|
||||||
|
|
||||||
## TRUE and FALSE
|
|
||||||
|
|
||||||
TRUE and FALSE are still in v3 dialect and are still numbers 1 and 0.
|
|
||||||
But we recommend not using them.
|
|
||||||
|
|
||||||
You can still pass them as arguments to PDB calls taking a boolean,
|
|
||||||
and they are still converted to the C notion of boolean truth.
|
|
||||||
|
|
||||||
FALSE which is 0 is truthy in Scheme!!!
|
|
||||||
It converts to the C notion of false only in a call the the PDB.
|
|
||||||
In the ScriptFu Console:
|
|
||||||
```
|
|
||||||
>(equal? FALSE #t)
|
|
||||||
#t
|
|
||||||
```
|
|
||||||
|
|
||||||
TRUE and FALSE symbols may become obsolete in the future.
|
|
||||||
|
|
||||||
## An argument of type SF-TOGGLE is FALSE or TRUE, not #f or #t
|
|
||||||
|
|
||||||
The v3 dialect does not affect the binding of arguments to a script.
|
|
||||||
So the value of an argument of type SF-TOGGLE is zero or one,
|
|
||||||
not #f or #t.
|
|
||||||
|
|
||||||
You must continue to check boolean arguments to a script like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
(define script-fu-my-plugin (should-invert)
|
|
||||||
(if (= should-invert TRUE)
|
|
||||||
(
|
|
||||||
; do invert
|
|
||||||
)))
|
|
||||||
|
|
||||||
(script-fu-register-procedure "script-fu-my-plugin"
|
|
||||||
"My plugin..."
|
|
||||||
...
|
|
||||||
SF-TOGGLE "Invert?" FALSE
|
|
||||||
)
|
|
||||||
```
|
|
||||||
This may change when in the future we obsolete v2 dialect
|
|
||||||
and the symbols TRUE and FALSE.
|
|
||||||
|
|
||||||
## Plans for the future
|
|
||||||
|
|
||||||
This dialect is shorter and more natural for Scheme programmers.
|
|
||||||
|
|
||||||
The long-term goal is for the v3 dialect to be the only dialect of ScriptFu.
|
|
||||||
For the short term, for backward compatibility,
|
|
||||||
the default dialect of ScriptFu is the v2 dialect.
|
|
||||||
|
|
||||||
You should write any new scripts in the v3 dialect,
|
|
||||||
and call *script-fu-use-v3*.
|
|
||||||
|
|
||||||
You should plan on porting existing scripts to the v3 dialect,
|
|
||||||
since eventually ScriptFu may obolete the v2 dialect.
|
|
||||||
|
|
||||||
## Example conversions from v2 to v3 dialects
|
|
||||||
|
|
||||||
### An example script using v3 dialect
|
|
||||||
|
|
||||||
```
|
|
||||||
; !!! Usually not call (script-fu-use-v3) here in global scope
|
|
||||||
|
|
||||||
(define script-fu-my-plugin (should-invert)
|
|
||||||
; the body switches to the v3 dialect
|
|
||||||
(script-fu-use-v3)
|
|
||||||
|
|
||||||
(let* (
|
|
||||||
; don't need a car, unlike v2
|
|
||||||
(angle gimp-context-get-brush-angle)))
|
|
||||||
|
|
||||||
; call PDB returning boolean
|
|
||||||
; don't need (= (car (gimp-context-get-feather)) TRUE)
|
|
||||||
(if (gimp-context-get-feather)
|
|
||||||
; do feather
|
|
||||||
)
|
|
||||||
|
|
||||||
; boolean arg to script is still C notion of truth
|
|
||||||
(if (= should-invert TRUE)
|
|
||||||
(
|
|
||||||
; do invert
|
|
||||||
))
|
|
||||||
|
|
||||||
; calling a v2 plugin, temporarily switch to v2 dialect
|
|
||||||
(script-fu-use-v2)
|
|
||||||
(script-fu-add-bevel ...)
|
|
||||||
|
|
||||||
; rest of script in v3 dialect
|
|
||||||
(script-fu-use-v3)
|
|
||||||
...
|
|
||||||
)
|
|
||||||
|
|
||||||
(script-fu-register-procedure "script-fu-my-plugin"
|
|
||||||
"My plugin..."
|
|
||||||
...
|
|
||||||
SF-TOGGLE "Invert?" FALSE
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### A call to a PDB procedure returning a single value
|
|
||||||
|
|
||||||
```
|
|
||||||
(set! (width (car (gimp-drawable-get-width pic-layer))))
|
|
||||||
```
|
|
||||||
*must* become
|
|
||||||
```
|
|
||||||
(set! (width (gimp-drawable-get-width pic-layer)))
|
|
||||||
```
|
|
||||||
The PDB call returns a single integer,
|
|
||||||
so no *car* is needed.
|
|
||||||
|
|
||||||
### A call to a PDB procedure returning boolean
|
|
||||||
```
|
|
||||||
(if (= (gimp-image-is-rgb image) TRUE) ...
|
|
||||||
```
|
|
||||||
*must* become:
|
|
||||||
```
|
|
||||||
(if (gimp-image-is-rgb image) ...
|
|
||||||
```
|
|
||||||
The PDB procedure returns a boolean,
|
|
||||||
which is bound to #t or #f,
|
|
||||||
the usual symbols for Scheme truth.
|
|
||||||
|
|
||||||
### A call to a PDB procedure taking a boolean
|
|
||||||
|
|
||||||
```
|
|
||||||
(gimp-context-set-antialias TRUE)
|
|
||||||
```
|
|
||||||
*should* become
|
|
||||||
```
|
|
||||||
(gimp-context-set-antialias #t)
|
|
||||||
```
|
|
||||||
This doesn't *require* conversion because TRUE is 1 and is truthy in Scheme.
|
|
||||||
|
|
||||||
!!! But FALSE is 0 and 0 is truthy in Scheme
|
|
||||||
```
|
|
||||||
(gimp-context-set-antialias FALSE)
|
|
||||||
```
|
|
||||||
This *should* be converted, for clarity, but doesn't *require* conversion.
|
|
||||||
For now, ScriptFu still binds Scheme 0 to C 0.
|
|
||||||
So it still does what the script intends.
|
|
||||||
|
|
||||||
### A call to a PDB procedure returning a list
|
|
||||||
|
|
||||||
```
|
|
||||||
(set! brushes (car (gimp-brushes-get-list)))
|
|
||||||
```
|
|
||||||
*must* become:
|
|
||||||
```
|
|
||||||
(set! brushes (gimp-brushes-get-list))
|
|
||||||
```
|
|
||||||
Formerly, the PDB procedure returned a list wrapped in a list,
|
|
||||||
i.e. ((...))
|
|
||||||
In the v3 dialect, it returns just a list, i.e. (...)
|
|
||||||
which is a single value, a single container.
|
|
||||||
|
|
||||||
### A call to a PDB procedure returning a list, getting the first element
|
|
||||||
|
|
||||||
```
|
|
||||||
(set! first-brush (caar (gimp-brushes-get-list)))
|
|
||||||
```
|
|
||||||
Gets the first brush in GIMP.
|
|
||||||
This *must* become:
|
|
||||||
```
|
|
||||||
(set! first-brush (car (gimp-brushes-get-list)))
|
|
||||||
```
|
|
||||||
The call to *caar* is consecutive calls to *car*,
|
|
||||||
and you must eliminate the first call to *car*.
|
|
||||||
|
|
||||||
|
|
||||||
## Knowing what constructs need conversion
|
|
||||||
|
|
||||||
You *should* (but are not required to)
|
|
||||||
eliminate most uses of symbols TRUE and FALSE from a script
|
|
||||||
using v3 dialect.
|
|
||||||
|
|
||||||
You should eliminate many, *but not all*, uses of the *car* function wrapping a call to the PDB,
|
|
||||||
where the PDB procedure returns a single value.
|
|
||||||
There are several hundred such PDB procedures in the PDB.
|
|
||||||
Examine the signature of a PDB procedure using the PDB Browser.
|
|
||||||
|
|
||||||
For example, gimp-brush-get-angle:
|
|
||||||
```
|
|
||||||
Return Values
|
|
||||||
angle gdouble ....
|
|
||||||
Additional Information
|
|
||||||
```
|
|
||||||
This returns a single value so no need to use car.
|
|
||||||
|
|
||||||
For example, gimp-brushes-get-list:
|
|
||||||
```
|
|
||||||
Return Values
|
|
||||||
brush-list GStrv
|
|
||||||
Additional Information
|
|
||||||
```
|
|
||||||
This also returns a single value.
|
|
||||||
But the single value is a list i.e. container, of strings.
|
|
||||||
In the v2 dialect, this returned a list wrapped in a list,
|
|
||||||
for example (("foo" "bar")).
|
|
||||||
|
|
||||||
See "Example conversions from v2 to v3"
|
|
||||||
|
|
||||||
### Does not require changes to calls to PDB procedures returning void
|
|
||||||
|
|
||||||
You should not need to change scripts on calls to PDB procedures returning C void because a script should not be examining the result.
|
|
||||||
|
|
||||||
Some scripts might examine the result of a call to a void PDB procedure, thinking that (#t) is the success of the call,
|
|
||||||
but that is a misconception and should be fixed.
|
|
||||||
|
|
||||||
Calls to PDB procedures that return C void return (#t) in v2 and the empty list () i.e. nil in v3 dialect.
|
|
||||||
|
|
||||||
## Details of the implementation
|
|
||||||
|
|
||||||
There are new functions in the dialect:
|
|
||||||
```
|
|
||||||
script-fu-use-v3
|
|
||||||
script-fu-use-v2
|
|
||||||
```
|
|
||||||
These functions have side-effects on the state of the interpreter.
|
|
||||||
They always return the empty list ().
|
|
||||||
|
|
||||||
The effect is immediate.
|
|
||||||
The interpreter interprets a dialect from then on,
|
|
||||||
until the script returns,
|
|
||||||
or until the script changes the dialect again.
|
|
||||||
|
|
||||||
A call to *script-fu-use-v3* sets a flag in the state of the interpreter.
|
|
||||||
When the flag is set, the interpreter binds arguments to PDB calls slightly differently, as described.
|
|
||||||
Binding of args to PDB calls is done at run time.
|
|
||||||
|
|
||||||
Similarly, a call to *script-fu-use-v2* clears the flag
|
|
||||||
and restores the interpreter state to binding using the v2 dialect.
|
|
||||||
|
|
||||||
When in the v3 state,
|
|
||||||
any PDB call constructs using v2 binding will yield errors,
|
|
||||||
and vice versa.
|
|
||||||
|
|
||||||
Note that the difference in interpretation is only in binding, but both to and from the PDB:
|
|
||||||
|
|
||||||
1. Single return values *from* the PDB are not wrapped in lists.
|
|
||||||
2. Boolean return values *from* the PDB are bound to #t and #f.
|
|
||||||
3. Boolean values *to* the PDB can be #t and #f.
|
|
Loading…
Add table
Add a link
Reference in a new issue