Adapting scripts to PDB version 3
About
This describes some changes needed to port a Scriptfu script to GIMP 3.
This discusses changes required due to changes to the PDB API:
- changes in types
- changes in PDB signatures for multi-layer support
It also discusses a few changes to ScriptFu itself:
- changes in error detection for calls to the PDB
- changes in logging
- keyword arguments
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
- changes in signature, where arguments are reordered or changed in number
Notation
This gives examples and explanations as if you were using v3 of the ScriptFu dialect. See “Using the version 3 dialect for PDB values”.
Where we say “returns a vector”, in the v2 dialect, the returned value is actually a vector wrapped in a list, and you must use the car function to unwrap it. In the v3 dialect, the returned value is just a vector, not wrapped in a list.
Whether a called PDB procedure wraps its returned values in a list depends on the arity of the return values, that is, whether the PDB procedure returns a single result.
Overview of changes to the PDB API
This is a general discussion. See the rest of the document for details, especially regarding representations in Scheme.
The API of the PDB has become more object oriented.
Passing objects instead of names
Formerly, the declared types of some arguments were primitives such as string names, or lists of numbers. Some of those arguments have changed to object types.
For example, resources arguments were of type string, which was a name. Now the arguments are of object types. The objects still have names as attributes.
For another example, file arguments were of type string. Now the arguments are object types, GFile. The objects still have names as attributes.
Passing containers as objects
Formerly, the PDB passed C arrays as an integer length and the data of the array.
Now an array is passed as an object, which has a method for getting its length. (Both in C, and in Scheme.)
Generalized re passing selected layers to plugins
Formerly, a plugin that is a filter received a single drawable.
Now a plugin receives a container of drawables. A user can select many drawables to be passed to plugins.
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, GLib, and GIMP types.
This table summarizes changes in the PDB API from v2 to v3. It gives the corresponding Scheme types. Each row is explained below, in the context of a Scheme plugin.
Purpose | Old C type | New C type | Old Scheme type | New Scheme type | Note |
---|---|---|---|---|---|
Pass file name | gchar*, gchar* | GFile | string string | string | 1 |
Recv file name | gchar* | GFile | string | string | 2 |
Pass selected drawable | GimpDrawable | GimpCoreObjectArray | int (an ID) | vector | 3 |
Pass obj array | gint, GimpInt32Array | GimpCoreObjectArray | int vector | vector | 4 |
Recv obj array | gint, GimpInt32Array | GimpCoreObjectArray | int vector | vector | 5 |
Pass set of str | gint, GimpStringArray | GStrv | int list-of-string | list-of-string | 6 |
Recv set of str | gint, GimpStringArray | GStrv | int list-of-string | list-of-string | 7 |
Pass or Recv a color | GimpRGB | GeglColor | int triplet, or string name | same, or quadruplet | 8 |
Pass or Recv a resource | gchar* | GimpFont, etc. | string | int (an ID) | 9 |
Recv array of color | gint, GimpInt8Array | GimpColorArray | int vector | vector | 10 |
Where “obj” means an object of a GIMP type such as GimpDrawable or similar.
In the explanations below, we use integer literals for the ID’s of images and drawables. Ordinarily, scripts don’t do that, but instead pass object ID’s opaquely. Remember that internally, ScriptFu represents GIMP object by numeric IDs.
1 Pass 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 type 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")
2 PDB procedures still return a string to Scheme, 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.
3,4 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 GimpCoreObjectArray.)
This affects most plugins that are filters (which take a drawable.) It also affects other PDB procedures. See the list below.
These changes support a user or script selecting multiple layers for an operation. This is also known as the “multi-select” feature. This makes plugins more general, not limited to a single drawable.
For PDB procedures that now take an array of drawables, in Scheme pass a vector of numeric drawable ID’s.
Examples:
(gimp-edit-copy drawable) => (gimp-edit-copy (vector drawable))
(gimp-edit-copy 2) => (gimp-edit-copy '#(2))
(gimp-edit-copy 2) => (gimp-edit-copy (vector 2))
(plug-in-despeckle NON-INTERACTIVE 1 2) => (plug-in-despeckle NON-INTERACTIVE 1 (vector 2))
Some PDB procedures that formerly took a single drawable still take a single drawable. No changes are required in Scheme plugins.
The PDB procedures which formerly took a single object but now take GimpCoreObjectArray
- Many of the file load/save procedures.
- Most plugins that are filters
- 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
5 Receiving an array of drawables or other objects
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 GimpCoreObjectArray. A script receives 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 Scheme vector of numerics, for drawable ID’s.
6,7 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 of strings. 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 in the v2 dialect, the result of a call to the PDB can be wrapped in an extra list. In this case the result is a list containing a list of strings, and for example you get the list of strings like “(car (gimp-fonts-get-list “.*”))”
8 Passing or receiving colors
No changes are required to Scheme scripts.
The C type in the PDB changes from GimpRGB to GeglColor.
You should not use Scheme scripts to alter colors as objects. ScriptFu and the PDB do not have all the object methods needed to manipulate colors as objects.
Scripts usually receive and pass colors opaquely, for example when getting and putting colors of a pixel.
In a Scheme script, you can name the most common colors. You can also identify the 16 million colors in three byte RGB usings lists of numbers e.g. (255, 255, 255).
You may also receive a quadruplet for a color from an image with transparency.
9 Passing or receiving resources e.g. fonts
A resource is a brush, font, gradient, palette or pattern.
Formerly, a script passed or received the name of a resource. A name is type string. Now resources are passed as objects, identified by an opaque integer ID.
The PDB has methods on superclass Resource.
A script can get an object for a resource by name.
(gimp-context-set-font "Sans Serif") => (gimp-context-set-font (gimp-font-get-by-name "Sans Serif"))
A script can get attributes of a resource object.
(gimp-resource-get-name (gimp-context-get-brush))
10 Receiving an array of color
Formerly, a script received an integer length and a list of lists of numbers.
Now a script receives just a list of lists of numbers. Where each list of numbers was a triplet, i.e. an RGB representation.
See gimp-palette-get-colors and the type GimpColorArray.
Changes in error detection for calls to the PDB
ScriptFu is now more forgiving in calls to PDB procedures.
Formerly, ScriptFu would not accept a call construct, to a PDB procedure, where the argument count was wrong, except for the case when you provided one argument to a PDB procedure that took zero arguments, 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.
Keyword arguments in calls to plugins in the PDB
A script can call PDB procedures. Certain procedures in the PDB are Plugins. Other procedures are Internal.
Now, you can use keyword syntax for calls to plugins, but not for calls to internal procedures.
Using keyword arguments is optional, but it is all-or-nothing within a call: all arguments must have keywords, or none.
Keyword syntax is also known as “named arguments”. The syntax is like the syntax from other Scheme implementations. The characters “#:” precede the name of the argument (as given in the PDB API.)
Example:
(plug-in-tile #:run-mode RUN-NONINTERACTIVE
#:image testImage
#:drawables testLayers
#:new-width 10
#:new-height 20
#:new-image #f)
We recommend you use keyword style arguments for calls to plugins. It future-proofs a script from changes to plugin signatures. It also lets you omit arguments inside the sequence of args (not just omit trailing arguments.) It also lets you pass arguments in an order different from the order declared in the PDB.
Unlike Python, all arguments must have names, not just trailing arguments. Python has mandatory leading positional arguments and optional trailing keyword arguments.
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 most useful for GIMP developers, but sometimes useful to debug a script plugin.