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